summaryrefslogtreecommitdiffstats
path: root/plat
diff options
context:
space:
mode:
Diffstat (limited to 'plat')
-rw-r--r--plat/allwinner/common/allwinner-common.mk114
-rw-r--r--plat/allwinner/common/arisc_off.S115
-rw-r--r--plat/allwinner/common/include/mentor_i2c_plat.h28
-rw-r--r--plat/allwinner/common/include/plat_macros.S27
-rw-r--r--plat/allwinner/common/include/platform_def.h84
-rw-r--r--plat/allwinner/common/include/sunxi_def.h26
-rw-r--r--plat/allwinner/common/include/sunxi_private.h61
-rw-r--r--plat/allwinner/common/plat_helpers.S49
-rw-r--r--plat/allwinner/common/sunxi_bl31_setup.c204
-rw-r--r--plat/allwinner/common/sunxi_common.c187
-rw-r--r--plat/allwinner/common/sunxi_cpu_ops.c108
-rw-r--r--plat/allwinner/common/sunxi_native_pm.c81
-rw-r--r--plat/allwinner/common/sunxi_pm.c60
-rw-r--r--plat/allwinner/common/sunxi_prepare_dtb.c52
-rw-r--r--plat/allwinner/common/sunxi_scpi_pm.c207
-rw-r--r--plat/allwinner/common/sunxi_security.c40
-rw-r--r--plat/allwinner/common/sunxi_topology.c39
-rw-r--r--plat/allwinner/sun50i_a64/include/core_off_arisc.h39
-rw-r--r--plat/allwinner/sun50i_a64/include/sunxi_ccu.h14
-rw-r--r--plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h39
-rw-r--r--plat/allwinner/sun50i_a64/include/sunxi_mmap.h74
-rw-r--r--plat/allwinner/sun50i_a64/include/sunxi_spc.h16
-rw-r--r--plat/allwinner/sun50i_a64/platform.mk17
-rw-r--r--plat/allwinner/sun50i_a64/sunxi_idle_states.c27
-rw-r--r--plat/allwinner/sun50i_a64/sunxi_power.c259
-rw-r--r--plat/allwinner/sun50i_h6/include/sunxi_ccu.h14
-rw-r--r--plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h35
-rw-r--r--plat/allwinner/sun50i_h6/include/sunxi_mmap.h63
-rw-r--r--plat/allwinner/sun50i_h6/include/sunxi_spc.h16
-rw-r--r--plat/allwinner/sun50i_h6/platform.mk14
-rw-r--r--plat/allwinner/sun50i_h6/sunxi_idle_states.c11
-rw-r--r--plat/allwinner/sun50i_h6/sunxi_power.c119
-rw-r--r--plat/allwinner/sun50i_h616/include/sunxi_ccu.h14
-rw-r--r--plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h35
-rw-r--r--plat/allwinner/sun50i_h616/include/sunxi_mmap.h46
-rw-r--r--plat/allwinner/sun50i_h616/include/sunxi_spc.h16
-rw-r--r--plat/allwinner/sun50i_h616/platform.mk22
-rw-r--r--plat/allwinner/sun50i_h616/sunxi_idle_states.c11
-rw-r--r--plat/allwinner/sun50i_h616/sunxi_power.c121
-rw-r--r--plat/allwinner/sun50i_r329/include/sunxi_ccu.h14
-rw-r--r--plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h31
-rw-r--r--plat/allwinner/sun50i_r329/include/sunxi_mmap.h55
-rw-r--r--plat/allwinner/sun50i_r329/include/sunxi_spc.h17
-rw-r--r--plat/allwinner/sun50i_r329/platform.mk20
-rw-r--r--plat/allwinner/sun50i_r329/sunxi_idle_states.c11
-rw-r--r--plat/allwinner/sun50i_r329/sunxi_power.c27
-rw-r--r--plat/amlogic/axg/axg_bl31_setup.c170
-rw-r--r--plat/amlogic/axg/axg_common.c115
-rw-r--r--plat/amlogic/axg/axg_def.h129
-rw-r--r--plat/amlogic/axg/axg_pm.c166
-rw-r--r--plat/amlogic/axg/include/platform_def.h66
-rw-r--r--plat/amlogic/axg/platform.mk95
-rw-r--r--plat/amlogic/common/aarch64/aml_helpers.S97
-rw-r--r--plat/amlogic/common/aml_console.c33
-rw-r--r--plat/amlogic/common/aml_efuse.c25
-rw-r--r--plat/amlogic/common/aml_mhu.c52
-rw-r--r--plat/amlogic/common/aml_scpi.c234
-rw-r--r--plat/amlogic/common/aml_sip_svc.c99
-rw-r--r--plat/amlogic/common/aml_thermal.c27
-rw-r--r--plat/amlogic/common/aml_topology.c53
-rw-r--r--plat/amlogic/common/include/aml_private.h41
-rw-r--r--plat/amlogic/common/include/plat_macros.S71
-rw-r--r--plat/amlogic/g12a/g12a_bl31_setup.c142
-rw-r--r--plat/amlogic/g12a/g12a_common.c125
-rw-r--r--plat/amlogic/g12a/g12a_def.h135
-rw-r--r--plat/amlogic/g12a/g12a_pm.c215
-rw-r--r--plat/amlogic/g12a/include/platform_def.h63
-rw-r--r--plat/amlogic/g12a/platform.mk91
-rw-r--r--plat/amlogic/gxbb/gxbb_bl31_setup.c144
-rw-r--r--plat/amlogic/gxbb/gxbb_common.c117
-rw-r--r--plat/amlogic/gxbb/gxbb_def.h123
-rw-r--r--plat/amlogic/gxbb/gxbb_pm.c191
-rw-r--r--plat/amlogic/gxbb/include/platform_def.h66
-rw-r--r--plat/amlogic/gxbb/platform.mk75
-rw-r--r--plat/amlogic/gxl/gxl_bl31_setup.c162
-rw-r--r--plat/amlogic/gxl/gxl_common.c117
-rw-r--r--plat/amlogic/gxl/gxl_def.h133
-rw-r--r--plat/amlogic/gxl/gxl_pm.c214
-rw-r--r--plat/amlogic/gxl/include/platform_def.h63
-rw-r--r--plat/amlogic/gxl/platform.mk91
-rw-r--r--plat/arm/board/a5ds/a5ds_bl1_setup.c20
-rw-r--r--plat/arm/board/a5ds/a5ds_bl2_setup.c18
-rw-r--r--plat/arm/board/a5ds/a5ds_common.c56
-rw-r--r--plat/arm/board/a5ds/a5ds_err.c17
-rw-r--r--plat/arm/board/a5ds/a5ds_pm.c75
-rw-r--r--plat/arm/board/a5ds/a5ds_private.h15
-rw-r--r--plat/arm/board/a5ds/a5ds_security.c17
-rw-r--r--plat/arm/board/a5ds/a5ds_topology.c53
-rw-r--r--plat/arm/board/a5ds/aarch32/a5ds_helpers.S126
-rw-r--r--plat/arm/board/a5ds/fdts/a5ds_fw_config.dts27
-rw-r--r--plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts16
-rw-r--r--plat/arm/board/a5ds/include/platform_def.h376
-rw-r--r--plat/arm/board/a5ds/platform.mk111
-rw-r--r--plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c27
-rw-r--r--plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk22
-rw-r--r--plat/arm/board/arm_fpga/aarch64/fpga_helpers.S167
-rw-r--r--plat/arm/board/arm_fpga/build_axf.ld.S53
-rw-r--r--plat/arm/board/arm_fpga/fpga_bl31_setup.c402
-rw-r--r--plat/arm/board/arm_fpga/fpga_console.c38
-rw-r--r--plat/arm/board/arm_fpga/fpga_def.h39
-rw-r--r--plat/arm/board/arm_fpga/fpga_gicv3.c162
-rw-r--r--plat/arm/board/arm_fpga/fpga_pm.c103
-rw-r--r--plat/arm/board/arm_fpga/fpga_private.h34
-rw-r--r--plat/arm/board/arm_fpga/fpga_topology.c77
-rw-r--r--plat/arm/board/arm_fpga/include/plat_macros.S13
-rw-r--r--plat/arm/board/arm_fpga/include/platform_def.h88
-rw-r--r--plat/arm/board/arm_fpga/kernel_trampoline.S35
-rw-r--r--plat/arm/board/arm_fpga/platform.mk130
-rw-r--r--plat/arm/board/arm_fpga/rom_trampoline.S24
-rw-r--r--plat/arm/board/common/aarch32/board_arm_helpers.S32
-rw-r--r--plat/arm/board/common/aarch64/board_arm_helpers.S34
-rw-r--r--plat/arm/board/common/board_arm_trusted_boot.c263
-rw-r--r--plat/arm/board/common/board_common.mk120
-rw-r--r--plat/arm/board/common/protpk/README14
-rw-r--r--plat/arm/board/common/protpk/arm_dev_protpk.S18
-rw-r--r--plat/arm/board/common/protpk/arm_protprivk_rsa.pem27
-rw-r--r--plat/arm/board/common/rotpk/arm_dev_rotpk.S33
-rw-r--r--plat/arm/board/common/rotpk/arm_rotpk_ecdsa.derbin0 -> 91 bytes
-rw-r--r--plat/arm/board/common/rotpk/arm_rotpk_rsa.derbin0 -> 294 bytes
-rw-r--r--plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem5
-rw-r--r--plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem28
-rw-r--r--plat/arm/board/common/swd_rotpk/README14
-rw-r--r--plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S18
-rw-r--r--plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin1
-rw-r--r--plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem27
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c85
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_err.c17
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_helpers.S67
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_plat.c126
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_pm.c37
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_security.c16
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_stack_protector.c35
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_topology.c43
-rw-r--r--plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c53
-rw-r--r--plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts30
-rw-r--r--plat/arm/board/corstone1000/common/include/platform_def.h394
-rw-r--r--plat/arm/board/corstone1000/include/plat_macros.S22
-rw-r--r--plat/arm/board/corstone1000/platform.mk83
-rw-r--r--plat/arm/board/corstone700/common/corstone700_helpers.S100
-rw-r--r--plat/arm/board/corstone700/common/corstone700_plat.c39
-rw-r--r--plat/arm/board/corstone700/common/corstone700_pm.c22
-rw-r--r--plat/arm/board/corstone700/common/corstone700_security.c16
-rw-r--r--plat/arm/board/corstone700/common/corstone700_stack_protector.c35
-rw-r--r--plat/arm/board/corstone700/common/corstone700_topology.c43
-rw-r--r--plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c117
-rw-r--r--plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.h37
-rw-r--r--plat/arm/board/corstone700/common/include/platform_def.h282
-rw-r--r--plat/arm/board/corstone700/platform.mk63
-rw-r--r--plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c13
-rw-r--r--plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk24
-rw-r--r--plat/arm/board/fvp/aarch32/fvp_helpers.S143
-rw-r--r--plat/arm/board/fvp/aarch64/fvp_helpers.S177
-rw-r--r--plat/arm/board/fvp/aarch64/fvp_ras.c16
-rw-r--r--plat/arm/board/fvp/fconf/fconf_hw_config_getter.c299
-rw-r--r--plat/arm/board/fvp/fconf/fconf_nt_config_getter.c64
-rw-r--r--plat/arm/board/fvp/fdts/event_log.dtsi12
-rw-r--r--plat/arm/board/fvp/fdts/fvp_fw_config.dts55
-rw-r--r--plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts19
-rw-r--r--plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts11
-rw-r--r--plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts89
-rw-r--r--plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts64
-rw-r--r--plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts127
-rw-r--r--plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts13
-rw-r--r--plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts34
-rw-r--r--plat/arm/board/fvp/fdts/optee_sp_manifest.dts44
-rw-r--r--plat/arm/board/fvp/fvp_bl1_measured_boot.c75
-rw-r--r--plat/arm/board/fvp/fvp_bl1_setup.c89
-rw-r--r--plat/arm/board/fvp/fvp_bl2_el3_setup.c30
-rw-r--r--plat/arm/board/fvp/fvp_bl2_measured_boot.c234
-rw-r--r--plat/arm/board/fvp/fvp_bl2_setup.c105
-rw-r--r--plat/arm/board/fvp/fvp_bl2u_setup.c22
-rw-r--r--plat/arm/board/fvp/fvp_bl31_setup.c156
-rw-r--r--plat/arm/board/fvp/fvp_common.c544
-rw-r--r--plat/arm/board/fvp/fvp_common_measured_boot.c55
-rw-r--r--plat/arm/board/fvp/fvp_console.c54
-rw-r--r--plat/arm/board/fvp/fvp_def.h181
-rw-r--r--plat/arm/board/fvp/fvp_drtm_addr.c36
-rw-r--r--plat/arm/board/fvp/fvp_drtm_dma_prot.c76
-rw-r--r--plat/arm/board/fvp/fvp_drtm_err.c22
-rw-r--r--plat/arm/board/fvp/fvp_drtm_measurement.c29
-rw-r--r--plat/arm/board/fvp/fvp_drtm_stub.c35
-rw-r--r--plat/arm/board/fvp/fvp_el3_spmc.c47
-rw-r--r--plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c61
-rw-r--r--plat/arm/board/fvp/fvp_err.c43
-rw-r--r--plat/arm/board/fvp/fvp_gicv3.c174
-rw-r--r--plat/arm/board/fvp/fvp_io_storage.c174
-rw-r--r--plat/arm/board/fvp/fvp_plat_attest_token.c111
-rw-r--r--plat/arm/board/fvp/fvp_pm.c467
-rw-r--r--plat/arm/board/fvp/fvp_private.h24
-rw-r--r--plat/arm/board/fvp/fvp_realm_attest_key.c36
-rw-r--r--plat/arm/board/fvp/fvp_security.c42
-rw-r--r--plat/arm/board/fvp/fvp_stack_protector.c24
-rw-r--r--plat/arm/board/fvp/fvp_topology.c123
-rw-r--r--plat/arm/board/fvp/fvp_trusted_boot.c71
-rw-r--r--plat/arm/board/fvp/include/fconf_hw_config_getter.h48
-rw-r--r--plat/arm/board/fvp/include/fconf_nt_config_getter.h27
-rw-r--r--plat/arm/board/fvp/include/fvp_critical_data.h23
-rw-r--r--plat/arm/board/fvp/include/plat.ld.S15
-rw-r--r--plat/arm/board/fvp/include/plat_macros.S42
-rw-r--r--plat/arm/board/fvp/include/platform_def.h416
-rw-r--r--plat/arm/board/fvp/jmptbl.i63
-rw-r--r--plat/arm/board/fvp/platform.mk464
-rw-r--r--plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c121
-rw-r--r--plat/arm/board/fvp/sp_min/sp_min-fvp.mk39
-rw-r--r--plat/arm/board/fvp/trp/trp-fvp.mk12
-rw-r--r--plat/arm/board/fvp/tsp/fvp_tsp_setup.c17
-rw-r--r--plat/arm/board/fvp/tsp/tsp-fvp.mk14
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c35
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S93
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S120
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_main.c268
-rw-r--r--plat/arm/board/fvp_r/fvp_r_bl1_setup.c248
-rw-r--r--plat/arm/board/fvp_r/fvp_r_common.c289
-rw-r--r--plat/arm/board/fvp_r/fvp_r_context_mgmt.c53
-rw-r--r--plat/arm/board/fvp_r/fvp_r_debug.S47
-rw-r--r--plat/arm/board/fvp_r/fvp_r_def.h103
-rw-r--r--plat/arm/board/fvp_r/fvp_r_err.c48
-rw-r--r--plat/arm/board/fvp_r/fvp_r_helpers.S128
-rw-r--r--plat/arm/board/fvp_r/fvp_r_io_storage.c105
-rw-r--r--plat/arm/board/fvp_r/fvp_r_misc_helpers.S32
-rw-r--r--plat/arm/board/fvp_r/fvp_r_private.h23
-rw-r--r--plat/arm/board/fvp_r/fvp_r_stack_protector.c24
-rw-r--r--plat/arm/board/fvp_r/fvp_r_trusted_boot.c73
-rw-r--r--plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h28
-rw-r--r--plat/arm/board/fvp_r/include/platform_def.h268
-rw-r--r--plat/arm/board/fvp_r/platform.mk99
-rw-r--r--plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S62
-rw-r--r--plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts27
-rw-r--r--plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts16
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c33
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c41
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_common.c63
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_def.h84
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_err.c17
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_pm.c25
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_private.h18
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_security.c22
-rw-r--r--plat/arm/board/fvp_ve/fvp_ve_topology.c37
-rw-r--r--plat/arm/board/fvp_ve/include/platform_def.h361
-rw-r--r--plat/arm/board/fvp_ve/platform.mk139
-rw-r--r--plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c15
-rw-r--r--plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk22
-rw-r--r--plat/arm/board/juno/aarch32/juno_helpers.S176
-rw-r--r--plat/arm/board/juno/aarch64/juno_helpers.S275
-rw-r--r--plat/arm/board/juno/fdts/juno_fw_config.dts27
-rw-r--r--plat/arm/board/juno/fdts/juno_tb_fw_config.dts26
-rw-r--r--plat/arm/board/juno/include/plat_macros.S24
-rw-r--r--plat/arm/board/juno/include/platform_def.h313
-rw-r--r--plat/arm/board/juno/jmptbl.i62
-rw-r--r--plat/arm/board/juno/juno_bl1_setup.c122
-rw-r--r--plat/arm/board/juno/juno_bl2_setup.c73
-rw-r--r--plat/arm/board/juno/juno_bl31_setup.c60
-rw-r--r--plat/arm/board/juno/juno_common.c134
-rw-r--r--plat/arm/board/juno/juno_def.h99
-rw-r--r--plat/arm/board/juno/juno_err.c27
-rw-r--r--plat/arm/board/juno/juno_pm.c17
-rw-r--r--plat/arm/board/juno/juno_security.c166
-rw-r--r--plat/arm/board/juno/juno_stack_protector.c27
-rw-r--r--plat/arm/board/juno/juno_topology.c78
-rw-r--r--plat/arm/board/juno/juno_trng.c108
-rw-r--r--plat/arm/board/juno/juno_trusted_boot.c126
-rw-r--r--plat/arm/board/juno/juno_tzmp1_def.h83
-rw-r--r--plat/arm/board/juno/platform.mk201
-rw-r--r--plat/arm/board/juno/sp_min/sp_min-juno.mk22
-rw-r--r--plat/arm/board/juno/tsp/tsp-juno.mk12
-rw-r--r--plat/arm/board/morello/aarch64/morello_helper.S55
-rw-r--r--plat/arm/board/morello/fdts/morello_fw_config.dts26
-rw-r--r--plat/arm/board/morello/fdts/morello_nt_fw_config.dts26
-rw-r--r--plat/arm/board/morello/fdts/morello_tb_fw_config.dts27
-rw-r--r--plat/arm/board/morello/include/plat_macros.S25
-rw-r--r--plat/arm/board/morello/include/platform_def.h194
-rw-r--r--plat/arm/board/morello/morello_bl1_setup.c19
-rw-r--r--plat/arm/board/morello/morello_bl2_setup.c226
-rw-r--r--plat/arm/board/morello/morello_bl31_setup.c35
-rw-r--r--plat/arm/board/morello/morello_def.h92
-rw-r--r--plat/arm/board/morello/morello_err.c17
-rw-r--r--plat/arm/board/morello/morello_image_load.c185
-rw-r--r--plat/arm/board/morello/morello_interconnect.c33
-rw-r--r--plat/arm/board/morello/morello_plat.c70
-rw-r--r--plat/arm/board/morello/morello_security.c12
-rw-r--r--plat/arm/board/morello/morello_topology.c60
-rw-r--r--plat/arm/board/morello/morello_trusted_boot.c54
-rw-r--r--plat/arm/board/morello/platform.mk110
-rw-r--r--plat/arm/board/n1sdp/aarch64/n1sdp_helper.S78
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts29
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts23
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts30
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts27
-rw-r--r--plat/arm/board/n1sdp/include/plat_macros.S24
-rw-r--r--plat/arm/board/n1sdp/include/platform_def.h251
-rw-r--r--plat/arm/board/n1sdp/n1sdp_bl1_setup.c19
-rw-r--r--plat/arm/board/n1sdp/n1sdp_bl2_setup.c89
-rw-r--r--plat/arm/board/n1sdp/n1sdp_bl31_setup.c161
-rw-r--r--plat/arm/board/n1sdp/n1sdp_def.h52
-rw-r--r--plat/arm/board/n1sdp/n1sdp_err.c17
-rw-r--r--plat/arm/board/n1sdp/n1sdp_image_load.c143
-rw-r--r--plat/arm/board/n1sdp/n1sdp_interconnect.c33
-rw-r--r--plat/arm/board/n1sdp/n1sdp_plat.c73
-rw-r--r--plat/arm/board/n1sdp/n1sdp_security.c12
-rw-r--r--plat/arm/board/n1sdp/n1sdp_topology.c59
-rw-r--r--plat/arm/board/n1sdp/n1sdp_trusted_boot.c54
-rw-r--r--plat/arm/board/n1sdp/platform.mk111
-rw-r--r--plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts27
-rw-r--r--plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts23
-rw-r--r--plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts28
-rw-r--r--plat/arm/board/rde1edge/include/platform_def.h48
-rw-r--r--plat/arm/board/rde1edge/platform.mk66
-rw-r--r--plat/arm/board/rde1edge/rde1edge_err.c17
-rw-r--r--plat/arm/board/rde1edge/rde1edge_plat.c29
-rw-r--r--plat/arm/board/rde1edge/rde1edge_security.c36
-rw-r--r--plat/arm/board/rde1edge/rde1edge_topology.c36
-rw-r--r--plat/arm/board/rde1edge/rde1edge_trusted_boot.c26
-rw-r--r--plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts27
-rw-r--r--plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts22
-rw-r--r--plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts27
-rw-r--r--plat/arm/board/rdn1edge/include/platform_def.h54
-rw-r--r--plat/arm/board/rdn1edge/platform.mk75
-rw-r--r--plat/arm/board/rdn1edge/rdn1edge_err.c17
-rw-r--r--plat/arm/board/rdn1edge/rdn1edge_plat.c97
-rw-r--r--plat/arm/board/rdn1edge/rdn1edge_security.c36
-rw-r--r--plat/arm/board/rdn1edge/rdn1edge_topology.c54
-rw-r--r--plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c26
-rw-r--r--plat/arm/board/rdn2/fdts/rdn2_fw_config.dts27
-rw-r--r--plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts43
-rw-r--r--plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts28
-rw-r--r--plat/arm/board/rdn2/include/platform_def.h103
-rw-r--r--plat/arm/board/rdn2/platform.mk90
-rw-r--r--plat/arm/board/rdn2/rdn2_err.c17
-rw-r--r--plat/arm/board/rdn2/rdn2_plat.c138
-rw-r--r--plat/arm/board/rdn2/rdn2_security.c63
-rw-r--r--plat/arm/board/rdn2/rdn2_topology.c97
-rw-r--r--plat/arm/board/rdn2/rdn2_trusted_boot.c26
-rw-r--r--plat/arm/board/rdv1/fdts/rdv1_fw_config.dts27
-rw-r--r--plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts22
-rw-r--r--plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts28
-rw-r--r--plat/arm/board/rdv1/include/platform_def.h68
-rw-r--r--plat/arm/board/rdv1/platform.mk65
-rw-r--r--plat/arm/board/rdv1/rdv1_err.c17
-rw-r--r--plat/arm/board/rdv1/rdv1_plat.c30
-rw-r--r--plat/arm/board/rdv1/rdv1_security.c22
-rw-r--r--plat/arm/board/rdv1/rdv1_topology.c62
-rw-r--r--plat/arm/board/rdv1/rdv1_trusted_boot.c26
-rw-r--r--plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts27
-rw-r--r--plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts22
-rw-r--r--plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts28
-rw-r--r--plat/arm/board/rdv1mc/include/platform_def.h63
-rw-r--r--plat/arm/board/rdv1mc/platform.mk76
-rw-r--r--plat/arm/board/rdv1mc/rdv1mc_err.c17
-rw-r--r--plat/arm/board/rdv1mc/rdv1mc_plat.c131
-rw-r--r--plat/arm/board/rdv1mc/rdv1mc_security.c64
-rw-r--r--plat/arm/board/rdv1mc/rdv1mc_topology.c78
-rw-r--r--plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c26
-rw-r--r--plat/arm/board/sgi575/fdts/sgi575_fw_config.dts27
-rw-r--r--plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts22
-rw-r--r--plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts28
-rw-r--r--plat/arm/board/sgi575/include/platform_def.h49
-rw-r--r--plat/arm/board/sgi575/platform.mk67
-rw-r--r--plat/arm/board/sgi575/sgi575_err.c17
-rw-r--r--plat/arm/board/sgi575/sgi575_plat.c30
-rw-r--r--plat/arm/board/sgi575/sgi575_security.c36
-rw-r--r--plat/arm/board/sgi575/sgi575_topology.c32
-rw-r--r--plat/arm/board/sgi575/sgi575_trusted_boot.c26
-rw-r--r--plat/arm/board/tc/fdts/tc_fw_config.dts33
-rw-r--r--plat/arm/board/tc/fdts/tc_spmc_manifest.dts125
-rw-r--r--plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts124
-rw-r--r--plat/arm/board/tc/fdts/tc_tb_fw_config.dts76
-rw-r--r--plat/arm/board/tc/include/plat_macros.S24
-rw-r--r--plat/arm/board/tc/include/platform_def.h294
-rw-r--r--plat/arm/board/tc/include/tc_helpers.S61
-rw-r--r--plat/arm/board/tc/include/tc_plat.h12
-rw-r--r--plat/arm/board/tc/platform.mk199
-rw-r--r--plat/arm/board/tc/tc_bl1_measured_boot.c55
-rw-r--r--plat/arm/board/tc/tc_bl2_measured_boot.c54
-rw-r--r--plat/arm/board/tc/tc_bl2_setup.c47
-rw-r--r--plat/arm/board/tc/tc_bl31_setup.c73
-rw-r--r--plat/arm/board/tc/tc_common_measured_boot.c35
-rw-r--r--plat/arm/board/tc/tc_err.c17
-rw-r--r--plat/arm/board/tc/tc_interconnect.c35
-rw-r--r--plat/arm/board/tc/tc_plat.c156
-rw-r--r--plat/arm/board/tc/tc_security.c23
-rw-r--r--plat/arm/board/tc/tc_topology.c58
-rw-r--r--plat/arm/board/tc/tc_trusted_boot.c26
-rw-r--r--plat/arm/common/aarch32/arm_bl2_mem_params_desc.c91
-rw-r--r--plat/arm/common/aarch32/arm_helpers.S77
-rw-r--r--plat/arm/common/aarch64/arm_bl2_mem_params_desc.c227
-rw-r--r--plat/arm/common/aarch64/arm_helpers.S136
-rw-r--r--plat/arm/common/aarch64/arm_pauth.c28
-rw-r--r--plat/arm/common/aarch64/arm_sdei.c66
-rw-r--r--plat/arm/common/aarch64/execution_state_switch.c180
-rw-r--r--plat/arm/common/arm_bl1_fwu.c102
-rw-r--r--plat/arm/common/arm_bl1_setup.c258
-rw-r--r--plat/arm/common/arm_bl2_el3_setup.c100
-rw-r--r--plat/arm/common/arm_bl2_setup.c322
-rw-r--r--plat/arm/common/arm_bl2u_setup.c97
-rw-r--r--plat/arm/common/arm_bl31_setup.c435
-rw-r--r--plat/arm/common/arm_cci.c50
-rw-r--r--plat/arm/common/arm_ccn.c57
-rw-r--r--plat/arm/common/arm_common.c243
-rw-r--r--plat/arm/common/arm_common.mk456
-rw-r--r--plat/arm/common/arm_console.c71
-rw-r--r--plat/arm/common/arm_dyn_cfg.c231
-rw-r--r--plat/arm/common/arm_dyn_cfg_helpers.c369
-rw-r--r--plat/arm/common/arm_err.c20
-rw-r--r--plat/arm/common/arm_gicv2.c114
-rw-r--r--plat/arm/common/arm_gicv3.c247
-rw-r--r--plat/arm/common/arm_image_load.c141
-rw-r--r--plat/arm/common/arm_io_storage.c250
-rw-r--r--plat/arm/common/arm_nor_psci_mem_protect.c138
-rw-r--r--plat/arm/common/arm_pm.c210
-rw-r--r--plat/arm/common/arm_sip_svc.c143
-rw-r--r--plat/arm/common/arm_topology.c58
-rw-r--r--plat/arm/common/arm_tzc400.c79
-rw-r--r--plat/arm/common/arm_tzc_dmc500.c79
-rw-r--r--plat/arm/common/fconf/arm_fconf_io.c381
-rw-r--r--plat/arm/common/fconf/arm_fconf_sp.c165
-rw-r--r--plat/arm/common/fconf/fconf_ethosn_getter.c354
-rw-r--r--plat/arm/common/fconf/fconf_nv_cntr_getter.c62
-rw-r--r--plat/arm/common/fconf/fconf_sdei_getter.c103
-rw-r--r--plat/arm/common/fconf/fconf_sec_intr_config.c131
-rw-r--r--plat/arm/common/sp_min/arm_sp_min.mk20
-rw-r--r--plat/arm/common/sp_min/arm_sp_min_setup.c241
-rw-r--r--plat/arm/common/trp/arm_trp.mk12
-rw-r--r--plat/arm/common/trp/arm_trp_setup.c72
-rw-r--r--plat/arm/common/tsp/arm_tsp.mk10
-rw-r--r--plat/arm/common/tsp/arm_tsp_setup.c86
-rw-r--r--plat/arm/css/common/aarch32/css_helpers.S102
-rw-r--r--plat/arm/css/common/aarch64/css_helpers.S120
-rw-r--r--plat/arm/css/common/css_bl1_setup.c22
-rw-r--r--plat/arm/css/common/css_bl2_setup.c86
-rw-r--r--plat/arm/css/common/css_bl2u_setup.c56
-rw-r--r--plat/arm/css/common/css_common.mk97
-rw-r--r--plat/arm/css/common/css_pm.c415
-rw-r--r--plat/arm/css/common/css_topology.c48
-rw-r--r--plat/arm/css/common/sp_min/css_sp_min.mk22
-rw-r--r--plat/arm/css/sgi/aarch64/sgi_helper.S106
-rw-r--r--plat/arm/css/sgi/include/plat_macros.S24
-rw-r--r--plat/arm/css/sgi/include/sgi_base_platform_def.h300
-rw-r--r--plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h36
-rw-r--r--plat/arm/css/sgi/include/sgi_plat.h13
-rw-r--r--plat/arm/css/sgi/include/sgi_ras.h21
-rw-r--r--plat/arm/css/sgi/include/sgi_sdei.h25
-rw-r--r--plat/arm/css/sgi/include/sgi_soc_css_def.h47
-rw-r--r--plat/arm/css/sgi/include/sgi_soc_css_def_v2.h202
-rw-r--r--plat/arm/css/sgi/include/sgi_soc_platform_def.h33
-rw-r--r--plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h31
-rw-r--r--plat/arm/css/sgi/include/sgi_variant.h49
-rw-r--r--plat/arm/css/sgi/sgi-common.mk86
-rw-r--r--plat/arm/css/sgi/sgi_bl31_setup.c139
-rw-r--r--plat/arm/css/sgi/sgi_image_load.c155
-rw-r--r--plat/arm/css/sgi/sgi_interconnect.c36
-rw-r--r--plat/arm/css/sgi/sgi_plat.c176
-rw-r--r--plat/arm/css/sgi/sgi_plat_v2.c175
-rw-r--r--plat/arm/css/sgi/sgi_ras.c194
-rw-r--r--plat/arm/css/sgi/sgi_topology.c29
-rw-r--r--plat/arm/soc/common/soc_css.mk15
-rw-r--r--plat/arm/soc/common/soc_css_security.c73
-rw-r--r--plat/brcm/board/common/bcm_console.c65
-rw-r--r--plat/brcm/board/common/bcm_elog.c268
-rw-r--r--plat/brcm/board/common/bcm_elog_ddr.c133
-rw-r--r--plat/brcm/board/common/bcm_elog_ddr.h107
-rw-r--r--plat/brcm/board/common/board_arm_trusted_boot.c625
-rw-r--r--plat/brcm/board/common/board_common.c74
-rw-r--r--plat/brcm/board/common/board_common.mk294
-rw-r--r--plat/brcm/board/common/brcm_mbedtls.c12
-rw-r--r--plat/brcm/board/common/chip_id.h37
-rw-r--r--plat/brcm/board/common/cmn_plat_def.h82
-rw-r--r--plat/brcm/board/common/cmn_plat_util.h43
-rw-r--r--plat/brcm/board/common/cmn_sec.c49
-rw-r--r--plat/brcm/board/common/cmn_sec.h19
-rw-r--r--plat/brcm/board/common/err.c37
-rw-r--r--plat/brcm/board/common/plat_setup.c27
-rw-r--r--plat/brcm/board/common/platform_common.c94
-rw-r--r--plat/brcm/board/common/sbl_util.c40
-rw-r--r--plat/brcm/board/common/sbl_util.h19
-rw-r--r--plat/brcm/board/common/timer_sync.c71
-rw-r--r--plat/brcm/board/stingray/aarch64/plat_helpers.S263
-rw-r--r--plat/brcm/board/stingray/bcm958742t-ns3.mk22
-rw-r--r--plat/brcm/board/stingray/bcm958742t.mk19
-rw-r--r--plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h33
-rw-r--r--plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c302
-rw-r--r--plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h11
-rw-r--r--plat/brcm/board/stingray/driver/ihost_pll_config.c287
-rw-r--r--plat/brcm/board/stingray/driver/plat_emmc.c109
-rw-r--r--plat/brcm/board/stingray/driver/sr_usb.h135
-rw-r--r--plat/brcm/board/stingray/driver/swreg.c375
-rw-r--r--plat/brcm/board/stingray/driver/usb.c296
-rw-r--r--plat/brcm/board/stingray/driver/usb_phy.c601
-rw-r--r--plat/brcm/board/stingray/include/bl33_info.h38
-rw-r--r--plat/brcm/board/stingray/include/board_info.h38
-rw-r--r--plat/brcm/board/stingray/include/crmu_def.h227
-rw-r--r--plat/brcm/board/stingray/include/ddr_init.h39
-rw-r--r--plat/brcm/board/stingray/include/fsx.h37
-rw-r--r--plat/brcm/board/stingray/include/ihost_pm.h19
-rw-r--r--plat/brcm/board/stingray/include/iommu.h19
-rw-r--r--plat/brcm/board/stingray/include/ncsi.h32
-rw-r--r--plat/brcm/board/stingray/include/paxb.h74
-rw-r--r--plat/brcm/board/stingray/include/paxc.h23
-rw-r--r--plat/brcm/board/stingray/include/plat_macros.S52
-rw-r--r--plat/brcm/board/stingray/include/platform_def.h268
-rw-r--r--plat/brcm/board/stingray/include/platform_sotp.h36
-rw-r--r--plat/brcm/board/stingray/include/platform_usb.h19
-rw-r--r--plat/brcm/board/stingray/include/scp_cmd.h25
-rw-r--r--plat/brcm/board/stingray/include/scp_utils.h34
-rw-r--r--plat/brcm/board/stingray/include/sdio.h247
-rw-r--r--plat/brcm/board/stingray/include/sr_def.h624
-rw-r--r--plat/brcm/board/stingray/include/sr_utils.h42
-rw-r--r--plat/brcm/board/stingray/include/swreg.h36
-rw-r--r--plat/brcm/board/stingray/include/timer_sync.h12
-rw-r--r--plat/brcm/board/stingray/include/usb_phy.h244
-rw-r--r--plat/brcm/board/stingray/platform.mk304
-rw-r--r--plat/brcm/board/stingray/src/bl2_setup.c743
-rw-r--r--plat/brcm/board/stingray/src/bl31_setup.c1071
-rw-r--r--plat/brcm/board/stingray/src/brcm_pm_ops.c408
-rw-r--r--plat/brcm/board/stingray/src/fsx.c477
-rw-r--r--plat/brcm/board/stingray/src/ihost_pm.c355
-rw-r--r--plat/brcm/board/stingray/src/iommu.c536
-rw-r--r--plat/brcm/board/stingray/src/ncsi.c54
-rw-r--r--plat/brcm/board/stingray/src/paxb.c911
-rw-r--r--plat/brcm/board/stingray/src/paxc.c267
-rw-r--r--plat/brcm/board/stingray/src/pm.c131
-rw-r--r--plat/brcm/board/stingray/src/scp_cmd.c60
-rw-r--r--plat/brcm/board/stingray/src/scp_utils.c227
-rw-r--r--plat/brcm/board/stingray/src/sdio.c144
-rw-r--r--plat/brcm/board/stingray/src/sr_paxb_phy.c806
-rw-r--r--plat/brcm/board/stingray/src/topology.c52
-rw-r--r--plat/brcm/board/stingray/src/tz_sec.c153
-rw-r--r--plat/brcm/common/brcm_bl2_mem_params_desc.c106
-rw-r--r--plat/brcm/common/brcm_bl2_setup.c202
-rw-r--r--plat/brcm/common/brcm_bl31_setup.c291
-rw-r--r--plat/brcm/common/brcm_ccn.c36
-rw-r--r--plat/brcm/common/brcm_common.c59
-rw-r--r--plat/brcm/common/brcm_gicv3.c91
-rw-r--r--plat/brcm/common/brcm_image_load.c41
-rw-r--r--plat/brcm/common/brcm_io_storage.c408
-rw-r--r--plat/brcm/common/brcm_mhu.c131
-rw-r--r--plat/brcm/common/brcm_mhu.h19
-rw-r--r--plat/brcm/common/brcm_scpi.c252
-rw-r--r--plat/brcm/common/brcm_scpi.h107
-rw-r--r--plat/common/aarch32/crash_console_helpers.S68
-rw-r--r--plat/common/aarch32/plat_common.c21
-rw-r--r--plat/common/aarch32/plat_sp_min_common.c25
-rw-r--r--plat/common/aarch32/platform_helpers.S89
-rw-r--r--plat/common/aarch32/platform_mp_stack.S47
-rw-r--r--plat/common/aarch32/platform_up_stack.S47
-rw-r--r--plat/common/aarch64/crash_console_helpers.S187
-rw-r--r--plat/common/aarch64/plat_common.c104
-rw-r--r--plat/common/aarch64/plat_ehf.c37
-rw-r--r--plat/common/aarch64/platform_helpers.S122
-rw-r--r--plat/common/aarch64/platform_mp_stack.S61
-rw-r--r--plat/common/aarch64/platform_up_stack.S50
-rw-r--r--plat/common/plat_bl1_common.c117
-rw-r--r--plat/common/plat_bl_common.c137
-rw-r--r--plat/common/plat_gicv2.c336
-rw-r--r--plat/common/plat_gicv3.c370
-rw-r--r--plat/common/plat_log_common.c29
-rw-r--r--plat/common/plat_psci_common.c167
-rw-r--r--plat/common/plat_spmd_manifest.c194
-rw-r--r--plat/common/tbbr/plat_tbbr.c52
-rw-r--r--plat/common/ubsan.c220
-rw-r--r--plat/hisilicon/hikey/aarch64/hikey_common.c128
-rw-r--r--plat/hisilicon/hikey/aarch64/hikey_helpers.S159
-rw-r--r--plat/hisilicon/hikey/hikey_bl1_setup.c165
-rw-r--r--plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c167
-rw-r--r--plat/hisilicon/hikey/hikey_bl2_setup.c329
-rw-r--r--plat/hisilicon/hikey/hikey_bl31_setup.c155
-rw-r--r--plat/hisilicon/hikey/hikey_bl_common.c390
-rw-r--r--plat/hisilicon/hikey/hikey_ddr.c1451
-rw-r--r--plat/hisilicon/hikey/hikey_image_load.c34
-rw-r--r--plat/hisilicon/hikey/hikey_io_storage.c315
-rw-r--r--plat/hisilicon/hikey/hikey_pm.c288
-rw-r--r--plat/hisilicon/hikey/hikey_private.h77
-rw-r--r--plat/hisilicon/hikey/hikey_rotpk.S16
-rw-r--r--plat/hisilicon/hikey/hikey_security.c108
-rw-r--r--plat/hisilicon/hikey/hikey_tbbr.c36
-rw-r--r--plat/hisilicon/hikey/hikey_topology.c66
-rw-r--r--plat/hisilicon/hikey/hisi_dvfs.c781
-rw-r--r--plat/hisilicon/hikey/hisi_ipc.c207
-rw-r--r--plat/hisilicon/hikey/hisi_mcu.c206
-rw-r--r--plat/hisilicon/hikey/hisi_pwrc.c104
-rw-r--r--plat/hisilicon/hikey/hisi_pwrc_sram.S70
-rw-r--r--plat/hisilicon/hikey/hisi_sip_svc.c85
-rw-r--r--plat/hisilicon/hikey/include/hi6220.h77
-rw-r--r--plat/hisilicon/hikey/include/hi6220_regs_acpu.h300
-rw-r--r--plat/hisilicon/hikey/include/hi6220_regs_ao.h334
-rw-r--r--plat/hisilicon/hikey/include/hi6220_regs_peri.h380
-rw-r--r--plat/hisilicon/hikey/include/hi6220_regs_pin.h43
-rw-r--r--plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h101
-rw-r--r--plat/hisilicon/hikey/include/hi6553.h82
-rw-r--r--plat/hisilicon/hikey/include/hikey_def.h106
-rw-r--r--plat/hisilicon/hikey/include/hikey_layout.h122
-rw-r--r--plat/hisilicon/hikey/include/hisi_ipc.h46
-rw-r--r--plat/hisilicon/hikey/include/hisi_mcu.h16
-rw-r--r--plat/hisilicon/hikey/include/hisi_pwrc.h22
-rw-r--r--plat/hisilicon/hikey/include/hisi_sip_svc.h21
-rw-r--r--plat/hisilicon/hikey/include/hisi_sram_map.h327
-rw-r--r--plat/hisilicon/hikey/include/plat_macros.S78
-rw-r--r--plat/hisilicon/hikey/include/platform_def.h85
-rw-r--r--plat/hisilicon/hikey/platform.mk172
-rw-r--r--plat/hisilicon/hikey960/aarch64/hikey960_common.c123
-rw-r--r--plat/hisilicon/hikey960/aarch64/hikey960_helpers.S181
-rw-r--r--plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c206
-rw-r--r--plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c417
-rw-r--r--plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h57
-rw-r--r--plat/hisilicon/hikey960/hikey960_bl1_setup.c265
-rw-r--r--plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c183
-rw-r--r--plat/hisilicon/hikey960/hikey960_bl2_setup.c344
-rw-r--r--plat/hisilicon/hikey960/hikey960_bl31_setup.c264
-rw-r--r--plat/hisilicon/hikey960/hikey960_bl_common.c480
-rw-r--r--plat/hisilicon/hikey960/hikey960_boardid.c167
-rw-r--r--plat/hisilicon/hikey960/hikey960_def.h82
-rw-r--r--plat/hisilicon/hikey960/hikey960_el3_spmc_logical_sp.c61
-rw-r--r--plat/hisilicon/hikey960/hikey960_image_load.c55
-rw-r--r--plat/hisilicon/hikey960/hikey960_io_storage.c383
-rw-r--r--plat/hisilicon/hikey960/hikey960_mcu_load.c54
-rw-r--r--plat/hisilicon/hikey960/hikey960_pm.c337
-rw-r--r--plat/hisilicon/hikey960/hikey960_private.h55
-rw-r--r--plat/hisilicon/hikey960/hikey960_rotpk.S16
-rw-r--r--plat/hisilicon/hikey960/hikey960_tbbr.c36
-rw-r--r--plat/hisilicon/hikey960/hikey960_topology.c66
-rw-r--r--plat/hisilicon/hikey960/include/hi3660.h392
-rw-r--r--plat/hisilicon/hikey960/include/hi3660_crg.h179
-rw-r--r--plat/hisilicon/hikey960/include/hi3660_hkadc.h61
-rw-r--r--plat/hisilicon/hikey960/include/hi3660_mem_map.h20
-rw-r--r--plat/hisilicon/hikey960/include/hisi_ipc.h24
-rw-r--r--plat/hisilicon/hikey960/include/plat.ld.S22
-rw-r--r--plat/hisilicon/hikey960/include/plat_macros.S78
-rw-r--r--plat/hisilicon/hikey960/include/platform_def.h150
-rw-r--r--plat/hisilicon/hikey960/platform.mk182
-rw-r--r--plat/hisilicon/poplar/aarch64/platform_common.c79
-rw-r--r--plat/hisilicon/poplar/aarch64/poplar_helpers.S87
-rw-r--r--plat/hisilicon/poplar/bl1_plat_setup.c119
-rw-r--r--plat/hisilicon/poplar/bl2_plat_mem_params_desc.c168
-rw-r--r--plat/hisilicon/poplar/bl2_plat_setup.c219
-rw-r--r--plat/hisilicon/poplar/bl31_plat_setup.c137
-rw-r--r--plat/hisilicon/poplar/include/hi3798cv200.h105
-rw-r--r--plat/hisilicon/poplar/include/plat_macros.S10
-rw-r--r--plat/hisilicon/poplar/include/plat_private.h37
-rw-r--r--plat/hisilicon/poplar/include/platform_def.h171
-rw-r--r--plat/hisilicon/poplar/include/poplar_layout.h132
-rw-r--r--plat/hisilicon/poplar/plat_pm.c173
-rw-r--r--plat/hisilicon/poplar/plat_storage.c254
-rw-r--r--plat/hisilicon/poplar/plat_topology.c33
-rw-r--r--plat/hisilicon/poplar/platform.mk112
-rw-r--r--plat/hisilicon/poplar/poplar_gicv2.c63
-rw-r--r--plat/hisilicon/poplar/poplar_image_load.c34
-rw-r--r--plat/imx/common/aarch32/imx_uart_console.S50
-rw-r--r--plat/imx/common/imx7_clock.c55
-rw-r--r--plat/imx/common/imx8_helpers.S125
-rw-r--r--plat/imx/common/imx8_psci.c62
-rw-r--r--plat/imx/common/imx8_topology.c40
-rw-r--r--plat/imx/common/imx_aips.c57
-rw-r--r--plat/imx/common/imx_caam.c24
-rw-r--r--plat/imx/common/imx_clock.c155
-rw-r--r--plat/imx/common/imx_csu.c19
-rw-r--r--plat/imx/common/imx_ehf.c22
-rw-r--r--plat/imx/common/imx_io_mux.c24
-rw-r--r--plat/imx/common/imx_io_storage.c301
-rw-r--r--plat/imx/common/imx_sdei.c32
-rw-r--r--plat/imx/common/imx_sip_handler.c255
-rw-r--r--plat/imx/common/imx_sip_svc.c85
-rw-r--r--plat/imx/common/imx_snvs.c22
-rw-r--r--plat/imx/common/imx_uart_console.S88
-rw-r--r--plat/imx/common/imx_wdog.c25
-rw-r--r--plat/imx/common/include/imx8_iomux.h25
-rw-r--r--plat/imx/common/include/imx8_lpuart.h61
-rw-r--r--plat/imx/common/include/imx8qm_pads.h293
-rw-r--r--plat/imx/common/include/imx8qx_pads.h198
-rw-r--r--plat/imx/common/include/imx_aips.h22
-rw-r--r--plat/imx/common/include/imx_caam.h70
-rw-r--r--plat/imx/common/include/imx_clock.h1003
-rw-r--r--plat/imx/common/include/imx_csu.h44
-rw-r--r--plat/imx/common/include/imx_hab.h33
-rw-r--r--plat/imx/common/include/imx_io_mux.h652
-rw-r--r--plat/imx/common/include/imx_sip_svc.h94
-rw-r--r--plat/imx/common/include/imx_snvs.h84
-rw-r--r--plat/imx/common/include/imx_uart.h18
-rw-r--r--plat/imx/common/include/imx_wdog.h62
-rw-r--r--plat/imx/common/include/plat_imx8.h35
-rw-r--r--plat/imx/common/include/plat_macros.S34
-rw-r--r--plat/imx/common/include/sci/sci.h21
-rw-r--r--plat/imx/common/include/sci/sci_ipc.h67
-rw-r--r--plat/imx/common/include/sci/sci_rpc.h128
-rw-r--r--plat/imx/common/include/sci/sci_scfw.h36
-rw-r--r--plat/imx/common/include/sci/sci_types.h849
-rw-r--r--plat/imx/common/include/sci/svc/misc/sci_misc_api.h539
-rw-r--r--plat/imx/common/include/sci/svc/pad/sci_pad_api.h572
-rw-r--r--plat/imx/common/include/sci/svc/pm/sci_pm_api.h684
-rw-r--r--plat/imx/common/include/sci/svc/rm/sci_rm_api.h757
-rw-r--r--plat/imx/common/include/sci/svc/timer/sci_timer_api.h358
-rw-r--r--plat/imx/common/lpuart_console.S76
-rw-r--r--plat/imx/common/plat_imx8_gic.c114
-rw-r--r--plat/imx/common/sci/imx8_mu.c73
-rw-r--r--plat/imx/common/sci/imx8_mu.h36
-rw-r--r--plat/imx/common/sci/ipc.c120
-rw-r--r--plat/imx/common/sci/sci_api.mk13
-rw-r--r--plat/imx/common/sci/svc/misc/misc_rpc_clnt.c506
-rw-r--r--plat/imx/common/sci/svc/misc/sci_misc_rpc.h76
-rw-r--r--plat/imx/common/sci/svc/pad/pad_rpc_clnt.c454
-rw-r--r--plat/imx/common/sci/svc/pad/sci_pad_rpc.h66
-rw-r--r--plat/imx/common/sci/svc/pm/pm_rpc_clnt.c459
-rw-r--r--plat/imx/common/sci/svc/pm/sci_pm_rpc.h71
-rw-r--r--plat/imx/common/sci/svc/rm/rm_rpc_clnt.c639
-rw-r--r--plat/imx/common/sci/svc/rm/sci_rm_rpc.h81
-rw-r--r--plat/imx/common/sci/svc/timer/sci_timer_rpc.h69
-rw-r--r--plat/imx/common/sci/svc/timer/timer_rpc_clnt.c396
-rw-r--r--plat/imx/imx7/common/imx7.mk112
-rw-r--r--plat/imx/imx7/common/imx7_bl2_el3_common.c198
-rw-r--r--plat/imx/imx7/common/imx7_bl2_mem_params_desc.c81
-rw-r--r--plat/imx/imx7/common/imx7_helpers.S59
-rw-r--r--plat/imx/imx7/common/imx7_image_load.c24
-rw-r--r--plat/imx/imx7/common/imx7_rotpk.S15
-rw-r--r--plat/imx/imx7/common/imx7_trusted_boot.c36
-rw-r--r--plat/imx/imx7/include/imx7_def.h20
-rw-r--r--plat/imx/imx7/include/imx_hab_arch.h12
-rw-r--r--plat/imx/imx7/include/imx_regs.h108
-rw-r--r--plat/imx/imx7/picopi/include/platform_def.h204
-rw-r--r--plat/imx/imx7/picopi/picopi_bl2_el3_setup.c134
-rw-r--r--plat/imx/imx7/picopi/platform.mk40
-rw-r--r--plat/imx/imx7/warp7/include/platform_def.h218
-rw-r--r--plat/imx/imx7/warp7/platform.mk37
-rw-r--r--plat/imx/imx7/warp7/warp7_bl2_el3_setup.c143
-rw-r--r--plat/imx/imx8m/ddr/clock.c136
-rw-r--r--plat/imx/imx8m/ddr/ddr4_dvfs.c241
-rw-r--r--plat/imx/imx8m/ddr/dram.c263
-rw-r--r--plat/imx/imx8m/ddr/dram_retention.c203
-rw-r--r--plat/imx/imx8m/ddr/lpddr4_dvfs.c292
-rw-r--r--plat/imx/imx8m/gpc_common.c308
-rw-r--r--plat/imx/imx8m/imx8m_caam.c48
-rw-r--r--plat/imx/imx8m/imx8m_csu.c56
-rw-r--r--plat/imx/imx8m/imx8m_dyn_cfg_helpers.c201
-rw-r--r--plat/imx/imx8m/imx8m_image_load.c26
-rw-r--r--plat/imx/imx8m/imx8m_measured_boot.c85
-rw-r--r--plat/imx/imx8m/imx8m_psci_common.c259
-rw-r--r--plat/imx/imx8m/imx8mm/gpc.c414
-rw-r--r--plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c143
-rw-r--r--plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c94
-rw-r--r--plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c252
-rw-r--r--plat/imx/imx8m/imx8mm/imx8mm_psci.c45
-rw-r--r--plat/imx/imx8m/imx8mm/imx8mm_rotpk.S15
-rw-r--r--plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c36
-rw-r--r--plat/imx/imx8m/imx8mm/include/gpc_reg.h129
-rw-r--r--plat/imx/imx8m/imx8mm/include/imx8mm_private.h15
-rw-r--r--plat/imx/imx8m/imx8mm/include/imx_sec_def.h216
-rw-r--r--plat/imx/imx8m/imx8mm/include/platform_def.h176
-rw-r--r--plat/imx/imx8m/imx8mm/platform.mk185
-rw-r--r--plat/imx/imx8m/imx8mn/gpc.c207
-rw-r--r--plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c249
-rw-r--r--plat/imx/imx8m/imx8mn/imx8mn_psci.c44
-rw-r--r--plat/imx/imx8m/imx8mn/include/gpc_reg.h111
-rw-r--r--plat/imx/imx8m/imx8mn/include/imx_sec_def.h210
-rw-r--r--plat/imx/imx8m/imx8mn/include/platform_def.h162
-rw-r--r--plat/imx/imx8m/imx8mn/platform.mk77
-rw-r--r--plat/imx/imx8m/imx8mp/gpc.c385
-rw-r--r--plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c117
-rw-r--r--plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c94
-rw-r--r--plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c248
-rw-r--r--plat/imx/imx8m/imx8mp/imx8mp_psci.c44
-rw-r--r--plat/imx/imx8m/imx8mp/imx8mp_rotpk.S15
-rw-r--r--plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c36
-rw-r--r--plat/imx/imx8m/imx8mp/include/gpc_reg.h151
-rw-r--r--plat/imx/imx8m/imx8mp/include/imx8mp_private.h15
-rw-r--r--plat/imx/imx8m/imx8mp/include/imx_sec_def.h274
-rw-r--r--plat/imx/imx8m/imx8mp/include/platform_def.h203
-rw-r--r--plat/imx/imx8m/imx8mp/platform.mk168
-rw-r--r--plat/imx/imx8m/imx8mq/gpc.c189
-rw-r--r--plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c242
-rw-r--r--plat/imx/imx8m/imx8mq/imx8mq_psci.c133
-rw-r--r--plat/imx/imx8m/imx8mq/include/gpc_reg.h89
-rw-r--r--plat/imx/imx8m/imx8mq/include/imx_sec_def.h249
-rw-r--r--plat/imx/imx8m/imx8mq/include/platform_def.h132
-rw-r--r--plat/imx/imx8m/imx8mq/platform.mk57
-rw-r--r--plat/imx/imx8m/imx_aipstz.c24
-rw-r--r--plat/imx/imx8m/imx_hab.c124
-rw-r--r--plat/imx/imx8m/imx_rdc.c37
-rw-r--r--plat/imx/imx8m/include/ddrc.h336
-rw-r--r--plat/imx/imx8m/include/dram.h78
-rw-r--r--plat/imx/imx8m/include/gpc.h75
-rw-r--r--plat/imx/imx8m/include/imx8m_caam.h35
-rw-r--r--plat/imx/imx8m/include/imx8m_csu.h74
-rw-r--r--plat/imx/imx8m/include/imx8m_measured_boot.h16
-rw-r--r--plat/imx/imx8m/include/imx8m_psci.h24
-rw-r--r--plat/imx/imx8m/include/imx_aipstz.h27
-rw-r--r--plat/imx/imx8m/include/imx_rdc.h73
-rw-r--r--plat/imx/imx8qm/imx8qm_bl31_setup.c415
-rw-r--r--plat/imx/imx8qm/imx8qm_psci.c326
-rw-r--r--plat/imx/imx8qm/include/platform_def.h79
-rw-r--r--plat/imx/imx8qm/include/sec_rsrc.h32
-rw-r--r--plat/imx/imx8qm/platform.mk50
-rw-r--r--plat/imx/imx8qx/imx8qx_bl31_setup.c383
-rw-r--r--plat/imx/imx8qx/imx8qx_psci.c246
-rw-r--r--plat/imx/imx8qx/include/platform_def.h68
-rw-r--r--plat/imx/imx8qx/include/sec_rsrc.h25
-rw-r--r--plat/imx/imx8qx/platform.mk42
-rw-r--r--plat/intel/soc/agilex/bl2_plat_setup.c189
-rw-r--r--plat/intel/soc/agilex/bl31_plat_setup.c160
-rw-r--r--plat/intel/soc/agilex/include/agilex_clock_manager.h131
-rw-r--r--plat/intel/soc/agilex/include/agilex_memory_controller.h163
-rw-r--r--plat/intel/soc/agilex/include/agilex_mmc.h7
-rw-r--r--plat/intel/soc/agilex/include/agilex_pinmux.h20
-rw-r--r--plat/intel/soc/agilex/include/socfpga_plat_def.h40
-rw-r--r--plat/intel/soc/agilex/platform.mk83
-rw-r--r--plat/intel/soc/agilex/soc/agilex_clock_manager.c399
-rw-r--r--plat/intel/soc/agilex/soc/agilex_memory_controller.c399
-rw-r--r--plat/intel/soc/agilex/soc/agilex_mmc.c19
-rw-r--r--plat/intel/soc/agilex/soc/agilex_pinmux.c225
-rw-r--r--plat/intel/soc/common/aarch64/plat_helpers.S150
-rw-r--r--plat/intel/soc/common/aarch64/platform_common.c60
-rw-r--r--plat/intel/soc/common/bl2_plat_mem_params_desc.c96
-rw-r--r--plat/intel/soc/common/drivers/ccu/ncore_ccu.c132
-rw-r--r--plat/intel/soc/common/drivers/ccu/ncore_ccu.h109
-rw-r--r--plat/intel/soc/common/drivers/qspi/cadence_qspi.c822
-rw-r--r--plat/intel/soc/common/drivers/qspi/cadence_qspi.h178
-rw-r--r--plat/intel/soc/common/drivers/wdt/watchdog.c52
-rw-r--r--plat/intel/soc/common/drivers/wdt/watchdog.h39
-rw-r--r--plat/intel/soc/common/include/plat_macros.S22
-rw-r--r--plat/intel/soc/common/include/platform_def.h242
-rw-r--r--plat/intel/soc/common/include/socfpga_emac.h24
-rw-r--r--plat/intel/soc/common/include/socfpga_f2sdram_manager.h39
-rw-r--r--plat/intel/soc/common/include/socfpga_fcs.h308
-rw-r--r--plat/intel/soc/common/include/socfpga_handoff.h135
-rw-r--r--plat/intel/soc/common/include/socfpga_mailbox.h240
-rw-r--r--plat/intel/soc/common/include/socfpga_noc.h95
-rw-r--r--plat/intel/soc/common/include/socfpga_private.h68
-rw-r--r--plat/intel/soc/common/include/socfpga_reset_manager.h125
-rw-r--r--plat/intel/soc/common/include/socfpga_sip_svc.h217
-rw-r--r--plat/intel/soc/common/include/socfpga_system_manager.h54
-rw-r--r--plat/intel/soc/common/sip/socfpga_sip_ecc.c46
-rw-r--r--plat/intel/soc/common/sip/socfpga_sip_fcs.c1739
-rw-r--r--plat/intel/soc/common/soc/socfpga_emac.c38
-rw-r--r--plat/intel/soc/common/soc/socfpga_firewall.c123
-rw-r--r--plat/intel/soc/common/soc/socfpga_handoff.c39
-rw-r--r--plat/intel/soc/common/soc/socfpga_mailbox.c647
-rw-r--r--plat/intel/soc/common/soc/socfpga_reset_manager.c331
-rw-r--r--plat/intel/soc/common/socfpga_delay_timer.c49
-rw-r--r--plat/intel/soc/common/socfpga_image_load.c58
-rw-r--r--plat/intel/soc/common/socfpga_psci.c229
-rw-r--r--plat/intel/soc/common/socfpga_sip_svc.c1131
-rw-r--r--plat/intel/soc/common/socfpga_sip_svc_v2.c174
-rw-r--r--plat/intel/soc/common/socfpga_storage.c193
-rw-r--r--plat/intel/soc/common/socfpga_topology.c51
-rw-r--r--plat/intel/soc/n5x/bl31_plat_setup.c165
-rw-r--r--plat/intel/soc/n5x/include/socfpga_plat_def.h42
-rw-r--r--plat/intel/soc/n5x/platform.mk52
-rw-r--r--plat/intel/soc/stratix10/bl2_plat_setup.c188
-rw-r--r--plat/intel/soc/stratix10/bl31_plat_setup.c173
-rw-r--r--plat/intel/soc/stratix10/include/s10_clock_manager.h99
-rw-r--r--plat/intel/soc/stratix10/include/s10_memory_controller.h160
-rw-r--r--plat/intel/soc/stratix10/include/s10_mmc.h12
-rw-r--r--plat/intel/soc/stratix10/include/s10_pinmux.h20
-rw-r--r--plat/intel/soc/stratix10/include/socfpga_plat_def.h40
-rw-r--r--plat/intel/soc/stratix10/platform.mk80
-rw-r--r--plat/intel/soc/stratix10/soc/s10_clock_manager.c322
-rw-r--r--plat/intel/soc/stratix10/soc/s10_memory_controller.c412
-rw-r--r--plat/intel/soc/stratix10/soc/s10_mmc.c19
-rw-r--r--plat/intel/soc/stratix10/soc/s10_pinmux.c217
-rw-r--r--plat/marvell/armada/a3k/a3700/board/pm_src.c37
-rw-r--r--plat/marvell/armada/a3k/a3700/mvebu_def.h13
-rw-r--r--plat/marvell/armada/a3k/a3700/plat_bl31_setup.c70
-rw-r--r--plat/marvell/armada/a3k/a3700/platform.mk10
-rw-r--r--plat/marvell/armada/a3k/common/a3700_common.mk247
-rw-r--r--plat/marvell/armada/a3k/common/a3700_ea.c78
-rw-r--r--plat/marvell/armada/a3k/common/a3700_sip_svc.c84
-rw-r--r--plat/marvell/armada/a3k/common/aarch64/a3700_clock.S35
-rw-r--r--plat/marvell/armada/a3k/common/aarch64/a3700_common.c53
-rw-r--r--plat/marvell/armada/a3k/common/aarch64/plat_helpers.S68
-rw-r--r--plat/marvell/armada/a3k/common/cm3_system_reset.c62
-rw-r--r--plat/marvell/armada/a3k/common/dram_win.c282
-rw-r--r--plat/marvell/armada/a3k/common/include/a3700_plat_def.h169
-rw-r--r--plat/marvell/armada/a3k/common/include/a3700_pm.h53
-rw-r--r--plat/marvell/armada/a3k/common/include/ddr_info.h14
-rw-r--r--plat/marvell/armada/a3k/common/include/dram_win.h18
-rw-r--r--plat/marvell/armada/a3k/common/include/io_addr_dec.h66
-rw-r--r--plat/marvell/armada/a3k/common/include/plat_macros.S26
-rw-r--r--plat/marvell/armada/a3k/common/include/platform_def.h228
-rw-r--r--plat/marvell/armada/a3k/common/io_addr_dec.c175
-rw-r--r--plat/marvell/armada/a3k/common/marvell_plat_config.c34
-rw-r--r--plat/marvell/armada/a3k/common/plat_cci.c35
-rw-r--r--plat/marvell/armada/a3k/common/plat_pm.c822
-rw-r--r--plat/marvell/armada/a8k/a70x0/board/dram_port.c91
-rw-r--r--plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c151
-rw-r--r--plat/marvell/armada/a8k/a70x0/mvebu_def.h15
-rw-r--r--plat/marvell/armada/a8k/a70x0/platform.mk20
-rw-r--r--plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c91
-rw-r--r--plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c148
-rw-r--r--plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h31
-rw-r--r--plat/marvell/armada/a8k/a70x0_amc/platform.mk20
-rw-r--r--plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c227
-rw-r--r--plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c145
-rw-r--r--plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h87
-rw-r--r--plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h15
-rw-r--r--plat/marvell/armada/a8k/a70x0_mochabin/platform.mk20
-rw-r--r--plat/marvell/armada/a8k/a80x0/board/dram_port.c147
-rw-r--r--plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c202
-rw-r--r--plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h192
-rw-r--r--plat/marvell/armada/a8k/a80x0/mvebu_def.h17
-rw-r--r--plat/marvell/armada/a8k/a80x0/platform.mk20
-rw-r--r--plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c131
-rw-r--r--plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c200
-rw-r--r--plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h17
-rw-r--r--plat/marvell/armada/a8k/a80x0_mcbin/platform.mk20
-rw-r--r--plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c140
-rw-r--r--plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c201
-rw-r--r--plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c59
-rw-r--r--plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h17
-rw-r--r--plat/marvell/armada/a8k/a80x0_puzzle/platform.mk20
-rw-r--r--plat/marvell/armada/a8k/common/a8k_common.mk192
-rw-r--r--plat/marvell/armada/a8k/common/aarch64/a8k_common.c70
-rw-r--r--plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c95
-rw-r--r--plat/marvell/armada/a8k/common/aarch64/plat_helpers.S112
-rw-r--r--plat/marvell/armada/a8k/common/ble/ble.ld.S76
-rw-r--r--plat/marvell/armada/a8k/common/ble/ble.mk35
-rw-r--r--plat/marvell/armada/a8k/common/ble/ble_main.c99
-rw-r--r--plat/marvell/armada/a8k/common/ble/ble_mem.S30
-rw-r--r--plat/marvell/armada/a8k/common/include/a8k_plat_def.h195
-rw-r--r--plat/marvell/armada/a8k/common/include/ddr_info.h9
-rw-r--r--plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h33
-rw-r--r--plat/marvell/armada/a8k/common/include/plat_macros.S20
-rw-r--r--plat/marvell/armada/a8k/common/include/platform_def.h196
-rw-r--r--plat/marvell/armada/a8k/common/mss/mss_a8k.mk22
-rw-r--r--plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c165
-rw-r--r--plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c37
-rw-r--r--plat/marvell/armada/a8k/common/mss/mss_defs.h33
-rw-r--r--plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c85
-rw-r--r--plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h35
-rw-r--r--plat/marvell/armada/a8k/common/plat_bl1_setup.c19
-rw-r--r--plat/marvell/armada/a8k/common/plat_bl31_setup.c148
-rw-r--r--plat/marvell/armada/a8k/common/plat_ble_setup.c765
-rw-r--r--plat/marvell/armada/a8k/common/plat_pm.c853
-rw-r--r--plat/marvell/armada/a8k/common/plat_pm_trace.c94
-rw-r--r--plat/marvell/armada/a8k/common/plat_thermal.c130
-rw-r--r--plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c168
-rw-r--r--plat/marvell/armada/common/aarch64/marvell_common.c137
-rw-r--r--plat/marvell/armada/common/aarch64/marvell_helpers.S259
-rw-r--r--plat/marvell/armada/common/marvell_bl1_setup.c105
-rw-r--r--plat/marvell/armada/common/marvell_bl2_setup.c158
-rw-r--r--plat/marvell/armada/common/marvell_bl31_setup.c237
-rw-r--r--plat/marvell/armada/common/marvell_cci.c52
-rw-r--r--plat/marvell/armada/common/marvell_common.mk99
-rw-r--r--plat/marvell/armada/common/marvell_console.c77
-rw-r--r--plat/marvell/armada/common/marvell_ddr_info.c112
-rw-r--r--plat/marvell/armada/common/marvell_gicv2.c148
-rw-r--r--plat/marvell/armada/common/marvell_gicv3.c210
-rw-r--r--plat/marvell/armada/common/marvell_image_load.c36
-rw-r--r--plat/marvell/armada/common/marvell_io_storage.c227
-rw-r--r--plat/marvell/armada/common/marvell_pm.c60
-rw-r--r--plat/marvell/armada/common/marvell_topology.c84
-rw-r--r--plat/marvell/armada/common/mrvl_sip_svc.c188
-rw-r--r--plat/marvell/armada/common/mss/mss_common.mk20
-rw-r--r--plat/marvell/armada/common/mss/mss_ipc_drv.c113
-rw-r--r--plat/marvell/armada/common/mss/mss_ipc_drv.h120
-rw-r--r--plat/marvell/armada/common/mss/mss_mem.h60
-rw-r--r--plat/marvell/armada/common/mss/mss_scp_bl2_format.h45
-rw-r--r--plat/marvell/armada/common/mss/mss_scp_bootloader.c368
-rw-r--r--plat/marvell/armada/common/mss/mss_scp_bootloader.h20
-rw-r--r--plat/marvell/armada/common/plat_delay_timer.c34
-rw-r--r--plat/marvell/marvell.mk21
-rw-r--r--plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c158
-rw-r--r--plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c192
-rw-r--r--plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h145
-rw-r--r--plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h25
-rw-r--r--plat/marvell/octeontx/otx2/t91/t9130/platform.mk20
-rw-r--r--plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c224
-rw-r--r--plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk33
-rw-r--r--plat/mediatek/build_helpers/conditional_eval_options.mk51
-rw-r--r--plat/mediatek/build_helpers/mtk_build_helpers.mk142
-rw-r--r--plat/mediatek/build_helpers/mtk_build_helpers_epilogue.mk30
-rw-r--r--plat/mediatek/build_helpers/options.mk25
-rw-r--r--plat/mediatek/common/common_config.mk34
-rw-r--r--plat/mediatek/common/coreboot_config.mk15
-rw-r--r--plat/mediatek/common/lpm/mt_lp_rm.c110
-rw-r--r--plat/mediatek/common/lpm/mt_lp_rm.h42
-rw-r--r--plat/mediatek/common/lpm/rules.mk14
-rw-r--r--plat/mediatek/common/mtk_bl31_setup.c175
-rw-r--r--plat/mediatek/common/mtk_plat_common.c65
-rw-r--r--plat/mediatek/common/mtk_plat_common.h47
-rw-r--r--plat/mediatek/common/mtk_sip_svc.c129
-rw-r--r--plat/mediatek/common/mtk_smc_handlers.c235
-rw-r--r--plat/mediatek/common/params_setup.c35
-rw-r--r--plat/mediatek/common/plat_params.h17
-rw-r--r--plat/mediatek/common/rules.mk15
-rw-r--r--plat/mediatek/drivers/audio/audio.c43
-rw-r--r--plat/mediatek/drivers/audio/audio.h30
-rw-r--r--plat/mediatek/drivers/audio/mt8188/audio_domain.c44
-rw-r--r--plat/mediatek/drivers/audio/mt8188/mt_audio_private.h20
-rw-r--r--plat/mediatek/drivers/audio/mt8188/rules.mk13
-rw-r--r--plat/mediatek/drivers/audio/rules.mk19
-rw-r--r--plat/mediatek/drivers/cirq/mt_cirq.c549
-rw-r--r--plat/mediatek/drivers/cirq/mt_cirq.h122
-rw-r--r--plat/mediatek/drivers/cirq/rules.mk14
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.c466
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.h119
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c253
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.h100
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.c95
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.h78
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c93
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.h27
-rw-r--r--plat/mediatek/drivers/cpu_pm/cpcv3_2/rules.mk19
-rw-r--r--plat/mediatek/drivers/cpu_pm/rules.mk13
-rw-r--r--plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.c402
-rw-r--r--plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.h59
-rw-r--r--plat/mediatek/drivers/dcm/mtk_dcm.c84
-rw-r--r--plat/mediatek/drivers/dcm/mtk_dcm.h15
-rw-r--r--plat/mediatek/drivers/dcm/rules.mk17
-rw-r--r--plat/mediatek/drivers/dfd/dfd.c43
-rw-r--r--plat/mediatek/drivers/dfd/dfd.h16
-rw-r--r--plat/mediatek/drivers/dfd/mt8188/plat_dfd.c82
-rw-r--r--plat/mediatek/drivers/dfd/mt8188/plat_dfd.h78
-rw-r--r--plat/mediatek/drivers/dfd/rules.mk17
-rw-r--r--plat/mediatek/drivers/dp/mt_dp.c79
-rw-r--r--plat/mediatek/drivers/dp/mt_dp.h28
-rw-r--r--plat/mediatek/drivers/dp/rules.mk14
-rw-r--r--plat/mediatek/drivers/emi_mpu/emi_mpu.h64
-rw-r--r--plat/mediatek/drivers/emi_mpu/emi_mpu_common.c123
-rw-r--r--plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c14
-rw-r--r--plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h45
-rw-r--r--plat/mediatek/drivers/emi_mpu/rules.mk16
-rw-r--r--plat/mediatek/drivers/gic600/mt_gic_v3.c208
-rw-r--r--plat/mediatek/drivers/gic600/mt_gic_v3.h28
-rw-r--r--plat/mediatek/drivers/gic600/rules.mk14
-rw-r--r--plat/mediatek/drivers/gpio/mt8188/mtgpio.c38
-rw-r--r--plat/mediatek/drivers/gpio/mt8188/mtgpio.h221
-rw-r--r--plat/mediatek/drivers/gpio/mtgpio_common.c302
-rw-r--r--plat/mediatek/drivers/gpio/mtgpio_common.h109
-rw-r--r--plat/mediatek/drivers/gpio/rules.mk18
-rw-r--r--plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c99
-rw-r--r--plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h24
-rw-r--r--plat/mediatek/drivers/iommu/mtk_iommu_priv.h44
-rw-r--r--plat/mediatek/drivers/iommu/mtk_iommu_smc.c125
-rw-r--r--plat/mediatek/drivers/iommu/rules.mk17
-rw-r--r--plat/mediatek/drivers/mcusys/mcusys.c15
-rw-r--r--plat/mediatek/drivers/mcusys/rules.mk15
-rw-r--r--plat/mediatek/drivers/mcusys/v1/mcucfg.h232
-rw-r--r--plat/mediatek/drivers/msdc/mt8186/mt_msdc_priv.h13
-rw-r--r--plat/mediatek/drivers/msdc/mt_msdc.c19
-rw-r--r--plat/mediatek/drivers/msdc/mt_msdc.h15
-rw-r--r--plat/mediatek/drivers/pmic/pmic.c13
-rw-r--r--plat/mediatek/drivers/pmic/pmic.h15
-rw-r--r--plat/mediatek/drivers/pmic/rules.mk15
-rw-r--r--plat/mediatek/drivers/pmic_wrap/mt8188/pmic_wrap_init.h30
-rw-r--r--plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c165
-rw-r--r--plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_common.h61
-rw-r--r--plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c143
-rw-r--r--plat/mediatek/drivers/pmic_wrap/rules.mk20
-rw-r--r--plat/mediatek/drivers/ptp3/mt8188/ptp3_plat.h47
-rw-r--r--plat/mediatek/drivers/ptp3/ptp3_common.c122
-rw-r--r--plat/mediatek/drivers/ptp3/ptp3_common.h21
-rw-r--r--plat/mediatek/drivers/ptp3/rules.mk16
-rw-r--r--plat/mediatek/drivers/rtc/mt8188/rtc.h12
-rw-r--r--plat/mediatek/drivers/rtc/rtc_common.c64
-rw-r--r--plat/mediatek/drivers/rtc/rtc_mt6359p.c148
-rw-r--r--plat/mediatek/drivers/rtc/rtc_mt6359p.h197
-rw-r--r--plat/mediatek/drivers/rtc/rules.mk20
-rw-r--r--plat/mediatek/drivers/timer/mt_timer.c44
-rw-r--r--plat/mediatek/drivers/timer/mt_timer.h35
-rw-r--r--plat/mediatek/drivers/timer/rules.mk14
-rw-r--r--plat/mediatek/drivers/uart/8250_console.S163
-rw-r--r--plat/mediatek/drivers/uart/uart.c112
-rw-r--r--plat/mediatek/drivers/uart/uart.h100
-rw-r--r--plat/mediatek/drivers/uart/uart8250.h38
-rw-r--r--plat/mediatek/helpers/armv8_2/arch_helpers.S118
-rw-r--r--plat/mediatek/helpers/rules.mk12
-rw-r--r--plat/mediatek/include/armv8_2/arch_def.h38
-rw-r--r--plat/mediatek/include/lib/mtk_init/mtk_init.h58
-rw-r--r--plat/mediatek/include/lib/mtk_init/mtk_init_def.h22
-rw-r--r--plat/mediatek/include/mtk_mmap_pool.h58
-rw-r--r--plat/mediatek/include/mtk_sip_def.h25
-rw-r--r--plat/mediatek/include/mtk_sip_svc.h106
-rw-r--r--plat/mediatek/include/plat.ld.rodata.inc30
-rw-r--r--plat/mediatek/include/vendor_pubsub_events.h21
-rw-r--r--plat/mediatek/lib/mtk_init/mtk_init.c39
-rw-r--r--plat/mediatek/lib/mtk_init/mtk_mmap_init.c55
-rw-r--r--plat/mediatek/lib/mtk_init/rules.mk14
-rw-r--r--plat/mediatek/lib/pm/armv8_2/pwr_ctrl.c543
-rw-r--r--plat/mediatek/lib/pm/armv8_2/rules.mk12
-rw-r--r--plat/mediatek/lib/pm/mtk_pm.c120
-rw-r--r--plat/mediatek/lib/pm/mtk_pm.h223
-rw-r--r--plat/mediatek/lib/pm/rules.mk17
-rw-r--r--plat/mediatek/lib/system_reset/reset_cros.c56
-rw-r--r--plat/mediatek/lib/system_reset/rules.mk14
-rw-r--r--plat/mediatek/mt8173/aarch64/plat_helpers.S49
-rw-r--r--plat/mediatek/mt8173/aarch64/platform_common.c89
-rw-r--r--plat/mediatek/mt8173/bl31_plat_setup.c146
-rw-r--r--plat/mediatek/mt8173/drivers/crypt/crypt.c123
-rw-r--r--plat/mediatek/mt8173/drivers/crypt/crypt.h16
-rw-r--r--plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c274
-rw-r--r--plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h18
-rw-r--r--plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h169
-rw-r--r--plat/mediatek/mt8173/drivers/rtc/rtc.c26
-rw-r--r--plat/mediatek/mt8173/drivers/rtc/rtc.h60
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm.c370
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm.h335
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm_hotplug.c275
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm_hotplug.h13
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm_mcdi.c503
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm_mcdi.h14
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm_suspend.c315
-rw-r--r--plat/mediatek/mt8173/drivers/spm/spm_suspend.h16
-rw-r--r--plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c34
-rw-r--r--plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h16
-rw-r--r--plat/mediatek/mt8173/drivers/wdt/wdt.c115
-rw-r--r--plat/mediatek/mt8173/drivers/wdt/wdt.h20
-rw-r--r--plat/mediatek/mt8173/include/mcucfg.h220
-rw-r--r--plat/mediatek/mt8173/include/mt8173_def.h140
-rw-r--r--plat/mediatek/mt8173/include/plat_macros.S78
-rw-r--r--plat/mediatek/mt8173/include/plat_private.h27
-rw-r--r--plat/mediatek/mt8173/include/plat_sip_calls.h23
-rw-r--r--plat/mediatek/mt8173/include/platform_def.h141
-rw-r--r--plat/mediatek/mt8173/include/power_tracer.h19
-rw-r--r--plat/mediatek/mt8173/include/scu.h13
-rw-r--r--plat/mediatek/mt8173/plat_mt_gic.c30
-rw-r--r--plat/mediatek/mt8173/plat_pm.c603
-rw-r--r--plat/mediatek/mt8173/plat_sip_calls.c115
-rw-r--r--plat/mediatek/mt8173/plat_topology.c60
-rw-r--r--plat/mediatek/mt8173/platform.mk75
-rw-r--r--plat/mediatek/mt8173/power_tracer.c48
-rw-r--r--plat/mediatek/mt8173/scu.c30
-rw-r--r--plat/mediatek/mt8183/aarch64/plat_helpers.S34
-rw-r--r--plat/mediatek/mt8183/aarch64/platform_common.c84
-rw-r--r--plat/mediatek/mt8183/bl31_plat_setup.c181
-rw-r--r--plat/mediatek/mt8183/drivers/devapc/devapc.c231
-rw-r--r--plat/mediatek/mt8183/drivers/devapc/devapc.h499
-rw-r--r--plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c147
-rw-r--r--plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h106
-rw-r--r--plat/mediatek/mt8183/drivers/gpio/mtgpio.c439
-rw-r--r--plat/mediatek/mt8183/drivers/gpio/mtgpio.h154
-rw-r--r--plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h208
-rw-r--r--plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c259
-rw-r--r--plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h34
-rw-r--r--plat/mediatek/mt8183/drivers/mcsi/mcsi.c211
-rw-r--r--plat/mediatek/mt8183/drivers/mcsi/mcsi.h116
-rw-r--r--plat/mediatek/mt8183/drivers/pmic/pmic.c42
-rw-r--r--plat/mediatek/mt8183/drivers/pmic/pmic.h30
-rw-r--r--plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h94
-rw-r--r--plat/mediatek/mt8183/drivers/rtc/rtc.c133
-rw-r--r--plat/mediatek/mt8183/drivers/rtc/rtc.h147
-rw-r--r--plat/mediatek/mt8183/drivers/spm/spm.c363
-rw-r--r--plat/mediatek/mt8183/drivers/spm/spm.h2552
-rw-r--r--plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c170
-rw-r--r--plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h50
-rw-r--r--plat/mediatek/mt8183/drivers/spm/spm_suspend.c255
-rw-r--r--plat/mediatek/mt8183/drivers/spm/spm_suspend.h13
-rw-r--r--plat/mediatek/mt8183/drivers/spmc/mtspmc.c366
-rw-r--r--plat/mediatek/mt8183/drivers/spmc/mtspmc.h42
-rw-r--r--plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h233
-rw-r--r--plat/mediatek/mt8183/drivers/sspm/sspm.c159
-rw-r--r--plat/mediatek/mt8183/drivers/sspm/sspm.h32
-rw-r--r--plat/mediatek/mt8183/drivers/timer/mt_timer.c29
-rw-r--r--plat/mediatek/mt8183/drivers/timer/mt_timer.h20
-rw-r--r--plat/mediatek/mt8183/include/mcucfg.h568
-rw-r--r--plat/mediatek/mt8183/include/mt_gic_v3.h34
-rw-r--r--plat/mediatek/mt8183/include/plat_dcm.h53
-rw-r--r--plat/mediatek/mt8183/include/plat_debug.h34
-rw-r--r--plat/mediatek/mt8183/include/plat_macros.S78
-rw-r--r--plat/mediatek/mt8183/include/plat_private.h28
-rw-r--r--plat/mediatek/mt8183/include/platform_def.h321
-rw-r--r--plat/mediatek/mt8183/include/power_tracer.h20
-rw-r--r--plat/mediatek/mt8183/include/scu.h13
-rw-r--r--plat/mediatek/mt8183/include/sspm_reg.h41
-rw-r--r--plat/mediatek/mt8183/plat_dcm.c112
-rw-r--r--plat/mediatek/mt8183/plat_debug.c58
-rw-r--r--plat/mediatek/mt8183/plat_mt_gic.c160
-rw-r--r--plat/mediatek/mt8183/plat_pm.c589
-rw-r--r--plat/mediatek/mt8183/plat_topology.c59
-rw-r--r--plat/mediatek/mt8183/platform.mk90
-rw-r--r--plat/mediatek/mt8183/scu.c56
-rw-r--r--plat/mediatek/mt8186/aarch64/plat_helpers.S45
-rw-r--r--plat/mediatek/mt8186/aarch64/platform_common.c44
-rw-r--r--plat/mediatek/mt8186/bl31_plat_setup.c113
-rw-r--r--plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c66
-rw-r--r--plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h14
-rw-r--r--plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c490
-rw-r--r--plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h58
-rw-r--r--plat/mediatek/mt8186/drivers/dfd/plat_dfd.c98
-rw-r--r--plat/mediatek/mt8186/drivers/dfd/plat_dfd.h64
-rw-r--r--plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c133
-rw-r--r--plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h98
-rw-r--r--plat/mediatek/mt8186/drivers/gpio/mtgpio.c44
-rw-r--r--plat/mediatek/mt8186/drivers/gpio/mtgpio.h230
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c149
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h34
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c269
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h102
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c74
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h15
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c150
-rw-r--r--plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h12
-rw-r--r--plat/mediatek/mt8186/drivers/pmic/pmic.c23
-rw-r--r--plat/mediatek/mt8186/drivers/pmic/pmic.h19
-rw-r--r--plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h61
-rw-r--r--plat/mediatek/mt8186/drivers/rtc/rtc.c133
-rw-r--r--plat/mediatek/mt8186/drivers/rtc/rtc.h145
-rw-r--r--plat/mediatek/mt8186/drivers/spm/build.mk78
-rw-r--r--plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c241
-rw-r--r--plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c105
-rw-r--r--plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c187
-rw-r--r--plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h48
-rw-r--r--plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c197
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm.c110
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm.h82
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c212
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h60
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c165
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h21
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h64
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c23
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h12
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c240
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h24
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c623
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h620
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c166
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h39
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h2957
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h26
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c286
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h28
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c533
-rw-r--r--plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h316
-rw-r--r--plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h23
-rw-r--r--plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h36
-rw-r--r--plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c41
-rw-r--r--plat/mediatek/mt8186/drivers/spm/pcm_def.h180
-rw-r--r--plat/mediatek/mt8186/drivers/spm/sleep_def.h146
-rw-r--r--plat/mediatek/mt8186/drivers/spmc/mtspmc.c172
-rw-r--r--plat/mediatek/mt8186/drivers/spmc/mtspmc.h31
-rw-r--r--plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h176
-rw-r--r--plat/mediatek/mt8186/include/mcucfg.h255
-rw-r--r--plat/mediatek/mt8186/include/mt_spm_resource_req.h32
-rw-r--r--plat/mediatek/mt8186/include/plat_helpers.h12
-rw-r--r--plat/mediatek/mt8186/include/plat_macros.S37
-rw-r--r--plat/mediatek/mt8186/include/plat_mtk_lpm.h49
-rw-r--r--plat/mediatek/mt8186/include/plat_pm.h128
-rw-r--r--plat/mediatek/mt8186/include/plat_private.h18
-rw-r--r--plat/mediatek/mt8186/include/plat_sip_calls.h15
-rw-r--r--plat/mediatek/mt8186/include/plat_uart.h25
-rw-r--r--plat/mediatek/mt8186/include/platform_def.h161
-rw-r--r--plat/mediatek/mt8186/include/sspm_reg.h21
-rw-r--r--plat/mediatek/mt8186/plat_pm.c400
-rw-r--r--plat/mediatek/mt8186/plat_sip_calls.c49
-rw-r--r--plat/mediatek/mt8186/plat_topology.c70
-rw-r--r--plat/mediatek/mt8186/platform.mk110
-rw-r--r--plat/mediatek/mt8188/include/plat_helpers.h12
-rw-r--r--plat/mediatek/mt8188/include/plat_macros.S38
-rw-r--r--plat/mediatek/mt8188/include/plat_private.h18
-rw-r--r--plat/mediatek/mt8188/include/platform_def.h183
-rw-r--r--plat/mediatek/mt8188/include/spm_reg.h499
-rw-r--r--plat/mediatek/mt8188/plat_config.mk48
-rw-r--r--plat/mediatek/mt8188/plat_mmap.c20
-rw-r--r--plat/mediatek/mt8188/platform.mk65
-rw-r--r--plat/mediatek/mt8192/aarch64/plat_helpers.S49
-rw-r--r--plat/mediatek/mt8192/aarch64/platform_common.c56
-rw-r--r--plat/mediatek/mt8192/bl31_plat_setup.c121
-rw-r--r--plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c68
-rw-r--r--plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h42
-rw-r--r--plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c571
-rw-r--r--plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h12
-rw-r--r--plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h110
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c63
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h14
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c562
-rw-r--r--plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h68
-rw-r--r--plat/mediatek/mt8192/drivers/devapc/devapc.c2847
-rw-r--r--plat/mediatek/mt8192/drivers/devapc/devapc.h211
-rw-r--r--plat/mediatek/mt8192/drivers/dfd/plat_dfd.c139
-rw-r--r--plat/mediatek/mt8192/drivers/dfd/plat_dfd.h70
-rw-r--r--plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c144
-rw-r--r--plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h102
-rw-r--r--plat/mediatek/mt8192/drivers/gpio/mtgpio.c53
-rw-r--r--plat/mediatek/mt8192/drivers/gpio/mtgpio.h269
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c149
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c269
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h106
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c150
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h14
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c151
-rw-r--r--plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h12
-rw-r--r--plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h30
-rw-r--r--plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h48
-rw-r--r--plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c84
-rw-r--r--plat/mediatek/mt8192/drivers/spm/build.mk68
-rw-r--r--plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c230
-rw-r--r--plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c104
-rw-r--r--plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c191
-rw-r--r--plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h45
-rw-r--r--plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c192
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm.c104
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm.h68
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c219
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h56
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c155
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h20
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h63
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c249
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h17
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c588
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h637
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c159
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h45
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h2919
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h25
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c303
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h26
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c405
-rw-r--r--plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h135
-rw-r--r--plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h21
-rw-r--r--plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h33
-rw-r--r--plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c47
-rw-r--r--plat/mediatek/mt8192/drivers/spm/pcm_def.h179
-rw-r--r--plat/mediatek/mt8192/drivers/spm/sleep_def.h151
-rw-r--r--plat/mediatek/mt8192/drivers/spmc/mtspmc.c177
-rw-r--r--plat/mediatek/mt8192/drivers/spmc/mtspmc.h31
-rw-r--r--plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h184
-rw-r--r--plat/mediatek/mt8192/include/mcucfg.h257
-rw-r--r--plat/mediatek/mt8192/include/plat_helpers.h12
-rw-r--r--plat/mediatek/mt8192/include/plat_macros.S38
-rw-r--r--plat/mediatek/mt8192/include/plat_mtk_lpm.h48
-rw-r--r--plat/mediatek/mt8192/include/plat_pm.h38
-rw-r--r--plat/mediatek/mt8192/include/plat_private.h18
-rw-r--r--plat/mediatek/mt8192/include/plat_sip_calls.h15
-rw-r--r--plat/mediatek/mt8192/include/platform_def.h151
-rw-r--r--plat/mediatek/mt8192/include/rtc.h12
-rw-r--r--plat/mediatek/mt8192/plat_pm.c398
-rw-r--r--plat/mediatek/mt8192/plat_sip_calls.c49
-rw-r--r--plat/mediatek/mt8192/plat_topology.c75
-rw-r--r--plat/mediatek/mt8192/platform.mk103
-rw-r--r--plat/mediatek/mt8195/aarch64/plat_helpers.S49
-rw-r--r--plat/mediatek/mt8195/aarch64/platform_common.c56
-rw-r--r--plat/mediatek/mt8195/bl31_plat_setup.c117
-rw-r--r--plat/mediatek/mt8195/drivers/apusys/apupll.c581
-rw-r--r--plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c341
-rw-r--r--plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h23
-rw-r--r--plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h195
-rw-r--r--plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c83
-rw-r--r--plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h51
-rw-r--r--plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c63
-rw-r--r--plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h14
-rw-r--r--plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c483
-rw-r--r--plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h59
-rw-r--r--plat/mediatek/mt8195/drivers/dfd/plat_dfd.c156
-rw-r--r--plat/mediatek/mt8195/drivers/dfd/plat_dfd.h85
-rw-r--r--plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c151
-rw-r--r--plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h98
-rw-r--r--plat/mediatek/mt8195/drivers/gpio/mtgpio.c44
-rw-r--r--plat/mediatek/mt8195/drivers/gpio/mtgpio.h183
-rw-r--r--plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c150
-rw-r--r--plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c269
-rw-r--r--plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h106
-rw-r--r--plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c69
-rw-r--r--plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h14
-rw-r--r--plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c151
-rw-r--r--plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h12
-rw-r--r--plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h30
-rw-r--r--plat/mediatek/mt8195/drivers/ptp3/ptp3_plat.h46
-rw-r--r--plat/mediatek/mt8195/drivers/spm/build.mk68
-rw-r--r--plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c241
-rw-r--r--plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c106
-rw-r--r--plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c201
-rw-r--r--plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h43
-rw-r--r--plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c200
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm.c98
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm.h68
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c235
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h73
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c155
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h20
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h63
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c346
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h17
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c550
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h583
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c159
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h45
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h2859
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h25
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c394
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h26
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c526
-rw-r--r--plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h328
-rw-r--r--plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h21
-rw-r--r--plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h33
-rw-r--r--plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c38
-rw-r--r--plat/mediatek/mt8195/drivers/spm/pcm_def.h179
-rw-r--r--plat/mediatek/mt8195/drivers/spm/sleep_def.h151
-rw-r--r--plat/mediatek/mt8195/drivers/spmc/mtspmc.c166
-rw-r--r--plat/mediatek/mt8195/drivers/spmc/mtspmc.h31
-rw-r--r--plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h183
-rw-r--r--plat/mediatek/mt8195/include/mcucfg.h257
-rw-r--r--plat/mediatek/mt8195/include/plat_helpers.h12
-rw-r--r--plat/mediatek/mt8195/include/plat_macros.S37
-rw-r--r--plat/mediatek/mt8195/include/plat_mtk_lpm.h48
-rw-r--r--plat/mediatek/mt8195/include/plat_pm.h38
-rw-r--r--plat/mediatek/mt8195/include/plat_private.h18
-rw-r--r--plat/mediatek/mt8195/include/plat_sip_calls.h15
-rw-r--r--plat/mediatek/mt8195/include/platform_def.h168
-rw-r--r--plat/mediatek/mt8195/include/rtc.h12
-rw-r--r--plat/mediatek/mt8195/plat_pm.c403
-rw-r--r--plat/mediatek/mt8195/plat_sip_calls.c56
-rw-r--r--plat/mediatek/mt8195/plat_topology.c70
-rw-r--r--plat/mediatek/mt8195/platform.mk113
-rw-r--r--plat/mediatek/topology/armv8_2/topology.c28
-rw-r--r--plat/mediatek/topology/rules.mk12
-rw-r--r--plat/nvidia/tegra/common/aarch64/tegra_helpers.S428
-rw-r--r--plat/nvidia/tegra/common/tegra_bl31_setup.c366
-rw-r--r--plat/nvidia/tegra/common/tegra_common.mk59
-rw-r--r--plat/nvidia/tegra/common/tegra_delay_timer.c57
-rw-r--r--plat/nvidia/tegra/common/tegra_fiq_glue.c149
-rw-r--r--plat/nvidia/tegra/common/tegra_gicv2.c72
-rw-r--r--plat/nvidia/tegra/common/tegra_gicv3.c79
-rw-r--r--plat/nvidia/tegra/common/tegra_io_storage.c20
-rw-r--r--plat/nvidia/tegra/common/tegra_platform.c309
-rw-r--r--plat/nvidia/tegra/common/tegra_pm.c329
-rw-r--r--plat/nvidia/tegra/common/tegra_sdei.c56
-rw-r--r--plat/nvidia/tegra/common/tegra_sip_calls.c158
-rw-r--r--plat/nvidia/tegra/common/tegra_stack_protector.c28
-rw-r--r--plat/nvidia/tegra/drivers/bpmp/bpmp.c231
-rw-r--r--plat/nvidia/tegra/drivers/bpmp_ipc/intf.c345
-rw-r--r--plat/nvidia/tegra/drivers/bpmp_ipc/intf.h127
-rw-r--r--plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c654
-rw-r--r--plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h50
-rw-r--r--plat/nvidia/tegra/drivers/flowctrl/flowctrl.c322
-rw-r--r--plat/nvidia/tegra/drivers/gpcdma/gpcdma.c188
-rw-r--r--plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c212
-rw-r--r--plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c354
-rw-r--r--plat/nvidia/tegra/drivers/pmc/pmc.c153
-rw-r--r--plat/nvidia/tegra/drivers/smmu/smmu.c121
-rw-r--r--plat/nvidia/tegra/drivers/spe/shared_console.S187
-rw-r--r--plat/nvidia/tegra/include/drivers/bpmp.h127
-rw-r--r--plat/nvidia/tegra/include/drivers/bpmp_ipc.h43
-rw-r--r--plat/nvidia/tegra/include/drivers/flowctrl.h98
-rw-r--r--plat/nvidia/tegra/include/drivers/gpcdma.h17
-rw-r--r--plat/nvidia/tegra/include/drivers/mce.h76
-rw-r--r--plat/nvidia/tegra/include/drivers/memctrl.h18
-rw-r--r--plat/nvidia/tegra/include/drivers/memctrl_v1.h57
-rw-r--r--plat/nvidia/tegra/include/drivers/memctrl_v2.h107
-rw-r--r--plat/nvidia/tegra/include/drivers/pmc.h72
-rw-r--r--plat/nvidia/tegra/include/drivers/security_engine.h60
-rw-r--r--plat/nvidia/tegra/include/drivers/smmu.h92
-rw-r--r--plat/nvidia/tegra/include/drivers/spe.h23
-rw-r--r--plat/nvidia/tegra/include/drivers/tegra_gic.h30
-rw-r--r--plat/nvidia/tegra/include/lib/profiler.h20
-rw-r--r--plat/nvidia/tegra/include/plat_macros.S63
-rw-r--r--plat/nvidia/tegra/include/platform_def.h132
-rw-r--r--plat/nvidia/tegra/include/t186/tegra186_private.h12
-rw-r--r--plat/nvidia/tegra/include/t186/tegra_def.h327
-rw-r--r--plat/nvidia/tegra/include/t186/tegra_mc_def.h398
-rw-r--r--plat/nvidia/tegra/include/t194/tegra194_private.h16
-rw-r--r--plat/nvidia/tegra/include/t194/tegra194_ras_private.h263
-rw-r--r--plat/nvidia/tegra/include/t194/tegra_def.h326
-rw-r--r--plat/nvidia/tegra/include/t210/tegra_def.h293
-rw-r--r--plat/nvidia/tegra/include/tegra_platform.h70
-rw-r--r--plat/nvidia/tegra/include/tegra_private.h158
-rw-r--r--plat/nvidia/tegra/lib/debug/profiler.c144
-rw-r--r--plat/nvidia/tegra/platform.mk97
-rw-r--r--plat/nvidia/tegra/scat/bl31.scat284
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h260
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h437
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S31
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/mce/ari.c564
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/mce/mce.c476
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c256
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/se/se.c277
-rw-r--r--plat/nvidia/tegra/soc/t186/drivers/se/se_private.h100
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_memctrl.c700
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_psci_handlers.c472
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_secondary.c41
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_setup.c397
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_sip_calls.c159
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_smmu.c22
-rw-r--r--plat/nvidia/tegra/soc/t186/plat_trampoline.S41
-rw-r--r--plat/nvidia/tegra/soc/t186/platform_t186.mk77
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h79
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/include/se.h15
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h429
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S52
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/mce/mce.c255
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c262
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/se/se.c511
-rw-r--r--plat/nvidia/tegra/soc/t194/drivers/se/se_private.h165
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_memctrl.c83
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_psci_handlers.c505
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_ras.c493
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_secondary.c75
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_setup.c449
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_sip_calls.c103
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_smmu.c35
-rw-r--r--plat/nvidia/tegra/soc/t194/plat_trampoline.S150
-rw-r--r--plat/nvidia/tegra/soc/t194/platform_t194.mk85
-rw-r--r--plat/nvidia/tegra/soc/t210/drivers/se/se_private.h663
-rw-r--r--plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c1071
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_psci_handlers.c609
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_secondary.c41
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_setup.c318
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_sip_calls.c97
-rw-r--r--plat/nvidia/tegra/soc/t210/platform_t210.mk62
-rw-r--r--plat/nxp/common/aarch64/bl31_data.S558
-rw-r--r--plat/nxp/common/aarch64/ls_helpers.S220
-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.c83
-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.h70
-rw-r--r--plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h83
-rw-r--r--plat/nxp/common/include/default/ch_3/soc_default_base_addr.h100
-rw-r--r--plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h98
-rw-r--r--plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h88
-rw-r--r--plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h87
-rw-r--r--plat/nxp/common/include/default/plat_default_def.h172
-rw-r--r--plat/nxp/common/nv_storage/nv_storage.mk29
-rw-r--r--plat/nxp/common/nv_storage/plat_nv_storage.c121
-rw-r--r--plat/nxp/common/nv_storage/plat_nv_storage.h40
-rw-r--r--plat/nxp/common/ocram/aarch64/ocram.S71
-rw-r--r--plat/nxp/common/ocram/ocram.h13
-rw-r--r--plat/nxp/common/ocram/ocram.mk14
-rw-r--r--plat/nxp/common/plat_make_helper/plat_build_macros.mk11
-rw-r--r--plat/nxp/common/plat_make_helper/plat_common_def.mk103
-rw-r--r--plat/nxp/common/plat_make_helper/soc_common_def.mk117
-rw-r--r--plat/nxp/common/psci/aarch64/psci_utils.S1155
-rw-r--r--plat/nxp/common/psci/include/plat_psci.h145
-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.mk22
-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.h152
-rw-r--r--plat/nxp/common/setup/include/plat_macros.S22
-rw-r--r--plat/nxp/common/setup/ls_bl2_el3_setup.c303
-rw-r--r--plat/nxp/common/setup/ls_bl31_setup.c212
-rw-r--r--plat/nxp/common/setup/ls_common.c277
-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.c556
-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/soc_errata/errata.c59
-rw-r--r--plat/nxp/common/soc_errata/errata.h15
-rw-r--r--plat/nxp/common/soc_errata/errata.mk26
-rw-r--r--plat/nxp/common/soc_errata/errata_a008850.c42
-rw-r--r--plat/nxp/common/soc_errata/errata_a009660.c14
-rw-r--r--plat/nxp/common/soc_errata/errata_a010539.c26
-rw-r--r--plat/nxp/common/soc_errata/errata_a050426.c201
-rw-r--r--plat/nxp/common/soc_errata/errata_list.h28
-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.mk162
-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-ls1028a/aarch64/ls1028a.S1387
-rw-r--r--plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S70
-rw-r--r--plat/nxp/soc-ls1028a/include/soc.h149
-rw-r--r--plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c185
-rw-r--r--plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h76
-rw-r--r--plat/nxp/soc-ls1028a/ls1028ardb/platform.c28
-rw-r--r--plat/nxp/soc-ls1028a/ls1028ardb/platform.mk33
-rw-r--r--plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h13
-rw-r--r--plat/nxp/soc-ls1028a/ls1028ardb/policy.h16
-rw-r--r--plat/nxp/soc-ls1028a/soc.c432
-rw-r--r--plat/nxp/soc-ls1028a/soc.def97
-rw-r--r--plat/nxp/soc-ls1028a/soc.mk113
-rw-r--r--plat/nxp/soc-ls1043a/aarch64/ls1043a.S1637
-rw-r--r--plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S70
-rw-r--r--plat/nxp/soc-ls1043a/include/ns_access.h175
-rw-r--r--plat/nxp/soc-ls1043a/include/soc.h234
-rw-r--r--plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c163
-rw-r--r--plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h79
-rw-r--r--plat/nxp/soc-ls1043a/ls1043ardb/platform.c28
-rw-r--r--plat/nxp/soc-ls1043a/ls1043ardb/platform.mk40
-rw-r--r--plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h13
-rw-r--r--plat/nxp/soc-ls1043a/ls1043ardb/policy.h16
-rw-r--r--plat/nxp/soc-ls1043a/soc.c435
-rw-r--r--plat/nxp/soc-ls1043a/soc.def107
-rw-r--r--plat/nxp/soc-ls1043a/soc.mk114
-rw-r--r--plat/nxp/soc-ls1046a/aarch64/ls1046a.S937
-rw-r--r--plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S92
-rw-r--r--plat/nxp/soc-ls1046a/include/ns_access.h174
-rw-r--r--plat/nxp/soc-ls1046a/include/soc.h125
-rw-r--r--plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c177
-rw-r--r--plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h79
-rw-r--r--plat/nxp/soc-ls1046a/ls1046afrwy/platform.c28
-rw-r--r--plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk39
-rw-r--r--plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h13
-rw-r--r--plat/nxp/soc-ls1046a/ls1046afrwy/policy.h16
-rw-r--r--plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c91
-rw-r--r--plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h79
-rw-r--r--plat/nxp/soc-ls1046a/ls1046aqds/platform.c28
-rw-r--r--plat/nxp/soc-ls1046a/ls1046aqds/platform.mk39
-rw-r--r--plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h13
-rw-r--r--plat/nxp/soc-ls1046a/ls1046aqds/policy.h16
-rw-r--r--plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c267
-rw-r--r--plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h79
-rw-r--r--plat/nxp/soc-ls1046a/ls1046ardb/platform.c28
-rw-r--r--plat/nxp/soc-ls1046a/ls1046ardb/platform.mk38
-rw-r--r--plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h13
-rw-r--r--plat/nxp/soc-ls1046a/ls1046ardb/policy.h16
-rw-r--r--plat/nxp/soc-ls1046a/soc.c395
-rw-r--r--plat/nxp/soc-ls1046a/soc.def107
-rw-r--r--plat/nxp/soc-ls1046a/soc.mk114
-rw-r--r--plat/nxp/soc-ls1088a/aarch64/ls1088a.S1817
-rw-r--r--plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S69
-rw-r--r--plat/nxp/soc-ls1088a/include/soc.h229
-rw-r--r--plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c84
-rw-r--r--plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h81
-rw-r--r--plat/nxp/soc-ls1088a/ls1088aqds/platform.c28
-rw-r--r--plat/nxp/soc-ls1088a/ls1088aqds/platform.mk31
-rw-r--r--plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h13
-rw-r--r--plat/nxp/soc-ls1088a/ls1088aqds/policy.h16
-rw-r--r--plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c86
-rw-r--r--plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h80
-rw-r--r--plat/nxp/soc-ls1088a/ls1088ardb/platform.c28
-rw-r--r--plat/nxp/soc-ls1088a/ls1088ardb/platform.mk30
-rw-r--r--plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h13
-rw-r--r--plat/nxp/soc-ls1088a/ls1088ardb/policy.h15
-rw-r--r--plat/nxp/soc-ls1088a/soc.c397
-rw-r--r--plat/nxp/soc-ls1088a/soc.def87
-rw-r--r--plat/nxp/soc-ls1088a/soc.mk110
-rw-r--r--plat/nxp/soc-lx2160a/aarch64/lx2160a.S1816
-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/include/soc.h141
-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.mk51
-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.mk51
-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.mk52
-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.c509
-rw-r--r--plat/nxp/soc-lx2160a/soc.def116
-rw-r--r--plat/nxp/soc-lx2160a/soc.mk174
-rw-r--r--plat/qemu/common/aarch32/plat_helpers.S139
-rw-r--r--plat/qemu/common/aarch64/plat_helpers.S136
-rw-r--r--plat/qemu/common/include/plat_macros.S26
-rw-r--r--plat/qemu/common/qemu_bl1_setup.c62
-rw-r--r--plat/qemu/common/qemu_bl2_mem_params_desc.c150
-rw-r--r--plat/qemu/common/qemu_bl2_setup.c247
-rw-r--r--plat/qemu/common/qemu_bl31_setup.c113
-rw-r--r--plat/qemu/common/qemu_common.c169
-rw-r--r--plat/qemu/common/qemu_console.c23
-rw-r--r--plat/qemu/common/qemu_gicv2.c44
-rw-r--r--plat/qemu/common/qemu_gicv3.c52
-rw-r--r--plat/qemu/common/qemu_image_load.c34
-rw-r--r--plat/qemu/common/qemu_io_storage.c449
-rw-r--r--plat/qemu/common/qemu_pm.c257
-rw-r--r--plat/qemu/common/qemu_private.h51
-rw-r--r--plat/qemu/common/qemu_rotpk.S15
-rw-r--r--plat/qemu/common/qemu_spm.c147
-rw-r--r--plat/qemu/common/qemu_spmd_manifest.c31
-rw-r--r--plat/qemu/common/qemu_stack_protector.c32
-rw-r--r--plat/qemu/common/qemu_trusted_boot.c31
-rw-r--r--plat/qemu/common/sp_min/sp_min-qemu.mk22
-rw-r--r--plat/qemu/common/sp_min/sp_min_setup.c147
-rw-r--r--plat/qemu/common/topology.c57
-rw-r--r--plat/qemu/qemu/include/platform_def.h278
-rw-r--r--plat/qemu/qemu/platform.mk266
-rw-r--r--plat/qemu/qemu/qemu_bl1_measured_boot.c28
-rw-r--r--plat/qemu/qemu/qemu_common_measured_boot.c34
-rw-r--r--plat/qemu/qemu/qemu_helpers.c216
-rw-r--r--plat/qemu/qemu/qemu_measured_boot.c103
-rw-r--r--plat/qemu/qemu_sbsa/include/platform_def.h378
-rw-r--r--plat/qemu/qemu_sbsa/platform.mk127
-rw-r--r--plat/qemu/qemu_sbsa/sbsa_pm.c237
-rw-r--r--plat/qemu/qemu_sbsa/sbsa_private.h17
-rw-r--r--plat/qemu/qemu_sbsa/sbsa_topology.c63
-rw-r--r--plat/qti/common/inc/aarch64/plat_macros.S106
-rw-r--r--plat/qti/common/inc/qti_board_def.h37
-rw-r--r--plat/qti/common/inc/qti_cpu.h22
-rw-r--r--plat/qti/common/inc/qti_interrupt_svc.h12
-rw-r--r--plat/qti/common/inc/qti_plat.h62
-rw-r--r--plat/qti/common/inc/qti_rng.h14
-rw-r--r--plat/qti/common/inc/qti_uart_console.h19
-rw-r--r--plat/qti/common/inc/spmi_arb.h23
-rw-r--r--plat/qti/common/src/aarch64/qti_helpers.S81
-rw-r--r--plat/qti/common/src/aarch64/qti_kryo4_gold.S77
-rw-r--r--plat/qti/common/src/aarch64/qti_kryo4_silver.S71
-rw-r--r--plat/qti/common/src/aarch64/qti_kryo6_gold.S75
-rw-r--r--plat/qti/common/src/aarch64/qti_kryo6_silver.S71
-rw-r--r--plat/qti/common/src/aarch64/qti_uart_console.S102
-rw-r--r--plat/qti/common/src/pm_ps_hold.c41
-rw-r--r--plat/qti/common/src/qti_bl31_setup.c150
-rw-r--r--plat/qti/common/src/qti_common.c203
-rw-r--r--plat/qti/common/src/qti_gic_v3.c169
-rw-r--r--plat/qti/common/src/qti_interrupt_svc.c66
-rw-r--r--plat/qti/common/src/qti_pm.c287
-rw-r--r--plat/qti/common/src/qti_rng.c53
-rw-r--r--plat/qti/common/src/qti_stack_protector.c26
-rw-r--r--plat/qti/common/src/qti_syscall.c386
-rw-r--r--plat/qti/common/src/qti_topology.c48
-rw-r--r--plat/qti/common/src/spmi_arb.c113
-rw-r--r--plat/qti/msm8916/aarch64/msm8916_helpers.S164
-rw-r--r--plat/qti/msm8916/aarch64/uartdm_console.S154
-rw-r--r--plat/qti/msm8916/include/msm8916_mmap.h41
-rw-r--r--plat/qti/msm8916/include/plat_macros.S27
-rw-r--r--plat/qti/msm8916/include/platform_def.h57
-rw-r--r--plat/qti/msm8916/include/uartdm_console.h12
-rw-r--r--plat/qti/msm8916/msm8916_bl31_setup.c219
-rw-r--r--plat/qti/msm8916/msm8916_cpu_boot.c66
-rw-r--r--plat/qti/msm8916/msm8916_gicv2.c59
-rw-r--r--plat/qti/msm8916/msm8916_gicv2.h12
-rw-r--r--plat/qti/msm8916/msm8916_pm.c59
-rw-r--r--plat/qti/msm8916/msm8916_pm.h12
-rw-r--r--plat/qti/msm8916/msm8916_topology.c35
-rw-r--r--plat/qti/msm8916/platform.mk62
-rw-r--r--plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h59
-rw-r--r--plat/qti/qtiseclib/inc/qtiseclib_defs.h104
-rw-r--r--plat/qti/qtiseclib/inc/qtiseclib_interface.h99
-rw-r--r--plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h35
-rw-r--r--plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h45
-rw-r--r--plat/qti/qtiseclib/src/qtiseclib_cb_interface.c211
-rw-r--r--plat/qti/qtiseclib/src/qtiseclib_interface_stub.c129
-rw-r--r--plat/qti/sc7180/inc/platform_def.h198
-rw-r--r--plat/qti/sc7180/inc/qti_map_chipinfo.h28
-rw-r--r--plat/qti/sc7180/inc/qti_rng_io.h15
-rw-r--r--plat/qti/sc7180/inc/qti_secure_io_cfg.h30
-rw-r--r--plat/qti/sc7180/platform.mk128
-rw-r--r--plat/qti/sc7280/inc/platform_def.h198
-rw-r--r--plat/qti/sc7280/inc/qti_map_chipinfo.h34
-rw-r--r--plat/qti/sc7280/inc/qti_rng_io.h15
-rw-r--r--plat/qti/sc7280/inc/qti_secure_io_cfg.h30
-rw-r--r--plat/qti/sc7280/platform.mk130
-rw-r--r--plat/renesas/common/aarch64/plat_helpers.S396
-rw-r--r--plat/renesas/common/aarch64/platform_common.c271
-rw-r--r--plat/renesas/common/bl2_cpg_init.c408
-rw-r--r--plat/renesas/common/bl2_interrupt_error.c109
-rw-r--r--plat/renesas/common/bl2_plat_mem_params_desc.c88
-rw-r--r--plat/renesas/common/bl2_secure_setting.c362
-rw-r--r--plat/renesas/common/bl31_plat_setup.c133
-rw-r--r--plat/renesas/common/common.mk143
-rw-r--r--plat/renesas/common/include/plat.ld.S36
-rw-r--r--plat/renesas/common/include/plat_macros.S88
-rw-r--r--plat/renesas/common/include/platform_def.h200
-rw-r--r--plat/renesas/common/include/rcar_def.h313
-rw-r--r--plat/renesas/common/include/rcar_private.h108
-rw-r--r--plat/renesas/common/include/rcar_version.h17
-rw-r--r--plat/renesas/common/include/registers/axi_registers.h246
-rw-r--r--plat/renesas/common/include/registers/cpg_registers.h142
-rw-r--r--plat/renesas/common/include/registers/lifec_registers.h144
-rw-r--r--plat/renesas/common/plat_image_load.c38
-rw-r--r--plat/renesas/common/plat_pm.c321
-rw-r--r--plat/renesas/common/plat_storage.c417
-rw-r--r--plat/renesas/common/plat_topology.c47
-rw-r--r--plat/renesas/common/rcar_common.c99
-rw-r--r--plat/renesas/rcar/bl2_plat_setup.c1199
-rw-r--r--plat/renesas/rcar/platform.mk371
-rw-r--r--plat/renesas/rzg/bl2_plat_setup.c1020
-rw-r--r--plat/renesas/rzg/platform.mk274
-rw-r--r--plat/rockchip/common/aarch32/plat_helpers.S164
-rw-r--r--plat/rockchip/common/aarch32/platform_common.c57
-rw-r--r--plat/rockchip/common/aarch32/pmu_sram_cpus_on.S56
-rw-r--r--plat/rockchip/common/aarch64/plat_helpers.S163
-rw-r--r--plat/rockchip/common/aarch64/platform_common.c87
-rw-r--r--plat/rockchip/common/aarch64/pmu_sram_cpus_on.S52
-rw-r--r--plat/rockchip/common/bl31_plat_setup.c102
-rw-r--r--plat/rockchip/common/drivers/parameter/ddr_parameter.c135
-rw-r--r--plat/rockchip/common/drivers/parameter/ddr_parameter.h44
-rw-r--r--plat/rockchip/common/drivers/pmu/pmu_com.h122
-rw-r--r--plat/rockchip/common/include/plat_macros.S118
-rw-r--r--plat/rockchip/common/include/plat_params.h14
-rw-r--r--plat/rockchip/common/include/plat_private.h155
-rw-r--r--plat/rockchip/common/include/rockchip_sip_svc.h27
-rw-r--r--plat/rockchip/common/params_setup.c256
-rw-r--r--plat/rockchip/common/plat_pm.c413
-rw-r--r--plat/rockchip/common/plat_topology.c39
-rw-r--r--plat/rockchip/common/pmusram/cpus_on_fixed_addr.S48
-rw-r--r--plat/rockchip/common/pmusram/cpus_on_fixed_addr.h55
-rw-r--r--plat/rockchip/common/rockchip_gicv2.c81
-rw-r--r--plat/rockchip/common/rockchip_gicv3.c95
-rw-r--r--plat/rockchip/common/rockchip_sip_svc.c84
-rw-r--r--plat/rockchip/common/rockchip_stack_protector.c24
-rw-r--r--plat/rockchip/common/sp_min_plat_setup.c103
-rw-r--r--plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S21
-rw-r--r--plat/rockchip/px30/drivers/pmu/pmu.c1071
-rw-r--r--plat/rockchip/px30/drivers/pmu/pmu.h331
-rw-r--r--plat/rockchip/px30/drivers/secure/secure.c103
-rw-r--r--plat/rockchip/px30/drivers/secure/secure.h65
-rw-r--r--plat/rockchip/px30/drivers/soc/soc.c134
-rw-r--r--plat/rockchip/px30/drivers/soc/soc.h118
-rw-r--r--plat/rockchip/px30/include/plat.ld.S38
-rw-r--r--plat/rockchip/px30/include/plat_sip_calls.h12
-rw-r--r--plat/rockchip/px30/include/platform_def.h118
-rw-r--r--plat/rockchip/px30/plat_sip_calls.c25
-rw-r--r--plat/rockchip/px30/platform.mk73
-rw-r--r--plat/rockchip/px30/px30_def.h176
-rw-r--r--plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S17
-rw-r--r--plat/rockchip/rk3288/drivers/pmu/pmu.c391
-rw-r--r--plat/rockchip/rk3288/drivers/pmu/pmu.h151
-rw-r--r--plat/rockchip/rk3288/drivers/secure/secure.c165
-rw-r--r--plat/rockchip/rk3288/drivers/secure/secure.h102
-rw-r--r--plat/rockchip/rk3288/drivers/soc/soc.c223
-rw-r--r--plat/rockchip/rk3288/drivers/soc/soc.h110
-rw-r--r--plat/rockchip/rk3288/include/plat_sip_calls.h12
-rw-r--r--plat/rockchip/rk3288/include/plat_sp_min.ld.S72
-rw-r--r--plat/rockchip/rk3288/include/platform_def.h101
-rw-r--r--plat/rockchip/rk3288/include/shared/bl32_param.h26
-rw-r--r--plat/rockchip/rk3288/plat_sip_calls.c25
-rw-r--r--plat/rockchip/rk3288/platform.mk69
-rw-r--r--plat/rockchip/rk3288/rk3288_def.h127
-rw-r--r--plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk8
-rw-r--r--plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S21
-rw-r--r--plat/rockchip/rk3328/drivers/pmu/pmu.c667
-rw-r--r--plat/rockchip/rk3328/drivers/pmu/pmu.h129
-rw-r--r--plat/rockchip/rk3328/drivers/soc/soc.c158
-rw-r--r--plat/rockchip/rk3328/drivers/soc/soc.h111
-rw-r--r--plat/rockchip/rk3328/include/plat.ld.S37
-rw-r--r--plat/rockchip/rk3328/include/platform_def.h117
-rw-r--r--plat/rockchip/rk3328/platform.mk75
-rw-r--r--plat/rockchip/rk3328/rk3328_def.h151
-rw-r--r--plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c482
-rw-r--r--plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h247
-rw-r--r--plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S17
-rw-r--r--plat/rockchip/rk3368/drivers/pmu/pmu.c373
-rw-r--r--plat/rockchip/rk3368/drivers/pmu/pmu.h207
-rw-r--r--plat/rockchip/rk3368/drivers/soc/soc.c209
-rw-r--r--plat/rockchip/rk3368/drivers/soc/soc.h141
-rw-r--r--plat/rockchip/rk3368/include/plat.ld.S37
-rw-r--r--plat/rockchip/rk3368/include/plat_sip_calls.h12
-rw-r--r--plat/rockchip/rk3368/include/platform_def.h120
-rw-r--r--plat/rockchip/rk3368/plat_sip_calls.c25
-rw-r--r--plat/rockchip/rk3368/platform.mk67
-rw-r--r--plat/rockchip/rk3368/rk3368_def.h116
-rw-r--r--plat/rockchip/rk3399/drivers/dp/cdn_dp.c70
-rw-r--r--plat/rockchip/rk3399/drivers/dp/cdn_dp.h49
-rw-r--r--plat/rockchip/rk3399/drivers/dram/dfs.c2114
-rw-r--r--plat/rockchip/rk3399/drivers/dram/dfs.h50
-rw-r--r--plat/rockchip/rk3399/drivers/dram/dram.c53
-rw-r--r--plat/rockchip/rk3399/drivers/dram/dram.h156
-rw-r--r--plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c1324
-rw-r--r--plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h507
-rw-r--r--plat/rockchip/rk3399/drivers/dram/suspend.c852
-rw-r--r--plat/rockchip/rk3399/drivers/dram/suspend.h28
-rw-r--r--plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c400
-rw-r--r--plat/rockchip/rk3399/drivers/m0/Makefile125
-rw-r--r--plat/rockchip/rk3399/drivers/m0/include/addressmap.h15
-rw-r--r--plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h32
-rw-r--r--plat/rockchip/rk3399/drivers/m0/src/dram.c84
-rw-r--r--plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S26
-rw-r--r--plat/rockchip/rk3399/drivers/m0/src/startup.c92
-rw-r--r--plat/rockchip/rk3399/drivers/m0/src/stopwatch.c74
-rw-r--r--plat/rockchip/rk3399/drivers/m0/src/suspend.c62
-rw-r--r--plat/rockchip/rk3399/drivers/pmu/m0_ctl.c102
-rw-r--r--plat/rockchip/rk3399/drivers/pmu/m0_ctl.h29
-rw-r--r--plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S136
-rw-r--r--plat/rockchip/rk3399/drivers/pmu/pmu.c1626
-rw-r--r--plat/rockchip/rk3399/drivers/pmu/pmu.h141
-rw-r--r--plat/rockchip/rk3399/drivers/pmu/pmu_fw.c22
-rw-r--r--plat/rockchip/rk3399/drivers/pwm/pwm.c123
-rw-r--r--plat/rockchip/rk3399/drivers/pwm/pwm.h13
-rw-r--r--plat/rockchip/rk3399/drivers/secure/secure.c167
-rw-r--r--plat/rockchip/rk3399/drivers/secure/secure.h105
-rw-r--r--plat/rockchip/rk3399/drivers/soc/soc.c362
-rw-r--r--plat/rockchip/rk3399/drivers/soc/soc.h289
-rw-r--r--plat/rockchip/rk3399/include/addressmap.h19
-rw-r--r--plat/rockchip/rk3399/include/plat.ld.S98
-rw-r--r--plat/rockchip/rk3399/include/plat_sip_calls.h12
-rw-r--r--plat/rockchip/rk3399/include/platform_def.h104
-rw-r--r--plat/rockchip/rk3399/include/shared/addressmap_shared.h104
-rw-r--r--plat/rockchip/rk3399/include/shared/bl31_param.h26
-rw-r--r--plat/rockchip/rk3399/include/shared/dram_regs.h100
-rw-r--r--plat/rockchip/rk3399/include/shared/m0_param.h25
-rw-r--r--plat/rockchip/rk3399/include/shared/misc_regs.h27
-rw-r--r--plat/rockchip/rk3399/include/shared/pmu_bits.h697
-rw-r--r--plat/rockchip/rk3399/include/shared/pmu_regs.h148
-rw-r--r--plat/rockchip/rk3399/plat_sip_calls.c78
-rw-r--r--plat/rockchip/rk3399/platform.mk113
-rw-r--r--plat/rockchip/rk3399/rk3399_def.h65
-rw-r--r--plat/rpi/common/aarch64/plat_helpers.S244
-rw-r--r--plat/rpi/common/include/rpi_shared.h41
-rw-r--r--plat/rpi/common/rpi3_common.c247
-rw-r--r--plat/rpi/common/rpi3_image_load.c36
-rw-r--r--plat/rpi/common/rpi3_io_storage.c271
-rw-r--r--plat/rpi/common/rpi3_pm.c274
-rw-r--r--plat/rpi/common/rpi3_rotpk.S15
-rw-r--r--plat/rpi/common/rpi3_stack_protector.c29
-rw-r--r--plat/rpi/common/rpi3_topology.c58
-rw-r--r--plat/rpi/common/rpi3_trusted_boot.c36
-rw-r--r--plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c136
-rw-r--r--plat/rpi/rpi3/include/plat_macros.S20
-rw-r--r--plat/rpi/rpi3/include/platform_def.h263
-rw-r--r--plat/rpi/rpi3/include/rpi_hw.h114
-rw-r--r--plat/rpi/rpi3/platform.mk221
-rw-r--r--plat/rpi/rpi3/rpi3_bl1_setup.c101
-rw-r--r--plat/rpi/rpi3/rpi3_bl2_setup.c144
-rw-r--r--plat/rpi/rpi3/rpi3_bl31_setup.c226
-rw-r--r--plat/rpi/rpi3/rpi_mbox_board.c56
-rw-r--r--plat/rpi/rpi4/aarch64/armstub8_header.S37
-rw-r--r--plat/rpi/rpi4/include/plat.ld.S23
-rw-r--r--plat/rpi/rpi4/include/plat_macros.S20
-rw-r--r--plat/rpi/rpi4/include/platform_def.h140
-rw-r--r--plat/rpi/rpi4/include/rpi_hw.h114
-rw-r--r--plat/rpi/rpi4/platform.mk116
-rw-r--r--plat/rpi/rpi4/rpi4_bl31_setup.c304
-rw-r--r--plat/rpi/rpi4/rpi4_pci_svc.c215
-rw-r--r--plat/socionext/synquacer/drivers/mhu/sq_mhu.c98
-rw-r--r--plat/socionext/synquacer/drivers/mhu/sq_mhu.h19
-rw-r--r--plat/socionext/synquacer/drivers/scp/sq_scmi.c244
-rw-r--r--plat/socionext/synquacer/drivers/scp/sq_scp.c21
-rw-r--r--plat/socionext/synquacer/drivers/scpi/sq_scpi.c219
-rw-r--r--plat/socionext/synquacer/drivers/scpi/sq_scpi.h83
-rw-r--r--plat/socionext/synquacer/include/plat.ld.S31
-rw-r--r--plat/socionext/synquacer/include/plat_macros.S16
-rw-r--r--plat/socionext/synquacer/include/platform_def.h207
-rw-r--r--plat/socionext/synquacer/include/sq_common.h56
-rw-r--r--plat/socionext/synquacer/platform.mk117
-rw-r--r--plat/socionext/synquacer/sq_bl2_setup.c84
-rw-r--r--plat/socionext/synquacer/sq_bl31_setup.c247
-rw-r--r--plat/socionext/synquacer/sq_ccn.c45
-rw-r--r--plat/socionext/synquacer/sq_gicv3.c94
-rw-r--r--plat/socionext/synquacer/sq_helpers.S115
-rw-r--r--plat/socionext/synquacer/sq_image_desc.c76
-rw-r--r--plat/socionext/synquacer/sq_io_storage.c246
-rw-r--r--plat/socionext/synquacer/sq_psci.c215
-rw-r--r--plat/socionext/synquacer/sq_rotpk.S16
-rw-r--r--plat/socionext/synquacer/sq_spm.c75
-rw-r--r--plat/socionext/synquacer/sq_tbbr.c40
-rw-r--r--plat/socionext/synquacer/sq_topology.c40
-rw-r--r--plat/socionext/synquacer/sq_xlat_setup.c56
-rw-r--r--plat/socionext/uniphier/include/plat_macros.S13
-rw-r--r--plat/socionext/uniphier/include/platform_def.h76
-rw-r--r--plat/socionext/uniphier/platform.mk140
-rw-r--r--plat/socionext/uniphier/tsp/tsp-uniphier.mk9
-rw-r--r--plat/socionext/uniphier/tsp/uniphier_tsp_setup.c34
-rw-r--r--plat/socionext/uniphier/uniphier.h76
-rw-r--r--plat/socionext/uniphier/uniphier_bl2_setup.c166
-rw-r--r--plat/socionext/uniphier/uniphier_bl31_setup.c89
-rw-r--r--plat/socionext/uniphier/uniphier_boot_device.c189
-rw-r--r--plat/socionext/uniphier/uniphier_cci.c81
-rw-r--r--plat/socionext/uniphier/uniphier_console.S65
-rw-r--r--plat/socionext/uniphier/uniphier_console.h25
-rw-r--r--plat/socionext/uniphier/uniphier_console_setup.c92
-rw-r--r--plat/socionext/uniphier/uniphier_emmc.c308
-rw-r--r--plat/socionext/uniphier/uniphier_gicv3.c116
-rw-r--r--plat/socionext/uniphier/uniphier_helpers.S34
-rw-r--r--plat/socionext/uniphier/uniphier_image_desc.c119
-rw-r--r--plat/socionext/uniphier/uniphier_io_storage.c373
-rw-r--r--plat/socionext/uniphier/uniphier_nand.c283
-rw-r--r--plat/socionext/uniphier/uniphier_psci.c167
-rw-r--r--plat/socionext/uniphier/uniphier_rotpk.S16
-rw-r--r--plat/socionext/uniphier/uniphier_scp.c107
-rw-r--r--plat/socionext/uniphier/uniphier_smp.S29
-rw-r--r--plat/socionext/uniphier/uniphier_soc_info.c57
-rw-r--r--plat/socionext/uniphier/uniphier_syscnt.c12
-rw-r--r--plat/socionext/uniphier/uniphier_tbbr.c40
-rw-r--r--plat/socionext/uniphier/uniphier_topology.c40
-rw-r--r--plat/socionext/uniphier/uniphier_usb.c183
-rw-r--r--plat/socionext/uniphier/uniphier_xlat_setup.c81
-rw-r--r--plat/st/common/bl2_io_storage.c731
-rw-r--r--plat/st/common/include/stm32cubeprogrammer.h29
-rw-r--r--plat/st/common/include/stm32mp_common.h129
-rw-r--r--plat/st/common/include/stm32mp_dt.h46
-rw-r--r--plat/st/common/include/stm32mp_efi.h15
-rw-r--r--plat/st/common/include/stm32mp_fconf_getter.h31
-rw-r--r--plat/st/common/include/stm32mp_io_storage.h27
-rw-r--r--plat/st/common/include/stm32mp_shared_resources.h58
-rw-r--r--plat/st/common/include/usb_dfu.h80
-rw-r--r--plat/st/common/stm32cubeprogrammer_uart.c520
-rw-r--r--plat/st/common/stm32cubeprogrammer_usb.c197
-rw-r--r--plat/st/common/stm32mp_common.c279
-rw-r--r--plat/st/common/stm32mp_crypto_lib.c661
-rw-r--r--plat/st/common/stm32mp_dt.c429
-rw-r--r--plat/st/common/stm32mp_fconf_io.c181
-rw-r--r--plat/st/common/stm32mp_trusted_boot.c204
-rw-r--r--plat/st/common/usb_dfu.c538
-rw-r--r--plat/st/stm32mp1/bl2_plat_setup.c562
-rw-r--r--plat/st/stm32mp1/cert_create_tbbr.mk19
-rw-r--r--plat/st/stm32mp1/include/boot_api.h409
-rw-r--r--plat/st/stm32mp1/include/plat_def_fip_uuid.h14
-rw-r--r--plat/st/stm32mp1/include/plat_tbbr_img_def.h40
-rw-r--r--plat/st/stm32mp1/include/platform_def.h218
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_dbgmcu.h16
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h119
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_private.h38
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_shared_resources.h38
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_smc.h67
-rw-r--r--plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h19
-rw-r--r--plat/st/stm32mp1/plat_bl2_mem_params_desc.c134
-rw-r--r--plat/st/stm32mp1/plat_def_uuid_config.c18
-rw-r--r--plat/st/stm32mp1/plat_fiptool.mk25
-rw-r--r--plat/st/stm32mp1/plat_image_load.c36
-rw-r--r--plat/st/stm32mp1/platform.mk553
-rw-r--r--plat/st/stm32mp1/services/bsec_svc.c60
-rw-r--r--plat/st/stm32mp1/services/bsec_svc.h19
-rw-r--r--plat/st/stm32mp1/services/stm32mp1_svc_setup.c100
-rw-r--r--plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk53
-rw-r--r--plat/st/stm32mp1/sp_min/sp_min_setup.c197
-rw-r--r--plat/st/stm32mp1/stm32mp1.S11
-rw-r--r--plat/st/stm32mp1/stm32mp1.ld.S71
-rw-r--r--plat/st/stm32mp1/stm32mp1_boot_device.c209
-rw-r--r--plat/st/stm32mp1/stm32mp1_dbgmcu.c74
-rw-r--r--plat/st/stm32mp1/stm32mp1_def.h669
-rw-r--r--plat/st/stm32mp1/stm32mp1_fconf_firewall.c128
-rw-r--r--plat/st/stm32mp1/stm32mp1_fip_def.h138
-rw-r--r--plat/st/stm32mp1/stm32mp1_gic.c92
-rw-r--r--plat/st/stm32mp1/stm32mp1_helper.S336
-rw-r--r--plat/st/stm32mp1/stm32mp1_pm.c243
-rw-r--r--plat/st/stm32mp1/stm32mp1_private.c788
-rw-r--r--plat/st/stm32mp1/stm32mp1_scmi.c479
-rw-r--r--plat/st/stm32mp1/stm32mp1_shared_resources.c596
-rw-r--r--plat/st/stm32mp1/stm32mp1_stack_protector.c22
-rw-r--r--plat/st/stm32mp1/stm32mp1_syscfg.c411
-rw-r--r--plat/st/stm32mp1/stm32mp1_tbb_cert.c37
-rw-r--r--plat/st/stm32mp1/stm32mp1_topology.c57
-rw-r--r--plat/st/stm32mp1/stm32mp1_usb_dfu.c423
-rw-r--r--plat/ti/k3/board/generic/board.mk24
-rw-r--r--plat/ti/k3/board/generic/include/board_def.h43
-rw-r--r--plat/ti/k3/board/j784s4/board.mk24
-rw-r--r--plat/ti/k3/board/j784s4/include/board_def.h43
-rw-r--r--plat/ti/k3/board/lite/board.mk24
-rw-r--r--plat/ti/k3/board/lite/include/board_def.h45
-rw-r--r--plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c341
-rw-r--r--plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h82
-rw-r--r--plat/ti/k3/common/drivers/ti_sci/ti_sci.c1739
-rw-r--r--plat/ti/k3/common/drivers/ti_sci/ti_sci.h232
-rw-r--r--plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h734
-rw-r--r--plat/ti/k3/common/k3_bl31_setup.c197
-rw-r--r--plat/ti/k3/common/k3_console.c21
-rw-r--r--plat/ti/k3/common/k3_gicv3.c113
-rw-r--r--plat/ti/k3/common/k3_helpers.S155
-rw-r--r--plat/ti/k3/common/k3_psci.c295
-rw-r--r--plat/ti/k3/common/k3_topology.c46
-rw-r--r--plat/ti/k3/common/plat_common.mk95
-rw-r--r--plat/ti/k3/include/k3_console.h12
-rw-r--r--plat/ti/k3/include/k3_gicv3.h20
-rw-r--r--plat/ti/k3/include/plat_macros.S21
-rw-r--r--plat/ti/k3/include/platform_def.h191
-rw-r--r--plat/ti/k3/platform.mk14
-rw-r--r--plat/xilinx/common/include/ipi.h77
-rw-r--r--plat/xilinx/common/include/plat_startup.h41
-rw-r--r--plat/xilinx/common/include/pm_client.h33
-rw-r--r--plat/xilinx/common/include/pm_common.h62
-rw-r--r--plat/xilinx/common/include/pm_ipi.h36
-rw-r--r--plat/xilinx/common/ipi.c222
-rw-r--r--plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c133
-rw-r--r--plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h39
-rw-r--r--plat/xilinx/common/plat_startup.c260
-rw-r--r--plat/xilinx/common/pm_service/pm_ipi.c300
-rw-r--r--plat/xilinx/versal/aarch64/versal_common.c54
-rw-r--r--plat/xilinx/versal/aarch64/versal_helpers.S73
-rw-r--r--plat/xilinx/versal/bl31_versal_setup.c236
-rw-r--r--plat/xilinx/versal/include/plat_ipi.h55
-rw-r--r--plat/xilinx/versal/include/plat_macros.S110
-rw-r--r--plat/xilinx/versal/include/plat_pm_common.h22
-rw-r--r--plat/xilinx/versal/include/plat_private.h39
-rw-r--r--plat/xilinx/versal/include/platform_def.h104
-rw-r--r--plat/xilinx/versal/include/versal_def.h146
-rw-r--r--plat/xilinx/versal/plat_psci.c249
-rw-r--r--plat/xilinx/versal/plat_topology.c14
-rw-r--r--plat/xilinx/versal/plat_versal.c21
-rw-r--r--plat/xilinx/versal/platform.mk98
-rw-r--r--plat/xilinx/versal/pm_service/pm_api_sys.c589
-rw-r--r--plat/xilinx/versal/pm_service/pm_api_sys.h101
-rw-r--r--plat/xilinx/versal/pm_service/pm_client.c261
-rw-r--r--plat/xilinx/versal/pm_service/pm_defs.h167
-rw-r--r--plat/xilinx/versal/pm_service/pm_node.h192
-rw-r--r--plat/xilinx/versal/pm_service/pm_svc_main.c395
-rw-r--r--plat/xilinx/versal/pm_service/pm_svc_main.h18
-rw-r--r--plat/xilinx/versal/sip_svc_setup.c102
-rw-r--r--plat/xilinx/versal/versal_gicv3.c186
-rw-r--r--plat/xilinx/versal/versal_ipi.c82
-rw-r--r--plat/xilinx/versal_net/aarch64/versal_net_common.c127
-rw-r--r--plat/xilinx/versal_net/aarch64/versal_net_helpers.S110
-rw-r--r--plat/xilinx/versal_net/bl31_versal_net_setup.c223
-rw-r--r--plat/xilinx/versal_net/include/plat_ipi.h58
-rw-r--r--plat/xilinx/versal_net/include/plat_macros.S118
-rw-r--r--plat/xilinx/versal_net/include/plat_pm_common.h25
-rw-r--r--plat/xilinx/versal_net/include/plat_private.h49
-rw-r--r--plat/xilinx/versal_net/include/platform_def.h114
-rw-r--r--plat/xilinx/versal_net/include/versal_net_def.h171
-rw-r--r--plat/xilinx/versal_net/plat_psci.c220
-rw-r--r--plat/xilinx/versal_net/plat_psci_pm.c264
-rw-r--r--plat/xilinx/versal_net/plat_topology.c63
-rw-r--r--plat/xilinx/versal_net/platform.mk102
-rw-r--r--plat/xilinx/versal_net/pm_service/pm_client.c240
-rw-r--r--plat/xilinx/versal_net/sip_svc_setup.c101
-rw-r--r--plat/xilinx/versal_net/versal_net_gicv3.c222
-rw-r--r--plat/xilinx/versal_net/versal_net_ipi.c85
-rw-r--r--plat/xilinx/zynqmp/aarch64/zynqmp_common.c391
-rw-r--r--plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S86
-rw-r--r--plat/xilinx/zynqmp/bl31_zynqmp_setup.c268
-rw-r--r--plat/xilinx/zynqmp/include/plat_ipi.h56
-rw-r--r--plat/xilinx/zynqmp/include/plat_macros.S28
-rw-r--r--plat/xilinx/zynqmp/include/plat_pm_common.h24
-rw-r--r--plat/xilinx/zynqmp/include/plat_private.h33
-rw-r--r--plat/xilinx/zynqmp/include/platform_def.h161
-rw-r--r--plat/xilinx/zynqmp/include/zynqmp_def.h365
-rw-r--r--plat/xilinx/zynqmp/plat_psci.c230
-rw-r--r--plat/xilinx/zynqmp/plat_topology.c13
-rw-r--r--plat/xilinx/zynqmp/plat_zynqmp.c21
-rw-r--r--plat/xilinx/zynqmp/platform.mk143
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_clock.c3048
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_clock.h333
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c767
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h96
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c2112
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h723
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.c1836
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.h197
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_client.c354
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_defs.h363
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_svc_main.c621
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_svc_main.h20
-rw-r--r--plat/xilinx/zynqmp/sip_svc_setup.c105
-rw-r--r--plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk8
-rw-r--r--plat/xilinx/zynqmp/tsp/tsp_plat_setup.c65
-rw-r--r--plat/xilinx/zynqmp/zynqmp_ehf.c24
-rw-r--r--plat/xilinx/zynqmp/zynqmp_ipi.c100
-rw-r--r--plat/xilinx/zynqmp/zynqmp_sdei.c37
2136 files changed, 309756 insertions, 0 deletions
diff --git a/plat/allwinner/common/allwinner-common.mk b/plat/allwinner/common/allwinner-common.mk
new file mode 100644
index 0000000..61c1dbe
--- /dev/null
+++ b/plat/allwinner/common/allwinner-common.mk
@@ -0,0 +1,114 @@
+#
+# Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+include lib/libfdt/libfdt.mk
+include drivers/arm/gic/v2/gicv2.mk
+
+AW_PLAT := plat/allwinner
+
+PLAT_INCLUDES := -Iinclude/plat/arm/common/aarch64 \
+ -I${AW_PLAT}/common/include \
+ -I${AW_PLAT}/${PLAT}/include
+
+PLAT_BL_COMMON_SOURCES := drivers/ti/uart/${ARCH}/16550_console.S \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${AW_PLAT}/common/plat_helpers.S \
+ ${AW_PLAT}/common/sunxi_common.c
+
+BL31_SOURCES += drivers/allwinner/axp/common.c \
+ ${GICV2_SOURCES} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/${ARCH}/cortex_a53.S \
+ plat/common/plat_gicv2.c \
+ plat/common/plat_psci_common.c \
+ ${AW_PLAT}/common/sunxi_bl31_setup.c \
+ ${AW_PLAT}/${PLAT}/sunxi_idle_states.c \
+ ${AW_PLAT}/common/sunxi_pm.c \
+ ${AW_PLAT}/${PLAT}/sunxi_power.c \
+ ${AW_PLAT}/common/sunxi_security.c \
+ ${AW_PLAT}/common/sunxi_topology.c
+
+# By default, attempt to use SCPI to the ARISC management processor. If SCPI
+# is not enabled or SCP firmware is not loaded, fall back to a simpler native
+# implementation that does not support CPU or system suspend.
+#
+# If SCP firmware will always be present (or absent), the unused implementation
+# can be compiled out.
+SUNXI_PSCI_USE_NATIVE ?= 1
+SUNXI_PSCI_USE_SCPI ?= 1
+
+$(eval $(call assert_boolean,SUNXI_PSCI_USE_NATIVE))
+$(eval $(call assert_boolean,SUNXI_PSCI_USE_SCPI))
+$(eval $(call add_define,SUNXI_PSCI_USE_NATIVE))
+$(eval $(call add_define,SUNXI_PSCI_USE_SCPI))
+
+ifeq (${SUNXI_PSCI_USE_NATIVE}${SUNXI_PSCI_USE_SCPI},00)
+$(error "At least one of SCPI or native PSCI ops must be enabled")
+endif
+
+ifeq (${SUNXI_PSCI_USE_NATIVE},1)
+BL31_SOURCES += ${AW_PLAT}/common/sunxi_cpu_ops.c \
+ ${AW_PLAT}/common/sunxi_native_pm.c
+endif
+
+ifeq (${SUNXI_PSCI_USE_SCPI},1)
+BL31_SOURCES += drivers/allwinner/sunxi_msgbox.c \
+ drivers/arm/css/scpi/css_scpi.c \
+ ${AW_PLAT}/common/sunxi_scpi_pm.c
+endif
+
+SUNXI_SETUP_REGULATORS ?= 1
+$(eval $(call assert_boolean,SUNXI_SETUP_REGULATORS))
+$(eval $(call add_define,SUNXI_SETUP_REGULATORS))
+
+SUNXI_BL31_IN_DRAM ?= 0
+$(eval $(call assert_boolean,SUNXI_BL31_IN_DRAM))
+
+ifeq (${SUNXI_BL31_IN_DRAM},1)
+SUNXI_AMEND_DTB := 1
+$(eval $(call add_define,SUNXI_BL31_IN_DRAM))
+endif
+
+SUNXI_AMEND_DTB ?= 0
+$(eval $(call assert_boolean,SUNXI_AMEND_DTB))
+$(eval $(call add_define,SUNXI_AMEND_DTB))
+
+ifeq (${SUNXI_AMEND_DTB},1)
+BL31_SOURCES += common/fdt_fixup.c \
+ ${AW_PLAT}/common/sunxi_prepare_dtb.c
+endif
+
+# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
+COLD_BOOT_SINGLE_CPU := 1
+
+# Do not enable SPE (not supported on ARM v8.0).
+ENABLE_SPE_FOR_LOWER_ELS := 0
+
+# Do not enable SVE (not supported on ARM v8.0).
+ENABLE_SVE_FOR_NS := 0
+
+# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
+
+# The traditional U-Boot load address is 160MB into DRAM.
+PRELOADED_BL33_BASE ?= 0x4a000000
+
+# The reset vector can be changed for each CPU.
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+# Allow mapping read-only data as execute-never.
+SEPARATE_CODE_AND_RODATA := 1
+
+# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
+RESET_TO_BL31 := 1
+
+# This platform is single-cluster and does not require coherency setup.
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
diff --git a/plat/allwinner/common/arisc_off.S b/plat/allwinner/common/arisc_off.S
new file mode 100644
index 0000000..ed10832
--- /dev/null
+++ b/plat/allwinner/common/arisc_off.S
@@ -0,0 +1,115 @@
+# turn_off_core.S
+#
+# Copyright (c) 2018, Andre Przywara <osp@andrep.de>
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# OpenRISC assembly to turn off an ARM core on an Allwinner SoC from
+# the arisc management controller.
+# Generate a binary representation with:
+# $ or1k-elf-as -c -o turn_off_core.o turn_off_core.S
+# $ or1k-elf-objcopy -O binary --reverse-bytes=4 turn_off_core.o \
+# turn_off_core.bin
+# The encoded instructions go into an array defined in
+# plat/allwinner/sun50i_*/include/core_off_arisc.h, to be handed off to
+# the arisc processor.
+#
+# This routine is meant to be called directly from arisc reset (put the
+# start address in the reset vector), to be actually triggered by that
+# very ARM core to be turned off.
+# It expects the core number presented as a mask in the upper half of
+# r3, so to be patched in the lower 16 bits of the first instruction,
+# overwriting the 0 in this code here.
+# The code will do the following:
+# - Read the C_CPU_STATUS register, which contains the status of the WFI
+# lines of each of the four A53 cores.
+# - Loop until the core in question reaches WFI.
+# - Using that mask, activate the core output clamps by setting the
+# respective core bit in CPUX_PWROFF_GATING_REG (0x1f01500).
+# Note that the clamp for core 0 covers more than just the core, activating
+# it hangs the whole system. So we skip this step for core 0.
+# - Using the negated mask, assert the core's reset line by clearing the
+# respective bit in C_RST_CTRL (0x1f01c30).
+# - Finally turn off the core's power switch by writing 0xff to the
+# respective CPUx_PWR_SWITCH_REG (0x1f01540 ff.)
+# - Assert the arisc's own reset to end execution.
+# This also signals other arisc users that the chip is free again.
+# So in C this would look like:
+# while (!(readl(0x1700030) & (1U << core_nr)))
+# ;
+# if (core_nr != 0)
+# writel(readl(0x1f01500) | (1U << core_nr), 0x1f01500);
+# writel(readl(0x1f01c30) & ~(1U << core_nr), 0x1f01c30);
+# writel(0xff, 0x1f01540 + (core_nr * 4));
+# (using A64/H5 addresses)
+
+.text
+_start:
+ l.movhi r3, 0 # FIXUP! with core mask
+ l.movhi r0, 0 # clear r0
+ l.movhi r13, 0x170 # r13: CPU_CFG_BASE=0x01700000
+wait_wfi:
+ l.lwz r5, 0x30(r13) # load C_CPU_STATUS
+ l.and r5, r5, r3 # mask requested core
+ l.sfeq r5, r0 # is it not yet in WFI?
+ l.bf wait_wfi # try again
+
+ l.srli r6, r3, 16 # move mask to lower 16 bits
+ l.sfeqi r6, 1 # core 0 is special
+ l.bf 1f # don't touch the bit for core 0
+ l.movhi r13, 0x1f0 # address of R_CPUCFG (delay)
+ l.lwz r5, 0x1500(r13) # core output clamps
+ l.or r5, r5, r6 # set bit to ...
+ l.sw 0x1500(r13), r5 # ... activate for our core
+
+1: l.lwz r5, 0x1c30(r13) # CPU power-on reset
+ l.xori r6, r6, -1 # negate core mask
+ l.and r5, r5, r6 # clear bit to ...
+ l.sw 0x1c30(r13), r5 # ... assert for our core
+
+ l.ff1 r6, r3 # get core number from high mask
+ l.addi r6, r6, -17 # convert to 0-3
+ l.slli r6, r6, 2 # r5: core number*4 (0-12)
+ l.add r6, r6, r13 # add to base address
+ l.ori r5, r0, 0xff # 0xff means all switches off
+ l.sw 0x1540(r6), r5 # core power switch registers
+
+reset: l.sw 0x1c00(r13),r0 # pull down our own reset line
+
+ l.j reset # just in case ....
+ l.nop 0x0 # (delay slot)
+
+# same as above, but with the MMIO addresses matching the H6 SoC
+_start_h6:
+ l.movhi r3, 0 # FIXUP! with core mask
+ l.movhi r0, 0 # clear r0
+ l.movhi r13, 0x901 # r13: CPU_CFG_BASE=0x09010000
+1:
+ l.lwz r5, 0x80(r13) # load C_CPU_STATUS
+ l.and r5, r5, r3 # mask requested core
+ l.sfeq r5, r0 # is it not yet in WFI?
+ l.bf 1b # try again
+
+ l.srli r6, r3, 16 # move mask to lower 16 bits(ds)
+ l.sfeqi r6, 1 # core 0 is special
+ l.bf 1f # don't touch the bit for core 0
+ l.movhi r13, 0x700 # address of R_CPUCFG (ds)
+ l.lwz r5, 0x0444(r13) # core output clamps
+ l.or r5, r5, r6 # set bit to ...
+ l.sw 0x0444(r13), r5 # ... activate for our core
+
+1: l.lwz r5, 0x0440(r13) # CPU power-on reset
+ l.xori r6, r6, -1 # negate core mask
+ l.and r5, r5, r6 # clear bit to ...
+ l.sw 0x0440(r13), r5 # ... assert for our core
+
+ l.ff1 r6, r3 # get core number from high mask
+ l.addi r6, r6, -17 # convert to 0-3
+ l.slli r6, r6, 2 # r5: core number*4 (0-12)
+ l.add r6, r6, r13 # add to base address
+ l.ori r5, r0, 0xff # 0xff means all switches off
+ l.sw 0x0450(r6), r5 # core power switch registers
+
+1: l.sw 0x0400(r13),r0 # pull down our own reset line
+
+ l.j 1b # just in case ...
+ l.nop 0x0 # (delay slot)
diff --git a/plat/allwinner/common/include/mentor_i2c_plat.h b/plat/allwinner/common/include/mentor_i2c_plat.h
new file mode 100644
index 0000000..d03f2d1
--- /dev/null
+++ b/plat/allwinner/common/include/mentor_i2c_plat.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+/* This driver provides I2C support for Allwinner sunXi SoCs */
+
+#ifndef MENTOR_I2C_PLAT_H
+#define MENTOR_I2C_PLAT_H
+
+#define CONFIG_SYS_TCLK 24000000
+#define CONFIG_SYS_I2C_SPEED 100000
+#define CONFIG_SYS_I2C_SLAVE 0
+
+#define I2C_INTERRUPT_CLEAR_INVERTED
+
+struct mentor_i2c_regs {
+ uint32_t slave_address;
+ uint32_t xtnd_slave_addr;
+ uint32_t data;
+ uint32_t control;
+ uint32_t status;
+ uint32_t baudrate;
+ uint32_t soft_reset;
+};
+
+#endif /* MENTOR_I2C_PLAT_H */
diff --git a/plat/allwinner/common/include/plat_macros.S b/plat/allwinner/common/include/plat_macros.S
new file mode 100644
index 0000000..77f183d
--- /dev/null
+++ b/plat/allwinner/common/include/plat_macros.S
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+#include <sunxi_mmap.h>
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x17, SUNXI_GICC_BASE
+ mov_imm x16, SUNXI_GICD_BASE
+ arm_print_gic_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
new file mode 100644
index 0000000..c9d075a
--- /dev/null
+++ b/plat/allwinner/common/include/platform_def.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include <sunxi_mmap.h>
+
+#ifdef SUNXI_BL31_IN_DRAM
+
+#define BL31_BASE SUNXI_DRAM_BASE
+#define BL31_LIMIT (SUNXI_DRAM_BASE + 0x40000)
+
+#define MAX_XLAT_TABLES 4
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+
+#define SUNXI_BL33_VIRT_BASE PRELOADED_BL33_BASE
+
+#else /* !SUNXI_BL31_IN_DRAM */
+
+#define BL31_BASE (SUNXI_SRAM_A2_BASE + \
+ SUNXI_SRAM_A2_BL31_OFFSET)
+#define BL31_LIMIT (SUNXI_SRAM_A2_BASE + \
+ SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE)
+
+/* Overwrite U-Boot SPL, but reserve the first page for the SPL header. */
+#define BL31_NOBITS_BASE (SUNXI_SRAM_A1_BASE + 0x1000)
+#define BL31_NOBITS_LIMIT (SUNXI_SRAM_A1_BASE + SUNXI_SRAM_A1_SIZE)
+
+#define MAX_XLAT_TABLES 1
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 28)
+
+#define SUNXI_BL33_VIRT_BASE SUNXI_DRAM_VIRT_BASE
+
+/* The SCP firmware is allocated the last 16KiB of SRAM A2. */
+#define SUNXI_SCP_BASE BL31_LIMIT
+#define SUNXI_SCP_SIZE 0x4000
+
+#endif /* SUNXI_BL31_IN_DRAM */
+
+/* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */
+#define SUNXI_DRAM_MAP_SIZE (64U << 20)
+
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#define MAX_STATIC_MMAP_REGIONS 3
+#define MAX_MMAP_REGIONS (5 + MAX_STATIC_MMAP_REGIONS)
+
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
+ (SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE - 0x200)
+
+/* These states are used directly for SCPI communication. */
+#define PLAT_MAX_PWR_LVL_STATES U(3)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(3)
+
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_NUM_PWR_DOMAINS (U(1) + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
+ PLATFORM_MAX_CPUS_PER_CLUSTER)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT)
+
+#ifndef SPD_none
+#ifndef BL32_BASE
+#define BL32_BASE SUNXI_DRAM_BASE
+#endif
+#endif
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
new file mode 100644
index 0000000..c17ef95
--- /dev/null
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_DEF_H
+#define SUNXI_DEF_H
+
+/* Clock configuration */
+#define SUNXI_OSC24M_CLK_IN_HZ 24000000
+
+/* UART configuration */
+#define SUNXI_UART0_BAUDRATE 115200
+#define SUNXI_UART0_CLK_IN_HZ SUNXI_OSC24M_CLK_IN_HZ
+
+#define SUNXI_SOC_A64 0x1689
+#define SUNXI_SOC_H5 0x1718
+#define SUNXI_SOC_H6 0x1728
+#define SUNXI_SOC_H616 0x1823
+#define SUNXI_SOC_R329 0x1851
+
+#define JEDEC_ALLWINNER_BKID 9U
+#define JEDEC_ALLWINNER_MFID 0x9eU
+
+#endif /* SUNXI_DEF_H */
diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h
new file mode 100644
index 0000000..6a38657
--- /dev/null
+++ b/plat/allwinner/common/include/sunxi_private.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_PRIVATE_H
+#define SUNXI_PRIVATE_H
+
+#include <common/fdt_fixup.h>
+
+#include <lib/psci/psci.h>
+
+extern const struct psci_cpu_idle_state sunxi_idle_states[];
+
+void sunxi_configure_mmu_el3(int flags);
+
+void sunxi_cpu_on(u_register_t mpidr);
+void sunxi_cpu_power_off_others(void);
+void sunxi_cpu_power_off_self(void);
+void sunxi_power_down(void);
+
+#if SUNXI_PSCI_USE_NATIVE
+void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops);
+#else
+static inline void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+}
+#endif
+#if SUNXI_PSCI_USE_SCPI
+bool sunxi_psci_is_scpi(void);
+int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops);
+#else
+static inline bool sunxi_psci_is_scpi(void)
+{
+ return false;
+}
+static inline int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+ return -1;
+}
+#endif
+int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint);
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt);
+void sunxi_security_setup(void);
+
+uint16_t sunxi_read_soc_id(void);
+void sunxi_set_gpio_out(char port, int pin, bool level_high);
+int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb);
+void sunxi_execute_arisc_code(uint32_t *code, size_t size, uint16_t param);
+
+#if SUNXI_AMEND_DTB
+void sunxi_prepare_dtb(void *fdt);
+#else
+static inline void sunxi_prepare_dtb(void *fdt)
+{
+}
+#endif
+
+#endif /* SUNXI_PRIVATE_H */
diff --git a/plat/allwinner/common/plat_helpers.S b/plat/allwinner/common/plat_helpers.S
new file mode 100644
index 0000000..b00c7ae
--- /dev/null
+++ b/plat/allwinner/common/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_my_core_pos
+ .globl platform_mem_init
+ .globl plat_report_exception
+
+func plat_crash_console_init
+ mov_imm x0, SUNXI_UART0_BASE
+ mov_imm x1, SUNXI_UART0_CLK_IN_HZ
+ mov_imm x2, SUNXI_UART0_BAUDRATE
+ b console_16550_core_init
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+ mov_imm x1, SUNXI_UART0_BASE
+ b console_16550_core_putc
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+ ret
+endfunc plat_crash_console_flush
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CLUSTER_MASK
+ and x0, x0, #MPIDR_CPU_MASK
+ add x0, x0, x1, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+func plat_report_exception
+ ret
+endfunc plat_report_exception
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
new file mode 100644
index 0000000..a32124a
--- /dev/null
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+static console_t console;
+
+static void *fdt;
+
+static const gicv2_driver_data_t sunxi_gic_data = {
+ .gicd_base = SUNXI_GICD_BASE,
+ .gicc_base = SUNXI_GICC_BASE,
+};
+
+/*
+ * Try to find a DTB loaded in memory by previous stages.
+ *
+ * At the moment we implement a heuristic to find the DTB attached to U-Boot:
+ * U-Boot appends its DTB to the end of the image. Assuming that BL33 is
+ * U-Boot, try to find the size of the U-Boot image to learn the DTB address.
+ * The generic ARMv8 U-Boot image contains the load address and its size
+ * as u64 variables at the beginning of the image. There might be padding
+ * or other headers before that data, so scan the first 2KB after the BL33
+ * entry point to find the load address, which should be followed by the
+ * size. Adding those together gives us the address of the DTB.
+ */
+static void sunxi_find_dtb(void)
+{
+ uint64_t *u_boot_base;
+ int i;
+
+ u_boot_base = (void *)SUNXI_BL33_VIRT_BASE;
+
+ for (i = 0; i < 2048 / sizeof(uint64_t); i++) {
+ void *dtb_base;
+
+ if (u_boot_base[i] != PRELOADED_BL33_BASE)
+ continue;
+
+ /* Does the suspected U-Boot size look anyhow reasonable? */
+ if (u_boot_base[i + 1] >= 256 * 1024 * 1024)
+ continue;
+
+ /* end of the image: base address + size */
+ dtb_base = (char *)u_boot_base + u_boot_base[i + 1];
+
+ if (fdt_check_header(dtb_base) == 0) {
+ fdt = dtb_base;
+ return;
+ }
+ }
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ /* Initialize the debug console as soon as possible */
+ console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
+ SUNXI_UART0_BAUDRATE, &console);
+
+#ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+#endif
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
+ bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ sunxi_configure_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ const char *soc_name;
+ uint16_t soc_id = sunxi_read_soc_id();
+
+ switch (soc_id) {
+ case SUNXI_SOC_A64:
+ soc_name = "A64/H64/R18";
+ break;
+ case SUNXI_SOC_H5:
+ soc_name = "H5";
+ break;
+ case SUNXI_SOC_H6:
+ soc_name = "H6";
+ break;
+ case SUNXI_SOC_H616:
+ soc_name = "H616";
+ break;
+ case SUNXI_SOC_R329:
+ soc_name = "R329";
+ break;
+ default:
+ soc_name = "unknown";
+ break;
+ }
+ NOTICE("BL31: Detected Allwinner %s SoC (%04x)\n", soc_name, soc_id);
+
+ generic_delay_timer_init();
+
+ sunxi_find_dtb();
+ if (fdt) {
+ const char *model;
+ int length;
+
+ model = fdt_getprop(fdt, 0, "model", &length);
+ NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt,
+ model ?: "unknown");
+ } else {
+ NOTICE("BL31: No DTB found.\n");
+ }
+
+ /* Configure the interrupt controller */
+ gicv2_driver_init(&sunxi_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ sunxi_security_setup();
+
+ /*
+ * On the A64 U-Boot's SPL sets the bus clocks to some conservative
+ * values, to work around FEL mode instabilities with SRAM C accesses.
+ * FEL mode is gone when we reach ATF, so bring the AHB1 bus
+ * (the "main" bus) clock frequency back to the recommended 200MHz,
+ * for improved performance.
+ */
+ if (soc_id == SUNXI_SOC_A64)
+ mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x00003180);
+
+ /*
+ * U-Boot or the kernel don't setup AHB2, which leaves it at the
+ * AHB1 frequency (200 MHz, see above). However Allwinner recommends
+ * 300 MHz, for improved Ethernet and USB performance. Switch the
+ * clock to use "PLL_PERIPH0 / 2".
+ */
+ if (soc_id == SUNXI_SOC_A64 || soc_id == SUNXI_SOC_H5)
+ mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0x1);
+
+ sunxi_pmic_setup(soc_id, fdt);
+
+ INFO("BL31: Platform setup done\n");
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ /* Change the DTB if the configuration requires so. */
+ sunxi_prepare_dtb(fdt);
+
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ assert(sec_state_is_valid(type) != 0);
+
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+
+ if ((type == SECURE) && bl32_image_ep_info.pc)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
new file mode 100644
index 0000000..092659c
--- /dev/null
+++ b/plat/allwinner/common/sunxi_common.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <services/arm_arch_svc.h>
+
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+static const mmap_region_t sunxi_mmap[MAX_STATIC_MMAP_REGIONS + 1] = {
+ MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
+ MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
+ MAP_REGION(PRELOADED_BL33_BASE, SUNXI_BL33_VIRT_BASE,
+ SUNXI_DRAM_MAP_SIZE, MT_RW_DATA | MT_NS),
+ {},
+};
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SUNXI_OSC24M_CLK_IN_HZ;
+}
+
+void sunxi_configure_mmu_el3(int flags)
+{
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+ mmap_add_region(BL_CODE_END, BL_CODE_END,
+ BL_END - BL_CODE_END,
+ MT_RW_DATA | MT_SECURE);
+#if SEPARATE_CODE_AND_RODATA
+ mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE);
+#endif
+#if SEPARATE_NOBITS_REGION
+ mmap_add_region(BL_NOBITS_BASE, BL_NOBITS_BASE,
+ BL_NOBITS_END - BL_NOBITS_BASE,
+ MT_RW_DATA | MT_SECURE);
+#endif
+#if USE_COHERENT_MEM
+ mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER);
+#endif
+
+ mmap_add(sunxi_mmap);
+ init_xlat_tables();
+
+ enable_mmu_el3(0);
+}
+
+#define SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24)
+uint16_t sunxi_read_soc_id(void)
+{
+ uint32_t reg = mmio_read_32(SRAM_VER_REG);
+
+ /* Set bit 15 to prepare for the SOCID read. */
+ mmio_write_32(SRAM_VER_REG, reg | BIT(15));
+
+ reg = mmio_read_32(SRAM_VER_REG);
+
+ /* deactivate the SOCID access again */
+ mmio_write_32(SRAM_VER_REG, reg & ~BIT(15));
+
+ return reg >> 16;
+}
+
+/*
+ * Configure a given pin to the GPIO-OUT function and sets its level.
+ * The port is given as a capital letter, the pin is the number within
+ * this port group.
+ * So to set pin PC7 to high, use: sunxi_set_gpio_out('C', 7, true);
+ */
+void sunxi_set_gpio_out(char port, int pin, bool level_high)
+{
+ uintptr_t port_base;
+
+ if (port < 'A' || port > 'L')
+ return;
+ if (port == 'L')
+ port_base = SUNXI_R_PIO_BASE;
+ else
+ port_base = SUNXI_PIO_BASE + (port - 'A') * 0x24;
+
+ /* Set the new level first before configuring the pin. */
+ if (level_high)
+ mmio_setbits_32(port_base + 0x10, BIT(pin));
+ else
+ mmio_clrbits_32(port_base + 0x10, BIT(pin));
+
+ /* configure pin as GPIO out (4(3) bits per pin, 1: GPIO out */
+ mmio_clrsetbits_32(port_base + (pin / 8) * 4,
+ 0x7 << ((pin % 8) * 4),
+ 0x1 << ((pin % 8) * 4));
+}
+
+int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb)
+{
+ uint32_t pin_func = 0x77;
+ uint32_t device_bit;
+ unsigned int reset_offset = 0xb0;
+
+ switch (socid) {
+ case SUNXI_SOC_H5:
+ if (use_rsb)
+ return -ENODEV;
+ pin_func = 0x22;
+ device_bit = BIT(6);
+ break;
+ case SUNXI_SOC_H6:
+ case SUNXI_SOC_H616:
+ pin_func = use_rsb ? 0x22 : 0x33;
+ device_bit = BIT(16);
+ reset_offset = use_rsb ? 0x1bc : 0x19c;
+ break;
+ case SUNXI_SOC_A64:
+ pin_func = use_rsb ? 0x22 : 0x33;
+ device_bit = use_rsb ? BIT(3) : BIT(6);
+ break;
+ default:
+ INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid);
+ return -ENODEV;
+ }
+
+ /* un-gate R_PIO clock */
+ if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616)
+ mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0));
+
+ /* switch pins PL0 and PL1 to the desired function */
+ mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func);
+
+ /* level 2 drive strength */
+ mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU);
+
+ /* set both pins to pull-up */
+ mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U);
+
+ /* un-gate clock */
+ if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616)
+ mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit);
+ else
+ mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0));
+
+ /* assert, then de-assert reset of I2C/RSB controller */
+ mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
+ mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
+
+ return 0;
+}
+
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
+int32_t plat_get_soc_version(void)
+{
+ int32_t ret;
+
+ ret = SOC_ID_SET_JEP_106(JEDEC_ALLWINNER_BKID, JEDEC_ALLWINNER_MFID);
+
+ return ret | (sunxi_read_soc_id() & SOC_ID_IMPL_DEF_MASK);
+}
+
+int32_t plat_get_soc_revision(void)
+{
+ uint32_t reg = mmio_read_32(SRAM_VER_REG);
+
+ return reg & GENMASK_32(7, 0);
+}
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
new file mode 100644
index 0000000..46e7090
--- /dev/null
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+
+#include <sunxi_cpucfg.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core)
+{
+ if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
+ return;
+
+ VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
+
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
+}
+
+static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core)
+{
+ if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
+ return;
+
+ VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
+
+ /* Power enable sequence from original Allwinner sources */
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8);
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
+ udelay(1);
+}
+
+/* We can't turn ourself off like this, but it works for other cores. */
+static void sunxi_cpu_off(u_register_t mpidr)
+{
+ unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
+
+ /* Deassert DBGPWRDUP */
+ mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+ /* Activate the core output clamps, but not for core 0. */
+ if (core != 0)
+ mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
+ /* Assert CPU power-on reset */
+ mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+ /* Remove power from the CPU */
+ sunxi_cpu_disable_power(cluster, core);
+}
+
+void sunxi_cpu_on(u_register_t mpidr)
+{
+ unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core);
+
+ /* Assert CPU core reset */
+ mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+ /* Assert CPU power-on reset */
+ mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+ /* Set CPU to start in AArch64 mode */
+ mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
+ BIT(SUNXI_AA64nAA32_OFFSET + core));
+ /* Apply power to the CPU */
+ sunxi_cpu_enable_power(cluster, core);
+ /* Release the core output clamps */
+ mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
+ /* Deassert CPU power-on reset */
+ mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+ /* Deassert CPU core reset */
+ mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+ /* Assert DBGPWRDUP */
+ mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+}
+
+void sunxi_cpu_power_off_others(void)
+{
+ u_register_t self = read_mpidr();
+ unsigned int cluster;
+ unsigned int core;
+
+ for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) {
+ for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) {
+ u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) |
+ (core << MPIDR_AFF0_SHIFT) |
+ BIT(31);
+ if (mpidr != self)
+ sunxi_cpu_off(mpidr);
+ }
+ }
+}
diff --git a/plat/allwinner/common/sunxi_native_pm.c b/plat/allwinner/common/sunxi_native_pm.c
new file mode 100644
index 0000000..148f50e
--- /dev/null
+++ b/plat/allwinner/common/sunxi_native_pm.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010)
+#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014)
+#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018)
+
+static int sunxi_pwr_domain_on(u_register_t mpidr)
+{
+ sunxi_cpu_on(mpidr);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ gicv2_cpuif_disable();
+
+ sunxi_cpu_power_off_self();
+}
+
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static void __dead2 sunxi_system_off(void)
+{
+ gicv2_cpuif_disable();
+
+ /* Attempt to power down the board (may not return) */
+ sunxi_power_down();
+
+ /* Turn off all CPUs */
+ sunxi_cpu_power_off_others();
+ sunxi_cpu_power_off_self();
+ psci_power_down_wfi();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+ gicv2_cpuif_disable();
+
+ /* Reset the whole system when the watchdog times out */
+ mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
+ /* Enable the watchdog with the shortest timeout (0.5 seconds) */
+ mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
+ /* Wait for twice the watchdog timeout before panicking */
+ mdelay(1000);
+
+ ERROR("PSCI: System reset failed\n");
+ panic();
+}
+
+static const plat_psci_ops_t sunxi_native_psci_ops = {
+ .pwr_domain_on = sunxi_pwr_domain_on,
+ .pwr_domain_off = sunxi_pwr_domain_off,
+ .pwr_domain_on_finish = sunxi_pwr_domain_on_finish,
+ .system_off = sunxi_system_off,
+ .system_reset = sunxi_system_reset,
+ .validate_ns_entrypoint = sunxi_validate_ns_entrypoint,
+};
+
+void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &sunxi_native_psci_ops;
+}
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
new file mode 100644
index 0000000..3772b4a
--- /dev/null
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <common/fdt_fixup.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <sunxi_cpucfg.h>
+#include <sunxi_private.h>
+
+static bool psci_is_scpi;
+
+#if SUNXI_PSCI_USE_SCPI
+bool sunxi_psci_is_scpi(void)
+{
+ return psci_is_scpi;
+}
+#endif
+
+int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+ /* The non-secure entry point must be in DRAM */
+ if (ns_entrypoint < SUNXI_DRAM_BASE) {
+ return PSCI_E_INVALID_ADDRESS;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ assert(psci_ops);
+
+ /* Program all CPU entry points. */
+ for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) {
+ mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
+ sec_entrypoint & 0xffffffff);
+ mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
+ sec_entrypoint >> 32);
+ }
+
+ if (sunxi_set_scpi_psci_ops(psci_ops) == 0) {
+ INFO("PSCI: Suspend is available via SCPI\n");
+ psci_is_scpi = true;
+ } else {
+ INFO("PSCI: Suspend is unavailable\n");
+ sunxi_set_native_psci_ops(psci_ops);
+ }
+
+ return 0;
+}
diff --git a/plat/allwinner/common/sunxi_prepare_dtb.c b/plat/allwinner/common/sunxi_prepare_dtb.c
new file mode 100644
index 0000000..66af35a
--- /dev/null
+++ b/plat/allwinner/common/sunxi_prepare_dtb.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <libfdt.h>
+
+#include <common/debug.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+
+#include <sunxi_private.h>
+
+void sunxi_prepare_dtb(void *fdt)
+{
+ int ret;
+
+ if (fdt == NULL || fdt_check_header(fdt) != 0) {
+ return;
+ }
+
+ ret = fdt_open_into(fdt, fdt, 0x10000);
+ if (ret < 0) {
+ ERROR("Preparing devicetree at %p: error %d\n", fdt, ret);
+ return;
+ }
+
+#ifdef SUNXI_BL31_IN_DRAM
+ /* Reserve memory used by Trusted Firmware. */
+ if (fdt_add_reserved_memory(fdt, "tf-a@40000000", BL31_BASE,
+ BL31_LIMIT - BL31_BASE)) {
+ WARN("Failed to add reserved memory nodes to DT.\n");
+ }
+#endif
+
+ if (sunxi_psci_is_scpi()) {
+ ret = fdt_add_cpu_idle_states(fdt, sunxi_idle_states);
+ if (ret < 0) {
+ WARN("Failed to add idle states to DT: %d\n", ret);
+ }
+ }
+
+ ret = fdt_pack(fdt);
+ if (ret < 0) {
+ ERROR("Failed to pack devicetree at %p: error %d\n",
+ fdt, ret);
+ }
+
+ clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
+ INFO("Changed devicetree.\n");
+}
diff --git a/plat/allwinner/common/sunxi_scpi_pm.c b/plat/allwinner/common/sunxi_scpi_pm.c
new file mode 100644
index 0000000..41dc563
--- /dev/null
+++ b/plat/allwinner/common/sunxi_scpi_pm.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_scpi.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+/*
+ * The addresses for the SCP exception vectors are defined in the or1k
+ * architecture specification.
+ */
+#define OR1K_VEC_FIRST 0x01
+#define OR1K_VEC_LAST 0x0e
+#define OR1K_VEC_ADDR(n) (0x100 * (n))
+
+/*
+ * This magic value is the little-endian representation of the or1k
+ * instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the
+ * first instruction in the SCP firmware.
+ */
+#define SCP_FIRMWARE_MAGIC 0xb4400012
+
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+#define CPU_PWR_LVL MPIDR_AFFLVL0
+#define CLUSTER_PWR_LVL MPIDR_AFFLVL1
+#define SYSTEM_PWR_LVL MPIDR_AFFLVL2
+
+#define CPU_PWR_STATE(state) \
+ ((state)->pwr_domain_state[CPU_PWR_LVL])
+#define CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[CLUSTER_PWR_LVL])
+#define SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[SYSTEM_PWR_LVL])
+
+static void sunxi_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr = read_scr_el3();
+
+ assert(is_local_state_retn(cpu_state));
+
+ write_scr_el3(scr | SCR_IRQ_BIT);
+ wfi();
+ write_scr_el3(scr);
+}
+
+static int sunxi_pwr_domain_on(u_register_t mpidr)
+{
+ scpi_set_css_power_state(mpidr,
+ scpi_power_on,
+ scpi_power_on,
+ scpi_power_on);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state);
+ plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
+ plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state);
+
+ if (is_local_state_off(cpu_pwr_state)) {
+ gicv2_cpuif_disable();
+ }
+
+ scpi_set_css_power_state(read_mpidr(),
+ cpu_pwr_state,
+ cluster_pwr_state,
+ system_pwr_state);
+}
+
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
+ gicv2_distif_init();
+ }
+ if (is_local_state_off(CPU_PWR_STATE(target_state))) {
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+ }
+}
+
+static void __dead2 sunxi_system_off(void)
+{
+ uint32_t ret;
+
+ gicv2_cpuif_disable();
+
+ /* Send the power down request to the SCP. */
+ ret = scpi_sys_power_state(scpi_system_shutdown);
+ if (ret != SCP_OK) {
+ ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret);
+ }
+
+ psci_power_down_wfi();
+}
+
+static void __dead2 sunxi_system_reset(void)
+{
+ uint32_t ret;
+
+ gicv2_cpuif_disable();
+
+ /* Send the system reset request to the SCP. */
+ ret = scpi_sys_power_state(scpi_system_reboot);
+ if (ret != SCP_OK) {
+ ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret);
+ }
+
+ psci_power_down_wfi();
+}
+
+static int sunxi_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int power_level = psci_get_pstate_pwrlvl(power_state);
+ unsigned int state_id = psci_get_pstate_id(power_state);
+ unsigned int type = psci_get_pstate_type(power_state);
+ unsigned int i;
+
+ assert(req_state != NULL);
+
+ if (power_level > PLAT_MAX_PWR_LVL) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (type == PSTATE_TYPE_STANDBY) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ /* Pass through the requested PSCI state as-is. */
+ for (i = 0; i <= power_level; ++i) {
+ unsigned int local_pstate = state_id & PLAT_LOCAL_PSTATE_MASK;
+
+ req_state->pwr_domain_state[i] = local_pstate;
+ state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
+ }
+
+ /* Higher power domain levels should all remain running */
+ for (; i <= PLAT_MAX_PWR_LVL; ++i) {
+ req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ assert(req_state != NULL);
+
+ for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) {
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ }
+}
+
+static const plat_psci_ops_t sunxi_scpi_psci_ops = {
+ .cpu_standby = sunxi_cpu_standby,
+ .pwr_domain_on = sunxi_pwr_domain_on,
+ .pwr_domain_off = sunxi_pwr_domain_off,
+ .pwr_domain_suspend = sunxi_pwr_domain_off,
+ .pwr_domain_on_finish = sunxi_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish,
+ .system_off = sunxi_system_off,
+ .system_reset = sunxi_system_reset,
+ .validate_power_state = sunxi_validate_power_state,
+ .validate_ns_entrypoint = sunxi_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state,
+};
+
+int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &sunxi_scpi_psci_ops;
+
+ /* Check for a valid SCP firmware. */
+ if (mmio_read_32(SUNXI_SCP_BASE) != SCP_FIRMWARE_MAGIC) {
+ return -1;
+ }
+
+ /* Program SCP exception vectors to the firmware entrypoint. */
+ for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
+ uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i);
+ uint32_t offset = SUNXI_SCP_BASE - vector;
+
+ mmio_write_32(vector, offset >> 2);
+ }
+
+ /* Take the SCP out of reset. */
+ mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
+
+ /* Wait for the SCP firmware to boot. */
+ return scpi_wait_ready();
+}
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
new file mode 100644
index 0000000..98b91c3
--- /dev/null
+++ b/plat/allwinner/common/sunxi_security.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <sunxi_ccu.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+#include <sunxi_spc.h>
+
+#define DMA_SEC_REG 0x20
+
+/*
+ * Setup the peripherals to be accessible by non-secure world.
+ * This will not work for the Secure Peripherals Controller (SPC) unless
+ * a fuse it burnt (seems to be an erratum), but we do it nevertheless,
+ * to allow booting on boards using secure boot.
+ */
+void sunxi_security_setup(void)
+{
+ int i;
+
+ INFO("Configuring SPC Controller\n");
+ /* SPC setup: set all devices to non-secure */
+ for (i = 0; i < SUNXI_SPC_NUM_PORTS; i++)
+ mmio_write_32(SUNXI_SPC_DECPORT_SET_REG(i), 0xffffffff);
+
+ /* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
+ mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
+
+ /* Set R_PRCM bus clocks to non-secure */
+ mmio_write_32(SUNXI_R_PRCM_SEC_SWITCH_REG, 0x1);
+
+ /* Set all DMA channels (16 max.) to non-secure */
+ mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
+}
diff --git a/plat/allwinner/common/sunxi_topology.c b/plat/allwinner/common/sunxi_topology.c
new file mode 100644
index 0000000..45be1e0
--- /dev/null
+++ b/plat/allwinner/common/sunxi_topology.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <plat/common/platform.h>
+
+static const unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = {
+ /* One root node for the SoC */
+ 1,
+ /* One node for each cluster */
+ PLATFORM_CLUSTER_COUNT,
+ /* One set of CPUs per cluster */
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+};
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+ MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
+ cluster >= PLATFORM_CLUSTER_COUNT ||
+ core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core;
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return plat_power_domain_tree_desc;
+}
diff --git a/plat/allwinner/sun50i_a64/include/core_off_arisc.h b/plat/allwinner/sun50i_a64/include/core_off_arisc.h
new file mode 100644
index 0000000..ae436ca
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/core_off_arisc.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+static uint32_t arisc_core_off[] = {
+ 0x18600000, /* l.movhi r3, <corenr> */
+ 0x18000000, /* l.movhi r0, 0x0 */
+ 0x19a00170, /* l.movhi r13, 0x170 */
+ 0x84ad0030, /* l.lwz r5, 0x30(r13) */
+ 0xe0a51803, /* l.and r5, r5, r3 */
+ 0xe4050000, /* l.sfeq r5, r0 */
+ 0x13fffffd, /* l.bf -12 */
+
+ 0xb8c30050, /* l.srli r6, r3, 16 */
+ 0xbc060001, /* l.sfeqi r6, 1 */
+ 0x10000005, /* l.bf +20 */
+ 0x19a001f0, /* l.movhi r13, 0x1f0 */
+ 0x84ad1500, /* l.lwz r5, 0x1500(r13) */
+ 0xe0a53004, /* l.or r5, r5, r6 */
+ 0xd44d2d00, /* l.sw 0x1500(r13), r5 */
+
+ 0x84ad1c30, /* l.lwz r5, 0x1c30(r13) */
+ 0xacc6ffff, /* l.xori r6, r6, -1 */
+ 0xe0a53003, /* l.and r5, r5, r6 */
+ 0xd46d2c30, /* l.sw 0x1c30(r13), r5 */
+
+ 0xe0c3000f, /* l.ff1 r6, r3 */
+ 0x9cc6ffef, /* l.addi r6, r6, -17 */
+ 0xb8c60002, /* l.slli r6, r6, 2 */
+ 0xe0c66800, /* l.add r6, r6, r13 */
+ 0xa8a000ff, /* l.ori r5, r0, 0xff */
+ 0xd4462d40, /* l.sw 0x1540(r6), r5 */
+
+ 0xd46d0400, /* l.sw 0x1c00(r13), r0 */
+ 0x03ffffff, /* l.j -1 */
+ 0x15000000, /* l.nop */
+};
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_ccu.h b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h
new file mode 100644
index 0000000..2a24886
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x02f0)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x01d0)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..aed3585
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 16)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0004 + (c) * 16)
+#define SUNXI_CPUCFG_CACHE_CFG_REG0 (SUNXI_CPUCFG_BASE + 0x0008)
+#define SUNXI_CPUCFG_CACHE_CFG_REG1 (SUNXI_CPUCFG_BASE + 0x000c)
+#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x0020)
+#define SUNXI_CPUCFG_GLB_CTRL_REG (SUNXI_CPUCFG_BASE + 0x0028)
+#define SUNXI_CPUCFG_CPU_STS_REG(c) (SUNXI_CPUCFG_BASE + 0x0030 + (c) * 4)
+#define SUNXI_CPUCFG_L2_STS_REG (SUNXI_CPUCFG_BASE + 0x003c)
+#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0080 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x00a0 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x00a4 + (n) * 8)
+
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_PRCM_BASE + 0x0140 + \
+ (c) * 16 + (n) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_PRCM_BASE + 0x0100 + (c) * 4)
+#define SUNXI_R_CPUCFG_CPUS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0000)
+#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0030 + (c) * 4)
+#define SUNXI_R_CPUCFG_SYS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
+#define SUNXI_R_CPUCFG_SS_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01a0)
+#define SUNXI_R_CPUCFG_CPU_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a4)
+#define SUNXI_R_CPUCFG_SS_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a8)
+#define SUNXI_R_CPUCFG_HP_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01ac)
+
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 24
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
new file mode 100644
index 0000000..6d10921
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_MMAP_H
+#define SUNXI_MMAP_H
+
+/* Memory regions */
+#define SUNXI_ROM_BASE 0x00000000
+#define SUNXI_ROM_SIZE 0x00010000
+#define SUNXI_SRAM_BASE 0x00010000
+#define SUNXI_SRAM_SIZE 0x00044000
+#define SUNXI_SRAM_A1_BASE 0x00010000
+#define SUNXI_SRAM_A1_SIZE 0x00008000
+#define SUNXI_SRAM_A2_BASE 0x00040000
+#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000
+#define SUNXI_SRAM_A2_SIZE 0x00014000
+#define SUNXI_SRAM_C_BASE 0x00018000
+#define SUNXI_SRAM_C_SIZE 0x0001c000
+#define SUNXI_DEV_BASE 0x01000000
+#define SUNXI_DEV_SIZE 0x01000000
+#define SUNXI_DRAM_BASE 0x40000000
+#define SUNXI_DRAM_VIRT_BASE 0x02000000
+
+/* Memory-mapped devices */
+#define SUNXI_CPU_MBIST_BASE 0x01502000
+#define SUNXI_CPUCFG_BASE 0x01700000
+#define SUNXI_SYSCON_BASE 0x01c00000
+#define SUNXI_DMA_BASE 0x01c02000
+#define SUNXI_KEYMEM_BASE 0x01c0b000
+#define SUNXI_SMHC0_BASE 0x01c0f000
+#define SUNXI_SMHC1_BASE 0x01c10000
+#define SUNXI_SMHC2_BASE 0x01c11000
+#define SUNXI_SID_BASE 0x01c14000
+#define SUNXI_MSGBOX_BASE 0x01c17000
+#define SUNXI_SPINLOCK_BASE 0x01c18000
+#define SUNXI_CCU_BASE 0x01c20000
+#define SUNXI_PIO_BASE 0x01c20800
+#define SUNXI_TIMER_BASE 0x01c20c00
+#define SUNXI_WDOG_BASE 0x01c20ca0
+#define SUNXI_SPC_BASE 0x01c23400
+#define SUNXI_THS_BASE 0x01c25000
+#define SUNXI_UART0_BASE 0x01c28000
+#define SUNXI_UART1_BASE 0x01c28400
+#define SUNXI_UART2_BASE 0x01c28800
+#define SUNXI_UART3_BASE 0x01c28c00
+#define SUNXI_I2C0_BASE 0x01c2ac00
+#define SUNXI_I2C1_BASE 0x01c2b000
+#define SUNXI_I2C2_BASE 0x01c2b400
+#define SUNXI_DRAMCOM_BASE 0x01c62000
+#define SUNXI_DRAMCTL_BASE 0x01c63000
+#define SUNXI_DRAMPHY_BASE 0x01c65000
+#define SUNXI_SPI0_BASE 0x01c68000
+#define SUNXI_SPI1_BASE 0x01c69000
+#define SUNXI_SCU_BASE 0x01c80000
+#define SUNXI_GICD_BASE 0x01c81000
+#define SUNXI_GICC_BASE 0x01c82000
+#define SUNXI_RTC_BASE 0x01f00000
+#define SUNXI_R_TIMER_BASE 0x01f00800
+#define SUNXI_R_INTC_BASE 0x01f00c00
+#define SUNXI_R_WDOG_BASE 0x01f01000
+#define SUNXI_R_PRCM_BASE 0x01f01400
+#define SUNXI_R_TWD_BASE 0x01f01800
+#define SUNXI_R_CPUCFG_BASE 0x01f01c00
+#define SUNXI_R_CIR_BASE 0x01f02000
+#define SUNXI_R_I2C_BASE 0x01f02400
+#define SUNXI_R_UART_BASE 0x01f02800
+#define SUNXI_R_PIO_BASE 0x01f02c00
+#define SUNXI_R_RSB_BASE 0x01f03400
+#define SUNXI_R_PWM_BASE 0x01f03800
+
+#endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_spc.h b/plat/allwinner/sun50i_a64/include/sunxi_spc.h
new file mode 100644
index 0000000..5ba7e18
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/include/sunxi_spc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+#define SUNXI_SPC_NUM_PORTS 6
+
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x0c * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x0c * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x000c + 0x0c * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk
new file mode 100644
index 0000000..e3c7c52
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/platform.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# The differences between the platform are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
+
+BL31_SOURCES += drivers/allwinner/axp/axp803.c \
+ drivers/allwinner/sunxi_rsb.c
+
+FDT_ASSUME_MASK := "(ASSUME_LATEST | ASSUME_NO_ROLLBACK | ASSUME_LIBFDT_ORDER)"
+$(eval $(call add_define,FDT_ASSUME_MASK))
+
+# Put NOBITS memory in SRAM A1, overwriting U-Boot's SPL.
+SEPARATE_NOBITS_REGION := 1
diff --git a/plat/allwinner/sun50i_a64/sunxi_idle_states.c b/plat/allwinner/sun50i_a64/sunxi_idle_states.c
new file mode 100644
index 0000000..2918bb7
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/sunxi_idle_states.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <sunxi_private.h>
+
+const struct psci_cpu_idle_state sunxi_idle_states[] = {
+ {
+ .name = "cpu-sleep",
+ .power_state = 0x00010003,
+ .local_timer_stop = true,
+ .entry_latency_us = 800,
+ .exit_latency_us = 1500,
+ .min_residency_us = 25000
+ },
+ {
+ .name = "cluster-sleep",
+ .power_state = 0x01010013,
+ .local_timer_stop = true,
+ .entry_latency_us = 850,
+ .exit_latency_us = 1500,
+ .min_residency_us = 50000
+ },
+ {}
+};
diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c
new file mode 100644
index 0000000..a35b9dd
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/sunxi_power.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/allwinner/axp.h>
+#include <drivers/allwinner/sunxi_rsb.h>
+#include <lib/mmio.h>
+
+#include <core_off_arisc.h>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+static enum pmic_type {
+ UNKNOWN,
+ GENERIC_H5,
+ GENERIC_A64,
+ REF_DESIGN_H5, /* regulators controlled by GPIO pins on port L */
+ AXP803_RSB, /* PMIC connected via RSB on most A64 boards */
+} pmic;
+
+#define AXP803_HW_ADDR 0x3a3
+#define AXP803_RT_ADDR 0x2d
+
+/*
+ * On boards without a proper PMIC we struggle to turn off the system properly.
+ * Try to turn off as much off the system as we can, to reduce power
+ * consumption. This should be entered with only one core running and SMP
+ * disabled.
+ * This function only cares about peripherals.
+ */
+static void sunxi_turn_off_soc(uint16_t socid)
+{
+ int i;
+
+ /** Turn off most peripherals, most importantly DRAM users. **/
+ /* Keep DRAM controller running for now. */
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14));
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14));
+ /* Contains msgbox (bit 21) and spinlock (bit 22) */
+ mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0);
+ mmio_write_32(SUNXI_CCU_BASE + 0x64, 0);
+ mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0);
+ /* Keep PIO controller running for now. */
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5)));
+ mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0);
+ /* Contains UART0 (bit 16) */
+ mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0);
+ mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0);
+ mmio_write_32(SUNXI_CCU_BASE + 0x70, 0);
+
+ /** Turn off DRAM controller. **/
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14));
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14));
+
+ /** Migrate CPU and bus clocks away from the PLLs. **/
+ /* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */
+ mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000);
+ /* APB2: use OSC24M */
+ mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000);
+ /* AHB2: use AHB1 clock */
+ mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0);
+ /* CPU: use OSC24M */
+ mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000);
+
+ /** Turn off PLLs. **/
+ for (i = 0; i < 6; i++)
+ mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31));
+ switch (socid) {
+ case SUNXI_SOC_H5:
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31));
+ break;
+ case SUNXI_SOC_A64:
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31));
+ mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31));
+ break;
+ }
+}
+
+static int rsb_init(void)
+{
+ int ret;
+
+ ret = rsb_init_controller();
+ if (ret)
+ return ret;
+
+ /* Switch to the recommended 3 MHz bus clock. */
+ ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
+ if (ret)
+ return ret;
+
+ /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
+ ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
+ if (ret)
+ return ret;
+
+ /* Associate the 8-bit runtime address with the 12-bit bus address. */
+ ret = rsb_assign_runtime_address(AXP803_HW_ADDR,
+ AXP803_RT_ADDR);
+ if (ret)
+ return ret;
+
+ return axp_check_id();
+}
+
+int axp_read(uint8_t reg)
+{
+ return rsb_read(AXP803_RT_ADDR, reg);
+}
+
+int axp_write(uint8_t reg, uint8_t val)
+{
+ return rsb_write(AXP803_RT_ADDR, reg, val);
+}
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+ int ret;
+
+ switch (socid) {
+ case SUNXI_SOC_H5:
+ NOTICE("PMIC: Assuming H5 reference regulator design\n");
+
+ pmic = REF_DESIGN_H5;
+
+ break;
+ case SUNXI_SOC_A64:
+ pmic = GENERIC_A64;
+
+ INFO("PMIC: Probing AXP803 on RSB\n");
+
+ ret = sunxi_init_platform_r_twi(socid, true);
+ if (ret)
+ return ret;
+
+ ret = rsb_init();
+ if (ret)
+ return ret;
+
+ pmic = AXP803_RSB;
+ axp_setup_regulators(fdt);
+
+ /* Switch the PMIC back to I2C mode. */
+ ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
+ if (ret)
+ return ret;
+
+ break;
+ default:
+ return -ENODEV;
+ }
+ return 0;
+}
+
+void sunxi_power_down(void)
+{
+ switch (pmic) {
+ case GENERIC_H5:
+ /* Turn off as many peripherals and clocks as we can. */
+ sunxi_turn_off_soc(SUNXI_SOC_H5);
+ /* Turn off the pin controller now. */
+ mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
+ break;
+ case GENERIC_A64:
+ /* Turn off as many peripherals and clocks as we can. */
+ sunxi_turn_off_soc(SUNXI_SOC_A64);
+ /* Turn off the pin controller now. */
+ mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
+ break;
+ case REF_DESIGN_H5:
+ sunxi_turn_off_soc(SUNXI_SOC_H5);
+
+ /*
+ * Switch PL pins to power off the board:
+ * - PL5 (VCC_IO) -> high
+ * - PL8 (PWR-STB = CPU power supply) -> low
+ * - PL9 (PWR-DRAM) ->low
+ * - PL10 (power LED) -> low
+ * Note: Clearing PL8 will reset the board, so keep it up.
+ */
+ sunxi_set_gpio_out('L', 5, 1);
+ sunxi_set_gpio_out('L', 9, 0);
+ sunxi_set_gpio_out('L', 10, 0);
+
+ /* Turn off pin controller now. */
+ mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
+
+ break;
+ case AXP803_RSB:
+ /* (Re-)init RSB in case the rich OS has disabled it. */
+ sunxi_init_platform_r_twi(SUNXI_SOC_A64, true);
+ rsb_init();
+ axp_power_off();
+ break;
+ default:
+ break;
+ }
+
+}
+
+/* This lock synchronises access to the arisc management processor. */
+static DEFINE_BAKERY_LOCK(arisc_lock);
+
+/*
+ * If we are supposed to turn ourself off, tell the arisc SCP to do that
+ * work for us. Without any SCPI provider running there, we place some
+ * OpenRISC code into SRAM, put the address of that into the reset vector
+ * and release the arisc reset line. The SCP will wait for the core to enter
+ * WFI, then execute that code and pull the line up again.
+ * The code expects the core mask to be patched into the first instruction.
+ */
+void sunxi_cpu_power_off_self(void)
+{
+ u_register_t mpidr = read_mpidr();
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+ uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE + 0x100;
+ uint32_t *code = arisc_core_off;
+
+ do {
+ bakery_lock_get(&arisc_lock);
+ /* Wait until the arisc is in reset state. */
+ if (!(mmio_read_32(SUNXI_R_CPUCFG_BASE) & BIT(0)))
+ break;
+
+ bakery_lock_release(&arisc_lock);
+ } while (1);
+
+ /* Patch up the code to feed in an input parameter. */
+ code[0] = (code[0] & ~0xffff) | BIT_32(core);
+ clean_dcache_range((uintptr_t)code, sizeof(arisc_core_off));
+
+ /*
+ * The OpenRISC unconditional branch has opcode 0, the branch offset
+ * is in the lower 26 bits, containing the distance to the target,
+ * in instruction granularity (32 bits).
+ */
+ mmio_write_32(arisc_reset_vec, ((uintptr_t)code - arisc_reset_vec) / 4);
+
+ /* De-assert the arisc reset line to let it run. */
+ mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
+
+ /*
+ * We release the lock here, although the arisc is still busy.
+ * But as long as it runs, the reset line is high, so other users
+ * won't leave the loop above.
+ * Once it has finished, the code is supposed to clear the reset line,
+ * to signal this to other users.
+ */
+ bakery_lock_release(&arisc_lock);
+}
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_ccu.h b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h
new file mode 100644
index 0000000..85fbb90
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..5bfda5d
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
+#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
+ (c) * 0x10 + (n) * 4)
+
+#define SUNXI_CPUIDLE_EN_REG (SUNXI_R_CPUCFG_BASE + 0x0100)
+#define SUNXI_CORE_CLOSE_REG (SUNXI_R_CPUCFG_BASE + 0x0104)
+#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
+#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144)
+
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 24
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
new file mode 100644
index 0000000..58216d8
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_MMAP_H
+#define SUNXI_MMAP_H
+
+/* Memory regions */
+#define SUNXI_ROM_BASE 0x00000000
+#define SUNXI_ROM_SIZE 0x00010000
+#define SUNXI_SRAM_BASE 0x00020000
+#define SUNXI_SRAM_SIZE 0x000f8000
+#define SUNXI_SRAM_A1_BASE 0x00020000
+#define SUNXI_SRAM_A1_SIZE 0x00008000
+#define SUNXI_SRAM_A2_BASE 0x00100000
+#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000
+#define SUNXI_SRAM_A2_SIZE 0x00018000
+#define SUNXI_SRAM_C_BASE 0x00028000
+#define SUNXI_SRAM_C_SIZE 0x0001e000
+#define SUNXI_DEV_BASE 0x01000000
+#define SUNXI_DEV_SIZE 0x09000000
+#define SUNXI_DRAM_BASE 0x40000000
+#define SUNXI_DRAM_VIRT_BASE 0x0a000000
+
+/* Memory-mapped devices */
+#define SUNXI_SYSCON_BASE 0x03000000
+#define SUNXI_CPUCFG_BASE 0x09010000
+#define SUNXI_SID_BASE 0x03006000
+#define SUNXI_DMA_BASE 0x03002000
+#define SUNXI_MSGBOX_BASE 0x03003000
+#define SUNXI_CCU_BASE 0x03001000
+#define SUNXI_PIO_BASE 0x0300b000
+#define SUNXI_SPC_BASE 0x03008000
+#define SUNXI_TIMER_BASE 0x03009000
+#define SUNXI_WDOG_BASE 0x030090a0
+#define SUNXI_THS_BASE 0x05070400
+#define SUNXI_UART0_BASE 0x05000000
+#define SUNXI_UART1_BASE 0x05000400
+#define SUNXI_UART2_BASE 0x05000800
+#define SUNXI_UART3_BASE 0x05000c00
+#define SUNXI_I2C0_BASE 0x05002000
+#define SUNXI_I2C1_BASE 0x05002400
+#define SUNXI_I2C2_BASE 0x05002800
+#define SUNXI_I2C3_BASE 0x05002c00
+#define SUNXI_SPI0_BASE 0x05010000
+#define SUNXI_SPI1_BASE 0x05011000
+#define SUNXI_SCU_BASE 0x03020000
+#define SUNXI_GICD_BASE 0x03021000
+#define SUNXI_GICC_BASE 0x03022000
+#define SUNXI_R_TIMER_BASE 0x07020000
+#define SUNXI_R_INTC_BASE 0x07021000
+#define SUNXI_R_WDOG_BASE 0x07020400
+#define SUNXI_R_PRCM_BASE 0x07010000
+#define SUNXI_R_TWD_BASE 0x07020800
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_R_I2C_BASE 0x07081400
+#define SUNXI_R_RSB_BASE 0x07083000
+#define SUNXI_R_UART_BASE 0x07080000
+#define SUNXI_R_PIO_BASE 0x07022000
+
+#endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_spc.h b/plat/allwinner/sun50i_h6/include/sunxi_spc.h
new file mode 100644
index 0000000..0f5965b
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_spc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+#define SUNXI_SPC_NUM_PORTS 14
+
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk
new file mode 100644
index 0000000..e13e8cb
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/platform.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# The differences between the platform are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
+
+BL31_SOURCES += drivers/allwinner/axp/axp805.c \
+ drivers/allwinner/sunxi_rsb.c
+
+# Put NOBITS memory in SRAM A1, overwriting U-Boot's SPL.
+SEPARATE_NOBITS_REGION := 1
diff --git a/plat/allwinner/sun50i_h6/sunxi_idle_states.c b/plat/allwinner/sun50i_h6/sunxi_idle_states.c
new file mode 100644
index 0000000..4339bcd
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/sunxi_idle_states.c
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <sunxi_private.h>
+
+const struct psci_cpu_idle_state sunxi_idle_states[] = {
+ {}
+};
diff --git a/plat/allwinner/sun50i_h6/sunxi_power.c b/plat/allwinner/sun50i_h6/sunxi_power.c
new file mode 100644
index 0000000..d298e6b
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/sunxi_power.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/allwinner/axp.h>
+#include <drivers/allwinner/sunxi_rsb.h>
+#include <lib/mmio.h>
+
+#include <sunxi_cpucfg.h>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+#define AXP805_HW_ADDR 0x745
+#define AXP805_RT_ADDR 0x3a
+
+static enum pmic_type {
+ UNKNOWN,
+ AXP805,
+} pmic;
+
+int axp_read(uint8_t reg)
+{
+ return rsb_read(AXP805_RT_ADDR, reg);
+}
+
+int axp_write(uint8_t reg, uint8_t val)
+{
+ return rsb_write(AXP805_RT_ADDR, reg, val);
+}
+
+static int rsb_init(void)
+{
+ int ret;
+
+ ret = rsb_init_controller();
+ if (ret)
+ return ret;
+
+ /* Switch to the recommended 3 MHz bus clock. */
+ ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
+ if (ret)
+ return ret;
+
+ /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
+ ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
+ if (ret)
+ return ret;
+
+ /* Associate the 8-bit runtime address with the 12-bit bus address. */
+ ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
+ if (ret)
+ return ret;
+
+ return axp_check_id();
+}
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+ int ret;
+
+ INFO("PMIC: Probing AXP805 on RSB\n");
+
+ ret = sunxi_init_platform_r_twi(socid, true);
+ if (ret)
+ return ret;
+
+ ret = rsb_init();
+ if (ret)
+ return ret;
+
+ /* Switch the AXP805 to master/single-PMIC mode. */
+ ret = axp_write(0xff, 0x0);
+ if (ret)
+ return ret;
+
+ pmic = AXP805;
+ axp_setup_regulators(fdt);
+
+ /* Switch the PMIC back to I2C mode. */
+ ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void sunxi_power_down(void)
+{
+ switch (pmic) {
+ case AXP805:
+ /* (Re-)init RSB in case the rich OS has disabled it. */
+ sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
+ rsb_init();
+ axp_power_off();
+ break;
+ default:
+ break;
+ }
+}
+
+void sunxi_cpu_power_off_self(void)
+{
+ u_register_t mpidr = read_mpidr();
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* Enable the CPUIDLE hardware (only really needs to be done once). */
+ mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
+ mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
+
+ /* Trigger power off for this core. */
+ mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
+}
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_ccu.h b/plat/allwinner/sun50i_h616/include/sunxi_ccu.h
new file mode 100644
index 0000000..85fbb90
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..dab663b
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
+#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
+ (c) * 0x10 + (n) * 4)
+
+#define SUNXI_CPUIDLE_EN_REG (SUNXI_R_CPUCFG_BASE + 0x0100)
+#define SUNXI_CORE_CLOSE_REG (SUNXI_R_CPUCFG_BASE + 0x0104)
+#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
+#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144)
+
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 24
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_mmap.h b/plat/allwinner/sun50i_h616/include/sunxi_mmap.h
new file mode 100644
index 0000000..3b4f4a0
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/include/sunxi_mmap.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_MMAP_H
+#define SUNXI_MMAP_H
+
+/* Memory regions */
+#define SUNXI_ROM_BASE 0x00000000
+#define SUNXI_ROM_SIZE 0x00010000
+#define SUNXI_SRAM_BASE 0x00020000
+#define SUNXI_SRAM_SIZE 0x00038000
+#define SUNXI_SRAM_A1_BASE 0x00020000
+#define SUNXI_SRAM_A1_SIZE 0x00008000
+#define SUNXI_SRAM_C_BASE 0x00028000
+#define SUNXI_SRAM_C_SIZE 0x00030000
+#define SUNXI_DEV_BASE 0x01000000
+#define SUNXI_DEV_SIZE 0x09000000
+#define SUNXI_DRAM_BASE 0x40000000
+#define SUNXI_DRAM_VIRT_BASE SUNXI_DRAM_BASE
+
+/* Memory-mapped devices */
+#define SUNXI_SYSCON_BASE 0x03000000
+#define SUNXI_CCU_BASE 0x03001000
+#define SUNXI_DMA_BASE 0x03002000
+#define SUNXI_SID_BASE 0x03006000
+#define SUNXI_SPC_BASE 0x03008000
+#define SUNXI_WDOG_BASE 0x030090a0
+#define SUNXI_PIO_BASE 0x0300b000
+#define SUNXI_GICD_BASE 0x03021000
+#define SUNXI_GICC_BASE 0x03022000
+#define SUNXI_UART0_BASE 0x05000000
+#define SUNXI_SPI0_BASE 0x05010000
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_R_PRCM_BASE 0x07010000
+//#define SUNXI_R_WDOG_BASE 0x07020400
+#define SUNXI_R_WDOG_BASE SUNXI_WDOG_BASE
+#define SUNXI_R_PIO_BASE 0x07022000
+#define SUNXI_R_UART_BASE 0x07080000
+#define SUNXI_R_I2C_BASE 0x07081400
+#define SUNXI_R_RSB_BASE 0x07083000
+#define SUNXI_CPUCFG_BASE 0x09010000
+
+#endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_spc.h b/plat/allwinner/sun50i_h616/include/sunxi_spc.h
new file mode 100644
index 0000000..0f5965b
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/include/sunxi_spc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+#define SUNXI_SPC_NUM_PORTS 14
+
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_h616/platform.mk b/plat/allwinner/sun50i_h616/platform.mk
new file mode 100644
index 0000000..de494a2
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/platform.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2017-2020, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+SUNXI_BL31_IN_DRAM := 1
+
+# Without a management processor there is no SCPI support.
+SUNXI_PSCI_USE_SCPI := 0
+SUNXI_PSCI_USE_NATIVE := 1
+
+# The differences between the platforms are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
+
+# the above could be overwritten on the command line
+ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
+ $(error "H616 does not support SCPI PSCI ops")
+endif
+
+BL31_SOURCES += drivers/allwinner/axp/axp805.c \
+ drivers/allwinner/sunxi_rsb.c \
diff --git a/plat/allwinner/sun50i_h616/sunxi_idle_states.c b/plat/allwinner/sun50i_h616/sunxi_idle_states.c
new file mode 100644
index 0000000..4339bcd
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/sunxi_idle_states.c
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <sunxi_private.h>
+
+const struct psci_cpu_idle_state sunxi_idle_states[] = {
+ {}
+};
diff --git a/plat/allwinner/sun50i_h616/sunxi_power.c b/plat/allwinner/sun50i_h616/sunxi_power.c
new file mode 100644
index 0000000..dd6ebba
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/sunxi_power.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/allwinner/axp.h>
+#include <drivers/allwinner/sunxi_rsb.h>
+#include <lib/mmio.h>
+
+#include <sunxi_cpucfg.h>
+#include <sunxi_def.h>
+#include <sunxi_mmap.h>
+#include <sunxi_private.h>
+
+#define AXP305_I2C_ADDR 0x36
+#define AXP305_HW_ADDR 0x745
+#define AXP305_RT_ADDR 0x3a
+
+static enum pmic_type {
+ UNKNOWN,
+ AXP305,
+} pmic;
+
+int axp_read(uint8_t reg)
+{
+ return rsb_read(AXP305_RT_ADDR, reg);
+}
+
+int axp_write(uint8_t reg, uint8_t val)
+{
+ return rsb_write(AXP305_RT_ADDR, reg, val);
+}
+
+static int rsb_init(void)
+{
+ int ret;
+
+ ret = rsb_init_controller();
+ if (ret)
+ return ret;
+
+ /* Switch to the recommended 3 MHz bus clock. */
+ ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
+ if (ret)
+ return ret;
+
+ /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
+ ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
+ if (ret)
+ return ret;
+
+ /* Associate the 8-bit runtime address with the 12-bit bus address. */
+ ret = rsb_assign_runtime_address(AXP305_HW_ADDR, AXP305_RT_ADDR);
+ if (ret)
+ return ret;
+
+ return axp_check_id();
+}
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+ int ret;
+
+ INFO("PMIC: Probing AXP305 on RSB\n");
+
+ ret = sunxi_init_platform_r_twi(socid, true);
+ if (ret) {
+ INFO("Could not init platform bus: %d\n", ret);
+ return ret;
+ }
+
+ ret = rsb_init();
+ if (ret) {
+ INFO("Could not init RSB: %d\n", ret);
+ return ret;
+ }
+
+ pmic = AXP305;
+ axp_setup_regulators(fdt);
+
+ /* Switch the PMIC back to I2C mode. */
+ ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void sunxi_power_down(void)
+{
+ switch (pmic) {
+ case AXP305:
+ /* Re-initialise after rich OS might have used it. */
+ sunxi_init_platform_r_twi(SUNXI_SOC_H616, true);
+ rsb_init();
+ axp_power_off();
+ break;
+ default:
+ break;
+ }
+}
+
+void sunxi_cpu_power_off_self(void)
+{
+ u_register_t mpidr = read_mpidr();
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* Enable the CPUIDLE hardware (only really needs to be done once). */
+ mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
+ mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
+
+ /* Trigger power off for this core. */
+ mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
+}
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_ccu.h b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
new file mode 100644
index 0000000..0e6b543
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..9478f32
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_C0_CPUXCFG_BASE + 0x0010)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_C0_CPUXCFG_BASE + 0x0014)
+#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_C0_CPUXCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_C0_CPUXCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_C0_CPUXCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_GEN_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
+ (c) * 0x10 + (n) * 4)
+
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_GEN_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 4
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_mmap.h b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
new file mode 100644
index 0000000..a4469b5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_MMAP_H
+#define SUNXI_MMAP_H
+
+/* Memory regions */
+#define SUNXI_ROM_BASE 0x00000000
+#define SUNXI_ROM_SIZE 0x00010000
+/*
+ * In fact all SRAM from 0x100000 is SRAM A2. However as it's too big for
+ * firmware, and the user manual gives a tip on a 2*64K/27*64K partition,
+ * only use the first 2*64K for firmwares now, with the SPL using the first
+ * 64K and BL3-1 using the second one.
+ *
+ * Only the used 2*64K SRAM is defined here, to prevent a gaint translation
+ * table to be generated.
+ */
+#define SUNXI_SRAM_BASE 0x00100000
+#define SUNXI_SRAM_SIZE 0x00020000
+#define SUNXI_SRAM_A1_BASE 0x00100000
+#define SUNXI_SRAM_A1_SIZE 0x00010000
+#define SUNXI_SRAM_A2_BASE 0x00110000
+#define SUNXI_SRAM_A2_BL31_OFFSET 0x00000000
+#define SUNXI_SRAM_A2_SIZE 0x00010000
+#define SUNXI_DEV_BASE 0x01000000
+#define SUNXI_DEV_SIZE 0x09000000
+#define SUNXI_DRAM_BASE 0x40000000
+#define SUNXI_DRAM_VIRT_BASE 0x0a000000
+
+/* Memory-mapped devices */
+#define SUNXI_WDOG_BASE 0x020000a0
+#define SUNXI_R_WDOG_BASE SUNXI_WDOG_BASE
+#define SUNXI_PIO_BASE 0x02000400
+#define SUNXI_SPC_BASE 0x02000800
+#define SUNXI_CCU_BASE 0x02001000
+#define SUNXI_UART0_BASE 0x02500000
+#define SUNXI_SYSCON_BASE 0x03000000
+#define SUNXI_DMA_BASE 0x03002000
+#define SUNXI_SID_BASE 0x03006000
+#define SUNXI_GICD_BASE 0x03021000
+#define SUNXI_GICC_BASE 0x03022000
+#define SUNXI_SPI0_BASE 0x04025000
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_R_PRCM_BASE 0x07010000
+#define SUNXI_R_PIO_BASE 0x07022000
+#define SUNXI_R_UART_BASE 0x07080000
+#define SUNXI_R_I2C_BASE 0x07081400
+#define SUNXI_CPUCFG_BASE 0x08100000
+#define SUNXI_C0_CPUXCFG_BASE 0x09010000
+
+#endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_spc.h b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
new file mode 100644
index 0000000..2c87bca
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+/* Get by REing stock ATF and checking initialization loop boundary */
+#define SUNXI_SPC_NUM_PORTS 11
+
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_r329/platform.mk b/plat/allwinner/sun50i_r329/platform.mk
new file mode 100644
index 0000000..05d7cde
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021 Sipeed
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Without a management processor there is no SCPI support.
+SUNXI_PSCI_USE_SCPI := 0
+SUNXI_PSCI_USE_NATIVE := 1
+
+# The differences between the platforms are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
+
+# the above could be overwritten on the command line
+ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
+ $(error "R329 does not support SCPI PSCI ops")
+endif
+
+# Put NOBITS memory in the first 64K of SRAM A2, overwriting U-Boot's SPL.
+SEPARATE_NOBITS_REGION := 1
diff --git a/plat/allwinner/sun50i_r329/sunxi_idle_states.c b/plat/allwinner/sun50i_r329/sunxi_idle_states.c
new file mode 100644
index 0000000..4339bcd
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/sunxi_idle_states.c
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <sunxi_private.h>
+
+const struct psci_cpu_idle_state sunxi_idle_states[] = {
+ {}
+};
diff --git a/plat/allwinner/sun50i_r329/sunxi_power.c b/plat/allwinner/sun50i_r329/sunxi_power.c
new file mode 100644
index 0000000..96a24d5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/sunxi_power.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_cpucfg.h>
+#include <sunxi_private.h>
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+ /* Currently known hardware has no PMIC */
+
+ return 0;
+}
+
+void sunxi_power_down(void)
+{
+}
+
+void sunxi_cpu_power_off_self(void)
+{
+ /* TODO: It's still unknown whether CPUIDLE exists on R329 */
+}
diff --git a/plat/amlogic/axg/axg_bl31_setup.c b/plat/amlogic/axg/axg_bl31_setup.c
new file mode 100644
index 0000000..8cc9d69
--- /dev/null
+++ b/plat/amlogic/axg/axg_bl31_setup.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static image_info_t bl30_image_info;
+static image_info_t bl301_image_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ?
+ &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc != 0U)
+ return next_image_info;
+
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+struct axg_bl31_param {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+ image_info_t *scp_image_info[];
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct axg_bl31_param *from_bl2;
+
+ /* Initialize the console to provide early debug support */
+ aml_console_init();
+
+ from_bl2 = (struct axg_bl31_param *)arg0;
+
+ /* Check params passed from BL2 are not NULL. */
+ assert(from_bl2 != NULL);
+ assert(from_bl2->h.type == PARAM_BL31);
+ assert(from_bl2->h.version >= VERSION_1);
+
+ /*
+ * Copy BL32 and BL33 entry point information. It is stored in Secure
+ * RAM, in BL2's address space.
+ */
+ bl32_image_ep_info = *from_bl2->bl32_ep_info;
+ bl33_image_ep_info = *from_bl2->bl33_ep_info;
+
+#if AML_USE_ATOS
+ /*
+ * BL2 is unconditionally setting 0 (OPTEE_AARCH64) in arg0 even when
+ * the BL32 image is 32bit (OPTEE_AARCH32). This is causing the boot to
+ * hang when ATOS (32bit Amlogic BL32 binary-only TEE OS) is used.
+ *
+ * Hardcode to OPTEE_AARCH32 / MODE_RW_32.
+ */
+ bl32_image_ep_info.args.arg0 = MODE_RW_32;
+#endif
+
+ if (bl33_image_ep_info.pc == 0U) {
+ ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
+ panic();
+ }
+
+ bl30_image_info = *from_bl2->scp_image_info[0];
+ bl301_image_info = *from_bl2->scp_image_info[1];
+}
+
+void bl31_plat_arch_setup(void)
+{
+ aml_setup_page_tables();
+
+ enable_mmu_el3(0);
+}
+
+static inline bool axg_scp_ready(void)
+{
+ return AML_AO_RTI_SCP_IS_READY(mmio_read_32(AML_AO_RTI_SCP_STAT));
+}
+
+static inline void axg_scp_boot(void)
+{
+ aml_scpi_upload_scp_fw(bl30_image_info.image_base,
+ bl30_image_info.image_size, 0);
+ aml_scpi_upload_scp_fw(bl301_image_info.image_base,
+ bl301_image_info.image_size, 1);
+ while (!axg_scp_ready())
+ ;
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t axg_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+};
+
+static const gicv2_driver_data_t axg_gic_data = {
+ .gicd_base = AML_GICD_BASE,
+ .gicc_base = AML_GICC_BASE,
+ .interrupt_props = axg_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(axg_interrupt_props)
+};
+
+void bl31_platform_setup(void)
+{
+ aml_mhu_secure_init();
+
+ gicv2_driver_init(&axg_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ axg_scp_boot();
+}
diff --git a/plat/amlogic/axg/axg_common.c b/plat/amlogic/axg/axg_common.c
new file mode 100644
index 0000000..870daf4
--- /dev/null
+++ b/plat/amlogic/axg/axg_common.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/ep_info.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
+ AML_NSDRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NS_SHARE_MEM MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE, \
+ AML_NS_SHARE_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_SHARE_MEM MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE, \
+ AML_SEC_SHARE_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
+ AML_SEC_DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW)
+
+#define MAP_GIC_DEVICE MAP_REGION_FLAT(AML_GIC_DEVICE_BASE, \
+ AML_GIC_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
+ AML_SEC_DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
+ AML_SEC_DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
+ AML_TZRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t axg_mmap[] = {
+ MAP_NSDRAM0,
+ MAP_NS_SHARE_MEM,
+ MAP_SEC_SHARE_MEM,
+ MAP_SEC_DEVICE0,
+ MAP_GIC_DEVICE,
+ MAP_SEC_DEVICE1,
+ MAP_SEC_DEVICE2,
+ MAP_TZRAM,
+ {0}
+};
+
+/*******************************************************************************
+ * Per-image regions
+ ******************************************************************************/
+#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
+ BL31_END - BL31_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
+ BL_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+
+#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
+ BL_RO_DATA_END - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+
+#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void aml_setup_page_tables(void)
+{
+#if IMAGE_BL31
+ const mmap_region_t axg_bl_mmap[] = {
+ MAP_BL31,
+ MAP_BL_CODE,
+ MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+ MAP_BL_COHERENT,
+#endif
+ {0}
+ };
+#endif
+
+ mmap_add(axg_bl_mmap);
+
+ mmap_add(axg_mmap);
+
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ mmio_clrbits_32(AML_SYS_CPU_CFG7, PLAT_SYS_CPU_CFG7);
+ mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, PLAT_AO_TIMESTAMP_CNTL);
+
+ return AML_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/amlogic/axg/axg_def.h b/plat/amlogic/axg/axg_def.h
new file mode 100644
index 0000000..d90681a
--- /dev/null
+++ b/plat/amlogic/axg/axg_def.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AXG_DEF_H
+#define AXG_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define AML_NS_SHARE_MEM_BASE UL(0x05000000)
+#define AML_NS_SHARE_MEM_SIZE UL(0x00100000)
+
+#define AML_SEC_SHARE_MEM_BASE UL(0x05200000)
+#define AML_SEC_SHARE_MEM_SIZE UL(0x00100000)
+
+#define AML_GIC_DEVICE_BASE UL(0xFFC00000)
+#define AML_GIC_DEVICE_SIZE UL(0x00008000)
+
+#define AML_NSDRAM0_BASE UL(0x01000000)
+#define AML_NSDRAM0_SIZE UL(0x0F000000)
+
+#define BL31_BASE UL(0x05100000)
+#define BL31_SIZE UL(0x00100000)
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000)
+#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
+
+#define AML_SEC_DEVICE0_BASE UL(0xFFD00000)
+#define AML_SEC_DEVICE0_SIZE UL(0x00026000)
+
+#define AML_SEC_DEVICE1_BASE UL(0xFF800000)
+#define AML_SEC_DEVICE1_SIZE UL(0x0000A000)
+
+#define AML_SEC_DEVICE2_BASE UL(0xFF620000)
+#define AML_SEC_DEVICE2_SIZE UL(0x00028000)
+
+#define AML_TZRAM_BASE UL(0xFFFC0000)
+#define AML_TZRAM_SIZE UL(0x00020000)
+
+/* Mailboxes */
+#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xFFFD3800)
+#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xFFFD3A00)
+#define AML_PSCI_MAILBOX_BASE UL(0xFFFD3F00)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define AML_GICD_BASE UL(0xFFC01000)
+#define AML_GICC_BASE UL(0xFFC02000)
+
+#define IRQ_SEC_PHY_TIMER 29
+
+#define IRQ_SEC_SGI_0 8
+#define IRQ_SEC_SGI_1 9
+#define IRQ_SEC_SGI_2 10
+#define IRQ_SEC_SGI_3 11
+#define IRQ_SEC_SGI_4 12
+#define IRQ_SEC_SGI_5 13
+#define IRQ_SEC_SGI_6 14
+#define IRQ_SEC_SGI_7 15
+#define IRQ_SEC_SGI_8 16
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define AML_UART0_AO_BASE UL(0xFF803000)
+#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
+#define AML_UART_BAUDRATE U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define AML_AO_TIMESTAMP_CNTL UL(0xFF8000B4)
+
+#define AML_SYS_CPU_CFG7 UL(0xFF634664)
+
+#define AML_AO_RTI_STATUS_REG3 UL(0xFF80001C)
+#define AML_AO_RTI_SCP_STAT UL(0xFF80023C)
+#define AML_AO_RTI_SCP_READY_OFF U(0x14)
+#define AML_A0_RTI_SCP_READY_MASK U(3)
+#define AML_AO_RTI_SCP_IS_READY(v) \
+ ((((v) >> AML_AO_RTI_SCP_READY_OFF) & \
+ AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
+
+#define AML_HIU_MAILBOX_SET_0 UL(0xFF63C404)
+#define AML_HIU_MAILBOX_STAT_0 UL(0xFF63C408)
+#define AML_HIU_MAILBOX_CLR_0 UL(0xFF63C40C)
+#define AML_HIU_MAILBOX_SET_3 UL(0xFF63C428)
+#define AML_HIU_MAILBOX_STAT_3 UL(0xFF63C42C)
+#define AML_HIU_MAILBOX_CLR_3 UL(0xFF63C430)
+
+#define AML_SHA_DMA_BASE UL(0xFF63E000)
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x28)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
+#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
+
+#define AML_SM_EFUSE_READ U(0x82000030)
+#define AML_SM_EFUSE_USER_MAX U(0x82000033)
+
+#define AML_SM_JTAG_ON U(0x82000040)
+#define AML_SM_JTAG_OFF U(0x82000041)
+#define AML_SM_GET_CHIP_ID U(0x82000044)
+
+#define AML_JTAG_STATE_ON U(0)
+#define AML_JTAG_STATE_OFF U(1)
+
+#define AML_JTAG_M3_AO U(0)
+#define AML_JTAG_M3_EE U(1)
+#define AML_JTAG_A53_AO U(2)
+#define AML_JTAG_A53_EE U(3)
+
+#endif /* AXG_DEF_H */
diff --git a/plat/amlogic/axg/axg_pm.c b/plat/amlogic/axg/axg_pm.c
new file mode 100644
index 0000000..e67f263
--- /dev/null
+++ b/plat/amlogic/axg/axg_pm.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+#define SCPI_POWER_ON 0
+#define SCPI_POWER_RETENTION 1
+#define SCPI_POWER_OFF 3
+
+#define SCPI_SYSTEM_SHUTDOWN 0
+#define SCPI_SYSTEM_REBOOT 1
+
+static uintptr_t axg_sec_entrypoint;
+
+static void axg_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
+
+ mmio_write_64(cpu_mailbox_addr, value);
+}
+
+static void axg_pm_reset(u_register_t mpidr, uint32_t value)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
+
+ mmio_write_32(cpu_mailbox_addr, value);
+}
+
+static void __dead2 axg_system_reset(void)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ int ret;
+
+ INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
+ panic();
+ }
+
+ axg_pm_reset(mpidr, 0);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+ panic();
+}
+
+static void __dead2 axg_system_off(void)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ int ret;
+
+ INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
+ panic();
+ }
+
+ axg_pm_set_reset_addr(mpidr, 0);
+ axg_pm_reset(mpidr, 0);
+
+ dmbsy();
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+ panic();
+}
+
+static int32_t axg_pwr_domain_on(u_register_t mpidr)
+{
+ axg_pm_set_reset_addr(mpidr, axg_sec_entrypoint);
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+ dmbsy();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void axg_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ axg_pm_set_reset_addr(read_mpidr_el1(), 0);
+}
+
+static void axg_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ uint32_t system_state = SCPI_POWER_ON;
+ uint32_t cluster_state = SCPI_POWER_ON;
+
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ axg_pm_reset(mpidr, -1);
+
+ gicv2_cpuif_disable();
+
+ if (target_state->pwr_domain_state[MPIDR_AFFLVL2] ==
+ PLAT_LOCAL_STATE_OFF)
+ system_state = SCPI_POWER_OFF;
+
+ if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
+ PLAT_LOCAL_STATE_OFF)
+ cluster_state = SCPI_POWER_OFF;
+
+
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_OFF, cluster_state,
+ system_state);
+}
+
+static void __dead2 axg_pwr_domain_pwr_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ dsbsy();
+ axg_pm_reset(read_mpidr_el1(), 0);
+
+ for (;;)
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t axg_ops = {
+ .pwr_domain_on = axg_pwr_domain_on,
+ .pwr_domain_on_finish = axg_pwr_domain_on_finish,
+ .pwr_domain_off = axg_pwr_domain_off,
+ .pwr_domain_pwr_down_wfi = axg_pwr_domain_pwr_down_wfi,
+ .system_off = axg_system_off,
+ .system_reset = axg_system_reset
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ axg_sec_entrypoint = sec_entrypoint;
+ *psci_ops = &axg_ops;
+ return 0;
+}
diff --git a/plat/amlogic/axg/include/platform_def.h b/plat/amlogic/axg/include/platform_def.h
new file mode 100644
index 0000000..c97687e
--- /dev/null
+++ b/plat/amlogic/axg/include/platform_def.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "../axg_def.h"
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE UL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define AML_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+#define PLAT_SYS_CPU_CFG7 (U(1) << 25)
+#define PLAT_AO_TIMESTAMP_CNTL U(0x1ff)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains. */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* Memory-related defines */
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS 16
+#define MAX_XLAT_TABLES 8
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amlogic/axg/platform.mk b/plat/amlogic/axg/platform.mk
new file mode 100644
index 0000000..3560b0c
--- /dev/null
+++ b/plat/amlogic/axg/platform.mk
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AML_PLAT := plat/amlogic
+AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
+AML_PLAT_COMMON := ${AML_PLAT}/common
+
+DOIMAGEPATH ?= tools/amlogic
+DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
+
+PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
+ -I${AML_PLAT_SOC}/include \
+ -I${AML_PLAT_COMMON}/include
+
+GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ drivers/amlogic/console/aarch64/meson_console.S \
+ ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
+ ${AML_PLAT_SOC}/${PLAT}_pm.c \
+ ${AML_PLAT_SOC}/${PLAT}_common.c \
+ ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
+ ${AML_PLAT_COMMON}/aml_efuse.c \
+ ${AML_PLAT_COMMON}/aml_mhu.c \
+ ${AML_PLAT_COMMON}/aml_scpi.c \
+ ${AML_PLAT_COMMON}/aml_sip_svc.c \
+ ${AML_PLAT_COMMON}/aml_thermal.c \
+ ${AML_PLAT_COMMON}/aml_topology.c \
+ ${AML_PLAT_COMMON}/aml_console.c \
+ drivers/amlogic/crypto/sha_dma.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${GIC_SOURCES}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_855873 := 1
+ERRATA_A53_819472 := 1
+ERRATA_A53_824069 := 1
+ERRATA_A53_827319 := 1
+
+WORKAROUND_CVE_2017_5715 := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+AML_USE_ATOS := 0
+$(eval $(call assert_boolean,AML_USE_ATOS))
+$(eval $(call add_define,AML_USE_ATOS))
+
+# Verify build config
+# -------------------
+
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: ${PLAT} needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on ${PLAT})
+endif
+
+all: ${BUILD_PLAT}/bl31.img
+distclean realclean clean: cleanimage
+
+cleanimage:
+ ${Q}${MAKE} -C ${DOIMAGEPATH} clean
+
+${DOIMAGETOOL}:
+ ${Q}${MAKE} -C ${DOIMAGEPATH}
+
+${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
+ ${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
+
diff --git a/plat/amlogic/common/aarch64/aml_helpers.S b/plat/amlogic/common/aarch64/aml_helpers.S
new file mode 100644
index 0000000..159c7d1
--- /dev/null
+++ b/plat/amlogic/common/aarch64/aml_helpers.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018-2020, 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 <platform_def.h>
+
+ .globl plat_crash_console_flush
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl platform_mem_init
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+ .globl plat_calc_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void);
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_calc_core_pos(u_register_t mpidr);
+ * -----------------------------------------------------
+ */
+func plat_calc_core_pos
+ and x0, x0, #MPIDR_CPU_MASK
+ ret
+endfunc plat_calc_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary(void);
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #AML_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* ---------------------------------------------
+ * void platform_mem_init(void);
+ * ---------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, AML_UART0_AO_BASE
+ mov_imm x1, AML_UART0_AO_CLK_IN_HZ
+ mov_imm x2, AML_UART_BAUDRATE
+ b console_meson_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, AML_UART0_AO_BASE
+ b console_meson_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, AML_UART0_AO_BASE
+ b console_meson_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * void plat_reset_handler(void);
+ * ---------------------------------------------
+ */
+func plat_reset_handler
+ ret
+endfunc plat_reset_handler
diff --git a/plat/amlogic/common/aml_console.c b/plat/amlogic/common/aml_console.c
new file mode 100644
index 0000000..e21d707
--- /dev/null
+++ b/plat/amlogic/common/aml_console.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019, Carlo Caione <ccaione@baylibre.com>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <meson_console.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Function that sets up the console
+ ******************************************************************************/
+static console_t aml_console;
+
+void aml_console_init(void)
+{
+ int rc = console_meson_register(AML_UART0_AO_BASE,
+ AML_UART0_AO_CLK_IN_HZ,
+ AML_UART_BAUDRATE,
+ &aml_console);
+ if (rc == 0) {
+ /*
+ * The crash console doesn't use the multi console API, it uses
+ * the core console functions directly. It is safe to call panic
+ * and let it print debug information.
+ */
+ panic();
+ }
+
+ console_set_scope(&aml_console,
+ CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+}
diff --git a/plat/amlogic/common/aml_efuse.c b/plat/amlogic/common/aml_efuse.c
new file mode 100644
index 0000000..00884eb
--- /dev/null
+++ b/plat/amlogic/common/aml_efuse.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "aml_private.h"
+
+#define EFUSE_BASE 0x140
+#define EFUSE_SIZE 0xC0
+
+uint64_t aml_efuse_read(void *dst, uint32_t offset, uint32_t size)
+{
+ if ((uint64_t)(offset + size) > (uint64_t)EFUSE_SIZE)
+ return 0;
+
+ return aml_scpi_efuse_read(dst, offset + EFUSE_BASE, size);
+}
+
+uint64_t aml_efuse_user_max(void)
+{
+ return EFUSE_SIZE;
+}
diff --git a/plat/amlogic/common/aml_mhu.c b/plat/amlogic/common/aml_mhu.c
new file mode 100644
index 0000000..001686a
--- /dev/null
+++ b/plat/amlogic/common/aml_mhu.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+static DEFINE_BAKERY_LOCK(mhu_lock);
+
+void aml_mhu_secure_message_start(void)
+{
+ bakery_lock_get(&mhu_lock);
+
+ while (mmio_read_32(AML_HIU_MAILBOX_STAT_3) != 0)
+ ;
+}
+
+void aml_mhu_secure_message_send(uint32_t msg)
+{
+ mmio_write_32(AML_HIU_MAILBOX_SET_3, msg);
+
+ while (mmio_read_32(AML_HIU_MAILBOX_STAT_3) != 0)
+ ;
+}
+
+uint32_t aml_mhu_secure_message_wait(void)
+{
+ uint32_t val;
+
+ do {
+ val = mmio_read_32(AML_HIU_MAILBOX_STAT_0);
+ } while (val == 0);
+
+ return val;
+}
+
+void aml_mhu_secure_message_end(void)
+{
+ mmio_write_32(AML_HIU_MAILBOX_CLR_0, 0xFFFFFFFF);
+
+ bakery_lock_release(&mhu_lock);
+}
+
+void aml_mhu_secure_init(void)
+{
+ bakery_lock_init(&mhu_lock);
+
+ mmio_write_32(AML_HIU_MAILBOX_CLR_3, 0xFFFFFFFF);
+}
diff --git a/plat/amlogic/common/aml_scpi.c b/plat/amlogic/common/aml_scpi.c
new file mode 100644
index 0000000..c8a6772
--- /dev/null
+++ b/plat/amlogic/common/aml_scpi.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <crypto/sha_dma.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <string.h>
+
+#include "aml_private.h"
+
+#define SIZE_SHIFT 20
+#define SIZE_MASK 0x1FF
+#define SIZE_FWBLK 0x200UL
+
+/*
+ * Note: The Amlogic SCP firmware uses the legacy SCPI protocol.
+ */
+#define SCPI_CMD_SET_CSS_POWER_STATE 0x04
+#define SCPI_CMD_SET_SYS_POWER_STATE 0x08
+
+#define SCPI_CMD_JTAG_SET_STATE 0xC0
+#define SCPI_CMD_EFUSE_READ 0xC2
+#define SCPI_CMD_CHIP_ID 0xC6
+
+#define SCPI_CMD_COPY_FW 0xd4
+#define SCPI_CMD_SET_FW_ADDR 0xd3
+#define SCPI_CMD_FW_SIZE 0xd2
+
+static inline uint32_t aml_scpi_cmd(uint32_t command, uint32_t size)
+{
+ return command | (size << SIZE_SHIFT);
+}
+
+static void aml_scpi_secure_message_send(uint32_t command, uint32_t size)
+{
+ aml_mhu_secure_message_send(aml_scpi_cmd(command, size));
+}
+
+static uint32_t aml_scpi_secure_message_receive(void **message_out, size_t *size_out)
+{
+ uint32_t response = aml_mhu_secure_message_wait();
+
+ size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
+
+ response &= ~(SIZE_MASK << SIZE_SHIFT);
+
+ if (size_out != NULL)
+ *size_out = size;
+
+ if (message_out != NULL)
+ *message_out = (void *)AML_MHU_SECURE_SCP_TO_AP_PAYLOAD;
+
+ return response;
+}
+
+void aml_scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
+ uint32_t cluster_state, uint32_t css_state)
+{
+ uint32_t state = (mpidr & 0x0F) | /* CPU ID */
+ ((mpidr & 0xF00) >> 4) | /* Cluster ID */
+ (cpu_state << 8) |
+ (cluster_state << 12) |
+ (css_state << 16);
+
+ aml_mhu_secure_message_start();
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, state);
+ aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4));
+ aml_mhu_secure_message_wait();
+ aml_mhu_secure_message_end();
+}
+
+uint32_t aml_scpi_sys_power_state(uint64_t system_state)
+{
+ uint32_t *response;
+ size_t size;
+
+ aml_mhu_secure_message_start();
+ mmio_write_8(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state);
+ aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1));
+ aml_scpi_secure_message_receive((void *)&response, &size);
+ aml_mhu_secure_message_end();
+
+ return *response;
+}
+
+void aml_scpi_jtag_set_state(uint32_t state, uint8_t select)
+{
+ assert(state <= AML_JTAG_STATE_OFF);
+
+ if (select > AML_JTAG_A53_EE) {
+ WARN("BL31: Invalid JTAG select (0x%x).\n", select);
+ return;
+ }
+
+ aml_mhu_secure_message_start();
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD,
+ (state << 8) | (uint32_t)select);
+ aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4));
+ aml_mhu_secure_message_wait();
+ aml_mhu_secure_message_end();
+}
+
+uint32_t aml_scpi_efuse_read(void *dst, uint32_t base, uint32_t size)
+{
+ uint32_t *response;
+ size_t resp_size;
+
+ if (size > 0x1FC)
+ return 0;
+
+ aml_mhu_secure_message_start();
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, base);
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size);
+ aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_EFUSE_READ, 8));
+ aml_scpi_secure_message_receive((void *)&response, &resp_size);
+ aml_mhu_secure_message_end();
+
+ /*
+ * response[0] is the size of the response message.
+ * response[1 ... N] are the contents.
+ */
+ if (*response != 0)
+ memcpy(dst, response + 1, *response);
+
+ return *response;
+}
+
+void aml_scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
+ uint32_t arg2, uint32_t arg3)
+{
+ aml_mhu_secure_message_start();
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0);
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1);
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2);
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3);
+ aml_mhu_secure_message_send(aml_scpi_cmd(0xC3, 16));
+ aml_mhu_secure_message_wait();
+ aml_mhu_secure_message_end();
+}
+
+uint32_t aml_scpi_get_chip_id(uint8_t *obuff, uint32_t osize)
+{
+ uint32_t *response;
+ size_t resp_size;
+
+ if ((osize != 16) && (osize != 12))
+ return 0;
+
+ aml_mhu_secure_message_start();
+ aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_CHIP_ID, osize));
+ aml_scpi_secure_message_receive((void *)&response, &resp_size);
+ aml_mhu_secure_message_end();
+
+ if (!((resp_size == 16) && (osize == 16)) &&
+ !((resp_size == 0) && (osize == 12)))
+ return 0;
+
+ memcpy((void *)obuff, (const void *)response, osize);
+
+ return osize;
+}
+
+static inline void aml_scpi_copy_scp_data(uint8_t *data, size_t len)
+{
+ void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+ size_t sz;
+
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
+ aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
+ aml_mhu_secure_message_wait();
+
+ for (sz = 0; sz < len; sz += SIZE_FWBLK) {
+ memcpy(dst, data + sz, MIN(SIZE_FWBLK, len - sz));
+ aml_mhu_secure_message_send(SCPI_CMD_COPY_FW);
+ }
+}
+
+static inline void aml_scpi_set_scp_addr(uint64_t addr, size_t len)
+{
+ volatile uint64_t *dst = (uint64_t *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+
+ /*
+ * It is ok as AML_MHU_SECURE_AP_TO_SCP_PAYLOAD is mapped as
+ * non cachable
+ */
+ *dst = addr;
+ aml_scpi_secure_message_send(SCPI_CMD_SET_FW_ADDR, sizeof(addr));
+ aml_mhu_secure_message_wait();
+
+ mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
+ aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
+ aml_mhu_secure_message_wait();
+}
+
+static inline void aml_scpi_send_fw_hash(uint8_t hash[], size_t len)
+{
+ void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
+
+ memcpy(dst, hash, len);
+ aml_mhu_secure_message_send(0xd0);
+ aml_mhu_secure_message_send(0xd1);
+ aml_mhu_secure_message_send(0xd5);
+ aml_mhu_secure_message_end();
+}
+
+/**
+ * Upload a FW to SCP.
+ *
+ * @param addr: firmware data address
+ * @param size: size of firmware
+ * @param send: If set, actually copy the firmware in SCP memory otherwise only
+ * send the firmware address.
+ */
+void aml_scpi_upload_scp_fw(uintptr_t addr, size_t size, int send)
+{
+ struct asd_ctx ctx;
+
+ asd_sha_init(&ctx, ASM_SHA256);
+ asd_sha_update(&ctx, (void *)addr, size);
+ asd_sha_finalize(&ctx);
+
+ aml_mhu_secure_message_start();
+ if (send == 0)
+ aml_scpi_set_scp_addr(addr, size);
+ else
+ aml_scpi_copy_scp_data((void *)addr, size);
+
+ aml_scpi_send_fw_hash(ctx.digest, sizeof(ctx.digest));
+}
diff --git a/plat/amlogic/common/aml_sip_svc.c b/plat/amlogic/common/aml_sip_svc.c
new file mode 100644
index 0000000..ab4c015
--- /dev/null
+++ b/plat/amlogic/common/aml_sip_svc.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "aml_private.h"
+
+struct aml_cpu_info {
+ uint32_t version;
+ uint8_t chip_id[16];
+};
+
+static int aml_sip_get_chip_id(uint64_t version)
+{
+ struct aml_cpu_info *info = (void *)AML_SHARE_MEM_OUTPUT_BASE;
+ uint32_t size;
+
+ if (version > 2)
+ return -1;
+
+ memset(info, 0, sizeof(struct aml_cpu_info));
+
+ if (version == 2) {
+ info->version = 2;
+ size = 16;
+ } else {
+ info->version = 1;
+ size = 12;
+ }
+
+ if (aml_scpi_get_chip_id(info->chip_id, size) == 0)
+ return -1;
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function is responsible for handling all SiP calls
+ ******************************************************************************/
+static uintptr_t aml_sip_handler(uint32_t smc_fid,
+ u_register_t x1, u_register_t x2,
+ u_register_t x3, u_register_t x4,
+ void *cookie, void *handle,
+ u_register_t flags)
+{
+ switch (smc_fid) {
+
+ case AML_SM_GET_SHARE_MEM_INPUT_BASE:
+ SMC_RET1(handle, AML_SHARE_MEM_INPUT_BASE);
+
+ case AML_SM_GET_SHARE_MEM_OUTPUT_BASE:
+ SMC_RET1(handle, AML_SHARE_MEM_OUTPUT_BASE);
+
+ case AML_SM_EFUSE_READ:
+ {
+ void *dst = (void *)AML_SHARE_MEM_OUTPUT_BASE;
+ uint64_t ret = aml_efuse_read(dst, (uint32_t)x1, x2);
+
+ SMC_RET1(handle, ret);
+ }
+ case AML_SM_EFUSE_USER_MAX:
+ SMC_RET1(handle, aml_efuse_user_max());
+
+ case AML_SM_JTAG_ON:
+ aml_scpi_jtag_set_state(AML_JTAG_STATE_ON, x1);
+ SMC_RET1(handle, 0);
+
+ case AML_SM_JTAG_OFF:
+ aml_scpi_jtag_set_state(AML_JTAG_STATE_OFF, x1);
+ SMC_RET1(handle, 0);
+
+ case AML_SM_GET_CHIP_ID:
+ SMC_RET1(handle, aml_sip_get_chip_id(x1));
+
+ default:
+ ERROR("BL31: Unhandled SIP SMC: 0x%08x\n", smc_fid);
+ break;
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+}
+
+DECLARE_RT_SVC(
+ aml_sip_handler,
+
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ aml_sip_handler
+);
diff --git a/plat/amlogic/common/aml_thermal.c b/plat/amlogic/common/aml_thermal.c
new file mode 100644
index 0000000..53ed103
--- /dev/null
+++ b/plat/amlogic/common/aml_thermal.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "aml_private.h"
+
+static int32_t modules_initialized = -1;
+
+/*******************************************************************************
+ * Unknown commands related to something thermal-related
+ ******************************************************************************/
+void aml_thermal_unknown(void)
+{
+ uint16_t ret;
+
+ if (modules_initialized == -1) {
+ aml_scpi_efuse_read(&ret, 0, 2);
+ modules_initialized = ret;
+ }
+
+ aml_scpi_unknown_thermal(10, 2, /* thermal */
+ 13, 1); /* thermalver */
+}
diff --git a/plat/amlogic/common/aml_topology.c b/plat/amlogic/common/aml_topology.c
new file mode 100644
index 0000000..0a04c11
--- /dev/null
+++ b/plat/amlogic/common/aml_topology.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+#include "aml_private.h"
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first node */
+ PLATFORM_CLUSTER0_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return plat_calc_core_pos(mpidr);
+}
diff --git a/plat/amlogic/common/include/aml_private.h b/plat/amlogic/common/include/aml_private.h
new file mode 100644
index 0000000..724f382
--- /dev/null
+++ b/plat/amlogic/common/include/aml_private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AML_PRIVATE_H
+#define AML_PRIVATE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* Utility functions */
+unsigned int plat_calc_core_pos(u_register_t mpidr);
+void aml_console_init(void);
+void aml_setup_page_tables(void);
+
+/* MHU functions */
+void aml_mhu_secure_message_start(void);
+void aml_mhu_secure_message_send(uint32_t msg);
+uint32_t aml_mhu_secure_message_wait(void);
+void aml_mhu_secure_message_end(void);
+void aml_mhu_secure_init(void);
+
+/* SCPI functions */
+void aml_scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
+ uint32_t cluster_state, uint32_t css_state);
+uint32_t aml_scpi_sys_power_state(uint64_t system_state);
+void aml_scpi_jtag_set_state(uint32_t state, uint8_t select);
+uint32_t aml_scpi_efuse_read(void *dst, uint32_t base, uint32_t size);
+void aml_scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
+ uint32_t arg2, uint32_t arg3);
+void aml_scpi_upload_scp_fw(uintptr_t addr, size_t size, int send);
+uint32_t aml_scpi_get_chip_id(uint8_t *obuff, uint32_t osize);
+
+/* Peripherals */
+void aml_thermal_unknown(void);
+uint64_t aml_efuse_read(void *dst, uint32_t offset, uint32_t size);
+uint64_t aml_efuse_user_max(void);
+
+#endif /* AML_PRIVATE_H */
diff --git a/plat/amlogic/common/include/plat_macros.S b/plat/amlogic/common/include/plat_macros.S
new file mode 100644
index 0000000..d620fcf
--- /dev/null
+++ b/plat/amlogic/common/include/plat_macros.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <drivers/arm/gicv2.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+
+ /* GICC registers */
+
+ mov_imm x17, AML_GICC_BASE
+
+ adr x6, gicc_regs
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ bl str_in_crash_buf_print
+
+ /* GICD registers */
+
+ mov_imm x16, AML_GICD_BASE
+
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/amlogic/g12a/g12a_bl31_setup.c b/plat/amlogic/g12a/g12a_bl31_setup.c
new file mode 100644
index 0000000..77057a1
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_bl31_setup.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static image_info_t bl30_image_info;
+static image_info_t bl301_image_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ?
+ &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc != 0U)
+ return next_image_info;
+
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+struct g12a_bl31_param {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+ image_info_t *scp_image_info[];
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct g12a_bl31_param *from_bl2;
+
+ /* Initialize the console to provide early debug support */
+ aml_console_init();
+
+ from_bl2 = (struct g12a_bl31_param *)arg0;
+
+ /* Check params passed from BL2 are not NULL. */
+ assert(from_bl2 != NULL);
+ assert(from_bl2->h.type == PARAM_BL31);
+ assert(from_bl2->h.version >= VERSION_1);
+
+ /*
+ * Copy BL32 and BL33 entry point information. It is stored in Secure
+ * RAM, in BL2's address space.
+ */
+ bl32_image_ep_info = *from_bl2->bl32_ep_info;
+ bl33_image_ep_info = *from_bl2->bl33_ep_info;
+
+ if (bl33_image_ep_info.pc == 0U) {
+ ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
+ panic();
+ }
+
+ bl30_image_info = *from_bl2->scp_image_info[0];
+ bl301_image_info = *from_bl2->scp_image_info[1];
+}
+
+void bl31_plat_arch_setup(void)
+{
+ aml_setup_page_tables();
+
+ enable_mmu_el3(0);
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t g12a_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+};
+
+static const gicv2_driver_data_t g12a_gic_data = {
+ .gicd_base = AML_GICD_BASE,
+ .gicc_base = AML_GICC_BASE,
+ .interrupt_props = g12a_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g12a_interrupt_props)
+};
+
+void bl31_platform_setup(void)
+{
+ aml_mhu_secure_init();
+
+ gicv2_driver_init(&g12a_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
diff --git a/plat/amlogic/g12a/g12a_common.c b/plat/amlogic/g12a/g12a_common.c
new file mode 100644
index 0000000..e74ed04
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_common.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/ep_info.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
+ AML_NSDRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NS_SHARE_MEM MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE, \
+ AML_NS_SHARE_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_SHARE_MEM MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE, \
+ AML_SEC_SHARE_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
+ AML_SEC_DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW)
+
+#define MAP_HDCP_RX MAP_REGION_FLAT(AML_HDCP_RX_BASE, \
+ AML_HDCP_RX_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_HDCP_TX MAP_REGION_FLAT(AML_HDCP_TX_BASE, \
+ AML_HDCP_TX_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_GIC_DEVICE MAP_REGION_FLAT(AML_GIC_DEVICE_BASE, \
+ AML_GIC_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
+ AML_SEC_DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
+ AML_SEC_DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
+ AML_TZRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t g12a_mmap[] = {
+ MAP_NSDRAM0,
+ MAP_NS_SHARE_MEM,
+ MAP_SEC_SHARE_MEM,
+ MAP_SEC_DEVICE0,
+ MAP_HDCP_RX,
+ MAP_HDCP_TX,
+ MAP_GIC_DEVICE,
+ MAP_SEC_DEVICE1,
+ MAP_SEC_DEVICE2,
+ MAP_TZRAM,
+ {0}
+};
+
+/*******************************************************************************
+ * Per-image regions
+ ******************************************************************************/
+#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
+ BL31_END - BL31_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
+ BL_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+
+#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
+ BL_RO_DATA_END - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+
+#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void aml_setup_page_tables(void)
+{
+#if IMAGE_BL31
+ const mmap_region_t g12a_bl_mmap[] = {
+ MAP_BL31,
+ MAP_BL_CODE,
+ MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+ MAP_BL_COHERENT,
+#endif
+ {0}
+ };
+#endif
+
+ mmap_add(g12a_bl_mmap);
+
+ mmap_add(g12a_mmap);
+
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ mmio_clrbits_32(AML_SYS_CPU_CFG7, ~0xFDFFFFFF);
+ mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, ~0xFFFFFE00);
+
+ return AML_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/amlogic/g12a/g12a_def.h b/plat/amlogic/g12a/g12a_def.h
new file mode 100644
index 0000000..d032815
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_def.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef G12A_DEF_H
+#define G12A_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define AML_HDCP_RX_BASE UL(0xFFE0D000)
+#define AML_HDCP_RX_SIZE UL(0x00002000)
+
+#define AML_HDCP_TX_BASE UL(0xFFE01000)
+#define AML_HDCP_TX_SIZE UL(0x00001000)
+
+#define AML_NS_SHARE_MEM_BASE UL(0x05000000)
+#define AML_NS_SHARE_MEM_SIZE UL(0x00100000)
+
+#define AML_SEC_SHARE_MEM_BASE UL(0x05200000)
+#define AML_SEC_SHARE_MEM_SIZE UL(0x00100000)
+
+#define AML_GIC_DEVICE_BASE UL(0xFFC00000)
+#define AML_GIC_DEVICE_SIZE UL(0x00008000)
+
+#define AML_NSDRAM0_BASE UL(0x01000000)
+#define AML_NSDRAM0_SIZE UL(0x0F000000)
+
+#define BL31_BASE UL(0x05100000)
+#define BL31_SIZE UL(0x00100000)
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000)
+#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
+
+#define AML_SEC_DEVICE0_BASE UL(0xFFD00000)
+#define AML_SEC_DEVICE0_SIZE UL(0x00026000)
+
+#define AML_SEC_DEVICE1_BASE UL(0xFF800000)
+#define AML_SEC_DEVICE1_SIZE UL(0x0000A000)
+
+#define AML_TZRAM_BASE UL(0xFFFA0000)
+#define AML_TZRAM_SIZE UL(0x00048000)
+
+/* Mailboxes */
+#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xFFFE7800)
+#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xFFFE7A00)
+#define AML_PSCI_MAILBOX_BASE UL(0xFFFE7F00)
+
+#define AML_SEC_DEVICE2_BASE UL(0xFF620000)
+#define AML_SEC_DEVICE2_SIZE UL(0x00028000)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define AML_GICD_BASE UL(0xFFC01000)
+#define AML_GICC_BASE UL(0xFFC02000)
+
+#define IRQ_SEC_PHY_TIMER 29
+
+#define IRQ_SEC_SGI_0 8
+#define IRQ_SEC_SGI_1 9
+#define IRQ_SEC_SGI_2 10
+#define IRQ_SEC_SGI_3 11
+#define IRQ_SEC_SGI_4 12
+#define IRQ_SEC_SGI_5 13
+#define IRQ_SEC_SGI_6 14
+#define IRQ_SEC_SGI_7 15
+#define IRQ_SEC_SGI_8 16
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define AML_UART0_AO_BASE UL(0xFF803000)
+#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
+#define AML_UART_BAUDRATE U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define AML_AO_TIMESTAMP_CNTL UL(0xFF8000B4)
+
+#define AML_SYS_CPU_CFG7 UL(0xFF634664)
+
+#define AML_AO_RTI_STATUS_REG3 UL(0xFF80001C)
+#define AML_AO_RTI_SCP_STAT UL(0xFF80023C)
+#define AML_AO_RTI_SCP_READY_OFF U(0x14)
+#define AML_A0_RTI_SCP_READY_MASK U(3)
+#define AML_AO_RTI_SCP_IS_READY(v) \
+ ((((v) >> AML_AO_RTI_SCP_READY_OFF) & \
+ AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
+
+#define AML_HIU_MAILBOX_SET_0 UL(0xFF63C404)
+#define AML_HIU_MAILBOX_STAT_0 UL(0xFF63C408)
+#define AML_HIU_MAILBOX_CLR_0 UL(0xFF63C40C)
+#define AML_HIU_MAILBOX_SET_3 UL(0xFF63C428)
+#define AML_HIU_MAILBOX_STAT_3 UL(0xFF63C42C)
+#define AML_HIU_MAILBOX_CLR_3 UL(0xFF63C430)
+
+#define AML_SHA_DMA_BASE UL(0xFF63E000)
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x28)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
+#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
+
+#define AML_SM_EFUSE_READ U(0x82000030)
+#define AML_SM_EFUSE_USER_MAX U(0x82000033)
+
+#define AML_SM_JTAG_ON U(0x82000040)
+#define AML_SM_JTAG_OFF U(0x82000041)
+#define AML_SM_GET_CHIP_ID U(0x82000044)
+
+#define AML_JTAG_STATE_ON U(0)
+#define AML_JTAG_STATE_OFF U(1)
+
+#define AML_JTAG_M3_AO U(0)
+#define AML_JTAG_M3_EE U(1)
+#define AML_JTAG_A53_AO U(2)
+#define AML_JTAG_A53_EE U(3)
+
+#endif /* G12A_DEF_H */
diff --git a/plat/amlogic/g12a/g12a_pm.c b/plat/amlogic/g12a/g12a_pm.c
new file mode 100644
index 0000000..c9fe3e9
--- /dev/null
+++ b/plat/amlogic/g12a/g12a_pm.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+#define SCPI_POWER_ON 0
+#define SCPI_POWER_RETENTION 1
+#define SCPI_POWER_OFF 3
+
+#define SCPI_SYSTEM_SHUTDOWN 0
+#define SCPI_SYSTEM_REBOOT 1
+
+static uintptr_t g12a_sec_entrypoint;
+static volatile uint32_t g12a_cpu0_go;
+
+static void g12a_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
+
+ mmio_write_64(cpu_mailbox_addr, value);
+}
+
+static void g12a_pm_reset(u_register_t mpidr)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
+
+ mmio_write_32(cpu_mailbox_addr, 0);
+}
+
+static void __dead2 g12a_system_reset(void)
+{
+ INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3);
+ int ret;
+
+ NOTICE("BL31: Reboot reason: 0x%x\n", status);
+
+ status &= 0xFFFF0FF0;
+
+ console_flush();
+
+ mmio_write_32(AML_AO_RTI_STATUS_REG3, status);
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
+ panic();
+ }
+
+ g12a_pm_reset(mpidr);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+ panic();
+}
+
+static void __dead2 g12a_system_off(void)
+{
+ INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ int ret;
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
+ panic();
+ }
+
+ g12a_pm_set_reset_addr(mpidr, 0);
+ g12a_pm_reset(mpidr);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+ panic();
+}
+
+static int32_t g12a_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ /* CPU0 can't be turned OFF */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
+
+ g12a_cpu0_go = 1;
+ flush_dcache_range((uintptr_t)&g12a_cpu0_go,
+ sizeof(g12a_cpu0_go));
+ dsb();
+ isb();
+
+ sev();
+
+ return PSCI_E_SUCCESS;
+ }
+
+ g12a_pm_set_reset_addr(mpidr, g12a_sec_entrypoint);
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+ dmbsy();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void g12a_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ unsigned int core = plat_calc_core_pos(read_mpidr_el1());
+
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ if (core == AML_PRIMARY_CPU) {
+ g12a_cpu0_go = 0;
+ flush_dcache_range((uintptr_t)&g12a_cpu0_go,
+ sizeof(g12a_cpu0_go));
+ dsb();
+ isb();
+ }
+
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static void g12a_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ gicv2_cpuif_disable();
+
+ /* CPU0 can't be turned OFF */
+ if (core == AML_PRIMARY_CPU)
+ return;
+
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_OFF, SCPI_POWER_ON,
+ SCPI_POWER_ON);
+}
+
+static void __dead2 g12a_pwr_domain_pwr_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: CPU0 entering wait loop...\n");
+
+ while (g12a_cpu0_go == 0)
+ wfe();
+
+ VERBOSE("BL31: CPU0 resumed.\n");
+
+ /*
+ * Because setting CPU0's warm reset entrypoint through PSCI
+ * mailbox and/or mmio mapped RVBAR (0xda834650) does not seem
+ * to work, jump to it manually.
+ * In order to avoid an assert, MMU has to be disabled.
+ */
+ disable_mmu_el3();
+ ((void(*)(void))g12a_sec_entrypoint)();
+ }
+
+ dsbsy();
+ g12a_pm_set_reset_addr(mpidr, 0);
+ g12a_pm_reset(mpidr);
+
+ for (;;)
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t g12a_ops = {
+ .pwr_domain_on = g12a_pwr_domain_on,
+ .pwr_domain_on_finish = g12a_pwr_domain_on_finish,
+ .pwr_domain_off = g12a_pwr_domain_off,
+ .pwr_domain_pwr_down_wfi = g12a_pwr_domain_pwr_down_wfi,
+ .system_off = g12a_system_off,
+ .system_reset = g12a_system_reset
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ g12a_sec_entrypoint = sec_entrypoint;
+ *psci_ops = &g12a_ops;
+ g12a_cpu0_go = 0;
+ return 0;
+}
diff --git a/plat/amlogic/g12a/include/platform_def.h b/plat/amlogic/g12a/include/platform_def.h
new file mode 100644
index 0000000..23d816d
--- /dev/null
+++ b/plat/amlogic/g12a/include/platform_def.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "../g12a_def.h"
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE UL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define AML_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains. */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* Memory-related defines */
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS 16
+#define MAX_XLAT_TABLES 8
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amlogic/g12a/platform.mk b/plat/amlogic/g12a/platform.mk
new file mode 100644
index 0000000..b0c91b0
--- /dev/null
+++ b/plat/amlogic/g12a/platform.mk
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AML_PLAT := plat/amlogic
+AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
+AML_PLAT_COMMON := ${AML_PLAT}/common
+
+DOIMAGEPATH ?= tools/amlogic
+DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
+
+PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
+ -I${AML_PLAT_SOC}/include \
+ -I${AML_PLAT_COMMON}/include
+
+GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ drivers/amlogic/console/aarch64/meson_console.S \
+ ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
+ ${AML_PLAT_SOC}/${PLAT}_pm.c \
+ ${AML_PLAT_SOC}/${PLAT}_common.c \
+ ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
+ ${AML_PLAT_COMMON}/aml_efuse.c \
+ ${AML_PLAT_COMMON}/aml_mhu.c \
+ ${AML_PLAT_COMMON}/aml_scpi.c \
+ ${AML_PLAT_COMMON}/aml_sip_svc.c \
+ ${AML_PLAT_COMMON}/aml_thermal.c \
+ ${AML_PLAT_COMMON}/aml_topology.c \
+ ${AML_PLAT_COMMON}/aml_console.c \
+ drivers/amlogic/crypto/sha_dma.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${GIC_SOURCES}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_855873 := 1
+ERRATA_A53_819472 := 1
+ERRATA_A53_824069 := 1
+ERRATA_A53_827319 := 1
+
+WORKAROUND_CVE_2017_5715 := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Verify build config
+# -------------------
+
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: ${PLAT} needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on ${PLAT})
+endif
+
+all: ${BUILD_PLAT}/bl31.img
+distclean realclean clean: cleanimage
+
+cleanimage:
+ ${Q}${MAKE} -C ${DOIMAGEPATH} clean
+
+${DOIMAGETOOL}:
+ ${Q}${MAKE} -C ${DOIMAGEPATH}
+
+${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
+ ${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
+
diff --git a/plat/amlogic/gxbb/gxbb_bl31_setup.c b/plat/amlogic/gxbb/gxbb_bl31_setup.c
new file mode 100644
index 0000000..cc7a1c4
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_bl31_setup.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(type == NON_SECURE);
+
+ next_image_info = &bl33_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc != 0U) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+struct gxbb_bl31_param {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct gxbb_bl31_param *from_bl2;
+
+ /* Initialize the console to provide early debug support */
+ aml_console_init();
+
+ /*
+ * In debug builds, we pass a special value in 'arg1' to verify platform
+ * parameters from BL2 to BL31. In release builds it's not used.
+ */
+ assert(arg1 == AML_BL31_PLAT_PARAM_VAL);
+
+ /* Check that params passed from BL2 are not NULL. */
+ from_bl2 = (struct gxbb_bl31_param *) arg0;
+
+ /* Check params passed from BL2 are not NULL. */
+ assert(from_bl2 != NULL);
+ assert(from_bl2->h.type == PARAM_BL31);
+ assert(from_bl2->h.version >= VERSION_1);
+
+ /*
+ * Copy BL33 entry point information. It is stored in Secure RAM, in
+ * BL2's address space.
+ */
+ bl33_image_ep_info = *from_bl2->bl33_ep_info;
+
+ if (bl33_image_ep_info.pc == 0U) {
+ ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
+ panic();
+ }
+}
+
+void bl31_plat_arch_setup(void)
+{
+ aml_setup_page_tables();
+
+ enable_mmu_el3(0);
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t gxbb_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+static const gicv2_driver_data_t gxbb_gic_data = {
+ .gicd_base = AML_GICD_BASE,
+ .gicc_base = AML_GICC_BASE,
+ .interrupt_props = gxbb_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(gxbb_interrupt_props),
+};
+
+void bl31_platform_setup(void)
+{
+ aml_mhu_secure_init();
+
+ gicv2_driver_init(&gxbb_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ aml_thermal_unknown();
+}
diff --git a/plat/amlogic/gxbb/gxbb_common.c b/plat/amlogic/gxbb/gxbb_common.c
new file mode 100644
index 0000000..260a347
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_common.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/ep_info.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
+ AML_NSDRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NSDRAM1 MAP_REGION_FLAT(AML_NSDRAM1_BASE, \
+ AML_NSDRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
+ AML_SEC_DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
+ AML_SEC_DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
+ AML_TZRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
+ AML_SEC_DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE3 MAP_REGION_FLAT(AML_SEC_DEVICE3_BASE, \
+ AML_SEC_DEVICE3_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t gxbb_mmap[] = {
+ MAP_NSDRAM0,
+ MAP_NSDRAM1,
+ MAP_SEC_DEVICE0,
+ MAP_SEC_DEVICE1,
+ MAP_TZRAM,
+ MAP_SEC_DEVICE2,
+ MAP_SEC_DEVICE3,
+ {0}
+};
+
+/*******************************************************************************
+ * Per-image regions
+ ******************************************************************************/
+#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
+ BL31_END - BL31_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
+ BL_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+
+#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
+ BL_RO_DATA_END - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+
+#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void aml_setup_page_tables(void)
+{
+#if IMAGE_BL31
+ const mmap_region_t gxbb_bl_mmap[] = {
+ MAP_BL31,
+ MAP_BL_CODE,
+ MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+ MAP_BL_COHERENT,
+#endif
+ {0}
+ };
+#endif
+
+ mmap_add(gxbb_bl_mmap);
+
+ mmap_add(gxbb_mmap);
+
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ uint32_t val;
+
+ val = mmio_read_32(AML_SYS_CPU_CFG7);
+ val &= 0xFDFFFFFF;
+ mmio_write_32(AML_SYS_CPU_CFG7, val);
+
+ val = mmio_read_32(AML_AO_TIMESTAMP_CNTL);
+ val &= 0xFFFFFE00;
+ mmio_write_32(AML_AO_TIMESTAMP_CNTL, val);
+
+ return AML_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/amlogic/gxbb/gxbb_def.h b/plat/amlogic/gxbb/gxbb_def.h
new file mode 100644
index 0000000..fa5e4fa
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_def.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GXBB_DEF_H
+#define GXBB_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define AML_NSDRAM0_BASE UL(0x01000000)
+#define AML_NSDRAM0_SIZE UL(0x0F000000)
+
+#define AML_NSDRAM1_BASE UL(0x10000000)
+#define AML_NSDRAM1_SIZE UL(0x00100000)
+
+#define BL31_BASE UL(0x10100000)
+#define BL31_SIZE UL(0x000C0000)
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define AML_SHARE_MEM_INPUT_BASE UL(0x100FE000)
+#define AML_SHARE_MEM_OUTPUT_BASE UL(0x100FF000)
+
+#define AML_SEC_DEVICE0_BASE UL(0xC0000000)
+#define AML_SEC_DEVICE0_SIZE UL(0x09000000)
+
+#define AML_SEC_DEVICE1_BASE UL(0xD0040000)
+#define AML_SEC_DEVICE1_SIZE UL(0x00008000)
+
+#define AML_TZRAM_BASE UL(0xD9000000)
+#define AML_TZRAM_SIZE UL(0x00014000)
+/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */
+
+/* Mailboxes */
+#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xD9013800)
+#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xD9013A00)
+#define AML_PSCI_MAILBOX_BASE UL(0xD9013F00)
+
+#define AML_TZROM_BASE UL(0xD9040000)
+#define AML_TZROM_SIZE UL(0x00010000)
+
+#define AML_SEC_DEVICE2_BASE UL(0xDA000000)
+#define AML_SEC_DEVICE2_SIZE UL(0x00200000)
+
+#define AML_SEC_DEVICE3_BASE UL(0xDA800000)
+#define AML_SEC_DEVICE3_SIZE UL(0x00200000)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define AML_GICD_BASE UL(0xC4301000)
+#define AML_GICC_BASE UL(0xC4302000)
+
+#define IRQ_SEC_PHY_TIMER 29
+
+#define IRQ_SEC_SGI_0 8
+#define IRQ_SEC_SGI_1 9
+#define IRQ_SEC_SGI_2 10
+#define IRQ_SEC_SGI_3 11
+#define IRQ_SEC_SGI_4 12
+#define IRQ_SEC_SGI_5 13
+#define IRQ_SEC_SGI_6 14
+#define IRQ_SEC_SGI_7 15
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define AML_UART0_AO_BASE UL(0xC81004C0)
+#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
+#define AML_UART_BAUDRATE U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define AML_AO_TIMESTAMP_CNTL UL(0xC81000B4)
+
+#define AML_SYS_CPU_CFG7 UL(0xC8834664)
+
+#define AML_AO_RTI_STATUS_REG3 UL(0xDA10001C)
+
+#define AML_HIU_MAILBOX_SET_0 UL(0xDA83C404)
+#define AML_HIU_MAILBOX_STAT_0 UL(0xDA83C408)
+#define AML_HIU_MAILBOX_CLR_0 UL(0xDA83C40C)
+#define AML_HIU_MAILBOX_SET_3 UL(0xDA83C428)
+#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C)
+#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430)
+
+#define AML_SHA_DMA_BASE UL(0xC883E000)
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
+#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
+
+#define AML_SM_EFUSE_READ U(0x82000030)
+#define AML_SM_EFUSE_USER_MAX U(0x82000033)
+
+#define AML_SM_JTAG_ON U(0x82000040)
+#define AML_SM_JTAG_OFF U(0x82000041)
+#define AML_SM_GET_CHIP_ID U(0x82000044)
+
+#define AML_JTAG_STATE_ON U(0)
+#define AML_JTAG_STATE_OFF U(1)
+
+#define AML_JTAG_M3_AO U(0)
+#define AML_JTAG_M3_EE U(1)
+#define AML_JTAG_A53_AO U(2)
+#define AML_JTAG_A53_EE U(3)
+
+#endif /* GXBB_DEF_H */
diff --git a/plat/amlogic/gxbb/gxbb_pm.c b/plat/amlogic/gxbb/gxbb_pm.c
new file mode 100644
index 0000000..48bff7b
--- /dev/null
+++ b/plat/amlogic/gxbb/gxbb_pm.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+#define SCPI_POWER_ON 0
+#define SCPI_POWER_RETENTION 1
+#define SCPI_POWER_OFF 3
+
+#define SCPI_SYSTEM_SHUTDOWN 0
+#define SCPI_SYSTEM_REBOOT 1
+
+static uintptr_t gxbb_sec_entrypoint;
+static volatile uint32_t gxbb_cpu0_go;
+
+static void gxbb_program_mailbox(u_register_t mpidr, uint64_t value)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
+
+ mmio_write_64(cpu_mailbox_addr, value);
+ flush_dcache_range(cpu_mailbox_addr, sizeof(uint64_t));
+}
+
+static void __dead2 gxbb_system_reset(void)
+{
+ INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+ uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3);
+
+ NOTICE("BL31: Reboot reason: 0x%x\n", status);
+
+ status &= 0xFFFF0FF0;
+
+ console_flush();
+
+ mmio_write_32(AML_AO_RTI_STATUS_REG3, status);
+
+ int ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %u\n", ret);
+ panic();
+ }
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+ panic();
+}
+
+static void __dead2 gxbb_system_off(void)
+{
+ INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+ unsigned int ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %u\n", ret);
+ panic();
+ }
+
+ gxbb_program_mailbox(read_mpidr_el1(), 0);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+ panic();
+}
+
+static int32_t gxbb_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
+
+ gxbb_cpu0_go = 1;
+ flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go));
+ dsb();
+ isb();
+
+ sev();
+
+ return PSCI_E_SUCCESS;
+ }
+
+ gxbb_program_mailbox(mpidr, gxbb_sec_entrypoint);
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+ dmbsy();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void gxbb_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ unsigned int core = plat_calc_core_pos(read_mpidr_el1());
+
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ if (core == AML_PRIMARY_CPU) {
+ gxbb_cpu0_go = 0;
+ flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go));
+ dsb();
+ isb();
+ }
+
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static void gxbb_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t addr = AML_PSCI_MAILBOX_BASE + 8 + (core << 4);
+
+ mmio_write_32(addr, 0xFFFFFFFF);
+ flush_dcache_range(addr, sizeof(uint32_t));
+
+ gicv2_cpuif_disable();
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU)
+ return;
+
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON);
+}
+
+static void __dead2 gxbb_pwr_domain_pwr_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ unsigned int core = plat_calc_core_pos(read_mpidr_el1());
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: CPU0 entering wait loop...\n");
+
+ while (gxbb_cpu0_go == 0)
+ wfe();
+
+ VERBOSE("BL31: CPU0 resumed.\n");
+
+ write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT);
+ }
+
+ dsbsy();
+
+ for (;;)
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t gxbb_ops = {
+ .pwr_domain_on = gxbb_pwr_domain_on,
+ .pwr_domain_on_finish = gxbb_pwr_domain_on_finish,
+ .pwr_domain_off = gxbb_pwr_domain_off,
+ .pwr_domain_pwr_down_wfi = gxbb_pwr_domain_pwr_down_wfi,
+ .system_off = gxbb_system_off,
+ .system_reset = gxbb_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ gxbb_sec_entrypoint = sec_entrypoint;
+ *psci_ops = &gxbb_ops;
+ gxbb_cpu0_go = 0;
+ return 0;
+}
diff --git a/plat/amlogic/gxbb/include/platform_def.h b/plat/amlogic/gxbb/include/platform_def.h
new file mode 100644
index 0000000..a5cbe78
--- /dev/null
+++ b/plat/amlogic/gxbb/include/platform_def.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "../gxbb_def.h"
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define AML_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE UL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define AML_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains. */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* Memory-related defines */
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS 12
+#define MAX_XLAT_TABLES 5
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amlogic/gxbb/platform.mk b/plat/amlogic/gxbb/platform.mk
new file mode 100644
index 0000000..62384d2
--- /dev/null
+++ b/plat/amlogic/gxbb/platform.mk
@@ -0,0 +1,75 @@
+#
+# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AML_PLAT := plat/amlogic
+AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
+AML_PLAT_COMMON := ${AML_PLAT}/common
+
+PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
+ -I${AML_PLAT_SOC}/include \
+ -I${AML_PLAT_COMMON}/include
+
+GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ drivers/amlogic/console/aarch64/meson_console.S \
+ ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
+ ${AML_PLAT_SOC}/${PLAT}_pm.c \
+ ${AML_PLAT_SOC}/${PLAT}_common.c \
+ ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
+ ${AML_PLAT_COMMON}/aml_efuse.c \
+ ${AML_PLAT_COMMON}/aml_mhu.c \
+ ${AML_PLAT_COMMON}/aml_scpi.c \
+ ${AML_PLAT_COMMON}/aml_sip_svc.c \
+ ${AML_PLAT_COMMON}/aml_thermal.c \
+ ${AML_PLAT_COMMON}/aml_topology.c \
+ ${AML_PLAT_COMMON}/aml_console.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${GIC_SOURCES}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_826319 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+WORKAROUND_CVE_2017_5715 := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Verify build config
+# -------------------
+
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: ${PLAT} needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on ${PLAT})
+endif
diff --git a/plat/amlogic/gxl/gxl_bl31_setup.c b/plat/amlogic/gxl/gxl_bl31_setup.c
new file mode 100644
index 0000000..f581dd1
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_bl31_setup.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl33_image_ep_info;
+static image_info_t bl30_image_info;
+static image_info_t bl301_image_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(type == NON_SECURE);
+
+ next_image_info = &bl33_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc != 0U) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+struct gxl_bl31_param {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+ image_info_t *scp_image_info[];
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct gxl_bl31_param *from_bl2;
+
+ /* Initialize the console to provide early debug support */
+ aml_console_init();
+
+ /* Check that params passed from BL2 are not NULL. */
+ from_bl2 = (struct gxl_bl31_param *) arg0;
+
+ /* Check params passed from BL2 are not NULL. */
+ assert(from_bl2 != NULL);
+ assert(from_bl2->h.type == PARAM_BL31);
+ assert(from_bl2->h.version >= VERSION_1);
+
+ /*
+ * Copy BL33 entry point information. It is stored in Secure RAM, in
+ * BL2's address space.
+ */
+ bl33_image_ep_info = *from_bl2->bl33_ep_info;
+
+ if (bl33_image_ep_info.pc == 0U) {
+ ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
+ panic();
+ }
+
+ bl30_image_info = *from_bl2->scp_image_info[0];
+ bl301_image_info = *from_bl2->scp_image_info[1];
+}
+
+void bl31_plat_arch_setup(void)
+{
+ aml_setup_page_tables();
+
+ enable_mmu_el3(0);
+}
+
+static inline bool gxl_scp_ready(void)
+{
+ return AML_AO_RTI_SCP_IS_READY(mmio_read_32(AML_AO_RTI_SCP_STAT));
+}
+
+static inline void gxl_scp_boot(void)
+{
+ aml_scpi_upload_scp_fw(bl30_image_info.image_base,
+ bl30_image_info.image_size, 0);
+ aml_scpi_upload_scp_fw(bl301_image_info.image_base,
+ bl301_image_info.image_size, 1);
+ while (!gxl_scp_ready())
+ ;
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t gxl_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+static const gicv2_driver_data_t gxl_gic_data = {
+ .gicd_base = AML_GICD_BASE,
+ .gicc_base = AML_GICC_BASE,
+ .interrupt_props = gxl_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(gxl_interrupt_props),
+};
+
+void bl31_platform_setup(void)
+{
+ aml_mhu_secure_init();
+
+ gicv2_driver_init(&gxl_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ gxl_scp_boot();
+
+ aml_thermal_unknown();
+}
diff --git a/plat/amlogic/gxl/gxl_common.c b/plat/amlogic/gxl/gxl_common.c
new file mode 100644
index 0000000..e1d7bfb
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_common.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/ep_info.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
+ AML_NSDRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NSDRAM1 MAP_REGION_FLAT(AML_NSDRAM1_BASE, \
+ AML_NSDRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
+ AML_SEC_DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
+ AML_SEC_DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
+ AML_TZRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
+ AML_SEC_DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE3 MAP_REGION_FLAT(AML_SEC_DEVICE3_BASE, \
+ AML_SEC_DEVICE3_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t gxl_mmap[] = {
+ MAP_NSDRAM0,
+ MAP_NSDRAM1,
+ MAP_SEC_DEVICE0,
+ MAP_SEC_DEVICE1,
+ MAP_TZRAM,
+ MAP_SEC_DEVICE2,
+ MAP_SEC_DEVICE3,
+ {0}
+};
+
+/*******************************************************************************
+ * Per-image regions
+ ******************************************************************************/
+#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
+ BL31_END - BL31_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
+ BL_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+
+#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
+ BL_RO_DATA_END - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+
+#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void aml_setup_page_tables(void)
+{
+#if IMAGE_BL31
+ const mmap_region_t gxl_bl_mmap[] = {
+ MAP_BL31,
+ MAP_BL_CODE,
+ MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+ MAP_BL_COHERENT,
+#endif
+ {0}
+ };
+#endif
+
+ mmap_add(gxl_bl_mmap);
+
+ mmap_add(gxl_mmap);
+
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ uint32_t val;
+
+ val = mmio_read_32(AML_SYS_CPU_CFG7);
+ val &= 0xFDFFFFFF;
+ mmio_write_32(AML_SYS_CPU_CFG7, val);
+
+ val = mmio_read_32(AML_AO_TIMESTAMP_CNTL);
+ val &= 0xFFFFFE00;
+ mmio_write_32(AML_AO_TIMESTAMP_CNTL, val);
+
+ return AML_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/amlogic/gxl/gxl_def.h b/plat/amlogic/gxl/gxl_def.h
new file mode 100644
index 0000000..f30eb28
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_def.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GXL_DEF_H
+#define GXL_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define AML_NSDRAM0_BASE UL(0x01000000)
+#define AML_NSDRAM0_SIZE UL(0x0F000000)
+
+#define AML_NSDRAM1_BASE UL(0x10000000)
+#define AML_NSDRAM1_SIZE UL(0x00100000)
+
+#define BL31_BASE UL(0x05100000)
+#define BL31_SIZE UL(0x000C0000)
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000)
+#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
+
+#define AML_SEC_DEVICE0_BASE UL(0xC0000000)
+#define AML_SEC_DEVICE0_SIZE UL(0x09000000)
+
+#define AML_SEC_DEVICE1_BASE UL(0xD0040000)
+#define AML_SEC_DEVICE1_SIZE UL(0x00008000)
+
+#define AML_TZRAM_BASE UL(0xD9000000)
+#define AML_TZRAM_SIZE UL(0x00014000)
+/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */
+
+/* Mailboxes */
+#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xD9013800)
+#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xD9013A00)
+#define AML_PSCI_MAILBOX_BASE UL(0xD9013F00)
+
+// * [ 1K] 0xD901_3800 - 0xD901_3BFF Secure Mailbox (3)
+// * [ 1K] 0xD901_3400 - 0xD901_37FF High Mailbox (2) *
+// * [ 1K] 0xD901_3000 - 0xD901_33FF High Mailbox (1) *
+
+#define AML_TZROM_BASE UL(0xD9040000)
+#define AML_TZROM_SIZE UL(0x00010000)
+
+#define AML_SEC_DEVICE2_BASE UL(0xDA000000)
+#define AML_SEC_DEVICE2_SIZE UL(0x00200000)
+
+#define AML_SEC_DEVICE3_BASE UL(0xDA800000)
+#define AML_SEC_DEVICE3_SIZE UL(0x00200000)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define AML_GICD_BASE UL(0xC4301000)
+#define AML_GICC_BASE UL(0xC4302000)
+
+#define IRQ_SEC_PHY_TIMER 29
+
+#define IRQ_SEC_SGI_0 8
+#define IRQ_SEC_SGI_1 9
+#define IRQ_SEC_SGI_2 10
+#define IRQ_SEC_SGI_3 11
+#define IRQ_SEC_SGI_4 12
+#define IRQ_SEC_SGI_5 13
+#define IRQ_SEC_SGI_6 14
+#define IRQ_SEC_SGI_7 15
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define AML_UART0_AO_BASE UL(0xC81004C0)
+#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
+#define AML_UART_BAUDRATE U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define AML_AO_TIMESTAMP_CNTL UL(0xC81000B4)
+
+#define AML_SYS_CPU_CFG7 UL(0xC8834664)
+
+#define AML_AO_RTI_STATUS_REG3 UL(0xDA10001C)
+#define AML_AO_RTI_SCP_STAT UL(0xDA10023C)
+#define AML_AO_RTI_SCP_READY_OFF U(0x14)
+#define AML_A0_RTI_SCP_READY_MASK U(3)
+#define AML_AO_RTI_SCP_IS_READY(v) \
+ ((((v) >> AML_AO_RTI_SCP_READY_OFF) & \
+ AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
+
+#define AML_HIU_MAILBOX_SET_0 UL(0xDA83C404)
+#define AML_HIU_MAILBOX_STAT_0 UL(0xDA83C408)
+#define AML_HIU_MAILBOX_CLR_0 UL(0xDA83C40C)
+#define AML_HIU_MAILBOX_SET_3 UL(0xDA83C428)
+#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C)
+#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430)
+
+#define AML_SHA_DMA_BASE UL(0xC883E000)
+#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
+#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
+
+#define AML_SM_EFUSE_READ U(0x82000030)
+#define AML_SM_EFUSE_USER_MAX U(0x82000033)
+
+#define AML_SM_JTAG_ON U(0x82000040)
+#define AML_SM_JTAG_OFF U(0x82000041)
+#define AML_SM_GET_CHIP_ID U(0x82000044)
+
+#define AML_JTAG_STATE_ON U(0)
+#define AML_JTAG_STATE_OFF U(1)
+
+#define AML_JTAG_M3_AO U(0)
+#define AML_JTAG_M3_EE U(1)
+#define AML_JTAG_A53_AO U(2)
+#define AML_JTAG_A53_EE U(3)
+
+#endif /* GXL_DEF_H */
diff --git a/plat/amlogic/gxl/gxl_pm.c b/plat/amlogic/gxl/gxl_pm.c
new file mode 100644
index 0000000..433140b
--- /dev/null
+++ b/plat/amlogic/gxl/gxl_pm.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+#define SCPI_POWER_ON 0
+#define SCPI_POWER_RETENTION 1
+#define SCPI_POWER_OFF 3
+
+#define SCPI_SYSTEM_SHUTDOWN 0
+#define SCPI_SYSTEM_REBOOT 1
+
+static uintptr_t gxl_sec_entrypoint;
+static volatile uint32_t gxl_cpu0_go;
+
+static void gxl_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
+
+ mmio_write_64(cpu_mailbox_addr, value);
+}
+
+static void gxl_pm_reset(u_register_t mpidr)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+ uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
+
+ mmio_write_32(cpu_mailbox_addr, 0);
+}
+
+static void __dead2 gxl_system_reset(void)
+{
+ INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3);
+ int ret;
+
+ NOTICE("BL31: Reboot reason: 0x%x\n", status);
+
+ status &= 0xFFFF0FF0;
+
+ console_flush();
+
+ mmio_write_32(AML_AO_RTI_STATUS_REG3, status);
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
+ panic();
+ }
+
+ gxl_pm_reset(mpidr);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+ panic();
+}
+
+static void __dead2 gxl_system_off(void)
+{
+ INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+ u_register_t mpidr = read_mpidr_el1();
+ int ret;
+
+ ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+ if (ret != 0) {
+ ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
+ panic();
+ }
+
+ gxl_pm_set_reset_addr(mpidr, 0);
+ gxl_pm_reset(mpidr);
+
+ wfi();
+
+ ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+ panic();
+}
+
+static int32_t gxl_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
+
+ gxl_cpu0_go = 1;
+ flush_dcache_range((uintptr_t)&gxl_cpu0_go,
+ sizeof(gxl_cpu0_go));
+ dsb();
+ isb();
+
+ sev();
+
+ return PSCI_E_SUCCESS;
+ }
+
+ gxl_pm_set_reset_addr(mpidr, gxl_sec_entrypoint);
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+ dmbsy();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void gxl_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ unsigned int core = plat_calc_core_pos(read_mpidr_el1());
+
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ if (core == AML_PRIMARY_CPU) {
+ gxl_cpu0_go = 0;
+ flush_dcache_range((uintptr_t)&gxl_cpu0_go,
+ sizeof(gxl_cpu0_go));
+ dsb();
+ isb();
+ }
+
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static void gxl_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ gicv2_cpuif_disable();
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU)
+ return;
+
+ aml_scpi_set_css_power_state(mpidr,
+ SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON);
+}
+
+static void __dead2 gxl_pwr_domain_pwr_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = plat_calc_core_pos(mpidr);
+
+ /* CPU0 can't be turned OFF, emulate it with a WFE loop */
+ if (core == AML_PRIMARY_CPU) {
+ VERBOSE("BL31: CPU0 entering wait loop...\n");
+
+ while (gxl_cpu0_go == 0)
+ wfe();
+
+ VERBOSE("BL31: CPU0 resumed.\n");
+
+ /*
+ * Because setting CPU0's warm reset entrypoint through PSCI
+ * mailbox and/or mmio mapped RVBAR (0xda834650) does not seem
+ * to work, jump to it manually.
+ * In order to avoid an assert, mmu has to be disabled.
+ */
+ disable_mmu_el3();
+ ((void(*)(void))gxl_sec_entrypoint)();
+ }
+
+ dsbsy();
+ gxl_pm_set_reset_addr(mpidr, 0);
+ gxl_pm_reset(mpidr);
+
+ for (;;)
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t gxl_ops = {
+ .pwr_domain_on = gxl_pwr_domain_on,
+ .pwr_domain_on_finish = gxl_pwr_domain_on_finish,
+ .pwr_domain_off = gxl_pwr_domain_off,
+ .pwr_domain_pwr_down_wfi = gxl_pwr_domain_pwr_down_wfi,
+ .system_off = gxl_system_off,
+ .system_reset = gxl_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ gxl_sec_entrypoint = sec_entrypoint;
+ *psci_ops = &gxl_ops;
+ gxl_cpu0_go = 0;
+ return 0;
+}
diff --git a/plat/amlogic/gxl/include/platform_def.h b/plat/amlogic/gxl/include/platform_def.h
new file mode 100644
index 0000000..ec64d68
--- /dev/null
+++ b/plat/amlogic/gxl/include/platform_def.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "../gxl_def.h"
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE UL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define AML_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains. */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* Memory-related defines */
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS 12
+#define MAX_XLAT_TABLES 6
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amlogic/gxl/platform.mk b/plat/amlogic/gxl/platform.mk
new file mode 100644
index 0000000..641d177
--- /dev/null
+++ b/plat/amlogic/gxl/platform.mk
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AML_PLAT := plat/amlogic
+AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
+AML_PLAT_COMMON := ${AML_PLAT}/common
+
+DOIMAGEPATH ?= tools/amlogic
+DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
+
+PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
+ -I${AML_PLAT_SOC}/include \
+ -I${AML_PLAT_COMMON}/include
+
+GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ drivers/amlogic/console/aarch64/meson_console.S \
+ ${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
+ ${AML_PLAT_SOC}/${PLAT}_pm.c \
+ ${AML_PLAT_SOC}/${PLAT}_common.c \
+ ${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
+ ${AML_PLAT_COMMON}/aml_efuse.c \
+ ${AML_PLAT_COMMON}/aml_mhu.c \
+ ${AML_PLAT_COMMON}/aml_scpi.c \
+ ${AML_PLAT_COMMON}/aml_sip_svc.c \
+ ${AML_PLAT_COMMON}/aml_thermal.c \
+ ${AML_PLAT_COMMON}/aml_topology.c \
+ ${AML_PLAT_COMMON}/aml_console.c \
+ drivers/amlogic/crypto/sha_dma.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${GIC_SOURCES}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_855873 := 1
+ERRATA_A53_819472 := 1
+ERRATA_A53_824069 := 1
+ERRATA_A53_827319 := 1
+
+WORKAROUND_CVE_2017_5715 := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Verify build config
+# -------------------
+
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: ${PLAT} needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on ${PLAT})
+endif
+
+all: ${BUILD_PLAT}/bl31.img
+distclean realclean clean: cleanimage
+
+cleanimage:
+ ${Q}${MAKE} -C ${DOIMAGEPATH} clean
+
+${DOIMAGETOOL}:
+ ${Q}${MAKE} -C ${DOIMAGEPATH}
+
+${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
+ ${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
+
diff --git a/plat/arm/board/a5ds/a5ds_bl1_setup.c b/plat/arm/board/a5ds/a5ds_bl1_setup.c
new file mode 100644
index 0000000..629c928
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_bl1_setup.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ arm_bl1_early_platform_setup();
+}
+
+void bl1_platform_setup(void)
+{
+ arm_bl1_platform_setup();
+}
diff --git a/plat/arm/board/a5ds/a5ds_bl2_setup.c b/plat/arm/board/a5ds/a5ds_bl2_setup.c
new file mode 100644
index 0000000..1979c50
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_bl2_setup.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
+}
+
+void bl2_platform_setup(void)
+{
+ arm_bl2_platform_setup();
+}
diff --git a/plat/arm/board/a5ds/a5ds_common.c b/plat/arm/board/a5ds/a5ds_common.c
new file mode 100644
index 0000000..a4a0cff
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_common.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+
+#define MAP_PERIPHBASE MAP_REGION_FLAT(PERIPHBASE,\
+ PERIPH_SIZE,\
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_A5_PERIPHERALS MAP_REGION_FLAT(A5_PERIPHERALS_BASE,\
+ A5_PERIPHERALS_SIZE,\
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#ifdef IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ MAP_PERIPHBASE,
+ MAP_A5_PERIPHERALS,
+ MAP_BOOT_RW,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ MAP_PERIPHBASE,
+ MAP_A5_PERIPHERALS,
+ MAP_BOOT_RW,
+ ARM_MAP_NS_DRAM1,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL32
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ MAP_PERIPHBASE,
+ MAP_A5_PERIPHERALS,
+ {0}
+};
+#endif
+
+ARM_CASSERT_MMAP
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return A5DS_TIMER_BASE_FREQUENCY;
+}
diff --git a/plat/arm/board/a5ds/a5ds_err.c b/plat/arm/board/a5ds/a5ds_err.c
new file mode 100644
index 0000000..feb9fdf
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * a5ds error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/a5ds/a5ds_pm.c b/plat/arm/board/a5ds/a5ds_pm.c
new file mode 100644
index 0000000..7774002
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_pm.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int a5ds_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int pos = plat_core_pos_by_mpidr(mpidr);
+ uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE;
+
+ hold_base[pos] = A5DS_HOLD_STATE_GO;
+ dsbish();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* TODO: This setup is needed only after a cold boot*/
+ gicv2_pcpu_distif_init();
+
+ /* Enable the gic cpu interface */
+ gicv2_cpuif_enable();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ * a5ds only has always-on power domain and there is no power control present.
+ ******************************************************************************/
+void a5ds_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ ERROR("CPU_OFF not supported on this platform\n");
+ assert(false);
+ panic();
+}
+
+/*******************************************************************************
+ * Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t a5ds_psci_pm_ops = {
+ /* dummy struct */
+ .validate_ns_entrypoint = NULL,
+ .pwr_domain_on = a5ds_pwr_domain_on,
+ .pwr_domain_on_finish = a5ds_pwr_domain_on_finish,
+ .pwr_domain_off = a5ds_pwr_domain_off
+};
+
+int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE;
+ *mailbox = sec_entrypoint;
+
+ *psci_ops = &a5ds_psci_pm_ops;
+
+ return 0;
+}
diff --git a/plat/arm/board/a5ds/a5ds_private.h b/plat/arm/board/a5ds/a5ds_private.h
new file mode 100644
index 0000000..f577249
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_private.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef A5DS_PRIVATE_H
+#define A5DS_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void a5ds_config_setup(void);
+
+#endif /* A5DS_PRIVATE_H */
diff --git a/plat/arm/board/a5ds/a5ds_security.c b/plat/arm/board/a5ds/a5ds_security.c
new file mode 100644
index 0000000..5593ae0
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_security.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * We assume that all security programming is done by the primary core.
+ */
+void plat_arm_security_setup(void)
+{
+ /*
+ * The platform currently does not have any security setup.
+ */
+}
diff --git a/plat/arm/board/a5ds/a5ds_topology.c b/plat/arm/board/a5ds/a5ds_topology.c
new file mode 100644
index 0000000..94fa71f
--- /dev/null
+++ b/plat/arm/board/a5ds/a5ds_topology.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+/* The A5DS power domain tree descriptor */
+static const unsigned char a5ds_power_domain_tree_desc[] = {
+ 1,
+ /* No of children for the root node */
+ A5DS_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ A5DS_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the topology according to A5DS_CLUSTER_COUNT.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return a5ds_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * Get core position using mpidr
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= A5DS_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= A5DS_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
+
+}
diff --git a/plat/arm/board/a5ds/aarch32/a5ds_helpers.S b/plat/arm/board/a5ds/aarch32/a5ds_helpers.S
new file mode 100644
index 0000000..ed7ad9c
--- /dev/null
+++ b/plat/arm/board/a5ds/aarch32/a5ds_helpers.S
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* Calculate address of our hold entry */
+ bl plat_my_core_pos
+ lsl r0, r0, #A5DS_HOLD_ENTRY_SHIFT
+ mov_imm r2, A5DS_HOLD_BASE
+ /* Clear the value stored in the hold address for the specific core */
+ mov_imm r3, A5DS_HOLD_STATE_WAIT
+ str r3, [r2, r0]
+ dmb ish
+
+ /* Wait until we have a go */
+poll_mailbox:
+ ldr r1, [r2, r0]
+ cmp r1, #A5DS_HOLD_STATE_WAIT
+ beq 1f
+ mov_imm r0, A5DS_TRUSTED_MAILBOX_BASE
+ ldr r1, [r0]
+ bx r1
+1:
+ wfe
+ b poll_mailbox
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot.
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* TODO support warm boot */
+ /* Cold reset */
+ mov r0, #0
+ bx lr
+
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ ldcopr r0, MPIDR
+ ldr r1, =MPIDR_AFFINITY_MASK
+ and r0, r1
+ cmp r0, #0
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+endfunc plat_is_my_cpu_primary
+
+ /* ---------------------------------------------------------------------
+ * Loads MPIDR in r0 and calls plat_arm_calc_core_pos
+ * ---------------------------------------------------------------------
+ */
+func plat_my_core_pos
+ ldcopr r0, MPIDR
+ b plat_arm_calc_core_pos
+
+endfunc plat_my_core_pos
+
+ /* ---------------------------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Function to calculate the core position on A5DS.
+ *
+ * (ClusterId * A5DS_MAX_CPUS_PER_CLUSTER * A5DS_MAX_PE_PER_CPU) +
+ * (CPUId * A5DS_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * A5DS_MAX_CPUS_PER_CLUSTER + CPUId) * A5DS_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ mov r3, r0
+
+ /*
+ * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+ * look as if in a multi-threaded implementation
+ */
+ tst r0, #MPIDR_MT_MASK
+ lsleq r3, r0, #MPIDR_AFFINITY_BITS
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov r3, #A5DS_MAX_CPUS_PER_CLUSTER
+ mla r1, r2, r3, r1
+ mov r3, #A5DS_MAX_PE_PER_CPU
+ mla r0, r1, r3, r0
+
+ bx lr
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
new file mode 100644
index 0000000..b9ff8bf
--- /dev/null
+++ b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x2001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ hw-config {
+ load-address = <0x0 0x83000000>;
+ max-size = <0x01000000>;
+ id = <HW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
new file mode 100644
index 0000000..c66186f
--- /dev/null
+++ b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ };
+};
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
new file mode 100644
index 0000000..9f3df1e
--- /dev/null
+++ b/plat/arm/board/a5ds/include/platform_def.h
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+
+/* Memory location options for TSP */
+#define ARM_DRAM_ID 2
+
+#define ARM_DRAM1_BASE UL(0x80000000)
+#define ARM_DRAM1_SIZE UL(0x80000000)
+#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
+ ARM_DRAM1_SIZE - 1)
+
+#define SRAM_BASE 0x2000000
+#define SRAM_SIZE 0x200000
+
+/* The first 4KB of NS DRAM1 are used as shared memory */
+#define A5DS_SHARED_RAM_BASE SRAM_BASE
+#define A5DS_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
+
+/* The next 252 kB of NS DRAM is used to load the BL images */
+#define ARM_BL_RAM_BASE (A5DS_SHARED_RAM_BASE + \
+ A5DS_SHARED_RAM_SIZE)
+#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \
+ A5DS_SHARED_RAM_SIZE)
+
+#define PERIPHBASE 0x1a000000
+#define PERIPH_SIZE 0x00240000
+#define A5_PERIPHERALS_BASE 0x1c000000
+#define A5_PERIPHERALS_SIZE 0x10000
+
+#define ARM_CACHE_WRITEBACK_SHIFT 5
+
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+#define ARM_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+#define A5DS_IRQ_TZ_WDOG 56
+#define A5DS_IRQ_SEC_SYS_TIMER 57
+
+/* Default cluster count for A5DS */
+#define A5DS_CLUSTER_COUNT U(1)
+
+/* Default number of CPUs per cluster on A5DS */
+#define A5DS_MAX_CPUS_PER_CLUSTER U(4)
+
+/* Default number of threads per CPU on A5DS */
+#define A5DS_MAX_PE_PER_CPU U(1)
+
+#define A5DS_CORE_COUNT U(4)
+
+#define A5DS_PRIMARY_CPU 0x0
+
+#define BOOT_BASE ARM_DRAM1_BASE
+#define BOOT_SIZE UL(0x2800000)
+
+#define ARM_NS_DRAM1_BASE (ARM_DRAM1_BASE + BOOT_SIZE)
+/*
+ * The last 2MB is meant to be NOLOAD and will not be zero
+ * initialized.
+ */
+#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \
+ BOOT_SIZE - \
+ 0x00200000)
+
+#define MAP_BOOT_RW MAP_REGION_FLAT( \
+ BOOT_BASE, \
+ BOOT_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
+ A5DS_SHARED_RAM_BASE, \
+ A5DS_SHARED_RAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
+ ARM_NS_DRAM1_BASE, \
+ ARM_NS_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_SRAM MAP_REGION_FLAT( \
+ SRAM_BASE, \
+ SRAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+/*
+ * Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
+ * share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides
+ * in the BL1 RW region. Hence, BL2 needs access to the BL1 RW region in order
+ * to be able to access the heap.
+ */
+
+#define ARM_MAP_BL_RO MAP_REGION_FLAT(\
+ BL_CODE_BASE,\
+ BL_CODE_END - BL_CODE_BASE,\
+ MT_CODE | MT_SECURE),\
+ MAP_REGION_FLAT(\
+ BL_RO_DATA_BASE,\
+ BL_RO_DATA_END\
+ - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+
+#if USE_COHERENT_MEM
+#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT(\
+ BL_COHERENT_RAM_BASE,\
+ BL_COHERENT_RAM_END \
+ - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
+ (ARM_FW_CONFIGS_LIMIT \
+ - ARM_BL_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * The max number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#define ARM_BL_REGIONS 6
+
+#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
+ ARM_BL_REGIONS)
+
+/* Memory mapped Generic timer interfaces */
+#define A5DS_TIMER_BASE_FREQUENCY UL(7500000)
+
+#define ARM_CONSOLE_BAUDRATE 115200
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
+ * and limit. Leave enough space of BL2 meminfo.
+ */
+#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
+/*******************************************************************************
+ * BL1 specific defines.
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ ******************************************************************************/
+#define BL1_RO_BASE 0x00000000
+#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE
+/*
+ * Put BL1 RW at the top of the memory allocated for BL images in NS DRAM.
+ */
+#define BL1_RW_BASE (ARM_BL_RAM_BASE + \
+ ARM_BL_RAM_SIZE - \
+ (PLAT_ARM_MAX_BL1_RW_SIZE))
+#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \
+ (ARM_BL_RAM_SIZE))
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+
+/*
+ * Put BL2 just below BL1.
+ */
+#define BL2_BASE (BL1_RW_BASE - A5DS_MAX_BL2_SIZE)
+#define BL2_LIMIT BL1_RW_BASE
+
+/* Put BL32 below BL2 in NS DRAM.*/
+#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
+ + (PAGE_SIZE / 2U))
+
+#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
+ - PLAT_ARM_MAX_BL32_SIZE)
+#define BL32_PROGBITS_LIMIT BL2_BASE
+#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+
+/* Required platform porting definitions */
+#define PLATFORM_CORE_COUNT A5DS_CORE_COUNT
+#define PLAT_NUM_PWR_DOMAINS (A5DS_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT) + U(1)
+
+#define PLAT_MAX_PWR_LVL 2
+
+/*
+ * Other platform porting definitions are provided by included headers
+ */
+
+/*
+ * Required ARM standard platform porting definitions
+ */
+
+#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */
+
+#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000
+#define PLAT_ARM_TRUSTED_ROM_SIZE 0x10000 /* 64KB */
+
+#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000)
+
+/*
+ * Load address of BL33 for this platform port
+ */
+#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000))
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if defined(IMAGE_BL32)
+# define PLAT_ARM_MMAP_ENTRIES 8
+# define MAX_XLAT_TABLES 6
+#else
+# define PLAT_ARM_MMAP_ENTRIES 12
+# define MAX_XLAT_TABLES 6
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000
+
+/*
+ * A5DS_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#define A5DS_MAX_BL2_SIZE 0x11000
+
+/*
+ * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
+ * calculated using the current SP_MIN PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+#define PLAT_ARM_MAX_BL32_SIZE 0x3B000
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+# define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
+#define PLAT_ARM_FLASH_IMAGE_BASE BOOT_BASE
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#define PLAT_ARM_NVM_BASE BOOT_BASE
+#define PLAT_ARM_NVM_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_ARM_BOOT_UART_BASE 0x1A200000
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ UL(7500000)
+
+#define PLAT_ARM_RUN_UART_BASE 0x1A210000
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ UL(7500000)
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define A5DS_TIMER_BASE_FREQUENCY UL(7500000)
+
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID 1
+
+/* Mailbox base address */
+#define A5DS_TRUSTED_MAILBOX_BASE A5DS_SHARED_RAM_BASE
+#define A5DS_TRUSTED_MAILBOX_SIZE (8 + A5DS_HOLD_SIZE)
+#define A5DS_HOLD_BASE (A5DS_TRUSTED_MAILBOX_BASE + 8)
+#define A5DS_HOLD_SIZE (PLATFORM_CORE_COUNT * \
+ A5DS_HOLD_ENTRY_SIZE)
+#define A5DS_HOLD_ENTRY_SHIFT 3
+#define A5DS_HOLD_ENTRY_SIZE (1 << A5DS_HOLD_ENTRY_SHIFT)
+#define A5DS_HOLD_STATE_WAIT 0
+#define A5DS_HOLD_STATE_GO 1
+
+/* Snoop Control Unit base address */
+#define A5DS_SCU_BASE 0x1C000000
+
+/*
+ * GIC related constants to cater for GICv2
+ */
+#define PLAT_ARM_GICD_BASE 0x1C001000
+#define PLAT_ARM_GICC_BASE 0x1C000100
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ ARM_G1S_IRQ_PROPS(grp), \
+ INTR_PROP_DESC(A5DS_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(A5DS_IRQ_SEC_SYS_TIMER,\
+ GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
new file mode 100644
index 0000000..4f87306
--- /dev/null
+++ b/plat/arm/board/a5ds/platform.mk
@@ -0,0 +1,111 @@
+#
+# Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Firmware Configuration Framework sources
+include common/fdt_wrappers.mk
+include lib/fconf/fconf.mk
+
+BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+
+# Add `libfdt` and Arm common helpers required for Dynamic Config
+include lib/libfdt/libfdt.mk
+
+DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \
+ plat/arm/common/arm_dyn_cfg_helpers.c
+
+DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+A5DS_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+
+A5DS_SECURITY_SOURCES := plat/arm/board/a5ds/a5ds_security.c
+
+PLAT_INCLUDES := -Iplat/arm/board/a5ds/include
+
+PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/${ARCH}/pl011_console.S \
+ plat/arm/board/a5ds/a5ds_common.c \
+ plat/arm/common/${ARCH}/arm_helpers.S \
+ plat/arm/common/arm_common.c \
+ plat/arm/common/arm_console.c \
+ plat/arm/board/common/${ARCH}/board_arm_helpers.S
+
+A5DS_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S
+
+BL1_SOURCES += drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ plat/arm/common/arm_bl1_setup.c \
+ plat/arm/common/arm_err.c \
+ plat/arm/board/a5ds/a5ds_err.c \
+ plat/arm/common/arm_io_storage.c \
+ plat/arm/common/fconf/arm_fconf_io.c \
+ plat/arm/board/a5ds/${ARCH}/a5ds_helpers.S \
+ plat/arm/board/a5ds/a5ds_bl1_setup.c \
+ lib/aarch32/arm32_aeabi_divmod.c \
+ lib/aarch32/arm32_aeabi_divmod_a32.S \
+ ${A5DS_CPU_LIBS} \
+ ${DYN_CFG_SOURCES}
+
+BL2_SOURCES += lib/aarch32/arm32_aeabi_divmod.c \
+ lib/aarch32/arm32_aeabi_divmod_a32.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/arm/board/a5ds/a5ds_bl2_setup.c \
+ plat/arm/common/arm_bl2_setup.c \
+ plat/arm/common/arm_err.c \
+ plat/arm/board/a5ds/a5ds_err.c \
+ plat/arm/common/arm_io_storage.c \
+ plat/arm/common/fconf/arm_fconf_io.c \
+ plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \
+ plat/arm/common/arm_image_load.c \
+ common/desc_image_load.c \
+ ${DYN_CFG_SOURCES} \
+ ${A5DS_SECURITY_SOURCES}
+
+# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
+ifdef UNIX_MK
+
+FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb
+
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+
+$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \
+ fdts/$(notdir ${FVP_HW_CONFIG_DTS})))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
+
+FDT_SOURCES += plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
+ plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
+ ${FVP_HW_CONFIG_DTS}
+endif
+
+NEED_BL32 := yes
+
+MULTI_CONSOLE_API := 1
+
+PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch32/nonlpae_tables.c
+
+# Use translation tables library v1 when using Cortex-A5
+ARM_XLAT_TABLES_LIB_V1 := 1
+$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
+$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
+
+$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG))
+$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG))
diff --git a/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c b/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c
new file mode 100644
index 0000000..a951dc7
--- /dev/null
+++ b/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/scu.h>
+#include <plat/arm/common/plat_arm.h>
+
+
+void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /* enable snoop control unit */
+ enable_snoop_ctrl_unit(A5DS_SCU_BASE);
+}
+
+/*
+ * A5DS will only have one always-on power domain and there
+ * is no power control present.
+ */
+void plat_arm_pwrc_setup(void)
+{
+}
+
diff --git a/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
new file mode 100644
index 0000000..4b0c97d
--- /dev/null
+++ b/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2019, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SP_MIN source files specific to A5DS platform
+BL32_SOURCES += drivers/arm/scu/scu.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ lib/aarch32/arm32_aeabi_divmod.c \
+ lib/aarch32/arm32_aeabi_divmod_a32.S \
+ plat/arm/board/a5ds/aarch32/a5ds_helpers.S \
+ plat/arm/board/a5ds/a5ds_pm.c \
+ plat/arm/board/a5ds/a5ds_topology.c \
+ plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c \
+ plat/arm/common/sp_min/arm_sp_min_setup.c \
+ plat/common/aarch32/platform_mp_stack.S \
+ plat/common/plat_psci_common.c \
+ ${A5DS_CPU_LIBS} \
+ ${A5DS_GIC_SOURCES} \
+ ${A5DS_SECURITY_SOURCES}
diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
new file mode 100644
index 0000000..20120c9
--- /dev/null
+++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include "../fpga_private.h"
+
+#include <platform_def.h>
+
+ .globl plat_get_my_entrypoint
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_is_my_cpu_primary
+ .globl platform_mem_init
+ .globl plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_fpga_calc_core_pos
+
+/* -----------------------------------------------------------------------
+ * Indicate a cold boot for every CPU - warm boot is unsupported for the
+ * holding pen PSCI implementation.
+ * -----------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mov x0, #0
+ ret
+endfunc plat_get_my_entrypoint
+
+/* -----------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ * -----------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+
+ /*
+ * Wait for the primary processor to initialise the .BSS segment
+ * to avoid a race condition that would erase fpga_valid_mpids
+ * if it is populated before the C runtime is ready.
+ *
+ * We cannot use the current spin-lock implementation until the
+ * runtime is up and we should not rely on sevl/wfe instructions as
+ * it is optional whether they are implemented or not, so we use
+ * a global variable as lock and wait for the primary processor to
+ * finish the C runtime bring-up.
+ */
+
+ ldr w0, =C_RUNTIME_READY_KEY
+ adrp x1, secondary_core_spinlock
+ add x1, x1, :lo12:secondary_core_spinlock
+1:
+ wfe
+ ldr w2, [x1]
+ cmp w2, w0
+ b.ne 1b
+ /* Prevent reordering of the store into fpga_valid_mpids below */
+ dmb ish
+
+ mov x10, x30
+ bl plat_my_core_pos
+ mov x30, x10
+
+ adrp x4, fpga_valid_mpids
+ add x4, x4, :lo12:fpga_valid_mpids
+ mov x5, #VALID_MPID
+ strb w5, [x4, x0]
+
+ /*
+ * Poll the CPU's hold entry until it indicates to jump
+ * to the entrypoint address.
+ */
+
+ adrp x1, hold_base
+ add x1, x1, :lo12:hold_base
+poll_hold_entry:
+ ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
+ cmp x3, #PLAT_FPGA_HOLD_STATE_GO
+ b.ne 1f
+
+ adrp x2, fpga_sec_entrypoint
+ add x2, x2, :lo12:fpga_sec_entrypoint
+ ldr x3, [x2]
+ br x3
+1:
+ wfe
+ b poll_hold_entry
+
+endfunc plat_secondary_cold_boot_setup
+
+/* -----------------------------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary cpu
+ * -----------------------------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ mov_imm x1, MPIDR_AFFINITY_MASK
+ and x0, x0, x1
+ cmp x0, #FPGA_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+func plat_my_core_pos
+ ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
+ mrs x0, mpidr_el1
+ and x0, x0, x1
+ b plat_fpga_calc_core_pos
+
+endfunc plat_my_core_pos
+
+/* -----------------------------------------------------------------------
+ * unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
+ * Clobber registers: x0 to x5
+ * -----------------------------------------------------------------------
+ */
+func plat_fpga_calc_core_pos
+ /*
+ * Check for MT bit in MPIDR, which may be either value for images
+ * running on the FPGA.
+ *
+ * If not set, shift MPIDR to left to make it look as if in a
+ * multi-threaded implementation.
+ *
+ */
+ tst x0, #MPIDR_MT_MASK
+ lsl x3, x0, #MPIDR_AFFINITY_BITS
+ csel x3, x3, x0, eq
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ mov x4, #FPGA_MAX_CPUS_PER_CLUSTER
+ mov x5, #FPGA_MAX_PE_PER_CPU
+
+ /* Compute linear position */
+ madd x1, x2, x4, x1
+ madd x0, x1, x5, x0
+
+ ret
+endfunc plat_fpga_calc_core_pos
+
+func plat_crash_console_init
+ mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+ mov_imm x1, PLAT_FPGA_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+ mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/arm/board/arm_fpga/build_axf.ld.S b/plat/arm/board/arm_fpga/build_axf.ld.S
new file mode 100644
index 0000000..d8254e5
--- /dev/null
+++ b/plat/arm/board/arm_fpga/build_axf.ld.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Linker script for the Arm Ltd. FPGA boards to generate an ELF file that
+ * contains the ROM trampoline, BL31 and the DTB.
+ *
+ * This allows to pass just one file to the uploader tool, and automatically
+ * provides the correct load addresses.
+ */
+
+#include <platform_def.h>
+
+OUTPUT_FORMAT("elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+
+INPUT(./rom_trampoline.o)
+INPUT(./kernel_trampoline.o)
+
+TARGET(binary)
+INPUT(./bl31.bin)
+INPUT(./fdts/arm_fpga.dtb)
+
+ENTRY(_start)
+
+SECTIONS
+{
+ .rom (0x0): {
+ *rom_trampoline.o(.text*)
+ KEEP(*(.rom))
+ }
+
+ .bl31 (BL31_BASE): {
+ ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned");
+ *bl31.bin
+ }
+
+ .dtb (FPGA_PRELOADED_DTB_BASE): {
+ ASSERT(. == ALIGN(8), "DTB address is not 8-byte aligned");
+ *arm_fpga.dtb
+ }
+
+ .kern_tramp (PRELOADED_BL33_BASE): {
+ *kernel_trampoline.o(.text*)
+ KEEP(*(.kern_tramp))
+ }
+
+ /DISCARD/ : { *(stacks) }
+ /DISCARD/ : { *(.debug_*) }
+ /DISCARD/ : { *(.note*) }
+ /DISCARD/ : { *(.comment*) }
+}
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
new file mode 100644
index 0000000..e1b3abb
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/extensions/spe.h>
+#include <lib/mmio.h>
+#include <libfdt.h>
+
+#include "fpga_private.h"
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+static entry_point_info_t bl33_image_ep_info;
+static unsigned int system_freq;
+volatile uint32_t secondary_core_spinlock;
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return 0ULL;
+#endif
+}
+
+uint32_t fpga_get_spsr_for_bl33_entry(void)
+{
+ return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ /* Add this core to the VALID mpids list */
+ fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID;
+
+ /*
+ * Notify the secondary CPUs that the C runtime is ready
+ * so they can announce themselves.
+ */
+ secondary_core_spinlock = C_RUNTIME_READY_KEY;
+ dsbish();
+ sev();
+
+ fpga_console_init();
+
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ /* Set x0-x3 for the primary CPU as expected by the kernel */
+ bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE;
+ bl33_image_ep_info.args.arg1 = 0U;
+ bl33_image_ep_info.args.arg2 = 0U;
+ bl33_image_ep_info.args.arg3 = 0U;
+}
+
+void bl31_plat_arch_setup(void)
+{
+}
+
+void bl31_platform_setup(void)
+{
+ /* Write frequency to CNTCRL and initialize timer */
+ generic_delay_timer_init();
+
+ /*
+ * Before doing anything else, wait for some time to ensure that
+ * the secondary CPUs have populated the fpga_valid_mpids array.
+ * As the number of secondary cores is unknown and can even be 0,
+ * it is not possible to rely on any signal from them, so use a
+ * delay instead.
+ */
+ mdelay(5);
+
+ /*
+ * On the event of a cold reset issued by, for instance, a reset pin
+ * assertion, we cannot guarantee memory to be initialized to zero.
+ * In such scenario, if the secondary cores reached
+ * plat_secondary_cold_boot_setup before the primary one initialized
+ * .BSS, we could end up having a race condition if the spinlock
+ * was not cleared before.
+ *
+ * Similarly, if there were a reset before the spinlock had been
+ * cleared, the secondary cores would find the lock opened before
+ * .BSS is cleared, causing another race condition.
+ *
+ * So clean the spinlock as soon as we think it is safe to reduce the
+ * chances of any race condition on a reset.
+ */
+ secondary_core_spinlock = 0UL;
+
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ plat_fpga_gic_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+ next_image_info = &bl33_image_ep_info;
+
+ /* Only expecting BL33: the kernel will run in EL2NS */
+ assert(type == NON_SECURE);
+
+ /* None of the images can have 0x0 as the entrypoint */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * Even though we sell the FPGA UART as an SBSA variant, it is actually
+ * a full fledged PL011. So the baudrate divider registers exist.
+ */
+#ifndef UARTIBRD
+#define UARTIBRD 0x024
+#define UARTFBRD 0x028
+#endif
+
+/* Round an integer to the closest multiple of a value. */
+static unsigned int round_multiple(unsigned int x, unsigned int multiple)
+{
+ if (multiple < 2) {
+ return x;
+ }
+
+ return ((x + (multiple / 2 - 1)) / multiple) * multiple;
+}
+
+#define PL011_FRAC_SHIFT 6
+#define FPGA_DEFAULT_BAUDRATE 38400
+#define PL011_OVERSAMPLING 16
+static unsigned int pl011_freq_from_divider(unsigned int divider)
+{
+ unsigned int freq;
+
+ freq = divider * FPGA_DEFAULT_BAUDRATE * PL011_OVERSAMPLING;
+
+ return freq >> PL011_FRAC_SHIFT;
+}
+
+/*
+ * The FPGAs run most peripherals from one main clock, among them the CPUs,
+ * the arch timer, and the UART baud base clock.
+ * The SCP knows this frequency and programs the UART clock divider for a
+ * 38400 bps baudrate. Recalculate the base input clock from there.
+ */
+static unsigned int fpga_get_system_frequency(void)
+{
+ const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
+ int node, err;
+
+ /*
+ * If the arch timer DT node has an explicit clock-frequency property
+ * set, use that, to allow people overriding auto-detection.
+ */
+ node = fdt_node_offset_by_compatible(fdt, 0, "arm,armv8-timer");
+ if (node >= 0) {
+ uint32_t freq;
+
+ err = fdt_read_uint32(fdt, node, "clock-frequency", &freq);
+ if (err >= 0) {
+ return freq;
+ }
+ }
+
+ node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011");
+ if (node >= 0) {
+ uintptr_t pl011_base;
+ unsigned int divider;
+
+ err = fdt_get_reg_props_by_index(fdt, node, 0,
+ &pl011_base, NULL);
+ if (err >= 0) {
+ divider = mmio_read_32(pl011_base + UARTIBRD);
+ divider <<= PL011_FRAC_SHIFT;
+ divider += mmio_read_32(pl011_base + UARTFBRD);
+
+ /*
+ * The result won't be exact, due to rounding errors,
+ * but the input frequency was a multiple of 250 KHz.
+ */
+ return round_multiple(pl011_freq_from_divider(divider),
+ 250000);
+ } else {
+ WARN("Cannot read PL011 MMIO base\n");
+ }
+ } else {
+ WARN("No PL011 DT node\n");
+ }
+
+ /* No PL011 DT node or calculation failed. */
+ return FPGA_DEFAULT_TIMER_FREQUENCY;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ if (system_freq == 0U) {
+ system_freq = fpga_get_system_frequency();
+ }
+
+ return system_freq;
+}
+
+static void fpga_dtb_update_clock(void *fdt, unsigned int freq)
+{
+ uint32_t freq_dtb = fdt32_to_cpu(freq);
+ uint32_t phandle;
+ int node, err;
+
+ node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011");
+ if (node < 0) {
+ WARN("%s(): No PL011 DT node found\n", __func__);
+
+ return;
+ }
+
+ err = fdt_read_uint32(fdt, node, "clocks", &phandle);
+ if (err != 0) {
+ WARN("Cannot find clocks property\n");
+
+ return;
+ }
+
+ node = fdt_node_offset_by_phandle(fdt, phandle);
+ if (node < 0) {
+ WARN("Cannot get phandle\n");
+
+ return;
+ }
+
+ err = fdt_setprop_inplace(fdt, node,
+ "clock-frequency",
+ &freq_dtb,
+ sizeof(freq_dtb));
+ if (err < 0) {
+ WARN("Could not update DT baud clock frequency\n");
+
+ return;
+ }
+}
+
+#define CMDLINE_SIGNATURE "CMD:"
+
+static int fpga_dtb_set_commandline(void *fdt, const char *cmdline)
+{
+ int chosen;
+ const char *eol;
+ char nul = 0;
+ int slen, err;
+
+ chosen = fdt_add_subnode(fdt, 0, "chosen");
+ if (chosen == -FDT_ERR_EXISTS) {
+ chosen = fdt_path_offset(fdt, "/chosen");
+ }
+
+ if (chosen < 0) {
+ return chosen;
+ }
+
+ /*
+ * There is most likely an EOL at the end of the
+ * command line, make sure we terminate the line there.
+ * We can't replace the EOL with a NUL byte in the
+ * source, as this is in read-only memory. So we first
+ * create the property without any termination, then
+ * append a single NUL byte.
+ */
+ eol = strchr(cmdline, '\n');
+ if (eol == NULL) {
+ eol = strchr(cmdline, 0);
+ }
+ /* Skip the signature and omit the EOL/NUL byte. */
+ slen = eol - (cmdline + strlen(CMDLINE_SIGNATURE));
+ /*
+ * Let's limit the size of the property, just in case
+ * we find the signature by accident. The Linux kernel
+ * limits to 4096 characters at most (in fact 2048 for
+ * arm64), so that sounds like a reasonable number.
+ */
+ if (slen > 4095) {
+ slen = 4095;
+ }
+
+ err = fdt_setprop(fdt, chosen, "bootargs",
+ cmdline + strlen(CMDLINE_SIGNATURE), slen);
+ if (err != 0) {
+ return err;
+ }
+
+ return fdt_appendprop(fdt, chosen, "bootargs", &nul, 1);
+}
+
+static void fpga_prepare_dtb(void)
+{
+ void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
+ const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE;
+ int err;
+
+ err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE);
+ if (err < 0) {
+ ERROR("cannot open devicetree at %p: %d\n", fdt, err);
+ panic();
+ }
+
+ /* Reserve memory used by Trusted Firmware. */
+ if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE,
+ BL31_LIMIT - BL31_BASE)) {
+ WARN("Failed to add reserved memory node to DT\n");
+ }
+
+ /* Check for the command line signature. */
+ if (!strncmp(cmdline, CMDLINE_SIGNATURE, strlen(CMDLINE_SIGNATURE))) {
+ err = fpga_dtb_set_commandline(fdt, cmdline);
+ if (err == 0) {
+ INFO("using command line at 0x%x\n",
+ FPGA_PRELOADED_CMD_LINE);
+ } else {
+ ERROR("failed to put command line into DTB: %d\n", err);
+ }
+ }
+
+ if (err < 0) {
+ ERROR("Error %d extending Device Tree\n", err);
+ panic();
+ }
+
+ err = fdt_add_cpus_node(fdt, FPGA_MAX_PE_PER_CPU,
+ FPGA_MAX_CPUS_PER_CLUSTER,
+ FPGA_MAX_CLUSTER_COUNT);
+
+ if (err == -EEXIST) {
+ WARN("Not overwriting already existing /cpus node in DTB\n");
+ } else {
+ if (err < 0) {
+ ERROR("Error %d creating the /cpus DT node\n", err);
+ panic();
+ } else {
+ unsigned int nr_cores = fpga_get_nr_gic_cores();
+
+ INFO("Adjusting GICR DT region to cover %u cores\n",
+ nr_cores);
+ err = fdt_adjust_gic_redist(fdt, nr_cores,
+ fpga_get_redist_base(),
+ fpga_get_redist_size());
+ if (err < 0) {
+ ERROR("Error %d fixing up GIC DT node\n", err);
+ }
+ }
+ }
+
+ fpga_dtb_update_clock(fdt, system_freq);
+
+ /* Check whether we support the SPE PMU. Remove the DT node if not. */
+ if (!spe_supported()) {
+ int node = fdt_node_offset_by_compatible(fdt, 0,
+ "arm,statistical-profiling-extension-v1");
+
+ if (node >= 0) {
+ fdt_del_node(fdt, node);
+ }
+ }
+
+ /* Check whether we have an ITS. Remove the DT node if not. */
+ if (!fpga_has_its()) {
+ int node = fdt_node_offset_by_compatible(fdt, 0,
+ "arm,gic-v3-its");
+
+ if (node >= 0) {
+ fdt_del_node(fdt, node);
+ }
+ }
+
+ err = fdt_pack(fdt);
+ if (err < 0) {
+ ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err);
+ }
+
+ clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ fpga_prepare_dtb();
+}
+
+void bl31_plat_enable_mmu(uint32_t flags)
+{
+ /* TODO: determine if MMU needs to be enabled */
+}
diff --git a/plat/arm/board/arm_fpga/fpga_console.c b/plat/arm/board/arm_fpga/fpga_console.c
new file mode 100644
index 0000000..8c1da62
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_console.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+
+#include <platform_def.h>
+
+static console_t console;
+
+void fpga_console_init(void)
+{
+ const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
+ uintptr_t base_addr = PLAT_FPGA_CRASH_UART_BASE;
+ int node;
+
+ /*
+ * Try to read the UART base address from the DT, by chasing the
+ * stdout-path property of the chosen node.
+ * If this does not work, use the crash console address as a fallback.
+ */
+ node = fdt_get_stdout_node_offset(fdt);
+ if (node >= 0) {
+ fdt_get_reg_props_by_index(fdt, node, 0, &base_addr, NULL);
+ }
+
+ (void)console_pl011_register(base_addr, 0, 0, &console);
+
+ console_set_scope(&console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME);
+}
diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h
new file mode 100644
index 0000000..2884ea6
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_def.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/utils_def.h>
+
+#ifndef FPGA_DEF_H
+#define FPGA_DEF_H
+
+/*
+ * These are set to large values to account for images describing systems with
+ * larger cluster configurations.
+ *
+ * For cases where the number of clusters, cores or threads is smaller than a
+ * maximum value below, this does not affect the PSCI functionality as any PEs
+ * that are present will still be indexed appropriately regardless of any empty
+ * entries in the array used to represent the topology.
+ */
+
+#define FPGA_MAX_CLUSTER_COUNT 4
+#define FPGA_MAX_CPUS_PER_CLUSTER 8
+#define FPGA_MAX_PE_PER_CPU 4
+
+#define FPGA_PRIMARY_CPU 0x0
+/*******************************************************************************
+ * FPGA image memory map related constants
+ ******************************************************************************/
+
+/*
+ * UART base address, just for the crash console, as a fallback.
+ * The actual console UART address is taken from the DT.
+ */
+#define PLAT_FPGA_CRASH_UART_BASE 0x7ff80000
+
+#define FPGA_DEFAULT_TIMER_FREQUENCY 10000000
+
+#endif
diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c
new file mode 100644
index 0000000..e06a9da
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_gicv3.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/arm_gicv3_common.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/mmio.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+static const interrupt_prop_t fpga_interrupt_props[] = {
+ PLATFORM_G1S_PROPS(INTR_GROUP1S),
+ PLATFORM_G0_PROPS(INTR_GROUP0)
+};
+
+static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+static int nr_itses;
+
+static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+static gicv3_driver_data_t fpga_gicv3_driver_data = {
+ .interrupt_props = fpga_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = fpga_rdistif_base_addrs,
+ .mpidr_to_core_pos = fpga_mpidr_to_core_pos
+};
+
+void plat_fpga_gic_init(void)
+{
+ const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
+ uintptr_t gicr_base = 0U;
+ uint32_t iidr;
+ int node, ret;
+
+ node = fdt_node_offset_by_compatible(fdt, 0, "arm,gic-v3");
+ if (node < 0) {
+ WARN("No \"arm,gic-v3\" compatible node found in DT, no GIC support.\n");
+ return;
+ }
+
+ /* TODO: Assuming only empty "ranges;" properties up the bus path. */
+ ret = fdt_get_reg_props_by_index(fdt, node, 0,
+ &fpga_gicv3_driver_data.gicd_base, NULL);
+ if (ret < 0) {
+ WARN("Could not read GIC distributor address from DT.\n");
+ return;
+ }
+
+ iidr = mmio_read_32(fpga_gicv3_driver_data.gicd_base + GICD_IIDR);
+ if (((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
+ ((iidr & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)) {
+ unsigned int frame_id;
+
+ /*
+ * According to the GIC TRMs, if there are any ITSes, they
+ * start four 64K pages after the distributor. After all
+ * the ITSes then follow the redistributors.
+ */
+ gicr_base = fpga_gicv3_driver_data.gicd_base + (4U << 16);
+
+ do {
+ uint64_t its_typer;
+
+ /* Each GIC component can be identified by its ID. */
+ frame_id = gicv3_get_component_partnum(gicr_base);
+
+ if (frame_id == PIDR_COMPONENT_ARM_REDIST) {
+ INFO("Found %d ITSes, redistributors start at 0x%llx\n",
+ nr_itses, (unsigned long long)gicr_base);
+ break;
+ }
+
+ if (frame_id != PIDR_COMPONENT_ARM_ITS) {
+ WARN("GICv3: found unexpected frame 0x%x\n",
+ frame_id);
+ gicr_base = 0U;
+ break;
+ }
+
+ /*
+ * Found an ITS, now work out if it supports virtual
+ * SGIs (for direct guest injection). If yes, each
+ * ITS occupies four 64K pages, otherwise just two.
+ */
+ its_typer = mmio_read_64(gicr_base + GITS_TYPER);
+ if ((its_typer & GITS_TYPER_VSGI) != 0U) {
+ gicr_base += 4U << 16;
+ } else {
+ gicr_base += 2U << 16;
+ }
+ nr_itses++;
+ } while (true);
+ }
+
+ /*
+ * If this is not a GIC-600 or -700, or the autodetection above failed,
+ * use the base address from the device tree.
+ */
+ if (gicr_base == 0U) {
+ ret = fdt_get_reg_props_by_index(fdt, node, 1,
+ &fpga_gicv3_driver_data.gicr_base,
+ NULL);
+ if (ret < 0) {
+ WARN("Could not read GIC redistributor address from DT.\n");
+ return;
+ }
+ } else {
+ fpga_gicv3_driver_data.gicr_base = gicr_base;
+ }
+
+ gicv3_driver_init(&fpga_gicv3_driver_data);
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void fpga_pwr_gic_on_finish(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void fpga_pwr_gic_off(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+ gicv3_rdistif_off(plat_my_core_pos());
+}
+
+unsigned int fpga_get_nr_gic_cores(void)
+{
+ return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base);
+}
+
+uintptr_t fpga_get_redist_size(void)
+{
+ uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base +
+ GICR_TYPER);
+
+ return gicv3_redist_size(typer_val);
+}
+
+uintptr_t fpga_get_redist_base(void)
+{
+ return fpga_gicv3_driver_data.gicr_base;
+}
+
+bool fpga_has_its(void)
+{
+ return nr_itses > 0;
+}
diff --git a/plat/arm/board/arm_fpga/fpga_pm.c b/plat/arm/board/arm_fpga/fpga_pm.c
new file mode 100644
index 0000000..a306a23
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_pm.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include "fpga_private.h"
+#include <platform_def.h>
+
+/*
+ * This is a basic PSCI implementation that allows secondary CPUs to be
+ * released from their initial state and continue to the warm boot entrypoint.
+ *
+ * The secondary CPUs are placed in a holding pen and released by calls
+ * to fpga_pwr_domain_on(mpidr), which updates the hold entry for the CPU
+ * specified by the mpidr argument - the (polling) target CPU will then branch
+ * to the BL31 warm boot sequence at the entrypoint address.
+ *
+ * Additionally, the secondary CPUs are kept in a low-power wfe() state
+ * (placed there at the end of each poll) and woken when necessary through
+ * calls to sev() in fpga_pwr_domain_on(mpidr), once the hold state for the
+ * relevant CPU has been updated.
+ *
+ * Hotplug is currently implemented using a wfi-loop, which removes the
+ * dependencies on any power controllers or other mechanism that is specific
+ * to the running system as specified by the FPGA image.
+ */
+
+uint64_t hold_base[PLATFORM_CORE_COUNT];
+uintptr_t fpga_sec_entrypoint;
+
+/*
+ * Calls to the CPU specified by the mpidr will set its hold entry to a value
+ * indicating that it should stop polling and branch off to the warm entrypoint.
+ */
+static int fpga_pwr_domain_on(u_register_t mpidr)
+{
+ int pos = plat_core_pos_by_mpidr(mpidr);
+ unsigned long current_mpidr = read_mpidr_el1();
+
+ if (pos < 0) {
+ panic();
+ }
+
+ if (mpidr == current_mpidr) {
+ return PSCI_E_ALREADY_ON;
+ }
+ hold_base[pos] = PLAT_FPGA_HOLD_STATE_GO;
+ flush_dcache_range((uintptr_t)&hold_base[pos], sizeof(uint64_t));
+ sev(); /* Wake any CPUs from wfe */
+
+ return PSCI_E_SUCCESS;
+}
+
+void fpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ fpga_pwr_gic_on_finish();
+}
+
+static void fpga_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ fpga_pwr_gic_off();
+
+ while (1) {
+ wfi();
+ }
+}
+
+static void fpga_cpu_standby(plat_local_state_t cpu_state)
+{
+ /*
+ * Enter standby state
+ * dsb is good practice before using wfi to enter low power states
+ */
+ u_register_t scr = read_scr_el3();
+ write_scr_el3(scr|SCR_IRQ_BIT);
+ dsb();
+ wfi();
+ write_scr_el3(scr);
+}
+
+plat_psci_ops_t plat_fpga_psci_pm_ops = {
+ .pwr_domain_on = fpga_pwr_domain_on,
+ .pwr_domain_on_finish = fpga_pwr_domain_on_finish,
+ .pwr_domain_off = fpga_pwr_domain_off,
+ .cpu_standby = fpga_cpu_standby
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ fpga_sec_entrypoint = sec_entrypoint;
+ flush_dcache_range((uint64_t)&fpga_sec_entrypoint,
+ sizeof(fpga_sec_entrypoint));
+ *psci_ops = &plat_fpga_psci_pm_ops;
+ return 0;
+}
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
new file mode 100644
index 0000000..84d651c
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FPGA_PRIVATE_H
+#define FPGA_PRIVATE_H
+
+#include "../fpga_def.h"
+#include <platform_def.h>
+
+#define C_RUNTIME_READY_KEY (0xaa55aa55)
+#define VALID_MPID (1U)
+#define FPGA_MAX_DTB_SIZE 0x10000
+
+#ifndef __ASSEMBLER__
+
+extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
+
+void fpga_console_init(void);
+
+void plat_fpga_gic_init(void);
+void fpga_pwr_gic_on_finish(void);
+void fpga_pwr_gic_off(void);
+unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
+unsigned int fpga_get_nr_gic_cores(void);
+uintptr_t fpga_get_redist_size(void);
+uintptr_t fpga_get_redist_base(void);
+bool fpga_has_its(void);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* FPGA_PRIVATE_H */
diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c
new file mode 100644
index 0000000..7fead86
--- /dev/null
+++ b/plat/arm/board/arm_fpga/fpga_topology.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/spinlock.h>
+
+#include "fpga_private.h"
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ unsigned int i;
+
+ /*
+ * The highest level is the system level. The next level is constituted
+ * by clusters and then cores in clusters.
+ *
+ * This description of the power domain topology is aligned with the CPU
+ * indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos()
+ * APIs.
+ *
+ * A description of the topology tree can be found at
+ * https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design
+ */
+
+ if (fpga_power_domain_tree_desc[0] == 0U) {
+ /*
+ * As fpga_power_domain_tree_desc[0] == 0, assume that the
+ * Power Domain Topology Tree has not been initialized, so
+ * perform the initialization here.
+ */
+
+ fpga_power_domain_tree_desc[0] = 1U;
+ fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
+
+ for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) {
+ fpga_power_domain_tree_desc[2 + i] =
+ (FPGA_MAX_CPUS_PER_CLUSTER *
+ FPGA_MAX_PE_PER_CPU);
+ }
+ }
+
+ return fpga_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int core_pos;
+
+ mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
+ mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+
+ if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) ||
+ (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) ||
+ (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) {
+ ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr);
+ panic();
+ }
+
+ /* Calculate the core position, based on the maximum topology. */
+ core_pos = plat_fpga_calc_core_pos(mpidr);
+
+ /* Check whether this core is actually present. */
+ if (fpga_valid_mpids[core_pos] != VALID_MPID) {
+ return -1;
+ }
+
+ return core_pos;
+}
diff --git a/plat/arm/board/arm_fpga/include/plat_macros.S b/plat/arm/board/arm_fpga/include/plat_macros.S
new file mode 100644
index 0000000..44cddeb
--- /dev/null
+++ b/plat/arm/board/arm_fpga/include/plat_macros.S
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+.macro plat_crash_print_regs
+.endm
+
+#endif
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
new file mode 100644
index 0000000..2350d87
--- /dev/null
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <plat/common/common_def.h>
+#include <platform_def.h>
+#include "../fpga_def.h"
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE UL(0x800)
+
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+#define PLATFORM_CORE_COUNT \
+ (FPGA_MAX_CLUSTER_COUNT * \
+ FPGA_MAX_CPUS_PER_CLUSTER * \
+ FPGA_MAX_PE_PER_CPU)
+
+#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1)
+
+#if !ENABLE_PIE
+#define BL31_BASE UL(0x80000000)
+#define BL31_LIMIT UL(0x80070000)
+#else
+#define BL31_BASE UL(0x0)
+#define BL31_LIMIT UL(0x01000000)
+#endif
+
+#define PLAT_SDEI_NORMAL_PRI 0x70
+
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLATFORM_G1S_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+#define PLAT_MAX_RET_STATE 1
+#define PLAT_MAX_OFF_STATE 2
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+#define PLAT_FPGA_HOLD_ENTRY_SHIFT 3
+#define PLAT_FPGA_HOLD_STATE_WAIT 0
+#define PLAT_FPGA_HOLD_STATE_GO 1
+
+#endif
diff --git a/plat/arm/board/arm_fpga/kernel_trampoline.S b/plat/arm/board/arm_fpga/kernel_trampoline.S
new file mode 100644
index 0000000..f4c08ef
--- /dev/null
+++ b/plat/arm/board/arm_fpga/kernel_trampoline.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * The traditional arm64 Linux kernel load address is 512KiB from the
+ * beginning of DRAM, caused by this having been the default value of the
+ * kernel's CONFIG_TEXT_OFFSET Kconfig value.
+ * However kernel version 5.8 changed the default offset (into a 2MB page)
+ * to 0, so TF-A's default assumption is no longer true. Fortunately the
+ * kernel got more relaxed about this offset at the same time, so it
+ * tolerates the wrong offset, but issues a warning:
+ * [Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader!
+ *
+ * We cannot easily change the load address offset in TF-A to be 2MiB, because
+ * this would break older kernels - and they are not as forgiving in this
+ * respect.
+ *
+ * But we can allow users to load the kernel at the right offset, and
+ * offer this trampoline here to transition to this new load address.
+ * Any older kernels, or newer kernels misloaded, will overwrite this code
+ * here, so it does no harm in this case.
+ */
+
+#include <asm_macros.S>
+#include <common/bl_common.ld.h>
+
+.text
+.global _tramp_start
+
+_tramp_start:
+ adr x4, _tramp_start
+ orr x4, x4, #0x1fffff
+ add x4, x4, #1 /* align up to 2MB */
+ br x4
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
new file mode 100644
index 0000000..a14a0d8
--- /dev/null
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -0,0 +1,130 @@
+#
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+include lib/libfdt/libfdt.mk
+
+RESET_TO_BL31 := 1
+ifeq (${RESET_TO_BL31}, 0)
+$(error "This is a BL31-only port; RESET_TO_BL31 must be enabled")
+endif
+
+ifeq (${ENABLE_PIE}, 1)
+override SEPARATE_CODE_AND_RODATA := 1
+endif
+
+CTX_INCLUDE_AARCH32_REGS := 0
+ifeq (${CTX_INCLUDE_AARCH32_REGS}, 1)
+$(error "This is an AArch64-only port; CTX_INCLUDE_AARCH32_REGS must be disabled")
+endif
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+$(error "TRUSTED_BOARD_BOOT must be disabled")
+endif
+
+PRELOADED_BL33_BASE := 0x80080000
+
+FPGA_PRELOADED_DTB_BASE := 0x80070000
+$(eval $(call add_define,FPGA_PRELOADED_DTB_BASE))
+
+FPGA_PRELOADED_CMD_LINE := 0x1000
+$(eval $(call add_define,FPGA_PRELOADED_CMD_LINE))
+
+ENABLE_AMU := 1
+
+# Treating this as a memory-constrained port for now
+USE_COHERENT_MEM := 0
+
+# This can be overridden depending on CPU(s) used in the FPGA image
+HW_ASSISTED_COHERENCY := 1
+
+PL011_GENERIC_UART := 1
+
+SUPPORT_UNKNOWN_MPID ?= 1
+
+FPGA_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
+
+# select a different set of CPU files, depending on whether we compile for
+# hardware assisted coherency cores or not
+ifeq (${HW_ASSISTED_COHERENCY}, 0)
+# Cores used without DSU
+ FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/cpus/aarch64/cortex_a73.S
+else
+# AArch64-only cores
+ FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \
+ lib/cpus/aarch64/cortex_a76ae.S \
+ lib/cpus/aarch64/cortex_a77.S \
+ lib/cpus/aarch64/cortex_a78.S \
+ lib/cpus/aarch64/neoverse_n_common.S \
+ lib/cpus/aarch64/neoverse_n1.S \
+ lib/cpus/aarch64/neoverse_n2.S \
+ lib/cpus/aarch64/neoverse_e1.S \
+ lib/cpus/aarch64/neoverse_v1.S \
+ lib/cpus/aarch64/cortex_a78_ae.S \
+ lib/cpus/aarch64/cortex_a65.S \
+ lib/cpus/aarch64/cortex_a65ae.S \
+ lib/cpus/aarch64/cortex_a510.S \
+ lib/cpus/aarch64/cortex_a710.S \
+ lib/cpus/aarch64/cortex_a715.S \
+ lib/cpus/aarch64/cortex_x3.S \
+ lib/cpus/aarch64/cortex_a78c.S
+
+# AArch64/AArch32 cores
+ FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \
+ lib/cpus/aarch64/cortex_a75.S
+endif
+
+ifeq (${SUPPORT_UNKNOWN_MPID}, 1)
+# Add support for unknown/invalid MPIDs (aarch64 only)
+$(eval $(call add_define,SUPPORT_UNKNOWN_MPID))
+ FPGA_CPU_LIBS += lib/cpus/aarch64/generic.S
+endif
+
+# Allow detection of GIC-600
+GICV3_SUPPORT_GIC600 := 1
+
+GIC_ENABLE_V4_EXTN := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+FPGA_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/arm/board/arm_fpga/fpga_gicv3.c
+
+FDT_SOURCES := fdts/arm_fpga.dts
+
+PLAT_INCLUDES := -Iplat/arm/board/arm_fpga/include
+
+PLAT_BL_COMMON_SOURCES := plat/arm/board/arm_fpga/${ARCH}/fpga_helpers.S
+
+BL31_SOURCES += common/fdt_fixup.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/arm/pl011/${ARCH}/pl011_console.S \
+ plat/common/plat_psci_common.c \
+ plat/arm/board/arm_fpga/fpga_pm.c \
+ plat/arm/board/arm_fpga/fpga_topology.c \
+ plat/arm/board/arm_fpga/fpga_console.c \
+ plat/arm/board/arm_fpga/fpga_bl31_setup.c \
+ ${FPGA_CPU_LIBS} \
+ ${FPGA_GIC_SOURCES}
+
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,bl31))
+$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/kernel_trampoline.S,bl31))
+$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,bl31))
+
+bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/kernel_trampoline.o ${BUILD_PLAT}/build_axf.ld
+ $(ECHO) " LD $@"
+ $(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf
+
+all: bl31.axf
diff --git a/plat/arm/board/arm_fpga/rom_trampoline.S b/plat/arm/board/arm_fpga/rom_trampoline.S
new file mode 100644
index 0000000..cd66c79
--- /dev/null
+++ b/plat/arm/board/arm_fpga/rom_trampoline.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * The Arm Ltd. FPGA images start execution at address 0x0, which is
+ * mapped at an (emulated) ROM image. The payload uploader can write to
+ * this memory, but write access by the CPU cores is prohibited.
+ *
+ * Provide a simple trampoline to start BL31 execution at the actual
+ * load address. We put the DTB address in x0, so any code in DRAM could
+ * make use of that information (not yet used in BL31 right now).
+ */
+
+#include <asm_macros.S>
+#include <common/bl_common.ld.h>
+
+.text
+.global _start
+
+_start:
+ mov_imm x1, BL31_BASE /* beginning of DRAM */
+ mov_imm x0, FPGA_PRELOADED_DTB_BASE
+ br x1
diff --git a/plat/arm/board/common/aarch32/board_arm_helpers.S b/plat/arm/board/common/aarch32/board_arm_helpers.S
new file mode 100644
index 0000000..8c63693
--- /dev/null
+++ b/plat/arm/board/common/aarch32/board_arm_helpers.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <platform_def.h>
+
+ .globl plat_report_exception
+
+
+ /* -------------------------------------------------------
+ * void plat_report_exception(unsigned int type)
+ * Function to report an unhandled exception
+ * with platform-specific means.
+ * On FVP platform, it updates the LEDs
+ * to indicate where we are.
+ * SYS_LED[0] - 0x0
+ * SYS_LED[2:1] - 0x0
+ * SYS_LED[7:3] - Exception Mode.
+ * Clobbers: r0-r1
+ * -------------------------------------------------------
+ */
+func plat_report_exception
+ lsl r0, r0, #V2M_SYS_LED_EC_SHIFT
+ ldr r1, =V2M_SYSREGS_BASE
+ add r1, r1, #V2M_SYS_LED
+ str r0, [r1]
+ bx lr
+endfunc plat_report_exception
diff --git a/plat/arm/board/common/aarch64/board_arm_helpers.S b/plat/arm/board/common/aarch64/board_arm_helpers.S
new file mode 100644
index 0000000..cde6b00
--- /dev/null
+++ b/plat/arm/board/common/aarch64/board_arm_helpers.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <platform_def.h>
+
+ .globl plat_report_exception
+
+
+ /* ---------------------------------------------
+ * void plat_report_exception(unsigned int type)
+ * Function to report an unhandled exception
+ * with platform-specific means.
+ * On FVP platform, it updates the LEDs
+ * to indicate where we are
+ * ---------------------------------------------
+ */
+func plat_report_exception
+ mrs x1, CurrentEl
+ lsr x1, x1, #MODE_EL_SHIFT
+ lsl x1, x1, #V2M_SYS_LED_EL_SHIFT
+ lsl x0, x0, #V2M_SYS_LED_EC_SHIFT
+ mov x2, #(SECURE << V2M_SYS_LED_SS_SHIFT)
+ orr x0, x0, x2
+ orr x0, x0, x1
+ mov x1, #V2M_SYSREGS_BASE
+ add x1, x1, #V2M_SYS_LED
+ str w0, [x1]
+ ret
+endfunc plat_report_exception
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
new file mode 100644
index 0000000..714c444
--- /dev/null
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/arm/cryptocell/cc_rotpk.h>
+#include <drivers/delay_timer.h>
+#include <lib/cassert.h>
+#include <lib/fconf/fconf.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+#if defined(ARM_COT_cca)
+#include <tools_share/cca_oid.h>
+#elif defined(ARM_COT_dualroot)
+#include <tools_share/dualroot_oid.h>
+#elif defined(ARM_COT_tbbr)
+#include <tools_share/tbbr_oid.h>
+#endif
+
+#include <plat/arm/common/fconf_nv_cntr_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+#if !ARM_CRYPTOCELL_INTEG
+#if !ARM_ROTPK_LOCATION_ID
+ #error "ARM_ROTPK_LOCATION_ID not defined"
+#endif
+#endif
+
+#if COT_DESC_IN_DTB && defined(IMAGE_BL2)
+uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS];
+#else
+uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS] = {
+ TFW_NVCTR_BASE,
+ NTFW_CTR_BASE
+};
+#endif
+
+
+/* Weak definition may be overridden in specific platform */
+#pragma weak plat_get_nv_ctr
+#pragma weak plat_set_nv_ctr
+
+extern unsigned char arm_rotpk_header[], arm_rotpk_hash_end[];
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) || ARM_CRYPTOCELL_INTEG
+static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
+#endif
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+/*
+ * Return the ROTPK hash stored in dedicated registers.
+ */
+int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ uint8_t *dst;
+ uint32_t *src, tmp;
+ unsigned int words, i;
+
+ assert(key_ptr != NULL);
+ assert(key_len != NULL);
+ assert(flags != NULL);
+
+ /* Copy the DER header */
+
+ memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+ dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
+
+ words = ARM_ROTPK_HASH_LEN >> 2;
+
+ src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
+ for (i = 0 ; i < words ; i++) {
+ tmp = src[words - 1 - i];
+ /* Words are read in little endian */
+ *dst++ = (uint8_t)(tmp & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+ }
+
+ *key_ptr = (void *)rotpk_hash_der;
+ *key_len = (unsigned int)sizeof(rotpk_hash_der);
+ *flags = ROTPK_IS_HASH;
+ return 0;
+}
+#endif
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+ (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+/*
+ * Return development ROTPK hash generated from ROT_KEY.
+ */
+int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = arm_rotpk_header;
+ *key_len = arm_rotpk_hash_end - arm_rotpk_header;
+ *flags = ROTPK_IS_HASH;
+ return 0;
+}
+#endif
+
+#if ARM_CRYPTOCELL_INTEG
+/*
+ * Return ROTPK hash from CryptoCell.
+ */
+int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ unsigned char *dst;
+
+ assert(key_ptr != NULL);
+ assert(key_len != NULL);
+ assert(flags != NULL);
+
+ /* Copy the DER header */
+ memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+ dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
+ *key_ptr = rotpk_hash_der;
+ *key_len = sizeof(rotpk_hash_der);
+ return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags);
+}
+#endif
+
+/*
+ * Wrapper function for most Arm platforms to get ROTPK hash.
+ */
+static int get_rotpk_info(void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+#if ARM_CRYPTOCELL_INTEG
+ return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
+#else
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+ (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+ return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+ return arm_get_rotpk_info_regs(key_ptr, key_len, flags);
+#else
+ return 1;
+#endif
+#endif /* ARM_CRYPTOCELL_INTEG */
+}
+
+#if defined(ARM_COT_tbbr)
+
+int arm_get_rotpk_info(void *cookie __unused, void **key_ptr,
+ unsigned int *key_len, unsigned int *flags)
+{
+ return get_rotpk_info(key_ptr, key_len, flags);
+}
+
+#elif defined(ARM_COT_dualroot)
+
+int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ /*
+ * Return the right root of trust key hash based on the cookie value:
+ * - NULL means the primary ROTPK.
+ * - Otherwise, interpret cookie as the OID of the certificate
+ * extension containing the key.
+ */
+ if (cookie == NULL) {
+ return get_rotpk_info(key_ptr, key_len, flags);
+ } else if (strcmp(cookie, PROT_PK_OID) == 0) {
+ extern unsigned char arm_protpk_hash[];
+ extern unsigned char arm_protpk_hash_end[];
+ *key_ptr = arm_protpk_hash;
+ *key_len = arm_protpk_hash_end - arm_protpk_hash;
+ *flags = ROTPK_IS_HASH;
+ return 0;
+ } else {
+ /* Invalid key ID. */
+ return 1;
+ }
+}
+
+#elif defined(ARM_COT_cca)
+
+int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ /*
+ * Return the right root of trust key hash based on the cookie value:
+ * - NULL means the primary ROTPK.
+ * - Otherwise, interpret cookie as the OID of the certificate
+ * extension containing the key.
+ */
+ if (cookie == NULL) {
+ return get_rotpk_info(key_ptr, key_len, flags);
+ } else if (strcmp(cookie, PROT_PK_OID) == 0) {
+ extern unsigned char arm_protpk_hash[];
+ extern unsigned char arm_protpk_hash_end[];
+ *key_ptr = arm_protpk_hash;
+ *key_len = arm_protpk_hash_end - arm_protpk_hash;
+ *flags = ROTPK_IS_HASH;
+ return 0;
+ } else if (strcmp(cookie, SWD_ROT_PK_OID) == 0) {
+ extern unsigned char arm_swd_rotpk_hash[];
+ extern unsigned char arm_swd_rotpk_hash_end[];
+ *key_ptr = arm_swd_rotpk_hash;
+ *key_len = arm_swd_rotpk_hash_end - arm_swd_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+ return 0;
+ } else {
+ /* Invalid key ID. */
+ return 1;
+ }
+}
+
+#endif
+
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ const char *oid;
+ uint32_t *nv_ctr_addr;
+
+ assert(cookie != NULL);
+ assert(nv_ctr != NULL);
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ TRUSTED_NV_CTR_ID);
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = (uint32_t *)FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ NON_TRUSTED_NV_CTR_ID);
+ } else {
+ return 1;
+ }
+
+ *nv_ctr = (unsigned int)(*nv_ctr_addr);
+
+ return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. By default on ARM development
+ * platforms, the non-volatile counters are RO and cannot be modified. We expect
+ * the values in the certificates to always match the RO values so that this
+ * function is never called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
new file mode 100644
index 0000000..1d0eb13
--- /dev/null
+++ b/plat/arm/board/common/board_common.mk
@@ -0,0 +1,120 @@
+#
+# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_BL_COMMON_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \
+ plat/arm/board/common/${ARCH}/board_arm_helpers.S
+
+BL1_SOURCES += drivers/cfi/v2m/v2m_flash.c
+
+BL2_SOURCES += drivers/cfi/v2m/v2m_flash.c
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
+# ROTPK hash location
+ifeq (${ARM_ROTPK_LOCATION}, regs)
+ ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
+else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
+ CRYPTO_ALG=rsa
+ ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
+ ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin
+$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
+$(warning Development keys support for FVP is deprecated. Use `regs` \
+option instead)
+else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
+ CRYPTO_ALG=ec
+ ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
+ ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin
+$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
+$(warning Development keys support for FVP is deprecated. Use `regs` \
+option instead)
+else
+$(error "Unsupported ARM_ROTPK_LOCATION value")
+endif
+
+$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+
+ifeq (${ENABLE_RME}, 1)
+COT := cca
+endif
+
+# Force generation of the new hash if ROT_KEY is specified
+ifdef ROT_KEY
+ HASH_PREREQUISITES = $(ROT_KEY) FORCE
+else
+ HASH_PREREQUISITES = $(ROT_KEY)
+endif
+
+$(ARM_ROTPK_HASH) : $(HASH_PREREQUISITES)
+ifndef ROT_KEY
+ $(error Cannot generate hash: no ROT_KEY defined)
+endif
+ ${OPENSSL_BIN_PATH}/openssl ${CRYPTO_ALG} -in $< -pubout -outform DER | \
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@
+
+# Certificate NV-Counters. Use values corresponding to tied off values in
+# ARM development platforms
+TFW_NVCTR_VAL ?= 31
+NTFW_NVCTR_VAL ?= 223
+else
+# Certificate NV-Counters when CryptoCell is integrated. For development
+# platforms we set the counter to first valid value.
+TFW_NVCTR_VAL ?= 0
+NTFW_NVCTR_VAL ?= 0
+endif
+BL1_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \
+ plat/arm/board/common/rotpk/arm_dev_rotpk.S
+BL2_SOURCES += plat/arm/board/common/board_arm_trusted_boot.c \
+ plat/arm/board/common/rotpk/arm_dev_rotpk.S
+
+# Allows platform code to provide implementation variants depending on the
+# selected chain of trust.
+$(eval $(call add_define,ARM_COT_${COT}))
+
+ifeq (${COT},dualroot)
+# Platform Root of Trust key files.
+ARM_PROT_KEY := plat/arm/board/common/protpk/arm_protprivk_rsa.pem
+ARM_PROTPK_HASH := plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
+
+# Provide the private key to cert_create tool. It needs it to sign the images.
+PROT_KEY := ${ARM_PROT_KEY}
+
+$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"'))
+
+BL1_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S
+BL2_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S
+
+$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+endif
+
+ifeq (${COT},cca)
+# Platform and Secure World Root of Trust key files.
+ARM_PROT_KEY := plat/arm/board/common/protpk/arm_protprivk_rsa.pem
+ARM_PROTPK_HASH := plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin
+ARM_SWD_ROT_KEY := plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem
+ARM_SWD_ROTPK_HASH := plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin
+
+# Provide the private keys to cert_create tool. It needs them to sign the images.
+PROT_KEY := ${ARM_PROT_KEY}
+SWD_ROT_KEY := ${ARM_SWD_ROT_KEY}
+
+$(eval $(call add_define_val,ARM_PROTPK_HASH,'"$(ARM_PROTPK_HASH)"'))
+$(eval $(call add_define_val,ARM_SWD_ROTPK_HASH,'"$(ARM_SWD_ROTPK_HASH)"'))
+
+BL1_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S \
+ plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S
+BL2_SOURCES += plat/arm/board/common/protpk/arm_dev_protpk.S \
+ plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S
+
+$(BUILD_PLAT)/bl1/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+$(BUILD_PLAT)/bl1/arm_dev_swd_rotpk.o: $(ARM_SWD_ROTPK_HASH)
+$(BUILD_PLAT)/bl2/arm_dev_protpk.o: $(ARM_PROTPK_HASH)
+$(BUILD_PLAT)/bl2/arm_dev_swd_rotpk.o: $(ARM_SWD_ROTPK_HASH)
+endif
+
+endif
diff --git a/plat/arm/board/common/protpk/README b/plat/arm/board/common/protpk/README
new file mode 100644
index 0000000..3aca180
--- /dev/null
+++ b/plat/arm/board/common/protpk/README
@@ -0,0 +1,14 @@
+This directory contains some development keys to be used as the platform
+root-of-trust key.
+
+* arm_protprivk_rsa.pem is a 2K RSA private key in PEM format. It has been
+ generated using the openssl command line tool:
+
+ openssl genrsa 2048 > arm_protprivk_rsa.pem
+
+* arm_protpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key
+ associated with the above private key. It has been generated using the openssl
+ command line tool:
+
+ openssl rsa -in arm_protprivk_rsa.pem -pubout -outform DER | \
+ openssl dgst -sha256 -binary > arm_protpk_rsa_sha256.bin
diff --git a/plat/arm/board/common/protpk/arm_dev_protpk.S b/plat/arm/board/common/protpk/arm_dev_protpk.S
new file mode 100644
index 0000000..2688cbb
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_dev_protpk.S
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global arm_protpk_hash
+ .global arm_protpk_hash_end
+
+ .section .rodata.arm_protpk_hash, "a"
+
+arm_protpk_hash:
+ /* DER header. */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* Key hash. */
+ .incbin ARM_PROTPK_HASH
+arm_protpk_hash_end:
diff --git a/plat/arm/board/common/protpk/arm_protprivk_rsa.pem b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem
new file mode 100644
index 0000000..eeaad9e
--- /dev/null
+++ b/plat/arm/board/common/protpk/arm_protprivk_rsa.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAzR0h/Z4Up17wfuRlYrUWseGDmlGKpl1PflGiYbyVmI7PwTTp
+y/T77EiljGp52suLWntHsc0lee50pW16DU2c5bVfmyofau3GjJ1Yqw5XFAahr6eM
+/0mkN8utrevvcRT9CP07D+zdhb/WlRUAnedqr/AUHU8BXS+Bxe8P0Z0Z7+DKjYZp
+thzXxsjKM02BFFzNwyVrlyBFDkW/53A4M+dpmuWDjAGCJH88W/u0LdmLcii11IzD
+/Ofz8Jxc/ZhqL+9FFK4qU+AJp8yXAnACSB46DlNltJrode0y5tmPhtS37ZF7EFb8
+UZWwZVgtuQyuyz9RYUS6jtiGuq6s8GlRwjTe7wIDAQABAoIBAFoWIYeyln+sQxR4
+W88umfkmgxaUGcFX2kIwuJEUst9+WeERzF24C62LeqphWYOvQlVLMAH3iC41fSXr
+H2AYZoC9WHBd386nAD1iHj+C3Nv+zaTIgjTdszKOUonAxjl0bm40SmyELAdCaoyv
+3MV9jm4Xk74LpR24b9bvWJNH3MxttH9hiYS+n0IzeTXDfO8GrNvHh92zx+jo8yMm
+Khhu+TDC9jA2pHpJcF/0EXxYMhwYiQT16nnHb+xMgS4JpalQhvVK01s4VYGHRoFk
+K6xh4TIS336LDLyalrGsPlfNfEdx+DimShDIfBUx9Jp3Pp11TUQUz4rhIHB9WdfG
+b6bV4wECgYEA+cgPS2TQ7XQ1RJq1S7OGePtBXvnoH226KwGS6Fey8838tLxbblim
+MU+EOYs3O66V6U2YpzmIakXo8030k8thY+jKbZl3l0m/hMuPOG66hfE5i7dYsiP4
+atok5wFiNeNYYjHMEayzk53MhG8EOh36msAO7ohKmenONUBA7pk6yTkCgYEA0jhk
+HPshwi+wKkx+JLTnuoEgx40tkRgSF2xBqKssMTasaQmX8qG+w9CEs0R8nZCI70Vc
+tXSFcidjdkHUVE2WsygIFuS1tbsAnpaxtn3E6rjie30X/Z280+TV0HjR0EMETmwl
+ShC5lZ0oP3LpEZfjbR5qs2kFW4MOxA7tjQVaMWcCgYEA5ZbVMBifzdMl70RA5i9C
+qEtSQAl3KgRCvar5rKSHsX+iC0Kiy9+iCusq/3WONEZ6NvMDIJpKYFyYDaOW7o5f
+m2TrRChu+1lnN5mfsGBfBCTBH0JMvZlAin6ussLb0eqBX+ijyY8zlLjTttsQSJcr
+tThZwTj3UVfOGbZQuL+RgEkCgYBXO3U3nXI9vUIx2zoBC1yZRNoQVGITMlTXiWGZ
+lyYoadKTZ5q44Sti4BUguounaoGYIEU/OtHhM70PJnPwY53kS/lHXrKUbbvtEwU9
+f+UFraC1s4wP/rOLjgq3jlsqO5T+4dt7Z4NLNUKtSYazeT6zWgrW1f6WIcUv0C38
+9bqegwKBgFCK3Oa5ibL5sPaPQ/1UfdeW4JVuu6A4JhHS7r+cVLsmcrvE1Qv7Wcvw
+B5aqXeqLu2dtIN8/f++3tzccs9LXKY/fh72D4TVjfrqOSSZoGTH9l4U5NXbqWM3I
+skkAYb2bMST/d1qSyYesgXVNAlaQHRh3vEz8x853nJ3v9OFj8/rW
+-----END RSA PRIVATE KEY-----
diff --git a/plat/arm/board/common/rotpk/arm_dev_rotpk.S b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
new file mode 100644
index 0000000..06e2a06
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* corstone1000 platform provides custom values for the macros defined in
+ * arm_def.h , so only platform_def.h needs to be included
+ */
+#if !defined(TARGET_PLATFORM_FVP) && !defined(TARGET_PLATFORM_FPGA)
+#include "plat/arm/common/arm_def.h"
+#else
+#include <platform_def.h>
+#endif
+
+ .global arm_rotpk_header
+ .global arm_rotpk_header_end
+ .section .rodata.arm_rotpk_hash, "a"
+
+arm_rotpk_header:
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+arm_rotpk_header_len:
+
+#ifdef ARM_ROTPK_HASH
+ .global arm_rotpk_hash_end
+ .incbin ARM_ROTPK_HASH
+arm_rotpk_hash_end:
+#endif
+
+.if ARM_ROTPK_HEADER_LEN != arm_rotpk_header_len - arm_rotpk_header
+.error "Invalid ROTPK header length."
+.endif
diff --git a/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der
new file mode 100644
index 0000000..2547877
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der
Binary files differ
diff --git a/plat/arm/board/common/rotpk/arm_rotpk_rsa.der b/plat/arm/board/common/rotpk/arm_rotpk_rsa.der
new file mode 100644
index 0000000..661f899
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_rotpk_rsa.der
Binary files differ
diff --git a/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem b/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem
new file mode 100644
index 0000000..fb328e3
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEINSaX6nvzS3teiBJA7WlTLRKJOajpy29o2cArLbUXoZBoAoGCCqGSM49
+AwEHoUQDQgAEm+ZIvTQ44aKk83DhVLsvsFpKDP/Ch9vA+4Hp+fmVfX6gDH8K1OBi
+SpRf7FJ9RGPIn2H6xst+a1OtLMWUDRqGkQ==
+-----END EC PRIVATE KEY-----
diff --git a/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem b/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
new file mode 100644
index 0000000..71410ec
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLLGDVjWPUB3l+
+xxaWvU0kTqyG5rdx48VUC+cUHL0pGsE/erYCqqs2xNk2aWziZcObsb89qFYmy/0E
+AbqsPlQyynleu7IF6gZY8nS64fSHwBkKH2YHd4SDoRzv/yhZ58NofSYgQ+tWY/M5
+MdgrUam8T9D23pXcX1vB7ZBv7CiRfhfteJD0YKfEx09Q7V0TOiErcMVhewghZTrN
+glaMekesieilSEgx2R1G5YWGmKDlwKZqvQfkkldhB499Wk3Krja5VgQQ8my+9jts
+gD6+DqNNx9R+p0nU8tK8zzCo53SPZN+8XEdozEBM+IPMy0A1BGDKs6QXnwPKHVr6
+0a8hVxDTAgMBAAECggEAfwsc8ewbhDW4TwIGqfNtDUr0rtYN13VpqohW0ki2L8G/
+HQaKUViO/wxQFqoNn/OqQO0AfHmKhXAAokTCiXngBHJ/OjF7vB7+IRhazZEE6u2/
+uoivr/OYNQbFpXyTqsQ1eFzpPju6KKcPK7BzT4Mc89ek/vloFAi8w6LdMl8lbvOg
+LBWqX+5A+UQoenPUTvYM4U22YNcEAWubkpsYAmViiWiac+a+uPRk39aKyfOedDNu
++ty9MtCwekivoUTfP/1+O+jFlDnPMJUOEkBmcBqxseYYAHu7blBpdHxYpAItC2pv
+YwJJSvsE+HLBLPk177Jahg7sOUqcP0F/X+T65yuvIQKBgQDxdjXdJT5K8j7rG2fv
+2bvF2H1GPaHaTYRk0EGI2Ql6Nn+ddfeCE6gaT7aPPgg87wAhNu93coFuYHw0p/sc
+ZkXMJ+BmlstPV555cWXmwcxZLsni0fOXrt4YxwWkZwmh74m0NVM/cSFw56PU0oj1
+yDNeq3fgmsJocmuNTe1eG9qA7QKBgQDXaAGrNA5Xel5mqqMYTHHQWI6l2uzdNtt7
+eDn3K9+Eh3ywTqrwP845MAjKDU2Lq61I6t2H89dEifHq823VIcLCHd9BF04MrAH7
+qDPzrmPP2iB9g+YFmGBKe+K0HFE1t1KrTlo9VV6ZAC6RJNLAgwD4kvfIVYNkCGwe
++hoZBdhgvwKBgBrOsPQ4ak4PzwRzKnrqhXpVqrLdrNZ7vLMkm+IBlpfG7SwiKLR8
+UjF5oB8PGAML1cvaOYPdZplGhQOjkrF4eU9NLhC1tSS96Y46FMIlyfYsx6UzAgRZ
+GbdOgUXbWqpr2bH0KaXlfXz3eqzqIuKGs41TJB//jo3iBibN/AhytzORAoGAeGov
+5KDpE4XYl9Pz8HVremjG9Xh4yQENmOwQm1fvT4rd7UFM1ZkVk2qCv1DIdLe32vdQ
+d9ucDzh+ADWsxGRnF1TTpPN+Mh9FzISu5h4qtdreJsxBHgecbIbsqHrb+wdMM29N
+itPaWfV8Eq9fETcqp8qgsWD8XkNHDdoKFMrrtskCgYAoSt/Je1D3ZE/3HEjez7bq
+fenS3J6KG2SEn2PNFn+R0R5vBo4DaV/cQysKh44GD2+sh0QDyh6nuWJufyhPzROP
+DU6DCLbwNePj/yaGuzi36oLt6bBgfPWCiJY7jIdK8DmTLW25m7fRtCC5pxZlSzgl
+KBf7R6cbaTvaFe05Y2FJXA==
+-----END PRIVATE KEY-----
diff --git a/plat/arm/board/common/swd_rotpk/README b/plat/arm/board/common/swd_rotpk/README
new file mode 100644
index 0000000..b628a5f
--- /dev/null
+++ b/plat/arm/board/common/swd_rotpk/README
@@ -0,0 +1,14 @@
+This directory contains some development keys to be used as the secure world
+root-of-trust key used in the CCA chain of trust.
+
+* swd_rotprivk_rsa.pem is a 2K RSA private key in PEM format. It has been
+ generated using the openssl command line tool:
+
+ openssl genrsa 2048 > arm_swd_rotprivk_rsa.pem
+
+* swd_rotpk_rsa_sha256.bin is the SHA-256 hash of the DER-encoded public key
+ associated with the above private key. It has been generated using the openssl
+ command line tool:
+
+ openssl rsa -in arm_swd_rotprivk_rsa.pem -pubout -outform DER | \
+ openssl dgst -sha256 -binary > arm_swd_rotpk_rsa_sha256.bin
diff --git a/plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S b/plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S
new file mode 100644
index 0000000..ae4f9d2
--- /dev/null
+++ b/plat/arm/board/common/swd_rotpk/arm_dev_swd_rotpk.S
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global arm_swd_rotpk_hash
+ .global arm_swd_rotpk_hash_end
+
+ .section .rodata.arm_swd_rotpk_hash, "a"
+
+arm_swd_rotpk_hash:
+ /* DER header. */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* Key hash. */
+ .incbin ARM_SWD_ROTPK_HASH
+arm_swd_rotpk_hash_end:
diff --git a/plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin b/plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin
new file mode 100644
index 0000000..b2f3e60
--- /dev/null
+++ b/plat/arm/board/common/swd_rotpk/arm_swd_rotpk_rsa_sha256.bin
@@ -0,0 +1 @@
+0¾âà ’æœÈË“(ì¨0ŠwIÓÕéã¡gk \ No newline at end of file
diff --git a/plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem b/plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem
new file mode 100644
index 0000000..0de655d
--- /dev/null
+++ b/plat/arm/board/common/swd_rotpk/arm_swd_rotprivk_rsa.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA8igTd5QdZd181kz9vINr7Au34Rr/pQ1jpesfLlc1ZXCNAI9y
+/rhQlpw00y8rwOfgZsf18gPwGWWGhDJMsXI7OPem7BEUr8xKumuJuCiOdJh1STcR
+/JoFvz8wJPyycj/DOERRGsz+RvFBs6cLjSZHNQdzKDW+DE5vVJpmNWBVkoK7MCRD
+Wh/PMZVSoq9PeJOzayYcsipKvifT1+Wo9y2MG5zTDxi28rLr/FBm0CpTepBcRe8L
+pmgS7XJKhCQYxdDSzxi/0t/qXAwWuME4jv2HbNxsUZjahiBYpA0BafXanSuxVHly
+qpD0BmKAu7PpgKrEnUcPuHpZ2W+a05lNk6zjewIDAQABAoIBAG3twYCcTYgrtvs1
+8k38vyZl33CiKAGOhXkRtpL75fKJ2IizljmKBJOKj/R6ynsFCHrANadLIFj3HMyw
+ZN59A+OFkVJDIsf3jsj3/ooKZzkI6N120YSBizBZiAqSaJOy3HWTldn7y0b7SJ88
+quLFyLeLDTzowMCnbqTSfqmmdNJQAn+Q+7RX5sZGyBQUF2pRAA67cOYzc3a5MZ5E
+zBOs2u8VboC3ulEq876XWQbcXpRh/ap3eplQ1kAdyy64IPp2WbxqyXW0IQAQqaqh
+6oj19ME6mVD5wtELcYscJCDb7pA6WJtPp6nz/og2ifCJE/75T5RJ6fc6eBFMcofQ
+STIClGECgYEA/ZC0GX1HTKEKK3c1TiS3Zy0DS5ZoN5KFK7Sp1ZAjPE63iAr1a3z9
+Kepb+L8TBSw50tVD74MF5ChEid/ghF5BrVC3/YJkiiNpM1F51SMLGFeiDPRzJcx5
+KJkSflX7Q36BAXqj85Yz5AjgTPKcBqQRVZ6pNZN1HY99MloMg22WPRECgYEA9HtU
+FXmnTplXaNnihdq+vL5Z4/KDM+1f1E95y1PB8vkLI+o1szVNFP+BYz+w42lKtHW+
+c+z40AhFBGZQ0QCx83NOyObCReFjEbP8Nz71BsHe6GyMk9tSPIpzu9XB49Rs+9EO
+DAvFM5y2j5bH+lXE0pSyS3oBf51L9ZCPhp/vB8sCgYEAydwB1Gzsbu+hFfs/v2bx
+brzh67HgY6VMSP/5WF/3/RG5gB8hQ6HsNQsyjrMmZC7SFarb+3e2H+2CqrREm3wi
+EuS4pKPCgEoyfL03HVtZgNZ61o9gf83pAk3h8Bto/VFfSBsnHEsOIlKCph9Z4NuK
+RTwa/uDWEmNhyszvO03pldECgYEA2zB7GWnhc1mNgabfLY0JtuSeaPzzXqnyYcID
+eyUT3QglUcTY8lvWSP4ufdILgEfVP2fVIdAS30iawDAPQuLxqEf4Gayx/r7s+GE6
+vjlGqxFEDXPMsX9QApFK49voop/AOiCbDHe9DOHy11ei4TDmbrn8BClVkJlxEa/S
+ziszvfMCgYEA2V0zXziooI0toaOJEWZlAYhEONS5SG2z28HMLNgbdMcueGNhseaR
+NBGgPcu3EQhbL/hD0tBs09u6gjy1WD1i0HYnm1K1YQ1flzfbjUa3BqZETMbNhugd
+CM9yv0GEL/udZyOmO401aYl+QGXZX/WwlLQOe7WqQXOXJvW73oSqy7M=
+-----END RSA PRIVATE KEY-----
diff --git a/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
new file mode 100644
index 0000000..fe521a9
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+ .ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL,
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+ .next_handoff_image_id = BL32_IMAGE_ID,
+ },
+
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+ .ep_info.args.arg0 = CORSTONE1000_TOS_FW_CONFIG_BASE,
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /* Fill TOS_FW_CONFIG related information */
+ {
+ .image_id = TOS_FW_CONFIG_ID,
+ .image_info.image_base = CORSTONE1000_TOS_FW_CONFIG_BASE,
+ .image_info.image_max_size = (CORSTONE1000_TOS_FW_CONFIG_LIMIT -
+ CORSTONE1000_TOS_FW_CONFIG_BASE),
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+ .ep_info.pc = BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL33_BASE,
+ .image_info.image_max_size = BL33_LIMIT - BL33_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/arm/board/corstone1000/common/corstone1000_err.c b/plat/arm/board/corstone1000/common/corstone1000_err.c
new file mode 100644
index 0000000..376799f
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * corstone1000 error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (1) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/corstone1000/common/corstone1000_helpers.S b/plat/arm/board/corstone1000/common/corstone1000_helpers.S
new file mode 100644
index 0000000..cbe27c3
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_helpers.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_arm_calc_core_pos
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * For AArch32, cold-booting secondary CPUs is not yet
+ * implemented and they panic.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot. On corstone1000, this information can be queried from the power
+ * controller. The Power Control SYS Status Register (PSYSR) indicates
+ * the wake-up reason for the CPU.
+ *
+ * For a cold boot, return 0.
+ * For a warm boot, Not yet supported.
+ *
+ * TODO: PSYSR is a common register and should be
+ * accessed using locks. Since it is not possible
+ * to use locks immediately after a cold reset
+ * we are relying on the fact that after a cold
+ * reset all cpus will read the same WK field
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* TODO support warm boot */
+ /* Cold reset */
+ mov x0, #0
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current CPU is the primary
+ * CPU.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ mov_imm x1, MPIDR_AFFINITY_MASK
+ and x0, x0, x1
+ cmp x0, #CORSTONE1000_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c
new file mode 100644
index 0000000..0235f8b
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+
+#include <drivers/generic_delay_timer.h>
+#include <drivers/io/io_storage.h>
+#include <plat/common/platform.h>
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ ARM_MAP_NS_SHARED_RAM,
+ ARM_MAP_NS_DRAM1,
+ CORSTONE1000_MAP_DEVICE,
+ CORSTONE1000_EXTERNAL_FLASH,
+ {0}
+};
+
+static void set_fip_image_source(void)
+{
+ const struct plat_io_policy *policy;
+ /*
+ * metadata for firmware update is written at 0x0000 offset of the flash.
+ * PLAT_ARM_BOOT_BANK_FLAG contains the boot bank that TF-M is booted.
+ * As per firmware update spec, at a given point of time, only one bank
+ * is active. This means, TF-A should boot from the same bank as TF-M.
+ */
+ volatile uint32_t *boot_bank_flag = (uint32_t *)(PLAT_ARM_BOOT_BANK_FLAG);
+
+ if (*boot_bank_flag > 1) {
+ VERBOSE("Boot_bank is set higher than possible values");
+ }
+
+ VERBOSE("Boot bank flag = %u.\n\r", *boot_bank_flag);
+
+ policy = FCONF_GET_PROPERTY(arm, io_policies, FIP_IMAGE_ID);
+
+ assert(policy != NULL);
+ assert(policy->image_spec != 0UL);
+
+ io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
+
+ if ((*boot_bank_flag) == 0) {
+ VERBOSE("Booting from bank 0: fip offset = 0x%lx\n\r",
+ PLAT_ARM_FIP_BASE_BANK0);
+ spec->offset = PLAT_ARM_FIP_BASE_BANK0;
+ } else {
+ VERBOSE("Booting from bank 1: fip offset = 0x%lx\n\r",
+ PLAT_ARM_FIP_BASE_BANK1);
+ spec->offset = PLAT_ARM_FIP_BASE_BANK1;
+ }
+}
+
+void bl2_platform_setup(void)
+{
+ arm_bl2_platform_setup();
+ /*
+ * Identify the start address of the FIP by reading the boot
+ * index flag from the flash.
+ */
+ set_fip_image_source();
+}
+
+/* corstone1000 only has one always-on power domain and there
+ * is no power control present
+ */
+void __init plat_arm_pwrc_setup(void)
+{
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ /* Returning the Generic Timer Frequency */
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+
+/*
+ * Helper function to initialize ARM interconnect driver.
+ */
+void plat_arm_interconnect_init(void)
+{
+}
+
+/*
+ * Helper function to place current master into coherency
+ */
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/*
+ * Helper function to remove current master from coherency
+ */
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
+
+/*
+ * This function is invoked during Mbed TLS library initialisation to get a heap
+ * The function simply returns the default allocated heap.
+ */
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c
new file mode 100644
index 0000000..4b0a791
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+/*******************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+
+static void __dead2 corstone1000_system_reset(void)
+{
+
+ uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG;
+ uint32_t volatile * const watchdog_val_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_VAL_REG;
+
+ *(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL;
+ *watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE;
+ while (1) {
+ wfi();
+ }
+}
+
+plat_psci_ops_t plat_arm_psci_pm_ops = {
+ .system_reset = corstone1000_system_reset,
+ .validate_ns_entrypoint = NULL
+};
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ ops = &plat_arm_psci_pm_ops;
+ return ops;
+}
diff --git a/plat/arm/board/corstone1000/common/corstone1000_security.c b/plat/arm/board/corstone1000/common/corstone1000_security.c
new file mode 100644
index 0000000..c88201b
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_security.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * We assume that all security programming is done by the primary core.
+ */
+void plat_arm_security_setup(void)
+{
+ /*
+ * If the platform had additional peripheral specific security
+ * configurations, those would be configured here.
+ */
+}
diff --git a/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c b/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c
new file mode 100644
index 0000000..393235e
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+static uint32_t plat_generate_random_number(void)
+{
+ uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U);
+ uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U);
+ uint64_t cntpct = read_cntpct_el0();
+
+ /* Generate 32-bit pattern: saving the 2 least significant bytes
+ * in random_lo and random_hi
+ */
+ uint16_t random_lo = (uint16_t)(
+ (((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct
+ );
+
+ uint16_t random_hi = (uint16_t)(
+ (((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct
+ );
+
+ return (((uint32_t)random_hi) << 16) | random_lo;
+}
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ return plat_generate_random_number(); /* a 32-bit pattern returned */
+}
diff --git a/plat/arm/board/corstone1000/common/corstone1000_topology.c b/plat/arm/board/corstone1000/common/corstone1000_topology.c
new file mode 100644
index 0000000..5351896
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_topology.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* The corstone1000 power domain tree descriptor */
+static unsigned char corstone1000_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT
+ + 2];
+/*******************************************************************************
+ * This function dynamically constructs the topology according to
+ * CLUSTER_COUNT and returns it.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ int i;
+
+ /*
+ * The highest level is the system level. The next level is constituted
+ * by clusters and then cores in clusters.
+ */
+ corstone1000_power_domain_tree_desc[0] = 1;
+ corstone1000_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT;
+
+ for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++)
+ corstone1000_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT;
+
+ return corstone1000_power_domain_tree_desc;
+}
+
+/******************************************************************************
+ * This function implements a part of the critical interface between the PSCI
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is
+ * returned in case the MPIDR is invalid.
+ *****************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ return plat_arm_calc_core_pos(mpidr);
+}
diff --git a/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c b/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c
new file mode 100644
index 0000000..7e8fbb2
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ *
+ * The function returns 0 on success. Any other value is treated as error by the
+ * Trusted Board Boot. The function also reports extra information related
+ * to the ROTPK in the flags parameter: ROTPK_IS_HASH, ROTPK_NOT_DEPLOYED.
+ *
+ * Refer to the TF-A porting-guide document for more details.
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
+
+/*
+ * STUB overriding the non-volatile counter reading.
+ * NV counters are not implemented at this stage of development.
+ * Return: 0 = success
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = CORSTONE1000_FW_NVCTR_VAL;
+ return 0;
+}
+
+/*
+ * STUB overriding the non-volatile counter updating.
+ * NV counters are not implemented at this stage of development.
+ * Return: 0 = success
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 0;
+}
diff --git a/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts b/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts
new file mode 100644
index 0000000..8e49ab8
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ /*
+ * BL32 image details needed by SPMC
+ *
+ * Note:
+ * binary_size: size of BL32 + TOS_FW_CONFIG
+ */
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x1>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x2002000>;
+ entrypoint = <0x0 0x2002000>;
+ binary_size = <0xae000>;
+ };
+
+};
diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h
new file mode 100644
index 0000000..584d485
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/include/platform_def.h
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+
+#define ARM_ROTPK_HEADER_LEN 19
+#define ARM_ROTPK_HASH_LEN 32
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define ARM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978)
+
+/* PL011 UART related constants */
+#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ
+#undef V2M_IOFPGA_UART0_CLK_IN_HZ
+#endif
+
+#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ
+#undef V2M_IOFPGA_UART1_CLK_IN_HZ
+#endif
+
+#define V2M_IOFPGA_UART0_CLK_IN_HZ 50000000
+#define V2M_IOFPGA_UART1_CLK_IN_HZ 50000000
+
+/* Core/Cluster/Thread counts for corstone1000 */
+#define CORSTONE1000_CLUSTER_COUNT U(1)
+#define CORSTONE1000_MAX_CPUS_PER_CLUSTER U(4)
+#define CORSTONE1000_MAX_PE_PER_CPU U(1)
+#define CORSTONE1000_PRIMARY_CPU U(0)
+
+#define PLAT_ARM_CLUSTER_COUNT CORSTONE1000_CLUSTER_COUNT
+
+#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \
+ CORSTONE1000_MAX_CPUS_PER_CLUSTER * \
+ CORSTONE1000_MAX_PE_PER_CPU)
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE 0x1a510000
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
+#define PLAT_ARM_RUN_UART_BASE 0x1a520000
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+#define ARM_CONSOLE_BAUDRATE 115200
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+/* Memory related constants */
+
+/* SRAM (CVM) memory layout
+ *
+ * <ARM_TRUSTED_SRAM_BASE>
+ * partition size: sizeof(meminfo_t) = 16 bytes
+ * content: memory info area used by the next BL
+ *
+ * <ARM_FW_CONFIG_BASE>
+ * partition size: 4080 bytes
+ *
+ * <ARM_BL2_MEM_DESC_BASE>
+ * partition size: 4 KB
+ * content: Area where BL2 copies the images descriptors
+ *
+ * <ARM_BL_RAM_BASE> = <BL32_BASE>
+ * partition size: 688 KB
+ * content: BL32 (optee-os)
+ *
+ * <CORSTONE1000_TOS_FW_CONFIG_BASE> = 0x20ae000
+ * partition size: 8 KB
+ * content: BL32 config (TOS_FW_CONFIG)
+ *
+ * <BL31_BASE>
+ * partition size: 140 KB
+ * content: BL31
+ *
+ * <BL2_SIGNATURE_BASE>
+ * partition size: 4 KB
+ * content: MCUBOOT data needed to verify TF-A BL2
+ *
+ * <BL2_BASE>
+ * partition size: 176 KB
+ * content: BL2
+ *
+ * <ARM_NS_SHARED_RAM_BASE> = <ARM_TRUSTED_SRAM_BASE> + 1 MB
+ * partition size: 512 KB
+ * content: BL33 (u-boot)
+ */
+
+/* DDR memory */
+#define ARM_DRAM1_BASE UL(0x80000000)
+#define ARM_DRAM1_SIZE (SZ_2G) /* 2GB*/
+#define ARM_DRAM1_END (ARM_DRAM1_BASE + ARM_DRAM1_SIZE - 1)
+
+/* DRAM1 and DRAM2 are the same for corstone1000 */
+#define ARM_DRAM2_BASE ARM_DRAM1_BASE
+#define ARM_DRAM2_SIZE ARM_DRAM1_SIZE
+#define ARM_DRAM2_END ARM_DRAM1_END
+
+#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE
+#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE
+#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE - 1)
+
+/* The first 8 KB of Trusted SRAM are used as shared memory */
+#define ARM_TRUSTED_SRAM_BASE UL(0x02000000)
+#define ARM_SHARED_RAM_SIZE (SZ_8K) /* 8 KB */
+#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE
+
+/* The remaining Trusted SRAM is used to load the BL images */
+#define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */
+
+/* Last 512KB of CVM is allocated for shared RAM as an example openAMP */
+#define ARM_NS_SHARED_RAM_SIZE (512 * SZ_1K)
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \
+ ARM_NS_SHARED_RAM_SIZE - \
+ ARM_SHARED_RAM_SIZE)
+
+#define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */
+
+#define PLAT_ARM_MAX_BL31_SIZE (140 * SZ_1K) /* 140 KB */
+
+#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE)
+#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
+ ARM_SHARED_RAM_SIZE)
+
+#define BL2_SIGNATURE_SIZE (SZ_4K) /* 4 KB */
+
+#define BL2_SIGNATURE_BASE (BL2_LIMIT - PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_BASE (BL2_LIMIT - \
+ PLAT_ARM_MAX_BL2_SIZE + \
+ BL2_SIGNATURE_SIZE)
+#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+
+#define BL31_BASE (BL2_SIGNATURE_BASE - PLAT_ARM_MAX_BL31_SIZE)
+#define BL31_LIMIT BL2_SIGNATURE_BASE
+
+#define CORSTONE1000_TOS_FW_CONFIG_BASE (BL31_BASE - \
+ CORSTONE1000_TOS_FW_CONFIG_SIZE)
+#define CORSTONE1000_TOS_FW_CONFIG_SIZE (SZ_8K) /* 8 KB */
+#define CORSTONE1000_TOS_FW_CONFIG_LIMIT BL31_BASE
+
+#define BL32_BASE ARM_BL_RAM_BASE
+#define PLAT_ARM_MAX_BL32_SIZE (CORSTONE1000_TOS_FW_CONFIG_BASE - BL32_BASE)
+
+#define BL32_LIMIT (BL32_BASE + PLAT_ARM_MAX_BL32_SIZE)
+
+/* SPD_spmd settings */
+
+#define PLAT_ARM_SPMC_BASE BL32_BASE
+#define PLAT_ARM_SPMC_SIZE PLAT_ARM_MAX_BL32_SIZE
+
+/* NS memory */
+
+/* The last 512KB of the SRAM is allocated as shared memory */
+#define ARM_NS_SHARED_RAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SRAM_SIZE - \
+ (PLAT_ARM_MAX_BL31_SIZE + \
+ PLAT_ARM_MAX_BL32_SIZE))
+
+#define BL33_BASE ARM_DRAM1_BASE
+#define PLAT_ARM_MAX_BL33_SIZE (12 * SZ_1M) /* 12 MB*/
+#define BL33_LIMIT (ARM_DRAM1_BASE + PLAT_ARM_MAX_BL33_SIZE)
+
+/* end of the definition of SRAM memory layout */
+
+/* NOR Flash */
+
+#define PLAT_ARM_BOOT_BANK_FLAG UL(0x08002000)
+#define PLAT_ARM_FIP_BASE_BANK0 UL(0x081EF000)
+#define PLAT_ARM_FIP_BASE_BANK1 UL(0x0916F000)
+#define PLAT_ARM_FIP_MAX_SIZE UL(0x1ff000) /* 1.996 MB */
+
+#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE (SZ_32M) /* 32 MB */
+
+#define PLAT_ARM_FLASH_IMAGE_BASE PLAT_ARM_FIP_BASE_BANK0
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE PLAT_ARM_FIP_MAX_SIZE
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
+#define ARM_CACHE_WRITEBACK_SHIFT 6
+
+/*
+ * Define FW_CONFIG area base and limit. Leave enough space for BL2 meminfo.
+ * FW_CONFIG is intended to host the device tree. Currently, This area is not
+ * used because corstone1000 platform doesn't use a device tree at TF-A level.
+ */
+#define ARM_FW_CONFIG_BASE (ARM_SHARED_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT (ARM_SHARED_RAM_BASE + \
+ (ARM_SHARED_RAM_SIZE >> 1))
+
+/*
+ * Boot parameters passed from BL2 to BL31/BL32 are stored here
+ */
+#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT ARM_BL_RAM_BASE
+
+/*
+ * The max number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#define ARM_BL_REGIONS 3
+#define PLAT_ARM_MMAP_ENTRIES 8
+#define MAX_XLAT_TABLES 5
+#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + ARM_BL_REGIONS)
+#define MAX_IO_DEVICES 2
+#define MAX_IO_HANDLES 3
+#define MAX_IO_BLOCK_DEVICES 1
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE 0x1C010000
+#define PLAT_ARM_GICC_BASE 0x1C02F000
+
+/* MHUv2 Secure Channel receiver and sender */
+#define PLAT_SDK700_MHU0_SEND 0x1B800000
+#define PLAT_SDK700_MHU0_RECV 0x1B810000
+
+/* Timer/watchdog related constants */
+#define ARM_SYS_CNTCTL_BASE UL(0x1a200000)
+#define ARM_SYS_CNTREAD_BASE UL(0x1a210000)
+#define ARM_SYS_TIMCTL_BASE UL(0x1a220000)
+
+#define SECURE_WATCHDOG_ADDR_CTRL_REG 0x1A320000
+#define SECURE_WATCHDOG_ADDR_VAL_REG 0x1A320008
+#define SECURE_WATCHDOG_MASK_ENABLE 0x01
+#define SECURE_WATCHDOG_COUNTDOWN_VAL 0x1000
+
+#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */
+
+#define CORSTONE1000_IRQ_TZ_WDOG 32
+#define CORSTONE1000_IRQ_SEC_SYS_TIMER 34
+
+#define PLAT_MAX_PWR_LVL 2
+/*
+ * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The
+ * power levels have a 1:1 mapping with the MPIDR affinity levels.
+ */
+#define ARM_PWR_LVL0 MPIDR_AFFLVL0
+#define ARM_PWR_LVL1 MPIDR_AFFLVL1
+#define ARM_PWR_LVL2 MPIDR_AFFLVL2
+
+/*
+ * Macros for local power states in ARM platforms encoded by State-ID field
+ * within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define ARM_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define ARM_LOCAL_STATE_RET U(1)
+/* Local power state for OFF/power-down. Valid for CPU and cluster
+ * power domains
+ */
+#define ARM_LOCAL_STATE_OFF U(2)
+
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
+#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
+
+#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * ID will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+#define PLATFORM_STACK_SIZE UL(0x440)
+
+#define CORSTONE1000_EXTERNAL_FLASH MAP_REGION_FLAT( \
+ PLAT_ARM_NVM_BASE, \
+ PLAT_ARM_NVM_SIZE, \
+ MT_DEVICE | MT_RO | MT_SECURE)
+
+#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
+ ARM_SHARED_RAM_BASE, \
+ ARM_SHARED_RAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \
+ ARM_NS_SHARED_RAM_BASE, \
+ ARM_NS_SHARED_RAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
+ ARM_NS_DRAM1_BASE, \
+ ARM_NS_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ (BL_CODE_END - BL_CODE_BASE), \
+ MT_CODE | MT_SECURE), \
+ MAP_REGION_FLAT( \
+ BL_RO_DATA_BASE, \
+ (BL_RO_DATA_END - BL_RO_DATA_BASE), \
+ MT_RO_DATA | MT_SECURE)
+#if USE_COHERENT_MEM
+#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
+ BL_COHERENT_RAM_BASE, \
+ (BL_COHERENT_RAM_END \
+ - BL_COHERENT_RAM_BASE), \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+/*
+ * Map the region for the optional device tree configuration with read and
+ * write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT( \
+ ARM_FW_CONFIG_BASE, \
+ (ARM_FW_CONFIG_LIMIT \
+ - ARM_FW_CONFIG_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define CORSTONE1000_DEVICE_BASE (0x1A000000)
+#define CORSTONE1000_DEVICE_SIZE (0x26000000)
+#define CORSTONE1000_MAP_DEVICE MAP_REGION_FLAT( \
+ CORSTONE1000_DEVICE_BASE, \
+ CORSTONE1000_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE)
+
+#define ARM_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ ARM_G1S_IRQ_PROPS(grp), \
+ INTR_PROP_DESC(CORSTONE1000_IRQ_TZ_WDOG, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(CORSTONE1000_IRQ_SEC_SYS_TIMER, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/corstone1000/include/plat_macros.S b/plat/arm/board/corstone1000/include/plat_macros.S
new file mode 100644
index 0000000..9334201
--- /dev/null
+++ b/plat/arm/board/corstone1000/include/plat_macros.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <css_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ css_print_gic_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk
new file mode 100644
index 0000000..d891691
--- /dev/null
+++ b/plat/arm/board/corstone1000/platform.mk
@@ -0,0 +1,83 @@
+#
+# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Making sure the corstone1000 platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
+ $(error TARGET_PLATFORM must be fpga or fvp)
+endif
+
+CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a35.S
+
+PLAT_INCLUDES := -Iplat/arm/board/corstone1000/common/include \
+ -Iplat/arm/board/corstone1000/include \
+ -Iinclude/plat/arm/common \
+ -Iinclude/plat/arm/css/common/aarch64
+
+
+CORSTONE1000_FW_NVCTR_VAL := 255
+TFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL}
+NTFW_NVCTR_VAL := ${CORSTONE1000_FW_NVCTR_VAL}
+
+override NEED_BL1 := no
+
+override NEED_BL2 := yes
+FIP_BL2_ARGS := tb-fw
+
+override NEED_BL2U := no
+override NEED_BL31 := yes
+NEED_BL32 := yes
+override NEED_BL33 := yes
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+CORSTONE1000_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+
+
+BL2_SOURCES += plat/arm/board/corstone1000/common/corstone1000_security.c \
+ plat/arm/board/corstone1000/common/corstone1000_err.c \
+ plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c \
+ lib/utils/mem_region.c \
+ plat/arm/board/corstone1000/common/corstone1000_helpers.S \
+ plat/arm/board/corstone1000/common/corstone1000_plat.c \
+ plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c \
+ ${CORSTONE1000_CPU_LIBS} \
+
+
+BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/board/corstone1000/common/corstone1000_helpers.S \
+ plat/arm/board/corstone1000/common/corstone1000_topology.c \
+ plat/arm/board/corstone1000/common/corstone1000_security.c \
+ plat/arm/board/corstone1000/common/corstone1000_plat.c \
+ plat/arm/board/corstone1000/common/corstone1000_pm.c \
+ ${CORSTONE1000_CPU_LIBS} \
+ ${CORSTONE1000_GIC_SOURCES}
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+ ifneq (${ENABLE_STACK_PROTECTOR},none)
+ CORSTONE1000_SECURITY_SOURCES := plat/arm/board/corstone1000/common/corstone1000_stack_protector.c
+ BL2_SOURCES += ${CORSTONE1000_SECURITY_SOURCES}
+ BL31_SOURCES += ${CORSTONE1000_SECURITY_SOURCES}
+ endif
+endif
+
+FDT_SOURCES += plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts
+CORSTONE1000_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/corstone1000_spmc_manifest.dtb
+
+# Add the SPMC manifest to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE1000_TOS_FW_CONFIG},--tos-fw-config,${CORSTONE1000_TOS_FW_CONFIG}))
+
+# Adding TARGET_PLATFORM as a GCC define (-D option)
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
+# Adding CORSTONE1000_FW_NVCTR_VAL as a GCC define (-D option)
+$(eval $(call add_define,CORSTONE1000_FW_NVCTR_VAL))
+
+include plat/arm/common/arm_common.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/corstone700/common/corstone700_helpers.S b/plat/arm/board/corstone700/common/corstone700_helpers.S
new file mode 100644
index 0000000..c713f4f
--- /dev/null
+++ b/plat/arm/board/corstone700/common/corstone700_helpers.S
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_arm_calc_core_pos
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * For AArch32, cold-booting secondary CPUs is not yet
+ * implemented and they panic.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot. On Corstone700, this information can be queried from the power
+ * controller. The Power Control SYS Status Register (PSYSR) indicates
+ * the wake-up reason for the CPU.
+ *
+ * For a cold boot, return 0.
+ * For a warm boot, Not yet supported.
+ *
+ * TODO: PSYSR is a common register and should be
+ * accessed using locks. Since it is not possible
+ * to use locks immediately after a cold reset
+ * we are relying on the fact that after a cold
+ * reset all cpus will read the same WK field
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* TODO support warm boot */
+ /* Cold reset */
+ mov r0, #0
+ bx lr
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current CPU is the primary
+ * CPU.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ ldcopr r0, MPIDR
+ ldr r1, =MPIDR_AFFINITY_MASK
+ and r0, r1
+ cmp r0, #0
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+endfunc plat_is_my_cpu_primary
+
+ /* ---------------------------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Function to calculate the core position on Corstone700.
+ *
+ * (ClusterId * MAX_CPUS_PER_CLUSTER * MAX_PE_PER_CPU) +
+ * (CPUId * MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * MAX_CPUS_PER_CLUSTER + CPUId) * MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ mov r3, r0
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov r3, #CORSTONE700_MAX_CPUS_PER_CLUSTER
+ mla r1, r2, r3, r1
+ mov r3, #CORSTONE700_MAX_PE_PER_CPU
+ mla r0, r1, r3, r0
+
+ bx lr
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/corstone700/common/corstone700_plat.c b/plat/arm/board/corstone700/common/corstone700_plat.c
new file mode 100644
index 0000000..dd7531d
--- /dev/null
+++ b/plat/arm/board/corstone700/common/corstone700_plat.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+
+#include <corstone700_mhu.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ ARM_MAP_NS_SHARED_RAM,
+ ARM_MAP_NS_DRAM1,
+ CORSTONE700_MAP_DEVICE,
+ {0}
+};
+
+/* Corstone700 only has one always-on power domain and there
+ * is no power control present
+ */
+void __init plat_arm_pwrc_setup(void)
+{
+ mhu_secure_init();
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ /* Returning the Generic Timer Frequency */
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/arm/board/corstone700/common/corstone700_pm.c b/plat/arm/board/corstone700/common/corstone700_pm.c
new file mode 100644
index 0000000..4884ea5
--- /dev/null
+++ b/plat/arm/board/corstone700/common/corstone700_pm.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t plat_arm_psci_pm_ops = {
+ /* dummy struct */
+ .validate_ns_entrypoint = NULL
+};
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return ops;
+}
diff --git a/plat/arm/board/corstone700/common/corstone700_security.c b/plat/arm/board/corstone700/common/corstone700_security.c
new file mode 100644
index 0000000..39b2fc9
--- /dev/null
+++ b/plat/arm/board/corstone700/common/corstone700_security.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * We assume that all security programming is done by the primary core.
+ */
+void plat_arm_security_setup(void)
+{
+ /*
+ * If the platform had additional peripheral specific security
+ * configurations, those would be configured here.
+ */
+}
diff --git a/plat/arm/board/corstone700/common/corstone700_stack_protector.c b/plat/arm/board/corstone700/common/corstone700_stack_protector.c
new file mode 100644
index 0000000..6fd09da
--- /dev/null
+++ b/plat/arm/board/corstone700/common/corstone700_stack_protector.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+static uint32_t plat_generate_random_number(void)
+{
+ uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U);
+ uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U);
+ uint64_t cntpct = read_cntpct_el0();
+
+ /* Generate 32-bit pattern: saving the 2 least significant bytes
+ * in random_lo and random_hi
+ */
+ uint16_t random_lo = (uint16_t)(
+ (((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct
+ );
+
+ uint16_t random_hi = (uint16_t)(
+ (((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct
+ );
+
+ return (((uint32_t)random_hi) << 16) | random_lo;
+}
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ return plat_generate_random_number(); /* a 32-bit pattern is returned */
+}
diff --git a/plat/arm/board/corstone700/common/corstone700_topology.c b/plat/arm/board/corstone700/common/corstone700_topology.c
new file mode 100644
index 0000000..904f5ab
--- /dev/null
+++ b/plat/arm/board/corstone700/common/corstone700_topology.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* The Corstone700 power domain tree descriptor */
+static unsigned char corstone700_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT
+ + 2];
+/*******************************************************************************
+ * This function dynamically constructs the topology according to
+ * CLUSTER_COUNT and returns it.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ int i;
+
+ /*
+ * The highest level is the system level. The next level is constituted
+ * by clusters and then cores in clusters.
+ */
+ corstone700_power_domain_tree_desc[0] = 1;
+ corstone700_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT;
+
+ for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++)
+ corstone700_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT;
+
+ return corstone700_power_domain_tree_desc;
+}
+
+/******************************************************************************
+ * This function implements a part of the critical interface between the PSCI
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is
+ * returned in case the MPIDR is invalid.
+ *****************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ return plat_arm_calc_core_pos(mpidr);
+}
diff --git a/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c
new file mode 100644
index 0000000..832cfb7
--- /dev/null
+++ b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include "corstone700_mhu.h"
+#include <plat_arm.h>
+#include <platform_def.h>
+
+ARM_INSTANTIATE_LOCK;
+
+#pragma weak plat_arm_pwrc_setup
+
+/*
+ * Slot 31 is reserved because the MHU hardware uses this register bit to
+ * indicate a non-secure access attempt. The total number of available slots is
+ * therefore 31 [30:0].
+ */
+#define MHU_MAX_SLOT_ID 30
+
+void mhu_secure_message_start(uintptr_t address, unsigned int slot_id)
+{
+ unsigned int intr_stat_check;
+ uint64_t timeout_cnt;
+ volatile uint8_t expiration;
+
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+ arm_lock_get();
+
+ /*
+ * Make sure any previous command has finished
+ * and polling timeout not expired
+ */
+
+ timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
+
+ do {
+ intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) &
+ (1 << slot_id));
+
+ expiration = timeout_elapsed(timeout_cnt);
+
+ } while ((intr_stat_check != 0U) && (expiration == 0U));
+
+ /*
+ * Note: No risk of timer overflows while waiting
+ * for the timeout expiration.
+ * According to Armv8 TRM: System counter roll-over
+ * time of not less than 40 years
+ */
+}
+
+void mhu_secure_message_send(uintptr_t address,
+ unsigned int slot_id,
+ unsigned int message)
+{
+ unsigned char access_ready;
+ uint64_t timeout_cnt;
+ volatile uint8_t expiration;
+
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+ assert((mmio_read_32(address + CPU_INTR_S_STAT) &
+ (1 << slot_id)) == 0U);
+
+ MHU_V2_ACCESS_REQUEST(address);
+
+ timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
+
+ do {
+ access_ready = MHU_V2_IS_ACCESS_READY(address);
+ expiration = timeout_elapsed(timeout_cnt);
+
+ } while ((access_ready == 0U) && (expiration == 0U));
+
+ /*
+ * Note: No risk of timer overflows while waiting
+ * for the timeout expiration.
+ * According to Armv8 TRM: System counter roll-over
+ * time of not less than 40 years
+ */
+
+ mmio_write_32(address + CPU_INTR_S_SET, message);
+}
+
+void mhu_secure_message_end(uintptr_t address, unsigned int slot_id)
+{
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+ /*
+ * Clear any response we got by writing one in the relevant slot bit to
+ * the CLEAR register
+ */
+ MHU_V2_CLEAR_REQUEST(address);
+
+ arm_lock_release();
+}
+
+void __init mhu_secure_init(void)
+{
+ arm_lock_init();
+
+ /*
+ * The STAT register resets to zero. Ensure it is in the expected state,
+ * as a stale or garbage value would make us think it's a message we've
+ * already sent.
+ */
+
+ assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0);
+}
diff --git a/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.h b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.h
new file mode 100644
index 0000000..7f14ca5
--- /dev/null
+++ b/plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORSTONE700_MHU_H
+#define CORSTONE700_MHU_H
+
+#define MHU_POLL_INTR_STAT_TIMEOUT 50000 /*timeout value in us*/
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT 0x00
+#define CPU_INTR_S_SET 0x0C
+
+/* MHUv2 Control Registers Offsets */
+#define MHU_V2_MSG_CFG_OFFSET 0xF80
+#define MHU_V2_ACCESS_REQ_OFFSET 0xF88
+#define MHU_V2_ACCESS_READY_OFFSET 0xF8C
+
+#define MHU_V2_ACCESS_REQUEST(addr) \
+ mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1)
+
+#define MHU_V2_CLEAR_REQUEST(addr) \
+ mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0)
+
+#define MHU_V2_IS_ACCESS_READY(addr) \
+ (mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1)
+
+void mhu_secure_message_start(uintptr_t address, unsigned int slot_id);
+void mhu_secure_message_send(uintptr_t address,
+ unsigned int slot_id,
+ unsigned int message);
+void mhu_secure_message_end(uintptr_t address, unsigned int slot_id);
+void mhu_secure_init(void);
+
+#endif /* CORSTONE700_MHU_H */
diff --git a/plat/arm/board/corstone700/common/include/platform_def.h b/plat/arm/board/corstone700/common/include/platform_def.h
new file mode 100644
index 0000000..57b0551
--- /dev/null
+++ b/plat/arm/board/corstone700/common/include/platform_def.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+
+/* PL011 UART related constants */
+#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ
+#undef V2M_IOFPGA_UART0_CLK_IN_HZ
+#endif
+
+#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ
+#undef V2M_IOFPGA_UART1_CLK_IN_HZ
+#endif
+
+#define V2M_IOFPGA_UART0_CLK_IN_HZ 32000000
+#define V2M_IOFPGA_UART1_CLK_IN_HZ 32000000
+
+/* Core/Cluster/Thread counts for Corstone700 */
+#define CORSTONE700_CLUSTER_COUNT U(1)
+#define CORSTONE700_MAX_CPUS_PER_CLUSTER U(4)
+#define CORSTONE700_MAX_PE_PER_CPU U(1)
+
+#define PLAT_ARM_CLUSTER_COUNT CORSTONE700_CLUSTER_COUNT
+
+#define PLATFORM_CORE_COUNT (PLAT_ARM_CLUSTER_COUNT * \
+ CORSTONE700_MAX_CPUS_PER_CLUSTER * \
+ CORSTONE700_MAX_PE_PER_CPU)
+
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE 0x1a510000
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
+#define PLAT_ARM_RUN_UART_BASE 0x1a520000
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+#define ARM_CONSOLE_BAUDRATE 115200
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+/* Memory related constants */
+#define ARM_DRAM1_BASE UL(0x80000000)
+#define ARM_DRAM1_SIZE UL(0x80000000)
+#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
+ ARM_DRAM1_SIZE - 1)
+#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE
+#define ARM_NS_DRAM1_SIZE ARM_DRAM1_SIZE
+#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \
+ ARM_NS_DRAM1_SIZE - 1)
+#define ARM_TRUSTED_SRAM_BASE UL(0x02000000)
+#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE
+#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
+#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 KB */
+
+/* The remaining Trusted SRAM is used to load the BL images */
+#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + \
+ ARM_SHARED_RAM_SIZE)
+#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
+ ARM_SHARED_RAM_SIZE)
+
+#define ARM_NS_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE + UL(0x00100000)
+#define ARM_NS_SHARED_RAM_SIZE 0x00300000
+
+/*
+ * SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
+ * the page reserved for fw_configs) to BL32
+ */
+#define BL32_BASE (ARM_BL_RAM_BASE + PAGE_SIZE)
+#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
+#define ARM_CACHE_WRITEBACK_SHIFT 6
+
+/*
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
+ * and limit. Leave enough space for BL2 meminfo.
+ */
+#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
+
+/*
+ * Boot parameters passed from BL2 to BL31/BL32 are stored here
+ */
+#define ARM_BL2_MEM_DESC_BASE (ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
+ + (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
+/*
+ * The max number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#define ARM_BL_REGIONS 3
+#define PLAT_ARM_MMAP_ENTRIES 8
+#define MAX_XLAT_TABLES 5
+#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
+ ARM_BL_REGIONS)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE 0x1C010000
+#define PLAT_ARM_GICC_BASE 0x1C02F000
+
+/* MHUv2 Secure Channel receiver and sender */
+#define PLAT_SDK700_MHU0_SEND 0x1B800000
+#define PLAT_SDK700_MHU0_RECV 0x1B810000
+
+/* Timer/watchdog related constants */
+#define ARM_SYS_CNTCTL_BASE UL(0x1a200000)
+#define ARM_SYS_CNTREAD_BASE UL(0x1a210000)
+#define ARM_SYS_TIMCTL_BASE UL(0x1a220000)
+
+#ifdef TARGET_PLATFORM_FVP
+#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */
+#else
+#define SYS_COUNTER_FREQ_IN_TICKS UL(32000000) /* 32MHz */
+#endif
+
+#define CORSTONE700_IRQ_TZ_WDOG 32
+#define CORSTONE700_IRQ_SEC_SYS_TIMER 34
+
+#define PLAT_MAX_PWR_LVL 2
+/*
+ * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The
+ * power levels have a 1:1 mapping with the MPIDR affinity levels.
+ */
+#define ARM_PWR_LVL0 MPIDR_AFFLVL0
+#define ARM_PWR_LVL1 MPIDR_AFFLVL1
+#define ARM_PWR_LVL2 MPIDR_AFFLVL2
+
+/*
+ * Macros for local power states in ARM platforms encoded by State-ID field
+ * within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define ARM_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define ARM_LOCAL_STATE_RET U(1)
+/* Local power state for OFF/power-down. Valid for CPU and cluster
+ * power domains
+ */
+#define ARM_LOCAL_STATE_OFF U(2)
+
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
+#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
+
+#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * ID will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+#define PLATFORM_STACK_SIZE UL(0x440)
+
+#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
+ ARM_SHARED_RAM_BASE, \
+ ARM_SHARED_RAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \
+ ARM_NS_SHARED_RAM_BASE, \
+ ARM_NS_SHARED_RAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
+ ARM_NS_DRAM1_BASE, \
+ ARM_NS_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL_CODE_END \
+ - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE), \
+ MAP_REGION_FLAT( \
+ BL_RO_DATA_BASE, \
+ BL_RO_DATA_END \
+ - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+#if USE_COHERENT_MEM
+#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
+ BL_COHERENT_RAM_BASE, \
+ BL_COHERENT_RAM_END \
+ - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
+ (ARM_FW_CONFIGS_LIMIT \
+ - ARM_BL_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define CORSTONE700_DEVICE_BASE (0x1A000000)
+#define CORSTONE700_DEVICE_SIZE (0x26000000)
+#define CORSTONE700_MAP_DEVICE MAP_REGION_FLAT( \
+ CORSTONE700_DEVICE_BASE,\
+ CORSTONE700_DEVICE_SIZE,\
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_EDGE)
+
+#define ARM_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ ARM_G1S_IRQ_PROPS(grp), \
+ INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(CORSTONE700_IRQ_SEC_SYS_TIMER, \
+ GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
new file mode 100644
index 0000000..75833f6
--- /dev/null
+++ b/plat/arm/board/corstone700/platform.mk
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Making sure the corstone700 platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
+ $(error TARGET_PLATFORM must be fpga or fvp)
+endif
+
+CORSTONE700_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S
+
+BL32_SOURCES += plat/arm/common/aarch32/arm_helpers.S \
+ plat/arm/common/arm_console.c \
+ plat/arm/common/arm_common.c \
+ lib/xlat_tables/aarch32/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ ${CORSTONE700_CPU_LIBS} \
+ plat/arm/board/corstone700/common/drivers/mhu/corstone700_mhu.c
+
+PLAT_INCLUDES := -Iplat/arm/board/corstone700/common/include \
+ -Iinclude/plat/arm/common \
+ -Iplat/arm/board/corstone700/common/drivers/mhu
+
+NEED_BL32 := yes
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+CORSTONE700_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+
+# BL1/BL2 Image not a part of the capsule Image for Corstone700
+override NEED_BL1 := no
+override NEED_BL2 := no
+override NEED_BL2U := no
+override NEED_BL33 := yes
+
+#TFA for Corstone700 starts from BL32
+override RESET_TO_SP_MIN := 1
+
+#Device tree
+CORSTONE700_HW_CONFIG_DTS := fdts/corstone700_${TARGET_PLATFORM}.dts
+CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/fdts/corstone700_${TARGET_PLATFORM}.dtb
+FDT_SOURCES += ${CORSTONE700_HW_CONFIG_DTS}
+$(eval CORSTONE700_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(CORSTONE700_HW_CONFIG_DTS)))
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${CORSTONE700_HW_CONFIG},--hw-config,${CORSTONE700_HW_CONFIG}))
+
+# Check for Linux kernel as a BL33 image by default
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
+ ifndef ARM_PRELOADED_DTB_BASE
+ $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
+ endif
+ $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
+# Adding TARGET_PLATFORM as a GCC define (-D option)
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c b/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c
new file mode 100644
index 0000000..2fc0e0d
--- /dev/null
+++ b/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+}
diff --git a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
new file mode 100644
index 0000000..75dc0f1
--- /dev/null
+++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SP_MIN source files specific to FVP platform
+BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/board/corstone700/common/corstone700_helpers.S \
+ plat/arm/board/corstone700/common/corstone700_topology.c \
+ plat/arm/board/corstone700/common/corstone700_security.c \
+ plat/arm/board/corstone700/common/corstone700_plat.c \
+ plat/arm/board/corstone700/common/corstone700_pm.c \
+ plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c \
+ ${CORSTONE700_GIC_SOURCES}
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+ ifneq (${ENABLE_STACK_PROTECTOR},none)
+ BL32_SOURCES += plat/arm/board/corstone700/common/corstone700_stack_protector.c
+ endif
+endif
+
+include plat/arm/common/sp_min/arm_sp_min.mk
diff --git a/plat/arm/board/fvp/aarch32/fvp_helpers.S b/plat/arm/board/fvp/aarch32/fvp_helpers.S
new file mode 100644
index 0000000..9985c1d
--- /dev/null
+++ b/plat/arm/board/fvp/aarch32/fvp_helpers.S
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_arm_calc_core_pos
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * For AArch32, cold-booting secondary CPUs is not yet
+ * implemented and they panic.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot. On FVP, this information can be queried from the power
+ * controller. The Power Control SYS Status Register (PSYSR) indicates
+ * the wake-up reason for the CPU.
+ *
+ * For a cold boot, return 0.
+ * For a warm boot, read the mailbox and return the address it contains.
+ *
+ * TODO: PSYSR is a common register and should be
+ * accessed using locks. Since it is not possible
+ * to use locks immediately after a cold reset
+ * we are relying on the fact that after a cold
+ * reset all cpus will read the same WK field
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* ---------------------------------------------------------------------
+ * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
+ * WakeRequest signal" then it is a warm boot.
+ * ---------------------------------------------------------------------
+ */
+ ldcopr r2, MPIDR
+ ldr r1, =PWRC_BASE
+ str r2, [r1, #PSYSR_OFF]
+ ldr r2, [r1, #PSYSR_OFF]
+ ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
+ cmp r2, #WKUP_PPONR
+ beq warm_reset
+ cmp r2, #WKUP_GICREQ
+ beq warm_reset
+
+ /* Cold reset */
+ mov r0, #0
+ bx lr
+
+warm_reset:
+ /* ---------------------------------------------------------------------
+ * A mailbox is maintained in the trusted SRAM. It is flushed out of the
+ * caches after every update using normal memory so it is safe to read
+ * it here with SO attributes.
+ * ---------------------------------------------------------------------
+ */
+ ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr r0, [r0]
+ cmp r0, #0
+ beq _panic
+ bx lr
+
+ /* ---------------------------------------------------------------------
+ * The power controller indicates this is a warm reset but the mailbox
+ * is empty. This should never happen!
+ * ---------------------------------------------------------------------
+ */
+_panic:
+ b _panic
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ ldcopr r0, MPIDR
+ ldr r1, =MPIDR_AFFINITY_MASK
+ and r0, r1
+ cmp r0, #FVP_PRIMARY_CPU
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+endfunc plat_is_my_cpu_primary
+
+ /* ---------------------------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Function to calculate the core position on FVP.
+ *
+ * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
+ * (CPUId * FVP_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ mov r3, r0
+
+ /*
+ * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+ * look as if in a multi-threaded implementation
+ */
+ tst r0, #MPIDR_MT_MASK
+ lsleq r3, r0, #MPIDR_AFFINITY_BITS
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov r3, #FVP_MAX_CPUS_PER_CLUSTER
+ mla r1, r2, r3, r1
+ mov r3, #FVP_MAX_PE_PER_CPU
+ mla r0, r1, r3, r0
+
+ bx lr
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/fvp/aarch64/fvp_helpers.S b/plat/arm/board/fvp/aarch64/fvp_helpers.S
new file mode 100644
index 0000000..8efc238
--- /dev/null
+++ b/plat/arm/board/fvp/aarch64/fvp_helpers.S
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_arm_calc_core_pos
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * TODO: Should we read the PSYS register to make sure
+ * that the request has gone through.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+#ifndef EL3_PAYLOAD_BASE
+ /* ---------------------------------------------
+ * Power down this cpu.
+ * TODO: Do we need to worry about powering the
+ * cluster down as well here. That will need
+ * locks which we won't have unless an elf-
+ * loader zeroes out the zi section.
+ * ---------------------------------------------
+ */
+ mrs x0, mpidr_el1
+ mov_imm x1, PWRC_BASE
+ str w0, [x1, #PPOFFR_OFF]
+
+ /* ---------------------------------------------
+ * There is no sane reason to come out of this
+ * wfi so panic if we do. This cpu will be pow-
+ * ered on and reset by the cpu_on pm api
+ * ---------------------------------------------
+ */
+ dsb sy
+ wfi
+ no_ret plat_panic_handler
+#else
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+
+ /* Wait until the entrypoint gets populated */
+poll_mailbox:
+ ldr x1, [x0]
+ cbz x1, 1f
+ br x1
+1:
+ wfe
+ b poll_mailbox
+#endif /* EL3_PAYLOAD_BASE */
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot. On FVP, this information can be queried from the power
+ * controller. The Power Control SYS Status Register (PSYSR) indicates
+ * the wake-up reason for the CPU.
+ *
+ * For a cold boot, return 0.
+ * For a warm boot, read the mailbox and return the address it contains.
+ *
+ * TODO: PSYSR is a common register and should be
+ * accessed using locks. Since it is not possible
+ * to use locks immediately after a cold reset
+ * we are relying on the fact that after a cold
+ * reset all cpus will read the same WK field
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* ---------------------------------------------------------------------
+ * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
+ * WakeRequest signal" then it is a warm boot.
+ * ---------------------------------------------------------------------
+ */
+ mrs x2, mpidr_el1
+ mov_imm x1, PWRC_BASE
+ str w2, [x1, #PSYSR_OFF]
+ ldr w2, [x1, #PSYSR_OFF]
+ ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
+ cmp w2, #WKUP_PPONR
+ beq warm_reset
+ cmp w2, #WKUP_GICREQ
+ beq warm_reset
+
+ /* Cold reset */
+ mov x0, #0
+ ret
+
+warm_reset:
+ /* ---------------------------------------------------------------------
+ * A mailbox is maintained in the trusted SRAM. It is flushed out of the
+ * caches after every update using normal memory so it is safe to read
+ * it here with SO attributes.
+ * ---------------------------------------------------------------------
+ */
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr x0, [x0]
+ cbz x0, _panic_handler
+ ret
+
+ /* ---------------------------------------------------------------------
+ * The power controller indicates this is a warm reset but the mailbox
+ * is empty. This should never happen!
+ * ---------------------------------------------------------------------
+ */
+_panic_handler:
+ no_ret plat_panic_handler
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ mov_imm x1, MPIDR_AFFINITY_MASK
+ and x0, x0, x1
+ cmp x0, #FVP_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* ---------------------------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Function to calculate the core position on FVP.
+ *
+ * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
+ * (CPUId * FVP_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ /*
+ * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+ * look as if in a multi-threaded implementation.
+ */
+ tst x0, #MPIDR_MT_MASK
+ lsl x3, x0, #MPIDR_AFFINITY_BITS
+ csel x3, x3, x0, eq
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x4, #FVP_MAX_CPUS_PER_CLUSTER
+ madd x1, x2, x4, x1
+ mov x5, #FVP_MAX_PE_PER_CPU
+ madd x0, x1, x5, x0
+ ret
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/fvp/aarch64/fvp_ras.c b/plat/arm/board/fvp/aarch64/fvp_ras.c
new file mode 100644
index 0000000..759f6d0
--- /dev/null
+++ b/plat/arm/board/fvp/aarch64/fvp_ras.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/extensions/ras.h>
+
+struct ras_interrupt fvp_ras_interrupts[] = {
+};
+
+struct err_record_info fvp_err_records[] = {
+};
+
+REGISTER_ERR_RECORD_INFO(fvp_err_records);
+REGISTER_RAS_INTERRUPTS(fvp_ras_interrupts);
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
new file mode 100644
index 0000000..45e3b7e
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <fconf_hw_config_getter.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+
+struct gicv3_config_t gicv3_config;
+struct hw_topology_t soc_topology;
+struct uart_serial_config_t uart_serial_config;
+struct cpu_timer_t cpu_timer;
+
+#define ILLEGAL_ADDR ULL(~0)
+
+int fconf_populate_gicv3_config(uintptr_t config)
+{
+ int err;
+ int node;
+ uintptr_t addr;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ /*
+ * Find the offset of the node containing "arm,gic-v3" compatible property.
+ * Populating fconf strucutures dynamically is not supported for legacy
+ * systems which use GICv2 IP. Simply skip extracting GIC properties.
+ */
+ node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
+ if (node < 0) {
+ WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n");
+ return 0;
+ }
+ /* The GICv3 DT binding holds at least two address/size pairs,
+ * the first describing the distributor, the second the redistributors.
+ * See: bindings/interrupt-controller/arm,gic-v3.yaml
+ */
+ err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
+ if (err < 0) {
+ ERROR("FCONF: Failed to read GICD reg property of GIC node\n");
+ return err;
+ }
+ gicv3_config.gicd_base = addr;
+
+ err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
+ if (err < 0) {
+ ERROR("FCONF: Failed to read GICR reg property of GIC node\n");
+ } else {
+ gicv3_config.gicr_base = addr;
+ }
+
+ return err;
+}
+
+int fconf_populate_topology(uintptr_t config)
+{
+ int err, node, cluster_node, core_node, thread_node;
+ uint32_t cluster_count = 0, max_cpu_per_cluster = 0, total_cpu_count = 0;
+ uint32_t max_pwr_lvl = 0;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ /* Find the offset of the node containing "arm,psci-1.0" compatible property */
+ node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,psci-1.0");
+ if (node < 0) {
+ ERROR("FCONF: Unable to locate node with arm,psci-1.0 compatible property\n");
+ return node;
+ }
+
+ err = fdt_read_uint32(hw_config_dtb, node, "max-pwr-lvl", &max_pwr_lvl);
+ if (err < 0) {
+ /*
+ * Some legacy FVP dts may not have this property. Assign the default
+ * value.
+ */
+ WARN("FCONF: Could not locate max-pwr-lvl property\n");
+ max_pwr_lvl = 2;
+ }
+
+ assert(max_pwr_lvl <= MPIDR_AFFLVL2);
+
+ /* Find the offset of the "cpus" node */
+ node = fdt_path_offset(hw_config_dtb, "/cpus");
+ if (node < 0) {
+ ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpus");
+ return node;
+ }
+
+ /* A typical cpu-map node in a device tree is shown here for reference
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+ core1 {
+ cpu = <&CPU1>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&CPU2>;
+ };
+ core1 {
+ cpu = <&CPU3>;
+ };
+ };
+ };
+ */
+
+ /* Locate the cpu-map child node */
+ node = fdt_subnode_offset(hw_config_dtb, node, "cpu-map");
+ if (node < 0) {
+ ERROR("FCONF: Node '%s' not found in hardware configuration dtb\n", "cpu-map");
+ return node;
+ }
+
+ uint32_t cpus_per_cluster[PLAT_ARM_CLUSTER_COUNT] = {0};
+
+ /* Iterate through cluster nodes */
+ fdt_for_each_subnode(cluster_node, hw_config_dtb, node) {
+ assert(cluster_count < PLAT_ARM_CLUSTER_COUNT);
+
+ /* Iterate through core nodes */
+ fdt_for_each_subnode(core_node, hw_config_dtb, cluster_node) {
+ /* core nodes may have child nodes i.e., "thread" nodes */
+ if (fdt_first_subnode(hw_config_dtb, core_node) < 0) {
+ cpus_per_cluster[cluster_count]++;
+ } else {
+ /* Multi-threaded CPU description is found in dtb */
+ fdt_for_each_subnode(thread_node, hw_config_dtb, core_node) {
+ cpus_per_cluster[cluster_count]++;
+ }
+
+ /* Since in some dtbs, core nodes may not have thread node,
+ * no need to error if even one child node is not found.
+ */
+ }
+ }
+
+ /* Ensure every cluster node has at least 1 child node */
+ if (cpus_per_cluster[cluster_count] < 1U) {
+ ERROR("FCONF: Unable to locate the core node in cluster %d\n", cluster_count);
+ return -1;
+ }
+
+ VERBOSE("CLUSTER ID: %d cpu-count: %d\n", cluster_count,
+ cpus_per_cluster[cluster_count]);
+
+ /* Find the maximum number of cpus in any cluster */
+ max_cpu_per_cluster = MAX(max_cpu_per_cluster, cpus_per_cluster[cluster_count]);
+ total_cpu_count += cpus_per_cluster[cluster_count];
+ cluster_count++;
+ }
+
+
+ /* At least one cluster node is expected in hardware configuration dtb */
+ if (cluster_count < 1U) {
+ ERROR("FCONF: Unable to locate the cluster node in cpu-map node\n");
+ return -1;
+ }
+
+ soc_topology.plat_max_pwr_level = max_pwr_lvl;
+ soc_topology.plat_cluster_count = cluster_count;
+ soc_topology.cluster_cpu_count = max_cpu_per_cluster;
+ soc_topology.plat_cpu_count = total_cpu_count;
+
+ return 0;
+}
+
+int fconf_populate_uart_config(uintptr_t config)
+{
+ int uart_node, node, err;
+ uintptr_t addr;
+ const char *path;
+ uint32_t phandle;
+ uint64_t translated_addr;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ /*
+ * uart child node is indirectly referenced through its path which is
+ * specified in the `serial1` property of the "aliases" node.
+ * Note that TF-A boot console is mapped to serial0 while runtime
+ * console is mapped to serial1.
+ */
+
+ path = fdt_get_alias(hw_config_dtb, "serial1");
+ if (path == NULL) {
+ ERROR("FCONF: Could not read serial1 property in aliases node\n");
+ return -1;
+ }
+
+ /* Find the offset of the uart serial node */
+ uart_node = fdt_path_offset(hw_config_dtb, path);
+ if (uart_node < 0) {
+ ERROR("FCONF: Failed to locate uart serial node using its path\n");
+ return -1;
+ }
+
+ /* uart serial node has its offset and size of address in reg property */
+ err = fdt_get_reg_props_by_index(hw_config_dtb, uart_node, 0, &addr,
+ NULL);
+ if (err < 0) {
+ ERROR("FCONF: Failed to read reg property of '%s' node\n",
+ "uart serial");
+ return err;
+ }
+ VERBOSE("FCONF: UART node address: %lx\n", addr);
+
+ /*
+ * Perform address translation of local device address to CPU address
+ * domain.
+ */
+ translated_addr = fdtw_translate_address(hw_config_dtb,
+ uart_node, (uint64_t)addr);
+ if (translated_addr == ILLEGAL_ADDR) {
+ ERROR("FCONF: failed to translate UART node base address");
+ return -1;
+ }
+
+ uart_serial_config.uart_base = translated_addr;
+
+ VERBOSE("FCONF: UART serial device base address: %" PRIx64 "\n",
+ uart_serial_config.uart_base);
+
+ /*
+ * The phandle of the DT node which captures the clock info of uart
+ * serial node is specified in the "clocks" property.
+ */
+ err = fdt_read_uint32(hw_config_dtb, uart_node, "clocks", &phandle);
+ if (err < 0) {
+ ERROR("FCONF: Could not read clocks property in uart serial node\n");
+ return err;
+ }
+
+ node = fdt_node_offset_by_phandle(hw_config_dtb, phandle);
+ if (node < 0) {
+ ERROR("FCONF: Failed to locate clk node using its path\n");
+ return node;
+ }
+
+ /*
+ * Retrieve clock frequency. We assume clock provider generates a fixed
+ * clock.
+ */
+ err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency",
+ &uart_serial_config.uart_clk);
+ if (err < 0) {
+ ERROR("FCONF: Could not read clock-frequency property in clk node\n");
+ return err;
+ }
+
+ VERBOSE("FCONF: UART serial device clk frequency: %x\n",
+ uart_serial_config.uart_clk);
+
+ return 0;
+}
+
+int fconf_populate_cpu_timer(uintptr_t config)
+{
+ int err, node;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ /* Find the node offset point to "arm,armv8-timer" compatible property,
+ * a per-core architected timer attached to a GIC to deliver its per-processor
+ * interrupts via PPIs */
+ node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,armv8-timer");
+ if (node < 0) {
+ ERROR("FCONF: Unrecognized hardware configuration dtb (%d)\n", node);
+ return node;
+ }
+
+ /* Locate the cell holding the clock-frequency, an optional field */
+ err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", &cpu_timer.clock_freq);
+ if (err < 0) {
+ WARN("FCONF failed to read clock-frequency property\n");
+ }
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
diff --git a/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
new file mode 100644
index 0000000..e258015
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+
+#include <libfdt.h>
+#include <fconf_nt_config_getter.h>
+
+#include <plat/common/platform.h>
+
+struct event_log_config_t event_log_config;
+
+int fconf_populate_event_log_config(uintptr_t config)
+{
+ int err;
+ int node;
+
+ /* Necessary to work with libfdt APIs */
+ const void *dtb = (const void *)config;
+
+ /*
+ * Find the offset of the node containing "arm,tpm_event_log"
+ * compatible property
+ */
+ const char *compatible_str = "arm,tpm_event_log";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find '%s' compatible in dtb\n",
+ compatible_str);
+ return node;
+ }
+
+ /* Retrieve Event Log details from the DTB */
+#ifdef SPD_opteed
+ err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2,
+ &event_log_config.tpm_event_log_sm_addr);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n");
+ return err;
+ }
+#endif
+ err = fdtw_read_cells(dtb, node,
+ "tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n");
+ return err;
+ }
+
+ err = fdtw_read_cells(dtb, node,
+ "tpm_event_log_size", 1, &event_log_config.tpm_event_log_size);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n");
+ }
+
+ return err;
+}
+
+FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config,
+ fconf_populate_event_log_config);
diff --git a/plat/arm/board/fvp/fdts/event_log.dtsi b/plat/arm/board/fvp/fdts/event_log.dtsi
new file mode 100644
index 0000000..47af672
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/event_log.dtsi
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* TPM Event Log Config */
+event_log: tpm_event_log {
+ compatible = "arm,tpm_event_log";
+ tpm_event_log_addr = <0x0 0x0>;
+ tpm_event_log_size = <0x0>;
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
new file mode 100644
index 0000000..577ac74
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x1800>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ hw-config {
+ load-address = <0x0 0x07f00000>;
+ max-size = <0x00100000>;
+ id = <HW_CONFIG_ID>;
+ ns-load-address = <0x0 0x82000000>;
+ };
+
+ /*
+ * Load SoC and TOS firmware configs at the base of
+ * non shared SRAM. The runtime checks ensure we don't
+ * overlap BL2, BL31 or BL32. The NT firmware config
+ * is loaded at base of DRAM.
+ */
+ soc_fw-config {
+ load-address = <0x0 0x04001300>;
+ max-size = <0x200>;
+ id = <SOC_FW_CONFIG_ID>;
+ };
+
+/* If required, SPD should enable loading of trusted OS fw config */
+#if defined(SPD_tspd) || defined(SPD_spmd)
+ tos_fw-config {
+ load-address = <0x0 0x04001500>;
+ max-size = <0xB00>;
+ id = <TOS_FW_CONFIG_ID>;
+ };
+#endif
+
+ nt_fw-config {
+ load-address = <0x0 0x80000000>;
+ max-size = <0x200>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
new file mode 100644
index 0000000..8f32b98
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
+};
+
+#if MEASURED_BOOT && defined(SPD_opteed)
+&event_log {
+ tpm_event_log_sm_addr = <0x0 0x0>;
+};
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts
new file mode 100644
index 0000000..7ab980b
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
new file mode 100644
index 0000000..4543671
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define AFF 00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define POST \
+ };
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x1>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x6000000>;
+ entrypoint = <0x0 0x6000000>;
+ binary_size = <0x80000>;
+ };
+
+ hypervisor {
+ compatible = "hafnium,hafnium";
+ vm1 {
+ is_ffa_partition;
+ debug_name = "cactus-primary";
+ load_address = <0x7000000>;
+ vcpu_count = <8>;
+ mem_size = <1048576>;
+ };
+ vm2 {
+ is_ffa_partition;
+ debug_name = "cactus-secondary";
+ load_address = <0x7100000>;
+ vcpu_count = <8>;
+ mem_size = <1048576>;
+ };
+ vm3 {
+ is_ffa_partition;
+ debug_name = "cactus-tertiary";
+ load_address = <0x7200000>;
+ vcpu_count = <1>;
+ mem_size = <1048576>;
+ };
+ vm4 {
+ is_ffa_partition;
+ debug_name = "ivy";
+ load_address = <0x7600000>;
+ vcpu_count = <1>;
+ mem_size = <1048576>;
+ };
+ };
+
+ cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
+ CPU_0
+
+ /*
+ * SPMC (Hafnium) requires secondary core nodes are declared
+ * in descending order.
+ */
+ CPU_7
+ CPU_6
+ CPU_5
+ CPU_4
+ CPU_3
+ CPU_2
+ CPU_1
+ };
+
+ memory@6000000 {
+ device_type = "memory";
+ reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
+ };
+
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
new file mode 100644
index 0000000..041dade
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define AFF 00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define POST \
+ };
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x1>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x6000000>;
+ entrypoint = <0x0 0x6000000>;
+ binary_size = <0x80000>;
+ };
+
+ hypervisor {
+ compatible = "hafnium,hafnium";
+ vm1 {
+ is_ffa_partition;
+ debug_name = "op-tee";
+ load_address = <0x6280000>;
+ vcpu_count = <8>;
+ mem_size = <1048576>;
+ };
+ };
+
+ cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
+ CPU_0
+
+ /*
+ * SPMC (Hafnium) requires secondary core nodes are declared
+ * in descending order.
+ */
+ CPU_7
+ CPU_6
+ CPU_5
+ CPU_4
+ CPU_3
+ CPU_2
+ CPU_1
+ };
+
+ memory@6000000 {
+ device_type = "memory";
+ reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
+ };
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
new file mode 100644
index 0000000..6fd334d
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/libc/cdefs.h>
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+
+ /*
+ * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in
+ * network order (big endian)
+ */
+
+#if ARM_IO_IN_DTB
+ arm-io_policies {
+ fip-handles {
+ compatible = "arm,io-fip-handle";
+ scp_bl2_uuid = "9766fd3d-89be-e849-ae5d-78a140608213";
+ bl31_uuid = "47d4086d-4cfe-9846-9b95-2950cbbd5a00";
+ bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38";
+ bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288";
+ bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9";
+ bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
+ hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
+ soc_fw_cfg_uuid = "9979814b-0376-fb46-8c8e-8d267f7859e0";
+ tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
+ nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
+ cca_cert_uuid = "36d83d85-761d-4daf-96f1-cd99d6569b00";
+ core_swd_cert_uuid = "52222d31-820f-494d-8bbc-ea6825d3c35a";
+ plat_cert_uuid = "d43cd902-5b9f-412e-8ac6-92b6d18be60d";
+ t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c";
+ scp_fw_key_uuid = "024221a1-f860-e411-8d9b-f33c0e15a014";
+ soc_fw_key_uuid = "8ab8becc-f960-e411-9ad0-eb4822d8dcf8";
+ tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04";
+ nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859";
+ scp_fw_content_cert_uuid = "44be6f04-5e63-e411-b28b-73d8eaae9656";
+ soc_fw_content_cert_uuid = "e2b20c20-5e63-e411-9ce8-abccf92bb666";
+ tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d";
+ nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7";
+ sp_content_cert_uuid = "776dfd44-8697-4c3b-91eb-c13e025a2a6f";
+ };
+ };
+#endif /* ARM_IO_IN_DTB */
+
+ secure-partitions {
+ compatible = "arm,sp";
+
+#ifdef ARM_BL2_SP_LIST_DTS
+ #include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
+#ifdef OPTEE_SP_FW_CONFIG
+ op-tee {
+ uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b";
+ load-address = <0x6280000>;
+ };
+#else
+ cactus-primary {
+ uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb";
+ load-address = <0x7000000>;
+ owner = "SiP";
+ };
+
+ cactus-secondary {
+ uuid = "d1582309-f023-47b9-827c-4464f5578fc8";
+ load-address = <0x7100000>;
+ owner = "Plat";
+ };
+
+ cactus-tertiary {
+ uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2";
+ load-address = <0x7200000>;
+ owner = "Plat";
+ };
+
+ ivy {
+ uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7";
+ load-address = <0x7600000>;
+ owner = "Plat";
+ };
+#endif
+#endif /* ARM_BL2_SP_LIST_DTS */
+ };
+
+#if COT_DESC_IN_DTB
+ #include "cot_descriptors.dtsi"
+#endif
+
+#if MEASURED_BOOT
+ #include "event_log.dtsi"
+#endif
+
+};
+
+#if COT_DESC_IN_DTB
+
+#include "../fvp_def.h"
+
+&trusted_nv_counter {
+ reg = <TFW_NVCTR_BASE>;
+};
+
+&non_trusted_nv_counter {
+ reg = <NTFW_CTR_BASE>;
+};
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
new file mode 100644
index 0000000..7bed6cb
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts
new file mode 100644
index 0000000..1587c72
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_tsp_sp_manifest.dts
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define AFF 00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define POST \
+ };
+
+#define S_EL0 (0x1)
+#define S_EL1 (0x2)
+
+/* For consumption by EL3 SPMC. */
+/ {
+ compatible = "arm,ffa-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ ffa-version = <0x00010001>; /* 31:16 - Major, 15:0 - Minor */
+ id = <0x8001>;
+ uuid = <0x6b43b460 0x74a24b78 0xade24502 0x40682886>;
+ messaging-method = <0x3>; /* Direct Messaging Only */
+ exception-level = <S_EL1>;
+ execution-state = <0>;
+ execution-ctx-count = <8>;
+ gp-register-num = <0>;
+ /* Subscribe to CPU_OFF, CPU_SUSPEND and CPU_SUSPEND_RESUME PM Msgs */
+ power-management-messages = <0x7>;
+};
diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
new file mode 100644
index 0000000..27f4724
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
+ * that has additional optional properties defined.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-manifest-1.0";
+
+ /* Properties */
+ description = "op-tee";
+ ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+ uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>;
+ id = <1>;
+ execution-ctx-count = <8>;
+ exception-level = <2>; /* S-EL1 */
+ execution-state = <0>; /* AARCH64 */
+ load-address = <0x6280000>;
+ entrypoint-offset = <0x4000>;
+ xlat-granule = <0>; /* 4KiB */
+ boot-order = <0>;
+ messaging-method = <0x3>; /* Direct request/response supported. */
+ managed-exit;
+ run-time-model = <1>; /* SP pre-emptible. */
+
+ /* Boot protocol */
+ gp-register-num = <0x0>;
+
+ device-regions {
+ compatible = "arm,ffa-manifest-device-regions";
+
+ uart1 {
+ base-address = <0x00000000 0x1c0a0000>;
+ pages-count = <1>;
+ attributes = <0x3>; /* read-write */
+ };
+ };
+};
diff --git a/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
new file mode 100644
index 0000000..76cd918
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl1_measured_boot.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* Event Log data */
+static uint8_t event_log[PLAT_ARM_EVENT_LOG_MAX_SIZE];
+
+/* FVP table with platform specific image IDs, names and PCRs */
+const event_log_metadata_t fvp_event_log_metadata[] = {
+ { FW_CONFIG_ID, EVLOG_FW_CONFIG_STRING, PCR_0 },
+ { TB_FW_CONFIG_ID, EVLOG_TB_FW_CONFIG_STRING, PCR_0 },
+ { BL2_IMAGE_ID, EVLOG_BL2_STRING, PCR_0 },
+
+ { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+/* FVP table with platform specific image IDs and metadata. Intentionally not a
+ * const struct, some members might set by bootloaders during trusted boot.
+ */
+struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
+ {
+ .id = FW_CONFIG_ID,
+ .slot = U(6),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = TB_FW_CONFIG_ID,
+ .slot = U(7),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_TB_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = BL2_IMAGE_ID,
+ .slot = U(8),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_BL2_STRING,
+ .lock_measurement = true },
+
+ {
+ .id = RSS_MBOOT_INVALID_ID }
+};
+
+void bl1_plat_mboot_init(void)
+{
+ event_log_init(event_log, event_log + sizeof(event_log));
+ event_log_write_header();
+
+ rss_measured_boot_init();
+}
+
+void bl1_plat_mboot_finish(void)
+{
+ size_t event_log_cur_size;
+
+ event_log_cur_size = event_log_get_cur_size(event_log);
+ int rc = arm_set_tb_fw_info((uintptr_t)event_log,
+ event_log_cur_size);
+ if (rc != 0) {
+ /*
+ * It is a fatal error because on FVP platform, BL2 software
+ * assumes that a valid Event Log buffer exist and it will use
+ * same Event Log buffer to append image measurements.
+ */
+ panic();
+ }
+}
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
new file mode 100644
index 0000000..59fc0f3
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <bl1/bl1.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/smmu_v3.h>
+#include <drivers/arm/sp805.h>
+#include <lib/mmio.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/common/platform.h>
+#include "fvp_private.h"
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ arm_bl1_early_platform_setup();
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ fvp_interconnect_init();
+ /*
+ * Enable coherency in Interconnect for the primary CPU's cluster.
+ */
+ fvp_interconnect_enable();
+}
+
+void plat_arm_secure_wdt_start(void)
+{
+ sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sp805_stop(ARM_SP805_TWDG_BASE);
+}
+
+void bl1_platform_setup(void)
+{
+ arm_bl1_platform_setup();
+
+ /* Initialize System level generic or SP804 timer */
+ fvp_timer_init();
+
+ /* On FVP RevC, initialize SMMUv3 */
+ if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
+ smmuv3_security_init(PLAT_FVP_SMMUV3_BASE);
+}
+
+__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
+{
+ uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
+
+ /* Clear the NV flags register. */
+ mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR),
+ nv_flags);
+
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ while (true)
+ wfi();
+}
+
+/*******************************************************************************
+ * The following function checks if Firmware update is needed by checking error
+ * reported in NV flag.
+ ******************************************************************************/
+bool plat_arm_bl1_fwu_needed(void)
+{
+ int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
+
+ /* if image load/authentication failed */
+ return ((nv_flags == -EAUTH) || (nv_flags == -ENOENT));
+}
diff --git a/plat/arm/board/fvp/fvp_bl2_el3_setup.c b/plat/arm/board/fvp/fvp_bl2_el3_setup.c
new file mode 100644
index 0000000..7def56a
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl2_el3_setup.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+#include "fvp_private.h"
+
+void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ arm_bl2_el3_early_platform_setup();
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ fvp_interconnect_init();
+ /*
+ * Enable coherency in Interconnect for the primary CPU's cluster.
+ */
+ fvp_interconnect_enable();
+}
diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
new file mode 100644
index 0000000..e938e24
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
+#include <tools_share/tbbr_oid.h>
+#include <fvp_critical_data.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+
+/* Event Log data */
+static uint64_t event_log_base;
+
+/* FVP table with platform specific image IDs, names and PCRs */
+const event_log_metadata_t fvp_event_log_metadata[] = {
+ { BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 },
+ { BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 },
+ { BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 },
+ { BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 },
+ { BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 },
+ { HW_CONFIG_ID, EVLOG_HW_CONFIG_STRING, PCR_0 },
+ { NT_FW_CONFIG_ID, EVLOG_NT_FW_CONFIG_STRING, PCR_0 },
+ { SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 },
+ { SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 },
+ { TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 },
+ { RMM_IMAGE_ID, EVLOG_RMM_STRING, PCR_0},
+
+#if defined(SPD_spmd)
+ { SP_PKG1_ID, EVLOG_SP1_STRING, PCR_0 },
+ { SP_PKG2_ID, EVLOG_SP2_STRING, PCR_0 },
+ { SP_PKG3_ID, EVLOG_SP3_STRING, PCR_0 },
+ { SP_PKG4_ID, EVLOG_SP4_STRING, PCR_0 },
+ { SP_PKG5_ID, EVLOG_SP5_STRING, PCR_0 },
+ { SP_PKG6_ID, EVLOG_SP6_STRING, PCR_0 },
+ { SP_PKG7_ID, EVLOG_SP7_STRING, PCR_0 },
+ { SP_PKG8_ID, EVLOG_SP8_STRING, PCR_0 },
+#endif
+
+ { CRITICAL_DATA_ID, EVLOG_CRITICAL_DATA_STRING, PCR_1 },
+
+ { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+/* FVP table with platform specific image IDs and metadata. Intentionally not a
+ * const struct, some members might set by bootloaders during trusted boot.
+ */
+struct rss_mboot_metadata fvp_rss_mboot_metadata[] = {
+ {
+ .id = BL31_IMAGE_ID,
+ .slot = U(9),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_BL31_STRING,
+ .lock_measurement = true },
+ {
+ .id = HW_CONFIG_ID,
+ .slot = U(10),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_HW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = SOC_FW_CONFIG_ID,
+ .slot = U(11),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_SOC_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = RMM_IMAGE_ID,
+ .slot = U(12),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_RMM_STRING,
+ .lock_measurement = true },
+ {
+ .id = RSS_MBOOT_INVALID_ID }
+};
+
+void bl2_plat_mboot_init(void)
+{
+ uint8_t *event_log_start;
+ uint8_t *event_log_finish;
+ size_t bl1_event_log_size;
+ int rc;
+
+ rc = arm_get_tb_fw_info(&event_log_base, &bl1_event_log_size);
+ if (rc != 0) {
+ ERROR("%s(): Unable to get Event Log info from TB_FW_CONFIG\n",
+ __func__);
+ /*
+ * It is a fatal error because on FVP platform, BL2 software
+ * assumes that a valid Event Log buffer exist and it will use
+ * same Event Log buffer to append image measurements.
+ */
+ panic();
+ }
+
+ /*
+ * BL1 and BL2 share the same Event Log buffer and that BL2 will
+ * append its measurements after BL1's
+ */
+ event_log_start = (uint8_t *)((uintptr_t)event_log_base +
+ bl1_event_log_size);
+ event_log_finish = (uint8_t *)((uintptr_t)event_log_base +
+ PLAT_ARM_EVENT_LOG_MAX_SIZE);
+
+ event_log_init((uint8_t *)event_log_start, event_log_finish);
+
+ rss_measured_boot_init();
+}
+
+int plat_mboot_measure_critical_data(unsigned int critical_data_id,
+ const void *base, size_t size)
+{
+ /*
+ * It is very unlikely that the critical data size would be
+ * bigger than 2^32 bytes
+ */
+ assert(size < UINT32_MAX);
+ assert(base != NULL);
+
+ /* Calculate image hash and record data in Event Log */
+ int err = event_log_measure_and_record((uintptr_t)base, (uint32_t)size,
+ critical_data_id);
+ if (err != 0) {
+ ERROR("%s%s critical data (%i)\n",
+ "Failed to ", "record", err);
+ return err;
+ }
+
+ return 0;
+}
+
+#if TRUSTED_BOARD_BOOT
+static int fvp_populate_critical_data(struct fvp_critical_data *critical_data)
+{
+ char *nv_ctr_oids[MAX_NV_CTR_IDS] = {
+ [TRUSTED_NV_CTR_ID] = TRUSTED_FW_NVCOUNTER_OID,
+ [NON_TRUSTED_NV_CTR_ID] = NON_TRUSTED_FW_NVCOUNTER_OID,
+ };
+
+ for (int i = 0; i < MAX_NV_CTR_IDS; i++) {
+ int rc = plat_get_nv_ctr(nv_ctr_oids[i],
+ &critical_data->nv_ctr[i]);
+ if (rc != 0) {
+ return rc;
+ }
+ }
+
+ return 0;
+}
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int fvp_populate_and_measure_critical_data(void)
+{
+ int rc = 0;
+
+/*
+ * FVP platform only measures 'platform NV-counter' and hence its
+ * measurement makes sense during Trusted-Boot flow only.
+ */
+#if TRUSTED_BOARD_BOOT
+ struct fvp_critical_data populate_critical_data;
+
+ rc = fvp_populate_critical_data(&populate_critical_data);
+ if (rc == 0) {
+ rc = plat_mboot_measure_critical_data(CRITICAL_DATA_ID,
+ &populate_critical_data,
+ sizeof(populate_critical_data));
+ }
+#endif /* TRUSTED_BOARD_BOOT */
+
+ return rc;
+}
+
+void bl2_plat_mboot_finish(void)
+{
+ int rc;
+
+ /* Event Log address in Non-Secure memory */
+ uintptr_t ns_log_addr;
+
+ /* Event Log filled size */
+ size_t event_log_cur_size;
+
+ rc = fvp_populate_and_measure_critical_data();
+ if (rc != 0) {
+ panic();
+ }
+
+ event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
+
+ rc = arm_set_nt_fw_info(
+#ifdef SPD_opteed
+ (uintptr_t)event_log_base,
+#endif
+ event_log_cur_size, &ns_log_addr);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "NT");
+ /*
+ * It is a fatal error because on FVP secure world software
+ * assumes that a valid event log exists and will use it to
+ * record the measurements into the fTPM.
+ * Note: In FVP platform, OP-TEE uses nt_fw_config to get the
+ * secure Event Log buffer address.
+ */
+ panic();
+ }
+
+ /* Copy Event Log to Non-secure memory */
+ (void)memcpy((void *)ns_log_addr, (const void *)event_log_base,
+ event_log_cur_size);
+
+ /* Ensure that the Event Log is visible in Non-secure memory */
+ flush_dcache_range(ns_log_addr, event_log_cur_size);
+
+#if defined(SPD_tspd) || defined(SPD_spmd)
+ /* Set Event Log data in TOS_FW_CONFIG */
+ rc = arm_set_tos_fw_info((uintptr_t)event_log_base,
+ event_log_cur_size);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "TOS");
+ panic();
+ }
+#endif /* defined(SPD_tspd) || defined(SPD_spmd) */
+
+ dump_event_log((uint8_t *)event_log_base, event_log_cur_size);
+}
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
new file mode 100644
index 0000000..74e5d72
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "fvp_private.h"
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
+{
+ arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+}
+
+void bl2_platform_setup(void)
+{
+ arm_bl2_platform_setup();
+
+ /* Initialize System level generic or SP804 timer */
+ fvp_timer_init();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ struct bl_params *arm_bl_params;
+ const struct dyn_cfg_dtb_info_t *hw_config_info __unused;
+ bl_mem_params_node_t *param_node __unused;
+
+ arm_bl_params = arm_get_next_bl_params();
+
+#if !BL2_AT_EL3 && !EL3_PAYLOAD_BASE
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ uintptr_t fw_config_base = 0UL;
+ entry_point_info_t *ep_info;
+
+#if __aarch64__
+ /* Get BL31 image node */
+ param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+#else /* aarch32 */
+ /* Get SP_MIN image node */
+ param_node = get_bl_mem_params_node(BL32_IMAGE_ID);
+#endif /* __aarch64__ */
+ assert(param_node != NULL);
+
+ /* get fw_config load address */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ assert(fw_config_info != NULL);
+
+ fw_config_base = fw_config_info->config_addr;
+ assert(fw_config_base != 0UL);
+
+ /*
+ * Get the entry point info of next executable image and override
+ * arg1 of entry point info with fw_config base address
+ */
+ ep_info = &param_node->ep_info;
+ ep_info->args.arg1 = (uint32_t)fw_config_base;
+
+ /* grab NS HW config address */
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+
+ /* To retrieve actual size of the HW_CONFIG */
+ param_node = get_bl_mem_params_node(HW_CONFIG_ID);
+ assert(param_node != NULL);
+
+ /* Copy HW config from Secure address to NS address */
+ memcpy((void *)hw_config_info->ns_config_addr,
+ (void *)hw_config_info->config_addr,
+ (size_t)param_node->image_info.image_size);
+
+ /*
+ * Ensure HW-config device tree committed to memory, as there is
+ * a possibility to use HW-config without cache and MMU enabled
+ * at BL33
+ */
+ flush_dcache_range(hw_config_info->ns_config_addr,
+ param_node->image_info.image_size);
+
+ param_node = get_bl_mem_params_node(BL33_IMAGE_ID);
+ assert(param_node != NULL);
+
+ /* Update BL33's ep info with NS HW config address */
+ param_node->ep_info.args.arg1 = hw_config_info->ns_config_addr;
+#endif /* !BL2_AT_EL3 && !EL3_PAYLOAD_BASE */
+
+ return arm_bl_params;
+}
diff --git a/plat/arm/board/fvp/fvp_bl2u_setup.c b/plat/arm/board/fvp/fvp_bl2u_setup.c
new file mode 100644
index 0000000..fd73767
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl2u_setup.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "fvp_private.h"
+
+void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info)
+{
+ arm_bl2u_early_platform_setup(mem_layout, plat_info);
+
+ /* Initialize System level generic or SP804 timer */
+ fvp_timer_init();
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+}
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
new file mode 100644
index 0000000..dd90965
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/arm/smmu_v3.h>
+#include <fconf_hw_config_getter.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/mmio.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include "fvp_private.h"
+
+static const struct dyn_cfg_dtb_info_t *hw_config_info __unused;
+
+void __init bl31_early_platform_setup2(u_register_t arg0,
+ u_register_t arg1, u_register_t arg2, u_register_t arg3)
+{
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+#if !RESET_TO_BL31 && !BL2_AT_EL3
+ const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
+
+ INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", arg1);
+
+ soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID);
+ if (soc_fw_config_info != NULL) {
+ arg1 = soc_fw_config_info->config_addr;
+ }
+
+ /*
+ * arg2 is currently holding the 'secure' address of HW_CONFIG.
+ * But arm_bl31_early_platform_setup() below expects the 'non-secure'
+ * address of HW_CONFIG (which it will pass to BL33).
+ * This why we need to override arg2 here.
+ */
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+ assert(hw_config_info->ns_config_addr != 0UL);
+ arg2 = hw_config_info->ns_config_addr;
+#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 */
+
+ arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+
+ /*
+ * Initialize the correct interconnect for this cluster during cold
+ * boot. No need for locks as no other CPU is active.
+ */
+ fvp_interconnect_init();
+
+ /*
+ * Enable coherency in interconnect for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this (e.g. Trusted
+ * Firmware's BL1 does it) but we can't assume so. There is no harm in
+ * executing this code twice anyway.
+ * FVP PSCI code will enable coherency for other clusters.
+ */
+ fvp_interconnect_enable();
+
+ /* Initialize System level generic or SP804 timer */
+ fvp_timer_init();
+
+ /* On FVP RevC, initialize SMMUv3 */
+ if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
+ smmuv3_init(PLAT_FVP_SMMUV3_BASE);
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+ int rc __unused;
+ uintptr_t hw_config_base_align __unused;
+ size_t mapped_size_align __unused;
+
+ arm_bl31_plat_arch_setup();
+
+ /*
+ * For RESET_TO_BL31 systems, BL31 is the first bootloader to run.
+ * So there is no BL2 to load the HW_CONFIG dtb into memory before
+ * control is passed to BL31. The code below relies on dynamic mapping
+ * capability, which is not supported by xlat tables lib V1.
+ * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support
+ * gets deprecated.
+ */
+#if !RESET_TO_BL31 && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1
+ assert(hw_config_info != NULL);
+ assert(hw_config_info->config_addr != 0UL);
+
+ /* Page aligned address and size if necessary */
+ hw_config_base_align = page_align(hw_config_info->config_addr, DOWN);
+ mapped_size_align = page_align(hw_config_info->config_max_size, UP);
+
+ if ((hw_config_info->config_addr != hw_config_base_align) &&
+ (hw_config_info->config_max_size == mapped_size_align)) {
+ mapped_size_align += PAGE_SIZE;
+ }
+
+ /*
+ * map dynamically HW config region with its aligned base address and
+ * size
+ */
+ rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align,
+ hw_config_base_align,
+ mapped_size_align,
+ MT_RO_DATA);
+ if (rc != 0) {
+ ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc);
+ panic();
+ }
+
+ /* Populate HW_CONFIG device tree with the mapped address */
+ fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+
+ /* unmap the HW_CONFIG memory region */
+ rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align);
+ if (rc != 0) {
+ ERROR("Error while unmapping HW_CONFIG device tree (%d).\n",
+ rc);
+ panic();
+ }
+#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1 */
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+
+#if !RESET_TO_BL31 && !BL2_AT_EL3
+ /* Get the frequency through FCONF API for HW_CONFIG */
+ counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq);
+ if (counter_base_frequency > 0U) {
+ return counter_base_frequency;
+ }
+#endif
+
+ /* Read the frequency from Frequency modes table */
+ counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
+
+ /* The first entry of the frequency modes table must not be 0 */
+ if (counter_base_frequency == 0U) {
+ panic();
+ }
+
+ return counter_base_frequency;
+}
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
new file mode 100644
index 0000000..f8463f1
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/ccn.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <platform_def.h>
+#include <services/arm_arch_svc.h>
+#if ENABLE_RME
+#include <services/rmm_core_manifest.h>
+#endif
+#if SPM_MM
+#include <services/spm_mm_partition.h>
+#endif
+
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include "fvp_private.h"
+
+/* Defines for GIC Driver build time selection */
+#define FVP_GICV2 1
+#define FVP_GICV3 2
+
+/*******************************************************************************
+ * arm_config holds the characteristics of the differences between the three FVP
+ * platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
+ * at each boot stage by the primary before enabling the MMU (to allow
+ * interconnect configuration) & used thereafter. Each BL will have its own copy
+ * to allow independent operation.
+ ******************************************************************************/
+arm_config_t arm_config;
+
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \
+ DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#if FVP_GICR_REGION_PROTECTION
+#define MAP_GICD_MEM MAP_REGION_FLAT(BASE_GICD_BASE, \
+ BASE_GICD_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/* Map all core's redistributor memory as read-only. After boots up,
+ * per-core map its redistributor memory as read-write */
+#define MAP_GICR_MEM MAP_REGION_FLAT(BASE_GICR_BASE, \
+ (BASE_GICR_SIZE * PLATFORM_CORE_COUNT),\
+ MT_DEVICE | MT_RO | MT_SECURE)
+#endif /* FVP_GICR_REGION_PROTECTION */
+
+/*
+ * Need to be mapped with write permissions in order to set a new non-volatile
+ * counter value.
+ */
+#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \
+ DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of memory regions for various BL stages to map using the MMU.
+ * This doesn't include Trusted SRAM as setup_page_tables() already takes care
+ * of mapping it.
+ */
+#ifdef IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH0_RO,
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+ MAP_DEVICE1,
+#endif
+#if TRUSTED_BOARD_BOOT
+ /* To access the Root of Trust Public Key registers. */
+ MAP_DEVICE2,
+ /* Map DRAM to authenticate NS_BL2U image. */
+ ARM_MAP_NS_DRAM1,
+#endif
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH0_RW,
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+ MAP_DEVICE1,
+#endif
+ ARM_MAP_NS_DRAM1,
+#ifdef __aarch64__
+ ARM_MAP_DRAM2,
+#endif
+ /*
+ * Required to load HW_CONFIG, SPMC and SPs to trusted DRAM.
+ */
+ ARM_MAP_TRUSTED_DRAM,
+#if ENABLE_RME
+ ARM_MAP_RMM_DRAM,
+ ARM_MAP_GPT_L1_DRAM,
+#endif /* ENABLE_RME */
+#ifdef SPD_tspd
+ ARM_MAP_TSP_SEC_MEM,
+#endif
+#if TRUSTED_BOARD_BOOT
+ /* To access the Root of Trust Public Key registers. */
+ MAP_DEVICE2,
+#endif /* TRUSTED_BOARD_BOOT */
+
+#if CRYPTO_SUPPORT && !BL2_AT_EL3
+ /*
+ * To access shared the Mbed TLS heap while booting the
+ * system with Crypto support
+ */
+ ARM_MAP_BL1_RW,
+#endif /* CRYPTO_SUPPORT && !BL2_AT_EL3 */
+#if SPM_MM || SPMC_AT_EL3
+ ARM_SP_IMAGE_MMAP,
+#endif
+#if ARM_BL31_IN_DRAM
+ ARM_MAP_BL31_SEC_DRAM,
+#endif
+#ifdef SPD_opteed
+ ARM_MAP_OPTEE_CORE_MEM,
+ ARM_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2U
+const mmap_region_t plat_arm_mmap[] = {
+ MAP_DEVICE0,
+ V2M_MAP_IOFPGA,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+#if USE_DEBUGFS
+ /* Required by devfip, can be removed if devfip is not used */
+ V2M_MAP_FLASH0_RW,
+#endif /* USE_DEBUGFS */
+ ARM_MAP_EL3_TZC_DRAM,
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+#if FVP_GICR_REGION_PROTECTION
+ MAP_GICD_MEM,
+ MAP_GICR_MEM,
+#else
+ MAP_DEVICE1,
+#endif /* FVP_GICR_REGION_PROTECTION */
+ ARM_V2M_MAP_MEM_PROTECT,
+#if SPM_MM
+ ARM_SPM_BUF_EL3_MMAP,
+#endif
+#if ENABLE_RME
+ ARM_MAP_GPT_L1_DRAM,
+ ARM_MAP_EL3_RMM_SHARED_MEM,
+#endif
+ {0}
+};
+
+#if defined(IMAGE_BL31) && SPM_MM
+const mmap_region_t plat_arm_secure_partition_mmap[] = {
+ V2M_MAP_IOFPGA_EL0, /* for the UART */
+ MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RO | MT_SECURE | MT_USER),
+ ARM_SP_IMAGE_MMAP,
+ ARM_SP_IMAGE_NS_BUF_MMAP,
+ ARM_SP_IMAGE_RW_MMAP,
+ ARM_SPM_BUF_EL0_MMAP,
+ {0}
+};
+#endif
+#endif
+#ifdef IMAGE_BL32
+const mmap_region_t plat_arm_mmap[] = {
+#ifndef __aarch64__
+ ARM_MAP_SHARED_RAM,
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+ MAP_DEVICE1,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_RMM
+const mmap_region_t plat_arm_mmap[] = {
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+ MAP_DEVICE1,
+ {0}
+};
+#endif
+
+ARM_CASSERT_MMAP
+
+#if FVP_INTERCONNECT_DRIVER != FVP_CCN
+static const int fvp_cci400_map[] = {
+ PLAT_FVP_CCI400_CLUS0_SL_PORT,
+ PLAT_FVP_CCI400_CLUS1_SL_PORT,
+};
+
+static const int fvp_cci5xx_map[] = {
+ PLAT_FVP_CCI5XX_CLUS0_SL_PORT,
+ PLAT_FVP_CCI5XX_CLUS1_SL_PORT,
+};
+
+static unsigned int get_interconnect_master(void)
+{
+ unsigned int master;
+ u_register_t mpidr;
+
+ mpidr = read_mpidr_el1();
+ master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
+ MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);
+
+ assert(master < FVP_CLUSTER_COUNT);
+ return master;
+}
+#endif
+
+#if defined(IMAGE_BL31) && SPM_MM
+/*
+ * Boot information passed to a secure partition during initialisation. Linear
+ * indices in MP information will be filled at runtime.
+ */
+static spm_mm_mp_info_t sp_mp_info[] = {
+ [0] = {0x80000000, 0},
+ [1] = {0x80000001, 0},
+ [2] = {0x80000002, 0},
+ [3] = {0x80000003, 0},
+ [4] = {0x80000100, 0},
+ [5] = {0x80000101, 0},
+ [6] = {0x80000102, 0},
+ [7] = {0x80000103, 0},
+};
+
+const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
+ .h.type = PARAM_SP_IMAGE_BOOT_INFO,
+ .h.version = VERSION_1,
+ .h.size = sizeof(spm_mm_boot_info_t),
+ .h.attr = 0,
+ .sp_mem_base = ARM_SP_IMAGE_BASE,
+ .sp_mem_limit = ARM_SP_IMAGE_LIMIT,
+ .sp_image_base = ARM_SP_IMAGE_BASE,
+ .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
+ .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE,
+ .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
+ .sp_shared_buf_base = PLAT_SPM_BUF_BASE,
+ .sp_image_size = ARM_SP_IMAGE_SIZE,
+ .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+ .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE,
+ .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
+ .sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
+ .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS,
+ .num_cpus = PLATFORM_CORE_COUNT,
+ .mp_info = &sp_mp_info[0],
+};
+
+const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
+{
+ return plat_arm_secure_partition_mmap;
+}
+
+const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
+ void *cookie)
+{
+ return &plat_arm_secure_partition_boot_info;
+}
+#endif
+
+/*******************************************************************************
+ * A single boot loader stack is expected to work on both the Foundation FVP
+ * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
+ * SYS_ID register provides a mechanism for detecting the differences between
+ * these platforms. This information is stored in a per-BL array to allow the
+ * code to take the correct path.Per BL platform configuration.
+ ******************************************************************************/
+void __init fvp_config_setup(void)
+{
+ unsigned int rev, hbi, bld, arch, sys_id;
+
+ sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
+ rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
+ hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
+ bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
+ arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
+
+ if (arch != ARCH_MODEL) {
+ ERROR("This firmware is for FVP models\n");
+ panic();
+ }
+
+ /*
+ * The build field in the SYS_ID tells which variant of the GIC
+ * memory is implemented by the model.
+ */
+ switch (bld) {
+ case BLD_GIC_VE_MMAP:
+ ERROR("Legacy Versatile Express memory map for GIC peripheral"
+ " is not supported\n");
+ panic();
+ break;
+ case BLD_GIC_A53A57_MMAP:
+ break;
+ default:
+ ERROR("Unsupported board build %x\n", bld);
+ panic();
+ }
+
+ /*
+ * The hbi field in the SYS_ID is 0x020 for the Base FVP & 0x010
+ * for the Foundation FVP.
+ */
+ switch (hbi) {
+ case HBI_FOUNDATION_FVP:
+ arm_config.flags = 0;
+
+ /*
+ * Check for supported revisions of Foundation FVP
+ * Allow future revisions to run but emit warning diagnostic
+ */
+ switch (rev) {
+ case REV_FOUNDATION_FVP_V2_0:
+ case REV_FOUNDATION_FVP_V2_1:
+ case REV_FOUNDATION_FVP_v9_1:
+ case REV_FOUNDATION_FVP_v9_6:
+ break;
+ default:
+ WARN("Unrecognized Foundation FVP revision %x\n", rev);
+ break;
+ }
+ break;
+ case HBI_BASE_FVP:
+ arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
+
+ /*
+ * Check for supported revisions
+ * Allow future revisions to run but emit warning diagnostic
+ */
+ switch (rev) {
+ case REV_BASE_FVP_V0:
+ arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
+ break;
+ case REV_BASE_FVP_REVC:
+ arm_config.flags |= (ARM_CONFIG_FVP_HAS_SMMUV3 |
+ ARM_CONFIG_FVP_HAS_CCI5XX);
+ break;
+ default:
+ WARN("Unrecognized Base FVP revision %x\n", rev);
+ break;
+ }
+ break;
+ default:
+ ERROR("Unsupported board HBI number 0x%x\n", hbi);
+ panic();
+ }
+
+ /*
+ * We assume that the presence of MT bit, and therefore shifted
+ * affinities, is uniform across the platform: either all CPUs, or no
+ * CPUs implement it.
+ */
+ if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U)
+ arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
+}
+
+
+void __init fvp_interconnect_init(void)
+{
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+ if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) {
+ ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported");
+ panic();
+ }
+
+ plat_arm_interconnect_init();
+#else
+ uintptr_t cci_base = 0U;
+ const int *cci_map = NULL;
+ unsigned int map_size = 0U;
+
+ /* Initialize the right interconnect */
+ if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) {
+ cci_base = PLAT_FVP_CCI5XX_BASE;
+ cci_map = fvp_cci5xx_map;
+ map_size = ARRAY_SIZE(fvp_cci5xx_map);
+ } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) {
+ cci_base = PLAT_FVP_CCI400_BASE;
+ cci_map = fvp_cci400_map;
+ map_size = ARRAY_SIZE(fvp_cci400_map);
+ } else {
+ return;
+ }
+
+ assert(cci_base != 0U);
+ assert(cci_map != NULL);
+ cci_init(cci_base, cci_map, map_size);
+#endif
+}
+
+void fvp_interconnect_enable(void)
+{
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+ plat_arm_interconnect_enter_coherency();
+#else
+ unsigned int master;
+
+ if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+ ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+ master = get_interconnect_master();
+ cci_enable_snoop_dvm_reqs(master);
+ }
+#endif
+}
+
+void fvp_interconnect_disable(void)
+{
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+ plat_arm_interconnect_exit_coherency();
+#else
+ unsigned int master;
+
+ if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+ ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+ master = get_interconnect_master();
+ cci_disable_snoop_dvm_reqs(master);
+ }
+#endif
+}
+
+#if CRYPTO_SUPPORT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif /* CRYPTO_SUPPORT */
+
+void fvp_timer_init(void)
+{
+#if USE_SP804_TIMER
+ /* Enable the clock override for SP804 timer 0, which means that no
+ * clock dividers are applied and the raw (35MHz) clock will be used.
+ */
+ mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);
+
+ /* Initialize delay timer driver using SP804 dual timer 0 */
+ sp804_timer_init(V2M_SP804_TIMER0_BASE,
+ SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
+#else
+ generic_delay_timer_init();
+
+ /* Enable System level generic timer */
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0U) | CNTCR_EN);
+#endif /* USE_SP804_TIMER */
+}
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ * feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+ return (int32_t)
+ (SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE,
+ ARM_SOC_IDENTIFICATION_CODE) |
+ (FVP_SOC_ID & SOC_ID_IMPL_DEF_MASK));
+}
+
+/* Get SOC revision */
+int32_t plat_get_soc_revision(void)
+{
+ unsigned int sys_id;
+
+ sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
+ return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) &
+ V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK);
+}
+
+#if ENABLE_RME
+/*
+ * Get a pointer to the RMM-EL3 Shared buffer and return it
+ * through the pointer passed as parameter.
+ *
+ * This function returns the size of the shared buffer.
+ */
+size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared)
+{
+ *shared = (uintptr_t)RMM_SHARED_BASE;
+
+ return (size_t)RMM_SHARED_SIZE;
+}
+
+int plat_rmmd_load_manifest(rmm_manifest_t *manifest)
+{
+ assert(manifest != NULL);
+
+ manifest->version = RMMD_MANIFEST_VERSION;
+ manifest->plat_data = (uintptr_t)NULL;
+
+ return 0;
+}
+
+#endif
diff --git a/plat/arm/board/fvp/fvp_common_measured_boot.c b/plat/arm/board/fvp/fvp_common_measured_boot.c
new file mode 100644
index 0000000..93aa055
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_common_measured_boot.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/desc_image_load.h>
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+extern event_log_metadata_t fvp_event_log_metadata[];
+extern struct rss_mboot_metadata fvp_rss_mboot_metadata[];
+
+const event_log_metadata_t *plat_event_log_get_metadata(void)
+{
+ return fvp_event_log_metadata;
+}
+
+struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void)
+{
+ return fvp_rss_mboot_metadata;
+}
+
+int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
+{
+ int err;
+ int rc = 0;
+
+ /* Calculate image hash and record data in Event Log */
+ err = event_log_measure_and_record(image_data->image_base,
+ image_data->image_size,
+ image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "Failed to ", "record in event log", image_id, err);
+ rc = err;
+ }
+
+ /* Calculate image hash and record data in RSS */
+ err = rss_mboot_measure_and_record(image_data->image_base,
+ image_data->image_size,
+ image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "Failed to ", "record in RSS", image_id, err);
+ rc = (rc == 0) ? err : -1;
+ }
+
+ return rc;
+}
diff --git a/plat/arm/board/fvp/fvp_console.c b/plat/arm/board/fvp/fvp_console.c
new file mode 100644
index 0000000..1a6cd42
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_console.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <fconf_hw_config_getter.h>
+#include <plat/arm/common/plat_arm.h>
+
+static console_t fvp_runtime_console;
+
+/* Initialize the runtime console */
+void arm_console_runtime_init(void)
+{
+ uintptr_t uart_base;
+ uint32_t uart_clk;
+
+ /*
+ * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and
+ * BL2_AT_EL3 systems.
+ */
+#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3
+ uart_base = PLAT_ARM_RUN_UART_BASE;
+ uart_clk = PLAT_ARM_RUN_UART_CLK_IN_HZ;
+#else
+ uart_base = FCONF_GET_PROPERTY(hw_config, uart_serial_config,
+ uart_base);
+ uart_clk = FCONF_GET_PROPERTY(hw_config, uart_serial_config,
+ uart_clk);
+#endif
+
+ int rc = console_pl011_register(uart_base, uart_clk,
+ ARM_CONSOLE_BAUDRATE,
+ &fvp_runtime_console);
+
+ if (rc == 0) {
+ panic();
+ }
+
+ console_set_scope(&fvp_runtime_console, CONSOLE_FLAG_RUNTIME);
+}
+
+void arm_console_runtime_end(void)
+{
+ console_flush();
+ (void)console_unregister(&fvp_runtime_console);
+}
diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h
new file mode 100644
index 0000000..831eb35
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_def.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_DEF_H
+#define FVP_DEF_H
+
+#include <lib/utils_def.h>
+
+#ifndef FVP_CLUSTER_COUNT
+#error "FVP_CLUSTER_COUNT is not set in makefile"
+#endif
+
+#ifndef FVP_MAX_CPUS_PER_CLUSTER
+#error "FVP_MAX_CPUS_PER_CLUSTER is not set in makefile"
+#endif
+
+#ifndef FVP_MAX_PE_PER_CPU
+#error "FVP_MAX_PE_PER_CPU is not set in makefile"
+#endif
+
+#define FVP_PRIMARY_CPU 0x0
+
+/* Defines for the Interconnect build selection */
+#define FVP_CCI 1
+#define FVP_CCN 2
+
+/******************************************************************************
+ * Definition of platform soc id
+ *****************************************************************************/
+#define FVP_SOC_ID 0
+
+/*******************************************************************************
+ * FVP memory map related constants
+ ******************************************************************************/
+
+#define FLASH1_BASE UL(0x0c000000)
+#define FLASH1_SIZE UL(0x04000000)
+
+#define PSRAM_BASE UL(0x14000000)
+#define PSRAM_SIZE UL(0x04000000)
+
+#define VRAM_BASE UL(0x18000000)
+#define VRAM_SIZE UL(0x02000000)
+
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE UL(0x20000000)
+#define DEVICE0_SIZE UL(0x0c200000)
+
+/*
+ * In case of FVP models with CCN, the CCN register space overlaps into
+ * the NSRAM area.
+ */
+#if FVP_INTERCONNECT_DRIVER == FVP_CCN
+#define DEVICE1_BASE UL(0x2e000000)
+#define DEVICE1_SIZE UL(0x1A00000)
+#else
+#define DEVICE1_BASE BASE_GICD_BASE
+
+#if GIC_ENABLE_V4_EXTN
+/* GICv4 mapping: GICD + CORE_COUNT * 256KB */
+#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \
+ (PLATFORM_CORE_COUNT * 0x40000))
+#else
+/* GICv2 and GICv3 mapping: GICD + CORE_COUNT * 128KB */
+#define DEVICE1_SIZE ((BASE_GICR_BASE - BASE_GICD_BASE) + \
+ (PLATFORM_CORE_COUNT * 0x20000))
+#endif /* GIC_ENABLE_V4_EXTN */
+
+#define NSRAM_BASE UL(0x2e000000)
+#define NSRAM_SIZE UL(0x10000)
+#endif
+/* Devices in the second GB */
+#define DEVICE2_BASE UL(0x7fe00000)
+#define DEVICE2_SIZE UL(0x00200000)
+
+#define PCIE_EXP_BASE UL(0x40000000)
+#define TZRNG_BASE UL(0x7fe60000)
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE UL(0x7fe70000)
+#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000))
+#define TFW_NVCTR_SIZE UL(4)
+#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004))
+#define NTFW_CTR_SIZE UL(4)
+
+/* Keys */
+#define SOC_KEYS_BASE UL(0x7fe80000)
+#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000))
+#define TZ_PUB_KEY_HASH_SIZE UL(32)
+#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020))
+#define HU_KEY_SIZE UL(16)
+#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044))
+#define END_KEY_SIZE UL(32)
+
+/* Constants to distinguish FVP type */
+#define HBI_BASE_FVP U(0x020)
+#define REV_BASE_FVP_V0 U(0x0)
+#define REV_BASE_FVP_REVC U(0x2)
+
+#define HBI_FOUNDATION_FVP U(0x010)
+#define REV_FOUNDATION_FVP_V2_0 U(0x0)
+#define REV_FOUNDATION_FVP_V2_1 U(0x1)
+#define REV_FOUNDATION_FVP_v9_1 U(0x2)
+#define REV_FOUNDATION_FVP_v9_6 U(0x3)
+
+#define BLD_GIC_VE_MMAP U(0x0)
+#define BLD_GIC_A53A57_MMAP U(0x1)
+
+#define ARCH_MODEL U(0x1)
+
+/* FVP Power controller base address*/
+#define PWRC_BASE UL(0x1c100000)
+
+/* FVP SP804 timer frequency is 35 MHz*/
+#define SP804_TIMER_CLKMULT 1
+#define SP804_TIMER_CLKDIV 35
+
+/* SP810 controller. FVP specific flags */
+#define FVP_SP810_CTRL_TIM0_OV BIT_32(16)
+#define FVP_SP810_CTRL_TIM1_OV BIT_32(18)
+#define FVP_SP810_CTRL_TIM2_OV BIT_32(20)
+#define FVP_SP810_CTRL_TIM3_OV BIT_32(22)
+
+/*******************************************************************************
+ * GIC & interrupt handling related constants
+ ******************************************************************************/
+/* VE compatible GIC memory map */
+#define VE_GICD_BASE UL(0x2c001000)
+#define VE_GICC_BASE UL(0x2c002000)
+#define VE_GICH_BASE UL(0x2c004000)
+#define VE_GICV_BASE UL(0x2c006000)
+
+/* Base FVP compatible GIC memory map */
+#define BASE_GICD_BASE UL(0x2f000000)
+#define BASE_GICD_SIZE UL(0x10000)
+#define BASE_GICR_BASE UL(0x2f100000)
+
+#if GIC_ENABLE_V4_EXTN
+/* GICv4 redistributor size: 256KB */
+#define BASE_GICR_SIZE UL(0x40000)
+#else
+#define BASE_GICR_SIZE UL(0x20000)
+#endif /* GIC_ENABLE_V4_EXTN */
+
+#define BASE_GICC_BASE UL(0x2c000000)
+#define BASE_GICH_BASE UL(0x2c010000)
+#define BASE_GICV_BASE UL(0x2c02f000)
+
+#define FVP_IRQ_TZ_WDOG 56
+#define FVP_IRQ_SEC_SYS_TIMER 57
+
+/*******************************************************************************
+ * TrustZone address space controller related constants
+ ******************************************************************************/
+
+/* NSAIDs used by devices in TZC filter 0 on FVP */
+#define FVP_NSAID_DEFAULT 0
+#define FVP_NSAID_PCI 1
+#define FVP_NSAID_VIRTIO 8 /* from FVP v5.6 onwards */
+#define FVP_NSAID_AP 9 /* Application Processors */
+#define FVP_NSAID_VIRTIO_OLD 15 /* until FVP v5.5 */
+
+/* NSAIDs used by devices in TZC filter 2 on FVP */
+#define FVP_NSAID_HDLCD0 2
+#define FVP_NSAID_CLCD 7
+
+/*******************************************************************************
+ * Memprotect definitions
+ ******************************************************************************/
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \
+ V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#endif /* FVP_DEF_H */
diff --git a/plat/arm/board/fvp/fvp_drtm_addr.c b/plat/arm/board/fvp/fvp_drtm_addr.c
new file mode 100644
index 0000000..eeaa342
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_drtm_addr.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Check passed region is within Non-Secure region of DRAM
+ ******************************************************************************/
+int plat_drtm_validate_ns_region(uintptr_t region_start,
+ size_t region_size)
+{
+ uintptr_t region_end = region_start + region_size - 1;
+
+ if (region_start >= region_end) {
+ return -1;
+ } else if ((region_start >= ARM_NS_DRAM1_BASE) &&
+ (region_start < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE)) &&
+ (region_end >= ARM_NS_DRAM1_BASE) &&
+ (region_end < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) {
+ return 0;
+ } else if ((region_start >= ARM_DRAM2_BASE) &&
+ (region_start < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE)) &&
+ (region_end >= ARM_DRAM2_BASE) &&
+ (region_end < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) {
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/plat/arm/board/fvp/fvp_drtm_dma_prot.c b/plat/arm/board/fvp/fvp_drtm_dma_prot.c
new file mode 100644
index 0000000..38ff7fe
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_drtm_dma_prot.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <drivers/arm/smmu_v3.h>
+#include <lib/utils_def.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/**
+ * Array mentioning number of SMMUs supported by FVP
+ */
+static const uintptr_t fvp_smmus[] = {
+ PLAT_FVP_SMMUV3_BASE,
+};
+
+bool plat_has_non_host_platforms(void)
+{
+ /* FVP base platforms typically have GPU, as per FVP Reference guide */
+ return true;
+}
+
+bool plat_has_unmanaged_dma_peripherals(void)
+{
+ /*
+ * FVP Reference guide does not show devices that are described as
+ * DMA-capable but not managed by an SMMU in the FVP documentation.
+ * However, the SMMU seems to have only been introduced in the RevC
+ * revision.
+ */
+ return (arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) == 0;
+}
+
+unsigned int plat_get_total_smmus(void)
+{
+ if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) {
+ return ARRAY_SIZE(fvp_smmus);
+ } else {
+ return 0;
+ }
+}
+
+void plat_enumerate_smmus(const uintptr_t **smmus_out,
+ size_t *smmu_count_out)
+{
+ if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) {
+ *smmus_out = fvp_smmus;
+ *smmu_count_out = ARRAY_SIZE(fvp_smmus);
+ } else {
+ *smmus_out = NULL;
+ *smmu_count_out = 0;
+ }
+}
+
+/* DRTM DMA Protection Features */
+static const plat_drtm_dma_prot_features_t dma_prot_features = {
+ .max_num_mem_prot_regions = 0, /* No protection regions are present */
+ .dma_protection_support = 0x1 /* Complete DMA protection only */
+};
+
+const plat_drtm_dma_prot_features_t *plat_drtm_get_dma_prot_features(void)
+{
+ return &dma_prot_features;
+}
+
+uint64_t plat_drtm_dma_prot_get_max_table_bytes(void)
+{
+ return 0U;
+}
diff --git a/plat/arm/board/fvp/fvp_drtm_err.c b/plat/arm/board/fvp/fvp_drtm_err.c
new file mode 100644
index 0000000..95259fa
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_drtm_err.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <plat/common/platform.h>
+
+int plat_set_drtm_error(uint64_t error_code)
+{
+ /* TODO: Set DRTM error in NV-storage */
+ return 0;
+}
+
+int plat_get_drtm_error(uint64_t *error_code)
+{
+ /* TODO: Get DRTM error from NV-storage */
+ *error_code = 0;
+ return 0;
+}
diff --git a/plat/arm/board/fvp/fvp_drtm_measurement.c b/plat/arm/board/fvp/fvp_drtm_measurement.c
new file mode 100644
index 0000000..4fbedd8
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_drtm_measurement.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* DRTM TPM Features */
+static const plat_drtm_tpm_features_t tpm_features = {
+ /* No TPM-based hashing supported. */
+ .tpm_based_hash_support = false,
+
+ /* Set to decided algorithm by Event Log driver */
+ .firmware_hash_algorithm = TPM_ALG_ID
+
+};
+
+const plat_drtm_tpm_features_t *plat_drtm_get_tpm_features(void)
+{
+ return &tpm_features;
+}
diff --git a/plat/arm/board/fvp/fvp_drtm_stub.c b/plat/arm/board/fvp/fvp_drtm_stub.c
new file mode 100644
index 0000000..e2bc516
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_drtm_stub.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <stdint.h>
+
+#include <services/drtm_svc.h>
+
+/*
+ * This file contains DRTM platform functions which don't really do anything on
+ * FVP but are needed for DRTM to function.
+ */
+
+uint64_t plat_drtm_get_min_size_normal_world_dce(void)
+{
+ return 0ULL;
+}
+
+uint64_t plat_drtm_get_imp_def_dlme_region_size(void)
+{
+ return 0ULL;
+}
+
+uint64_t plat_drtm_get_tcb_hash_features(void)
+{
+ return 0ULL;
+}
+
+uint64_t plat_drtm_get_tcb_hash_table_size(void)
+{
+ return 0ULL;
+}
diff --git a/plat/arm/board/fvp/fvp_el3_spmc.c b/plat/arm/board/fvp/fvp_el3_spmc.c
new file mode 100644
index 0000000..2b347ed
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_el3_spmc.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <services/el3_spmc_ffa_memory.h>
+
+#include <platform_def.h>
+
+/*
+ * On the FVP platform when using the EL3 SPMC implementation allocate the
+ * datastore for tracking shared memory descriptors in the TZC DRAM section
+ * to ensure sufficient storage can be allocated.
+ * Provide an implementation of the accessor method to allow the datastore
+ * details to be retrieved by the SPMC.
+ * The SPMC will take care of initializing the memory region.
+ */
+
+#define PLAT_SPMC_SHMEM_DATASTORE_SIZE 512 * 1024
+
+__section("arm_el3_tzc_dram") static uint8_t
+plat_spmc_shmem_datastore[PLAT_SPMC_SHMEM_DATASTORE_SIZE];
+
+int plat_spmc_shmem_datastore_get(uint8_t **datastore, size_t *size)
+{
+ *datastore = plat_spmc_shmem_datastore;
+ *size = PLAT_SPMC_SHMEM_DATASTORE_SIZE;
+ return 0;
+}
+
+/*
+ * Add dummy implementations of memory management related platform hooks.
+ * These can be used to implement platform specific functionality to support
+ * a memory sharing/lending operation.
+ *
+ * Note: The hooks must be located as part of the initial share request and
+ * final reclaim to prevent order dependencies with operations that may take
+ * place in the normal world without visibility of the SPMC.
+ */
+int plat_spmc_shmem_begin(struct ffa_mtd *desc)
+{
+ return 0;
+}
+int plat_spmc_shmem_reclaim(struct ffa_mtd *desc)
+{
+ return 0;
+}
diff --git a/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c b/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c
new file mode 100644
index 0000000..b9e4f86
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_el3_spmc_logical_sp.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <services/el3_spmc_logical_sp.h>
+#include <services/ffa_svc.h>
+#include <smccc_helpers.h>
+
+#define LP_PARTITION_ID 0xC001
+#define LP_UUID {0x47a3bf57, 0xe98e43ad, 0xb7db524f, 0x1588f4e3}
+
+/* Our Logical SP currently only supports receipt of direct messaging. */
+#define PARTITION_PROPERTIES FFA_PARTITION_DIRECT_REQ_RECV
+
+static int32_t sp_init(void)
+{
+ INFO("LSP: Init function called.\n");
+ return 0;
+}
+
+static uint64_t handle_ffa_direct_request(uint32_t smc_fid, bool secure_origin,
+ uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie,
+ void *handle, uint64_t flags)
+{
+ uint64_t ret;
+
+ /* Determine if we have a 64 or 32 direct request. */
+ if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC32) {
+ ret = FFA_MSG_SEND_DIRECT_RESP_SMC32;
+ } else if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC64) {
+ ret = FFA_MSG_SEND_DIRECT_RESP_SMC64;
+ } else {
+ panic(); /* Unknown SMC. */
+ }
+ /*
+ * Handle the incoming request. For testing purposes we echo the
+ * incoming message.
+ */
+ INFO("Logical Partition: Received Direct Request from %s world!\n",
+ secure_origin ? "Secure" : "Normal");
+
+ /*
+ * Logical SP's must always send a direct response so we can populate
+ * our response directly.
+ */
+ SMC_RET8(handle, ret, 0, 0, x4, 0, 0, 0, 0);
+}
+
+/* Register logical partition */
+DECLARE_LOGICAL_PARTITION(
+ my_logical_partition,
+ sp_init, /* Init Function */
+ LP_PARTITION_ID, /* FF-A Partition ID */
+ LP_UUID, /* UUID */
+ PARTITION_PROPERTIES, /* Partition Properties. */
+ handle_ffa_direct_request /* Callback for direct requests. */
+);
diff --git a/plat/arm/board/fvp/fvp_err.c b/plat/arm/board/fvp/fvp_err.c
new file mode 100644
index 0000000..244659a
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_err.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/cfi/v2m_flash.h>
+#include <lib/mmio.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*
+ * FVP error handler
+ */
+__dead2 void plat_arm_error_handler(int err)
+{
+ /* Propagate the err code in the NV-flags register */
+ mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err);
+
+ console_flush();
+
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ for (;;)
+ wfi();
+}
+
+void __dead2 plat_arm_system_reset(void)
+{
+ /* Write the System Configuration Control Register */
+ mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL,
+ V2M_CFGCTRL_START |
+ V2M_CFGCTRL_RW |
+ V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT));
+ wfi();
+ ERROR("FVP System Reset: operation not handled.\n");
+ panic();
+}
diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c
new file mode 100644
index 0000000..e780f21
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_gicv3.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <fconf_hw_config_getter.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/common/fconf_sec_intr_config.h>
+#include <plat/common/platform.h>
+
+#if FVP_GICR_REGION_PROTECTION
+/* To indicate GICR region of the core initialized as Read-Write */
+static bool fvp_gicr_rw_region_init[PLATFORM_CORE_COUNT] = {false};
+#endif /* FVP_GICR_REGION_PROTECTION */
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* Default GICR base address to be used for GICR probe. */
+static uint64_t fvp_gicr_base_addrs[2] = { 0U };
+
+/* List of zero terminated GICR frame addresses which CPUs will probe */
+static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs;
+
+#if !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \
+ (defined(__aarch64__) && defined(IMAGE_BL31))))
+static const interrupt_prop_t fvp_interrupt_props[] = {
+ PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+#endif
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ * - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr)
+{
+ u_register_t temp_mpidr = mpidr;
+
+ temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+ return plat_arm_calc_core_pos(temp_mpidr);
+}
+
+
+static gicv3_driver_data_t fvp_gic_data = {
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = fvp_rdistif_base_addrs,
+ .mpidr_to_core_pos = fvp_gicv3_mpidr_hash
+};
+
+/******************************************************************************
+ * This function gets called per core to make its redistributor frame rw
+ *****************************************************************************/
+static void fvp_gicv3_make_rdistrif_rw(void)
+{
+#if FVP_GICR_REGION_PROTECTION
+ unsigned int core_pos = plat_my_core_pos();
+
+ /* Make the redistributor frame RW if it is not done previously */
+ if (fvp_gicr_rw_region_init[core_pos] != true) {
+ int ret = xlat_change_mem_attributes(BASE_GICR_BASE +
+ (core_pos * BASE_GICR_SIZE),
+ BASE_GICR_SIZE,
+ MT_EXECUTE_NEVER |
+ MT_DEVICE | MT_RW |
+ MT_SECURE);
+
+ if (ret != 0) {
+ ERROR("Failed to make redistributor frame \
+ read write = %d\n", ret);
+ panic();
+ } else {
+ fvp_gicr_rw_region_init[core_pos] = true;
+ }
+ }
+#else
+ return;
+#endif /* FVP_GICR_REGION_PROTECTION */
+}
+
+void plat_arm_gic_driver_init(void)
+{
+ fvp_gicv3_make_rdistrif_rw();
+ /*
+ * Get GICD and GICR base addressed through FCONF APIs.
+ * FCONF is not supported in BL32 for FVP.
+ */
+#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
+ (defined(__aarch64__) && defined(IMAGE_BL31))
+ fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config,
+ gicv3_config,
+ gicd_base);
+ fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config,
+ gicr_base);
+#if SEC_INT_DESC_IN_FCONF
+ fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config,
+ sec_intr_prop, descriptor);
+ fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config,
+ sec_intr_prop, count);
+#else
+ fvp_gic_data.interrupt_props = fvp_interrupt_props;
+ fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+#endif
+#else
+ fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE;
+ fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE;
+ fvp_gic_data.interrupt_props = fvp_interrupt_props;
+ fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+#endif
+
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+
+#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
+ (defined(__aarch64__) && defined(IMAGE_BL31))
+ gicv3_driver_init(&fvp_gic_data);
+ if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) {
+ ERROR("No GICR base frame found for Primary CPU\n");
+ panic();
+ }
+#endif
+}
+
+/******************************************************************************
+ * Function to iterate over all GICR frames and discover the corresponding
+ * per-cpu redistributor frame as well as initialize the corresponding
+ * interface in GICv3.
+ *****************************************************************************/
+void plat_arm_gic_pcpu_init(void)
+{
+ int result;
+ const uint64_t *plat_gicr_frames = fvp_gicr_frames;
+
+ fvp_gicv3_make_rdistrif_rw();
+
+ do {
+ result = gicv3_rdistif_probe(*plat_gicr_frames);
+
+ /* If the probe is successful, no need to proceed further */
+ if (result == 0)
+ break;
+
+ plat_gicr_frames++;
+ } while (*plat_gicr_frames != 0U);
+
+ if (result == -1) {
+ ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
+ panic();
+ }
+ gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/arm/board/fvp/fvp_io_storage.c b/plat/arm/board/fvp/fvp_io_storage.c
new file mode 100644
index 0000000..4eef51c
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_io_storage.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_semihosting.h>
+#include <drivers/io/io_storage.h>
+#include <lib/semihosting.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+
+/* Semihosting filenames */
+#define BL2_IMAGE_NAME "bl2.bin"
+#define BL31_IMAGE_NAME "bl31.bin"
+#define BL32_IMAGE_NAME "bl32.bin"
+#define BL33_IMAGE_NAME "bl33.bin"
+#define TB_FW_CONFIG_NAME "fvp_tb_fw_config.dtb"
+#define SOC_FW_CONFIG_NAME "fvp_soc_fw_config.dtb"
+#define TOS_FW_CONFIG_NAME "fvp_tsp_fw_config.dtb"
+#define NT_FW_CONFIG_NAME "fvp_nt_fw_config.dtb"
+#define FW_CONFIG_NAME "fvp_fw_config.dtb"
+#define HW_CONFIG_NAME "hw_config.dtb"
+
+#if TRUSTED_BOARD_BOOT
+#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt"
+#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
+#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt"
+#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt"
+#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt"
+#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt"
+#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt"
+#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* IO devices */
+static const io_dev_connector_t *sh_dev_con;
+static uintptr_t sh_dev_handle;
+
+static const io_file_spec_t sh_file_spec[] = {
+ [BL2_IMAGE_ID] = {
+ .path = BL2_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL31_IMAGE_ID] = {
+ .path = BL31_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL32_IMAGE_ID] = {
+ .path = BL32_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL33_IMAGE_ID] = {
+ .path = BL33_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TB_FW_CONFIG_ID] = {
+ .path = TB_FW_CONFIG_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [SOC_FW_CONFIG_ID] = {
+ .path = SOC_FW_CONFIG_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TOS_FW_CONFIG_ID] = {
+ .path = TOS_FW_CONFIG_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NT_FW_CONFIG_ID] = {
+ .path = NT_FW_CONFIG_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [FW_CONFIG_ID] = {
+ .path = FW_CONFIG_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [HW_CONFIG_ID] = {
+ .path = HW_CONFIG_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ .path = TRUSTED_BOOT_FW_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ .path = TRUSTED_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ .path = SOC_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ .path = TOS_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ .path = NT_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ .path = SOC_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ .path = TOS_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ .path = NT_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+
+static int open_semihosting(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if the file exists on semi-hosting.*/
+ result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(sh_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Semi-hosting IO\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+void plat_arm_io_setup(void)
+{
+ int io_result;
+
+ io_result = arm_io_setup();
+ if (io_result < 0) {
+ panic();
+ }
+
+ /* Register the additional IO devices on this platform */
+ io_result = register_io_dev_sh(&sh_dev_con);
+ if (io_result < 0) {
+ panic();
+ }
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
+ if (io_result < 0) {
+ panic();
+ }
+}
+
+/*
+ * FVP provides semihosting as an alternative to load images
+ */
+int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
+ if (result == 0) {
+ *dev_handle = sh_dev_handle;
+ *image_spec = (uintptr_t)&sh_file_spec[image_id];
+ }
+
+ return result;
+}
diff --git a/plat/arm/board/fvp/fvp_plat_attest_token.c b/plat/arm/board/fvp/fvp_plat_attest_token.c
new file mode 100644
index 0000000..4dd37a4
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_plat_attest_token.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+
+/* Using hardcoded token values for AEM FVP */
+static uint8_t platform_token[] = {
+ 0xD2, 0x84, 0x40, 0xA0, 0x59, 0x02, 0x46, 0xA9,
+ 0x19, 0x01, 0x09, 0x78, 0x1C, 0x68, 0x74, 0x74,
+ 0x70, 0x3A, 0x2F, 0x2F, 0x61, 0x72, 0x6D, 0x2E,
+ 0x63, 0x6F, 0x6D, 0x2F, 0x43, 0x43, 0x41, 0x2D,
+ 0x53, 0x53, 0x44, 0x2F, 0x31, 0x2E, 0x30, 0x2E,
+ 0x30, 0x0A, 0x58, 0x20, 0x07, 0x06, 0x05, 0x04,
+ 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C,
+ 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, 0x14,
+ 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, 0x1C,
+ 0x1B, 0x1A, 0x19, 0x18, 0x19, 0x09, 0x5C, 0x58,
+ 0x40, 0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x50, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xA0, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38,
+ 0x00, 0x09, 0x00, 0x40, 0x00, 0x1C, 0x00, 0x1B,
+ 0x00, 0x19, 0x01, 0x00, 0x58, 0x21, 0x01, 0x07,
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F,
+ 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17,
+ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F,
+ 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x19,
+ 0x09, 0x61, 0x58, 0x21, 0x01, 0x07, 0x06, 0x05,
+ 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D,
+ 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15,
+ 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D,
+ 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x19, 0x09, 0x5B,
+ 0x19, 0x30, 0x03, 0x19, 0x09, 0x62, 0x67, 0x73,
+ 0x68, 0x61, 0x2D, 0x32, 0x35, 0x36, 0x19, 0x09,
+ 0x5F, 0x84, 0xA5, 0x01, 0x62, 0x42, 0x4C, 0x05,
+ 0x58, 0x20, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
+ 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A,
+ 0x09, 0x08, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12,
+ 0x11, 0x10, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A,
+ 0x19, 0x18, 0x04, 0x65, 0x33, 0x2E, 0x34, 0x2E,
+ 0x32, 0x02, 0x58, 0x20, 0x07, 0x06, 0x05, 0x04,
+ 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C,
+ 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15, 0x14,
+ 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D, 0x1C,
+ 0x1B, 0x1A, 0x19, 0x18, 0x06, 0x67, 0x73, 0x68,
+ 0x61, 0x2D, 0x32, 0x35, 0x36, 0xA4, 0x01, 0x62,
+ 0x4D, 0x31, 0x05, 0x58, 0x20, 0x07, 0x06, 0x05,
+ 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D,
+ 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15,
+ 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D,
+ 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x04, 0x63, 0x31,
+ 0x2E, 0x32, 0x02, 0x58, 0x20, 0x07, 0x06, 0x05,
+ 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D,
+ 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15,
+ 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D,
+ 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0xA4, 0x01, 0x62,
+ 0x4D, 0x32, 0x05, 0x58, 0x20, 0x07, 0x06, 0x05,
+ 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D,
+ 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15,
+ 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D,
+ 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x04, 0x65, 0x31,
+ 0x2E, 0x32, 0x2E, 0x33, 0x02, 0x58, 0x20, 0x07,
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F,
+ 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17,
+ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F,
+ 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0xA4,
+ 0x01, 0x62, 0x4D, 0x33, 0x05, 0x58, 0x20, 0x07,
+ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F,
+ 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17,
+ 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F,
+ 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x04,
+ 0x61, 0x31, 0x02, 0x58, 0x20, 0x07, 0x06, 0x05,
+ 0x04, 0x03, 0x02, 0x01, 0x00, 0x0F, 0x0E, 0x0D,
+ 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x17, 0x16, 0x15,
+ 0x14, 0x13, 0x12, 0x11, 0x10, 0x1F, 0x1E, 0x1D,
+ 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x19, 0x09, 0x60,
+ 0x6C, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65,
+ 0x72, 0x2E, 0x63, 0x6F, 0x6D, 0x58, 0x40, 0x84,
+ 0x32, 0x12, 0x5B, 0x92, 0x6B, 0x20, 0xD8, 0x14,
+ 0xC1, 0xC1, 0x8C, 0x3C, 0x73, 0xB8, 0x29, 0x0F,
+ 0x42, 0xBC, 0x0B, 0x25, 0x87, 0x5C, 0x4F, 0xA4,
+ 0xFA, 0xD9, 0xDE, 0xC1, 0x2B, 0x20, 0xED, 0xDF,
+ 0x1C, 0xDD, 0x1A, 0x09, 0xBD, 0xA0, 0x25, 0x48,
+ 0xC6, 0xBB, 0x99, 0xA1, 0x30, 0x4F, 0x2C, 0xDC,
+ 0x89, 0xE8, 0xB7, 0xFF, 0x32, 0xE9, 0x3F, 0xBB,
+ 0xC6, 0xBF, 0x9D, 0x38, 0x68, 0xE1, 0xB2,
+};
+
+int plat_rmmd_get_cca_attest_token(uintptr_t buf, size_t *len,
+ uintptr_t hash, size_t hash_size)
+{
+ (void)hash;
+ (void)hash_size;
+
+ if (*len < sizeof(platform_token)) {
+ return -EINVAL;
+ }
+
+ (void)memcpy((void *)buf, platform_token, sizeof(platform_token));
+ *len = sizeof(platform_token);
+
+ return 0;
+}
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
new file mode 100644
index 0000000..6b9d618
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <lib/extensions/spe.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+#include "fvp_private.h"
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+
+
+#if ARM_RECOM_STATE_ID_ENC
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+const unsigned int arm_pm_idle_states[] = {
+ /* State-id - 0x01 */
+ arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RET,
+ ARM_PWR_LVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x02 */
+ arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF,
+ ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x22 */
+ arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
+ ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x222 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
+ ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
+ 0,
+};
+#endif
+
+/*******************************************************************************
+ * Function which implements the common FVP specific operations to power down a
+ * cluster in response to a CPU_OFF or CPU_SUSPEND request.
+ ******************************************************************************/
+static void fvp_cluster_pwrdwn_common(void)
+{
+ uint64_t mpidr = read_mpidr_el1();
+
+#if ENABLE_SPE_FOR_LOWER_ELS
+ /*
+ * On power down we need to disable statistical profiling extensions
+ * before exiting coherency.
+ */
+ spe_disable();
+#endif
+
+ /* Disable coherency if this cluster is to be turned off */
+ fvp_interconnect_disable();
+
+#if HW_ASSISTED_COHERENCY
+ uint32_t reg;
+
+ /*
+ * If we have determined this core to be the last man standing and we
+ * intend to power down the cluster proactively, we provide a hint to
+ * the power controller that cluster power is not required when all
+ * cores are powered down.
+ * Note that this is only an advisory to power controller and is supported
+ * by SoCs with DynamIQ Shared Units only.
+ */
+ reg = read_clusterpwrdn();
+
+ /* Clear and set bit 0 : Cluster power not required */
+ reg &= ~DSU_CLUSTER_PWR_MASK;
+ reg |= DSU_CLUSTER_PWR_OFF;
+ write_clusterpwrdn(reg);
+#endif
+
+ /* Program the power controller to turn the cluster off */
+ fvp_pwrc_write_pcoffr(mpidr);
+}
+
+/*
+ * Empty implementation of these hooks avoid setting the GICR_WAKER.Sleep bit
+ * on ARM GICv3 implementations on FVP. This is required, because FVP does not
+ * support SYSTEM_SUSPEND and it is `faked` in firmware. Hence, for wake up
+ * from `fake` system suspend the GIC must not be powered off.
+ */
+void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
+{}
+
+void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num)
+{}
+
+static void fvp_power_domain_on_finish_common(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr;
+
+ assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
+ ARM_LOCAL_STATE_OFF);
+
+ /* Get the mpidr for this cpu */
+ mpidr = read_mpidr_el1();
+
+ /* Perform the common cluster specific operations */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
+ ARM_LOCAL_STATE_OFF) {
+ /*
+ * This CPU might have woken up whilst the cluster was
+ * attempting to power down. In this case the FVP power
+ * controller will have a pending cluster power off request
+ * which needs to be cleared by writing to the PPONR register.
+ * This prevents the power controller from interpreting a
+ * subsequent entry of this cpu into a simple wfi as a power
+ * down request.
+ */
+ fvp_pwrc_write_pponr(mpidr);
+
+ /* Enable coherency if this cluster was off */
+ fvp_interconnect_enable();
+ }
+ /* Perform the common system specific operations */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
+ ARM_LOCAL_STATE_OFF)
+ arm_system_pwr_domain_resume();
+
+ /*
+ * Clear PWKUPR.WEN bit to ensure interrupts do not interfere
+ * with a cpu power down unless the bit is set again
+ */
+ fvp_pwrc_clr_wen(mpidr);
+}
+
+/*******************************************************************************
+ * FVP handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+static void fvp_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr = read_scr_el3();
+
+ assert(cpu_state == ARM_LOCAL_STATE_RET);
+
+ /*
+ * Enable the Non-secure interrupt to wake the CPU.
+ * In GICv3 affinity routing mode, the Non-secure Group 1 interrupts
+ * use Physical FIQ at EL3 whereas in GICv2, Physical IRQ is used.
+ * Enabling both the bits works for both GICv2 mode and GICv3 affinity
+ * routing mode.
+ */
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+ isb();
+
+ /*
+ * Enter standby state.
+ * dsb is good practice before using wfi to enter low power states.
+ */
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR_EL3 to the original value, synchronisation of SCR_EL3
+ * is done by eret in el3_exit() to save some execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+/*******************************************************************************
+ * FVP handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int fvp_pwr_domain_on(u_register_t mpidr)
+{
+ int rc = PSCI_E_SUCCESS;
+ unsigned int psysr;
+
+ /*
+ * Ensure that we do not cancel an inflight power off request for the
+ * target cpu. That would leave it in a zombie wfi. Wait for it to power
+ * off and then program the power controller to turn that CPU on.
+ */
+ do {
+ psysr = fvp_pwrc_read_psysr(mpidr);
+ } while ((psysr & PSYSR_AFF_L0) != 0U);
+
+ fvp_pwrc_write_pponr(mpidr);
+ return rc;
+}
+
+/*******************************************************************************
+ * FVP handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void fvp_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
+ ARM_LOCAL_STATE_OFF);
+
+ /*
+ * If execution reaches this stage then this power domain will be
+ * suspended. Perform at least the cpu specific actions followed
+ * by the cluster specific operations if applicable.
+ */
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_arm_gic_cpuif_disable();
+
+ /* Turn redistributor off */
+ plat_arm_gic_redistif_off();
+
+ /* Program the power controller to power off this cpu. */
+ fvp_pwrc_write_ppoffr(read_mpidr_el1());
+
+ if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
+ ARM_LOCAL_STATE_OFF)
+ fvp_cluster_pwrdwn_common();
+
+}
+
+/*******************************************************************************
+ * FVP handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void fvp_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr;
+
+ /*
+ * FVP has retention only at cpu level. Just return
+ * as nothing is to be done for retention.
+ */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL0] ==
+ ARM_LOCAL_STATE_RET)
+ return;
+
+ assert(target_state->pwr_domain_state[ARM_PWR_LVL0] ==
+ ARM_LOCAL_STATE_OFF);
+
+ /* Get the mpidr for this cpu */
+ mpidr = read_mpidr_el1();
+
+ /* Program the power controller to enable wakeup interrupts. */
+ fvp_pwrc_set_wen(mpidr);
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_arm_gic_cpuif_disable();
+
+ /*
+ * The Redistributor is not powered off as it can potentially prevent
+ * wake up events reaching the CPUIF and/or might lead to losing
+ * register context.
+ */
+
+ /* Perform the common cluster specific operations */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL1] ==
+ ARM_LOCAL_STATE_OFF)
+ fvp_cluster_pwrdwn_common();
+
+ /* Perform the common system specific operations */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL2] ==
+ ARM_LOCAL_STATE_OFF)
+ arm_system_pwr_domain_save();
+
+ /* Program the power controller to power off this cpu. */
+ fvp_pwrc_write_ppoffr(read_mpidr_el1());
+}
+
+/*******************************************************************************
+ * FVP handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+static void fvp_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ fvp_power_domain_on_finish_common(target_state);
+
+}
+
+/*******************************************************************************
+ * FVP handler called when a power domain has just been powered on and the cpu
+ * and its cluster are fully participating in coherent transaction on the
+ * interconnect. Data cache must be enabled for CPU at this point.
+ ******************************************************************************/
+static void fvp_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
+{
+ /* Program GIC per-cpu distributor or re-distributor interface */
+ plat_arm_gic_pcpu_init();
+
+ /* Enable GIC CPU interface */
+ plat_arm_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * FVP handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+static void fvp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ /*
+ * Nothing to be done on waking up from retention from CPU level.
+ */
+ if (target_state->pwr_domain_state[ARM_PWR_LVL0] ==
+ ARM_LOCAL_STATE_RET)
+ return;
+
+ fvp_power_domain_on_finish_common(target_state);
+
+ /* Enable GIC CPU interface */
+ plat_arm_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * FVP handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 fvp_system_off(void)
+{
+ /* Write the System Configuration Control Register */
+ mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL,
+ V2M_CFGCTRL_START |
+ V2M_CFGCTRL_RW |
+ V2M_CFGCTRL_FUNC(V2M_FUNC_SHUTDOWN));
+ wfi();
+ ERROR("FVP System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 fvp_system_reset(void)
+{
+ /* Write the System Configuration Control Register */
+ mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL,
+ V2M_CFGCTRL_START |
+ V2M_CFGCTRL_RW |
+ V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT));
+ wfi();
+ ERROR("FVP System Reset: operation not handled.\n");
+ panic();
+}
+
+static int fvp_node_hw_state(u_register_t target_cpu,
+ unsigned int power_level)
+{
+ unsigned int psysr;
+ int ret;
+
+ /*
+ * The format of 'power_level' is implementation-defined, but 0 must
+ * mean a CPU. We also allow 1 to denote the cluster
+ */
+ if ((power_level != ARM_PWR_LVL0) && (power_level != ARM_PWR_LVL1))
+ return PSCI_E_INVALID_PARAMS;
+
+ /*
+ * Read the status of the given MPDIR from FVP power controller. The
+ * power controller only gives us on/off status, so map that to expected
+ * return values of the PSCI call
+ */
+ psysr = fvp_pwrc_read_psysr(target_cpu);
+ if (psysr == PSYSR_INVALID)
+ return PSCI_E_INVALID_PARAMS;
+
+ if (power_level == ARM_PWR_LVL0) {
+ ret = ((psysr & PSYSR_AFF_L0) != 0U) ? HW_ON : HW_OFF;
+ } else {
+ /* power_level == ARM_PWR_LVL1 */
+ ret = ((psysr & PSYSR_AFF_L1) != 0U) ? HW_ON : HW_OFF;
+ }
+
+ return ret;
+}
+
+/*
+ * The FVP doesn't truly support power management at SYSTEM power domain. The
+ * SYSTEM_SUSPEND will be down-graded to the cluster level within the platform
+ * layer. The `fake` SYSTEM_SUSPEND allows us to validate some of the driver
+ * save and restore sequences on FVP.
+ */
+#if !ARM_BL31_IN_DRAM
+static void fvp_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF;
+}
+#endif
+
+/*******************************************************************************
+ * Handler to filter PSCI requests.
+ ******************************************************************************/
+/*
+ * The system power domain suspend is only supported only via
+ * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain
+ * will be downgraded to the lower level.
+ */
+static int fvp_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int rc;
+ rc = arm_validate_power_state(power_state, req_state);
+
+ /*
+ * Ensure that the system power domain level is never suspended
+ * via PSCI CPU SUSPEND API. Currently system suspend is only
+ * supported via PSCI SYSTEM SUSPEND API.
+ */
+ req_state->pwr_domain_state[ARM_PWR_LVL2] = ARM_LOCAL_STATE_RUN;
+ return rc;
+}
+
+/*
+ * Custom `translate_power_state_by_mpidr` handler for FVP. Unlike in the
+ * `fvp_validate_power_state`, we do not downgrade the system power
+ * domain level request in `power_state` as it will be used to query the
+ * PSCI_STAT_COUNT/RESIDENCY at the system power domain level.
+ */
+static int fvp_translate_power_state_by_mpidr(u_register_t mpidr,
+ unsigned int power_state,
+ psci_power_state_t *output_state)
+{
+ return arm_validate_power_state(power_state, output_state);
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t plat_arm_psci_pm_ops = {
+ .cpu_standby = fvp_cpu_standby,
+ .pwr_domain_on = fvp_pwr_domain_on,
+ .pwr_domain_off = fvp_pwr_domain_off,
+ .pwr_domain_suspend = fvp_pwr_domain_suspend,
+ .pwr_domain_on_finish = fvp_pwr_domain_on_finish,
+ .pwr_domain_on_finish_late = fvp_pwr_domain_on_finish_late,
+ .pwr_domain_suspend_finish = fvp_pwr_domain_suspend_finish,
+ .system_off = fvp_system_off,
+ .system_reset = fvp_system_reset,
+ .validate_power_state = fvp_validate_power_state,
+ .validate_ns_entrypoint = arm_validate_psci_entrypoint,
+ .translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr,
+ .get_node_hw_state = fvp_node_hw_state,
+#if !ARM_BL31_IN_DRAM
+ /*
+ * The TrustZone Controller is set up during the warmboot sequence after
+ * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM
+ * this is not a problem but, if it is in TZC-secured DRAM, it tries to
+ * reconfigure the same memory it is running on, causing an exception.
+ */
+ .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state,
+#endif
+ .mem_protect_chk = arm_psci_mem_protect_chk,
+ .read_mem_protect = arm_psci_read_mem_protect,
+ .write_mem_protect = arm_nor_psci_write_mem_protect,
+};
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return ops;
+}
diff --git a/plat/arm/board/fvp/fvp_private.h b/plat/arm/board/fvp/fvp_private.h
new file mode 100644
index 0000000..3590370
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_private.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_PRIVATE_H
+#define FVP_PRIVATE_H
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+void fvp_config_setup(void);
+
+void fvp_interconnect_init(void);
+void fvp_interconnect_enable(void);
+void fvp_interconnect_disable(void);
+void fvp_timer_init(void);
+void tsp_early_platform_setup(void);
+
+#endif /* FVP_PRIVATE_H */
diff --git a/plat/arm/board/fvp/fvp_realm_attest_key.c b/plat/arm/board/fvp/fvp_realm_attest_key.c
new file mode 100644
index 0000000..1af1f0d
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_realm_attest_key.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <services/rmmd_svc.h>
+
+static uint8_t sample_attest_priv_key[] = {
+ 0x20, 0x11, 0xC7, 0xF0, 0x3C, 0xEE, 0x43, 0x25, 0x17, 0x6E,
+ 0x52, 0x4F, 0x03, 0x3C, 0x0C, 0xE1, 0xE2, 0x1A, 0x76, 0xE6,
+ 0xC1, 0xA4, 0xF0, 0xB8, 0x39, 0xAA, 0x1D, 0xF6, 0x1E, 0x0E,
+ 0x8A, 0x5C, 0x8A, 0x05, 0x74, 0x0F, 0x9B, 0x69, 0xEF, 0xA7,
+ 0xEB, 0x1A, 0x41, 0x85, 0xBD, 0x11, 0x7F, 0x68
+};
+
+int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
+ unsigned int type)
+{
+ assert(type == ATTEST_KEY_CURVE_ECC_SECP384R1);
+
+ if (*len < sizeof(sample_attest_priv_key)) {
+ return -EINVAL;
+ }
+
+ (void)memcpy((void *)buf, sample_attest_priv_key,
+ sizeof(sample_attest_priv_key));
+ *len = sizeof(sample_attest_priv_key);
+
+ return 0;
+}
diff --git a/plat/arm/board/fvp/fvp_security.c b/plat/arm/board/fvp/fvp_security.c
new file mode 100644
index 0000000..573d92e
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_security.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*
+ * We assume that all security programming is done by the primary core.
+ */
+void plat_arm_security_setup(void)
+{
+ /*
+ * The Base FVP has a TrustZone address space controller, the Foundation
+ * FVP does not. Trying to program the device on the foundation FVP will
+ * cause an abort.
+ *
+ * If the platform had additional peripheral specific security
+ * configurations, those would be configured here.
+ */
+
+ const arm_tzc_regions_info_t fvp_tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+#if !SPM_MM && !ENABLE_RME
+ {FVP_DRAM3_BASE, FVP_DRAM3_END,
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS},
+ {FVP_DRAM4_BASE, FVP_DRAM4_END,
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS},
+ {FVP_DRAM5_BASE, FVP_DRAM5_END,
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS},
+ {FVP_DRAM6_BASE, FVP_DRAM6_END,
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS},
+#endif
+ {0}
+ };
+
+ if ((get_arm_config()->flags & ARM_CONFIG_HAS_TZC) != 0U)
+ arm_tzc400_setup(PLAT_ARM_TZC_BASE, fvp_tzc_regions);
+}
diff --git a/plat/arm/board/fvp/fvp_stack_protector.c b/plat/arm/board/fvp/fvp_stack_protector.c
new file mode 100644
index 0000000..e940a12
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_stack_protector.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * Ideally, a random number should be returned instead of the
+ * combination of a timer's value and a compile-time constant. As the
+ * FVP does not have any random number generator, this is better than
+ * nothing but not necessarily really secure.
+ */
+ return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
+
diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c
new file mode 100644
index 0000000..80cfbd5
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_topology.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <fconf_hw_config_getter.h>
+#include <lib/cassert.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* The FVP power domain tree descriptor */
+static unsigned char fvp_power_domain_tree_desc[FVP_CLUSTER_COUNT + 2];
+
+
+CASSERT(((FVP_CLUSTER_COUNT > 0) && (FVP_CLUSTER_COUNT <= 256)),
+ assert_invalid_fvp_cluster_count);
+
+/*******************************************************************************
+ * This function dynamically constructs the topology according to cpu-map node
+ * in HW_CONFIG dtb and returns it.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ unsigned int i;
+ uint32_t cluster_count, cpus_per_cluster;
+
+ /*
+ * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and
+ * BL2_AT_EL3 systems.
+ */
+#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3
+ cluster_count = FVP_CLUSTER_COUNT;
+ cpus_per_cluster = FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU;
+#else
+ cluster_count = FCONF_GET_PROPERTY(hw_config, topology, plat_cluster_count);
+ cpus_per_cluster = FCONF_GET_PROPERTY(hw_config, topology, cluster_cpu_count);
+ /* Several FVP Models use the same blanket dts. Ex: FVP_Base_Cortex-A65x4
+ * and FVP_Base_Cortex-A65AEx8 both use same dts but have different number of
+ * CPUs in the cluster, as reflected by build flags FVP_MAX_CPUS_PER_CLUSTER.
+ * Take the minimum of two to ensure PSCI functions do not exceed the size of
+ * the PSCI data structures allocated at build time.
+ */
+ cpus_per_cluster = MIN(cpus_per_cluster,
+ (uint32_t)(FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU));
+
+#endif
+
+ assert(cluster_count > 0U);
+ assert(cpus_per_cluster > 0U);
+
+ /*
+ * The highest level is the system level. The next level is constituted
+ * by clusters and then cores in clusters.
+ */
+ fvp_power_domain_tree_desc[0] = 1;
+ fvp_power_domain_tree_desc[1] = (unsigned char)cluster_count;
+
+ for (i = 0; i < cluster_count; i++)
+ fvp_power_domain_tree_desc[i + 2] = (unsigned char)cpus_per_cluster;
+
+ return fvp_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+ return FVP_MAX_CPUS_PER_CLUSTER;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int clus_id, cpu_id, thread_id;
+
+ /* Validate affinity fields */
+ if ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) {
+ thread_id = MPIDR_AFFLVL0_VAL(mpidr);
+ cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
+ clus_id = MPIDR_AFFLVL2_VAL(mpidr);
+ } else {
+ thread_id = 0;
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+ clus_id = MPIDR_AFFLVL1_VAL(mpidr);
+ }
+
+ if (clus_id >= FVP_CLUSTER_COUNT)
+ return -1;
+ if (cpu_id >= FVP_MAX_CPUS_PER_CLUSTER)
+ return -1;
+ if (thread_id >= FVP_MAX_PE_PER_CPU)
+ return -1;
+
+ if (fvp_pwrc_read_psysr(mpidr) == PSYSR_INVALID)
+ return -1;
+
+ /*
+ * Core position calculation for FVP platform depends on the MT bit in
+ * MPIDR. This function cannot assume that the supplied MPIDR has the MT
+ * bit set even if the implementation has. For example, PSCI clients
+ * might supply MPIDR values without the MT bit set. Therefore, we
+ * inject the current PE's MT bit so as to get the calculation correct.
+ * This of course assumes that none or all CPUs on the platform has MT
+ * bit set.
+ */
+ mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+ return (int) plat_arm_calc_core_pos(mpidr);
+}
diff --git a/plat/arm/board/fvp/fvp_trusted_boot.c b/plat/arm/board/fvp/fvp_trusted_boot.c
new file mode 100644
index 0000000..1ea37f7
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_trusted_boot.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <lib/mmio.h>
+#include <lib/fconf/fconf.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/common/fconf_nv_cntr_getter.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <tools_share/tbbr_oid.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
+
+/*
+ * Store a new non-volatile counter value.
+ *
+ * On some FVP versions, the non-volatile counters are read-only so this
+ * function will always fail.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ const char *oid;
+ uintptr_t nv_ctr_addr;
+
+ assert(cookie != NULL);
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ TRUSTED_NV_CTR_ID);
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ NON_TRUSTED_NV_CTR_ID);
+ } else {
+ return 1;
+ }
+
+ mmio_write_32(nv_ctr_addr, nv_ctr);
+
+ /*
+ * If the FVP models a locked counter then its value cannot be updated
+ * and the above write operation has been silently ignored.
+ */
+ return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1;
+}
diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
new file mode 100644
index 0000000..ca85f7a
--- /dev/null
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_HW_CONFIG_GETTER_H
+#define FCONF_HW_CONFIG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* Hardware Config related getter */
+#define hw_config__gicv3_config_getter(prop) gicv3_config.prop
+#define hw_config__topology_getter(prop) soc_topology.prop
+#define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop
+#define hw_config__cpu_timer_getter(prop) cpu_timer.prop
+
+struct gicv3_config_t {
+ uint64_t gicd_base;
+ uint64_t gicr_base;
+};
+
+struct hw_topology_t {
+ uint32_t plat_cluster_count;
+ uint32_t cluster_cpu_count;
+ uint32_t plat_cpu_count;
+ uint32_t plat_max_pwr_level;
+};
+
+struct uart_serial_config_t {
+ uint64_t uart_base;
+ uint32_t uart_clk;
+};
+
+struct cpu_timer_t {
+ uint32_t clock_freq;
+};
+
+int fconf_populate_gicv3_config(uintptr_t config);
+int fconf_populate_topology(uintptr_t config);
+int fconf_populate_uart_config(uintptr_t config);
+int fconf_populate_cpu_timer(uintptr_t config);
+
+extern struct gicv3_config_t gicv3_config;
+extern struct hw_topology_t soc_topology;
+extern struct uart_serial_config_t uart_serial_config;
+extern struct cpu_timer_t cpu_timer;
+#endif /* FCONF_HW_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
new file mode 100644
index 0000000..0824c35
--- /dev/null
+++ b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_NT_CONFIG_GETTER_H
+#define FCONF_NT_CONFIG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* NT Firmware Config related getter */
+#define nt_config__event_log_config_getter(prop) event_log.prop
+
+struct event_log_config_t {
+#ifdef SPD_opteed
+ void *tpm_event_log_sm_addr;
+#endif
+ void *tpm_event_log_addr;
+ size_t tpm_event_log_size;
+};
+
+int fconf_populate_event_log_config(uintptr_t config);
+
+extern struct event_log_config_t event_log_config;
+
+#endif /* FCONF_NT_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/fvp_critical_data.h b/plat/arm/board/fvp/include/fvp_critical_data.h
new file mode 100644
index 0000000..04bd5b2
--- /dev/null
+++ b/plat/arm/board/fvp/include/fvp_critical_data.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef FVP_CRITICAL_DATA_H
+#define FVP_CRITICAL_DATA_H
+
+#include <common/nv_cntr_ids.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+
+#define EVLOG_CRITICAL_DATA_STRING "CRITICAL DATA"
+
+#define CRITICAL_DATA_ID CRITICAL_DATA_ID_BASE
+
+struct fvp_critical_data {
+
+ /* platform NV counters */
+ unsigned int nv_ctr[MAX_NV_CTR_IDS];
+};
+
+#endif /* FVP_CRITICAL_DATA_H */
diff --git a/plat/arm/board/fvp/include/plat.ld.S b/plat/arm/board/fvp/include/plat.ld.S
new file mode 100644
index 0000000..7c8bf06
--- /dev/null
+++ b/plat/arm/board/fvp/include/plat.ld.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_LD_S
+#define PLAT_LD_S
+
+#include <plat/arm/common/arm_tzc_dram.ld.S>
+
+#if RECLAIM_INIT_CODE
+#include <plat/arm/common/arm_reclaim_init.ld.S>
+#endif /* RECLAIM_INIT_CODE */
+
+#endif /* PLAT_LD_S */
diff --git a/plat/arm/board/fvp/include/plat_macros.S b/plat/arm/board/fvp/include/plat_macros.S
new file mode 100644
index 0000000..57f5924
--- /dev/null
+++ b/plat/arm/board/fvp/include/plat_macros.S
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+#include <platform_def.h>
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC registers whenever an
+ * unhandled exception is taken in BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /*
+ * Detect if we're using the base memory map or
+ * the legacy VE memory map
+ */
+ mov_imm x0, (V2M_SYSREGS_BASE + V2M_SYS_ID)
+ ldr w16, [x0]
+ /* Extract BLD (12th - 15th bits) from the SYS_ID */
+ ubfx x16, x16, #V2M_SYS_ID_BLD_SHIFT, #4
+ /* Check if VE mmap */
+ cmp w16, #BLD_GIC_VE_MMAP
+ b.eq use_ve_mmap
+ /* Assume Base Cortex mmap */
+ mov_imm x17, BASE_GICC_BASE
+ mov_imm x16, BASE_GICD_BASE
+ b print_gic_regs
+use_ve_mmap:
+ mov_imm x17, VE_GICC_BASE
+ mov_imm x16, VE_GICD_BASE
+print_gic_regs:
+ arm_print_gic_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
new file mode 100644
index 0000000..1ef6c87
--- /dev/null
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <drivers/arm/tzc400.h>
+#include <lib/utils_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/common/common_def.h>
+
+#include "../fvp_def.h"
+
+/* Required platform porting definitions */
+#define PLATFORM_CORE_COUNT (U(FVP_CLUSTER_COUNT) * \
+ U(FVP_MAX_CPUS_PER_CLUSTER) * \
+ U(FVP_MAX_PE_PER_CPU))
+
+#define PLAT_NUM_PWR_DOMAINS (U(FVP_CLUSTER_COUNT) + \
+ PLATFORM_CORE_COUNT + U(1))
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2
+
+/*
+ * Other platform porting definitions are provided by included headers
+ */
+
+/*
+ * Required ARM standard platform porting definitions
+ */
+#define PLAT_ARM_CLUSTER_COUNT U(FVP_CLUSTER_COUNT)
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */
+
+#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x00000000)
+#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */
+
+#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x06000000)
+#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */
+
+#if ENABLE_RME
+#define PLAT_ARM_RMM_BASE (RMM_BASE)
+#define PLAT_ARM_RMM_SIZE (RMM_LIMIT - RMM_BASE)
+#endif
+
+/*
+ * Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to
+ * max size of BL32 image.
+ */
+#if defined(SPD_spmd)
+#define PLAT_ARM_SPMC_BASE PLAT_ARM_TRUSTED_DRAM_BASE
+#define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */
+#endif
+
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
+
+/* No SCP in FVP */
+#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0)
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) /* 36-bit range */
+#define PLAT_ARM_DRAM2_SIZE ULL(0x780000000) /* 30 GB */
+
+#define FVP_DRAM3_BASE ULL(0x8800000000) /* 40-bit range */
+#define FVP_DRAM3_SIZE ULL(0x7800000000) /* 480 GB */
+#define FVP_DRAM3_END (FVP_DRAM3_BASE + FVP_DRAM3_SIZE - 1U)
+
+#define FVP_DRAM4_BASE ULL(0x88000000000) /* 44-bit range */
+#define FVP_DRAM4_SIZE ULL(0x78000000000) /* 7.5 TB */
+#define FVP_DRAM4_END (FVP_DRAM4_BASE + FVP_DRAM4_SIZE - 1U)
+
+#define FVP_DRAM5_BASE ULL(0x880000000000) /* 48-bit range */
+#define FVP_DRAM5_SIZE ULL(0x780000000000) /* 120 TB */
+#define FVP_DRAM5_END (FVP_DRAM5_BASE + FVP_DRAM5_SIZE - 1U)
+
+#define FVP_DRAM6_BASE ULL(0x8800000000000) /* 52-bit range */
+#define FVP_DRAM6_SIZE ULL(0x7800000000000) /* 1920 TB */
+#define FVP_DRAM6_END (FVP_DRAM6_BASE + FVP_DRAM6_SIZE - 1U)
+
+/* Range of kernel DTB load address */
+#define FVP_DTB_DRAM_MAP_START ULL(0x82000000)
+#define FVP_DTB_DRAM_MAP_SIZE ULL(0x02000000) /* 32 MB */
+
+#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \
+ FVP_DTB_DRAM_MAP_START, \
+ FVP_DTB_DRAM_MAP_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
+
+#if SPMC_AT_EL3
+/*
+ * Number of Secure Partitions supported.
+ * SPMC at EL3, uses this count to configure the maximum number of supported
+ * secure partitions.
+ */
+#define SECURE_PARTITION_COUNT 1
+
+/*
+ * Number of Normal World Partitions supported.
+ * SPMC at EL3, uses this count to configure the maximum number of supported
+ * NWd partitions.
+ */
+#define NS_PARTITION_COUNT 1
+
+/*
+ * Number of Logical Partitions supported.
+ * SPMC at EL3, uses this count to configure the maximum number of supported
+ * logical partitions.
+ */
+#define MAX_EL3_LP_DESCS_COUNT 1
+
+#endif /* SPMC_AT_EL3 */
+
+/*
+ * Load address of BL33 for this platform port
+ */
+#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + UL(0x8000000))
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if defined(IMAGE_BL31)
+# if SPM_MM
+# define PLAT_ARM_MMAP_ENTRIES 10
+# define MAX_XLAT_TABLES 9
+# define PLAT_SP_IMAGE_MMAP_REGIONS 30
+# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
+# elif SPMC_AT_EL3
+# define PLAT_ARM_MMAP_ENTRIES 13
+# define MAX_XLAT_TABLES 11
+# else
+# define PLAT_ARM_MMAP_ENTRIES 9
+# if USE_DEBUGFS
+# if ENABLE_RME
+# define MAX_XLAT_TABLES 9
+# else
+# define MAX_XLAT_TABLES 8
+# endif
+# else
+# if ENABLE_RME
+# define MAX_XLAT_TABLES 8
+# elif DRTM_SUPPORT
+# define MAX_XLAT_TABLES 8
+# else
+# define MAX_XLAT_TABLES 7
+# endif
+# endif
+# endif
+#elif defined(IMAGE_BL32)
+# if SPMC_AT_EL3
+# define PLAT_ARM_MMAP_ENTRIES 270
+# define MAX_XLAT_TABLES 10
+# else
+# define PLAT_ARM_MMAP_ENTRIES 9
+# define MAX_XLAT_TABLES 6
+# endif
+#elif !USE_ROMLIB
+# define PLAT_ARM_MMAP_ENTRIES 11
+# define MAX_XLAT_TABLES 5
+#else
+# define PLAT_ARM_MMAP_ENTRIES 12
+# define MAX_XLAT_TABLES 6
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000)
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000)
+#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0x5000)
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0)
+#define FVP_BL2_ROMLIB_OPTIMIZATION UL(0)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT && COT_DESC_IN_DTB
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1E000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+#elif CRYPTO_SUPPORT
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+#elif ARM_BL31_IN_DRAM
+/* When ARM_BL31_IN_DRAM is set, BL2 can use almost all of Trusted SRAM. */
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1F000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+#endif
+
+#if RESET_TO_BL31
+/* Size of Trusted SRAM - the first 4KB of shared memory - GPT L0 Tables */
+#define PLAT_ARM_MAX_BL31_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
+ ARM_SHARED_RAM_SIZE - \
+ ARM_L0_GPT_SIZE)
+#else
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+#define PLAT_ARM_MAX_BL31_SIZE (UL(0x3D000) - ARM_L0_GPT_SIZE)
+#endif /* RESET_TO_BL31 */
+
+#ifndef __aarch64__
+#if RESET_TO_SP_MIN
+/* Size of Trusted SRAM - the first 4KB of shared memory */
+#define PLAT_ARM_MAX_BL32_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
+ ARM_SHARED_RAM_SIZE)
+#else
+/*
+ * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
+ * calculated using the current SP_MIN PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+# define PLAT_ARM_MAX_BL32_SIZE UL(0x3B000)
+#endif /* RESET_TO_SP_MIN */
+#endif
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if CRYPTO_SUPPORT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x500)
+# endif /* CRYPTO_SUPPORT */
+#elif defined(IMAGE_BL2)
+# if CRYPTO_SUPPORT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x600)
+# endif /* CRYPTO_SUPPORT */
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE UL(0x400)
+#elif defined(IMAGE_BL31)
+# if DRTM_SUPPORT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x800)
+# endif /* DRTM_SUPPORT */
+#elif defined(IMAGE_BL32)
+# if SPMC_AT_EL3
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x440)
+# endif /* SPMC_AT_EL3 */
+#elif defined(IMAGE_RMM)
+# define PLATFORM_STACK_SIZE UL(0x440)
+#endif
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
+#define PLAT_ARM_FLASH_IMAGE_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#if ARM_GPT_SUPPORT
+/*
+ * Offset of the FIP in the GPT image. BL1 component uses this option
+ * as it does not load the partition table to get the FIP base
+ * address. At sector 34 by default (i.e. after reserved sectors 0-33)
+ * Offset = 34 * 512(sector size) = 17408 i.e. 0x4400
+ */
+#define PLAT_ARM_FIP_OFFSET_IN_GPT 0x4400
+#endif /* ARM_GPT_SUPPORT */
+
+#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
+
+#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE
+#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ
+
+#define PLAT_ARM_TRP_UART_BASE V2M_IOFPGA_UART3_BASE
+#define PLAT_ARM_TRP_UART_CLK_IN_HZ V2M_IOFPGA_UART3_CLK_IN_HZ
+
+#define PLAT_FVP_SMMUV3_BASE UL(0x2b400000)
+#define PLAT_ARM_SMMUV3_ROOT_REG_OFFSET UL(0x20000)
+
+/* CCI related constants */
+#define PLAT_FVP_CCI400_BASE UL(0x2c090000)
+#define PLAT_FVP_CCI400_CLUS0_SL_PORT 3
+#define PLAT_FVP_CCI400_CLUS1_SL_PORT 4
+
+/* CCI-500/CCI-550 on Base platform */
+#define PLAT_FVP_CCI5XX_BASE UL(0x2a000000)
+#define PLAT_FVP_CCI5XX_CLUS0_SL_PORT 5
+#define PLAT_FVP_CCI5XX_CLUS1_SL_PORT 6
+
+/* CCN related constants. Only CCN 502 is currently supported */
+#define PLAT_ARM_CCN_BASE UL(0x2e000000)
+#define PLAT_ARM_CLUSTER_TO_CCN_ID_MAP 1, 5, 7, 11
+
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
+
+/* Mailbox base address */
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
+
+
+/* TrustZone controller related constants
+ *
+ * Currently only filters 0 and 2 are connected on Base FVP.
+ * Filter 0 : CPU clusters (no access to DRAM by default)
+ * Filter 1 : not connected
+ * Filter 2 : LCDs (access to VRAM allowed by default)
+ * Filter 3 : not connected
+ * Programming unconnected filters will have no effect at the
+ * moment. These filter could, however, be connected in future.
+ * So care should be taken not to configure the unused filters.
+ *
+ * Allow only non-secure access to all DRAM to supported devices.
+ * Give access to the CPUs and Virtio. Some devices
+ * would normally use the default ID so allow that too.
+ */
+#define PLAT_ARM_TZC_BASE UL(0x2a4a0000)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
+ TZC_REGION_ACCESS_RDWR(FVP_NSAID_DEFAULT) | \
+ TZC_REGION_ACCESS_RDWR(FVP_NSAID_PCI) | \
+ TZC_REGION_ACCESS_RDWR(FVP_NSAID_AP) | \
+ TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO) | \
+ TZC_REGION_ACCESS_RDWR(FVP_NSAID_VIRTIO_OLD))
+
+/*
+ * GIC related constants to cater for both GICv2 and GICv3 instances of an
+ * FVP. They could be overridden at runtime in case the FVP implements the
+ * legacy VE memory map.
+ */
+#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
+#define PLAT_ARM_GICR_BASE BASE_GICR_BASE
+#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ ARM_G1S_IRQ_PROPS(grp), \
+ INTR_PROP_DESC(FVP_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(FVP_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+#if SDEI_IN_FCONF
+#define PLAT_SDEI_DP_EVENT_MAX_CNT ARM_SDEI_DP_EVENT_MAX_CNT
+#define PLAT_SDEI_DS_EVENT_MAX_CNT ARM_SDEI_DS_EVENT_MAX_CNT
+#else
+#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
+#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
+#endif
+
+#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
+ PLAT_SP_IMAGE_NS_BUF_SIZE)
+
+#define PLAT_SP_PRI PLAT_RAS_PRI
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+/*
+ * Maximum size of Event Log buffer used in Measured Boot Event Log driver
+ */
+#define PLAT_ARM_EVENT_LOG_MAX_SIZE UL(0x400)
+
+/*
+ * Maximum size of Event Log buffer used for DRTM
+ */
+#define PLAT_DRTM_EVENT_LOG_MAX_SIZE UL(0x300)
+
+/*
+ * Number of MMAP entries used by DRTM implementation
+ */
+#define PLAT_DRTM_MMAP_ENTRIES PLAT_ARM_MMAP_ENTRIES
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
new file mode 100644
index 0000000..85e6e3a
--- /dev/null
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform specific romlib functions can be added or included here.
+# The index in the output file will be generated cumulatively in the same
+# order as it is given in this file.
+# Output file can be found at: $BUILD_DIR/jmptbl.i
+#
+# Format:
+# lib function [patch]
+# Example:
+# rom rom_lib_init
+# fdt fdt_getprop_namelen patch
+
+rom rom_lib_init
+fdt fdt_getprop
+fdt fdt_get_property
+fdt fdt_getprop_namelen
+fdt fdt_setprop_inplace
+fdt fdt_check_header
+fdt fdt_node_offset_by_compatible
+fdt fdt_setprop_inplace_namelen_partial
+fdt fdt_first_subnode
+fdt fdt_next_subnode
+fdt fdt_path_offset
+fdt fdt_path_offset_namelen
+fdt fdt_subnode_offset
+fdt fdt_address_cells
+fdt fdt_size_cells
+fdt fdt_parent_offset
+fdt fdt_stringlist_search
+fdt fdt_get_alias_namelen
+fdt fdt_get_name
+fdt fdt_get_alias
+fdt fdt_node_offset_by_phandle
+fdt fdt_subnode_offset
+fdt fdt_add_subnode
+mbedtls mbedtls_asn1_get_alg
+mbedtls mbedtls_asn1_get_alg_null
+mbedtls mbedtls_asn1_get_bitstring_null
+mbedtls mbedtls_asn1_get_bool
+mbedtls mbedtls_asn1_get_int
+mbedtls mbedtls_asn1_get_tag
+mbedtls mbedtls_free
+mbedtls mbedtls_md
+mbedtls mbedtls_md_get_size
+mbedtls mbedtls_memory_buffer_alloc_init
+mbedtls mbedtls_oid_get_md_alg
+mbedtls mbedtls_oid_get_numeric_string
+mbedtls mbedtls_oid_get_pk_alg
+mbedtls mbedtls_oid_get_sig_alg
+mbedtls mbedtls_pk_free
+mbedtls mbedtls_pk_init
+mbedtls mbedtls_pk_parse_subpubkey
+mbedtls mbedtls_pk_verify_ext
+mbedtls mbedtls_platform_set_snprintf
+mbedtls mbedtls_x509_get_rsassa_pss_params
+mbedtls mbedtls_x509_get_sig_alg
+mbedtls mbedtls_md_info_from_type
+c exit
+c atexit
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
new file mode 100644
index 0000000..51ba035
--- /dev/null
+++ b/plat/arm/board/fvp/platform.mk
@@ -0,0 +1,464 @@
+#
+# Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+# Use the GICv3 driver on the FVP by default
+FVP_USE_GIC_DRIVER := FVP_GICV3
+
+# Default cluster count for FVP
+FVP_CLUSTER_COUNT := 2
+
+# Default number of CPUs per cluster on FVP
+FVP_MAX_CPUS_PER_CLUSTER := 4
+
+# Default number of threads per CPU on FVP
+FVP_MAX_PE_PER_CPU := 1
+
+# Disable redistributor frame of inactive/fused CPU cores by marking it as read
+# only; enable redistributor frames of all CPU cores by default.
+FVP_GICR_REGION_PROTECTION := 0
+
+FVP_DT_PREFIX := fvp-base-gicv3-psci
+
+# The FVP platform depends on this macro to build with correct GIC driver.
+$(eval $(call add_define,FVP_USE_GIC_DRIVER))
+
+# Pass FVP_CLUSTER_COUNT to the build system.
+$(eval $(call add_define,FVP_CLUSTER_COUNT))
+
+# Pass FVP_MAX_CPUS_PER_CLUSTER to the build system.
+$(eval $(call add_define,FVP_MAX_CPUS_PER_CLUSTER))
+
+# Pass FVP_MAX_PE_PER_CPU to the build system.
+$(eval $(call add_define,FVP_MAX_PE_PER_CPU))
+
+# Pass FVP_GICR_REGION_PROTECTION to the build system.
+$(eval $(call add_define,FVP_GICR_REGION_PROTECTION))
+
+# Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2,
+# choose the CCI driver , else the CCN driver
+ifeq ($(FVP_CLUSTER_COUNT), 0)
+$(error "Incorrect cluster count specified for FVP port")
+else ifeq ($(FVP_CLUSTER_COUNT),$(filter $(FVP_CLUSTER_COUNT),1 2))
+FVP_INTERCONNECT_DRIVER := FVP_CCI
+else
+FVP_INTERCONNECT_DRIVER := FVP_CCN
+endif
+
+$(eval $(call add_define,FVP_INTERCONNECT_DRIVER))
+
+# Choose the GIC sources depending upon the how the FVP will be invoked
+ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
+
+# The GIC model (GIC-600 or GIC-500) will be detected at runtime
+GICV3_SUPPORT_GIC600 := 1
+GICV3_OVERRIDE_DISTIF_PWR_OPS := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+FVP_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/arm/common/arm_gicv3.c
+
+ ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31} ${RESET_TO_SP_MIN}),)
+ FVP_GIC_SOURCES += plat/arm/board/fvp/fvp_gicv3.c
+ endif
+
+else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
+
+# No GICv4 extension
+GIC_ENABLE_V4_EXTN := 0
+$(eval $(call add_define,GIC_ENABLE_V4_EXTN))
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+FVP_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+
+FVP_DT_PREFIX := fvp-base-gicv2-psci
+else
+$(error "Incorrect GIC driver chosen on FVP port")
+endif
+
+ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCI)
+FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c
+else ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCN)
+FVP_INTERCONNECT_SOURCES := drivers/arm/ccn/ccn.c \
+ plat/arm/common/arm_ccn.c
+else
+$(error "Incorrect CCN driver chosen on FVP port")
+endif
+
+FVP_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
+ plat/arm/board/fvp/fvp_security.c \
+ plat/arm/common/arm_tzc400.c
+
+
+PLAT_INCLUDES := -Iplat/arm/board/fvp/include
+
+
+PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp/fvp_common.c
+
+FVP_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
+
+ifeq (${ARCH}, aarch64)
+
+# select a different set of CPU files, depending on whether we compile for
+# hardware assisted coherency cores or not
+ifeq (${HW_ASSISTED_COHERENCY}, 0)
+# Cores used without DSU
+ FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/cpus/aarch64/cortex_a73.S
+else
+# Cores used with DSU only
+ ifeq (${CTX_INCLUDE_AARCH32_REGS}, 0)
+ # AArch64-only cores
+ FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \
+ lib/cpus/aarch64/cortex_a76ae.S \
+ lib/cpus/aarch64/cortex_a77.S \
+ lib/cpus/aarch64/cortex_a78.S \
+ lib/cpus/aarch64/neoverse_n_common.S \
+ lib/cpus/aarch64/neoverse_n1.S \
+ lib/cpus/aarch64/neoverse_n2.S \
+ lib/cpus/aarch64/neoverse_e1.S \
+ lib/cpus/aarch64/neoverse_v1.S \
+ lib/cpus/aarch64/neoverse_v2.S \
+ lib/cpus/aarch64/cortex_a78_ae.S \
+ lib/cpus/aarch64/cortex_a510.S \
+ lib/cpus/aarch64/cortex_a710.S \
+ lib/cpus/aarch64/cortex_a715.S \
+ lib/cpus/aarch64/cortex_x3.S \
+ lib/cpus/aarch64/cortex_a65.S \
+ lib/cpus/aarch64/cortex_a65ae.S \
+ lib/cpus/aarch64/cortex_a78c.S \
+ lib/cpus/aarch64/cortex_hayes.S \
+ lib/cpus/aarch64/cortex_hunter.S \
+ lib/cpus/aarch64/cortex_hunter_elp_arm.S \
+ lib/cpus/aarch64/cortex_x2.S \
+ lib/cpus/aarch64/neoverse_poseidon.S
+ endif
+ # AArch64/AArch32 cores
+ FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \
+ lib/cpus/aarch64/cortex_a75.S
+endif
+
+else
+FVP_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S
+endif
+
+BL1_SOURCES += drivers/arm/smmu/smmu_v3.c \
+ drivers/arm/sp805/sp805.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/io/io_semihosting.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
+ plat/arm/board/fvp/fvp_bl1_setup.c \
+ plat/arm/board/fvp/fvp_err.c \
+ plat/arm/board/fvp/fvp_io_storage.c \
+ ${FVP_CPU_LIBS} \
+ ${FVP_INTERCONNECT_SOURCES}
+
+ifeq (${USE_SP804_TIMER},1)
+BL1_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+else
+BL1_SOURCES += drivers/delay_timer/generic_delay_timer.c
+endif
+
+
+BL2_SOURCES += drivers/arm/sp805/sp805.c \
+ drivers/io/io_semihosting.c \
+ lib/utils/mem_region.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ plat/arm/board/fvp/fvp_bl2_setup.c \
+ plat/arm/board/fvp/fvp_err.c \
+ plat/arm/board/fvp/fvp_io_storage.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
+ ${FVP_SECURITY_SOURCES}
+
+
+ifeq (${COT_DESC_IN_DTB},1)
+BL2_SOURCES += plat/arm/common/fconf/fconf_nv_cntr_getter.c
+endif
+
+ifeq (${ENABLE_RME},1)
+BL2_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S
+BL31_SOURCES += plat/arm/board/fvp/fvp_plat_attest_token.c \
+ plat/arm/board/fvp/fvp_realm_attest_key.c
+endif
+
+ifeq (${BL2_AT_EL3},1)
+BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \
+ plat/arm/board/fvp/fvp_bl2_el3_setup.c \
+ ${FVP_CPU_LIBS} \
+ ${FVP_INTERCONNECT_SOURCES}
+endif
+
+ifeq (${USE_SP804_TIMER},1)
+BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+endif
+
+BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \
+ ${FVP_SECURITY_SOURCES}
+
+ifeq (${USE_SP804_TIMER},1)
+BL2U_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+endif
+
+BL31_SOURCES += drivers/arm/fvp/fvp_pwrc.c \
+ drivers/arm/smmu/smmu_v3.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/board/fvp/fvp_bl31_setup.c \
+ plat/arm/board/fvp/fvp_console.c \
+ plat/arm/board/fvp/fvp_pm.c \
+ plat/arm/board/fvp/fvp_topology.c \
+ plat/arm/board/fvp/aarch64/fvp_helpers.S \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
+ ${FVP_CPU_LIBS} \
+ ${FVP_GIC_SOURCES} \
+ ${FVP_INTERCONNECT_SOURCES} \
+ ${FVP_SECURITY_SOURCES}
+
+# Support for fconf in BL31
+# Added separately from the above list for better readability
+ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),)
+BL31_SOURCES += lib/fconf/fconf.c \
+ lib/fconf/fconf_dyn_cfg_getter.c \
+ plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+ifeq (${SEC_INT_DESC_IN_FCONF},1)
+BL31_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c
+endif
+
+endif
+
+ifeq (${USE_SP804_TIMER},1)
+BL31_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+else
+BL31_SOURCES += drivers/delay_timer/generic_delay_timer.c
+endif
+
+# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
+ifdef UNIX_MK
+FVP_HW_CONFIG_DTS := fdts/${FVP_DT_PREFIX}.dts
+FDT_SOURCES += $(addprefix plat/arm/board/fvp/fdts/, \
+ ${PLAT}_fw_config.dts \
+ ${PLAT}_tb_fw_config.dts \
+ ${PLAT}_soc_fw_config.dts \
+ ${PLAT}_nt_fw_config.dts \
+ )
+
+FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FVP_SOC_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb
+FVP_NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+ifeq (${SPD},tspd)
+FDT_SOURCES += plat/arm/board/fvp/fdts/${PLAT}_tsp_fw_config.dts
+FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tsp_fw_config.dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config,${FVP_TOS_FW_CONFIG}))
+endif
+
+ifeq (${SPD},spmd)
+
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS := plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS}
+FVP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config,${FVP_TOS_FW_CONFIG}))
+endif
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config,${FVP_FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config,${FVP_TB_FW_CONFIG}))
+# Add the SOC_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_SOC_FW_CONFIG},--soc-fw-config,${FVP_SOC_FW_CONFIG}))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_NT_FW_CONFIG},--nt-fw-config,${FVP_NT_FW_CONFIG}))
+
+FDT_SOURCES += ${FVP_HW_CONFIG_DTS}
+$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(FVP_HW_CONFIG_DTS)))
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
+endif
+
+# Enable Activity Monitor Unit extensions by default
+ENABLE_AMU := 1
+
+# Enable dynamic mitigation support by default
+DYNAMIC_WORKAROUND_CVE_2018_3639 := 1
+
+ifeq (${ENABLE_AMU},1)
+BL31_SOURCES += lib/cpus/aarch64/cpuamu.c \
+ lib/cpus/aarch64/cpuamu_helpers.S
+
+ifeq (${HW_ASSISTED_COHERENCY}, 1)
+BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \
+ lib/cpus/aarch64/neoverse_n1_pubsub.c
+endif
+endif
+
+ifeq (${RAS_EXTENSION},1)
+BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ras.c
+endif
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c
+endif
+
+ifeq (${ARCH},aarch32)
+ NEED_BL32 := yes
+endif
+
+# Enable the dynamic translation tables library.
+ifeq ($(filter 1,${BL2_AT_EL3} ${ARM_XLAT_TABLES_LIB_V1}),)
+ ifeq (${ARCH},aarch32)
+ BL32_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+ else # AArch64
+ BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+ endif
+endif
+
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+ ifeq (${ARCH},aarch32)
+ BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
+ else # AArch64
+ BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
+ ifeq (${SPD},tspd)
+ BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
+ endif
+ endif
+endif
+
+ifeq (${USE_DEBUGFS},1)
+ BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+endif
+
+# Add support for platform supplied linker script for BL31 build
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+ifneq (${BL2_AT_EL3}, 0)
+ override BL1_SOURCES =
+endif
+
+# Include Measured Boot makefile before any Crypto library makefile.
+# Crypto library makefile may need default definitions of Measured Boot build
+# flags present in Measured Boot makefile.
+ifeq (${MEASURED_BOOT},1)
+ RSS_MEASURED_BOOT_MK := drivers/measured_boot/rss/rss_measured_boot.mk
+ $(info Including ${RSS_MEASURED_BOOT_MK})
+ include ${RSS_MEASURED_BOOT_MK}
+
+ ifneq (${MBOOT_RSS_HASH_ALG}, sha256)
+ $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
+ endif
+
+ BL1_SOURCES += ${MEASURED_BOOT_SOURCES}
+ BL2_SOURCES += ${MEASURED_BOOT_SOURCES}
+endif
+
+include plat/arm/board/common/board_common.mk
+include plat/arm/common/arm_common.mk
+
+ifeq (${MEASURED_BOOT},1)
+BL1_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
+ plat/arm/board/fvp/fvp_bl1_measured_boot.c \
+ lib/psa/measured_boot.c
+
+BL2_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \
+ plat/arm/board/fvp/fvp_bl2_measured_boot.c \
+ lib/psa/measured_boot.c
+
+# Note that attestation code does not depend on measured boot interfaces per se,
+# but the two features go together - attestation without boot measurements is
+# pretty much pointless...
+BL31_SOURCES += lib/psa/delegated_attestation.c
+
+PLAT_INCLUDES += -Iinclude/lib/psa
+
+# RSS is not supported on FVP right now. Thus, we use the mocked version
+# of the provided PSA APIs. They return with success and hard-coded data.
+PLAT_RSS_NOT_SUPPORTED := 1
+
+# Even though RSS is not supported on FVP (see above), we support overriding
+# PLAT_RSS_NOT_SUPPORTED from the command line, just for the purpose of building
+# the code to detect any build regressions. The resulting firmware will not be
+# functional.
+ifneq (${PLAT_RSS_NOT_SUPPORTED},1)
+ $(warning "RSS is not supported on FVP. The firmware will not be functional.")
+ include drivers/arm/rss/rss_comms.mk
+ BL1_SOURCES += ${RSS_COMMS_SOURCES}
+ BL2_SOURCES += ${RSS_COMMS_SOURCES}
+ BL31_SOURCES += ${RSS_COMMS_SOURCES} \
+ lib/psa/delegated_attestation.c
+
+ BL1_CFLAGS += -DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0
+ BL2_CFLAGS += -DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0
+ BL31_CFLAGS += -DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0
+endif
+
+endif
+
+ifeq (${DRTM_SUPPORT}, 1)
+BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_addr.c \
+ plat/arm/board/fvp/fvp_drtm_dma_prot.c \
+ plat/arm/board/fvp/fvp_drtm_err.c \
+ plat/arm/board/fvp/fvp_drtm_measurement.c \
+ plat/arm/board/fvp/fvp_drtm_stub.c \
+ plat/arm/common/arm_dyn_cfg.c \
+ plat/arm/board/fvp/fvp_err.c
+endif
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c
+BL2_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c
+
+# FVP being a development platform, enable capability to disable Authentication
+# dynamically if TRUSTED_BOARD_BOOT is set.
+DYN_DISABLE_AUTH := 1
+endif
+
+# enable trace buffer control registers access to NS by default
+ENABLE_TRBE_FOR_NS := 1
+
+# enable branch record buffer control registers access in NS by default
+# only enable for aarch64
+# do not enable when ENABLE_RME=1
+ifeq (${ARCH}, aarch64)
+ifeq (${ENABLE_RME},0)
+ ENABLE_BRBE_FOR_NS := 1
+endif
+endif
+
+# enable trace system registers access to NS by default
+ENABLE_SYS_REG_TRACE_FOR_NS := 1
+
+# enable trace filter control registers access to NS by default
+ENABLE_TRF_FOR_NS := 1
+
+ifeq (${SPMC_AT_EL3}, 1)
+PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_el3_spmc.c
+endif
diff --git a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
new file mode 100644
index 0000000..9ab36a6
--- /dev/null
+++ b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <bl32/sp_min/platform_sp_min.h>
+#include <common/debug.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "../fvp_private.h"
+
+void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ const struct dyn_cfg_dtb_info_t *tos_fw_config_info __unused;
+
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+#if !RESET_TO_SP_MIN && !BL2_AT_EL3
+
+ INFO("SP_MIN FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", arg1);
+
+ tos_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TOS_FW_CONFIG_ID);
+ if (tos_fw_config_info != NULL) {
+ arg1 = tos_fw_config_info->config_addr;
+ }
+#endif /* !RESET_TO_SP_MIN && !BL2_AT_EL3 */
+
+ arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+
+ /*
+ * Initialize the correct interconnect for this cluster during cold
+ * boot. No need for locks as no other CPU is active.
+ */
+ fvp_interconnect_init();
+
+ /*
+ * Enable coherency in interconnect for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this (e.g. Trusted
+ * Firmware's BL1 does it) but we can't assume so. There is no harm in
+ * executing this code twice anyway.
+ * FVP PSCI code will enable coherency for other clusters.
+ */
+ fvp_interconnect_enable();
+}
+
+void sp_min_plat_arch_setup(void)
+{
+ int rc __unused;
+ const struct dyn_cfg_dtb_info_t *hw_config_info __unused;
+ uintptr_t hw_config_base_align __unused;
+ size_t mapped_size_align __unused;
+
+ arm_sp_min_plat_arch_setup();
+
+ /*
+ * For RESET_TO_SP_MIN systems, SP_MIN(BL32) is the first bootloader
+ * to run. So there is no BL2 to load the HW_CONFIG dtb into memory
+ * before control is passed to SP_MIN.
+ * Also, BL2 skips loading HW_CONFIG dtb for BL2_AT_EL3 builds.
+ * The code below relies on dynamic mapping capability, which is not
+ * supported by xlat tables lib V1.
+ * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support
+ * gets deprecated.
+ */
+#if !RESET_TO_SP_MIN && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+ assert(hw_config_info->config_addr != 0UL);
+
+ INFO("SP_MIN FCONF: HW_CONFIG address = %p\n",
+ (void *)hw_config_info->config_addr);
+
+ /*
+ * Preferrably we expect this address and size are page aligned,
+ * but if they are not then align it.
+ */
+ hw_config_base_align = page_align(hw_config_info->config_addr, DOWN);
+ mapped_size_align = page_align(hw_config_info->config_max_size, UP);
+
+ if ((hw_config_info->config_addr != hw_config_base_align) &&
+ (hw_config_info->config_max_size == mapped_size_align)) {
+ mapped_size_align += PAGE_SIZE;
+ }
+
+ /*
+ * map dynamically HW config region with its aligned base address and
+ * size
+ */
+ rc = mmap_add_dynamic_region((unsigned long long)hw_config_base_align,
+ hw_config_base_align,
+ mapped_size_align,
+ MT_RO_DATA);
+ if (rc != 0) {
+ ERROR("Error while mapping HW_CONFIG device tree (%d).\n", rc);
+ panic();
+ }
+
+ /* Populate HW_CONFIG device tree with the mapped address */
+ fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+
+ /* unmap the HW_CONFIG memory region */
+ rc = mmap_remove_dynamic_region(hw_config_base_align, mapped_size_align);
+ if (rc != 0) {
+ ERROR("Error while unmapping HW_CONFIG device tree (%d).\n",
+ rc);
+ panic();
+ }
+#endif /* !RESET_TO_SP_MIN && !BL2_AT_EL3 && !ARM_XLAT_TABLES_LIB_V1 */
+}
diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
new file mode 100644
index 0000000..183d802
--- /dev/null
+++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2016-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+# SP_MIN source files specific to FVP platform
+BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/board/fvp/aarch32/fvp_helpers.S \
+ plat/arm/board/fvp/fvp_pm.c \
+ plat/arm/board/fvp/fvp_console.c \
+ plat/arm/board/fvp/fvp_topology.c \
+ plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
+ ${FVP_CPU_LIBS} \
+ ${FVP_GIC_SOURCES} \
+ ${FVP_INTERCONNECT_SOURCES} \
+ ${FVP_SECURITY_SOURCES}
+
+# Support for fconf in SP_MIN(BL32)
+# Added separately from the above list for better readability
+ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_SP_MIN}),)
+BL32_SOURCES += lib/fconf/fconf.c \
+ lib/fconf/fconf_dyn_cfg_getter.c \
+ plat/arm/board/fvp/fconf/fconf_hw_config_getter.c \
+
+BL32_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+ifeq (${SEC_INT_DESC_IN_FCONF},1)
+BL32_SOURCES += plat/arm/common/fconf/fconf_sec_intr_config.c
+endif
+
+endif
+
+include plat/arm/common/sp_min/arm_sp_min.mk
diff --git a/plat/arm/board/fvp/trp/trp-fvp.mk b/plat/arm/board/fvp/trp/trp-fvp.mk
new file mode 100644
index 0000000..a450541
--- /dev/null
+++ b/plat/arm/board/fvp/trp/trp-fvp.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TRP source files specific to FVP platform
+
+RMM_SOURCES += plat/arm/board/fvp/aarch64/fvp_helpers.S
+
+include plat/arm/common/trp/arm_trp.mk
+
diff --git a/plat/arm/board/fvp/tsp/fvp_tsp_setup.c b/plat/arm/board/fvp/tsp/fvp_tsp_setup.c
new file mode 100644
index 0000000..3c8a963
--- /dev/null
+++ b/plat/arm/board/fvp/tsp/fvp_tsp_setup.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+#include "../fvp_private.h"
+
+void tsp_early_platform_setup(void)
+{
+ arm_tsp_early_platform_setup();
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+}
diff --git a/plat/arm/board/fvp/tsp/tsp-fvp.mk b/plat/arm/board/fvp/tsp/tsp-fvp.mk
new file mode 100644
index 0000000..ab3f225
--- /dev/null
+++ b/plat/arm/board/fvp/tsp/tsp-fvp.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TSP source files specific to FVP platform
+BL32_SOURCES += drivers/arm/fvp/fvp_pwrc.c \
+ plat/arm/board/fvp/aarch64/fvp_helpers.S \
+ plat/arm/board/fvp/fvp_topology.c \
+ plat/arm/board/fvp/tsp/fvp_tsp_setup.c \
+ ${FVP_GIC_SOURCES}
+
+include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
new file mode 100644
index 0000000..ae6af6c
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "../../../../bl1/bl1_private.h"
+#include <arch.h>
+
+#include <fvp_r_arch_helpers.h>
+
+/*******************************************************************************
+ * Function that does the first bit of architectural setup that affects
+ * execution in the non-secure address space.
+ ******************************************************************************/
+void bl1_arch_setup(void)
+{
+ /* v8-R64 does not include SCRs. */
+}
+
+/*******************************************************************************
+ * Set the Secure EL1 required architectural state
+ ******************************************************************************/
+void bl1_arch_next_el_setup(void)
+{
+ u_register_t next_sctlr;
+
+ /* Use the same endianness than the current BL */
+ next_sctlr = (read_sctlr_el2() & SCTLR_EE_BIT);
+
+ /* Set SCTLR Secure EL1 */
+ next_sctlr |= SCTLR_EL1_RES1;
+
+ write_sctlr_el1(next_sctlr);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
new file mode 100644
index 0000000..15f4c43
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <el2_common_macros.S>
+#include <lib/xlat_mpu/xlat_mpu.h>
+
+ .globl bl1_entrypoint
+ .globl bl1_run_next_image
+
+
+ /* -----------------------------------------------------
+ * bl1_entrypoint() is the entry point into the trusted
+ * firmware code when a cpu is released from warm or
+ * cold reset.
+ * -----------------------------------------------------
+ */
+
+func bl1_entrypoint
+ /* ---------------------------------------------------------------------
+ * If the reset address is programmable then bl1_entrypoint() is
+ * executed only on the cold boot path. Therefore, we can skip the warm
+ * boot mailbox mechanism.
+ * ---------------------------------------------------------------------
+ */
+ el2_entrypoint_common \
+ _init_sctlr=1 \
+ _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
+ _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
+ _init_memory=1 \
+ _init_c_runtime=1 \
+ _exception_vectors=bl1_exceptions \
+ _pie_fixup_size=0
+
+ /* --------------------------------------------------------------------
+ * Perform BL1 setup
+ * --------------------------------------------------------------------
+ */
+ bl bl1_setup
+
+ /* --------------------------------------------------------------------
+ * Initialize platform and jump to our c-entry point
+ * for this type of reset.
+ * --------------------------------------------------------------------
+ */
+ bl bl1_main
+
+ /* ---------------------------------------------
+ * Should never reach this point.
+ * ---------------------------------------------
+ */
+ no_ret plat_panic_handler
+endfunc bl1_entrypoint
+
+func bl1_run_next_image
+ mov x20,x0
+
+ /* ---------------------------------------------
+ * MPU needs to be disabled because both BL1 and BL33 execute
+ * in EL2, and therefore share the same address space.
+ * BL33 will initialize the address space according to its
+ * own requirement.
+ * ---------------------------------------------
+ */
+ bl disable_mpu_icache_el2
+
+ /* ---------------------------------------------
+ * Wipe clean and disable all MPU regions. This function expects
+ * that the MPU has already been turned off, and caching concerns
+ * addressed, but it also explicitly turns off the MPU.
+ * ---------------------------------------------
+ */
+ bl clear_all_mpu_regions
+
+ /* --------------------------------------------------
+ * Do the transition to next boot image.
+ * --------------------------------------------------
+ */
+ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+ msr elr_el2, x0
+ msr spsr_el2, x1
+
+ ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
+ ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
+ ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
+ ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
+ exception_return
+endfunc bl1_run_next_image
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
new file mode 100644
index 0000000..43c2e01
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <context.h>
+
+/* -----------------------------------------------------------------------------
+ * File contains an EL2 equivalent of the EL3 vector table from:
+ * .../bl1/aarch64/bl1_exceptions.S
+ * -----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------
+ * Very simple stackless exception handlers used by BL1.
+ * -----------------------------------------------------------------------------
+ */
+ .globl bl1_exceptions
+
+vector_base bl1_exceptions
+
+ /* -----------------------------------------------------
+ * Current EL with SP0 : 0x0 - 0x200
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionSP0
+ mov x0, #SYNC_EXCEPTION_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SynchronousExceptionSP0
+
+vector_entry IrqSP0
+ mov x0, #IRQ_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry IrqSP0
+
+vector_entry FiqSP0
+ mov x0, #FIQ_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry FiqSP0
+
+vector_entry SErrorSP0
+ mov x0, #SERROR_SP_EL0
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SErrorSP0
+
+ /* -----------------------------------------------------
+ * Current EL with SPx: 0x200 - 0x400
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionSPx
+ mov x0, #SYNC_EXCEPTION_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SynchronousExceptionSPx
+
+vector_entry IrqSPx
+ mov x0, #IRQ_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry IrqSPx
+
+vector_entry FiqSPx
+ mov x0, #FIQ_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry FiqSPx
+
+vector_entry SErrorSPx
+ mov x0, #SERROR_SP_ELX
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SErrorSPx
+
+ /* -----------------------------------------------------
+ * Lower EL using AArch64 : 0x400 - 0x600
+ * -----------------------------------------------------
+ */
+vector_entry SynchronousExceptionA64
+ /* The current v8-R64 implementation does not support conduit calls */
+ b el2_panic
+end_vector_entry SynchronousExceptionA64
+
+vector_entry IrqA64
+ mov x0, #IRQ_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry IrqA64
+
+vector_entry FiqA64
+ mov x0, #FIQ_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry FiqA64
+
+vector_entry SErrorA64
+ mov x0, #SERROR_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+end_vector_entry SErrorA64
+
+
+unexpected_sync_exception:
+ mov x0, #SYNC_EXCEPTION_AARCH64
+ bl plat_report_exception
+ no_ret plat_panic_handler
+
+ /* -----------------------------------------------------
+ * Save Secure/Normal world context and jump to
+ * BL1 SMC handler.
+ * -----------------------------------------------------
+ */
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
new file mode 100644
index 0000000..841a176
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include "../../../../bl1/bl1_private.h"
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/auth_mod.h>
+#include <drivers/console.h>
+#include <lib/cpus/errata_report.h>
+#include <lib/utils.h>
+#include <smccc_helpers.h>
+#include <tools_share/uuid.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+
+void cm_prepare_el2_exit(void);
+
+void bl1_run_next_image(const struct entry_point_info *bl_ep_info);
+
+/*******************************************************************************
+ * Function to perform late architectural and platform specific initialization.
+ * It also queries the platform to load and run next BL image. Only called
+ * by the primary cpu after a cold boot.
+ ******************************************************************************/
+void bl1_transfer_bl33(void)
+{
+ unsigned int image_id;
+
+ /* Get the image id of next image to load and run. */
+ image_id = bl1_plat_get_next_image_id();
+
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Disable watchdog before leaving BL1 */
+ plat_arm_secure_wdt_stop();
+#endif
+
+ bl1_run_next_image(&bl1_plat_get_image_desc(image_id)->ep_info);
+}
+
+/*******************************************************************************
+ * This function locates and loads the BL33 raw binary image in the trusted SRAM.
+ * Called by the primary cpu after a cold boot.
+ * TODO: Add support for alternative image load mechanism e.g using virtio/elf
+ * loader etc.
+ ******************************************************************************/
+void bl1_load_bl33(void)
+{
+ image_desc_t *desc;
+ image_info_t *info;
+ int err;
+
+ /* Get the image descriptor */
+ desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
+ assert(desc != NULL);
+
+ /* Get the image info */
+ info = &desc->image_info;
+ INFO("BL1: Loading BL33\n");
+
+ err = bl1_plat_handle_pre_image_load(BL33_IMAGE_ID);
+ if (err != 0) {
+ ERROR("Failure in pre image load handling of BL33 (%d)\n", err);
+ plat_error_handler(err);
+ }
+
+ err = load_auth_image(BL33_IMAGE_ID, info);
+ if (err != 0) {
+ ERROR("Failed to load BL33 firmware.\n");
+ plat_error_handler(err);
+ }
+
+ /* Allow platform to handle image information. */
+ err = bl1_plat_handle_post_image_load(BL33_IMAGE_ID);
+ if (err != 0) {
+ ERROR("Failure in post image load handling of BL33 (%d)\n", err);
+ plat_error_handler(err);
+ }
+
+ NOTICE("BL1: Booting BL33\n");
+}
+
+/*******************************************************************************
+ * Helper utility to calculate the BL2 memory layout taking into consideration
+ * the BL1 RW data assuming that it is at the top of the memory layout.
+ ******************************************************************************/
+void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
+ meminfo_t *bl2_mem_layout)
+{
+ assert(bl1_mem_layout != NULL);
+ assert(bl2_mem_layout != NULL);
+
+ /*
+ * Remove BL1 RW data from the scope of memory visible to BL2.
+ * This is assuming BL1 RW data is at the top of bl1_mem_layout.
+ */
+ assert(bl1_mem_layout->total_base < BL1_RW_BASE);
+ bl2_mem_layout->total_base = bl1_mem_layout->total_base;
+ bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base;
+
+ flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t));
+}
+
+/*******************************************************************************
+ * This function prepares for entry to BL33
+ ******************************************************************************/
+void bl1_prepare_next_image(unsigned int image_id)
+{
+ unsigned int mode = MODE_EL1;
+ image_desc_t *desc;
+ entry_point_info_t *next_bl_ep;
+
+#if CTX_INCLUDE_AARCH32_REGS
+ /*
+ * Ensure that the build flag to save AArch32 system registers in CPU
+ * context is not set for AArch64-only platforms.
+ */
+ if (el_implemented(1) == EL_IMPL_A64ONLY) {
+ ERROR("EL1 supports AArch64-only. Please set build flag %s",
+ "CTX_INCLUDE_AARCH32_REGS = 0\n");
+ panic();
+ }
+#endif
+
+ /* Get the image descriptor. */
+ desc = bl1_plat_get_image_desc(image_id);
+ assert(desc != NULL);
+
+ /* Get the entry point info. */
+ next_bl_ep = &desc->ep_info;
+
+ /* FVP-R is only secure */
+ assert(GET_SECURITY_STATE(next_bl_ep->h.attr) == SECURE);
+
+ /* Prepare the SPSR for the next BL image. */
+ next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode,
+ (uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+
+ /* Allow platform to make change */
+ bl1_plat_set_ep_info(image_id, next_bl_ep);
+
+ /* Prepare context for the next EL */
+ cm_prepare_el2_exit();
+
+ /* Indicate that image is in execution state. */
+ desc->state = IMAGE_STATE_EXECUTED;
+
+ print_entry_point_info(next_bl_ep);
+}
+
+/*******************************************************************************
+ * Setup function for BL1.
+ ******************************************************************************/
+void bl1_setup(void)
+{
+ /* Perform early platform-specific setup */
+ bl1_early_platform_setup();
+
+ /* Perform late platform-specific setup */
+ bl1_plat_arch_setup();
+}
+
+/*******************************************************************************
+ * Function to perform late architectural and platform specific initialization.
+ * It also queries the platform to load and run next BL image. Only called
+ * by the primary cpu after a cold boot.
+ ******************************************************************************/
+void bl1_main(void)
+{
+ unsigned int image_id;
+
+ /* Announce our arrival */
+ NOTICE(FIRMWARE_WELCOME_STR);
+ NOTICE("BL1: %s\n", version_string);
+ NOTICE("BL1: %s\n", build_message);
+
+ INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT);
+
+ print_errata_status();
+
+#if ENABLE_ASSERTIONS
+ u_register_t val;
+ /*
+ * Ensure that MMU/Caches and coherency are turned on
+ */
+ val = read_sctlr_el2();
+
+ assert((val & SCTLR_M_BIT) != 0U);
+ assert((val & SCTLR_C_BIT) != 0U);
+ assert((val & SCTLR_I_BIT) != 0U);
+ /*
+ * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
+ * provided platform value
+ */
+ val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
+ /*
+ * If CWG is zero, then no CWG information is available but we can
+ * at least check the platform value is less than the architectural
+ * maximum.
+ */
+ if (val != 0) {
+ assert(SIZE_FROM_LOG2_WORDS(val) == CACHE_WRITEBACK_GRANULE);
+ } else {
+ assert(MAX_CACHE_LINE_SIZE >= CACHE_WRITEBACK_GRANULE);
+ }
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Perform remaining generic architectural setup from ELmax */
+ bl1_arch_setup();
+
+#if TRUSTED_BOARD_BOOT
+ /* Initialize authentication module */
+ auth_mod_init();
+#endif /* TRUSTED_BOARD_BOOT */
+
+ /* Perform platform setup in BL1. */
+ bl1_platform_setup();
+
+ /* Get the image id of next image to load and run. */
+ image_id = bl1_plat_get_next_image_id();
+
+ /*
+ * We currently interpret any image id other than
+ * BL2_IMAGE_ID as the start of firmware update.
+ */
+ if (image_id == BL33_IMAGE_ID) {
+ bl1_load_bl33();
+ } else {
+ NOTICE("BL1-FWU: *******FWU Process Started*******\n");
+ }
+
+ bl1_prepare_next_image(image_id);
+
+ console_flush();
+
+ bl1_transfer_bl33();
+}
+
+/*******************************************************************************
+ * Function called just before handing over to the next BL to inform the user
+ * about the boot progress. In debug mode, also print details about the BL
+ * image's execution context.
+ ******************************************************************************/
+void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info)
+{
+ NOTICE("BL1: Booting BL31\n");
+ print_entry_point_info(bl_ep_info);
+}
+
+#if SPIN_ON_BL1_EXIT
+void print_debug_loop_message(void)
+{
+ NOTICE("BL1: Debug loop, spinning forever\n");
+ NOTICE("BL1: Please connect the debugger to continue\n");
+}
+#endif
+
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
new file mode 100644
index 0000000..1ac0a9c
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Use the xlat_tables_v2 data structures: */
+#define XLAT_TABLES_LIB_V2 1
+
+#include <assert.h>
+
+#include <bl1/bl1.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/sp805.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/xlat_mpu/xlat_mpu.h>
+
+#include "fvp_r_private.h"
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#define MAP_BL1_TOTAL MAP_REGION_FLAT( \
+ bl1_tzram_layout.total_base, \
+ bl1_tzram_layout.total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+/*
+ * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
+ * otherwise one region is defined containing both
+ */
+#if SEPARATE_CODE_AND_RODATA
+#define MAP_BL1_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL1_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE), \
+ MAP_REGION_FLAT( \
+ BL1_RO_DATA_BASE, \
+ BL1_RO_DATA_END \
+ - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+#else
+#define MAP_BL1_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL1_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+#endif
+
+/* Data structure which holds the extents of the trusted SRAM for BL1*/
+static meminfo_t bl1_tzram_layout;
+
+struct meminfo *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+void arm_bl1_early_platform_setup(void)
+{
+
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Enable watchdog */
+ plat_arm_secure_wdt_start();
+#endif
+
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = ARM_BL_RAM_BASE;
+ bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE;
+}
+
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ arm_bl1_early_platform_setup();
+
+ /* Initialize the platform config for future decision making */
+ fvp_config_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ fvp_interconnect_init();
+ /*
+ * Enable coherency in Interconnect for the primary CPU's cluster.
+ */
+ fvp_interconnect_enable();
+}
+
+void arm_bl1_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL1_TOTAL,
+ MAP_BL1_RO,
+#if USE_ROMLIB
+ ARM_MAP_ROMLIB_CODE,
+ ARM_MAP_ROMLIB_DATA,
+#endif
+#if ARM_CRYPTOCELL_INTEG
+ ARM_MAP_BL_COHERENT_RAM,
+#endif
+ /* DRAM1_region: */
+ MAP_REGION_FLAT( \
+ PLAT_ARM_DRAM1_BASE, \
+ PLAT_ARM_DRAM1_SIZE, \
+ MT_MEMORY | MT_SECURE | MT_EXECUTE \
+ | MT_RW | MT_NON_CACHEABLE),
+ /* NULL terminator: */
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+ enable_mpu_el2(0);
+
+ arm_setup_romlib();
+}
+
+void plat_arm_secure_wdt_start(void)
+{
+ sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sp805_stop(ARM_SP805_TWDG_BASE);
+}
+
+/*
+ * Perform the platform specific architecture setup shared between
+ * ARM standard platforms.
+ */
+void arm_bl1_platform_setup(void)
+{
+ uint32_t fw_config_max_size;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_arm_io_setup();
+
+ /* Check if we need FWU before further processing */
+ is_fwu_needed = plat_arm_bl1_fwu_needed();
+ if (is_fwu_needed) {
+ ERROR("Skip platform setup as FWU detected\n");
+ return;
+ }
+
+ /* Set global DTB info for fixed fw_config information */
+ fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
+ set_config_info(ARM_FW_CONFIG_BASE, ~0UL, fw_config_max_size,
+ FW_CONFIG_ID);
+
+ assert(bl1_plat_get_image_desc(BL33_IMAGE_ID) != NULL);
+
+ /*
+ * Allow access to the System counter timer module and program
+ * counter frequency for non secure images during FWU
+ */
+#ifdef ARM_SYS_TIMCTL_BASE
+ arm_configure_sys_timer();
+#endif
+#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER)
+ write_cntfrq_el0(plat_get_syscnt_freq2());
+#endif
+}
+
+void bl1_platform_setup(void)
+{
+ arm_bl1_platform_setup();
+
+ /* Initialize System level generic or SP804 timer */
+ fvp_timer_init();
+}
+
+__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
+{
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ while (true) {
+ wfi();
+ }
+}
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ return is_fwu_needed ? NS_BL1U_IMAGE_ID : BL33_IMAGE_ID;
+}
+
+/*
+ * Returns BL33 image details.
+ */
+struct image_desc *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ static image_desc_t bl33_img_desc = BL33_IMAGE_DESC;
+
+ return &bl33_img_desc;
+}
+
+/*
+ * This function populates the default arguments to BL33.
+ * The BL33 memory layout structure is allocated and the
+ * calculated layout is populated in arg1 to BL33.
+ */
+int bl1_plat_handle_post_image_load(unsigned int image_id)
+{
+ meminfo_t *bl33_secram_layout;
+ meminfo_t *bl1_secram_layout;
+ image_desc_t *image_desc;
+ entry_point_info_t *ep_info;
+
+ if (image_id != BL33_IMAGE_ID) {
+ return 0;
+ }
+ /* Get the image descriptor */
+ image_desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
+ assert(image_desc != NULL);
+
+ /* Get the entry point info */
+ ep_info = &image_desc->ep_info;
+
+ /* Find out how much free trusted ram remains after BL1 load */
+ bl1_secram_layout = bl1_plat_sec_mem_layout();
+
+ /*
+ * Create a new layout of memory for BL33 as seen by BL1 i.e.
+ * tell it the amount of total and free memory available.
+ * This layout is created at the first free address visible
+ * to BL33. BL33 will read the memory layout before using its
+ * memory for other purposes.
+ */
+ bl33_secram_layout = (meminfo_t *) bl1_secram_layout->total_base;
+
+ bl1_calc_bl2_mem_layout(bl1_secram_layout, bl33_secram_layout);
+
+ ep_info->args.arg1 = (uintptr_t)bl33_secram_layout;
+
+ VERBOSE("BL1: BL3 memory layout address = %p\n",
+ (void *) bl33_secram_layout);
+ return 0;
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_common.c b/plat/arm/board/fvp_r/fvp_r_common.c
new file mode 100644
index 0000000..edcf658
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_common.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* This uses xlat_mpu, but tables are set up using V2 mmap_region_t */
+#define XLAT_TABLES_LIB_V2 1
+
+#include <assert.h>
+#include <common/debug.h>
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
+
+#include "fvp_r_private.h"
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+
+/* Defines for GIC Driver build time selection */
+#define FVP_R_GICV3 2
+
+/*******************************************************************************
+ * arm_config holds the characteristics of the differences between the FVP_R
+ * platforms. It will be populated during cold boot at each boot stage by the
+ * primary before enabling the MPU (to allow interconnect configuration) &
+ * used thereafter. Each BL will have its own copy to allow independent
+ * operation.
+ ******************************************************************************/
+arm_config_t arm_config;
+
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \
+ DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Need to be mapped with write permissions in order to set a new non-volatile
+ * counter value.
+ */
+#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \
+ DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of memory regions for various BL stages to map using the MPU.
+ * This doesn't include Trusted SRAM as setup_page_tables() already takes care
+ * of mapping it.
+ *
+ * The flash needs to be mapped as writable in order to erase the FIP's Table of
+ * Contents in case of unrecoverable error (see plat_error_handler()).
+ */
+#ifdef IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH0_RW,
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+ MAP_DEVICE1,
+#if TRUSTED_BOARD_BOOT
+ /* To access the Root of Trust Public Key registers. */
+ MAP_DEVICE2,
+#endif
+ {0}
+};
+#endif
+
+ARM_CASSERT_MMAP
+
+static const int fvp_cci400_map[] = {
+ PLAT_FVP_R_CCI400_CLUS0_SL_PORT,
+ PLAT_FVP_R_CCI400_CLUS1_SL_PORT,
+};
+
+static const int fvp_cci5xx_map[] = {
+ PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT,
+ PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT,
+};
+
+static unsigned int get_interconnect_master(void)
+{
+ unsigned int master;
+ u_register_t mpidr;
+
+ mpidr = read_mpidr_el1();
+ master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
+ MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);
+
+ assert(master < FVP_R_CLUSTER_COUNT);
+ return master;
+}
+
+/*******************************************************************************
+ * Initialize the platform config for future decision making
+ ******************************************************************************/
+void __init fvp_config_setup(void)
+{
+ unsigned int rev, hbi, bld, arch, sys_id;
+
+ arm_config.flags |= ARM_CONFIG_BASE_MMAP;
+ sys_id = mmio_read_32(V2M_FVP_R_SYSREGS_BASE + V2M_SYS_ID);
+ rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
+ hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
+ bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
+ arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
+
+ if (arch != ARCH_MODEL) {
+ ERROR("This firmware is for FVP_R models\n");
+ panic();
+ }
+
+ /*
+ * The build field in the SYS_ID tells which variant of the GIC
+ * memory is implemented by the model.
+ */
+ switch (bld) {
+ case BLD_GIC_VE_MMAP:
+ ERROR("Legacy Versatile Express memory map for GIC %s",
+ "peripheral is not supported\n");
+ panic();
+ break;
+ case BLD_GIC_A53A57_MMAP:
+ break;
+ default:
+ ERROR("Unsupported board build %x\n", bld);
+ panic();
+ }
+
+ /*
+ * The hbi field in the SYS_ID is 0x020 for the Base FVP_R & 0x010
+ * for the Foundation FVP_R.
+ */
+ switch (hbi) {
+ case HBI_FOUNDATION_FVP_R:
+ arm_config.flags = 0;
+
+ /*
+ * Check for supported revisions of Foundation FVP_R
+ * Allow future revisions to run but emit warning diagnostic
+ */
+ switch (rev) {
+ case REV_FOUNDATION_FVP_R_V2_0:
+ case REV_FOUNDATION_FVP_R_V2_1:
+ case REV_FOUNDATION_FVP_R_v9_1:
+ case REV_FOUNDATION_FVP_R_v9_6:
+ break;
+ default:
+ WARN("Unrecognized Foundation FVP_R revision %x\n", rev);
+ break;
+ }
+ break;
+ case HBI_BASE_FVP_R:
+ arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
+
+ /*
+ * Check for supported revisions
+ * Allow future revisions to run but emit warning diagnostic
+ */
+ switch (rev) {
+ case REV_BASE_FVP_R_V0:
+ arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
+ break;
+ default:
+ WARN("Unrecognized Base FVP_R revision %x\n", rev);
+ break;
+ }
+ break;
+ default:
+ ERROR("Unsupported board HBI number 0x%x\n", hbi);
+ panic();
+ }
+
+ /*
+ * We assume that the presence of MT bit, and therefore shifted
+ * affinities, is uniform across the platform: either all CPUs, or no
+ * CPUs implement it.
+ */
+ if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) {
+ arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
+ }
+}
+
+
+void __init fvp_interconnect_init(void)
+{
+ uintptr_t cci_base = 0U;
+ const int *cci_map = NULL;
+ unsigned int map_size = 0U;
+
+ /* Initialize the right interconnect */
+ if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) {
+ cci_base = PLAT_FVP_R_CCI5XX_BASE;
+ cci_map = fvp_cci5xx_map;
+ map_size = ARRAY_SIZE(fvp_cci5xx_map);
+ } else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) {
+ cci_base = PLAT_FVP_R_CCI400_BASE;
+ cci_map = fvp_cci400_map;
+ map_size = ARRAY_SIZE(fvp_cci400_map);
+ } else {
+ return;
+ }
+
+ assert(cci_base != 0U);
+ assert(cci_map != NULL);
+ cci_init(cci_base, cci_map, map_size);
+}
+
+void fvp_interconnect_enable(void)
+{
+ unsigned int master;
+
+ if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+ ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+ master = get_interconnect_master();
+ cci_enable_snoop_dvm_reqs(master);
+ }
+}
+
+void fvp_interconnect_disable(void)
+{
+ unsigned int master;
+
+ if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+ ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+ master = get_interconnect_master();
+ cci_disable_snoop_dvm_reqs(master);
+ }
+}
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void fvp_timer_init(void)
+{
+#if USE_SP804_TIMER
+ /* Enable the clock override for SP804 timer 0, which means that no
+ * clock dividers are applied and the raw (35MHz) clock will be used.
+ */
+ mmio_write_32(V2M_SP810_BASE, FVP_R_SP810_CTRL_TIM0_OV);
+
+ /* Initialize delay timer driver using SP804 dual timer 0 */
+ sp804_timer_init(V2M_SP804_TIMER0_BASE,
+ SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
+#else
+ generic_delay_timer_init();
+
+ /* Enable System level generic timer */
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0U) | CNTCR_EN);
+#endif /* USE_SP804_TIMER */
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+ return (int32_t)
+ ((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT)
+ | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT)
+ | FVP_R_SOC_ID);
+}
+
+/* Get SOC revision */
+int32_t plat_get_soc_revision(void)
+{
+ unsigned int sys_id;
+
+ sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
+ return (int32_t)((sys_id >> V2M_SYS_ID_REV_SHIFT) &
+ V2M_SYS_ID_REV_MASK);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
new file mode 100644
index 0000000..d172d2d
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+
+/************************************************************
+ * For R-class everything is in secure world.
+ * Prepare the CPU system registers for first entry into EL1
+ ************************************************************/
+void cm_prepare_el2_exit(void)
+{
+ uint64_t hcr_el2 = 0U;
+
+ /*
+ * The use of ARMv8.3 pointer authentication (PAuth) is governed
+ * by fields in HCR_EL2, which trigger a 'trap to EL2' if not
+ * enabled. This register initialized at boot up, update PAuth
+ * bits.
+ *
+ * HCR_API_BIT: Set to one to disable traps to EL2 if lower ELs
+ * access PAuth registers
+ *
+ * HCR_APK_BIT: Set to one to disable traps to EL2 if lower ELs
+ * access PAuth instructions
+ */
+ hcr_el2 = read_hcr_el2();
+ write_hcr_el2(hcr_el2 | HCR_API_BIT | HCR_APK_BIT);
+
+ /*
+ * Initialise CNTHCTL_EL2. All fields are architecturally UNKNOWN
+ * on reset and are set to zero except for field(s) listed below.
+ *
+ * CNTHCTL_EL2.EL1PCEN: Set to one to disable traps to EL2
+ * if lower ELs accesses to the physical timer registers.
+ *
+ * CNTHCTL_EL2.EL1PCTEN: Set to one to disable traps to EL2
+ * if lower ELs access to the physical counter registers.
+ */
+ write_cnthctl_el2(CNTHCTL_RESET_VAL | EL1PCEN_BIT | EL1PCTEN_BIT);
+
+ /*
+ * On Armv8-R, the EL1&0 memory system architecture is configurable
+ * as a VMSA or PMSA. All the fields architecturally UNKNOWN on reset
+ * and are set to zero except for field listed below.
+ *
+ * VCTR_EL2.MSA: Set to one to ensure the VMSA is enabled so that
+ * rich OS can boot.
+ */
+ write_vtcr_el2(VTCR_RESET_VAL | VTCR_EL2_MSA);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_debug.S b/plat/arm/board/fvp_r/fvp_r_debug.S
new file mode 100644
index 0000000..88f0a29
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_debug.S
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/debug.h>
+
+ .globl el2_panic
+
+ /***********************************************************
+ * The common implementation of do_panic for all BL stages
+ ***********************************************************/
+
+.section .rodata.panic_str, "aS"
+ panic_msg: .asciz "PANIC at PC : 0x"
+
+/*
+ * el2_panic will be redefined by the
+ * crash reporting mechanism (if enabled)
+ */
+el2_panic:
+ mov x6, x30
+ bl plat_crash_console_init
+
+ /* Check if the console is initialized */
+ cbz x0, _panic_handler
+
+ /* The console is initialized */
+ adr x4, panic_msg
+ bl asm_print_str
+ mov x4, x6
+
+ /* The panic location is lr -4 */
+ sub x4, x4, #4
+ bl asm_print_hex
+
+ bl plat_crash_console_flush
+
+_panic_handler:
+ /* Pass to plat_panic_handler the address from where el2_panic was
+ * called, not the address of the call from el2_panic.
+ */
+ mov x30, x6
+ b plat_panic_handler
diff --git a/plat/arm/board/fvp_r/fvp_r_def.h b/plat/arm/board/fvp_r/fvp_r_def.h
new file mode 100644
index 0000000..eda39cf
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_def.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_DEF_H
+#define FVP_R_DEF_H
+
+#include <lib/utils_def.h>
+
+/******************************************************************************
+ * FVP-R topology constants
+ *****************************************************************************/
+#define FVP_R_CLUSTER_COUNT 2
+#define FVP_R_MAX_CPUS_PER_CLUSTER 4
+#define FVP_R_MAX_PE_PER_CPU 1
+#define FVP_R_PRIMARY_CPU 0x0
+
+/******************************************************************************
+ * Definition of platform soc id
+ *****************************************************************************/
+#define FVP_R_SOC_ID 0
+
+/*******************************************************************************
+ * FVP_R memory map related constants
+ ******************************************************************************/
+
+#define FLASH1_BASE UL(0x8c000000)
+#define FLASH1_SIZE UL(0x04000000)
+
+#define PSRAM_BASE UL(0x94000000)
+#define PSRAM_SIZE UL(0x04000000)
+
+#define VRAM_BASE UL(0x98000000)
+#define VRAM_SIZE UL(0x02000000)
+
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE UL(0xa0000000)
+#define DEVICE0_SIZE UL(0x0c200000)
+
+/*
+ * In case of FVP_R models with CCN, the CCN register space overlaps into
+ * the NSRAM area.
+ */
+#define DEVICE1_BASE UL(0xae000000)
+#define DEVICE1_SIZE UL(0x1A00000)
+
+#define NSRAM_BASE UL(0xae000000)
+#define NSRAM_SIZE UL(0x10000)
+/* Devices in the second GB */
+#define DEVICE2_BASE UL(0xffe00000)
+#define DEVICE2_SIZE UL(0x00200000)
+
+#define PCIE_EXP_BASE UL(0xc0000000)
+#define TZRNG_BASE UL(0x7fe60000)
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE UL(0xffe70000)
+#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000))
+#define TFW_NVCTR_SIZE UL(4)
+#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004))
+#define NTFW_CTR_SIZE UL(4)
+
+/* Keys */
+#define SOC_KEYS_BASE UL(0xffe80000)
+#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000))
+#define TZ_PUB_KEY_HASH_SIZE UL(32)
+#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020))
+#define HU_KEY_SIZE UL(16)
+#define END_KEY_BASE (SOC_KEYS_BASE + UL(0x0044))
+#define END_KEY_SIZE UL(32)
+
+/* Constants to distinguish FVP_R type */
+#define HBI_BASE_FVP_R U(0x020)
+#define REV_BASE_FVP_R_V0 U(0x0)
+#define REV_BASE_FVP_R_REVC U(0x2)
+
+#define HBI_FOUNDATION_FVP_R U(0x010)
+#define REV_FOUNDATION_FVP_R_V2_0 U(0x0)
+#define REV_FOUNDATION_FVP_R_V2_1 U(0x1)
+#define REV_FOUNDATION_FVP_R_v9_1 U(0x2)
+#define REV_FOUNDATION_FVP_R_v9_6 U(0x3)
+
+#define BLD_GIC_VE_MMAP U(0x0)
+#define BLD_GIC_A53A57_MMAP U(0x1)
+
+#define ARCH_MODEL U(0x1)
+
+/* FVP_R Power controller base address*/
+#define PWRC_BASE UL(0x1c100000)
+
+/* FVP_R SP804 timer frequency is 35 MHz*/
+#define SP804_TIMER_CLKMULT 1
+#define SP804_TIMER_CLKDIV 35
+
+/* SP810 controller. FVP_R specific flags */
+#define FVP_R_SP810_CTRL_TIM0_OV BIT_32(16)
+#define FVP_R_SP810_CTRL_TIM1_OV BIT_32(18)
+#define FVP_R_SP810_CTRL_TIM2_OV BIT_32(20)
+#define FVP_R_SP810_CTRL_TIM3_OV BIT_32(22)
+
+#endif /* FVP_R_DEF_H */
diff --git a/plat/arm/board/fvp_r/fvp_r_err.c b/plat/arm/board/fvp_r/fvp_r_err.c
new file mode 100644
index 0000000..7ee752b
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_err.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/cfi/v2m_flash.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*
+ * FVP_R error handler
+ */
+__dead2 void plat_arm_error_handler(int err)
+{
+ int ret;
+
+ switch (err) {
+ case -ENOENT:
+ case -EAUTH:
+ /* Image load or authentication error. Erase the ToC */
+ INFO("Erasing FIP ToC from flash...\n");
+ (void)nor_unlock(PLAT_ARM_FLASH_IMAGE_BASE);
+ ret = nor_word_program(PLAT_ARM_FLASH_IMAGE_BASE, 0);
+ if (ret != 0) {
+ ERROR("Cannot erase ToC\n");
+ } else {
+ INFO("Done\n");
+ }
+ break;
+ default:
+ /* Unexpected error */
+ break;
+ }
+
+ (void)console_flush();
+
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_helpers.S b/plat/arm/board/fvp_r/fvp_r_helpers.S
new file mode 100644
index 0000000..ba85777
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_helpers.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+
+#include <platform_def.h>
+
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * TODO: Should we read the PSYS register to make sure
+ * that the request has gone through.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* ---------------------------------------------
+ * Power down this cpu.
+ * TODO: Do we need to worry about powering the
+ * cluster down as well here? That will need
+ * locks which we won't have unless an elf-
+ * loader zeroes out the zi section.
+ * ---------------------------------------------
+ */
+ mrs x0, mpidr_el1
+ mov_imm x1, PWRC_BASE
+ str w0, [x1, #PPOFFR_OFF]
+
+ /* ---------------------------------------------
+ * There is no sane reason to come out of this
+ * wfi so panic if we do. This cpu will be pow-
+ * ered on and reset by the cpu_on pm api
+ * ---------------------------------------------
+ */
+ dsb sy
+ wfi
+ no_ret plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot. On FVP_R, this information can be queried from the power
+ * controller. The Power Control SYS Status Register (PSYSR) indicates
+ * the wake-up reason for the CPU.
+ *
+ * For a cold boot, return 0.
+ * For a warm boot, read the mailbox and return the address it contains.
+ *
+ * TODO: PSYSR is a common register and should be
+ * accessed using locks. Since it is not possible
+ * to use locks immediately after a cold reset
+ * we are relying on the fact that after a cold
+ * reset all cpus will read the same WK field
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* ---------------------------------------------------------------------
+ * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
+ * WakeRequest signal" then it is a warm boot.
+ * ---------------------------------------------------------------------
+ */
+ mrs x2, mpidr_el1
+ mov_imm x1, PWRC_BASE
+ str w2, [x1, #PSYSR_OFF]
+ ldr w2, [x1, #PSYSR_OFF]
+ ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
+ cmp w2, #WKUP_PPONR
+ beq warm_reset
+ cmp w2, #WKUP_GICREQ
+ beq warm_reset
+
+ /* Cold reset */
+ mov x0, #0
+ ret
+
+warm_reset:
+ /* ---------------------------------------------------------------------
+ * A mailbox is maintained in the trusted SRAM. It is flushed out of the
+ * caches after every update using normal memory so it is safe to read
+ * it here with SO attributes.
+ * ---------------------------------------------------------------------
+ */
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr x0, [x0]
+ cbz x0, _panic_handler
+ ret
+
+ /* ---------------------------------------------------------------------
+ * The power controller indicates this is a warm reset but the mailbox
+ * is empty. This should never happen!
+ * ---------------------------------------------------------------------
+ */
+_panic_handler:
+ no_ret plat_panic_handler
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ mov_imm x1, MPIDR_AFFINITY_MASK
+ and x0, x0, x1
+ cmp x0, #FVP_R_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/arm/board/fvp_r/fvp_r_io_storage.c b/plat/arm/board/fvp_r/fvp_r_io_storage.c
new file mode 100644
index 0000000..3b44828
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_io_storage.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_semihosting.h>
+#include <drivers/io/io_storage.h>
+#include <lib/semihosting.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+
+/* Semihosting filenames */
+#define BL33_IMAGE_NAME "bl33.bin"
+
+#if TRUSTED_BOARD_BOOT
+#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
+#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt"
+#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* IO devices */
+static const io_dev_connector_t *sh_dev_con;
+static uintptr_t sh_dev_handle;
+
+static const io_file_spec_t sh_file_spec[] = {
+ [BL33_IMAGE_ID] = {
+ .path = BL33_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_KEY_CERT_ID] = {
+ .path = TRUSTED_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ .path = NT_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ .path = NT_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+
+static int open_semihosting(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if the file exists on semi-hosting.*/
+ result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(sh_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Semi-hosting IO\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+void plat_arm_io_setup(void)
+{
+ int io_result;
+
+ io_result = arm_io_setup();
+ if (io_result < 0) {
+ panic();
+ }
+
+ /* Register the additional IO devices on this platform */
+ io_result = register_io_dev_sh(&sh_dev_con);
+ if (io_result < 0) {
+ panic();
+ }
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
+ if (io_result < 0) {
+ panic();
+ }
+}
+
+/*
+ * FVP_R provides semihosting as an alternative to load images
+ */
+int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
+
+ if (result == 0) {
+ *dev_handle = sh_dev_handle;
+ *image_spec = (uintptr_t)&sh_file_spec[image_id];
+ }
+
+ return result;
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_misc_helpers.S b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
new file mode 100644
index 0000000..67ad164
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+ .globl disable_mpu_el2
+ .globl disable_mpu_icache_el2
+
+/* ---------------------------------------------------------------------------
+ * Disable the MPU at EL2.
+ * ---------------------------------------------------------------------------
+ */
+
+func disable_mpu_el2
+ mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT)
+do_disable_mpu_el2:
+ mrs x0, sctlr_el2
+ bic x0, x0, x1
+ msr sctlr_el2, x0
+ isb /* ensure MMU is off */
+ dsb sy
+ ret
+endfunc disable_mpu_el2
+
+
+func disable_mpu_icache_el2
+ mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
+ b do_disable_mpu_el2
+endfunc disable_mpu_icache_el2
diff --git a/plat/arm/board/fvp_r/fvp_r_private.h b/plat/arm/board/fvp_r/fvp_r_private.h
new file mode 100644
index 0000000..48f6e89
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_private.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_PRIVATE_H
+#define FVP_R_PRIVATE_H
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+void fvp_config_setup(void);
+
+void fvp_interconnect_init(void);
+void fvp_interconnect_enable(void);
+void fvp_interconnect_disable(void);
+void fvp_timer_init(void);
+
+#endif /* FVP_R_PRIVATE_H */
diff --git a/plat/arm/board/fvp_r/fvp_r_stack_protector.c b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
new file mode 100644
index 0000000..69b6312
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <fvp_r_arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 8092347823957523895ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * Ideally, a random number should be returned instead of the
+ * combination of a timer's value and a compile-time constant. As the
+ * FVP_R does not have any random number generator, this is better than
+ * nothing but not necessarily really secure.
+ */
+ return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
+
diff --git a/plat/arm/board/fvp_r/fvp_r_trusted_boot.c b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
new file mode 100644
index 0000000..de0b28f
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <lib/fconf/fconf.h>
+#include <lib/mmio.h>
+#include <tools_share/tbbr_oid.h>
+
+#include <plat/arm/common/fconf_nv_cntr_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
+
+/*
+ * Store a new non-volatile counter value.
+ *
+ * On some FVP_R versions, the non-volatile counters are read-only so this
+ * function will always fail.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ const char *oid;
+ uintptr_t nv_ctr_addr;
+
+ assert(cookie != NULL);
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ TRUSTED_NV_CTR_ID);
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+ NON_TRUSTED_NV_CTR_ID);
+ } else {
+ return 1;
+ }
+
+ mmio_write_32(nv_ctr_addr, nv_ctr);
+
+ /*
+ * If the FVP_R models a locked counter then its value cannot be updated
+ * and the above write operation has been silently ignored.
+ */
+ return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1;
+}
diff --git a/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
new file mode 100644
index 0000000..92bf484
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_ARCH_HELPERS_H
+#define FVP_R_ARCH_HELPERS_H
+
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * MPU register definitions
+ ******************************************************************************/
+#define MPUIR_EL2 S3_4_C0_C0_4
+#define PRBAR_EL2 S3_4_C6_C8_0
+#define PRLAR_EL2 S3_4_C6_C8_1
+#define PRSELR_EL2 S3_4_C6_C2_1
+#define PRENR_EL2 S3_4_C6_C1_1
+
+/* v8-R64 MPU registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(mpuir_el2, MPUIR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prenr_el2, PRENR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prselr_el2, PRSELR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prbar_el2, PRBAR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prlar_el2, PRLAR_EL2)
+
+#endif /* FVP_R_ARCH_HELPERS_H */
diff --git a/plat/arm/board/fvp_r/include/platform_def.h b/plat/arm/board/fvp_r/include/platform_def.h
new file mode 100644
index 0000000..ea3a258
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/platform_def.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_PLATFORM_DEF_H
+#define FVP_R_PLATFORM_DEF_H
+
+#define PLAT_V2M_OFFSET 0x80000000
+
+#define BL33_IMAGE_DESC { \
+ .image_id = BL33_IMAGE_ID, \
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, \
+ VERSION_2, image_info_t, 0), \
+ .image_info.image_base = PLAT_ARM_DRAM1_BASE + 0x1000, \
+ .image_info.image_max_size = UL(0x3ffff000), \
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, \
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),\
+ .ep_info.pc = PLAT_ARM_DRAM1_BASE + 0x1000, \
+ .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), \
+}
+
+#include "../fvp_r_def.h"
+#include <drivers/arm/tzc400.h>
+#include <lib/utils_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+
+/* These are referenced by arm_def.h #included next, so #define first. */
+#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x80000000)
+#define PLAT_ARM_TRUSTED_SRAM_BASE UL(0x84000000)
+#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x86000000)
+#define PLAT_ARM_DRAM1_BASE ULL(0x0)
+#define PLAT_ARM_DRAM2_BASE ULL(0x080000000)
+
+#define PLAT_HW_CONFIG_DTB_BASE ULL(0x12000000)
+#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000)
+#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000)
+#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000)
+#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000)
+#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000)
+#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000)
+
+#include <plat/arm/common/arm_def.h>
+#include <plat/common/common_def.h>
+
+
+/* Required to create plat_regions: */
+#define MIN_LVL_BLOCK_DESC U(1)
+
+/* Required platform porting definitions */
+#define PLATFORM_CORE_COUNT (U(FVP_R_CLUSTER_COUNT) * \
+ U(FVP_R_MAX_CPUS_PER_CLUSTER) * \
+ U(FVP_R_MAX_PE_PER_CPU))
+
+#define PLAT_NUM_PWR_DOMAINS (U(FVP_R_CLUSTER_COUNT) + \
+ PLATFORM_CORE_COUNT + U(1))
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2
+
+/*
+ * Other platform porting definitions are provided by included headers
+ */
+
+/*
+ * Required ARM standard platform porting definitions
+ */
+#define PLAT_ARM_CLUSTER_COUNT U(FVP_R_CLUSTER_COUNT)
+#define PLAT_ARM_DRAM1_SIZE ULL(0x7fffffff)
+#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */
+#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */
+#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */
+
+/* These two are defined thus in arm_def.h, but doesn't seem to see it... */
+#define PLAT_BL1_RO_LIMIT (BL1_RO_BASE \
+ + PLAT_ARM_TRUSTED_ROM_SIZE)
+
+#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000)
+#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000)
+#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000)
+#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000)
+#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000)
+#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000)
+
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
+
+/* No SCP in FVP_R */
+#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0)
+
+#define PLAT_ARM_DRAM2_SIZE UL(0x80000000)
+
+#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000)
+
+#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \
+ PLAT_HW_CONFIG_DTB_BASE, \
+ PLAT_HW_CONFIG_DTB_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
+
+#define V2M_FVP_R_SYSREGS_BASE UL(0x9c010000)
+
+/*
+ * Load address of BL33 for this platform port,
+ * U-Boot specifically must be loaded at a 4K aligned address.
+ */
+#define PLAT_ARM_NS_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + 0x1000)
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if !USE_ROMLIB
+# define PLAT_ARM_MMAP_ENTRIES 11
+# define MAX_XLAT_TABLES 5
+#else
+# define PLAT_ARM_MMAP_ENTRIES 12
+# define MAX_XLAT_TABLES 6
+#endif
+# define N_MPU_REGIONS 16 /* number of MPU regions */
+# define ALL_MPU_EL2_REGIONS_USED 0xffffffff
+ /* this is the PRENR_EL2 value if all MPU regions are in use */
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000)
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000)
+#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0x6000)
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0)
+#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+#if COT_DESC_IN_DTB
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1E000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#endif
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#endif
+
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000)
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x500)
+# endif
+#endif
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+/*
+ * These nominally reserve the last block of flash for PSCI MEM PROTECT flag,
+ * but no PSCI in FVP_R platform, so reserve nothing:
+ */
+#define PLAT_ARM_FLASH_IMAGE_BASE (PLAT_ARM_DRAM1_BASE + UL(0x40000000))
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (PLAT_ARM_DRAM1_SIZE - UL(0x40000000))
+
+#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
+
+#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE
+#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ
+
+/* CCI related constants */
+#define PLAT_FVP_R_CCI400_BASE UL(0xac090000)
+#define PLAT_FVP_R_CCI400_CLUS0_SL_PORT 3
+#define PLAT_FVP_R_CCI400_CLUS1_SL_PORT 4
+
+/* CCI-500/CCI-550 on Base platform */
+#define PLAT_FVP_R_CCI5XX_BASE UL(0xaa000000)
+#define PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT 5
+#define PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT 6
+
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
+
+/* Mailbox base address */
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
+
+
+/* TrustZone controller related constants
+ *
+ * Currently only filters 0 and 2 are connected on Base FVP_R.
+ * Filter 0 : CPU clusters (no access to DRAM by default)
+ * Filter 1 : not connected
+ * Filter 2 : LCDs (access to VRAM allowed by default)
+ * Filter 3 : not connected
+ * Programming unconnected filters will have no effect at the
+ * moment. These filter could, however, be connected in future.
+ * So care should be taken not to configure the unused filters.
+ *
+ * Allow only non-secure access to all DRAM to supported devices.
+ * Give access to the CPUs and Virtio. Some devices
+ * would normally use the default ID so allow that too.
+ */
+#define PLAT_ARM_TZC_BASE UL(0xaa4a0000)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_DEFAULT) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_PCI) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_AP) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO) | \
+ TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO_OLD))
+
+/*
+ * GIC related constants to cater for both GICv2 and GICv3 instances of an
+ * FVP_R. They could be overridden at runtime in case the FVP_R implements the
+ * legacy VE memory map.
+ */
+#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
+#define PLAT_ARM_GICR_BASE BASE_GICR_BASE
+#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
+
+#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
+ PLAT_SP_IMAGE_NS_BUF_SIZE)
+
+#define PLAT_SP_PRI PLAT_RAS_PRI
+
+/*
+ * Physical and virtual address space limits for MPU in AARCH64 & AARCH32 modes
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
+
+#define ARM_SOC_CONTINUATION_SHIFT U(24)
+#define ARM_SOC_IDENTIFICATION_SHIFT U(16)
+
+#endif /* FVP_R_PLATFORM_DEF_H */
diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk
new file mode 100644
index 0000000..93b5cf2
--- /dev/null
+++ b/plat/arm/board/fvp_r/platform.mk
@@ -0,0 +1,99 @@
+#
+# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Only aarch64 ARCH supported for FVP_R
+ARCH := aarch64
+
+# Override to exclude BL2, BL2U, BL31, and BL33 for FVP_R
+override NEED_BL2 := no
+override NEED_BL2U := no
+override NEED_BL31 := no
+NEED_BL32 := no
+
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+# Use MPU-based memory management:
+XLAT_MPU_LIB_V1 := 1
+
+# FVP R will not have more than 2 clusters so just use CCI interconnect
+FVP_R_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c
+
+
+include plat/arm/board/common/board_common.mk
+include plat/arm/common/arm_common.mk
+
+PLAT_INCLUDES := -Iplat/arm/board/fvp_r/include
+
+FVP_R_BL_COMMON_SOURCES := plat/arm/board/fvp_r/fvp_r_common.c \
+ plat/arm/board/fvp_r/fvp_r_context_mgmt.c \
+ plat/arm/board/fvp_r/fvp_r_debug.S \
+ plat/arm/board/fvp_r/fvp_r_err.c \
+ plat/arm/board/fvp_r/fvp_r_helpers.S \
+ plat/arm/board/fvp_r/fvp_r_misc_helpers.S
+
+FVP_R_BL1_SOURCES := plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c \
+ plat/arm/board/fvp_r/fvp_r_bl1_setup.c \
+ plat/arm/board/fvp_r/fvp_r_io_storage.c \
+ plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S \
+ plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S \
+ plat/arm/board/fvp_r/fvp_r_bl1_main.c
+
+FVP_R_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
+
+FVP_R_DYNC_CFG_SOURCES := common/fdt_wrappers.c \
+ plat/arm/common/arm_dyn_cfg.c
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+FVP_R_AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ lib/fconf/fconf_tbbr_getter.c \
+ plat/common/tbbr/plat_tbbr.c \
+ drivers/auth/tbbr/tbbr_cot_bl1_r64.c \
+ drivers/auth/tbbr/tbbr_cot_common.c \
+ plat/arm/board/common/board_arm_trusted_boot.c \
+ plat/arm/board/common/rotpk/arm_dev_rotpk.S \
+ plat/arm/board/fvp_r/fvp_r_trusted_boot.c
+
+FVP_R_BL1_SOURCES += ${MBEDTLS_SOURCES} \
+ ${FVP_R_AUTH_SOURCES}
+endif
+
+ifeq (${USE_SP804_TIMER},1)
+FVP_R_BL_COMMON_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+else
+FVP_R_BL_COMMON_SOURCES += drivers/delay_timer/generic_delay_timer.c
+endif
+
+# Enable Activity Monitor Unit extensions by default
+ENABLE_AMU := 1
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+FVP_R_BL_COMMON_SOURCES += plat/arm/board/fvp_r/fvp_r_stack_protector.c
+endif
+
+override BL1_SOURCES := drivers/arm/sp805/sp805.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_semihosting.c \
+ lib/cpus/aarch64/cpu_helpers.S \
+ lib/fconf/fconf_dyn_cfg_getter.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ plat/arm/common/arm_bl1_setup.c \
+ plat/arm/common/arm_err.c \
+ plat/arm/common/arm_io_storage.c \
+ plat/arm/common/fconf/arm_fconf_io.c \
+ plat/common/plat_bl1_common.c \
+ plat/common/aarch64/platform_up_stack.S \
+ ${FVP_R_BL1_SOURCES} \
+ ${FVP_R_BL_COMMON_SOURCES} \
+ ${FVP_R_CPU_LIBS} \
+ ${FVP_R_DYNC_CFG_SOURCES} \
+ ${FVP_R_INTERCONNECT_SOURCES}
diff --git a/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S b/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S
new file mode 100644
index 0000000..78f6c68
--- /dev/null
+++ b/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * For AArch32, cold-booting secondary CPUs is not yet
+ * implemented and they panic.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot. On FVP, this information can be queried from the power
+ * controller. The Power Control SYS Status Register (PSYSR) indicates
+ * the wake-up reason for the CPU.
+ *
+ * For a cold boot, return 0.
+ * For a warm boot, read the mailbox and return the address it contains.
+ *
+ * TODO: PSYSR is a common register and should be
+ * accessed using locks. Since it is not possible
+ * to use locks immediately after a cold reset
+ * we are relying on the fact that after a cold
+ * reset all cpus will read the same WK field
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* TODO support warm boot */
+ /* Cold reset */
+ mov r0, #0
+ bx lr
+
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Currently configured for a sigle CPU
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mov r0, #1
+ bx lr
+endfunc plat_is_my_cpu_primary
diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
new file mode 100644
index 0000000..6e5691b
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x80001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ hw-config {
+ load-address = <0x0 0x82000000>;
+ max-size = <0x01000000>;
+ id = <HW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
new file mode 100644
index 0000000..c66186f
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ };
+};
diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
new file mode 100644
index 0000000..736cf42
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/sp805.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ arm_bl1_early_platform_setup();
+}
+
+void plat_arm_secure_wdt_start(void)
+{
+ sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sp805_stop(ARM_SP805_TWDG_BASE);
+}
+
+void bl1_platform_setup(void)
+{
+ arm_bl1_platform_setup();
+}
diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c
new file mode 100644
index 0000000..4ccae27
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/sp804_delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "fvp_ve_private.h"
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
+{
+ arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
+
+ /* Initialize the platform config for future decision making */
+ fvp_ve_config_setup();
+}
+
+void bl2_platform_setup(void)
+{
+ arm_bl2_platform_setup();
+
+#if USE_SP804_TIMER
+ /*
+ * Enable the clock override for SP804 timer 0, which means that no
+ * clock dividers are applied and the raw (35 MHz) clock will be used
+ */
+ mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV);
+
+ /* Initialize delay timer driver using SP804 dual timer 0 */
+ sp804_timer_init(V2M_SP804_TIMER0_BASE,
+ SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
+#else
+ generic_delay_timer_init();
+#endif /* USE_SP804_TIMER */
+}
diff --git a/plat/arm/board/fvp_ve/fvp_ve_common.c b/plat/arm/board/fvp_ve/fvp_ve_common.c
new file mode 100644
index 0000000..768dad5
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_common.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#ifdef IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH1_RW,
+ V2M_MAP_IOFPGA,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH1_RW,
+ V2M_MAP_IOFPGA,
+ ARM_MAP_NS_DRAM1,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL32
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_IOFPGA,
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+
+ARM_CASSERT_MMAP
+
+void __init fvp_ve_config_setup(void)
+{
+ unsigned int sys_id, arch;
+
+ sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
+ arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
+
+ if (arch != ARCH_MODEL_VE) {
+ ERROR("This firmware is for FVP VE models\n");
+ panic();
+ }
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return FVP_VE_TIMER_BASE_FREQUENCY;
+}
diff --git a/plat/arm/board/fvp_ve/fvp_ve_def.h b/plat/arm/board/fvp_ve/fvp_ve_def.h
new file mode 100644
index 0000000..98de5f6
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_def.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_VE_DEF_H
+#define FVP_VE_DEF_H
+
+#include <lib/utils_def.h>
+
+/* Default cluster count for FVP VE */
+#define FVP_VE_CLUSTER_COUNT U(1)
+
+/* Default number of CPUs per cluster on FVP VE */
+#define FVP_VE_MAX_CPUS_PER_CLUSTER U(1)
+
+/* Default number of threads per CPU on FVP VE */
+#define FVP_VE_MAX_PE_PER_CPU U(1)
+
+#define FVP_VE_CORE_COUNT U(1)
+
+#define FVP_VE_PRIMARY_CPU 0x0
+
+/*******************************************************************************
+ * FVP memory map related constants
+ ******************************************************************************/
+
+#define FLASH1_BASE 0x0c000000
+#define FLASH1_SIZE 0x04000000
+
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE 0x20000000
+#define DEVICE0_SIZE 0x0c200000
+
+#define NSRAM_BASE 0x2e000000
+#define NSRAM_SIZE 0x10000
+
+#define PCIE_EXP_BASE 0x40000000
+#define TZRNG_BASE 0x7fe60000
+
+#define ARCH_MODEL_VE 0x5
+
+/* FVP Power controller base address*/
+#define PWRC_BASE UL(0x1c100000)
+
+/* FVP SP804 timer frequency is 35 MHz*/
+#define SP804_TIMER_CLKMULT 1
+#define SP804_TIMER_CLKDIV 35
+
+/* SP810 controller. FVP specific flags */
+#define FVP_SP810_CTRL_TIM0_OV (1 << 16)
+#define FVP_SP810_CTRL_TIM1_OV (1 << 18)
+#define FVP_SP810_CTRL_TIM2_OV (1 << 20)
+#define FVP_SP810_CTRL_TIM3_OV (1 << 22)
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+/* VE compatible GIC memory map */
+#define VE_GICD_BASE 0x2c001000
+#ifdef ARM_CORTEX_A5
+#define VE_GICC_BASE 0x2c000100
+#else
+#define VE_GICC_BASE 0x2c002000
+#endif
+#define VE_GICH_BASE 0x2c004000
+#define VE_GICV_BASE 0x2c006000
+
+#define FVP_VE_IRQ_TZ_WDOG 56
+#define FVP_VE_IRQ_SEC_SYS_TIMER 57
+
+#define V2M_FLASH1_BASE UL(0x0C000000)
+#define V2M_FLASH1_SIZE UL(0x04000000)
+
+#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\
+ V2M_FLASH1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\
+ V2M_FLASH1_SIZE, \
+ MT_RO_DATA | MT_SECURE)
+
+#endif /* FVP_VE_DEF_H */
diff --git a/plat/arm/board/fvp_ve/fvp_ve_err.c b/plat/arm/board/fvp_ve/fvp_ve_err.c
new file mode 100644
index 0000000..8d35688
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * FVP VE error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/fvp_ve/fvp_ve_pm.c b/plat/arm/board/fvp_ve/fvp_ve_pm.c
new file mode 100644
index 0000000..a4d627b
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_pm.c
@@ -0,0 +1,25 @@
+/*
+* Copyright (c) 2019, Arm Limited. All rights reserved.
+*
+* SPDX-License-Identifier: BSD-3-Clause
+*/
+
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Export the platform handlers via fvp_ve_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t fvp_ve_psci_pm_ops = {
+ /* dummy struct */
+ .validate_ns_entrypoint = NULL,
+};
+
+int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &fvp_ve_psci_pm_ops;
+
+ return 0;
+}
diff --git a/plat/arm/board/fvp_ve/fvp_ve_private.h b/plat/arm/board/fvp_ve/fvp_ve_private.h
new file mode 100644
index 0000000..5d396bc
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_VE_PRIVATE_H
+#define FVP_VE_PRIVATE_H
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+void fvp_ve_config_setup(void);
+
+#endif /* FVP_VE_PRIVATE_H */
diff --git a/plat/arm/board/fvp_ve/fvp_ve_security.c b/plat/arm/board/fvp_ve/fvp_ve_security.c
new file mode 100644
index 0000000..24465cb
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_security.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * We assume that all security programming is done by the primary core.
+ */
+void plat_arm_security_setup(void)
+{
+ /*
+ * The Base FVP has a TrustZone address space controller, the Foundation
+ * FVP does not. Trying to program the device on the foundation FVP will
+ * cause an abort.
+ *
+ * If the platform had additional peripheral specific security
+ * configurations, those would be configured here.
+ */
+
+ return;
+}
diff --git a/plat/arm/board/fvp_ve/fvp_ve_topology.c b/plat/arm/board/fvp_ve/fvp_ve_topology.c
new file mode 100644
index 0000000..51cc9da
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fvp_ve_topology.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* The FVP VE power domain tree descriptor */
+static const unsigned char fvp_ve_power_domain_tree_desc[] = {
+ 1,
+ /* No of children for the root node */
+ FVP_VE_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ FVP_VE_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the topology according to FVP_VE_CLUSTER_COUNT.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return fvp_ve_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * Currently FVP VE has only been tested with one core, therefore 0 is returned.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ return 0;
+}
diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h
new file mode 100644
index 0000000..bd8ef6a
--- /dev/null
+++ b/plat/arm/board/fvp_ve/include/platform_def.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+
+#include "../fvp_ve_def.h"
+
+#define ARM_CACHE_WRITEBACK_SHIFT 6
+
+/* Memory location options for TSP */
+#define ARM_DRAM_ID 2
+
+#define ARM_DRAM1_BASE UL(0x80000000)
+#define ARM_DRAM1_SIZE UL(0x80000000)
+#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
+ ARM_DRAM1_SIZE - 1)
+
+#define ARM_DRAM2_BASE PLAT_ARM_DRAM2_BASE
+#define ARM_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE
+#define ARM_DRAM2_END (ARM_DRAM2_BASE + \
+ ARM_DRAM2_SIZE - 1)
+
+#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE
+/*
+ * The last 2MB is meant to be NOLOAD and will not be zero
+ * initialized.
+ */
+#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \
+ 0x00200000)
+
+
+/* The first 4KB of NS DRAM1 are used as shared memory */
+#define FVP_VE_SHARED_RAM_BASE ARM_NS_DRAM1_BASE
+#define FVP_VE_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
+
+/* The next 252 kB of NS DRAM is used to load the BL images */
+#define ARM_BL_RAM_BASE (FVP_VE_SHARED_RAM_BASE + \
+ FVP_VE_SHARED_RAM_SIZE)
+#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \
+ FVP_VE_SHARED_RAM_SIZE)
+
+
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+#define ARM_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
+ FVP_VE_SHARED_RAM_BASE, \
+ FVP_VE_SHARED_RAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
+ ARM_NS_DRAM1_BASE, \
+ ARM_NS_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \
+ ARM_DRAM2_BASE, \
+ ARM_DRAM2_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE), \
+ MAP_REGION_FLAT( \
+ BL_RO_DATA_BASE, \
+ BL_RO_DATA_END \
+ - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+
+#if USE_COHERENT_MEM
+#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
+ BL_COHERENT_RAM_BASE, \
+ BL_COHERENT_RAM_END \
+ - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
+ (ARM_FW_CONFIGS_LIMIT \
+ - ARM_BL_RAM_BASE), \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+
+/*
+ * The max number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#define ARM_BL_REGIONS 6
+
+#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
+ ARM_BL_REGIONS)
+
+/* Memory mapped Generic timer interfaces */
+#define FVP_VE_TIMER_BASE_FREQUENCY UL(24000000)
+#define ARM_SYS_CNTREAD_BASE UL(0x2a800000)
+#define ARM_SYS_CNT_BASE_S UL(0x2a820000)
+#define ARM_SYS_CNT_BASE_NS UL(0x2a830000)
+
+#define ARM_CONSOLE_BAUDRATE 115200
+
+/* Trusted Watchdog constants */
+#define ARM_SP805_TWDG_BASE UL(0x1C0F0000)
+#define ARM_SP805_TWDG_CLK_HZ 32768
+/* The TBBR document specifies a watchdog timeout of 256 seconds. SP805
+ * asserts reset after two consecutive countdowns (2 x 128 = 256 sec) */
+#define ARM_TWDG_TIMEOUT_SEC 128
+#define ARM_TWDG_LOAD_VAL (ARM_SP805_TWDG_CLK_HZ * \
+ ARM_TWDG_TIMEOUT_SEC)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
+ * and limit. Leave enough space of BL2 meminfo.
+ */
+#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT ((ARM_BL_RAM_BASE + PAGE_SIZE) \
+ + (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
+/*******************************************************************************
+ * BL1 specific defines.
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ ******************************************************************************/
+#define BL1_RO_BASE 0x00000000
+#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE
+/*
+ * Put BL1 RW at the top of the memory allocated for BL images in NS DRAM.
+ */
+#define BL1_RW_BASE (ARM_BL_RAM_BASE + \
+ ARM_BL_RAM_SIZE - \
+ (PLAT_ARM_MAX_BL1_RW_SIZE))
+#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \
+ (ARM_BL_RAM_SIZE))
+
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+
+/*
+ * Put BL2 just below BL1.
+ */
+#define BL2_BASE (BL1_RW_BASE - FVP_VE_MAX_BL2_SIZE)
+#define BL2_LIMIT BL1_RW_BASE
+
+
+/* Put BL32 below BL2 in NS DRAM.*/
+#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
+ + (PAGE_SIZE / 2U))
+
+#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
+ - PLAT_ARM_MAX_BL32_SIZE)
+#define BL32_PROGBITS_LIMIT BL2_BASE
+#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+
+/* Required platform porting definitions */
+#define PLATFORM_CORE_COUNT FVP_VE_CLUSTER_COUNT
+#define PLAT_NUM_PWR_DOMAINS ((FVP_VE_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT) + U(1))
+
+#define PLAT_MAX_PWR_LVL 2
+
+/*
+ * Other platform porting definitions are provided by included headers
+ */
+
+/*
+ * Required ARM standard platform porting definitions
+ */
+
+#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */
+
+#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000
+#define PLAT_ARM_TRUSTED_ROM_SIZE 0x04000000 /* 64 MB */
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x880000000)
+#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000)
+
+/*
+ * Load address of BL33 for this platform port
+ */
+#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000))
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if defined(IMAGE_BL32)
+# define PLAT_ARM_MMAP_ENTRIES 8
+# define MAX_XLAT_TABLES 6
+#else
+# define PLAT_ARM_MMAP_ENTRIES 12
+# define MAX_XLAT_TABLES 6
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000
+
+/*
+ * FVP_VE_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#define FVP_VE_MAX_BL2_SIZE 0x11000
+
+/*
+ * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
+ * calculated using the current SP_MIN PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+#define PLAT_ARM_MAX_BL32_SIZE 0x3B000
+/*
+
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+# define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
+#define PLAT_ARM_FLASH_IMAGE_BASE V2M_FLASH1_BASE
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#define PLAT_ARM_NVM_BASE V2M_FLASH1_BASE
+#define PLAT_ARM_NVM_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ
+
+#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID 1
+
+/* Mailbox base address */
+#define FVP_VE_TRUSTED_MAILBOX_BASE FVP_VE_SHARED_RAM_BASE
+
+/*
+ * GIC related constants to cater for GICv2
+ */
+#define PLAT_ARM_GICD_BASE VE_GICD_BASE
+#define PLAT_ARM_GICC_BASE VE_GICC_BASE
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ ARM_G1S_IRQ_PROPS(grp), \
+ INTR_PROP_DESC(FVP_VE_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(FVP_VE_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+#endif /* PLATFORM_H */
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
new file mode 100644
index 0000000..f7eace8
--- /dev/null
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -0,0 +1,139 @@
+#
+# Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+ifdef ARM_CORTEX_A5
+# Use the SP804 timer instead of the generic one
+USE_SP804_TIMER := 1
+BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c
+endif
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+FVP_VE_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+
+FVP_VE_SECURITY_SOURCES := plat/arm/board/fvp_ve/fvp_ve_security.c
+
+PLAT_INCLUDES := -Iplat/arm/board/fvp_ve/include
+
+PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp_ve/fvp_ve_common.c \
+ plat/arm/common/${ARCH}/arm_helpers.S \
+ plat/arm/common/arm_common.c \
+ plat/arm/common/arm_console.c \
+ drivers/arm/pl011/${ARCH}/pl011_console.S \
+ plat/arm/board/common/${ARCH}/board_arm_helpers.S
+
+ifdef ARM_CORTEX_A5
+FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S
+else
+FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a7.S
+endif
+
+BL1_SOURCES += drivers/arm/sp805/sp805.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/arm/common/arm_bl1_setup.c \
+ plat/arm/common/arm_err.c \
+ plat/arm/board/fvp_ve/fvp_ve_err.c \
+ plat/arm/common/arm_io_storage.c \
+ plat/arm/common/fconf/arm_fconf_io.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ plat/arm/board/fvp_ve/${ARCH}/fvp_ve_helpers.S \
+ plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c \
+ lib/aarch32/arm32_aeabi_divmod.c \
+ lib/aarch32/arm32_aeabi_divmod_a32.S \
+ ${FVP_VE_CPU_LIBS} \
+ ${DYN_CFG_SOURCES}
+
+BL2_SOURCES += plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c \
+ lib/aarch32/arm32_aeabi_divmod.c \
+ lib/aarch32/arm32_aeabi_divmod_a32.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/arm/common/arm_bl2_setup.c \
+ plat/arm/common/arm_err.c \
+ plat/arm/board/fvp_ve/fvp_ve_err.c \
+ plat/arm/common/arm_io_storage.c \
+ plat/arm/common/fconf/arm_fconf_io.c \
+ plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \
+ plat/arm/common/arm_image_load.c \
+ common/desc_image_load.c \
+ ${DYN_CFG_SOURCES} \
+ ${FVP_VE_SECURITY_SOURCES}
+
+# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
+ifdef UNIX_MK
+
+FDT_SOURCES += plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts \
+ plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
+
+FVP_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb
+FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config,${FVP_FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config,${FVP_TB_FW_CONFIG}))
+
+FDT_SOURCES += ${FVP_HW_CONFIG_DTS}
+$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \
+ fdts/$(notdir ${FVP_HW_CONFIG_DTS})))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
+endif
+
+NEED_BL32 := yes
+
+# Modification of arm_common.mk
+
+# Process ARM_DISABLE_TRUSTED_WDOG flag
+# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set
+ARM_DISABLE_TRUSTED_WDOG := 0
+ifeq (${SPIN_ON_BL1_EXIT}, 1)
+ARM_DISABLE_TRUSTED_WDOG := 1
+endif
+$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG))
+$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG))
+
+# Use translation tables library v1 if using Cortex-A5
+ifdef ARM_CORTEX_A5
+ARM_XLAT_TABLES_LIB_V1 := 1
+else
+ARM_XLAT_TABLES_LIB_V1 := 0
+endif
+$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
+$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
+
+ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+ # Only use nonlpae version of xlatv1 otherwise use xlat v2
+ PLAT_BL_COMMON_SOURCES += lib/xlat_tables/${ARCH}/nonlpae_tables.c
+else
+ include lib/xlat_tables_v2/xlat_tables.mk
+ PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+endif
+
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
+
+BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+
+# Add `libfdt` and Arm common helpers required for Dynamic Config
+include lib/libfdt/libfdt.mk
+
+DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \
+ plat/arm/common/arm_dyn_cfg_helpers.c
+
+DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES}
diff --git a/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c b/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c
new file mode 100644
index 0000000..e6a1bbe
--- /dev/null
+++ b/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+}
diff --git a/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk
new file mode 100644
index 0000000..4ca810d
--- /dev/null
+++ b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SP_MIN source files specific to FVP platform
+BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S \
+ drivers/arm/fvp/fvp_pwrc.c \
+ plat/arm/board/fvp_ve/fvp_ve_pm.c \
+ plat/arm/board/fvp_ve/fvp_ve_topology.c \
+ plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c \
+ lib/aarch32/arm32_aeabi_divmod.c \
+ lib/aarch32/arm32_aeabi_divmod_a32.S \
+ plat/arm/common/sp_min/arm_sp_min_setup.c \
+ plat/common/aarch32/platform_mp_stack.S \
+ plat/common/plat_psci_common.c \
+ ${FVP_VE_CPU_LIBS} \
+ ${FVP_VE_GIC_SOURCES} \
+ ${FVP_VE_SECURITY_SOURCES}
diff --git a/plat/arm/board/juno/aarch32/juno_helpers.S b/plat/arm/board/juno/aarch32/juno_helpers.S
new file mode 100644
index 0000000..8f9561c
--- /dev/null
+++ b/plat/arm/board/juno/aarch32/juno_helpers.S
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a53.h>
+#include <cortex_a57.h>
+#include <cortex_a72.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+ .globl plat_reset_handler
+ .globl plat_arm_calc_core_pos
+
+#define JUNO_REVISION(rev) REV_JUNO_R##rev
+#define JUNO_HANDLER(rev) plat_reset_handler_juno_r##rev
+#define JUMP_TO_HANDLER_IF_JUNO_R(revision) \
+ jump_to_handler JUNO_REVISION(revision), JUNO_HANDLER(revision)
+
+ /* --------------------------------------------------------------------
+ * Helper macro to jump to the given handler if the board revision
+ * matches.
+ * Expects the Juno board revision in x0.
+ * --------------------------------------------------------------------
+ */
+ .macro jump_to_handler _revision, _handler
+ cmp r0, #\_revision
+ beq \_handler
+ .endm
+
+ /* --------------------------------------------------------------------
+ * Platform reset handler for Juno R0.
+ *
+ * Juno R0 has the following topology:
+ * - Quad core Cortex-A53 processor cluster;
+ * - Dual core Cortex-A57 processor cluster.
+ *
+ * This handler does the following:
+ * - Implement workaround for defect id 831273 by enabling an event
+ * stream every 65536 cycles.
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * --------------------------------------------------------------------
+ */
+func JUNO_HANDLER(0)
+ /* --------------------------------------------------------------------
+ * Enable the event stream every 65536 cycles
+ * --------------------------------------------------------------------
+ */
+ mov r0, #(0xf << EVNTI_SHIFT)
+ orr r0, r0, #EVNTEN_BIT
+ stcopr r0, CNTKCTL
+
+ /* --------------------------------------------------------------------
+ * Nothing else to do on Cortex-A53.
+ * --------------------------------------------------------------------
+ */
+ jump_if_cpu_midr CORTEX_A53_MIDR, 1f
+
+ /* --------------------------------------------------------------------
+ * Cortex-A57 specific settings
+ * --------------------------------------------------------------------
+ */
+ mov r0, #((CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT))
+ stcopr r0, CORTEX_A57_L2CTLR
+1:
+ isb
+ bx lr
+endfunc JUNO_HANDLER(0)
+
+ /* --------------------------------------------------------------------
+ * Platform reset handler for Juno R1.
+ *
+ * Juno R1 has the following topology:
+ * - Quad core Cortex-A53 processor cluster;
+ * - Dual core Cortex-A57 processor cluster.
+ *
+ * This handler does the following:
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ *
+ * Note that:
+ * - The default value for the L2 Tag RAM latency for Cortex-A57 is
+ * suitable.
+ * - Defect #831273 doesn't affect Juno R1.
+ * --------------------------------------------------------------------
+ */
+func JUNO_HANDLER(1)
+ /* --------------------------------------------------------------------
+ * Nothing to do on Cortex-A53.
+ * --------------------------------------------------------------------
+ */
+ jump_if_cpu_midr CORTEX_A57_MIDR, A57
+ bx lr
+
+A57:
+ /* --------------------------------------------------------------------
+ * Cortex-A57 specific settings
+ * --------------------------------------------------------------------
+ */
+ mov r0, #(CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT)
+ stcopr r0, CORTEX_A57_L2CTLR
+ isb
+ bx lr
+endfunc JUNO_HANDLER(1)
+
+ /* --------------------------------------------------------------------
+ * Platform reset handler for Juno R2.
+ *
+ * Juno R2 has the following topology:
+ * - Quad core Cortex-A53 processor cluster;
+ * - Dual core Cortex-A72 processor cluster.
+ *
+ * This handler does the following:
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72
+ * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72
+ *
+ * Note that:
+ * - Defect #831273 doesn't affect Juno R2.
+ * --------------------------------------------------------------------
+ */
+func JUNO_HANDLER(2)
+ /* --------------------------------------------------------------------
+ * Nothing to do on Cortex-A53.
+ * --------------------------------------------------------------------
+ */
+ jump_if_cpu_midr CORTEX_A72_MIDR, A72
+ bx lr
+
+A72:
+ /* --------------------------------------------------------------------
+ * Cortex-A72 specific settings
+ * --------------------------------------------------------------------
+ */
+ mov r0, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES << CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT))
+ stcopr r0, CORTEX_A72_L2CTLR
+ isb
+ bx lr
+endfunc JUNO_HANDLER(2)
+
+ /* --------------------------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Determine the Juno board revision and call the appropriate reset
+ * handler.
+ * --------------------------------------------------------------------
+ */
+func plat_reset_handler
+ /* Read the V2M SYS_ID register */
+ ldr r0, =(V2M_SYSREGS_BASE + V2M_SYS_ID)
+ ldr r1, [r0]
+ /* Extract board revision from the SYS_ID */
+ ubfx r0, r1, #V2M_SYS_ID_REV_SHIFT, #4
+
+ JUMP_TO_HANDLER_IF_JUNO_R(0)
+ JUMP_TO_HANDLER_IF_JUNO_R(1)
+ JUMP_TO_HANDLER_IF_JUNO_R(2)
+
+ /* Board revision is not supported */
+ no_ret plat_panic_handler
+
+endfunc plat_reset_handler
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ * Helper function to calculate the core position.
+ * -----------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ b css_calc_core_pos_swap_cluster
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/juno/aarch64/juno_helpers.S b/plat/arm/board/juno/aarch64/juno_helpers.S
new file mode 100644
index 0000000..c94fa3e
--- /dev/null
+++ b/plat/arm/board/juno/aarch64/juno_helpers.S
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a53.h>
+#include <cortex_a57.h>
+#include <cortex_a72.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+ .globl plat_reset_handler
+ .globl plat_arm_calc_core_pos
+#if JUNO_AARCH32_EL3_RUNTIME
+ .globl plat_get_my_entrypoint
+ .globl juno_reset_to_aarch32_state
+#endif
+
+#define JUNO_REVISION(rev) REV_JUNO_R##rev
+#define JUNO_HANDLER(rev) plat_reset_handler_juno_r##rev
+#define JUMP_TO_HANDLER_IF_JUNO_R(revision) \
+ jump_to_handler JUNO_REVISION(revision), JUNO_HANDLER(revision)
+
+ /* --------------------------------------------------------------------
+ * Helper macro to jump to the given handler if the board revision
+ * matches.
+ * Expects the Juno board revision in x0.
+ * --------------------------------------------------------------------
+ */
+ .macro jump_to_handler _revision, _handler
+ cmp x0, #\_revision
+ b.eq \_handler
+ .endm
+
+ /* --------------------------------------------------------------------
+ * Platform reset handler for Juno R0.
+ *
+ * Juno R0 has the following topology:
+ * - Quad core Cortex-A53 processor cluster;
+ * - Dual core Cortex-A57 processor cluster.
+ *
+ * This handler does the following:
+ * - Implement workaround for defect id 831273 by enabling an event
+ * stream every 65536 cycles.
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * --------------------------------------------------------------------
+ */
+func JUNO_HANDLER(0)
+ /* --------------------------------------------------------------------
+ * Enable the event stream every 65536 cycles
+ * --------------------------------------------------------------------
+ */
+ mov x0, #(0xf << EVNTI_SHIFT)
+ orr x0, x0, #EVNTEN_BIT
+ msr CNTKCTL_EL1, x0
+
+ /* --------------------------------------------------------------------
+ * Nothing else to do on Cortex-A53.
+ * --------------------------------------------------------------------
+ */
+ jump_if_cpu_midr CORTEX_A53_MIDR, 1f
+
+ /* --------------------------------------------------------------------
+ * Cortex-A57 specific settings
+ * --------------------------------------------------------------------
+ */
+ mov x0, #((CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT))
+ msr CORTEX_A57_L2CTLR_EL1, x0
+1:
+ isb
+ ret
+endfunc JUNO_HANDLER(0)
+
+ /* --------------------------------------------------------------------
+ * Platform reset handler for Juno R1.
+ *
+ * Juno R1 has the following topology:
+ * - Quad core Cortex-A53 processor cluster;
+ * - Dual core Cortex-A57 processor cluster.
+ *
+ * This handler does the following:
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ *
+ * Note that:
+ * - The default value for the L2 Tag RAM latency for Cortex-A57 is
+ * suitable.
+ * - Defect #831273 doesn't affect Juno R1.
+ * --------------------------------------------------------------------
+ */
+func JUNO_HANDLER(1)
+ /* --------------------------------------------------------------------
+ * Nothing to do on Cortex-A53.
+ * --------------------------------------------------------------------
+ */
+ jump_if_cpu_midr CORTEX_A57_MIDR, A57
+ ret
+
+A57:
+ /* --------------------------------------------------------------------
+ * Cortex-A57 specific settings
+ * --------------------------------------------------------------------
+ */
+ mov x0, #(CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT)
+ msr CORTEX_A57_L2CTLR_EL1, x0
+ isb
+ ret
+endfunc JUNO_HANDLER(1)
+
+ /* --------------------------------------------------------------------
+ * Platform reset handler for Juno R2.
+ *
+ * Juno R2 has the following topology:
+ * - Quad core Cortex-A53 processor cluster;
+ * - Dual core Cortex-A72 processor cluster.
+ *
+ * This handler does the following:
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72
+ * - Set the L2 Tag RAM latency to 1 (i.e. 2 cycles) for Cortex-A72
+ *
+ * Note that:
+ * - Defect #831273 doesn't affect Juno R2.
+ * --------------------------------------------------------------------
+ */
+func JUNO_HANDLER(2)
+ /* --------------------------------------------------------------------
+ * Nothing to do on Cortex-A53.
+ * --------------------------------------------------------------------
+ */
+ jump_if_cpu_midr CORTEX_A72_MIDR, A72
+ ret
+
+A72:
+ /* --------------------------------------------------------------------
+ * Cortex-A72 specific settings
+ * --------------------------------------------------------------------
+ */
+ mov x0, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES << CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT))
+ msr CORTEX_A57_L2CTLR_EL1, x0
+ isb
+ ret
+endfunc JUNO_HANDLER(2)
+
+ /* --------------------------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Determine the Juno board revision and call the appropriate reset
+ * handler.
+ * --------------------------------------------------------------------
+ */
+func plat_reset_handler
+ /* Read the V2M SYS_ID register */
+ mov_imm x0, (V2M_SYSREGS_BASE + V2M_SYS_ID)
+ ldr w1, [x0]
+ /* Extract board revision from the SYS_ID */
+ ubfx x0, x1, #V2M_SYS_ID_REV_SHIFT, #4
+
+ JUMP_TO_HANDLER_IF_JUNO_R(0)
+ JUMP_TO_HANDLER_IF_JUNO_R(1)
+ JUMP_TO_HANDLER_IF_JUNO_R(2)
+
+ /* Board revision is not supported */
+ no_ret plat_panic_handler
+
+endfunc plat_reset_handler
+
+ /* -----------------------------------------------------
+ * void juno_do_reset_to_aarch32_state(void);
+ *
+ * Request warm reset to AArch32 mode.
+ * -----------------------------------------------------
+ */
+func juno_do_reset_to_aarch32_state
+ mov x0, #RMR_EL3_RR_BIT
+ dsb sy
+ msr rmr_el3, x0
+ isb
+ wfi
+ b plat_panic_handler
+endfunc juno_do_reset_to_aarch32_state
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ * Helper function to calculate the core position.
+ * -----------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ b css_calc_core_pos_swap_cluster
+endfunc plat_arm_calc_core_pos
+
+#if JUNO_AARCH32_EL3_RUNTIME
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and a warm
+ * boot. On JUNO platform, this distinction is based on the contents of
+ * the Trusted Mailbox. It is initialised to zero by the SCP before the
+ * AP cores are released from reset. Therefore, a zero mailbox means
+ * it's a cold reset. If it is a warm boot then a request to reset to
+ * AArch32 state is issued. This is the only way to reset to AArch32
+ * in EL3 on Juno. A trampoline located at the high vector address
+ * has already been prepared by BL1.
+ *
+ * This functions returns the contents of the mailbox, i.e.:
+ * - 0 for a cold boot;
+ * - request warm reset in AArch32 state for warm boot case;
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr x0, [x0]
+ cbz x0, return
+ b juno_do_reset_to_aarch32_state
+return:
+ ret
+endfunc plat_get_my_entrypoint
+
+/*
+ * Emit a "movw r0, #imm16" which moves the lower
+ * 16 bits of `_val` into r0.
+ */
+.macro emit_movw _reg_d, _val
+ mov_imm \_reg_d, (0xe3000000 | \
+ ((\_val & 0xfff) | \
+ ((\_val & 0xf000) << 4)))
+.endm
+
+/*
+ * Emit a "movt r0, #imm16" which moves the upper
+ * 16 bits of `_val` into r0.
+ */
+.macro emit_movt _reg_d, _val
+ mov_imm \_reg_d, (0xe3400000 | \
+ (((\_val & 0x0fff0000) >> 16) | \
+ ((\_val & 0xf0000000) >> 12)))
+.endm
+
+/*
+ * This function writes the trampoline code at HI-VEC (0xFFFF0000)
+ * address which loads r0 with the entrypoint address for
+ * BL32 (a.k.a SP_MIN) when EL3 is in AArch32 mode. A warm reset
+ * to AArch32 mode is then requested by writing into RMR_EL3.
+ */
+func juno_reset_to_aarch32_state
+ /*
+ * Invalidate all caches before the warm reset to AArch32 state.
+ * This is required on the Juno AArch32 boot flow because the L2
+ * unified cache may contain code and data from when the processor
+ * was still executing in AArch64 state. This code only runs on
+ * the primary core, all other cores are powered down.
+ */
+ mov x0, #DCISW
+ bl dcsw_op_all
+
+ emit_movw w0, BL32_BASE
+ emit_movt w1, BL32_BASE
+ /* opcode "bx r0" to branch using r0 in AArch32 mode */
+ mov_imm w2, 0xe12fff10
+
+ /* Write the above opcodes at HI-VECTOR location */
+ mov_imm x3, HI_VECTOR_BASE
+ str w0, [x3], #4
+ str w1, [x3], #4
+ str w2, [x3]
+
+ b juno_do_reset_to_aarch32_state
+endfunc juno_reset_to_aarch32_state
+
+#endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/fdts/juno_fw_config.dts b/plat/arm/board/juno/fdts/juno_fw_config.dts
new file mode 100644
index 0000000..4b88efe
--- /dev/null
+++ b/plat/arm/board/juno/fdts/juno_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019-2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ hw-config {
+ load-address = <0x0 0x82000000>;
+ max-size = <0x8000>;
+ id = <HW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/juno/fdts/juno_tb_fw_config.dts b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
new file mode 100644
index 0000000..80cfa3e
--- /dev/null
+++ b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/juno/include/plat_macros.S b/plat/arm/board/juno/include/plat_macros.S
new file mode 100644
index 0000000..ec94a4f
--- /dev/null
+++ b/plat/arm/board/juno/include/plat_macros.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <cci_macros.S>
+#include <css_macros.S>
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ css_print_gic_regs
+ print_cci_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
new file mode 100644
index 0000000..409d7a6
--- /dev/null
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <drivers/arm/tzc400.h>
+#if TRUSTED_BOARD_BOOT
+#include MBEDTLS_CONFIG_FILE
+#endif
+#include <plat/arm/board/common/board_css_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/css/common/css_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+#include <plat/common/common_def.h>
+
+#include "../juno_def.h"
+
+/* Required platform porting definitions */
+/* Juno supports system power domain */
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2
+#define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \
+ JUNO_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLATFORM_CORE_COUNT (JUNO_CLUSTER0_CORE_COUNT + \
+ JUNO_CLUSTER1_CORE_COUNT)
+
+/* Cryptocell HW Base address */
+#define PLAT_CRYPTOCELL_BASE UL(0x60050000)
+
+/*
+ * Other platform porting definitions are provided by included headers
+ */
+
+/*
+ * Required ARM standard platform porting definitions
+ */
+#define PLAT_ARM_CLUSTER_COUNT JUNO_CLUSTER_COUNT
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */
+
+/* Use the bypass address */
+#define PLAT_ARM_TRUSTED_ROM_BASE (V2M_FLASH0_BASE + \
+ BL1_ROM_BYPASS_OFFSET)
+
+#define NSRAM_BASE UL(0x2e000000)
+#define NSRAM_SIZE UL(0x00008000) /* 32KB */
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x880000000)
+#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
+
+/* Range of kernel DTB load address */
+#define JUNO_DTB_DRAM_MAP_START ULL(0x82000000)
+#define JUNO_DTB_DRAM_MAP_SIZE ULL(0x00008000) /* 32KB */
+
+#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \
+ JUNO_DTB_DRAM_MAP_START, \
+ JUNO_DTB_DRAM_MAP_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
+
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xe000)
+#define JUNO_BL2_ROMLIB_OPTIMIZATION UL(0x8000)
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0)
+#define JUNO_BL2_ROMLIB_OPTIMIZATION UL(0)
+#endif
+
+/*
+ * Actual ROM size on Juno is 64 KB, but TBB currently requires at least 80 KB
+ * in debug mode. We can test TBB on Juno bypassing the ROM and using 128 KB of
+ * flash
+ */
+
+#if TRUSTED_BOARD_BOOT
+#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00020000)
+#else
+#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00010000)
+#endif /* TRUSTED_BOARD_BOOT */
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#ifdef IMAGE_BL1
+# define PLAT_ARM_MMAP_ENTRIES 7
+# define MAX_XLAT_TABLES 4
+#endif
+
+#ifdef IMAGE_BL2
+#ifdef SPD_opteed
+# define PLAT_ARM_MMAP_ENTRIES 11
+# define MAX_XLAT_TABLES 5
+#else
+# define PLAT_ARM_MMAP_ENTRIES 10
+# define MAX_XLAT_TABLES 4
+#endif
+#endif
+
+#ifdef IMAGE_BL2U
+# define PLAT_ARM_MMAP_ENTRIES 5
+# define MAX_XLAT_TABLES 3
+#endif
+
+#ifdef IMAGE_BL31
+# define PLAT_ARM_MMAP_ENTRIES 7
+# define MAX_XLAT_TABLES 5
+#endif
+
+#ifdef IMAGE_BL32
+# define PLAT_ARM_MMAP_ENTRIES 6
+# define MAX_XLAT_TABLES 4
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xB000)
+#else
+# define PLAT_ARM_MAX_BL1_RW_SIZE UL(0x6000)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1F000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
+#elif TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
+#endif
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (UL(0x13000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
+#endif
+
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL31 -> BL2_BASE.
+ * Hence the BL31 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
+ */
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x3D000)
+
+#if JUNO_AARCH32_EL3_RUNTIME
+/*
+ * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
+ * calculated using the current BL32 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW. SCP_BL2 image is loaded into the space BL32 -> BL2_BASE.
+ * Hence the BL32 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
+ */
+#define PLAT_ARM_MAX_BL32_SIZE UL(0x3D000)
+#endif
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x440)
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x400)
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE UL(0x400)
+#elif defined(IMAGE_BL31)
+# if PLAT_XLAT_TABLES_DYNAMIC
+# define PLATFORM_STACK_SIZE UL(0x800)
+# else
+# define PLATFORM_STACK_SIZE UL(0x400)
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE UL(0x440)
+#endif
+
+/* CCI related constants */
+#define PLAT_ARM_CCI_BASE UL(0x2c090000)
+#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4
+#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 3
+
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
+
+/* TZC related constants */
+#define PLAT_ARM_TZC_BASE UL(0x2a4a0000)
+#define PLAT_ARM_TZC_NS_DEV_ACCESS ( \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD0) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD1) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_USB) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_DMA330) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_THINLINKS) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_AP) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU) | \
+ TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT))
+
+/* TZC related constants */
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL
+
+/*
+ * Required ARM CSS based platform porting definitions
+ */
+
+/* GIC related constants (no GICR in GIC-400) */
+#define PLAT_ARM_GICD_BASE UL(0x2c010000)
+#define PLAT_ARM_GICC_BASE UL(0x2c02f000)
+#define PLAT_ARM_GICH_BASE UL(0x2c04f000)
+#define PLAT_ARM_GICV_BASE UL(0x2c06f000)
+
+/* MHU related constants */
+#define PLAT_CSS_MHU_BASE UL(0x2b1f0000)
+
+/*
+ * Base address of the first memory region used for communication between AP
+ * and SCP. Used by the BOM and SCPI protocols.
+ */
+#if !CSS_USE_SCMI_SDS_DRIVER
+/*
+ * Note that this is located at the same address as SCP_BOOT_CFG_ADDR, which
+ * means the SCP/AP configuration data gets overwritten when the AP initiates
+ * communication with the SCP. The configuration data is expected to be a
+ * 32-bit word on all CSS platforms. On Juno, part of this configuration is
+ * which CPU is the primary, according to the shift and mask definitions below.
+ */
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE (ARM_TRUSTED_SRAM_BASE + UL(0x80))
+#define PLAT_CSS_PRIMARY_CPU_SHIFT 8
+#define PLAT_CSS_PRIMARY_CPU_BIT_WIDTH 4
+#endif
+
+/*
+ * SCP_BL2 uses up whatever remaining space is available as it is loaded before
+ * anything else in this memory region and is handed over to the SCP before
+ * BL31 is loaded over the top.
+ */
+#define PLAT_CSS_MAX_SCP_BL2_SIZE \
+ ((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
+
+#define PLAT_CSS_MAX_SCP_BL2U_SIZE PLAT_CSS_MAX_SCP_BL2_SIZE
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ CSS_G1S_IRQ_PROPS(grp), \
+ ARM_G1S_IRQ_PROPS(grp), \
+ INTR_PROP_DESC(JUNO_IRQ_DMA_SMMU, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(JUNO_IRQ_HDLCD0_SMMU, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(JUNO_IRQ_HDLCD1_SMMU, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(JUNO_IRQ_USB_SMMU, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(JUNO_IRQ_THIN_LINKS_SMMU, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(JUNO_IRQ_SEC_I2C, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(JUNO_IRQ_GPU_SMMU_1, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(JUNO_IRQ_ETR_SMMU, GIC_HIGHEST_SEC_PRIORITY, \
+ (grp), GIC_INTR_CFG_LEVEL)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+/*
+ * Required ARM CSS SoC based platform porting definitions
+ */
+
+/* CSS SoC NIC-400 Global Programmers View (GPV) */
+#define PLAT_SOC_CSS_NIC400_BASE UL(0x2a000000)
+
+#define PLAT_ARM_PRIVATE_SDEI_EVENTS ARM_SDEI_PRIVATE_EVENTS
+#define PLAT_ARM_SHARED_SDEI_EVENTS ARM_SDEI_SHARED_EVENTS
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
new file mode 100644
index 0000000..8932aa0
--- /dev/null
+++ b/plat/arm/board/juno/jmptbl.i
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform specific romlib functions can be added or included here.
+# The index in the output file will be generated cumulatively in the same
+# order as it is given in this file.
+# Output file can be found at: $BUILD_DIR/jmptbl.i
+#
+# Format:
+# lib function [patch]
+# Example:
+# rom rom_lib_init
+# fdt fdt_getprop_namelen patch
+
+rom rom_lib_init
+fdt fdt_getprop
+fdt fdt_get_property
+fdt fdt_getprop_namelen
+fdt fdt_setprop_inplace
+fdt fdt_check_header
+fdt fdt_node_offset_by_compatible
+fdt fdt_setprop_inplace_namelen_partial
+fdt fdt_first_subnode
+fdt fdt_next_subnode
+fdt fdt_parent_offset
+fdt fdt_stringlist_search
+fdt fdt_get_alias_namelen
+fdt fdt_path_offset
+fdt fdt_path_offset_namelen
+fdt fdt_address_cells
+fdt fdt_size_cells
+fdt fdt_get_name
+fdt fdt_get_alias
+fdt fdt_node_offset_by_phandle
+fdt fdt_subnode_offset
+fdt fdt_add_subnode
+mbedtls mbedtls_asn1_get_alg
+mbedtls mbedtls_asn1_get_alg_null
+mbedtls mbedtls_asn1_get_bitstring_null
+mbedtls mbedtls_asn1_get_bool
+mbedtls mbedtls_asn1_get_int
+mbedtls mbedtls_asn1_get_tag
+mbedtls mbedtls_free
+mbedtls mbedtls_md
+mbedtls mbedtls_md_get_size
+mbedtls mbedtls_memory_buffer_alloc_init
+mbedtls mbedtls_oid_get_md_alg
+mbedtls mbedtls_oid_get_numeric_string
+mbedtls mbedtls_oid_get_pk_alg
+mbedtls mbedtls_oid_get_sig_alg
+mbedtls mbedtls_pk_free
+mbedtls mbedtls_pk_init
+mbedtls mbedtls_pk_parse_subpubkey
+mbedtls mbedtls_pk_verify_ext
+mbedtls mbedtls_platform_set_snprintf
+mbedtls mbedtls_x509_get_rsassa_pss_params
+mbedtls mbedtls_x509_get_sig_alg
+mbedtls mbedtls_md_info_from_type
+c exit
+c atexit
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
new file mode 100644
index 0000000..a9d5cc3
--- /dev/null
+++ b/plat/arm/board/juno/juno_bl1_setup.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/css/sds.h>
+#include <drivers/arm/sp805.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+void juno_reset_to_aarch32_state(void);
+
+static int is_watchdog_reset(void)
+{
+#if !CSS_USE_SCMI_SDS_DRIVER
+ #define RESET_REASON_WDOG_RESET (0x2)
+ const uint32_t *reset_flags_ptr = (const uint32_t *)SSC_GPRETN;
+
+ if ((*reset_flags_ptr & RESET_REASON_WDOG_RESET) != 0)
+ return 1;
+
+ return 0;
+#else
+ int ret;
+ uint32_t scp_reset_synd_flags;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SCP SDS initialization failed\n");
+ panic();
+ }
+
+ ret = sds_struct_read(SDS_RESET_SYNDROME_STRUCT_ID,
+ SDS_RESET_SYNDROME_OFFSET,
+ &scp_reset_synd_flags,
+ SDS_RESET_SYNDROME_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Getting reset reason from SDS failed\n");
+ panic();
+ }
+
+ /* Check if the WATCHDOG_RESET_BIT is set in the reset syndrome */
+ if (scp_reset_synd_flags & SDS_RESET_SYNDROME_AP_WD_RESET_BIT)
+ return 1;
+
+ return 0;
+#endif
+}
+
+/*******************************************************************************
+ * The following function checks if Firmware update is needed,
+ * by checking if TOC in FIP image is valid or watchdog reset happened.
+ ******************************************************************************/
+bool plat_arm_bl1_fwu_needed(void)
+{
+ int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
+
+ /* Check if TOC is invalid or watchdog reset happened. */
+ return (!arm_io_is_toc_valid() || (((nv_flags == -EAUTH) ||
+ (nv_flags == -ENOENT)) && is_watchdog_reset()));
+}
+
+/*******************************************************************************
+ * On JUNO update the arg2 with address of SCP_BL2U image info.
+ ******************************************************************************/
+void bl1_plat_set_ep_info(unsigned int image_id,
+ entry_point_info_t *ep_info)
+{
+ if (image_id == BL2U_IMAGE_ID) {
+ image_desc_t *image_desc = bl1_plat_get_image_desc(SCP_BL2U_IMAGE_ID);
+ ep_info->args.arg2 = (unsigned long)&image_desc->image_info;
+ }
+}
+
+/*******************************************************************************
+ * On Juno clear SYS_NVFLAGS and wait for watchdog reset.
+ ******************************************************************************/
+__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
+{
+ uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
+
+ /* Clear the NV flags register. */
+ mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR),
+ nv_flags);
+
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ while (true)
+ wfi();
+}
+
+#if JUNO_AARCH32_EL3_RUNTIME
+void bl1_plat_prepare_exit(entry_point_info_t *ep_info)
+{
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Disable watchdog before leaving BL1 */
+ sp805_stop(ARM_SP805_TWDG_BASE);
+#endif
+
+ juno_reset_to_aarch32_state();
+}
+#endif /* JUNO_AARCH32_EL3_RUNTIME */
+
+void plat_arm_secure_wdt_start(void)
+{
+ sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sp805_stop(ARM_SP805_TWDG_BASE);
+}
diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c
new file mode 100644
index 0000000..849acd6
--- /dev/null
+++ b/plat/arm/board/juno/juno_bl2_setup.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016-2017,2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+#if JUNO_AARCH32_EL3_RUNTIME
+/*******************************************************************************
+ * This function changes the spsr for BL32 image to bypass
+ * the check in BL1 AArch64 exception handler. This is needed in the aarch32
+ * boot flow as the core comes up in aarch64 and to enter the BL32 image a warm
+ * reset in aarch32 state is required.
+ ******************************************************************************/
+int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = arm_bl2_handle_post_image_load(image_id);
+
+ if (!err && (image_id == BL32_IMAGE_ID)) {
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ assert(bl_mem_params);
+ bl_mem_params->ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ }
+
+ return err;
+}
+
+#else
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ struct bl_params *arm_bl_params = arm_get_next_bl_params();
+
+#if __aarch64__
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ bl_mem_params_node_t *param_node;
+ uintptr_t fw_config_base = 0U;
+ entry_point_info_t *ep_info;
+
+ /* Get BL31 image node */
+ param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+ assert(param_node != NULL);
+
+ /* Get fw_config load address */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ assert(fw_config_info != NULL);
+
+ fw_config_base = fw_config_info->config_addr;
+ assert(fw_config_base != 0U);
+
+ /*
+ * Get the entry point info of BL31 image and override
+ * arg1 of entry point info with fw_config base address
+ */
+ ep_info = &param_node->ep_info;
+ ep_info->args.arg1 = (uint32_t)fw_config_base;
+#endif /* __aarch64__ */
+
+ return arm_bl_params;
+}
+#endif /* JUNO_AARCH32_EL3_RUNTIME */
diff --git a/plat/arm/board/juno/juno_bl31_setup.c b/plat/arm/board/juno/juno_bl31_setup.c
new file mode 100644
index 0000000..7a0a6d9
--- /dev/null
+++ b/plat/arm/board/juno/juno_bl31_setup.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+void __init bl31_early_platform_setup2(u_register_t arg0,
+ u_register_t arg1, u_register_t arg2, u_register_t arg3)
+{
+ const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
+
+ INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
+
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", arg1);
+
+ soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID);
+ if (soc_fw_config_info != NULL) {
+ arg1 = soc_fw_config_info->config_addr;
+ }
+
+ arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_arm_interconnect_init();
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this (e.g. Trusted
+ * Firmware's BL1 does it) but we can't assume so. There is no harm in
+ * executing this code twice anyway.
+ * Platform specific PSCI code will enable coherency for other
+ * clusters.
+ */
+ plat_arm_interconnect_enter_coherency();
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+ arm_bl31_plat_arch_setup();
+
+ /* HW_CONFIG was also loaded by BL2 */
+ const struct dyn_cfg_dtb_info_t *hw_config_info;
+
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+
+ fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+}
diff --git a/plat/arm/board/juno/juno_common.c b/plat/arm/board/juno/juno_common.c
new file mode 100644
index 0000000..038f604
--- /dev/null
+++ b/plat/arm/board/juno/juno_common.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/smccc.h>
+#include <platform_def.h>
+#include <services/arm_arch_svc.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Table of memory regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted SRAM as setup_page_tables() already takes care
+ * of mapping it.
+ */
+#ifdef IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH0_RW,
+ V2M_MAP_IOFPGA,
+ CSS_MAP_DEVICE,
+ SOC_CSS_MAP_DEVICE,
+#if TRUSTED_BOARD_BOOT
+ /* Map DRAM to authenticate NS_BL2U image. */
+ ARM_MAP_NS_DRAM1,
+#endif
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_FLASH0_RW,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+ V2M_MAP_IOFPGA,
+ CSS_MAP_DEVICE,
+ SOC_CSS_MAP_DEVICE,
+ ARM_MAP_NS_DRAM1,
+#ifdef __aarch64__
+ ARM_MAP_DRAM2,
+#endif
+#ifdef SPD_tspd
+ ARM_MAP_TSP_SEC_MEM,
+#endif
+#ifdef SPD_opteed
+ ARM_MAP_OPTEE_CORE_MEM,
+ ARM_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2U
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ CSS_MAP_DEVICE,
+ CSS_MAP_SCP_BL2U,
+ V2M_MAP_IOFPGA,
+ SOC_CSS_MAP_DEVICE,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_IOFPGA,
+ CSS_MAP_DEVICE,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+ SOC_CSS_MAP_DEVICE,
+ ARM_DTB_DRAM_NS,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL32
+const mmap_region_t plat_arm_mmap[] = {
+#ifndef __aarch64__
+ ARM_MAP_SHARED_RAM,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+#endif
+ V2M_MAP_IOFPGA,
+ CSS_MAP_DEVICE,
+ SOC_CSS_MAP_DEVICE,
+ {0}
+};
+#endif
+
+ARM_CASSERT_MMAP
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ * feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+ return (int32_t)
+ (SOC_ID_SET_JEP_106(ARM_SOC_CONTINUATION_CODE,
+ ARM_SOC_IDENTIFICATION_CODE) |
+ (JUNO_SOC_ID & SOC_ID_IMPL_DEF_MASK));
+}
+
+/* Get SOC revision */
+int32_t plat_get_soc_revision(void)
+{
+ unsigned int sys_id;
+
+ sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
+ return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) &
+ V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK);
+}
diff --git a/plat/arm/board/juno/juno_def.h b/plat/arm/board/juno/juno_def.h
new file mode 100644
index 0000000..ddf99dc
--- /dev/null
+++ b/plat/arm/board/juno/juno_def.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef JUNO_DEF_H
+#define JUNO_DEF_H
+
+#include <lib/utils_def.h>
+
+/******************************************************************************
+ * Definition of platform soc id
+ *****************************************************************************/
+#define JUNO_SOC_ID 1
+
+/*******************************************************************************
+ * Juno memory map related constants
+ ******************************************************************************/
+
+/* Board revisions */
+#define REV_JUNO_R0 U(0x1) /* Rev B */
+#define REV_JUNO_R1 U(0x2) /* Rev C */
+#define REV_JUNO_R2 U(0x3) /* Rev D */
+
+/* Bypass offset from start of NOR flash */
+#define BL1_ROM_BYPASS_OFFSET UL(0x03EC0000)
+
+#define EMMC_BASE UL(0x0c000000)
+#define EMMC_SIZE UL(0x04000000)
+
+#define PSRAM_BASE UL(0x14000000)
+#define PSRAM_SIZE UL(0x02000000)
+
+#define JUNO_SSC_VER_PART_NUM U(0x030)
+
+/*******************************************************************************
+ * Juno topology related constants
+ ******************************************************************************/
+#define JUNO_CLUSTER_COUNT U(2)
+#define JUNO_CLUSTER0_CORE_COUNT U(2)
+#define JUNO_CLUSTER1_CORE_COUNT U(4)
+
+/*******************************************************************************
+ * TZC-400 related constants
+ ******************************************************************************/
+#define TZC400_NSAID_CCI400 0 /* Note: Same as default NSAID!! */
+#define TZC400_NSAID_PCIE 1
+#define TZC400_NSAID_HDLCD0 2
+#define TZC400_NSAID_HDLCD1 3
+#define TZC400_NSAID_USB 4
+#define TZC400_NSAID_DMA330 5
+#define TZC400_NSAID_THINLINKS 6
+#define TZC400_NSAID_AP 9
+#define TZC400_NSAID_GPU 10
+#define TZC400_NSAID_SCP 11
+#define TZC400_NSAID_CORESIGHT 12
+
+/*******************************************************************************
+ * TRNG related constants
+ ******************************************************************************/
+#define TRNG_BASE UL(0x7FE60000)
+#define TRNG_NOUTPUTS 4
+#define TRNG_STATUS UL(0x10)
+#define TRNG_INTMASK UL(0x14)
+#define TRNG_CONFIG UL(0x18)
+#define TRNG_CONTROL UL(0x1C)
+#define TRNG_NBYTES 16 /* Number of bytes generated per round. */
+
+/*******************************************************************************
+ * MMU-401 related constants
+ ******************************************************************************/
+#define MMU401_SSD_OFFSET UL(0x4000)
+#define MMU401_DMA330_BASE UL(0x7fb00000)
+
+/*******************************************************************************
+ * Interrupt handling constants
+ ******************************************************************************/
+#define JUNO_IRQ_DMA_SMMU 126
+#define JUNO_IRQ_HDLCD0_SMMU 128
+#define JUNO_IRQ_HDLCD1_SMMU 130
+#define JUNO_IRQ_USB_SMMU 132
+#define JUNO_IRQ_THIN_LINKS_SMMU 134
+#define JUNO_IRQ_SEC_I2C 137
+#define JUNO_IRQ_GPU_SMMU_1 73
+#define JUNO_IRQ_ETR_SMMU 75
+
+/*******************************************************************************
+ * Memprotect definitions
+ ******************************************************************************/
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \
+ V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#endif /* JUNO_DEF_H */
diff --git a/plat/arm/board/juno/juno_err.c b/plat/arm/board/juno/juno_err.c
new file mode 100644
index 0000000..02d751e
--- /dev/null
+++ b/plat/arm/board/juno/juno_err.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <drivers/arm/sp805.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*
+ * Juno error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ /* Propagate the err code in the NV-flags register */
+ mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err);
+
+ /* Setup the watchdog to reset the system as soon as possible */
+ sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+ for (;;)
+ wfi();
+}
diff --git a/plat/arm/board/juno/juno_pm.c b/plat/arm/board/juno/juno_pm.c
new file mode 100644
index 0000000..cc80651
--- /dev/null
+++ b/plat/arm/board/juno/juno_pm.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/css/scmi.h>
+#include <plat/arm/common/plat_arm.h>
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+#if CSS_USE_SCMI_SDS_DRIVER
+ return css_scmi_override_pm_ops(ops);
+#else
+ return ops;
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
+}
diff --git a/plat/arm/board/juno/juno_security.c b/plat/arm/board/juno/juno_security.c
new file mode 100644
index 0000000..654a7f1
--- /dev/null
+++ b/plat/arm/board/juno/juno_security.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/arm/nic_400.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/soc/common/soc_css.h>
+#include <plat/common/platform.h>
+
+#include "juno_tzmp1_def.h"
+
+#ifdef JUNO_TZMP1
+/*
+ * Protect buffer for VPU/GPU/DPU memory usage with hardware protection
+ * enabled. Propose 224MB video output, 96 MB video input and 32MB video
+ * private.
+ *
+ * Ind Memory Range Caption S_ATTR NS_ATTR
+ * 1 0x080000000 - 0x0E7FFFFFF ARM_NS_DRAM1 NONE RDWR | MEDIA_RW
+ * 2 0x0E8000000 - 0x0F5FFFFFF JUNO_MEDIA_TZC_PROT_DRAM1 NONE MEDIA_RW | AP_WR
+ * 3 0x0F6000000 - 0x0FBFFFFFF JUNO_VPU_TZC_PROT_DRAM1 RDWR VPU_PROT_RW
+ * 4 0x0FC000000 - 0x0FDFFFFFF JUNO_VPU_TZC_PRIV_DRAM1 RDWR VPU_PRIV_RW
+ * 5 0x0FE000000 - 0x0FEFFFFFF JUNO_AP_TZC_SHARE_DRAM1 NONE RDWR | MEDIA_RW
+ * 6 0x0FF000000 - 0x0FFFFFFFF ARM_AP_TZC_DRAM1 RDWR NONE
+ * 7 0x880000000 - 0x9FFFFFFFF ARM_DRAM2 NONE RDWR | MEDIA_RW
+ *
+ * Memory regions are neighbored to save limited TZC regions. Calculation
+ * started from ARM_TZC_SHARE_DRAM1 since it is known and fixed for both
+ * protected-enabled and protected-disabled settings.
+ *
+ * Video private buffer aheads of ARM_TZC_SHARE_DRAM1
+ */
+
+static const arm_tzc_regions_info_t juno_tzmp1_tzc_regions[] = {
+ {ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0},
+ {JUNO_NS_DRAM1_PT1_BASE, JUNO_NS_DRAM1_PT1_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS},
+ {JUNO_MEDIA_TZC_PROT_DRAM1_BASE, JUNO_MEDIA_TZC_PROT_DRAM1_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_PROT_ACCESS},
+ {JUNO_VPU_TZC_PROT_DRAM1_BASE, JUNO_VPU_TZC_PROT_DRAM1_END,
+ TZC_REGION_S_RDWR, JUNO_VPU_TZC_PROT_ACCESS},
+ {JUNO_VPU_TZC_PRIV_DRAM1_BASE, JUNO_VPU_TZC_PRIV_DRAM1_END,
+ TZC_REGION_S_RDWR, JUNO_VPU_TZC_PRIV_ACCESS},
+ {JUNO_AP_TZC_SHARE_DRAM1_BASE, JUNO_AP_TZC_SHARE_DRAM1_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS},
+ {ARM_DRAM2_BASE, ARM_DRAM2_END,
+ TZC_REGION_S_NONE, JUNO_MEDIA_TZC_NS_DEV_ACCESS},
+ {},
+};
+
+/*******************************************************************************
+ * Program dp650 to configure NSAID value for protected mode.
+ ******************************************************************************/
+static void init_dp650(void)
+{
+ mmio_write_32(DP650_BASE + DP650_PROT_NSAID_OFFSET,
+ DP650_PROT_NSAID_CONFIG);
+}
+
+/*******************************************************************************
+ * Program v550 to configure NSAID value for protected mode.
+ ******************************************************************************/
+static void init_v550(void)
+{
+ /*
+ * bits[31:28] is for PRIVATE,
+ * bits[27:24] is for OUTBUF,
+ * bits[23:20] is for PROTECTED.
+ */
+ mmio_write_32(V550_BASE + V550_PROTCTRL_OFFSET, V550_PROTCTRL_CONFIG);
+}
+
+#endif /* JUNO_TZMP1 */
+
+/*******************************************************************************
+ * Set up the MMU-401 SSD tables. The power-on configuration has all stream IDs
+ * assigned to Non-Secure except some for the DMA-330. Assign those back to the
+ * Non-Secure world as well, otherwise EL1 may end up erroneously generating
+ * (untranslated) Secure transactions if it turns the SMMU on.
+ ******************************************************************************/
+static void init_mmu401(void)
+{
+ uint32_t reg = mmio_read_32(MMU401_DMA330_BASE + MMU401_SSD_OFFSET);
+ reg |= 0x1FF;
+ mmio_write_32(MMU401_DMA330_BASE + MMU401_SSD_OFFSET, reg);
+}
+
+/*******************************************************************************
+ * Program CSS-NIC400 to allow non-secure access to some CSS regions.
+ ******************************************************************************/
+static void css_init_nic400(void)
+{
+ /* Note: This is the NIC-400 device on the CSS */
+ mmio_write_32(PLAT_SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(CSS_NIC400_SLAVE_BOOTSECURE),
+ ~0);
+}
+
+/*******************************************************************************
+ * Initialize debug configuration.
+ ******************************************************************************/
+static void init_debug_cfg(void)
+{
+#if !DEBUG
+ /* Set internal drive selection for SPIDEN. */
+ mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_SET,
+ 1U << SPIDEN_SEL_SET_SHIFT);
+
+ /* Drive SPIDEN LOW to disable invasive debug of secure state. */
+ mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_CLR,
+ 1U << SPIDEN_INT_CLR_SHIFT);
+
+ /* Set internal drive selection for SPNIDEN. */
+ mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_SET,
+ 1U << SPNIDEN_SEL_SET_SHIFT);
+
+ /* Drive SPNIDEN LOW to disable non-invasive debug of secure state. */
+ mmio_write_32(SSC_REG_BASE + SSC_DBGCFG_CLR,
+ 1U << SPNIDEN_INT_CLR_SHIFT);
+#endif
+}
+
+/*******************************************************************************
+ * Initialize the secure environment.
+ ******************************************************************************/
+void plat_arm_security_setup(void)
+{
+ /* Initialize debug configuration */
+ init_debug_cfg();
+ /* Initialize the TrustZone Controller */
+#ifdef JUNO_TZMP1
+ arm_tzc400_setup(PLAT_ARM_TZC_BASE, juno_tzmp1_tzc_regions);
+ INFO("TZC protected shared memory base address for TZMP usecase: %p\n",
+ (void *)JUNO_AP_TZC_SHARE_DRAM1_BASE);
+ INFO("TZC protected shared memory end address for TZMP usecase: %p\n",
+ (void *)JUNO_AP_TZC_SHARE_DRAM1_END);
+#else
+ arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL);
+#endif
+ /* Do ARM CSS internal NIC setup */
+ css_init_nic400();
+ /* Do ARM CSS SoC security setup */
+ soc_css_security_setup();
+ /* Initialize the SMMU SSD tables */
+ init_mmu401();
+#ifdef JUNO_TZMP1
+ init_dp650();
+ init_v550();
+#endif
+}
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
diff --git a/plat/arm/board/juno/juno_stack_protector.c b/plat/arm/board/juno/juno_stack_protector.c
new file mode 100644
index 0000000..3924af8
--- /dev/null
+++ b/plat/arm/board/juno/juno_stack_protector.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/utils.h>
+#include <plat/common/plat_trng.h>
+#include <platform_def.h>
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ uint64_t entropy;
+
+ if (!plat_get_entropy(&entropy)) {
+ ERROR("Not enough entropy to initialize canary value\n");
+ panic();
+ }
+
+ if (sizeof(entropy) == sizeof(u_register_t)) {
+ return entropy;
+ }
+
+ return (entropy & 0xffffffffULL) ^ (entropy >> 32);
+}
diff --git a/plat/arm/board/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c
new file mode 100644
index 0000000..075f512
--- /dev/null
+++ b/plat/arm/board/juno/juno_topology.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#if CSS_USE_SCMI_SDS_DRIVER
+static scmi_channel_plat_info_t juno_scmi_plat_info = {
+ .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhu_ring_doorbell,
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+ return &juno_scmi_plat_info;
+}
+
+#endif
+/*
+ * On Juno, the system power level is the highest power level.
+ * The first entry in the power domain descriptor specifies the
+ * number of system power domains i.e. 1.
+ */
+#define JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL ARM_SYSTEM_COUNT
+
+/*
+ * The Juno power domain tree descriptor. The cluster power domains
+ * are arranged so that when the PSCI generic code creates the power
+ * domain tree, the indices of the CPU power domain nodes it allocates
+ * match the linear indices returned by plat_core_pos_by_mpidr()
+ * i.e. CLUSTER1 CPUs are allocated indices from 0 to 3 and the higher
+ * indices for CLUSTER0 CPUs.
+ */
+static const unsigned char juno_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ JUNO_PWR_DOMAINS_AT_MAX_PWR_LVL,
+ /* No of children for the root node */
+ JUNO_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ JUNO_CLUSTER1_CORE_COUNT,
+ /* No of children for the second cluster node */
+ JUNO_CLUSTER0_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the Juno topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return juno_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+ return (((mpidr & (u_register_t) 0x100) != 0U) ?
+ JUNO_CLUSTER1_CORE_COUNT : JUNO_CLUSTER0_CORE_COUNT);
+}
+
+/*
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ */
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+ 2, 3, 4, 5, 0, 1 };
diff --git a/plat/arm/board/juno/juno_trng.c b/plat/arm/board/juno/juno_trng.c
new file mode 100644
index 0000000..09552a6
--- /dev/null
+++ b/plat/arm/board/juno/juno_trng.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arm_acle.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+#include <lib/smccc.h>
+#include <services/trng_svc.h>
+#include <smccc_helpers.h>
+
+#include <plat/common/platform.h>
+
+#define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */
+#define NRETRIES 5
+
+/* initialised to false */
+static bool juno_trng_initialized;
+
+static bool output_valid(void)
+{
+ int i;
+
+ for (i = 0; i < NRETRIES; i++) {
+ uint32_t val;
+
+ val = mmio_read_32(TRNG_BASE + TRNG_STATUS);
+ if (val & 1U)
+ return true;
+ }
+ return false; /* No output data available. */
+}
+
+DEFINE_SVC_UUID2(_plat_trng_uuid,
+ 0x23523c58, 0x7448, 0x4083, 0x9d, 0x16,
+ 0xe3, 0xfa, 0xb9, 0xf1, 0x73, 0xbc
+);
+uuid_t plat_trng_uuid;
+
+static uint32_t crc_value = ~0U;
+
+/*
+ * Uses the Trusted Entropy Source peripheral on Juno to return 8 bytes of
+ * entropy. Returns 'true' when done successfully, 'false' otherwise.
+ */
+bool plat_get_entropy(uint64_t *out)
+{
+ uint64_t ret;
+
+ assert(out);
+ assert(!check_uptr_overflow((uintptr_t)out, sizeof(*out)));
+
+ if (!juno_trng_initialized) {
+ /* Disable interrupt mode. */
+ mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0);
+ /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */
+ mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS);
+ /* Abort any potentially pending sampling. */
+ mmio_write_32(TRNG_BASE + TRNG_CONTROL, 2);
+ /* Reset TRNG outputs. */
+ mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
+
+ juno_trng_initialized = true;
+ }
+
+ if (!output_valid()) {
+ /* Start TRNG. */
+ mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1);
+
+ if (!output_valid())
+ return false;
+ }
+
+ /* CRC each two 32-bit registers together, combine the pairs */
+ crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 0));
+ crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 4));
+ ret = (uint64_t)crc_value << 32;
+
+ crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 8));
+ crc_value = __crc32w(crc_value, mmio_read_32(TRNG_BASE + 12));
+ *out = ret | crc_value;
+
+ /* Acknowledge current cycle, clear output registers. */
+ mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
+ /* Trigger next TRNG cycle. */
+ mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1);
+
+ return true;
+}
+
+void plat_entropy_setup(void)
+{
+ uint64_t dummy;
+
+ plat_trng_uuid = _plat_trng_uuid;
+
+ /* Initialise the entropy source and trigger RNG generation */
+ plat_get_entropy(&dummy);
+}
diff --git a/plat/arm/board/juno/juno_trusted_boot.c b/plat/arm/board/juno/juno_trusted_boot.c
new file mode 100644
index 0000000..25a7470
--- /dev/null
+++ b/plat/arm/board/juno/juno_trusted_boot.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/arm/cryptocell/cc_rotpk.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+
+static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
+
+extern unsigned char arm_rotpk_header[];
+
+/*
+ * Return the ROTPK hash stored in the registers of Juno board.
+ */
+static int juno_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ uint8_t *dst;
+ uint32_t *src, tmp;
+ unsigned int words, i;
+
+ assert(key_ptr != NULL);
+ assert(key_len != NULL);
+ assert(flags != NULL);
+
+ /* Copy the DER header */
+ memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+ dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
+
+
+ /*
+ * Append the hash from Trusted Root-Key Storage registers. The hash has
+ * not been written linearly into the registers, so we have to do a bit
+ * of byte swapping:
+ *
+ * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C
+ * +---------------------------------------------------------------+
+ * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 |
+ * +---------------------------------------------------------------+
+ * | ... ... | | ... ... |
+ * | +--------------------+ | +-------+
+ * | | | |
+ * +----------------------------+ +----------------------------+
+ * | | | |
+ * +-------+ | +--------------------+ |
+ * | | | |
+ * v v v v
+ * +---------------------------------------------------------------+
+ * | | |
+ * +---------------------------------------------------------------+
+ * 0 15 16 31
+ *
+ * Additionally, we have to access the registers in 32-bit words
+ */
+ words = ARM_ROTPK_HASH_LEN >> 3;
+
+ /* Swap bytes 0-15 (first four registers) */
+ src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
+ for (i = 0 ; i < words ; i++) {
+ tmp = src[words - 1 - i];
+ /* Words are read in little endian */
+ *dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+ *dst++ = (uint8_t)(tmp & 0xFF);
+ }
+
+ /* Swap bytes 16-31 (last four registers) */
+ src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + ARM_ROTPK_HASH_LEN / 2);
+ for (i = 0 ; i < words ; i++) {
+ tmp = src[words - 1 - i];
+ *dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+ *dst++ = (uint8_t)(tmp & 0xFF);
+ }
+
+ *key_ptr = (void *)rotpk_hash_der;
+ *key_len = (unsigned int)sizeof(rotpk_hash_der);
+ *flags = ROTPK_IS_HASH;
+ return 0;
+}
+
+#endif
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+#if ARM_CRYPTOCELL_INTEG
+ return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
+#else
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+ (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+ return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+ return juno_get_rotpk_info_regs(key_ptr, key_len, flags);
+#else
+ return 1;
+#endif
+
+#endif /* ARM_CRYPTOCELL_INTEG */
+}
diff --git a/plat/arm/board/juno/juno_tzmp1_def.h b/plat/arm/board/juno/juno_tzmp1_def.h
new file mode 100644
index 0000000..4186d02
--- /dev/null
+++ b/plat/arm/board/juno/juno_tzmp1_def.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef JUNO_TZMP1_DEF_H
+#define JUNO_TZMP1_DEF_H
+
+/*
+ * Public memory regions for both protected and non-protected mode
+ *
+ * OPTEE shared memory 0xFEE00000 - 0xFEFFFFFF
+ */
+#define JUNO_AP_TZC_SHARE_DRAM1_SIZE ULL(0x02000000)
+#define JUNO_AP_TZC_SHARE_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \
+ JUNO_AP_TZC_SHARE_DRAM1_SIZE)
+#define JUNO_AP_TZC_SHARE_DRAM1_END (ARM_AP_TZC_DRAM1_BASE - 1)
+
+/* ARM_MEDIA_FEATURES for MEDIA GPU Protect Mode Test */
+#define JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE 8 /* GPU/DPU protected, VPU outbuf */
+#define JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED 7 /* VPU protected */
+#define JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE 10 /* VPU private (firmware) */
+
+#define JUNO_VPU_TZC_PRIV_DRAM1_SIZE ULL(0x02000000)
+#define JUNO_VPU_TZC_PRIV_DRAM1_BASE (JUNO_AP_TZC_SHARE_DRAM1_BASE - \
+ JUNO_VPU_TZC_PRIV_DRAM1_SIZE)
+#define JUNO_VPU_TZC_PRIV_DRAM1_END (JUNO_AP_TZC_SHARE_DRAM1_BASE - 1)
+
+/* Video input protected buffer follows upper item */
+#define JUNO_VPU_TZC_PROT_DRAM1_SIZE ULL(0x06000000)
+#define JUNO_VPU_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PRIV_DRAM1_BASE - \
+ JUNO_VPU_TZC_PROT_DRAM1_SIZE)
+#define JUNO_VPU_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PRIV_DRAM1_BASE - 1)
+
+/* Video, graphics and display shares same NSAID and same protected buffer */
+#define JUNO_MEDIA_TZC_PROT_DRAM1_SIZE ULL(0x0e000000)
+#define JUNO_MEDIA_TZC_PROT_DRAM1_BASE (JUNO_VPU_TZC_PROT_DRAM1_BASE - \
+ JUNO_MEDIA_TZC_PROT_DRAM1_SIZE)
+#define JUNO_MEDIA_TZC_PROT_DRAM1_END (JUNO_VPU_TZC_PROT_DRAM1_BASE - 1)
+
+/* Rest of DRAM1 are Non-Secure public buffer */
+#define JUNO_NS_DRAM1_PT1_BASE ARM_DRAM1_BASE
+#define JUNO_NS_DRAM1_PT1_END (JUNO_MEDIA_TZC_PROT_DRAM1_BASE - 1)
+#define JUNO_NS_DRAM1_PT1_SIZE (JUNO_NS_DRAM1_PT1_END - \
+ JUNO_NS_DRAM1_PT1_BASE + 1)
+
+/* TZC filter flags */
+#define JUNO_MEDIA_TZC_NS_DEV_ACCESS (PLAT_ARM_TZC_NS_DEV_ACCESS | \
+ TZC_REGION_ACCESS_RD(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE))
+
+/* VPU / GPU /DPU protected access */
+#define JUNO_MEDIA_TZC_PROT_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_MEDIA_SECURE) | \
+ TZC_REGION_ACCESS_WR(TZC400_NSAID_AP))
+
+#define JUNO_VPU_TZC_PROT_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PROTECTED))
+
+#define JUNO_VPU_TZC_PRIV_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(JUNO_TZC400_NSAID_FPGA_VIDEO_PRIVATE))
+
+/*******************************************************************************
+ * Mali-DP650 related constants
+ ******************************************************************************/
+/* Base address of DP650 */
+#define DP650_BASE 0x6f200000
+/* offset to PROT_NSAID register */
+#define DP650_PROT_NSAID_OFFSET 0x10004
+/* config to PROT_NSAID register */
+#define DP650_PROT_NSAID_CONFIG 0x08008888
+
+/*******************************************************************************
+ * Mali-V550 related constants
+ ******************************************************************************/
+/* Base address of V550 */
+#define V550_BASE 0x6f030000
+/* offset to PROTCTRL register */
+#define V550_PROTCTRL_OFFSET 0x0040
+/* config to PROTCTRL register */
+#define V550_PROTCTRL_CONFIG 0xa8700000
+
+#endif /* JUNO_TZMP1_DEF_H */
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
new file mode 100644
index 0000000..2c84eb3
--- /dev/null
+++ b/plat/arm/board/juno/platform.mk
@@ -0,0 +1,201 @@
+#
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+JUNO_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/arm/common/arm_gicv2.c
+
+JUNO_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \
+ plat/arm/common/arm_cci.c
+
+JUNO_SECURITY_SOURCES := drivers/arm/tzc/tzc400.c \
+ plat/arm/board/juno/juno_security.c \
+ plat/arm/board/juno/juno_trng.c \
+ plat/arm/common/arm_tzc400.c
+
+ifneq (${ENABLE_STACK_PROTECTOR}, 0)
+JUNO_SECURITY_SOURCES += plat/arm/board/juno/juno_stack_protector.c
+endif
+
+# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the
+# SCP during power management operations and for SCP RAM Firmware transfer.
+CSS_USE_SCMI_SDS_DRIVER := 1
+
+PLAT_INCLUDES := -Iplat/arm/board/juno/include
+
+PLAT_BL_COMMON_SOURCES := plat/arm/board/juno/${ARCH}/juno_helpers.S \
+ plat/arm/board/juno/juno_common.c
+
+# Flag to enable support for AArch32 state on JUNO
+JUNO_AARCH32_EL3_RUNTIME := 0
+$(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME))
+$(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME))
+
+# Flag to enable support for TZMP1 on JUNO
+JUNO_TZMP1 := 0
+$(eval $(call assert_boolean,JUNO_TZMP1))
+ifeq (${JUNO_TZMP1}, 1)
+$(eval $(call add_define,JUNO_TZMP1))
+endif
+
+TRNG_SUPPORT := 1
+
+ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
+# Include BL32 in FIP
+NEED_BL32 := yes
+# BL31 is not required
+override BL31_SOURCES =
+
+# The BL32 needs to be built separately invoking the AARCH32 compiler and
+# be specifed via `BL32` build option.
+ ifneq (${ARCH}, aarch32)
+ override BL32_SOURCES =
+ endif
+endif
+
+ifeq (${ARCH},aarch64)
+BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ plat/arm/board/juno/juno_err.c \
+ plat/arm/board/juno/juno_bl1_setup.c \
+ drivers/arm/sp805/sp805.c \
+ ${JUNO_INTERCONNECT_SOURCES} \
+ ${JUNO_SECURITY_SOURCES}
+
+BL2_SOURCES += drivers/arm/sp805/sp805.c \
+ lib/utils/mem_region.c \
+ plat/arm/board/juno/juno_err.c \
+ plat/arm/board/juno/juno_bl2_setup.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
+ ${JUNO_SECURITY_SOURCES}
+
+BL2U_SOURCES += ${JUNO_SECURITY_SOURCES}
+
+BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/utils/mem_region.c \
+ lib/fconf/fconf.c \
+ lib/fconf/fconf_dyn_cfg_getter.c \
+ plat/arm/board/juno/juno_bl31_setup.c \
+ plat/arm/board/juno/juno_pm.c \
+ plat/arm/board/juno/juno_topology.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
+ ${JUNO_GIC_SOURCES} \
+ ${JUNO_INTERCONNECT_SOURCES} \
+ ${JUNO_SECURITY_SOURCES}
+
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
+BL1_SOURCES += drivers/arm/css/sds/sds.c
+endif
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += plat/arm/board/juno/juno_trusted_boot.c
+BL2_SOURCES += plat/arm/board/juno/juno_trusted_boot.c
+endif
+
+endif
+
+ifneq (${RESET_TO_BL31},0)
+ $(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \
+ Please set RESET_TO_BL31 to 0.")
+endif
+
+ifeq ($(USE_ROMLIB),1)
+all : bl1_romlib.bin
+endif
+
+bl1_romlib.bin : $(BUILD_PLAT)/bl1.bin romlib.bin
+ @echo "Building combined BL1 and ROMLIB binary for Juno $@"
+ ./lib/romlib/gen_combined_bl1_romlib.sh -o bl1_romlib.bin $(BUILD_PLAT)
+
+# Errata workarounds for Cortex-A53:
+ERRATA_A53_819472 := 1
+ERRATA_A53_824069 := 1
+ERRATA_A53_826319 := 1
+ERRATA_A53_827319 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+# Errata workarounds for Cortex-A57:
+ERRATA_A57_806969 := 0
+ERRATA_A57_813419 := 1
+ERRATA_A57_813420 := 1
+ERRATA_A57_814670 := 1
+ERRATA_A57_817169 := 1
+ERRATA_A57_826974 := 1
+ERRATA_A57_826977 := 1
+ERRATA_A57_828024 := 1
+ERRATA_A57_829520 := 1
+ERRATA_A57_833471 := 1
+ERRATA_A57_859972 := 0
+
+# Errata workarounds for Cortex-A72:
+ERRATA_A72_859971 := 0
+
+# Enable option to skip L1 data cache flush during the Cortex-A57 cluster
+# power down sequence
+SKIP_A57_L1_FLUSH_PWR_DWN := 1
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+# Enable the dynamic translation tables library.
+ifeq (${ARCH},aarch32)
+ ifeq (${RESET_TO_SP_MIN},1)
+ BL32_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+ endif
+else
+ ifeq (${RESET_TO_BL31},1)
+ BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+ endif
+endif
+
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+ ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
+ BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
+ else
+ BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
+ endif
+endif
+
+BL1_CPPFLAGS += -march=armv8-a+crc
+BL2_CPPFLAGS += -march=armv8-a+crc
+BL2U_CPPFLAGS += -march=armv8-a+crc
+BL31_CPPFLAGS += -march=armv8-a+crc
+BL32_CPPFLAGS += -march=armv8-a+crc
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += plat/arm/board/juno/fdts/${PLAT}_fw_config.dts \
+ plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts \
+ fdts/${PLAT}.dts
+
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${HW_CONFIG},--hw-config,${HW_CONFIG}))
+
+include plat/arm/board/common/board_common.mk
+include plat/arm/common/arm_common.mk
+include plat/arm/soc/common/soc_css.mk
+include plat/arm/css/common/css_common.mk
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
new file mode 100644
index 0000000..b3471c1
--- /dev/null
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SP_MIN source files specific to JUNO platform
+BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \
+ lib/cpus/aarch32/cortex_a53.S \
+ lib/cpus/aarch32/cortex_a57.S \
+ lib/cpus/aarch32/cortex_a72.S \
+ lib/utils/mem_region.c \
+ plat/arm/board/juno/juno_pm.c \
+ plat/arm/board/juno/juno_topology.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c \
+ plat/arm/soc/common/soc_css_security.c \
+ ${JUNO_GIC_SOURCES} \
+ ${JUNO_INTERCONNECT_SOURCES} \
+ ${JUNO_SECURITY_SOURCES}
+
+include plat/arm/common/sp_min/arm_sp_min.mk
+include plat/arm/css/common/sp_min/css_sp_min.mk
diff --git a/plat/arm/board/juno/tsp/tsp-juno.mk b/plat/arm/board/juno/tsp/tsp-juno.mk
new file mode 100644
index 0000000..be75c4d
--- /dev/null
+++ b/plat/arm/board/juno/tsp/tsp-juno.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_SOURCES += plat/arm/board/juno/juno_topology.c \
+ plat/arm/css/common/css_topology.c \
+ ${JUNO_GIC_SOURCES} \
+ ${JUNO_SECURITY_SOURCES}
+
+include plat/arm/common/tsp/arm_tsp.mk
diff --git a/plat/arm/board/morello/aarch64/morello_helper.S b/plat/arm/board/morello/aarch64/morello_helper.S
new file mode 100644
index 0000000..60470a8
--- /dev/null
+++ b/plat/arm/board/morello/aarch64/morello_helper.S
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+#include <rainier.h>
+
+#include <platform_def.h>
+
+ .globl plat_arm_calc_core_pos
+ .globl plat_reset_handler
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Helper function to calculate the core position.
+ * ((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+ * MORELLO_MAX_CPUS_PER_CLUSTER * MORELLO_MAX_PE_PER_CPU) +
+ * (CPUId * MORELLO_MAX_PE_PER_CPU) + ThreadId
+ *
+ * which can be simplified as:
+ *
+ * (((ChipId * MORELLO_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+ * MORELLO_MAX_CPUS_PER_CLUSTER + CPUId) * MORELLO_MAX_PE_PER_CPU) +
+ * ThreadId
+ * ------------------------------------------------------
+ */
+
+func plat_arm_calc_core_pos
+ mov x4, x0
+
+ /*
+ * The MT bit in MPIDR is always set for morello and the
+ * affinity level 0 corresponds to thread affinity level.
+ */
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x4, #MORELLO_MAX_CLUSTERS_PER_CHIP
+ madd x2, x3, x4, x2
+ mov x4, #MORELLO_MAX_CPUS_PER_CLUSTER
+ madd x1, x2, x4, x1
+ mov x4, #MORELLO_MAX_PE_PER_CPU
+ madd x0, x1, x4, x0
+ ret
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/morello/fdts/morello_fw_config.dts b/plat/arm/board/morello/fdts/morello_fw_config.dts
new file mode 100644
index 0000000..c47bae5
--- /dev/null
+++ b/plat/arm/board/morello/fdts/morello_fw_config.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/morello/fdts/morello_nt_fw_config.dts b/plat/arm/board/morello/fdts/morello_nt_fw_config.dts
new file mode 100644
index 0000000..e730d34
--- /dev/null
+++ b/plat/arm/board/morello/fdts/morello_nt_fw_config.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,morello";
+
+ /*
+ * Place holder for platform-info node with default values.
+ * The values will be set to the correct values during
+ * the BL2 stage of boot.
+ */
+ platform-info {
+ local-ddr-size = <0x0 0x0>;
+#ifdef TARGET_PLATFORM_SOC
+ remote-ddr-size = <0x0 0x0>;
+ remote-chip-count = <0x0>;
+ multichip-mode = <0x0>;
+ scc-config = <0x0>;
+#endif
+ };
+};
diff --git a/plat/arm/board/morello/fdts/morello_tb_fw_config.dts b/plat/arm/board/morello/fdts/morello_tb_fw_config.dts
new file mode 100644
index 0000000..305a818
--- /dev/null
+++ b/plat/arm/board/morello/fdts/morello_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/morello/include/plat_macros.S b/plat/arm/board/morello/include/plat_macros.S
new file mode 100644
index 0000000..195be84
--- /dev/null
+++ b/plat/arm/board/morello/include/plat_macros.S
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <css_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/morello/include/platform_def.h b/plat/arm/board/morello/include/platform_def.h
new file mode 100644
index 0000000..08e2d60
--- /dev/null
+++ b/plat/arm/board/morello/include/platform_def.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/css/common/css_def.h>
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE ULL(0x2A400000)
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ U(50000000)
+
+/* IOFPGA UART0 */
+#define PLAT_ARM_RUN_UART_BASE ULL(0x1C090000)
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ U(24000000)
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE ULL(0xF80000000)
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+#define PLAT_ARM_FLASH_IMAGE_BASE ULL(0x1A000000)
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE ULL(0x01000000)
+
+#define PLAT_ARM_NVM_BASE ULL(0x1A000000)
+#define PLAT_ARM_NVM_SIZE ULL(0x01000000)
+
+#if defined NS_BL1U_BASE
+#undef NS_BL1U_BASE
+#define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x00800000))
+#endif
+
+/*
+ * There are no non-volatile counters in morello, these macros points
+ * to unused addresses.
+ */
+#define SOC_TRUSTED_NVCTR_BASE ULL(0x7FE70000)
+#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + U(0x0000))
+#define TFW_NVCTR_SIZE U(4)
+#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + U(0x0004))
+#define NTFW_CTR_SIZE U(4)
+
+/*
+ * To access the complete DDR memory along with remote chip's DDR memory,
+ * which is at 4 TB offset, physical and virtual address space limits are
+ * extended to 43-bits.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43)
+
+#if CSS_USE_SCMI_SDS_DRIVER
+#define MORELLO_SCMI_PAYLOAD_BASE ULL(0x45400000)
+#else
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE ULL(0x45400000)
+#endif
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00080000)
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE UL(0xC000)
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE UL(0x1000)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE UL(0xE000)
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE U(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE U(0)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE UL(0x1D000)
+#else
+# define PLAT_ARM_MAX_BL2_SIZE UL(0x14000)
+#endif
+
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x3B000)
+
+/*******************************************************************************
+ * MORELLO topology related constants
+ ******************************************************************************/
+#define MORELLO_MAX_CPUS_PER_CLUSTER U(2)
+#define PLAT_ARM_CLUSTER_COUNT U(2)
+#define PLAT_MORELLO_CHIP_COUNT U(1)
+#define MORELLO_MAX_CLUSTERS_PER_CHIP U(2)
+#define MORELLO_MAX_PE_PER_CPU U(1)
+
+#define PLATFORM_CORE_COUNT (PLAT_MORELLO_CHIP_COUNT * \
+ PLAT_ARM_CLUSTER_COUNT * \
+ MORELLO_MAX_CPUS_PER_CLUSTER * \
+ MORELLO_MAX_PE_PER_CPU)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if IMAGE_BL1 || IMAGE_BL31
+# define PLAT_ARM_MMAP_ENTRIES U(6)
+# define MAX_XLAT_TABLES U(7)
+#else
+# define PLAT_ARM_MMAP_ENTRIES U(5)
+# define MAX_XLAT_TABLES U(6)
+#endif
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x440)
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE UL(0x1000)
+# else
+# define PLATFORM_STACK_SIZE UL(0x400)
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE UL(0x400)
+#elif defined(IMAGE_BL31)
+# if SPM_MM
+# define PLATFORM_STACK_SIZE UL(0x500)
+# else
+# define PLATFORM_STACK_SIZE UL(0x400)
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE UL(0x440)
+#endif
+
+#define PLAT_ARM_NSTIMER_FRAME_ID U(0)
+
+#define PLAT_ARM_TRUSTED_ROM_BASE U(0x0)
+#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x00020000) /* 128KB */
+
+#define PLAT_ARM_NSRAM_BASE ULL(0x06000000)
+#define PLAT_ARM_NSRAM_SIZE UL(0x00010000) /* 64KB */
+
+#define PLAT_CSS_MHU_BASE UL(0x45000000)
+#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE
+#define PLAT_MAX_PWR_LVL U(2)
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+#define MORELLO_DEVICE_BASE ULL(0x08000000)
+#define MORELLO_DEVICE_SIZE ULL(0x48000000)
+
+/*Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT UL(1000)
+
+#define MORELLO_MAP_DEVICE MAP_REGION_FLAT( \
+ MORELLO_DEVICE_BASE, \
+ MORELLO_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_MAP_DRAM1 MAP_REGION_FLAT( \
+ ARM_DRAM1_BASE, \
+ ARM_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE UL(0x300C0000)
+
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/morello/morello_bl1_setup.c b/plat/arm/board/morello/morello_bl1_setup.c
new file mode 100644
index 0000000..9155542
--- /dev/null
+++ b/plat/arm/board/morello/morello_bl1_setup.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+
+void soc_css_init_nic400(void)
+{
+}
+
+void soc_css_init_pcie(void)
+{
+}
diff --git a/plat/arm/board/morello/morello_bl2_setup.c b/plat/arm/board/morello/morello_bl2_setup.c
new file mode 100644
index 0000000..da1f7ae
--- /dev/null
+++ b/plat/arm/board/morello/morello_bl2_setup.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/css/sds.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "morello_def.h"
+#include <platform_def.h>
+
+#ifdef TARGET_PLATFORM_FVP
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size
+ * - Local DDR size in bytes, DDR memory in main board
+ */
+struct morello_plat_info {
+ uint64_t local_ddr_size;
+} __packed;
+#else
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which is an information about multichip setup
+ * - Local DDR size in bytes, DDR memory in main board
+ * - Remote DDR size in bytes, DDR memory in remote board
+ * - remote_chip_count
+ * - multichip mode
+ * - scc configuration
+ */
+struct morello_plat_info {
+ uint64_t local_ddr_size;
+ uint64_t remote_ddr_size;
+ uint8_t remote_chip_count;
+ bool multichip_mode;
+ uint32_t scc_config;
+} __packed;
+#endif
+
+/* Compile time assertion to ensure the size of structure is 18 bytes */
+CASSERT(sizeof(struct morello_plat_info) == MORELLO_SDS_PLATFORM_INFO_SIZE,
+ assert_invalid_plat_info_size);
+
+#ifdef TARGET_PLATFORM_SOC
+/*
+ * Morello platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC-Bing. Zeroing out several gigabytes of
+ * memory from SCP is quite time consuming so the following function
+ * is added to zero out the DDR memory from application processor which is
+ * much faster compared to SCP.
+ */
+
+static void dmc_ecc_setup(struct morello_plat_info *plat_info)
+{
+ uint64_t dram2_size;
+ uint32_t val;
+ uint64_t tag_mem_base;
+ uint64_t usable_mem_size;
+
+ INFO("Total DIMM size: %uGB\n",
+ (uint32_t)(plat_info->local_ddr_size / 0x40000000));
+
+ assert(plat_info->local_ddr_size > ARM_DRAM1_SIZE);
+ dram2_size = plat_info->local_ddr_size - ARM_DRAM1_SIZE;
+
+ INFO("Zeroing DDR memory range 0x80000000 - 0xFFFFFFFF\n");
+ zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+ flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+
+ INFO("Zeroing DDR memory range 0x%llx - 0x%llx\n",
+ ARM_DRAM2_BASE, ARM_DRAM2_BASE + dram2_size);
+ zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size);
+ flush_dcache_range(ARM_DRAM2_BASE, dram2_size);
+
+ /* Clear previous ECC errors while zeroing out the memory */
+ val = mmio_read_32(MORELLO_DMC0_ERR2STATUS_REG);
+ mmio_write_32(MORELLO_DMC0_ERR2STATUS_REG, val);
+
+ val = mmio_read_32(MORELLO_DMC1_ERR2STATUS_REG);
+ mmio_write_32(MORELLO_DMC1_ERR2STATUS_REG, val);
+
+ /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */
+ mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG);
+ mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_CONFIG);
+
+ while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) &
+ MORELLO_DMC_MEMC_STATUS_MASK) !=
+ MORELLO_DMC_MEMC_CMD_CONFIG) {
+ continue;
+ }
+
+ while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) &
+ MORELLO_DMC_MEMC_STATUS_MASK) !=
+ MORELLO_DMC_MEMC_CMD_CONFIG) {
+ continue;
+ }
+
+ /* Configure Bing client/server mode based on SCC configuration */
+ if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) {
+ INFO("Configuring DMC Bing in client mode\n");
+ usable_mem_size = plat_info->local_ddr_size -
+ (plat_info->local_ddr_size / 128ULL);
+
+ /* Linear DDR address */
+ tag_mem_base = usable_mem_size;
+ tag_mem_base = tag_mem_base / 4;
+
+ /* Reverse translation */
+ if (tag_mem_base < ARM_DRAM1_BASE) {
+ tag_mem_base += ARM_DRAM1_BASE;
+ } else {
+ tag_mem_base = tag_mem_base - ARM_DRAM1_BASE +
+ ARM_DRAM2_BASE;
+ }
+
+ mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x1);
+ mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x1);
+ mmio_write_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x1);
+ mmio_write_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x1);
+
+ if (plat_info->scc_config & MORELLO_SCC_C1_TAG_CACHE_EN_MASK) {
+ mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x2);
+ mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x2);
+ INFO("C1 Tag Cache Enabled\n");
+ }
+
+ if (plat_info->scc_config & MORELLO_SCC_C2_TAG_CACHE_EN_MASK) {
+ mmio_setbits_32(MORELLO_DMC0_TAG_CACHE_CFG, 0x4);
+ mmio_setbits_32(MORELLO_DMC1_TAG_CACHE_CFG, 0x4);
+ INFO("C2 Tag Cache Enabled\n");
+ }
+
+ mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL,
+ (uint32_t)tag_mem_base);
+ mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL,
+ (uint32_t)tag_mem_base);
+ mmio_write_32(MORELLO_DMC0_MEM_ADDR_CTL2,
+ (uint32_t)(tag_mem_base >> 32));
+ mmio_write_32(MORELLO_DMC1_MEM_ADDR_CTL2,
+ (uint32_t)(tag_mem_base >> 32));
+
+ mmio_setbits_32(MORELLO_DMC0_MEM_ACCESS_CTL,
+ MORELLO_DMC_MEM_ACCESS_DIS);
+ mmio_setbits_32(MORELLO_DMC1_MEM_ACCESS_CTL,
+ MORELLO_DMC_MEM_ACCESS_DIS);
+
+ INFO("Tag base set to 0x%lx\n", tag_mem_base);
+ plat_info->local_ddr_size = usable_mem_size;
+ } else {
+ INFO("Configuring DMC Bing in server mode\n");
+ mmio_write_32(MORELLO_DMC0_CAP_CTRL_REG, 0x0);
+ mmio_write_32(MORELLO_DMC1_CAP_CTRL_REG, 0x0);
+ }
+
+ INFO("Enabling ECC on DMCs\n");
+ /* Enable ECC in DMCs */
+ mmio_setbits_32(MORELLO_DMC0_ERR0CTLR0_REG,
+ MORELLO_DMC_ERR0CTLR0_ECC_EN);
+ mmio_setbits_32(MORELLO_DMC1_ERR0CTLR0_REG,
+ MORELLO_DMC_ERR0CTLR0_ECC_EN);
+
+ /* Set DMCs to READY state */
+ mmio_write_32(MORELLO_DMC0_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY);
+ mmio_write_32(MORELLO_DMC1_MEMC_CMD_REG, MORELLO_DMC_MEMC_CMD_READY);
+
+ while ((mmio_read_32(MORELLO_DMC0_MEMC_STATUS_REG) &
+ MORELLO_DMC_MEMC_STATUS_MASK) !=
+ MORELLO_DMC_MEMC_CMD_READY) {
+ continue;
+ }
+
+ while ((mmio_read_32(MORELLO_DMC1_MEMC_STATUS_REG) &
+ MORELLO_DMC_MEMC_STATUS_MASK) !=
+ MORELLO_DMC_MEMC_CMD_READY) {
+ continue;
+ }
+}
+#endif
+
+void bl2_platform_setup(void)
+{
+ int ret;
+ struct morello_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed. ret:%d\n", ret);
+ panic();
+ }
+
+ ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
+ MORELLO_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ MORELLO_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS. ret:%d\n", ret);
+ panic();
+ }
+
+ /* Validate plat_info SDS */
+#ifdef TARGET_PLATFORM_FVP
+ if (plat_info.local_ddr_size == 0U) {
+#else
+ if ((plat_info.local_ddr_size == 0U)
+ || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY)
+ || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY)
+ || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT)
+ ) {
+#endif
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+#ifdef TARGET_PLATFORM_SOC
+ dmc_ecc_setup(&plat_info);
+#endif
+ arm_bl2_platform_setup();
+}
diff --git a/plat/arm/board/morello/morello_bl31_setup.c b/plat/arm/board/morello/morello_bl31_setup.c
new file mode 100644
index 0000000..a044212
--- /dev/null
+++ b/plat/arm/board/morello/morello_bl31_setup.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "morello_def.h"
+#include <platform_def.h>
+
+static scmi_channel_plat_info_t morello_scmi_plat_info = {
+ .scmi_mbx_mem = MORELLO_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhu_ring_doorbell
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+ return &morello_scmi_plat_info;
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
+
+void bl31_platform_setup(void)
+{
+ arm_bl31_platform_setup();
+}
diff --git a/plat/arm/board/morello/morello_def.h b/plat/arm/board/morello/morello_def.h
new file mode 100644
index 0000000..f154924
--- /dev/null
+++ b/plat/arm/board/morello/morello_def.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MORELLO_DEF_H
+#define MORELLO_DEF_H
+
+/* Non-secure SRAM MMU mapping */
+#define MORELLO_NS_SRAM_BASE UL(0x06000000)
+#define MORELLO_NS_SRAM_SIZE UL(0x00010000)
+#define MORELLO_MAP_NS_SRAM MAP_REGION_FLAT( \
+ MORELLO_NS_SRAM_BASE, \
+ MORELLO_NS_SRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/* SDS Platform information defines */
+#define MORELLO_SDS_PLATFORM_INFO_STRUCT_ID U(8)
+#define MORELLO_SDS_PLATFORM_INFO_OFFSET U(0)
+#ifdef TARGET_PLATFORM_FVP
+# define MORELLO_SDS_PLATFORM_INFO_SIZE U(8)
+#else
+# define MORELLO_SDS_PLATFORM_INFO_SIZE U(22)
+#endif
+#define MORELLO_MAX_DDR_CAPACITY U(0x1000000000)
+#define MORELLO_MAX_REMOTE_CHIP_COUNT U(16)
+
+#define MORELLO_SCC_SERVER_MODE U(0)
+#define MORELLO_SCC_CLIENT_MODE_MASK U(1)
+#define MORELLO_SCC_C1_TAG_CACHE_EN_MASK U(4)
+#define MORELLO_SCC_C2_TAG_CACHE_EN_MASK U(8)
+
+/* Base address of non-secure SRAM where Platform information will be filled */
+#define MORELLO_PLATFORM_INFO_BASE UL(0x06000000)
+
+/* DMC memory status registers */
+#define MORELLO_DMC0_MEMC_STATUS_REG UL(0x4E000000)
+#define MORELLO_DMC1_MEMC_STATUS_REG UL(0x4E100000)
+
+#define MORELLO_DMC_MEMC_STATUS_MASK U(7)
+
+/* DMC memory command registers */
+#define MORELLO_DMC0_MEMC_CMD_REG UL(0x4E000008)
+#define MORELLO_DMC1_MEMC_CMD_REG UL(0x4E100008)
+
+/* DMC capability control register */
+#define MORELLO_DMC0_CAP_CTRL_REG UL(0x4E000D00)
+#define MORELLO_DMC1_CAP_CTRL_REG UL(0x4E100D00)
+
+/* DMC tag cache control register */
+#define MORELLO_DMC0_TAG_CACHE_CTL UL(0x4E000D04)
+#define MORELLO_DMC1_TAG_CACHE_CTL UL(0x4E100D04)
+
+/* DMC tag cache config register */
+#define MORELLO_DMC0_TAG_CACHE_CFG UL(0x4E000D08)
+#define MORELLO_DMC1_TAG_CACHE_CFG UL(0x4E100D08)
+
+/* DMC memory access control register */
+#define MORELLO_DMC0_MEM_ACCESS_CTL UL(0x4E000D0C)
+#define MORELLO_DMC1_MEM_ACCESS_CTL UL(0x4E100D0C)
+
+#define MORELLO_DMC_MEM_ACCESS_DIS (1UL << 16)
+
+/* DMC memory address control register */
+#define MORELLO_DMC0_MEM_ADDR_CTL UL(0x4E000D10)
+#define MORELLO_DMC1_MEM_ADDR_CTL UL(0x4E100D10)
+
+/* DMC memory address control 2 register */
+#define MORELLO_DMC0_MEM_ADDR_CTL2 UL(0x4E000D14)
+#define MORELLO_DMC1_MEM_ADDR_CTL2 UL(0x4E100D14)
+
+/* DMC special control register */
+#define MORELLO_DMC0_SPL_CTL_REG UL(0x4E000D18)
+#define MORELLO_DMC1_SPL_CTL_REG UL(0x4E100D18)
+
+/* DMC ERR0CTLR0 registers */
+#define MORELLO_DMC0_ERR0CTLR0_REG UL(0x4E000708)
+#define MORELLO_DMC1_ERR0CTLR0_REG UL(0x4E100708)
+
+/* DMC ECC in ERR0CTLR0 register */
+#define MORELLO_DMC_ERR0CTLR0_ECC_EN U(9)
+
+/* DMC ERR2STATUS register */
+#define MORELLO_DMC0_ERR2STATUS_REG UL(0x4E000790)
+#define MORELLO_DMC1_ERR2STATUS_REG UL(0x4E100790)
+
+/* DMC memory commands */
+#define MORELLO_DMC_MEMC_CMD_CONFIG U(0)
+#define MORELLO_DMC_MEMC_CMD_READY U(3)
+
+#endif /* MORELLO_DEF_H */
diff --git a/plat/arm/board/morello/morello_err.c b/plat/arm/board/morello/morello_err.c
new file mode 100644
index 0000000..4d20a09
--- /dev/null
+++ b/plat/arm/board/morello/morello_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * morello error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/morello/morello_image_load.c b/plat/arm/board/morello/morello_image_load.c
new file mode 100644
index 0000000..52d46f3
--- /dev/null
+++ b/plat/arm/board/morello/morello_image_load.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/css/sds.h>
+#include <libfdt.h>
+
+#include "morello_def.h"
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#ifdef TARGET_PLATFORM_FVP
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which is an information about multichip setup
+ * - Local DDR size in bytes, DDR memory in main board
+ */
+struct morello_plat_info {
+ uint64_t local_ddr_size;
+} __packed;
+#else
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which is an information about multichip setup
+ * - Local DDR size in bytes, DDR memory in main board
+ * - Remote DDR size in bytes, DDR memory in remote board
+ * - remote_chip_count
+ * - multichip mode
+ * - scc configuration
+ */
+struct morello_plat_info {
+ uint64_t local_ddr_size;
+ uint64_t remote_ddr_size;
+ uint8_t remote_chip_count;
+ bool multichip_mode;
+ uint32_t scc_config;
+} __packed;
+#endif
+
+/* In client mode, a part of the DDR memory is reserved for Tag bits.
+ * Calculate the usable memory size after subtracting the Tag memory.
+ */
+static inline uint64_t get_mem_client_mode(uint64_t size)
+{
+ return (size - (size / 128ULL));
+}
+
+/*******************************************************************************
+ * This function inserts Platform information via device tree nodes as,
+ * platform-info {
+ * local-ddr-size = <0x0 0x0>;
+ *#ifdef TARGET_PLATFORM_SOC
+ * remote-ddr-size = <0x0 0x0>;
+ * remote-chip-count = <0x0>;
+ * multichip-mode = <0x0>;
+ * scc-config = <0x0>;
+ *#endif
+ * };
+ ******************************************************************************/
+static int plat_morello_append_config_node(struct morello_plat_info *plat_info)
+{
+ bl_mem_params_node_t *mem_params;
+ void *fdt;
+ int nodeoffset, err;
+ uint64_t usable_mem_size;
+
+ usable_mem_size = plat_info->local_ddr_size;
+
+ mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+ if (mem_params == NULL) {
+ ERROR("NT_FW CONFIG base address is NULL\n");
+ return -1;
+ }
+
+ fdt = (void *)(mem_params->image_info.image_base);
+
+ /* Check the validity of the fdt */
+ if (fdt_check_header(fdt) != 0) {
+ ERROR("Invalid NT_FW_CONFIG DTB passed\n");
+ return -1;
+ }
+
+ nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info");
+ if (nodeoffset < 0) {
+ ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n");
+ return -1;
+ }
+
+#ifdef TARGET_PLATFORM_SOC
+ err = fdt_setprop_u64(fdt, nodeoffset, "remote-ddr-size",
+ plat_info->remote_ddr_size);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "remote-chip-count",
+ plat_info->remote_chip_count);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set remote-chip-count\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode",
+ plat_info->multichip_mode);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "scc-config",
+ plat_info->scc_config);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set scc-config\n");
+ return -1;
+ }
+
+ if (plat_info->scc_config & MORELLO_SCC_CLIENT_MODE_MASK) {
+ usable_mem_size = get_mem_client_mode(plat_info->local_ddr_size);
+ }
+#endif
+ err = fdt_setprop_u64(fdt, nodeoffset, "local-ddr-size",
+ usable_mem_size);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n");
+ return -1;
+ }
+
+ flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ int ret;
+ struct morello_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed. ret:%d\n", ret);
+ panic();
+ }
+
+ ret = sds_struct_read(MORELLO_SDS_PLATFORM_INFO_STRUCT_ID,
+ MORELLO_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ MORELLO_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS. ret:%d\n", ret);
+ panic();
+ }
+
+ /* Validate plat_info SDS */
+#ifdef TARGET_PLATFORM_FVP
+ if (plat_info.local_ddr_size == 0U) {
+#else
+ if ((plat_info.local_ddr_size == 0U)
+ || (plat_info.local_ddr_size > MORELLO_MAX_DDR_CAPACITY)
+ || (plat_info.remote_ddr_size > MORELLO_MAX_DDR_CAPACITY)
+ || (plat_info.remote_chip_count > MORELLO_MAX_REMOTE_CHIP_COUNT)
+ ){
+#endif
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+ ret = plat_morello_append_config_node(&plat_info);
+ if (ret != 0) {
+ panic();
+ }
+
+ return arm_get_next_bl_params();
+}
diff --git a/plat/arm/board/morello/morello_interconnect.c b/plat/arm/board/morello/morello_interconnect.c
new file mode 100644
index 0000000..d941bfe
--- /dev/null
+++ b/plat/arm/board/morello/morello_interconnect.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/*
+ * For MORELLO which supports FCM (with automatic interconnect enter/exit),
+ * we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/board/morello/morello_plat.c b/plat/arm/board/morello/morello_plat.c
new file mode 100644
index 0000000..1da0ff9
--- /dev/null
+++ b/plat/arm/board/morello/morello_plat.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/sbsa.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "morello_def.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ MORELLO_MAP_DEVICE,
+ MORELLO_MAP_NS_SRAM,
+ ARM_MAP_DRAM1,
+ ARM_MAP_DRAM2,
+ {0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ MORELLO_MAP_DEVICE,
+ MORELLO_MAP_NS_SRAM,
+ {0}
+};
+#endif
+
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ MORELLO_MAP_DEVICE,
+ MORELLO_MAP_NS_SRAM,
+ ARM_MAP_DRAM1,
+ ARM_MAP_DRAM2,
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif
+ {0}
+};
+#endif
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+ sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/board/morello/morello_security.c b/plat/arm/board/morello/morello_security.c
new file mode 100644
index 0000000..a388a80
--- /dev/null
+++ b/plat/arm/board/morello/morello_security.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * TZC programming is currently not done.
+ */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/morello/morello_topology.c b/plat/arm/board/morello/morello_topology.c
new file mode 100644
index 0000000..ef2f753
--- /dev/null
+++ b/plat/arm/board/morello/morello_topology.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/cassert.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* Compile time assertion to ensure the core count is 4 */
+CASSERT(PLATFORM_CORE_COUNT == 4U, assert_invalid_platform_core_count);
+
+/* Topology */
+typedef struct morello_topology {
+ const unsigned char *power_tree;
+ unsigned int plat_cluster_core_count;
+} morello_topology_t;
+
+/*
+ * The power domain tree descriptor. The cluster power domains are
+ * arranged so that when the PSCI generic code creates the power domain tree,
+ * the indices of the CPU power domain nodes it allocates match the linear
+ * indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char morello_pd_tree_desc[] = {
+ PLAT_MORELLO_CHIP_COUNT,
+ PLAT_ARM_CLUSTER_COUNT,
+ MORELLO_MAX_CPUS_PER_CLUSTER,
+ MORELLO_MAX_CPUS_PER_CLUSTER,
+};
+
+/* Topology configuration for morello */
+const morello_topology_t morello_topology = {
+ .power_tree = morello_pd_tree_desc,
+ .plat_cluster_core_count = MORELLO_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return morello_topology.power_tree;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+ return morello_topology.plat_cluster_core_count;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+ 0, 1, 2, 3};
diff --git a/plat/arm/board/morello/morello_trusted_boot.c b/plat/arm/board/morello/morello_trusted_boot.c
new file mode 100644
index 0000000..f9bc009
--- /dev/null
+++ b/plat/arm/board/morello/morello_trusted_boot.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = MORELLO_FW_NVCTR_VAL;
+
+ return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. By default on ARM development
+ * platforms, the non-volatile counters are RO and cannot be modified. We expect
+ * the values in the certificates to always match the RO values so that this
+ * function is never called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/morello/platform.mk b/plat/arm/board/morello/platform.mk
new file mode 100644
index 0000000..156b7ea
--- /dev/null
+++ b/plat/arm/board/morello/platform.mk
@@ -0,0 +1,110 @@
+#
+# Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Making sure the Morello platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fvp soc),)
+ $(error TARGET_PLATFORM must be fvp or soc)
+endif
+
+MORELLO_BASE := plat/arm/board/morello
+
+INTERCONNECT_SOURCES := ${MORELLO_BASE}/morello_interconnect.c
+
+PLAT_INCLUDES := -I${MORELLO_BASE}/include
+
+MORELLO_CPU_SOURCES := lib/cpus/aarch64/rainier.S
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+MORELLO_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/arm/common/arm_gicv3.c \
+
+PLAT_BL_COMMON_SOURCES := ${MORELLO_BASE}/morello_plat.c \
+ ${MORELLO_BASE}/aarch64/morello_helper.S
+
+BL1_SOURCES := ${MORELLO_CPU_SOURCES} \
+ ${INTERCONNECT_SOURCES} \
+ ${MORELLO_BASE}/morello_err.c \
+ ${MORELLO_BASE}/morello_trusted_boot.c \
+ ${MORELLO_BASE}/morello_bl1_setup.c \
+ drivers/arm/sbsa/sbsa.c
+
+BL2_SOURCES := ${MORELLO_BASE}/morello_security.c \
+ ${MORELLO_BASE}/morello_err.c \
+ ${MORELLO_BASE}/morello_trusted_boot.c \
+ ${MORELLO_BASE}/morello_bl2_setup.c \
+ ${MORELLO_BASE}/morello_image_load.c \
+ lib/utils/mem_region.c \
+ drivers/arm/css/sds/sds.c
+
+BL31_SOURCES := ${MORELLO_CPU_SOURCES} \
+ ${INTERCONNECT_SOURCES} \
+ ${MORELLO_GIC_SOURCES} \
+ ${MORELLO_BASE}/morello_bl31_setup.c \
+ ${MORELLO_BASE}/morello_topology.c \
+ ${MORELLO_BASE}/morello_security.c \
+ drivers/arm/css/sds/sds.c
+
+FDT_SOURCES += fdts/morello-${TARGET_PLATFORM}.dts \
+ ${MORELLO_BASE}/fdts/morello_fw_config.dts \
+ ${MORELLO_BASE}/fdts/morello_tb_fw_config.dts \
+ ${MORELLO_BASE}/fdts/morello_nt_fw_config.dts
+
+FW_CONFIG := ${BUILD_PLAT}/fdts/morello_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/morello_tb_fw_config.dtb
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/morello_nt_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+MORELLO_FW_NVCTR_VAL := 0
+TFW_NVCTR_VAL := ${MORELLO_FW_NVCTR_VAL}
+NTFW_NVCTR_VAL := ${MORELLO_FW_NVCTR_VAL}
+
+# TF-A not required to load the SCP Images
+override CSS_LOAD_SCP_IMAGES := 0
+
+override NEED_BL2U := no
+
+# 32 bit mode not supported
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+override ARM_PLAT_MT := 1
+
+override ARM_BL31_IN_DRAM := 1
+
+# Errata workarounds:
+ERRATA_N1_1868343 := 1
+
+# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the
+# SCP during power management operations and for SCP RAM Firmware transfer.
+CSS_USE_SCMI_SDS_DRIVER := 1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY := 1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM := 0
+
+# Add TARGET_PLATFORM to differentiate between Morello FVP and Morello SoC platform
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
+# Add MORELLO_FW_NVCTR_VAL
+$(eval $(call add_define,MORELLO_FW_NVCTR_VAL))
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S
new file mode 100644
index 0000000..3da55b6
--- /dev/null
+++ b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <neoverse_n1.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+ .globl plat_arm_calc_core_pos
+ .globl plat_reset_handler
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Helper function to calculate the core position.
+ * ((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+ * N1SDP_MAX_CPUS_PER_CLUSTER * N1SDP_MAX_PE_PER_CPU) +
+ * (CPUId * N1SDP_MAX_PE_PER_CPU) + ThreadId
+ *
+ * which can be simplified as:
+ *
+ * (((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+ * N1SDP_MAX_CPUS_PER_CLUSTER + CPUId) * N1SDP_MAX_PE_PER_CPU) +
+ * ThreadId
+ * ------------------------------------------------------
+ */
+
+func plat_arm_calc_core_pos
+ mov x4, x0
+
+ /*
+ * The MT bit in MPIDR is always set for n1sdp and the
+ * affinity level 0 corresponds to thread affinity level.
+ */
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x4, #N1SDP_MAX_CLUSTERS_PER_CHIP
+ madd x2, x3, x4, x2
+ mov x4, #N1SDP_MAX_CPUS_PER_CLUSTER
+ madd x1, x2, x4, x1
+ mov x4, #N1SDP_MAX_PE_PER_CPU
+ madd x0, x1, x4, x0
+ ret
+endfunc plat_arm_calc_core_pos
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Determine the CPU MIDR and disable power down bit for
+ * that CPU.
+ * -----------------------------------------------------
+ */
+
+func plat_reset_handler
+ jump_if_cpu_midr NEOVERSE_N1_MIDR, N1
+ ret
+
+ /* -----------------------------------------------------
+ * Disable CPU power down bit in power control register
+ * -----------------------------------------------------
+ */
+N1:
+ mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1
+ bic x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK
+ msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+endfunc plat_reset_handler
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts
new file mode 100644
index 0000000..700b900
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+ tos_fw-config {
+ load-address = <0x0 0x4001600>;
+ max-size = <0x1000>;
+ id = <TOS_FW_CONFIG_ID>;
+ };
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts
new file mode 100644
index 0000000..da5e04d
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,n1sdp";
+
+ /*
+ * Place holder for platform-info node with default values.
+ * The values will be set to the correct values during
+ * the BL2 stage of boot.
+ */
+ platform-info {
+ multichip-mode = <0x0>;
+ secondary-chip-count = <0x0>;
+ local-ddr-size = <0x0>;
+ remote-ddr-size = <0x0>;
+ };
+}; \ No newline at end of file
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts b/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts
new file mode 100644
index 0000000..ed87080
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ /*
+ * BL32 image details needed by SPMC
+ *
+ * Note:
+ * binary_size: size of BL32 + TOS_FW_CONFIG
+ */
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x0>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x08000000>;
+ entrypoint = <0x0 0x08000000>;
+ binary_size = <0x2000000>;
+ };
+
+};
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts
new file mode 100644
index 0000000..e5ffba3
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/n1sdp/include/plat_macros.S b/plat/arm/board/n1sdp/include/plat_macros.S
new file mode 100644
index 0000000..521bcc3
--- /dev/null
+++ b/plat/arm/board/n1sdp/include/plat_macros.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <css_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
new file mode 100644
index 0000000..b3799a7
--- /dev/null
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/css/common/css_def.h>
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE 0x2A400000
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ 50000000
+
+/* IOFPGA UART0 */
+#define PLAT_ARM_RUN_UART_BASE 0x1C090000
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ 24000000
+
+#define PLAT_ARM_SP_MIN_RUN_UART_BASE 0x2A410000
+#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ 50000000
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE ULL(0xF80000000)
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+#define PLAT_ARM_FLASH_IMAGE_BASE 0x18200000
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE 0x00800000
+
+#define PLAT_ARM_NVM_BASE 0x18200000
+#define PLAT_ARM_NVM_SIZE 0x00800000
+
+#if defined NS_BL1U_BASE
+# undef NS_BL1U_BASE
+# define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x00800000))
+#endif
+
+/* Non-volatile counters */
+#define SOC_TRUSTED_NVCTR_BASE 0x7fe70000
+#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE)
+#define TFW_NVCTR_SIZE U(4)
+#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE U(4)
+
+/* N1SDP remote chip at 4 TB offset */
+#define PLAT_ARM_REMOTE_CHIP_OFFSET (ULL(1) << 42)
+
+#define N1SDP_REMOTE_DRAM1_BASE ARM_DRAM1_BASE + \
+ PLAT_ARM_REMOTE_CHIP_OFFSET
+#define N1SDP_REMOTE_DRAM1_SIZE ARM_DRAM1_SIZE
+
+#define N1SDP_REMOTE_DRAM2_BASE PLAT_ARM_DRAM2_BASE + \
+ PLAT_ARM_REMOTE_CHIP_OFFSET
+#define N1SDP_REMOTE_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. To access the complete DDR memory
+ * along with remote chip's DDR memory, which is at 4 TB offset, physical
+ * and virtual address space limits are extended to 43-bits.
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+#if CSS_USE_SCMI_SDS_DRIVER
+#define N1SDP_SCMI_PAYLOAD_BASE 0x45400000
+#else
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE 0x45400000
+#endif
+
+/*
+ * Trusted SRAM in N1SDP is 512 KB but only the bottom 384 KB
+ * is used for trusted board boot flow. The top 128 KB is used
+ * to load AP-BL1 image.
+ */
+#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00060000 /* 384 KB */
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE 0xC000
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+# define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000
+# define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000
+#else
+# define PLAT_ARM_MAX_ROMLIB_RW_SIZE U(0)
+# define PLAT_ARM_MAX_ROMLIB_RO_SIZE U(0)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE 0x22000
+#else
+# define PLAT_ARM_MAX_BL2_SIZE 0x14000
+#endif
+
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x40000)
+
+#define PLAT_ARM_SPMC_BASE U(0x08000000)
+#define PLAT_ARM_SPMC_SIZE UL(0x02000000) /* 32 MB */
+
+
+/*******************************************************************************
+ * N1SDP topology related constants
+ ******************************************************************************/
+#define N1SDP_MAX_CPUS_PER_CLUSTER U(2)
+#define PLAT_ARM_CLUSTER_COUNT U(2)
+#define PLAT_N1SDP_CHIP_COUNT U(2)
+#define N1SDP_MAX_CLUSTERS_PER_CHIP U(2)
+#define N1SDP_MAX_PE_PER_CPU U(1)
+
+#define PLATFORM_CORE_COUNT (PLAT_N1SDP_CHIP_COUNT * \
+ PLAT_ARM_CLUSTER_COUNT * \
+ N1SDP_MAX_CPUS_PER_CLUSTER * \
+ N1SDP_MAX_PE_PER_CPU)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+
+#ifdef IMAGE_BL1
+# define PLAT_ARM_MMAP_ENTRIES U(6)
+# define MAX_XLAT_TABLES U(5)
+#endif
+
+#ifdef IMAGE_BL2
+# define PLAT_ARM_MMAP_ENTRIES U(11)
+# define MAX_XLAT_TABLES U(10)
+#endif
+
+#ifdef IMAGE_BL31
+# define PLAT_ARM_MMAP_ENTRIES U(12)
+# define MAX_XLAT_TABLES U(12)
+#endif
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x440
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+# if SPM_MM
+# define PLATFORM_STACK_SIZE 0x500
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define PLAT_ARM_NSTIMER_FRAME_ID 0
+#define PLAT_CSS_MHU_BASE 0x45000000
+#define PLAT_MAX_PWR_LVL 2
+
+#define PLAT_ARM_G1S_IRQS ARM_G1S_IRQS, \
+ CSS_IRQ_MHU
+#define PLAT_ARM_G0_IRQS ARM_G0_IRQS
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+
+#define N1SDP_DEVICE_BASE ULL(0x08000000)
+#define N1SDP_DEVICE_SIZE ULL(0x48000000)
+#define N1SDP_REMOTE_DEVICE_BASE N1SDP_DEVICE_BASE + \
+ PLAT_ARM_REMOTE_CHIP_OFFSET
+#define N1SDP_REMOTE_DEVICE_SIZE N1SDP_DEVICE_SIZE
+
+/* Real base is 0x0. Changed to load BL1 at this address */
+# define PLAT_ARM_TRUSTED_ROM_BASE 0x04060000
+# define PLAT_ARM_TRUSTED_ROM_SIZE 0x00020000 /* 128KB */
+
+#define N1SDP_MAP_DEVICE MAP_REGION_FLAT( \
+ N1SDP_DEVICE_BASE, \
+ N1SDP_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_MAP_DRAM1 MAP_REGION_FLAT( \
+ ARM_DRAM1_BASE, \
+ ARM_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define N1SDP_MAP_REMOTE_DEVICE MAP_REGION_FLAT( \
+ N1SDP_REMOTE_DEVICE_BASE, \
+ N1SDP_REMOTE_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define N1SDP_MAP_REMOTE_DRAM1 MAP_REGION_FLAT( \
+ N1SDP_REMOTE_DRAM1_BASE, \
+ N1SDP_REMOTE_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define N1SDP_MAP_REMOTE_DRAM2 MAP_REGION_FLAT( \
+ N1SDP_REMOTE_DRAM2_BASE, \
+ N1SDP_REMOTE_DRAM2_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE 0x30000000
+#define PLAT_ARM_GICC_BASE 0x2C000000
+#define PLAT_ARM_GICR_BASE 0x300C0000
+
+/* Platform ID address */
+#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
+
+/* Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT UL(100)
+
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/n1sdp/n1sdp_bl1_setup.c b/plat/arm/board/n1sdp/n1sdp_bl1_setup.c
new file mode 100644
index 0000000..ed93222
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_bl1_setup.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+
+void soc_css_init_nic400(void)
+{
+}
+
+void soc_css_init_pcie(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_bl2_setup.c b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c
new file mode 100644
index 0000000..5f8af9f
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/css/sds.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+
+#include "n1sdp_def.h"
+#include <plat/arm/common/plat_arm.h>
+
+struct n1sdp_plat_info {
+ bool multichip_mode;
+ uint8_t secondary_count;
+ uint8_t local_ddr_size;
+ uint8_t remote_ddr_size;
+} __packed;
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. Zeroing out several gigabytes of
+ * memory from SCP is quite time consuming so the following function
+ * is added to zero out the DDR memory from application processor which is
+ * much faster compared to SCP.
+ */
+
+void dmc_ecc_setup(uint8_t ddr_size_gb)
+{
+ uint64_t dram2_size;
+
+ dram2_size = (ddr_size_gb * 1024UL * 1024UL * 1024UL) -
+ ARM_DRAM1_SIZE;
+
+ INFO("Zeroing DDR memories\n");
+ zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+ flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+ zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size);
+ flush_dcache_range(ARM_DRAM2_BASE, dram2_size);
+
+ INFO("Enabling ECC on DMCs\n");
+ /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */
+ mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG);
+ mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG);
+
+ /* Enable ECC in DMCs */
+ mmio_setbits_32(N1SDP_DMC0_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN);
+ mmio_setbits_32(N1SDP_DMC1_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN);
+
+ /* Set DMCs to READY state */
+ mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+ mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+}
+
+void bl2_platform_setup(void)
+{
+ int ret;
+ struct n1sdp_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed\n");
+ panic();
+ }
+
+ ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+ N1SDP_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ N1SDP_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS\n");
+ panic();
+ }
+ /* Validate plat_info SDS */
+ if ((plat_info.local_ddr_size == 0)
+ || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) {
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+ dmc_ecc_setup(plat_info.local_ddr_size);
+ arm_bl2_platform_setup();
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
new file mode 100644
index 0000000..5e897fe
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <drivers/arm/css/sds.h>
+#include <drivers/arm/gic600_multichip.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "n1sdp_def.h"
+#include <platform_def.h>
+
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which will be used to zero out the memory before
+ * enabling the ECC capability as well as information
+ * about multichip setup
+ * - multichip mode
+ * - secondary_count
+ * - Local DDR size in GB, DDR memory in master board
+ * - Remote DDR size in GB, DDR memory in secondary board
+ */
+struct n1sdp_plat_info {
+ bool multichip_mode;
+ uint8_t secondary_count;
+ uint8_t local_ddr_size;
+ uint8_t remote_ddr_size;
+} __packed;
+
+static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
+ .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhu_ring_doorbell
+};
+
+static struct gic600_multichip_data n1sdp_multichip_data __init = {
+ .rt_owner_base = PLAT_ARM_GICD_BASE,
+ .rt_owner = 0,
+ .chip_count = 1,
+ .chip_addrs = {
+ PLAT_ARM_GICD_BASE >> 16,
+ PLAT_ARM_GICD_BASE >> 16
+ },
+ .spi_ids = {
+ {32, 479},
+ {512, 959}
+ }
+};
+
+static uintptr_t n1sdp_multichip_gicr_frames[3] = {
+ PLAT_ARM_GICR_BASE,
+ PLAT_ARM_GICR_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET,
+ 0
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+ return &n1sdp_scmi_plat_info;
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. Zeroing out several gigabytes of
+ * memory from SCP is quite time consuming so the following function
+ * is added to zero out the DDR memory from application processor which is
+ * much faster compared to SCP. Local DDR memory is zeroed out during BL2
+ * stage. If remote chip is connected, it's DDR memory is zeroed out here.
+ */
+
+void remote_dmc_ecc_setup(uint8_t remote_ddr_size)
+{
+ uint64_t remote_dram2_size;
+
+ remote_dram2_size = (remote_ddr_size * 1024UL * 1024UL * 1024UL) -
+ N1SDP_REMOTE_DRAM1_SIZE;
+ /* multichip setup */
+ INFO("Zeroing remote DDR memories\n");
+ zero_normalmem((void *)N1SDP_REMOTE_DRAM1_BASE,
+ N1SDP_REMOTE_DRAM1_SIZE);
+ flush_dcache_range(N1SDP_REMOTE_DRAM1_BASE, N1SDP_REMOTE_DRAM1_SIZE);
+ zero_normalmem((void *)N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size);
+ flush_dcache_range(N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size);
+
+ INFO("Enabling ECC on remote DMCs\n");
+ /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */
+ mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG,
+ N1SDP_DMC_MEMC_CMD_CONFIG);
+ mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG,
+ N1SDP_DMC_MEMC_CMD_CONFIG);
+
+ /* Enable ECC in DMCs */
+ mmio_setbits_32(N1SDP_REMOTE_DMC0_ERR0CTLR0_REG,
+ N1SDP_DMC_ERR0CTLR0_ECC_EN);
+ mmio_setbits_32(N1SDP_REMOTE_DMC1_ERR0CTLR0_REG,
+ N1SDP_DMC_ERR0CTLR0_ECC_EN);
+
+ /* Set DMCs to READY state */
+ mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+ mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+}
+
+void n1sdp_bl31_multichip_setup(void)
+{
+ plat_arm_override_gicr_frames(n1sdp_multichip_gicr_frames);
+ gic600_multichip_init(&n1sdp_multichip_data);
+}
+
+void bl31_platform_setup(void)
+{
+ int ret;
+ struct n1sdp_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed\n");
+ panic();
+ }
+
+ ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+ N1SDP_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ N1SDP_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS\n");
+ panic();
+ }
+ /* Validate plat_info SDS */
+ if ((plat_info.local_ddr_size == 0)
+ || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) {
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+ if (plat_info.multichip_mode) {
+ n1sdp_multichip_data.chip_count = plat_info.secondary_count + 1;
+ n1sdp_bl31_multichip_setup();
+ }
+ arm_bl31_platform_setup();
+
+ /* Check if remote memory is present */
+ if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0))
+ remote_dmc_ecc_setup(plat_info.remote_ddr_size);
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_def.h b/plat/arm/board/n1sdp/n1sdp_def.h
new file mode 100644
index 0000000..ffa6a03
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_def.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef N1SDP_DEF_H
+#define N1SDP_DEF_H
+
+/* Non-secure SRAM MMU mapping */
+#define N1SDP_NS_SRAM_BASE (0x06000000)
+#define N1SDP_NS_SRAM_SIZE (0x00010000)
+#define N1SDP_MAP_NS_SRAM MAP_REGION_FLAT( \
+ N1SDP_NS_SRAM_BASE, \
+ N1SDP_NS_SRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/* SDS Platform information defines */
+#define N1SDP_SDS_PLATFORM_INFO_STRUCT_ID 8
+#define N1SDP_SDS_PLATFORM_INFO_OFFSET 0
+#define N1SDP_SDS_PLATFORM_INFO_SIZE 4
+#define N1SDP_MAX_DDR_CAPACITY_GB 64
+#define N1SDP_MAX_SECONDARY_COUNT 16
+
+/* DMC memory command registers */
+#define N1SDP_DMC0_MEMC_CMD_REG 0x4E000008
+#define N1SDP_DMC1_MEMC_CMD_REG 0x4E100008
+
+/* DMC ERR0CTLR0 registers */
+#define N1SDP_DMC0_ERR0CTLR0_REG 0x4E000708
+#define N1SDP_DMC1_ERR0CTLR0_REG 0x4E100708
+
+/* Remote DMC memory command registers */
+#define N1SDP_REMOTE_DMC0_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC0_MEMC_CMD_REG
+#define N1SDP_REMOTE_DMC1_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC1_MEMC_CMD_REG
+
+/* Remote DMC ERR0CTLR0 registers */
+#define N1SDP_REMOTE_DMC0_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC0_ERR0CTLR0_REG
+#define N1SDP_REMOTE_DMC1_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC1_ERR0CTLR0_REG
+
+/* DMC memory commands */
+#define N1SDP_DMC_MEMC_CMD_CONFIG 0
+#define N1SDP_DMC_MEMC_CMD_READY 3
+
+/* DMC ECC enable bit in ERR0CTLR0 register */
+#define N1SDP_DMC_ERR0CTLR0_ECC_EN 0x1
+
+#endif /* N1SDP_DEF_H */
diff --git a/plat/arm/board/n1sdp/n1sdp_err.c b/plat/arm/board/n1sdp/n1sdp_err.c
new file mode 100644
index 0000000..629e76a
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * n1sdp error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_image_load.c b/plat/arm/board/n1sdp/n1sdp_image_load.c
new file mode 100644
index 0000000..6c3528c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_image_load.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/css/sds.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+
+#include "n1sdp_def.h"
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which will be used to zero out the memory before
+ * enabling the ECC capability as well as information
+ * about multichip setup
+ * - multichip mode
+ * - secondary_count
+ * - Local DDR size in GB, DDR memory in master board
+ * - Remote DDR size in GB, DDR memory in secondary board
+ */
+struct n1sdp_plat_info {
+ bool multichip_mode;
+ uint8_t secondary_count;
+ uint8_t local_ddr_size;
+ uint8_t remote_ddr_size;
+} __packed;
+
+/*******************************************************************************
+ * This function inserts Platform information via device tree nodes as,
+ * platform-info {
+ * multichip-mode = <0x0>;
+ * secondary-chip-count = <0x0>;
+ * local-ddr-size = <0x0>;
+ * remote-ddr-size = <0x0>;
+ * };
+ ******************************************************************************/
+static int plat_n1sdp_append_config_node(struct n1sdp_plat_info *plat_info)
+{
+ bl_mem_params_node_t *mem_params;
+ void *fdt;
+ int nodeoffset, err;
+
+ mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+ if (mem_params == NULL) {
+ ERROR("NT_FW CONFIG base address is NULL\n");
+ return -1;
+ }
+
+ fdt = (void *)(mem_params->image_info.image_base);
+
+ /* Check the validity of the fdt */
+ if (fdt_check_header(fdt) != 0) {
+ ERROR("Invalid NT_FW_CONFIG DTB passed\n");
+ return -1;
+ }
+
+ nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info");
+ if (nodeoffset < 0) {
+ ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode",
+ plat_info->multichip_mode);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "secondary-chip-count",
+ plat_info->secondary_count);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set secondary-chip-count\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "local-ddr-size",
+ plat_info->local_ddr_size);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "remote-ddr-size",
+ plat_info->remote_ddr_size);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n");
+ return -1;
+ }
+
+ flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ int ret;
+ struct n1sdp_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed. ret:%d\n", ret);
+ panic();
+ }
+
+ ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+ N1SDP_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ N1SDP_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS. ret:%d\n", ret);
+ panic();
+ }
+
+ /* Validate plat_info SDS */
+ if ((plat_info.local_ddr_size == 0U)
+ || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)
+ ){
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+ ret = plat_n1sdp_append_config_node(&plat_info);
+ if (ret != 0) {
+ panic();
+ }
+
+ return arm_get_next_bl_params();
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_interconnect.c b/plat/arm/board/n1sdp/n1sdp_interconnect.c
new file mode 100644
index 0000000..908f41c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_interconnect.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/*
+ * For N1SDP which support FCM (with automatic interconnect enter/exit),
+ * we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_plat.c b/plat/arm/board/n1sdp/n1sdp_plat.c
new file mode 100644
index 0000000..502268c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_plat.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/sbsa.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "n1sdp_def.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ N1SDP_MAP_DEVICE,
+ N1SDP_MAP_NS_SRAM,
+ ARM_MAP_DRAM1,
+ {0}
+};
+#endif
+
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ N1SDP_MAP_DEVICE,
+ N1SDP_MAP_NS_SRAM,
+ ARM_MAP_DRAM1,
+ ARM_MAP_DRAM2,
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif
+ {0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ N1SDP_MAP_DEVICE,
+ N1SDP_MAP_NS_SRAM,
+ N1SDP_MAP_REMOTE_DEVICE,
+ N1SDP_MAP_REMOTE_DRAM1,
+ N1SDP_MAP_REMOTE_DRAM2,
+ {0}
+};
+#endif
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+ sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_security.c b/plat/arm/board/n1sdp/n1sdp_security.c
new file mode 100644
index 0000000..d2a187b
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_security.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * TZC programming is currently not done.
+ */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_topology.c b/plat/arm/board/n1sdp/n1sdp_topology.c
new file mode 100644
index 0000000..5c2db71
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_topology.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/* Topology */
+typedef struct n1sdp_topology {
+ const unsigned char *power_tree;
+ unsigned int plat_cluster_core_count;
+} n1sdp_topology_t;
+
+/*
+ * The power domain tree descriptor. The cluster power domains are
+ * arranged so that when the PSCI generic code creates the power domain tree,
+ * the indices of the CPU power domain nodes it allocates match the linear
+ * indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char n1sdp_pd_tree_desc[] = {
+ PLAT_N1SDP_CHIP_COUNT,
+ PLAT_ARM_CLUSTER_COUNT,
+ PLAT_ARM_CLUSTER_COUNT,
+ N1SDP_MAX_CPUS_PER_CLUSTER,
+ N1SDP_MAX_CPUS_PER_CLUSTER,
+ N1SDP_MAX_CPUS_PER_CLUSTER,
+ N1SDP_MAX_CPUS_PER_CLUSTER
+};
+
+/* Topology configuration for n1sdp */
+const n1sdp_topology_t n1sdp_topology = {
+ .power_tree = n1sdp_pd_tree_desc,
+ .plat_cluster_core_count = N1SDP_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return n1sdp_topology.power_tree;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+ return n1sdp_topology.plat_cluster_core_count;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+ 0, 1, 2, 3, 4, 5, 6, 7};
diff --git a/plat/arm/board/n1sdp/n1sdp_trusted_boot.c b/plat/arm/board/n1sdp/n1sdp_trusted_boot.c
new file mode 100644
index 0000000..c7dc47f
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_trusted_boot.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = N1SDP_FW_NVCTR_VAL;
+ return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. By default on ARM development
+ * platforms, the non-volatile counters are RO and cannot be modified. We expect
+ * the values in the certificates to always match the RO values so that this
+ * function is never called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
+
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
new file mode 100644
index 0000000..9c0cc02
--- /dev/null
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -0,0 +1,111 @@
+#
+# Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+N1SDP_BASE := plat/arm/board/n1sdp
+
+INTERCONNECT_SOURCES := ${N1SDP_BASE}/n1sdp_interconnect.c
+
+PLAT_INCLUDES := -I${N1SDP_BASE}/include
+
+
+N1SDP_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+GICV3_IMPL_GIC600_MULTICHIP := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+N1SDP_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/arm/common/arm_gicv3.c \
+
+PLAT_BL_COMMON_SOURCES := ${N1SDP_BASE}/n1sdp_plat.c \
+ ${N1SDP_BASE}/aarch64/n1sdp_helper.S
+
+BL1_SOURCES := ${N1SDP_CPU_SOURCES} \
+ ${INTERCONNECT_SOURCES} \
+ ${N1SDP_BASE}/n1sdp_err.c \
+ ${N1SDP_BASE}/n1sdp_trusted_boot.c \
+ ${N1SDP_BASE}/n1sdp_bl1_setup.c \
+ drivers/arm/sbsa/sbsa.c
+
+BL2_SOURCES := ${N1SDP_BASE}/n1sdp_security.c \
+ ${N1SDP_BASE}/n1sdp_err.c \
+ ${N1SDP_BASE}/n1sdp_trusted_boot.c \
+ lib/utils/mem_region.c \
+ ${N1SDP_BASE}/n1sdp_bl2_setup.c \
+ ${N1SDP_BASE}/n1sdp_image_load.c \
+ drivers/arm/css/sds/sds.c
+
+BL31_SOURCES := ${N1SDP_CPU_SOURCES} \
+ ${INTERCONNECT_SOURCES} \
+ ${N1SDP_GIC_SOURCES} \
+ ${N1SDP_BASE}/n1sdp_bl31_setup.c \
+ ${N1SDP_BASE}/n1sdp_topology.c \
+ ${N1SDP_BASE}/n1sdp_security.c \
+ drivers/arm/css/sds/sds.c
+
+FDT_SOURCES += fdts/${PLAT}-single-chip.dts \
+ fdts/${PLAT}-multi-chip.dts \
+ ${N1SDP_BASE}/fdts/n1sdp_fw_config.dts \
+ ${N1SDP_BASE}/fdts/n1sdp_tb_fw_config.dts \
+ ${N1SDP_BASE}/fdts/n1sdp_nt_fw_config.dts
+
+FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_tb_fw_config.dtb
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_nt_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+N1SDP_SPMC_MANIFEST_DTS := ${N1SDP_BASE}/fdts/${PLAT}_optee_spmc_manifest.dts
+FDT_SOURCES += ${N1SDP_SPMC_MANIFEST_DTS}
+N1SDP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_optee_spmc_manifest.dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${N1SDP_TOS_FW_CONFIG},--tos-fw-config,${N1SDP_TOS_FW_CONFIG}))
+
+# Setting to 0 as no NVCTR in N1SDP
+N1SDP_FW_NVCTR_VAL := 0
+TFW_NVCTR_VAL := ${N1SDP_FW_NVCTR_VAL}
+NTFW_NVCTR_VAL := ${N1SDP_FW_NVCTR_VAL}
+
+# Add N1SDP_FW_NVCTR_VAL
+$(eval $(call add_define,N1SDP_FW_NVCTR_VAL))
+
+# TF-A not required to load the SCP Images
+override CSS_LOAD_SCP_IMAGES := 0
+
+override NEED_BL2U := no
+
+# 32 bit mode not supported
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+override ARM_PLAT_MT := 1
+
+# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the
+# SCP during power management operations and for SCP RAM Firmware transfer.
+CSS_USE_SCMI_SDS_DRIVER := 1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY := 1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM := 0
+
+# Enable the flag since N1SDP has a system level cache
+NEOVERSE_Nx_EXTERNAL_LLC := 1
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
new file mode 100644
index 0000000..69fb0d4
--- /dev/null
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts
new file mode 100644
index 0000000..0af821e
--- /dev/null
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,rd-e1edge";
+
+ /*
+ * Place holder for system-id node with default values. The
+ * value of platform-id and config-id will be set to the
+ * correct values during the BL2 stage of boot.
+ */
+ system-id {
+ platform-id = <0x0>;
+ config-id = <0x0>;
+ multi-chip-mode = <0x0>;
+ };
+
+};
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
new file mode 100644
index 0000000..dba91e5
--- /dev/null
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rde1edge/include/platform_def.h b/plat/arm/board/rde1edge/include/platform_def.h
new file mode 100644
index 0000000..69bfd7b
--- /dev/null
+++ b/plat/arm/board/rde1edge/include/platform_def.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#include <sgi_sdei.h>
+#include <sgi_soc_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT U(2)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(8)
+#define CSS_SGI_MAX_PE_PER_CPU U(2)
+
+#define PLAT_CSS_MHU_BASE UL(0x45400000)
+
+/* Base address of DMC-620 instances */
+#define RDE1EDGE_DMC620_BASE0 UL(0x4e000000)
+#define RDE1EDGE_DMC620_BASE1 UL(0x4e100000)
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2
+
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3
+
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP U(36)
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE UL(0x300C0000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
new file mode 100644
index 0000000..0f9dd49
--- /dev/null
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDE1EDGE_BASE = plat/arm/board/rde1edge
+
+PLAT_INCLUDES += -I${RDE1EDGE_BASE}/include/
+
+SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_e1.S
+
+PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c
+
+BL1_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDE1EDGE_BASE}/rde1edge_err.c
+
+BL2_SOURCES += ${RDE1EDGE_BASE}/rde1edge_plat.c \
+ ${RDE1EDGE_BASE}/rde1edge_security.c \
+ ${RDE1EDGE_BASE}/rde1edge_err.c \
+ drivers/arm/tzc/tzc_dmc620.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDE1EDGE_BASE}/rde1edge_plat.c \
+ ${RDE1EDGE_BASE}/rde1edge_topology.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${RDE1EDGE_BASE}/rde1edge_trusted_boot.c
+BL2_SOURCES += ${RDE1EDGE_BASE}/rde1edge_trusted_boot.c
+endif
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+FDT_SOURCES += ${RDE1EDGE_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+ifneq ($(CSS_SGI_CHIP_COUNT),1)
+ $(error "Chip count for RDE1Edge should be 1, currently set to \
+ ${CSS_SGI_CHIP_COUNT}.")
+endif
+
+ifneq ($(CSS_SGI_PLATFORM_VARIANT),0)
+ $(error "CSS_SGI_PLATFORM_VARIANT for RD-E1-Edge should always be 0, \
+ currently set to ${CSS_SGI_PLATFORM_VARIANT}.")
+endif
+
+override CTX_INCLUDE_AARCH32_REGS := 0
diff --git a/plat/arm/board/rde1edge/rde1edge_err.c b/plat/arm/board/rde1edge/rde1edge_err.c
new file mode 100644
index 0000000..c72c18c
--- /dev/null
+++ b/plat/arm/board/rde1edge/rde1edge_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rde1edge error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/rde1edge/rde1edge_plat.c b/plat/arm/board/rde1edge/rde1edge_plat.c
new file mode 100644
index 0000000..44d818a
--- /dev/null
+++ b/plat/arm/board/rde1edge/rde1edge_plat.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+#include <sgi_plat.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+ & SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+ return 0;
+}
+
+void bl31_platform_setup(void)
+{
+ sgi_bl31_common_platform_setup();
+}
diff --git a/plat/arm/board/rde1edge/rde1edge_security.c b/plat/arm/board/rde1edge/rde1edge_security.c
new file mode 100644
index 0000000..35f81d1
--- /dev/null
+++ b/plat/arm/board/rde1edge/rde1edge_security.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <sgi_dmc620_tzc_regions.h>
+
+uintptr_t rde1edge_dmc_base[] = {
+ RDE1EDGE_DMC620_BASE0,
+ RDE1EDGE_DMC620_BASE1
+};
+
+static const tzc_dmc620_driver_data_t rde1edge_plat_driver_data = {
+ .dmc_base = rde1edge_dmc_base,
+ .dmc_count = ARRAY_SIZE(rde1edge_dmc_base)
+};
+
+static const tzc_dmc620_acc_addr_data_t rde1edge_acc_addr_data[] = {
+ CSS_SGI_DMC620_TZC_REGIONS_DEF
+};
+
+static const tzc_dmc620_config_data_t rde1edge_plat_config_data = {
+ .plat_drv_data = &rde1edge_plat_driver_data,
+ .plat_acc_addr_data = rde1edge_acc_addr_data,
+ .acc_addr_count = ARRAY_SIZE(rde1edge_acc_addr_data)
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+ arm_tzc_dmc620_setup(&rde1edge_plat_config_data);
+}
diff --git a/plat/arm/board/rde1edge/rde1edge_topology.c b/plat/arm/board/rde1edge/rde1edge_topology.c
new file mode 100644
index 0000000..a16283e
--- /dev/null
+++ b/plat/arm/board/rde1edge/rde1edge_topology.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor. RD-E1-Edge platform consists of two
+ * clusters with eight CPUs in each cluster. The CPUs are multi-threaded with
+ * two threads per CPU.
+ ******************************************************************************/
+static const unsigned char rde1edge_pd_tree_desc[] = {
+ CSS_SGI_CHIP_COUNT,
+ PLAT_ARM_CLUSTER_COUNT,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU
+};
+
+/******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rde1edge_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+};
diff --git a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
new file mode 100644
index 0000000..d3b7fba
--- /dev/null
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
+
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts
new file mode 100644
index 0000000..68366c5
--- /dev/null
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,rd-n1edge";
+
+ /*
+ * Place holder for system-id node with default values. The
+ * value of platform-id and config-id will be set to the
+ * correct values during the BL2 stage of boot.
+ */
+ system-id {
+ platform-id = <0x0>;
+ config-id = <0x0>;
+ multi-chip-mode = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
new file mode 100644
index 0000000..257ef4a
--- /dev/null
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdn1edge/include/platform_def.h b/plat/arm/board/rdn1edge/include/platform_def.h
new file mode 100644
index 0000000..de01902
--- /dev/null
+++ b/plat/arm/board/rdn1edge/include/platform_def.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#include <sgi_sdei.h>
+#include <sgi_soc_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT U(2)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4)
+#define CSS_SGI_MAX_PE_PER_CPU U(1)
+
+#define PLAT_CSS_MHU_BASE UL(0x45400000)
+
+/* Base address of DMC-620 instances */
+#define RDN1EDGE_DMC620_BASE0 UL(0x4e000000)
+#define RDN1EDGE_DMC620_BASE1 UL(0x4e100000)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
+/* Virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
+
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP U(42)
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+ CSS_SGI_CHIP_COUNT)
+#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+ CSS_SGI_CHIP_COUNT)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE UL(0x300C0000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
new file mode 100644
index 0000000..95753aa
--- /dev/null
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -0,0 +1,75 @@
+#
+# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+$(warning Platform ${PLAT} is deprecated. Some of the features might not work as expected)
+
+# GIC-600 configuration
+GICV3_IMPL_GIC600_MULTICHIP := 1
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDN1EDGE_BASE = plat/arm/board/rdn1edge
+
+PLAT_INCLUDES += -I${RDN1EDGE_BASE}/include/
+
+SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S
+
+PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c
+
+BL1_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDN1EDGE_BASE}/rdn1edge_err.c
+
+BL2_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_plat.c \
+ ${RDN1EDGE_BASE}/rdn1edge_security.c \
+ ${RDN1EDGE_BASE}/rdn1edge_err.c \
+ drivers/arm/tzc/tzc_dmc620.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDN1EDGE_BASE}/rdn1edge_plat.c \
+ ${RDN1EDGE_BASE}/rdn1edge_topology.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c
+BL2_SOURCES += ${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c
+endif
+
+# Enable dynamic addition of MMAP regions in BL31
+BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+FDT_SOURCES += ${RDN1EDGE_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+$(eval $(call CREATE_SEQ,SEQ,2))
+ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ)))
+ $(error "Chip count for RDN1Edge platform should be one of $(SEQ), currently \
+ set to ${CSS_SGI_CHIP_COUNT}.")
+endif
+
+ifneq ($(CSS_SGI_PLATFORM_VARIANT),0)
+ $(error "CSS_SGI_PLATFORM_VARIANT for RD-N1-Edge should always be 0, \
+ currently set to ${CSS_SGI_PLATFORM_VARIANT}.")
+endif
+
+override CTX_INCLUDE_AARCH32_REGS := 0
diff --git a/plat/arm/board/rdn1edge/rdn1edge_err.c b/plat/arm/board/rdn1edge/rdn1edge_err.c
new file mode 100644
index 0000000..46d318c
--- /dev/null
+++ b/plat/arm/board/rdn1edge/rdn1edge_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rdn1edge error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/rdn1edge/rdn1edge_plat.c b/plat/arm/board/rdn1edge/rdn1edge_plat.c
new file mode 100644
index 0000000..1dbbf26
--- /dev/null
+++ b/plat/arm/board/rdn1edge/rdn1edge_plat.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/gic600_multichip.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <sgi_soc_platform_def.h>
+#include <sgi_plat.h>
+
+#if defined(IMAGE_BL31)
+static const mmap_region_t rdn1edge_dynamic_mmap[] = {
+ ARM_MAP_SHARED_RAM_REMOTE_CHIP(1),
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1),
+ SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1)
+};
+
+static struct gic600_multichip_data rdn1e1_multichip_data __init = {
+ .rt_owner_base = PLAT_ARM_GICD_BASE,
+ .rt_owner = 0,
+ .chip_count = CSS_SGI_CHIP_COUNT,
+ .chip_addrs = {
+ PLAT_ARM_GICD_BASE >> 16,
+ (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
+ },
+ .spi_ids = {
+ {32, 255},
+ {0, 0}
+ }
+};
+
+static uintptr_t rdn1e1_multichip_gicr_frames[] = {
+ PLAT_ARM_GICR_BASE, /* Chip 0's GICR Base */
+ PLAT_ARM_GICR_BASE +
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1), /* Chip 1's GICR BASE */
+ UL(0) /* Zero Termination */
+};
+#endif /* IMAGE_BL31 */
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+ & SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+ return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+ SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+/*
+ * IMAGE_BL31 macro is added to build bl31_platform_setup function only for BL31
+ * because PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not
+ * for other stages.
+ */
+#if defined(IMAGE_BL31)
+void bl31_platform_setup(void)
+{
+ int i, ret;
+
+ if (plat_arm_sgi_get_multi_chip_mode() == 0 && CSS_SGI_CHIP_COUNT > 1) {
+ ERROR("Chip Count is set to %d but multi-chip mode not enabled\n",
+ CSS_SGI_CHIP_COUNT);
+ panic();
+ } else if (plat_arm_sgi_get_multi_chip_mode() == 1 &&
+ CSS_SGI_CHIP_COUNT > 1) {
+ INFO("Enabling support for multi-chip in RD-N1-Edge\n");
+
+ for (i = 0; i < ARRAY_SIZE(rdn1edge_dynamic_mmap); i++) {
+ ret = mmap_add_dynamic_region(
+ rdn1edge_dynamic_mmap[i].base_pa,
+ rdn1edge_dynamic_mmap[i].base_va,
+ rdn1edge_dynamic_mmap[i].size,
+ rdn1edge_dynamic_mmap[i].attr
+ );
+ if (ret != 0) {
+ ERROR("Failed to add dynamic mmap entry\n");
+ panic();
+ }
+ }
+
+ plat_arm_override_gicr_frames(rdn1e1_multichip_gicr_frames);
+ gic600_multichip_init(&rdn1e1_multichip_data);
+ }
+
+ sgi_bl31_common_platform_setup();
+}
+#endif /* IMAGE_BL31 */
diff --git a/plat/arm/board/rdn1edge/rdn1edge_security.c b/plat/arm/board/rdn1edge/rdn1edge_security.c
new file mode 100644
index 0000000..4943532
--- /dev/null
+++ b/plat/arm/board/rdn1edge/rdn1edge_security.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <sgi_dmc620_tzc_regions.h>
+
+uintptr_t rdn1edge_dmc_base[] = {
+ RDN1EDGE_DMC620_BASE0,
+ RDN1EDGE_DMC620_BASE1
+};
+
+static const tzc_dmc620_driver_data_t rdn1edge_plat_driver_data = {
+ .dmc_base = rdn1edge_dmc_base,
+ .dmc_count = ARRAY_SIZE(rdn1edge_dmc_base)
+};
+
+static const tzc_dmc620_acc_addr_data_t rdn1edge_acc_addr_data[] = {
+ CSS_SGI_DMC620_TZC_REGIONS_DEF
+};
+
+static const tzc_dmc620_config_data_t rdn1edge_plat_config_data = {
+ .plat_drv_data = &rdn1edge_plat_driver_data,
+ .plat_acc_addr_data = rdn1edge_acc_addr_data,
+ .acc_addr_count = ARRAY_SIZE(rdn1edge_acc_addr_data)
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+ arm_tzc_dmc620_setup(&rdn1edge_plat_config_data);
+}
diff --git a/plat/arm/board/rdn1edge/rdn1edge_topology.c b/plat/arm/board/rdn1edge/rdn1edge_topology.c
new file mode 100644
index 0000000..5bbea69
--- /dev/null
+++ b/plat/arm/board/rdn1edge/rdn1edge_topology.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+static const unsigned char rdn1edge_pd_tree_desc[] = {
+ (PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT),
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#if (CSS_SGI_CHIP_COUNT > 1)
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER
+#endif
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rdn1edge_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+#if (CSS_SGI_CHIP_COUNT > 1)
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x4)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x5)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x6)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x7)),
+#endif
+};
diff --git a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts
new file mode 100644
index 0000000..9c9cefe
--- /dev/null
+++ b/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts
new file mode 100644
index 0000000..dd70141
--- /dev/null
+++ b/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2020 - 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,rd-n2";
+
+ /*
+ * Place holder for system-id node with default values. The
+ * value of platform-id and config-id will be set to the
+ * correct values during the BL2 stage of boot.
+ */
+ system-id {
+ platform-id = <0x0>;
+ config-id = <0x0>;
+ multi-chip-mode = <0x0>;
+ /*
+ * First cell pair: Count of isolated CPUs in the list.
+ * Rest of the cells: MPID list of the isolated CPUs.
+ */
+ isolated-cpu-list = <0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0
+ 0x0 0x0>;
+ };
+};
diff --git a/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
new file mode 100644
index 0000000..3474016
--- /dev/null
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#include <sgi_soc_platform_def_v2.h>
+
+#if (CSS_SGI_PLATFORM_VARIANT == 1)
+#define PLAT_ARM_CLUSTER_COUNT U(8)
+#elif (CSS_SGI_PLATFORM_VARIANT == 2)
+#define PLAT_ARM_CLUSTER_COUNT U(4)
+#else
+#define PLAT_ARM_CLUSTER_COUNT U(16)
+#endif
+
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1)
+#define CSS_SGI_MAX_PE_PER_CPU U(1)
+
+#define PLAT_CSS_MHU_BASE UL(0x2A920000)
+#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE
+
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE UL(0x10720000)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC400_OFFSET UL(0x1000000)
+
+#if (CSS_SGI_PLATFORM_VARIANT == 1)
+#define TZC400_COUNT U(2)
+#elif (CSS_SGI_PLATFORM_VARIANT == 2)
+#define TZC400_COUNT U(4)
+#else
+#define TZC400_COUNT U(8)
+#endif
+
+#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \
+ (n * TZC400_OFFSET))
+
+#define TZC_NSAID_ALL_AP U(0)
+#define TZC_NSAID_PCI U(1)
+#define TZC_NSAID_HDLCD0 U(2)
+#define TZC_NSAID_DMA U(5)
+#define TZC_NSAID_DMA2 U(8)
+#define TZC_NSAID_CLCD U(7)
+#define TZC_NSAID_AP U(9)
+#define TZC_NSAID_VIRTIO U(15)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA2)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#if (CSS_SGI_PLATFORM_VARIANT == 2)
+#define CSS_SGI_ADDR_BITS_PER_CHIP U(46) /* 64TB */
+#else
+#define CSS_SGI_ADDR_BITS_PER_CHIP U(42) /* 4TB */
+#endif
+
+#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+ CSS_SGI_CHIP_COUNT)
+#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+ CSS_SGI_CHIP_COUNT)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+
+/* Virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xC0000000)
+
+#if (CSS_SGI_PLATFORM_VARIANT == 1)
+#define PLAT_ARM_GICR_BASE UL(0x30100000)
+#else
+#define PLAT_ARM_GICR_BASE UL(0x301C0000)
+#endif
+
+/* Interrupt priority level for shutdown/reboot */
+#define PLAT_REBOOT_PRI GIC_HIGHEST_SEC_PRIORITY
+#define PLAT_EHF_DESC EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_REBOOT_PRI)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
new file mode 100644
index 0000000..7492fe5
--- /dev/null
+++ b/plat/arm/board/rdn2/platform.mk
@@ -0,0 +1,90 @@
+# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+RD_N2_VARIANTS := 0 1 2
+ifneq ($(CSS_SGI_PLATFORM_VARIANT),\
+ $(filter $(CSS_SGI_PLATFORM_VARIANT),$(RD_N2_VARIANTS)))
+ $(error "CSS_SGI_PLATFORM_VARIANT for RD-N2 should be 0, 1 or 2, currently set \
+ to ${CSS_SGI_PLATFORM_VARIANT}.")
+endif
+
+$(eval $(call CREATE_SEQ,SEQ,4))
+ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ)))
+ $(error "Chip count for RD-N2-MC should be either $(SEQ) \
+ currently it is set to ${CSS_SGI_CHIP_COUNT}.")
+endif
+
+# RD-N2 platform uses GIC-700 which is based on GICv4.1
+GIC_ENABLE_V4_EXTN := 1
+GIC_EXT_INTID := 1
+
+#Enable GIC Multichip Extension only for Multichip Platforms
+ifeq (${CSS_SGI_PLATFORM_VARIANT}, 2)
+GICV3_IMPL_GIC600_MULTICHIP := 1
+endif
+
+override CSS_SYSTEM_GRACEFUL_RESET := 1
+override EL3_EXCEPTION_HANDLING := 1
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDN2_BASE = plat/arm/board/rdn2
+
+PLAT_INCLUDES += -I${RDN2_BASE}/include/
+
+SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_n2.S \
+ lib/cpus/aarch64/neoverse_v2.S
+
+PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat_v2.c
+
+BL1_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDN2_BASE}/rdn2_err.c
+
+BL2_SOURCES += ${RDN2_BASE}/rdn2_plat.c \
+ ${RDN2_BASE}/rdn2_security.c \
+ ${RDN2_BASE}/rdn2_err.c \
+ lib/utils/mem_region.c \
+ drivers/arm/tzc/tzc400.c \
+ plat/arm/common/arm_tzc400.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDN2_BASE}/rdn2_plat.c \
+ ${RDN2_BASE}/rdn2_topology.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c
+BL2_SOURCES += ${RDN2_BASE}/rdn2_trusted_boot.c
+endif
+
+ifeq (${CSS_SGI_PLATFORM_VARIANT}, 2)
+BL31_SOURCES += drivers/arm/gic/v3/gic600_multichip.c
+
+# Enable dynamic addition of MMAP regions in BL31
+BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+endif
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDN2_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+FDT_SOURCES += ${RDN2_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
+
+override CTX_INCLUDE_AARCH32_REGS := 0
+override ENABLE_AMU := 1
diff --git a/plat/arm/board/rdn2/rdn2_err.c b/plat/arm/board/rdn2/rdn2_err.c
new file mode 100644
index 0000000..802ac21
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rdn2 error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (1) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/rdn2/rdn2_plat.c b/plat/arm/board/rdn2/rdn2_plat.c
new file mode 100644
index 0000000..2506f9d
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_plat.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/gic600_multichip.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <sgi_soc_platform_def_v2.h>
+#include <sgi_plat.h>
+
+#if defined(IMAGE_BL31)
+#if (CSS_SGI_PLATFORM_VARIANT == 2)
+static const mmap_region_t rdn2mc_dynamic_mmap[] = {
+#if CSS_SGI_CHIP_COUNT > 1
+ ARM_MAP_SHARED_RAM_REMOTE_CHIP(1),
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1),
+#endif
+#if CSS_SGI_CHIP_COUNT > 2
+ ARM_MAP_SHARED_RAM_REMOTE_CHIP(2),
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2),
+#endif
+#if CSS_SGI_CHIP_COUNT > 3
+ ARM_MAP_SHARED_RAM_REMOTE_CHIP(3),
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3),
+#endif
+};
+#endif
+
+#if (CSS_SGI_PLATFORM_VARIANT == 2)
+static struct gic600_multichip_data rdn2mc_multichip_data __init = {
+ .rt_owner_base = PLAT_ARM_GICD_BASE,
+ .rt_owner = 0,
+ .chip_count = CSS_SGI_CHIP_COUNT,
+ .chip_addrs = {
+ PLAT_ARM_GICD_BASE >> 16,
+#if CSS_SGI_CHIP_COUNT > 1
+ (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+#endif
+#if CSS_SGI_CHIP_COUNT > 2
+ (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+#endif
+#if CSS_SGI_CHIP_COUNT > 3
+ (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+#endif
+ },
+ .spi_ids = {
+ {32, 511},
+ #if CSS_SGI_CHIP_COUNT > 1
+ {512, 991},
+ #endif
+ #if CSS_SGI_CHIP_COUNT > 2
+ {4096, 4575},
+ #endif
+ #if CSS_SGI_CHIP_COUNT > 3
+ {4576, 5055},
+ #endif
+ }
+};
+#endif
+
+#if (CSS_SGI_PLATFORM_VARIANT == 2)
+static uintptr_t rdn2mc_multichip_gicr_frames[] = {
+ /* Chip 0's GICR Base */
+ PLAT_ARM_GICR_BASE,
+#if CSS_SGI_CHIP_COUNT > 1
+ /* Chip 1's GICR BASE */
+ PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1),
+#endif
+#if CSS_SGI_CHIP_COUNT > 2
+ /* Chip 2's GICR BASE */
+ PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2),
+#endif
+#if CSS_SGI_CHIP_COUNT > 3
+ /* Chip 3's GICR BASE */
+ PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3),
+#endif
+ UL(0) /* Zero Termination */
+};
+#endif
+#endif /* IMAGE_BL31 */
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+ & SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+ return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+ SID_MULTI_CHIP_MODE_MASK) >>
+ SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+#if defined(IMAGE_BL31)
+void bl31_platform_setup(void)
+{
+#if (CSS_SGI_PLATFORM_VARIANT == 2)
+ int ret;
+ unsigned int i;
+
+ if (plat_arm_sgi_get_multi_chip_mode() == 0) {
+ ERROR("Chip Count is set to %u but multi-chip mode is not "
+ "enabled\n", CSS_SGI_CHIP_COUNT);
+ panic();
+ } else {
+ INFO("Enabling multi-chip support for RD-N2 variant\n");
+
+ for (i = 0; i < ARRAY_SIZE(rdn2mc_dynamic_mmap); i++) {
+ ret = mmap_add_dynamic_region(
+ rdn2mc_dynamic_mmap[i].base_pa,
+ rdn2mc_dynamic_mmap[i].base_va,
+ rdn2mc_dynamic_mmap[i].size,
+ rdn2mc_dynamic_mmap[i].attr);
+ if (ret != 0) {
+ ERROR("Failed to add dynamic mmap entry for"
+ " i: %d " "(ret=%d)\n", i, ret);
+ panic();
+ }
+ }
+
+ plat_arm_override_gicr_frames(
+ rdn2mc_multichip_gicr_frames);
+ gic600_multichip_init(&rdn2mc_multichip_data);
+ }
+#endif
+
+ sgi_bl31_common_platform_setup();
+}
+#endif /* IMAGE_BL31 */
diff --git a/plat/arm/board/rdn2/rdn2_security.c b/plat/arm/board/rdn2/rdn2_security.c
new file mode 100644
index 0000000..dff6a19
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_security.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+static const arm_tzc_regions_info_t tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+ {}
+};
+
+#if (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1)
+static const arm_tzc_regions_info_t tzc_regions_mc[][CSS_SGI_CHIP_COUNT - 1] = {
+ {
+ /* TZC memory regions for second chip */
+ SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(1),
+ {}
+ },
+#if CSS_SGI_CHIP_COUNT > 2
+ {
+ /* TZC memory regions for third chip */
+ SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(2),
+ {}
+ },
+#endif
+#if CSS_SGI_CHIP_COUNT > 3
+ {
+ /* TZC memory regions for fourth chip */
+ SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(3),
+ {}
+ },
+#endif
+};
+#endif /* CSS_SGI_PLATFORM_VARIANT && CSS_SGI_CHIP_COUNT */
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+ unsigned int i;
+
+ INFO("Configuring TrustZone Controller for Chip 0\n");
+
+ for (i = 0; i < TZC400_COUNT; i++) {
+ arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
+ }
+
+#if (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1)
+ unsigned int j;
+
+ for (i = 1; i < CSS_SGI_CHIP_COUNT; i++) {
+ INFO("Configuring TrustZone Controller for Chip %u\n", i);
+
+ for (j = 0; j < TZC400_COUNT; j++) {
+ arm_tzc400_setup(CSS_SGI_REMOTE_CHIP_MEM_OFFSET(i)
+ + TZC400_BASE(j), tzc_regions_mc[i-1]);
+ }
+ }
+#endif
+}
diff --git a/plat/arm/board/rdn2/rdn2_topology.c b/plat/arm/board/rdn2/rdn2_topology.c
new file mode 100644
index 0000000..89300f8
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_topology.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+const unsigned char rd_n2_pd_tree_desc[] = {
+ (PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT),
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#if (CSS_SGI_PLATFORM_VARIANT != 2 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 1))
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#endif
+#if (CSS_SGI_PLATFORM_VARIANT == 0 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 2))
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#endif
+#if (CSS_SGI_PLATFORM_VARIANT == 0 || (CSS_SGI_PLATFORM_VARIANT == 2 && CSS_SGI_CHIP_COUNT > 3))
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#endif
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rd_n2_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+#if (CSS_SGI_PLATFORM_VARIANT == 2)
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+#if (CSS_SGI_CHIP_COUNT > 1)
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 2)
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x3)),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x3)),
+#endif
+};
+#else
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+#if (CSS_SGI_PLATFORM_VARIANT == 0)
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF)),
+#endif
+};
+#endif
diff --git a/plat/arm/board/rdn2/rdn2_trusted_boot.c b/plat/arm/board/rdn2/rdn2_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rdn2/rdn2_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts
new file mode 100644
index 0000000..9c9cefe
--- /dev/null
+++ b/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts
new file mode 100644
index 0000000..62ba2c3
--- /dev/null
+++ b/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,rd-v1";
+
+ /*
+ * Place holder for system-id node with default values. The
+ * value of platform-id and config-id will be set to the
+ * correct values during the BL2 stage of boot.
+ */
+ system-id {
+ platform-id = <0x0>;
+ config-id = <0x0>;
+ multi-chip-mode = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts b/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdv1/include/platform_def.h b/plat/arm/board/rdv1/include/platform_def.h
new file mode 100644
index 0000000..620fa3e
--- /dev/null
+++ b/plat/arm/board/rdv1/include/platform_def.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#include <sgi_soc_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT U(16)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1)
+#define CSS_SGI_MAX_PE_PER_CPU U(1)
+
+#define PLAT_CSS_MHU_BASE UL(0x45400000)
+#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE
+
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE UL(0x21830000)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC400_OFFSET UL(0x1000000)
+#define TZC400_COUNT 4
+
+#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \
+ (n * TZC400_OFFSET))
+
+#define TZC_NSAID_ALL_AP U(0)
+#define TZC_NSAID_PCI U(1)
+#define TZC_NSAID_HDLCD0 U(2)
+#define TZC_NSAID_CLCD U(7)
+#define TZC_NSAID_AP U(9)
+#define TZC_NSAID_VIRTIO U(15)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
+
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP U(42)
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE UL(0x30140000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk
new file mode 100644
index 0000000..11f5212
--- /dev/null
+++ b/plat/arm/board/rdv1/platform.mk
@@ -0,0 +1,65 @@
+# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# RD-V1 platform uses GIC-700 which is based on GICv4.1
+GIC_ENABLE_V4_EXTN := 1
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDV1_BASE = plat/arm/board/rdv1
+
+PLAT_INCLUDES += -I${RDV1_BASE}/include/
+
+SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S
+
+PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c
+
+BL1_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDV1_BASE}/rdv1_err.c
+
+BL2_SOURCES += ${RDV1_BASE}/rdv1_plat.c \
+ ${RDV1_BASE}/rdv1_security.c \
+ ${RDV1_BASE}/rdv1_err.c \
+ lib/utils/mem_region.c \
+ drivers/arm/tzc/tzc400.c \
+ plat/arm/common/arm_tzc400.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDV1_BASE}/rdv1_plat.c \
+ ${RDV1_BASE}/rdv1_topology.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c
+BL2_SOURCES += ${RDV1_BASE}/rdv1_trusted_boot.c
+endif
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDV1_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+FDT_SOURCES += ${RDV1_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+override CTX_INCLUDE_AARCH32_REGS := 0
+override ENABLE_AMU := 1
+
+ifneq ($(CSS_SGI_PLATFORM_VARIANT),0)
+ $(error "CSS_SGI_PLATFORM_VARIANT for RD-V1 should always be 0, \
+ currently set to ${CSS_SGI_PLATFORM_VARIANT}.")
+endif
diff --git a/plat/arm/board/rdv1/rdv1_err.c b/plat/arm/board/rdv1/rdv1_err.c
new file mode 100644
index 0000000..68f9a3e
--- /dev/null
+++ b/plat/arm/board/rdv1/rdv1_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rdv1 error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (1) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/rdv1/rdv1_plat.c b/plat/arm/board/rdv1/rdv1_plat.c
new file mode 100644
index 0000000..ab5251e
--- /dev/null
+++ b/plat/arm/board/rdv1/rdv1_plat.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+#include <sgi_plat.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+ & SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+ return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+ SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+void bl31_platform_setup(void)
+{
+ sgi_bl31_common_platform_setup();
+}
diff --git a/plat/arm/board/rdv1/rdv1_security.c b/plat/arm/board/rdv1/rdv1_security.c
new file mode 100644
index 0000000..1247db8
--- /dev/null
+++ b/plat/arm/board/rdv1/rdv1_security.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+static const arm_tzc_regions_info_t tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+ {}
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+ int i;
+
+ for (i = 0; i < TZC400_COUNT; i++)
+ arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
+}
diff --git a/plat/arm/board/rdv1/rdv1_topology.c b/plat/arm/board/rdv1/rdv1_topology.c
new file mode 100644
index 0000000..ab64fd8
--- /dev/null
+++ b/plat/arm/board/rdv1/rdv1_topology.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+const unsigned char rd_v1_pd_tree_desc[] = {
+ PLAT_ARM_CLUSTER_COUNT,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rd_v1_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF))
+};
diff --git a/plat/arm/board/rdv1/rdv1_trusted_boot.c b/plat/arm/board/rdv1/rdv1_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rdv1/rdv1_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts
new file mode 100644
index 0000000..9c9cefe
--- /dev/null
+++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts
new file mode 100644
index 0000000..71c7db3
--- /dev/null
+++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,rd-v1-mc";
+
+ /*
+ * Place holder for system-id node with default values. The
+ * value of platform-id and config-id will be set to the
+ * correct values during the BL2 stage of boot.
+ */
+ system-id {
+ platform-id = <0x0>;
+ config-id = <0x0>;
+ multi-chip-mode = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts b/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/rdv1mc/include/platform_def.h b/plat/arm/board/rdv1mc/include/platform_def.h
new file mode 100644
index 0000000..3670904
--- /dev/null
+++ b/plat/arm/board/rdv1mc/include/platform_def.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <sgi_soc_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT U(4)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(1)
+#define CSS_SGI_MAX_PE_PER_CPU U(1)
+
+#define PLAT_CSS_MHU_BASE UL(0x45400000)
+#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE
+
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE UL(0x21830000)
+#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \
+ (n * TZC400_OFFSET))
+#define TZC400_OFFSET UL(0x1000000)
+#define TZC400_COUNT U(8)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC_NSAID_ALL_AP U(0)
+#define TZC_NSAID_PCI U(1)
+#define TZC_NSAID_HDLCD0 U(2)
+#define TZC_NSAID_CLCD U(7)
+#define TZC_NSAID_AP U(9)
+#define TZC_NSAID_VIRTIO U(15)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD)) | \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
+
+/* Virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xC0000000)
+
+/* Remote chip address offset (4TB per chip) */
+#define CSS_SGI_ADDR_BITS_PER_CHIP U(42)
+
+/* Physical and virtual address space limits for MMU in AARCH64 mode */
+#define PLAT_PHY_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+ CSS_SGI_CHIP_COUNT)
+#define PLAT_VIRT_ADDR_SPACE_SIZE CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+ CSS_SGI_CHIP_COUNT)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE UL(0x30140000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdv1mc/platform.mk b/plat/arm/board/rdv1mc/platform.mk
new file mode 100644
index 0000000..df0b09a
--- /dev/null
+++ b/plat/arm/board/rdv1mc/platform.mk
@@ -0,0 +1,76 @@
+# Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Enable GICv4 extension with multichip driver
+GIC_ENABLE_V4_EXTN := 1
+GICV3_IMPL_GIC600_MULTICHIP := 1
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDV1MC_BASE = plat/arm/board/rdv1mc
+
+PLAT_INCLUDES += -I${RDV1MC_BASE}/include/
+
+SGI_CPU_SOURCES := lib/cpus/aarch64/neoverse_v1.S
+
+PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c
+
+BL1_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDV1MC_BASE}/rdv1mc_err.c
+
+BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_plat.c \
+ ${RDV1MC_BASE}/rdv1mc_security.c \
+ ${RDV1MC_BASE}/rdv1mc_err.c \
+ drivers/arm/tzc/tzc400.c \
+ plat/arm/common/arm_tzc400.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${RDV1MC_BASE}/rdv1mc_plat.c \
+ ${RDV1MC_BASE}/rdv1mc_topology.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ drivers/arm/gic/v3/gic600_multichip.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c
+BL2_SOURCES += ${RDV1MC_BASE}/rdv1mc_trusted_boot.c
+endif
+
+# Enable dynamic addition of MMAP regions in BL31
+BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDV1MC_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+$(eval $(call CREATE_SEQ,SEQ,4))
+ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ)))
+ $(error "Chip count for RD-V1-MC should be either $(SEQ) \
+ currently it is set to ${CSS_SGI_CHIP_COUNT}.")
+endif
+
+FDT_SOURCES += ${RDV1MC_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+override CTX_INCLUDE_AARCH32_REGS := 0
+override ENABLE_AMU := 1
+
+ifneq ($(CSS_SGI_PLATFORM_VARIANT),0)
+ $(error "CSS_SGI_PLATFORM_VARIANT for RD-V1-MC should always be 0, \
+ currently set to ${CSS_SGI_PLATFORM_VARIANT}.")
+endif
diff --git a/plat/arm/board/rdv1mc/rdv1mc_err.c b/plat/arm/board/rdv1mc/rdv1mc_err.c
new file mode 100644
index 0000000..755a503
--- /dev/null
+++ b/plat/arm/board/rdv1mc/rdv1mc_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rdv1mc error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/rdv1mc/rdv1mc_plat.c b/plat/arm/board/rdv1mc/rdv1mc_plat.c
new file mode 100644
index 0000000..d859400
--- /dev/null
+++ b/plat/arm/board/rdv1mc/rdv1mc_plat.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/gic600_multichip.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <sgi_soc_platform_def.h>
+#include <sgi_plat.h>
+
+#if defined(IMAGE_BL31)
+static const mmap_region_t rdv1mc_dynamic_mmap[] = {
+ ARM_MAP_SHARED_RAM_REMOTE_CHIP(1),
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1),
+ SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1),
+#if (CSS_SGI_CHIP_COUNT > 2)
+ ARM_MAP_SHARED_RAM_REMOTE_CHIP(2),
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2),
+ SOC_CSS_MAP_DEVICE_REMOTE_CHIP(2),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+ ARM_MAP_SHARED_RAM_REMOTE_CHIP(3),
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3),
+ SOC_CSS_MAP_DEVICE_REMOTE_CHIP(3)
+#endif
+};
+
+static struct gic600_multichip_data rdv1mc_multichip_data __init = {
+ .rt_owner_base = PLAT_ARM_GICD_BASE,
+ .rt_owner = 0,
+ .chip_count = CSS_SGI_CHIP_COUNT,
+ .chip_addrs = {
+ PLAT_ARM_GICD_BASE >> 16,
+ (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+#if (CSS_SGI_CHIP_COUNT > 2)
+ (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+ (PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+#endif
+ },
+ .spi_ids = {
+ {32, 255},
+ {0, 0},
+#if (CSS_SGI_CHIP_COUNT > 2)
+ {0, 0},
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+ {0, 0},
+#endif
+ }
+};
+
+static uintptr_t rdv1mc_multichip_gicr_frames[] = {
+ /* Chip 0's GICR Base */
+ PLAT_ARM_GICR_BASE,
+ /* Chip 1's GICR BASE */
+ PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1),
+#if (CSS_SGI_CHIP_COUNT > 2)
+ /* Chip 2's GICR BASE */
+ PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+ /* Chip 3's GICR BASE */
+ PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3),
+#endif
+ UL(0) /* Zero Termination */
+};
+#endif /* IMAGE_BL31 */
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+ & SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+ return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+ SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+/*
+ * bl31_platform_setup_function is guarded by IMAGE_BL31 macro because
+ * PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not
+ * for other stages.
+ */
+#if defined(IMAGE_BL31)
+void bl31_platform_setup(void)
+{
+ int ret;
+ unsigned int i;
+
+ if ((plat_arm_sgi_get_multi_chip_mode() == 0) &&
+ (CSS_SGI_CHIP_COUNT > 1)) {
+ ERROR("Chip Count is set to %u but multi-chip mode is not "
+ "enabled\n", CSS_SGI_CHIP_COUNT);
+ panic();
+ } else if ((plat_arm_sgi_get_multi_chip_mode() == 1) &&
+ (CSS_SGI_CHIP_COUNT > 1)) {
+ INFO("Enabling support for multi-chip in RD-V1-MC\n");
+
+ for (i = 0; i < ARRAY_SIZE(rdv1mc_dynamic_mmap); i++) {
+ ret = mmap_add_dynamic_region(
+ rdv1mc_dynamic_mmap[i].base_pa,
+ rdv1mc_dynamic_mmap[i].base_va,
+ rdv1mc_dynamic_mmap[i].size,
+ rdv1mc_dynamic_mmap[i].attr);
+ if (ret != 0) {
+ ERROR("Failed to add dynamic mmap entry "
+ "(ret=%d)\n", ret);
+ panic();
+ }
+ }
+
+ plat_arm_override_gicr_frames(
+ rdv1mc_multichip_gicr_frames);
+ gic600_multichip_init(&rdv1mc_multichip_data);
+ }
+
+ sgi_bl31_common_platform_setup();
+}
+#endif /* IMAGE_BL31 */
diff --git a/plat/arm/board/rdv1mc/rdv1mc_security.c b/plat/arm/board/rdv1mc/rdv1mc_security.c
new file mode 100644
index 0000000..adc0bf8
--- /dev/null
+++ b/plat/arm/board/rdv1mc/rdv1mc_security.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/* TZC memory regions for the first chip */
+static const arm_tzc_regions_info_t tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+ {}
+};
+
+#if CSS_SGI_CHIP_COUNT > 1
+static const arm_tzc_regions_info_t tzc_regions_mc[][CSS_SGI_CHIP_COUNT - 1] = {
+ {
+ /* TZC memory regions for second chip */
+ SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(1),
+ {}
+ },
+#if CSS_SGI_CHIP_COUNT > 2
+ {
+ /* TZC memory regions for third chip */
+ SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(2),
+ {}
+ },
+#endif
+#if CSS_SGI_CHIP_COUNT > 3
+ {
+ /* TZC memory regions for fourth chip */
+ SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(3),
+ {}
+ },
+#endif
+};
+#endif /* CSS_SGI_CHIP_COUNT */
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+ unsigned int i;
+
+ INFO("Configuring TrustZone Controller for Chip 0\n");
+
+ for (i = 0; i < TZC400_COUNT; i++) {
+ arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
+ }
+
+#if CSS_SGI_CHIP_COUNT > 1
+ unsigned int j;
+
+ for (i = 1; i < CSS_SGI_CHIP_COUNT; i++) {
+ INFO("Configuring TrustZone Controller for Chip %u\n", i);
+
+ for (j = 0; j < TZC400_COUNT; j++) {
+ arm_tzc400_setup(CSS_SGI_REMOTE_CHIP_MEM_OFFSET(i)
+ + TZC400_BASE(j), tzc_regions_mc[i-1]);
+ }
+ }
+#endif
+}
diff --git a/plat/arm/board/rdv1mc/rdv1mc_topology.c b/plat/arm/board/rdv1mc/rdv1mc_topology.c
new file mode 100644
index 0000000..4486e5c
--- /dev/null
+++ b/plat/arm/board/rdv1mc/rdv1mc_topology.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+#include <sgi_variant.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+const unsigned char rd_v1_mc_pd_tree_desc_multi_chip[] = {
+ ((PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT)),
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#if (CSS_SGI_CHIP_COUNT > 1)
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#endif
+#if (CSS_SGI_CHIP_COUNT > 2)
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER
+#endif
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ if (plat_arm_sgi_get_multi_chip_mode() == 1)
+ return rd_v1_mc_pd_tree_desc_multi_chip;
+ panic();
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+#if (CSS_SGI_CHIP_COUNT > 1)
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 2)
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x3)),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x3))
+#endif
+};
diff --git a/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c b/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
new file mode 100644
index 0000000..84fc1ad
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts
new file mode 100644
index 0000000..260247a
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,sgi575";
+
+ /*
+ * Place holder for system-id node with default values. The
+ * value of platform-id and config-id will be set to the
+ * correct values during the BL2 stage of boot.
+ */
+ system-id {
+ platform-id = <0x0>;
+ config-id = <0x0>;
+ multi-chip-mode = <0x0>;
+ };
+};
diff --git a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
new file mode 100644
index 0000000..82a38c5
--- /dev/null
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#include <sgi_sdei.h>
+#include <sgi_soc_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT U(2)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER U(4)
+#define CSS_SGI_MAX_PE_PER_CPU U(1)
+
+#define PLAT_CSS_MHU_BASE UL(0x45000000)
+
+/* Base address of DMC-620 instances */
+#define SGI575_DMC620_BASE0 UL(0x4e000000)
+#define SGI575_DMC620_BASE1 UL(0x4e100000)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
+/* Maximum number of address bits used per chip */
+#define CSS_SGI_ADDR_BITS_PER_CHIP U(36)
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << CSS_SGI_ADDR_BITS_PER_CHIP)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE UL(0x300C0000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
new file mode 100644
index 0000000..2f2bf73
--- /dev/null
+++ b/plat/arm/board/sgi575/platform.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+$(warning Platform ${PLAT} is deprecated. Some of the features might not work as expected)
+
+include plat/arm/css/sgi/sgi-common.mk
+
+SGI575_BASE = plat/arm/board/sgi575
+
+PLAT_INCLUDES += -I${SGI575_BASE}/include/
+
+SGI_CPU_SOURCES := lib/cpus/aarch64/cortex_a75.S
+
+PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/sgi_plat.c
+
+BL1_SOURCES += ${SGI_CPU_SOURCES} \
+ ${SGI575_BASE}/sgi575_err.c
+
+BL2_SOURCES += ${SGI575_BASE}/sgi575_plat.c \
+ ${SGI575_BASE}/sgi575_security.c \
+ ${SGI575_BASE}/sgi575_err.c \
+ drivers/arm/tzc/tzc_dmc620.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${SGI_CPU_SOURCES} \
+ ${SGI575_BASE}/sgi575_plat.c \
+ ${SGI575_BASE}/sgi575_topology.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES += ${SGI575_BASE}/sgi575_trusted_boot.c
+BL2_SOURCES += ${SGI575_BASE}/sgi575_trusted_boot.c
+endif
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts
+
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+FDT_SOURCES += ${SGI575_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+ifneq ($(CSS_SGI_CHIP_COUNT),1)
+ $(error "Chip count for SGI575 should be 1, currently set to \
+ ${CSS_SGI_CHIP_COUNT}.")
+endif
+
+ifneq ($(CSS_SGI_PLATFORM_VARIANT),0)
+ $(error "CSS_SGI_PLATFORM_VARIANT for SGI575 should always be 0,\
+ currently set to ${CSS_SGI_PLATFORM_VARIANT}.")
+endif
diff --git a/plat/arm/board/sgi575/sgi575_err.c b/plat/arm/board/sgi575/sgi575_err.c
new file mode 100644
index 0000000..21bfcb7
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * sgi575 error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/sgi575/sgi575_plat.c b/plat/arm/board/sgi575/sgi575_plat.c
new file mode 100644
index 0000000..dc294e6
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_plat.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+#include <sgi_plat.h>
+#include <sgi_variant.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+ return mmio_read_32(SSC_VERSION) & SSC_VERSION_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+ return (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT)
+ & SSC_VERSION_CONFIG_MASK;
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+ return 0;
+}
+
+void bl31_platform_setup(void)
+{
+ sgi_bl31_common_platform_setup();
+}
diff --git a/plat/arm/board/sgi575/sgi575_security.c b/plat/arm/board/sgi575/sgi575_security.c
new file mode 100644
index 0000000..17d07d1
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_security.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <sgi_dmc620_tzc_regions.h>
+
+uintptr_t sgi575_dmc_base[] = {
+ SGI575_DMC620_BASE0,
+ SGI575_DMC620_BASE1
+};
+
+static const tzc_dmc620_driver_data_t sgi575_plat_driver_data = {
+ .dmc_base = sgi575_dmc_base,
+ .dmc_count = ARRAY_SIZE(sgi575_dmc_base)
+};
+
+static const tzc_dmc620_acc_addr_data_t sgi575_acc_addr_data[] = {
+ CSS_SGI_DMC620_TZC_REGIONS_DEF
+};
+
+static const tzc_dmc620_config_data_t sgi575_plat_config_data = {
+ .plat_drv_data = &sgi575_plat_driver_data,
+ .plat_acc_addr_data = sgi575_acc_addr_data,
+ .acc_addr_count = ARRAY_SIZE(sgi575_acc_addr_data)
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+ arm_tzc_dmc620_setup(&sgi575_plat_config_data);
+}
diff --git a/plat/arm/board/sgi575/sgi575_topology.c b/plat/arm/board/sgi575/sgi575_topology.c
new file mode 100644
index 0000000..f7c3856
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_topology.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+static const unsigned char sgi575_pd_tree_desc[] = {
+ PLAT_ARM_CLUSTER_COUNT,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER,
+ CSS_SGI_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return sgi575_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7
+};
diff --git a/plat/arm/board/sgi575/sgi575_trusted_boot.c b/plat/arm/board/sgi575/sgi575_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/tc/fdts/tc_fw_config.dts b/plat/arm/board/tc/fdts/tc_fw_config.dts
new file mode 100644
index 0000000..a84c7f8
--- /dev/null
+++ b/plat/arm/board/tc/fdts/tc_fw_config.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x400>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+
+ tos_fw-config {
+ load-address = <0x0 0x04001700>;
+ max-size = <0x1000>;
+ id = <TOS_FW_CONFIG_ID>;
+ };
+
+ hw-config {
+ load-address = <0x0 0x83000000>;
+ max-size = <0x8000>;
+ id = <HW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/tc/fdts/tc_spmc_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
new file mode 100644
index 0000000..d3a5e1a
--- /dev/null
+++ b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x1>;
+ exec_state = <0x0>;
+ load_address = <0x0 0xfd000000>;
+ entrypoint = <0x0 0xfd000000>;
+ binary_size = <0x80000>;
+ };
+
+ hypervisor {
+ compatible = "hafnium,hafnium";
+ vm1 {
+ is_ffa_partition;
+ debug_name = "cactus-primary";
+ load_address = <0xfe000000>;
+ vcpu_count = <8>;
+ mem_size = <1048576>;
+ };
+ vm2 {
+ is_ffa_partition;
+ debug_name = "cactus-secondary";
+ load_address = <0xfe100000>;
+ vcpu_count = <8>;
+ mem_size = <1048576>;
+ };
+ vm3 {
+ is_ffa_partition;
+ debug_name = "cactus-tertiary";
+ load_address = <0xfe200000>;
+ vcpu_count = <1>;
+ mem_size = <1048576>;
+ };
+ vm4 {
+ is_ffa_partition;
+ debug_name = "ivy";
+ load_address = <0xfe600000>;
+ vcpu_count = <1>;
+ mem_size = <1048576>;
+ };
+ };
+
+ cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
+ CPU0:cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ };
+
+ /*
+ * SPMC (Hafnium) requires secondary cpu nodes are declared in
+ * descending order
+ */
+ CPU7:cpu@700 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x700>;
+ enable-method = "psci";
+ };
+
+ CPU6:cpu@600 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x600>;
+ enable-method = "psci";
+ };
+
+ CPU5:cpu@500 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x500>;
+ enable-method = "psci";
+ };
+
+ CPU4:cpu@400 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x400>;
+ enable-method = "psci";
+ };
+
+ CPU3:cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ };
+
+ CPU2:cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ };
+
+ CPU1:cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ };
+ };
+
+ /* 32MB of TC_TZC_DRAM1_BASE */
+ memory@fd000000 {
+ device_type = "memory";
+ reg = <0x0 0xfd000000 0x2000000>;
+ };
+};
diff --git a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
new file mode 100644
index 0000000..92e2ddd
--- /dev/null
+++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x1>;
+ exec_state = <0x0>;
+ load_address = <0x0 0xfd000000>;
+ entrypoint = <0x0 0xfd000000>;
+ binary_size = <0x80000>;
+ };
+
+ hypervisor {
+ compatible = "hafnium,hafnium";
+ vm1 {
+ is_ffa_partition;
+ debug_name = "op-tee";
+ load_address = <0xfd280000>;
+ vcpu_count = <8>;
+#ifdef TS_SP_FW_CONFIG
+ mem_size = <26738688>; /* 25MB TZC DRAM */
+#else
+ mem_size = <30928896>; /* 29MB TZC DRAM */
+#endif
+ };
+#ifdef TS_SP_FW_CONFIG
+ vm2 {
+ is_ffa_partition;
+ debug_name = "internal-trusted-storage";
+ load_address = <0xfee00000>;
+ vcpu_count = <1>;
+ mem_size = <2097152>; /* 2MB TZC DRAM */
+ };
+ vm3 {
+ is_ffa_partition;
+ debug_name = "crypto";
+ load_address = <0xfec00000>;
+ vcpu_count = <1>;
+ mem_size = <2097152>; /* 2MB TZC DRAM */
+ };
+#endif
+ };
+
+ cpus {
+ #address-cells = <0x2>;
+ #size-cells = <0x0>;
+
+ CPU0:cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ };
+
+ /*
+ * SPMC (Hafnium) requires secondary cpu nodes are declared in
+ * descending order
+ */
+ CPU7:cpu@700 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x700>;
+ enable-method = "psci";
+ };
+
+ CPU6:cpu@600 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x600>;
+ enable-method = "psci";
+ };
+
+ CPU5:cpu@500 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x500>;
+ enable-method = "psci";
+ };
+
+ CPU4:cpu@400 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x400>;
+ enable-method = "psci";
+ };
+
+ CPU3:cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ };
+
+ CPU2:cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ };
+
+ CPU1:cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ };
+ };
+
+ /* 32MB of TC_TZC_DRAM1_BASE */
+ memory@fd000000 {
+ device_type = "memory";
+ reg = <0x0 0xfd000000 0x2000000>;
+ };
+};
diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
new file mode 100644
index 0000000..4c6ccef
--- /dev/null
+++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/libc/cdefs.h>
+
+/dts-v1/;
+
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+
+ secure-partitions {
+ compatible = "arm,sp";
+#ifdef ARM_BL2_SP_LIST_DTS
+ #include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
+#ifdef TS_SP_FW_CONFIG
+ internal-trusted-storage {
+ uuid = "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14";
+ load-address = <0xfee00000>;
+ };
+ crypto {
+ uuid = "d9df52d5-16a2-4bb2-9aa4-d26d3b84e8c0";
+ load-address = <0xfec00000>;
+ };
+#endif
+#if OPTEE_SP_FW_CONFIG
+ op-tee {
+ uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b";
+ load-address = <0xfd280000>;
+ };
+#else
+ cactus-primary {
+ uuid = "b4b5671e-4a90-4fe1-b81f-fb13dae1dacb";
+ load-address = <0xfe000000>;
+ owner = "SiP";
+ };
+
+ cactus-secondary {
+ uuid = "d1582309-f023-47b9-827c-4464f5578fc8";
+ load-address = <0xfe100000>;
+ owner = "Plat";
+ };
+
+ cactus-tertiary {
+ uuid = "79b55c73-1d8c-44b9-8593-61e1770ad8d2";
+ load-address = <0xfe200000>;
+ };
+
+ ivy {
+ uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7";
+ load-address = <0xfe600000>;
+ owner = "Plat";
+ };
+#endif
+#endif /* ARM_BL2_SP_LIST_DTS */
+ };
+};
diff --git a/plat/arm/board/tc/include/plat_macros.S b/plat/arm/board/tc/include/plat_macros.S
new file mode 100644
index 0000000..6006fa5
--- /dev/null
+++ b/plat/arm/board/tc/include/plat_macros.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
new file mode 100644
index 0000000..bc4f254
--- /dev/null
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/board/common/board_css_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/arm/css/common/css_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_CORE_COUNT 8
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */
+
+/*
+ * The top 16MB of ARM_DRAM1 is configured as secure access only using the TZC,
+ * its base is ARM_AP_TZC_DRAM1_BASE.
+ *
+ * Reserve 32MB below ARM_AP_TZC_DRAM1_BASE for:
+ * - BL32_BASE when SPD_spmd is enabled
+ * - Region to load Trusted OS
+ */
+#define TC_TZC_DRAM1_BASE (ARM_AP_TZC_DRAM1_BASE - \
+ TC_TZC_DRAM1_SIZE)
+#define TC_TZC_DRAM1_SIZE UL(0x02000000) /* 32 MB */
+#define TC_TZC_DRAM1_END (TC_TZC_DRAM1_BASE + \
+ TC_TZC_DRAM1_SIZE - 1)
+
+#define TC_NS_DRAM1_BASE ARM_DRAM1_BASE
+#define TC_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \
+ ARM_TZC_DRAM1_SIZE - \
+ TC_TZC_DRAM1_SIZE)
+#define TC_NS_DRAM1_END (TC_NS_DRAM1_BASE + \
+ TC_NS_DRAM1_SIZE - 1)
+
+/*
+ * Mappings for TC DRAM1 (non-secure) and TC TZC DRAM1 (secure)
+ */
+#define TC_MAP_NS_DRAM1 MAP_REGION_FLAT( \
+ TC_NS_DRAM1_BASE, \
+ TC_NS_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+
+#define TC_MAP_TZC_DRAM1 MAP_REGION_FLAT( \
+ TC_TZC_DRAM1_BASE, \
+ TC_TZC_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define PLAT_HW_CONFIG_DTB_BASE ULL(0x83000000)
+#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000)
+
+#define PLAT_DTB_DRAM_NS MAP_REGION_FLAT( \
+ PLAT_HW_CONFIG_DTB_BASE, \
+ PLAT_HW_CONFIG_DTB_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
+/*
+ * Max size of SPMC is 2MB for tc. With SPMD enabled this value corresponds to
+ * max size of BL32 image.
+ */
+#if defined(SPD_spmd)
+#define PLAT_ARM_SPMC_BASE TC_TZC_DRAM1_BASE
+#define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */
+#endif
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if defined(IMAGE_BL31)
+# if SPM_MM
+# define PLAT_ARM_MMAP_ENTRIES 9
+# define MAX_XLAT_TABLES 7
+# define PLAT_SP_IMAGE_MMAP_REGIONS 7
+# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10
+# else
+# define PLAT_ARM_MMAP_ENTRIES 8
+# define MAX_XLAT_TABLES 8
+# endif
+#elif defined(IMAGE_BL32)
+# define PLAT_ARM_MMAP_ENTRIES 8
+# define MAX_XLAT_TABLES 5
+#elif !USE_ROMLIB
+# define PLAT_ARM_MMAP_ENTRIES 11
+# define MAX_XLAT_TABLES 7
+#else
+# define PLAT_ARM_MMAP_ENTRIES 12
+# define MAX_XLAT_TABLES 6
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE 0xD000
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth. Current size is considering that TRUSTED_BOARD_BOOT
+ * and MEASURED_BOOT is enabled.
+ */
+# define PLAT_ARM_MAX_BL2_SIZE 0x26000
+
+
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW. Current size is considering that TRUSTED_BOARD_BOOT and
+ * MEASURED_BOOT is enabled.
+ */
+#define PLAT_ARM_MAX_BL31_SIZE 0x47000
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x440
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+# if SPM_MM
+# define PLATFORM_STACK_SIZE 0x500
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+
+/*
+ * In the current implementation the RoT Service request that requires the
+ * biggest message buffer is the RSS_DELEGATED_ATTEST_GET_PLATFORM_TOKEN. The
+ * maximum required buffer size is calculated based on the platform-specific
+ * needs of this request.
+ */
+#define PLAT_RSS_COMMS_PAYLOAD_MAX_SIZE 0x500
+
+#define TC_DEVICE_BASE 0x21000000
+#define TC_DEVICE_SIZE 0x5f000000
+
+// TC_MAP_DEVICE covers different peripherals
+// available to the platform
+#define TC_MAP_DEVICE MAP_REGION_FLAT( \
+ TC_DEVICE_BASE, \
+ TC_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+
+#define TC_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+ V2M_FLASH0_SIZE, \
+ MT_DEVICE | MT_RO | MT_SECURE)
+
+#define PLAT_ARM_NSTIMER_FRAME_ID 0
+
+#if (TARGET_PLATFORM >= 2)
+#define PLAT_ARM_TRUSTED_ROM_BASE 0x1000
+#else
+#define PLAT_ARM_TRUSTED_ROM_BASE 0x0
+#endif
+
+/* PLAT_ARM_TRUSTED_ROM_SIZE 512KB minus ROM base. */
+#define PLAT_ARM_TRUSTED_ROM_SIZE (0x00080000 - PLAT_ARM_TRUSTED_ROM_BASE)
+
+#define PLAT_ARM_NSRAM_BASE 0x06000000
+#define PLAT_ARM_NSRAM_SIZE 0x00080000 /* 512KB */
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
+#define PLAT_ARM_DRAM2_END (PLAT_ARM_DRAM2_BASE + PLAT_ARM_DRAM2_SIZE - 1ULL)
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
+ PLAT_SP_IMAGE_NS_BUF_SIZE)
+
+/*******************************************************************************
+ * Memprotect definitions
+ ******************************************************************************/
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \
+ V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT UL(100)
+
+#define PLAT_ARM_SCMI_CHANNEL_COUNT 1
+
+#define PLAT_ARM_CLUSTER_COUNT U(1)
+#define PLAT_MAX_CPUS_PER_CLUSTER U(8)
+#define PLAT_MAX_PE_PER_CPU U(1)
+
+/* Message Handling Unit (MHU) base addresses */
+#define PLAT_CSS_MHU_BASE UL(0x45400000)
+#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE
+
+/* TC2: AP<->RSS MHUs */
+#define PLAT_RSS_AP_SND_MHU_BASE UL(0x2A840000)
+#define PLAT_RSS_AP_RCV_MHU_BASE UL(0x2A850000)
+
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL ARM_PWR_LVL1
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE UL(0x30000000)
+#define PLAT_ARM_GICC_BASE UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE UL(0x30080000)
+
+/*
+ * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current
+ * SCP_BL2 size plus a little space for growth.
+ */
+#define PLAT_CSS_MAX_SCP_BL2_SIZE 0x20000
+
+/*
+ * PLAT_CSS_MAX_SCP_BL2U_SIZE is calculated using the current
+ * SCP_BL2U size plus a little space for growth.
+ */
+#define PLAT_CSS_MAX_SCP_BL2U_SIZE 0x20000
+
+/* TZC Related Constants */
+#define PLAT_ARM_TZC_BASE UL(0x25000000)
+#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define TZC400_OFFSET UL(0x1000000)
+#define TZC400_COUNT 4
+
+#define TZC400_BASE(n) (PLAT_ARM_TZC_BASE + \
+ (n * TZC400_OFFSET))
+
+#define TZC_NSAID_DEFAULT U(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS \
+ (TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT))
+
+/*
+ * The first region below, TC_TZC_DRAM1_BASE (0xfd000000) to
+ * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 48 MB of DRAM as
+ * secure. The second and third regions gives non secure access to rest of DRAM.
+ */
+#define TC_TZC_REGIONS_DEF \
+ {TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END, \
+ TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+ PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {PLAT_ARM_DRAM2_BASE, PLAT_ARM_DRAM2_END, \
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}
+
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/tc/include/tc_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
new file mode 100644
index 0000000..5f54856
--- /dev/null
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <cpu_macros.S>
+
+ .globl plat_arm_calc_core_pos
+ .globl plat_reset_handler
+
+ /* ---------------------------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Function to calculate the core position on TC.
+ *
+ * (ClusterId * PLAT_MAX_CPUS_PER_CLUSTER * PLAT_MAX_PE_PER_CPU) +
+ * (CPUId * PLAT_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * PLAT_MAX_CPUS_PER_CLUSTER + CPUId) * PLAT_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ /*
+ * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+ * look as if in a multi-threaded implementation.
+ */
+ tst x0, #MPIDR_MT_MASK
+ lsl x3, x0, #MPIDR_AFFINITY_BITS
+ csel x3, x3, x0, eq
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x4, #PLAT_MAX_CPUS_PER_CLUSTER
+ madd x1, x2, x4, x1
+ mov x5, #PLAT_MAX_PE_PER_CPU
+ madd x0, x1, x5, x0
+ ret
+endfunc plat_arm_calc_core_pos
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Determine the CPU MIDR and disable power down bit for
+ * that CPU.
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ ret
+endfunc plat_reset_handler
diff --git a/plat/arm/board/tc/include/tc_plat.h b/plat/arm/board/tc/include/tc_plat.h
new file mode 100644
index 0000000..28c0308
--- /dev/null
+++ b/plat/arm/board/tc/include/tc_plat.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TC_PLAT_H
+#define TC_PLAT_H
+
+void tc_bl31_common_platform_setup(void);
+
+#endif /* TC_PLAT_H */
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
new file mode 100644
index 0000000..37ba229
--- /dev/null
+++ b/plat/arm/board/tc/platform.mk
@@ -0,0 +1,199 @@
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+ifeq ($(TARGET_PLATFORM), 0)
+$(warning Platform ${PLAT}$(TARGET_PLATFORM) is deprecated. \
+Some of the features might not work as expected)
+endif
+
+ifeq ($(shell expr $(TARGET_PLATFORM) \<= 2), 0)
+ $(error TARGET_PLATFORM must be less than or equal to 2)
+endif
+
+$(eval $(call add_define,TARGET_PLATFORM))
+
+CSS_LOAD_SCP_IMAGES := 1
+
+CSS_USE_SCMI_SDS_DRIVER := 1
+
+RAS_EXTENSION := 0
+
+SDEI_SUPPORT := 0
+
+EL3_EXCEPTION_HANDLING := 0
+
+HANDLE_EA_EL3_FIRST_NS := 0
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY := 1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM := 0
+
+GIC_ENABLE_V4_EXTN := 1
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+
+# Enable SVE
+ENABLE_SVE_FOR_NS := 1
+ENABLE_SVE_FOR_SWD := 1
+
+# enable trace buffer control registers access to NS by default
+ENABLE_TRBE_FOR_NS := 1
+
+# enable trace system registers access to NS by default
+ENABLE_SYS_REG_TRACE_FOR_NS := 1
+
+# enable trace filter control registers access to NS by default
+ENABLE_TRF_FOR_NS := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+ENT_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/arm/common/arm_gicv3.c
+
+override NEED_BL2U := no
+
+override ARM_PLAT_MT := 1
+
+TC_BASE = plat/arm/board/tc
+
+PLAT_INCLUDES += -I${TC_BASE}/include/
+
+# CPU libraries for TARGET_PLATFORM=0
+ifeq (${TARGET_PLATFORM}, 0)
+TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a510.S \
+ lib/cpus/aarch64/cortex_a710.S \
+ lib/cpus/aarch64/cortex_x2.S
+endif
+
+# CPU libraries for TARGET_PLATFORM=1
+ifeq (${TARGET_PLATFORM}, 1)
+TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a510.S \
+ lib/cpus/aarch64/cortex_a715.S \
+ lib/cpus/aarch64/cortex_x3.S
+endif
+
+# CPU libraries for TARGET_PLATFORM=2
+ifeq (${TARGET_PLATFORM}, 2)
+TC_CPU_SOURCES += lib/cpus/aarch64/cortex_hayes.S \
+ lib/cpus/aarch64/cortex_hunter.S \
+ lib/cpus/aarch64/cortex_hunter_elp_arm.S
+endif
+
+INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c
+
+PLAT_BL_COMMON_SOURCES += ${TC_BASE}/tc_plat.c \
+ ${TC_BASE}/include/tc_helpers.S
+
+BL1_SOURCES += ${INTERCONNECT_SOURCES} \
+ ${TC_CPU_SOURCES} \
+ ${TC_BASE}/tc_trusted_boot.c \
+ ${TC_BASE}/tc_err.c \
+ drivers/arm/sbsa/sbsa.c
+
+BL2_SOURCES += ${TC_BASE}/tc_security.c \
+ ${TC_BASE}/tc_err.c \
+ ${TC_BASE}/tc_trusted_boot.c \
+ ${TC_BASE}/tc_bl2_setup.c \
+ lib/utils/mem_region.c \
+ drivers/arm/tzc/tzc400.c \
+ plat/arm/common/arm_tzc400.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${INTERCONNECT_SOURCES} \
+ ${TC_CPU_SOURCES} \
+ ${ENT_GIC_SOURCES} \
+ ${TC_BASE}/tc_bl31_setup.c \
+ ${TC_BASE}/tc_topology.c \
+ lib/fconf/fconf.c \
+ lib/fconf/fconf_dyn_cfg_getter.c \
+ drivers/cfi/v2m/v2m_flash.c \
+ lib/utils/mem_region.c \
+ plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES += ${TC_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${TC_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+ifeq (${SPD},spmd)
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS := ${TC_BASE}/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES += ${ARM_SPMC_MANIFEST_DTS}
+TC_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TC_TOS_FW_CONFIG},--tos-fw-config,${TC_TOS_FW_CONFIG}))
+endif
+
+#Device tree
+TC_HW_CONFIG_DTS := fdts/tc.dts
+TC_HW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}.dtb
+FDT_SOURCES += ${TC_HW_CONFIG_DTS}
+$(eval TC_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC_HW_CONFIG_DTS)))
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TC_HW_CONFIG},--hw-config,${TC_HW_CONFIG}))
+
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+override CTX_INCLUDE_PAUTH_REGS := 1
+
+override ENABLE_SPE_FOR_LOWER_ELS := 0
+
+override ENABLE_AMU := 1
+override ENABLE_AMU_AUXILIARY_COUNTERS := 1
+override ENABLE_AMU_FCONF := 1
+
+override ENABLE_MPMM := 1
+override ENABLE_MPMM_FCONF := 1
+
+# Include Measured Boot makefile before any Crypto library makefile.
+# Crypto library makefile may need default definitions of Measured Boot build
+# flags present in Measured Boot makefile.
+ifeq (${MEASURED_BOOT},1)
+ MEASURED_BOOT_MK := drivers/measured_boot/rss/rss_measured_boot.mk
+ $(info Including ${MEASURED_BOOT_MK})
+ include ${MEASURED_BOOT_MK}
+ $(info Including rss_comms.mk)
+ include drivers/arm/rss/rss_comms.mk
+
+ BL1_SOURCES += ${MEASURED_BOOT_SOURCES} \
+ plat/arm/board/tc/tc_common_measured_boot.c \
+ plat/arm/board/tc/tc_bl1_measured_boot.c \
+ lib/psa/measured_boot.c \
+ ${RSS_COMMS_SOURCES}
+
+ BL2_SOURCES += ${MEASURED_BOOT_SOURCES} \
+ plat/arm/board/tc/tc_common_measured_boot.c \
+ plat/arm/board/tc/tc_bl2_measured_boot.c \
+ lib/psa/measured_boot.c \
+ ${RSS_COMMS_SOURCES}
+
+PLAT_INCLUDES += -Iinclude/lib/psa
+
+endif
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/soc/common/soc_css.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/tc/tc_bl1_measured_boot.c b/plat/arm/board/tc/tc_bl1_measured_boot.c
new file mode 100644
index 0000000..0d29c51
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl1_measured_boot.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <drivers/arm/rss_comms.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
+#include <lib/psa/measured_boot.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/* Table with platform specific image IDs and metadata. Intentionally not a
+ * const struct, some members might set by bootloaders during trusted boot.
+ */
+struct rss_mboot_metadata tc_rss_mboot_metadata[] = {
+ {
+ .id = FW_CONFIG_ID,
+ .slot = U(6),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = TB_FW_CONFIG_ID,
+ .slot = U(7),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_TB_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = BL2_IMAGE_ID,
+ .slot = U(8),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_BL2_STRING,
+ .lock_measurement = true },
+
+ {
+ .id = RSS_MBOOT_INVALID_ID }
+};
+
+void bl1_plat_mboot_init(void)
+{
+ /* Initialize the communication channel between AP and RSS */
+ (void)rss_comms_init(PLAT_RSS_AP_SND_MHU_BASE,
+ PLAT_RSS_AP_RCV_MHU_BASE);
+
+ rss_measured_boot_init();
+}
+
+void bl1_plat_mboot_finish(void)
+{
+ /* Nothing to do. */
+}
diff --git a/plat/arm/board/tc/tc_bl2_measured_boot.c b/plat/arm/board/tc/tc_bl2_measured_boot.c
new file mode 100644
index 0000000..7ea2c2e
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl2_measured_boot.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <drivers/arm/rss_comms.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
+#include <lib/psa/measured_boot.h>
+
+#include <plat/common/common_def.h>
+#include <platform_def.h>
+
+/* TC specific table with image IDs and metadata. Intentionally not a
+ * const struct, some members might set by bootloaders during trusted boot.
+ */
+struct rss_mboot_metadata tc_rss_mboot_metadata[] = {
+ {
+ .id = BL31_IMAGE_ID,
+ .slot = U(9),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_BL31_STRING,
+ .lock_measurement = true },
+ {
+ .id = HW_CONFIG_ID,
+ .slot = U(10),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_HW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = SOC_FW_CONFIG_ID,
+ .slot = U(11),
+ .signer_id_size = SIGNER_ID_MIN_SIZE,
+ .sw_type = RSS_MBOOT_SOC_FW_CONFIG_STRING,
+ .lock_measurement = true },
+ {
+ .id = RSS_MBOOT_INVALID_ID }
+};
+
+void bl2_plat_mboot_init(void)
+{
+ /* Initialize the communication channel between AP and RSS */
+ (void)rss_comms_init(PLAT_RSS_AP_SND_MHU_BASE,
+ PLAT_RSS_AP_RCV_MHU_BASE);
+
+ rss_measured_boot_init();
+}
+
+void bl2_plat_mboot_finish(void)
+{
+ /* Nothing to do. */
+}
diff --git a/plat/arm/board/tc/tc_bl2_setup.c b/plat/arm/board/tc/tc_bl2_setup.c
new file mode 100644
index 0000000..74ef569
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl2_setup.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ struct bl_params *arm_bl_params = arm_get_next_bl_params();
+
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ bl_mem_params_node_t *param_node;
+ uintptr_t fw_config_base = 0U;
+ entry_point_info_t *ep_info;
+
+ /* Get BL31 image node */
+ param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+ assert(param_node != NULL);
+
+ /* Get fw_config load address */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ assert(fw_config_info != NULL);
+
+ fw_config_base = fw_config_info->config_addr;
+ assert(fw_config_base != 0U);
+
+ /*
+ * Get the entry point info of BL31 image and override
+ * arg1 of entry point info with fw_config base address
+ */
+ ep_info = &param_node->ep_info;
+ ep_info->args.arg1 = (uint32_t)fw_config_base;
+
+ return arm_bl_params;
+}
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
new file mode 100644
index 0000000..0523ef8
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+#include <tc_plat.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+static scmi_channel_plat_info_t tc_scmi_plat_info[] = {
+ {
+ .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhuv2_ring_doorbell,
+ }
+};
+
+void bl31_platform_setup(void)
+{
+ tc_bl31_common_platform_setup();
+}
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+
+ return &tc_scmi_plat_info[channel_id];
+
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", arg1);
+}
+
+void tc_bl31_common_platform_setup(void)
+{
+ arm_bl31_platform_setup();
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+ arm_bl31_plat_arch_setup();
+
+ /* HW_CONFIG was also loaded by BL2 */
+ const struct dyn_cfg_dtb_info_t *hw_config_info;
+
+ hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+ assert(hw_config_info != NULL);
+
+ fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+}
diff --git a/plat/arm/board/tc/tc_common_measured_boot.c b/plat/arm/board/tc/tc_common_measured_boot.c
new file mode 100644
index 0000000..fe71899
--- /dev/null
+++ b/plat/arm/board/tc/tc_common_measured_boot.c
@@ -0,0 +1,35 @@
+
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/desc_image_load.h>
+#include <drivers/measured_boot/rss/rss_measured_boot.h>
+
+extern struct rss_mboot_metadata tc_rss_mboot_metadata[];
+
+struct rss_mboot_metadata *plat_rss_mboot_get_metadata(void)
+{
+ return tc_rss_mboot_metadata;
+}
+
+int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
+{
+ int err;
+
+ /* Calculate image hash and record data in RSS */
+ err = rss_mboot_measure_and_record(image_data->image_base,
+ image_data->image_size,
+ image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "Failed to ", "record in RSS", image_id, err);
+ }
+
+ return err;
+}
diff --git a/plat/arm/board/tc/tc_err.c b/plat/arm/board/tc/tc_err.c
new file mode 100644
index 0000000..9ed7e92
--- /dev/null
+++ b/plat/arm/board/tc/tc_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * tc error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/tc/tc_interconnect.c b/plat/arm/board/tc/tc_interconnect.c
new file mode 100644
index 0000000..e2fc4e1
--- /dev/null
+++ b/plat/arm/board/tc/tc_interconnect.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * For Total Compute we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void __init plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/board/tc/tc_plat.c b/plat/arm/board/tc/tc_plat.c
new file mode 100644
index 0000000..77db023
--- /dev/null
+++ b/plat/arm/board/tc/tc_plat.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <plat/common/platform.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/ccn.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
+
+#if SPM_MM
+#include <services/spm_mm_partition.h>
+#endif
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * arm_configure_mmu_elx() will give the available subset of that.
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ TC_FLASH0_RO,
+ TC_MAP_DEVICE,
+ {0}
+};
+#endif
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ TC_FLASH0_RO,
+ TC_MAP_DEVICE,
+ TC_MAP_NS_DRAM1,
+#if defined(SPD_spmd)
+ TC_MAP_TZC_DRAM1,
+#endif
+#if ARM_BL31_IN_DRAM
+ ARM_MAP_BL31_SEC_DRAM,
+#endif
+#if SPM_MM
+ ARM_SP_IMAGE_MMAP,
+#endif
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif
+#ifdef SPD_opteed
+ ARM_MAP_OPTEE_CORE_MEM,
+ ARM_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
+ {0}
+};
+#endif
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_IOFPGA,
+ TC_MAP_DEVICE,
+ PLAT_DTB_DRAM_NS,
+#if SPM_MM
+ ARM_SPM_BUF_EL3_MMAP,
+#endif
+ {0}
+};
+
+#if SPM_MM && defined(IMAGE_BL31)
+const mmap_region_t plat_arm_secure_partition_mmap[] = {
+ PLAT_ARM_SECURE_MAP_DEVICE,
+ ARM_SP_IMAGE_MMAP,
+ ARM_SP_IMAGE_NS_BUF_MMAP,
+ ARM_SP_CPER_BUF_MMAP,
+ ARM_SP_IMAGE_RW_MMAP,
+ ARM_SPM_BUF_EL0_MMAP,
+ {0}
+};
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+#endif
+
+ARM_CASSERT_MMAP
+
+#if SPM_MM && defined(IMAGE_BL31)
+/*
+ * Boot information passed to a secure partition during initialisation. Linear
+ * indices in MP information will be filled at runtime.
+ */
+static spm_mm_mp_info_t sp_mp_info[] = {
+ [0] = {0x81000000, 0},
+ [1] = {0x81000100, 0},
+ [2] = {0x81000200, 0},
+ [3] = {0x81000300, 0},
+ [4] = {0x81010000, 0},
+ [5] = {0x81010100, 0},
+ [6] = {0x81010200, 0},
+ [7] = {0x81010300, 0},
+};
+
+const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
+ .h.type = PARAM_SP_IMAGE_BOOT_INFO,
+ .h.version = VERSION_1,
+ .h.size = sizeof(spm_mm_boot_info_t),
+ .h.attr = 0,
+ .sp_mem_base = ARM_SP_IMAGE_BASE,
+ .sp_mem_limit = ARM_SP_IMAGE_LIMIT,
+ .sp_image_base = ARM_SP_IMAGE_BASE,
+ .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
+ .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE,
+ .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
+ .sp_shared_buf_base = PLAT_SPM_BUF_BASE,
+ .sp_image_size = ARM_SP_IMAGE_SIZE,
+ .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+ .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE,
+ .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
+ .sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
+ .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS,
+ .num_cpus = PLATFORM_CORE_COUNT,
+ .mp_info = &sp_mp_info[0],
+};
+
+const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
+{
+ return plat_arm_secure_partition_mmap;
+}
+
+const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
+ void *cookie)
+{
+ return &plat_arm_secure_partition_boot_info;
+}
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+
+#if TRUSTED_BOARD_BOOT || MEASURED_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+ sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/board/tc/tc_security.c b/plat/arm/board/tc/tc_security.c
new file mode 100644
index 0000000..6a34501
--- /dev/null
+++ b/plat/arm/board/tc/tc_security.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+static const arm_tzc_regions_info_t tzc_regions[] = {
+ TC_TZC_REGIONS_DEF,
+ {}
+};
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+ unsigned int i;
+
+ for (i = 0U; i < TZC400_COUNT; i++) {
+ arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
+ }
+}
diff --git a/plat/arm/board/tc/tc_topology.c b/plat/arm/board/tc/tc_topology.c
new file mode 100644
index 0000000..9e18da6
--- /dev/null
+++ b/plat/arm/board/tc/tc_topology.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+const unsigned char tc_pd_tree_desc[] = {
+ PLAT_ARM_CLUSTER_COUNT,
+ PLAT_MAX_CPUS_PER_CLUSTER,
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return tc_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+ (SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+};
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+ return PLAT_MAX_CPUS_PER_CLUSTER;
+}
+
+#if ARM_PLAT_MT
+/******************************************************************************
+ * Return the number of PE's supported by the CPU.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+ return PLAT_MAX_PE_PER_CPU;
+}
+#endif
diff --git a/plat/arm/board/tc/tc_trusted_boot.c b/plat/arm/board/tc/tc_trusted_boot.c
new file mode 100644
index 0000000..614f7e2
--- /dev/null
+++ b/plat/arm/board/tc/tc_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c b/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c
new file mode 100644
index 0000000..18f1a37
--- /dev/null
+++ b/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = PLAT_CSS_MAX_SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL32_BASE,
+ .ep_info.spsr = SPSR_MODE32(MODE32_mon, SPSR_T_ARM,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+ /* Fill HW_CONFIG related information if it exists */
+ {
+ .image_id = HW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+#ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#else
+ .ep_info.pc = PLAT_ARM_NS_IMAGE_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_ARM_NS_IMAGE_BASE,
+ .image_info.image_max_size = ARM_DRAM1_BASE + ARM_DRAM1_SIZE
+ - PLAT_ARM_NS_IMAGE_BASE,
+#endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/arm/common/aarch32/arm_helpers.S b/plat/arm/common/aarch32/arm_helpers.S
new file mode 100644
index 0000000..1da2d4c
--- /dev/null
+++ b/plat/arm/common/aarch32/arm_helpers.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .weak plat_arm_calc_core_pos
+ .weak plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_arm_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ ldcopr r0, MPIDR
+ b plat_arm_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(uint64_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 4) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ and r1, r0, #MPIDR_CPU_MASK
+ and r0, r0, #MPIDR_CLUSTER_MASK
+ add r0, r1, r0, LSR #6
+ bx lr
+endfunc plat_arm_calc_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : r0 - r3
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ ldr r0, =PLAT_ARM_CRASH_UART_BASE
+ ldr r1, =PLAT_ARM_CRASH_UART_CLK_IN_HZ
+ ldr r2, =ARM_CONSOLE_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : r1 - r2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ ldr r1, =PLAT_ARM_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : r0
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ ldr r0, =PLAT_ARM_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
new file mode 100644
index 0000000..3d7b361
--- /dev/null
+++ b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = PLAT_CSS_MAX_SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# if defined(BL32_BASE)
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# elif ENABLE_RME
+ .next_handoff_image_id = RMM_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+ /* Fill HW_CONFIG related information */
+ {
+ .image_id = HW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ /* Fill SOC_FW_CONFIG related information */
+ {
+ .image_id = SOC_FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+# if ENABLE_RME
+ /* Fill RMM related information */
+ {
+ .image_id = RMM_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, EP_REALM | EXECUTABLE),
+ .ep_info.pc = RMM_BASE,
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = RMM_BASE,
+ .image_info.image_max_size = RMM_LIMIT - RMM_BASE,
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+# endif
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+# if ENABLE_RME
+ .next_handoff_image_id = RMM_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the pager
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the paged
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = ARM_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = ARM_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill TOS_FW_CONFIG related information */
+ {
+ .image_id = TOS_FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = PLAT_ARM_NS_IMAGE_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_ARM_NS_IMAGE_BASE,
+ .image_info.image_max_size = ARM_DRAM1_BASE + ARM_DRAM1_SIZE
+ - PLAT_ARM_NS_IMAGE_BASE,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ /* Fill NT_FW_CONFIG related information */
+ {
+ .image_id = NT_FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S
new file mode 100644
index 0000000..b470781
--- /dev/null
+++ b/plat/arm/common/aarch64/arm_helpers.S
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .weak plat_arm_calc_core_pos
+ .weak plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl platform_mem_init
+
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_arm_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_arm_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 4) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func plat_arm_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_arm_calc_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_ARM_CRASH_UART_BASE
+ mov_imm x1, PLAT_ARM_CRASH_UART_CLK_IN_HZ
+ mov_imm x2, ARM_CONSOLE_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_ARM_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : r0
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, PLAT_ARM_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on ARM
+ * platforms. The Secure RAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+/*
+ * Need to use coherent stack when ARM Cryptocell is used to autheticate images
+ * since Cryptocell uses DMA to transfer data and it is not coherent with the
+ * AP CPU.
+ */
+#if ARM_CRYPTOCELL_INTEG
+#if defined(IMAGE_BL1) || defined(IMAGE_BL2)
+ .globl plat_get_my_stack
+ .globl plat_set_my_stack
+ .local platform_coherent_stacks
+
+ /* -------------------------------------------------------
+ * uintptr_t plat_get_my_stack ()
+ *
+ * For cold-boot BL images, only the primary CPU needs a
+ * stack. This function returns the stack pointer for a
+ * stack allocated in coherent memory.
+ * -------------------------------------------------------
+ */
+func plat_get_my_stack
+ get_up_stack platform_coherent_stacks, PLATFORM_STACK_SIZE
+ ret
+endfunc plat_get_my_stack
+
+ /* -------------------------------------------------------
+ * void plat_set_my_stack ()
+ *
+ * For cold-boot BL images, only the primary CPU needs a
+ * stack. This function sets the stack pointer to a stack
+ * allocated in coherent memory.
+ * -------------------------------------------------------
+ */
+func plat_set_my_stack
+ get_up_stack platform_coherent_stacks, PLATFORM_STACK_SIZE
+ mov sp, x0
+ ret
+endfunc plat_set_my_stack
+
+ /* ----------------------------------------------------
+ * Single cpu stack in coherent memory.
+ * ----------------------------------------------------
+ */
+declare_stack platform_coherent_stacks, tzfw_coherent_mem, \
+ PLATFORM_STACK_SIZE, 1, CACHE_WRITEBACK_GRANULE
+
+#endif /* defined(IMAGE_BL1) || defined(IMAGE_BL2) */
+#endif /* ARM_CRYPTOCELL_INTEG */
diff --git a/plat/arm/common/aarch64/arm_pauth.c b/plat/arm/common/aarch64/arm_pauth.c
new file mode 100644
index 0000000..7cea8a0
--- /dev/null
+++ b/plat/arm/common/aarch64/arm_pauth.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <cdefs.h>
+#include <stdint.h>
+
+/*
+ * This is only a toy implementation to generate a seemingly random
+ * 128-bit key from sp, x30 and cntpct_el0 values.
+ * A production system must re-implement this function to generate
+ * keys from a reliable randomness source.
+ */
+uint128_t plat_init_apkey(void)
+{
+ uint64_t return_addr = (uint64_t)__builtin_return_address(0U);
+ uint64_t frame_addr = (uint64_t)__builtin_frame_address(0U);
+ uint64_t cntpct = read_cntpct_el0();
+
+ /* Generate 128-bit key */
+ uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ cntpct;
+ uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ cntpct;
+
+ return ((uint128_t)(key_hi) << 64) | key_lo;
+}
diff --git a/plat/arm/common/aarch64/arm_sdei.c b/plat/arm/common/aarch64/arm_sdei.c
new file mode 100644
index 0000000..3c74a46
--- /dev/null
+++ b/plat/arm/common/aarch64/arm_sdei.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* SDEI configuration for ARM platforms */
+
+#include <bl31/ehf.h>
+#include <common/debug.h>
+#include <services/sdei.h>
+
+#if SDEI_IN_FCONF
+#include <plat/arm/common/fconf_sdei_getter.h>
+#endif
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+
+#if SDEI_IN_FCONF
+/* Private event mappings */
+static sdei_ev_map_t arm_sdei_private[PLAT_SDEI_DP_EVENT_MAX_CNT + 1] = { 0 };
+
+/* Shared event mappings */
+static sdei_ev_map_t arm_sdei_shared[PLAT_SDEI_DS_EVENT_MAX_CNT] = { 0 };
+
+void plat_sdei_setup(void)
+{
+ uint32_t i;
+
+ arm_sdei_private[0] = (sdei_ev_map_t)SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI);
+
+ for (i = 0; i < FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_cnt); i++) {
+ arm_sdei_private[i + 1] = (sdei_ev_map_t)SDEI_PRIVATE_EVENT(
+ FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_nums[i]),
+ FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_intrs[i]),
+ FCONF_GET_PROPERTY(sdei, dyn_config, private_ev_flags[i]));
+ }
+
+ for (i = 0; i < FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_cnt); i++) {
+ arm_sdei_shared[i] = (sdei_ev_map_t)SDEI_SHARED_EVENT( \
+ FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_nums[i]),
+ FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_intrs[i]),
+ FCONF_GET_PROPERTY(sdei, dyn_config, shared_ev_flags[i]));
+ }
+ INFO("FCONF: SDEI platform setup\n");
+}
+#else
+/* Private event mappings */
+static sdei_ev_map_t arm_sdei_private[] = {
+ PLAT_ARM_PRIVATE_SDEI_EVENTS
+};
+
+/* Shared event mappings */
+static sdei_ev_map_t arm_sdei_shared[] = {
+ PLAT_ARM_SHARED_SDEI_EVENTS
+};
+
+void plat_sdei_setup(void)
+{
+ INFO("SDEI platform setup\n");
+}
+#endif /* SDEI_IN_FCONF */
+
+/* Export ARM SDEI events */
+REGISTER_SDEI_MAP(arm_sdei_private, arm_sdei_shared);
diff --git a/plat/arm/common/aarch64/execution_state_switch.c b/plat/arm/common/aarch64/execution_state_switch.c
new file mode 100644
index 0000000..2353e6a
--- /dev/null
+++ b/plat/arm/common/aarch64/execution_state_switch.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/psci/psci.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+#include <smccc_helpers.h>
+
+/*
+ * Handle SMC from a lower exception level to switch its execution state
+ * (either from AArch64 to AArch32, or vice versa).
+ *
+ * smc_fid:
+ * SMC function ID - either ARM_SIP_SVC_STATE_SWITCH_64 or
+ * ARM_SIP_SVC_STATE_SWITCH_32.
+ * pc_hi, pc_lo:
+ * PC upon re-entry to the calling exception level; width dependent on the
+ * calling exception level.
+ * cookie_hi, cookie_lo:
+ * Opaque pointer pairs received from the caller to pass it back, upon
+ * re-entry.
+ * handle:
+ * Handle to saved context.
+ */
+int arm_execution_state_switch(unsigned int smc_fid,
+ uint32_t pc_hi,
+ uint32_t pc_lo,
+ uint32_t cookie_hi,
+ uint32_t cookie_lo,
+ void *handle)
+{
+ bool caller_64, thumb = false, from_el2;
+ unsigned int el, endianness;
+ u_register_t spsr, pc, scr, sctlr;
+ entry_point_info_t ep;
+ cpu_context_t *ctx = (cpu_context_t *) handle;
+ el3_state_t *el3_ctx = get_el3state_ctx(ctx);
+
+ /* Validate supplied entry point */
+ pc = (u_register_t) (((uint64_t) pc_hi << 32) | pc_lo);
+ if (arm_validate_ns_entrypoint(pc) != 0)
+ goto invalid_param;
+
+ /* That the SMC originated from NS is already validated by the caller */
+
+ /*
+ * Disallow state switch if any of the secondaries have been brought up.
+ */
+ if (psci_secondaries_brought_up() != 0)
+ goto exec_denied;
+
+ spsr = read_ctx_reg(el3_ctx, CTX_SPSR_EL3);
+ caller_64 = (GET_RW(spsr) == MODE_RW_64);
+
+ if (caller_64) {
+ /*
+ * If the call originated from AArch64, expect 32-bit pointers when
+ * switching to AArch32.
+ */
+ if ((pc_hi != 0U) || (cookie_hi != 0U))
+ goto invalid_param;
+
+ pc = pc_lo;
+
+ /* Instruction state when entering AArch32 */
+ thumb = (pc & 1U) != 0U;
+ } else {
+ /* Construct AArch64 PC */
+ pc = (((u_register_t) pc_hi) << 32) | pc_lo;
+ }
+
+ /* Make sure PC is 4-byte aligned, except for Thumb */
+ if (((pc & 0x3U) != 0U) && !thumb)
+ goto invalid_param;
+
+ /*
+ * EL3 controls register width of the immediate lower EL only. Expect
+ * this request from EL2/Hyp unless:
+ *
+ * - EL2 is not implemented;
+ * - EL2 is implemented, but was disabled. This can be inferred from
+ * SCR_EL3.HCE.
+ */
+ from_el2 = caller_64 ? (GET_EL(spsr) == MODE_EL2) :
+ (GET_M32(spsr) == MODE32_hyp);
+ scr = read_ctx_reg(el3_ctx, CTX_SCR_EL3);
+ if (!from_el2) {
+ /* The call is from NS privilege level other than HYP */
+
+ /*
+ * Disallow switching state if there's a Hypervisor in place;
+ * this request must be taken up with the Hypervisor instead.
+ */
+ if ((scr & SCR_HCE_BIT) != 0U)
+ goto exec_denied;
+ }
+
+ /*
+ * Return to the caller using the same endianness. Extract
+ * endianness bit from the respective system control register
+ * directly.
+ */
+ sctlr = from_el2 ? read_sctlr_el2() : read_sctlr_el1();
+ endianness = ((sctlr & SCTLR_EE_BIT) != 0U) ? 1U : 0U;
+
+ /* Construct SPSR for the exception state we're about to switch to */
+ if (caller_64) {
+ unsigned long long impl;
+
+ /*
+ * Switching from AArch64 to AArch32. Ensure this CPU implements
+ * the target EL in AArch32.
+ */
+ impl = from_el2 ? el_implemented(2) : el_implemented(1);
+ if (impl != EL_IMPL_A64_A32)
+ goto exec_denied;
+
+ /* Return to the equivalent AArch32 privilege level */
+ el = from_el2 ? MODE32_hyp : MODE32_svc;
+ spsr = SPSR_MODE32((u_register_t) el,
+ thumb ? SPSR_T_THUMB : SPSR_T_ARM,
+ endianness, DISABLE_ALL_EXCEPTIONS);
+ } else {
+ /*
+ * Switching from AArch32 to AArch64. Since it's not possible to
+ * implement an EL as AArch32-only (from which this call was
+ * raised), it's safe to assume AArch64 is also implemented.
+ */
+ el = from_el2 ? MODE_EL2 : MODE_EL1;
+ spsr = SPSR_64((u_register_t) el, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ }
+
+ /*
+ * Use the context management library to re-initialize the existing
+ * context with the execution state flipped. Since the library takes
+ * entry_point_info_t pointer as the argument, construct a dummy one
+ * with PC, state width, endianness, security etc. appropriately set.
+ * Other entries in the entry point structure are irrelevant for
+ * purpose.
+ */
+ zeromem(&ep, sizeof(ep));
+ ep.pc = pc;
+ ep.spsr = (uint32_t) spsr;
+ SET_PARAM_HEAD(&ep, PARAM_EP, VERSION_1,
+ ((unsigned int) ((endianness != 0U) ? EP_EE_BIG :
+ EP_EE_LITTLE)
+ | NON_SECURE | EP_ST_DISABLE));
+
+ /*
+ * Re-initialize the system register context, and exit EL3 as if for the
+ * first time. State switch is effectively a soft reset of the
+ * calling EL.
+ */
+ cm_init_my_context(&ep);
+ cm_prepare_el3_exit_ns();
+
+ /*
+ * State switch success. The caller of SMC wouldn't see the SMC
+ * returning. Instead, execution starts at the supplied entry point,
+ * with context pointers populated in registers 0 and 1.
+ */
+ SMC_RET2(handle, cookie_hi, cookie_lo);
+
+invalid_param:
+ SMC_RET1(handle, STATE_SW_E_PARAM);
+
+exec_denied:
+ /* State switch denied */
+ SMC_RET1(handle, STATE_SW_E_DENIED);
+}
diff --git a/plat/arm/common/arm_bl1_fwu.c b/plat/arm/common/arm_bl1_fwu.c
new file mode 100644
index 0000000..ce2c356
--- /dev/null
+++ b/plat/arm/common/arm_bl1_fwu.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <bl1/tbbr/tbbr_img_desc.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#pragma weak bl1_plat_get_image_desc
+
+/* Struct to keep track of usable memory */
+typedef struct bl1_mem_info {
+ uintptr_t mem_base;
+ unsigned int mem_size;
+} bl1_mem_info_t;
+
+static bl1_mem_info_t fwu_addr_map_secure[] = {
+ {
+ .mem_base = ARM_SHARED_RAM_BASE,
+ .mem_size = ARM_SHARED_RAM_SIZE
+ },
+ {
+ .mem_size = 0
+ }
+};
+
+static bl1_mem_info_t fwu_addr_map_non_secure[] = {
+ {
+ .mem_base = ARM_NS_DRAM1_BASE,
+ .mem_size = ARM_NS_DRAM1_SIZE
+ },
+ {
+ .mem_base = PLAT_ARM_NVM_BASE,
+ .mem_size = PLAT_ARM_NVM_SIZE
+ },
+ {
+ .mem_size = 0
+ }
+};
+
+int bl1_plat_mem_check(uintptr_t mem_base,
+ unsigned int mem_size,
+ unsigned int flags)
+{
+ unsigned int index = 0;
+ bl1_mem_info_t *mmap;
+
+ assert(mem_base);
+ assert(mem_size);
+ /*
+ * The caller of this function is responsible for checking upfront that
+ * the end address doesn't overflow. We double-check this in debug
+ * builds.
+ */
+ assert(!check_uptr_overflow(mem_base, mem_size - 1));
+
+ /*
+ * Check the given image source and size.
+ */
+ if (GET_SECURITY_STATE(flags) == SECURE)
+ mmap = fwu_addr_map_secure;
+ else
+ mmap = fwu_addr_map_non_secure;
+
+ while (mmap[index].mem_size) {
+ if ((mem_base >= mmap[index].mem_base) &&
+ ((mem_base + mem_size)
+ <= (mmap[index].mem_base +
+ mmap[index].mem_size)))
+ return 0;
+
+ index++;
+ }
+
+ return -ENOMEM;
+}
+
+/*******************************************************************************
+ * This function does linear search for image_id and returns image_desc.
+ ******************************************************************************/
+image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ unsigned int index = 0;
+
+ while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) {
+ if (bl1_tbbr_image_descs[index].image_id == image_id)
+ return &bl1_tbbr_image_descs[index];
+ index++;
+ }
+
+ return NULL;
+}
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
new file mode 100644
index 0000000..7000236
--- /dev/null
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak bl1_early_platform_setup
+#pragma weak bl1_plat_arch_setup
+#pragma weak bl1_plat_sec_mem_layout
+#pragma weak arm_bl1_early_platform_setup
+#pragma weak bl1_plat_prepare_exit
+#pragma weak bl1_plat_get_next_image_id
+#pragma weak plat_arm_bl1_fwu_needed
+#pragma weak arm_bl1_plat_arch_setup
+#pragma weak arm_bl1_platform_setup
+
+#define MAP_BL1_TOTAL MAP_REGION_FLAT( \
+ bl1_tzram_layout.total_base, \
+ bl1_tzram_layout.total_size, \
+ MT_MEMORY | MT_RW | EL3_PAS)
+/*
+ * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
+ * otherwise one region is defined containing both
+ */
+#if SEPARATE_CODE_AND_RODATA
+#define MAP_BL1_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL1_CODE_END - BL_CODE_BASE, \
+ MT_CODE | EL3_PAS), \
+ MAP_REGION_FLAT( \
+ BL1_RO_DATA_BASE, \
+ BL1_RO_DATA_END \
+ - BL_RO_DATA_BASE, \
+ MT_RO_DATA | EL3_PAS)
+#else
+#define MAP_BL1_RO MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL1_CODE_END - BL_CODE_BASE, \
+ MT_CODE | EL3_PAS)
+#endif
+
+/* Data structure which holds the extents of the trusted SRAM for BL1*/
+static meminfo_t bl1_tzram_layout;
+
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
+struct meminfo *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * BL1 specific platform actions shared between ARM standard platforms.
+ ******************************************************************************/
+void arm_bl1_early_platform_setup(void)
+{
+
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Enable watchdog */
+ plat_arm_secure_wdt_start();
+#endif
+
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = ARM_BL_RAM_BASE;
+ bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE;
+}
+
+void bl1_early_platform_setup(void)
+{
+ arm_bl1_early_platform_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_arm_interconnect_init();
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ plat_arm_interconnect_enter_coherency();
+}
+
+/******************************************************************************
+ * Perform the very early platform specific architecture setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl1_arch_setup()) does not do anything platform
+ * specific.
+ *****************************************************************************/
+void arm_bl1_plat_arch_setup(void)
+{
+#if USE_COHERENT_MEM && !ARM_CRYPTOCELL_INTEG
+ /*
+ * Ensure ARM platforms don't use coherent memory in BL1 unless
+ * cryptocell integration is enabled.
+ */
+ assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U);
+#endif
+
+ const mmap_region_t bl_regions[] = {
+ MAP_BL1_TOTAL,
+ MAP_BL1_RO,
+#if USE_ROMLIB
+ ARM_MAP_ROMLIB_CODE,
+ ARM_MAP_ROMLIB_DATA,
+#endif
+#if ARM_CRYPTOCELL_INTEG
+ ARM_MAP_BL_COHERENT_RAM,
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+#ifdef __aarch64__
+ enable_mmu_el3(0);
+#else
+ enable_mmu_svc_mon(0);
+#endif /* __aarch64__ */
+
+ arm_setup_romlib();
+}
+
+void bl1_plat_arch_setup(void)
+{
+ arm_bl1_plat_arch_setup();
+}
+
+/*
+ * Perform the platform specific architecture setup shared between
+ * ARM standard platforms.
+ */
+void arm_bl1_platform_setup(void)
+{
+ const struct dyn_cfg_dtb_info_t *fw_config_info;
+ image_desc_t *desc;
+ uint32_t fw_config_max_size;
+ int err = -1;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_arm_io_setup();
+
+ /* Check if we need FWU before further processing */
+ is_fwu_needed = plat_arm_bl1_fwu_needed();
+ if (is_fwu_needed) {
+ ERROR("Skip platform setup as FWU detected\n");
+ return;
+ }
+
+ /* Set global DTB info for fixed fw_config information */
+ fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
+ set_config_info(ARM_FW_CONFIG_BASE, ~0UL, fw_config_max_size, FW_CONFIG_ID);
+
+ /* Fill the device tree information struct with the info from the config dtb */
+ err = fconf_load_config(FW_CONFIG_ID);
+ if (err < 0) {
+ ERROR("Loading of FW_CONFIG failed %d\n", err);
+ plat_error_handler(err);
+ }
+
+ /*
+ * FW_CONFIG loaded successfully. If FW_CONFIG device tree parsing
+ * is successful then load TB_FW_CONFIG device tree.
+ */
+ fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+ if (fw_config_info != NULL) {
+ err = fconf_populate_dtb_registry(fw_config_info->config_addr);
+ if (err < 0) {
+ ERROR("Parsing of FW_CONFIG failed %d\n", err);
+ plat_error_handler(err);
+ }
+ /* load TB_FW_CONFIG */
+ err = fconf_load_config(TB_FW_CONFIG_ID);
+ if (err < 0) {
+ ERROR("Loading of TB_FW_CONFIG failed %d\n", err);
+ plat_error_handler(err);
+ }
+ } else {
+ ERROR("Invalid FW_CONFIG address\n");
+ plat_error_handler(err);
+ }
+
+ /* The BL2 ep_info arg0 is modified to point to FW_CONFIG */
+ desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+ assert(desc != NULL);
+ desc->ep_info.args.arg0 = fw_config_info->config_addr;
+
+#if CRYPTO_SUPPORT
+ /* Share the Mbed TLS heap info with other images */
+ arm_bl1_set_mbedtls_heap();
+#endif /* CRYPTO_SUPPORT */
+
+ /*
+ * Allow access to the System counter timer module and program
+ * counter frequency for non secure images during FWU
+ */
+#ifdef ARM_SYS_TIMCTL_BASE
+ arm_configure_sys_timer();
+#endif
+#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER)
+ write_cntfrq_el0(plat_get_syscnt_freq2());
+#endif
+}
+
+void bl1_plat_prepare_exit(entry_point_info_t *ep_info)
+{
+#if !ARM_DISABLE_TRUSTED_WDOG
+ /* Disable watchdog before leaving BL1 */
+ plat_arm_secure_wdt_stop();
+#endif
+
+#ifdef EL3_PAYLOAD_BASE
+ /*
+ * Program the EL3 payload's entry point address into the CPUs mailbox
+ * in order to release secondary CPUs from their holding pen and make
+ * them jump there.
+ */
+ plat_arm_program_trusted_mailbox(ep_info->pc);
+ dsbsy();
+ sev();
+#endif
+}
+
+/*
+ * On Arm platforms, the FWU process is triggered when the FIP image has
+ * been tampered with.
+ */
+bool plat_arm_bl1_fwu_needed(void)
+{
+ return !arm_io_is_toc_valid();
+}
+
+/*******************************************************************************
+ * The following function checks if Firmware update is needed,
+ * by checking if TOC in FIP image is valid or not.
+ ******************************************************************************/
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ return is_fwu_needed ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
+}
diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c
new file mode 100644
index 0000000..97b5a88
--- /dev/null
+++ b/plat/arm/common/arm_bl2_el3_setup.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/generic_delay_timer.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#pragma weak bl2_el3_early_platform_setup
+#pragma weak bl2_el3_plat_arch_setup
+#pragma weak bl2_el3_plat_prepare_exit
+
+#define MAP_BL2_EL3_TOTAL MAP_REGION_FLAT( \
+ bl2_el3_tzram_layout.total_base, \
+ bl2_el3_tzram_layout.total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+static meminfo_t bl2_el3_tzram_layout;
+
+/*
+ * Perform arm specific early platform setup. At this moment we only initialize
+ * the console and the memory layout.
+ */
+void arm_bl2_el3_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+ /*
+ * Allow BL2 to see the whole Trusted RAM. This is determined
+ * statically since we cannot rely on BL1 passing this information
+ * in the BL2_AT_EL3 case.
+ */
+ bl2_el3_tzram_layout.total_base = ARM_BL_RAM_BASE;
+ bl2_el3_tzram_layout.total_size = ARM_BL_RAM_SIZE;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_arm_io_setup();
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ arm_bl2_el3_early_platform_setup();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_arm_interconnect_init();
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ plat_arm_interconnect_enter_coherency();
+
+ generic_delay_timer_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void arm_bl2_el3_plat_arch_setup(void)
+{
+
+#if USE_COHERENT_MEM
+ /* Ensure ARM platforms dont use coherent memory in BL2_AT_EL3 */
+ assert(BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE == 0U);
+#endif
+
+ const mmap_region_t bl_regions[] = {
+ MAP_BL2_EL3_TOTAL,
+ ARM_MAP_BL_RO,
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+
+#ifdef __aarch64__
+ enable_mmu_el3(0);
+#else
+ enable_mmu_svc_mon(0);
+#endif
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ arm_bl2_el3_plat_arch_setup();
+}
+
+void bl2_el3_plat_prepare_exit(void)
+{
+}
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
new file mode 100644
index 0000000..08c014d
--- /dev/null
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/partition/partition.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#if ENABLE_RME
+#include <lib/gpt_rme/gpt_rme.h>
+#endif /* ENABLE_RME */
+#ifdef SPD_opteed
+#include <lib/optee_utils.h>
+#endif
+#include <lib/utils.h>
+#if ENABLE_RME
+#include <plat/arm/common/arm_pas_def.h>
+#endif /* ENABLE_RME */
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/* Base address of fw_config received from BL1 */
+static uintptr_t config_base;
+
+/*
+ * Check that BL2_BASE is above ARM_FW_CONFIG_LIMIT. This reserved page is
+ * for `meminfo_t` data structure and fw_configs passed from BL1.
+ */
+CASSERT(BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl2_base_overflows);
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak bl2_early_platform_setup2
+#pragma weak bl2_platform_setup
+#pragma weak bl2_plat_arch_setup
+#pragma weak bl2_plat_sec_mem_layout
+
+#if ENABLE_RME
+#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
+ bl2_tzram_layout.total_base, \
+ bl2_tzram_layout.total_size, \
+ MT_MEMORY | MT_RW | MT_ROOT)
+#else
+#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
+ bl2_tzram_layout.total_base, \
+ bl2_tzram_layout.total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif /* ENABLE_RME */
+
+#pragma weak arm_bl2_plat_handle_post_image_load
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted SRAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted SRAM.
+ * Copy it to a safe location before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+void arm_bl2_early_platform_setup(uintptr_t fw_config,
+ struct meminfo *mem_layout)
+{
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ config_base = fw_config;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_arm_io_setup();
+
+ /* Load partition table */
+#if ARM_GPT_SUPPORT
+ partition_init(GPT_IMAGE_ID);
+#endif /* ARM_GPT_SUPPORT */
+
+}
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
+{
+ arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
+
+ generic_delay_timer_init();
+}
+
+/*
+ * Perform BL2 preload setup. Currently we initialise the dynamic
+ * configuration here.
+ */
+void bl2_plat_preload_setup(void)
+{
+ arm_bl2_dyn_cfg_init();
+
+#if ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT
+ /* Always use the FIP from bank 0 */
+ arm_set_fip_addr(0U);
+#endif /* ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT */
+}
+
+/*
+ * Perform ARM standard platform setup.
+ */
+void arm_bl2_platform_setup(void)
+{
+#if !ENABLE_RME
+ /* Initialize the secure environment */
+ plat_arm_security_setup();
+#endif
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+ arm_nor_psci_do_static_mem_protect();
+#endif
+}
+
+void bl2_platform_setup(void)
+{
+ arm_bl2_platform_setup();
+}
+
+#if ENABLE_RME
+
+static void arm_bl2_plat_gpt_setup(void)
+{
+ /*
+ * The GPT library might modify the gpt regions structure to optimize
+ * the layout, so the array cannot be constant.
+ */
+ pas_region_t pas_regions[] = {
+ ARM_PAS_KERNEL,
+ ARM_PAS_SECURE,
+ ARM_PAS_REALM,
+ ARM_PAS_EL3_DRAM,
+ ARM_PAS_GPTS
+ };
+
+ /* Initialize entire protected space to GPT_GPI_ANY. */
+ if (gpt_init_l0_tables(GPCCR_PPS_4GB, ARM_L0_GPT_ADDR_BASE,
+ ARM_L0_GPT_SIZE) < 0) {
+ ERROR("gpt_init_l0_tables() failed!\n");
+ panic();
+ }
+
+ /* Carve out defined PAS ranges. */
+ if (gpt_init_pas_l1_tables(GPCCR_PGS_4K,
+ ARM_L1_GPT_ADDR_BASE,
+ ARM_L1_GPT_SIZE,
+ pas_regions,
+ (unsigned int)(sizeof(pas_regions) /
+ sizeof(pas_region_t))) < 0) {
+ ERROR("gpt_init_pas_l1_tables() failed!\n");
+ panic();
+ }
+
+ INFO("Enabling Granule Protection Checks\n");
+ if (gpt_enable() < 0) {
+ ERROR("gpt_enable() failed!\n");
+ panic();
+ }
+}
+
+#endif /* ENABLE_RME */
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here.
+ * When RME is enabled the secure environment is initialised before
+ * initialising and enabling Granule Protection.
+ * This function initialises the MMU in a quick and dirty way.
+ ******************************************************************************/
+void arm_bl2_plat_arch_setup(void)
+{
+#if USE_COHERENT_MEM && !ARM_CRYPTOCELL_INTEG
+ /*
+ * Ensure ARM platforms don't use coherent memory in BL2 unless
+ * cryptocell integration is enabled.
+ */
+ assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U);
+#endif
+
+ const mmap_region_t bl_regions[] = {
+ MAP_BL2_TOTAL,
+ ARM_MAP_BL_RO,
+#if USE_ROMLIB
+ ARM_MAP_ROMLIB_CODE,
+ ARM_MAP_ROMLIB_DATA,
+#endif
+#if ARM_CRYPTOCELL_INTEG
+ ARM_MAP_BL_COHERENT_RAM,
+#endif
+ ARM_MAP_BL_CONFIG_REGION,
+#if ENABLE_RME
+ ARM_MAP_L0_GPT_REGION,
+#endif
+ {0}
+ };
+
+#if ENABLE_RME
+ /* Initialise the secure environment */
+ plat_arm_security_setup();
+#endif
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+
+#ifdef __aarch64__
+#if ENABLE_RME
+ /* BL2 runs in EL3 when RME enabled. */
+ assert(get_armv9_2_feat_rme_support() != 0U);
+ enable_mmu_el3(0);
+
+ /* Initialise and enable granule protection after MMU. */
+ arm_bl2_plat_gpt_setup();
+#else
+ enable_mmu_el1(0);
+#endif
+#else
+ enable_mmu_svc_mon(0);
+#endif
+
+ arm_setup_romlib();
+}
+
+void bl2_plat_arch_setup(void)
+{
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+
+ arm_bl2_plat_arch_setup();
+
+ /* Fill the properties struct with the info from the config dtb */
+ fconf_populate("FW_CONFIG", config_base);
+
+ /* TB_FW_CONFIG was also loaded by BL1 */
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ fconf_populate("TB_FW", tb_fw_config_info->config_addr);
+}
+
+int arm_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+ assert(bl_mem_params != NULL);
+
+ switch (image_id) {
+#ifdef __aarch64__
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+#endif
+ bl_mem_params->ep_info.spsr = arm_get_spsr_for_bl32_entry();
+ break;
+#endif
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = arm_get_spsr_for_bl33_entry();
+ break;
+
+#ifdef SCP_BL2_BASE
+ case SCP_BL2_IMAGE_ID:
+ /* The subsequent handling of SCP_BL2 is platform specific */
+ err = plat_arm_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+ if (err) {
+ WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+ }
+ break;
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD
+ /* For Secure Partitions we don't need post processing */
+ if ((image_id >= (MAX_NUMBER_IDS - MAX_SP_IDS)) &&
+ (image_id < MAX_NUMBER_IDS)) {
+ return 0;
+ }
+#endif
+ return arm_bl2_handle_post_image_load(image_id);
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return arm_bl2_plat_handle_post_image_load(image_id);
+}
diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c
new file mode 100644
index 0000000..3614c7d
--- /dev/null
+++ b/plat/arm/common/arm_bl2u_setup.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <drivers/generic_delay_timer.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak bl2u_platform_setup
+#pragma weak bl2u_early_platform_setup
+#pragma weak bl2u_plat_arch_setup
+
+#define MAP_BL2U_TOTAL MAP_REGION_FLAT( \
+ BL2U_BASE, \
+ BL2U_LIMIT - BL2U_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Perform ARM standard platform setup for BL2U
+ */
+void arm_bl2u_platform_setup(void)
+{
+ /* Initialize the secure environment */
+ plat_arm_security_setup();
+}
+
+void bl2u_platform_setup(void)
+{
+ arm_bl2u_platform_setup();
+}
+
+void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info)
+{
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+ generic_delay_timer_init();
+}
+
+/*******************************************************************************
+ * BL1 can pass platform dependent information to BL2U in x1.
+ * In case of ARM CSS platforms x1 contains SCP_BL2U image info.
+ * In case of ARM FVP platforms x1 is not used.
+ * In both cases, x0 contains the extents of the memory available to BL2U
+ ******************************************************************************/
+void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info)
+{
+ arm_bl2u_early_platform_setup(mem_layout, plat_info);
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ * The memory that is used by BL2U is only mapped.
+ ******************************************************************************/
+void arm_bl2u_plat_arch_setup(void)
+{
+
+#if USE_COHERENT_MEM
+ /* Ensure ARM platforms dont use coherent memory in BL2U */
+ assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U);
+#endif
+
+ const mmap_region_t bl_regions[] = {
+ MAP_BL2U_TOTAL,
+ ARM_MAP_BL_RO,
+#if USE_ROMLIB
+ ARM_MAP_ROMLIB_CODE,
+ ARM_MAP_ROMLIB_DATA,
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+
+#ifdef __aarch64__
+ enable_mmu_el1(0);
+#else
+ enable_mmu_svc_mon(0);
+#endif
+ arm_setup_romlib();
+}
+
+void bl2u_plat_arch_setup(void)
+{
+ arm_bl2u_plat_arch_setup();
+}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
new file mode 100644
index 0000000..cf403b1
--- /dev/null
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/debugfs.h>
+#include <lib/extensions/ras.h>
+#if ENABLE_RME
+#include <lib/gpt_rme/gpt_rme.h>
+#endif
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+#if ENABLE_RME
+static entry_point_info_t rmm_image_ep_info;
+#endif
+
+#if !RESET_TO_BL31
+/*
+ * Check that BL31_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
+ * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
+ */
+CASSERT(BL31_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
+#endif
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak bl31_early_platform_setup2
+#pragma weak bl31_platform_setup
+#pragma weak bl31_plat_arch_setup
+#pragma weak bl31_plat_get_next_image_ep_info
+
+#define MAP_BL31_TOTAL MAP_REGION_FLAT( \
+ BL31_START, \
+ BL31_END - BL31_START, \
+ MT_MEMORY | MT_RW | EL3_PAS)
+#if RECLAIM_INIT_CODE
+IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE);
+IMPORT_SYM(unsigned long, __INIT_CODE_END__, BL_CODE_END_UNALIGNED);
+IMPORT_SYM(unsigned long, __STACKS_END__, BL_STACKS_END_UNALIGNED);
+
+#define BL_INIT_CODE_END ((BL_CODE_END_UNALIGNED + PAGE_SIZE - 1) & \
+ ~(PAGE_SIZE - 1))
+#define BL_STACKS_END ((BL_STACKS_END_UNALIGNED + PAGE_SIZE - 1) & \
+ ~(PAGE_SIZE - 1))
+
+#define MAP_BL_INIT_CODE MAP_REGION_FLAT( \
+ BL_INIT_CODE_BASE, \
+ BL_INIT_CODE_END \
+ - BL_INIT_CODE_BASE, \
+ MT_CODE | EL3_PAS)
+#endif
+
+#if SEPARATE_NOBITS_REGION
+#define MAP_BL31_NOBITS MAP_REGION_FLAT( \
+ BL31_NOBITS_BASE, \
+ BL31_NOBITS_LIMIT \
+ - BL31_NOBITS_BASE, \
+ MT_MEMORY | MT_RW | EL3_PAS)
+
+#endif
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for the
+ * security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ if (type == NON_SECURE) {
+ next_image_info = &bl33_image_ep_info;
+ }
+#if ENABLE_RME
+ else if (type == REALM) {
+ next_image_info = &rmm_image_ep_info;
+ }
+#endif
+ else {
+ next_image_info = &bl32_image_ep_info;
+ }
+
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup common to ARM standard platforms.
+ * Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be
+ * done before the MMU is initialized so that the memory layout can be used
+ * while creating page tables. BL2 has flushed this information to memory, so
+ * we are guaranteed to pick up good data.
+ ******************************************************************************/
+void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config,
+ uintptr_t hw_config, void *plat_params_from_bl2)
+{
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+#if RESET_TO_BL31
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(from_bl2 == NULL);
+ assert(plat_params_from_bl2 == NULL);
+
+# ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+
+#if defined(SPD_spmd)
+ /* SPM (hafnium in secure world) expects SPM Core manifest base address
+ * in x0, which in !RESET_TO_BL31 case loaded after base of non shared
+ * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non
+ * shared SRAM is allocated to BL31, so to avoid overwriting of manifest
+ * keep it in the last page.
+ */
+ bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE +
+ PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE;
+#endif
+
+# endif /* BL32_BASE */
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+
+ bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#if ENABLE_RME
+ /*
+ * Populate entry point information for RMM.
+ * Only PC needs to be set as other fields are determined by RMMD.
+ */
+ rmm_image_ep_info.pc = RMM_BASE;
+#endif /* ENABLE_RME */
+
+#else /* RESET_TO_BL31 */
+
+ /*
+ * In debug builds, we pass a special value in 'plat_params_from_bl2'
+ * to verify platform parameters from BL2 to BL31.
+ * In release builds, it's not used.
+ */
+ assert(((unsigned long long)plat_params_from_bl2) ==
+ ARM_BL31_PLAT_PARAM_VAL);
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33, BL32 and RMM (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params != NULL) {
+ if (bl_params->image_id == BL32_IMAGE_ID) {
+ bl32_image_ep_info = *bl_params->ep_info;
+ }
+#if ENABLE_RME
+ else if (bl_params->image_id == RMM_IMAGE_ID) {
+ rmm_image_ep_info = *bl_params->ep_info;
+ }
+#endif
+ else if (bl_params->image_id == BL33_IMAGE_ID) {
+ bl33_image_ep_info = *bl_params->ep_info;
+ }
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0U)
+ panic();
+#if ENABLE_RME
+ if (rmm_image_ep_info.pc == 0U)
+ panic();
+#endif
+#endif /* RESET_TO_BL31 */
+
+# if ARM_LINUX_KERNEL_AS_BL33
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ * Repurpose the option to load Hafnium hypervisor in the normal world.
+ * It expects its manifest address in x0. This is essentially the linux
+ * dts (passed to the primary VM) by adding 'hypervisor' and chosen
+ * nodes specifying the Hypervisor configuration.
+ */
+#if RESET_TO_BL31
+ bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE;
+#else
+ bl33_image_ep_info.args.arg0 = (u_register_t)hw_config;
+#endif
+ bl33_image_ep_info.args.arg1 = 0U;
+ bl33_image_ep_info.args.arg2 = 0U;
+ bl33_image_ep_info.args.arg3 = 0U;
+# endif
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_arm_interconnect_init();
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this (e.g. Trusted
+ * Firmware's BL1 does it) but we can't assume so. There is no harm in
+ * executing this code twice anyway.
+ * Platform specific PSCI code will enable coherency for other
+ * clusters.
+ */
+ plat_arm_interconnect_enter_coherency();
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ ******************************************************************************/
+void arm_bl31_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ plat_arm_gic_driver_init();
+ plat_arm_gic_init();
+
+#if RESET_TO_BL31
+ /*
+ * Do initial security configuration to allow DRAM/device access
+ * (if earlier BL has not already done so).
+ */
+ plat_arm_security_setup();
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+ arm_nor_psci_do_dyn_mem_protect();
+#endif /* PLAT_ARM_MEM_PROT_ADDR */
+
+#endif /* RESET_TO_BL31 */
+
+ /* Enable and initialize the System level generic timer */
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0U) | CNTCR_EN);
+
+ /* Allow access to the System counter timer module */
+ arm_configure_sys_timer();
+
+ /* Initialize power controller before setting up topology */
+ plat_arm_pwrc_setup();
+
+#if RAS_EXTENSION
+ ras_init();
+#endif
+
+#if USE_DEBUGFS
+ debugfs_init();
+#endif /* USE_DEBUGFS */
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM
+ * standard platforms
+ * Perform BL31 platform setup
+ ******************************************************************************/
+void arm_bl31_plat_runtime_setup(void)
+{
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+
+ /* Initialize the runtime console */
+ arm_console_runtime_init();
+
+#if RECLAIM_INIT_CODE
+ arm_free_init_memory();
+#endif
+
+#if PLAT_RO_XLAT_TABLES
+ arm_xlat_make_tables_readonly();
+#endif
+}
+
+#if RECLAIM_INIT_CODE
+/*
+ * Make memory for image boot time code RW to reclaim it as stack for the
+ * secondary cores, or RO where it cannot be reclaimed:
+ *
+ * |-------- INIT SECTION --------|
+ * -----------------------------------------
+ * | CORE 0 | CORE 1 | CORE 2 | EXTRA |
+ * | STACK | STACK | STACK | SPACE |
+ * -----------------------------------------
+ * <-------------------> <------>
+ * MAKE RW AND XN MAKE
+ * FOR STACKS RO AND XN
+ */
+void arm_free_init_memory(void)
+{
+ int ret = 0;
+
+ if (BL_STACKS_END < BL_INIT_CODE_END) {
+ /* Reclaim some of the init section as stack if possible. */
+ if (BL_INIT_CODE_BASE < BL_STACKS_END) {
+ ret |= xlat_change_mem_attributes(BL_INIT_CODE_BASE,
+ BL_STACKS_END - BL_INIT_CODE_BASE,
+ MT_RW_DATA);
+ }
+ /* Make the rest of the init section read-only. */
+ ret |= xlat_change_mem_attributes(BL_STACKS_END,
+ BL_INIT_CODE_END - BL_STACKS_END,
+ MT_RO_DATA);
+ } else {
+ /* The stacks cover the init section, so reclaim it all. */
+ ret |= xlat_change_mem_attributes(BL_INIT_CODE_BASE,
+ BL_INIT_CODE_END - BL_INIT_CODE_BASE,
+ MT_RW_DATA);
+ }
+
+ if (ret != 0) {
+ ERROR("Could not reclaim initialization code");
+ panic();
+ }
+}
+#endif
+
+void __init bl31_platform_setup(void)
+{
+ arm_bl31_platform_setup();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ arm_bl31_plat_runtime_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ ******************************************************************************/
+void __init arm_bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL31_TOTAL,
+#if ENABLE_RME
+ ARM_MAP_L0_GPT_REGION,
+#endif
+#if RECLAIM_INIT_CODE
+ MAP_BL_INIT_CODE,
+#endif
+#if SEPARATE_NOBITS_REGION
+ MAP_BL31_NOBITS,
+#endif
+ ARM_MAP_BL_RO,
+#if USE_ROMLIB
+ ARM_MAP_ROMLIB_CODE,
+ ARM_MAP_ROMLIB_DATA,
+#endif
+#if USE_COHERENT_MEM
+ ARM_MAP_BL_COHERENT_RAM,
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+
+ enable_mmu_el3(0);
+
+#if ENABLE_RME
+ /*
+ * Initialise Granule Protection library and enable GPC for the primary
+ * processor. The tables have already been initialized by a previous BL
+ * stage, so there is no need to provide any PAS here. This function
+ * sets up pointers to those tables.
+ */
+ if (gpt_runtime_init() < 0) {
+ ERROR("gpt_runtime_init() failed!\n");
+ panic();
+ }
+#endif /* ENABLE_RME */
+
+ arm_setup_romlib();
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+ arm_bl31_plat_arch_setup();
+}
diff --git a/plat/arm/common/arm_cci.c b/plat/arm/common/arm_cci.c
new file mode 100644
index 0000000..3795fc5
--- /dev/null
+++ b/plat/arm/common/arm_cci.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <drivers/arm/cci.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+
+static const int cci_map[] = {
+ PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX
+};
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way ARM CCI driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_interconnect_init
+#pragma weak plat_arm_interconnect_enter_coherency
+#pragma weak plat_arm_interconnect_exit_coherency
+
+
+/******************************************************************************
+ * Helper function to initialize ARM CCI driver.
+ *****************************************************************************/
+void __init plat_arm_interconnect_init(void)
+{
+ cci_init(PLAT_ARM_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/arm/common/arm_ccn.c b/plat/arm/common/arm_ccn.c
new file mode 100644
index 0000000..2e681ca
--- /dev/null
+++ b/plat/arm/common/arm_ccn.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <drivers/arm/ccn.h>
+#include <plat/arm/common/plat_arm.h>
+
+static const unsigned char master_to_rn_id_map[] = {
+ PLAT_ARM_CLUSTER_TO_CCN_ID_MAP
+};
+
+static const ccn_desc_t arm_ccn_desc = {
+ .periphbase = PLAT_ARM_CCN_BASE,
+ .num_masters = ARRAY_SIZE(master_to_rn_id_map),
+ .master_to_rn_id_map = master_to_rn_id_map
+};
+
+CASSERT(PLAT_ARM_CLUSTER_COUNT == ARRAY_SIZE(master_to_rn_id_map),
+ assert_invalid_cluster_count_for_ccn_variant);
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way ARM CCN driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_interconnect_init
+#pragma weak plat_arm_interconnect_enter_coherency
+#pragma weak plat_arm_interconnect_exit_coherency
+
+
+/******************************************************************************
+ * Helper function to initialize ARM CCN driver.
+ *****************************************************************************/
+void __init plat_arm_interconnect_init(void)
+{
+ ccn_init(&arm_ccn_desc);
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+ ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+ ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
new file mode 100644
index 0000000..fc68114
--- /dev/null
+++ b/plat/arm/common/arm_common.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/romlib.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_get_ns_image_entrypoint
+#pragma weak plat_arm_get_mmap
+
+/* Conditionally provide a weak definition of plat_get_syscnt_freq2 to avoid
+ * conflicts with the definition in plat/common. */
+#pragma weak plat_get_syscnt_freq2
+
+/* Get ARM SOC-ID */
+#pragma weak plat_arm_get_soc_id
+
+/*******************************************************************************
+ * Changes the memory attributes for the region of mapped memory where the BL
+ * image's translation tables are located such that the tables will have
+ * read-only permissions.
+ ******************************************************************************/
+#if PLAT_RO_XLAT_TABLES
+void arm_xlat_make_tables_readonly(void)
+{
+ int rc = xlat_make_tables_readonly();
+
+ if (rc != 0) {
+ ERROR("Failed to make translation tables read-only at EL%u.\n",
+ get_current_el());
+ panic();
+ }
+
+ INFO("Translation tables are now read-only at EL%u.\n",
+ get_current_el());
+}
+#endif
+
+void arm_setup_romlib(void)
+{
+#if USE_ROMLIB
+ if (!rom_lib_init(ROMLIB_VERSION))
+ panic();
+#endif
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return PLAT_ARM_NS_IMAGE_BASE;
+#endif
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t arm_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifdef __aarch64__
+uint32_t arm_get_spsr_for_bl33_entry(void)
+{
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#else
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t arm_get_spsr_for_bl33_entry(void)
+{
+ unsigned int hyp_status, mode, spsr;
+
+ hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+ mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#endif /* __aarch64__ */
+
+/*******************************************************************************
+ * Configures access to the system counter timer module.
+ ******************************************************************************/
+#ifdef ARM_SYS_TIMCTL_BASE
+void arm_configure_sys_timer(void)
+{
+ unsigned int reg_val;
+
+ /* Read the frequency of the system counter */
+ unsigned int freq_val = plat_get_syscnt_freq2();
+
+#if ARM_CONFIG_CNTACR
+ reg_val = (1U << CNTACR_RPCT_SHIFT) | (1U << CNTACR_RVCT_SHIFT);
+ reg_val |= (1U << CNTACR_RFRQ_SHIFT) | (1U << CNTACR_RVOFF_SHIFT);
+ reg_val |= (1U << CNTACR_RWVT_SHIFT) | (1U << CNTACR_RWPT_SHIFT);
+ mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTACR_BASE(PLAT_ARM_NSTIMER_FRAME_ID), reg_val);
+#endif /* ARM_CONFIG_CNTACR */
+
+ reg_val = (1U << CNTNSAR_NS_SHIFT(PLAT_ARM_NSTIMER_FRAME_ID));
+ mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+ /*
+ * Initialize CNTFRQ register in CNTCTLBase frame. The CNTFRQ
+ * system register initialized during psci_arch_setup() is different
+ * from this and has to be updated independently.
+ */
+ mmio_write_32(ARM_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val);
+
+#if defined(PLAT_juno) || defined(PLAT_n1sdp) || defined(PLAT_morello)
+ /*
+ * Initialize CNTFRQ register in Non-secure CNTBase frame.
+ * This is required for Juno, N1SDP and Morello because they do not
+ * follow ARM ARM in that the value updated in CNTFRQ is not
+ * reflected in CNTBASEN_CNTFRQ. Hence update the value manually.
+ */
+ mmio_write_32(ARM_SYS_CNT_BASE_NS + CNTBASEN_CNTFRQ, freq_val);
+#endif
+}
+#endif /* ARM_SYS_TIMCTL_BASE */
+
+/*******************************************************************************
+ * Returns ARM platform specific memory map regions.
+ ******************************************************************************/
+const mmap_region_t *plat_arm_get_mmap(void)
+{
+ return plat_arm_mmap;
+}
+
+#ifdef ARM_SYS_CNTCTL_BASE
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+
+ /* Read the frequency from Frequency modes table */
+ counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
+
+ /* The first entry of the frequency modes table must not be 0 */
+ if (counter_base_frequency == 0U)
+ panic();
+
+ return counter_base_frequency;
+}
+
+#endif /* ARM_SYS_CNTCTL_BASE */
+
+#if SDEI_SUPPORT
+/*
+ * Translate SDEI entry point to PA, and perform standard ARM entry point
+ * validation on it.
+ */
+int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode)
+{
+ uint64_t par, pa;
+ u_register_t scr_el3;
+
+ /* Doing Non-secure address translation requires SCR_EL3.NS set */
+ scr_el3 = read_scr_el3();
+ write_scr_el3(scr_el3 | SCR_NS_BIT);
+ isb();
+
+ assert((client_mode == MODE_EL2) || (client_mode == MODE_EL1));
+ if (client_mode == MODE_EL2) {
+ /*
+ * Translate entry point to Physical Address using the EL2
+ * translation regime.
+ */
+ ats1e2r(ep);
+ } else {
+ /*
+ * Translate entry point to Physical Address using the EL1&0
+ * translation regime, including stage 2.
+ */
+ AT(ats12e1r, ep);
+ }
+ isb();
+ par = read_par_el1();
+
+ /* Restore original SCRL_EL3 */
+ write_scr_el3(scr_el3);
+ isb();
+
+ /* If the translation resulted in fault, return failure */
+ if ((par & PAR_F_MASK) != 0)
+ return -1;
+
+ /* Extract Physical Address from PAR */
+ pa = (par & (PAR_ADDR_MASK << PAR_ADDR_SHIFT));
+
+ /* Perform NS entry point validation on the physical address */
+ return arm_validate_ns_entrypoint(pa);
+}
+#endif
+
+const mmap_region_t *plat_get_addr_mmap(void)
+{
+ return plat_arm_mmap;
+}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
new file mode 100644
index 0000000..7162ce9
--- /dev/null
+++ b/plat/arm/common/arm_common.mk
@@ -0,0 +1,456 @@
+#
+# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+ifeq (${ARCH}, aarch64)
+ # On ARM standard platorms, the TSP can execute from Trusted SRAM, Trusted
+ # DRAM (if available) or the TZC secured area of DRAM.
+ # TZC secured DRAM is the default.
+
+ ARM_TSP_RAM_LOCATION ?= dram
+
+ ifeq (${ARM_TSP_RAM_LOCATION}, tsram)
+ ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID
+ else ifeq (${ARM_TSP_RAM_LOCATION}, tdram)
+ ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_DRAM_ID
+ else ifeq (${ARM_TSP_RAM_LOCATION}, dram)
+ ARM_TSP_RAM_LOCATION_ID = ARM_DRAM_ID
+ else
+ $(error "Unsupported ARM_TSP_RAM_LOCATION value")
+ endif
+
+ # Process flags
+ # Process ARM_BL31_IN_DRAM flag
+ ARM_BL31_IN_DRAM := 0
+ $(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
+ $(eval $(call add_define,ARM_BL31_IN_DRAM))
+else
+ ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID
+endif
+
+$(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID))
+
+
+# For the original power-state parameter format, the State-ID can be encoded
+# according to the recommended encoding or zero. This flag determines which
+# State-ID encoding to be parsed.
+ARM_RECOM_STATE_ID_ENC := 0
+
+# If the PSCI_EXTENDED_STATE_ID is set, then ARM_RECOM_STATE_ID_ENC need to
+# be set. Else throw a build error.
+ifeq (${PSCI_EXTENDED_STATE_ID}, 1)
+ ifeq (${ARM_RECOM_STATE_ID_ENC}, 0)
+ $(error Build option ARM_RECOM_STATE_ID_ENC needs to be set if \
+ PSCI_EXTENDED_STATE_ID is set for ARM platforms)
+ endif
+endif
+
+# Process ARM_RECOM_STATE_ID_ENC flag
+$(eval $(call assert_boolean,ARM_RECOM_STATE_ID_ENC))
+$(eval $(call add_define,ARM_RECOM_STATE_ID_ENC))
+
+# Process ARM_DISABLE_TRUSTED_WDOG flag
+# By default, Trusted Watchdog is always enabled unless
+# SPIN_ON_BL1_EXIT or ENABLE_RME is set
+ARM_DISABLE_TRUSTED_WDOG := 0
+ifneq ($(filter 1,${SPIN_ON_BL1_EXIT} ${ENABLE_RME}),)
+ARM_DISABLE_TRUSTED_WDOG := 1
+endif
+$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG))
+$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG))
+
+# Process ARM_CONFIG_CNTACR
+ARM_CONFIG_CNTACR := 1
+$(eval $(call assert_boolean,ARM_CONFIG_CNTACR))
+$(eval $(call add_define,ARM_CONFIG_CNTACR))
+
+# Process ARM_BL31_IN_DRAM flag
+ARM_BL31_IN_DRAM := 0
+$(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
+$(eval $(call add_define,ARM_BL31_IN_DRAM))
+
+# As per CCA security model, all root firmware must execute from on-chip secure
+# memory. This means we must not run BL31 from TZC-protected DRAM.
+ifeq (${ARM_BL31_IN_DRAM},1)
+ ifeq (${ENABLE_RME},1)
+ $(error "BL31 must not run from DRAM on RME-systems. Please set ARM_BL31_IN_DRAM to 0")
+ endif
+endif
+
+# Process ARM_PLAT_MT flag
+ARM_PLAT_MT := 0
+$(eval $(call assert_boolean,ARM_PLAT_MT))
+$(eval $(call add_define,ARM_PLAT_MT))
+
+# Use translation tables library v2 by default
+ARM_XLAT_TABLES_LIB_V1 := 0
+$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
+$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
+
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33 := 0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
+
+ifeq (${ARM_LINUX_KERNEL_AS_BL33},1)
+ ifneq (${ARCH},aarch64)
+ ifneq (${RESET_TO_SP_MIN},1)
+ $(error "ARM_LINUX_KERNEL_AS_BL33 is only available if RESET_TO_SP_MIN=1.")
+ endif
+ endif
+ ifndef PRELOADED_BL33_BASE
+ $(error "PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
+ endif
+ ifeq (${RESET_TO_BL31},1)
+ ifndef ARM_PRELOADED_DTB_BASE
+ $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is
+ used with RESET_TO_BL31.")
+ endif
+ $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+ endif
+endif
+
+# Arm(R) Ethos(TM)-N NPU SiP service
+ARM_ETHOSN_NPU_DRIVER := 0
+$(eval $(call assert_boolean,ARM_ETHOSN_NPU_DRIVER))
+$(eval $(call add_define,ARM_ETHOSN_NPU_DRIVER))
+
+# Use an implementation of SHA-256 with a smaller memory footprint but reduced
+# speed.
+$(eval $(call add_define,MBEDTLS_SHA256_SMALLER))
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
+# Enable PSCI_STAT_COUNT/RESIDENCY APIs on ARM platforms
+ENABLE_PSCI_STAT := 1
+ENABLE_PMF := 1
+
+# Override the standard libc with optimised libc_asm
+OVERRIDE_LIBC := 1
+ifeq (${OVERRIDE_LIBC},1)
+ include lib/libc/libc_asm.mk
+endif
+
+# On ARM platforms, separate the code and read-only data sections to allow
+# mapping the former as executable and the latter as execute-never.
+SEPARATE_CODE_AND_RODATA := 1
+
+# On ARM platforms, disable SEPARATE_NOBITS_REGION by default. Both PROGBITS
+# and NOBITS sections of BL31 image are adjacent to each other and loaded
+# into Trusted SRAM.
+SEPARATE_NOBITS_REGION := 0
+
+# In order to support SEPARATE_NOBITS_REGION for Arm platforms, we need to load
+# BL31 PROGBITS into secure DRAM space and BL31 NOBITS into SRAM. Hence mandate
+# the build to require that ARM_BL31_IN_DRAM is enabled as well.
+ifeq ($(SEPARATE_NOBITS_REGION),1)
+ ifneq ($(ARM_BL31_IN_DRAM),1)
+ $(error For SEPARATE_NOBITS_REGION, ARM_BL31_IN_DRAM must be enabled)
+ endif
+ ifneq ($(RECLAIM_INIT_CODE),0)
+ $(error For SEPARATE_NOBITS_REGION, RECLAIM_INIT_CODE cannot be supported)
+ endif
+endif
+
+# Disable ARM Cryptocell by default
+ARM_CRYPTOCELL_INTEG := 0
+$(eval $(call assert_boolean,ARM_CRYPTOCELL_INTEG))
+$(eval $(call add_define,ARM_CRYPTOCELL_INTEG))
+
+# Enable PIE support for RESET_TO_BL31/RESET_TO_SP_MIN case
+ifneq ($(filter 1,${RESET_TO_BL31} ${RESET_TO_SP_MIN}),)
+ ENABLE_PIE := 1
+endif
+
+# CryptoCell integration relies on coherent buffers for passing data from
+# the AP CPU to the CryptoCell
+ifeq (${ARM_CRYPTOCELL_INTEG},1)
+ ifeq (${USE_COHERENT_MEM},0)
+ $(error "ARM_CRYPTOCELL_INTEG needs USE_COHERENT_MEM to be set.")
+ endif
+endif
+
+# Disable GPT parser support, use FIP image by default
+ARM_GPT_SUPPORT := 0
+$(eval $(call assert_boolean,ARM_GPT_SUPPORT))
+$(eval $(call add_define,ARM_GPT_SUPPORT))
+
+# Include necessary sources to parse GPT image
+ifeq (${ARM_GPT_SUPPORT}, 1)
+ BL2_SOURCES += drivers/partition/gpt.c \
+ drivers/partition/partition.c
+endif
+
+# Enable CRC instructions via extension for ARMv8-A CPUs.
+# For ARMv8.1-A, and onwards CRC instructions are default enabled.
+# Enable HW computed CRC support unconditionally in BL2 component.
+ifeq (${ARM_ARCH_MAJOR},8)
+ ifeq (${ARM_ARCH_MINOR},0)
+ BL2_CPPFLAGS += -march=armv8-a+crc
+ endif
+endif
+
+ifeq ($(PSA_FWU_SUPPORT),1)
+ # GPT support is recommended as per PSA FWU specification hence
+ # PSA FWU implementation is tightly coupled with GPT support,
+ # and it does not support other formats.
+ ifneq ($(ARM_GPT_SUPPORT),1)
+ $(error For PSA_FWU_SUPPORT, ARM_GPT_SUPPORT must be enabled)
+ endif
+ FWU_MK := drivers/fwu/fwu.mk
+ $(info Including ${FWU_MK})
+ include ${FWU_MK}
+endif
+
+ifeq (${ARCH}, aarch64)
+PLAT_INCLUDES += -Iinclude/plat/arm/common/aarch64
+endif
+
+PLAT_BL_COMMON_SOURCES += plat/arm/common/${ARCH}/arm_helpers.S \
+ plat/arm/common/arm_common.c \
+ plat/arm/common/arm_console.c
+
+ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/${ARCH}/xlat_tables.c
+else
+ifeq (${XLAT_MPU_LIB_V1}, 1)
+include lib/xlat_mpu/xlat_mpu.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_MPU_LIB_V1_SRCS}
+else
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+endif
+endif
+
+ARM_IO_SOURCES += plat/arm/common/arm_io_storage.c \
+ plat/arm/common/fconf/arm_fconf_io.c
+ifeq (${SPD},spmd)
+ ifeq (${BL2_ENABLE_SP_LOAD},1)
+ ARM_IO_SOURCES += plat/arm/common/fconf/arm_fconf_sp.c
+ endif
+endif
+
+BL1_SOURCES += drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/arm/common/arm_bl1_setup.c \
+ plat/arm/common/arm_err.c \
+ ${ARM_IO_SOURCES}
+
+ifdef EL3_PAYLOAD_BASE
+# Need the plat_arm_program_trusted_mailbox() function to release secondary CPUs from
+# their holding pen
+BL1_SOURCES += plat/arm/common/arm_pm.c
+endif
+
+BL2_SOURCES += drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/arm/common/arm_bl2_setup.c \
+ plat/arm/common/arm_err.c \
+ common/tf_crc32.c \
+ ${ARM_IO_SOURCES}
+
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
+
+BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+
+# Add `libfdt` and Arm common helpers required for Dynamic Config
+include lib/libfdt/libfdt.mk
+
+DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \
+ plat/arm/common/arm_dyn_cfg_helpers.c \
+ common/uuid.c
+
+DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+BL1_SOURCES += ${DYN_CFG_SOURCES}
+BL2_SOURCES += ${DYN_CFG_SOURCES}
+
+ifeq (${BL2_AT_EL3},1)
+BL2_SOURCES += plat/arm/common/arm_bl2_el3_setup.c
+endif
+
+# Because BL1/BL2 execute in AArch64 mode but BL32 in AArch32 we need to use
+# the AArch32 descriptors.
+ifeq (${JUNO_AARCH32_EL3_RUNTIME},1)
+BL2_SOURCES += plat/arm/common/aarch32/arm_bl2_mem_params_desc.c
+else
+ifneq (${PLAT}, corstone1000)
+BL2_SOURCES += plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c
+endif
+endif
+BL2_SOURCES += plat/arm/common/arm_image_load.c \
+ common/desc_image_load.c
+ifeq (${SPD},opteed)
+BL2_SOURCES += lib/optee/optee_utils.c
+endif
+
+BL2U_SOURCES += drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ plat/arm/common/arm_bl2u_setup.c
+
+BL31_SOURCES += plat/arm/common/arm_bl31_setup.c \
+ plat/arm/common/arm_pm.c \
+ plat/arm/common/arm_topology.c \
+ plat/common/plat_psci_common.c
+
+ifneq ($(filter 1,${ENABLE_PMF} ${ARM_ETHOSN_NPU_DRIVER}),)
+ARM_SVC_HANDLER_SRCS :=
+
+ifeq (${ENABLE_PMF},1)
+ARM_SVC_HANDLER_SRCS += lib/pmf/pmf_smc.c
+endif
+
+ifeq (${ARM_ETHOSN_NPU_DRIVER},1)
+ARM_SVC_HANDLER_SRCS += plat/arm/common/fconf/fconf_ethosn_getter.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/arm/ethosn/ethosn_smc.c
+endif
+
+ifeq (${ARCH}, aarch64)
+BL31_SOURCES += plat/arm/common/aarch64/execution_state_switch.c\
+ plat/arm/common/arm_sip_svc.c \
+ ${ARM_SVC_HANDLER_SRCS}
+else
+BL32_SOURCES += plat/arm/common/arm_sip_svc.c \
+ ${ARM_SVC_HANDLER_SRCS}
+endif
+endif
+
+ifeq (${EL3_EXCEPTION_HANDLING},1)
+BL31_SOURCES += plat/common/aarch64/plat_ehf.c
+endif
+
+ifeq (${SDEI_SUPPORT},1)
+BL31_SOURCES += plat/arm/common/aarch64/arm_sdei.c
+ifeq (${SDEI_IN_FCONF},1)
+BL31_SOURCES += plat/arm/common/fconf/fconf_sdei_getter.c
+endif
+endif
+
+# RAS sources
+ifeq (${RAS_EXTENSION},1)
+BL31_SOURCES += lib/extensions/ras/std_err_record.c \
+ lib/extensions/ras/ras_common.c
+endif
+
+# Pointer Authentication sources
+ifeq (${ENABLE_PAUTH}, 1)
+PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c \
+ lib/extensions/pauth/pauth_helpers.S
+endif
+
+ifeq (${SPD},spmd)
+BL31_SOURCES += plat/common/plat_spmd_manifest.c \
+ common/uuid.c \
+ ${LIBFDT_SRCS}
+
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+endif
+
+ifeq (${DRTM_SUPPORT},1)
+BL31_SOURCES += plat/arm/common/arm_err.c
+endif
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+ # Include common TBB sources
+ AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/img_parser_mod.c
+
+ # Include the selected chain of trust sources.
+ ifeq (${COT},tbbr)
+ BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl1.c
+ ifneq (${COT_DESC_IN_DTB},0)
+ BL2_SOURCES += lib/fconf/fconf_cot_getter.c
+ else
+ BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+ endif
+ else ifeq (${COT},dualroot)
+ AUTH_SOURCES += drivers/auth/dualroot/cot.c
+ else ifeq (${COT},cca)
+ AUTH_SOURCES += drivers/auth/cca/cot.c
+ else
+ $(error Unknown chain of trust ${COT})
+ endif
+
+ BL1_SOURCES += ${AUTH_SOURCES} \
+ bl1/tbbr/tbbr_img_desc.c \
+ plat/arm/common/arm_bl1_fwu.c \
+ plat/common/tbbr/plat_tbbr.c
+
+ BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c
+
+ $(eval $(call TOOL_ADD_IMG,ns_bl2u,--fwu,FWU_))
+
+ IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk
+
+ $(info Including ${IMG_PARSER_LIB_MK})
+ include ${IMG_PARSER_LIB_MK}
+endif
+
+# Include Measured Boot makefile before any Crypto library makefile.
+# Crypto library makefile may need default definitions of Measured Boot build
+# flags present in Measured Boot makefile.
+ifneq ($(filter 1,${MEASURED_BOOT} ${DRTM_SUPPORT}),)
+ MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
+ $(info Including ${MEASURED_BOOT_MK})
+ include ${MEASURED_BOOT_MK}
+
+ ifneq (${MBOOT_EL_HASH_ALG}, sha256)
+ $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
+ endif
+
+ ifeq (${MEASURED_BOOT},1)
+ BL1_SOURCES += ${EVENT_LOG_SOURCES}
+ BL2_SOURCES += ${EVENT_LOG_SOURCES}
+ endif
+
+ ifeq (${DRTM_SUPPORT},1)
+ BL31_SOURCES += ${EVENT_LOG_SOURCES}
+ endif
+endif
+
+ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT} ${DRTM_SUPPORT}),)
+ CRYPTO_SOURCES := drivers/auth/crypto_mod.c \
+ lib/fconf/fconf_tbbr_getter.c
+ BL1_SOURCES += ${CRYPTO_SOURCES}
+ BL2_SOURCES += ${CRYPTO_SOURCES}
+ BL31_SOURCES += drivers/auth/crypto_mod.c
+
+ # We expect to locate the *.mk files under the directories specified below
+ ifeq (${ARM_CRYPTOCELL_INTEG},0)
+ CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk
+ else
+ CRYPTO_LIB_MK := drivers/auth/cryptocell/cryptocell_crypto.mk
+ endif
+
+ $(info Including ${CRYPTO_LIB_MK})
+ include ${CRYPTO_LIB_MK}
+endif
+
+ifeq (${RECLAIM_INIT_CODE}, 1)
+ ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+ $(error "To reclaim init code xlat tables v2 must be used")
+ endif
+endif
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
new file mode 100644
index 0000000..51830c9
--- /dev/null
+++ b/plat/arm/common/arm_console.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <plat/arm/common/plat_arm.h>
+
+#pragma weak arm_console_runtime_init
+#pragma weak arm_console_runtime_end
+
+/*******************************************************************************
+ * Functions that set up the console
+ ******************************************************************************/
+static console_t arm_boot_console;
+static console_t arm_runtime_console;
+
+/* Initialize the console to provide early debug support */
+void __init arm_console_boot_init(void)
+{
+ /* If the console was initialized already, don't initialize again */
+ if (arm_boot_console.base == PLAT_ARM_BOOT_UART_BASE) {
+ return;
+ }
+
+ int rc = console_pl011_register(PLAT_ARM_BOOT_UART_BASE,
+ PLAT_ARM_BOOT_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE,
+ &arm_boot_console);
+ if (rc == 0) {
+ /*
+ * The crash console doesn't use the multi console API, it uses
+ * the core console functions directly. It is safe to call panic
+ * and let it print debug information.
+ */
+ panic();
+ }
+
+ console_set_scope(&arm_boot_console, CONSOLE_FLAG_BOOT);
+}
+
+void arm_console_boot_end(void)
+{
+ console_flush();
+ (void)console_unregister(&arm_boot_console);
+}
+
+/* Initialize the runtime console */
+void arm_console_runtime_init(void)
+{
+ int rc = console_pl011_register(PLAT_ARM_RUN_UART_BASE,
+ PLAT_ARM_RUN_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE,
+ &arm_runtime_console);
+ if (rc == 0)
+ panic();
+
+ console_set_scope(&arm_runtime_console, CONSOLE_FLAG_RUNTIME);
+}
+
+void arm_console_runtime_end(void)
+{
+ console_flush();
+}
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
new file mode 100644
index 0000000..c88621e
--- /dev/null
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/tbbr/tbbr_img_def.h>
+#if CRYPTO_SUPPORT
+#include MBEDTLS_CONFIG_FILE
+#endif /* CRYPTO_SUPPORT */
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
+
+#include <plat/arm/common/arm_dyn_cfg_helpers.h>
+#include <plat/arm/common/plat_arm.h>
+
+#if CRYPTO_SUPPORT
+
+static void *mbedtls_heap_addr;
+static size_t mbedtls_heap_size;
+
+/*
+ * This function is the implementation of the shared Mbed TLS heap between
+ * BL1 and BL2 for Arm platforms. The shared heap address is passed from BL1
+ * to BL2 with a pointer. This pointer resides inside the TB_FW_CONFIG file
+ * which is a DTB.
+ *
+ * This function is placed inside an #if directive for the below reasons:
+ * - To allocate space for the Mbed TLS heap --only if-- Trusted Board Boot
+ * is enabled.
+ * - This implementation requires the DTB to be present so that BL1 has a
+ * mechanism to pass the pointer to BL2.
+ */
+int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+#if defined(IMAGE_BL1) || BL2_AT_EL3 || defined(IMAGE_BL31)
+
+ /* If in BL1 or BL2_AT_EL3 define a heap */
+ static unsigned char heap[TF_MBEDTLS_HEAP_SIZE];
+
+ *heap_addr = heap;
+ *heap_size = sizeof(heap);
+ mbedtls_heap_addr = heap;
+ mbedtls_heap_size = sizeof(heap);
+
+#elif defined(IMAGE_BL2)
+
+ /* If in BL2, retrieve the already allocated heap's info from DTB */
+ *heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr);
+ *heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size);
+
+#endif
+
+ return 0;
+}
+
+/*
+ * Puts the shared Mbed TLS heap information to the DTB.
+ * Executed only from BL1.
+ */
+void arm_bl1_set_mbedtls_heap(void)
+{
+ int err;
+ uintptr_t tb_fw_cfg_dtb;
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+
+ /*
+ * If tb_fw_cfg_dtb==NULL then DTB is not present for the current
+ * platform. As such, we don't attempt to write to the DTB at all.
+ *
+ * If mbedtls_heap_addr==NULL, then it means we are using the default
+ * heap implementation. As such, BL2 will have its own heap for sure
+ * and hence there is no need to pass any information to the DTB.
+ *
+ * In the latter case, if we still wanted to write in the DTB the heap
+ * information, we would need to call plat_get_mbedtls_heap to retrieve
+ * the default heap's address and size.
+ */
+
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
+
+ if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) {
+ /* As libfdt uses void *, we can't avoid this cast */
+ void *dtb = (void *)tb_fw_cfg_dtb;
+
+ err = arm_set_dtb_mbedtls_heap_info(dtb,
+ mbedtls_heap_addr, mbedtls_heap_size);
+ if (err < 0) {
+ ERROR("%swrite shared Mbed TLS heap information%s",
+ "BL1: unable to ", " to DTB\n");
+ panic();
+ }
+#if !MEASURED_BOOT
+ /*
+ * Ensure that the info written to the DTB is visible to other
+ * images. It's critical because BL2 won't be able to proceed
+ * without the heap info.
+ *
+ * In MEASURED_BOOT case flushing is done in a function which
+ * is called after heap information is written in the DTB.
+ */
+ flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize(dtb));
+#endif /* !MEASURED_BOOT */
+ }
+}
+#endif /* CRYPTO_SUPPORT */
+
+/*
+ * BL2 utility function to initialize dynamic configuration specified by
+ * FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if
+ * specified in FW_CONFIG.
+ */
+void arm_bl2_dyn_cfg_init(void)
+{
+ unsigned int i;
+ bl_mem_params_node_t *cfg_mem_params = NULL;
+ uintptr_t image_base;
+ uint32_t image_size;
+ unsigned int error_config_id = MAX_IMAGE_IDS;
+ const unsigned int config_ids[] = {
+ HW_CONFIG_ID,
+ SOC_FW_CONFIG_ID,
+ NT_FW_CONFIG_ID,
+ TOS_FW_CONFIG_ID
+ };
+
+ const struct dyn_cfg_dtb_info_t *dtb_info;
+
+ /* Iterate through all the fw config IDs */
+ for (i = 0; i < ARRAY_SIZE(config_ids); i++) {
+ /* Get the config load address and size */
+ cfg_mem_params = get_bl_mem_params_node(config_ids[i]);
+ if (cfg_mem_params == NULL) {
+ VERBOSE("%sconfig_id = %d in bl_mem_params_node\n",
+ "Couldn't find ", config_ids[i]);
+ continue;
+ }
+
+ dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]);
+ if (dtb_info == NULL) {
+ VERBOSE("%sconfig_id %d load info in FW_CONFIG\n",
+ "Couldn't find ", config_ids[i]);
+ continue;
+ }
+
+ image_base = dtb_info->config_addr;
+ image_size = dtb_info->config_max_size;
+
+ /*
+ * Do some runtime checks on the load addresses of soc_fw_config,
+ * tos_fw_config, nt_fw_config. This is not a comprehensive check
+ * of all invalid addresses but to prevent trivial porting errors.
+ */
+ if (config_ids[i] != HW_CONFIG_ID) {
+
+ if (check_uptr_overflow(image_base, image_size)) {
+ VERBOSE("%s=%d as its %s is overflowing uptr\n",
+ "skip loading of firmware config",
+ config_ids[i],
+ "load-address");
+ error_config_id = config_ids[i];
+ continue;
+ }
+#ifdef BL31_BASE
+ /* Ensure the configs don't overlap with BL31 */
+ if ((image_base >= BL31_BASE) &&
+ (image_base <= BL31_LIMIT)) {
+ VERBOSE("%s=%d as its %s is overlapping BL31\n",
+ "skip loading of firmware config",
+ config_ids[i],
+ "load-address");
+ error_config_id = config_ids[i];
+ continue;
+ }
+#endif
+ /* Ensure the configs are loaded in a valid address */
+ if (image_base < ARM_BL_RAM_BASE) {
+ VERBOSE("%s=%d as its %s is invalid\n",
+ "skip loading of firmware config",
+ config_ids[i],
+ "load-address");
+ error_config_id = config_ids[i];
+ continue;
+ }
+#ifdef BL32_BASE
+ /*
+ * If BL32 is present, ensure that the configs don't
+ * overlap with it.
+ */
+ if ((image_base >= BL32_BASE) &&
+ (image_base <= BL32_LIMIT)) {
+ VERBOSE("%s=%d as its %s is overlapping BL32\n",
+ "skip loading of firmware config",
+ config_ids[i],
+ "load-address");
+ error_config_id = config_ids[i];
+ continue;
+ }
+#endif
+ }
+
+ cfg_mem_params->image_info.image_base = image_base;
+ cfg_mem_params->image_info.image_max_size = (uint32_t)image_size;
+
+ /*
+ * Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from
+ * HW_CONFIG or FW_CONFIG nodes
+ */
+ cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+ }
+
+ if (error_config_id != MAX_IMAGE_IDS) {
+ ERROR("Invalid config file %u\n", error_config_id);
+ panic();
+ }
+}
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
new file mode 100644
index 0000000..e88ea65
--- /dev/null
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#if MEASURED_BOOT
+#include <common/desc_image_load.h>
+#endif
+#include <common/fdt_wrappers.h>
+
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <libfdt.h>
+
+#include <plat/arm/common/arm_dyn_cfg_helpers.h>
+#include <plat/arm/common/plat_arm.h>
+
+#define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr"
+#define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"
+
+#if MEASURED_BOOT
+#ifdef SPD_opteed
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this property should be removed when this feature is supported.
+ */
+#define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr"
+#endif /* SPD_opteed */
+#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
+#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
+#endif /* MEASURED_BOOT */
+
+/*******************************************************************************
+ * Validate the tb_fw_config is a valid DTB file and returns the node offset
+ * to "arm,tb_fw" property.
+ * Arguments:
+ * void *dtb - pointer to the TB_FW_CONFIG in memory
+ * int *node - Returns the node offset to "arm,tb_fw" property if found.
+ *
+ * Returns 0 on success and -1 on error.
+ ******************************************************************************/
+int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
+{
+ assert(dtb != NULL);
+ assert(node != NULL);
+
+ /* Check if the pointer to DT is correct */
+ if (fdt_check_header(dtb) != 0) {
+ WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG");
+ return -1;
+ }
+
+ /* Assert the node offset point to "arm,tb_fw" compatible property */
+ *node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
+ if (*node < 0) {
+ WARN("The compatible property '%s' not%s", "arm,tb_fw",
+ " found in the config\n");
+ return -1;
+ }
+
+ VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n");
+ return 0;
+}
+
+/*
+ * This function writes the Mbed TLS heap address and size in the DTB. When it
+ * is called, it is guaranteed that a DTB is available. However it is not
+ * guaranteed that the shared Mbed TLS heap implementation is used. Thus we
+ * return error code from here and it's the responsibility of the caller to
+ * determine the action upon error.
+ *
+ * This function is supposed to be called only by BL1.
+ *
+ * Returns:
+ * 0 = success
+ * -1 = error
+ */
+int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size)
+{
+ int dtb_root;
+
+ /*
+ * Verify that the DTB is valid, before attempting to write to it,
+ * and get the DTB root node.
+ */
+ int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
+ if (err < 0) {
+ ERROR("Invalid%s loaded. Unable to get root node\n",
+ " TB_FW_CONFIG");
+ return -1;
+ }
+
+ /*
+ * Write the heap address and size in the DTB.
+ *
+ * NOTE: The variables heap_addr and heap_size are corrupted
+ * by the "fdtw_write_inplace_cells" function. After the
+ * function calls they must NOT be reused.
+ */
+ err = fdtw_write_inplace_cells(dtb, dtb_root,
+ DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR);
+ return -1;
+ }
+
+ err = fdtw_write_inplace_cells(dtb, dtb_root,
+ DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE);
+ return -1;
+ }
+
+ return 0;
+}
+
+#if MEASURED_BOOT
+/*
+ * Write the Event Log address and its size in the DTB.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+static int arm_set_event_log_info(uintptr_t config_base,
+#ifdef SPD_opteed
+ uintptr_t sm_log_addr,
+#endif
+ uintptr_t log_addr, size_t log_size)
+{
+ /* As libfdt uses void *, we can't avoid this cast */
+ void *dtb = (void *)config_base;
+ const char *compatible = "arm,tpm_event_log";
+ int err, node;
+
+ /*
+ * Verify that the DTB is valid, before attempting to write to it,
+ * and get the DTB root node.
+ */
+
+ /* Check if the pointer to DT is correct */
+ err = fdt_check_header(dtb);
+ if (err < 0) {
+ WARN("Invalid DTB file passed\n");
+ return err;
+ }
+
+ /* Assert the node offset point to compatible property */
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible);
+ if (node < 0) {
+ WARN("The compatible property '%s' not%s", compatible,
+ " found in the config\n");
+ return node;
+ }
+
+ VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
+
+#ifdef SPD_opteed
+ if (sm_log_addr != 0UL) {
+ err = fdtw_write_inplace_cells(dtb, node,
+ DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_HW_SM_LOG_ADDR);
+ return err;
+ }
+ }
+#endif
+ err = fdtw_write_inplace_cells(dtb, node,
+ DTB_PROP_HW_LOG_ADDR, 2, &log_addr);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_HW_LOG_ADDR);
+ return err;
+ }
+
+ err = fdtw_write_inplace_cells(dtb, node,
+ DTB_PROP_HW_LOG_SIZE, 1, &log_size);
+ if (err < 0) {
+ ERROR("%sDTB property '%s'\n",
+ "Unable to write ", DTB_PROP_HW_LOG_SIZE);
+ } else {
+ /*
+ * Ensure that the info written to the DTB is visible
+ * to other images.
+ */
+ flush_dcache_range(config_base, fdt_totalsize(dtb));
+ }
+
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the TOS_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size)
+{
+ uintptr_t config_base;
+ const bl_mem_params_node_t *cfg_mem_params;
+ int err;
+
+ assert(log_addr != 0UL);
+
+ /* Get the config load address and size of TOS_FW_CONFIG */
+ cfg_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
+ assert(cfg_mem_params != NULL);
+
+ config_base = cfg_mem_params->image_info.image_base;
+
+ /* Write the Event Log address and its size in the DTB */
+ err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+ 0UL,
+#endif
+ log_addr, log_size);
+ if (err < 0) {
+ ERROR("%sEvent Log data to TOS_FW_CONFIG\n",
+ "Unable to write ");
+ }
+
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the NT_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int arm_set_nt_fw_info(
+#ifdef SPD_opteed
+ uintptr_t log_addr,
+#endif
+ size_t log_size, uintptr_t *ns_log_addr)
+{
+ uintptr_t config_base;
+ uintptr_t ns_addr;
+ const bl_mem_params_node_t *cfg_mem_params;
+ int err;
+
+ assert(ns_log_addr != NULL);
+
+ /* Get the config load address and size from NT_FW_CONFIG */
+ cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+ assert(cfg_mem_params != NULL);
+
+ config_base = cfg_mem_params->image_info.image_base;
+
+ /* Calculate Event Log address in Non-secure memory */
+ ns_addr = cfg_mem_params->image_info.image_base +
+ cfg_mem_params->image_info.image_max_size;
+
+ /* Check for memory space */
+ if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) {
+ return -1;
+ }
+
+ /* Write the Event Log address and its size in the DTB */
+ err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+ log_addr,
+#endif
+ ns_addr, log_size);
+
+ /* Return Event Log address in Non-secure memory */
+ *ns_log_addr = (err < 0) ? 0UL : ns_addr;
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the TB_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL1.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size)
+{
+ /*
+ * Read tb_fw_config device tree for Event Log properties
+ * and write the Event Log address and its size in the DTB
+ */
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+ uintptr_t tb_fw_cfg_dtb;
+ int err;
+
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
+
+ err = arm_set_event_log_info(tb_fw_cfg_dtb,
+#ifdef SPD_opteed
+ 0UL,
+#endif
+ log_addr, log_size);
+ return err;
+}
+
+/*
+ * This function reads the Event Log address and its size
+ * properties present in TB_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ * Alongside returns Event Log address and its size.
+ */
+
+int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size)
+{
+ /* As libfdt uses void *, we can't avoid this cast */
+ const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+ int node, rc;
+
+ tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+ assert(tb_fw_config_info != NULL);
+
+ void *dtb = (void *)tb_fw_config_info->config_addr;
+ const char *compatible = "arm,tpm_event_log";
+
+ /* Assert the node offset point to compatible property */
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible);
+ if (node < 0) {
+ WARN("The compatible property '%s'%s", compatible,
+ " not specified in TB_FW config.\n");
+ return node;
+ }
+
+ VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
+
+ rc = fdt_read_uint64(dtb, node, DTB_PROP_HW_LOG_ADDR, log_addr);
+ if (rc != 0) {
+ ERROR("%s%s", DTB_PROP_HW_LOG_ADDR,
+ " not specified in TB_FW config.\n");
+ return rc;
+ }
+
+ rc = fdt_read_uint32(dtb, node, DTB_PROP_HW_LOG_SIZE, (uint32_t *)log_size);
+ if (rc != 0) {
+ ERROR("%s%s", DTB_PROP_HW_LOG_SIZE,
+ " not specified in TB_FW config.\n");
+ }
+
+ return rc;
+}
+#endif /* MEASURED_BOOT */
diff --git a/plat/arm/common/arm_err.c b/plat/arm/common/arm_err.c
new file mode 100644
index 0000000..fa36e8d
--- /dev/null
+++ b/plat/arm/common/arm_err.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+void __dead2 plat_error_handler(int err)
+{
+ plat_arm_error_handler(err);
+}
+
+void __dead2 plat_system_reset(void)
+{
+ plat_arm_system_reset();
+}
diff --git a/plat/arm/common/arm_gicv2.c b/plat/arm/common/arm_gicv2.c
new file mode 100644
index 0000000..80a845f
--- /dev/null
+++ b/plat/arm/common/arm_gicv2.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/arm/gicv2.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv2 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_gic_driver_init
+#pragma weak plat_arm_gic_init
+#pragma weak plat_arm_gic_cpuif_enable
+#pragma weak plat_arm_gic_cpuif_disable
+#pragma weak plat_arm_gic_pcpu_init
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t arm_interrupt_props[] = {
+ PLAT_ARM_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ PLAT_ARM_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t arm_gic_data = {
+ .gicd_base = PLAT_ARM_GICD_BASE,
+ .gicc_base = PLAT_ARM_GICC_BASE,
+ .interrupt_props = arm_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(arm_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/******************************************************************************
+ * ARM common helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void plat_arm_gic_driver_init(void)
+{
+ gicv2_driver_init(&arm_gic_data);
+}
+
+void plat_arm_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * ARM common helper to enable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * ARM common helper to disable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_disable(void)
+{
+ gicv2_cpuif_disable();
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the per cpu distributor interface in GICv2
+ *****************************************************************************/
+void plat_arm_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Stubs for Redistributor power management. Although GICv2 doesn't have
+ * Redistributor interface, these are provided for the sake of uniform GIC API
+ *****************************************************************************/
+void plat_arm_gic_redistif_on(void)
+{
+ return;
+}
+
+void plat_arm_gic_redistif_off(void)
+{
+ return;
+}
+
+
+/******************************************************************************
+ * ARM common helper to save & restore the GICv3 on resume from system suspend.
+ * The normal world currently takes care of saving and restoring the GICv2
+ * registers due to legacy reasons. Hence we just initialize the Distributor
+ * on resume from system suspend.
+ *****************************************************************************/
+void plat_arm_gic_save(void)
+{
+ return;
+}
+
+void plat_arm_gic_resume(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+}
diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c
new file mode 100644
index 0000000..469e22a
--- /dev/null
+++ b/plat/arm/common/arm_gicv3.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_arm_gic_driver_init
+#pragma weak plat_arm_gic_init
+#pragma weak plat_arm_gic_cpuif_enable
+#pragma weak plat_arm_gic_cpuif_disable
+#pragma weak plat_arm_gic_pcpu_init
+#pragma weak plat_arm_gic_redistif_on
+#pragma weak plat_arm_gic_redistif_off
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* Default GICR base address to be used for GICR probe. */
+static const uintptr_t gicr_base_addrs[2] = {
+ PLAT_ARM_GICR_BASE, /* GICR Base address of the primary CPU */
+ 0U /* Zero Termination */
+};
+
+/* List of zero terminated GICR frame addresses which CPUs will probe */
+static const uintptr_t *gicr_frames = gicr_base_addrs;
+
+static const interrupt_prop_t arm_interrupt_props[] = {
+ PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * We save and restore the GICv3 context on system suspend. Allocate the
+ * data in the designated EL3 Secure carve-out memory. The `used` attribute
+ * is used to prevent the compiler from removing the gicv3 contexts.
+ */
+static gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram") __used;
+static gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram") __used;
+
+/* Define accessor function to get reference to the GICv3 context */
+DEFINE_LOAD_SYM_ADDR(rdist_ctx)
+DEFINE_LOAD_SYM_ADDR(dist_ctx)
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ * - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int arm_gicv3_mpidr_hash(u_register_t mpidr)
+{
+ mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+ return plat_arm_calc_core_pos(mpidr);
+}
+
+static const gicv3_driver_data_t arm_gic_data __unused = {
+ .gicd_base = PLAT_ARM_GICD_BASE,
+ .gicr_base = 0U,
+ .interrupt_props = arm_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(arm_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = arm_gicv3_mpidr_hash
+};
+
+/*
+ * By default, gicr_frames will be pointing to gicr_base_addrs. If
+ * the platform supports a non-contiguous GICR frames (GICR frames located
+ * at uneven offset), plat_arm_override_gicr_frames function can be used by
+ * such platform to override the gicr_frames.
+ */
+void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames)
+{
+ assert(plat_gicr_frames != NULL);
+ gicr_frames = plat_gicr_frames;
+}
+
+void __init plat_arm_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
+ (defined(__aarch64__) && defined(IMAGE_BL31))
+ gicv3_driver_init(&arm_gic_data);
+
+ if (gicv3_rdistif_probe(gicr_base_addrs[0]) == -1) {
+ ERROR("No GICR base frame found for Primary CPU\n");
+ panic();
+ }
+#endif
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the GIC. Only invoked by BL31
+ *****************************************************************************/
+void __init plat_arm_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_arm_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper function to iterate over all GICR frames and discover the
+ * corresponding per-cpu redistributor frame as well as initialize the
+ * corresponding interface in GICv3.
+ *****************************************************************************/
+void plat_arm_gic_pcpu_init(void)
+{
+ int result;
+ const uintptr_t *plat_gicr_frames = gicr_frames;
+
+ do {
+ result = gicv3_rdistif_probe(*plat_gicr_frames);
+
+ /* If the probe is successful, no need to proceed further */
+ if (result == 0)
+ break;
+
+ plat_gicr_frames++;
+ } while (*plat_gicr_frames != 0U);
+
+ if (result == -1) {
+ ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
+ panic();
+ }
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helpers to power GIC redistributor interface
+ *****************************************************************************/
+void plat_arm_gic_redistif_on(void)
+{
+ gicv3_rdistif_on(plat_my_core_pos());
+}
+
+void plat_arm_gic_redistif_off(void)
+{
+ gicv3_rdistif_off(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to save & restore the GICv3 on resume from system suspend
+ *****************************************************************************/
+void plat_arm_gic_save(void)
+{
+ gicv3_redist_ctx_t * const rdist_context =
+ (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
+ gicv3_dist_ctx_t * const dist_context =
+ (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx);
+
+ /*
+ * If an ITS is available, save its context before
+ * the Redistributor using:
+ * gicv3_its_save_disable(gits_base, &its_ctx[i])
+ * Additionally, an implementation-defined sequence may
+ * be required to save the whole ITS state.
+ */
+
+ /*
+ * Save the GIC Redistributors and ITS contexts before the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to save the context of the CPU that is issuing
+ * the SYSTEM SUSPEND call, i.e. the current CPU.
+ */
+ gicv3_rdistif_save(plat_my_core_pos(), rdist_context);
+
+ /* Save the GIC Distributor context */
+ gicv3_distif_save(dist_context);
+
+ /*
+ * From here, all the components of the GIC can be safely powered down
+ * as long as there is an alternate way to handle wakeup interrupt
+ * sources.
+ */
+}
+
+void plat_arm_gic_resume(void)
+{
+ const gicv3_redist_ctx_t *rdist_context =
+ (gicv3_redist_ctx_t *)LOAD_ADDR_OF(rdist_ctx);
+ const gicv3_dist_ctx_t *dist_context =
+ (gicv3_dist_ctx_t *)LOAD_ADDR_OF(dist_ctx);
+
+ /* Restore the GIC Distributor context */
+ gicv3_distif_init_restore(dist_context);
+
+ /*
+ * Restore the GIC Redistributor and ITS contexts after the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to restore the context of the CPU that issued
+ * the SYSTEM SUSPEND call.
+ */
+ gicv3_rdistif_init_restore(plat_my_core_pos(), rdist_context);
+
+ /*
+ * If an ITS is available, restore its context after
+ * the Redistributor using:
+ * gicv3_its_restore(gits_base, &its_ctx[i])
+ * An implementation-defined sequence may be required to
+ * restore the whole ITS state. The ITS must also be
+ * re-enabled after this sequence has been executed.
+ */
+}
diff --git a/plat/arm/common/arm_image_load.c b/plat/arm/common/arm_image_load.c
new file mode 100644
index 0000000..c411c6c
--- /dev/null
+++ b/plat/arm/common/arm_image_load.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#if defined(SPD_spmd)
+#include <plat/arm/common/fconf_arm_sp_getter.h>
+#endif
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#pragma weak plat_flush_next_bl_params
+#pragma weak plat_get_bl_image_load_info
+#pragma weak plat_get_next_bl_params
+
+static bl_params_t *next_bl_params_cpy_ptr;
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ assert(next_bl_params_cpy_ptr != NULL);
+
+ flush_bl_params_desc_args(bl_mem_params_desc_ptr,
+ bl_mem_params_desc_num,
+ next_bl_params_cpy_ptr);
+}
+
+#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD
+/*******************************************************************************
+ * This function appends Secure Partitions to list of loadable images.
+ ******************************************************************************/
+static void plat_add_sp_images_load_info(struct bl_load_info *load_info)
+{
+ bl_load_info_node_t *curr_node = load_info->head;
+ bl_load_info_node_t *prev_node;
+
+ /* Shortcut for empty SP list */
+ if (sp_mem_params_descs[0].image_id == 0) {
+ ERROR("No Secure Partition Image available\n");
+ return;
+ }
+
+ /* Traverse through the bl images list */
+ do {
+ curr_node = curr_node->next_load_info;
+ } while (curr_node->next_load_info != NULL);
+
+ prev_node = curr_node;
+
+ for (unsigned int index = 0; index < MAX_SP_IDS; index++) {
+ if (sp_mem_params_descs[index].image_id == 0) {
+ return;
+ }
+ curr_node = &sp_mem_params_descs[index].load_node_mem;
+ /* Populate the image information */
+ curr_node->image_id = sp_mem_params_descs[index].image_id;
+ curr_node->image_info = &sp_mem_params_descs[index].image_info;
+
+ prev_node->next_load_info = curr_node;
+ prev_node = curr_node;
+ }
+
+ INFO("Reached Max number of SPs\n");
+}
+#endif
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+struct bl_load_info *plat_get_bl_image_load_info(void)
+{
+#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD
+ bl_load_info_t *bl_load_info;
+
+ bl_load_info = get_bl_load_info_from_mem_params_desc();
+ plat_add_sp_images_load_info(bl_load_info);
+
+ return bl_load_info;
+#else
+ return get_bl_load_info_from_mem_params_desc();
+#endif
+}
+
+/*******************************************************************************
+ * ARM helper function to return the list of executable images.Since the default
+ * descriptors are allocated within BL2 RW memory, this prevents BL31/BL32
+ * overlay of BL2 memory. Hence this function also copies the descriptors to a
+ * pre-allocated memory indicated by ARM_BL2_MEM_DESC_BASE.
+ ******************************************************************************/
+struct bl_params *arm_get_next_bl_params(void)
+{
+ bl_mem_params_node_t *bl2_mem_params_descs_cpy
+ = (bl_mem_params_node_t *)ARM_BL2_MEM_DESC_BASE;
+ const bl_params_t *next_bl_params;
+
+ next_bl_params_cpy_ptr =
+ (bl_params_t *)(ARM_BL2_MEM_DESC_BASE +
+ (bl_mem_params_desc_num * sizeof(bl_mem_params_node_t)));
+
+ /*
+ * Copy the memory descriptors to ARM_BL2_MEM_DESC_BASE area.
+ */
+ (void) memcpy(bl2_mem_params_descs_cpy, bl_mem_params_desc_ptr,
+ (bl_mem_params_desc_num * sizeof(bl_mem_params_node_t)));
+
+ /*
+ * Modify the global 'bl_mem_params_desc_ptr' to point to the
+ * copied location.
+ */
+ bl_mem_params_desc_ptr = bl2_mem_params_descs_cpy;
+
+ next_bl_params = get_next_bl_params_from_mem_params_desc();
+ assert(next_bl_params != NULL);
+
+ /*
+ * Copy 'next_bl_params' to the reserved location after the copied
+ * memory descriptors.
+ */
+ (void) memcpy(next_bl_params_cpy_ptr, next_bl_params,
+ (sizeof(bl_params_t)));
+
+ populate_next_bl_params_config(next_bl_params_cpy_ptr);
+
+ return next_bl_params_cpy_ptr;
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ return arm_get_next_bl_params();
+}
+
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
new file mode 100644
index 0000000..19ee1b0
--- /dev/null
+++ b/plat/arm/common/arm_io_storage.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/fwu/fwu_metadata.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/partition/partition.h>
+#include <lib/utils.h>
+
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+uintptr_t memmap_dev_handle;
+
+#if ARM_GPT_SUPPORT
+/* fip partition names */
+static const char * const fip_part_names[] = {"FIP_A", "FIP_B"};
+CASSERT(sizeof(fip_part_names)/sizeof(char *) == NR_OF_FW_BANKS,
+ assert_fip_partition_names_missing);
+#endif /* ARM_GPT_SUPPORT */
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_arm_io_setup
+#pragma weak plat_arm_get_alt_image_source
+
+int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+int arm_io_setup(void)
+{
+ int io_result;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ if (io_result < 0) {
+ return io_result;
+ }
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ if (io_result < 0) {
+ return io_result;
+ }
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ if (io_result < 0) {
+ return io_result;
+ }
+
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+
+ return io_result;
+}
+
+void plat_arm_io_setup(void)
+{
+ int err;
+
+ err = arm_io_setup();
+ if (err < 0) {
+ panic();
+ }
+}
+
+int plat_arm_get_alt_image_source(
+ unsigned int image_id __unused,
+ uintptr_t *dev_handle __unused,
+ uintptr_t *image_spec __unused)
+{
+ /* By default do not try an alternative */
+ return -ENOENT;
+}
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ policy = FCONF_GET_PROPERTY(arm, io_policies, image_id);
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ } else {
+ VERBOSE("Trying alternative IO\n");
+ result = plat_arm_get_alt_image_source(image_id, dev_handle,
+ image_spec);
+ }
+
+ return result;
+}
+
+/*
+ * See if a Firmware Image Package is available,
+ * by checking if TOC is valid or not.
+ */
+bool arm_io_is_toc_valid(void)
+{
+ return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0);
+}
+
+#if ARM_GPT_SUPPORT
+/******************************************************************************
+ * Retrieve partition entry details such as offset and length, and set these
+ * details in the I/O policy of the requested image.
+ *
+ * @image_id: image id whose I/O policy to be updated
+ *
+ * @part_name: partition name whose details to be retrieved
+ *
+ * Returns 0 on success, error otherwise
+ * Alongside, returns device handle and image specification of requested
+ * image.
+ ******************************************************************************/
+int arm_set_image_source(unsigned int image_id, const char *part_name,
+ uintptr_t *dev_handle, uintptr_t *image_spec)
+{
+ const partition_entry_t *entry = get_partition_entry(part_name);
+
+ if (entry == NULL) {
+ ERROR("Unable to find the %s partition\n", part_name);
+ return -ENOENT;
+ }
+
+ struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm,
+ io_policies,
+ image_id);
+
+ assert(policy != NULL);
+ assert(policy->image_spec != 0UL);
+
+ io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
+ /* set offset and length of the image */
+ spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start;
+ spec->length = entry->length;
+
+ *dev_handle = *(policy->dev_handle);
+ *image_spec = policy->image_spec;
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Set the source offset and length of the FIP image in its I/O policy.
+ *
+ * @active_fw_bank_idx: active firmware bank index gathered from FWU metadata.
+ ******************************************************************************/
+void arm_set_fip_addr(uint32_t active_fw_bank_idx)
+{
+ uintptr_t dev_handle __unused;
+ uintptr_t image_spec __unused;
+
+ assert(active_fw_bank_idx < NR_OF_FW_BANKS);
+
+ INFO("Booting with partition %s\n", fip_part_names[active_fw_bank_idx]);
+
+ int result = arm_set_image_source(FIP_IMAGE_ID,
+ fip_part_names[active_fw_bank_idx],
+ &dev_handle,
+ &image_spec);
+ if (result != 0) {
+ panic();
+ }
+}
+#endif /* ARM_GPT_SUPPORT */
+
+#if PSA_FWU_SUPPORT
+/*******************************************************************************
+ * Read the FIP partition of the GPT image corresponding to the active firmware
+ * bank to get its offset and length, and update these details in the I/O policy
+ * of the FIP image.
+ ******************************************************************************/
+void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
+{
+ arm_set_fip_addr(metadata->active_index);
+}
+
+/*******************************************************************************
+ * Read the requested FWU metadata partition of the GPT image to get its offset
+ * and length, and update these details in the I/O policy of the requested FWU
+ * metadata image.
+ ******************************************************************************/
+int plat_fwu_set_metadata_image_source(unsigned int image_id,
+ uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result = -1;
+
+ if (image_id == FWU_METADATA_IMAGE_ID) {
+ result = arm_set_image_source(FWU_METADATA_IMAGE_ID,
+ "FWU-Metadata",
+ dev_handle,
+ image_spec);
+ } else if (image_id == BKUP_FWU_METADATA_IMAGE_ID) {
+ result = arm_set_image_source(BKUP_FWU_METADATA_IMAGE_ID,
+ "Bkup-FWU-Metadata",
+ dev_handle,
+ image_spec);
+ }
+
+ return result;
+}
+#endif /* PSA_FWU_SUPPORT */
diff --git a/plat/arm/common/arm_nor_psci_mem_protect.c b/plat/arm/common/arm_nor_psci_mem_protect.c
new file mode 100644
index 0000000..1fa234d
--- /dev/null
+++ b/plat/arm/common/arm_nor_psci_mem_protect.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/cfi/v2m_flash.h>
+#include <lib/psci/psci.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * DRAM1 is used also to load the NS boot loader. For this reason we
+ * cannot clear the full DRAM1, because in that case we would clear
+ * the NS images (especially for RESET_TO_BL31 and RESET_TO_SPMIN cases).
+ * For this reason we reserve 64 MB for the NS images and protect the RAM
+ * until the end of DRAM1.
+ * We limit the size of DRAM2 to 1 GB to avoid big delays while booting
+ */
+#define DRAM1_NS_IMAGE_LIMIT (PLAT_ARM_NS_IMAGE_BASE + (32 << TWO_MB_SHIFT))
+#define DRAM1_PROTECTED_SIZE (ARM_NS_DRAM1_END+1u - DRAM1_NS_IMAGE_LIMIT)
+
+static mem_region_t arm_ram_ranges[] = {
+ {DRAM1_NS_IMAGE_LIMIT, DRAM1_PROTECTED_SIZE},
+#ifdef __aarch64__
+ {ARM_DRAM2_BASE, 1u << ONE_GB_SHIFT},
+#endif
+};
+
+/*******************************************************************************
+ * Function that reads the content of the memory protect variable that
+ * enables clearing of non secure memory when system boots. This variable
+ * should be stored in a secure NVRAM.
+ ******************************************************************************/
+int arm_psci_read_mem_protect(int *enabled)
+{
+ int tmp;
+
+ tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
+ *enabled = (tmp == 1) ? 1 : 0;
+ return 0;
+}
+
+/*******************************************************************************
+ * Function that writes the content of the memory protect variable that
+ * enables overwritten of non secure memory when system boots.
+ ******************************************************************************/
+int arm_nor_psci_write_mem_protect(int val)
+{
+ unsigned long enable = (val != 0) ? 1UL : 0UL;
+
+ if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+ ERROR("unlocking memory protect variable\n");
+ return -1;
+ }
+
+ if (enable == 1UL) {
+ /*
+ * If we want to write a value different than 0
+ * then we have to erase the full block because
+ * otherwise we cannot ensure that the value programmed
+ * into the flash is going to be the same than the value
+ * requested by the caller
+ */
+ if (nor_erase(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+ ERROR("erasing block containing memory protect variable\n");
+ return -1;
+ }
+ }
+
+ if (nor_word_program(PLAT_ARM_MEM_PROT_ADDR, enable) != 0) {
+ ERROR("programming memory protection variable\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ * Function used for required psci operations performed when
+ * system boots
+ ******************************************************************************/
+/*
+ * PLAT_MEM_PROTECT_VA_FRAME is a address specifically
+ * selected in a way that is not needed an additional
+ * translation table for memprotect. It happens because
+ * we use a chunk of size 2MB and it means that it can
+ * be mapped in a level 2 table and the level 2 table
+ * for 0xc0000000 is already used and the entry for
+ * 0xc0000000 is not used.
+ */
+#if defined(PLAT_XLAT_TABLES_DYNAMIC)
+void arm_nor_psci_do_dyn_mem_protect(void)
+{
+ int enable;
+
+ arm_psci_read_mem_protect(&enable);
+ if (enable == 0)
+ return;
+
+ INFO("PSCI: Overwriting non secure memory\n");
+ clear_map_dyn_mem_regions(arm_ram_ranges,
+ ARRAY_SIZE(arm_ram_ranges),
+ PLAT_ARM_MEM_PROTEC_VA_FRAME,
+ 1 << TWO_MB_SHIFT);
+}
+#endif
+
+/*******************************************************************************
+ * Function used for required psci operations performed when
+ * system boots and dynamic memory is not used.
+ ******************************************************************************/
+void arm_nor_psci_do_static_mem_protect(void)
+{
+ int enable;
+
+ (void) arm_psci_read_mem_protect(&enable);
+ if (enable == 0)
+ return;
+
+ INFO("PSCI: Overwriting non secure memory\n");
+ clear_mem_regions(arm_ram_ranges,
+ ARRAY_SIZE(arm_ram_ranges));
+ (void) arm_nor_psci_write_mem_protect(0);
+}
+
+/*******************************************************************************
+ * Function that checks if a region is protected by the memory protect
+ * mechanism
+ ******************************************************************************/
+int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length)
+{
+ return mem_region_in_array_chk(arm_ram_ranges,
+ ARRAY_SIZE(arm_ram_ranges),
+ base, length);
+}
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
new file mode 100644
index 0000000..5434c94
--- /dev/null
+++ b/plat/arm/common/arm_pm.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* Allow ARM Standard platforms to override these functions */
+#pragma weak plat_arm_program_trusted_mailbox
+
+#if !ARM_RECOM_STATE_ID_ENC
+/*******************************************************************************
+ * ARM standard platform handler called to check the validity of the power state
+ * parameter.
+ ******************************************************************************/
+int arm_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int i;
+
+ assert(req_state != NULL);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's possible to enter standby only on power level 0
+ * Ignore any other power level.
+ */
+ if (pwr_lvl != ARM_PWR_LVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[ARM_PWR_LVL0] =
+ ARM_LOCAL_STATE_RET;
+ } else {
+ for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ ARM_LOCAL_STATE_OFF;
+ }
+
+ /*
+ * We expect the 'state id' to be zero.
+ */
+ if (psci_get_pstate_id(power_state) != 0U)
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+#else
+/*******************************************************************************
+ * ARM standard platform handler called to check the validity of the power
+ * state parameter. The power state parameter has to be a composite power
+ * state.
+ ******************************************************************************/
+int arm_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ int i;
+
+ assert(req_state != NULL);
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
+ */
+ for (i = 0; !!arm_pm_idle_states[i]; i++) {
+ if (power_state == arm_pm_idle_states[i])
+ break;
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!arm_pm_idle_states[i])
+ return PSCI_E_INVALID_PARAMS;
+
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id &
+ ARM_LOCAL_PSTATE_MASK;
+ state_id >>= ARM_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+#endif /* __ARM_RECOM_STATE_ID_ENC__ */
+
+/*******************************************************************************
+ * ARM standard platform handler called to check the validity of the non secure
+ * entrypoint. Returns 0 if the entrypoint is valid, or -1 otherwise.
+ ******************************************************************************/
+int arm_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint <
+ (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) {
+ return 0;
+ }
+#ifdef __aarch64__
+ if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint <
+ (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) {
+ return 0;
+ }
+#endif
+
+ return -1;
+}
+
+int arm_validate_psci_entrypoint(uintptr_t entrypoint)
+{
+ return (arm_validate_ns_entrypoint(entrypoint) == 0) ? PSCI_E_SUCCESS :
+ PSCI_E_INVALID_ADDRESS;
+}
+
+/******************************************************************************
+ * Helper function to save the platform state before a system suspend. Save the
+ * state of the system components which are not in the Always ON power domain.
+ *****************************************************************************/
+void arm_system_pwr_domain_save(void)
+{
+ /* Assert system power domain is available on the platform */
+ assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
+
+ plat_arm_gic_save();
+
+ /*
+ * Unregister console now so that it is not registered for a second
+ * time during resume.
+ */
+ arm_console_runtime_end();
+
+ /*
+ * All the other peripheral which are configured by ARM TF are
+ * re-initialized on resume from system suspend. Hence we
+ * don't save their state here.
+ */
+}
+
+/******************************************************************************
+ * Helper function to resume the platform from system suspend. Reinitialize
+ * the system components which are not in the Always ON power domain.
+ * TODO: Unify the platform setup when waking up from cold boot and system
+ * resume in arm_bl31_platform_setup().
+ *****************************************************************************/
+void arm_system_pwr_domain_resume(void)
+{
+ /* Initialize the console */
+ arm_console_runtime_init();
+
+ /* Assert system power domain is available on the platform */
+ assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2);
+
+ plat_arm_gic_resume();
+
+ plat_arm_security_setup();
+ arm_configure_sys_timer();
+}
+
+/*******************************************************************************
+ * ARM platform function to program the mailbox for a cpu before it is released
+ * from reset. This function assumes that the Trusted mail box base is within
+ * the ARM_SHARED_RAM region
+ ******************************************************************************/
+void plat_arm_program_trusted_mailbox(uintptr_t address)
+{
+ uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE;
+
+ *mailbox = address;
+
+ /*
+ * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within
+ * ARM_SHARED_RAM region.
+ */
+ assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) &&
+ ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \
+ (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE)));
+}
+
+/*******************************************************************************
+ * The ARM Standard platform definition of platform porting API
+ * `plat_setup_psci_ops`.
+ ******************************************************************************/
+int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops);
+
+ /* Setup mailbox with entry point. */
+ plat_arm_program_trusted_mailbox(sec_entrypoint);
+ return 0;
+}
diff --git a/plat/arm/common/arm_sip_svc.c b/plat/arm/common/arm_sip_svc.c
new file mode 100644
index 0000000..6456c78
--- /dev/null
+++ b/plat/arm/common/arm_sip_svc.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/arm/ethosn.h>
+#include <lib/debugfs.h>
+#include <lib/pmf/pmf.h>
+#include <plat/arm/common/arm_sip_svc.h>
+#include <plat/arm/common/plat_arm.h>
+#include <tools_share/uuid.h>
+
+/* ARM SiP Service UUID */
+DEFINE_SVC_UUID2(arm_sip_svc_uid,
+ 0x556d75e2, 0x6033, 0xb54b, 0xb5, 0x75,
+ 0x62, 0x79, 0xfd, 0x11, 0x37, 0xff);
+
+static int arm_sip_setup(void)
+{
+ if (pmf_setup() != 0) {
+ return 1;
+ }
+
+#if USE_DEBUGFS
+
+ if (debugfs_smc_setup() != 0) {
+ return 1;
+ }
+
+#endif /* USE_DEBUGFS */
+
+ return 0;
+}
+
+/*
+ * This function handles ARM defined SiP Calls
+ */
+static uintptr_t arm_sip_handler(unsigned int smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ int call_count = 0;
+
+#if ENABLE_PMF
+
+ /*
+ * Dispatch PMF calls to PMF SMC handler and return its return
+ * value
+ */
+ if (is_pmf_fid(smc_fid)) {
+ return pmf_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+
+#endif /* ENABLE_PMF */
+
+#if USE_DEBUGFS
+
+ if (is_debugfs_fid(smc_fid)) {
+ return debugfs_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+
+#endif /* USE_DEBUGFS */
+
+#if ARM_ETHOSN_NPU_DRIVER
+
+ if (is_ethosn_fid(smc_fid)) {
+ return ethosn_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+
+#endif /* ARM_ETHOSN_NPU_DRIVER */
+
+ switch (smc_fid) {
+ case ARM_SIP_SVC_EXE_STATE_SWITCH: {
+ /* Execution state can be switched only if EL3 is AArch64 */
+#ifdef __aarch64__
+ /* Allow calls from non-secure only */
+ if (!is_caller_non_secure(flags))
+ SMC_RET1(handle, STATE_SW_E_DENIED);
+
+ /*
+ * Pointers used in execution state switch are all 32 bits wide
+ */
+ return (uintptr_t) arm_execution_state_switch(smc_fid,
+ (uint32_t) x1, (uint32_t) x2, (uint32_t) x3,
+ (uint32_t) x4, handle);
+#else
+ /* State switch denied */
+ SMC_RET1(handle, STATE_SW_E_DENIED);
+#endif /* __aarch64__ */
+ }
+
+ case ARM_SIP_SVC_CALL_COUNT:
+ /* PMF calls */
+ call_count += PMF_NUM_SMC_CALLS;
+
+#if ARM_ETHOSN_NPU_DRIVER
+ /* ETHOSN calls */
+ call_count += ETHOSN_NUM_SMC_CALLS;
+#endif /* ARM_ETHOSN_NPU_DRIVER */
+
+ /* State switch call */
+ call_count += 1;
+
+ SMC_RET1(handle, call_count);
+
+ case ARM_SIP_SVC_UID:
+ /* Return UID to the caller */
+ SMC_UUID_RET(handle, arm_sip_svc_uid);
+
+ case ARM_SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ SMC_RET2(handle, ARM_SIP_SVC_VERSION_MAJOR, ARM_SIP_SVC_VERSION_MINOR);
+
+ default:
+ WARN("Unimplemented ARM SiP Service Call: 0x%x \n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+}
+
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ arm_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ arm_sip_setup,
+ arm_sip_handler
+);
diff --git a/plat/arm/common/arm_topology.c b/plat/arm/common/arm_topology.c
new file mode 100644
index 0000000..c9993a7
--- /dev/null
+++ b/plat/arm/common/arm_topology.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * This function validates an MPIDR by checking whether it falls within the
+ * acceptable bounds. An error code (-1) is returned if an incorrect mpidr
+ * is passed.
+ ******************************************************************************/
+int arm_check_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+ uint64_t valid_mask;
+
+#if ARM_PLAT_MT
+ unsigned int pe_id;
+
+ valid_mask = ~(MPIDR_AFFLVL_MASK |
+ (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) |
+ (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT) |
+ (MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
+ cluster_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ pe_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+#else
+ valid_mask = ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK);
+ cluster_id = (unsigned int) ((mpidr >> MPIDR_AFF1_SHIFT) &
+ MPIDR_AFFLVL_MASK);
+ cpu_id = (unsigned int) ((mpidr >> MPIDR_AFF0_SHIFT) &
+ MPIDR_AFFLVL_MASK);
+#endif /* ARM_PLAT_MT */
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+ if ((mpidr & valid_mask) != 0U)
+ return -1;
+
+ if (cluster_id >= PLAT_ARM_CLUSTER_COUNT)
+ return -1;
+
+ /* Validate cpu_id by checking whether it represents a CPU in
+ one of the two clusters present on the platform. */
+ if (cpu_id >= plat_arm_get_cluster_core_count(mpidr))
+ return -1;
+
+#if ARM_PLAT_MT
+ if (pe_id >= plat_arm_get_cpu_pe_count(mpidr))
+ return -1;
+#endif /* ARM_PLAT_MT */
+
+ return 0;
+}
diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c
new file mode 100644
index 0000000..370ef0a
--- /dev/null
+++ b/plat/arm/common/arm_tzc400.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/arm/tzc400.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_arm_security_setup
+
+
+/*******************************************************************************
+ * Initialize the TrustZone Controller for ARM standard platforms.
+ * When booting an EL3 payload, this is simplified: we configure region 0 with
+ * secure access only and do not enable any other region.
+ ******************************************************************************/
+void arm_tzc400_setup(uintptr_t tzc_base,
+ const arm_tzc_regions_info_t *tzc_regions)
+{
+#ifndef EL3_PAYLOAD_BASE
+ unsigned int region_index = 1U;
+ const arm_tzc_regions_info_t *p;
+ const arm_tzc_regions_info_t init_tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+ {0}
+ };
+#endif
+
+ INFO("Configuring TrustZone Controller\n");
+
+ tzc400_init(tzc_base);
+
+ /* Disable filters. */
+ tzc400_disable_filters();
+
+#ifndef EL3_PAYLOAD_BASE
+ if (tzc_regions == NULL)
+ p = init_tzc_regions;
+ else
+ p = tzc_regions;
+
+ /* Region 0 set to no access by default */
+ tzc400_configure_region0(TZC_REGION_S_NONE, 0);
+
+ /* Rest Regions set according to tzc_regions array */
+ for (; p->base != 0ULL; p++) {
+ tzc400_configure_region(PLAT_ARM_TZC_FILTERS, region_index,
+ p->base, p->end, p->sec_attr, p->nsaid_permissions);
+ region_index++;
+ }
+
+ INFO("Total %u regions set.\n", region_index);
+
+#else /* if defined(EL3_PAYLOAD_BASE) */
+
+ /* Allow Secure and Non-secure access to DRAM for EL3 payloads */
+ tzc400_configure_region0(TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS);
+
+#endif /* EL3_PAYLOAD_BASE */
+
+ /*
+ * Raise an exception if a NS device tries to access secure memory
+ * TODO: Add interrupt handling support.
+ */
+ tzc400_set_action(TZC_ACTION_ERR);
+
+ /* Enable filters. */
+ tzc400_enable_filters();
+}
+
+void plat_arm_security_setup(void)
+{
+ arm_tzc400_setup(PLAT_ARM_TZC_BASE, NULL);
+}
diff --git a/plat/arm/common/arm_tzc_dmc500.c b/plat/arm/common/arm_tzc_dmc500.c
new file mode 100644
index 0000000..e9f897f
--- /dev/null
+++ b/plat/arm/common/arm_tzc_dmc500.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/arm/tzc_dmc500.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Initialize the DMC500-TrustZone Controller for ARM standard platforms.
+ * When booting an EL3 payload, this is simplified: we configure region 0 with
+ * secure access only and do not enable any other region.
+ ******************************************************************************/
+void arm_tzc_dmc500_setup(tzc_dmc500_driver_data_t *plat_driver_data,
+ const arm_tzc_regions_info_t *tzc_regions)
+{
+#ifndef EL3_PAYLOAD_BASE
+ unsigned int region_index = 1U;
+ const arm_tzc_regions_info_t *p;
+ const arm_tzc_regions_info_t init_tzc_regions[] = {
+ ARM_TZC_REGIONS_DEF,
+ {0}
+ };
+#endif
+
+ assert(plat_driver_data);
+
+ INFO("Configuring DMC-500 TZ Settings\n");
+
+ tzc_dmc500_driver_init(plat_driver_data);
+
+#ifndef EL3_PAYLOAD_BASE
+ if (tzc_regions == NULL)
+ p = init_tzc_regions;
+ else
+ p = tzc_regions;
+
+ /* Region 0 set to no access by default */
+ tzc_dmc500_configure_region0(TZC_REGION_S_NONE, 0);
+
+ /* Rest Regions set according to tzc_regions array */
+ for (; p->base != 0ULL; p++) {
+ tzc_dmc500_configure_region(region_index, p->base, p->end,
+ p->sec_attr, p->nsaid_permissions);
+ region_index++;
+ }
+
+ INFO("Total %u regions set.\n", region_index);
+
+#else
+ /* Allow secure access only to DRAM for EL3 payloads */
+ tzc_dmc500_configure_region0(TZC_REGION_S_RDWR, 0);
+#endif
+ /*
+ * Raise an exception if a NS device tries to access secure memory
+ * TODO: Add interrupt handling support.
+ */
+ tzc_dmc500_set_action(TZC_ACTION_RV_LOWERR);
+
+ /*
+ * Flush the configuration settings to have an affect. Validate
+ * flush by checking FILTER_EN is set on region 1 attributes
+ * register.
+ */
+ tzc_dmc500_config_complete();
+
+ /*
+ * Wait for the flush to complete.
+ * TODO: Have a timeout for this loop
+ */
+ while (tzc_dmc500_verify_complete())
+ ;
+}
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
new file mode 100644
index 0000000..6c32331
--- /dev/null
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/partition/partition.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <platform_def.h>
+
+#if PSA_FWU_SUPPORT
+/* metadata entry details */
+static io_block_spec_t fwu_metadata_spec;
+#endif /* PSA_FWU_SUPPORT */
+
+io_block_spec_t fip_block_spec = {
+/*
+ * This is fixed FIP address used by BL1, BL2 loads partition table
+ * to get FIP address.
+ */
+#if ARM_GPT_SUPPORT
+ .offset = PLAT_ARM_FLASH_IMAGE_BASE + PLAT_ARM_FIP_OFFSET_IN_GPT,
+#else
+ .offset = PLAT_ARM_FLASH_IMAGE_BASE,
+#endif /* ARM_GPT_SUPPORT */
+ .length = PLAT_ARM_FLASH_IMAGE_MAX_SIZE
+};
+
+#if ARM_GPT_SUPPORT
+static const io_block_spec_t gpt_spec = {
+ .offset = PLAT_ARM_FLASH_IMAGE_BASE,
+ /*
+ * PLAT_PARTITION_BLOCK_SIZE = 512
+ * PLAT_PARTITION_MAX_ENTRIES = 128
+ * each sector has 4 partition entries, and there are
+ * 2 reserved sectors i.e. protective MBR and primary
+ * GPT header hence length gets calculated as,
+ * length = 512 * (128/4 + 2)
+ */
+ .length = PLAT_PARTITION_BLOCK_SIZE *
+ (PLAT_PARTITION_MAX_ENTRIES / 4 + 2),
+};
+#endif /* ARM_GPT_SUPPORT */
+
+const io_uuid_spec_t arm_uuid_spec[MAX_NUMBER_IDS] = {
+ [BL2_IMAGE_ID] = {UUID_TRUSTED_BOOT_FIRMWARE_BL2},
+ [TB_FW_CONFIG_ID] = {UUID_TB_FW_CONFIG},
+ [FW_CONFIG_ID] = {UUID_FW_CONFIG},
+#if !ARM_IO_IN_DTB
+ [SCP_BL2_IMAGE_ID] = {UUID_SCP_FIRMWARE_SCP_BL2},
+ [BL31_IMAGE_ID] = {UUID_EL3_RUNTIME_FIRMWARE_BL31},
+ [BL32_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32},
+ [BL32_EXTRA1_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32_EXTRA1},
+ [BL32_EXTRA2_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32_EXTRA2},
+ [BL33_IMAGE_ID] = {UUID_NON_TRUSTED_FIRMWARE_BL33},
+ [HW_CONFIG_ID] = {UUID_HW_CONFIG},
+ [SOC_FW_CONFIG_ID] = {UUID_SOC_FW_CONFIG},
+ [TOS_FW_CONFIG_ID] = {UUID_TOS_FW_CONFIG},
+ [NT_FW_CONFIG_ID] = {UUID_NT_FW_CONFIG},
+ [RMM_IMAGE_ID] = {UUID_REALM_MONITOR_MGMT_FIRMWARE},
+#endif /* ARM_IO_IN_DTB */
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {UUID_TRUSTED_BOOT_FW_CERT},
+#if !ARM_IO_IN_DTB
+ [CCA_CONTENT_CERT_ID] = {UUID_CCA_CONTENT_CERT},
+ [CORE_SWD_KEY_CERT_ID] = {UUID_CORE_SWD_KEY_CERT},
+ [PLAT_KEY_CERT_ID] = {UUID_PLAT_KEY_CERT},
+ [TRUSTED_KEY_CERT_ID] = {UUID_TRUSTED_KEY_CERT},
+ [SCP_FW_KEY_CERT_ID] = {UUID_SCP_FW_KEY_CERT},
+ [SOC_FW_KEY_CERT_ID] = {UUID_SOC_FW_KEY_CERT},
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {UUID_TRUSTED_OS_FW_KEY_CERT},
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {UUID_NON_TRUSTED_FW_KEY_CERT},
+ [SCP_FW_CONTENT_CERT_ID] = {UUID_SCP_FW_CONTENT_CERT},
+ [SOC_FW_CONTENT_CERT_ID] = {UUID_SOC_FW_CONTENT_CERT},
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {UUID_TRUSTED_OS_FW_CONTENT_CERT},
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {UUID_NON_TRUSTED_FW_CONTENT_CERT},
+#if defined(SPD_spmd)
+ [SIP_SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT},
+ [PLAT_SP_CONTENT_CERT_ID] = {UUID_PLAT_SECURE_PARTITION_CONTENT_CERT},
+#endif
+#endif /* ARM_IO_IN_DTB */
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+/* By default, ARM platforms load images from the FIP */
+struct plat_io_policy policies[MAX_NUMBER_IDS] = {
+#if ARM_GPT_SUPPORT
+ [GPT_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&gpt_spec,
+ open_memmap
+ },
+#endif /* ARM_GPT_SUPPORT */
+#if PSA_FWU_SUPPORT
+ [FWU_METADATA_IMAGE_ID] = {
+ &memmap_dev_handle,
+ /* filled runtime from partition information */
+ (uintptr_t)&fwu_metadata_spec,
+ open_memmap
+ },
+ [BKUP_FWU_METADATA_IMAGE_ID] = {
+ &memmap_dev_handle,
+ /* filled runtime from partition information */
+ (uintptr_t)&fwu_metadata_spec,
+ open_memmap
+ },
+#endif /* PSA_FWU_SUPPORT */
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[BL2_IMAGE_ID],
+ open_fip
+ },
+ [TB_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[TB_FW_CONFIG_ID],
+ open_fip
+ },
+ [FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[FW_CONFIG_ID],
+ open_fip
+ },
+#if !ARM_IO_IN_DTB
+ [SCP_BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[SCP_BL2_IMAGE_ID],
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[BL31_IMAGE_ID],
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[BL32_IMAGE_ID],
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[BL32_EXTRA1_IMAGE_ID],
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[BL32_EXTRA2_IMAGE_ID],
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[BL33_IMAGE_ID],
+ open_fip
+ },
+ [RMM_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[RMM_IMAGE_ID],
+ open_fip
+ },
+ [HW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[HW_CONFIG_ID],
+ open_fip
+ },
+ [SOC_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[SOC_FW_CONFIG_ID],
+ open_fip
+ },
+ [TOS_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[TOS_FW_CONFIG_ID],
+ open_fip
+ },
+ [NT_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[NT_FW_CONFIG_ID],
+ open_fip
+ },
+#endif /* ARM_IO_IN_DTB */
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[TRUSTED_BOOT_FW_CERT_ID],
+ open_fip
+ },
+#if !ARM_IO_IN_DTB
+ [CCA_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[CCA_CONTENT_CERT_ID],
+ open_fip
+ },
+ [CORE_SWD_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[CORE_SWD_KEY_CERT_ID],
+ open_fip
+ },
+ [PLAT_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[PLAT_KEY_CERT_ID],
+ open_fip
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[TRUSTED_KEY_CERT_ID],
+ open_fip
+ },
+ [SCP_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[SCP_FW_KEY_CERT_ID],
+ open_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[SOC_FW_KEY_CERT_ID],
+ open_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[TRUSTED_OS_FW_KEY_CERT_ID],
+ open_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[NON_TRUSTED_FW_KEY_CERT_ID],
+ open_fip
+ },
+ [SCP_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[SCP_FW_CONTENT_CERT_ID],
+ open_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[SOC_FW_CONTENT_CERT_ID],
+ open_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[TRUSTED_OS_FW_CONTENT_CERT_ID],
+ open_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[NON_TRUSTED_FW_CONTENT_CERT_ID],
+ open_fip
+ },
+#if defined(SPD_spmd)
+ [SIP_SP_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[SIP_SP_CONTENT_CERT_ID],
+ open_fip
+ },
+ [PLAT_SP_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&arm_uuid_spec[PLAT_SP_CONTENT_CERT_ID],
+ open_fip
+ },
+#endif
+#endif /* ARM_IO_IN_DTB */
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+#ifdef IMAGE_BL2
+
+#if TRUSTED_BOARD_BOOT
+#define FCONF_ARM_IO_UUID_NUMBER U(24)
+#else
+#define FCONF_ARM_IO_UUID_NUMBER U(10)
+#endif
+
+static io_uuid_spec_t fconf_arm_uuids[FCONF_ARM_IO_UUID_NUMBER];
+static OBJECT_POOL_ARRAY(fconf_arm_uuids_pool, fconf_arm_uuids);
+
+struct policies_load_info {
+ unsigned int image_id;
+ const char *name;
+};
+
+/* image id to property name table */
+static const struct policies_load_info load_info[FCONF_ARM_IO_UUID_NUMBER] = {
+ {SCP_BL2_IMAGE_ID, "scp_bl2_uuid"},
+ {BL31_IMAGE_ID, "bl31_uuid"},
+ {BL32_IMAGE_ID, "bl32_uuid"},
+ {BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"},
+ {BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"},
+ {BL33_IMAGE_ID, "bl33_uuid"},
+ {HW_CONFIG_ID, "hw_cfg_uuid"},
+ {SOC_FW_CONFIG_ID, "soc_fw_cfg_uuid"},
+ {TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
+ {NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
+#if TRUSTED_BOARD_BOOT
+ {CCA_CONTENT_CERT_ID, "cca_cert_uuid"},
+ {CORE_SWD_KEY_CERT_ID, "core_swd_cert_uuid"},
+ {PLAT_KEY_CERT_ID, "plat_cert_uuid"},
+ {TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"},
+ {SCP_FW_KEY_CERT_ID, "scp_fw_key_uuid"},
+ {SOC_FW_KEY_CERT_ID, "soc_fw_key_uuid"},
+ {TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"},
+ {NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"},
+ {SCP_FW_CONTENT_CERT_ID, "scp_fw_content_cert_uuid"},
+ {SOC_FW_CONTENT_CERT_ID, "soc_fw_content_cert_uuid"},
+ {TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
+ {NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
+#if defined(SPD_spmd)
+ {SIP_SP_CONTENT_CERT_ID, "sip_sp_content_cert_uuid"},
+ {PLAT_SP_CONTENT_CERT_ID, "plat_sp_content_cert_uuid"},
+#endif
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+int fconf_populate_arm_io_policies(uintptr_t config)
+{
+ int err, node;
+ unsigned int i;
+
+ union uuid_helper_t uuid_helper;
+ io_uuid_spec_t *uuid_ptr;
+
+ /* As libfdt uses void *, we can't avoid this cast */
+ const void *dtb = (void *)config;
+
+ /* Assert the node offset point to "arm,io-fip-handle" compatible property */
+ const char *compatible_str = "arm,io-fip-handle";
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+ return node;
+ }
+
+ /* Locate the uuid cells and read the value for all the load info uuid */
+ for (i = 0; i < FCONF_ARM_IO_UUID_NUMBER; i++) {
+ uuid_ptr = pool_alloc(&fconf_arm_uuids_pool);
+ err = fdtw_read_uuid(dtb, node, load_info[i].name, 16,
+ (uint8_t *)&uuid_helper);
+ if (err < 0) {
+ WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
+ return err;
+ }
+
+ VERBOSE("FCONF: arm-io_policies.%s cell found with value = "
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+ load_info[i].name,
+ uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1],
+ uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3],
+ uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1],
+ uuid_helper.uuid_struct.time_hi_and_version[0],
+ uuid_helper.uuid_struct.time_hi_and_version[1],
+ uuid_helper.uuid_struct.clock_seq_hi_and_reserved,
+ uuid_helper.uuid_struct.clock_seq_low,
+ uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1],
+ uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3],
+ uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5]);
+
+ uuid_ptr->uuid = uuid_helper.uuid_struct;
+ policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
+ policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
+ policies[load_info[i].image_id].check = open_fip;
+ }
+ return 0;
+}
+
+#if ARM_IO_IN_DTB
+FCONF_REGISTER_POPULATOR(TB_FW, arm_io, fconf_populate_arm_io_policies);
+#endif /* ARM_IO_IN_DTB */
+
+#endif /* IMAGE_BL2 */
diff --git a/plat/arm/common/fconf/arm_fconf_sp.c b/plat/arm/common/fconf/arm_fconf_sp.c
new file mode 100644
index 0000000..18c83c7
--- /dev/null
+++ b/plat/arm/common/fconf/arm_fconf_sp.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/io/io_storage.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <plat/arm/common/fconf_arm_sp_getter.h>
+#include <platform_def.h>
+#include <tools_share/firmware_image_package.h>
+
+#ifdef IMAGE_BL2
+
+bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS];
+
+struct arm_sp_t arm_sp;
+
+int fconf_populate_arm_sp(uintptr_t config)
+{
+ int sp_node, node, err;
+ union uuid_helper_t uuid_helper;
+ unsigned int index = 0;
+ uint32_t val32;
+ const unsigned int sip_start = SP_PKG1_ID;
+ unsigned int sip_index = sip_start;
+#if defined(ARM_COT_dualroot)
+ const unsigned int sip_end = sip_start + MAX_SP_IDS / 2;
+ /* Allocating index range for platform SPs */
+ const unsigned int plat_start = SP_PKG5_ID;
+ unsigned int plat_index = plat_start;
+ const unsigned int plat_end = plat_start + MAX_SP_IDS / 2;
+ bool is_plat_owned = false;
+#endif /* ARM_COT_dualroot */
+
+ /* As libfdt use void *, we can't avoid this cast */
+ const void *dtb = (void *)config;
+
+ /* Assert the node offset point to "arm,sp" compatible property */
+ const char *compatible_str = "arm,sp";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s in dtb\n", compatible_str);
+ return node;
+ }
+
+ fdt_for_each_subnode(sp_node, dtb, node) {
+ if (index == MAX_SP_IDS) {
+ ERROR("FCONF: Reached max number of SPs\n");
+ return -1;
+ }
+
+#if defined(ARM_COT_dualroot)
+ if ((sip_index == sip_end) || (plat_index == plat_end)) {
+ ERROR("FCONF: Reached max number of plat/SiP SPs\n");
+ return -1;
+ }
+#endif /* ARM_COT_dualroot */
+
+ /* Read UUID */
+ err = fdtw_read_uuid(dtb, sp_node, "uuid", 16,
+ (uint8_t *)&uuid_helper);
+ if (err < 0) {
+ ERROR("FCONF: cannot read SP uuid\n");
+ return -1;
+ }
+
+ arm_sp.uuids[index] = uuid_helper;
+
+ /* Read Load address */
+ err = fdt_read_uint32(dtb, sp_node, "load-address", &val32);
+ if (err < 0) {
+ ERROR("FCONF: cannot read SP load address\n");
+ return -1;
+ }
+ arm_sp.load_addr[index] = val32;
+
+ VERBOSE("FCONF: %s UUID"
+ " %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+ " load_addr=%lx\n",
+ __func__,
+ uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1],
+ uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3],
+ uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1],
+ uuid_helper.uuid_struct.time_hi_and_version[0],
+ uuid_helper.uuid_struct.time_hi_and_version[1],
+ uuid_helper.uuid_struct.clock_seq_hi_and_reserved,
+ uuid_helper.uuid_struct.clock_seq_low,
+ uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1],
+ uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3],
+ uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5],
+ arm_sp.load_addr[index]);
+
+ /* Read owner field only for dualroot CoT */
+#if defined(ARM_COT_dualroot)
+ /* Owner is an optional field, no need to catch error */
+ fdtw_read_string(dtb, sp_node, "owner",
+ arm_sp.owner[index], ARM_SP_OWNER_NAME_LEN);
+
+ /* If owner is empty mark it as SiP owned */
+ if ((strncmp(arm_sp.owner[index], "SiP",
+ ARM_SP_OWNER_NAME_LEN) == 0) ||
+ (strncmp(arm_sp.owner[index], "",
+ ARM_SP_OWNER_NAME_LEN) == 0)) {
+ is_plat_owned = false;
+ } else if (strcmp(arm_sp.owner[index], "Plat") == 0) {
+ is_plat_owned = true;
+ } else {
+ ERROR("FCONF: %s is not a valid SP owner\n",
+ arm_sp.owner[index]);
+ return -1;
+ }
+ /*
+ * Add SP information in mem param descriptor and IO policies
+ * structure.
+ */
+ if (is_plat_owned) {
+ sp_mem_params_descs[index].image_id = plat_index;
+ policies[plat_index].image_spec =
+ (uintptr_t)&arm_sp.uuids[index];
+ policies[plat_index].dev_handle = &fip_dev_handle;
+ policies[plat_index].check = open_fip;
+ plat_index++;
+ } else
+#endif /* ARM_COT_dualroot */
+ {
+ sp_mem_params_descs[index].image_id = sip_index;
+ policies[sip_index].image_spec =
+ (uintptr_t)&arm_sp.uuids[index];
+ policies[sip_index].dev_handle = &fip_dev_handle;
+ policies[sip_index].check = open_fip;
+ sip_index++;
+ }
+ SET_PARAM_HEAD(&sp_mem_params_descs[index].image_info,
+ PARAM_IMAGE_BINARY, VERSION_2, 0);
+ sp_mem_params_descs[index].image_info.image_max_size =
+ ARM_SP_MAX_SIZE;
+ sp_mem_params_descs[index].next_handoff_image_id =
+ INVALID_IMAGE_ID;
+ sp_mem_params_descs[index].image_info.image_base =
+ arm_sp.load_addr[index];
+ index++;
+ }
+
+ if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) {
+ ERROR("%u: fdt_for_each_subnode(): %d\n", __LINE__, node);
+ return sp_node;
+ }
+
+ arm_sp.number_of_sp = index;
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(TB_FW, arm_sp, fconf_populate_arm_sp);
+
+#endif /* IMAGE_BL2 */
diff --git a/plat/arm/common/fconf/fconf_ethosn_getter.c b/plat/arm/common/fconf/fconf_ethosn_getter.c
new file mode 100644
index 0000000..0b48a98
--- /dev/null
+++ b/plat/arm/common/fconf/fconf_ethosn_getter.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+#include <plat/arm/common/fconf_ethosn_getter.h>
+
+struct ethosn_config_t ethosn_config = {0};
+
+struct ethosn_sub_allocator_t {
+ const char *name;
+ size_t name_len;
+ uint32_t stream_id;
+};
+
+static bool fdt_node_is_enabled(const void *fdt, int node)
+{
+ int len;
+ const char *node_status;
+
+ node_status = fdt_getprop(fdt, node, "status", &len);
+ if (node_status == NULL ||
+ (len == 5 && /* Includes null character */
+ strncmp(node_status, "okay", 4U) == 0)) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool fdt_node_has_reserved_memory(const void *fdt, int dev_node)
+{
+ return fdt_get_property(fdt, dev_node, "memory-region", NULL) != NULL;
+}
+
+static int fdt_node_get_iommus_stream_id(const void *fdt, int node, uint32_t *stream_id)
+{
+ int err;
+ uint32_t iommus_array[2] = {0U};
+
+ err = fdt_read_uint32_array(fdt, node, "iommus", 2U, iommus_array);
+ if (err) {
+ return err;
+ }
+
+ *stream_id = iommus_array[1];
+ return 0;
+}
+
+static int fdt_node_populate_sub_allocators(const void *fdt,
+ int alloc_node,
+ struct ethosn_sub_allocator_t *sub_allocators,
+ size_t num_allocs)
+{
+ int sub_node;
+ size_t i;
+ int err = -FDT_ERR_NOTFOUND;
+ uint32_t found_sub_allocators = 0U;
+
+ fdt_for_each_subnode(sub_node, fdt, alloc_node) {
+ const char *node_name;
+
+ if (!fdt_node_is_enabled(fdt, sub_node)) {
+ /* Ignore disabled node */
+ continue;
+ }
+
+ if (fdt_node_check_compatible(fdt, sub_node, "ethosn-memory") != 0) {
+ continue;
+ }
+
+ node_name = fdt_get_name(fdt, sub_node, NULL);
+ for (i = 0U; i < num_allocs; ++i) {
+ if (strncmp(node_name, sub_allocators[i].name,
+ sub_allocators[i].name_len) != 0) {
+ continue;
+ }
+
+ err = fdt_node_get_iommus_stream_id(fdt, sub_node,
+ &sub_allocators[i].stream_id);
+ if (err) {
+ ERROR("FCONF: Failed to get stream ID from sub-allocator %s\n",
+ node_name);
+ return err;
+ }
+
+ ++found_sub_allocators;
+ /* Nothing more to do for this node */
+ break;
+ }
+
+ /* Check that at least one of the sub-allocators matched */
+ if (i == num_allocs) {
+ ERROR("FCONF: Unknown sub-allocator %s\n", node_name);
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+ }
+
+ if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
+ ERROR("FCONF: Failed to parse sub-allocators\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ if (err == -FDT_ERR_NOTFOUND) {
+ ERROR("FCONF: No matching sub-allocator found\n");
+ return err;
+ }
+
+ if (found_sub_allocators != num_allocs) {
+ ERROR("FCONF: Not all sub-allocators were found\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ return 0;
+}
+
+static int fdt_node_populate_main_allocator(const void *fdt,
+ int alloc_node,
+ struct ethosn_main_allocator_t *allocator)
+{
+ int err;
+ struct ethosn_sub_allocator_t sub_allocators[] = {
+ {.name = "firmware", .name_len = 8U},
+ {.name = "working_data", .name_len = 12U}
+ };
+
+ err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
+ ARRAY_SIZE(sub_allocators));
+ if (err) {
+ return err;
+ }
+
+ allocator->firmware.stream_id = sub_allocators[0].stream_id;
+ allocator->working_data.stream_id = sub_allocators[1].stream_id;
+
+ return 0;
+}
+
+static int fdt_node_populate_asset_allocator(const void *fdt,
+ int alloc_node,
+ struct ethosn_asset_allocator_t *allocator)
+{
+ int err;
+ struct ethosn_sub_allocator_t sub_allocators[] = {
+ {.name = "command_stream", .name_len = 14U},
+ {.name = "weight_data", .name_len = 11U},
+ {.name = "buffer_data", .name_len = 11U},
+ {.name = "intermediate_data", .name_len = 17U}
+ };
+
+ err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
+ ARRAY_SIZE(sub_allocators));
+ if (err) {
+ return err;
+ }
+
+
+ allocator->command_stream.stream_id = sub_allocators[0].stream_id;
+ allocator->weight_data.stream_id = sub_allocators[1].stream_id;
+ allocator->buffer_data.stream_id = sub_allocators[2].stream_id;
+ allocator->intermediate_data.stream_id = sub_allocators[3].stream_id;
+ return 0;
+}
+
+static int fdt_node_populate_core(const void *fdt,
+ int device_node,
+ int core_node,
+ bool has_reserved_memory,
+ uint32_t core_index,
+ struct ethosn_core_t *core)
+{
+ int err;
+ int sub_node;
+ uintptr_t core_addr;
+
+ err = fdt_get_reg_props_by_index(fdt, device_node, core_index,
+ &core_addr, NULL);
+ if (err < 0) {
+ ERROR("FCONF: Failed to read reg property for NPU core %u\n",
+ core_index);
+ return err;
+ }
+
+ err = -FDT_ERR_NOTFOUND;
+ fdt_for_each_subnode(sub_node, fdt, core_node) {
+
+ if (!fdt_node_is_enabled(fdt, sub_node)) {
+ continue;
+ }
+
+ if (fdt_node_check_compatible(fdt,
+ sub_node,
+ "ethosn-main_allocator") != 0) {
+ continue;
+ }
+
+ if (has_reserved_memory) {
+ ERROR("FCONF: Main allocator not supported when using reserved memory\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ if (err != -FDT_ERR_NOTFOUND) {
+ ERROR("FCONF: NPU core 0x%lx has more than one main allocator\n",
+ core_addr);
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ err = fdt_node_populate_main_allocator(fdt, sub_node, &core->main_allocator);
+ if (err) {
+ ERROR("FCONF: Failed to parse main allocator for NPU core 0x%lx\n",
+ core_addr);
+ return err;
+ }
+ }
+
+ if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
+ ERROR("FCONF: Failed to parse core sub nodes\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ if (!has_reserved_memory && err) {
+ ERROR("FCONF: Main allocator not found for NPU core 0x%lx\n",
+ core_addr);
+ return err;
+ }
+
+ core->addr = core_addr;
+
+ return 0;
+}
+
+int fconf_populate_ethosn_config(uintptr_t config)
+{
+ int ethosn_node;
+ uint32_t dev_count = 0U;
+ const void *hw_conf_dtb = (const void *)config;
+
+ INFO("Probing Arm(R) Ethos(TM)-N NPU\n");
+
+ fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") {
+ struct ethosn_device_t *dev = &ethosn_config.devices[dev_count];
+ uint32_t dev_asset_alloc_count = 0U;
+ uint32_t dev_core_count = 0U;
+ bool has_reserved_memory;
+ int sub_node;
+
+ if (!fdt_node_is_enabled(hw_conf_dtb, ethosn_node)) {
+ continue;
+ }
+
+ if (dev_count >= ETHOSN_DEV_NUM_MAX) {
+ ERROR("FCONF: Reached max number of NPUs\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ has_reserved_memory = fdt_node_has_reserved_memory(hw_conf_dtb, ethosn_node);
+ fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
+ int err;
+
+ if (!fdt_node_is_enabled(hw_conf_dtb, sub_node)) {
+ /* Ignore disabled sub node */
+ continue;
+ }
+
+ if (fdt_node_check_compatible(hw_conf_dtb,
+ sub_node,
+ "ethosn-core") == 0) {
+
+ if (dev_core_count >= ETHOSN_DEV_CORE_NUM_MAX) {
+ ERROR("FCONF: Reached max number of NPU cores for NPU %u\n",
+ dev_count);
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ err = fdt_node_populate_core(hw_conf_dtb,
+ ethosn_node,
+ sub_node,
+ has_reserved_memory,
+ dev_core_count,
+ &(dev->cores[dev_core_count]));
+ if (err) {
+ return err;
+ }
+ ++dev_core_count;
+ } else if (fdt_node_check_compatible(hw_conf_dtb,
+ sub_node,
+ "ethosn-asset_allocator") == 0) {
+
+ if (dev_asset_alloc_count >=
+ ETHOSN_DEV_ASSET_ALLOCATOR_NUM_MAX) {
+ ERROR("FCONF: Reached max number of asset allocators for NPU %u\n",
+ dev_count);
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ if (has_reserved_memory) {
+ ERROR("FCONF: Asset allocator not supported when using reserved memory\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ err = fdt_node_populate_asset_allocator(hw_conf_dtb,
+ sub_node,
+ &(dev->asset_allocators[dev_asset_alloc_count]));
+ if (err) {
+ ERROR("FCONF: Failed to parse asset allocator for NPU %u\n",
+ dev_count);
+ return err;
+ }
+ ++dev_asset_alloc_count;
+ }
+ }
+
+ if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
+ ERROR("FCONF: Failed to parse sub nodes for NPU %u\n",
+ dev_count);
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ if (dev_core_count == 0U) {
+ ERROR("FCONF: NPU %u must have at least one enabled core\n",
+ dev_count);
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ if (!has_reserved_memory && dev_asset_alloc_count == 0U) {
+ ERROR("FCONF: NPU %u must have at least one asset allocator\n",
+ dev_count);
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ dev->num_cores = dev_core_count;
+ dev->num_allocators = dev_asset_alloc_count;
+ dev->has_reserved_memory = has_reserved_memory;
+ ++dev_count;
+ }
+
+ if (dev_count == 0U) {
+ ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+
+ ethosn_config.num_devices = dev_count;
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config);
diff --git a/plat/arm/common/fconf/fconf_nv_cntr_getter.c b/plat/arm/common/fconf/fconf_nv_cntr_getter.c
new file mode 100644
index 0000000..8d645ef
--- /dev/null
+++ b/plat/arm/common/fconf/fconf_nv_cntr_getter.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+
+#include <libfdt.h>
+
+#include <plat/arm/common/fconf_nv_cntr_getter.h>
+
+/*******************************************************************************
+ * fconf_populate_cot_descs() - Populate available nv-counters and update global
+ * structure.
+ * @config[in]: Pointer to the device tree blob in memory
+ *
+ * Return 0 on success or an error value otherwise.
+ ******************************************************************************/
+static int fconf_populate_nv_cntrs(uintptr_t config)
+{
+ int rc, node, child;
+ uint32_t id;
+ uintptr_t reg;
+
+ /* As libfdt uses void *, we can't avoid this cast */
+ const void *dtb = (void *)config;
+ const char *compatible_str = "arm, non-volatile-counter";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s compatible in node\n",
+ compatible_str);
+ return node;
+ }
+
+ fdt_for_each_subnode(child, dtb, node) {
+
+ rc = fdt_read_uint32(dtb, child, "id", &id);
+ if (rc < 0) {
+ ERROR("FCONF: Can't find %s property in node\n", "id");
+ return rc;
+ }
+
+ assert(id < MAX_NV_CTR_IDS);
+
+ rc = fdt_get_reg_props_by_index(dtb, child, 0, &reg, NULL);
+ if (rc < 0) {
+ ERROR("FCONF: Can't find %s property in node\n", "reg");
+ return rc;
+ }
+
+ nv_cntr_base_addr[id] = reg;
+ }
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(TB_FW, nv_cntrs, fconf_populate_nv_cntrs);
diff --git a/plat/arm/common/fconf/fconf_sdei_getter.c b/plat/arm/common/fconf/fconf_sdei_getter.c
new file mode 100644
index 0000000..c26e316
--- /dev/null
+++ b/plat/arm/common/fconf/fconf_sdei_getter.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+#include <plat/arm/common/fconf_sdei_getter.h>
+
+#define PRIVATE_EVENT_NUM(i) private_events[3 * (i)]
+#define PRIVATE_EVENT_INTR(i) private_events[3 * (i) + 1]
+#define PRIVATE_EVENT_FLAGS(i) private_events[3 * (i) + 2]
+
+#define SHARED_EVENT_NUM(i) shared_events[3 * (i)]
+#define SHARED_EVENT_INTR(i) shared_events[3 * (i) + 1]
+#define SHARED_EVENT_FLAGS(i) shared_events[3 * (i) + 2]
+
+struct sdei_dyn_config_t sdei_dyn_config;
+
+int fconf_populate_sdei_dyn_config(uintptr_t config)
+{
+ uint32_t i;
+ int node, err;
+ uint32_t private_events[PLAT_SDEI_DP_EVENT_MAX_CNT * 3];
+ uint32_t shared_events[PLAT_SDEI_DS_EVENT_MAX_CNT * 3];
+
+ const void *dtb = (void *)config;
+
+ /* Check that the node offset points to compatible property */
+ node = fdt_node_offset_by_compatible(dtb, -1, "arm,sdei-1.0");
+ if (node < 0) {
+ ERROR("FCONF: Can't find 'arm,sdei-1.0' compatible node in dtb\n");
+ return node;
+ }
+
+ /* Read number of private mappings */
+ err = fdt_read_uint32(dtb, node, "private_event_count",
+ &sdei_dyn_config.private_ev_cnt);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'private_event_count': %u\n",
+ sdei_dyn_config.private_ev_cnt);
+ return err;
+ }
+
+ /* Check if the value is in range */
+ if (sdei_dyn_config.private_ev_cnt > PLAT_SDEI_DP_EVENT_MAX_CNT) {
+ ERROR("FCONF: Invalid value for 'private_event_count': %u\n",
+ sdei_dyn_config.private_ev_cnt);
+ return -1;
+ }
+
+ /* Read private mappings */
+ err = fdt_read_uint32_array(dtb, node, "private_events",
+ sdei_dyn_config.private_ev_cnt * 3, private_events);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'private_events': %d\n", err);
+ return err;
+ }
+
+ /* Move data to fconf struct */
+ for (i = 0; i < sdei_dyn_config.private_ev_cnt; i++) {
+ sdei_dyn_config.private_ev_nums[i] = PRIVATE_EVENT_NUM(i);
+ sdei_dyn_config.private_ev_intrs[i] = PRIVATE_EVENT_INTR(i);
+ sdei_dyn_config.private_ev_flags[i] = PRIVATE_EVENT_FLAGS(i);
+ }
+
+ /* Read number of shared mappings */
+ err = fdt_read_uint32(dtb, node, "shared_event_count",
+ &sdei_dyn_config.shared_ev_cnt);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'shared_event_count'\n");
+ return err;
+ }
+
+ /* Check if the value is in range */
+ if (sdei_dyn_config.shared_ev_cnt > PLAT_SDEI_DS_EVENT_MAX_CNT) {
+ ERROR("FCONF: Invalid value for 'shared_event_count': %u\n",
+ sdei_dyn_config.shared_ev_cnt);
+ return -1;
+ }
+
+ /* Read shared mappings */
+ err = fdt_read_uint32_array(dtb, node, "shared_events",
+ sdei_dyn_config.shared_ev_cnt * 3, shared_events);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'shared_events': %d\n", err);
+ return err;
+ }
+
+ /* Move data to fconf struct */
+ for (i = 0; i < sdei_dyn_config.shared_ev_cnt; i++) {
+ sdei_dyn_config.shared_ev_nums[i] = SHARED_EVENT_NUM(i);
+ sdei_dyn_config.shared_ev_intrs[i] = SHARED_EVENT_INTR(i);
+ sdei_dyn_config.shared_ev_flags[i] = SHARED_EVENT_FLAGS(i);
+ }
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(HW_CONFIG, sdei, fconf_populate_sdei_dyn_config);
diff --git a/plat/arm/common/fconf/fconf_sec_intr_config.c b/plat/arm/common/fconf/fconf_sec_intr_config.c
new file mode 100644
index 0000000..f28be24
--- /dev/null
+++ b/plat/arm/common/fconf/fconf_sec_intr_config.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+#include <plat/arm/common/fconf_sec_intr_config.h>
+
+#define G0_INTR_NUM(i) g0_intr_prop[3U * (i)]
+#define G0_INTR_PRIORITY(i) g0_intr_prop[3U * (i) + 1]
+#define G0_INTR_CONFIG(i) g0_intr_prop[3U * (i) + 2]
+
+#define G1S_INTR_NUM(i) g1s_intr_prop[3U * (i)]
+#define G1S_INTR_PRIORITY(i) g1s_intr_prop[3U * (i) + 1]
+#define G1S_INTR_CONFIG(i) g1s_intr_prop[3U * (i) + 2]
+
+struct sec_intr_prop_t sec_intr_prop;
+
+static void print_intr_prop(interrupt_prop_t prop)
+{
+ VERBOSE("FCONF: Secure Interrupt NUM: %d, PRI: %d, TYPE: %d\n",
+ prop.intr_num, prop.intr_pri, prop.intr_cfg);
+}
+
+int fconf_populate_sec_intr_config(uintptr_t config)
+{
+ int node, err;
+ uint32_t g0_intr_count, g1s_intr_count;
+ uint32_t g0_intr_prop[SEC_INT_COUNT_MAX * 3];
+ uint32_t g1s_intr_prop[SEC_INT_COUNT_MAX * 3];
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ node = fdt_node_offset_by_compatible(hw_config_dtb, -1,
+ "arm,secure_interrupt_desc");
+ if (node < 0) {
+ ERROR("FCONF: Unable to locate node with %s compatible property\n",
+ "arm,secure_interrupt_desc");
+ return node;
+ }
+
+ /* Read number of Group 0 interrupts specified by platform */
+ err = fdt_read_uint32(hw_config_dtb, node, "g0_intr_cnt", &g0_intr_count);
+ if (err < 0) {
+ ERROR("FCONF: Could not locate g0s_intr_cnt property\n");
+ return err;
+ }
+
+ /* At least 1 Group 0 interrupt description has to be provided*/
+ if (g0_intr_count < 1U) {
+ ERROR("FCONF: Invalid number of Group 0 interrupts count specified\n");
+ return -1;
+ }
+
+ /* Read number of Group 1 secure interrupts specified by platform */
+ err = fdt_read_uint32(hw_config_dtb, node, "g1s_intr_cnt",
+ &g1s_intr_count);
+ if (err < 0) {
+ ERROR("FCONF: Could not locate g1s_intr_cnt property\n");
+ return err;
+ }
+
+ /* At least one Group 1 interrupt description has to be provided*/
+ if (g1s_intr_count < 1U) {
+ ERROR("FCONF: Invalid number of Group 1 secure interrupts count specified\n");
+ return -1;
+ }
+
+ /*
+ * Check if the total number of secure interrupts described are within
+ * the limit defined statically by the platform.
+ */
+ if ((g0_intr_count + g1s_intr_count) > SEC_INT_COUNT_MAX) {
+ ERROR("FCONF: Total number of secure interrupts exceed limit the of %d\n",
+ SEC_INT_COUNT_MAX);
+ return -1;
+ }
+
+ sec_intr_prop.count = g0_intr_count + g1s_intr_count;
+
+ /* Read the Group 0 interrupt descriptors */
+ err = fdt_read_uint32_array(hw_config_dtb, node, "g0_intr_desc",
+ g0_intr_count * 3, g0_intr_prop);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'g0s_intr_desc': %d\n", err);
+ return err;
+ }
+
+ /* Read the Group 1 secure interrupt descriptors */
+ err = fdt_read_uint32_array(hw_config_dtb, node, "g1s_intr_desc",
+ g1s_intr_count * 3, g1s_intr_prop);
+ if (err < 0) {
+ ERROR("FCONF: Read cell failed for 'g1s_intr_desc': %d\n", err);
+ return err;
+ }
+
+ /* Populate Group 0 interrupt descriptors into fconf based C struct */
+ for (uint32_t i = 0; i < g0_intr_count; i++) {
+ interrupt_prop_t sec_intr_property;
+
+ /* Secure Interrupt Group: INTR_GROUP0 i.e., 0x1 */
+ sec_intr_property.intr_grp = 1;
+ sec_intr_property.intr_num = G0_INTR_NUM(i);
+ sec_intr_property.intr_pri = G0_INTR_PRIORITY(i);
+ sec_intr_property.intr_cfg = G0_INTR_CONFIG(i);
+ sec_intr_prop.descriptor[i] = sec_intr_property;
+ print_intr_prop(sec_intr_property);
+ }
+
+ /* Populate G1 secure interrupt descriptors into fconf based C struct */
+ for (uint32_t i = 0; i < g1s_intr_count; i++) {
+ interrupt_prop_t sec_intr_property;
+
+ /* Secure Interrupt Group: INTR_GROUP1S i.e., 0x0 */
+ sec_intr_property.intr_grp = 0;
+ sec_intr_property.intr_num = G1S_INTR_NUM(i);
+ sec_intr_property.intr_pri = G1S_INTR_PRIORITY(i);
+ sec_intr_property.intr_cfg = G1S_INTR_CONFIG(i);
+ sec_intr_prop.descriptor[i + g0_intr_count] = sec_intr_property;
+ print_intr_prop(sec_intr_property);
+ }
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(HW_CONFIG, sec_intr_prop, fconf_populate_sec_intr_config);
diff --git a/plat/arm/common/sp_min/arm_sp_min.mk b/plat/arm/common/sp_min/arm_sp_min.mk
new file mode 100644
index 0000000..dbd451c
--- /dev/null
+++ b/plat/arm/common/sp_min/arm_sp_min.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SP MIN source files common to ARM standard platforms
+
+# Skip building BL1, BL2 and BL2U if RESET_TO_SP_MIN flag is set.
+ifeq (${RESET_TO_SP_MIN},1)
+ BL1_SOURCES =
+ BL2_SOURCES =
+ BL2U_SOURCES =
+endif
+
+BL32_SOURCES += plat/arm/common/arm_pm.c \
+ plat/arm/common/arm_topology.c \
+ plat/arm/common/sp_min/arm_sp_min_setup.c \
+ plat/common/aarch32/platform_mp_stack.S \
+ plat/common/plat_psci_common.c
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
new file mode 100644
index 0000000..f15c137
--- /dev/null
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <bl32/sp_min/platform_sp_min.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+static entry_point_info_t bl33_image_ep_info;
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak sp_min_platform_setup
+#pragma weak sp_min_plat_arch_setup
+#pragma weak plat_arm_sp_min_early_platform_setup
+
+#define MAP_BL_SP_MIN_TOTAL MAP_REGION_FLAT( \
+ BL32_BASE, \
+ BL32_END - BL32_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Check that BL32_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
+ * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
+ */
+#if !RESET_TO_SP_MIN
+CASSERT(BL32_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
+#endif
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for the
+ * security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = &bl33_image_ep_info;
+
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Utility function to perform early platform setup.
+ ******************************************************************************/
+void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config,
+ uintptr_t hw_config, void *plat_params_from_bl2)
+{
+ /* Initialize the console to provide early debug support */
+ arm_console_boot_init();
+
+#if RESET_TO_SP_MIN
+ /* There are no parameters from BL2 if SP_MIN is a reset vector */
+ assert(from_bl2 == NULL);
+ assert(plat_params_from_bl2 == NULL);
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell SP_MIN where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+# if ARM_LINUX_KERNEL_AS_BL33
+ /*
+ * According to the file ``Documentation/arm/Booting`` of the Linux
+ * kernel tree, Linux expects:
+ * r0 = 0
+ * r1 = machine type number, optional in DT-only platforms (~0 if so)
+ * r2 = Physical address of the device tree blob
+ */
+ bl33_image_ep_info.args.arg0 = 0U;
+ bl33_image_ep_info.args.arg1 = ~0U;
+ bl33_image_ep_info.args.arg2 = (u_register_t)ARM_PRELOADED_DTB_BASE;
+# endif
+
+#else /* RESET_TO_SP_MIN */
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL33_IMAGE_ID) {
+ bl33_image_ep_info = *bl_params->ep_info;
+ break;
+ }
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0)
+ panic();
+
+#endif /* RESET_TO_SP_MIN */
+
+}
+
+/*******************************************************************************
+ * Default implementation for sp_min_platform_setup2() for ARM platforms
+ ******************************************************************************/
+void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_arm_interconnect_init();
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this (e.g. Trusted
+ * Firmware's BL1 does it) but we can't assume so. There is no harm in
+ * executing this code twice anyway.
+ * Platform specific PSCI code will enable coherency for other
+ * clusters.
+ */
+ plat_arm_interconnect_enter_coherency();
+}
+
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ plat_arm_sp_min_early_platform_setup(arg0, arg1, arg2, arg3);
+}
+
+/*******************************************************************************
+ * Perform any SP_MIN platform runtime setup prior to SP_MIN exit.
+ * Common to ARM standard platforms.
+ ******************************************************************************/
+void arm_sp_min_plat_runtime_setup(void)
+{
+ /* Initialize the runtime console */
+ arm_console_runtime_init();
+
+#if PLAT_RO_XLAT_TABLES
+ arm_xlat_make_tables_readonly();
+#endif
+}
+
+/*******************************************************************************
+ * Perform platform specific setup for SP_MIN
+ ******************************************************************************/
+void sp_min_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ plat_arm_gic_driver_init();
+ plat_arm_gic_init();
+
+ /*
+ * Do initial security configuration to allow DRAM/device access
+ * (if earlier BL has not already done so).
+ */
+#if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME
+ plat_arm_security_setup();
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+ arm_nor_psci_do_dyn_mem_protect();
+#endif /* PLAT_ARM_MEM_PROT_ADDR */
+
+#endif
+
+ /* Enable and initialize the System level generic timer */
+#ifdef ARM_SYS_CNTCTL_BASE
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0U) | CNTCR_EN);
+#endif
+#ifdef ARM_SYS_TIMCTL_BASE
+ /* Allow access to the System counter timer module */
+ arm_configure_sys_timer();
+#endif
+ /* Initialize power controller before setting up topology */
+ plat_arm_pwrc_setup();
+}
+
+void sp_min_plat_runtime_setup(void)
+{
+ arm_sp_min_plat_runtime_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this only initializes the MMU
+ ******************************************************************************/
+void arm_sp_min_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL_SP_MIN_TOTAL,
+ ARM_MAP_BL_RO,
+#if USE_COHERENT_MEM
+ ARM_MAP_BL_COHERENT_RAM,
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+
+ enable_mmu_svc_mon(0);
+}
+
+void sp_min_plat_arch_setup(void)
+{
+ arm_sp_min_plat_arch_setup();
+}
diff --git a/plat/arm/common/trp/arm_trp.mk b/plat/arm/common/trp/arm_trp.mk
new file mode 100644
index 0000000..204c14a
--- /dev/null
+++ b/plat/arm/common/trp/arm_trp.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TRP source files common to ARM standard platforms
+RMM_SOURCES += plat/arm/common/trp/arm_trp_setup.c \
+ plat/arm/common/arm_topology.c \
+ plat/common/aarch64/platform_mp_stack.S
+
+INCLUDES += -Iinclude/services/trp
diff --git a/plat/arm/common/trp/arm_trp_setup.c b/plat/arm/common/trp/arm_trp_setup.c
new file mode 100644
index 0000000..59b4c06
--- /dev/null
+++ b/plat/arm/common/trp/arm_trp_setup.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <services/rmm_core_manifest.h>
+#include <services/rmmd_svc.h>
+#include <services/trp/platform_trp.h>
+#include <trp_helpers.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Received from boot manifest and populated here
+ ******************************************************************************/
+extern uint32_t trp_boot_manifest_version;
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+static console_t arm_trp_runtime_console;
+
+static int arm_trp_process_manifest(rmm_manifest_t *manifest)
+{
+ /* Verify the Boot Manifest Version. Only the Major is considered */
+ if (RMMD_MANIFEST_VERSION_MAJOR !=
+ RMMD_GET_MANIFEST_VERSION_MAJOR(manifest->version)) {
+ return E_RMM_BOOT_MANIFEST_VERSION_NOT_SUPPORTED;
+ }
+
+ trp_boot_manifest_version = manifest->version;
+ flush_dcache_range((uintptr_t)manifest, sizeof(rmm_manifest_t));
+
+ return 0;
+}
+
+void arm_trp_early_platform_setup(rmm_manifest_t *manifest)
+{
+ int rc;
+
+ rc = arm_trp_process_manifest(manifest);
+ if (rc != 0) {
+ trp_boot_abort(rc);
+ }
+
+ /*
+ * Initialize a different console than already in use to display
+ * messages from trp
+ */
+ rc = console_pl011_register(PLAT_ARM_TRP_UART_BASE,
+ PLAT_ARM_TRP_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE,
+ &arm_trp_runtime_console);
+ if (rc == 0) {
+ panic();
+ }
+
+ console_set_scope(&arm_trp_runtime_console,
+ CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+
+}
+
+void trp_early_platform_setup(rmm_manifest_t *manifest)
+{
+ arm_trp_early_platform_setup(manifest);
+}
diff --git a/plat/arm/common/tsp/arm_tsp.mk b/plat/arm/common/tsp/arm_tsp.mk
new file mode 100644
index 0000000..4ad77c6
--- /dev/null
+++ b/plat/arm/common/tsp/arm_tsp.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TSP source files common to ARM standard platforms
+BL32_SOURCES += plat/arm/common/arm_topology.c \
+ plat/arm/common/tsp/arm_tsp_setup.c \
+ plat/common/aarch64/platform_mp_stack.S
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
new file mode 100644
index 0000000..a4da8c3
--- /dev/null
+++ b/plat/arm/common/tsp/arm_tsp_setup.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <bl32/tsp/platform_tsp.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak tsp_early_platform_setup
+#pragma weak tsp_platform_setup
+#pragma weak tsp_plat_arch_setup
+
+#define MAP_BL_TSP_TOTAL MAP_REGION_FLAT( \
+ BL32_BASE, \
+ BL32_END - BL32_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+static console_t arm_tsp_runtime_console;
+
+void arm_tsp_early_platform_setup(void)
+{
+ /*
+ * Initialize a different console than already in use to display
+ * messages from TSP
+ */
+ int rc = console_pl011_register(PLAT_ARM_TSP_UART_BASE,
+ PLAT_ARM_TSP_UART_CLK_IN_HZ,
+ ARM_CONSOLE_BAUDRATE,
+ &arm_tsp_runtime_console);
+ if (rc == 0)
+ panic();
+
+ console_set_scope(&arm_tsp_runtime_console,
+ CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+}
+
+void tsp_early_platform_setup(void)
+{
+ arm_tsp_early_platform_setup();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+ plat_arm_gic_driver_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+#if USE_COHERENT_MEM
+ /* Ensure ARM platforms don't use coherent memory in TSP */
+ assert((BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE) == 0U);
+#endif
+
+ const mmap_region_t bl_regions[] = {
+ MAP_BL_TSP_TOTAL,
+ ARM_MAP_BL_RO,
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+ enable_mmu_el1(0);
+
+#if PLAT_RO_XLAT_TABLES
+ arm_xlat_make_tables_readonly();
+#endif
+}
diff --git a/plat/arm/css/common/aarch32/css_helpers.S b/plat/arm/css/common/aarch32/css_helpers.S
new file mode 100644
index 0000000..d47e13d
--- /dev/null
+++ b/plat/arm/css/common/aarch32/css_helpers.S
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+ .weak plat_secondary_cold_boot_setup
+ .weak plat_get_my_entrypoint
+ .globl css_calc_core_pos_swap_cluster
+ .weak plat_is_my_cpu_primary
+
+ /* ---------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup(void);
+ * In the normal boot flow, cold-booting secondary
+ * CPUs is not yet implemented and they panic.
+ * ---------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* TODO: Implement secondary CPU cold boot setup on CSS platforms */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and a warm
+ * boot. On CSS platforms, this distinction is based on the contents of
+ * the Trusted Mailbox. It is initialised to zero by the SCP before the
+ * AP cores are released from reset. Therefore, a zero mailbox means
+ * it's a cold reset.
+ *
+ * This functions returns the contents of the mailbox, i.e.:
+ * - 0 for a cold boot;
+ * - the warm boot entrypoint for a warm boot.
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr r0, [r0]
+ bx lr
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------------
+ * unsigned int css_calc_core_pos_swap_cluster(u_register_t mpidr)
+ * Utility function to calculate the core position by
+ * swapping the cluster order. This is necessary in order to
+ * match the format of the boot information passed by the SCP
+ * and read in plat_is_my_cpu_primary below.
+ * -----------------------------------------------------------
+ */
+func css_calc_core_pos_swap_cluster
+ and r1, r0, #MPIDR_CPU_MASK
+ and r0, r0, #MPIDR_CLUSTER_MASK
+ eor r0, r0, #(1 << MPIDR_AFFINITY_BITS) // swap cluster order
+ add r0, r1, r0, LSR #6
+ bx lr
+endfunc css_calc_core_pos_swap_cluster
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu (applicable ony after a cold boot)
+ * -----------------------------------------------------
+ */
+#if CSS_USE_SCMI_SDS_DRIVER
+func plat_is_my_cpu_primary
+ mov r10, lr
+ bl plat_my_core_pos
+ mov r4, r0
+ bl sds_get_primary_cpu_id
+ /* Check for error */
+ mov r1, #0xffffffff
+ cmp r0, r1
+ beq 1f
+ cmp r0, r4
+ moveq r0, #1
+ movne r0, #0
+ bx r10
+1:
+ no_ret plat_panic_handler
+endfunc plat_is_my_cpu_primary
+#else
+func plat_is_my_cpu_primary
+ mov r10, lr
+ bl plat_my_core_pos
+ ldr r1, =SCP_BOOT_CFG_ADDR
+ ldr r1, [r1]
+ ubfx r1, r1, #PLAT_CSS_PRIMARY_CPU_SHIFT, \
+ #PLAT_CSS_PRIMARY_CPU_BIT_WIDTH
+ cmp r0, r1
+ moveq r0, #1
+ movne r0, #0
+ bx r10
+endfunc plat_is_my_cpu_primary
+#endif
diff --git a/plat/arm/css/common/aarch64/css_helpers.S b/plat/arm/css/common/aarch64/css_helpers.S
new file mode 100644
index 0000000..01669be
--- /dev/null
+++ b/plat/arm/css/common/aarch64/css_helpers.S
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+ .weak plat_secondary_cold_boot_setup
+ .weak plat_get_my_entrypoint
+ .globl css_calc_core_pos_swap_cluster
+ .weak plat_is_my_cpu_primary
+
+ /* ---------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup(void);
+ *
+ * In the normal boot flow, cold-booting secondary CPUs is not yet
+ * implemented and they panic.
+ *
+ * When booting an EL3 payload, secondary CPUs are placed in a holding
+ * pen, waiting for their mailbox to be populated. Note that all CPUs
+ * share the same mailbox ; therefore, populating it will release all
+ * CPUs from their holding pen. If finer-grained control is needed then
+ * this should be handled in the code that secondary CPUs jump to.
+ * ---------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+#ifndef EL3_PAYLOAD_BASE
+ /* TODO: Implement secondary CPU cold boot setup on CSS platforms */
+cb_panic:
+ b cb_panic
+#else
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+
+ /* Wait until the mailbox gets populated */
+poll_mailbox:
+ ldr x1, [x0]
+ cbz x1, 1f
+ br x1
+1:
+ wfe
+ b poll_mailbox
+#endif /* EL3_PAYLOAD_BASE */
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and a warm
+ * boot. On CSS platforms, this distinction is based on the contents of
+ * the Trusted Mailbox. It is initialised to zero by the SCP before the
+ * AP cores are released from reset. Therefore, a zero mailbox means
+ * it's a cold reset.
+ *
+ * This functions returns the contents of the mailbox, i.e.:
+ * - 0 for a cold boot;
+ * - the warm boot entrypoint for a warm boot.
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mov_imm x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+ ldr x0, [x0]
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------------
+ * unsigned int css_calc_core_pos_swap_cluster(u_register_t mpidr)
+ * Utility function to calculate the core position by
+ * swapping the cluster order. This is necessary in order to
+ * match the format of the boot information passed by the SCP
+ * and read in plat_is_my_cpu_primary below.
+ * -----------------------------------------------------------
+ */
+func css_calc_core_pos_swap_cluster
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ eor x0, x0, #(1 << MPIDR_AFFINITY_BITS) // swap cluster order
+ add x0, x1, x0, LSR #6
+ ret
+endfunc css_calc_core_pos_swap_cluster
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu (applicable ony after a cold boot)
+ * -----------------------------------------------------
+ */
+#if CSS_USE_SCMI_SDS_DRIVER
+func plat_is_my_cpu_primary
+ mov x9, x30
+ bl plat_my_core_pos
+ mov x4, x0
+ bl sds_get_primary_cpu_id
+ /* Check for error */
+ mov x1, #0xffffffff
+ cmp x0, x1
+ b.eq 1f
+ cmp x0, x4
+ cset w0, eq
+ ret x9
+1:
+ no_ret plat_panic_handler
+endfunc plat_is_my_cpu_primary
+#else
+func plat_is_my_cpu_primary
+ mov x9, x30
+ bl plat_my_core_pos
+ mov_imm x1, SCP_BOOT_CFG_ADDR
+ ldr x1, [x1]
+ ubfx x1, x1, #PLAT_CSS_PRIMARY_CPU_SHIFT, \
+ #PLAT_CSS_PRIMARY_CPU_BIT_WIDTH
+ cmp x0, x1
+ cset w0, eq
+ ret x9
+endfunc plat_is_my_cpu_primary
+#endif
diff --git a/plat/arm/css/common/css_bl1_setup.c b/plat/arm/css/common/css_bl1_setup.c
new file mode 100644
index 0000000..596cc3d
--- /dev/null
+++ b/plat/arm/css/common/css_bl1_setup.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/soc/common/soc_css.h>
+#include <plat/common/platform.h>
+
+void bl1_platform_setup(void)
+{
+ arm_bl1_platform_setup();
+ /*
+ * Do ARM CSS SoC security setup.
+ * BL1 needs to enable normal world access to memory.
+ */
+ soc_css_security_setup();
+}
+
diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c
new file mode 100644
index 0000000..002c6eb
--- /dev/null
+++ b/plat/arm/css/common/css_bl2_setup.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_scp.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/* Weak definition may be overridden in specific CSS based platform */
+#pragma weak plat_arm_bl2_handle_scp_bl2
+
+/*******************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int plat_arm_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ int ret;
+
+ INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
+
+ ret = css_scp_boot_image_xfer((void *)scp_bl2_image_info->image_base,
+ scp_bl2_image_info->image_size);
+
+ if (ret == 0)
+ ret = css_scp_boot_ready();
+
+ if (ret == 0)
+ INFO("BL2: SCP_BL2 transferred to SCP\n");
+ else
+ ERROR("BL2: SCP_BL2 transfer failure\n");
+
+ return ret;
+}
+
+#if !CSS_USE_SCMI_SDS_DRIVER
+# if defined(EL3_PAYLOAD_BASE) || JUNO_AARCH32_EL3_RUNTIME
+
+/*
+ * We need to override some of the platform functions when booting an EL3
+ * payload or SP_MIN on Juno AArch32. This needs to be done only for
+ * SCPI/BOM SCP systems as in case of SDS, the structures remain in memory and
+ * don't need to be overwritten.
+ */
+
+static unsigned int scp_boot_config;
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
+
+ /* Save SCP Boot config before it gets overwritten by SCP_BL2 loading */
+ scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR);
+ VERBOSE("BL2: Saved SCP Boot config = 0x%x\n", scp_boot_config);
+}
+
+void bl2_platform_setup(void)
+{
+ arm_bl2_platform_setup();
+
+ /*
+ * Before releasing the AP cores out of reset, the SCP writes some data
+ * at the beginning of the Trusted SRAM. It is is overwritten before
+ * reaching this function. We need to restore this data, as if the
+ * target had just come out of reset. This implies:
+ * - zeroing the first 128 bytes of Trusted SRAM using zeromem instead
+ * of zero_normalmem since this is device memory.
+ * - restoring the SCP boot configuration.
+ */
+ VERBOSE("BL2: Restoring SCP reset data in Trusted SRAM\n");
+ zeromem((void *) ARM_SHARED_RAM_BASE, 128);
+ mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
+}
+
+# endif /* EL3_PAYLOAD_BASE */
+
+#endif /* CSS_USE_SCMI_SDS_DRIVER */
diff --git a/plat/arm/css/common/css_bl2u_setup.c b/plat/arm/css/common/css_bl2u_setup.c
new file mode 100644
index 0000000..15cf4f6
--- /dev/null
+++ b/plat/arm/css/common/css_bl2u_setup.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_scp.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* Weak definition may be overridden in specific CSS based platform */
+#pragma weak bl2u_plat_handle_scp_bl2u
+
+/* Data structure which holds the SCP_BL2U image info for BL2U */
+static image_info_t scp_bl2u_image_info;
+
+/*******************************************************************************
+ * BL1 can pass platform dependent information to BL2U in x1.
+ * In case of ARM CSS platforms x1 contains SCP_BL2U image info.
+ * In case of ARM FVP platforms x1 is not used.
+ * In both cases, x0 contains the extents of the memory available to BL2U
+ ******************************************************************************/
+void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
+{
+ if (!plat_info)
+ panic();
+
+ arm_bl2u_early_platform_setup(mem_layout, plat_info);
+
+ scp_bl2u_image_info = *(image_info_t *)plat_info;
+}
+
+/*******************************************************************************
+ * Transfer SCP_BL2U from Trusted RAM using the SCP Download protocol.
+ ******************************************************************************/
+int bl2u_plat_handle_scp_bl2u(void)
+{
+ int ret;
+
+ INFO("BL2U: Initiating SCP_BL2U transfer to SCP\n");
+
+ ret = css_scp_boot_image_xfer((void *)scp_bl2u_image_info.image_base,
+ scp_bl2u_image_info.image_size);
+
+ if (ret == 0)
+ ret = css_scp_boot_ready();
+
+ if (ret == 0)
+ INFO("BL2U: SCP_BL2U transferred to SCP\n");
+ else
+ ERROR("BL2U: SCP_BL2U transfer failure\n");
+
+ return ret;
+}
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
new file mode 100644
index 0000000..1e4851c
--- /dev/null
+++ b/plat/arm/css/common/css_common.mk
@@ -0,0 +1,97 @@
+#
+# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+# By default, SCP images are needed by CSS platforms.
+CSS_LOAD_SCP_IMAGES ?= 1
+
+# By default, SCMI driver is disabled for CSS platforms
+CSS_USE_SCMI_SDS_DRIVER ?= 0
+
+PLAT_INCLUDES += -Iinclude/plat/arm/css/common/aarch64
+
+
+PLAT_BL_COMMON_SOURCES += plat/arm/css/common/${ARCH}/css_helpers.S
+
+BL1_SOURCES += plat/arm/css/common/css_bl1_setup.c
+
+BL2_SOURCES += plat/arm/css/common/css_bl2_setup.c
+
+BL2U_SOURCES += plat/arm/css/common/css_bl2u_setup.c
+
+BL31_SOURCES += plat/arm/css/common/css_pm.c \
+ plat/arm/css/common/css_topology.c
+
+ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
+BL31_SOURCES += drivers/arm/css/mhu/css_mhu.c \
+ drivers/arm/css/scp/css_pm_scpi.c \
+ drivers/arm/css/scpi/css_scpi.c
+else
+BL31_SOURCES += drivers/arm/css/mhu/css_mhu_doorbell.c \
+ drivers/arm/css/scmi/scmi_ap_core_proto.c \
+ drivers/arm/css/scmi/scmi_common.c \
+ drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \
+ drivers/arm/css/scmi/scmi_sys_pwr_proto.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/arm/css/scp/css_pm_scmi.c
+endif
+
+# Process CSS_LOAD_SCP_IMAGES flag
+$(eval $(call assert_boolean,CSS_LOAD_SCP_IMAGES))
+$(eval $(call add_define,CSS_LOAD_SCP_IMAGES))
+
+ifeq (${CSS_LOAD_SCP_IMAGES},1)
+ NEED_SCP_BL2 := yes
+ ifneq (${TRUSTED_BOARD_BOOT},0)
+ $(eval $(call TOOL_ADD_IMG,scp_bl2u,--scp-fwu-cfg,FWU_))
+ endif
+
+ ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
+ BL2U_SOURCES += drivers/arm/css/scp/css_sds.c \
+ drivers/arm/css/sds/sds.c
+
+ BL2_SOURCES += drivers/arm/css/scp/css_sds.c \
+ drivers/arm/css/sds/sds.c
+ else
+ BL2U_SOURCES += drivers/arm/css/mhu/css_mhu.c \
+ drivers/arm/css/scp/css_bom_bootloader.c \
+ drivers/arm/css/scpi/css_scpi.c
+
+ BL2_SOURCES += drivers/arm/css/mhu/css_mhu.c \
+ drivers/arm/css/scp/css_bom_bootloader.c \
+ drivers/arm/css/scpi/css_scpi.c
+ # Enable option to detect whether the SCP ROM firmware in use predates version
+ # 1.7.0 and therefore, is incompatible.
+ CSS_DETECT_PRE_1_7_0_SCP := 1
+
+ # Process CSS_DETECT_PRE_1_7_0_SCP flag
+ $(eval $(call assert_boolean,CSS_DETECT_PRE_1_7_0_SCP))
+ $(eval $(call add_define,CSS_DETECT_PRE_1_7_0_SCP))
+ endif
+endif
+
+ifeq (${CSS_USE_SCMI_SDS_DRIVER},1)
+ PLAT_BL_COMMON_SOURCES += drivers/arm/css/sds/${ARCH}/sds_helpers.S
+endif
+
+# Process CSS_USE_SCMI_SDS_DRIVER flag
+$(eval $(call assert_boolean,CSS_USE_SCMI_SDS_DRIVER))
+$(eval $(call add_define,CSS_USE_SCMI_SDS_DRIVER))
+
+# Process CSS_NON_SECURE_UART flag
+# This undocumented build option is only to enable debug access to the UART
+# from non secure code, which is useful on some platforms.
+# Default (obviously) is off.
+CSS_NON_SECURE_UART := 0
+$(eval $(call assert_boolean,CSS_NON_SECURE_UART))
+$(eval $(call add_define,CSS_NON_SECURE_UART))
+
+# Process CSS_SYSTEM_GRACEFUL_RESET flag
+# This build option can be used on CSS platforms that require all the CPUs
+# to execute the CPU specific power down sequence to complete a warm reboot
+# sequence in which only the CPUs are power cycled.
+CSS_SYSTEM_GRACEFUL_RESET := 0
+$(eval $(call add_define,CSS_SYSTEM_GRACEFUL_RESET))
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
new file mode 100644
index 0000000..9b2639c
--- /dev/null
+++ b/plat/arm/css/common/css_pm.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_scp.h>
+#include <lib/cassert.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include <plat/common/platform.h>
+
+#include <plat/arm/css/common/css_pm.h>
+
+/* Allow CSS platforms to override `plat_arm_psci_pm_ops` */
+#pragma weak plat_arm_psci_pm_ops
+
+#if ARM_RECOM_STATE_ID_ENC
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+const unsigned int arm_pm_idle_states[] = {
+ /* State-id - 0x001 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RUN,
+ ARM_LOCAL_STATE_RET, ARM_PWR_LVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x002 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RUN,
+ ARM_LOCAL_STATE_OFF, ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x022 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF,
+ ARM_LOCAL_STATE_OFF, ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
+#if PLAT_MAX_PWR_LVL > ARM_PWR_LVL1
+ /* State-id - 0x222 */
+ arm_make_pwrstate_lvl2(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
+ ARM_LOCAL_STATE_OFF, ARM_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
+#endif
+ 0,
+};
+#endif /* __ARM_RECOM_STATE_ID_ENC__ */
+
+/*
+ * All the power management helpers in this file assume at least cluster power
+ * level is supported.
+ */
+CASSERT(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL1,
+ assert_max_pwr_lvl_supported_mismatch);
+
+/*
+ * Ensure that the PLAT_MAX_PWR_LVL is not greater than CSS_SYSTEM_PWR_DMN_LVL
+ * assumed by the CSS layer.
+ */
+CASSERT(PLAT_MAX_PWR_LVL <= CSS_SYSTEM_PWR_DMN_LVL,
+ assert_max_pwr_lvl_higher_than_css_sys_lvl);
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be turned on. The
+ * level and mpidr determine the affinity instance.
+ ******************************************************************************/
+int css_pwr_domain_on(u_register_t mpidr)
+{
+ css_scp_on(mpidr);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void css_pwr_domain_on_finisher_common(
+ const psci_power_state_t *target_state)
+{
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
+
+ /*
+ * Perform the common cluster specific operations i.e enable coherency
+ * if this cluster was off.
+ */
+ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
+ plat_arm_interconnect_enter_coherency();
+}
+
+/*******************************************************************************
+ * Handler called when a power level has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from. This handler would never be invoked with
+ * the system power domain uninitialized as either the primary would have taken
+ * care of it as part of cold boot or the first core awakened from system
+ * suspend would have already initialized it.
+ ******************************************************************************/
+void css_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* Assert that the system power domain need not be initialized */
+ assert(css_system_pwr_state(target_state) == ARM_LOCAL_STATE_RUN);
+
+ css_pwr_domain_on_finisher_common(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain has just been powered on and the cpu
+ * and its cluster are fully participating in coherent transaction on the
+ * interconnect. Data cache must be enabled for CPU at this point.
+ ******************************************************************************/
+void css_pwr_domain_on_finish_late(const psci_power_state_t *target_state)
+{
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_arm_gic_pcpu_init();
+
+ /* Enable the gic cpu interface */
+ plat_arm_gic_cpuif_enable();
+
+ /* Setup the CPU power down request interrupt for secondary core(s) */
+ css_setup_cpu_pwr_down_intr();
+}
+
+/*******************************************************************************
+ * Common function called while turning a cpu off or suspending it. It is called
+ * from css_off() or css_suspend() when these functions in turn are called for
+ * power domain at the highest power level which will be powered down. It
+ * performs the actions common to the OFF and SUSPEND calls.
+ ******************************************************************************/
+static void css_power_down_common(const psci_power_state_t *target_state)
+{
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_arm_gic_cpuif_disable();
+
+ /* Turn redistributor off */
+ plat_arm_gic_redistif_off();
+
+ /* Cluster is to be turned off, so disable coherency */
+ if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
+ plat_arm_interconnect_exit_coherency();
+
+#if HW_ASSISTED_COHERENCY
+ uint32_t reg;
+
+ /*
+ * If we have determined this core to be the last man standing and we
+ * intend to power down the cluster proactively, we provide a hint to
+ * the power controller that cluster power is not required when all
+ * cores are powered down.
+ * Note that this is only an advisory to power controller and is supported
+ * by SoCs with DynamIQ Shared Units only.
+ */
+ reg = read_clusterpwrdn();
+
+ /* Clear and set bit 0 : Cluster power not required */
+ reg &= ~DSU_CLUSTER_PWR_MASK;
+ reg |= DSU_CLUSTER_PWR_OFF;
+ write_clusterpwrdn(reg);
+#endif
+ }
+}
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void css_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
+ css_power_down_common(target_state);
+ css_scp_off(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void css_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ /*
+ * CSS currently supports retention only at cpu level. Just return
+ * as nothing is to be done for retention.
+ */
+ if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
+ return;
+
+
+ assert(CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF);
+ css_power_down_common(target_state);
+
+ /* Perform system domain state saving if issuing system suspend */
+ if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) {
+ arm_system_pwr_domain_save();
+
+ /* Power off the Redistributor after having saved its context */
+ plat_arm_gic_redistif_off();
+ }
+
+ css_scp_suspend(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+void css_pwr_domain_suspend_finish(
+ const psci_power_state_t *target_state)
+{
+ /* Return as nothing is to be done on waking up from retention. */
+ if (CSS_CORE_PWR_STATE(target_state) == ARM_LOCAL_STATE_RET)
+ return;
+
+ /* Perform system domain restore if woken up from system suspend */
+ if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF)
+ /*
+ * At this point, the Distributor must be powered on to be ready
+ * to have its state restored. The Redistributor will be powered
+ * on as part of gicv3_rdistif_init_restore.
+ */
+ arm_system_pwr_domain_resume();
+
+ css_pwr_domain_on_finisher_common(target_state);
+
+ /* Enable the gic cpu interface */
+ plat_arm_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * Handlers to shutdown/reboot the system
+ ******************************************************************************/
+void __dead2 css_system_off(void)
+{
+ css_scp_sys_shutdown();
+}
+
+void __dead2 css_system_reset(void)
+{
+ css_scp_sys_reboot();
+}
+
+/*******************************************************************************
+ * Handler called when the CPU power domain is about to enter standby.
+ ******************************************************************************/
+void css_cpu_standby(plat_local_state_t cpu_state)
+{
+ unsigned int scr;
+
+ assert(cpu_state == ARM_LOCAL_STATE_RET);
+
+ scr = read_scr_el3();
+ /*
+ * Enable the Non secure interrupt to wake the CPU.
+ * In GICv3 affinity routing mode, the non secure group1 interrupts use
+ * the PhysicalFIQ at EL3 whereas in GICv2, it uses the PhysicalIRQ.
+ * Enabling both the bits works for both GICv2 mode and GICv3 affinity
+ * routing mode.
+ */
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+ isb();
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR to the original value, synchronisation of scr_el3 is
+ * done by eret while el3_exit to save some execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+/*******************************************************************************
+ * Handler called to return the 'req_state' for system suspend.
+ ******************************************************************************/
+void css_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ /*
+ * System Suspend is supported only if the system power domain node
+ * is implemented.
+ */
+ assert(PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL);
+
+ for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = ARM_LOCAL_STATE_OFF;
+}
+
+/*******************************************************************************
+ * Handler to query CPU/cluster power states from SCP
+ ******************************************************************************/
+int css_node_hw_state(u_register_t mpidr, unsigned int power_level)
+{
+ return css_scp_get_power_state(mpidr, power_level);
+}
+
+/*
+ * The system power domain suspend is only supported only via
+ * PSCI SYSTEM_SUSPEND API. PSCI CPU_SUSPEND request to system power domain
+ * will be downgraded to the lower level.
+ */
+static int css_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int rc;
+ rc = arm_validate_power_state(power_state, req_state);
+
+ /*
+ * Ensure that we don't overrun the pwr_domain_state array in the case
+ * where the platform supported max power level is less than the system
+ * power level
+ */
+
+#if (PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL)
+
+ /*
+ * Ensure that the system power domain level is never suspended
+ * via PSCI CPU SUSPEND API. Currently system suspend is only
+ * supported via PSCI SYSTEM SUSPEND API.
+ */
+
+ req_state->pwr_domain_state[CSS_SYSTEM_PWR_DMN_LVL] =
+ ARM_LOCAL_STATE_RUN;
+#endif
+
+ return rc;
+}
+
+/*
+ * Custom `translate_power_state_by_mpidr` handler for CSS. Unlike in the
+ * `css_validate_power_state`, we do not downgrade the system power
+ * domain level request in `power_state` as it will be used to query the
+ * PSCI_STAT_COUNT/RESIDENCY at the system power domain level.
+ */
+static int css_translate_power_state_by_mpidr(u_register_t mpidr,
+ unsigned int power_state,
+ psci_power_state_t *output_state)
+{
+ return arm_validate_power_state(power_state, output_state);
+}
+
+/*
+ * Setup the SGI interrupt that will be used trigger the execution of power
+ * down sequence for all the secondary cores. This interrupt is setup to be
+ * handled in EL3 context at a priority defined by the platform.
+ */
+void css_setup_cpu_pwr_down_intr(void)
+{
+#if CSS_SYSTEM_GRACEFUL_RESET
+ plat_ic_set_interrupt_type(CSS_CPU_PWR_DOWN_REQ_INTR, INTR_TYPE_EL3);
+ plat_ic_set_interrupt_priority(CSS_CPU_PWR_DOWN_REQ_INTR,
+ PLAT_REBOOT_PRI);
+ plat_ic_enable_interrupt(CSS_CPU_PWR_DOWN_REQ_INTR);
+#endif
+}
+
+/*
+ * For a graceful shutdown/reboot, each CPU in the system should do their power
+ * down sequence. On a PSCI shutdown/reboot request, only one CPU gets an
+ * opportunity to do the powerdown sequence. To achieve graceful reset, of all
+ * cores in the system, the CPU gets the opportunity raise warm reboot SGI to
+ * rest of the CPUs which are online. Add handler for the reboot SGI where the
+ * rest of the CPU execute the powerdown sequence.
+ */
+int css_reboot_interrupt_handler(uint32_t intr_raw, uint32_t flags,
+ void *handle, void *cookie)
+{
+ assert(intr_raw == CSS_CPU_PWR_DOWN_REQ_INTR);
+
+ /* Deactivate warm reboot SGI */
+ plat_ic_end_of_interrupt(CSS_CPU_PWR_DOWN_REQ_INTR);
+
+ /*
+ * Disable GIC CPU interface to prevent pending interrupt from waking
+ * up the AP from WFI.
+ */
+ plat_arm_gic_cpuif_disable();
+ plat_arm_gic_redistif_off();
+
+ psci_pwrdown_cpu(PLAT_MAX_PWR_LVL);
+
+ dmbsy();
+
+ wfi();
+ return 0;
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t plat_arm_psci_pm_ops = {
+ .pwr_domain_on = css_pwr_domain_on,
+ .pwr_domain_on_finish = css_pwr_domain_on_finish,
+ .pwr_domain_on_finish_late = css_pwr_domain_on_finish_late,
+ .pwr_domain_off = css_pwr_domain_off,
+ .cpu_standby = css_cpu_standby,
+ .pwr_domain_suspend = css_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = css_pwr_domain_suspend_finish,
+ .system_off = css_system_off,
+ .system_reset = css_system_reset,
+ .validate_power_state = css_validate_power_state,
+ .validate_ns_entrypoint = arm_validate_psci_entrypoint,
+ .translate_power_state_by_mpidr = css_translate_power_state_by_mpidr,
+ .get_node_hw_state = css_node_hw_state,
+ .get_sys_suspend_power_state = css_get_sys_suspend_power_state,
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+ .mem_protect_chk = arm_psci_mem_protect_chk,
+ .read_mem_protect = arm_psci_read_mem_protect,
+ .write_mem_protect = arm_nor_psci_write_mem_protect,
+#endif
+#if CSS_USE_SCMI_SDS_DRIVER
+ .system_reset2 = css_system_reset2,
+#endif
+};
diff --git a/plat/arm/css/common/css_topology.c b/plat/arm/css/common/css_topology.c
new file mode 100644
index 0000000..8aca744
--- /dev/null
+++ b/plat/arm/css/common/css_topology.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#if ARM_PLAT_MT
+#pragma weak plat_arm_get_cpu_pe_count
+#endif
+
+/******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is
+ * returned in case the MPIDR is invalid.
+ *****************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ if (arm_check_mpidr(mpidr) == 0) {
+#if ARM_PLAT_MT
+ assert((read_mpidr_el1() & MPIDR_MT_MASK) != 0);
+
+ /*
+ * The DTB files don't provide the MT bit in the mpidr argument
+ * so set it manually before calculating core position
+ */
+ mpidr |= MPIDR_MT_MASK;
+#endif
+ return plat_arm_calc_core_pos(mpidr);
+ }
+ return -1;
+}
+
+#if ARM_PLAT_MT
+/******************************************************************************
+ * This function returns the PE count within the physical cpu corresponding to
+ * `mpidr`. Now one cpu only have one thread, so just return 1.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+ return 1;
+}
+#endif /* ARM_PLAT_MT */
diff --git a/plat/arm/css/common/sp_min/css_sp_min.mk b/plat/arm/css/common/sp_min/css_sp_min.mk
new file mode 100644
index 0000000..ae489fd
--- /dev/null
+++ b/plat/arm/css/common/sp_min/css_sp_min.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SP MIN source files common to CSS platforms
+BL32_SOURCES += plat/arm/css/common/css_pm.c \
+ plat/arm/css/common/css_topology.c
+
+ifeq (${CSS_USE_SCMI_SDS_DRIVER},0)
+BL32_SOURCES += drivers/arm/css/mhu/css_mhu.c \
+ drivers/arm/css/scp/css_pm_scpi.c \
+ drivers/arm/css/scpi/css_scpi.c
+else
+BL32_SOURCES += drivers/arm/css/mhu/css_mhu_doorbell.c \
+ drivers/arm/css/scp/css_pm_scmi.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/arm/css/scmi/scmi_common.c \
+ drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \
+ drivers/arm/css/scmi/scmi_sys_pwr_proto.c
+endif
diff --git a/plat/arm/css/sgi/aarch64/sgi_helper.S b/plat/arm/css/sgi/aarch64/sgi_helper.S
new file mode 100644
index 0000000..ced59e8
--- /dev/null
+++ b/plat/arm/css/sgi/aarch64/sgi_helper.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <cortex_a75.h>
+#include <neoverse_n1.h>
+#include <neoverse_v1.h>
+#include <neoverse_n2.h>
+#include <cpu_macros.S>
+
+ .globl plat_arm_calc_core_pos
+ .globl plat_reset_handler
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Helper function to calculate the core position.
+ * (ChipId * PLAT_ARM_CLUSTER_COUNT *
+ * CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU) +
+ * (ClusterId * CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU) +
+ * (CPUId * CSS_SGI_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((((ChipId * PLAT_ARM_CLUSTER_COUNT) + ClusterId) *
+ * CSS_SGI_MAX_CPUS_PER_CLUSTER) + CPUId) * CSS_SGI_MAX_PE_PER_CPU +
+ * ThreadId
+ * ------------------------------------------------------
+ */
+
+func plat_arm_calc_core_pos
+ mov x4, x0
+
+ /*
+ * The MT bit in MPIDR is always set for SGI platforms
+ * and the affinity level 0 corresponds to thread affinity level.
+ */
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x4, #PLAT_ARM_CLUSTER_COUNT
+ madd x2, x3, x4, x2
+ mov x4, #CSS_SGI_MAX_CPUS_PER_CLUSTER
+ madd x1, x2, x4, x1
+ mov x4, #CSS_SGI_MAX_PE_PER_CPU
+ madd x0, x1, x4, x0
+ ret
+endfunc plat_arm_calc_core_pos
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Determine the CPU MIDR and disable power down bit for
+ * that CPU.
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ jump_if_cpu_midr CORTEX_A75_MIDR, A75
+ jump_if_cpu_midr NEOVERSE_N1_MIDR, N1
+ jump_if_cpu_midr NEOVERSE_V1_MIDR, V1
+ jump_if_cpu_midr NEOVERSE_N2_MIDR, N2
+ ret
+
+ /* -----------------------------------------------------
+ * Disable CPU power down bit in power control register
+ * -----------------------------------------------------
+ */
+A75:
+ mrs x0, CORTEX_A75_CPUPWRCTLR_EL1
+ bic x0, x0, #CORTEX_A75_CORE_PWRDN_EN_MASK
+ msr CORTEX_A75_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+
+N1:
+ mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1
+ bic x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK
+ msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+
+V1:
+ mrs x0, NEOVERSE_V1_CPUPWRCTLR_EL1
+ bic x0, x0, #NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+ msr NEOVERSE_V1_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+
+N2:
+ mrs x0, NEOVERSE_N2_CPUPWRCTLR_EL1
+ bic x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT
+ msr NEOVERSE_N2_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+endfunc plat_reset_handler
diff --git a/plat/arm/css/sgi/include/plat_macros.S b/plat/arm/css/sgi/include/plat_macros.S
new file mode 100644
index 0000000..521bcc3
--- /dev/null
+++ b/plat/arm/css/sgi/include/plat_macros.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <css_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
new file mode 100644
index 0000000..c1fadc6
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_BASE_PLATFORM_DEF_H
+#define SGI_BASE_PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/arm/css/common/css_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_CORE_COUNT (CSS_SGI_CHIP_COUNT * \
+ PLAT_ARM_CLUSTER_COUNT * \
+ CSS_SGI_MAX_CPUS_PER_CLUSTER * \
+ CSS_SGI_MAX_PE_PER_CPU)
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */
+
+/* Remote chip address offset */
+#define CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) \
+ ((ULL(1) << CSS_SGI_ADDR_BITS_PER_CHIP) * (n))
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage. In addition to that, on
+ * multi-chip platforms, address regions on each of the remote chips are
+ * also mapped. In BL31, for instance, three address regions on the remote
+ * chips are accessed - secure ram, css device and soc device regions.
+ */
+#if defined(IMAGE_BL31)
+# if SPM_MM
+# define PLAT_ARM_MMAP_ENTRIES (9 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
+# define MAX_XLAT_TABLES (7 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
+# define PLAT_SP_IMAGE_MMAP_REGIONS 10
+# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 12
+# else
+# define PLAT_ARM_MMAP_ENTRIES (5 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
+# define MAX_XLAT_TABLES (6 + ((CSS_SGI_CHIP_COUNT - 1) * 3))
+# endif
+#elif defined(IMAGE_BL32)
+# define PLAT_ARM_MMAP_ENTRIES 8
+# define MAX_XLAT_TABLES 5
+#elif defined(IMAGE_BL2)
+# define PLAT_ARM_MMAP_ENTRIES (11 + (CSS_SGI_CHIP_COUNT - 1))
+
+/*
+ * MAX_XLAT_TABLES entries need to be doubled because when the address width
+ * exceeds 40 bits an additional level of translation is required. In case of
+ * multichip platforms peripherals also fall into address space with width
+ * > 40 bits
+ *
+ */
+# define MAX_XLAT_TABLES (7 + ((CSS_SGI_CHIP_COUNT - 1) * 2))
+#elif !USE_ROMLIB
+# define PLAT_ARM_MMAP_ENTRIES 11
+# define MAX_XLAT_TABLES 7
+#else
+# define PLAT_ARM_MMAP_ENTRIES 12
+# define MAX_XLAT_TABLES 6
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE (64 * 1024) /* 64 KB */
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth. Additional 8KiB space is added per chip in
+ * order to accommodate the additional level of translation required for "TZC"
+ * peripheral access which lies in >4TB address space.
+ *
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE (0x20000 + ((CSS_SGI_CHIP_COUNT - 1) * \
+ 0x2000))
+#else
+# define PLAT_ARM_MAX_BL2_SIZE (0x14000 + ((CSS_SGI_CHIP_COUNT - 1) * \
+ 0x2000))
+#endif
+
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of BL2
+ * and BL1-RW. CSS_SGI_BL31_SIZE - is tuned with respect to the actual BL31
+ * PROGBITS size which is around 64-68KB at the time this change is being made.
+ * A buffer of ~35KB is added to account for future expansion of the image,
+ * making it a total of 100KB.
+ */
+#define CSS_SGI_BL31_SIZE (100 * 1024) /* 100 KB */
+#define PLAT_ARM_MAX_BL31_SIZE (CSS_SGI_BL31_SIZE + \
+ PLAT_ARM_MAX_BL2_SIZE + \
+ PLAT_ARM_MAX_BL1_RW_SIZE)
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x440
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+# if SPM_MM
+# define PLATFORM_STACK_SIZE 0x500
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+
+/* PL011 UART related constants */
+#define SOC_CSS_SEC_UART_BASE UL(0x2A410000)
+#define SOC_CSS_NSEC_UART_BASE UL(0x2A400000)
+#define SOC_CSS_UART_SIZE UL(0x10000)
+#define SOC_CSS_UART_CLK_IN_HZ UL(7372800)
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE SOC_CSS_SEC_UART_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ SOC_CSS_UART_CLK_IN_HZ
+
+#define PLAT_ARM_RUN_UART_BASE SOC_CSS_SEC_UART_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ SOC_CSS_UART_CLK_IN_HZ
+
+#define PLAT_ARM_CRASH_UART_BASE SOC_CSS_SEC_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ SOC_CSS_UART_CLK_IN_HZ
+
+#define PLAT_ARM_NSTIMER_FRAME_ID 0
+
+#define PLAT_ARM_TRUSTED_ROM_BASE 0x0
+#define PLAT_ARM_TRUSTED_ROM_SIZE 0x00080000 /* 512KB */
+
+#define PLAT_ARM_NSRAM_BASE 0x06000000
+#define PLAT_ARM_NSRAM_SIZE 0x00080000 /* 512KB */
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+#define CSS_SGI_DEVICE_BASE (0x20000000)
+#define CSS_SGI_DEVICE_SIZE (0x20000000)
+#define CSS_SGI_MAP_DEVICE MAP_REGION_FLAT( \
+ CSS_SGI_DEVICE_BASE, \
+ CSS_SGI_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_MAP_SHARED_RAM_REMOTE_CHIP(n) \
+ MAP_REGION_FLAT( \
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + \
+ ARM_SHARED_RAM_BASE, \
+ ARM_SHARED_RAM_SIZE, \
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE \
+ )
+
+#define CSS_SGI_MAP_DEVICE_REMOTE_CHIP(n) \
+ MAP_REGION_FLAT( \
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + \
+ CSS_SGI_DEVICE_BASE, \
+ CSS_SGI_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE \
+ )
+
+#define SOC_CSS_MAP_DEVICE_REMOTE_CHIP(n) \
+ MAP_REGION_FLAT( \
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + \
+ SOC_CSS_DEVICE_BASE, \
+ SOC_CSS_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE \
+ )
+
+/* Map the secure region for access from S-EL0 */
+#define PLAT_ARM_SECURE_MAP_DEVICE MAP_REGION_FLAT( \
+ SOC_CSS_DEVICE_BASE, \
+ SOC_CSS_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+
+#define PLAT_SP_PRI PLAT_RAS_PRI
+
+#if SPM_MM && RAS_EXTENSION
+/*
+ * CPER buffer memory of 128KB is reserved and it is placed adjacent to the
+ * memory shared between EL3 and S-EL0.
+ */
+#define CSS_SGI_SP_CPER_BUF_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
+ PLAT_SP_IMAGE_NS_BUF_SIZE)
+#define CSS_SGI_SP_CPER_BUF_SIZE ULL(0x20000)
+#define CSS_SGI_SP_CPER_BUF_MMAP MAP_REGION2( \
+ CSS_SGI_SP_CPER_BUF_BASE, \
+ CSS_SGI_SP_CPER_BUF_BASE, \
+ CSS_SGI_SP_CPER_BUF_SIZE, \
+ MT_RW_DATA | MT_NS | MT_USER, \
+ PAGE_SIZE)
+
+/*
+ * Secure partition stack follows right after the memory space reserved for
+ * CPER buffer memory.
+ */
+#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
+ PLAT_SP_IMAGE_NS_BUF_SIZE + \
+ CSS_SGI_SP_CPER_BUF_SIZE)
+#elif SPM_MM
+/*
+ * Secure partition stack follows right after the memory region that is shared
+ * between EL3 and S-EL0.
+ */
+#define PLAT_ARM_SP_IMAGE_STACK_BASE (PLAT_SP_IMAGE_NS_BUF_BASE + \
+ PLAT_SP_IMAGE_NS_BUF_SIZE)
+#endif /* SPM_MM && RAS_EXTENSION */
+
+/* Platform ID address */
+#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
+#ifndef __ASSEMBLER__
+/* SSC_VERSION related accessors */
+/* Returns the part number of the platform */
+#define GET_SGI_PART_NUM \
+ GET_SSC_VERSION_PART_NUM(mmio_read_32(SSC_VERSION))
+/* Returns the configuration number of the platform */
+#define GET_SGI_CONFIG_NUM \
+ GET_SSC_VERSION_CONFIG(mmio_read_32(SSC_VERSION))
+#endif /* __ASSEMBLER__ */
+
+/*******************************************************************************
+ * Memprotect definitions
+ ******************************************************************************/
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR (V2M_FLASH0_BASE + \
+ V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT UL(100)
+
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT CSS_SGI_CHIP_COUNT
+
+/*
+ * Mapping definition of the TrustZone Controller for ARM SGI/RD platforms
+ * where both the DRAM regions are marked for non-secure access. This applies
+ * to multi-chip platforms.
+ */
+#define SGI_PLAT_TZC_NS_REMOTE_REGIONS_DEF(n) \
+ {CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM1_BASE, \
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM1_END, \
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}, \
+ {CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM2_BASE, \
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + ARM_DRAM2_END, \
+ ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}
+
+#if SPM_MM
+
+/*
+ * Stand-alone MM logs would be routed via secure UART. Define page table
+ * entry for secure UART which would be common to all platforms.
+ */
+#define SOC_PLATFORM_SECURE_UART MAP_REGION_FLAT( \
+ SOC_CSS_SEC_UART_BASE, \
+ SOC_CSS_UART_SIZE, \
+ MT_DEVICE | MT_RW | \
+ MT_SECURE | MT_USER)
+
+#endif
+
+/* SDS ID for unusable CPU MPID list structure */
+#define SDS_ISOLATED_CPU_LIST_ID U(128)
+
+#endif /* SGI_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h b/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h
new file mode 100644
index 0000000..e939163
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_DMC620_TZC_REGIONS_H
+#define SGI_DMC620_TZC_REGIONS_H
+
+#include <drivers/arm/tzc_dmc620.h>
+
+#if SPM_MM
+#define CSS_SGI_DMC620_TZC_REGIONS_DEF \
+ { \
+ .region_base = ARM_AP_TZC_DRAM1_BASE, \
+ .region_top = PLAT_SP_IMAGE_NS_BUF_BASE - 1, \
+ .sec_attr = TZC_DMC620_REGION_S_RDWR \
+ }, { \
+ .region_base = PLAT_SP_IMAGE_NS_BUF_BASE, \
+ .region_top = PLAT_ARM_SP_IMAGE_STACK_BASE - 1, \
+ .sec_attr = TZC_DMC620_REGION_S_NS_RDWR \
+ }, { \
+ .region_base = PLAT_ARM_SP_IMAGE_STACK_BASE, \
+ .region_top = ARM_AP_TZC_DRAM1_END, \
+ .sec_attr = TZC_DMC620_REGION_S_RDWR \
+ }
+#else
+#define CSS_SGI_DMC620_TZC_REGIONS_DEF \
+ { \
+ .region_base = ARM_AP_TZC_DRAM1_BASE, \
+ .region_top = ARM_AP_TZC_DRAM1_END, \
+ .sec_attr = TZC_DMC620_REGION_S_RDWR \
+ }
+#endif /* SPM_MM */
+
+#endif /* SGI_DMC620_TZC_REGIONS_H */
diff --git a/plat/arm/css/sgi/include/sgi_plat.h b/plat/arm/css/sgi/include/sgi_plat.h
new file mode 100644
index 0000000..a5fbded
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_plat.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_PLAT_H
+#define SGI_PLAT_H
+
+/* BL31 platform setup common to all SGI based platforms */
+void sgi_bl31_common_platform_setup(void);
+
+#endif /* SGI_PLAT_H */
diff --git a/plat/arm/css/sgi/include/sgi_ras.h b/plat/arm/css/sgi/include/sgi_ras.h
new file mode 100644
index 0000000..e69a684
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_ras.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_RAS_H
+#define SGI_RAS_H
+
+/*
+ * Mapping the RAS interrupt with SDEI event number and the event
+ * id used with Standalone MM code
+ */
+struct sgi_ras_ev_map {
+ int sdei_ev_num; /* SDEI Event number */
+ int intr; /* Physical intr number */
+};
+
+int sgi_ras_intr_handler_setup(void);
+
+#endif /* SGI_RAS_H */
diff --git a/plat/arm/css/sgi/include/sgi_sdei.h b/plat/arm/css/sgi/include/sgi_sdei.h
new file mode 100644
index 0000000..f380122
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_sdei.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SDEI_H
+#define SGI_SDEI_H
+
+#if SDEI_SUPPORT
+
+/* ARM SDEI dynamic shared event numbers */
+#define SGI_SDEI_DS_EVENT_0 U(804)
+#define SGI_SDEI_DS_EVENT_1 U(805)
+
+#define PLAT_ARM_PRIVATE_SDEI_EVENTS \
+ SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \
+ SDEI_EXPLICIT_EVENT(SGI_SDEI_DS_EVENT_0, SDEI_MAPF_CRITICAL), \
+ SDEI_EXPLICIT_EVENT(SGI_SDEI_DS_EVENT_1, SDEI_MAPF_CRITICAL),
+
+#define PLAT_ARM_SHARED_SDEI_EVENTS
+
+#endif /* SDEI_SUPPORT */
+
+#endif /* SGI_SDEI_H */
diff --git a/plat/arm/css/sgi/include/sgi_soc_css_def.h b/plat/arm/css/sgi/include/sgi_soc_css_def.h
new file mode 100644
index 0000000..f78b45a
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_soc_css_def.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SOC_CSS_DEF_H
+#define SGI_SOC_CSS_DEF_H
+
+#include <lib/utils_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+#include <plat/common/common_def.h>
+
+/*
+ * Definitions common to all ARM CSSv1-based development platforms
+ */
+
+/* Platform ID address */
+#define BOARD_CSS_PLAT_ID_REG_ADDR UL(0x7ffe00e0)
+
+/* Platform ID related accessors */
+#define BOARD_CSS_PLAT_ID_REG_ID_MASK 0x0f
+#define BOARD_CSS_PLAT_ID_REG_ID_SHIFT 0x0
+#define BOARD_CSS_PLAT_TYPE_EMULATOR 0x02
+
+#ifndef __ASSEMBLER__
+
+#include <lib/mmio.h>
+
+#define BOARD_CSS_GET_PLAT_TYPE(addr) \
+ ((mmio_read_32(addr) & BOARD_CSS_PLAT_ID_REG_ID_MASK) \
+ >> BOARD_CSS_PLAT_ID_REG_ID_SHIFT)
+
+#endif /* __ASSEMBLER__ */
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
+#define PLAT_ARM_FLASH_IMAGE_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#endif /* SGI_SOC_CSS_DEF_H */
diff --git a/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h b/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h
new file mode 100644
index 0000000..acf31eb
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SOC_CSS_DEF_V2_H
+#define SGI_SOC_CSS_DEF_V2_H
+
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+/*
+ * Definitions common to all ARM CSS SoCs
+ */
+
+/* Following covers ARM CSS SoC Peripherals */
+
+#define SOC_SYSTEM_PERIPH_BASE UL(0x0C000000)
+#define SOC_SYSTEM_PERIPH_SIZE UL(0x02000000)
+
+#define SOC_PLATFORM_PERIPH_BASE UL(0x0E000000)
+#define SOC_PLATFORM_PERIPH_SIZE UL(0x02000000)
+
+#define SOC_CSS_PCIE_CONTROL_BASE UL(0x0ef20000)
+
+/* Memory controller */
+#define SOC_MEMCNTRL_BASE UL(0x10000000)
+#define SOC_MEMCNTRL_SIZE UL(0x10000000)
+
+/* SoC NIC-400 Global Programmers View (GPV) */
+#define SOC_CSS_NIC400_BASE UL(0x0ED00000)
+
+#define SOC_CSS_NIC400_USB_EHCI U(0)
+#define SOC_CSS_NIC400_TLX_MASTER U(1)
+#define SOC_CSS_NIC400_USB_OHCI U(2)
+#define SOC_CSS_NIC400_PL354_SMC U(3)
+/*
+ * The apb4_bridge controls access to:
+ * - the PCIe configuration registers
+ * - the MMU units for USB, HDLCD and DMA
+ */
+#define SOC_CSS_NIC400_APB4_BRIDGE U(4)
+
+/* Non-volatile counters */
+#define SOC_TRUSTED_NVCTR_BASE UL(0x0EE70000)
+#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0000)
+#define TFW_NVCTR_SIZE U(4)
+#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE U(4)
+
+/* Keys */
+#define SOC_KEYS_BASE UL(0x0EE80000)
+#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000)
+#define TZ_PUB_KEY_HASH_SIZE U(32)
+#define HU_KEY_BASE (SOC_KEYS_BASE + 0x0020)
+#define HU_KEY_SIZE U(16)
+#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044)
+#define END_KEY_SIZE U(32)
+
+#define SOC_PLATFORM_PERIPH_MAP_DEVICE MAP_REGION_FLAT( \
+ SOC_PLATFORM_PERIPH_BASE, \
+ SOC_PLATFORM_PERIPH_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#if SPM_MM
+/*
+ * Memory map definition for the platform peripheral memory region that is
+ * accessible from S-EL0 (with secure user mode access).
+ */
+#define SOC_PLATFORM_PERIPH_MAP_DEVICE_USER \
+ MAP_REGION_FLAT( \
+ SOC_PLATFORM_PERIPH_BASE, \
+ SOC_PLATFORM_PERIPH_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+#endif
+
+#define SOC_SYSTEM_PERIPH_MAP_DEVICE MAP_REGION_FLAT( \
+ SOC_SYSTEM_PERIPH_BASE, \
+ SOC_SYSTEM_PERIPH_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define SOC_MEMCNTRL_MAP_DEVICE MAP_REGION_FLAT( \
+ SOC_MEMCNTRL_BASE, \
+ SOC_MEMCNTRL_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(n) \
+ MAP_REGION_FLAT( \
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) + SOC_MEMCNTRL_BASE, \
+ SOC_MEMCNTRL_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * The bootsec_bridge controls access to a bunch of peripherals, e.g. the UARTs.
+ */
+#define SOC_CSS_NIC400_BOOTSEC_BRIDGE U(5)
+#define SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1 UL(1 << 12)
+
+/*
+ * Required platform porting definitions common to all ARM CSS SoCs
+ */
+/* 2MB used for SCP DDR retraining */
+#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x00200000)
+
+/* V2M motherboard system registers & offsets */
+#define V2M_SYSREGS_BASE UL(0x0C010000)
+#define V2M_SYS_LED U(0x8)
+
+/*
+ * V2M sysled bit definitions. The values written to this
+ * register are defined in arch.h & runtime_svc.h. Only
+ * used by the primary cpu to diagnose any cold boot issues.
+ *
+ * SYS_LED[0] - Security state (S=0/NS=1)
+ * SYS_LED[2:1] - Exception Level (EL3-EL0)
+ * SYS_LED[7:3] - Exception Class (Sync/Async & origin)
+ *
+ */
+#define V2M_SYS_LED_SS_SHIFT U(0)
+#define V2M_SYS_LED_EL_SHIFT U(1)
+#define V2M_SYS_LED_EC_SHIFT U(3)
+
+#define V2M_SYS_LED_SS_MASK U(0x01)
+#define V2M_SYS_LED_EL_MASK U(0x03)
+#define V2M_SYS_LED_EC_MASK U(0x1f)
+
+/* NOR Flash */
+#define V2M_FLASH0_BASE UL(0x08000000)
+#define V2M_FLASH0_SIZE UL(0x04000000)
+#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */
+
+/*
+ * The flash can be mapped either as read-only or read-write.
+ *
+ * If it is read-write then it should also be mapped as device memory because
+ * NOR flash programming involves sending a fixed, ordered sequence of commands.
+ *
+ * If it is read-only then it should also be mapped as:
+ * - Normal memory, because reading from NOR flash is transparent, it is like
+ * reading from RAM.
+ * - Non-executable by default. If some parts of the flash need to be executable
+ * then platform code is responsible for re-mapping the appropriate portion
+ * of it as executable.
+ */
+#define V2M_MAP_FLASH0_RW MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+ V2M_FLASH0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define V2M_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+ V2M_FLASH0_SIZE, \
+ MT_RO_DATA | MT_SECURE)
+
+#define SGI_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+ V2M_FLASH0_SIZE, \
+ MT_DEVICE | MT_RO | MT_SECURE)
+
+/* Platform ID address */
+#define BOARD_CSS_PLAT_ID_REG_ADDR UL(0x0EFE00E0)
+
+/* Platform ID related accessors */
+#define BOARD_CSS_PLAT_ID_REG_ID_MASK U(0x0F)
+#define BOARD_CSS_PLAT_ID_REG_ID_SHIFT U(0x00)
+#define BOARD_CSS_PLAT_ID_REG_VERSION_MASK U(0xF00)
+#define BOARD_CSS_PLAT_ID_REG_VERSION_SHIFT U(0x08)
+#define BOARD_CSS_PLAT_TYPE_RTL U(0x00)
+#define BOARD_CSS_PLAT_TYPE_FPGA U(0x01)
+#define BOARD_CSS_PLAT_TYPE_EMULATOR U(0x02)
+#define BOARD_CSS_PLAT_TYPE_FVP U(0x03)
+
+#ifndef __ASSEMBLER__
+
+#include <lib/mmio.h>
+
+#define BOARD_CSS_GET_PLAT_TYPE(addr) \
+ ((mmio_read_32(addr) & BOARD_CSS_PLAT_ID_REG_ID_MASK) \
+ >> BOARD_CSS_PLAT_ID_REG_ID_SHIFT)
+
+#endif /* __ASSEMBLER__ */
+
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
+#define PLAT_ARM_FLASH_IMAGE_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#if ARM_GPT_SUPPORT
+/*
+ * Offset of the FIP in the GPT image. BL1 component uses this option
+ * as it does not load the partition table to get the FIP base
+ * address. At sector 34 by default (i.e. after reserved sectors 0-33)
+ * Offset = 34 * 512(sector size) = 17408 i.e. 0x4400
+ */
+#define PLAT_ARM_FIP_OFFSET_IN_GPT 0x4400
+#endif /* ARM_GPT_SUPPORT */
+
+#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+#endif /* SGI_SOC_CSS_DEF_V2_H */
diff --git a/plat/arm/css/sgi/include/sgi_soc_platform_def.h b/plat/arm/css/sgi/include/sgi_soc_platform_def.h
new file mode 100644
index 0000000..3b8d9c6
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_soc_platform_def.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SOC_PLATFORM_DEF_H
+#define SGI_SOC_PLATFORM_DEF_H
+
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+#include <sgi_base_platform_def.h>
+#include <sgi_soc_css_def.h>
+
+/* Map the System registers to access from S-EL0 */
+#define CSS_SYSTEMREG_DEVICE_BASE (0x1C010000)
+#define CSS_SYSTEMREG_DEVICE_SIZE (0x00010000)
+#define PLAT_ARM_SECURE_MAP_SYSTEMREG MAP_REGION_FLAT( \
+ CSS_SYSTEMREG_DEVICE_BASE, \
+ CSS_SYSTEMREG_DEVICE_SIZE, \
+ (MT_DEVICE | MT_RW | \
+ MT_SECURE | MT_USER))
+
+/* Map the NOR2 Flash to access from S-EL0 */
+#define CSS_NOR2_FLASH_DEVICE_BASE (0x10000000)
+#define CSS_NOR2_FLASH_DEVICE_SIZE (0x04000000)
+#define PLAT_ARM_SECURE_MAP_NOR2 MAP_REGION_FLAT( \
+ CSS_NOR2_FLASH_DEVICE_BASE, \
+ CSS_NOR2_FLASH_DEVICE_SIZE, \
+ (MT_DEVICE | MT_RW | \
+ MT_SECURE | MT_USER))
+
+#endif /* SGI_SOC_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h b/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h
new file mode 100644
index 0000000..20dd682
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_SOC_PLATFORM_DEF_V2_H
+#define SGI_SOC_PLATFORM_DEF_V2_H
+
+#include <sgi_base_platform_def.h>
+#include <sgi_soc_css_def_v2.h>
+
+/* Map the System registers to access from S-EL0 */
+#define CSS_SYSTEMREG_DEVICE_BASE (0x0C010000)
+#define CSS_SYSTEMREG_DEVICE_SIZE (0x00010000)
+#define PLAT_ARM_SECURE_MAP_SYSTEMREG MAP_REGION_FLAT( \
+ CSS_SYSTEMREG_DEVICE_BASE, \
+ CSS_SYSTEMREG_DEVICE_SIZE, \
+ (MT_DEVICE | MT_RW | \
+ MT_SECURE | MT_USER))
+
+/* Map the NOR2 Flash to access from S-EL0 */
+#define CSS_NOR2_FLASH_DEVICE_BASE (0x001054000000)
+#define CSS_NOR2_FLASH_DEVICE_SIZE (0x000004000000)
+#define PLAT_ARM_SECURE_MAP_NOR2 MAP_REGION_FLAT( \
+ CSS_NOR2_FLASH_DEVICE_BASE, \
+ CSS_NOR2_FLASH_DEVICE_SIZE, \
+ (MT_DEVICE | MT_RW | \
+ MT_SECURE | MT_USER))
+
+#endif /* SGI_SOC_PLATFORM_DEF_V2_H */
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
new file mode 100644
index 0000000..223ac3e
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_VARIANT_H
+#define SGI_VARIANT_H
+
+/* SSC_VERSION values for SGI575 */
+#define SGI575_SSC_VER_PART_NUM 0x0783
+
+/* SID Version values for RD-N1E1-Edge */
+#define RD_N1E1_EDGE_SID_VER_PART_NUM 0x0786
+#define RD_E1_EDGE_CONFIG_ID 0x2
+
+/* SID Version values for RD-V1 */
+#define RD_V1_SID_VER_PART_NUM 0x078a
+
+/* SID Version values for RD-N2 */
+#define RD_N2_SID_VER_PART_NUM 0x07B7
+
+/* SID Version values for RD-N2 variants */
+#define RD_N2_CFG1_SID_VER_PART_NUM 0x07B6
+
+/* SID Version values for RD-V2 */
+#define RD_V2_SID_VER_PART_NUM 0x07F2
+#define RD_V2_CONFIG_ID 0x1
+
+/* Structure containing SGI platform variant information */
+typedef struct sgi_platform_info {
+ unsigned int platform_id; /* Part Number of the platform */
+ unsigned int config_id; /* Config Id of the platform */
+ unsigned int chip_id; /* Chip Id or Node number */
+ unsigned int multi_chip_mode; /* Multi-chip mode availability */
+} sgi_platform_info_t;
+
+extern sgi_platform_info_t sgi_plat_info;
+
+/* returns the part number of the platform*/
+unsigned int plat_arm_sgi_get_platform_id(void);
+
+/* returns the configuration id of the platform */
+unsigned int plat_arm_sgi_get_config_id(void);
+
+/* returns true if operating in multi-chip configuration */
+unsigned int plat_arm_sgi_get_multi_chip_mode(void);
+
+#endif /* SGI_VARIANT_H */
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
new file mode 100644
index 0000000..282a5f0
--- /dev/null
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -0,0 +1,86 @@
+#
+# Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+CSS_USE_SCMI_SDS_DRIVER := 1
+
+CSS_ENT_BASE := plat/arm/css/sgi
+
+RAS_EXTENSION := 0
+
+SDEI_SUPPORT := 0
+
+EL3_EXCEPTION_HANDLING := 0
+
+HANDLE_EA_EL3_FIRST_NS := 0
+
+CSS_SGI_CHIP_COUNT := 1
+
+CSS_SGI_PLATFORM_VARIANT := 0
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+CTX_INCLUDE_FPREGS := 1
+
+INTERCONNECT_SOURCES := ${CSS_ENT_BASE}/sgi_interconnect.c
+
+PLAT_INCLUDES += -I${CSS_ENT_BASE}/include
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+ENT_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/arm/common/arm_gicv3.c
+
+PLAT_BL_COMMON_SOURCES += ${CSS_ENT_BASE}/aarch64/sgi_helper.S
+
+BL1_SOURCES += ${INTERCONNECT_SOURCES} \
+ drivers/arm/sbsa/sbsa.c
+
+BL2_SOURCES += ${CSS_ENT_BASE}/sgi_image_load.c \
+ drivers/arm/css/sds/sds.c
+
+BL31_SOURCES += ${INTERCONNECT_SOURCES} \
+ ${ENT_GIC_SOURCES} \
+ ${CSS_ENT_BASE}/sgi_bl31_setup.c \
+ ${CSS_ENT_BASE}/sgi_topology.c
+
+ifeq (${RAS_EXTENSION},1)
+BL31_SOURCES += ${CSS_ENT_BASE}/sgi_ras.c
+endif
+
+ifneq (${RESET_TO_BL31},0)
+ $(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \
+ Please set RESET_TO_BL31 to 0.")
+endif
+
+$(eval $(call add_define,SGI_PLAT))
+
+$(eval $(call add_define,CSS_SGI_CHIP_COUNT))
+
+$(eval $(call add_define,CSS_SGI_PLATFORM_VARIANT))
+
+override CSS_LOAD_SCP_IMAGES := 0
+override NEED_BL2U := no
+override ARM_PLAT_MT := 1
+override PSCI_EXTENDED_STATE_ID := 1
+override ARM_RECOM_STATE_ID_ENC := 1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY := 1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM := 0
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/soc/common/soc_css.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
new file mode 100644
index 0000000..27cf183
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include <plat/common/platform.h>
+
+#include <plat/arm/css/common/css_pm.h>
+
+#include <sgi_ras.h>
+#include <sgi_variant.h>
+
+sgi_platform_info_t sgi_plat_info;
+
+static scmi_channel_plat_info_t sgi575_scmi_plat_info = {
+ .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhu_ring_doorbell,
+};
+
+static scmi_channel_plat_info_t plat_rd_scmi_info[] = {
+ {
+ .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhuv2_ring_doorbell,
+ },
+ #if (CSS_SGI_CHIP_COUNT > 1)
+ {
+ .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE +
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1),
+ .db_reg_addr = PLAT_CSS_MHU_BASE
+ + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1) + SENDER_REG_SET(0),
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhuv2_ring_doorbell,
+ },
+ #endif
+ #if (CSS_SGI_CHIP_COUNT > 2)
+ {
+ .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE +
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2),
+ .db_reg_addr = PLAT_CSS_MHU_BASE +
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2) + SENDER_REG_SET(0),
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhuv2_ring_doorbell,
+ },
+ #endif
+ #if (CSS_SGI_CHIP_COUNT > 3)
+ {
+ .scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE +
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3),
+ .db_reg_addr = PLAT_CSS_MHU_BASE +
+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3) + SENDER_REG_SET(0),
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhuv2_ring_doorbell,
+ },
+ #endif
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+ if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM ||
+ sgi_plat_info.platform_id == RD_V1_SID_VER_PART_NUM ||
+ sgi_plat_info.platform_id == RD_N2_SID_VER_PART_NUM ||
+ sgi_plat_info.platform_id == RD_V2_SID_VER_PART_NUM ||
+ sgi_plat_info.platform_id == RD_N2_CFG1_SID_VER_PART_NUM) {
+ if (channel_id >= ARRAY_SIZE(plat_rd_scmi_info))
+ panic();
+ return &plat_rd_scmi_info[channel_id];
+ }
+ else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM)
+ return &sgi575_scmi_plat_info;
+ else
+ panic();
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ sgi_plat_info.platform_id = plat_arm_sgi_get_platform_id();
+ sgi_plat_info.config_id = plat_arm_sgi_get_config_id();
+ sgi_plat_info.multi_chip_mode = plat_arm_sgi_get_multi_chip_mode();
+
+ arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+}
+
+void sgi_bl31_common_platform_setup(void)
+{
+ arm_bl31_platform_setup();
+
+#if RAS_EXTENSION
+ sgi_ras_intr_handler_setup();
+#endif
+
+ /* Configure the warm reboot SGI for primary core */
+ css_setup_cpu_pwr_down_intr();
+
+#if CSS_SYSTEM_GRACEFUL_RESET
+ /* Register priority level handlers for reboot */
+ ehf_register_priority_handler(PLAT_REBOOT_PRI,
+ css_reboot_interrupt_handler);
+#endif
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ /*
+ * For RD-E1-Edge, only CPU power ON/OFF, PSCI platform callbacks are
+ * supported.
+ */
+ if (((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) &&
+ (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID))) {
+ ops->cpu_standby = NULL;
+ ops->system_off = NULL;
+ ops->system_reset = NULL;
+ ops->get_sys_suspend_power_state = NULL;
+ ops->pwr_domain_suspend = NULL;
+ ops->pwr_domain_suspend_finish = NULL;
+ }
+
+ return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c
new file mode 100644
index 0000000..ac4bfd2
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_image_load.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <libfdt.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/css/sds.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+#include <sgi_base_platform_def.h>
+#include <sgi_variant.h>
+
+/*
+ * Information about the isolated CPUs obtained from SDS.
+ */
+struct isolated_cpu_mpid_list {
+ uint64_t num_entries; /* Number of entries in the list */
+ uint64_t mpid_list[PLATFORM_CORE_COUNT]; /* List of isolated CPU MPIDs */
+};
+
+/* Function to read isolated CPU MPID list from SDS. */
+void plat_arm_sgi_get_isolated_cpu_list(struct isolated_cpu_mpid_list *list)
+{
+ int ret;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed, error: %d\n", ret);
+ panic();
+ }
+
+ ret = sds_struct_read(SDS_ISOLATED_CPU_LIST_ID, 0, &list->num_entries,
+ sizeof(list->num_entries), SDS_ACCESS_MODE_CACHED);
+ if (ret != SDS_OK) {
+ INFO("SDS CPU num elements read failed, error: %d\n", ret);
+ list->num_entries = 0;
+ return;
+ }
+
+ if (list->num_entries > PLATFORM_CORE_COUNT) {
+ ERROR("Isolated CPU list count %ld greater than max"
+ " number supported %d\n",
+ list->num_entries, PLATFORM_CORE_COUNT);
+ panic();
+ } else if (list->num_entries == 0) {
+ INFO("SDS isolated CPU list is empty\n");
+ return;
+ }
+
+ ret = sds_struct_read(SDS_ISOLATED_CPU_LIST_ID,
+ sizeof(list->num_entries),
+ &list->mpid_list,
+ sizeof(list->mpid_list[0]) * list->num_entries,
+ SDS_ACCESS_MODE_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("SDS CPU list read failed. error: %d\n", ret);
+ panic();
+ }
+}
+
+/*******************************************************************************
+ * This function inserts Platform information via device tree nodes as,
+ * system-id {
+ * platform-id = <0>;
+ * config-id = <0>;
+ * isolated-cpu-list = <0>
+ * }
+ ******************************************************************************/
+static int plat_sgi_append_config_node(void)
+{
+ bl_mem_params_node_t *mem_params;
+ void *fdt;
+ int nodeoffset, err;
+ unsigned int platid = 0, platcfg = 0;
+ struct isolated_cpu_mpid_list cpu_mpid_list = {0};
+
+ mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+ if (mem_params == NULL) {
+ ERROR("NT_FW CONFIG base address is NULL");
+ return -1;
+ }
+
+ fdt = (void *)(mem_params->image_info.image_base);
+
+ /* Check the validity of the fdt */
+ if (fdt_check_header(fdt) != 0) {
+ ERROR("Invalid NT_FW_CONFIG DTB passed\n");
+ return -1;
+ }
+
+ nodeoffset = fdt_subnode_offset(fdt, 0, "system-id");
+ if (nodeoffset < 0) {
+ ERROR("Failed to get system-id node offset\n");
+ return -1;
+ }
+
+ platid = plat_arm_sgi_get_platform_id();
+ err = fdt_setprop_u32(fdt, nodeoffset, "platform-id", platid);
+ if (err < 0) {
+ ERROR("Failed to set platform-id\n");
+ return -1;
+ }
+
+ platcfg = plat_arm_sgi_get_config_id();
+ err = fdt_setprop_u32(fdt, nodeoffset, "config-id", platcfg);
+ if (err < 0) {
+ ERROR("Failed to set config-id\n");
+ return -1;
+ }
+
+ platcfg = plat_arm_sgi_get_multi_chip_mode();
+ err = fdt_setprop_u32(fdt, nodeoffset, "multi-chip-mode", platcfg);
+ if (err < 0) {
+ ERROR("Failed to set multi-chip-mode\n");
+ return -1;
+ }
+
+ plat_arm_sgi_get_isolated_cpu_list(&cpu_mpid_list);
+ if (cpu_mpid_list.num_entries > 0) {
+ err = fdt_setprop(fdt, nodeoffset, "isolated-cpu-list",
+ &cpu_mpid_list,
+ (sizeof(cpu_mpid_list.num_entries) *
+ (cpu_mpid_list.num_entries + 1)));
+ if (err < 0) {
+ ERROR("Failed to set isolated-cpu-list, error: %d\n",
+ err);
+ }
+ }
+
+ flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ int ret;
+
+ ret = plat_sgi_append_config_node();
+ if (ret != 0)
+ panic();
+
+ return arm_get_next_bl_params();
+}
+
diff --git a/plat/arm/css/sgi/sgi_interconnect.c b/plat/arm/css/sgi/sgi_interconnect.c
new file mode 100644
index 0000000..e9cd812
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_interconnect.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * For SGI575 which support FCM (with automatic interconnect enter/exit),
+ * we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void __init plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
new file mode 100644
index 0000000..a0199c3
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_plat.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/ccn.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
+#include <sgi_base_platform_def.h>
+
+#if SPM_MM
+#include <services/spm_mm_partition.h>
+#endif
+
+#define SGI_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+ V2M_FLASH0_SIZE, \
+ MT_DEVICE | MT_RO | MT_SECURE)
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * arm_configure_mmu_elx() will give the available subset of that.
+ *
+ * Replace or extend the below regions as required
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ SGI_MAP_FLASH0_RO,
+ CSS_SGI_MAP_DEVICE,
+ SOC_CSS_MAP_DEVICE,
+ {0}
+};
+#endif
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ SGI_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+ CSS_SGI_MAP_DEVICE,
+ SOC_CSS_MAP_DEVICE,
+ ARM_MAP_NS_DRAM1,
+#if CSS_SGI_CHIP_COUNT > 1
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1),
+#endif
+#if CSS_SGI_CHIP_COUNT > 2
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2),
+#endif
+#if CSS_SGI_CHIP_COUNT > 3
+ CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3),
+#endif
+#if ARM_BL31_IN_DRAM
+ ARM_MAP_BL31_SEC_DRAM,
+#endif
+#if SPM_MM
+ ARM_SP_IMAGE_MMAP,
+#endif
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif
+ {0}
+};
+#endif
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ V2M_MAP_IOFPGA,
+ CSS_SGI_MAP_DEVICE,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+ SOC_CSS_MAP_DEVICE,
+#if SPM_MM
+ ARM_SPM_BUF_EL3_MMAP,
+#endif
+ {0}
+};
+
+#if SPM_MM && defined(IMAGE_BL31)
+const mmap_region_t plat_arm_secure_partition_mmap[] = {
+ PLAT_ARM_SECURE_MAP_SYSTEMREG,
+ PLAT_ARM_SECURE_MAP_NOR2,
+ SOC_PLATFORM_SECURE_UART,
+ PLAT_ARM_SECURE_MAP_DEVICE,
+ ARM_SP_IMAGE_MMAP,
+ ARM_SP_IMAGE_NS_BUF_MMAP,
+#if RAS_EXTENSION
+ CSS_SGI_SP_CPER_BUF_MMAP,
+#endif
+ ARM_SP_IMAGE_RW_MMAP,
+ ARM_SPM_BUF_EL0_MMAP,
+ {0}
+};
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+#endif
+
+ARM_CASSERT_MMAP
+
+#if SPM_MM && defined(IMAGE_BL31)
+/*
+ * Boot information passed to a secure partition during initialisation. Linear
+ * indices in MP information will be filled at runtime.
+ */
+static spm_mm_mp_info_t sp_mp_info[] = {
+ [0] = {0x81000000, 0},
+ [1] = {0x81000100, 0},
+ [2] = {0x81000200, 0},
+ [3] = {0x81000300, 0},
+ [4] = {0x81010000, 0},
+ [5] = {0x81010100, 0},
+ [6] = {0x81010200, 0},
+ [7] = {0x81010300, 0},
+};
+
+const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
+ .h.type = PARAM_SP_IMAGE_BOOT_INFO,
+ .h.version = VERSION_1,
+ .h.size = sizeof(spm_mm_boot_info_t),
+ .h.attr = 0,
+ .sp_mem_base = ARM_SP_IMAGE_BASE,
+ .sp_mem_limit = ARM_SP_IMAGE_LIMIT,
+ .sp_image_base = ARM_SP_IMAGE_BASE,
+ .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
+ .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE,
+ .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
+ .sp_shared_buf_base = PLAT_SPM_BUF_BASE,
+ .sp_image_size = ARM_SP_IMAGE_SIZE,
+ .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+ .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE,
+ .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
+ .sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
+ .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS,
+ .num_cpus = PLATFORM_CORE_COUNT,
+ .mp_info = &sp_mp_info[0],
+};
+
+const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
+{
+ return plat_arm_secure_partition_mmap;
+}
+
+const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
+ void *cookie)
+{
+ return &plat_arm_secure_partition_boot_info;
+}
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+ sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/css/sgi/sgi_plat_v2.c b/plat/arm/css/sgi/sgi_plat_v2.c
new file mode 100644
index 0000000..cef5345
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_plat_v2.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
+
+#if SPM_MM
+#include <services/spm_mm_partition.h>
+#endif
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ SGI_MAP_FLASH0_RO,
+ CSS_SGI_MAP_DEVICE,
+ SOC_PLATFORM_PERIPH_MAP_DEVICE,
+ SOC_SYSTEM_PERIPH_MAP_DEVICE,
+ {0}
+};
+#endif
+
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ SGI_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+ CSS_SGI_MAP_DEVICE,
+ SOC_MEMCNTRL_MAP_DEVICE,
+ SOC_PLATFORM_PERIPH_MAP_DEVICE,
+ SOC_SYSTEM_PERIPH_MAP_DEVICE,
+ ARM_MAP_NS_DRAM1,
+#if CSS_SGI_CHIP_COUNT > 1
+ SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(1),
+#endif
+#if CSS_SGI_CHIP_COUNT > 2
+ SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(2),
+#endif
+#if CSS_SGI_CHIP_COUNT > 3
+ SOC_MEMCNTRL_MAP_DEVICE_REMOTE_CHIP(3),
+#endif
+#if ARM_BL31_IN_DRAM
+ ARM_MAP_BL31_SEC_DRAM,
+#endif
+#if SPM_MM
+ ARM_SP_IMAGE_MMAP,
+#endif
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif
+ {0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+ ARM_V2M_MAP_MEM_PROTECT,
+#endif
+ CSS_SGI_MAP_DEVICE,
+ SOC_PLATFORM_PERIPH_MAP_DEVICE,
+ SOC_SYSTEM_PERIPH_MAP_DEVICE,
+#if SPM_MM
+ ARM_SPM_BUF_EL3_MMAP,
+#endif
+ {0}
+};
+
+#if SPM_MM && defined(IMAGE_BL31)
+const mmap_region_t plat_arm_secure_partition_mmap[] = {
+ PLAT_ARM_SECURE_MAP_SYSTEMREG,
+ PLAT_ARM_SECURE_MAP_NOR2,
+ SOC_PLATFORM_SECURE_UART,
+ SOC_PLATFORM_PERIPH_MAP_DEVICE_USER,
+ ARM_SP_IMAGE_MMAP,
+ ARM_SP_IMAGE_NS_BUF_MMAP,
+ ARM_SP_IMAGE_RW_MMAP,
+ ARM_SPM_BUF_EL0_MMAP,
+ {0}
+};
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+#endif
+
+ARM_CASSERT_MMAP
+
+#if SPM_MM && defined(IMAGE_BL31)
+/*
+ * Boot information passed to a secure partition during initialisation. Linear
+ * indices in MP information will be filled at runtime.
+ */
+static spm_mm_mp_info_t sp_mp_info[] = {
+ [0] = {0x81000000, 0},
+ [1] = {0x81010000, 0},
+ [2] = {0x81020000, 0},
+ [3] = {0x81030000, 0},
+ [4] = {0x81040000, 0},
+ [5] = {0x81050000, 0},
+ [6] = {0x81060000, 0},
+ [7] = {0x81070000, 0},
+ [8] = {0x81080000, 0},
+ [9] = {0x81090000, 0},
+ [10] = {0x810a0000, 0},
+ [11] = {0x810b0000, 0},
+ [12] = {0x810c0000, 0},
+ [13] = {0x810d0000, 0},
+ [14] = {0x810e0000, 0},
+ [15] = {0x810f0000, 0},
+};
+
+const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
+ .h.type = PARAM_SP_IMAGE_BOOT_INFO,
+ .h.version = VERSION_1,
+ .h.size = sizeof(spm_mm_boot_info_t),
+ .h.attr = 0,
+ .sp_mem_base = ARM_SP_IMAGE_BASE,
+ .sp_mem_limit = ARM_SP_IMAGE_LIMIT,
+ .sp_image_base = ARM_SP_IMAGE_BASE,
+ .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
+ .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE,
+ .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
+ .sp_shared_buf_base = PLAT_SPM_BUF_BASE,
+ .sp_image_size = ARM_SP_IMAGE_SIZE,
+ .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+ .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE,
+ .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
+ .sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
+ .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS,
+ .num_cpus = PLATFORM_CORE_COUNT,
+ .mp_info = &sp_mp_info[0],
+};
+
+const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
+{
+ return plat_arm_secure_partition_mmap;
+}
+
+const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
+ void *cookie)
+{
+ return &plat_arm_secure_partition_boot_info;
+}
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+ sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/css/sgi/sgi_ras.c b/plat/arm/css/sgi/sgi_ras.c
new file mode 100644
index 0000000..4f03ac4
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_ras.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <bl31/interrupt_mgmt.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/extensions/ras.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/common/platform.h>
+#include <services/sdei.h>
+#include <services/spm_mm_svc.h>
+
+#include <sgi_ras.h>
+
+static int sgi_ras_intr_handler(const struct err_record_info *err_rec,
+ int probe_data,
+ const struct err_handler_data *const data);
+typedef struct mm_communicate_header {
+ struct efi_guid header_guid;
+ size_t message_len;
+ uint8_t data[8];
+} mm_communicate_header_t;
+
+/*
+ * GUID to indicate that the MM communication message is intended for DMC-620
+ * MM driver.
+ */
+const struct efi_guid dmc620_ecc_event_guid = {
+ 0x5ef0afd5, 0xe01a, 0x4c30,
+ {0x86, 0x19, 0x45, 0x46, 0x26, 0x91, 0x80, 0x98}
+};
+
+struct sgi_ras_ev_map sgi575_ras_map[] = {
+
+ /* DMC 0 error ECC error interrupt*/
+ {SGI_SDEI_DS_EVENT_0, 35},
+
+ /* DMC 1 error ECC error interrupt*/
+ {SGI_SDEI_DS_EVENT_1, 39},
+};
+
+#define SGI575_RAS_MAP_SIZE ARRAY_SIZE(sgi575_ras_map)
+
+struct err_record_info sgi_err_records[] = {
+ {
+ /* DMC 0 error record info */
+ .handler = &sgi_ras_intr_handler,
+ .aux_data = (void *)0,
+ }, {
+ /* DMC 1 error record info */
+ .handler = &sgi_ras_intr_handler,
+ .aux_data = (void *)1,
+ },
+};
+
+struct ras_interrupt sgi_ras_interrupts[] = {
+ {
+ .intr_number = 35,
+ .err_record = &sgi_err_records[0],
+ }, {
+ .intr_number = 39,
+ .err_record = &sgi_err_records[1],
+ }
+};
+
+REGISTER_ERR_RECORD_INFO(sgi_err_records);
+REGISTER_RAS_INTERRUPTS(sgi_ras_interrupts);
+
+static struct sgi_ras_ev_map *plat_sgi_get_ras_ev_map(void)
+{
+ return sgi575_ras_map;
+}
+
+static int plat_sgi_get_ras_ev_map_size(void)
+{
+ return SGI575_RAS_MAP_SIZE;
+}
+
+/*
+ * Find event mapping for a given interrupt number: On success, returns pointer
+ * to the event mapping. On error, returns NULL.
+ */
+static struct sgi_ras_ev_map *find_ras_event_map_by_intr(uint32_t intr_num)
+{
+ struct sgi_ras_ev_map *map = plat_sgi_get_ras_ev_map();
+ int i;
+ int size = plat_sgi_get_ras_ev_map_size();
+
+ for (i = 0; i < size; i++) {
+ if (map->intr == intr_num)
+ return map;
+
+ map++;
+ }
+
+ return NULL;
+}
+
+static void sgi_ras_intr_configure(int intr)
+{
+ plat_ic_set_interrupt_type(intr, INTR_TYPE_EL3);
+ plat_ic_set_interrupt_priority(intr, PLAT_RAS_PRI);
+ plat_ic_clear_interrupt_pending(intr);
+ plat_ic_set_spi_routing(intr, INTR_ROUTING_MODE_ANY,
+ (u_register_t)read_mpidr_el1());
+ plat_ic_enable_interrupt(intr);
+}
+
+static int sgi_ras_intr_handler(const struct err_record_info *err_rec,
+ int probe_data,
+ const struct err_handler_data *const data)
+{
+ struct sgi_ras_ev_map *ras_map;
+ mm_communicate_header_t *header;
+ uint32_t intr;
+ int ret;
+
+ cm_el1_sysregs_context_save(NON_SECURE);
+ intr = data->interrupt;
+
+ /*
+ * Find if this is a RAS interrupt. There must be an event against
+ * this interrupt
+ */
+ ras_map = find_ras_event_map_by_intr(intr);
+ assert(ras_map != NULL);
+
+ /*
+ * Populate the MM_COMMUNICATE payload to share the
+ * event info with StandaloneMM code. This allows us to use
+ * MM_COMMUNICATE as a common entry mechanism into S-EL0. The
+ * header data will be parsed in StandaloneMM to process the
+ * corresponding event.
+ *
+ * TBD - Currently, the buffer allocated by SPM for communication
+ * between EL3 and S-EL0 is being used(PLAT_SPM_BUF_BASE). But this
+ * should happen via a dynamic mem allocation, which should be
+ * managed by SPM -- the individual platforms then call the mem
+ * alloc api to get memory for the payload.
+ */
+ header = (void *) PLAT_SPM_BUF_BASE;
+ memset(header, 0, sizeof(*header));
+ memcpy(&header->data, &err_rec->aux_data, sizeof(err_rec->aux_data));
+ header->message_len = sizeof(err_rec->aux_data);
+ memcpy(&header->header_guid, (void *) &dmc620_ecc_event_guid,
+ sizeof(const struct efi_guid));
+
+ spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
+ plat_my_core_pos());
+
+ /*
+ * Do an EOI of the RAS interrupt. This allows the
+ * sdei event to be dispatched at the SDEI event's
+ * priority.
+ */
+ plat_ic_end_of_interrupt(intr);
+
+ /* Dispatch the event to the SDEI client */
+ ret = sdei_dispatch_event(ras_map->sdei_ev_num);
+ if (ret != 0) {
+ /*
+ * sdei_dispatch_event() may return failing result in some cases,
+ * for example kernel may not have registered a handler or RAS event
+ * may happen early during boot. We restore the NS context when
+ * sdei_dispatch_event() returns failing result.
+ */
+ ERROR("SDEI dispatch failed: %d", ret);
+ cm_el1_sysregs_context_restore(NON_SECURE);
+ cm_set_next_eret_context(NON_SECURE);
+ }
+
+ return ret;
+}
+
+int sgi_ras_intr_handler_setup(void)
+{
+ int i;
+ struct sgi_ras_ev_map *map = plat_sgi_get_ras_ev_map();
+ int size = plat_sgi_get_ras_ev_map_size();
+
+ for (i = 0; i < size; i++) {
+ sgi_ras_intr_configure(map->intr);
+ map++;
+ }
+
+ INFO("SGI: RAS Interrupt Handler successfully registered\n");
+
+ return 0;
+}
diff --git a/plat/arm/css/sgi/sgi_topology.c b/plat/arm/css/sgi/sgi_topology.c
new file mode 100644
index 0000000..1c3b5bf
--- /dev/null
+++ b/plat/arm/css/sgi/sgi_topology.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Common topology related methods for SGI and RD based platforms
+ */
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+ return CSS_SGI_MAX_CPUS_PER_CLUSTER;
+}
+
+#if ARM_PLAT_MT
+/******************************************************************************
+ * Return the number of PE's supported by the CPU.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+ return CSS_SGI_MAX_PE_PER_CPU;
+}
+#endif
diff --git a/plat/arm/soc/common/soc_css.mk b/plat/arm/soc/common/soc_css.mk
new file mode 100644
index 0000000..8cad2a5
--- /dev/null
+++ b/plat/arm/soc/common/soc_css.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#PLAT_BL_COMMON_SOURCES +=
+
+BL1_SOURCES += plat/arm/soc/common/soc_css_security.c
+
+BL2_SOURCES += plat/arm/soc/common/soc_css_security.c
+
+BL2U_SOURCES += plat/arm/soc/common/soc_css_security.c
+
+BL31_SOURCES += plat/arm/soc/common/soc_css_security.c
diff --git a/plat/arm/soc/common/soc_css_security.c b/plat/arm/soc/common/soc_css_security.c
new file mode 100644
index 0000000..4f6bf61
--- /dev/null
+++ b/plat/arm/soc/common/soc_css_security.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/arm/nic_400.h>
+#include <lib/mmio.h>
+#include <plat/arm/soc/common/soc_css.h>
+
+void soc_css_init_nic400(void)
+{
+ /*
+ * NIC-400 Access Control Initialization
+ *
+ * Define access privileges by setting each corresponding bit to:
+ * 0 = Secure access only
+ * 1 = Non-secure access allowed
+ */
+
+ /*
+ * Allow non-secure access to some SOC regions, excluding UART1, which
+ * remains secure (unless CSS_NON_SECURE_UART is set).
+ * Note: This is the NIC-400 device on the SOC
+ */
+ mmio_write_32(SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_USB_EHCI), ~0);
+ mmio_write_32(SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_TLX_MASTER), ~0);
+ mmio_write_32(SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_USB_OHCI), ~0);
+ mmio_write_32(SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_PL354_SMC), ~0);
+ mmio_write_32(SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_APB4_BRIDGE), ~0);
+#if CSS_NON_SECURE_UART
+ /* Configure UART for non-secure access */
+ mmio_write_32(SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_BOOTSEC_BRIDGE), ~0);
+#else
+ mmio_write_32(SOC_CSS_NIC400_BASE +
+ NIC400_ADDR_CTRL_SECURITY_REG(SOC_CSS_NIC400_BOOTSEC_BRIDGE),
+ ~SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1);
+#endif /* CSS_NON_SECURE_UART */
+
+}
+
+
+#define PCIE_SECURE_REG 0x3000
+/* Mask uses REG and MEM access bits */
+#define PCIE_SEC_ACCESS_MASK ((1 << 0) | (1 << 1))
+
+void soc_css_init_pcie(void)
+{
+#if !PLAT_juno
+ /*
+ * Do not initialize PCIe in emulator environment.
+ * Platform ID register not supported on Juno
+ */
+ if (BOARD_CSS_GET_PLAT_TYPE(BOARD_CSS_PLAT_ID_REG_ADDR) ==
+ BOARD_CSS_PLAT_TYPE_EMULATOR)
+ return;
+#endif /* PLAT_juno */
+
+ /*
+ * PCIE Root Complex Security settings to enable non-secure
+ * access to config registers.
+ */
+ mmio_write_32(SOC_CSS_PCIE_CONTROL_BASE + PCIE_SECURE_REG,
+ PCIE_SEC_ACCESS_MASK);
+}
diff --git a/plat/brcm/board/common/bcm_console.c b/plat/brcm/board/common/bcm_console.c
new file mode 100644
index 0000000..5f20094
--- /dev/null
+++ b/plat/brcm/board/common/bcm_console.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/ti/uart/uart_16550.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Functions that set up the console
+ ******************************************************************************/
+static console_t bcm_boot_console;
+static console_t bcm_runtime_console;
+
+/* Initialize the console to provide early debug support */
+void bcm_console_boot_init(void)
+{
+ int rc = console_16550_register(PLAT_BRCM_BOOT_UART_BASE,
+ PLAT_BRCM_BOOT_UART_CLK_IN_HZ,
+ BRCM_CONSOLE_BAUDRATE,
+ &bcm_boot_console);
+ if (rc == 0) {
+ /*
+ * The crash console doesn't use the multi console API, it uses
+ * the core console functions directly. It is safe to call panic
+ * and let it print debug information.
+ */
+ panic();
+ }
+
+ console_set_scope(&bcm_boot_console, CONSOLE_FLAG_BOOT);
+}
+
+void bcm_console_boot_end(void)
+{
+ console_flush();
+
+ (void)console_unregister(&bcm_boot_console);
+}
+
+/* Initialize the runtime console */
+void bcm_console_runtime_init(void)
+{
+ int rc = console_16550_register(PLAT_BRCM_BL31_RUN_UART_BASE,
+ PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ,
+ BRCM_CONSOLE_BAUDRATE,
+ &bcm_runtime_console);
+ if (rc == 0)
+ panic();
+
+ console_set_scope(&bcm_runtime_console, CONSOLE_FLAG_RUNTIME);
+}
+
+void bcm_console_runtime_end(void)
+{
+ console_flush();
+
+ (void)console_unregister(&bcm_runtime_console);
+}
diff --git a/plat/brcm/board/common/bcm_elog.c b/plat/brcm/board/common/bcm_elog.c
new file mode 100644
index 0000000..093157e
--- /dev/null
+++ b/plat/brcm/board/common/bcm_elog.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2018 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+#include <bcm_elog.h>
+
+/* error logging signature */
+#define BCM_ELOG_SIG_OFFSET 0x0000
+#define BCM_ELOG_SIG_VAL 0x75767971
+
+/* current logging offset that points to where new logs should be added */
+#define BCM_ELOG_OFF_OFFSET 0x0004
+
+/* current logging length (excluding header) */
+#define BCM_ELOG_LEN_OFFSET 0x0008
+
+#define BCM_ELOG_HEADER_LEN 12
+
+/*
+ * @base: base address of memory where log is saved
+ * @max_size: max size of memory reserved for logging
+ * @is_active: indicates logging is currently active
+ * @level: current logging level
+ */
+struct bcm_elog {
+ uintptr_t base;
+ uint32_t max_size;
+ unsigned int is_active;
+ unsigned int level;
+};
+
+static struct bcm_elog global_elog;
+
+extern void memcpy16(void *dst, const void *src, unsigned int len);
+
+/*
+ * Log one character
+ */
+static void elog_putchar(struct bcm_elog *elog, unsigned char c)
+{
+ uint32_t offset, len;
+
+ offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET);
+ len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET);
+ mmio_write_8(elog->base + offset, c);
+ offset++;
+
+ /* log buffer is now full and need to wrap around */
+ if (offset >= elog->max_size)
+ offset = BCM_ELOG_HEADER_LEN;
+
+ /* only increment length when log buffer is not full */
+ if (len < elog->max_size - BCM_ELOG_HEADER_LEN)
+ len++;
+
+ mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset);
+ mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len);
+}
+
+static void elog_unsigned_num(struct bcm_elog *elog, unsigned long unum,
+ unsigned int radix)
+{
+ /* Just need enough space to store 64 bit decimal integer */
+ unsigned char num_buf[20];
+ int i = 0, rem;
+
+ do {
+ rem = unum % radix;
+ if (rem < 0xa)
+ num_buf[i++] = '0' + rem;
+ else
+ num_buf[i++] = 'a' + (rem - 0xa);
+ } while (unum /= radix);
+
+ while (--i >= 0)
+ elog_putchar(elog, num_buf[i]);
+}
+
+static void elog_string(struct bcm_elog *elog, const char *str)
+{
+ while (*str)
+ elog_putchar(elog, *str++);
+}
+
+/*
+ * Routine to initialize error logging
+ */
+int bcm_elog_init(void *base, uint32_t size, unsigned int level)
+{
+ struct bcm_elog *elog = &global_elog;
+ uint32_t val;
+
+ elog->base = (uintptr_t)base;
+ elog->max_size = size;
+ elog->is_active = 1;
+ elog->level = level / 10;
+
+ /*
+ * If a valid signature can be found, it means logs have been copied
+ * into designated memory by another software. In this case, we should
+ * not re-initialize the entry header in the designated memory
+ */
+ val = mmio_read_32(elog->base + BCM_ELOG_SIG_OFFSET);
+ if (val != BCM_ELOG_SIG_VAL) {
+ mmio_write_32(elog->base + BCM_ELOG_SIG_OFFSET,
+ BCM_ELOG_SIG_VAL);
+ mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET,
+ BCM_ELOG_HEADER_LEN);
+ mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * Routine to disable error logging
+ */
+void bcm_elog_exit(void)
+{
+ struct bcm_elog *elog = &global_elog;
+
+ if (!elog->is_active)
+ return;
+
+ elog->is_active = 0;
+
+ flush_dcache_range(elog->base, elog->max_size);
+}
+
+/*
+ * Routine to copy error logs from current memory to 'dst' memory and continue
+ * logging from the new 'dst' memory.
+ * dst and base addresses must be 16-bytes aligned.
+ */
+int bcm_elog_copy_log(void *dst, uint32_t max_size)
+{
+ struct bcm_elog *elog = &global_elog;
+ uint32_t offset, len;
+
+ if (!elog->is_active || ((uintptr_t)dst == elog->base))
+ return -1;
+
+ /* flush cache before copying logs */
+ flush_dcache_range(elog->base, max_size);
+
+ /*
+ * If current offset exceeds the new max size, then that is considered
+ * as a buffer overflow situation. In this case, we reset the offset
+ * back to the beginning
+ */
+ offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET);
+ if (offset >= max_size) {
+ offset = BCM_ELOG_HEADER_LEN;
+ mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset);
+ }
+
+ /* note payload length does not include header */
+ len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET);
+ if (len > max_size - BCM_ELOG_HEADER_LEN) {
+ len = max_size - BCM_ELOG_HEADER_LEN;
+ mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len);
+ }
+
+ /* Need to copy everything including the header. */
+ memcpy16(dst, (const void *)elog->base, len + BCM_ELOG_HEADER_LEN);
+ elog->base = (uintptr_t)dst;
+ elog->max_size = max_size;
+
+ return 0;
+}
+
+/*
+ * Main routine to save logs into memory
+ */
+void bcm_elog(const char *fmt, ...)
+{
+ va_list args;
+ const char *prefix_str;
+ int bit64;
+ int64_t num;
+ uint64_t unum;
+ char *str;
+ struct bcm_elog *elog = &global_elog;
+
+ /* We expect the LOG_MARKER_* macro as the first character */
+ unsigned int level = fmt[0];
+
+ if (!elog->is_active || level > elog->level)
+ return;
+
+ prefix_str = plat_log_get_prefix(level);
+
+ while (*prefix_str != '\0') {
+ elog_putchar(elog, *prefix_str);
+ prefix_str++;
+ }
+
+ va_start(args, fmt);
+ fmt++;
+ while (*fmt) {
+ bit64 = 0;
+
+ if (*fmt == '%') {
+ fmt++;
+ /* Check the format specifier */
+loop:
+ switch (*fmt) {
+ case 'i': /* Fall through to next one */
+ case 'd':
+ if (bit64)
+ num = va_arg(args, int64_t);
+ else
+ num = va_arg(args, int32_t);
+
+ if (num < 0) {
+ elog_putchar(elog, '-');
+ unum = (unsigned long)-num;
+ } else
+ unum = (unsigned long)num;
+
+ elog_unsigned_num(elog, unum, 10);
+ break;
+ case 's':
+ str = va_arg(args, char *);
+ elog_string(elog, str);
+ break;
+ case 'x':
+ if (bit64)
+ unum = va_arg(args, uint64_t);
+ else
+ unum = va_arg(args, uint32_t);
+
+ elog_unsigned_num(elog, unum, 16);
+ break;
+ case 'l':
+ bit64 = 1;
+ fmt++;
+ goto loop;
+ case 'u':
+ if (bit64)
+ unum = va_arg(args, uint64_t);
+ else
+ unum = va_arg(args, uint32_t);
+
+ elog_unsigned_num(elog, unum, 10);
+ break;
+ default:
+ /* Exit on any other format specifier */
+ goto exit;
+ }
+ fmt++;
+ continue;
+ }
+ elog_putchar(elog, *fmt++);
+ }
+exit:
+ va_end(args);
+}
diff --git a/plat/brcm/board/common/bcm_elog_ddr.c b/plat/brcm/board/common/bcm_elog_ddr.c
new file mode 100644
index 0000000..89e7bff
--- /dev/null
+++ b/plat/brcm/board/common/bcm_elog_ddr.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2019-2020 Broadcom.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <ddr_init.h>
+#include <scp_cmd.h>
+#include <scp_utils.h>
+#include <platform_def.h>
+
+#include "bcm_elog_ddr.h"
+#include "m0_cfg.h"
+#include "m0_ipc.h"
+
+void elog_init_ddr_log(void)
+{
+ struct elog_setup setup = {0};
+ struct elog_global_header global;
+ struct elog_meta_record rec;
+ unsigned int rec_idx = 0;
+ uint32_t log_offset;
+ uintptr_t metadata;
+ char *rec_desc[ELOG_SUPPORTED_REC_CNT] = {"SYSRESET", "THERMAL",
+ "DDR_ECC", "APBOOTLG",
+ "IDM"};
+
+ /*
+ * If this is warm boot, return immediately.
+ * We expect metadata to be initialized already
+ */
+ if (is_warmboot()) {
+ WARN("Warmboot detected, skip ELOG metadata initialization\n");
+ return;
+ }
+
+ memset(&global, 0, sizeof(global));
+
+ global.sector_size = ELOG_SECTOR_SIZE;
+ global.signature = ELOG_GLOBAL_META_HDR_SIG;
+ global.rec_count = ELOG_SUPPORTED_REC_CNT;
+
+ /* Start of logging area in DDR memory */
+ log_offset = ELOG_STORE_OFFSET;
+
+ /* Shift to the first RECORD header */
+ log_offset += 2 * global.sector_size;
+
+ /* Temporary place to hold metadata */
+ metadata = TMP_ELOG_METADATA_BASE;
+
+ memcpy((void *)metadata, &global, sizeof(global));
+ metadata += sizeof(global);
+
+ while (rec_idx < global.rec_count) {
+ memset(&rec, 0, sizeof(rec));
+
+ rec.type = rec_idx;
+ if (rec_idx == ELOG_REC_UART_LOG) {
+ rec.format = ELOG_REC_FMT_ASCII;
+ rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR;
+ rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_FS4_SCRATCH;
+ rec.src_mem_addr = BCM_ELOG_BL31_BASE;
+ rec.alt_src_mem_addr = BCM_ELOG_BL2_BASE;
+ rec.rec_size = ELOG_APBOOTLG_REC_SIZE;
+ } else if (rec_idx == ELOG_REC_IDM_LOG) {
+ rec.type = IDM_ELOG_REC_TYPE;
+ rec.format = ELOG_REC_FMT_CUSTOM;
+ rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR;
+ rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
+ rec.src_mem_addr = ELOG_IDM_SRC_MEM_ADDR;
+ rec.alt_src_mem_addr = 0x0;
+ rec.rec_size = ELOG_DEFAULT_REC_SIZE;
+ } else {
+ rec.format = ELOG_REC_FMT_CUSTOM;
+ rec.src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
+ rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH;
+ rec.src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
+ rec.alt_src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR;
+ rec.rec_size = ELOG_DEFAULT_REC_SIZE;
+ }
+
+ rec.nvm_type = LOG_MEDIA_DDR;
+ rec.sector_size = ELOG_SECTOR_SIZE;
+
+ rec.rec_addr = (uint64_t)log_offset;
+ log_offset += rec.rec_size;
+
+ /* Sanity checks */
+ if (rec.type > ELOG_MAX_REC_COUNT ||
+ rec.format > ELOG_MAX_REC_FORMAT ||
+ (rec.nvm_type > ELOG_MAX_NVM_TYPE &&
+ rec.nvm_type != ELOG_NVM_DEFAULT) ||
+ !rec.rec_size ||
+ !rec.sector_size ||
+ rec_idx >= ELOG_SUPPORTED_REC_CNT) {
+ ERROR("Invalid ELOG record(%u) detected\n", rec_idx);
+ return;
+ }
+
+ memset(rec.rec_desc, ' ', sizeof(rec.rec_desc));
+
+ memcpy(rec.rec_desc, rec_desc[rec_idx],
+ strlen(rec_desc[rec_idx]));
+
+ memcpy((void *)metadata, &rec, sizeof(rec));
+ metadata += sizeof(rec);
+
+ rec_idx++;
+ }
+
+ setup.params[0] = TMP_ELOG_METADATA_BASE;
+ setup.params[1] = (sizeof(global) + global.rec_count * sizeof(rec));
+ setup.cmd = ELOG_SETUP_CMD_WRITE_META;
+
+ flush_dcache_range((uintptr_t)&setup, sizeof(struct elog_setup));
+ flush_dcache_range((uintptr_t)setup.params[0], setup.params[1]);
+
+ /* initialize DDR Logging METADATA if this is NOT warmboot */
+ if (!is_warmboot()) {
+ if (scp_send_cmd(MCU_IPC_MCU_CMD_ELOG_SETUP,
+ (uint32_t)(uintptr_t)(&setup),
+ SCP_CMD_DEFAULT_TIMEOUT_US)) {
+ ERROR("scp_send_cmd: timeout/error for elog setup\n");
+ return;
+ }
+ }
+
+ NOTICE("MCU Error logging initialized\n");
+}
diff --git a/plat/brcm/board/common/bcm_elog_ddr.h b/plat/brcm/board/common/bcm_elog_ddr.h
new file mode 100644
index 0000000..6f21a68
--- /dev/null
+++ b/plat/brcm/board/common/bcm_elog_ddr.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2019-2020 Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BCM_ELOG_DDR_H
+#define BCM_ELOG_DDR_H
+
+#define ELOG_GLOBAL_META_HDR_SIG 0x45524c47
+#define ELOG_MAX_REC_COUNT 13
+#define ELOG_MAX_REC_FORMAT 1
+#define ELOG_MAX_NVM_TYPE 4
+/* Use a default NVM, set by m0 configuration */
+#define ELOG_NVM_DEFAULT 0xff
+
+/* Max. number of cmd parameters per elog spec */
+#define ELOG_PARAM_COUNT 3
+/*
+ * Number of supported RECORD Types-
+ * SYSRESET, THERMAL, DDR_ECC, APBOOTLG, IDM
+ */
+#define ELOG_SUPPORTED_REC_CNT 5
+
+#define ELOG_REC_DESC_LENGTH 8
+
+#define ELOG_SECTOR_SIZE 0x1000
+
+/* Default Record size for all record types except APBOOTLOG */
+#define ELOG_DEFAULT_REC_SIZE 0x10000
+
+/* Default record size for APBOOTLOG record */
+#define ELOG_APBOOTLG_REC_SIZE 0x60000
+
+/* Use default CRMU provided mem address */
+#define ELOG_USE_DEFAULT_MEM_ADDR 0x0
+
+/* Temporary place to hold metadata */
+#define TMP_ELOG_METADATA_BASE (ELOG_AP_UART_LOG_BASE + \
+ BCM_ELOG_BL2_SIZE)
+/* IDM ELOG source memory address */
+#define ELOG_IDM_SRC_MEM_ADDR 0x8f213000
+
+#define IDM_ELOG_REC_TYPE 5
+
+enum elog_record_type {
+ ELOG_REC_SYS_RESET_EVT = 0,
+ ELOG_REC_THERMAL_EVT,
+ ELOG_REC_DDR_ECC,
+ ELOG_REC_UART_LOG,
+ ELOG_REC_IDM_LOG,
+ ELOG_REC_MAX
+};
+
+enum elog_record_format {
+ ELOG_REC_FMT_ASCII = 0,
+ ELOG_REC_FMT_CUSTOM
+};
+
+enum elog_src_memory_type {
+ ELOG_SRC_MEM_TYPE_CRMU_SCRATCH = 0,
+ ELOG_SRC_MEM_TYPE_FS4_SCRATCH,
+ ELOG_SRC_MEM_TYPE_DDR,
+ ELOG_SRC_MEM_TYPE_CHIMP_SCRATCH
+};
+
+enum elog_setup_cmd {
+ ELOG_SETUP_CMD_VALIDATE_META,
+ ELOG_SETUP_CMD_WRITE_META,
+ ELOG_SETUP_CMD_ERASE,
+ ELOG_SETUP_CMD_READ,
+ ELOG_SETUP_CMD_CHECK
+};
+
+struct elog_setup {
+ uint32_t cmd;
+ uint32_t params[ELOG_PARAM_COUNT];
+ uint32_t result;
+ uint32_t ret_code;
+};
+
+struct elog_meta_record {
+ uint8_t type;
+ uint8_t format;
+ uint8_t src_mem_type;
+ uint8_t alt_src_mem_type;
+ uint8_t nvm_type;
+ char rec_desc[ELOG_REC_DESC_LENGTH];
+ uint64_t src_mem_addr;
+ uint64_t alt_src_mem_addr;
+ uint64_t rec_addr;
+ uint32_t rec_size;
+ uint32_t sector_size;
+ uint8_t padding[3];
+} __packed;
+
+struct elog_global_header {
+ uint32_t signature;
+ uint32_t sector_size;
+ uint8_t revision;
+ uint8_t rec_count;
+ uint16_t padding;
+} __packed;
+
+void elog_init_ddr_log(void);
+
+#endif /* BCM_ELOG_DDR_H */
diff --git a/plat/brcm/board/common/board_arm_trusted_boot.c b/plat/brcm/board/common/board_arm_trusted_boot.c
new file mode 100644
index 0000000..da18c31
--- /dev/null
+++ b/plat/brcm/board/common/board_arm_trusted_boot.c
@@ -0,0 +1,625 @@
+/*
+ * Copyright 2015 - 2020 Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <tools_share/tbbr_oid.h>
+
+#include <sbl_util.h>
+#include <sotp.h>
+
+/* Weak definition may be overridden in specific platform */
+#pragma weak plat_match_rotpk
+#pragma weak plat_get_nv_ctr
+#pragma weak plat_set_nv_ctr
+
+/* SHA256 algorithm */
+#define SHA256_BYTES 32
+
+/* ROTPK locations */
+#define ARM_ROTPK_REGS_ID 1
+#define ARM_ROTPK_DEVEL_RSA_ID 2
+#define BRCM_ROTPK_SOTP_RSA_ID 3
+
+#if !ARM_ROTPK_LOCATION_ID
+ #error "ARM_ROTPK_LOCATION_ID not defined"
+#endif
+
+static const unsigned char rotpk_hash_hdr[] =
+ "\x30\x31\x30\x0D\x06\x09\x60\x86\x48"
+ "\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
+static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1;
+static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES];
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
+static const unsigned char arm_devel_rotpk_hash[] =
+ "\xB0\xF3\x82\x09\x12\x97\xD8\x3A"
+ "\x37\x7A\x72\x47\x1B\xEC\x32\x73"
+ "\xE9\x92\x32\xE2\x49\x59\xF6\x5E"
+ "\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA";
+#endif
+
+#pragma weak plat_rotpk_hash
+const unsigned char plat_rotpk_hash[] =
+ "\xdb\x06\x67\x95\x4f\x88\x2b\x88"
+ "\x49\xbf\x70\x3f\xde\x50\x4a\x96"
+ "\xd8\x17\x69\xd4\xa0\x6c\xba\xee"
+ "\x66\x3e\x71\x82\x2d\x95\x69\xe4";
+
+#pragma weak rom_slice
+const unsigned char rom_slice[] =
+ "\x77\x06\xbc\x98\x40\xbe\xfd\xab"
+ "\x60\x4b\x74\x3c\x9a\xb3\x80\x75"
+ "\x39\xb6\xda\x27\x07\x2e\x5b\xbf"
+ "\x5c\x47\x91\xc9\x95\x26\x26\x0c";
+
+#if (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID)
+static int plat_is_trusted_boot(void)
+{
+ uint64_t section3_row0_data;
+
+ section3_row0_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
+
+ if ((section3_row0_data & SOTP_DEVICE_SECURE_CFG0_AB_MASK) == 0) {
+ INFO("NOT AB\n");
+ return 0;
+ }
+
+ INFO("AB\n");
+ return TRUSTED_BOARD_BOOT;
+}
+
+/*
+ * FAST AUTH is enabled if all following conditions are met:
+ * - AB part
+ * - SOTP.DEV != 0
+ * - SOTP.CID != 0
+ * - SOTP.ENC_DEV_TYPE = ENC_AB_DEV
+ * - Manuf_debug strap set high
+ */
+static int plat_fast_auth_enabled(void)
+{
+ uint32_t chip_state;
+ uint64_t section3_row0_data;
+ uint64_t section3_row1_data;
+
+ section3_row0_data =
+ sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
+ section3_row1_data =
+ sotp_mem_read(SOTP_DEVICE_SECURE_CFG1_ROW, 0);
+
+ chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES);
+
+ if (plat_is_trusted_boot() &&
+ (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_DEV_MASK) &&
+ (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_CID_MASK) &&
+ ((section3_row1_data & SOTP_ENC_DEV_TYPE_MASK) ==
+ SOTP_ENC_DEV_TYPE_AB_DEV) &&
+ (chip_state & SOTP_CHIP_STATES_MANU_DEBUG_MASK))
+ return 1;
+
+ return 0;
+}
+#endif
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ uint8_t *dst;
+
+ assert(key_ptr != NULL);
+ assert(key_len != NULL);
+ assert(flags != NULL);
+
+ *flags = 0;
+
+ /* Copy the DER header */
+ memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
+ dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len];
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
+ memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+ uint32_t *src, tmp;
+ unsigned int words, i;
+
+ /*
+ * Append the hash from Trusted Root-Key Storage registers. The hash has
+ * not been written linearly into the registers, so we have to do a bit
+ * of byte swapping:
+ *
+ * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C
+ * +---------------------------------------------------------------+
+ * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 |
+ * +---------------------------------------------------------------+
+ * | ... ... | | ... ... |
+ * | +--------------------+ | +-------+
+ * | | | |
+ * +----------------------------+ +----------------------------+
+ * | | | |
+ * +-------+ | +--------------------+ |
+ * | | | |
+ * v v v v
+ * +---------------------------------------------------------------+
+ * | | |
+ * +---------------------------------------------------------------+
+ * 0 15 16 31
+ *
+ * Additionally, we have to access the registers in 32-bit words
+ */
+ words = SHA256_BYTES >> 3;
+
+ /* Swap bytes 0-15 (first four registers) */
+ src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
+ for (i = 0 ; i < words ; i++) {
+ tmp = src[words - 1 - i];
+ /* Words are read in little endian */
+ *dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+ *dst++ = (uint8_t)(tmp & 0xFF);
+ }
+
+ /* Swap bytes 16-31 (last four registers) */
+ src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2);
+ for (i = 0 ; i < words ; i++) {
+ tmp = src[words - 1 - i];
+ *dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+ *dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+ *dst++ = (uint8_t)(tmp & 0xFF);
+ }
+#elif (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID)
+{
+ int i;
+ int ret = -1;
+
+ /*
+ * In non-AB mode, we do not read the key.
+ * In AB mode:
+ * - The Dauth is in BL11 if SBL is enabled
+ * - The Dauth is in SOTP if SBL is disabled.
+ */
+ if (plat_is_trusted_boot() == 0) {
+
+ INFO("NON-AB: Do not read DAUTH!\n");
+ *flags = ROTPK_NOT_DEPLOYED;
+ ret = 0;
+
+ } else if ((sbl_status() == SBL_ENABLED) &&
+ (mmio_read_32(BL11_DAUTH_BASE) == BL11_DAUTH_ID)) {
+
+ /* Read hash from BL11 */
+ INFO("readKeys (DAUTH) from BL11\n");
+
+ memcpy(dst,
+ (void *)(BL11_DAUTH_BASE + sizeof(uint32_t)),
+ SHA256_BYTES);
+
+ for (i = 0; i < SHA256_BYTES; i++)
+ if (dst[i] != 0)
+ break;
+
+ if (i >= SHA256_BYTES)
+ ERROR("Hash not valid from BL11\n");
+ else
+ ret = 0;
+
+ } else if (sotp_key_erased()) {
+
+ memcpy(dst, plat_rotpk_hash, SHA256_BYTES);
+
+ INFO("SOTP erased, Use internal key hash.\n");
+ ret = 0;
+
+ } else if (plat_fast_auth_enabled()) {
+
+ INFO("AB DEV: FAST AUTH!\n");
+ *flags = ROTPK_NOT_DEPLOYED;
+ ret = 0;
+
+ } else if (!(mmio_read_32(SOTP_STATUS_1) & SOTP_DAUTH_ECC_ERROR_MASK)) {
+
+ /* Read hash from SOTP */
+ ret = sotp_read_key(dst,
+ SHA256_BYTES,
+ SOTP_DAUTH_ROW,
+ SOTP_K_HMAC_ROW-1);
+
+ INFO("sotp_read_key (DAUTH): %i\n", ret);
+
+ } else {
+
+ uint64_t row_data;
+ uint32_t k;
+
+ for (k = 0; k < (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW); k++) {
+ row_data = sotp_mem_read(SOTP_DAUTH_ROW + k,
+ SOTP_ROW_NO_ECC);
+
+ if (row_data != 0)
+ break;
+ }
+
+ if (k == (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW)) {
+ INFO("SOTP NOT PROGRAMMED: Do not use DAUTH!\n");
+
+ if (sotp_mem_read(SOTP_ATF2_CFG_ROW_ID,
+ SOTP_ROW_NO_ECC) & SOTP_ROMKEY_MASK) {
+ memcpy(dst, plat_rotpk_hash, SHA256_BYTES);
+
+ INFO("Use internal key hash.\n");
+ ret = 0;
+ } else {
+ *flags = ROTPK_NOT_DEPLOYED;
+ ret = 0;
+ }
+ } else {
+ INFO("No hash found in SOTP\n");
+ }
+ }
+ if (ret)
+ return ret;
+}
+#endif
+
+ *key_ptr = (void *)rotpk_hash_der;
+ *key_len = (unsigned int)sizeof(rotpk_hash_der);
+ *flags |= ROTPK_IS_HASH;
+
+ return 0;
+}
+
+#define SOTP_NUM_BITS_PER_ROW 41
+#define SOTP_NVCTR_ROW_ALL_ONES 0x1ffffffffff
+#define SOTP_NVCTR_TRUSTED_IN_USE \
+ ((uint64_t)0x3 << (SOTP_NUM_BITS_PER_ROW-2))
+#define SOTP_NVCTR_NON_TRUSTED_IN_USE ((uint64_t)0x3)
+#define SOTP_NVCTR_TRUSTED_NEAR_END SOTP_NVCTR_NON_TRUSTED_IN_USE
+#define SOTP_NVCTR_NON_TRUSTED_NEAR_END SOTP_NVCTR_TRUSTED_IN_USE
+
+#define SOTP_NVCTR_ROW_START 64
+#define SOTP_NVCTR_ROW_END 75
+
+/*
+ * SOTP NVCTR are stored in section 10 of SOTP (rows 64-75).
+ * Each row of SOTP is 41 bits.
+ * NVCTR's are stored in a bitstream format.
+ * We are tolerant to consecutive bit errors.
+ * Trusted NVCTR starts at the top of row 64 in bitstream format.
+ * Non Trusted NVCTR starts at the bottom of row 75 in reverse bitstream.
+ * Each row can only be used by 1 of the 2 counters. This is determined
+ * by 2 zeros remaining at the beginning or end of the last available row.
+ * If one counter has already starting using a row, the other will be
+ * prevent from writing to that row.
+ *
+ * Example counter values for SOTP programmed below:
+ * Trusted Counter (rows64-69) = 5 * 41 + 40 = 245
+ * NonTrusted Counter (row75-71) = 3 * 41 + 4 = 127
+ * 40 39 38 37 36 ..... 5 4 3 2 1 0
+ * row 64 1 1 1 1 1 1 1 1 1 1 1
+ * row 65 1 1 1 1 1 1 1 1 1 1 1
+ * row 66 1 1 1 1 1 1 1 1 1 1 1
+ * row 67 1 1 1 1 1 1 1 1 1 1 1
+ * row 68 1 1 1 1 1 1 1 1 1 1 1
+ * row 69 1 1 1 1 1 1 1 1 1 1 0
+ * row 71 0 0 0 0 0 0 0 0 0 0 0
+ * row 71 0 0 0 0 0 0 0 0 0 0 0
+ * row 71 0 0 0 0 0 0 0 1 1 1 1
+ * row 73 1 1 1 1 1 1 1 1 1 1 1
+ * row 74 1 1 1 1 1 1 1 1 1 1 1
+ * row 75 1 1 1 1 1 1 1 1 1 1 1
+ *
+ */
+
+#if (DEBUG == 1)
+/*
+ * Dump sotp rows
+ */
+void sotp_dump_rows(uint32_t start_row, uint32_t end_row)
+{
+ int32_t rownum;
+ uint64_t rowdata;
+
+ for (rownum = start_row; rownum <= end_row; rownum++) {
+ rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
+ INFO("%d 0x%" PRIx64 "\n", rownum, rowdata);
+ }
+}
+#endif
+
+/*
+ * Get SOTP Trusted nvctr
+ */
+unsigned int sotp_get_trusted_nvctr(void)
+{
+ uint64_t rowdata;
+ uint64_t nextrowdata;
+ uint32_t rownum;
+ unsigned int nvctr;
+
+ rownum = SOTP_NVCTR_ROW_START;
+ nvctr = SOTP_NUM_BITS_PER_ROW;
+
+ /*
+ * Determine what row has last valid data for trusted ctr
+ */
+ rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
+ while ((rowdata & SOTP_NVCTR_TRUSTED_IN_USE) &&
+ (rowdata & SOTP_NVCTR_TRUSTED_NEAR_END) &&
+ (rownum < SOTP_NVCTR_ROW_END)) {
+ /*
+ * Current row in use and has data in last 2 bits as well.
+ * Check if next row also has data for this counter
+ */
+ nextrowdata = sotp_mem_read(rownum+1, SOTP_ROW_NO_ECC);
+ if (nextrowdata & SOTP_NVCTR_TRUSTED_IN_USE) {
+ /* Next row also has data so increment rownum */
+ rownum++;
+ nvctr += SOTP_NUM_BITS_PER_ROW;
+ rowdata = nextrowdata;
+ } else {
+ /* Next row does not have data */
+ break;
+ }
+ }
+
+ if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) {
+ while ((rowdata & 0x1) == 0) {
+ nvctr--;
+ rowdata >>= 1;
+ }
+ } else
+ nvctr -= SOTP_NUM_BITS_PER_ROW;
+
+ INFO("CTR %i\n", nvctr);
+ return nvctr;
+}
+
+/*
+ * Get SOTP NonTrusted nvctr
+ */
+unsigned int sotp_get_nontrusted_nvctr(void)
+{
+ uint64_t rowdata;
+ uint64_t nextrowdata;
+ uint32_t rownum;
+ unsigned int nvctr;
+
+ nvctr = SOTP_NUM_BITS_PER_ROW;
+ rownum = SOTP_NVCTR_ROW_END;
+
+ /*
+ * Determine what row has last valid data for nontrusted ctr
+ */
+ rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC);
+ while ((rowdata & SOTP_NVCTR_NON_TRUSTED_NEAR_END) &&
+ (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) &&
+ (rownum > SOTP_NVCTR_ROW_START)) {
+ /*
+ * Current row in use and has data in last 2 bits as well.
+ * Check if next row also has data for this counter
+ */
+ nextrowdata = sotp_mem_read(rownum-1, SOTP_ROW_NO_ECC);
+ if (nextrowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) {
+ /* Next row also has data so decrement rownum */
+ rownum--;
+ nvctr += SOTP_NUM_BITS_PER_ROW;
+ rowdata = nextrowdata;
+ } else {
+ /* Next row does not have data */
+ break;
+ }
+ }
+
+ if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) {
+ while ((rowdata & ((uint64_t)0x1 << (SOTP_NUM_BITS_PER_ROW-1)))
+ ==
+ 0) {
+ nvctr--;
+ rowdata <<= 1;
+ }
+ } else
+ nvctr -= SOTP_NUM_BITS_PER_ROW;
+
+ INFO("NCTR %i\n", nvctr);
+ return nvctr;
+}
+
+/*
+ * Set SOTP Trusted nvctr
+ */
+int sotp_set_trusted_nvctr(unsigned int nvctr)
+{
+ int numrows_available;
+ uint32_t nontrusted_rownum;
+ uint32_t trusted_rownum;
+ uint64_t rowdata;
+ unsigned int maxnvctr;
+
+ /*
+ * Read SOTP to find out how many rows are used by the
+ * NON Trusted nvctr
+ */
+ nontrusted_rownum = SOTP_NVCTR_ROW_END;
+ do {
+ rowdata = sotp_mem_read(nontrusted_rownum, SOTP_ROW_NO_ECC);
+ if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE)
+ nontrusted_rownum--;
+ else
+ break;
+ } while (nontrusted_rownum >= SOTP_NVCTR_ROW_START);
+
+ /*
+ * Calculate maximum value we can have for nvctr based on
+ * number of available rows.
+ */
+ numrows_available = nontrusted_rownum - SOTP_NVCTR_ROW_START + 1;
+ maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW;
+ if (maxnvctr) {
+ /*
+ * Last 2 bits of counter can't be written or it will
+ * overflow with nontrusted counter
+ */
+ maxnvctr -= 2;
+ }
+
+ if (nvctr > maxnvctr) {
+ /* Error - not enough room */
+ WARN("tctr not set\n");
+ return 1;
+ }
+
+ /*
+ * It is safe to write the nvctr, fill all 1's up to the
+ * last row and then fill the last row with partial bitstream
+ */
+ trusted_rownum = SOTP_NVCTR_ROW_START;
+ rowdata = SOTP_NVCTR_ROW_ALL_ONES;
+
+ while (nvctr >= SOTP_NUM_BITS_PER_ROW) {
+ sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+ nvctr -= SOTP_NUM_BITS_PER_ROW;
+ trusted_rownum++;
+ }
+ rowdata <<= (SOTP_NUM_BITS_PER_ROW - nvctr);
+ sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+ return 0;
+}
+
+/*
+ * Set SOTP NonTrusted nvctr
+ */
+int sotp_set_nontrusted_nvctr(unsigned int nvctr)
+{
+ int numrows_available;
+ uint32_t nontrusted_rownum;
+ uint32_t trusted_rownum;
+ uint64_t rowdata;
+ unsigned int maxnvctr;
+
+ /*
+ * Read SOTP to find out how many rows are used by the
+ * Trusted nvctr
+ */
+ trusted_rownum = SOTP_NVCTR_ROW_START;
+ do {
+ rowdata = sotp_mem_read(trusted_rownum, SOTP_ROW_NO_ECC);
+ if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE)
+ trusted_rownum++;
+ else
+ break;
+ } while (trusted_rownum <= SOTP_NVCTR_ROW_END);
+
+ /*
+ * Calculate maximum value we can have for nvctr based on
+ * number of available rows.
+ */
+ numrows_available = SOTP_NVCTR_ROW_END - trusted_rownum + 1;
+ maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW;
+ if (maxnvctr) {
+ /*
+ * Last 2 bits of counter can't be written or it will
+ * overflow with nontrusted counter
+ */
+ maxnvctr -= 2;
+ }
+
+ if (nvctr > maxnvctr) {
+ /* Error - not enough room */
+ WARN("nctr not set\n");
+ return 1;
+ }
+
+ /*
+ * It is safe to write the nvctr, fill all 1's up to the
+ * last row and then fill the last row with partial bitstream
+ */
+ nontrusted_rownum = SOTP_NVCTR_ROW_END;
+ rowdata = SOTP_NVCTR_ROW_ALL_ONES;
+
+ while (nvctr >= SOTP_NUM_BITS_PER_ROW) {
+ sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+ nvctr -= SOTP_NUM_BITS_PER_ROW;
+ nontrusted_rownum--;
+ }
+ rowdata >>= (SOTP_NUM_BITS_PER_ROW - nvctr);
+ sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata);
+ return 0;
+}
+
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ const char *oid;
+
+ assert(cookie != NULL);
+ assert(nv_ctr != NULL);
+
+ *nv_ctr = 0;
+ if ((sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
+ SOTP_ATF_NVCOUNTER_ENABLE_MASK)) {
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0)
+ *nv_ctr = sotp_get_trusted_nvctr();
+ else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0)
+ *nv_ctr = sotp_get_nontrusted_nvctr();
+ else
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Store a new non-volatile counter value.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ const char *oid;
+
+ if (sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
+ SOTP_ATF_NVCOUNTER_ENABLE_MASK) {
+ INFO("set CTR %i\n", nv_ctr);
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0)
+ return sotp_set_trusted_nvctr(nv_ctr);
+ else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0)
+ return sotp_set_nontrusted_nvctr(nv_ctr);
+ return 1;
+ }
+ return 0;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/brcm/board/common/board_common.c b/plat/brcm/board/common/board_common.c
new file mode 100644
index 0000000..2f764ab
--- /dev/null
+++ b/plat/brcm/board/common/board_common.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <brcm_def.h>
+#include <plat_brcm.h>
+
+#if IMAGE_BL2
+const mmap_region_t plat_brcm_mmap[] = {
+ HSLS_REGION,
+ BRCM_MAP_SHARED_RAM,
+ BRCM_MAP_NAND_RO,
+ BRCM_MAP_QSPI_RO,
+#ifdef PERIPH0_REGION
+ PERIPH0_REGION,
+#endif
+#ifdef PERIPH1_REGION
+ PERIPH1_REGION,
+#endif
+#ifdef USE_DDR
+ BRCM_MAP_NS_DRAM1,
+#if BRCM_BL31_IN_DRAM
+ BRCM_MAP_BL31_SEC_DRAM,
+#endif
+#else
+#ifdef BRCM_MAP_EXT_SRAM
+ BRCM_MAP_EXT_SRAM,
+#endif
+#endif
+#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE)
+ CRMU_SRAM_REGION,
+#endif
+ {0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_brcm_mmap[] = {
+ HSLS_REGION,
+#ifdef PERIPH0_REGION
+ PERIPH0_REGION,
+#endif
+#ifdef PERIPH1_REGION
+ PERIPH1_REGION,
+#endif
+#ifdef PERIPH2_REGION
+ PERIPH2_REGION,
+#endif
+#ifdef USB_REGION
+ USB_REGION,
+#endif
+#ifdef USE_DDR
+ BRCM_MAP_NS_DRAM1,
+#ifdef BRCM_MAP_NS_SHARED_DRAM
+ BRCM_MAP_NS_SHARED_DRAM,
+#endif
+#else
+#ifdef BRCM_MAP_EXT_SRAM
+ BRCM_MAP_EXT_SRAM,
+#endif
+#endif
+#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE)
+ CRMU_SRAM_REGION,
+#endif
+ {0}
+};
+#endif
+
+CASSERT((ARRAY_SIZE(plat_brcm_mmap) - 1) <= PLAT_BRCM_MMAP_ENTRIES,
+ assert_plat_brcm_mmap_mismatch);
+CASSERT((PLAT_BRCM_MMAP_ENTRIES + BRCM_BL_REGIONS) <= MAX_MMAP_REGIONS,
+ assert_max_mmap_regions);
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
new file mode 100644
index 0000000..24a27ed
--- /dev/null
+++ b/plat/brcm/board/common/board_common.mk
@@ -0,0 +1,294 @@
+#
+# Copyright (c) 2015 - 2021, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_BL_COMMON_SOURCES += plat/brcm/board/common/board_common.c
+
+# If no board config makefile, do not include it
+ifneq (${BOARD_CFG},)
+BOARD_CFG_MAKE := $(shell find plat/brcm/board/${PLAT} -name '${BOARD_CFG}.mk')
+$(eval $(call add_define,BOARD_CFG))
+ifneq (${BOARD_CFG_MAKE},)
+$(info Including ${BOARD_CFG_MAKE})
+include ${BOARD_CFG_MAKE}
+else
+$(error Error: File ${BOARD_CFG}.mk not found in plat/brcm/board/${PLAT})
+endif
+endif
+
+# To compile with highest log level (VERBOSE) set value to 50
+LOG_LEVEL := 40
+
+# Use custom generic timer clock
+ifneq (${GENTIMER_ACTUAL_CLOCK},)
+$(info Using GENTIMER_ACTUAL_CLOCK=$(GENTIMER_ACTUAL_CLOCK))
+SYSCNT_FREQ := $(GENTIMER_ACTUAL_CLOCK)
+$(eval $(call add_define,SYSCNT_FREQ))
+endif
+
+ifeq (${DRIVER_EMMC_ENABLE},)
+DRIVER_EMMC_ENABLE :=1
+endif
+
+ifeq (${DRIVER_SPI_ENABLE},)
+DRIVER_SPI_ENABLE := 0
+endif
+
+ifeq (${DRIVER_I2C_ENABLE},)
+DRIVER_I2C_ENABLE := 0
+endif
+
+# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set
+ifeq (${BRCM_DISABLE_TRUSTED_WDOG},)
+BRCM_DISABLE_TRUSTED_WDOG := 0
+endif
+ifeq (${SPIN_ON_BL1_EXIT}, 1)
+BRCM_DISABLE_TRUSTED_WDOG := 1
+endif
+
+$(eval $(call assert_boolean,BRCM_DISABLE_TRUSTED_WDOG))
+$(eval $(call add_define,BRCM_DISABLE_TRUSTED_WDOG))
+
+# Process ARM_BL31_IN_DRAM flag
+ifeq (${ARM_BL31_IN_DRAM},)
+ARM_BL31_IN_DRAM := 0
+endif
+$(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
+$(eval $(call add_define,ARM_BL31_IN_DRAM))
+
+ifeq (${STANDALONE_BL2},yes)
+BL2_LOG_LEVEL := 40
+$(eval $(call add_define,MMU_DISABLED))
+endif
+
+# BL2 XIP from QSPI
+RUN_BL2_FROM_QSPI := 0
+ifeq (${RUN_BL2_FROM_QSPI},1)
+$(eval $(call add_define,RUN_BL2_FROM_QSPI))
+endif
+
+# BL2 XIP from NAND
+RUN_BL2_FROM_NAND := 0
+ifeq (${RUN_BL2_FROM_NAND},1)
+$(eval $(call add_define,RUN_BL2_FROM_NAND))
+endif
+
+ifneq (${ELOG_AP_UART_LOG_BASE},)
+$(eval $(call add_define,ELOG_AP_UART_LOG_BASE))
+endif
+
+ifeq (${ELOG_SUPPORT},1)
+ifeq (${ELOG_STORE_MEDIA},DDR)
+$(eval $(call add_define,ELOG_STORE_MEDIA_DDR))
+ifneq (${ELOG_STORE_OFFSET},)
+$(eval $(call add_define,ELOG_STORE_OFFSET))
+endif
+endif
+endif
+
+ifneq (${BL2_LOG_LEVEL},)
+$(eval $(call add_define,BL2_LOG_LEVEL))
+endif
+
+ifneq (${BL31_LOG_LEVEL},)
+$(eval $(call add_define,BL31_LOG_LEVEL))
+endif
+
+# Use CRMU SRAM from iHOST
+ifneq (${USE_CRMU_SRAM},)
+$(eval $(call add_define,USE_CRMU_SRAM))
+endif
+
+# Use PIO mode if DDR is not used
+ifeq (${USE_DDR},yes)
+EMMC_USE_DMA := 1
+else
+EMMC_USE_DMA := 0
+endif
+$(eval $(call add_define,EMMC_USE_DMA))
+
+# On BRCM platforms, separate the code and read-only data sections to allow
+# mapping the former as executable and the latter as execute-never.
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use generic OID definition (tbbr_oid.h)
+USE_TBBR_DEFS := 1
+
+PLAT_INCLUDES += -Iplat/brcm/board/common \
+ -Iinclude/drivers/brcm \
+ -Iinclude/drivers/brcm/emmc \
+ -Iinclude/drivers/brcm/mdio
+
+PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \
+ plat/brcm/board/common/cmn_sec.c \
+ plat/brcm/board/common/bcm_console.c \
+ plat/brcm/board/common/brcm_mbedtls.c \
+ plat/brcm/board/common/plat_setup.c \
+ plat/brcm/board/common/platform_common.c \
+ drivers/arm/sp804/sp804_delay_timer.c \
+ drivers/brcm/sotp.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ plat/brcm/common/brcm_io_storage.c \
+ plat/brcm/board/common/err.c \
+ plat/brcm/board/common/sbl_util.c \
+ drivers/arm/sp805/sp805.c
+
+# Add RNG driver
+DRIVER_RNG_ENABLE := 1
+ifeq (${DRIVER_RNG_ENABLE},1)
+PLAT_BL_COMMON_SOURCES += drivers/brcm/rng.c
+endif
+
+# Add eMMC driver
+ifeq (${DRIVER_EMMC_ENABLE},1)
+$(eval $(call add_define,DRIVER_EMMC_ENABLE))
+
+EMMC_SOURCES += drivers/brcm/emmc/emmc_chal_sd.c \
+ drivers/brcm/emmc/emmc_csl_sdcard.c \
+ drivers/brcm/emmc/emmc_csl_sdcmd.c \
+ drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c
+
+PLAT_BL_COMMON_SOURCES += ${EMMC_SOURCES}
+
+ifeq (${DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT},)
+$(eval $(call add_define,DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT))
+endif
+endif
+
+BL2_SOURCES += plat/brcm/common/brcm_bl2_mem_params_desc.c \
+ plat/brcm/common/brcm_image_load.c \
+ common/desc_image_load.c
+
+BL2_SOURCES += plat/brcm/common/brcm_bl2_setup.c
+
+BL31_SOURCES += plat/brcm/common/brcm_bl31_setup.c
+
+ifeq (${BCM_ELOG},yes)
+ELOG_SOURCES += plat/brcm/board/common/bcm_elog.c
+BL2_SOURCES += ${ELOG_SOURCES}
+BL31_SOURCES += ${ELOG_SOURCES}
+endif
+
+# Add spi driver
+ifeq (${DRIVER_SPI_ENABLE},1)
+PLAT_BL_COMMON_SOURCES += drivers/brcm/spi/iproc_spi.c \
+ drivers/brcm/spi/iproc_qspi.c
+endif
+
+# Add spi nor/flash driver
+ifeq (${DRIVER_SPI_NOR_ENABLE},1)
+PLAT_BL_COMMON_SOURCES += drivers/brcm/spi_sf.c \
+ drivers/brcm/spi_flash.c
+endif
+
+ifeq (${DRIVER_I2C_ENABLE},1)
+$(eval $(call add_define,DRIVER_I2C_ENABLE))
+BL2_SOURCES += drivers/brcm/i2c/i2c.c
+PLAT_INCLUDES += -Iinclude/drivers/brcm/i2c
+endif
+
+ifeq (${DRIVER_OCOTP_ENABLE},1)
+$(eval $(call add_define,DRIVER_OCOTP_ENABLE))
+BL2_SOURCES += drivers/brcm/ocotp.c
+endif
+
+# Enable FRU table support
+ifeq (${USE_FRU},yes)
+$(eval $(call add_define,USE_FRU))
+BL2_SOURCES += drivers/brcm/fru.c
+endif
+
+# Enable GPIO support
+ifeq (${USE_GPIO},yes)
+$(eval $(call add_define,USE_GPIO))
+BL2_SOURCES += drivers/gpio/gpio.c
+BL2_SOURCES += drivers/brcm/iproc_gpio.c
+ifeq (${GPIO_SUPPORT_FLOAT_DETECTION},yes)
+$(eval $(call add_define,GPIO_SUPPORT_FLOAT_DETECTION))
+endif
+endif
+
+# Include mbedtls if it can be located
+MBEDTLS_DIR ?= mbedtls
+MBEDTLS_CHECK := $(shell find ${MBEDTLS_DIR}/include -name '$(notdir ${MBEDTLS_DIR})')
+
+ifneq (${MBEDTLS_CHECK},)
+$(info Found mbedTLS at ${MBEDTLS_DIR})
+PLAT_INCLUDES += -I${MBEDTLS_DIR}/include/mbedtls
+
+# By default, use RSA keys
+KEY_ALG := rsa_1_5
+
+# Include common TBB sources
+AUTH_SOURCES += drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+BL2_SOURCES += ${AUTH_SOURCES}
+
+# Use ATF framework for MBEDTLS
+TRUSTED_BOARD_BOOT := 1
+CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk
+IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk
+$(info Including ${CRYPTO_LIB_MK})
+include ${CRYPTO_LIB_MK}
+$(info Including ${IMG_PARSER_LIB_MK})
+include ${IMG_PARSER_LIB_MK}
+
+# Use ATF secure boot functions
+# Use Hardcoded hash for devel
+
+ARM_ROTPK_LOCATION=arm_rsa
+ifeq (${ARM_ROTPK_LOCATION}, arm_rsa)
+ARM_ROTPK_LOCATION_ID=ARM_ROTPK_DEVEL_RSA_ID
+ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
+else ifeq (${ARM_ROTPK_LOCATION}, brcm_rsa)
+ARM_ROTPK_LOCATION_ID=BRCM_ROTPK_SOTP_RSA_ID
+ifeq (${ROT_KEY},)
+ROT_KEY=plat/brcm/board/common/rotpk/rsa_dauth2048_key.pem
+endif
+KEY_FIND := $(shell m="${ROT_KEY}"; [ -f "$$m" ] && echo "$$m")
+ifeq (${KEY_FIND},)
+$(error Error: No ${ROT_KEY} located)
+else
+$(info Using ROT_KEY: ${ROT_KEY})
+endif
+else
+$(error "Unsupported ARM_ROTPK_LOCATION value")
+endif
+
+$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+PLAT_BL_COMMON_SOURCES+=plat/brcm/board/common/board_arm_trusted_boot.c
+endif
+
+#M0 runtime firmware
+ifdef SCP_BL2
+$(eval $(call add_define,NEED_SCP_BL2))
+SCP_CFG_DIR=$(dir ${SCP_BL2})
+PLAT_INCLUDES += -I${SCP_CFG_DIR}
+endif
+
+ifneq (${NEED_BL33},yes)
+# If there is no BL33, BL31 will jump to this address.
+ifeq (${USE_DDR},yes)
+PRELOADED_BL33_BASE := 0x80000000
+else
+PRELOADED_BL33_BASE := 0x74000000
+endif
+endif
+
+# Use translation tables library v1 by default
+ARM_XLAT_TABLES_LIB_V1 := 1
+ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
+$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
+PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c
+endif
diff --git a/plat/brcm/board/common/brcm_mbedtls.c b/plat/brcm/board/common/brcm_mbedtls.c
new file mode 100644
index 0000000..af42b86
--- /dev/null
+++ b/plat/brcm/board/common/brcm_mbedtls.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2015 - 2020 Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+
+void tls_exit(int code)
+{
+ INFO("%s: 0x%x\n", __func__, code);
+}
diff --git a/plat/brcm/board/common/chip_id.h b/plat/brcm/board/common/chip_id.h
new file mode 100644
index 0000000..842ac1f
--- /dev/null
+++ b/plat/brcm/board/common/chip_id.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CHIP_ID_H
+#define CHIP_ID_H
+
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define CHIP_REV_MAJOR_MASK 0xF0
+#define CHIP_REV_MAJOR_AX 0x00
+#define CHIP_REV_MAJOR_BX 0x10
+#define CHIP_REV_MAJOR_CX 0x20
+#define CHIP_REV_MAJOR_DX 0x30
+
+/* Get Chip ID (product number) of the chip */
+static inline unsigned int chip_get_product_id(void)
+{
+ return PLAT_CHIP_ID_GET;
+}
+
+/* Get Revision ID (major and minor) number of the chip */
+static inline unsigned int chip_get_rev_id(void)
+{
+ return PLAT_CHIP_REV_GET;
+}
+
+static inline unsigned int chip_get_rev_id_major(void)
+{
+ return (chip_get_rev_id() & CHIP_REV_MAJOR_MASK);
+}
+
+#endif
diff --git a/plat/brcm/board/common/cmn_plat_def.h b/plat/brcm/board/common/cmn_plat_def.h
new file mode 100644
index 0000000..79d9a29
--- /dev/null
+++ b/plat/brcm/board/common/cmn_plat_def.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CMN_PLAT_DEF_H
+#define CMN_PLAT_DEF_H
+
+#include <bcm_elog.h>
+#include <platform_def.h>
+
+#ifndef GET_LOG_LEVEL
+#define GET_LOG_LEVEL() LOG_LEVEL
+#endif
+
+#ifndef SET_LOG_LEVEL
+#define SET_LOG_LEVEL(x) ((void)(x))
+#endif
+
+#define PLAT_LOG_NOTICE(...) \
+ do { \
+ if (GET_LOG_LEVEL() >= LOG_LEVEL_NOTICE) { \
+ bcm_elog(LOG_MARKER_NOTICE __VA_ARGS__); \
+ tf_log(LOG_MARKER_NOTICE __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PLAT_LOG_ERROR(...) \
+ do { \
+ if (GET_LOG_LEVEL() >= LOG_LEVEL_ERROR) { \
+ bcm_elog(LOG_MARKER_ERROR, __VA_ARGS__); \
+ tf_log(LOG_MARKER_ERROR __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PLAT_LOG_WARN(...) \
+ do { \
+ if (GET_LOG_LEVEL() >= LOG_LEVEL_WARNING) { \
+ bcm_elog(LOG_MARKER_WARNING, __VA_ARGS__);\
+ tf_log(LOG_MARKER_WARNING __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PLAT_LOG_INFO(...) \
+ do { \
+ if (GET_LOG_LEVEL() >= LOG_LEVEL_INFO) { \
+ bcm_elog(LOG_MARKER_INFO __VA_ARGS__); \
+ tf_log(LOG_MARKER_INFO __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PLAT_LOG_VERBOSE(...) \
+ do { \
+ if (GET_LOG_LEVEL() >= LOG_LEVEL_VERBOSE) { \
+ bcm_elog(LOG_MARKER_VERBOSE __VA_ARGS__);\
+ tf_log(LOG_MARKER_VERBOSE __VA_ARGS__); \
+ } \
+ } while (0)
+
+/*
+ * The number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#if USE_COHERENT_MEM
+#define CMN_BL_REGIONS 3
+#else
+#define CMN_BL_REGIONS 2
+#endif
+
+/*
+ * FIP definitions
+ */
+#define PLAT_FIP_ATTEMPT_OFFSET 0x20000
+#define PLAT_FIP_NUM_ATTEMPTS 128
+
+#define PLAT_BRCM_FIP_QSPI_BASE QSPI_BASE_ADDR
+#define PLAT_BRCM_FIP_NAND_BASE NAND_BASE_ADDR
+#define PLAT_BRCM_FIP_MAX_SIZE 0x01000000
+
+#define PLAT_BRCM_FIP_BASE PLAT_BRCM_FIP_QSPI_BASE
+#endif
diff --git a/plat/brcm/board/common/cmn_plat_util.h b/plat/brcm/board/common/cmn_plat_util.h
new file mode 100644
index 0000000..178c843
--- /dev/null
+++ b/plat/brcm/board/common/cmn_plat_util.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CMN_PLAT_UTIL_H
+#define CMN_PLAT_UTIL_H
+
+#include <lib/mmio.h>
+
+/* BOOT source */
+#define BOOT_SOURCE_MASK 7
+#define BOOT_SOURCE_QSPI 0
+#define BOOT_SOURCE_NAND 1
+#define BOOT_SOURCE_SPI_NAND 2
+#define BOOT_SOURCE_UART 3
+#define BOOT_SOURCE_RES4 4
+#define BOOT_SOURCE_EMMC 5
+#define BOOT_SOURCE_ATE 6
+#define BOOT_SOURCE_USB 7
+#define BOOT_SOURCE_MAX 8
+#define BOOT_SOURCE_UNKNOWN (-1)
+
+#define KHMAC_SHA256_KEY_SIZE 32
+
+#define SOFT_PWR_UP_RESET_L0 0
+#define SOFT_SYS_RESET_L1 1
+#define SOFT_RESET_L3 0x3
+
+#define BOOT_SOURCE_SOFT_DATA_OFFSET 8
+#define BOOT_SOURCE_SOFT_ENABLE_OFFSET 14
+#define BOOT_SOURCE_SOFT_ENABLE_MASK BIT(BOOT_SOURCE_SOFT_ENABLE_OFFSET)
+
+typedef struct _key {
+ uint8_t hmac_sha256[KHMAC_SHA256_KEY_SIZE];
+} cmn_key_t;
+
+uint32_t boot_source_get(void);
+void bl1_platform_wait_events(void);
+void plat_soft_reset(uint32_t reset);
+
+#endif
diff --git a/plat/brcm/board/common/cmn_sec.c b/plat/brcm/board/common/cmn_sec.c
new file mode 100644
index 0000000..c80d5dd
--- /dev/null
+++ b/plat/brcm/board/common/cmn_sec.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <cmn_sec.h>
+
+#pragma weak plat_tz_master_default_cfg
+#pragma weak plat_tz_sdio_ns_master_set
+#pragma weak plat_tz_usb_ns_master_set
+
+void plat_tz_master_default_cfg(void)
+{
+ /* This function should be implemented in the platform side. */
+ ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
+}
+
+void plat_tz_sdio_ns_master_set(uint32_t ns)
+{
+ /* This function should be implemented in the platform side. */
+ ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
+}
+
+void plat_tz_usb_ns_master_set(uint32_t ns)
+{
+ /* This function should be implemented in the platform side. */
+ ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__);
+}
+
+void tz_master_default_cfg(void)
+{
+ plat_tz_master_default_cfg();
+}
+
+void tz_sdio_ns_master_set(uint32_t ns)
+{
+ plat_tz_sdio_ns_master_set(ns);
+}
+
+void tz_usb_ns_master_set(uint32_t ns)
+{
+ plat_tz_usb_ns_master_set(ns);
+}
diff --git a/plat/brcm/board/common/cmn_sec.h b/plat/brcm/board/common/cmn_sec.h
new file mode 100644
index 0000000..f74863d
--- /dev/null
+++ b/plat/brcm/board/common/cmn_sec.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CMN_SEC_H
+#define CMN_SEC_H
+
+#include <stdint.h>
+
+#define SECURE_MASTER 0
+#define NS_MASTER 1
+
+void tz_master_default_cfg(void);
+void tz_usb_ns_master_set(uint32_t ns);
+void tz_sdio_ns_master_set(uint32_t ns);
+
+#endif
diff --git a/plat/brcm/board/common/err.c b/plat/brcm/board/common/err.c
new file mode 100644
index 0000000..1fc73c4
--- /dev/null
+++ b/plat/brcm/board/common/err.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define L0_RESET 0x2
+
+/*
+ * Brcm error handler
+ */
+void plat_error_handler(int err)
+{
+ INFO("L0 reset...\n");
+
+ /* Ensure the characters are flushed out */
+ console_flush();
+
+ mmio_write_32(CRMU_SOFT_RESET_CTRL, L0_RESET);
+
+ /*
+ * In case we get here:
+ * Loop until the watchdog resets the system
+ */
+ while (1) {
+ wfi();
+ }
+}
diff --git a/plat/brcm/board/common/plat_setup.c b/plat/brcm/board/common/plat_setup.c
new file mode 100644
index 0000000..95e12ed
--- /dev/null
+++ b/plat/brcm/board/common/plat_setup.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*
+ * This function returns the fixed clock frequency at which private
+ * timers run. This value will be programmed into CNTFRQ_EL0.
+ */
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYSCNT_FREQ;
+}
+
+static const char * const plat_prefix_str[] = {
+ "E: ", "N: ", "W: ", "I: ", "V: "
+};
+
+const char *plat_log_get_prefix(unsigned int log_level)
+{
+ return plat_prefix_str[log_level - 1U];
+}
diff --git a/plat/brcm/board/common/platform_common.c b/plat/brcm/board/common/platform_common.c
new file mode 100644
index 0000000..f4c9a73
--- /dev/null
+++ b/plat/brcm/board/common/platform_common.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/brcm/sotp.h>
+
+#include <cmn_plat_util.h>
+#include <platform_def.h>
+
+uint32_t boot_source_get(void)
+{
+ uint32_t data;
+
+#ifdef FORCE_BOOTSOURCE
+ data = FORCE_BOOTSOURCE;
+#else
+ /* Read primary boot strap from CRMU persistent registers */
+ data = mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1);
+ if (data & BOOT_SOURCE_SOFT_ENABLE_MASK) {
+ data >>= BOOT_SOURCE_SOFT_DATA_OFFSET;
+ } else {
+ uint64_t sotp_atf_row;
+
+ sotp_atf_row =
+ sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC);
+
+ if (sotp_atf_row & SOTP_BOOT_SOURCE_ENABLE_MASK) {
+ /* Construct the boot source based on SOTP bits */
+ data = 0;
+ if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS0)
+ data |= 0x1;
+ if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS1)
+ data |= 0x2;
+ if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS2)
+ data |= 0x4;
+ } else {
+
+ /*
+ * This path is for L0 reset with
+ * Primary Boot source disabled in SOTP.
+ * BOOT_SOURCE_FROM_PR_ON_L1 compile flag will allow
+ * to never come back here so that the
+ * external straps will not be read on L1 reset.
+ */
+
+ /* Use the external straps */
+ data = mmio_read_32(ROM_S0_IDM_IO_STATUS);
+
+#ifdef BOOT_SOURCE_FROM_PR_ON_L1
+ /* Enable boot source read from PR#1 */
+ mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1,
+ BOOT_SOURCE_SOFT_ENABLE_MASK);
+
+ /* set boot source */
+ data &= BOOT_SOURCE_MASK;
+ mmio_clrsetbits_32(CRMU_IHOST_SW_PERSISTENT_REG1,
+ BOOT_SOURCE_MASK << BOOT_SOURCE_SOFT_DATA_OFFSET,
+ data << BOOT_SOURCE_SOFT_DATA_OFFSET);
+#endif
+ }
+ }
+#endif
+ return (data & BOOT_SOURCE_MASK);
+}
+
+void __dead2 plat_soft_reset(uint32_t reset)
+{
+ if (reset == SOFT_RESET_L3) {
+ mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, reset);
+ mmio_write_32(CRMU_MAIL_BOX0, 0x0);
+ mmio_write_32(CRMU_MAIL_BOX1, 0xFFFFFFFF);
+ }
+
+ if (reset != SOFT_SYS_RESET_L1)
+ reset = SOFT_PWR_UP_RESET_L0;
+
+ if (reset == SOFT_PWR_UP_RESET_L0)
+ INFO("L0 RESET...\n");
+
+ if (reset == SOFT_SYS_RESET_L1)
+ INFO("L1 RESET...\n");
+
+ console_flush();
+
+ mmio_clrbits_32(CRMU_SOFT_RESET_CTRL, 1 << reset);
+
+ while (1) {
+ ;
+ }
+}
diff --git a/plat/brcm/board/common/sbl_util.c b/plat/brcm/board/common/sbl_util.c
new file mode 100644
index 0000000..06e5b33
--- /dev/null
+++ b/plat/brcm/board/common/sbl_util.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#include <platform_def.h>
+#include <sbl_util.h>
+#include <sotp.h>
+
+#pragma weak plat_sbl_status
+
+int plat_sbl_status(uint64_t sbl_status)
+{
+ return sbl_status ? 1:0;
+}
+
+int sbl_status(void)
+{
+ uint64_t sbl_sotp = 0;
+ int ret = SBL_DISABLED;
+
+ sbl_sotp = sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC);
+
+ if (sbl_sotp != SOTP_ECC_ERR_DETECT) {
+
+ sbl_sotp &= SOTP_SBL_MASK;
+
+ if (plat_sbl_status(sbl_sotp))
+ ret = SBL_ENABLED;
+ }
+
+ VERBOSE("SBL status: %d\n", ret);
+
+ return ret;
+}
diff --git a/plat/brcm/board/common/sbl_util.h b/plat/brcm/board/common/sbl_util.h
new file mode 100644
index 0000000..0747389
--- /dev/null
+++ b/plat/brcm/board/common/sbl_util.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SBL_UTIL_H
+#define SBL_UTIL_H
+
+#include <stdint.h>
+
+#include <sotp.h>
+
+#define SBL_DISABLED 0
+#define SBL_ENABLED 1
+
+int sbl_status(void);
+
+#endif /* #ifdef SBL_UTIL_H */
diff --git a/plat/brcm/board/common/timer_sync.c b/plat/brcm/board/common/timer_sync.c
new file mode 100644
index 0000000..7e33a94
--- /dev/null
+++ b/plat/brcm/board/common/timer_sync.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+#include <timer_sync.h>
+
+/*******************************************************************************
+ * Defines related to time sync and satelite timers
+ ******************************************************************************/
+#define TIME_SYNC_WR_ENA ((uint32_t)0xACCE55 << 8)
+#define IHOST_STA_TMR_CTRL 0x1800
+#define IHOST_SAT_TMR_INC_L 0x1814
+#define IHOST_SAT_TMR_INC_H 0x1818
+
+#define SAT_TMR_CYCLE_DELAY 2
+#define SAT_TMR_32BIT_WRAP_VAL (BIT_64(32) - SAT_TMR_CYCLE_DELAY)
+
+void ihost_enable_satellite_timer(unsigned int cluster_id)
+{
+ uintptr_t ihost_base;
+ uint32_t time_lx, time_h;
+ uintptr_t ihost_enable;
+
+ VERBOSE("Program iHost%u satellite timer\n", cluster_id);
+ ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
+
+ /* this read starts the satellite timer counting from 0 */
+ ihost_enable = CENTRAL_TIMER_GET_IHOST_ENA_BASE + cluster_id * 4;
+ time_lx = mmio_read_32(ihost_enable);
+
+ /*
+ * Increment the satellite timer by the central timer plus 2
+ * to accommodate for a 1 cycle delay through NOC
+ * plus counter starting from 0.
+ */
+ mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_L,
+ time_lx + SAT_TMR_CYCLE_DELAY);
+
+ /*
+ * Read the latched upper data, if lx will wrap by adding 2 to it
+ * we need to handle the wrap
+ */
+ time_h = mmio_read_32(CENTRAL_TIMER_GET_H);
+ if (time_lx >= SAT_TMR_32BIT_WRAP_VAL)
+ mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h + 1);
+ else
+ mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h);
+}
+
+void brcm_timer_sync_init(void)
+{
+ unsigned int cluster_id;
+
+ /* Get the Time Sync module out of reset */
+ mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
+ BIT(CDRU_MISC_RESET_CONTROL_TS_RESET_N));
+
+ /* Deassert the Central Timer TIMER_EN signal for all module */
+ mmio_write_32(CENTRAL_TIMER_SAT_TMR_ENA, TIME_SYNC_WR_ENA);
+
+ /* enables/programs iHost0 satellite timer*/
+ cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
+ ihost_enable_satellite_timer(cluster_id);
+}
diff --git a/plat/brcm/board/stingray/aarch64/plat_helpers.S b/plat/brcm/board/stingray/aarch64/plat_helpers.S
new file mode 100644
index 0000000..9a2039d
--- /dev/null
+++ b/plat/brcm/board/stingray/aarch64/plat_helpers.S
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <cpu_macros.S>
+#include <cortex_a72.h>
+#include <drivers/ti/uart/uart_16550.h>
+
+#include <platform_def.h>
+
+ .globl plat_reset_handler
+ .globl platform_get_entrypoint
+ .globl plat_secondary_cold_boot_setup
+ .globl platform_mem_init
+ .globl platform_check_mpidr
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_disable_acp
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl platform_is_primary_cpu
+ .globl plat_brcm_calc_core_pos
+ .globl plat_get_my_entrypoint
+
+
+ /* ------------------------------------------------------------
+ * void plat_l2_init(void);
+ *
+ * BL1 and BL2 run with one core, one cluster
+ * This is safe to disable cluster coherency
+ * to make use of the data cache MMU WB attribute
+ * for the SRAM.
+ *
+ * Set L2 Auxiliary Control Register
+ * --------------------------------------------------------------------
+ */
+func plat_l2_init
+ mrs x0, CORTEX_A72_L2ACTLR_EL1
+#if (IMAGE_BL1 || IMAGE_BL2) || defined(USE_SINGLE_CLUSTER)
+ orr x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI
+#else
+ bic x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI
+#endif
+ msr CORTEX_A72_L2ACTLR_EL1, x0
+
+ /* Set L2 Control Register */
+ mrs x0, CORTEX_A72_L2CTLR_EL1
+ mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_MASK << \
+ CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (CORTEX_A72_L2_TAG_RAM_LATENCY_MASK << \
+ CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT) | \
+ (U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \
+ (U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT))
+ bic x0, x0, x1
+ mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << \
+ CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \
+ (U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT))
+ orr x0, x0, x1
+ msr CORTEX_A72_L2CTLR_EL1, x0
+
+ isb
+ ret
+endfunc plat_l2_init
+
+ /* --------------------------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Before adding code in this function, refer to the guidelines in
+ * docs/firmware-design.md.
+ *
+ * --------------------------------------------------------------------
+ */
+func plat_reset_handler
+ mov x9, x30
+ bl plat_l2_init
+ mov x30, x9
+ ret
+endfunc plat_reset_handler
+
+ /* -----------------------------------------------------
+ * void platform_get_entrypoint (unsigned int mpid);
+ *
+ * Main job of this routine is to distinguish between
+ * a cold and warm boot.
+ * On a cold boot the secondaries first wait for the
+ * platform to be initialized after which they are
+ * hotplugged in. The primary proceeds to perform the
+ * platform initialization.
+ * -----------------------------------------------------
+ */
+func platform_get_entrypoint
+ /*TBD-STINGRAY*/
+ mov x0, #0
+ ret
+endfunc platform_get_entrypoint
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ bl plat_my_core_pos
+ mov_imm x1, SECONDARY_CPU_SPIN_BASE_ADDR
+ add x0, x1, x0, LSL #3
+ mov x1, #0
+ str x1, [x0]
+
+ /* Wait until the entrypoint gets populated */
+poll_mailbox:
+ ldr x1, [x0]
+ cbz x1, 1f
+ br x1
+1:
+ wfe
+ b poll_mailbox
+endfunc plat_secondary_cold_boot_setup
+
+
+ /* -----------------------------------------------------
+ * void platform_mem_init(void);
+ *
+ * We don't need to carry out any memory initialization
+ * on CSS platforms. The Secure RAM is accessible straight away.
+ * -----------------------------------------------------
+ */
+func platform_mem_init
+ /*TBD-STINGRAY*/
+ ret
+endfunc platform_mem_init
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func platform_check_mpidr
+ /*TBD-STINGRAY*/
+ mov x0, xzr
+ ret
+endfunc platform_check_mpidr
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+
+func plat_crash_console_init
+ mov_imm x0, BRCM_CRASH_CONSOLE_BASE
+ mov_imm x1, BRCM_CRASH_CONSOLE_REFCLK
+ mov_imm x2, BRCM_CRASH_CONSOLE_BAUDRATE
+ b console_16550_core_init
+ ret
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(void)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2, x3
+ * ---------------------------------------------
+ */
+
+func plat_crash_console_putc
+ mov_imm x1, BRCM_CRASH_CONSOLE_BASE
+ b console_16550_core_putc
+ ret
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush(void)
+ * Function to flush crash console
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, BRCM_CRASH_CONSOLE_BASE
+ b console_16550_core_flush
+ ret
+endfunc plat_crash_console_flush
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform. This function is allowed to use
+ * registers x0 - x17.
+ * -----------------------------------------------------
+ */
+
+func plat_disable_acp
+ /*TBD-STINGRAY*/
+ ret
+endfunc plat_disable_acp
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu (applicable only after a cold boot)
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ b platform_is_primary_cpu
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_brcm_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_brcm_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int platform_is_primary_cpu (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu (applicable only after a cold boot)
+ * -----------------------------------------------------
+ */
+func platform_is_primary_cpu
+ mov x9, x30
+ bl plat_my_core_pos
+ cmp x0, #PRIMARY_CPU
+ cset x0, eq
+ ret x9
+endfunc platform_is_primary_cpu
+
+ /* -----------------------------------------------------
+ * unsigned int plat_brcm_calc_core_pos(uint64_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 4) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func plat_brcm_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #7
+ ret
+endfunc plat_brcm_calc_core_pos
+
+func plat_get_my_entrypoint
+ mrs x0, mpidr_el1
+ b platform_get_entrypoint
+endfunc plat_get_my_entrypoint
diff --git a/plat/brcm/board/stingray/bcm958742t-ns3.mk b/plat/brcm/board/stingray/bcm958742t-ns3.mk
new file mode 100644
index 0000000..5164eeb
--- /dev/null
+++ b/plat/brcm/board/stingray/bcm958742t-ns3.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2015 - 2020, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#######################################################
+# Board config file for bcm958742t-ns3 Stingray SST100-NS3
+#######################################################
+
+include plat/brcm/board/stingray/bcm958742t.mk
+
+# Load BL33 at 0xFF00_0000 address
+ifneq (${BL33_OVERRIDE_LOAD_ADDR},)
+$(eval $(call add_define_val,BL33_OVERRIDE_LOAD_ADDR,0xFF000000))
+endif
+
+# Nitro DDR secure memory
+# Nitro FW and config 0x8AE00000 - 0x8B000000
+# Nitro Crash dump 0x8B000000 - 0x8D000000
+DDR_NITRO_SECURE_REGION_START := 0x8AE00000
+DDR_NITRO_SECURE_REGION_END := 0x8D000000
diff --git a/plat/brcm/board/stingray/bcm958742t.mk b/plat/brcm/board/stingray/bcm958742t.mk
new file mode 100644
index 0000000..5e164b8
--- /dev/null
+++ b/plat/brcm/board/stingray/bcm958742t.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2015 - 2020, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+#######################################################
+# Board config file for bcm958742t Stingray SST100
+#######################################################
+BOARD_FAMILY := "<bcm958742t.h>"
+$(eval $(call add_define,BOARD_FAMILY))
+
+# Board has internal programmable regulator
+IHOST_REG_TYPE := IHOST_REG_INTEGRATED
+$(eval $(call add_define,IHOST_REG_TYPE))
+
+# Board has internal programmable regulator
+VDDC_REG_TYPE := VDDC_REG_INTEGRATED
+$(eval $(call add_define,VDDC_REG_TYPE))
diff --git a/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h b/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h
new file mode 100644
index 0000000..b2427cf
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_FAMILY_H
+#define BOARD_FAMILY_H
+
+#if defined(DRIVER_SPD_ENABLE) && !defined(DRIVER_SPD_SPOOF)
+#include <spd.h>
+#endif
+
+#ifdef USE_GPIO
+/* max number of supported GPIOs to construct the bitmap for board detection */
+#define MAX_NR_GPIOS 4
+
+/* max GPIO bitmap value */
+#define MAX_GPIO_BITMAP_VAL (BIT(MAX_NR_GPIOS) - 1)
+#endif
+
+struct mcb_ref_group {
+ uint32_t mcb_ref;
+ unsigned int *mcb_cfg;
+};
+
+#define MCB_REF_GROUP(ref) \
+{ \
+ .mcb_ref = 0x ## ref, \
+ .mcb_cfg = mcb_ ## ref, \
+}
+
+#endif
diff --git a/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c
new file mode 100644
index 0000000..74d2077
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+static void brcm_stingray_pnor_pinmux_init(void)
+{
+ unsigned int i;
+
+ INFO(" - pnor pinmux init start.\n");
+
+ /* Set PNOR_ADV_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2dc),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_BAA_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e0),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_BLS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e4),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_BLS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e8),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_CRE_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2ec),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_CS_2_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f0),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_CS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f4),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_CS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f8),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2fc),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_OE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x300),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_INTR_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x304),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set PNOR_DAT_x_MODE_SEL_CONTROL.fsel = 0x2 */
+ for (i = 0; i < 0x40; i += 0x4) {
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x308 + i),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+ }
+
+ /* Set NAND_CE1_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x348),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set NAND_CE0_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x34c),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set NAND_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x350),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set NAND_WP_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x354),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set NAND_RE_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x358),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set NAND_RDY_BSY_N_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x35c),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set NAND_IOx_0_MODE_SEL_CONTROL.fsel = 0x2 */
+ for (i = 0; i < 0x40; i += 0x4) {
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x360 + i),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+ }
+
+ /* Set NAND_ALE_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a0),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ /* Set NAND_CLE_MODE_SEL_CONTROL.fsel = 0x2 */
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a4),
+ MODE_SEL_CONTROL_FSEL_MASK,
+ MODE_SEL_CONTROL_FSEL_MODE2);
+
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x40), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x44), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x48), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x4c), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x50), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x54), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x58), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x5c), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x60), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x64), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x68), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x6c), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x70), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x74), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x78), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x7c), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x80), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x84), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x88), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x8c), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x90), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x94), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x98), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x9c), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa0), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa4), (7 << 1), 0x8);
+ mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa8), (7 << 1), 0x8);
+
+ INFO(" - pnor pinmux init done.\n");
+}
+
+#if BL2_TEST_EXT_SRAM
+#define SRAM_CHECKS_GRANUL 0x100000
+#define SRAM_CHECKS_CNT 8
+static unsigned int sram_checks[SRAM_CHECKS_CNT] = {
+ /* offset, magic */
+ 0xd00dfeed,
+ 0xfadebabe,
+ 0xc001d00d,
+ 0xa5a5b5b5,
+ 0x5a5a5b5b,
+ 0xc5c5d5d5,
+ 0x5c5c5d5d,
+ 0xe5e5f5f5,
+};
+#endif
+
+static void brcm_stingray_pnor_sram_init(void)
+{
+ unsigned int val, tmp;
+#if BL2_TEST_EXT_SRAM
+ unsigned int off, i;
+#endif
+ INFO(" - pnor sram init start.\n");
+
+ /* Enable PNOR Clock */
+ INFO(" -- enable pnor clock\n");
+ mmio_write_32((uintptr_t)(PNOR_IDM_IO_CONTROL_DIRECT), 0x1);
+ udelay(500);
+
+ /* Reset PNOR */
+ INFO(" -- reset pnor\n");
+ mmio_setbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1);
+ udelay(500);
+ mmio_clrbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1);
+ udelay(500);
+
+ /* Configure slave address to chip-select mapping */
+ INFO(" -- configure pnor slave address to chip-select mapping\n");
+ /* 0x74000000-0x75ffffff => CS0 (32MB) */
+ val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT);
+ val |= (0x74);
+ mmio_write_32((uintptr_t)(PNOR_ICFG_CS_0), val);
+ /* 0x76000000-0x77ffffff => CS1 (32MB) */
+ val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT);
+ val |= (0x76);
+ mmio_write_32((uintptr_t)(PNOR_ICFG_CS_1), val);
+ /* 0xffffffff-0xffffffff => CS2 (0MB) */
+ val = (0x00 << PNOR_ICFG_CS_x_MASK0_SHIFT);
+ val |= (0xff);
+ mmio_write_32((uintptr_t)(PNOR_ICFG_CS_2), val);
+
+ /* Print PNOR ID */
+ tmp = 0x0;
+ val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID0));
+ tmp |= (val & PNOR_REG_PERIPH_IDx_MASK);
+ val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID1));
+ tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 8);
+ val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID2));
+ tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 16);
+ val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID3));
+ tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 24);
+ INFO(" -- pnor primecell_id = 0x%x\n", tmp);
+
+ /* PNOR set_cycles */
+#ifdef EMULATION_SETUP
+ val = 0x00129A44;
+#else
+ val = 0x00125954; /* 0x00002DEF; */
+#endif
+ mmio_write_32((uintptr_t)(PNOR_REG_SET_CYCLES), val);
+ INFO(" -- pnor set_cycles = 0x%x\n", val);
+
+ /* PNOR set_opmode */
+ val = 0x0;
+#ifdef EMULATION_SETUP
+ /* TODO: Final values to be provided by DV folks */
+ val &= ~(0x7 << 7); /* set_wr_bl */
+ val &= ~(0x7 << 3); /* set_rd_bl */
+ val &= ~(0x3);
+ val |= (0x1); /* set_mw */
+#else
+ /* TODO: Final values to be provided by DV folks */
+ val &= ~(0x7 << 7); /* set_wr_bl */
+ val &= ~(0x7 << 3); /* set_rd_bl */
+ val &= ~(0x3);
+ val |= (0x1); /* set_mw */
+#endif
+ mmio_write_32((uintptr_t)(PNOR_REG_SET_OPMODE), val);
+ INFO(" -- pnor set_opmode = 0x%x\n", val);
+
+#ifndef EMULATION_SETUP
+ /* Actual SRAM chip will require self-refresh */
+ val = 0x1;
+ mmio_write_32((uintptr_t)(PNOR_REG_REFRESH_0), val);
+ INFO(" -- pnor refresh_0 = 0x%x\n", val);
+#endif
+
+#if BL2_TEST_EXT_SRAM
+ /* Check PNOR SRAM access */
+ for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) {
+ i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT;
+ val = sram_checks[i];
+ INFO(" -- pnor sram write addr=0x%lx value=0x%lx\n",
+ (unsigned long)(NOR_BASE_ADDR + off),
+ (unsigned long)val);
+ mmio_write_32((uintptr_t)(NOR_BASE_ADDR + off), val);
+ }
+ tmp = 0;
+ for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) {
+ i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT;
+ val = mmio_read_32((uintptr_t)(NOR_BASE_ADDR + off));
+ INFO(" -- pnor sram read addr=0x%lx value=0x%lx\n",
+ (unsigned long)(NOR_BASE_ADDR + off),
+ (unsigned long)val);
+ if (val == sram_checks[i])
+ tmp++;
+ }
+ INFO(" -- pnor sram checks pass=%d total=%d\n",
+ tmp, (NOR_SIZE / SRAM_CHECKS_GRANUL));
+
+ if (tmp != (NOR_SIZE / SRAM_CHECKS_GRANUL)) {
+ INFO(" - pnor sram init failed.\n");
+ while (1)
+ ;
+ } else {
+ INFO(" - pnor sram init done.\n");
+ }
+#endif
+}
+
+void ext_sram_init(void)
+{
+ INFO("%s start.\n", __func__);
+
+ brcm_stingray_pnor_pinmux_init();
+
+ brcm_stingray_pnor_sram_init();
+
+ INFO("%s done.\n", __func__);
+}
diff --git a/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h
new file mode 100644
index 0000000..8508653
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EXT_SRAM_INIT_H
+#define EXT_SRAM_INIT_H
+
+void ext_sram_init(void);
+#endif
diff --git a/plat/brcm/board/stingray/driver/ihost_pll_config.c b/plat/brcm/board/stingray/driver/ihost_pll_config.c
new file mode 100644
index 0000000..1184928
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ihost_pll_config.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <dmu.h>
+
+#define IHOST0_CONFIG_ROOT 0x66000000
+#define IHOST1_CONFIG_ROOT 0x66002000
+#define IHOST2_CONFIG_ROOT 0x66004000
+#define IHOST3_CONFIG_ROOT 0x66006000
+#define A72_CRM_PLL_PWR_ON 0x00000070
+#define A72_CRM_PLL_PWR_ON__PLL0_RESETB_R 4
+#define A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R 5
+#define A72_CRM_PLL_CHNL_BYPS_EN 0x000000ac
+#define A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R 0
+#define A72_CRM_PLL_CHNL_BYPS_EN_DATAMASK 0x0000ec1f
+#define A72_CRM_PLL_CMD 0x00000080
+#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R 0
+#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R 1
+#define A72_CRM_PLL_STATUS 0x00000084
+#define A72_CRM_PLL_STATUS__PLL0_LOCK_R 9
+#define A72_CRM_PLL0_CTRL1 0x00000100
+#define A72_CRM_PLL0_CTRL2 0x00000104
+#define A72_CRM_PLL0_CTRL3 0x00000108
+#define A72_CRM_PLL0_CTRL3__PLL0_PDIV_R 12
+#define A72_CRM_PLL0_CTRL4 0x0000010c
+#define A72_CRM_PLL0_CTRL4__PLL0_KP_R 0
+#define A72_CRM_PLL0_CTRL4__PLL0_KI_R 4
+#define A72_CRM_PLL0_CTRL4__PLL0_KA_R 7
+#define A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R 10
+
+#define PLL_MODE_VCO 0x0
+#define PLL_MODE_BYPASS 0x1
+#define PLL_RESET_TYPE_PLL 0x1
+#define PLL_RESET_TYPE_POST 0x2
+#define PLL_VCO 0x1
+#define PLL_POSTDIV 0x2
+#define ARM_FREQ_3G PLL_FREQ_FULL
+#define ARM_FREQ_1P5G PLL_FREQ_HALF
+#define ARM_FREQ_750M PLL_FREQ_QRTR
+
+static unsigned int ARMCOE_crm_getBaseAddress(unsigned int cluster_num)
+{
+ unsigned int ihostx_config_root;
+
+ switch (cluster_num) {
+ case 0:
+ default:
+ ihostx_config_root = IHOST0_CONFIG_ROOT;
+ break;
+ case 1:
+ ihostx_config_root = IHOST1_CONFIG_ROOT;
+ break;
+ case 2:
+ ihostx_config_root = IHOST2_CONFIG_ROOT;
+ break;
+ case 3:
+ ihostx_config_root = IHOST3_CONFIG_ROOT;
+ break;
+ }
+
+ return ihostx_config_root;
+}
+
+static void ARMCOE_crm_pllAssertReset(unsigned int cluster_num,
+ unsigned int reset_type)
+{
+ unsigned long ihostx_config_root;
+ unsigned int pll_rst_ctrl;
+
+ ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+ pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
+
+ // PLL reset
+ if (reset_type & PLL_RESET_TYPE_PLL) {
+ pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
+ }
+ // post-div channel reset
+ if (reset_type & PLL_RESET_TYPE_POST) {
+ pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
+ }
+
+ mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
+}
+
+static void ARMCOE_crm_pllSetMode(unsigned int cluster_num, unsigned int mode)
+{
+ unsigned long ihostx_config_root;
+ unsigned int pll_byp_ctrl;
+
+ ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+ pll_byp_ctrl = mmio_read_32(ihostx_config_root +
+ A72_CRM_PLL_CHNL_BYPS_EN);
+
+ if (mode == PLL_MODE_VCO) {
+ // use PLL DCO output
+ pll_byp_ctrl &=
+ ~BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
+ } else {
+ // use PLL bypass sources
+ pll_byp_ctrl |=
+ BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
+ }
+
+ mmio_write_32(ihostx_config_root + A72_CRM_PLL_CHNL_BYPS_EN,
+ pll_byp_ctrl);
+}
+
+static void ARMCOE_crm_pllFreqSet(unsigned int cluster_num,
+ unsigned int ihost_pll_freq_sel,
+ unsigned int pdiv)
+{
+ unsigned int ndiv_int;
+ unsigned int ndiv_frac_low, ndiv_frac_high;
+ unsigned long ihostx_config_root;
+
+ ndiv_frac_low = 0x0;
+ ndiv_frac_high = 0x0;
+
+ if (ihost_pll_freq_sel == ARM_FREQ_3G) {
+ ndiv_int = 0x78;
+ } else if (ihost_pll_freq_sel == ARM_FREQ_1P5G) {
+ ndiv_int = 0x3c;
+ } else if (ihost_pll_freq_sel == ARM_FREQ_750M) {
+ ndiv_int = 0x1e;
+ } else {
+ return;
+ }
+
+ ndiv_int &= 0x3FF; // low 10 bits
+ ndiv_frac_low &= 0x3FF;
+ ndiv_frac_high &= 0x3FF;
+
+ ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+
+ mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL1, ndiv_frac_low);
+ mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL2, ndiv_frac_high);
+ mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL3,
+ ndiv_int |
+ ((pdiv << A72_CRM_PLL0_CTRL3__PLL0_PDIV_R & 0xF000)));
+
+ mmio_write_32(ihostx_config_root + A72_CRM_PLL0_CTRL4,
+ /* From Section 10 of PLL spec */
+ (3 << A72_CRM_PLL0_CTRL4__PLL0_KP_R) |
+ /* From Section 10 of PLL spec */
+ (2 << A72_CRM_PLL0_CTRL4__PLL0_KI_R) |
+ /* Normal mode (i.e. not fast-locking) */
+ (0 << A72_CRM_PLL0_CTRL4__PLL0_KA_R) |
+ /* 50 MHz */
+ (50 << A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R));
+}
+
+static void ARMCOE_crm_pllDeassertReset(unsigned int cluster_num,
+ unsigned int reset_type)
+{
+ unsigned long ihostx_config_root;
+ unsigned int pll_rst_ctrl;
+
+ ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+ pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
+
+ // PLL reset
+ if (reset_type & PLL_RESET_TYPE_PLL) {
+ pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
+ }
+
+ // post-div channel reset
+ if (reset_type & PLL_RESET_TYPE_POST) {
+ pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
+ }
+
+ mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
+}
+
+static void ARMCOE_crm_pllUpdate(unsigned int cluster_num, unsigned int type)
+{
+ unsigned long ihostx_config_root;
+ unsigned int pll_cmd;
+
+ ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+ pll_cmd = mmio_read_32(ihostx_config_root + A72_CRM_PLL_CMD);
+
+ // VCO update
+ if (type & PLL_VCO) {
+ pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R);
+ }
+ // post-div channel update
+ if (type & PLL_POSTDIV) {
+ pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R);
+ }
+
+ mmio_write_32(ihostx_config_root+A72_CRM_PLL_CMD, pll_cmd);
+}
+
+static void insert_delay(unsigned int delay)
+{
+ volatile unsigned int index;
+
+ for (index = 0; index < delay; index++)
+ ;
+}
+
+
+/*
+ * Returns 1 if PLL locked within certain interval
+ */
+static unsigned int ARMCOE_crm_pllIsLocked(unsigned int cluster_num)
+{
+ unsigned long ihostx_config_root;
+ unsigned int lock_status;
+ unsigned int i;
+
+ ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+
+ /* wait a while for pll to lock before returning from this function */
+ for (i = 0; i < 1500; i++) {
+ insert_delay(256);
+ lock_status = mmio_read_32(ihostx_config_root +
+ A72_CRM_PLL_STATUS);
+ if (lock_status & BIT(A72_CRM_PLL_STATUS__PLL0_LOCK_R))
+ return 1;
+ }
+
+ ERROR("PLL of Cluster #%u failed to lock\n", cluster_num);
+ return 0;
+}
+
+/*
+ * ihost PLL Variable Frequency Configuration
+ *
+ * Frequency Limit {VCO,ARM} (GHz):
+ * 0 - no limit,
+ * 1 - {3.0,1.5},
+ * 2 - {4.0,2.0},
+ * 3 - {5.0,2.5}
+ */
+uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel)
+{
+ NOTICE("cluster: %u, freq_sel:0x%x\n", cluster_num, ihost_pll_freq_sel);
+
+ //bypass PLL
+ ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_BYPASS);
+ //assert reset
+ ARMCOE_crm_pllAssertReset(cluster_num,
+ PLL_RESET_TYPE_PLL | PLL_RESET_TYPE_POST);
+ //set ndiv_int for different freq
+ ARMCOE_crm_pllFreqSet(cluster_num, ihost_pll_freq_sel, 0x1);
+ //de-assert reset
+ ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_PLL);
+ ARMCOE_crm_pllUpdate(cluster_num, PLL_VCO);
+ //waiting for PLL lock
+ ARMCOE_crm_pllIsLocked(cluster_num);
+ ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_POST);
+ //disable bypass PLL
+ ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_VCO);
+
+ return 0;
+}
+
+uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num)
+{
+ unsigned long ihostx_config_root;
+ uint32_t ndiv_int;
+ uint32_t ihost_pll_freq_sel;
+
+ ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
+ ndiv_int = mmio_read_32(ihostx_config_root+A72_CRM_PLL0_CTRL3) & 0x3FF;
+
+ if (ndiv_int == 0x78) {
+ ihost_pll_freq_sel = ARM_FREQ_3G;
+ } else if (ndiv_int == 0x3c) {
+ ihost_pll_freq_sel = ARM_FREQ_1P5G;
+ } else if (ndiv_int == 0x1e) {
+ ihost_pll_freq_sel = ARM_FREQ_750M;
+ } else {
+ /* return unlimit otherwise*/
+ ihost_pll_freq_sel = 0;
+ }
+ return ihost_pll_freq_sel;
+}
diff --git a/plat/brcm/board/stingray/driver/plat_emmc.c b/plat/brcm/board/stingray/driver/plat_emmc.c
new file mode 100644
index 0000000..82085e1
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/plat_emmc.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define ICFG_IPROC_IOPAD_CTRL_4 (IPROC_ROOT + 0x9c0)
+#define ICFG_IPROC_IOPAD_CTRL_5 (IPROC_ROOT + 0x9c4)
+#define ICFG_IPROC_IOPAD_CTRL_6 (IPROC_ROOT + 0x9c8)
+#define ICFG_IPROC_IOPAD_CTRL_7 (IPROC_ROOT + 0x9cc)
+
+#define IOPAD_CTRL4_SDIO0_CD_IND_R 30
+#define IOPAD_CTRL4_SDIO0_CD_SRC_R 31
+#define IOPAD_CTRL4_SDIO0_CD_HYS_R 29
+#define IOPAD_CTRL4_SDIO0_CD_PULL_R 28
+#define IOPAD_CTRL4_SDIO0_CD_DRIVE_R 24
+#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R 23
+#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R 21
+#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R 17
+
+#define IOPAD_CTRL4_SDIO0_DATA0_SRC_R 15
+#define IOPAD_CTRL4_SDIO0_DATA0_HYS_R 13
+#define IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R 9
+#define IOPAD_CTRL4_SDIO0_DATA1_SRC_R 7
+#define IOPAD_CTRL4_SDIO0_DATA1_HYS_R 5
+#define IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R 1
+
+#define IOPAD_CTRL5_SDIO0_DATA2_SRC_R 31
+#define IOPAD_CTRL5_SDIO0_DATA2_HYS_R 29
+#define IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R 25
+#define IOPAD_CTRL5_SDIO0_DATA3_SRC_R 23
+#define IOPAD_CTRL5_SDIO0_DATA3_IND_R 22
+#define IOPAD_CTRL5_SDIO0_DATA3_HYS_R 21
+#define IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R 17
+#define IOPAD_CTRL5_SDIO0_DATA4_SRC_R 15
+#define IOPAD_CTRL5_SDIO0_DATA4_HYS_R 13
+#define IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R 9
+#define IOPAD_CTRL5_SDIO0_DATA5_SRC_R 7
+#define IOPAD_CTRL5_SDIO0_DATA5_HYS_R 5
+#define IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R 1
+
+#define IOPAD_CTRL6_SDIO0_DATA6_SRC_R 31
+#define IOPAD_CTRL6_SDIO0_DATA6_HYS_R 29
+#define IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R 25
+#define IOPAD_CTRL6_SDIO0_DATA7_SRC_R 23
+#define IOPAD_CTRL6_SDIO0_DATA7_HYS_R 21
+#define IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R 17
+
+void emmc_soft_reset(void)
+{
+ uint32_t val = 0;
+
+ val = (BIT(IOPAD_CTRL6_SDIO0_DATA7_SRC_R) |
+ BIT(IOPAD_CTRL6_SDIO0_DATA7_HYS_R) |
+ BIT(IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R) |
+ BIT(IOPAD_CTRL6_SDIO0_DATA6_SRC_R) |
+ BIT(IOPAD_CTRL6_SDIO0_DATA6_HYS_R) |
+ BIT(IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R));
+
+ mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
+
+ val = (BIT(IOPAD_CTRL5_SDIO0_DATA3_SRC_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA3_HYS_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA4_SRC_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA4_HYS_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA5_SRC_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA5_HYS_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R));
+
+ mmio_write_32(ICFG_IPROC_IOPAD_CTRL_5, val);
+
+ val = (BIT(IOPAD_CTRL4_SDIO0_DATA0_SRC_R) |
+ BIT(IOPAD_CTRL4_SDIO0_DATA0_HYS_R) |
+ BIT(IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R) |
+ BIT(IOPAD_CTRL4_SDIO0_DATA1_SRC_R) |
+ BIT(IOPAD_CTRL4_SDIO0_DATA1_HYS_R) |
+ BIT(IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA2_SRC_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA2_HYS_R) |
+ BIT(IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R));
+
+ mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
+
+ val = (BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R) |
+ BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R) |
+ BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R) |
+ BIT(IOPAD_CTRL4_SDIO0_CD_SRC_R) |
+ BIT(IOPAD_CTRL4_SDIO0_CD_HYS_R));
+
+ /*
+ * set pull-down, clear pull-up=0
+ * bit 12: pull-down bit 11: pull-up
+ * Note: In emulation, this pull-down setting was not
+ * sufficient. Board design likely requires pull down on
+ * this pin for eMMC.
+ */
+
+ val |= BIT(IOPAD_CTRL4_SDIO0_CD_PULL_R);
+
+ mmio_write_32(ICFG_IPROC_IOPAD_CTRL_4, val);
+}
diff --git a/plat/brcm/board/stingray/driver/sr_usb.h b/plat/brcm/board/stingray/driver/sr_usb.h
new file mode 100644
index 0000000..5033683
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/sr_usb.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SR_USB_H
+#define SR_USB_H
+
+#define CDRU_PM_RESET_N_R BIT(CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R)
+#define CDRU_USBSS_RESET_N BIT(CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N)
+#define CDRU_MISC_CLK_USBSS \
+ BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R)
+
+#define RESCAL_I_RSTB BIT(26)
+#define RESCAL_I_PWRDNB BIT(27)
+
+#define DRDU3_U3PHY_CTRL 0x68500014
+#define PHY_RESET BIT(1)
+#define POR_RESET BIT(28)
+#define MDIO_RESET BIT(29)
+
+#define DRDU3_PWR_CTRL 0x6850002c
+#define POWER_CTRL_OVRD BIT(2)
+
+#define USB3H_U3PHY_CTRL 0x68510014
+#define USB3H_U3SOFT_RST_N BIT(30)
+
+#define USB3H_PWR_CTRL 0x68510028
+
+#define USB3_PHY_MDIO_BLOCK_BASE_REG 0x1f
+#define BDC_AXI_SOFT_RST_N_OFFSET 0
+#define XHC_AXI_SOFT_RST_N_OFFSET 1
+#define MDIO_BUS_ID 3
+#define USB3H_PHY_ID 5
+#define USB3DRD_PHY_ID 2
+
+#define USB3_PHY_RXPMD_BLOCK_BASE 0x8020
+#define USB3_PHY_RXPMD_REG1 0x1
+#define USB3_PHY_RXPMD_REG2 0x2
+#define USB3_PHY_RXPMD_REG5 0x5
+#define USB3_PHY_RXPMD_REG7 0x7
+
+#define USB3_PHY_TXPMD_BLOCK_BASE 0x8040
+#define USB3_PHY_TXPMD_REG1 0x1
+#define USB3_PHY_TXPMD_REG2 0x2
+
+#define USB3_PHY_ANA_BLOCK_BASE 0x8090
+#define USB3_PHY_ANA_REG0 0x0
+#define USB3_PHY_ANA_REG1 0x1
+#define USB3_PHY_ANA_REG2 0x2
+#define USB3_PHY_ANA_REG5 0x5
+#define USB3_PHY_ANA_REG8 0x8
+#define USB3_PHY_ANA_REG11 0xb
+
+#define USB3_PHY_AEQ_BLOCK_BASE 0x80e0
+#define USB3_PHY_AEQ_REG1 0x1
+#define USB3_PHY_AEQ_REG3 0x3
+
+#ifdef USB_DMA_COHERENT
+#define DRDU3_U3XHC_SOFT_RST_N BIT(31)
+#define DRDU3_U3BDC_SOFT_RST_N BIT(30)
+
+#define DRDU3_SOFT_RESET_CTRL 0x68500030
+#define DRDU3_XHC_AXI_SOFT_RST_N BIT(1)
+#define DRDU3_BDC_AXI_SOFT_RST_N BIT(0)
+
+#define DRDU2_PHY_CTRL 0x6852000c
+#define DRDU2_U2SOFT_RST_N BIT(29)
+
+#define USB3H_SOFT_RESET_CTRL 0x6851002c
+#define USB3H_XHC_AXI_SOFT_RST_N BIT(1)
+
+#define DRDU2_SOFT_RESET_CTRL 0x68520020
+#define DRDU2_BDC_AXI_SOFT_RST_N BIT(0)
+
+#define DRD2U3H_XHC_REGS_AXIWRA 0x68511c08
+#define DRD2U3H_XHC_REGS_AXIRDA 0x68511c0c
+#define DRDU2D_BDC_REGS_AXIWRA 0x68521c08
+#define DRDU2D_BDC_REGS_AXIRDA 0x68521c0c
+#define DRDU3H_XHC_REGS_AXIWRA 0x68501c08
+#define DRDU3H_XHC_REGS_AXIRDA 0x68501c0c
+#define DRDU3D_BDC_REGS_AXIWRA 0x68502c08
+#define DRDU3D_BDC_REGS_AXIRDA 0x68502c0c
+/* cacheable write-back, allocate on both reads and writes */
+#define USBAXI_AWCACHE 0xf
+#define USBAXI_ARCACHE 0xf
+/* non-secure */
+#define USBAXI_AWPROT 0x8
+#define USBAXI_ARPROT 0x8
+#define USBAXIWR_SA_VAL ((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 0)
+#define USBAXIWR_SA_MASK ((0xf << 4 | 0xf) << 0)
+#define USBAXIWR_UA_VAL ((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 16)
+#define USBAXIWR_UA_MASK ((0xf << 4 | 0xf) << 0)
+#define USBAXIRD_SA_VAL ((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 0)
+#define USBAXIRD_SA_MASK ((0xf << 4 | 0xf) << 0)
+#define USBAXIRD_UA_VAL ((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 16)
+#define USBAXIRD_UA_MASK ((0xf << 4 | 0xf) << 0)
+#endif /* USB_DMA_COHERENT */
+
+#define ICFG_DRDU3_SID_CTRL 0x6850001c
+#define ICFG_USB3H_SID_CTRL 0x6851001c
+#define ICFG_DRDU2_SID_CTRL 0x68520010
+#define ICFG_USB_SID_SHIFT 5
+#define ICFG_USB_SID_AWADDR_OFFSET 0x0
+#define ICFG_USB_SID_ARADDR_OFFSET 0x4
+
+#define USBIC_GPV_BASE 0x68600000
+#define USBIC_GPV_SECURITY0 (USBIC_GPV_BASE + 0x8)
+#define USBIC_GPV_SECURITY0_FIELD BIT(0)
+#define USBIC_GPV_SECURITY1 (USBIC_GPV_BASE + 0xc)
+#define USBIC_GPV_SECURITY1_FIELD (BIT(0) | BIT(1))
+#define USBIC_GPV_SECURITY2 (USBIC_GPV_BASE + 0x10)
+#define USBIC_GPV_SECURITY2_FIELD (BIT(0) | BIT(1))
+#define USBIC_GPV_SECURITY4 (USBIC_GPV_BASE + 0x18)
+#define USBIC_GPV_SECURITY4_FIELD BIT(0)
+#define USBIC_GPV_SECURITY10 (USBIC_GPV_BASE + 0x30)
+#define USBIC_GPV_SECURITY10_FIELD (0x7 << 0)
+
+#define USBSS_TZPCDECPROT_BASE 0x68540800
+#define USBSS_TZPCDECPROT0set (USBSS_TZPCDECPROT_BASE + 0x4)
+#define USBSS_TZPCDECPROT0clr (USBSS_TZPCDECPROT_BASE + 0x8)
+#define DECPROT0_USBSS_DRD2U3H BIT(3)
+#define DECPROT0_USBSS_DRDU2H BIT(2)
+#define DECPROT0_USBSS_DRDU3D BIT(1)
+#define DECPROT0_USBSS_DRDU2D BIT(0)
+#define USBSS_TZPCDECPROT0 \
+ (DECPROT0_USBSS_DRD2U3H | \
+ DECPROT0_USBSS_DRDU2H | \
+ DECPROT0_USBSS_DRDU3D | \
+ DECPROT0_USBSS_DRDU2D)
+
+int32_t usb_device_init(unsigned int);
+
+#endif /* SR_USB_H */
diff --git a/plat/brcm/board/stingray/driver/swreg.c b/plat/brcm/board/stingray/driver/swreg.c
new file mode 100644
index 0000000..2b7c53b
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/swreg.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <sr_utils.h>
+#include <swreg.h>
+
+#define MIN_VOLT 760000
+#define MAX_VOLT 1060000
+
+#define BSTI_WRITE 0x1
+#define BSTI_READ 0x2
+#define BSTI_COMMAND_TA 0x2
+#define BSTI_COMMAND_DATA 0xFF
+#define BSTI_CONTROL_VAL 0x81
+#define BSTI_CONTROL_BUSY 0x100
+#define BSTI_TOGGLE_BIT 0x2
+#define BSTI_CONFI_DONE_MASK 0xFFFFFFFD
+#define BSTI_REG_DATA_MASK 0xFFFF
+#define BSTI_CMD(sb, op, pa, ra, ta, data) \
+ ((((sb) & 0x3) << 30) | (((op) & 0x3) << 28) | \
+ (((pa) & 0x1F) << 23) | (((ra) & 0x1F) << 18) | \
+ (((ta) & 0x3) << 16) | (data))
+
+#define PHY_REG0 0x0
+#define PHY_REG1 0x1
+#define PHY_REG4 0x4
+#define PHY_REG5 0x5
+#define PHY_REG6 0x6
+#define PHY_REG7 0x7
+#define PHY_REGC 0xc
+
+#define IHOST_VDDC_DATA 0x560
+#define DDR_CORE_DATA 0x2560
+#define UPDATE_POS_EDGE(data, set) ((data) | ((set) << 1))
+
+/*
+ * Formula for SR A2 reworked board:
+ * step = ((vol/(1.4117 * 0.98)) - 500000)/3125
+ * where,
+ * vol - input voltage
+ * 500000 - Reference voltage
+ * 3125 - one step value
+ */
+#define A2_VOL_REF 500000
+#define ONE_STEP_VALUE 3125
+#define VOL_DIV(vol) (((vol*10000ull)/(14117*98ull)) * 100ull)
+#define STEP_VALUE(vol) \
+ ((((((VOL_DIV(vol)) - A2_VOL_REF) / ONE_STEP_VALUE) & 0xFF) << 8) | 4)
+
+#define B0_VOL_REF ((500000/100)*98)
+#define B0_ONE_STEP_VALUE 3125
+/*
+ * Formula for SR B0 chip for IHOST12/03 and VDDC_CORE
+ * step = ((vol/1.56) - (500000 * 0.98))/3125
+ * where,
+ * vol - input voltage
+ * 500000 - Reference voltage
+ * 3125 - one step value
+ */
+#define B0_VOL_DIV(vol) (((vol)*100ull)/156)
+#define B0_STEP_VALUE(vol) \
+ ((((((B0_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
+ & 0xFF) << 8) | 4)
+
+/*
+ * Formula for SR B0 chip for DDR-CORE
+ * step = ((vol/1) - (500000 * 0.98))/3125
+ * where,
+ * vol - input voltage
+ * 500000 - Reference voltage
+ * 3125 - one step value
+ */
+#define B0_DDR_VDDC_VOL_DIV(vol) ((vol)/1)
+#define B0_DDR_VDDC_STEP_VALUE(vol) \
+ ((((((B0_DDR_VDDC_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
+ & 0xFF) << 8) | 4)
+
+#define MAX_SWREG_CNT 8
+#define MAX_ADDR_PER_SWREG 16
+#define MAX_REG_ADDR 0xF
+#define MIN_REG_ADDR 0x0
+
+static const char *sw_reg_name[MAX_SWREG_CNT] = {
+ "DDR_VDDC",
+ "IHOST03",
+ "IHOST12",
+ "IHOST_ARRAY",
+ "DDRIO_SLAVE",
+ "VDDC_CORE",
+ "VDDC1",
+ "DDRIO_MASTER"
+};
+
+/* firmware values for all SWREG for 3.3V input operation */
+static const uint16_t swreg_fm_data_bx[MAX_SWREG_CNT][MAX_ADDR_PER_SWREG] = {
+ /* DDR logic: Power Domains independent of 12v or 3p3v */
+ {0x25E0, 0x2D54, 0x0EC6, 0x01EC, 0x28BB, 0x1144, 0x0200, 0x69C0,
+ 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x820C, 0x0003, 0x0001, 0x0000},
+
+ /* ihost03, 3p3V */
+ {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+ 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+ /* ihost12 3p3v */
+ {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+ 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+ /* ihost array */
+ {0x25E0, 0x2D94, 0x0EC6, 0x01EC, 0x2ABB, 0x1144, 0x0340, 0x69C0,
+ 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x860C, 0x0003, 0x0001, 0x0000},
+
+ /* ddr io slave : 3p3v */
+ {0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
+ 0x003F, 0x0FFF, 0x10D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
+
+ /* core master 3p3v */
+ {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+ 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+ /* core slave 3p3v */
+ {0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
+ 0x003F, 0x0FFF, 0x10D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
+
+ /* ddr io master : 3p3v */
+ {0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
+ 0x003F, 0x0FFF, 0x90D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
+};
+
+#define FM_DATA swreg_fm_data_bx
+
+static int swreg_poll(void)
+{
+ uint32_t data;
+ int retry = 100;
+
+ do {
+ data = mmio_read_32(BSTI_CONTROL_OFFSET);
+ if ((data & BSTI_CONTROL_BUSY) != BSTI_CONTROL_BUSY)
+ return 0;
+ retry--;
+ udelay(1);
+ } while (retry > 0);
+
+ return -ETIMEDOUT;
+}
+
+static int write_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t data)
+{
+ uint32_t cmd;
+ int ret;
+
+ cmd = BSTI_CMD(0x1, BSTI_WRITE, reg_id, addr, BSTI_COMMAND_TA, data);
+ mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
+ mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
+ ret = swreg_poll();
+ if (ret) {
+ ERROR("Failed to write swreg %s addr 0x%x\n",
+ sw_reg_name[reg_id-1], addr);
+ return ret;
+ }
+ return ret;
+}
+
+static int read_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t *data)
+{
+ uint32_t cmd;
+ int ret;
+
+ cmd = BSTI_CMD(0x1, BSTI_READ, reg_id, addr, BSTI_COMMAND_TA, PHY_REG0);
+ mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
+ mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
+ ret = swreg_poll();
+ if (ret) {
+ ERROR("Failed to read swreg %s addr 0x%x\n",
+ sw_reg_name[reg_id-1], addr);
+ return ret;
+ }
+
+ *data = mmio_read_32(BSTI_COMMAND_OFFSET);
+ *data &= BSTI_REG_DATA_MASK;
+ return ret;
+}
+
+static int swreg_config_done(enum sw_reg reg_id)
+{
+ uint32_t read_data;
+ int ret;
+
+ ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
+ if (ret)
+ return ret;
+
+ read_data &= BSTI_CONFI_DONE_MASK;
+ read_data |= BSTI_TOGGLE_BIT;
+ ret = write_swreg_config(reg_id, PHY_REG0, read_data);
+ if (ret)
+ return ret;
+
+ ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
+ if (ret)
+ return ret;
+
+ read_data &= BSTI_CONFI_DONE_MASK;
+ ret = write_swreg_config(reg_id, PHY_REG0, read_data);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+#ifdef DUMP_SWREG
+static void dump_swreg_firmware(void)
+{
+ enum sw_reg reg_id;
+ uint32_t data;
+ int addr;
+ int ret;
+
+ for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+ INFO("SWREG: %s\n", sw_reg_name[reg_id - 1]);
+ for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
+ ret = read_swreg_config(reg_id, addr, &data);
+ if (ret)
+ ERROR("Failed to read offset %d\n", addr);
+ INFO("\t0x%x: 0x%04x\n", addr, data);
+ }
+ }
+}
+#endif
+
+int set_swreg(enum sw_reg reg_id, uint32_t micro_volts)
+{
+ uint32_t step, programmed_step;
+ uint32_t data = IHOST_VDDC_DATA;
+ int ret;
+
+ if ((micro_volts > MAX_VOLT) || (micro_volts < MIN_VOLT)) {
+ ERROR("input voltage out-of-range\n");
+ ret = -EINVAL;
+ goto failed;
+ }
+
+ ret = read_swreg_config(reg_id, PHY_REGC, &programmed_step);
+ if (ret)
+ goto failed;
+
+ if (reg_id == DDR_VDDC)
+ step = B0_DDR_VDDC_STEP_VALUE(micro_volts);
+ else
+ step = B0_STEP_VALUE(micro_volts);
+
+ if ((step >> 8) != (programmed_step >> 8)) {
+ ret = write_swreg_config(reg_id, PHY_REGC, step);
+ if (ret)
+ goto failed;
+
+ if (reg_id == DDR_VDDC)
+ data = DDR_CORE_DATA;
+
+ ret = write_swreg_config(reg_id, PHY_REG0,
+ UPDATE_POS_EDGE(data, 1));
+ if (ret)
+ goto failed;
+
+ ret = write_swreg_config(reg_id, PHY_REG0,
+ UPDATE_POS_EDGE(data, 0));
+ if (ret)
+ goto failed;
+ }
+
+ INFO("%s voltage updated to %duV\n", sw_reg_name[reg_id-1],
+ micro_volts);
+ return ret;
+
+failed:
+ /*
+ * Stop booting if voltages are not set
+ * correctly. Booting will fail at random point
+ * if we continue with wrong voltage settings.
+ */
+ ERROR("Failed to set %s voltage to %duV\n", sw_reg_name[reg_id-1],
+ micro_volts);
+ assert(0);
+
+ return ret;
+}
+
+/* Update SWREG firmware for all power doman for A2 chip */
+int swreg_firmware_update(void)
+{
+ enum sw_reg reg_id;
+ uint32_t data;
+ int addr;
+ int ret;
+
+ /* write firmware values */
+ for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+ /* write higher location first */
+ for (addr = MAX_REG_ADDR; addr >= MIN_REG_ADDR; addr--) {
+ ret = write_swreg_config(reg_id, addr,
+ FM_DATA[reg_id - 1][addr]);
+ if (ret)
+ goto exit;
+ }
+ }
+
+ /* trigger SWREG firmware update */
+ for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+ /*
+ * Slave regulator doesn't have to be updated,
+ * Updating Master is enough
+ */
+ if ((reg_id == DDRIO_SLAVE) || (reg_id == VDDC1))
+ continue;
+
+ ret = swreg_config_done(reg_id);
+ if (ret) {
+ ERROR("Failed to trigger SWREG firmware update for %s\n"
+ , sw_reg_name[reg_id-1]);
+ return ret;
+ }
+ }
+
+ for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
+ /*
+ * IHOST_ARRAY will be used on some boards like STRATUS and
+ * there will not be any issue even if it is updated on other
+ * boards where it is not used.
+ */
+ if (reg_id == IHOST_ARRAY)
+ continue;
+
+ for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
+ ret = read_swreg_config(reg_id, addr, &data);
+ if (ret || (!ret &&
+ (data != FM_DATA[reg_id - 1][addr]))) {
+ ERROR("swreg fm update failed: %s at off %d\n",
+ sw_reg_name[reg_id - 1], addr);
+ ERROR("Read val: 0x%x, expected val: 0x%x\n",
+ data, FM_DATA[reg_id - 1][addr]);
+ return -1;
+ }
+ }
+ }
+
+ INFO("Updated SWREG firmware\n");
+
+#ifdef DUMP_SWREG
+ dump_swreg_firmware();
+#endif
+ return ret;
+
+exit:
+ /*
+ * Stop booting if swreg firmware update fails.
+ * Booting will fail at random point if we
+ * continue with wrong voltage settings.
+ */
+ ERROR("Failed to update firmware for %s SWREG\n",
+ sw_reg_name[reg_id-1]);
+ assert(0);
+
+ return ret;
+}
diff --git a/plat/brcm/board/stingray/driver/usb.c b/plat/brcm/board/stingray/driver/usb.c
new file mode 100644
index 0000000..4a84141
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/usb.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mdio.h>
+#include <platform_usb.h>
+#include <sr_utils.h>
+#include "sr_usb.h"
+#include <usbh_xhci_regs.h>
+
+static uint32_t usb_func = USB3_DRD | USB3H_USB2DRD;
+
+static void usb_pm_rescal_init(void)
+{
+ uint32_t data;
+ uint32_t try;
+
+ mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PM_RESET_N_R);
+ /* release reset */
+ mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0, RESCAL_I_RSTB);
+ udelay(10U);
+ /* power up */
+ mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0,
+ RESCAL_I_RSTB | RESCAL_I_PWRDNB);
+ try = 1000U;
+ do {
+ udelay(1U);
+ data = mmio_read_32(CDRU_CHIP_TOP_SPARE_REG1);
+ try--;
+ } while ((data & RESCAL_I_PWRDNB) == 0x0U && (try != 0U));
+
+ if (try == 0U) {
+ ERROR("CDRU_CHIP_TOP_SPARE_REG1: 0x%x\n", data);
+ }
+
+ INFO("USB and PM Rescal Init done..\n");
+}
+
+const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS] = {
+ XHC_PORTSC1_OFFSET,
+ XHC_PORTSC2_OFFSET,
+ XHC_PORTSC3_OFFSET,
+};
+
+static void usb3h_usb2drd_init(void)
+{
+ uint32_t val;
+
+ INFO("USB3H + USB 2DRD init\n");
+ mmio_clrbits_32(USB3H_U3PHY_CTRL, POR_RESET);
+ val = mmio_read_32(USB3H_PWR_CTRL);
+ val &= ~(0x3U << POWER_CTRL_OVRD);
+ val |= (1U << POWER_CTRL_OVRD);
+ mmio_write_32(USB3H_PWR_CTRL, val);
+ mmio_setbits_32(USB3H_U3PHY_CTRL, PHY_RESET);
+ /* Phy to come out of reset */
+ udelay(2U);
+ mmio_clrbits_32(USB3H_U3PHY_CTRL, MDIO_RESET);
+
+ /* MDIO in reset */
+ udelay(2U);
+ mmio_setbits_32(USB3H_U3PHY_CTRL, MDIO_RESET);
+
+ /* After MDIO reset release */
+ udelay(2U);
+
+ /* USB 3.0 phy Analog Block Initialization */
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_ANA_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU);
+
+ /* USB 3.0 phy RXPMD Block initialization*/
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_RXPMD_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U);
+
+ /* USB 3.0 phy AEQ Block initialization*/
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_AEQ_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U);
+
+ /* USB 3.0 phy TXPMD Block initialization*/
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_TXPMD_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU);
+ mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU);
+}
+
+static void usb3drd_init(void)
+{
+ uint32_t val;
+
+ INFO("USB3DRD init\n");
+ mmio_clrbits_32(DRDU3_U3PHY_CTRL, POR_RESET);
+ val = mmio_read_32(DRDU3_PWR_CTRL);
+ val &= ~(0x3U << POWER_CTRL_OVRD);
+ val |= (1U << POWER_CTRL_OVRD);
+ mmio_write_32(DRDU3_PWR_CTRL, val);
+ mmio_setbits_32(DRDU3_U3PHY_CTRL, PHY_RESET);
+ /* Phy to come out of reset */
+ udelay(2U);
+ mmio_clrbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET);
+
+ /* MDIO in reset */
+ udelay(2U);
+ mmio_setbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET);
+
+ /* After MDIO reset release */
+ udelay(2U);
+
+ /* USB 3.0 DRD phy Analog Block Initialization */
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_ANA_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU);
+
+ /* USB 3.0 DRD phy RXPMD Block initialization*/
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_RXPMD_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U);
+
+ /* USB 3.0 DRD phy AEQ Block initialization*/
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_AEQ_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U);
+
+ /* USB 3.0 DRD phy TXPMD Block initialization*/
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
+ USB3_PHY_TXPMD_BLOCK_BASE);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU);
+ mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU);
+}
+
+static void usb3_phy_init(void)
+{
+ usb_pm_rescal_init();
+
+ if ((usb_func & USB3H_USB2DRD) != 0U) {
+ usb3h_usb2drd_init();
+ }
+
+ if ((usb_func & USB3_DRD) != 0U) {
+ usb3drd_init();
+ }
+}
+
+#ifdef USB_DMA_COHERENT
+void usb_enable_coherence(void)
+{
+ if (usb_func & USB3H_USB2DRD) {
+ mmio_setbits_32(USB3H_SOFT_RESET_CTRL,
+ USB3H_XHC_AXI_SOFT_RST_N);
+ mmio_setbits_32(DRDU2_SOFT_RESET_CTRL,
+ DRDU2_BDC_AXI_SOFT_RST_N);
+ mmio_setbits_32(USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
+ mmio_setbits_32(DRDU2_PHY_CTRL, DRDU2_U2SOFT_RST_N);
+
+ mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIWRA,
+ (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+ (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+ mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIRDA,
+ (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+ (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+
+ mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIWRA,
+ (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+ (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+ mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIRDA,
+ (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+ (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+
+ }
+
+ if (usb_func & USB3_DRD) {
+ mmio_setbits_32(DRDU3_SOFT_RESET_CTRL,
+ (DRDU3_XHC_AXI_SOFT_RST_N |
+ DRDU3_BDC_AXI_SOFT_RST_N));
+ mmio_setbits_32(DRDU3_U3PHY_CTRL,
+ (DRDU3_U3XHC_SOFT_RST_N |
+ DRDU3_U3BDC_SOFT_RST_N));
+
+ mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIWRA,
+ (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+ (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+ mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIRDA,
+ (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+ (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+
+ mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIWRA,
+ (USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
+ (USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
+
+ mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIRDA,
+ (USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
+ (USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
+ }
+}
+#endif
+
+void xhci_phy_init(void)
+{
+ uint32_t val;
+
+ INFO("usb init start\n");
+ mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL,
+ CDRU_MISC_CLK_USBSS);
+
+ mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_USBSS_RESET_N);
+
+ if (usb_func & USB3_DRD) {
+ VERBOSE(" - configure stream_id = 0x6800 for DRDU3\n");
+ val = SR_SID_VAL(0x3U, 0x1U, 0x0U) << ICFG_USB_SID_SHIFT;
+ mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
+ val);
+ mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
+ val);
+
+ /*
+ * DRDU3 Device USB Space, DRDU3 Host USB Space,
+ * DRDU3 SS Config
+ */
+ mmio_setbits_32(USBIC_GPV_SECURITY10,
+ USBIC_GPV_SECURITY10_FIELD);
+ }
+
+ if (usb_func & USB3H_USB2DRD) {
+ VERBOSE(" - configure stream_id = 0x6801 for USB3H\n");
+ val = SR_SID_VAL(0x3U, 0x1U, 0x1U) << ICFG_USB_SID_SHIFT;
+ mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
+ val);
+ mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
+ val);
+
+ VERBOSE(" - configure stream_id = 0x6802 for DRDU2\n");
+ val = SR_SID_VAL(0x3U, 0x1U, 0x2U) << ICFG_USB_SID_SHIFT;
+ mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
+ val);
+ mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
+ val);
+
+ /* DRDU2 APB Bridge:DRDU2 USB Device, USB3H SS Config */
+ mmio_setbits_32(USBIC_GPV_SECURITY1, USBIC_GPV_SECURITY1_FIELD);
+
+ /*
+ * USB3H APB Bridge:DRDU2 Host + USB3 Host USB Space,
+ * USB3H SS Config
+ */
+ mmio_setbits_32(USBIC_GPV_SECURITY2, USBIC_GPV_SECURITY2_FIELD);
+ }
+
+ /* Configure Host masters as non-Secure */
+ mmio_setbits_32(USBSS_TZPCDECPROT0set, USBSS_TZPCDECPROT0);
+
+ /* CCN Slave on USBIC */
+ mmio_setbits_32(USBIC_GPV_SECURITY0, USBIC_GPV_SECURITY0_FIELD);
+
+ /* SLAVE_8:IDM Register Space */
+ mmio_setbits_32(USBIC_GPV_SECURITY4, USBIC_GPV_SECURITY4_FIELD);
+
+ usb3_phy_init();
+#ifdef USB_DMA_COHERENT
+ usb_enable_coherence();
+#endif
+
+ usb_device_init(usb_func);
+
+ INFO("PLAT USB: init done.\n");
+}
diff --git a/plat/brcm/board/stingray/driver/usb_phy.c b/plat/brcm/board/stingray/driver/usb_phy.c
new file mode 100644
index 0000000..54c98e1
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/usb_phy.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_usb.h>
+#include <usb_phy.h>
+
+#define USB_PHY_ALREADY_STARTED (-2)
+#define USB_MAX_DEVICES 2
+#define USB3H_USB2DRD_PHY 0
+#define USB3_DRD_PHY 1
+
+/* Common bit fields for all the USB2 phy */
+#define USB2_PHY_ISO DRDU2_U2PHY_ISO
+#define USB2_AFE_PLL_PWRDWNB DRDU2_U2AFE_PLL_PWRDWNB
+#define USB2_AFE_BG_PWRDWNB DRDU2_U2AFE_BG_PWRDWNB
+#define USB2_AFE_LDO_PWRDWNB DRDU2_U2AFE_LDO_PWRDWNB
+#define USB2_CTRL_CORERDY DRDU2_U2CTRL_CORERDY
+
+#define USB2_PHY_PCTL_MASK DRDU2_U2PHY_PCTL_MASK
+#define USB2_PHY_PCTL_OFFSET DRDU2_U2PHY_PCTL_OFFSET
+#define USB2_PHY_PCTL_VAL U2PHY_PCTL_VAL
+
+#define USB2_PLL_RESETB DRDU2_U2PLL_RESETB
+#define USB2_PHY_RESETB DRDU2_U2PHY_RESETB
+
+static usb_phy_port_t usb_phy_port[2U][MAX_NR_PORTS];
+
+static usb_phy_t usb_phy_info[2U] = {
+ {DRDU2_U2PLL_NDIV_FRAC, USB3H_PIPE_CTRL, 0U, USB3H_DRDU2_PHY},
+ {0U, 0U, DRDU3_PIPE_CTRL, DRDU3_PHY}
+};
+
+typedef struct {
+ void *pcd_id;
+} usb_platform_dev;
+
+/* index 0: USB3H + USB2 DRD, 1: USB3 DRD */
+static usb_platform_dev xhci_devices_configs[USB_MAX_DEVICES] = {
+ {&usb_phy_info[0U]},
+ {&usb_phy_info[1U]}
+};
+
+static int32_t pll_lock_check(uint32_t address, uint32_t bit)
+{
+ uint32_t retry;
+ uint32_t data;
+
+ retry = PLL_LOCK_RETRY_COUNT;
+ do {
+ data = mmio_read_32(address);
+ if ((data & bit) != 0U) {
+ return 0;
+ }
+ udelay(1);
+ } while (--retry != 0);
+
+ ERROR("%s(): FAIL (0x%08x)\n", __func__, address);
+ return -1;
+}
+
+/*
+ * USB2 PHY using external FSM bringup sequence
+ * Total #3 USB2 phys. All phys has the same
+ * bringup sequence. Register bit fields for
+ * some of the PHY's are different.
+ * Bit fields which are different are passed using
+ * struct u2_phy_ext_fsm with bit-fields and register addr.
+ */
+
+static void u2_phy_ext_fsm_power_on(struct u2_phy_ext_fsm *u2_phy)
+{
+ mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+
+ mmio_setbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+
+ mmio_clrbits_32(u2_phy->phy_ctrl_reg,
+ (USB2_AFE_BG_PWRDWNB |
+ USB2_AFE_PLL_PWRDWNB |
+ USB2_AFE_LDO_PWRDWNB |
+ USB2_CTRL_CORERDY));
+
+ mmio_clrsetbits_32(u2_phy->phy_ctrl_reg,
+ (USB2_PHY_PCTL_MASK << USB2_PHY_PCTL_OFFSET),
+ (USB2_PHY_PCTL_VAL << USB2_PHY_PCTL_OFFSET));
+ /* Delay as per external FSM spec */
+ udelay(160U);
+
+ mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_CTRL_CORERDY);
+ /* Delay as per external FSM spec */
+ udelay(50U);
+
+ mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_BG_PWRDWNB);
+ /* Delay as per external FSM spec */
+ udelay(200U);
+
+ mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_onin);
+ mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_LDO_PWRDWNB);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+
+ mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_okin);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+
+ mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_PLL_PWRDWNB);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+
+ mmio_clrbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+ mmio_clrbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
+ /* Delay as per external FSM spec */
+ udelay(1U);
+
+ mmio_setbits_32(u2_phy->pll_ctrl_reg, USB2_PLL_RESETB);
+ mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_RESETB);
+
+}
+
+static int32_t usb3h_u2_phy_power_on(uint32_t base)
+{
+ int32_t status;
+ struct u2_phy_ext_fsm u2_phy;
+
+ u2_phy.pll_ctrl_reg = base + USB3H_U2PLL_CTRL;
+ u2_phy.phy_ctrl_reg = base + USB3H_U2PHY_CTRL;
+ u2_phy.phy_iddq = USB3H_U2PHY_IDDQ;
+ u2_phy.pwr_ctrl_reg = base + USB3H_PWR_CTRL;
+ u2_phy.pwr_okin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN;
+ u2_phy.pwr_onin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN;
+
+ u2_phy_ext_fsm_power_on(&u2_phy);
+
+ status = pll_lock_check(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_LOCK);
+ if (status != 0) {
+ /* re-try by toggling the PLL reset */
+ mmio_clrbits_32(base + USB3H_U2PLL_CTRL,
+ (uint32_t)USB3H_U2PLL_RESETB);
+ mmio_setbits_32(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_RESETB);
+ status = pll_lock_check(base + USB3H_U2PLL_CTRL,
+ USB3H_U2PLL_LOCK);
+ if (status != 0)
+ ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
+ base + USB3H_U2PLL_CTRL);
+ }
+
+ mmio_clrsetbits_32(base + USB3H_U2PHY_CTRL,
+ (USB3H_U2PHY_PCTL_MASK << USB3H_U2PHY_PCTL_OFFSET),
+ (U2PHY_PCTL_NON_DRV_LOW << USB3H_U2PHY_PCTL_OFFSET));
+ return status;
+}
+
+static int32_t usb3h_u3_phy_power_on(uint32_t base)
+{
+ int32_t status;
+
+ /* Set pctl with mode and soft reset */
+ mmio_clrsetbits_32(base + USB3H_U3PHY_CTRL,
+ (USB3H_U3PHY_PCTL_MASK << USB3H_U3PHY_PCTL_OFFSET),
+ (U3PHY_PCTL_VAL << USB3H_U3PHY_PCTL_OFFSET));
+
+ mmio_clrbits_32(base + USB3H_U3PHY_PLL_CTRL,
+ (uint32_t) USB3H_U3SSPLL_SUSPEND_EN);
+ mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_SEQ_START);
+ mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_RESETB);
+
+ /* Time to stabilize the PLL Control */
+ mdelay(1U);
+
+ status = pll_lock_check(base + USB3H_U3PHY_PLL_CTRL,
+ USB3H_U3PLL_SS_LOCK);
+
+ return status;
+}
+
+static int32_t drdu3_u2_phy_power_on(uint32_t base)
+{
+ int32_t status;
+ struct u2_phy_ext_fsm u2_phy;
+
+ u2_phy.pll_ctrl_reg = base + DRDU3_U2PLL_CTRL;
+ u2_phy.phy_ctrl_reg = base + DRDU3_U2PHY_CTRL;
+ u2_phy.phy_iddq = DRDU3_U2PHY_IDDQ;
+ u2_phy.pwr_ctrl_reg = base + DRDU3_PWR_CTRL;
+ u2_phy.pwr_okin = DRDU3_U2PHY_DFE_SWITCH_PWROKIN;
+ u2_phy.pwr_onin = DRDU3_U2PHY_DFE_SWITCH_PWRONIN;
+
+ u2_phy_ext_fsm_power_on(&u2_phy);
+
+ status = pll_lock_check(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_LOCK);
+ if (status != 0) {
+ /* re-try by toggling the PLL reset */
+ mmio_clrbits_32(base + DRDU3_U2PLL_CTRL,
+ (uint32_t)DRDU2_U2PLL_RESETB);
+ mmio_setbits_32(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_RESETB);
+
+ status = pll_lock_check(base + DRDU3_U2PLL_CTRL,
+ DRDU3_U2PLL_LOCK);
+ if (status != 0) {
+ ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
+ base + DRDU3_U2PLL_CTRL);
+ }
+ }
+ mmio_clrsetbits_32(base + DRDU3_U2PHY_CTRL,
+ (DRDU3_U2PHY_PCTL_MASK << DRDU3_U2PHY_PCTL_OFFSET),
+ (U2PHY_PCTL_NON_DRV_LOW << DRDU3_U2PHY_PCTL_OFFSET));
+
+ return status;
+}
+
+static int32_t drdu3_u3_phy_power_on(uint32_t base)
+{
+ int32_t status;
+
+ /* Set pctl with mode and soft reset */
+ mmio_clrsetbits_32(base + DRDU3_U3PHY_CTRL,
+ (DRDU3_U3PHY_PCTL_MASK << DRDU3_U3PHY_PCTL_OFFSET),
+ (U3PHY_PCTL_VAL << DRDU3_U3PHY_PCTL_OFFSET));
+
+ mmio_clrbits_32(base + DRDU3_U3PHY_PLL_CTRL,
+ (uint32_t) DRDU3_U3SSPLL_SUSPEND_EN);
+ mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_SEQ_START);
+ mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_RESETB);
+
+ /* Time to stabilize the PLL Control */
+ mdelay(1U);
+
+ status = pll_lock_check(base + DRDU3_U3PHY_PLL_CTRL,
+ DRDU3_U3PLL_SS_LOCK);
+
+ return status;
+}
+
+static int32_t drdu2_u2_phy_power_on(uint32_t base)
+{
+ int32_t status;
+ struct u2_phy_ext_fsm u2_phy;
+
+ u2_phy.pll_ctrl_reg = base + DRDU2_U2PLL_CTRL;
+ u2_phy.phy_ctrl_reg = base + DRDU2_PHY_CTRL;
+ u2_phy.phy_iddq = DRDU2_U2IDDQ;
+ u2_phy.pwr_ctrl_reg = base + DRDU2_PWR_CTRL;
+ u2_phy.pwr_okin = DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I;
+ u2_phy.pwr_onin = DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I;
+
+ u2_phy_ext_fsm_power_on(&u2_phy);
+
+ status = pll_lock_check(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_LOCK);
+ if (status != 0) {
+ /* re-try by toggling the PLL reset */
+ mmio_clrbits_32(base + DRDU2_U2PLL_CTRL,
+ (uint32_t)DRDU2_U2PLL_RESETB);
+ mmio_setbits_32(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_RESETB);
+
+ status = pll_lock_check(base + DRDU2_U2PLL_CTRL,
+ DRDU2_U2PLL_LOCK);
+ if (status != 0)
+ ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
+ base + DRDU2_U2PLL_CTRL);
+ }
+ mmio_clrsetbits_32(base + DRDU2_PHY_CTRL,
+ (DRDU2_U2PHY_PCTL_MASK << DRDU2_U2PHY_PCTL_OFFSET),
+ (U2PHY_PCTL_NON_DRV_LOW << DRDU2_U2PHY_PCTL_OFFSET));
+
+ return status;
+}
+
+void u3h_u2drd_phy_reset(usb_phy_port_t *phy_port)
+{
+ usb_phy_t *phy = phy_port->p;
+
+ switch (phy_port->port_id) {
+ case USB3HS_PORT:
+ mmio_clrbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
+ (uint32_t) USB3H_U2CTRL_CORERDY);
+ mmio_setbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
+ USB3H_U2CTRL_CORERDY);
+ break;
+ case DRDU2_PORT:
+ mmio_clrbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
+ (uint32_t) DRDU2_U2CTRL_CORERDY);
+ mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
+ DRDU2_U2CTRL_CORERDY);
+ break;
+ }
+}
+
+void u3drd_phy_reset(usb_phy_port_t *phy_port)
+{
+ usb_phy_t *phy = phy_port->p;
+
+ if (phy_port->port_id == DRD3HS_PORT) {
+ mmio_clrbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
+ (uint32_t) DRDU3_U2CTRL_CORERDY);
+ mmio_setbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
+ DRDU3_U2CTRL_CORERDY);
+ }
+}
+
+static int32_t u3h_u2drd_phy_power_on(usb_phy_port_t *phy_port)
+{
+ usb_phy_t *phy = phy_port->p;
+ int32_t status;
+
+ switch (phy_port->port_id) {
+ case USB3SS_PORT:
+ mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+ (uint32_t) USB3H_DISABLE_USB30_P0);
+ status = usb3h_u3_phy_power_on(phy->usb3hreg);
+ if (status != 0) {
+ goto err_usb3h_phy_on;
+ }
+ break;
+ case USB3HS_PORT:
+ mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+ (uint32_t) USB3H_DISABLE_EUSB_P1);
+ mmio_setbits_32(AXI_DEBUG_CTRL,
+ AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+ mmio_setbits_32(USB3H_DEBUG_CTRL,
+ USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+
+ mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
+ USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+ mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
+ USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN);
+ status = usb3h_u2_phy_power_on(phy->usb3hreg);
+ if (status != 0) {
+ goto err_usb3h_phy_on;
+ }
+ break;
+ case DRDU2_PORT:
+ mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+ (uint32_t) USB3H_DISABLE_EUSB_P0);
+ mmio_setbits_32(AXI_DEBUG_CTRL,
+ AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+ mmio_setbits_32(USB3H_DEBUG_CTRL,
+ USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+
+ mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
+ DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+ mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
+ DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I);
+
+ status = drdu2_u2_phy_power_on(phy->drdu2reg);
+ if (status != 0) {
+ mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+ USB3H_DISABLE_EUSB_P0);
+ goto err_drdu2_phy_on;
+ }
+ break;
+ }
+
+ /* Device Mode */
+ if (phy_port->port_id == DRDU2_PORT) {
+ mmio_write_32(phy->drdu2reg + DRDU2_SOFT_RESET_CTRL,
+ DRDU2_BDC_AXI_SOFT_RST_N);
+ mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
+ DRDU2_U2SOFT_RST_N);
+ }
+ /* Host Mode */
+ mmio_write_32(phy->usb3hreg + USB3H_SOFT_RESET_CTRL,
+ USB3H_XHC_AXI_SOFT_RST_N);
+ mmio_setbits_32(phy->usb3hreg + USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
+
+ return 0U;
+ err_usb3h_phy_on:mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
+ (USB3H_DISABLE_EUSB_P1 |
+ USB3H_DISABLE_USB30_P0));
+ err_drdu2_phy_on:
+
+ return status;
+}
+
+static int32_t u3drd_phy_power_on(usb_phy_port_t *phy_port)
+{
+ usb_phy_t *phy = phy_port->p;
+ int32_t status;
+
+ switch (phy_port->port_id) {
+ case DRD3SS_PORT:
+ mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
+ (uint32_t) DRDU3_DISABLE_USB30_P0);
+
+ status = drdu3_u3_phy_power_on(phy->drdu3reg);
+ if (status != 0) {
+ goto err_drdu3_phy_on;
+ }
+ break;
+ case DRD3HS_PORT:
+ mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
+ (uint32_t) DRDU3_DISABLE_EUSB_P0);
+ mmio_setbits_32(AXI_DEBUG_CTRL,
+ AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+ mmio_setbits_32(USB3H_DEBUG_CTRL,
+ USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
+
+ mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
+ DRDU3_U2PHY_DFE_SWITCH_PWRONIN);
+ /* Delay as per external FSM spec */
+ udelay(10U);
+ mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
+ DRDU3_U2PHY_DFE_SWITCH_PWROKIN);
+
+ status = drdu3_u2_phy_power_on(phy->drdu3reg);
+ if (status != 0) {
+ goto err_drdu3_phy_on;
+ }
+
+ /* Host Mode */
+ mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
+ DRDU3_XHC_AXI_SOFT_RST_N);
+ mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
+ DRDU3_U3XHC_SOFT_RST_N);
+ /* Device Mode */
+ mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
+ DRDU3_BDC_AXI_SOFT_RST_N);
+ mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
+ DRDU3_U3BDC_SOFT_RST_N);
+ break;
+ }
+
+ return 0U;
+ err_drdu3_phy_on:mmio_setbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
+ (DRDU3_DISABLE_EUSB_P0 |
+ DRDU3_DISABLE_USB30_P0));
+
+ return status;
+}
+
+static void u3h_u2drd_phy_power_off(usb_phy_port_t *phy_port)
+{
+ usb_phy_t *p = phy_port->p;
+
+ switch (phy_port->port_id) {
+ case USB3SS_PORT:
+ mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
+ USB3H_DISABLE_USB30_P0);
+ break;
+ case USB3HS_PORT:
+ mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
+ USB3H_DISABLE_EUSB_P1);
+ break;
+ case DRDU2_PORT:
+ mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
+ USB3H_DISABLE_EUSB_P0);
+ break;
+ }
+}
+
+static void u3drd_phy_power_off(usb_phy_port_t *phy_port)
+{
+ usb_phy_t *p = phy_port->p;
+
+ switch (phy_port->port_id) {
+ case DRD3SS_PORT:
+ mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
+ DRDU3_DISABLE_USB30_P0);
+ break;
+ case DRD3HS_PORT:
+ mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
+ DRDU3_DISABLE_EUSB_P0);
+ break;
+ }
+}
+
+int32_t usb_info_fill(usb_phy_t *phy_info)
+{
+ int32_t index;
+
+ if (phy_info->initialized != 0U) {
+ return USB_PHY_ALREADY_STARTED;
+ }
+
+ if (phy_info->phy_id == USB3H_DRDU2_PHY) {
+ phy_info->phy_port = usb_phy_port[USB3H_DRDU2_PHY - 1U];
+ phy_info->ports_enabled = 0x7U;
+ } else {
+ phy_info->phy_port = usb_phy_port[DRDU3_PHY - 1U];
+ phy_info->ports_enabled = 0x3U;
+ }
+
+ for (index = MAX_NR_PORTS - 1U; index > -1; index--) {
+ phy_info->phy_port[index].enabled = (phy_info->ports_enabled
+ >> index) & 0x1U;
+ phy_info->phy_port[index].p = phy_info;
+ phy_info->phy_port[index].port_id = index;
+ }
+
+ return 0U;
+}
+
+int32_t usb_phy_init(usb_platform_dev *device)
+{
+ int32_t status;
+ usb_phy_t *phy_info;
+ uint32_t index;
+
+ phy_info = (usb_phy_t *)device->pcd_id;
+
+ status = usb_info_fill(phy_info);
+ if (status != 0) {
+ return (status == USB_PHY_ALREADY_STARTED) ? 0 : status;
+ }
+
+ for (index = 0U; index < MAX_NR_PORTS; index++) {
+ if (phy_info->phy_port[index].enabled != 0U) {
+ switch (phy_info->phy_id) {
+ case USB3H_DRDU2_PHY:
+ status =
+ u3h_u2drd_phy_power_on(&phy_info->
+ phy_port[index]);
+ break;
+ default:
+ status =
+ u3drd_phy_power_on(&phy_info->
+ phy_port[index]);
+ }
+ }
+ }
+
+ phy_info->initialized = !status;
+ return status;
+}
+
+void usb_phy_shutdown(usb_platform_dev *device)
+{
+ usb_phy_t *phy_info;
+ uint32_t index;
+
+ phy_info = (usb_phy_t *)device->pcd_id;
+
+ phy_info->initialized = 0U;
+
+ for (index = 0U; index < MAX_NR_PORTS; index++) {
+ if (phy_info->phy_port[index].enabled != 0U) {
+ switch (phy_info->phy_id) {
+ case USB3H_DRDU2_PHY:
+ u3h_u2drd_phy_power_off(&phy_info->
+ phy_port[index]);
+ break;
+ case DRDU3_PHY:
+ u3drd_phy_power_off(&phy_info->phy_port[index]);
+ break;
+ default:
+ INFO("%s: invalid phy id 0x%x\n", __func__,
+ phy_info->phy_id);
+ }
+ }
+ }
+}
+
+int32_t usb_xhci_init(usb_platform_dev *device)
+{
+ int32_t status;
+
+ status = usb_phy_init(device);
+ if (status == USB_PHY_ALREADY_STARTED) {
+ status = 0U;
+ }
+
+ return status;
+}
+
+int32_t usb_device_init(unsigned int usb_func)
+{
+ int32_t status;
+ int32_t devices_initialized = 0U;
+
+ if ((usb_func & USB3H_USB2DRD) != 0U) {
+ status = usb_xhci_init(
+ &xhci_devices_configs[USB3H_USB2DRD_PHY]);
+ if (status == 0) {
+ devices_initialized++;
+ } else {
+ ERROR("%s(): USB3H_USB2DRD init failure\n", __func__);
+ }
+ }
+
+ if ((usb_func & USB3_DRD) != 0U) {
+ status = usb_xhci_init(&xhci_devices_configs[USB3_DRD_PHY]);
+ if (status == 0) {
+ devices_initialized++;
+ } else {
+ ERROR("%s(): USB3_DRD init failure\n", __func__);
+ }
+ }
+
+ return devices_initialized;
+}
diff --git a/plat/brcm/board/stingray/include/bl33_info.h b/plat/brcm/board/stingray/include/bl33_info.h
new file mode 100644
index 0000000..1dac48c
--- /dev/null
+++ b/plat/brcm/board/stingray/include/bl33_info.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL33_INFO_H
+#define BL33_INFO_H
+
+/* Increase version number each time this file is modified */
+#define BL33_INFO_VERSION 4
+
+struct chip_info {
+ unsigned int chip_id;
+ unsigned int rev_id;
+};
+
+struct boot_time_info {
+ unsigned int bl1_start;
+ unsigned int bl1_end;
+ unsigned int bl2_start;
+ unsigned int bl2_end;
+ unsigned int bl31_start;
+ unsigned int bl31_end;
+ unsigned int bl32_start;
+ unsigned int bl32_end;
+ unsigned int bl33_start;
+ unsigned int bl33_prompt;
+ unsigned int bl33_end;
+};
+
+struct bl33_info {
+ unsigned int version;
+ struct chip_info chip;
+ struct boot_time_info boot_time_info;
+};
+
+#endif
diff --git a/plat/brcm/board/stingray/include/board_info.h b/plat/brcm/board/stingray/include/board_info.h
new file mode 100644
index 0000000..8901259
--- /dev/null
+++ b/plat/brcm/board/stingray/include/board_info.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_INFO_H
+#define BOARD_INFO_H
+
+#define IHOST_REG_INTEGRATED 0
+#define IHOST_REG_EXT_PROGRAMMABLE 1
+#define IHOST_REG_EXT_FIXED 2
+
+#if defined(IHOST_REG_TYPE)
+ #if ((IHOST_REG_TYPE != IHOST_REG_INTEGRATED) && \
+ (IHOST_REG_TYPE != IHOST_REG_EXT_PROGRAMMABLE) && \
+ (IHOST_REG_TYPE != IHOST_REG_EXT_FIXED))
+ #error "IHOST_REG_TYPE not valid"
+ #endif
+#else
+ #define IHOST_REG_TYPE IHOST_REG_INTEGRATED
+#endif
+
+#define VDDC_REG_INTEGRATED 0
+#define VDDC_REG_EXT_PROGRAMMABLE 1
+#define VDDC_REG_EXT_FIXED 2
+
+#if defined(VDDC_REG_TYPE)
+ #if ((VDDC_REG_TYPE != VDDC_REG_INTEGRATED) && \
+ (VDDC_REG_TYPE != VDDC_REG_EXT_PROGRAMMABLE) && \
+ (VDDC_REG_TYPE != VDDC_REG_EXT_FIXED))
+ #error "VDDC_REG_TYPE not valid"
+ #endif
+#else
+ #define VDDC_REG_TYPE VDDC_REG_INTEGRATED
+#endif
+
+#endif
diff --git a/plat/brcm/board/stingray/include/crmu_def.h b/plat/brcm/board/stingray/include/crmu_def.h
new file mode 100644
index 0000000..ebc2bb6
--- /dev/null
+++ b/plat/brcm/board/stingray/include/crmu_def.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CRMU_DEF_H
+#define CRMU_DEF_H
+
+#define CRMU_REGS_BASE 0x66410000
+/* 32 kB IDRAM */
+#define CRMU_IDRAM_BASE_ADDR CRMU_REGS_BASE
+#define CRMU_IDRAM_SIZE 0x8000
+/* 4 kB Scratch RAM */
+#define CRMU_SRAM_BASE (CRMU_IDRAM_BASE_ADDR + CRMU_IDRAM_SIZE)
+#define CRMU_SRAM_SIZE 0x1000
+
+#define CRMU_RESERVED_SPACE 0x3000
+#define CRMU_CORE_BASE (CRMU_SRAM_BASE + CRMU_SRAM_SIZE + \
+ CRMU_RESERVED_SPACE)
+
+#define CRMU_SHARED_SRAM_BASE CRMU_SRAM_BASE
+#define CRMU_SHARED_SRAM_SIZE 0x200
+#define CRMU_CFG_BASE (CRMU_SHARED_SRAM_BASE + \
+ CRMU_SHARED_SRAM_SIZE)
+
+#define CRMU_PWR_GOOD_STATUS CRMU_CORE_BASE
+#define CRMU_PWR_GOOD_STATUS__BBL_POWER_GOOD 0
+#define CRMU_ISO_CELL_CONTROL (CRMU_CORE_BASE + 0x4)
+#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL 16
+#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL_TAMPER 24
+#define CRMU_SPRU_SOURCE_SEL_STAT (CRMU_CORE_BASE + 0xc)
+#define CRMU_SPRU_SOURCE_SEL_STAT__SPRU_SOURCE_SELECT 0
+#define BSTI_BASE (CRMU_CORE_BASE + 0x28)
+#define BSTI_CONTROL_OFFSET BSTI_BASE
+#define BSTI_COMMAND_OFFSET (BSTI_BASE + 0x4)
+
+#define OCOTP_REGS_BASE (CRMU_CORE_BASE + 0x400)
+
+#define CRMU_TCI_BASE (CRMU_CORE_BASE + 0x800)
+#define CRMU_SWREG_STATUS_ADDR (CRMU_TCI_BASE + 0x0c)
+#define CRMU_CHIP_OTPC_STATUS (CRMU_TCI_BASE + 0x10)
+#define CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE 19
+#define CRMU_BISR_PDG_MASK (CRMU_TCI_BASE + 0x4c)
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST0 2
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1 3
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2 4
+#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3 0
+#define CRMU_POWER_POLL (CRMU_TCI_BASE + 0x60)
+#define CRMU_OTP_STATUS CRMU_POWER_POLL
+#define CRMU_OTP_STATUS_BIT 1
+#define CRMU_DDR_PHY_AON_CTRL (CRMU_TCI_BASE + 0x64)
+#define CRMU_DDRPHY2_HW_RESETN_R BIT(21)
+#define CRMU_DDRPHY2_PWROKIN_PHY_R BIT(20)
+#define CRMU_DDRPHY2_PWRONIN_PHY_R BIT(19)
+#define CRMU_DDRPHY2_ISO_PHY_DFI_R BIT(18)
+#define CRMU_DDRPHY2_ISO_PHY_REGS_R BIT(17)
+#define CRMU_DDRPHY2_ISO_PHY_PLL_R BIT(16)
+#define CRMU_DDRPHY1_HW_RESETN_R BIT(13)
+#define CRMU_DDRPHY1_PWROKIN_PHY_R BIT(12)
+#define CRMU_DDRPHY1_PWRONIN_PHY_R BIT(11)
+#define CRMU_DDRPHY1_ISO_PHY_DFI_R BIT(10)
+#define CRMU_DDRPHY1_ISO_PHY_REGS_R BIT(9)
+#define CRMU_DDRPHY1_ISO_PHY_PLL_R BIT(8)
+#define CRMU_DDRPHY0_HW_RESETN_R BIT(5)
+#define CRMU_DDRPHY0_PWROKIN_PHY_R BIT(4)
+#define CRMU_DDRPHY0_PWRONIN_PHY_R BIT(3)
+#define CRMU_DDRPHY0_ISO_PHY_DFI_R BIT(2)
+#define CRMU_DDRPHY0_ISO_PHY_REGS_R BIT(1)
+#define CRMU_DDRPHY0_ISO_PHY_PLL_R BIT(0)
+#define CRMU_EMEM_RESET_N_R BIT(16)
+#define CRMU_EMEM_PRESET_N_R BIT(0)
+#define CRMU_SWREG_CTRL_ADDR (CRMU_TCI_BASE + 0x6c)
+#define CRMU_AON_CTRL1 (CRMU_TCI_BASE + 0x70)
+#define CRMU_AON_CTRL1__LCPLL1_ISO_IN 18
+#define CRMU_AON_CTRL1__LCPLL1_PWRON_LDO 19
+#define CRMU_AON_CTRL1__LCPLL1_PWR_ON 20
+#define CRMU_AON_CTRL1__LCPLL0_ISO_IN 21
+#define CRMU_AON_CTRL1__LCPLL0_PWRON_LDO 22
+#define CRMU_AON_CTRL1__LCPLL0_PWR_ON 23
+#define CRMU_PCIE_LCPLL_PWR_ON_SHIFT 29
+#define CRMU_PCIE_LCPLL_PWR_ON_MASK BIT(CRMU_PCIE_LCPLL_PWR_ON_SHIFT)
+#define CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT 28
+#define CRMU_PCIE_LCPLL_PWRON_LDO_MASK BIT(CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT)
+#define CRMU_PCIE_LCPLL_ISO_IN_SHIFT 27
+#define CRMU_PCIE_LCPLL_ISO_IN_MASK BIT(CRMU_PCIE_LCPLL_ISO_IN_SHIFT)
+#define CRMU_MASTER_AXI_ARUSER_CONFIG (CRMU_TCI_BASE + 0x74)
+#define CRMU_MASTER_AXI_AWUSER_CONFIG (CRMU_TCI_BASE + 0x78)
+#define CRMU_DDR_PHY_AON_CTRL_1 (CRMU_TCI_BASE + 0x8c)
+
+#define CDRU_BASE_ADDR (CRMU_CORE_BASE + 0x1000)
+#define CDRU_MISC_RESET_CONTROL CDRU_BASE_ADDR
+#define CDRU_MISC_RESET_CONTROL_TS_RESET_N 16
+#define CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N 14
+#define CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R 15
+#define CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R 13
+#define CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R 3
+#define CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R 2
+#define CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R 1
+
+#define CDRU_PROC_EVENT_CLEAR (CDRU_BASE_ADDR + 0x48)
+#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2 0
+#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI 3
+#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2 5
+#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI 8
+#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2 10
+#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI 13
+#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2 15
+#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI 18
+
+#define CDRU_CHIP_STRAP_CTRL (CDRU_BASE_ADDR + 0x50)
+#define CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE 31
+
+#define CDRU_CHIP_IO_PAD_CONTROL (CDRU_BASE_ADDR + 0x58)
+#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PDN_R 8
+#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R 0
+
+#define CDRU_CHIP_STRAP_DATA_LSW (CDRU_BASE_ADDR + 0x5c)
+#define CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE 18
+#define CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK BIT(8)
+#define CDRU_CHIP_STRAP_DATA_LSW_PAD_USB_MODE BIT(26)
+
+#define CDRU_CHIP_STRAP_DATA (CDRU_BASE_ADDR + 0x5c)
+#define CDRU_DDR0_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xb8)
+#define CDRU_DDR1_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xbc)
+#define CDRU_DDR2_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xc0)
+#define CRMU_SW_POR_RESET_CTRL (CDRU_BASE_ADDR + 0x100)
+
+#define CDRU_GENPLL2_CONTROL1 (CDRU_BASE_ADDR + 0x1b0)
+#define CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK BIT(11)
+#define CDRU_GENPLL5_CONTROL1 (CDRU_BASE_ADDR + 0x24c)
+#define CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK BIT(6)
+#define CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK BIT(7)
+#define CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK BIT(8)
+
+#define CDRU_NITRO_CONTROL (CDRU_BASE_ADDR + 0x2c4)
+#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R 20
+#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R 16
+
+#define CDRU_MISC_CLK_ENABLE_CONTROL (CDRU_BASE_ADDR + 0x2c8)
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM2_CLK_EN_R 11
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM1_CLK_EN_R 10
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM0_CLK_EN_R 9
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R 8
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R 7
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_MHB_CLK_EN_R 6
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_HSLS_CLK_EN_R 5
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SCR_CLK_EN_R 4
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_FS4_CLK_EN_R 3
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PCIE_CLK_EN_R 2
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PM_CLK_EN_R 1
+#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_NITRO_CLK_EN_R 0
+
+#define CDRU_CCN_REGISTER_CONTROL_1 (CDRU_BASE_ADDR + 0x324)
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM0_BIT 6
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM1_BIT 5
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM2_BIT 4
+
+#define CDRU_CHIP_TOP_SPARE_REG0 (CDRU_BASE_ADDR + 0x378)
+#define CDRU_CHIP_TOP_SPARE_REG1 (CDRU_BASE_ADDR + 0x37c)
+
+#define CENTRAL_TIMER_BASE (CRMU_CORE_BASE + 0x5000)
+#define CENTRAL_TIMER_CTRL (CENTRAL_TIMER_BASE + 0x0)
+#define CENTRAL_TIMER_GET_L (CENTRAL_TIMER_BASE + 0x4)
+#define CENTRAL_TIMER_GET_L0 (CENTRAL_TIMER_BASE + 0x8) /* SCR STM */
+#define CENTRAL_TIMER_GET_L1 (CENTRAL_TIMER_BASE + 0xC) /* FS STM */
+#define CENTRAL_TIMER_GET_L2 (CENTRAL_TIMER_BASE + 0x10) /* iHost0 */
+#define CENTRAL_TIMER_GET_L3 (CENTRAL_TIMER_BASE + 0x14) /* iHost1 */
+#define CENTRAL_TIMER_GET_L4 (CENTRAL_TIMER_BASE + 0x18) /* iHost2 */
+#define CENTRAL_TIMER_GET_L5 (CENTRAL_TIMER_BASE + 0x1C) /* iHost3 */
+#define CENTRAL_TIMER_GET_H (CENTRAL_TIMER_BASE + 0x28)
+#define CENTRAL_TIMER_SAT_TMR_ENA (CENTRAL_TIMER_BASE + 0x34)
+#define CENTRAL_TIMER_GET_IHOST_ENA_BASE (CENTRAL_TIMER_GET_L2)
+
+#define CRMU_WDT_REGS_BASE (CRMU_CORE_BASE + 0x6000)
+
+#define CRMU_MAIL_BOX0 (CRMU_CORE_BASE + 0x8024)
+#define CRMU_MAIL_BOX1 (CRMU_CORE_BASE + 0x8028)
+#define CRMU_READ_MAIL_BOX0 (CRMU_CORE_BASE + 0x802c)
+#define CRMU_READ_MAIL_BOX1 (CRMU_CORE_BASE + 0x8030)
+#define AP_TO_SCP_MAILBOX1 CRMU_MAIL_BOX1
+#define SCP_TO_AP_MAILBOX1 CRMU_READ_MAIL_BOX1
+#define CRMU_IHOST_POWER_CONFIG (CRMU_CORE_BASE + 0x8038)
+#define CRMU_RESET_EVENT_LOG (CRMU_CORE_BASE + 0x8064)
+#define CRMU_SOFT_RESET_CTRL (CRMU_CORE_BASE + 0x8090)
+#define CRMU_SOFT_RESET_CTRL__SOFT_PWR_UP_RST 0
+#define CRMU_SOFT_RESET_CTRL__SOFT_SYS_RST 1
+#define CRMU_SPARE_REG_0 (CRMU_CORE_BASE + 0x80b8)
+#define CRMU_SPARE_REG_1 (CRMU_CORE_BASE + 0x80bc)
+#define CRMU_SPARE_REG_2 (CRMU_CORE_BASE + 0x80c0)
+#define CRMU_SPARE_REG_3 (CRMU_CORE_BASE + 0x80c4)
+#define CRMU_SPARE_REG_4 (CRMU_CORE_BASE + 0x80c8)
+#define CRMU_SPARE_REG_5 (CRMU_CORE_BASE + 0x80cc)
+#define CRMU_CORE_ADDR_RANGE0_LOW (CRMU_CORE_BASE + 0x8c30)
+#define CRMU_CORE_ADDR_RANGE1_LOW (CRMU_CORE_BASE + 0x8c38)
+#define CRMU_CORE_ADDR_RANGE2_LOW (CRMU_CORE_BASE + 0x8c40)
+#define CRMU_IHOST_SW_PERSISTENT_REG0 (CRMU_CORE_BASE + 0x8c54)
+#define CRMU_IHOST_SW_PERSISTENT_REG1 (CRMU_CORE_BASE + 0x8c58)
+#define CRMU_IHOST_SW_PERSISTENT_REG2 (CRMU_CORE_BASE + 0x8c5c)
+#define CRMU_IHOST_SW_PERSISTENT_REG3 (CRMU_CORE_BASE + 0x8c60)
+#define CRMU_IHOST_SW_PERSISTENT_REG4 (CRMU_CORE_BASE + 0x8c64)
+#define CRMU_IHOST_SW_PERSISTENT_REG5 (CRMU_CORE_BASE + 0x8c68)
+#define CRMU_IHOST_SW_PERSISTENT_REG6 (CRMU_CORE_BASE + 0x8c6c)
+#define CRMU_IHOST_SW_PERSISTENT_REG7 (CRMU_CORE_BASE + 0x8c70)
+#define CRMU_BBL_AUTH_CHECK (CRMU_CORE_BASE + 0x8c78)
+#define CRMU_SOTP_NEUTRALIZE_ENABLE (CRMU_CORE_BASE + 0x8c84)
+#define CRMU_IHOST_SW_PERSISTENT_REG8 (CRMU_CORE_BASE + 0x8c88)
+#define CRMU_IHOST_SW_PERSISTENT_REG9 (CRMU_CORE_BASE + 0x8c8c)
+#define CRMU_IHOST_SW_PERSISTENT_REG10 (CRMU_CORE_BASE + 0x8c90)
+#define CRMU_IHOST_SW_PERSISTENT_REG11 (CRMU_CORE_BASE + 0x8c94)
+
+#define CNT_CONTROL_BASE (CRMU_CORE_BASE + 0x9000)
+#define CNTCR (CNT_CONTROL_BASE)
+#define CNTCR__EN BIT(0)
+
+#define SPRU_BBL_WDATA (CRMU_CORE_BASE + 0xa000)
+#define SPRU_BBL_CMD (CRMU_CORE_BASE + 0xa004)
+#define SPRU_BBL_CMD__IND_SOFT_RST_N 10
+#define SPRU_BBL_CMD__IND_WR 11
+#define SPRU_BBL_CMD__BBL_ADDR_R 0
+#define SPRU_BBL_CMD__IND_RD 12
+#define SPRU_BBL_CMD__BBL_ADDR_R 0
+#define SPRU_BBL_STATUS (CRMU_CORE_BASE + 0xa008)
+#define SPRU_BBL_STATUS__ACC_DONE 0
+#define SPRU_BBL_RDATA (CRMU_CORE_BASE + 0xa00c)
+
+#endif /* CRMU_DEF_H */
diff --git a/plat/brcm/board/stingray/include/ddr_init.h b/plat/brcm/board/stingray/include/ddr_init.h
new file mode 100644
index 0000000..0c135b1
--- /dev/null
+++ b/plat/brcm/board/stingray/include/ddr_init.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DDR_INIT_H
+#define DDR_INIT_H
+
+#include <fru.h>
+
+#pragma weak ddr_initialize
+#pragma weak ddr_secure_region_config
+#pragma weak ddr_info_save
+#pragma weak get_active_ddr_channel
+#pragma weak is_warmboot
+
+void ddr_initialize(struct ddr_info *ddr)
+{
+}
+
+void ddr_secure_region_config(uint64_t start, uint64_t end)
+{
+}
+
+void ddr_info_save(void)
+{
+}
+
+unsigned char get_active_ddr_channel(void)
+{
+ return 0;
+}
+
+static inline unsigned int is_warmboot(void)
+{
+ return 0;
+}
+#endif
diff --git a/plat/brcm/board/stingray/include/fsx.h b/plat/brcm/board/stingray/include/fsx.h
new file mode 100644
index 0000000..c52ff0a
--- /dev/null
+++ b/plat/brcm/board/stingray/include/fsx.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FSX_H
+#define FSX_H
+
+#include <stdbool.h>
+
+typedef enum FSX_TYPE {
+ eFS4_RAID,
+ eFS4_CRYPTO,
+ eFS6_PKI,
+} eFSX_TYPE;
+
+void fsx_init(eFSX_TYPE fsx_type,
+ unsigned int ring_count,
+ unsigned int dme_count,
+ unsigned int ae_count,
+ unsigned int start_stream_id,
+ unsigned int msi_dev_id,
+ uintptr_t idm_io_control_direct,
+ uintptr_t idm_reset_control,
+ uintptr_t base,
+ uintptr_t dme_base);
+
+void fsx_meminit(const char *name,
+ uintptr_t idm_io_control_direct,
+ uintptr_t idm_io_status);
+
+void fs4_disable_clocks(bool disable_sram,
+ bool disable_crypto,
+ bool disable_raid);
+
+#endif /* FSX_H */
diff --git a/plat/brcm/board/stingray/include/ihost_pm.h b/plat/brcm/board/stingray/include/ihost_pm.h
new file mode 100644
index 0000000..83493ab
--- /dev/null
+++ b/plat/brcm/board/stingray/include/ihost_pm.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IHOST_PM
+#define IHOST_PM
+
+#include <stdint.h>
+
+#define CLUSTER_POWER_ON 0x1
+#define CLUSTER_POWER_OFF 0x0
+
+void ihost_power_on_cluster(u_register_t mpidr);
+void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar);
+void ihost_enable_satellite_timer(unsigned int cluster_id);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/iommu.h b/plat/brcm/board/stingray/include/iommu.h
new file mode 100644
index 0000000..e7b2985
--- /dev/null
+++ b/plat/brcm/board/stingray/include/iommu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IOMMU_H
+#define IOMMU_H
+
+enum iommu_domain {
+ PCIE_PAXC,
+ DOMAIN_CRMU,
+};
+
+void arm_smmu_create_identity_map(enum iommu_domain dom);
+void arm_smmu_reserve_secure_cntxt(void);
+void arm_smmu_enable_secure_client_port(void);
+
+#endif /* IOMMU_H */
diff --git a/plat/brcm/board/stingray/include/ncsi.h b/plat/brcm/board/stingray/include/ncsi.h
new file mode 100644
index 0000000..04dd640
--- /dev/null
+++ b/plat/brcm/board/stingray/include/ncsi.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NCSI_H
+#define NCSI_H
+
+/*
+ * There are 10 registers for NCSI IO drivers.
+ */
+#define NITRO_NCSI_IOPAD_CONTROL_NUM 10
+#define NITRO_NCSI_IOPAD_CONTROL_BASE 0x60e05080
+
+/*
+ * NCSI IO Drive strength
+ * 000 - Drives 2mA
+ * 001 - Drives 4mA
+ * 010 - Drives 6mA
+ * 011 - Drives 8mA
+ * 100 - Drives 10mA
+ * 101 - Drives 12mA
+ * 110 - Drives 14mA
+ * 111 - Drives 16mA
+ */
+#define PAD_SELX_VALUE(selx) ((selx) << 1)
+#define PAD_SELX_MASK (0x7 << 1)
+
+void brcm_stingray_ncsi_init(void);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/paxb.h b/plat/brcm/board/stingray/include/paxb.h
new file mode 100644
index 0000000..c64c8a6
--- /dev/null
+++ b/plat/brcm/board/stingray/include/paxb.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PAXB_H
+#define PAXB_H
+
+/* total number of PCIe cores */
+#define NUM_OF_SR_PCIE_CORES 8
+#define NUM_OF_NS3Z_PCIE_CORES 1
+
+/*
+ * List of PCIe core and PAXB wrapper memory power registers
+ */
+#define PCIE_CORE_BASE 0x40000800
+#define PCIE_CORE_SOFT_RST_CFG_BASE (PCIE_CORE_BASE + 0x40)
+#define PCIE_CORE_SOFT_RST 0x1
+#define PCIE_CORE_ISO_CFG_BASE (PCIE_CORE_BASE + 0x54)
+#define PCIE_CORE_MEM_ISO 0x2
+#define PCIE_CORE_ISO 0x1
+
+#define PCIE_CORE_MEM_PWR_BASE (PCIE_CORE_BASE + 0x58)
+#define PCIE_PAXB_MEM_PWR_BASE (PCIE_CORE_BASE + 0x5c)
+#define PCIE_CORE_PMI_CFG_BASE (PCIE_CORE_BASE + 0x64)
+#define PCIE_CORE_RESERVED_CFG (PCIE_CORE_BASE + 0x6c)
+#define PCIE_CORE_MEM_PWR_STATUS_BASE (PCIE_CORE_BASE + 0x74)
+#define PCIE_PAXB_MEM_PWR_STATUS_BASE (PCIE_CORE_BASE + 0x78)
+#define PCIE_CORE_PWR_OFFSET 0x100
+
+#define SR_A0_DEVICE_ID 0xd713
+#define SR_B0_DEVICE_ID 0xd714
+/* TODO: Modify device ID once available */
+#define NS3Z_DEVICE_ID 0xd715
+
+/* FIXME: change link speed to GEN3 when it's ready */
+#define GEN1_LINK_SPEED 1
+#define GEN2_LINK_SPEED 2
+#define GEN3_LINK_SPEED 3
+
+typedef struct {
+ uint32_t type;
+ uint32_t device_id;
+ uint32_t pipemux_idx;
+ uint32_t num_cores;
+ int (*pipemux_init)(void);
+ int (*phy_init)(void);
+ int (*core_needs_enable)(unsigned int core_idx);
+ unsigned int (*get_link_width)(unsigned int core_idx);
+ unsigned int (*get_link_speed)(void);
+} paxb_cfg;
+
+enum paxb_type {
+ PAXB_SR,
+ PAXB_NS3Z,
+};
+
+extern const paxb_cfg *paxb;
+
+#ifdef USE_PAXB
+void paxb_init(void);
+void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
+ uint32_t val);
+unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where);
+int pcie_core_needs_enable(unsigned int core_idx);
+const paxb_cfg *paxb_get_sr_config(void);
+#else
+static inline void paxb_init(void)
+{
+}
+#endif
+
+#endif /* PAXB_H */
diff --git a/plat/brcm/board/stingray/include/paxc.h b/plat/brcm/board/stingray/include/paxc.h
new file mode 100644
index 0000000..ae1af2e
--- /dev/null
+++ b/plat/brcm/board/stingray/include/paxc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PAXC_H
+#define PAXC_H
+
+#ifdef USE_PAXC
+void paxc_init(void);
+void paxc_mhb_ns_init(void);
+#else
+static inline void paxc_init(void)
+{
+}
+
+static inline void paxc_mhb_ns_init(void)
+{
+}
+#endif
+
+#endif /* PAXC_H */
diff --git a/plat/brcm/board/stingray/include/plat_macros.S b/plat/brcm/board/stingray/include/plat_macros.S
new file mode 100644
index 0000000..dccd54a
--- /dev/null
+++ b/plat/brcm/board/stingray/include/plat_macros.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant registers whenever an
+ * unhandled exception is taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+ nop
+.endm
+
+/* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_print_gic_regs
+ nop
+ /*TBD-STINGRAY*/
+.endm
+
+/* ------------------------------------------------
+ * The below required platform porting macro prints
+ * out relevant interconnect registers whenever an
+ * unhandled exception is taken in BL3-1.
+ * ------------------------------------------------
+ */
+.macro plat_print_interconnect_regs
+ nop
+ /*TBD-STINGRAY*/
+.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/brcm/board/stingray/include/platform_def.h b/plat/brcm/board/stingray/include/platform_def.h
new file mode 100644
index 0000000..4742124
--- /dev/null
+++ b/plat/brcm/board/stingray/include/platform_def.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2015-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <plat/common/common_def.h>
+
+#include <brcm_def.h>
+#include "sr_def.h"
+#include <cmn_plat_def.h>
+
+/*
+ * Most platform porting definitions provided by included headers
+ */
+#define PLAT_BRCM_SCP_TZC_DRAM1_SIZE ULL(0x0)
+
+/*
+ * Required by standard platform porting definitions
+ */
+#define PLATFORM_CLUSTER0_CORE_COUNT 2
+#define PLATFORM_CLUSTER1_CORE_COUNT 2
+#define PLATFORM_CLUSTER2_CORE_COUNT 2
+#define PLATFORM_CLUSTER3_CORE_COUNT 2
+
+#define BRCM_SYSTEM_COUNT 1
+#define BRCM_CLUSTER_COUNT 4
+
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \
+ PLATFORM_CLUSTER1_CORE_COUNT+ \
+ PLATFORM_CLUSTER2_CORE_COUNT+ \
+ PLATFORM_CLUSTER3_CORE_COUNT)
+
+#define PLAT_NUM_PWR_DOMAINS (BRCM_SYSTEM_COUNT + \
+ BRCM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/* TBD-STINGRAY */
+#define CACHE_WRITEBACK_SHIFT 6
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/* TBD-STINGRAY */
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL1
+
+#define BL1_PLATFORM_STACK_SIZE 0x3300
+#define BL2_PLATFORM_STACK_SIZE 0xc000
+#define BL11_PLATFORM_STACK_SIZE 0x2b00
+#define DEFAULT_PLATFORM_STACK_SIZE 0x400
+#if IMAGE_BL1
+# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE
+#else
+#if IMAGE_BL2
+#ifdef USE_BL1_RW
+# define PLATFORM_STACK_SIZE BL2_PLATFORM_STACK_SIZE
+#else
+# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE
+#endif
+#else
+#if IMAGE_BL11
+# define PLATFORM_STACK_SIZE BL11_PLATFORM_STACK_SIZE
+#else
+# define PLATFORM_STACK_SIZE DEFAULT_PLATFORM_STACK_SIZE
+#endif
+#endif
+#endif
+
+#define PLAT_BRCM_TRUSTED_SRAM_BASE 0x66D00000
+#define PLAT_BRCM_TRUSTED_SRAM_SIZE 0x00040000
+
+#ifdef RUN_BL1_FROM_QSPI /* BL1 XIP from QSPI */
+# define PLAT_BRCM_TRUSTED_ROM_BASE QSPI_BASE_ADDR
+#elif RUN_BL1_FROM_NAND /* BL1 XIP from NAND */
+# define PLAT_BRCM_TRUSTED_ROM_BASE NAND_BASE_ADDR
+#else /* BL1 executed in ROM */
+# define PLAT_BRCM_TRUSTED_ROM_BASE ROM_BASE_ADDR
+#endif
+#define PLAT_BRCM_TRUSTED_ROM_SIZE 0x00040000
+
+/*******************************************************************************
+ * BL1 specific defines.
+ ******************************************************************************/
+#define BL1_RO_BASE PLAT_BRCM_TRUSTED_ROM_BASE
+#define BL1_RO_LIMIT (PLAT_BRCM_TRUSTED_ROM_BASE \
+ + PLAT_BRCM_TRUSTED_ROM_SIZE)
+
+/*
+ * Put BL1 RW at the beginning of the Trusted SRAM.
+ */
+#define BL1_RW_BASE (BRCM_BL_RAM_BASE)
+#define BL1_RW_LIMIT (BL1_RW_BASE + 0x12000)
+
+#define BL11_RW_BASE BL1_RW_LIMIT
+#define BL11_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \
+ PLAT_BRCM_TRUSTED_SRAM_SIZE)
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+#if RUN_BL2_FROM_QSPI /* BL2 XIP from QSPI */
+#define BL2_BASE QSPI_BASE_ADDR
+#define BL2_LIMIT (BL2_BASE + 0x40000)
+#define BL2_RW_BASE BL1_RW_LIMIT
+#define BL2_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \
+ PLAT_BRCM_TRUSTED_SRAM_SIZE)
+#elif RUN_BL2_FROM_NAND /* BL2 XIP from NAND */
+#define BL2_BASE NAND_BASE_ADDR
+#define BL2_LIMIT (BL2_BASE + 0x40000)
+#define BL2_RW_BASE BL1_RW_LIMIT
+#define BL2_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \
+ PLAT_BRCM_TRUSTED_SRAM_SIZE)
+#else
+#define BL2_BASE (BL1_RW_LIMIT + PAGE_SIZE)
+#define BL2_LIMIT (BRCM_BL_RAM_BASE + BRCM_BL_RAM_SIZE)
+#endif
+
+/*
+ * BL1 persistent area in internal SRAM
+ * This area will increase as more features gets into BL1
+ */
+#define BL1_PERSISTENT_DATA_SIZE 0x2000
+
+/* To reduce BL2 runtime footprint, we can re-use some BL1_RW area */
+#define BL1_RW_RECLAIM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE + \
+ BL1_PERSISTENT_DATA_SIZE)
+
+/*******************************************************************************
+ * BL3-1 specific defines.
+ ******************************************************************************/
+/* Max Size of BL31 (in DRAM) */
+#define PLAT_BRCM_MAX_BL31_SIZE 0x30000
+
+#ifdef USE_DDR
+#define BL31_BASE BRCM_AP_TZC_DRAM1_BASE
+
+#define BL31_LIMIT (BRCM_AP_TZC_DRAM1_BASE + \
+ PLAT_BRCM_MAX_BL31_SIZE)
+#else
+/* Put BL3-1 at the end of external on-board SRAM connected as NOR flash */
+#define BL31_BASE (NOR_BASE_ADDR + NOR_SIZE - \
+ PLAT_BRCM_MAX_BL31_SIZE)
+
+#define BL31_LIMIT (NOR_BASE_ADDR + NOR_SIZE)
+#endif
+
+#define SECURE_DDR_END_ADDRESS BL31_LIMIT
+
+#ifdef NEED_SCP_BL2
+#define SCP_BL2_BASE BL31_BASE
+#define PLAT_MAX_SCP_BL2_SIZE 0x9000
+#define PLAT_SCP_COM_SHARED_MEM_BASE (CRMU_SHARED_SRAM_BASE)
+/* dummy defined */
+#define PLAT_BRCM_MHU_BASE 0x0
+#endif
+
+#define SECONDARY_CPU_SPIN_BASE_ADDR BRCM_SHARED_RAM_BASE
+
+/* Generic system timer counter frequency */
+#ifndef SYSCNT_FREQ
+#define SYSCNT_FREQ (125 * 1000 * 1000)
+#endif
+
+/*
+ * Enable the BL32 definitions, only when optee os is selected as secure
+ * payload (BL32).
+ */
+#ifdef SPD_opteed
+/*
+ * Reserved Memory Map : SHMEM & TZDRAM.
+ *
+ * +--------+----------+ 0x8D000000
+ * | SHMEM (NS) | 16MB
+ * +-------------------+ 0x8E000000
+ * | | TEE_RAM(S)| 4MB
+ * + TZDRAM +----------+ 0x8E400000
+ * | | TA_RAM(S) | 12MB
+ * +-------------------+ 0x8F000000
+ * | BL31 Binary (S) | 192KB
+ * +-------------------+ 0x8F030000
+ */
+
+#define BL32_VA_SIZE (4 * 1024 * 1024)
+#define BL32_BASE (0x8E000000)
+#define BL32_LIMIT (BL32_BASE + BL32_VA_SIZE)
+#define TSP_SEC_MEM_BASE BL32_BASE
+#define TSP_SEC_MEM_SIZE BL32_VA_SIZE
+#endif
+
+#ifdef SPD_opteed
+ #define SECURE_DDR_BASE_ADDRESS BL32_BASE
+#else
+ #define SECURE_DDR_BASE_ADDRESS BL31_BASE
+#endif
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+
+#define MAX_XLAT_TABLES 7
+
+#define PLAT_BRCM_MMAP_ENTRIES 10
+
+#define MAX_MMAP_REGIONS (PLAT_BRCM_MMAP_ENTRIES + \
+ BRCM_BL_REGIONS)
+
+#ifdef USE_DDR
+#ifdef BL33_OVERRIDE_LOAD_ADDR
+#define PLAT_BRCM_NS_IMAGE_OFFSET BL33_OVERRIDE_LOAD_ADDR
+#else
+/*
+ * BL3-3 image starting offset.
+ * Putting start of DRAM as of now.
+ */
+#define PLAT_BRCM_NS_IMAGE_OFFSET 0x80000000
+#endif /* BL33_OVERRIDE_LOAD_ADDR */
+#else
+/*
+ * BL3-3 image starting offset.
+ * Putting start of external on-board SRAM as of now.
+ */
+#define PLAT_BRCM_NS_IMAGE_OFFSET NOR_BASE_ADDR
+#endif /* USE_DDR */
+/******************************************************************************
+ * Required platform porting definitions common to all BRCM platforms
+ *****************************************************************************/
+
+#define MAX_IO_DEVICES 5
+#define MAX_IO_HANDLES 6
+
+#define PRIMARY_CPU 0
+
+/* GIC Parameter */
+#define PLAT_BRCM_GICD_BASE GIC500_BASE
+#define PLAT_BRCM_GICR_BASE (GIC500_BASE + 0x200000)
+
+/* Define secure interrupt as per Group here */
+#define PLAT_BRCM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(BRCM_IRQ_SEC_SPI_0, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+ GIC_INTR_CFG_EDGE)
+
+#define PLAT_BRCM_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
+ GIC_INTR_CFG_EDGE), \
+
+/*
+ *CCN 502 related constants.
+ */
+#define PLAT_BRCM_CLUSTER_COUNT 4 /* Number of RN-F Masters */
+#define PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP CLUSTER0_NODE_ID, CLUSTER1_NODE_ID, CLUSTER2_NODE_ID, CLUSTER3_NODE_ID
+#define CCN_SIZE 0x1000000
+#define CLUSTER0_NODE_ID 1
+#define CLUSTER1_NODE_ID 7
+#define CLUSTER2_NODE_ID 9
+#define CLUSTER3_NODE_ID 15
+
+#endif
diff --git a/plat/brcm/board/stingray/include/platform_sotp.h b/plat/brcm/board/stingray/include/platform_sotp.h
new file mode 100644
index 0000000..0389f38
--- /dev/null
+++ b/plat/brcm/board/stingray/include/platform_sotp.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_SOTP_H
+#define PLATFORM_SOTP_H
+
+#define SOTP_DEVICE_SECURE_CFG0_ROW 17
+#define SOTP_DEVICE_SECURE_CFG1_ROW 18
+#define SOTP_DEVICE_SECURE_CFG2_ROW 19
+#define SOTP_DEVICE_SECURE_CFG3_ROW 20
+#define SOTP_BRCM_SOFTWARE_CFG0_ROW 21
+#define SOTP_BRCM_SOFTWARE_CFG1_ROW 22
+#define SOTP_BRCM_SOFTWARE_CFG2_ROW 23
+#define SOTP_BRCM_SOFTWARE_CFG3_ROW 24
+#define SOTP_CUSTOMER_ID_CFG0_ROW 25
+#define SOTP_CUSTOMER_ID_CFG1_ROW 26
+#define SOTP_CUSTOMER_ID_CFG2_ROW 27
+#define SOTP_CUSTOMER_ID_CFG3_ROW 28
+#define SOTP_CUSTOMER_DEV_CFG0_ROW 29
+#define SOTP_CUSTOMER_DEV_CFG1_ROW 30
+#define SOTP_CUSTOMER_DEV_CFG2_ROW 31
+#define SOTP_CUSTOMER_DEV_CFG3_ROW 32
+#define SOTP_DAUTH_ROW 33
+#define SOTP_K_HMAC_ROW 45
+#define SOTP_K_AES_ROW 57
+#define SOTP_NVCOUNTER_ROW 69
+
+#define SOTP_BRCM_CFG_ECC_ERROR_MASK 0x100000
+#define SOTP_DAUTH_ECC_ERROR_MASK 0x800000
+#define SOTP_K_HMAC_ECC_ERROR_MASK 0x1000000
+#define SOTP_K_AES_ECC_ERROR_MASK 0x2000000
+
+#endif
diff --git a/plat/brcm/board/stingray/include/platform_usb.h b/plat/brcm/board/stingray/include/platform_usb.h
new file mode 100644
index 0000000..5b5309f
--- /dev/null
+++ b/plat/brcm/board/stingray/include/platform_usb.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_USB_H
+#define PLATFORM_USB_H
+
+#include <platform_def.h>
+
+#define USB3_DRD BIT(0U)
+#define USB3H_USB2DRD BIT(1U)
+
+extern const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS];
+
+void xhci_phy_init(void);
+
+#endif /* PLATFORM_USB_H */
diff --git a/plat/brcm/board/stingray/include/scp_cmd.h b/plat/brcm/board/stingray/include/scp_cmd.h
new file mode 100644
index 0000000..806ef56
--- /dev/null
+++ b/plat/brcm/board/stingray/include/scp_cmd.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCP_CMD_H
+#define SCP_SMD_H
+
+#include <stdint.h>
+
+typedef struct {
+ int cmd;
+ int completed;
+ int ret;
+} crmu_response_t;
+
+
+#define SCP_CMD_MASK 0xffff
+#define SCP_CMD_DEFAULT_TIMEOUT_US 1000
+#define SCP_CMD_SCP_BOOT_TIMEOUT_US 5000
+
+int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/scp_utils.h b/plat/brcm/board/stingray/include/scp_utils.h
new file mode 100644
index 0000000..c39b18c
--- /dev/null
+++ b/plat/brcm/board/stingray/include/scp_utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCP_UTILS_H
+#define SCP_UTILS_H
+
+#include <common/bl_common.h>
+#include <lib/mmio.h>
+
+#include <m0_cfg.h>
+
+int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info);
+
+bool is_crmu_alive(void);
+bool bcm_scp_issue_sys_reset(void);
+
+#define SCP_READ_CFG(cfg) mmio_read_32(CRMU_CFG_BASE + \
+ offsetof(M0CFG, cfg))
+#define SCP_WRITE_CFG(cfg, value) mmio_write_32(CRMU_CFG_BASE + \
+ offsetof(M0CFG, cfg), value)
+
+#define SCP_READ_CFG16(cfg) mmio_read_16(CRMU_CFG_BASE + \
+ offsetof(M0CFG, cfg))
+#define SCP_WRITE_CFG16(cfg, value) mmio_write_16(CRMU_CFG_BASE + \
+ offsetof(M0CFG, cfg), value)
+
+#define SCP_READ_CFG8(cfg) mmio_read_8(CRMU_CFG_BASE + \
+ offsetof(M0CFG, cfg))
+#define SCP_WRITE_CFG8(cfg, value) mmio_write_8(CRMU_CFG_BASE + \
+ offsetof(M0CFG, cfg), value)
+#endif
diff --git a/plat/brcm/board/stingray/include/sdio.h b/plat/brcm/board/stingray/include/sdio.h
new file mode 100644
index 0000000..e08904e
--- /dev/null
+++ b/plat/brcm/board/stingray/include/sdio.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SDIO_H
+#define SDIO_H
+
+#include <stdbool.h>
+
+#define SR_IPROC_SDIO0_CFG_BASE 0x689006e4
+#define SR_IPROC_SDIO0_SID_BASE 0x68900b00
+#define SR_IPROC_SDIO0_PAD_BASE 0x68a4017c
+#define SR_IPROC_SDIO0_IOCTRL_BASE 0x68e02408
+
+#define SR_IPROC_SDIO1_CFG_BASE 0x68900734
+#define SR_IPROC_SDIO1_SID_BASE 0x68900b08
+#define SR_IPROC_SDIO1_PAD_BASE 0x68a401b4
+#define SR_IPROC_SDIO1_IOCTRL_BASE 0x68e03408
+
+#define NS3Z_IPROC_SDIO0_CFG_BASE 0x68a20540
+#define NS3Z_IPROC_SDIO0_SID_BASE 0x68900b00
+#define NS3Z_IPROC_SDIO0_TP_OUT_SEL 0x68a20308
+#define NS3Z_IPROC_SDIO0_PAD_BASE 0x68a20500
+#define NS3Z_IPROC_SDIO0_IOCTRL_BASE 0x68e02408
+
+#define PHY_BYPASS BIT(14)
+#define LEGACY_EN BIT(31)
+#define PHY_DISABLE (LEGACY_EN | PHY_BYPASS)
+
+#define NS3Z_IPROC_SDIO1_CFG_BASE 0x68a30540
+#define NS3Z_IPROC_SDIO1_SID_BASE 0x68900b08
+#define NS3Z_IPROC_SDIO1_PAD_BASE 0x68a30500
+#define NS3Z_IPROC_SDIO1_IOCTRL_BASE 0x68e03408
+
+#define ICFG_SDIO_CAP0 0x10
+#define ICFG_SDIO_CAP1 0x14
+#define ICFG_SDIO_STRAPSTATUS_0 0x0
+#define ICFG_SDIO_STRAPSTATUS_1 0x4
+#define ICFG_SDIO_STRAPSTATUS_2 0x8
+#define ICFG_SDIO_STRAPSTATUS_3 0xc
+#define ICFG_SDIO_STRAPSTATUS_4 0x18
+
+#define ICFG_SDIO_SID_ARADDR 0x0
+#define ICFG_SDIO_SID_AWADDR 0x4
+
+#define ICFG_SDIOx_CAP0__SLOT_TYPE_MASK 0x3
+#define ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT 27
+#define ICFG_SDIOx_CAP0__INT_MODE_SHIFT 26
+#define ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT 25
+#define ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT 24
+#define ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT 23
+#define ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT 22
+#define ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT 21
+#define ICFG_SDIOx_CAP0__SDMA_SHIFT 20
+#define ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT 19
+#define ICFG_SDIOx_CAP0__ADMA2_SHIFT 18
+#define ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT 17
+#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_MASK 0x3
+#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT 15
+#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_MASK 0xff
+#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT 7
+#define ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT 6
+#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_MASK 0x3f
+#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT 0
+
+#define ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT 22
+#define ICFG_SDIOx_CAP1__SPI_MODE_SHIFT 21
+#define ICFG_SDIOx_CAP1__CLK_MULT_MASK 0xff
+#define ICFG_SDIOx_CAP1__CLK_MULT_SHIFT 13
+#define ICFG_SDIOx_CAP1__RETUNING_MODE_MASK 0x3
+#define ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT 11
+#define ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT 10
+#define ICFG_SDIOx_CAP1__TIME_RETUNE_MASK 0xf
+#define ICFG_SDIOx_CAP1__TIME_RETUNE_SHIFT 6
+#define ICFG_SDIOx_CAP1__DRIVER_D_SHIFT 5
+#define ICFG_SDIOx_CAP1__DRIVER_C_SHIFT 4
+#define ICFG_SDIOx_CAP1__DRIVER_A_SHIFT 3
+#define ICFG_SDIOx_CAP1__DDR50_SHIFT 2
+#define ICFG_SDIOx_CAP1__SDR104_SHIFT 1
+#define ICFG_SDIOx_CAP1__SDR50_SHIFT 0
+
+#ifdef USE_DDR
+#define SDIO_DMA 1
+#else
+#define SDIO_DMA 0
+#endif
+
+#define SDIO0_CAP0_CFG \
+ (0x1 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
+ | (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
+ | (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
+ | (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
+ | (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
+ | (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
+ | (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
+ | (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
+
+#define SDIO0_CAP1_CFG \
+ (0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
+ | (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
+ | (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
+ | (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
+ | (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
+
+#define SDIO1_CAP0_CFG \
+ (0x0 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
+ | (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
+ | (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
+ | (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
+ | (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
+ | (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
+ | (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
+ | (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
+ | (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
+
+#define SDIO1_CAP1_CFG \
+ (0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
+ | (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
+ | (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
+ | (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
+ | (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
+ | (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
+
+#define PAD_SDIO_CLK 0x4
+#define PAD_SDIO_DATA0 0x8
+#define PAD_SDIO_DATA1 0xc
+#define PAD_SDIO_DATA2 0x10
+#define PAD_SDIO_DATA3 0x14
+#define PAD_SDIO_DATA4 0x18
+#define PAD_SDIO_DATA5 0x1c
+#define PAD_SDIO_DATA6 0x20
+#define PAD_SDIO_DATA7 0x24
+#define PAD_SDIO_CMD 0x28
+
+/* 12mA Drive strength*/
+#define PAD_SDIO_SELX (0x5 << 1)
+#define PAD_SDIO_SRC (1 << 0)
+#define PAD_SDIO_MASK (0xF << 0)
+#define PAD_SDIO_VALUE (PAD_SDIO_SELX | PAD_SDIO_SRC)
+
+/*
+ * SDIO_PRESETVAL0
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field Bit(s) Description
+ * ============================================================
+ * SDR25_PRESET 25:13 Preset Value for SDR25
+ * SDR50_PRESET 12:0 Preset Value for SDR50
+ */
+#define SDIO_PRESETVAL0 0x01005001
+
+/*
+ * SDIO_PRESETVAL1
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field Bit(s) Description
+ * ============================================================
+ * SDR104_PRESET 25:13 Preset Value for SDR104
+ * SDR12_PRESET 12:0 Preset Value for SDR12
+ */
+#define SDIO_PRESETVAL1 0x03000004
+
+/*
+ * SDIO_PRESETVAL2
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field Bit(s) Description
+ * ============================================================
+ * HIGH_SPEED_PRESET 25:13 Preset Value for High Speed
+ * INIT_PRESET 12:0 Preset Value for Initialization
+ */
+#define SDIO_PRESETVAL2 0x010040FA
+
+/*
+ * SDIO_PRESETVAL3
+ *
+ * Each 13 Bit filed consists:
+ * drivestrength - 12:11
+ * clkgensel - b10
+ * sdkclkfreqsel - 9:0
+ * Field Bit(s) Description
+ * ============================================================
+ * DDR50_PRESET 25:13 Preset Value for DDR50
+ * DEFAULT_PRESET 12:0 Preset Value for Default Speed
+ */
+#define SDIO_PRESETVAL3 0x01004004
+
+/*
+ * SDIO_PRESETVAL4
+ *
+ * Field Bit(s) Description
+ * ============================================================
+ * FORCE_USE_IP_TUNE_CLK 30 Force use IP clock
+ * TUNING_COUNT 29:24 Tuning count
+ * OVERRIDE_1P8V 23:16
+ * OVERRIDE_3P3V 15:8
+ * OVERRIDE_3P0V 7:0
+ */
+#define SDIO_PRESETVAL4 0x20010101
+
+#define SDIO_SID_SHIFT 5
+
+typedef struct {
+ uintptr_t cfg_base;
+ uintptr_t sid_base;
+ uintptr_t io_ctrl_base;
+ uintptr_t pad_base;
+} SDIO_CFG;
+
+void brcm_stingray_sdio_init(void);
+
+#endif /* SDIO_H */
diff --git a/plat/brcm/board/stingray/include/sr_def.h b/plat/brcm/board/stingray/include/sr_def.h
new file mode 100644
index 0000000..277836e
--- /dev/null
+++ b/plat/brcm/board/stingray/include/sr_def.h
@@ -0,0 +1,624 @@
+/*
+ * Copyright (c) 2016-2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SR_DEF_H
+#define SR_DEF_H
+
+#ifndef __ASSEMBLER__
+#include <lib/mmio.h>
+#endif
+
+#include <common/interrupt_props.h>
+#include <drivers/arm/gic_common.h>
+
+#include <crmu_def.h>
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define BRCM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978)
+
+#define MHB_BASE_ADDR 0x60000000
+#define PLAT_BRCM_CCN_BASE 0x61000000
+#define CORESIGHT_BASE_ADDR 0x62000000
+#define SMMU_BASE 0x64000000
+
+/* memory map entries*/
+/* Grouping block device for bigger MMU region */
+/* covers MHB, CNN, coresight, GIC, MMU, APB, CRMU */
+#define PERIPH0_BASE MHB_BASE_ADDR
+#define PERIPH0_SIZE 0x06d00000
+
+#define PERIPH1_BASE 0x66d80000
+#define PERIPH1_SIZE 0x00f80000
+
+#define HSLS_BASE_ADDR 0x68900000
+#define HSLS_SIZE 0x04500000
+
+#define GIC500_BASE 0x63c00000
+#define GIC500_SIZE 0x400000
+
+/*******************************************************************************
+ * CCN related constants
+ ******************************************************************************/
+#define OLY_MN_REGISTERS_NODE0_SECURE_ACCESS (PLAT_BRCM_CCN_BASE + 0x0)
+
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x880500)
+
+/* Used for acceleration of coherent ordered writes */
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WUO BIT(4)
+/* Wait for completion of requests at RN-I */
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC BIT(3)
+
+/*
+ * Forces all reads from the RN-I to be sent with the request order bit set
+ * and this ensures ordered allocation of read data buffers in the RN-I
+ */
+#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_RQO BIT(5)
+
+#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x8e0500)
+
+/* Wait for completion of requests at RN-I */
+#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL_WFC BIT(3)
+
+#define OLY_HNI_REGISTERS_NODE0_POS_CONTROL (PLAT_BRCM_CCN_BASE + 0x80000)
+#define POS_CONTROL_HNI_POS_EN BIT(0)
+
+#define OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST \
+ (PLAT_BRCM_CCN_BASE + 0x80008)
+/* PAXB and PAXC connected to 8th Node */
+#define SR_RNI_PCIE_CONNECTED BIT(8)
+/* PAXB connected to 6th Node */
+#define SRP_RNI_PCIE_CONNECTED BIT(6)
+
+#define OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x80500)
+#define SA_AUX_CTL_POS_EARLY_WR_COMP_EN BIT(5)
+#define SA_AUX_CTL_SER_DEVNE_WR BIT(9)
+
+/*******************************************************************************
+ * Coresight related constants
+ ******************************************************************************/
+#define CORESIGHT_BASE_ADDR 0x62000000
+
+#define IHOST0_BASE 0x66000000
+#define IHOST_ADDR_SPACE 0x2000
+
+/*******************************************************************************
+ * SCR related constants
+ ******************************************************************************/
+#define SCR_BASE 0x6600a000
+#define SCR_ARCACHE_OFFSET 4
+#define SCR_ARCACHE_MASK (0x3 << SCR_ARCACHE_OFFSET)
+#define SCR_AWCACHE_OFFSET 6
+#define SCR_AWCACHE_MASK (0x3 << SCR_AWCACHE_OFFSET)
+#define SCR_AXCACHE_CONFIG_MASK (SCR_ARCACHE_MASK | SCR_AWCACHE_MASK)
+#define SCR_TBUX_AXCACHE_CONFIG ((0x1 << SCR_AWCACHE_OFFSET) | \
+ (0x1 << SCR_ARCACHE_OFFSET))
+
+#define SCR_REGS_SCR_SOFT_RESET (SCR_BASE + 0x1c)
+#define SCR_REGS_GIC_SOFT_RESET BIT(0)
+
+#define SCR_GPV_BASE 0x66100000
+#define SCR_NOC_SECURITY0 (SCR_GPV_BASE + 0x08)
+#define SCR_NOC_DDR_REGISTER_ACCESS (SCR_GPV_BASE + 0x30)
+
+/*******************************************************************************
+ * MEMC and DDR related constants
+ ******************************************************************************/
+#define DDR0_CONTROL_ROOT 0x66200000
+#define EMEM_SS_CFG_0_ROOT 0x66202000
+#define EMEM_SYS_IF_0_ROOT 0x66204000
+#define DDR_PHY0_ROOT 0x66240000
+
+#define DDR1_CONTROL_ROOT 0x66280000
+#define EMEM_SS_CFG_1_ROOT 0x66282000
+#define EMEM_SYS_IF_1_ROOT 0x66284000
+#define DDR_PHY1_ROOT 0x662c0000
+
+#define DDR2_CONTROL_ROOT 0x66300000
+#define EMEM_SS_CFG_2_ROOT 0x66302000
+#define EMEM_SYS_IF_2_ROOT 0x66304000
+#define DDR_PHY2_ROOT 0x66340000
+
+/*******************************************************************************
+ * TZC400 related constants
+ ******************************************************************************/
+#define TZC_400_BASE 0x66d84000
+
+/*******************************************************************************
+ * FS4 related constants
+ ******************************************************************************/
+#define FS4_SRAM_IDM_IO_CONTROL_DIRECT 0x66d8a408
+
+#define FS4_CRYPTO_IDM_IO_CONTROL_DIRECT 0x66d8e408
+#define FS4_CRYPTO_IDM_RESET_CONTROL 0x66d8e800
+#define FS4_CRYPTO_BASE 0x67000000
+#define FS4_CRYPTO_DME_BASE (FS4_CRYPTO_BASE + 0x280000)
+
+#define FS4_RAID_IDM_IO_CONTROL_DIRECT 0x66d8f408
+#define FS4_RAID_IDM_IO_STATUS 0x66d8f500
+#define FS4_RAID_IDM_RESET_CONTROL 0x66d8f800
+#define FS4_RAID_BASE 0x67400000
+#define FS4_RAID_DME_BASE (FS4_RAID_BASE + 0x280000)
+
+#define FS4_CRYPTO_GPV_BASE 0x67300000
+#define FS4_RAID_GPV_BASE 0x67700000
+
+#define FS6_PKI_BASE 0x67400000
+#define FS6_PKI_DME_BASE 0x66D90000
+
+#define TZC400_FS_SRAM_ROOT 0x66d84000
+#define GATE_KEEPER_OFFSET 0x8
+#define REGION_ATTRIBUTES_0_OFFSET 0x110
+#define REGION_ID_ACCESS_0_OFFSET 0x114
+
+#define NIC400_FS_NOC_ROOT 0x66e00000
+#define NIC400_FS_NOC_SECURITY2_OFFSET 0x10
+#define NIC400_FS_NOC_SECURITY4_OFFSET 0x18
+#define NIC400_FS_NOC_SECURITY7_OFFSET 0x24
+
+/*******************************************************************************
+ * SATA PHY related constants
+ ******************************************************************************/
+#define SATA_BASE 0x67d00000
+
+/*******************************************************************************
+ * USB related constants
+ ******************************************************************************/
+#define USB_BASE 0x68500000
+#define USB_SIZE 0x00400000
+#define XHC_BASE (USB_BASE + 0x11000)
+#define MAX_USB_PORTS 3
+
+/*******************************************************************************
+ * HSLS related constants
+ ******************************************************************************/
+#define IPROC_ROOT 0x68900000
+#define HSLS_ICFG_REGS_BASE IPROC_ROOT
+#define HSLS_IDM_REGS_BASE 0x68e00000
+#define HSLS_MODE_SEL_CONTROL 0x68a40000
+#define HSLS_TZPC_BASE 0x68b40000
+#define HSLS_GPV_BASE 0x6cd00000
+
+/*******************************************************************************
+ * Chip ID related constants
+ ******************************************************************************/
+#define ICFG_CHIP_ID HSLS_ICFG_REGS_BASE
+#define CHIP_ID_SR 0xd730
+#define CHIP_ID_NS3Z 0xe56d
+#define CHIP_ID_MASK 0xf000
+#define ICFG_CHIP_REVISION_ID (HSLS_ICFG_REGS_BASE + 0x4)
+#define PLAT_CHIP_ID_GET (mmio_read_32(ICFG_CHIP_ID))
+#define PLAT_CHIP_REV_GET (mmio_read_32(ICFG_CHIP_REVISION_ID))
+
+/*******************************************************************************
+ * CMIC MII (MDIO) related constant
+ ******************************************************************************/
+#define PLAT_CMIC_MIIM_BASE 0x68920000U
+
+/*******************************************************************************
+ * Timers related constants
+ ******************************************************************************/
+/* ChipcommonG_tim0_TIM_TIMER1Load 0x68930000 */
+#define SP804_TIMER0_BASE 0x68930000
+#define SP804_TIMER1_BASE 0x68940000
+#define SP804_TIMER0_TIMER_VAL_REG_OFFSET 0x4
+#define SP804_TIMER0_CLKMULT 2
+#define SP804_TIMER0_CLKDIV 25
+
+/*******************************************************************************
+ * GPIO related constants
+ ******************************************************************************/
+#define IPROC_GPIO_NS_BASE 0x689d0000
+#define IPROC_GPIO_S_BASE 0x68b00000
+#define IPROC_GPIO_NR 151
+#define GPIO_S_CNTRL_REG 0x68b60000
+
+/*******************************************************************************
+ * I2C SMBUS related constants
+ ******************************************************************************/
+#define SMBUS0_REGS_BASE 0x689b0000
+#define SMBUS1_REGS_BASE 0x689e0000
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define ChipcommonG_UART0_UART_RBR_THR_DLL 0x68a00000
+#define ChipcommonG_UART1_UART_RBR_THR_DLL 0x68a10000
+#define ChipcommonG_UART2_UART_RBR_THR_DLL 0x68a20000
+#define ChipcommonG_UART3_UART_RBR_THR_DLL 0x68a30000
+
+#define UART0_BASE_ADDR ChipcommonG_UART0_UART_RBR_THR_DLL
+#define UART1_BASE_ADDR ChipcommonG_UART1_UART_RBR_THR_DLL
+#define UART2_BASE_ADDR ChipcommonG_UART2_UART_RBR_THR_DLL
+#define UART3_BASE_ADDR ChipcommonG_UART3_UART_RBR_THR_DLL
+
+#define UART_SPR_OFFSET 0x1c /* Scratch Pad Register */
+
+#define LOG_LEVEL_REGISTER CRMU_SPARE_REG_3
+#define GET_LOG_LEVEL() (mmio_read_32(LOG_LEVEL_REGISTER))
+#define SET_LOG_LEVEL(x) (mmio_write_32(LOG_LEVEL_REGISTER, x))
+
+#define IO_RETRY_REGISTER CRMU_SPARE_REG_4
+
+#define DWC_UART_REFCLK (25 * 1000 * 1000)
+#define DWC_UART_REFCLK_DIV 16
+/* Baud rate in emulation will vary based on setting of 25MHz SCLK */
+#define DWC_UART_BAUDRATE 115200
+
+#define BRCM_CRASH_CONSOLE_BASE UART1_BASE_ADDR
+#define BRCM_CRASH_CONSOLE_REFCLK DWC_UART_REFCLK
+#define BRCM_CRASH_CONSOLE_BAUDRATE DWC_UART_BAUDRATE
+
+#ifdef BOARD_CONSOLE_UART
+#define PLAT_BRCM_BOOT_UART_BASE BOARD_CONSOLE_UART
+#else
+#define PLAT_BRCM_BOOT_UART_BASE UART1_BASE_ADDR
+#endif
+#define CONSOLE_UART_ID ((PLAT_BRCM_BOOT_UART_BASE >> 16) & 0x3)
+
+#define PLAT_BRCM_BOOT_UART_CLK_IN_HZ DWC_UART_REFCLK
+#define BRCM_CONSOLE_BAUDRATE DWC_UART_BAUDRATE
+
+#define PLAT_BRCM_BL31_RUN_UART_BASE PLAT_BRCM_BOOT_UART_BASE
+#define PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ PLAT_BRCM_BOOT_UART_CLK_IN_HZ
+
+/*******************************************************************************
+ * IOMUX related constants
+ ******************************************************************************/
+#define HSLS_IOPAD_BASE HSLS_MODE_SEL_CONTROL
+#define MODE_SEL_CONTROL_FSEL_MASK 0x7
+#define MODE_SEL_CONTROL_FSEL_MODE0 0x0
+#define MODE_SEL_CONTROL_FSEL_MODE1 0x1
+#define MODE_SEL_CONTROL_FSEL_MODE2 0x2
+#define MODE_SEL_CONTROL_FSEL_MODE3 0x3
+#define MODE_SEL_CONTROL_FSEL_DEBUG 0x4
+#define IPROC_IOPAD_MODE_BASE (HSLS_MODE_SEL_CONTROL + 0x29c)
+#define UART0_SIN_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x4a8)
+#define UART0_SOUT_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x4ac)
+#define UART1_SIN_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3b8)
+#define UART1_SOUT_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3bc)
+#define UARTx_SIN_MODE_SEL_CONTROL_FSEL 0
+#define UARTx_SOUT_MODE_SEL_CONTROL_FSEL 0
+
+/*******************************************************************************
+ * PKA constants
+ ******************************************************************************/
+#define ICFG_PKA_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xac0)
+#define ICFG_PKA_MEM_PWR_CTRL__POWERONIN BIT(0)
+#define ICFG_PKA_MEM_PWR_CTRL__POWEROKIN BIT(1)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN BIT(2)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN BIT(3)
+#define ICFG_PKA_MEM_PWR_CTRL__POWERONOUT BIT(4)
+#define ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT BIT(5)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT BIT(6)
+#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT BIT(7)
+#define ICFG_PKA_MEM_PWR_CTRL__ISO BIT(8)
+
+/*******************************************************************************
+ * RNG constants
+ ******************************************************************************/
+#define RNG_BASE_ADDR 0x68b20000
+
+/*******************************************************************************
+ * Trusted Watchdog constants
+ ******************************************************************************/
+#define ARM_SP805_TWDG_BASE 0x68b30000
+#define ARM_SP805_TWDG_CLK_HZ ((25 * 1000 * 1000) / 2)
+/*
+ * The TBBR document specifies a watchdog timeout of 256 seconds. SP805
+ * asserts reset after two consecutive countdowns (2 x 128 = 256 sec)
+ */
+#define ARM_TWDG_TIMEOUT_SEC 128
+#define ARM_TWDG_LOAD_VAL (ARM_SP805_TWDG_CLK_HZ * \
+ ARM_TWDG_TIMEOUT_SEC)
+
+/*******************************************************************************
+ * SOTP related constants
+ ******************************************************************************/
+#define SOTP_REGS_OTP_BASE 0x68b50000
+#define SOTP_CHIP_CTRL (SOTP_REGS_OTP_BASE + 0x4c)
+#define SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS 0
+
+/*******************************************************************************
+ * DMAC/PL330 related constants
+ ******************************************************************************/
+#define DMAC_M0_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x408)
+#define BOOT_MANAGER_NS BIT(25)
+#define DMAC_M0_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x800)
+#define ICFG_DMAC_CONFIG_0 (HSLS_ICFG_REGS_BASE + 0x190)
+#define ICFG_DMAC_CONFIG_1 (HSLS_ICFG_REGS_BASE + 0x194)
+#define ICFG_DMAC_CONFIG_2 (HSLS_ICFG_REGS_BASE + 0x198)
+#define BOOT_PERIPHERAL_NS 0xffffffff
+#define ICFG_DMAC_CONFIG_3 (HSLS_ICFG_REGS_BASE + 0x19c)
+#define BOOT_IRQ_NS 0x0000ffff
+#define ICFG_DMAC_SID_ARADDR_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf0)
+#define ICFG_DMAC_SID_AWADDR_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf4)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWERONIN BIT(0)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN BIT(1)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN BIT(2)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN BIT(3)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT BIT(4)
+#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT BIT(5)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT BIT(6)
+#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT BIT(7)
+#define ICFG_DMAC_MEM_PWR_CTRL__ISO BIT(8)
+#define ICFG_DMAC_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xadc)
+
+/*******************************************************************************
+ * PNOR related constants
+ ******************************************************************************/
+#define PNOR_ICFG_BASE (HSLS_ICFG_REGS_BASE + 0x780)
+#define PNOR_ICFG_CS_0 PNOR_ICFG_BASE
+#define PNOR_ICFG_CS_1 (PNOR_ICFG_BASE + 0x4)
+#define PNOR_ICFG_CS_2 (PNOR_ICFG_BASE + 0x8)
+#define PNOR_ICFG_CS_x_MASK0_MASK 0xff
+#define PNOR_ICFG_CS_x_MASK0_SHIFT 8
+#define PNOR_ICFG_CS_x_MATCH0_MASK 0xff
+#define PNOR_ICFG_CS_x_MATCH0_SHIFT 0
+
+#define PNOR_IDM_BASE (HSLS_IDM_REGS_BASE + 0xb000)
+#define PNOR_IDM_IO_CONTROL_DIRECT (PNOR_IDM_BASE + 0x408)
+#define PNOR_IDM_IO_RESET_CONTROL (PNOR_IDM_BASE + 0x800)
+
+#define PNOR_REG_BASE 0x68c50000
+#define PNOR_REG_DIRECT_CMD (PNOR_REG_BASE + 0x010)
+#define PNOR_REG_SET_CYCLES (PNOR_REG_BASE + 0x014)
+#define PNOR_REG_SET_OPMODE (PNOR_REG_BASE + 0x018)
+#define PNOR_REG_REFRESH_0 (PNOR_REG_BASE + 0x020)
+#define PNOR_REG_PERIPH_ID0 (PNOR_REG_BASE + 0xfe0)
+#define PNOR_REG_PERIPH_ID1 (PNOR_REG_BASE + 0xfe4)
+#define PNOR_REG_PERIPH_ID2 (PNOR_REG_BASE + 0xfe8)
+#define PNOR_REG_PERIPH_ID3 (PNOR_REG_BASE + 0xfec)
+#define PNOR_REG_PERIPH_IDx_MASK 0xff
+
+/*******************************************************************************
+ * NAND related constants
+ ******************************************************************************/
+#define NAND_FLASH_REVISION 0x68c60000
+#define NAND_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0xa408)
+#define NAND_IDM_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xa800)
+
+/*******************************************************************************
+ * eMMC related constants
+ ******************************************************************************/
+#define PLAT_SD_MAX_READ_LENGTH 0x400
+
+#define SDIO0_EMMCSDXC_SYSADDR 0x68cf1000
+#define SDIO_IDM0_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x2408)
+#define SDIO_IDM1_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x3408)
+#define SDIO_IDM0_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x2800)
+#define ICFG_SDIO0_BASE (HSLS_ICFG_REGS_BASE + 0x6e4)
+#define ICFG_SDIO1_BASE (HSLS_ICFG_REGS_BASE + 0x734)
+#define ICFG_SDIO0_CAP0 (ICFG_SDIO0_BASE + 0x10)
+#define ICFG_SDIO0_CAP1 (ICFG_SDIO0_BASE + 0x14)
+#define ICFG_SDIO0_SID (HSLS_ICFG_REGS_BASE + 0xb00)
+#define ICFG_SDIO1_SID (HSLS_ICFG_REGS_BASE + 0xb08)
+
+/*******************************************************************************
+ * Bootstrap related constants
+ ******************************************************************************/
+#define ROM_S0_IDM_IO_STATUS (HSLS_IDM_REGS_BASE + 0x9500)
+
+/*******************************************************************************
+ * ROM related constants
+ ******************************************************************************/
+#define ROM_BASE_ADDR 0x6ce00000
+#define ROM_VERSION_STRING_ADDR (ROM_BASE_ADDR + 0x28000)
+#define ROM_BUILD_MESSAGE_ADDR (ROM_BASE_ADDR + 0x28018)
+
+/*******************************************************************************
+ * Boot source peripheral related constants
+ ******************************************************************************/
+#define QSPI_CTRL_BASE_ADDR 0x68c70000
+#define QSPI_BASE_ADDR 0x70000000
+#define QSPI_SIZE 0x08000000
+#define NOR_BASE_ADDR 0x74000000
+#define NOR_SIZE 0x04000000
+#define NAND_BASE_ADDR 0x78000000
+#define NAND_SIZE 0x08000000
+
+#define QSPI_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xc800)
+
+#define APBR_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xe800)
+#define APBS_IDM_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xf800)
+
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x10408)
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL 2
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM0_SCLK_SEL 4
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM1_SCLK_SEL 6
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM2_SCLK_SEL 8
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM3_SCLK_SEL 10
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM4_SCLK_SEL 12
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM5_SCLK_SEL 13
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM6_SCLK_SEL 14
+#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM7_SCLK_SEL 15
+
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x11408)
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART0_SCLK_SEL 2
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART1_SCLK_SEL 4
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART2_SCLK_SEL 6
+#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART3_SCLK_SEL 8
+
+#define APBZ_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x12408)
+#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0
+#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL 2
+
+/*******************************************************************************
+ * Stingray memory map related constants
+ ******************************************************************************/
+
+/* The last 4KB of Trusted SRAM are used as shared memory */
+#define BRCM_SHARED_RAM_SIZE 0x0
+#define BRCM_SHARED_RAM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE + \
+ PLAT_BRCM_TRUSTED_SRAM_SIZE - \
+ BRCM_SHARED_RAM_SIZE)
+
+/* Reserve 4 KB to store error logs in BL2 */
+#define BCM_ELOG_BL2_SIZE 0x00001000
+#define BCM_ELOG_BL2_BASE BL1_RW_LIMIT
+
+/* The remaining Trusted SRAM is used to load the BL images */
+#define BRCM_BL_RAM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE)
+#define BRCM_BL_RAM_SIZE (PLAT_BRCM_TRUSTED_SRAM_SIZE - \
+ BRCM_SHARED_RAM_SIZE)
+
+/* DDR Address where TMON temperature values are written */
+#define TMON_SHARED_DDR_ADDRESS 0x8f100000
+
+/* Reserve 4 kB to pass data to BL33 */
+#define BL33_SHARED_DDR_BASE 0x8f102000
+#define BL33_SHARED_DDR_SIZE 0x1000
+
+/* Default AP error logging base addr */
+#ifndef ELOG_AP_UART_LOG_BASE
+#define ELOG_AP_UART_LOG_BASE 0x8f110000
+#endif
+
+/* Reserve 16 to store error logs in BL31 */
+#define BCM_ELOG_BL31_BASE ELOG_AP_UART_LOG_BASE
+#define BCM_ELOG_BL31_SIZE 0x4000
+
+/*******************************************************************************
+ * Non-secure DDR Map
+ ******************************************************************************/
+#define BRCM_DRAM1_BASE ULL(0x80000000)
+#define BRCM_DRAM1_SIZE ULL(0x10000000)
+#define BRCM_DRAM2_BASE ULL(0x880000000)
+#define BRCM_DRAM2_SIZE ULL(0x780000000)
+#define BRCM_DRAM3_BASE ULL(0x8800000000)
+#define BRCM_DRAM3_SIZE ULL(0x7800000000)
+#define BRCM_SHARED_DRAM_BASE BL33_SHARED_DDR_BASE
+#define BRCM_SHARED_DRAM_SIZE BL33_SHARED_DDR_SIZE
+#define BRCM_EXT_SRAM_BASE ULL(0x74000000)
+#define BRCM_EXT_SRAM_SIZE ULL(0x4000000)
+
+/* Priority levels for platforms */
+#define PLAT_RAS_PRI 0x10
+#define PLAT_SDEI_CRITICAL_PRI 0x60
+#define PLAT_SDEI_NORMAL_PRI 0x70
+
+/* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 */
+#define BRCM_IRQ_SEC_SGI_0 14
+#define BRCM_IRQ_SEC_SGI_1 15
+
+/* RTC periodic interrupt */
+#define BRCM_IRQ_SEC_SPI_0 49
+
+/*
+ * Macros for local power states in SR platforms encoded by State-ID field
+ * within the power-state parameter.
+ */
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN 0
+
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET 1
+
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF 2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE PLAT_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE PLAT_LOCAL_STATE_OFF
+
+/* ChiMP-related constants */
+
+#define NITRO_TZPC_TZPCDECPROT0clr 0x60c01808
+#define NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R 1
+
+#define NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT 0x60e00408
+
+#define CHIMP_INDIRECT_ADDR_MASK 0x3fffff
+#define CHIMP_INDIRECT_BASE 0x60800000
+
+#define CHIMP_REG_ECO_RESERVED 0x3042400
+
+#define CHIMP_FLASH_ACCESS_DONE_BIT 2
+
+/* indicate FRU table programming is done successfully */
+#define CHIMP_FRU_PROG_DONE_BIT 9
+
+#define CHIMP_REG_CTRL_BPE_MODE_REG 0x0
+#define CHIMP_REG_CTRL_BPE_STAT_REG 0x4
+#define CHIMP_REG_CTRL_FSTBOOT_PTR_REG 0x8
+#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_L 1
+#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R 1
+#define CHIMP_REG_CTRL_BASE 0x3040000
+#define CHIMP_FAST_BOOT_MODE_BIT 2
+#define CHIMP_REG_CHIMP_APE_SCPAD 0x3300000
+#define CHIMP_REG_CHIMP_SCPAD 0x3100000
+
+/* Chimp health status offset in scratch pad ram */
+#define CHIMP_HEALTH_STATUS_OFFSET 0x8
+/*
+ * If not in NIC mode then FASTBOOT can be enabled.
+ * "Not in NIC mode" means that FORCE_FASTBOOT is set
+ * and a valid (1 or 2) fastboot type is specified.
+ *
+ * Three types of fastboot are supported:
+ * 0 = No fastboot. Boots Nitro/ChiMP and lets ROM loader
+ * initialize ChiMP from NVRAM (QSPI).
+ *
+ * 1 = Jump in place (need a flat image)
+ * This is intended to speedup Nitro FW boot on Palladium,
+ * can be used with a real chip as well.
+ * 2 = Jump normally with decompression
+ * Modus operandi for a real chip. Works also on Palladium
+ * Note: image decompressing takes time on Palladium.
+ * 3 = No fastboot support. No ChiMP bringup
+ * (use only for AP debug or for ChiMP's deferred setup).
+ */
+#define CHIMP_FASTBOOT_JUMP_DECOMPRESS 2
+#define CHIMP_FASTBOOT_JUMP_IN_PLACE 1
+#define CHIMP_FASTBOOT_NITRO_RESET 0
+/*
+ * Definitions for a non-Nitro access
+ * to QSPI PAD after the handshake
+ */
+#define QSPI_HOLD_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3e8)
+#define QSPI_WP_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3ec)
+#define QSPI_SCK_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f0)
+#define QSPI_CS_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f4)
+#define QSPI_MOSI_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f8)
+#define QSPI_MISO_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3fc)
+
+/*******************************************************************************
+ * Stream IDs for different blocks of SR
+ * block_id for different blocks is as follows:
+ * PCIE : 0x0
+ * PAXC : 0x1
+ * FS4 : 0x2
+ * Rest of the masters(includes MHB via RNI): 0x3
+ ******************************************************************************/
+#define SR_SID_VAL(block_id, subblock_id, device_num) ((block_id << 13) | \
+ (subblock_id << 11) | \
+ (device_num))
+
+#define CRMU_STREAM_ID SR_SID_VAL(0x3, 0x0, 0x7)
+#define CRMU_SID_SHIFT 5
+
+#define DMAC_STREAM_ID SR_SID_VAL(0x3, 0x0, 0x0)
+#define DMAC_SID_SHIFT 5
+
+/* DDR SHMOO Values defines */
+#define IDRAM_SHMOO_VALUES_ADDR CRMU_IDRAM_BASE_ADDR
+#define DDR_SHMOO_VALUES_ADDR 0x8f103000
+#define SHMOO_SIZE_PER_CHANNEL 0x1000
+
+#endif /* SR_DEF_H */
diff --git a/plat/brcm/board/stingray/include/sr_utils.h b/plat/brcm/board/stingray/include/sr_utils.h
new file mode 100644
index 0000000..b3fc735
--- /dev/null
+++ b/plat/brcm/board/stingray/include/sr_utils.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SR_UTILS_H
+#define SR_UTILS_H
+
+#include <lib/mmio.h>
+
+#include <chip_id.h>
+#include <cmn_plat_util.h>
+#include <sr_def.h>
+
+static inline void brcm_stingray_set_qspi_mux(int enable_ap)
+{
+ mmio_write_32(QSPI_HOLD_N_MODE_SEL_CONTROL, enable_ap);
+ mmio_write_32(QSPI_WP_N_MODE_SEL_CONTROL, enable_ap);
+ mmio_write_32(QSPI_SCK_MODE_SEL_CONTROL, enable_ap);
+ mmio_write_32(QSPI_CS_N_MODE_SEL_CONTROL, enable_ap);
+ mmio_write_32(QSPI_MOSI_MODE_SEL_CONTROL, enable_ap);
+ mmio_write_32(QSPI_MISO_MODE_SEL_CONTROL, enable_ap);
+}
+
+static inline void brcm_stingray_set_straps(uint32_t boot_source)
+{
+ /* Enable software strap override */
+ mmio_setbits_32(CDRU_CHIP_STRAP_CTRL,
+ BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE));
+
+ /* set straps to the next boot source */
+ mmio_clrsetbits_32(CDRU_CHIP_STRAP_DATA,
+ BOOT_SOURCE_MASK,
+ boot_source);
+
+ /* Disable software strap override */
+ mmio_clrbits_32(CDRU_CHIP_STRAP_CTRL,
+ BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE));
+}
+
+#endif
diff --git a/plat/brcm/board/stingray/include/swreg.h b/plat/brcm/board/stingray/include/swreg.h
new file mode 100644
index 0000000..6e971ce
--- /dev/null
+++ b/plat/brcm/board/stingray/include/swreg.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SWREG_H
+#define SWREG_H
+
+/* default voltage if no valid OTP */
+#define VDDC_CORE_DEF_VOLT 910000 /* 0.91v */
+#define IHOST_DEF_VOLT 940000 /* 0.94v */
+
+#define B0_VDDC_CORE_DEF_VOLT 950000 /* 0.95v */
+#define B0_IHOST_DEF_VOLT 950000 /* 0.95v */
+#define B0_DDR_VDDC_DEF_VOLT 1000000 /* 1v */
+
+#define SWREG_IHOST1_DIS 4
+#define SWREG_IHOST1_REG_RESETB 5
+#define SWREG_IHOST1_PMU_STABLE 2
+
+enum sw_reg {
+ DDR_VDDC = 1,
+ IHOST03,
+ IHOST12,
+ IHOST_ARRAY,
+ DDRIO_SLAVE,
+ VDDC_CORE,
+ VDDC1,
+ DDRIO_MASTER
+};
+
+int set_swreg(enum sw_reg reg_id, uint32_t micro_volts);
+int swreg_firmware_update(void);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/timer_sync.h b/plat/brcm/board/stingray/include/timer_sync.h
new file mode 100644
index 0000000..1f15bb0
--- /dev/null
+++ b/plat/brcm/board/stingray/include/timer_sync.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TIMER_SYNC_H
+#define TIMER_SYNC_H
+
+void brcm_timer_sync_init(void);
+
+#endif
diff --git a/plat/brcm/board/stingray/include/usb_phy.h b/plat/brcm/board/stingray/include/usb_phy.h
new file mode 100644
index 0000000..7d83182
--- /dev/null
+++ b/plat/brcm/board/stingray/include/usb_phy.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2017 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef USB_PHY_H
+#define USB_PHY_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#define DRDU2_U2PLL_NDIV_FRAC_OFFSET 0x0U
+
+#define DRDU2_U2PLL_NDIV_INT 0x4U
+
+#define DRDU2_U2PLL_CTRL 0x8U
+#define DRDU2_U2PLL_LOCK BIT(6U)
+#define DRDU2_U2PLL_RESETB BIT(5U)
+#define DRDU2_U2PLL_PDIV_MASK 0xFU
+#define DRDU2_U2PLL_PDIV_OFFSET 1U
+#define DRDU2_U2PLL_SUSPEND_EN BIT(0U)
+
+#define DRDU2_PHY_CTRL 0x0CU
+#define DRDU2_U2IDDQ BIT(30U)
+#define DRDU2_U2SOFT_RST_N BIT(29U)
+#define DRDU2_U2PHY_ON_FLAG BIT(22U)
+#define DRDU2_U2PHY_PCTL_MASK 0xFFFFU
+#define DRDU2_U2PHY_PCTL_OFFSET 6U
+#define DRDU2_U2PHY_RESETB BIT(5U)
+#define DRDU2_U2PHY_ISO BIT(4U)
+#define DRDU2_U2AFE_BG_PWRDWNB BIT(3U)
+#define DRDU2_U2AFE_PLL_PWRDWNB BIT(2U)
+#define DRDU2_U2AFE_LDO_PWRDWNB BIT(1U)
+#define DRDU2_U2CTRL_CORERDY BIT(0U)
+
+#define DRDU2_STRAP_CTRL 0x18U
+#define DRDU2_FORCE_HOST_MODE BIT(5U)
+#define DRDU2_FORCE_DEVICE_MODE BIT(4U)
+#define BDC_USB_STP_SPD_MASK 0x7U
+#define BDC_USB_STP_SPD_OFFSET 0U
+
+#define DRDU2_PWR_CTRL 0x1CU
+#define DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I BIT(2U)
+#define DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I BIT(1U)
+
+#define DRDU2_SOFT_RESET_CTRL 0x20U
+#define DRDU2_BDC_AXI_SOFT_RST_N BIT(0U)
+
+#define USB3H_U2PLL_NDIV_FRAC 0x4U
+
+#define USB3H_U2PLL_NDIV_INT 0x8U
+
+#define USB3H_U2PLL_CTRL 0xCU
+#define USB3H_U2PLL_LOCK BIT(6U)
+#define USB3H_U2PLL_RESETB BIT(5U)
+#define USB3H_U2PLL_PDIV_MASK 0xFU
+#define USB3H_U2PLL_PDIV_OFFSET 1U
+
+#define USB3H_U2PHY_CTRL 0x10U
+#define USB3H_U2PHY_ON_FLAG 22U
+#define USB3H_U2PHY_PCTL_MASK 0xFFFFU
+#define USB3H_U2PHY_PCTL_OFFSET 6U
+#define USB3H_U2PHY_IDDQ BIT(29U)
+#define USB3H_U2PHY_RESETB BIT(5U)
+#define USB3H_U2PHY_ISO BIT(4U)
+#define USB3H_U2AFE_BG_PWRDWNB BIT(3U)
+#define USB3H_U2AFE_PLL_PWRDWNB BIT(2U)
+#define USB3H_U2AFE_LDO_PWRDWNB BIT(1U)
+#define USB3H_U2CTRL_CORERDY BIT(0U)
+
+#define USB3H_U3PHY_CTRL 0x14U
+#define USB3H_U3SOFT_RST_N BIT(30U)
+#define USB3H_U3MDIO_RESETB_I BIT(29U)
+#define USB3H_U3POR_RESET_I BIT(28U)
+#define USB3H_U3PHY_PCTL_MASK 0xFFFFU
+#define USB3H_U3PHY_PCTL_OFFSET 2U
+#define USB3H_U3PHY_RESETB BIT(1U)
+
+#define USB3H_U3PHY_PLL_CTRL 0x18U
+#define USB3H_U3PLL_REFCLK_MASK 0x7U
+#define USB3H_U3PLL_REFCLK_OFFSET 4U
+#define USB3H_U3PLL_SS_LOCK BIT(3U)
+#define USB3H_U3PLL_SEQ_START BIT(2U)
+#define USB3H_U3SSPLL_SUSPEND_EN BIT(1U)
+#define USB3H_U3PLL_RESETB BIT(0U)
+
+#define USB3H_PWR_CTRL 0x28U
+#define USB3H_PWR_CTRL_OVERRIDE_I_R 4U
+#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN BIT(11U)
+#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN BIT(10U)
+
+#define USB3H_SOFT_RESET_CTRL 0x2CU
+#define USB3H_XHC_AXI_SOFT_RST_N BIT(1U)
+
+#define USB3H_PHY_PWR_CTRL 0x38U
+#define USB3H_DISABLE_USB30_P0 BIT(2U)
+#define USB3H_DISABLE_EUSB_P1 BIT(1U)
+#define USB3H_DISABLE_EUSB_P0 BIT(0U)
+
+
+#define DRDU3_U2PLL_NDIV_FRAC 0x4U
+
+#define DRDU3_U2PLL_NDIV_INT 0x8U
+
+#define DRDU3_U2PLL_CTRL 0xCU
+#define DRDU3_U2PLL_LOCK BIT(6U)
+#define DRDU3_U2PLL_RESETB BIT(5U)
+#define DRDU3_U2PLL_PDIV_MASK 0xFU
+#define DRDU3_U2PLL_PDIV_OFFSET 1U
+
+#define DRDU3_U2PHY_CTRL 0x10U
+#define DRDU3_U2PHY_IDDQ BIT(29U)
+#define DRDU3_U2PHY_ON_FLAG BIT(22U)
+#define DRDU3_U2PHY_PCTL_MASK 0xFFFFU
+#define DRDU3_U2PHY_PCTL_OFFSET 6U
+#define DRDU3_U2PHY_RESETB BIT(5U)
+#define DRDU3_U2PHY_ISO BIT(4U)
+#define DRDU3_U2AFE_BG_PWRDWNB BIT(3U)
+#define DRDU3_U2AFE_PLL_PWRDWNB BIT(2U)
+#define DRDU3_U2AFE_LDO_PWRDWNB BIT(1U)
+#define DRDU3_U2CTRL_CORERDY BIT(0U)
+
+#define DRDU3_U3PHY_CTRL 0x14U
+#define DRDU3_U3XHC_SOFT_RST_N BIT(31U)
+#define DRDU3_U3BDC_SOFT_RST_N BIT(30U)
+#define DRDU3_U3MDIO_RESETB_I BIT(29U)
+#define DRDU3_U3POR_RESET_I BIT(28U)
+#define DRDU3_U3PHY_PCTL_MASK 0xFFFFU
+#define DRDU3_U3PHY_PCTL_OFFSET 2U
+#define DRDU3_U3PHY_RESETB BIT(1U)
+
+#define DRDU3_U3PHY_PLL_CTRL 0x18U
+#define DRDU3_U3PLL_REFCLK_MASK 0x7U
+#define DRDU3_U3PLL_REFCLK_OFFSET 4U
+#define DRDU3_U3PLL_SS_LOCK BIT(3U)
+#define DRDU3_U3PLL_SEQ_START BIT(2U)
+#define DRDU3_U3SSPLL_SUSPEND_EN BIT(1U)
+#define DRDU3_U3PLL_RESETB BIT(0U)
+
+#define DRDU3_STRAP_CTRL 0x28U
+#define BDC_USB_STP_SPD_MASK 0x7U
+#define BDC_USB_STP_SPD_OFFSET 0U
+#define BDC_USB_STP_SPD_SS 0x0U
+#define BDC_USB_STP_SPD_HS 0x2U
+
+#define DRDU3_PWR_CTRL 0x2cU
+#define DRDU3_U2PHY_DFE_SWITCH_PWROKIN BIT(12U)
+#define DRDU3_U2PHY_DFE_SWITCH_PWRONIN BIT(11U)
+#define DRDU3_PWR_CTRL_OVERRIDE_I_R 4U
+
+#define DRDU3_SOFT_RESET_CTRL 0x30U
+#define DRDU3_XHC_AXI_SOFT_RST_N BIT(1U)
+#define DRDU3_BDC_AXI_SOFT_RST_N BIT(0U)
+
+#define DRDU3_PHY_PWR_CTRL 0x3cU
+#define DRDU3_DISABLE_USB30_P0 BIT(2U)
+#define DRDU3_DISABLE_EUSB_P1 BIT(1U)
+#define DRDU3_DISABLE_EUSB_P0 BIT(0U)
+
+#define PLL_REFCLK_PAD 0x0U
+#define PLL_REFCLK_25MHZ 0x1U
+#define PLL_REFCLK_96MHZ 0x2U
+#define PLL_REFCLK_INTERNAL 0x3U
+/* USB PLL lock time out for 10 ms */
+#define PLL_LOCK_RETRY_COUNT 10000U
+
+
+#define U2PLL_NDIV_INT_VAL 0x13U
+#define U2PLL_NDIV_FRAC_VAL 0x1005U
+#define U2PLL_PDIV_VAL 0x1U
+/*
+ * Using external FSM
+ * BIT-3:2: device mode; mode is not effect
+ * BIT-1: soft reset active low
+ */
+#define U2PHY_PCTL_VAL 0x0003U
+/* Non-driving signal low */
+#define U2PHY_PCTL_NON_DRV_LOW 0x0002U
+#define U3PHY_PCTL_VAL 0x0006U
+
+#define MAX_NR_PORTS 3U
+
+#define USB3H_DRDU2_PHY 1U
+#define DRDU3_PHY 2U
+
+#define USB_HOST_MODE 1U
+#define USB_DEV_MODE 2U
+
+#define USB3SS_PORT 0U
+#define DRDU2_PORT 1U
+#define USB3HS_PORT 2U
+
+#define DRD3SS_PORT 0U
+#define DRD3HS_PORT 1U
+
+#define SR_USB_PHY_COUNT 2U
+
+#define DRDU3_PIPE_CTRL 0x68500000U
+#define DRDU3H_XHC_REGS_CPLIVER 0x68501000U
+#define USB3H_PIPE_CTRL 0x68510000U
+#define DRD2U3H_XHC_REGS_CPLIVER 0x68511000U
+#define DRDU2_U2PLL_NDIV_FRAC 0x68520000U
+
+#define AXI_DEBUG_CTRL 0x68500038U
+#define AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE BIT(12U)
+
+#define USB3H_DEBUG_CTRL 0x68510034U
+#define USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE BIT(7U)
+
+typedef struct _usb_phy_port usb_phy_port_t;
+
+typedef struct {
+ uint32_t drdu2reg;
+ uint32_t usb3hreg;
+ uint32_t drdu3reg;
+ uint32_t phy_id;
+ uint32_t ports_enabled;
+ uint32_t initialized;
+ usb_phy_port_t *phy_port;
+} usb_phy_t;
+
+struct _usb_phy_port {
+ uint32_t port_id;
+ uint32_t mode;
+ uint32_t enabled;
+ usb_phy_t *p;
+};
+
+struct u2_phy_ext_fsm {
+ uint32_t pll_ctrl_reg;
+ uint32_t phy_ctrl_reg;
+ uint32_t phy_iddq;
+ uint32_t pwr_ctrl_reg;
+ uint32_t pwr_okin;
+ uint32_t pwr_onin;
+};
+
+#endif /* USB_PHY_H */
diff --git a/plat/brcm/board/stingray/platform.mk b/plat/brcm/board/stingray/platform.mk
new file mode 100644
index 0000000..aa2fe86
--- /dev/null
+++ b/plat/brcm/board/stingray/platform.mk
@@ -0,0 +1,304 @@
+#
+# Copyright (c) 2019-2021, Broadcom
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Set the toc_flags to 1 for 100% speed operation
+# Set the toc_flags to 2 for 50% speed operation
+# Set the toc_flags to 3 for 25% speed operation
+# Set the toc_flags bit 3 to indicate ignore the fip in UEFI copy mode
+PLAT_TOC_FLAGS := 0x0
+
+# Set the IHOST_PLL_FREQ to,
+# 1 for full speed
+# 2 for 50% speed
+# 3 for 25% speed
+# 0 for bypass
+$(eval $(call add_define_val,IHOST_PLL_FREQ,1))
+
+# Enable workaround for ERRATA_A72_859971
+ERRATA_A72_859971 := 1
+
+# Cache Coherency Interconnect Driver needed
+DRIVER_CC_ENABLE := 1
+$(eval $(call add_define,DRIVER_CC_ENABLE))
+
+# Enable to erase eMMC
+INCLUDE_EMMC_DRIVER_ERASE_CODE := 0
+
+ifeq (${INCLUDE_EMMC_DRIVER_ERASE_CODE},1)
+$(eval $(call add_define,INCLUDE_EMMC_DRIVER_ERASE_CODE))
+endif
+
+# BL31 is in DRAM
+ARM_BL31_IN_DRAM := 1
+
+ifneq (${USE_EMULATOR},yes)
+STINGRAY_EMULATION_SETUP := 0
+ifeq (${FASTBOOT_TYPE},)
+override FASTBOOT_TYPE := 0
+endif
+USE_PAXB := yes
+USE_PAXC := yes
+USE_CHIMP := yes
+endif
+
+USE_CRMU_SRAM := yes
+
+# Disable FS4 clocks - they can be reenabled when needed by linux
+FS4_DISABLE_CLOCK := yes
+
+# Enable error logging by default for Stingray
+BCM_ELOG := yes
+
+# Enable FRU support by default for Stingray
+ifeq (${USE_FRU},)
+USE_FRU := no
+endif
+
+# Use single cluster
+ifeq (${USE_SINGLE_CLUSTER},yes)
+$(info Using Single Cluster)
+$(eval $(call add_define,USE_SINGLE_CLUSTER))
+endif
+
+# Use DDR
+ifeq (${USE_DDR},yes)
+$(info Using DDR)
+$(eval $(call add_define,USE_DDR))
+endif
+
+ifeq (${BOARD_CFG},)
+BOARD_CFG := bcm958742t
+endif
+
+# Use USB
+ifeq (${USE_USB},yes)
+$(info Using USB)
+$(eval $(call add_define,USE_USB))
+endif
+
+# Use PAXB
+ifeq (${USE_PAXB},yes)
+$(info Using PAXB)
+$(eval $(call add_define,USE_PAXB))
+endif
+
+# Use FS4
+ifeq (${USE_FS4},yes)
+$(info Using FS4)
+$(eval $(call add_define,USE_FS4))
+endif
+
+# Use FS6
+ifeq (${USE_FS6},yes)
+$(info Using FS6)
+$(eval $(call add_define,USE_FS6))
+endif
+
+# Disable FS4 clock
+ifeq (${FS4_DISABLE_CLOCK},yes)
+$(info Using FS4_DISABLE_CLOCK)
+$(eval $(call add_define,FS4_DISABLE_CLOCK))
+endif
+
+ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
+$(info Using NCSI_IO_DRIVE_STRENGTH_MA)
+$(eval $(call add_define,NCSI_IO_DRIVE_STRENGTH_MA))
+endif
+
+# Use NAND
+ifeq (${USE_NAND},$(filter yes, ${USE_NAND}))
+$(info Using NAND)
+$(eval $(call add_define,USE_NAND))
+endif
+
+# Enable Broadcom error logging support
+ifeq (${BCM_ELOG},yes)
+$(info Using BCM_ELOG)
+$(eval $(call add_define,BCM_ELOG))
+endif
+
+# BL31 build for standalone mode
+ifeq (${STANDALONE_BL31},yes)
+RESET_TO_BL31 := 1
+$(info Using RESET_TO_BL31)
+endif
+
+# BL31 force full frequency for all CPUs
+ifeq (${BL31_FORCE_CPU_FULL_FREQ},yes)
+$(info Using BL31_FORCE_CPU_FULL_FREQ)
+$(eval $(call add_define,BL31_FORCE_CPU_FULL_FREQ))
+endif
+
+# Enable non-secure accesses to CCN registers
+ifeq (${BL31_CCN_NONSECURE},yes)
+$(info Using BL31_CCN_NONSECURE)
+$(eval $(call add_define,BL31_CCN_NONSECURE))
+endif
+
+# Use ChiMP
+ifeq (${USE_CHIMP},yes)
+$(info Using ChiMP)
+$(eval $(call add_define,USE_CHIMP))
+endif
+
+# Use PAXC
+ifeq (${USE_PAXC},yes)
+$(info Using PAXC)
+$(eval $(call add_define,USE_PAXC))
+ifeq (${CHIMPFW_USE_SIDELOAD},yes)
+$(info Using ChiMP FW sideload)
+$(eval $(call add_define,CHIMPFW_USE_SIDELOAD))
+endif
+$(eval $(call add_define,FASTBOOT_TYPE))
+$(eval $(call add_define,CHIMP_FB1_ENTRY))
+endif
+
+ifeq (${DEFAULT_SWREG_CONFIG}, 1)
+$(eval $(call add_define,DEFAULT_SWREG_CONFIG))
+endif
+
+ifeq (${CHIMP_ALWAYS_NEEDS_QSPI},yes)
+$(eval $(call add_define,CHIMP_ALWAYS_NEEDS_QSPI))
+endif
+
+# For testing purposes, use memsys stubs. Remove once memsys is fully tested.
+USE_MEMSYS_STUBS := yes
+
+# Default, use BL1_RW area
+ifneq (${BL2_USE_BL1_RW},no)
+$(eval $(call add_define,USE_BL1_RW))
+endif
+
+# Default soft reset is L3
+$(eval $(call add_define,CONFIG_SOFT_RESET_L3))
+
+# Enable Chip OTP driver
+DRIVER_OCOTP_ENABLE := 1
+
+ifneq (${WARMBOOT_DDR_S3_SUPPORT},)
+DRIVER_SPI_ENABLE := 1
+endif
+
+include plat/brcm/board/common/board_common.mk
+
+SOC_DIR := brcm/board/stingray
+
+PLAT_INCLUDES += -Iplat/${SOC_DIR}/include/ \
+ -Iinclude/plat/brcm/common/ \
+ -Iplat/brcm/common/
+
+PLAT_BL_COMMON_SOURCES += lib/cpus/aarch64/cortex_a72.S \
+ plat/${SOC_DIR}/aarch64/plat_helpers.S \
+ drivers/ti/uart/aarch64/16550_console.S \
+ plat/${SOC_DIR}/src/tz_sec.c \
+ drivers/arm/tzc/tzc400.c \
+ plat/${SOC_DIR}/driver/plat_emmc.c \
+ plat/${SOC_DIR}/src/topology.c \
+ drivers/brcm/mdio/mdio.c
+
+ifeq (${USE_CHIMP},yes)
+PLAT_BL_COMMON_SOURCES += drivers/brcm/chimp.c
+endif
+
+ifeq (${USE_USB},yes)
+PLAT_BL_COMMON_SOURCES += plat/${SOC_DIR}/driver/usb.c \
+ plat/${SOC_DIR}/driver/usb_phy.c
+endif
+
+BL2_SOURCES += plat/${SOC_DIR}/driver/ihost_pll_config.c \
+ plat/${SOC_DIR}/src/bl2_setup.c \
+ plat/${SOC_DIR}/driver/swreg.c
+
+ifeq (${USE_DDR},yes)
+PLAT_INCLUDES += -Iplat/${SOC_DIR}/driver/ddr/soc/include
+else
+PLAT_INCLUDES += -Iplat/${SOC_DIR}/driver/ext_sram_init
+BL2_SOURCES += plat/${SOC_DIR}/driver/ext_sram_init/ext_sram_init.c
+endif
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+BRCM_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/brcm/common/brcm_gicv3.c
+
+BL31_SOURCES += \
+ drivers/arm/ccn/ccn.c \
+ plat/brcm/board/common/timer_sync.c \
+ plat/brcm/common/brcm_ccn.c \
+ plat/common/plat_psci_common.c \
+ plat/${SOC_DIR}/driver/ihost_pll_config.c \
+ plat/${SOC_DIR}/src/bl31_setup.c \
+ plat/${SOC_DIR}/src/fsx.c \
+ plat/${SOC_DIR}/src/iommu.c \
+ plat/${SOC_DIR}/src/sdio.c \
+ ${BRCM_GIC_SOURCES}
+
+ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
+BL31_SOURCES += plat/${SOC_DIR}/src/ncsi.c
+endif
+
+ifeq (${USE_PAXB},yes)
+BL31_SOURCES += plat/${SOC_DIR}/src/paxb.c
+BL31_SOURCES += plat/${SOC_DIR}/src/sr_paxb_phy.c
+endif
+
+ifeq (${USE_PAXC},yes)
+BL31_SOURCES += plat/${SOC_DIR}/src/paxc.c
+endif
+
+ifdef SCP_BL2
+PLAT_INCLUDES += -Iplat/brcm/common/
+
+BL2_SOURCES += plat/brcm/common/brcm_mhu.c \
+ plat/brcm/common/brcm_scpi.c \
+ plat/${SOC_DIR}/src/scp_utils.c \
+ plat/${SOC_DIR}/src/scp_cmd.c \
+ drivers/brcm/scp.c
+
+BL31_SOURCES += plat/brcm/common/brcm_mhu.c \
+ plat/brcm/common/brcm_scpi.c \
+ plat/${SOC_DIR}/src/brcm_pm_ops.c
+else
+BL31_SOURCES += plat/${SOC_DIR}/src/ihost_pm.c \
+ plat/${SOC_DIR}/src/pm.c
+endif
+
+ifeq (${ELOG_SUPPORT},1)
+ifeq (${ELOG_STORE_MEDIA},DDR)
+BL2_SOURCES += plat/brcm/board/common/bcm_elog_ddr.c
+endif
+endif
+
+ifeq (${BL31_BOOT_PRELOADED_SCP}, 1)
+ifdef SCP_BL2
+SCP_CFG_DIR=$(dir ${SCP_BL2})
+PLAT_INCLUDES += -I${SCP_CFG_DIR}
+endif
+PLAT_INCLUDES += -Iplat/brcm/common/
+
+# By default use OPTEE Assigned memory
+PRELOADED_SCP_BASE ?= 0x8E000000
+PRELOADED_SCP_SIZE ?= 0x10000
+$(eval $(call add_define,PRELOADED_SCP_BASE))
+$(eval $(call add_define,PRELOADED_SCP_SIZE))
+$(eval $(call add_define,BL31_BOOT_PRELOADED_SCP))
+BL31_SOURCES += plat/${SOC_DIR}/src/scp_utils.c \
+ plat/${SOC_DIR}/src/scp_cmd.c \
+ drivers/brcm/scp.c
+endif
+
+# Do not execute the startup code on warm reset.
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+# Nitro FW, config and Crash log uses secure DDR memory
+# Inaddition to above, Nitro master and slave is also secure
+ifneq ($(NITRO_SECURE_ACCESS),)
+$(eval $(call add_define,NITRO_SECURE_ACCESS))
+$(eval $(call add_define,DDR_NITRO_SECURE_REGION_START))
+$(eval $(call add_define,DDR_NITRO_SECURE_REGION_END))
+endif
diff --git a/plat/brcm/board/stingray/src/bl2_setup.c b/plat/brcm/board/stingray/src/bl2_setup.c
new file mode 100644
index 0000000..b2c8aec
--- /dev/null
+++ b/plat/brcm/board/stingray/src/bl2_setup.c
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2016-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <chimp.h>
+#include <chip_id.h>
+#include <cmn_plat_util.h>
+#include <dmu.h>
+#include <emmc_api.h>
+#include <fru.h>
+#ifdef USE_GPIO
+#include <drivers/gpio.h>
+#include <iproc_gpio.h>
+#endif
+#include <platform_def.h>
+#include <sotp.h>
+#include <swreg.h>
+#include <sr_utils.h>
+#ifdef USE_DDR
+#include <ddr_init.h>
+#else
+#include <ext_sram_init.h>
+#endif
+#if DRIVER_OCOTP_ENABLE
+#include <ocotp.h>
+#endif
+#include "board_info.h"
+
+#define WORD_SIZE 8
+#define SWREG_AVS_OTP_OFFSET (13 * WORD_SIZE) /* 13th row byte offset */
+#define AON_GPIO_OTP_OFFSET (28 * WORD_SIZE) /* 28th row byte offset */
+#define BYTES_TO_READ 8
+
+/* OTP voltage step definitions */
+#define MVOLT_STEP_MAX 0x18 /* 1v */
+#define MVOLT_PER_STEP 10 /* 0.01mv per step */
+#define MVOLT_BASE 760 /* 0.76v */
+
+#define STEP_TO_UVOLTS(step) \
+ ((MVOLT_BASE + (MVOLT_PER_STEP * (step))) * 1000)
+
+#define GET_BITS(first, last, data) \
+ ((data >> first) & ((1 << (last - first + 1)) - 1))
+
+/*
+ * SW-REG OTP encoding:
+ *
+ * SWREG_bits[11:0] = OTP 13th row 12 bits[55:44]
+ * SWREG_bits[11:10] - Valid Bits (0x2 - valid, if not 0x2 - Invalid)
+ * SWREG_bits[9:5] - iHost03, iHost12
+ * SWREG_bits[4:0] - Core VDDC
+ */
+#define SWREG_OTP_BITS_START 12 /* 44th bit in MSB 32-bits */
+#define SWREG_OTP_BITS_END 23 /* 55th bit in MSB 32-bits */
+#define SWREG_VDDC_FIELD_START 0
+#define SWREG_VDDC_FIELD_END 4
+#define SWREG_IHOST_FIELD_START 5
+#define SWREG_IHOST_FIELD_END 9
+#define SWREG_VALID_BIT_START 10
+#define SWREG_VALID_BIT_END 11
+#define SWREG_VALID_BITS 0x2
+
+/*
+ * Row 13 bit 56 is programmed as '1' today. It is not being used, so plan
+ * is to flip this bit to '0' for B1 rev. Hence SW can leverage this bit
+ * to identify Bx chip to program different sw-regulators.
+ */
+#define SPARE_BIT 24
+
+#define IS_SR_B0(data) (((data) >> SPARE_BIT) & 0x1)
+
+#if DRIVER_OCOTP_ENABLE
+static struct otpc_map otp_stingray_map = {
+ .otpc_row_size = 2,
+ .data_r_offset = {0x10, 0x5c},
+ .data_w_offset = {0x2c, 0x64},
+ .word_size = 8,
+ .stride = 8,
+};
+#endif
+
+void plat_bcm_bl2_early_platform_setup(void)
+{
+ /* Select UART0 for AP via mux setting*/
+ if (PLAT_BRCM_BOOT_UART_BASE == UART0_BASE_ADDR) {
+ mmio_write_32(UART0_SIN_MODE_SEL_CONTROL, 1);
+ mmio_write_32(UART0_SOUT_MODE_SEL_CONTROL, 1);
+ }
+}
+
+#ifdef USE_NAND
+static void brcm_stingray_nand_init(void)
+{
+ unsigned int val;
+ unsigned int nand_idm_reset_control = 0x68e0a800;
+
+ VERBOSE(" stingray nand init start.\n");
+
+ /* Reset NAND */
+ VERBOSE(" - reset nand\n");
+ val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0));
+ mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val | 0x1);
+ udelay(500);
+ val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0));
+ mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val & ~0x1);
+ udelay(500);
+
+ VERBOSE(" stingray nand init done.\n");
+}
+#endif
+
+#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA)
+#define PCIE_RESCAL_CFG_0 0x40000130
+#define PCIE_CFG_RESCAL_RSTB_R (1 << 16)
+#define PCIE_CFG_RESCAL_PWRDNB_R (1 << 8)
+#define PCIE_RESCAL_STATUS_0 0x4000014c
+#define PCIE_STAT_PON_VALID_R (1 << 0)
+#define PCIE_RESCAL_OUTPUT_STATUS 0x40000154
+#define CDRU_PCIE_RESET_N_R (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R)
+
+#ifdef EMULATION_SETUP
+static void brcm_stingray_pcie_reset(void)
+{
+}
+#else
+static void brcm_stingray_pcie_reset(void)
+{
+ unsigned int data;
+ int try;
+
+ if (bcm_chimp_is_nic_mode()) {
+ INFO("NIC mode detected; PCIe reset/rescal not executed\n");
+ return;
+ }
+
+ mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R);
+ mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R);
+ /* Release reset */
+ mmio_setbits_32(PCIE_RESCAL_CFG_0, PCIE_CFG_RESCAL_RSTB_R);
+ mdelay(1);
+ /* Power UP */
+ mmio_setbits_32(PCIE_RESCAL_CFG_0,
+ (PCIE_CFG_RESCAL_RSTB_R | PCIE_CFG_RESCAL_PWRDNB_R));
+
+ try = 1000;
+ do {
+ udelay(1);
+ data = mmio_read_32(PCIE_RESCAL_STATUS_0);
+ try--;
+ } while ((data & PCIE_STAT_PON_VALID_R) == 0x0 && (try > 0));
+
+ if (try <= 0)
+ ERROR("PCIE_RESCAL_STATUS_0: 0x%x\n", data);
+
+ VERBOSE("PCIE_SATA_RESCAL_STATUS_0 0x%x.\n",
+ mmio_read_32(PCIE_RESCAL_STATUS_0));
+ VERBOSE("PCIE_SATA_RESCAL_OUTPUT_STATUS 0x%x.\n",
+ mmio_read_32(PCIE_RESCAL_OUTPUT_STATUS));
+ INFO("PCIE SATA Rescal Init done\n");
+}
+#endif /* EMULATION_SETUP */
+#endif /* USE_PAXB || USE_PAXC || USE_SATA */
+
+#ifdef USE_PAXC
+void brcm_stingray_chimp_check_and_fastboot(void)
+{
+ int fastboot_init_result;
+
+ if (bcm_chimp_is_nic_mode())
+ /* Do not wait here */
+ return;
+
+#if WARMBOOT_DDR_S3_SUPPORT
+ /*
+ * Currently DDR shmoo parameters and QSPI boot source are
+ * tied. DDR shmoo parameters are stored in QSPI, which is
+ * used for warmboot.
+ * Do not reset nitro for warmboot
+ */
+ if (is_warmboot() && (boot_source_get() == BOOT_SOURCE_QSPI))
+ return;
+#endif /* WARMBOOT_DDR_S3_SUPPORT */
+
+ /*
+ * Not in NIC mode,
+ * initiate fastboot (if enabled)
+ */
+ if (FASTBOOT_TYPE == CHIMP_FASTBOOT_NITRO_RESET) {
+
+ VERBOSE("Bring up Nitro/ChiMP\n");
+
+ if (boot_source_get() == BOOT_SOURCE_QSPI)
+ WARN("Nitro boots from QSPI when AP has booted from QSPI.\n");
+ brcm_stingray_set_qspi_mux(0);
+ VERBOSE("Nitro controls the QSPI\n");
+ }
+
+ fastboot_init_result = bcm_chimp_initiate_fastboot(FASTBOOT_TYPE);
+ if (fastboot_init_result && boot_source_get() != BOOT_SOURCE_QSPI)
+ ERROR("Nitro init error %d. Status: 0x%x; bpe_mod reg: 0x%x\n"
+ "fastboot register: 0x%x; handshake register 0x%x\n",
+ fastboot_init_result,
+ bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG),
+ bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG),
+ bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
+ bcm_chimp_read(CHIMP_REG_ECO_RESERVED));
+
+ /*
+ * CRMU watchdog kicks is an example, which is L1 reset,
+ * does not clear Nitro scratch pad ram.
+ * For Nitro resets: Clear the Nitro health status memory.
+ */
+ bcm_chimp_write((CHIMP_REG_CHIMP_SCPAD + CHIMP_HEALTH_STATUS_OFFSET),
+ 0);
+}
+#endif
+
+void set_ihost_vddc_swreg(uint32_t ihost_uvolts, uint32_t vddc_uvolts)
+{
+ NOTICE("ihost_uvolts: %duv, vddc_uvolts: %duv\n",
+ ihost_uvolts, vddc_uvolts);
+
+ set_swreg(VDDC_CORE, vddc_uvolts);
+ set_swreg(IHOST03, ihost_uvolts);
+ set_swreg(IHOST12, ihost_uvolts);
+}
+
+/*
+ * Reads SWREG AVS OTP bits (13th row) with ECC enabled and get voltage
+ * defined in OTP if valid OTP is found
+ */
+void read_avs_otp_bits(uint32_t *ihost_uvolts, uint32_t *vddc_uvolts)
+{
+ uint32_t offset = SWREG_AVS_OTP_OFFSET;
+ uint32_t ihost_step, vddc_step;
+ uint32_t avs_bits;
+ uint32_t buf[2];
+
+ if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1)
+ return;
+
+ VERBOSE("AVS OTP %d ROW: 0x%x.0x%x\n",
+ offset/WORD_SIZE, buf[1], buf[0]);
+
+ /* get voltage readings from AVS OTP bits */
+ avs_bits = GET_BITS(SWREG_OTP_BITS_START,
+ SWREG_OTP_BITS_END,
+ buf[1]);
+
+ /* check for valid otp bits */
+ if (GET_BITS(SWREG_VALID_BIT_START, SWREG_VALID_BIT_END, avs_bits) !=
+ SWREG_VALID_BITS) {
+ WARN("Invalid AVS OTP bits at %d row\n", offset/WORD_SIZE);
+ return;
+ }
+
+ /* get ihost and vddc step value */
+ vddc_step = GET_BITS(SWREG_VDDC_FIELD_START,
+ SWREG_VDDC_FIELD_END,
+ avs_bits);
+
+ ihost_step = GET_BITS(SWREG_IHOST_FIELD_START,
+ SWREG_IHOST_FIELD_END,
+ avs_bits);
+
+ if ((ihost_step > MVOLT_STEP_MAX) || (vddc_step > MVOLT_STEP_MAX)) {
+ WARN("OTP entry invalid\n");
+ return;
+ }
+
+ /* get voltage in micro-volts */
+ *ihost_uvolts = STEP_TO_UVOLTS(ihost_step);
+ *vddc_uvolts = STEP_TO_UVOLTS(vddc_step);
+}
+
+/*
+ * This api reads otp bits and program internal swreg's - ihos12, ihost03,
+ * vddc_core and ddr_core based on different chip. External swreg's
+ * programming will be done from crmu.
+ *
+ * For A2 chip:
+ * Read OTP row 20, bit 50. This bit will be set for A2 chip. Once A2 chip is
+ * found, read AVS OTP row 13, 12bits[55:44], if valid otp bits are found
+ * then set ihost and vddc according to avs otp bits else set them to 0.94v
+ * and 0.91v respectively. Also update the firmware after setting voltage.
+ *
+ * For B0 chip:
+ * Read OTP row 13, bit 56. This bit will be set for B0 chip. Once B0 chip is
+ * found then set ihost and vddc to 0.95v and ddr_core to 1v. No AVS OTP bits
+ * are used get ihost/vddc voltages.
+ *
+ * For B1 chip:
+ * Read AVS OTP row 13, 12bits[55:44], if valid otp bits are found then set
+ * ihost and vddc according to avs otp bits else set them to 0.94v and 0.91v
+ * respectively.
+ */
+void set_swreg_based_on_otp(void)
+{
+ /* default voltage if no valid OTP */
+ uint32_t vddc_uvolts = VDDC_CORE_DEF_VOLT;
+ uint32_t ihost_uvolts = IHOST_DEF_VOLT;
+ uint32_t ddrc_uvolts;
+ uint32_t offset;
+ uint32_t buf[2];
+
+ offset = SWREG_AVS_OTP_OFFSET;
+ if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1)
+ return;
+
+ VERBOSE("OTP %d ROW: 0x%x.0x%x\n",
+ offset/WORD_SIZE, buf[1], buf[0]);
+
+ if (IS_SR_B0(buf[1])) {
+ /* don't read AVS OTP for B0 */
+ ihost_uvolts = B0_IHOST_DEF_VOLT;
+ vddc_uvolts = B0_VDDC_CORE_DEF_VOLT;
+ ddrc_uvolts = B0_DDR_VDDC_DEF_VOLT;
+ } else {
+ read_avs_otp_bits(&ihost_uvolts, &vddc_uvolts);
+ }
+
+#if (IHOST_REG_TYPE == IHOST_REG_INTEGRATED) && \
+ (VDDC_REG_TYPE == VDDC_REG_INTEGRATED)
+ /* enable IHOST12 cluster before changing voltage */
+ NOTICE("Switching on the Regulator idx: %u\n",
+ SWREG_IHOST1_DIS);
+ mmio_clrsetbits_32(CRMU_SWREG_CTRL_ADDR,
+ BIT(SWREG_IHOST1_DIS),
+ BIT(SWREG_IHOST1_REG_RESETB));
+
+ /* wait for regulator supply gets stable */
+ while (!(mmio_read_32(CRMU_SWREG_STATUS_ADDR) &
+ (1 << SWREG_IHOST1_PMU_STABLE)))
+ ;
+
+ INFO("Regulator supply got stable\n");
+
+#ifndef DEFAULT_SWREG_CONFIG
+ swreg_firmware_update();
+#endif
+
+ set_ihost_vddc_swreg(ihost_uvolts, vddc_uvolts);
+#endif
+ if (IS_SR_B0(buf[1])) {
+ NOTICE("ddrc_uvolts: %duv\n", ddrc_uvolts);
+ set_swreg(DDR_VDDC, ddrc_uvolts);
+ }
+}
+
+#ifdef USE_DDR
+static struct ddr_info ddr_info;
+#endif
+#ifdef USE_FRU
+static struct fru_area_info fru_area[FRU_MAX_NR_AREAS];
+static struct fru_board_info board_info;
+static struct fru_time fru_tm;
+static uint8_t fru_tbl[BCM_MAX_FRU_LEN];
+
+static void board_detect_fru(void)
+{
+ uint32_t i, result;
+ int ret = -1;
+
+ result = bcm_emmc_init(false);
+ if (!result) {
+ ERROR("eMMC init failed\n");
+ return;
+ }
+
+ /* go through eMMC boot partitions looking for FRU table */
+ for (i = EMMC_BOOT_PARTITION1; i <= EMMC_BOOT_PARTITION2; i++) {
+ result = emmc_partition_select(i);
+ if (!result) {
+ ERROR("Switching to eMMC part %u failed\n", i);
+ return;
+ }
+
+ result = emmc_read(BCM_FRU_TBL_OFFSET, (uintptr_t)fru_tbl,
+ BCM_MAX_FRU_LEN, BCM_MAX_FRU_LEN);
+ if (!result) {
+ ERROR("Failed to read from eMMC part %u\n", i);
+ return;
+ }
+
+ /*
+ * Run sanity check and checksum to make sure valid FRU table
+ * is detected
+ */
+ ret = fru_validate(fru_tbl, fru_area);
+ if (ret < 0) {
+ WARN("FRU table not found in eMMC part %u\n", i);
+ continue;
+ }
+
+ /* parse DDR information from FRU table */
+ ret = fru_parse_ddr(fru_tbl, &fru_area[FRU_AREA_INTERNAL],
+ &ddr_info);
+ if (ret < 0) {
+ WARN("No FRU DDR info found in eMMC part %u\n", i);
+ continue;
+ }
+
+ /* parse board information from FRU table */
+ ret = fru_parse_board(fru_tbl, &fru_area[FRU_AREA_BOARD_INFO],
+ &board_info);
+ if (ret < 0) {
+ WARN("No FRU board info found in eMMC part %u\n", i);
+ continue;
+ }
+
+ /* if we reach here, valid FRU table is parsed */
+ break;
+ }
+
+ if (ret < 0) {
+ WARN("FRU table missing for this board\n");
+ return;
+ }
+
+ for (i = 0; i < BCM_MAX_NR_DDR; i++) {
+ INFO("DDR channel index: %d\n", ddr_info.mcb[i].idx);
+ INFO("DDR size %u GB\n", ddr_info.mcb[i].size_mb / 1024);
+ INFO("DDR ref ID by SW (Not MCB Ref ID) 0x%x\n",
+ ddr_info.mcb[i].ref_id);
+ }
+
+ fru_format_time(board_info.mfg_date, &fru_tm);
+
+ INFO("**** FRU board information ****\n");
+ INFO("Language 0x%x\n", board_info.lang);
+ INFO("Manufacturing Date %u.%02u.%02u, %02u:%02u\n",
+ fru_tm.year, fru_tm.month, fru_tm.day,
+ fru_tm.hour, fru_tm.min);
+ INFO("Manufacturing Date(Raw) 0x%x\n", board_info.mfg_date);
+ INFO("Manufacturer %s\n", board_info.manufacturer);
+ INFO("Product Name %s\n", board_info.product_name);
+ INFO("Serial number %s\n", board_info.serial_number);
+ INFO("Part number %s\n", board_info.part_number);
+ INFO("File ID %s\n", board_info.file_id);
+}
+#endif /* USE_FRU */
+
+#ifdef USE_GPIO
+
+#define INVALID_GPIO 0xffff
+
+static const int gpio_cfg_bitmap[MAX_NR_GPIOS] = {
+#ifdef BRD_DETECT_GPIO_BIT0
+ BRD_DETECT_GPIO_BIT0,
+#else
+ INVALID_GPIO,
+#endif
+#ifdef BRD_DETECT_GPIO_BIT1
+ BRD_DETECT_GPIO_BIT1,
+#else
+ INVALID_GPIO,
+#endif
+#ifdef BRD_DETECT_GPIO_BIT2
+ BRD_DETECT_GPIO_BIT2,
+#else
+ INVALID_GPIO,
+#endif
+#ifdef BRD_DETECT_GPIO_BIT3
+ BRD_DETECT_GPIO_BIT3,
+#else
+ INVALID_GPIO,
+#endif
+};
+
+static uint8_t gpio_bitmap;
+
+/*
+ * Use an odd number to avoid potential conflict with public GPIO level
+ * defines
+ */
+#define GPIO_STATE_FLOAT 15
+
+/*
+ * If GPIO_SUPPORT_FLOAT_DETECTION is disabled, simply return GPIO level
+ *
+ * If GPIO_SUPPORT_FLOAT_DETECTION is enabled, add additional test for possible
+ * pin floating (unconnected) scenario. This support is assuming externally
+ * applied pull up / pull down will have a stronger pull than the internal pull
+ * up / pull down.
+ */
+static uint8_t gpio_get_state(int gpio)
+{
+ uint8_t val;
+
+ /* set direction to GPIO input */
+ gpio_set_direction(gpio, GPIO_DIR_IN);
+
+#ifndef GPIO_SUPPORT_FLOAT_DETECTION
+ if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH)
+ val = GPIO_LEVEL_HIGH;
+ else
+ val = GPIO_LEVEL_LOW;
+
+ return val;
+#else
+ /*
+ * Enable internal pull down. If GPIO level is still high, there must
+ * be an external pull up
+ */
+ gpio_set_pull(gpio, GPIO_PULL_DOWN);
+ if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) {
+ val = GPIO_LEVEL_HIGH;
+ goto exit;
+ }
+
+ /*
+ * Enable internal pull up. If GPIO level is still low, there must
+ * be an external pull down
+ */
+ gpio_set_pull(gpio, GPIO_PULL_UP);
+ if (gpio_get_value(gpio) == GPIO_LEVEL_LOW) {
+ val = GPIO_LEVEL_LOW;
+ goto exit;
+ }
+
+ /* if reached here, the pin must be not connected */
+ val = GPIO_STATE_FLOAT;
+
+exit:
+ /* make sure internall pull is disabled */
+ if (gpio_get_pull(gpio) != GPIO_PULL_NONE)
+ gpio_set_pull(gpio, GPIO_PULL_NONE);
+
+ return val;
+#endif
+}
+
+static void board_detect_gpio(void)
+{
+ unsigned int i, val;
+ int gpio;
+
+ iproc_gpio_init(IPROC_GPIO_S_BASE, IPROC_GPIO_NR,
+ IPROC_IOPAD_MODE_BASE, HSLS_IOPAD_BASE);
+
+ gpio_bitmap = 0;
+ for (i = 0; i < MAX_NR_GPIOS; i++) {
+ if (gpio_cfg_bitmap[i] == INVALID_GPIO)
+ continue;
+
+ /*
+ * Construct the bitmap based on GPIO value. Floating pin
+ * detection is a special case. As soon as a floating pin is
+ * detected, a special value of MAX_GPIO_BITMAP_VAL is
+ * assigned and we break out of the loop immediately
+ */
+ gpio = gpio_cfg_bitmap[i];
+ val = gpio_get_state(gpio);
+ if (val == GPIO_STATE_FLOAT) {
+ gpio_bitmap = MAX_GPIO_BITMAP_VAL;
+ break;
+ }
+
+ if (val == GPIO_LEVEL_HIGH)
+ gpio_bitmap |= BIT(i);
+ }
+
+ memcpy(&ddr_info, &gpio_ddr_info[gpio_bitmap], sizeof(ddr_info));
+ INFO("Board detection GPIO bitmap = 0x%x\n", gpio_bitmap);
+}
+#endif /* USE_GPIO */
+
+static void bcm_board_detect(void)
+{
+#ifdef DDR_LEGACY_MCB_SUPPORTED
+ /* Loading default DDR info */
+ memcpy(&ddr_info, &default_ddr_info, sizeof(ddr_info));
+#endif
+#ifdef USE_FRU
+ board_detect_fru();
+#endif
+#ifdef USE_GPIO
+ board_detect_gpio();
+#endif
+}
+
+static void dump_persistent_regs(void)
+{
+ NOTICE("pr0: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG0));
+ NOTICE("pr1: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1));
+ NOTICE("pr2: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG2));
+ NOTICE("pr3: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG3));
+ NOTICE("pr4: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG4));
+ NOTICE("pr5: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG5));
+ NOTICE("pr6: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG6));
+ NOTICE("pr7: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG7));
+ NOTICE("pr8: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG8));
+ NOTICE("pr9: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9));
+ NOTICE("pr10: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG10));
+ NOTICE("pr11: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG11));
+}
+
+void plat_bcm_bl2_plat_arch_setup(void)
+{
+ if (chip_get_rev_id_major() == CHIP_REV_MAJOR_AX) {
+ if (!(sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
+ SOTP_ATF_WATCHDOG_ENABLE_MASK)) {
+ /*
+ * Stop sp805 watchdog timer immediately.
+ * It might has been set up by MCU patch earlier for
+ * eMMC workaround.
+ *
+ * Note the watchdog timer started in CRMU has a very
+ * short timeout and needs to be stopped immediately.
+ * Down below we restart it with a much longer timeout
+ * for BL2 and BL31
+ */
+ sp805_stop(ARM_SP805_TWDG_BASE);
+ }
+ }
+
+#if !BRCM_DISABLE_TRUSTED_WDOG
+ /*
+ * start secure watchdog for BL2 and BL31.
+ * Note that UART download can take a longer time,
+ * so do not allow watchdog for UART download,
+ * as this boot source is not a standard modus operandi.
+ */
+ if (boot_source_get() != BOOT_SOURCE_UART)
+ sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+#endif
+
+#ifdef BCM_ELOG
+ /* Ensure logging is started out fresh in BL2. */
+ mmio_write_32(BCM_ELOG_BL2_BASE, 0);
+#endif
+ /*
+ * In BL2, since we have very limited space to store logs, we only
+ * save logs that are >= the WARNING level.
+ */
+ bcm_elog_init((void *)BCM_ELOG_BL2_BASE, BCM_ELOG_BL2_SIZE,
+ LOG_LEVEL_WARNING);
+
+ dump_persistent_regs();
+
+ /* Read CRMU mailbox 0 */
+ NOTICE("RESET (reported by CRMU): 0x%x\n",
+ mmio_read_32(CRMU_READ_MAIL_BOX0));
+
+ /*
+ * All non-boot-source PADs are in forced input-mode at
+ * reset so clear the force on non-boot-source PADs using
+ * CDRU register.
+ */
+ mmio_clrbits_32((uintptr_t)CDRU_CHIP_IO_PAD_CONTROL,
+ (1 << CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R));
+
+#if DRIVER_OCOTP_ENABLE
+ bcm_otpc_init(&otp_stingray_map);
+#endif
+
+ set_swreg_based_on_otp();
+
+#if IHOST_PLL_FREQ != 0
+ bcm_set_ihost_pll_freq(0x0, IHOST_PLL_FREQ);
+#endif
+
+#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
+ /* The erasable unit of the eMMC is the "Erase Group";
+ * Erase group is measured in write blocks which are the
+ * basic writable units of the Device.
+ * The size of the Erase Group is a Device specific parameter
+ */
+ emmc_erase(EMMC_ERASE_START_BLOCK, EMMC_ERASE_BLOCK_COUNT,
+ EMMC_ERASE_PARTITION);
+#endif
+
+ bcm_board_detect();
+#ifdef DRIVER_EMMC_ENABLE
+ /* Initialize the card, if it is not */
+ if (bcm_emmc_init(true) == 0)
+ WARN("eMMC Card Initialization Failed!!!\n");
+#endif
+
+#if BL2_TEST_I2C
+ i2c_test();
+#endif
+
+#ifdef USE_DDR
+ ddr_initialize(&ddr_info);
+
+ ddr_secure_region_config(SECURE_DDR_BASE_ADDRESS,
+ SECURE_DDR_END_ADDRESS);
+#ifdef NITRO_SECURE_ACCESS
+ ddr_secure_region_config(DDR_NITRO_SECURE_REGION_START,
+ DDR_NITRO_SECURE_REGION_END);
+#endif
+#else
+ ext_sram_init();
+#endif
+
+#if BL2_TEST_MEM
+ ddr_test();
+#endif
+
+#ifdef USE_NAND
+ brcm_stingray_nand_init();
+#endif
+
+#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA)
+ brcm_stingray_pcie_reset();
+#endif
+
+#ifdef USE_PAXC
+ if (boot_source_get() != BOOT_SOURCE_QSPI)
+ brcm_stingray_chimp_check_and_fastboot();
+#endif
+
+#if ((!CLEAN_DDR || MMU_DISABLED))
+ /*
+ * Now DDR has been initialized. We want to copy all the logs in SRAM
+ * into DDR so we will have much more space to store the logs in the
+ * next boot stage
+ */
+ bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE,
+ MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE)
+ );
+
+ /*
+ * We are not yet at the end of BL2, but we can stop log here so we do
+ * not need to add 'bcm_elog_exit' to the standard BL2 code. The
+ * benefit of capturing BL2 logs after this is very minimal in a
+ * production system
+ * NOTE: BL2 logging must be exited before going forward to setup
+ * page tables
+ */
+ bcm_elog_exit();
+#endif
+}
diff --git a/plat/brcm/board/stingray/src/bl31_setup.c b/plat/brcm/board/stingray/src/bl31_setup.c
new file mode 100644
index 0000000..04df6a0
--- /dev/null
+++ b/plat/brcm/board/stingray/src/bl31_setup.c
@@ -0,0 +1,1071 @@
+/*
+ * Copyright (c) 2015 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <cortex_a72.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+
+#include <bl33_info.h>
+#include <chimp.h>
+#include <cmn_plat_util.h>
+#include <dmu.h>
+#include <fsx.h>
+#include <iommu.h>
+#include <ncsi.h>
+#include <paxb.h>
+#include <paxc.h>
+#include <platform_def.h>
+#ifdef USE_USB
+#include <platform_usb.h>
+#endif
+#include <sdio.h>
+#include <sr_utils.h>
+#include <timer_sync.h>
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup common to ARM standard platforms
+ ******************************************************************************/
+
+static void brcm_stingray_gain_qspi_control(void)
+{
+ if (boot_source_get() != BOOT_SOURCE_QSPI) {
+ if (bcm_chimp_is_nic_mode() &&
+ (!bcm_chimp_handshake_done())) {
+ /*
+ * Last chance to wait for ChiMP firmware to report
+ * "I am done" before grabbing the QSPI
+ */
+ WARN("ChiMP still not booted\n");
+#ifndef CHIMP_ALWAYS_NEEDS_QSPI
+ WARN("ChiMP is given the last chance to boot (%d s)\n",
+ CHIMP_HANDSHAKE_TIMEOUT_MS / 1000);
+
+ if (!bcm_chimp_wait_handshake()) {
+ ERROR("ChiMP failed to boot\n");
+ } else {
+ INFO("ChiMP booted successfully\n");
+ }
+#endif
+ }
+
+#ifndef CHIMP_ALWAYS_NEEDS_QSPI
+ INFO("AP grabs QSPI\n");
+ /*
+ * For QSPI boot sbl/bl1 has already taken care.
+ * For other boot sources QSPI needs to be muxed to
+ * AP for exclusive use
+ */
+ brcm_stingray_set_qspi_mux(1);
+ INFO("AP (bl31) gained control over QSPI\n");
+#endif
+ }
+}
+
+static void brcm_stingray_dma_pl330_init(void)
+{
+ unsigned int val;
+
+ VERBOSE("dma pl330 init start\n");
+
+ /* Set DMAC boot_manager_ns = 0x1 */
+ VERBOSE(" - configure boot security state\n");
+ mmio_setbits_32(DMAC_M0_IDM_IO_CONTROL_DIRECT, BOOT_MANAGER_NS);
+ /* Set boot_peripheral_ns[n:0] = 0xffffffff */
+ mmio_write_32(ICFG_DMAC_CONFIG_2, BOOT_PERIPHERAL_NS);
+ /* Set boot_irq_ns[n:0] = 0x0000ffff */
+ mmio_write_32(ICFG_DMAC_CONFIG_3, BOOT_IRQ_NS);
+
+ /* Set DMAC stream_id */
+ VERBOSE(" - configure stream_id = 0x6000\n");
+ val = (DMAC_STREAM_ID << DMAC_SID_SHIFT);
+ mmio_write_32(ICFG_DMAC_SID_ARADDR_CONTROL, val);
+ mmio_write_32(ICFG_DMAC_SID_AWADDR_CONTROL, val);
+
+ /* Reset DMAC */
+ VERBOSE(" - reset dma pl330\n");
+
+ mmio_setbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1);
+ udelay(500);
+
+ mmio_clrbits_32(DMAC_M0_IDM_RESET_CONTROL, 0x1);
+ udelay(500);
+
+ INFO("dma pl330 init done\n");
+}
+
+static void brcm_stingray_spi_pl022_init(uintptr_t idm_reset_control)
+{
+ VERBOSE("spi pl022 init start\n");
+
+ /* Reset APB SPI bridge */
+ VERBOSE(" - reset apb spi bridge\n");
+ mmio_setbits_32(idm_reset_control, 0x1);
+ udelay(500);
+
+ mmio_clrbits_32(idm_reset_control, 0x1);
+ udelay(500);
+
+ INFO("spi pl022 init done\n");
+}
+
+#define CDRU_SATA_RESET_N \
+ BIT(CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R)
+#define CDRU_MISC_CLK_SATA \
+ BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R)
+#define CCN_CONFIG_CLK_ENABLE (1 << 2)
+#define MMU_CONFIG_CLK_ENABLE (0x3F << 16)
+
+#define SATA_SATA_TOP_CTRL_BUS_CTRL (SATA_BASE + 0x2044)
+#define DMA_BIT_CTRL_MASK 0x003
+#define DMA_DESCR_ENDIAN_CTRL (DMA_BIT_CTRL_MASK << 0x002)
+#define DMA_DATA_ENDIAN_CTRL (DMA_BIT_CTRL_MASK << 0x004)
+
+#define SATA_PORT_SATA3_PCB_REG8 (SATA_BASE + 0x2320)
+#define SATA_PORT_SATA3_PCB_REG11 (SATA_BASE + 0x232c)
+#define SATA_PORT_SATA3_PCB_BLOCK_ADDR (SATA_BASE + 0x233c)
+
+#define SATA3_AFE_TXRX_ACTRL 0x1d0
+/* TXDriver swing setting is 800mV */
+#define DFS_SWINGNOPE_VALUE (0x0 << 6)
+#define DFS_SWINGNOPE_MASK (0x3 << 6)
+
+#define DFS_SWINGPE_VALUE (0x1 << 4)
+#define DFS_SWINGPE_MASK (0x3 << 4)
+
+#define DFS_INJSTRENGTH_VALUE (0x0 << 4)
+#define DFS_INJSTRENGTH_MASK (0x3 << 4)
+
+#define DFS_INJEN (0x1 << 3)
+
+#define SATA_CORE_MEM_CTRL (SATA_BASE + 0x3a08)
+#define SATA_CORE_MEM_CTRL_ISO BIT(0)
+#define SATA_CORE_MEM_CTRL_ARRPOWEROKIN BIT(1)
+#define SATA_CORE_MEM_CTRL_ARRPOWERONIN BIT(2)
+#define SATA_CORE_MEM_CTRL_POWEROKIN BIT(3)
+#define SATA_CORE_MEM_CTRL_POWERONIN BIT(4)
+
+#define SATA0_IDM_RESET_CONTROL (SATA_BASE + 0x500800)
+#define SATA_APBT0_IDM_IO_CONTROL_DIRECT (SATA_BASE + 0x51a408)
+#define IO_CONTROL_DIRECT_CLK_ENABLE BIT(0)
+#define SATA_APBT0_IDM_RESET_CONTROL (SATA_BASE + 0x51a800)
+#define IDM_RESET_CONTROL_RESET BIT(0)
+
+#define NIC400_SATA_NOC_SECURITY1 0x6830000c
+#define SATA_NOC_SECURITY1_FIELD 0xf
+#define NIC400_SATA_NOC_SECURITY2 0x68300010
+#define SATA_NOC_SECURITY2_FIELD 0xf
+#define NIC400_SATA_NOC_SECURITY3 0x68300014
+#define SATA_NOC_SECURITY3_FIELD 0x1
+#define NIC400_SATA_NOC_SECURITY4 0x68300018
+#define SATA_NOC_SECURITY4_FIELD 0x1
+#define NIC400_SATA_NOC_SECURITY5 0x6830001c
+#define SATA_NOC_SECURITY5_FIELD 0xf
+#define NIC400_SATA_NOC_SECURITY6 0x68300020
+#define SATA_NOC_SECURITY6_FIELD 0x1
+#define NIC400_SATA_NOC_SECURITY7 0x68300024
+#define SATA_NOC_SECURITY7_FIELD 0xf
+#define NIC400_SATA_NOC_SECURITY8 0x68300028
+#define SATA_NOC_SECURITY8_FIELD 0xf
+#define NIC400_SATA_NOC_SECURITY9 0x6830002c
+#define SATA_NOC_SECURITY9_FIELD 0x1
+
+#define SATA_APBT_IDM_PORT_REG(port, reg) \
+ (((port/4) << 12) + reg)
+
+#define SATA_IDM_PORT_REG(port, reg) ((port << 12) + reg)
+
+#define SATA_PORT_REG(port, reg) \
+ (((port%4) << 16) + ((port/4) << 20) + reg)
+
+#define MAX_SATA_PORTS 8
+#define USE_SATA_PORTS 8
+
+#ifdef USE_SATA
+static const uint8_t sr_b0_sata_port[MAX_SATA_PORTS] = {
+ 0, 1, 2, 3, 4, 5, 6, 7
+};
+
+static uint32_t brcm_stingray_get_sata_port(unsigned int port)
+{
+ return sr_b0_sata_port[port];
+}
+
+static void brcm_stingray_sata_init(void)
+{
+ unsigned int port = 0;
+ uint32_t sata_port;
+
+ mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL,
+ CDRU_MISC_CLK_SATA);
+
+ mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N);
+ mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_SATA_RESET_N);
+
+ for (port = 0; port < USE_SATA_PORTS; port++) {
+
+ sata_port = brcm_stingray_get_sata_port(port);
+ mmio_write_32(SATA_APBT_IDM_PORT_REG(sata_port,
+ SATA_APBT0_IDM_RESET_CONTROL),
+ 0x0);
+ mmio_setbits_32(SATA_APBT_IDM_PORT_REG(sata_port,
+ SATA_APBT0_IDM_IO_CONTROL_DIRECT),
+ IO_CONTROL_DIRECT_CLK_ENABLE);
+ mmio_write_32(SATA_IDM_PORT_REG(sata_port,
+ SATA0_IDM_RESET_CONTROL),
+ 0x0);
+
+ mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+ SATA_CORE_MEM_CTRL_ARRPOWERONIN);
+ mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+ SATA_CORE_MEM_CTRL_ARRPOWEROKIN);
+ mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+ SATA_CORE_MEM_CTRL_POWERONIN);
+ mmio_setbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+ SATA_CORE_MEM_CTRL_POWEROKIN);
+ mmio_clrbits_32(SATA_PORT_REG(sata_port, SATA_CORE_MEM_CTRL),
+ SATA_CORE_MEM_CTRL_ISO);
+
+ mmio_clrbits_32(SATA_PORT_REG(sata_port,
+ SATA_SATA_TOP_CTRL_BUS_CTRL),
+ (DMA_DESCR_ENDIAN_CTRL | DMA_DATA_ENDIAN_CTRL));
+ }
+
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY1, SATA_NOC_SECURITY1_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY2, SATA_NOC_SECURITY2_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY3, SATA_NOC_SECURITY3_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY4, SATA_NOC_SECURITY4_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY5, SATA_NOC_SECURITY5_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY6, SATA_NOC_SECURITY6_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY7, SATA_NOC_SECURITY7_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY8, SATA_NOC_SECURITY8_FIELD);
+ mmio_setbits_32(NIC400_SATA_NOC_SECURITY9, SATA_NOC_SECURITY9_FIELD);
+
+ INFO("sata init done\n");
+}
+#else
+static void poweroff_sata_pll(void)
+{
+ /*
+ * SATA subsystem is clocked by LCPLL0 which is enabled by
+ * default by bootrom. Poweroff the PLL if SATA is not used
+ */
+
+ /* enable isolation */
+ mmio_setbits_32(CRMU_AON_CTRL1,
+ BIT(CRMU_AON_CTRL1__LCPLL0_ISO_IN));
+
+ /* Power off the SATA PLL/LDO */
+ mmio_clrbits_32(CRMU_AON_CTRL1,
+ (BIT(CRMU_AON_CTRL1__LCPLL0_PWRON_LDO) |
+ BIT(CRMU_AON_CTRL1__LCPLL0_PWR_ON)));
+}
+#endif
+
+#ifdef USE_AMAC
+#ifdef EMULATION_SETUP
+#define ICFG_AMAC_STRAP_CONFIG (HSLS_ICFG_REGS_BASE + 0xa5c)
+#define ICFG_AMAC_STRAP_DLL_BYPASS (1 << 2)
+#endif
+#define ICFG_AMAC_MAC_CTRL_REG (HSLS_ICFG_REGS_BASE + 0xa6c)
+#define ICFG_AMAC_MAC_FULL_DUPLEX (1 << 1)
+#define ICFG_AMAC_RGMII_PHY_CONFIG (HSLS_ICFG_REGS_BASE + 0xa60)
+#define ICFG_AMAC_SID_CONTROL (HSLS_ICFG_REGS_BASE + 0xb10)
+#define ICFG_AMAC_SID_SHIFT 5
+#define ICFG_AMAC_SID_AWADDR_OFFSET 0x0
+#define ICFG_AMAC_SID_ARADDR_OFFSET 0x4
+#define AMAC_RPHY_1000_DATARATE (1 << 20)
+#define AMAC_RPHY_FULL_DUPLEX (1 << 5)
+#define AMAC_RPHY_SPEED_OFFSET 2
+#define AMAC_RPHY_SPEED_MASK (7 << AMAC_RPHY_SPEED_OFFSET)
+#define AMAC_RPHY_1G_SPEED (2 << AMAC_RPHY_SPEED_OFFSET)
+#define ICFG_AMAC_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xa68)
+#define AMAC_ISO BIT(9)
+#define AMAC_STDBY BIT(8)
+#define AMAC_ARRPOWEROKIN BIT(7)
+#define AMAC_ARRPOWERONIN BIT(6)
+#define AMAC_POWEROKIN BIT(5)
+#define AMAC_POWERONIN BIT(4)
+
+#define AMAC_IDM0_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x4408)
+#define AMAC_IDM0_ARCACHE_OFFSET 16
+#define AMAC_IDM0_AWCACHE_OFFSET 7
+#define AMAC_IDM0_ARCACHE_MASK (0xF << AMAC_IDM0_ARCACHE_OFFSET)
+#define AMAC_IDM0_AWCACHE_MASK (0xF << AMAC_IDM0_AWCACHE_OFFSET)
+/* ARCACHE - AWCACHE is 0xB7 for write-back no allocate */
+#define AMAC_IDM0_ARCACHE_VAL (0xb << AMAC_IDM0_ARCACHE_OFFSET)
+#define AMAC_IDM0_AWCACHE_VAL (0x7 << AMAC_IDM0_AWCACHE_OFFSET)
+
+static void brcm_stingray_amac_init(void)
+{
+ unsigned int val;
+ uintptr_t icfg_amac_sid = ICFG_AMAC_SID_CONTROL;
+
+ VERBOSE("amac init start\n");
+
+ val = SR_SID_VAL(0x3, 0x0, 0x4) << ICFG_AMAC_SID_SHIFT;
+ mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_AWADDR_OFFSET, val);
+ mmio_write_32(icfg_amac_sid + ICFG_AMAC_SID_ARADDR_OFFSET, val);
+
+ mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWEROKIN);
+ mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ARRPOWERONIN);
+ mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWEROKIN);
+ mmio_setbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_POWERONIN);
+ mmio_clrbits_32(ICFG_AMAC_MEM_PWR_CTRL, AMAC_ISO);
+ mmio_write_32(APBR_IDM_RESET_CONTROL, 0x0);
+ mmio_clrsetbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_SPEED_MASK,
+ AMAC_RPHY_1G_SPEED); /*1 Gbps line rate*/
+ /* 1000 datarate set */
+ mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_1000_DATARATE);
+ /* full duplex */
+ mmio_setbits_32(ICFG_AMAC_RGMII_PHY_CONFIG, AMAC_RPHY_FULL_DUPLEX);
+#ifdef EMULATION_SETUP
+ /* DLL bypass */
+ mmio_setbits_32(ICFG_AMAC_STRAP_CONFIG, ICFG_AMAC_STRAP_DLL_BYPASS);
+#endif
+ /* serdes full duplex */
+ mmio_setbits_32(ICFG_AMAC_MAC_CTRL_REG, ICFG_AMAC_MAC_FULL_DUPLEX);
+ mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_ARCACHE_MASK,
+ AMAC_IDM0_ARCACHE_VAL);
+ mmio_clrsetbits_32(AMAC_IDM0_IO_CONTROL_DIRECT, AMAC_IDM0_AWCACHE_MASK,
+ AMAC_IDM0_AWCACHE_VAL);
+ INFO("amac init done\n");
+}
+#endif /* USE_AMAC */
+
+static void brcm_stingray_pka_meminit(void)
+{
+ uintptr_t icfg_mem_ctrl = ICFG_PKA_MEM_PWR_CTRL;
+
+ VERBOSE("pka meminit start\n");
+
+ VERBOSE(" - arrpoweron\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT))
+ ;
+
+ VERBOSE(" - arrpowerok\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT))
+ ;
+
+ VERBOSE(" - poweron\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_PKA_MEM_PWR_CTRL__POWERONIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_PKA_MEM_PWR_CTRL__POWERONOUT))
+ ;
+
+ VERBOSE(" - powerok\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_PKA_MEM_PWR_CTRL__POWEROKIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT))
+ ;
+
+ /* Wait sometime */
+ mdelay(1);
+
+ VERBOSE(" - remove isolation\n");
+ mmio_clrbits_32(icfg_mem_ctrl, ICFG_PKA_MEM_PWR_CTRL__ISO);
+
+ INFO("pka meminit done\n");
+}
+
+static void brcm_stingray_smmu_init(void)
+{
+ unsigned int val;
+ uintptr_t smmu_base = SMMU_BASE;
+
+ VERBOSE("smmu init start\n");
+
+ /* Configure SCR0 */
+ VERBOSE(" - configure scr0\n");
+ val = mmio_read_32(smmu_base + 0x0);
+ val |= (0x1 << 12);
+ mmio_write_32(smmu_base + 0x0, val);
+
+ /* Reserve context banks for secure masters */
+ arm_smmu_reserve_secure_cntxt();
+
+ /* Print configuration */
+ VERBOSE(" - scr0=0x%x scr1=0x%x scr2=0x%x\n",
+ mmio_read_32(smmu_base + 0x0),
+ mmio_read_32(smmu_base + 0x4),
+ mmio_read_32(smmu_base + 0x8));
+
+ VERBOSE(" - idr0=0x%x idr1=0x%x idr2=0x%x\n",
+ mmio_read_32(smmu_base + 0x20),
+ mmio_read_32(smmu_base + 0x24),
+ mmio_read_32(smmu_base + 0x28));
+
+ VERBOSE(" - idr3=0x%x idr4=0x%x idr5=0x%x\n",
+ mmio_read_32(smmu_base + 0x2c),
+ mmio_read_32(smmu_base + 0x30),
+ mmio_read_32(smmu_base + 0x34));
+
+ VERBOSE(" - idr6=0x%x idr7=0x%x\n",
+ mmio_read_32(smmu_base + 0x38),
+ mmio_read_32(smmu_base + 0x3c));
+
+ INFO("smmu init done\n");
+}
+
+static void brcm_stingray_dma_pl330_meminit(void)
+{
+ uintptr_t icfg_mem_ctrl = ICFG_DMAC_MEM_PWR_CTRL;
+
+ VERBOSE("dmac meminit start\n");
+
+ VERBOSE(" - arrpoweron\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT))
+ ;
+
+ VERBOSE(" - arrpowerok\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT))
+ ;
+
+ VERBOSE(" - poweron\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_DMAC_MEM_PWR_CTRL__POWERONIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT))
+ ;
+
+ VERBOSE(" - powerok\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT))
+ ;
+
+ /* Wait sometime */
+ mdelay(1);
+
+ VERBOSE(" - remove isolation\n");
+ mmio_clrbits_32(icfg_mem_ctrl, ICFG_DMAC_MEM_PWR_CTRL__ISO);
+
+ INFO("dmac meminit done\n");
+}
+
+/* program the crmu access ranges for allowing non sec access*/
+static void brcm_stingray_crmu_access_init(void)
+{
+ /* Enable 0x6641c001 - 0x6641c701 for non secure access */
+ mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW, 0x6641c001);
+ mmio_write_32(CRMU_CORE_ADDR_RANGE0_LOW + 0x4, 0x6641c701);
+
+ /* Enable 0x6641d001 - 0x66424b01 for non secure access */
+ mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW, 0x6641d001);
+ mmio_write_32(CRMU_CORE_ADDR_RANGE1_LOW + 0x4, 0x66424b01);
+
+ /* Enable 0x66425001 - 0x66425f01 for non secure access */
+ mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW, 0x66425001);
+ mmio_write_32(CRMU_CORE_ADDR_RANGE2_LOW + 0x4, 0x66425f01);
+
+ INFO("crmu access init done\n");
+}
+
+static void brcm_stingray_scr_init(void)
+{
+ unsigned int val;
+ uintptr_t scr_base = SCR_BASE;
+ unsigned int clr_mask = SCR_AXCACHE_CONFIG_MASK;
+ unsigned int set_mask = SCR_TBUX_AXCACHE_CONFIG;
+
+ VERBOSE("scr init start\n");
+
+ /* awdomain=0x1 and ardomain=0x1 */
+ mmio_clrsetbits_32(scr_base + 0x0, clr_mask, set_mask);
+ val = mmio_read_32(scr_base + 0x0);
+ VERBOSE(" - set tbu0_config=0x%x\n", val);
+
+ /* awdomain=0x1 and ardomain=0x1 */
+ mmio_clrsetbits_32(scr_base + 0x4, clr_mask, set_mask);
+ val = mmio_read_32(scr_base + 0x4);
+ VERBOSE(" - set tbu1_config=0x%x\n", val);
+
+ /* awdomain=0x1 and ardomain=0x1 */
+ mmio_clrsetbits_32(scr_base + 0x8, clr_mask, set_mask);
+ val = mmio_read_32(scr_base + 0x8);
+ VERBOSE(" - set tbu2_config=0x%x\n", val);
+
+ /* awdomain=0x1 and ardomain=0x1 */
+ mmio_clrsetbits_32(scr_base + 0xc, clr_mask, set_mask);
+ val = mmio_read_32(scr_base + 0xc);
+ VERBOSE(" - set tbu3_config=0x%x\n", val);
+
+ /* awdomain=0x1 and ardomain=0x1 */
+ mmio_clrsetbits_32(scr_base + 0x10, clr_mask, set_mask);
+ val = mmio_read_32(scr_base + 0x10);
+ VERBOSE(" - set tbu4_config=0x%x\n", val);
+
+ /* awdomain=0x0 and ardomain=0x0 */
+ mmio_clrbits_32(scr_base + 0x14, clr_mask);
+ val = mmio_read_32(scr_base + 0x14);
+ VERBOSE(" - set gic_config=0x%x\n", val);
+
+ INFO("scr init done\n");
+}
+
+static void brcm_stingray_hsls_tzpcprot_init(void)
+{
+ unsigned int val;
+ uintptr_t tzpcdecprot_base = HSLS_TZPC_BASE;
+
+ VERBOSE("hsls tzpcprot init start\n");
+
+ /* Treat third-party masters as non-secured */
+ val = 0;
+ val |= BIT(6); /* SDIO1 */
+ val |= BIT(5); /* SDIO0 */
+ val |= BIT(0); /* AMAC */
+ mmio_write_32(tzpcdecprot_base + 0x810, val);
+
+ /* Print TZPC decode status registers */
+ VERBOSE(" - tzpcdecprot0=0x%x\n",
+ mmio_read_32(tzpcdecprot_base + 0x800));
+
+ VERBOSE(" - tzpcdecprot1=0x%x\n",
+ mmio_read_32(tzpcdecprot_base + 0x80c));
+
+ INFO("hsls tzpcprot init done\n");
+}
+
+#ifdef USE_I2S
+#define ICFG_AUDIO_POWER_CTRL (HSLS_ICFG_REGS_BASE + 0xaa8)
+#define ICFG_AUDIO_POWER_CTRL__POWERONIN BIT(0)
+#define ICFG_AUDIO_POWER_CTRL__POWEROKIN BIT(1)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN BIT(2)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN BIT(3)
+#define ICFG_AUDIO_POWER_CTRL__POWERONOUT BIT(4)
+#define ICFG_AUDIO_POWER_CTRL__POWEROKOUT BIT(5)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT BIT(6)
+#define ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT BIT(7)
+#define ICFG_AUDIO_POWER_CTRL__ISO BIT(8)
+#define ICFG_AUDIO_SID_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf8)
+#define ICFG_AUDIO_SID_SHIFT 5
+#define ICFG_AUDIO_SID_AWADDR_OFFSET 0x0
+#define ICFG_AUDIO_SID_ARADDR_OFFSET 0x4
+
+#define I2S_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x1800)
+#define I2S_IDM_IO_CONTROL (HSLS_IDM_REGS_BASE + 0x1408)
+#define IO_CONTROL_CLK_ENABLE BIT(0)
+#define I2S_IDM0_ARCACHE_OFFSET 16
+#define I2S_IDM0_AWCACHE_OFFSET 20
+#define I2S_IDM0_ARCACHE_MASK (0xF << I2S_IDM0_ARCACHE_OFFSET)
+#define I2S_IDM0_AWCACHE_MASK (0xF << I2S_IDM0_AWCACHE_OFFSET)
+/* ARCACHE - AWCACHE is 0x22 Normal Non-cacheable Non-bufferable. */
+#define I2S_IDM0_ARCACHE_VAL (0x2 << I2S_IDM0_ARCACHE_OFFSET)
+#define I2S_IDM0_AWCACHE_VAL (0x2 << I2S_IDM0_AWCACHE_OFFSET)
+
+static void brcm_stingray_audio_init(void)
+{
+ unsigned int val;
+ uintptr_t icfg_mem_ctrl = ICFG_AUDIO_POWER_CTRL;
+ uintptr_t icfg_audio_sid = ICFG_AUDIO_SID_CONTROL;
+
+ mmio_write_32(I2S_RESET_CONTROL, 0x0);
+
+ mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_ARCACHE_MASK,
+ I2S_IDM0_ARCACHE_VAL);
+
+ mmio_clrsetbits_32(I2S_IDM_IO_CONTROL, I2S_IDM0_AWCACHE_MASK,
+ I2S_IDM0_AWCACHE_VAL);
+
+ mmio_setbits_32(I2S_IDM_IO_CONTROL, IO_CONTROL_CLK_ENABLE);
+
+ VERBOSE("audio meminit start\n");
+
+ VERBOSE(" - configure stream_id = 0x6001\n");
+ val = SR_SID_VAL(0x3, 0x0, 0x1) << ICFG_AUDIO_SID_SHIFT;
+ mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_AWADDR_OFFSET, val);
+ mmio_write_32(icfg_audio_sid + ICFG_AUDIO_SID_ARADDR_OFFSET, val);
+
+ VERBOSE(" - arrpoweron\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_AUDIO_POWER_CTRL__ARRPOWERONIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_AUDIO_POWER_CTRL__ARRPOWERONOUT))
+ ;
+
+ VERBOSE(" - arrpowerok\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_AUDIO_POWER_CTRL__ARRPOWEROKIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_AUDIO_POWER_CTRL__ARRPOWEROKOUT))
+ ;
+
+ VERBOSE(" - poweron\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_AUDIO_POWER_CTRL__POWERONIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_AUDIO_POWER_CTRL__POWERONOUT))
+ ;
+
+ VERBOSE(" - powerok\n");
+ mmio_setbits_32(icfg_mem_ctrl,
+ ICFG_AUDIO_POWER_CTRL__POWEROKIN);
+ while (!(mmio_read_32(icfg_mem_ctrl) &
+ ICFG_AUDIO_POWER_CTRL__POWEROKOUT))
+ ;
+
+ /* Wait sometime */
+ mdelay(1);
+
+ VERBOSE(" - remove isolation\n");
+ mmio_clrbits_32(icfg_mem_ctrl, ICFG_AUDIO_POWER_CTRL__ISO);
+
+ INFO("audio meminit done\n");
+}
+#endif /* USE_I2S */
+
+/*
+ * These defines do not match the regfile but they are renamed in a way such
+ * that they are much more readible
+ */
+
+#define SCR_GPV_SMMU_NS (SCR_GPV_BASE + 0x28)
+#define SCR_GPV_GIC500_NS (SCR_GPV_BASE + 0x34)
+#define HSLS_GPV_NOR_S0_NS (HSLS_GPV_BASE + 0x14)
+#define HSLS_GPV_IDM1_NS (HSLS_GPV_BASE + 0x18)
+#define HSLS_GPV_IDM2_NS (HSLS_GPV_BASE + 0x1c)
+#define HSLS_SDIO0_SLAVE_NS (HSLS_GPV_BASE + 0x20)
+#define HSLS_SDIO1_SLAVE_NS (HSLS_GPV_BASE + 0x24)
+#define HSLS_GPV_APBY_NS (HSLS_GPV_BASE + 0x2c)
+#define HSLS_GPV_APBZ_NS (HSLS_GPV_BASE + 0x30)
+#define HSLS_GPV_APBX_NS (HSLS_GPV_BASE + 0x34)
+#define HSLS_GPV_APBS_NS (HSLS_GPV_BASE + 0x38)
+#define HSLS_GPV_QSPI_S0_NS (HSLS_GPV_BASE + 0x68)
+#define HSLS_GPV_APBR_NS (HSLS_GPV_BASE + 0x6c)
+#define FS4_CRYPTO_GPV_RM_SLAVE_NS (FS4_CRYPTO_GPV_BASE + 0x8)
+#define FS4_CRYPTO_GPV_APB_SWITCH_NS (FS4_CRYPTO_GPV_BASE + 0xc)
+#define FS4_RAID_GPV_RM_SLAVE_NS (FS4_RAID_GPV_BASE + 0x8)
+#define FS4_RAID_GPV_APB_SWITCH_NS (FS4_RAID_GPV_BASE + 0xc)
+#define FS4_CRYPTO_IDM_NS (NIC400_FS_NOC_ROOT + 0x1c)
+#define FS4_RAID_IDM_NS (NIC400_FS_NOC_ROOT + 0x28)
+
+#define FS4_CRYPTO_RING_COUNT 32
+#define FS4_CRYPTO_DME_COUNT 10
+#define FS4_CRYPTO_AE_COUNT 10
+#define FS4_CRYPTO_START_STREAM_ID 0x4000
+#define FS4_CRYPTO_MSI_DEVICE_ID 0x4100
+
+#define FS4_RAID_RING_COUNT 32
+#define FS4_RAID_DME_COUNT 8
+#define FS4_RAID_AE_COUNT 8
+#define FS4_RAID_START_STREAM_ID 0x4200
+#define FS4_RAID_MSI_DEVICE_ID 0x4300
+
+#define FS6_PKI_AXI_SLAVE_NS \
+ (NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY2_OFFSET)
+
+#define FS6_PKI_AE_DME_APB_NS \
+ (NIC400_FS_NOC_ROOT + NIC400_FS_NOC_SECURITY7_OFFSET)
+#define FS6_PKI_IDM_IO_CONTROL_DIRECT 0x0
+#define FS6_PKI_IDM_RESET_CONTROL 0x0
+#define FS6_PKI_RING_COUNT 32
+#define FS6_PKI_DME_COUNT 1
+#define FS6_PKI_AE_COUNT 4
+#define FS6_PKI_START_STREAM_ID 0x4000
+#define FS6_PKI_MSI_DEVICE_ID 0x4100
+
+static void brcm_stingray_security_init(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(SCR_GPV_SMMU_NS);
+ val |= BIT(0); /* SMMU NS = 1 */
+ mmio_write_32(SCR_GPV_SMMU_NS, val);
+
+ val = mmio_read_32(SCR_GPV_GIC500_NS);
+ val |= BIT(0); /* GIC-500 NS = 1 */
+ mmio_write_32(SCR_GPV_GIC500_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_NOR_S0_NS);
+ val |= BIT(0); /* NOR SLAVE NS = 1 */
+ mmio_write_32(HSLS_GPV_NOR_S0_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_IDM1_NS);
+ val |= BIT(0); /* DMA IDM NS = 1 */
+ val |= BIT(1); /* I2S IDM NS = 1 */
+ val |= BIT(2); /* AMAC IDM NS = 1 */
+ val |= BIT(3); /* SDIO0 IDM NS = 1 */
+ val |= BIT(4); /* SDIO1 IDM NS = 1 */
+ val |= BIT(5); /* DS_3 IDM NS = 1 */
+ mmio_write_32(HSLS_GPV_IDM1_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_IDM2_NS);
+ val |= BIT(2); /* QSPI IDM NS = 1 */
+ val |= BIT(1); /* NOR IDM NS = 1 */
+ val |= BIT(0); /* NAND IDM NS = 1 */
+ mmio_write_32(HSLS_GPV_IDM2_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_APBY_NS);
+ val |= BIT(10); /* I2S NS = 1 */
+ val |= BIT(4); /* IOPAD NS = 1 */
+ val |= 0xf; /* UARTx NS = 1 */
+ mmio_write_32(HSLS_GPV_APBY_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_APBZ_NS);
+ val |= BIT(2); /* RNG NS = 1 */
+ mmio_write_32(HSLS_GPV_APBZ_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_APBS_NS);
+ val |= 0x3; /* SPIx NS = 1 */
+ mmio_write_32(HSLS_GPV_APBS_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_APBR_NS);
+ val |= BIT(7); /* QSPI APB NS = 1 */
+ val |= BIT(6); /* NAND APB NS = 1 */
+ val |= BIT(5); /* NOR APB NS = 1 */
+ val |= BIT(4); /* AMAC APB NS = 1 */
+ val |= BIT(1); /* DMA S1 APB NS = 1 */
+ mmio_write_32(HSLS_GPV_APBR_NS, val);
+
+ val = mmio_read_32(HSLS_SDIO0_SLAVE_NS);
+ val |= BIT(0); /* SDIO0 NS = 1 */
+ mmio_write_32(HSLS_SDIO0_SLAVE_NS, val);
+
+ val = mmio_read_32(HSLS_SDIO1_SLAVE_NS);
+ val |= BIT(0); /* SDIO1 NS = 1 */
+ mmio_write_32(HSLS_SDIO1_SLAVE_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_APBX_NS);
+ val |= BIT(14); /* SMBUS1 NS = 1 */
+ val |= BIT(13); /* GPIO NS = 1 */
+ val |= BIT(12); /* WDT NS = 1 */
+ val |= BIT(11); /* SMBUS0 NS = 1 */
+ val |= BIT(10); /* Timer7 NS = 1 */
+ val |= BIT(9); /* Timer6 NS = 1 */
+ val |= BIT(8); /* Timer5 NS = 1 */
+ val |= BIT(7); /* Timer4 NS = 1 */
+ val |= BIT(6); /* Timer3 NS = 1 */
+ val |= BIT(5); /* Timer2 NS = 1 */
+ val |= BIT(4); /* Timer1 NS = 1 */
+ val |= BIT(3); /* Timer0 NS = 1 */
+ val |= BIT(2); /* MDIO NS = 1 */
+ val |= BIT(1); /* PWM NS = 1 */
+ mmio_write_32(HSLS_GPV_APBX_NS, val);
+
+ val = mmio_read_32(HSLS_GPV_QSPI_S0_NS);
+ val |= BIT(0); /* QSPI NS = 1 */
+ mmio_write_32(HSLS_GPV_QSPI_S0_NS, val);
+
+#ifdef USE_FS4
+ val = 0x1; /* FS4 Crypto rm_slave */
+ mmio_write_32(FS4_CRYPTO_GPV_RM_SLAVE_NS, val);
+ val = 0x1; /* FS4 Crypto apb_switch */
+ mmio_write_32(FS4_CRYPTO_GPV_APB_SWITCH_NS, val);
+
+ val = 0x1; /* FS4 Raid rm_slave */
+ mmio_write_32(FS4_RAID_GPV_RM_SLAVE_NS, val);
+ val = 0x1; /* FS4 Raid apb_switch */
+ mmio_write_32(FS4_RAID_GPV_APB_SWITCH_NS, val);
+
+ val = 0x1; /* FS4 Crypto IDM */
+ mmio_write_32(FS4_CRYPTO_IDM_NS, val);
+ val = 0x1; /* FS4 RAID IDM */
+ mmio_write_32(FS4_RAID_IDM_NS, val);
+#endif
+
+#ifdef BL31_CCN_NONSECURE
+ /* Enable non-secure access to CCN registers */
+ mmio_write_32(OLY_MN_REGISTERS_NODE0_SECURE_ACCESS, 0x1);
+#endif
+
+#ifdef DDR_CTRL_PHY_NONSECURE
+ mmio_write_32(SCR_NOC_DDR_REGISTER_ACCESS, 0x1);
+#endif
+
+ paxc_mhb_ns_init();
+
+ /* unlock scr idm for non secure access */
+ mmio_write_32(SCR_NOC_SECURITY0, 0xffffffff);
+
+ INFO("security init done\r\n");
+}
+
+void brcm_gpio_pad_ns_init(void)
+{
+ /* configure all GPIO pads for non secure world access*/
+ mmio_write_32(GPIO_S_CNTRL_REG, 0xffffffff); /* 128-140 gpio pads */
+ mmio_write_32(GPIO_S_CNTRL_REG + 0x4, 0xffffffff); /* 96-127 gpio pad */
+ mmio_write_32(GPIO_S_CNTRL_REG + 0x8, 0xffffffff); /* 64-95 gpio pad */
+ mmio_write_32(GPIO_S_CNTRL_REG + 0xc, 0xffffffff); /* 32-63 gpio pad */
+ mmio_write_32(GPIO_S_CNTRL_REG + 0x10, 0xffffffff); /* 0-31 gpio pad */
+}
+
+#ifndef USE_DDR
+static void brcm_stingray_sram_ns_init(void)
+{
+ uintptr_t sram_root = TZC400_FS_SRAM_ROOT;
+ uintptr_t noc_root = NIC400_FS_NOC_ROOT;
+
+ mmio_write_32(sram_root + GATE_KEEPER_OFFSET, 1);
+ mmio_write_32(sram_root + REGION_ATTRIBUTES_0_OFFSET, 0xc0000000);
+ mmio_write_32(sram_root + REGION_ID_ACCESS_0_OFFSET, 0x00010001);
+ mmio_write_32(noc_root + NIC400_FS_NOC_SECURITY4_OFFSET, 0x1);
+ INFO(" stingray sram ns init done.\n");
+}
+#endif
+
+static void ccn_pre_init(void)
+{
+ /*
+ * Set WFC bit of RN-I nodes where FS4 is connected.
+ * This is required inorder to wait for read/write requests
+ * completion acknowledgment. Otherwise FS4 Ring Manager is
+ * getting stale data because of re-ordering of read/write
+ * requests at CCN level
+ */
+ mmio_setbits_32(OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL,
+ OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC);
+}
+
+static void ccn_post_init(void)
+{
+ mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST,
+ SRP_RNI_PCIE_CONNECTED);
+ mmio_setbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL,
+ SA_AUX_CTL_SER_DEVNE_WR);
+
+ mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_POS_CONTROL,
+ POS_CONTROL_HNI_POS_EN);
+ mmio_clrbits_32(OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL,
+ SA_AUX_CTL_POS_EARLY_WR_COMP_EN);
+}
+
+#ifndef BL31_BOOT_PRELOADED_SCP
+static void crmu_init(void)
+{
+ /*
+ * Configure CRMU for using SMMU
+ */
+
+ /*Program CRMU Stream ID */
+ mmio_write_32(CRMU_MASTER_AXI_ARUSER_CONFIG,
+ (CRMU_STREAM_ID << CRMU_SID_SHIFT));
+ mmio_write_32(CRMU_MASTER_AXI_AWUSER_CONFIG,
+ (CRMU_STREAM_ID << CRMU_SID_SHIFT));
+
+ /* Create Identity mapping */
+ arm_smmu_create_identity_map(DOMAIN_CRMU);
+
+ /* Enable Client Port for Secure Masters*/
+ arm_smmu_enable_secure_client_port();
+}
+#endif
+
+static void brcm_fsx_init(void)
+{
+#if defined(USE_FS4) && defined(USE_FS6)
+ #error "USE_FS4 and USE_FS6 should not be used together"
+#endif
+
+#ifdef USE_FS4
+ fsx_init(eFS4_CRYPTO, FS4_CRYPTO_RING_COUNT, FS4_CRYPTO_DME_COUNT,
+ FS4_CRYPTO_AE_COUNT, FS4_CRYPTO_START_STREAM_ID,
+ FS4_CRYPTO_MSI_DEVICE_ID, FS4_CRYPTO_IDM_IO_CONTROL_DIRECT,
+ FS4_CRYPTO_IDM_RESET_CONTROL, FS4_CRYPTO_BASE,
+ FS4_CRYPTO_DME_BASE);
+
+ fsx_init(eFS4_RAID, FS4_RAID_RING_COUNT, FS4_RAID_DME_COUNT,
+ FS4_RAID_AE_COUNT, FS4_RAID_START_STREAM_ID,
+ FS4_RAID_MSI_DEVICE_ID, FS4_RAID_IDM_IO_CONTROL_DIRECT,
+ FS4_RAID_IDM_RESET_CONTROL, FS4_RAID_BASE,
+ FS4_RAID_DME_BASE);
+
+ fsx_meminit("raid",
+ FS4_RAID_IDM_IO_CONTROL_DIRECT,
+ FS4_RAID_IDM_IO_STATUS);
+#endif
+}
+
+static void bcm_bl33_pass_info(void)
+{
+ struct bl33_info *info = (struct bl33_info *)BL33_SHARED_DDR_BASE;
+
+ if (sizeof(*info) > BL33_SHARED_DDR_SIZE)
+ WARN("bl33 shared area not reserved\n");
+
+ info->version = BL33_INFO_VERSION;
+ info->chip.chip_id = PLAT_CHIP_ID_GET;
+ info->chip.rev_id = PLAT_CHIP_REV_GET;
+}
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, CORTEX_A72_L2CTLR_EL1)
+
+void plat_bcm_bl31_early_platform_setup(void *from_bl2,
+ bl_params_t *plat_params_from_bl2)
+{
+#ifdef BL31_BOOT_PRELOADED_SCP
+ image_info_t scp_image_info;
+
+ scp_image_info.image_base = PRELOADED_SCP_BASE;
+ scp_image_info.image_size = PRELOADED_SCP_SIZE;
+ plat_bcm_bl2_plat_handle_scp_bl2(&scp_image_info);
+#endif
+ /*
+ * In BL31, logs are saved to DDR and we have much larger space to
+ * store logs. We can now afford to save all logs >= the 'INFO' level
+ */
+ bcm_elog_init((void *)BCM_ELOG_BL31_BASE, BCM_ELOG_BL31_SIZE,
+ LOG_LEVEL_INFO);
+
+ INFO("L2CTLR = 0x%lx\n", read_l2ctlr_el1());
+
+ brcm_timer_sync_init();
+
+ brcm_stingray_dma_pl330_init();
+
+ brcm_stingray_dma_pl330_meminit();
+
+ brcm_stingray_spi_pl022_init(APBS_IDM_IDM_RESET_CONTROL);
+
+#ifdef USE_AMAC
+ brcm_stingray_amac_init();
+#endif
+
+ brcm_stingray_sdio_init();
+
+#ifdef NCSI_IO_DRIVE_STRENGTH_MA
+ brcm_stingray_ncsi_init();
+#endif
+
+#ifdef USE_USB
+ xhci_phy_init();
+#endif
+
+#ifdef USE_SATA
+ brcm_stingray_sata_init();
+#else
+ poweroff_sata_pll();
+#endif
+
+ ccn_pre_init();
+
+ brcm_fsx_init();
+
+ brcm_stingray_smmu_init();
+
+ brcm_stingray_pka_meminit();
+
+ brcm_stingray_crmu_access_init();
+
+ brcm_stingray_scr_init();
+
+ brcm_stingray_hsls_tzpcprot_init();
+
+#ifdef USE_I2S
+ brcm_stingray_audio_init();
+#endif
+
+ ccn_post_init();
+
+ paxb_init();
+
+ paxc_init();
+
+#ifndef BL31_BOOT_PRELOADED_SCP
+ crmu_init();
+#endif
+
+ /* Note: this should be last thing because
+ * FS4 GPV registers only work after FS4 block
+ * (i.e. crypto,raid,cop) is out of reset.
+ */
+ brcm_stingray_security_init();
+
+ brcm_gpio_pad_ns_init();
+
+#ifndef USE_DDR
+ brcm_stingray_sram_ns_init();
+#endif
+
+#ifdef BL31_FORCE_CPU_FULL_FREQ
+ bcm_set_ihost_pll_freq(0x0, PLL_FREQ_FULL);
+#endif
+
+ brcm_stingray_gain_qspi_control();
+
+#ifdef USE_PAXC
+ /*
+ * Check that the handshake has occurred and report ChiMP status.
+ * This is required. Otherwise (especially on Palladium)
+ * Linux might have booted to the pcie stage whereas
+ * ChiMP has not yet booted. Note that nic_mode case has already
+ * been considered above.
+ */
+ if ((boot_source_get() != BOOT_SOURCE_QSPI) &&
+ (!bcm_chimp_is_nic_mode()) &&
+ (!bcm_chimp_wait_handshake())
+ ) {
+ /* Does ChiMP report an error ? */
+ uint32_t err;
+
+ err = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG);
+ if ((err & CHIMP_ERROR_MASK) == 0)
+ /* ChiMP has not booted yet, but no error reported */
+ WARN("ChiMP not booted yet, but no error reported.\n");
+ }
+
+#if DEBUG
+ if (boot_source_get() != BOOT_SOURCE_QSPI)
+ INFO("Current ChiMP Status: 0x%x; bpe_mod reg: 0x%x\n"
+ "fastboot register: 0x%x; handshake register 0x%x\n",
+ bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG),
+ bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG),
+ bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
+ bcm_chimp_read(CHIMP_REG_ECO_RESERVED));
+#endif /* DEBUG */
+#endif
+
+#ifdef FS4_DISABLE_CLOCK
+ flush_dcache_range(
+ PLAT_BRCM_TRUSTED_SRAM_BASE,
+ PLAT_BRCM_TRUSTED_SRAM_SIZE);
+ fs4_disable_clocks(true, true, true);
+#endif
+
+ /* pass information to BL33 through shared DDR region */
+ bcm_bl33_pass_info();
+
+ /*
+ * We are not yet at the end of BL31, but we can stop log here so we do
+ * not need to add 'bcm_elog_exit' to the standard BL31 code. The
+ * benefit of capturing BL31 logs after this is very minimal in a
+ * production system
+ */
+ bcm_elog_exit();
+
+#if !BRCM_DISABLE_TRUSTED_WDOG
+ /*
+ * Secure watchdog was started earlier in BL2, now it's time to stop
+ * it
+ */
+ sp805_stop(ARM_SP805_TWDG_BASE);
+#endif
+}
diff --git a/plat/brcm/board/stingray/src/brcm_pm_ops.c b/plat/brcm/board/stingray/src/brcm_pm_ops.c
new file mode 100644
index 0000000..5e07fac
--- /dev/null
+++ b/plat/brcm/board/stingray/src/brcm_pm_ops.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/ccn.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <brcm_scpi.h>
+#include <chimp.h>
+#include <cmn_plat_util.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#include "m0_cfg.h"
+
+
+#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL2])
+
+#define VENDOR_RST_TYPE_SHIFT 4
+
+#if HW_ASSISTED_COHERENCY
+/*
+ * On systems where participant CPUs are cache-coherent, we can use spinlocks
+ * instead of bakery locks.
+ */
+spinlock_t event_lock;
+#define event_lock_get(_lock) spin_lock(&_lock)
+#define event_lock_release(_lock) spin_unlock(&_lock)
+
+#else
+/*
+ * Use bakery locks for state coordination as not all participants are
+ * cache coherent now.
+ */
+DEFINE_BAKERY_LOCK(event_lock);
+#define event_lock_get(_lock) bakery_lock_get(&_lock)
+#define event_lock_release(_lock) bakery_lock_release(&_lock)
+#endif
+
+static int brcm_pwr_domain_on(u_register_t mpidr)
+{
+ /*
+ * SCP takes care of powering up parent power domains so we
+ * only need to care about level 0
+ */
+ scpi_set_brcm_power_state(mpidr, scpi_power_on, scpi_power_on,
+ scpi_power_on);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Handler called when a power level has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from. This handler would never be invoked with
+ * the system power domain uninitialized as either the primary would have taken
+ * care of it as part of cold boot or the first core awakened from system
+ * suspend would have already initialized it.
+ ******************************************************************************/
+static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
+
+ /* Assert that the system power domain need not be initialized */
+ assert(SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_RUN);
+
+ assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF);
+
+ /*
+ * Perform the common cluster specific operations i.e enable coherency
+ * if this cluster was off.
+ */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) {
+ INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id);
+ ccn_enter_snoop_dvm_domain(1 << cluster_id);
+ }
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_brcm_gic_pcpu_init();
+
+ /* Enable the gic cpu interface */
+ plat_brcm_gic_cpuif_enable();
+}
+
+static void brcm_power_down_common(void)
+{
+ unsigned int standbywfil2, standbywfi;
+ uint64_t mpidr = read_mpidr_el1();
+
+ switch (MPIDR_AFFLVL1_VAL(mpidr)) {
+ case 0x0:
+ standbywfi = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI;
+ standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2;
+ break;
+ case 0x1:
+ standbywfi = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI;
+ standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2;
+ break;
+ case 0x2:
+ standbywfi = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI;
+ standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2;
+ break;
+ case 0x3:
+ standbywfi = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI;
+ standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2;
+ break;
+ default:
+ ERROR("Invalid cluster #%" PRIx64 "\n", MPIDR_AFFLVL1_VAL(mpidr));
+ return;
+ }
+ /* Clear the WFI status bit */
+ event_lock_get(event_lock);
+ mmio_setbits_32(CDRU_PROC_EVENT_CLEAR,
+ (1 << (standbywfi + MPIDR_AFFLVL0_VAL(mpidr))) |
+ (1 << standbywfil2));
+ event_lock_release(event_lock);
+}
+
+/*
+ * Helper function to inform power down state to SCP.
+ */
+static void brcm_scp_suspend(const psci_power_state_t *target_state)
+{
+ uint32_t cluster_state = scpi_power_on;
+ uint32_t system_state = scpi_power_on;
+
+ /* Check if power down at system power domain level is requested */
+ if (SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
+ system_state = scpi_power_retention;
+
+ /* Check if Cluster is to be turned off */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
+ cluster_state = scpi_power_off;
+
+ /*
+ * Ask the SCP to power down the appropriate components depending upon
+ * their state.
+ */
+ scpi_set_brcm_power_state(read_mpidr_el1(),
+ scpi_power_off,
+ cluster_state,
+ system_state);
+}
+
+/*
+ * Helper function to turn off a CPU power domain and its parent power domains
+ * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we
+ * call the suspend helper here.
+ */
+static void brcm_scp_off(const psci_power_state_t *target_state)
+{
+ brcm_scp_suspend(target_state);
+}
+
+static void brcm_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
+
+ assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF);
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_brcm_gic_cpuif_disable();
+
+ /* Turn redistributor off */
+ plat_brcm_gic_redistif_off();
+
+ /* If Cluster is to be turned off, disable coherency */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
+ ccn_exit_snoop_dvm_domain(1 << cluster_id);
+
+ brcm_power_down_common();
+
+ brcm_scp_off(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when the CPU power domain is about to enter standby.
+ ******************************************************************************/
+static void brcm_cpu_standby(plat_local_state_t cpu_state)
+{
+ unsigned int scr;
+
+ assert(cpu_state == PLAT_LOCAL_STATE_RET);
+
+ scr = read_scr_el3();
+ /*
+ * Enable the Non secure interrupt to wake the CPU.
+ * In GICv3 affinity routing mode, the non secure group1 interrupts use
+ * the PhysicalFIQ at EL3 whereas in GICv2, it uses the PhysicalIRQ.
+ * Enabling both the bits works for both GICv2 mode and GICv3 affinity
+ * routing mode.
+ */
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+ isb();
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR to the original value, synchronisation of scr_el3 is
+ * done by eret while el3_exit to save some execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+/*
+ * Helper function to shutdown the system via SCPI.
+ */
+static void __dead2 brcm_scp_sys_shutdown(void)
+{
+ /*
+ * Disable GIC CPU interface to prevent pending interrupt
+ * from waking up the AP from WFI.
+ */
+ plat_brcm_gic_cpuif_disable();
+
+ /* Flush and invalidate data cache */
+ dcsw_op_all(DCCISW);
+
+ /* Bring Cluster out of coherency domain as its going to die */
+ plat_brcm_interconnect_exit_coherency();
+
+ brcm_power_down_common();
+
+ /* Send the power down request to the SCP */
+ scpi_sys_power_state(scpi_system_shutdown);
+
+ wfi();
+ ERROR("BRCM System Off: operation not handled.\n");
+ panic();
+}
+
+/*
+ * Helper function to reset the system
+ */
+static void __dead2 brcm_scp_sys_reset(unsigned int reset_type)
+{
+ /*
+ * Disable GIC CPU interface to prevent pending interrupt
+ * from waking up the AP from WFI.
+ */
+ plat_brcm_gic_cpuif_disable();
+
+ /* Flush and invalidate data cache */
+ dcsw_op_all(DCCISW);
+
+ /* Bring Cluster out of coherency domain as its going to die */
+ plat_brcm_interconnect_exit_coherency();
+
+ brcm_power_down_common();
+
+ /* Send the system reset request to the SCP
+ *
+ * As per PSCI spec system power state could be
+ * 0-> Shutdown
+ * 1-> Reboot- Board level Reset
+ * 2-> Reset - SoC level Reset
+ *
+ * Spec allocates 8 bits, 2 nibble, for this. One nibble is sufficient
+ * for sending the state hence We are utilizing 2nd nibble for vendor
+ * define reset type.
+ */
+ scpi_sys_power_state((reset_type << VENDOR_RST_TYPE_SHIFT) |
+ scpi_system_reboot);
+
+ wfi();
+ ERROR("BRCM System Reset: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 brcm_system_reset(void)
+{
+ unsigned int reset_type;
+
+ if (bcm_chimp_is_nic_mode())
+ reset_type = SOFT_RESET_L3;
+ else
+ reset_type = SOFT_SYS_RESET_L1;
+
+ brcm_scp_sys_reset(reset_type);
+}
+
+static int brcm_system_reset2(int is_vendor, int reset_type,
+ u_register_t cookie)
+{
+ if (!is_vendor) {
+ /* Architectural warm boot: only warm reset is supported */
+ reset_type = SOFT_RESET_L3;
+ } else {
+ uint32_t boot_source = (uint32_t)cookie;
+
+ boot_source &= BOOT_SOURCE_MASK;
+ brcm_stingray_set_straps(boot_source);
+ }
+ brcm_scp_sys_reset(reset_type);
+
+ /*
+ * brcm_scp_sys_reset cannot return (it is a __dead function),
+ * but brcm_system_reset2 has to return some value, even in
+ * this case.
+ */
+ return 0;
+}
+
+static int brcm_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint >= BRCM_NS_DRAM1_BASE) &&
+ (entrypoint < (BRCM_NS_DRAM1_BASE + BRCM_NS_DRAM1_SIZE)))
+ return PSCI_E_SUCCESS;
+#ifdef __aarch64__
+ if ((entrypoint >= BRCM_DRAM2_BASE) &&
+ (entrypoint < (BRCM_DRAM2_BASE + BRCM_DRAM2_SIZE)))
+ return PSCI_E_SUCCESS;
+
+ if ((entrypoint >= BRCM_DRAM3_BASE) &&
+ (entrypoint < (BRCM_DRAM3_BASE + BRCM_DRAM3_SIZE)))
+ return PSCI_E_SUCCESS;
+#endif
+
+ return PSCI_E_INVALID_ADDRESS;
+}
+
+/*******************************************************************************
+ * ARM standard platform handler called to check the validity of the power state
+ * parameter.
+ ******************************************************************************/
+static int brcm_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's possible to enter standby only on power level 0
+ * Ignore any other power level.
+ */
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] =
+ PLAT_LOCAL_STATE_RET;
+ } else {
+ for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ PLAT_LOCAL_STATE_OFF;
+ }
+
+ /*
+ * We expect the 'state id' to be zero.
+ */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard
+ * platform will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t plat_brcm_psci_pm_ops = {
+ .pwr_domain_on = brcm_pwr_domain_on,
+ .pwr_domain_on_finish = brcm_pwr_domain_on_finish,
+ .pwr_domain_off = brcm_pwr_domain_off,
+ .cpu_standby = brcm_cpu_standby,
+ .system_off = brcm_scp_sys_shutdown,
+ .system_reset = brcm_system_reset,
+ .system_reset2 = brcm_system_reset2,
+ .validate_ns_entrypoint = brcm_validate_ns_entrypoint,
+ .validate_power_state = brcm_validate_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ *psci_ops = &plat_brcm_psci_pm_ops;
+
+ /* Setup mailbox with entry point. */
+ mmio_write_64(CRMU_CFG_BASE + offsetof(M0CFG, core_cfg.rvbar),
+ sec_entrypoint);
+
+ return 0;
+}
diff --git a/plat/brcm/board/stingray/src/fsx.c b/plat/brcm/board/stingray/src/fsx.c
new file mode 100644
index 0000000..5725a2e
--- /dev/null
+++ b/plat/brcm/board/stingray/src/fsx.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/common_def.h>
+
+#include <fsx.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#define FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN 0
+
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON 11
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK 12
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON 13
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK 14
+#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO 15
+#define FS4_IDM_IO_CONTROL_DIRECT__CLK_EN 31
+
+#define FS4_IDM_IO_STATUS__MEM_POWERON 0
+#define FS4_IDM_IO_STATUS__MEM_POWEROK 1
+#define FS4_IDM_IO_STATUS__MEM_ARRPOWERON 2
+#define FS4_IDM_IO_STATUS__MEM_ARRPOWEROK 3
+#define FS4_IDM_IO_STATUS__MEM_ALLOK 0xf
+
+#define FS4_IDM_RESET_CONTROL__RESET 0
+
+#define FSX_RINGx_BASE(__b, __i) \
+ ((__b) + (__i) * 0x10000)
+
+#define FSX_RINGx_VERSION_NUMBER(__b, __i) \
+ (FSX_RINGx_BASE(__b, __i) + 0x0)
+
+#define FSX_RINGx_MSI_DEV_ID(__b, __i) \
+ (FSX_RINGx_BASE(__b, __i) + 0x44)
+
+#define FSX_COMM_RINGx_BASE(__b, __i) \
+ ((__b) + 0x200000 + (__i) * 0x100)
+
+#define FSX_COMM_RINGx_CONTROL(__b, __i) \
+ (FSX_COMM_RINGx_BASE(__b, __i) + 0x0)
+#define FSX_COMM_RINGx_CONTROL__AXI_ID 8
+#define FSX_COMM_RINGx_CONTROL__AXI_ID_MASK 0x1f
+#define FSX_COMM_RINGx_CONTROL__PRIORITY 4
+#define FSX_COMM_RINGx_CONTROL__PRIORITY_MASK 0x7
+#define FSX_COMM_RINGx_CONTROL__AE_GROUP 0
+#define FSX_COMM_RINGx_CONTROL__AE_GROUP_MASK 0x7
+
+#define FSX_COMM_RINGx_MSI_DEV_ID(__b, __i) \
+ (FSX_COMM_RINGx_BASE(__b, __i) + 0x4)
+
+#define FSX_AEx_BASE(__b, __i) \
+ ((__b) + 0x202000 + (__i) * 0x100)
+
+#define FSX_AEx_CONTROL_REGISTER(__b, __i) \
+ (FSX_AEx_BASE(__b, __i) + 0x0)
+#define FSX_AEx_CONTROL_REGISTER__ACTIVE 4
+#define FSX_AEx_CONTROL_REGISTER__GROUP_ID 0
+#define FSX_AEx_CONTROL_REGISTER__GROUP_ID_MASK 0x7
+
+#define FSX_COMM_RM_RING_SECURITY_SETTING 0x0
+
+#define FSX_COMM_RM_SSID_CONTROL 0x4
+#define FSX_COMM_RM_SSID_CONTROL__RING_BITS 5
+#define FSX_COMM_RM_SSID_CONTROL__MASK 0x3ff
+
+#define FSX_COMM_RM_CONTROL_REGISTER 0x8
+#define FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE 2
+#define FSX_COMM_RM_CONTROL_REGISTER__AE_TIMEOUT 5
+#define FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING 7
+
+#define FSX_COMM_RM_TIMER_CONTROL_0 0xc
+#define FSX_COMM_RM_TIMER_CONTROL_0__FAST 16
+#define FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM 0
+
+#define FSX_COMM_RM_TIMER_CONTROL_1 0x10
+#define FSX_COMM_RM_TIMER_CONTROL_1__SLOW 16
+#define FSX_COMM_RM_TIMER_CONTROL_1__IDLE 0
+
+#define FSX_COMM_RM_BURST_BD_THRESHOLD 0x14
+#define FSX_COMM_RM_BURST_BD_THRESHOLD_LOW 0
+#define FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH 16
+
+#define FSX_COMM_RM_BURST_LENGTH 0x18
+#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN 16
+#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN_MASK 0x1ff
+#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE 0
+#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE_MASK 0x1ff
+
+#define FSX_COMM_RM_FIFO_THRESHOLD 0x1c
+#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL 16
+#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL_MASK 0x1ff
+#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL 0
+#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL_MASK 0x1f
+
+#define FSX_COMM_RM_AE_TIMEOUT 0x24
+
+#define FSX_COMM_RM_RING_FLUSH_TIMEOUT 0x2c
+
+#define FSX_COMM_RM_MEMORY_CONFIGURATION 0x30
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN 12
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN 13
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN 14
+#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN 15
+
+#define FSX_COMM_RM_AXI_CONTROL 0x34
+#define FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN 28
+#define FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN 24
+#define FSX_COMM_RM_AXI_CONTROL__AWQOS 20
+#define FSX_COMM_RM_AXI_CONTROL__ARQOS 16
+#define FSX_COMM_RM_AXI_CONTROL__AWPROT 12
+#define FSX_COMM_RM_AXI_CONTROL__ARPROT 8
+#define FSX_COMM_RM_AXI_CONTROL__AWCACHE 4
+#define FSX_COMM_RM_AXI_CONTROL__ARCACHE 0
+
+#define FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR 0x48
+
+#define FSX_COMM_RM_GROUP_PKT_EXTENSION_SUPPORT 0xc0
+
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD 0xc8
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MASK 0x1ff
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX 16
+#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN 0
+
+#define FSX_COMM_RM_GROUP_RING_COUNT 0xcc
+
+#define FSX_COMM_RM_MAIN_HW_INIT_DONE 0x12c
+#define FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK 0x1
+
+#define FSX_DMEx_BASE(__b, __i) \
+ ((__b) + (__i) * 0x1000)
+
+#define FSX_DMEx_AXI_CONTROL(__b, __i) \
+ (FSX_DMEx_BASE(__b, __i) + 0x4)
+#define FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN 28
+#define FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN 24
+#define FSX_DMEx_AXI_CONTROL__AWQOS 20
+#define FSX_DMEx_AXI_CONTROL__ARQOS 16
+#define FSX_DMEx_AXI_CONTROL__AWCACHE 4
+#define FSX_DMEx_AXI_CONTROL__ARCACHE 0
+
+#define FSX_DMEx_WR_FIFO_THRESHOLD(__b, __i) \
+ (FSX_DMEx_BASE(__b, __i) + 0xc)
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MASK 0x3ff
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MAX 10
+#define FSX_DMEx_WR_FIFO_THRESHOLD__MIN 0
+
+#define FSX_DMEx_RD_FIFO_THRESHOLD(__b, __i) \
+ (FSX_DMEx_BASE(__b, __i) + 0x14)
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MASK 0x3ff
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MAX 10
+#define FSX_DMEx_RD_FIFO_THRESHOLD__MIN 0
+
+#define FS6_SUB_TOP_BASE 0x66D8F800
+#define FS6_PKI_DME_RESET 0x4
+#define PKI_DME_RESET 1
+
+char *fsx_type_names[] = {
+ "fs4-raid",
+ "fs4-crypto",
+ "fs6-pki",
+};
+
+void fsx_init(eFSX_TYPE fsx_type,
+ unsigned int ring_count,
+ unsigned int dme_count,
+ unsigned int ae_count,
+ unsigned int start_stream_id,
+ unsigned int msi_dev_id,
+ uintptr_t idm_io_control_direct,
+ uintptr_t idm_reset_control,
+ uintptr_t base,
+ uintptr_t dme_base)
+{
+ int try;
+ unsigned int i, v, data;
+ uintptr_t fs4_idm_io_control_direct = idm_io_control_direct;
+ uintptr_t fs4_idm_reset_control = idm_reset_control;
+ uintptr_t fsx_comm_rm = (base + 0x203000);
+
+ VERBOSE("fsx %s init start\n", fsx_type_names[fsx_type]);
+
+ if (fsx_type == eFS4_RAID || fsx_type == eFS4_CRYPTO) {
+ /* Enable FSx engine clock */
+ VERBOSE(" - enable fsx clock\n");
+ mmio_write_32(fs4_idm_io_control_direct,
+ (1U << FS4_IDM_IO_CONTROL_DIRECT__CLK_EN));
+ udelay(500);
+
+ /* Reset FSx engine */
+ VERBOSE(" - reset fsx\n");
+ v = mmio_read_32(fs4_idm_reset_control);
+ v |= (1 << FS4_IDM_RESET_CONTROL__RESET);
+ mmio_write_32(fs4_idm_reset_control, v);
+ udelay(500);
+ v = mmio_read_32(fs4_idm_reset_control);
+ v &= ~(1 << FS4_IDM_RESET_CONTROL__RESET);
+ mmio_write_32(fs4_idm_reset_control, v);
+ } else {
+ /*
+ * Default RM and AE are out of reset,
+ * So only DME Reset added here
+ */
+ v = mmio_read_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET);
+ v &= ~(PKI_DME_RESET);
+ mmio_write_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET, v);
+ }
+
+ /* Wait for HW-init done */
+ VERBOSE(" - wait for HW-init done\n");
+ try = 10000;
+ do {
+ udelay(1);
+ data = mmio_read_32(fsx_comm_rm +
+ FSX_COMM_RM_MAIN_HW_INIT_DONE);
+ try--;
+ } while (!(data & FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK) && (try > 0));
+
+ if (try <= 0)
+ ERROR("fsx_comm_rm + 0x%x: 0x%x\n",
+ data, FSX_COMM_RM_MAIN_HW_INIT_DONE);
+
+ /* Make all rings non-secured */
+ VERBOSE(" - make all rings non-secured\n");
+ v = 0xffffffff;
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_SECURITY_SETTING, v);
+
+ /* Set start stream-id for rings to */
+ VERBOSE(" - set start stream-id for rings to 0x%x\n",
+ start_stream_id);
+ v = start_stream_id >> FSX_COMM_RM_SSID_CONTROL__RING_BITS;
+ v &= FSX_COMM_RM_SSID_CONTROL__MASK;
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_SSID_CONTROL, v);
+
+ /* Set timer configuration */
+ VERBOSE(" - set timer configuration\n");
+ v = 0x0271 << FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM;
+ v |= (0x0138 << FSX_COMM_RM_TIMER_CONTROL_0__FAST);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_0, v);
+ v = 0x09c4 << FSX_COMM_RM_TIMER_CONTROL_1__IDLE;
+ v |= (0x04e2 << FSX_COMM_RM_TIMER_CONTROL_1__SLOW);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_1, v);
+ v = 0x0000f424;
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_FLUSH_TIMEOUT, v);
+
+ /* Set burst length and fifo threshold */
+ VERBOSE(" - set burst length, fifo and bd threshold\n");
+ v = 0x0;
+ v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN);
+ v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_LENGTH, v);
+ v = 0x0;
+ v |= (0x67 << FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL);
+ v |= (0x18 << FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_FIFO_THRESHOLD, v);
+ v = 0x0;
+ v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_LOW);
+ v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_BD_THRESHOLD, v);
+
+ /* Set memory configuration */
+ VERBOSE(" - set memory configuration\n");
+ v = 0x0;
+ v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN);
+ v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN);
+ v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN);
+ v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_MEMORY_CONFIGURATION, v);
+
+ /* AXI configuration for RM */
+ v = 0;
+ v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN);
+ v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN);
+ v |= (0xe << FSX_COMM_RM_AXI_CONTROL__AWQOS);
+ v |= (0xa << FSX_COMM_RM_AXI_CONTROL__ARQOS);
+ v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__AWPROT);
+ v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__ARPROT);
+ v |= (0xf << FSX_COMM_RM_AXI_CONTROL__AWCACHE);
+ v |= (0xf << FSX_COMM_RM_AXI_CONTROL__ARCACHE);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL, v);
+ VERBOSE(" - set AXI control = 0x%x\n",
+ mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL));
+ v = 0x0;
+ v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX);
+ v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD, v);
+ VERBOSE(" - set AXI read burst threshold = 0x%x\n",
+ mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD));
+
+ /* Configure group ring count for all groups */
+ /* By default we schedule extended packets
+ * on all AEs/DMEs in a group.
+ */
+ v = (dme_count & 0xf) << 0;
+ v |= (dme_count & 0xf) << 4;
+ v |= (dme_count & 0xf) << 8;
+ v |= (dme_count & 0xf) << 12;
+ v |= (dme_count & 0xf) << 16;
+ v |= (dme_count & 0xf) << 20;
+ v |= (dme_count & 0xf) << 24;
+ v |= (dme_count & 0xf) << 28;
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_GROUP_RING_COUNT, v);
+
+ /*
+ * Due to HW issue spurious interrupts are getting generated.
+ * To fix sw needs to clear the config status interrupts
+ * before setting CONFIG_DONE.
+ */
+ mmio_write_32(fsx_comm_rm +
+ FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR,
+ 0xffffffff);
+
+ /* Configure RM control */
+ VERBOSE(" - configure RM control\n");
+ v = mmio_read_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER);
+ v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
+ v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE);
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
+
+ /* Configure AE timeout */
+ VERBOSE(" - configure AE timeout\n");
+ v = 0x00003fff;
+ mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AE_TIMEOUT, v);
+
+ /* Initialize all AEs */
+ for (i = 0; i < ae_count; i++) {
+ VERBOSE(" - initialize AE%d\n", i);
+ v = (0x1 << FSX_AEx_CONTROL_REGISTER__ACTIVE);
+ mmio_write_32(FSX_AEx_CONTROL_REGISTER(base, i), v);
+ }
+
+ /* Initialize all DMEs */
+ for (i = 0; i < dme_count; i++) {
+ VERBOSE(" - initialize DME%d\n", i);
+ v = 0;
+ v |= (0x1 << FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN);
+ v |= (0x1 << FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN);
+ v |= (0xe << FSX_DMEx_AXI_CONTROL__AWQOS);
+ v |= (0xa << FSX_DMEx_AXI_CONTROL__ARQOS);
+ v |= (0xf << FSX_DMEx_AXI_CONTROL__AWCACHE);
+ v |= (0xf << FSX_DMEx_AXI_CONTROL__ARCACHE);
+ mmio_write_32(FSX_DMEx_AXI_CONTROL(dme_base, i), v);
+ VERBOSE(" -- AXI_CONTROL = 0x%x\n",
+ mmio_read_32(FSX_DMEx_AXI_CONTROL(dme_base, i)));
+ v = 0;
+ v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MIN);
+ v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MAX);
+ mmio_write_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i), v);
+ VERBOSE(" -- WR_FIFO_THRESHOLD = 0x%x\n",
+ mmio_read_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i)));
+ v = 0;
+ v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MIN);
+ v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MAX);
+ mmio_write_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i), v);
+ VERBOSE(" -- RD_FIFO_THRESHOLD = 0x%x\n",
+ mmio_read_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i)));
+ }
+
+ /* Configure ring axi id and msi device id */
+ for (i = 0; i < ring_count; i++) {
+ VERBOSE(" - ring%d version=0x%x\n", i,
+ mmio_read_32(FSX_RINGx_VERSION_NUMBER(base, i)));
+ mmio_write_32(FSX_COMM_RINGx_MSI_DEV_ID(base, i),
+ msi_dev_id);
+ v = 0;
+ v |= ((i & FSX_COMM_RINGx_CONTROL__AXI_ID_MASK) <<
+ FSX_COMM_RINGx_CONTROL__AXI_ID);
+ mmio_write_32(FSX_COMM_RINGx_CONTROL(base, i), v);
+ }
+
+ INFO("fsx %s init done\n", fsx_type_names[fsx_type]);
+}
+
+void fsx_meminit(const char *name,
+ uintptr_t idm_io_control_direct,
+ uintptr_t idm_io_status)
+{
+ int try;
+ unsigned int val;
+
+ VERBOSE("fsx %s meminit start\n", name);
+
+ VERBOSE(" - arrpoweron\n");
+ mmio_setbits_32(idm_io_control_direct,
+ BIT(FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON));
+ while (!(mmio_read_32(idm_io_status) &
+ BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWERON)))
+ ;
+
+ VERBOSE(" - arrpowerok\n");
+ mmio_setbits_32(idm_io_control_direct,
+ (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK));
+ while (!(mmio_read_32(idm_io_status) &
+ BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWEROK)))
+ ;
+
+ VERBOSE(" - poweron\n");
+ mmio_setbits_32(idm_io_control_direct,
+ (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON));
+ while (!(mmio_read_32(idm_io_status) &
+ BIT(FS4_IDM_IO_STATUS__MEM_POWERON)))
+ ;
+
+ VERBOSE(" - powerok\n");
+ mmio_setbits_32(idm_io_control_direct,
+ (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK));
+ while (!(mmio_read_32(idm_io_status) &
+ BIT(FS4_IDM_IO_STATUS__MEM_POWEROK)))
+ ;
+
+ /* Final check on all power bits */
+ try = 10;
+ do {
+ val = mmio_read_32(idm_io_status);
+ if (val == FS4_IDM_IO_STATUS__MEM_ALLOK)
+ break;
+
+ /* Wait sometime */
+ mdelay(1);
+
+ try--;
+ } while (try > 0);
+
+ /* Remove memory isolation if things are fine. */
+ if (try <= 0) {
+ INFO(" - powerup failed\n");
+ } else {
+ VERBOSE(" - remove isolation\n");
+ mmio_clrbits_32(idm_io_control_direct,
+ (1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO));
+ VERBOSE(" - powerup done\n");
+ }
+
+ INFO("fsx %s meminit done\n", name);
+}
+
+void fs4_disable_clocks(bool disable_sram,
+ bool disable_crypto,
+ bool disable_raid)
+{
+ VERBOSE("fs4 disable clocks start\n");
+
+ if (disable_sram) {
+ VERBOSE(" - disable sram clock\n");
+ mmio_clrbits_32(FS4_SRAM_IDM_IO_CONTROL_DIRECT,
+ (1 << FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN));
+ }
+
+ if (disable_crypto) {
+ VERBOSE(" - disable crypto clock\n");
+ mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+ CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK);
+ }
+
+ if (disable_raid) {
+ VERBOSE(" - disable raid clock\n");
+ mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+ CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK);
+ }
+
+ if (disable_sram && disable_crypto && disable_raid) {
+ VERBOSE(" - disable root clock\n");
+ mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
+ CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK);
+ mmio_setbits_32(CDRU_GENPLL2_CONTROL1,
+ CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK);
+ }
+
+ INFO("fs4 disable clocks done\n");
+}
diff --git a/plat/brcm/board/stingray/src/ihost_pm.c b/plat/brcm/board/stingray/src/ihost_pm.c
new file mode 100644
index 0000000..9141d3e
--- /dev/null
+++ b/plat/brcm/board/stingray/src/ihost_pm.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <dmu.h>
+#include <ihost_pm.h>
+#include <platform_def.h>
+
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1 2
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2 1
+#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3 0
+#define CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET 9
+#define CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET 8
+#define CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET 7
+#define A72_CRM_SOFTRESETN_0 0x480
+#define A72_CRM_SOFTRESETN_1 0x484
+#define A72_CRM_DOMAIN_4_CONTROL 0x810
+#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT 3
+#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM 6
+#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O 0
+#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_3 0xB4C
+#define MEMORY_PDA_HI_SHIFT 0x0
+#define A72_CRM_PLL_PWR_ON 0x70
+#define A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT 4
+#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO 1
+#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL 0
+#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_2 0xB48
+#define A72_CRM_PLL_INTERRUPT_STATUS 0x8c
+#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_LOST_STATUS 8
+#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_STATUS 9
+#define A72_CRM_INTERRUPT_ENABLE 0x4
+#define A72_CRM_INTERRUPT_ENABLE__PLL0_INT_ENABLE 4
+#define A72_CRM_PLL_INTERRUPT_ENABLE 0x88
+#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_STATUS_INT_ENB 9
+#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_LOST_STATUS_INT_ENB 8
+#define A72_CRM_PLL0_CFG0_CTRL 0x120
+#define A72_CRM_PLL0_CFG1_CTRL 0x124
+#define A72_CRM_PLL0_CFG2_CTRL 0x128
+#define A72_CRM_PLL0_CFG3_CTRL 0x12C
+#define A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV 0
+#define A72_CRM_CORE_CONFIG_DBGCTRL 0xD50
+#define A72_CRM_CORE_CONFIG_DBGROM_LO 0xD54
+#define A72_CRM_CORE_CONFIG_DBGROM_HI 0xD58
+#define A72_CRM_SUBSYSTEM_CONFIG_1__DBGL1RSTDISABLE 2
+#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN 0
+#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN 1
+#define A72_CRM_AXI_CLK_DESC 0x304
+#define A72_CRM_ACP_CLK_DESC 0x308
+#define A72_CRM_ATB_CLK_DESC 0x30C
+#define A72_CRM_PCLKDBG_DESC 0x310
+#define A72_CRM_CLOCK_MODE_CONTROL 0x40
+#define A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER 0
+#define A72_CRM_CLOCK_CONTROL_0 0x200
+#define A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL 0
+#define A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL 2
+#define A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL 4
+#define A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL 6
+#define A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL 8
+#define A72_CRM_CLOCK_CONTROL_1 0x204
+#define A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL 6
+#define A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL 8
+#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN 0
+#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN 1
+#define A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN 9
+#define A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN 10
+#define A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN 11
+#define A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN 12
+#define A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN 15
+#define A72_CRM_SOFTRESETN_0__L2_SOFTRESETN 3
+#define A72_CRM_SOFTRESETN_1__APB_SOFTRESETN 8
+
+/* core related regs */
+#define A72_CRM_DOMAIN_0_CONTROL 0x800
+#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM 0x6
+#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O 0x0
+#define A72_CRM_DOMAIN_1_CONTROL 0x804
+#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM 0x6
+#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O 0x0
+#define A72_CRM_CORE_CONFIG_RVBA0_LO 0xD10
+#define A72_CRM_CORE_CONFIG_RVBA0_MID 0xD14
+#define A72_CRM_CORE_CONFIG_RVBA0_HI 0xD18
+#define A72_CRM_CORE_CONFIG_RVBA1_LO 0xD20
+#define A72_CRM_CORE_CONFIG_RVBA1_MID 0xD24
+#define A72_CRM_CORE_CONFIG_RVBA1_HI 0xD28
+#define A72_CRM_SUBSYSTEM_CONFIG_0 0xC80
+#define A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT 4
+#define A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN 4
+#define A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN 5
+#define A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN 0
+#define A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN 4
+#define A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN 1
+#define A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN 5
+
+#define SPROC_MEMORY_BISR 0
+
+static int cluster_power_status[PLAT_BRCM_CLUSTER_COUNT] = {CLUSTER_POWER_ON,
+ CLUSTER_POWER_OFF,
+ CLUSTER_POWER_OFF,
+ CLUSTER_POWER_OFF};
+
+void ihost_power_on_cluster(u_register_t mpidr)
+{
+ uint32_t rst, d2xs;
+ uint32_t cluster_id;
+ uint32_t ihost_base;
+#if SPROC_MEMORY_BISR
+ uint32_t bisr, cnt;
+#endif
+ cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ uint32_t cluster0_freq_sel;
+
+ if (cluster_power_status[cluster_id] == CLUSTER_POWER_ON)
+ return;
+
+ cluster_power_status[cluster_id] = CLUSTER_POWER_ON;
+ INFO("enabling Cluster #%u\n", cluster_id);
+
+ switch (cluster_id) {
+ case 1:
+ rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET);
+ d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1);
+#if SPROC_MEMORY_BISR
+ bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1;
+#endif
+ break;
+ case 2:
+ rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET);
+ d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2);
+#if SPROC_MEMORY_BISR
+ bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2;
+#endif
+ break;
+ case 3:
+ rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET);
+ d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3);
+#if SPROC_MEMORY_BISR
+ bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3;
+#endif
+ break;
+ default:
+ ERROR("Invalid cluster :%u\n", cluster_id);
+ return;
+ }
+
+ /* Releasing ihost resets */
+ mmio_setbits_32(CDRU_MISC_RESET_CONTROL, rst);
+
+ /* calculate cluster/ihost base address */
+ ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
+
+ /* Remove Cluster IO isolation */
+ mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_4_CONTROL,
+ (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O),
+ (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT) |
+ (1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM));
+
+ /*
+ * Since BISR sequence requires that all cores of cluster should
+ * have removed I/O isolation hence doing same here.
+ */
+ /* Remove core0 memory IO isolations */
+ mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_0_CONTROL,
+ (1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O),
+ (1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM));
+
+ /* Remove core1 memory IO isolations */
+ mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_1_CONTROL,
+ (1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O),
+ (1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM));
+
+#if SPROC_MEMORY_BISR
+ mmio_setbits_32(CRMU_BISR_PDG_MASK, (1 << bisr));
+
+ if (!(mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW) &
+ (1 << CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE))) {
+ /* BISR completion would take max 2 usec */
+ cnt = 0;
+ while (cnt < 2) {
+ udelay(1);
+ if (mmio_read_32(CRMU_CHIP_OTPC_STATUS) &
+ (1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE))
+ break;
+ cnt++;
+ }
+ }
+
+ /* if BISR is not completed, need to be checked with ASIC team */
+ if (((mmio_read_32(CRMU_CHIP_OTPC_STATUS)) &
+ (1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE)) == 0) {
+ WARN("BISR did not completed and need to be addressed\n");
+ }
+#endif
+
+ /* PLL Power up. supply is already on. Turn on PLL LDO/PWR */
+ mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON,
+ (1 << A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT) |
+ (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) |
+ (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL));
+
+ /* 1us in spec; Doubling it to be safe*/
+ udelay(2);
+
+ /* Remove PLL output ISO */
+ mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON,
+ (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) |
+ (1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL));
+
+ /*
+ * PLL0 Configuration Control Register
+ * these 4 registers drive the i_pll_ctrl[63:0] input of pll
+ * (16b per register).
+ * the values are derived from the spec (sections 8 and 10).
+ */
+
+ mmio_write_32(ihost_base + A72_CRM_PLL0_CFG0_CTRL, 0x00000000);
+ mmio_write_32(ihost_base + A72_CRM_PLL0_CFG1_CTRL, 0x00008400);
+ mmio_write_32(ihost_base + A72_CRM_PLL0_CFG2_CTRL, 0x00000001);
+ mmio_write_32(ihost_base + A72_CRM_PLL0_CFG3_CTRL, 0x00000000);
+
+ /* Read the freq_sel from cluster 0, which is up already */
+ cluster0_freq_sel = bcm_get_ihost_pll_freq(0);
+ bcm_set_ihost_pll_freq(cluster_id, cluster0_freq_sel);
+
+ udelay(1);
+
+ /* Release clock source reset */
+ mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+ (1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN));
+
+ udelay(1);
+
+ /*
+ * Integer division for clks (divider value = n+1).
+ * These are the divisor of ARM PLL clock frequecy.
+ */
+ mmio_write_32(ihost_base + A72_CRM_AXI_CLK_DESC, 0x00000001);
+ mmio_write_32(ihost_base + A72_CRM_ACP_CLK_DESC, 0x00000001);
+ mmio_write_32(ihost_base + A72_CRM_ATB_CLK_DESC, 0x00000004);
+ mmio_write_32(ihost_base + A72_CRM_PCLKDBG_DESC, 0x0000000b);
+
+ /*
+ * clock change trigger - must set to take effect after clock
+ * source change
+ */
+ mmio_setbits_32(ihost_base + A72_CRM_CLOCK_MODE_CONTROL,
+ (1 << A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER));
+
+ /* turn on functional clocks */
+ mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_0,
+ (3 << A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL) |
+ (3 << A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL) |
+ (3 << A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL) |
+ (3 << A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL) |
+ (3 << A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL));
+
+ mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_1,
+ (3 << A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL) |
+ (3 << A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL));
+
+ /* Program D2XS Power Down Registers */
+ mmio_setbits_32(CDRU_CCN_REGISTER_CONTROL_1, d2xs);
+
+ /* Program Core Config Debug ROM Address Registers */
+ /* mark valid for Debug ROM base address */
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGCTRL,
+ (1 << A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV));
+
+ /* Program Lo and HI address of coresight DBG rom address */
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_LO,
+ (CORESIGHT_BASE_ADDR >> 12) & 0xffff);
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_HI,
+ (CORESIGHT_BASE_ADDR >> 28) & 0xffff);
+
+ /*
+ * Release soft resets of different components.
+ * Order: Bus clocks --> PERIPH --> L2 --> cores
+ */
+
+ /* Bus clocks soft resets */
+ mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+ (1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN));
+
+ mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1,
+ (1 << A72_CRM_SOFTRESETN_1__APB_SOFTRESETN));
+
+ /* Periph component softreset */
+ mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+ (1 << A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN));
+
+ /* L2 softreset */
+ mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+ (1 << A72_CRM_SOFTRESETN_0__L2_SOFTRESETN));
+
+ /* Enable and program Satellite timer */
+ ihost_enable_satellite_timer(cluster_id);
+}
+
+void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar)
+{
+ uint32_t ihost_base;
+ uint32_t coreid = MPIDR_AFFLVL0_VAL(mpidr);
+ uint32_t cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+
+ ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
+ INFO("programming core #%u\n", coreid);
+
+ if (coreid) {
+ /* program the entry point for core1 */
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_LO,
+ rvbar & 0xFFFF);
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_MID,
+ (rvbar >> 16) & 0xFFFF);
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_HI,
+ (rvbar >> 32) & 0xFFFF);
+ } else {
+ /* program the entry point for core */
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_LO,
+ rvbar & 0xFFFF);
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_MID,
+ (rvbar >> 16) & 0xFFFF);
+ mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_HI,
+ (rvbar >> 32) & 0xFFFF);
+ }
+
+ /* Tell debug logic which processor is up */
+ mmio_setbits_32(ihost_base + A72_CRM_SUBSYSTEM_CONFIG_0,
+ (coreid ?
+ (2 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT) :
+ (1 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT)));
+
+ /* releasing soft resets for IHOST core */
+ mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
+ (coreid ?
+ (1 << A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN) :
+ (1 << A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN)));
+
+ mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1,
+ (coreid ?
+ ((1 << A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN)) :
+ ((1 << A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN) |
+ (1 << A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN))));
+}
diff --git a/plat/brcm/board/stingray/src/iommu.c b/plat/brcm/board/stingray/src/iommu.c
new file mode 100644
index 0000000..de8b995
--- /dev/null
+++ b/plat/brcm/board/stingray/src/iommu.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <iommu.h>
+#include <platform_def.h>
+
+#define SMMU_BASE 0x64000000
+#define ARM_SMMU_MAX_NUM_CNTXT_BANK 64
+#define SMMU_CTX_BANK_IDX_SECURE_CRMU 63
+#define ARM_SMMU_NUM_SECURE_MASTER 1
+#define ARM_SMMU_NSNUMCBO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \
+ ARM_SMMU_NUM_SECURE_MASTER)
+#define ARM_SMMU_NSNUMSMRGO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \
+ ARM_SMMU_NUM_SECURE_MASTER)
+/* Reserved Banks. */
+#define SMMU_CTX_BANK_IDX (SMMU_CTX_BANK_IDX_SECURE_CRMU - \
+ ARM_SMMU_NUM_SECURE_MASTER)
+#define NUM_OF_SMRS 1
+
+#define STG1_WITH_STG2_BYPASS 1
+#define ARM_LPAE_PGTBL_PHYS_CRMU 0x880000000
+#define ARM_LPAE_PGTBL_PHYS 0x880200000
+#define ARM_LPAE_PGTBL_PTE_CNT 512
+#define ARM_LPAE_PTE_L1_BLOCK_SIZE 0x40000000
+#define ARM_LPAE_PTE_L1_ADDR_MASK 0x0000FFFFC0000000UL
+#define ARM_LPAE_PTE_TABLE 0x2UL
+#define ARM_LPAE_PTE_VALID 0x1UL
+#define ARM_LPAE_PTE_ATTRINDX 2
+#define ARM_LPAE_PTE_NS 5
+#define ARM_LPAE_PTE_AP 6
+#define ARM_LPAE_PTE_AP_EL1_RW 0x0
+#define ARM_LPAE_PTE_AP_EL0_RW 0x1
+#define ARM_LPAE_PTE_SH 8
+#define ARM_LPAE_PTE_SH_NON 0x0
+#define ARM_LPAE_PTE_SH_OUTER 0x2
+#define ARM_LPAE_PTE_SH_INNER 0x3
+#define ARM_LPAE_PTE_AF 10
+#define ARM_SMMU_RES_SIZE 0x80000
+
+#define ARM_LPAE_PTE_NSTABLE 0x8000000000000000UL
+#define ARM_LPAE_PTE_L1_INDEX_SHIFT 30
+#define ARM_LPAE_PTE_L1_INDEX_MASK 0x1ff
+#define ARM_LPAE_PTE_L0_INDEX_SHIFT 39
+#define ARM_LPAE_PTE_L0_INDEX_MASK 0x1ff
+#define ARM_LPAE_PTE_TABLE_MASK ~(0xfffUL)
+/* Configuration registers */
+#define ARM_SMMU_GR0_sCR0 0x0
+#define sCR0_CLIENTPD (1 << 0)
+#define sCR0_GFRE (1 << 1)
+#define sCR0_GFIE (1 << 2)
+#define sCR0_GCFGFRE (1 << 4)
+#define sCR0_GCFGFIE (1 << 5)
+#define sCR0_USFCFG (1 << 10)
+#define sCR0_VMIDPNE (1 << 11)
+#define sCR0_PTM (1 << 12)
+#define sCR0_FB (1 << 13)
+#define sCR0_VMID16EN (1 << 31)
+#define sCR0_BSU_SHIFT 14
+#define sCR0_BSU_MASK 0x3
+#define ARM_SMMU_SMMU_SCR1 0x4
+#define SCR1_NSNUMCBO_MASK 0xFF
+#define SCR1_NSNUMCBO_SHIFT 0x0
+#define SCR1_NSNUMSMRGO_MASK 0xFF00
+#define SCR1_NSNUMSMRGO_SHIFT 0x8
+
+/* Identification registers */
+#define ARM_SMMU_GR0_ID0 0x20
+#define ARM_SMMU_GR0_ID1 0x24
+#define ARM_SMMU_GR0_ID2 0x28
+#define ARM_SMMU_GR0_ID3 0x2c
+#define ARM_SMMU_GR0_ID4 0x30
+#define ARM_SMMU_GR0_ID5 0x34
+#define ARM_SMMU_GR0_ID6 0x38
+#define ARM_SMMU_GR0_ID7 0x3c
+#define ARM_SMMU_GR0_sGFSR 0x48
+#define ARM_SMMU_GR0_sGFSYNR0 0x50
+#define ARM_SMMU_GR0_sGFSYNR1 0x54
+#define ARM_SMMU_GR0_sGFSYNR2 0x58
+
+#define ID1_PAGESIZE (1U << 31)
+#define ID1_NUMPAGENDXB_SHIFT 28
+#define ID1_NUMPAGENDXB_MASK 7
+#define ID1_NUMS2CB_SHIFT 16
+#define ID1_NUMS2CB_MASK 0xff
+#define ID1_NUMCB_SHIFT 0
+#define ID1_NUMCB_MASK 0xff
+
+/* SMMU global address space */
+#define ARM_SMMU_GR0(smmu) ((smmu)->base)
+#define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift))
+
+/* Stream mapping registers */
+#define ARM_SMMU_GR0_SMR(n) (0x800 + (n << 2))
+#define SMR_VALID (1U << 31)
+#define SMR_MASK_SHIFT 16
+#define SMR_ID_SHIFT 0
+
+#define ARM_SMMU_GR0_S2CR(n) (0xc00 + (n << 2))
+#define S2CR_CBNDX_SHIFT 0
+#define S2CR_CBNDX_MASK 0xff
+#define S2CR_TYPE_SHIFT 16
+#define S2CR_TYPE_MASK 0x3
+
+#define ARM_SMMU_GR1_CBA2R(n) (0x800 + (n << 2))
+#define CBA2R_RW64_32BIT (0 << 0)
+#define CBA2R_RW64_64BIT (1 << 0)
+#define CBA2R_VMID_SHIFT 16
+#define CBA2R_VMID_MASK 0xffff
+
+#define ARM_SMMU_GR1_CBAR(n) (0x0 + (n << 2))
+#define CBAR_VMID_SHIFT 0
+#define CBAR_VMID_MASK 0xff
+#define CBAR_S1_BPSHCFG_SHIFT 8
+#define CBAR_S1_BPSHCFG_MASK 3
+#define CBAR_S1_BPSHCFG_NSH 3
+#define CBAR_S1_MEMATTR_SHIFT 12
+#define CBAR_S1_MEMATTR_MASK 0xf
+#define CBAR_S1_MEMATTR_WB 0xf
+#define CBAR_TYPE_SHIFT 16
+#define CBAR_TYPE_MASK 0x3
+#define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT)
+#define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT)
+#define CBAR_IRPTNDX_SHIFT 24
+#define CBAR_IRPTNDX_MASK 0xff
+
+/* Translation context bank */
+#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1))
+#define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift))
+
+#define ARM_SMMU_CB_SCTLR 0x0
+#define ARM_SMMU_CB_ACTLR 0x4
+#define ARM_SMMU_CB_RESUME 0x8
+#define ARM_SMMU_CB_TTBCR2 0x10
+#define ARM_SMMU_CB_TTBR0 0x20
+#define ARM_SMMU_CB_TTBR1 0x28
+#define ARM_SMMU_CB_TTBCR 0x30
+#define ARM_SMMU_CB_CONTEXTIDR 0x34
+#define ARM_SMMU_CB_S1_MAIR0 0x38
+#define ARM_SMMU_CB_S1_MAIR1 0x3c
+#define ARM_SMMU_CB_PAR 0x50
+#define ARM_SMMU_CB_FSR 0x58
+#define ARM_SMMU_CB_FAR 0x60
+#define ARM_SMMU_CB_FSYNR0 0x68
+#define ARM_SMMU_CB_S1_TLBIVA 0x600
+#define ARM_SMMU_CB_S1_TLBIASID 0x610
+#define ARM_SMMU_CB_S1_TLBIVAL 0x620
+#define ARM_SMMU_CB_S2_TLBIIPAS2 0x630
+#define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638
+#define ARM_SMMU_CB_ATS1PR 0x800
+#define ARM_SMMU_CB_ATSR 0x8f0
+
+#define SCTLR_S1_ASIDPNE (1 << 12)
+#define SCTLR_CFCFG (1 << 7)
+#define SCTLR_CFIE (1 << 6)
+#define SCTLR_CFRE (1 << 5)
+#define SCTLR_E (1 << 4)
+#define SCTLR_AFE (1 << 2)
+#define SCTLR_TRE (1 << 1)
+#define SCTLR_M (1 << 0)
+
+/* ARM LPAE configuration. */
+/**************************************************************/
+/* Register bits */
+#define ARM_32_LPAE_TCR_EAE (1 << 31)
+#define ARM_64_LPAE_S2_TCR_RES1 (1 << 31)
+
+#define ARM_LPAE_TCR_EPD1 (1 << 23)
+
+#define ARM_LPAE_TCR_TG0_4K (0 << 14)
+#define ARM_LPAE_TCR_TG0_64K (1 << 14)
+#define ARM_LPAE_TCR_TG0_16K (2 << 14)
+
+#define ARM_LPAE_TCR_SH0_SHIFT 12
+#define ARM_LPAE_TCR_SH0_MASK 0x3
+#define ARM_LPAE_TCR_SH_NS 0
+#define ARM_LPAE_TCR_SH_OS 2
+#define ARM_LPAE_TCR_SH_IS 3
+
+#define ARM_LPAE_TCR_ORGN0_SHIFT 10
+#define ARM_LPAE_TCR_IRGN0_SHIFT 8
+#define ARM_LPAE_TCR_RGN_MASK 0x3
+#define ARM_LPAE_TCR_RGN_NC 0
+#define ARM_LPAE_TCR_RGN_WBWA 1
+#define ARM_LPAE_TCR_RGN_WT 2
+#define ARM_LPAE_TCR_RGN_WB 3
+
+#define ARM_LPAE_TCR_SL0_SHIFT 6
+#define ARM_LPAE_TCR_SL0_MASK 0x3
+
+#define ARM_LPAE_TCR_T0SZ_SHIFT 0
+#define ARM_LPAE_TCR_SZ_MASK 0xf
+
+#define ARM_LPAE_TCR_PS_SHIFT 16
+#define ARM_LPAE_TCR_PS_MASK 0x7
+
+#define ARM_LPAE_TCR_IPS_SHIFT 32
+#define ARM_LPAE_TCR_IPS_MASK 0x7
+
+#define ARM_LPAE_TCR_PS_32_BIT 0x0ULL
+#define ARM_LPAE_TCR_PS_36_BIT 0x1ULL
+#define ARM_LPAE_TCR_PS_40_BIT 0x2ULL
+#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL
+#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL
+#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL
+
+#define ARM_LPAE_MAIR_ATTR_SHIFT(n) ((n) << 3)
+#define ARM_LPAE_MAIR_ATTR_MASK 0xff
+#define ARM_LPAE_MAIR_ATTR_DEVICE 0x04
+#define ARM_LPAE_MAIR_ATTR_NC 0x44
+#define ARM_LPAE_MAIR_ATTR_WBRWA 0xff
+#define ARM_LPAE_MAIR_ATTR_IDX_NC 0
+#define ARM_LPAE_MAIR_ATTR_IDX_CACHE 1
+#define ARM_LPAE_MAIR_ATTR_IDX_DEV 2
+
+#define TTBRn_ASID_SHIFT 48
+#define TTBCR2_SEP_SHIFT 15
+#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_AS (1 << 4)
+#define TTBCR_T0SZ(ia_bits) (64 - (ia_bits))
+
+#define S2CR_PRIVCFG_SHIFT 24
+#define S2CR_PRIVCFG_MASK 0x3
+
+/**************************************************************/
+
+uint16_t paxc_stream_ids[] = { 0x2000 };
+
+uint16_t paxc_stream_ids_mask[] = { 0x1fff };
+uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID };
+uint16_t crmu_stream_ids_mask[] = { 0x0 };
+
+enum arm_smmu_s2cr_type {
+ S2CR_TYPE_TRANS,
+ S2CR_TYPE_BYPASS,
+ S2CR_TYPE_FAULT,
+};
+
+enum arm_smmu_s2cr_privcfg {
+ S2CR_PRIVCFG_DEFAULT,
+ S2CR_PRIVCFG_DIPAN,
+ S2CR_PRIVCFG_UNPRIV,
+ S2CR_PRIVCFG_PRIV,
+};
+
+struct arm_smmu_smr {
+ uint16_t mask;
+ uint16_t id;
+ uint32_t valid;
+};
+
+struct arm_smmu_s2cr {
+ int count;
+ enum arm_smmu_s2cr_type type;
+ enum arm_smmu_s2cr_privcfg privcfg;
+ uint8_t cbndx;
+};
+
+struct arm_smmu_cfg {
+ uint8_t cbndx;
+ uint8_t irptndx;
+ uint32_t cbar;
+};
+
+struct arm_smmu_device {
+ uint8_t *base;
+ uint32_t streams;
+ unsigned long size;
+ unsigned long pgshift;
+ unsigned long va_size;
+ unsigned long ipa_size;
+ unsigned long pa_size;
+ struct arm_smmu_smr smr[NUM_OF_SMRS];
+ struct arm_smmu_s2cr s2cr[NUM_OF_SMRS];
+ struct arm_smmu_cfg cfg[NUM_OF_SMRS];
+ uint16_t *stream_ids;
+ uint16_t *stream_ids_mask;
+};
+
+void arm_smmu_enable_secure_client_port(void)
+{
+ uintptr_t smmu_base = SMMU_BASE;
+
+ mmio_clrbits_32(smmu_base, sCR0_CLIENTPD);
+}
+
+void arm_smmu_reserve_secure_cntxt(void)
+{
+ uintptr_t smmu_base = SMMU_BASE;
+
+ mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1,
+ (SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK),
+ ((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) |
+ (ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT)));
+}
+
+static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index)
+{
+ uint32_t idx = smmu->cfg[index].cbndx;
+ struct arm_smmu_smr *smr = &smmu->smr[index];
+ uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
+
+ if (smr->valid)
+ reg |= SMR_VALID;
+
+ mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
+ ARM_SMMU_GR0_SMR(idx)), reg);
+}
+
+static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index)
+{
+ uint32_t idx = smmu->cfg[index].cbndx;
+ struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index];
+
+ uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT |
+ (s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
+ (s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
+
+ mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
+ ARM_SMMU_GR0_S2CR(idx)), reg);
+}
+
+static void smmu_set_pgtbl(struct arm_smmu_device *smmu,
+ enum iommu_domain dom,
+ uint64_t *pg_table_base)
+{
+ int i, l0_index, l1_index;
+ uint64_t addr, *pte, *l0_base, *l1_base;
+ uint64_t addr_space_limit;
+
+ if (dom == PCIE_PAXC) {
+ addr_space_limit = 0xffffffffff;
+ } else if (dom == DOMAIN_CRMU) {
+ addr_space_limit = 0xffffffff;
+ } else {
+ ERROR("dom is not supported\n");
+ return;
+ }
+
+ l0_base = pg_table_base;
+ /* clear L0 descriptors. */
+ for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++)
+ l0_base[i] = 0x0;
+
+ addr = 0x0;
+ while (addr < addr_space_limit) {
+ /* find L0 pte */
+ l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) &
+ ARM_LPAE_PTE_L0_INDEX_MASK);
+ l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT);
+
+ /* setup L0 pte if required */
+ pte = l0_base + l0_index;
+ if (*pte == 0x0) {
+ *pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK);
+ if (dom == PCIE_PAXC)
+ *pte |= ARM_LPAE_PTE_NSTABLE;
+ *pte |= ARM_LPAE_PTE_TABLE;
+ *pte |= ARM_LPAE_PTE_VALID;
+ }
+
+ /* find L1 pte */
+ l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) &
+ ARM_LPAE_PTE_L1_INDEX_MASK);
+ pte = l1_base + l1_index;
+
+ /* setup L1 pte */
+ *pte = 0x0;
+ *pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK);
+ if (addr < 0x80000000) {
+ *pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV <<
+ ARM_LPAE_PTE_ATTRINDX);
+ if (dom == PCIE_PAXC)
+ *pte |= (1 << ARM_LPAE_PTE_NS);
+ } else {
+ *pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE <<
+ ARM_LPAE_PTE_ATTRINDX);
+ *pte |= (1 << ARM_LPAE_PTE_NS);
+ }
+ *pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP);
+ *pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH);
+ *pte |= (1 << ARM_LPAE_PTE_AF);
+ *pte |= ARM_LPAE_PTE_VALID;
+
+ addr += ARM_LPAE_PTE_L1_BLOCK_SIZE;
+ }
+}
+
+void arm_smmu_create_identity_map(enum iommu_domain dom)
+{
+ struct arm_smmu_device iommu;
+ struct arm_smmu_device *smmu = &iommu;
+ uint32_t reg, reg2;
+ unsigned long long reg64;
+ uint32_t idx;
+ uint16_t asid;
+ unsigned int context_bank_index;
+ unsigned long long pg_table_base;
+
+ smmu->base = (uint8_t *) SMMU_BASE;
+ reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1));
+ smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12;
+ smmu->size = ARM_SMMU_RES_SIZE;
+ smmu->stream_ids = NULL;
+
+ switch (dom) {
+ case PCIE_PAXC:
+ smmu->stream_ids = &paxc_stream_ids[0];
+ smmu->stream_ids_mask = &paxc_stream_ids_mask[0];
+ smmu->streams = ARRAY_SIZE(paxc_stream_ids);
+ context_bank_index = SMMU_CTX_BANK_IDX;
+ pg_table_base = ARM_LPAE_PGTBL_PHYS;
+ break;
+ case DOMAIN_CRMU:
+ smmu->stream_ids = &crmu_stream_ids[0];
+ smmu->stream_ids_mask = &crmu_stream_ids_mask[0];
+ smmu->streams = ARRAY_SIZE(crmu_stream_ids);
+ context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU;
+ pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU;
+ break;
+ default:
+ ERROR("domain not supported\n");
+ return;
+ }
+
+ if (smmu->streams > NUM_OF_SMRS) {
+ INFO("can not support more than %d sids\n", NUM_OF_SMRS);
+ return;
+ }
+
+ /* set up iommu dev. */
+ for (idx = 0; idx < smmu->streams; idx++) {
+ /* S2CR. */
+ smmu->s2cr[idx].type = S2CR_TYPE_TRANS;
+ smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT;
+ smmu->s2cr[idx].cbndx = context_bank_index;
+ smmu->cfg[idx].cbndx = context_bank_index;
+ smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT;
+ arm_smmu_s2cr_cfg(smmu, idx);
+
+ /* SMR. */
+ smmu->smr[idx].mask = smmu->stream_ids_mask[idx];
+ smmu->smr[idx].id = smmu->stream_ids[idx];
+ smmu->smr[idx].valid = 1;
+ arm_smmu_smr_cfg(smmu, idx);
+
+ /* CBA2R. 64-bit Translation */
+ mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
+ ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)),
+ 0x1);
+ /* CBAR.*/
+ reg = smmu->cfg[idx].cbar;
+ reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
+ (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+
+ mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
+ ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)),
+ reg);
+
+ /* TTBCR. */
+ reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) |
+ (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) |
+ (ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);
+ reg64 |= ARM_LPAE_TCR_TG0_4K;
+ reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT);
+ /* ias 40 bits.*/
+ reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT;
+ /* Disable speculative walks through TTBR1 */
+ reg64 |= ARM_LPAE_TCR_EPD1;
+ reg = (uint32_t) reg64;
+ reg2 = (uint32_t) (reg64 >> 32);
+ reg2 |= TTBCR2_SEP_UPSTREAM;
+ reg2 |= TTBCR2_AS;
+
+ mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+ ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+ ARM_SMMU_CB_TTBCR2), reg2);
+
+ mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+ ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+ ARM_SMMU_CB_TTBCR), reg);
+
+ /* TTBR0. */
+ asid = smmu->cfg[idx].cbndx;
+ reg64 = pg_table_base;
+ reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
+
+ mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+ ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+ ARM_SMMU_CB_TTBR0), reg64);
+ /* TTBR1. */
+ reg64 = 0;
+ reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
+
+ mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+ ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+ ARM_SMMU_CB_TTBR1), reg64);
+ /* MAIR. */
+ reg = (ARM_LPAE_MAIR_ATTR_NC
+ << ARM_LPAE_MAIR_ATTR_SHIFT
+ (ARM_LPAE_MAIR_ATTR_IDX_NC)) |
+ (ARM_LPAE_MAIR_ATTR_WBRWA <<
+ ARM_LPAE_MAIR_ATTR_SHIFT
+ (ARM_LPAE_MAIR_ATTR_IDX_CACHE)) |
+ (ARM_LPAE_MAIR_ATTR_DEVICE <<
+ ARM_LPAE_MAIR_ATTR_SHIFT
+ (ARM_LPAE_MAIR_ATTR_IDX_DEV));
+
+ mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+ ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+ ARM_SMMU_CB_S1_MAIR0), reg);
+
+ /* MAIR1. */
+ reg = 0;
+ mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+ ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+ ARM_SMMU_CB_S1_MAIR1), reg);
+ /* SCTLR. */
+ reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M;
+ /* stage 1.*/
+ reg |= SCTLR_S1_ASIDPNE;
+ mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
+ ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
+ ARM_SMMU_CB_SCTLR), reg);
+ }
+ smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base);
+}
diff --git a/plat/brcm/board/stingray/src/ncsi.c b/plat/brcm/board/stingray/src/ncsi.c
new file mode 100644
index 0000000..58ea9e2
--- /dev/null
+++ b/plat/brcm/board/stingray/src/ncsi.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <ncsi.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+static const char *const io_drives[] = {
+ "2mA", "4mA", "6mA", "8mA",
+ "10mA", "12mA", "14mA", "16mA"
+};
+
+void brcm_stingray_ncsi_init(void)
+{
+ unsigned int i = 0;
+ unsigned int selx = 0;
+
+#if NCSI_IO_DRIVE_STRENGTH_MA == 2
+ selx = 0x0;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 4
+ selx = 0x1;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 6
+ selx = 0x2;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 8
+ selx = 0x3;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 10
+ selx = 0x4;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 12
+ selx = 0x5;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 14
+ selx = 0x6;
+#elif NCSI_IO_DRIVE_STRENGTH_MA == 16
+ selx = 0x7;
+#else
+ ERROR("Unsupported NCSI_IO_DRIVE_STRENGTH_MA. Please check it.\n");
+ return;
+#endif
+ INFO("ncsi io drives: %s\n", io_drives[selx]);
+
+ for (i = 0; i < NITRO_NCSI_IOPAD_CONTROL_NUM; i++) {
+ mmio_clrsetbits_32((NITRO_NCSI_IOPAD_CONTROL_BASE + (i * 4)),
+ PAD_SELX_MASK, PAD_SELX_VALUE(selx));
+ }
+
+ INFO("ncsi init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/paxb.c b/plat/brcm/board/stingray/src/paxb.c
new file mode 100644
index 0000000..89f76d0
--- /dev/null
+++ b/plat/brcm/board/stingray/src/paxb.c
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <paxb.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+#define PCIE_CORE_PWR_ARR_POWERON 0x8
+#define PCIE_CORE_PWR_ARR_POWEROK 0x4
+#define PCIE_CORE_PWR_POWERON 0x2
+#define PCIE_CORE_PWR_POWEROK 0x1
+
+#define PCIE_CORE_USER_CFG (PCIE_CORE_BASE + 0x38)
+#define PCIE_PAXB_SMMU_SID_CFG (PCIE_CORE_BASE + 0x60)
+#ifdef SID_B8_D1_F1
+#define PAXB_SMMU_SID_CFG_BUS_WIDTH (0x8 << 8)
+#define PAXB_SMMU_SID_CFG_DEV_WIDTH (0x1 << 12)
+#define PAXB_SMMU_SID_CFG_FUN_WIDTH (0x1 << 16)
+#else
+#define PAXB_SMMU_SID_CFG_BUS_WIDTH (0x2 << 8)
+#define PAXB_SMMU_SID_CFG_DEV_WIDTH (0x5 << 12)
+#define PAXB_SMMU_SID_CFG_FUN_WIDTH (0x3 << 16)
+#endif
+
+#define PAXB_APB_TIMEOUT_COUNT_OFFSET 0x034
+
+/* allow up to 5 ms for each power switch to stabilize */
+#define PCIE_CORE_PWR_TIMEOUT_MS 5
+
+/* wait 1 microsecond for PCIe core soft reset */
+#define PCIE_CORE_SOFT_RST_DELAY_US 1
+
+/*
+ * List of PAXB APB registers
+ */
+#define PAXB_BASE 0x48000000
+#define PAXB_BASE_OFFSET 0x4000
+#define PAXB_OFFSET(core) (PAXB_BASE + \
+ (core) * PAXB_BASE_OFFSET)
+
+#define PAXB_CLK_CTRL_OFFSET 0x000
+#define PAXB_EP_PERST_SRC_SEL_MASK (1 << 2)
+#define PAXB_EP_MODE_PERST_MASK (1 << 1)
+#define PAXB_RC_PCIE_RST_OUT_MASK (1 << 0)
+
+#define PAXB_MAX_IMAP_WINDOWS 8
+#define PAXB_IMAP_REG_WIDTH 8
+#define PAXB_IMAP0_REG_WIDTH 4
+#define PAXB_AXUSER_REG_WIDTH 4
+
+#define PAXB_CFG_IND_ADDR_OFFSET 0x120
+#define PAXB_CFG_IND_DATA_OFFSET 0x124
+#define PAXB_CFG_IND_ADDR_MASK 0x1ffc
+#define PAXB_CFG_CFG_TYPE_MASK 0x1
+
+#define PAXB_EP_CFG_ADDR_OFFSET 0x1f8
+#define PAXB_EP_CFG_DATA_OFFSET 0x1fc
+#define PAXB_EP_CFG_ADDR_MASK 0xffc
+#define PAXB_EP_CFG_TYPE_MASK 0x1
+
+#define PAXB_0_DEFAULT_IMAP 0xed0
+#define DEFAULT_ADDR_INVALID BIT(0)
+#define PAXB_0_DEFAULT_IMAP_AXUSER 0xed8
+#define PAXB_0_DEFAULT_IMAP_AXCACHE 0xedc
+#define IMAP_AXCACHE 0xff
+#define OARR_VALID BIT(0)
+#define IMAP_VALID BIT(0)
+
+#define PAXB_IMAP0_BASE_OFFSET 0xc00
+#define PAXB_IARR0_BASE_OFFSET 0xd00
+#define PAXB_IMAP0_OFFSET(idx) (PAXB_IMAP0_BASE_OFFSET + \
+ (idx) * PAXB_IMAP0_REG_WIDTH)
+#define PAXB_IMAP0_WINDOW_SIZE 0x1000
+
+#define PAXB_IMAP2_OFFSET 0xcc0
+#define PAXB_IMAP0_REGS_TYPE_OFFSET 0xcd0
+#define PAXB_IARR2_LOWER_OFFSET 0xd10
+
+#define PAXB_IMAP3_BASE_OFFSET 0xe08
+#define PAXB_IMAP3_OFFSET(idx) (PAXB_IMAP3_BASE_OFFSET + \
+ (idx) * PAXB_IMAP_REG_WIDTH)
+
+#define PAXB_IMAP3_0_AXUSER_B_OFFSET 0xe48
+#define PAXB_IMAP3_0_AXUSER_OFFSET(idx) (PAXB_IMAP3_0_AXUSER_B_OFFSET + \
+ (idx) * PAXB_AXUSER_REG_WIDTH)
+
+#define PAXB_IMAP4_BASE_OFFSET 0xe70
+#define PAXB_IMAP4_OFFSET(idx) (PAXB_IMAP4_BASE_OFFSET + \
+ (idx) * PAXB_IMAP_REG_WIDTH)
+
+#define PAXB_IMAP4_0_AXUSER_B_OFFSET 0xeb0
+#define PAXB_IMAP4_0_AXUSER_OFFSET(idx) (PAXB_IMAP4_0_AXUSER_B_OFFSET + \
+ (idx) * PAXB_AXUSER_REG_WIDTH)
+
+#define PAXB_CFG_LINK_STATUS_OFFSET 0xf0c
+#define PAXB_CFG_PHYLINKUP_MASK (1 << 3)
+#define PAXB_CFG_DL_ACTIVE_MASK (1 << 2)
+
+#define PAXB_IMAP0_0_AXUSER_OFFSET 0xf60
+#define PAXB_IMAP2_AXUSER_OFFSET 0xfe0
+
+/* cacheable write-back, allocate on both reads and writes */
+#define IMAP_ARCACHE 0x0f0
+#define IMAP_AWCACHE 0xf00
+/* normal access, nonsecure access, and data access */
+/* AWQOS:0xe and ARQOS:0xa */
+/* AWPROT:0x2 and ARPROT:0x1 */
+#define IMAP_AXUSER 0x002e002a
+
+/*
+ * List of NIC security and PIPEMUX related registers
+ */
+#define SR_PCIE_NIC_SECURITY_BASE 0x58100000
+#define NS3Z_PCIE_NIC_SECURITY_BASE 0x48100000
+
+#define GITS_TRANSLATER 0x63c30000
+
+#define VENDOR_ID 0x14e4
+#define CFG_RC_DEV_ID 0x434
+#define CFG_RC_DEV_SUBID 0x438
+#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c
+#define PCI_CLASS_BRIDGE_MASK 0xffff00
+#define PCI_CLASS_BRIDGE_SHIFT 8
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+
+/*
+ * List of PAXB RC configuration space registers
+ */
+
+/* first capability list entry */
+#define PCI_CAPABILITY_LIST_OFFSET 0x34
+#define PCI_CAPABILITY_SPEED_OFFSET 0xc
+#define PCI_EP_CAPABILITY_OFFSET 0x10
+
+#define CFG_RC_LINK_STATUS_CTRL_2 0x0dc
+#define CFG_RC_LINK_SPEED_SHIFT 0
+#define CFG_RC_LINK_SPEED_MASK (0xf << CFG_RC_LINK_SPEED_SHIFT)
+
+#define CFG_RC_DEVICE_CAP 0x4d4
+#define CFG_RC_DEVICE_CAP_MPS_SHIFT 0
+#define CFG_RC_DEVICE_CAP_MPS_MASK (0x7 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+/* MPS 256 bytes */
+#define CFG_RC_DEVICE_CAP_MPS_256B (0x1 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+/* MPS 512 bytes */
+#define CFG_RC_DEVICE_CAP_MPS_512B (0x2 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
+
+#define CFG_RC_TL_FCIMM_NP_LIMIT 0xa10
+#define CFG_RC_TL_FCIMM_NP_VAL 0x01500000
+#define CFG_RC_TL_FCIMM_P_LIMIT 0xa14
+#define CFG_RC_TL_FCIMM_P_VAL 0x03408080
+
+#define CFG_RC_LINK_CAP 0x4dc
+#define CFG_RC_LINK_CAP_SPEED_SHIFT 0
+#define CFG_RC_LINK_CAP_SPEED_MASK (0xf << CFG_RC_LINK_CAP_SPEED_SHIFT)
+#define CFG_RC_LINK_CAP_WIDTH_SHIFT 4
+#define CFG_RC_LINK_CAP_WIDTH_MASK (0x1f << CFG_RC_LINK_CAP_WIDTH_SHIFT)
+
+#define CFG_LINK_CAP_RC 0x4f0
+#define CFG_RC_DL_ACTIVE_SHIFT 0
+#define CFG_RC_DL_ACTIVE_MASK (0x1 << CFG_RC_DL_ACTIVE_SHIFT)
+#define CFG_RC_SLOT_CLK_SHIFT 1
+#define CFG_RC_SLOT_CLK_MASK (0x1 << CFG_RC_SLOT_CLK_SHIFT)
+
+#define CFG_ROOT_CAP_RC 0x4f8
+#define CFG_ROOT_CAP_LTR_SHIFT 1
+#define CFG_ROOT_CAP_LTR_MASK (0x1 << CFG_ROOT_CAP_LTR_SHIFT)
+
+#define CFG_RC_CLKREQ_ENABLED 0x4fc
+#define CFG_RC_CLKREQ_ENABLED_SHIFT 0
+#define CFG_RC_CLKREQ_ENABLED_MASK (0x1 << CFG_RC_CLKREQ_ENABLED_SHIFT)
+
+#define CFG_RC_COEFF_ADDR 0x638
+
+#define CFG_RC_TL_CTRL_0 0x800
+#define RC_MEM_DW_CHK_MASK 0x03fe
+
+#define CFG_RC_PDL_CTRL_4 0x1010
+#define NPH_FC_INIT_SHIFT 24
+#define NPH_FC_INIT_MASK (U(0xff) << NPH_FC_INIT_SHIFT)
+#define PD_FC_INIT_SHIFT 12
+#define PD_FC_INIT_MASK (0xffff << PD_FC_INIT_SHIFT)
+
+#define CFG_RC_PDL_CTRL_5 0x1014
+#define PH_INIT_SHIFT 0
+#define PH_INIT_MASK (0xff << PH_INIT_SHIFT)
+
+#define DL_STATUS_OFFSET 0x1048
+#define PHYLINKUP BIT(13)
+
+#define PH_INIT 0x10
+#define PD_FC_INIT 0x100
+#define NPH_FC_INIT 0x8
+
+#define SRP_PH_INIT 0x7F
+#define SRP_PD_FC_INIT 0x200
+#define SRP_NPH_FC_INIT 0x7F
+
+#define CFG_ADDR_BUS_NUM_SHIFT 20
+#define CFG_ADDR_DEV_NUM_SHIFT 15
+#define CFG_ADDR_FUNC_NUM_SHIFT 12
+#define CFG_ADDR_REG_NUM_SHIFT 2
+#define CFG_ADDR_REG_NUM_MASK 0x00000ffc
+#define CFG_ADDR_CFG_TYPE_MASK 0x00000003
+
+#define DL_LINK_UP_TIMEOUT_MS 1000
+
+#define CFG_RETRY_STATUS 0xffff0001
+#define CRS_TIMEOUT_MS 5000
+
+/* create EP config data to write */
+#define DEF_BUS_NO 1 /* default bus 1 */
+#define DEF_SLOT_NO 0 /* default slot 0 */
+#define DEF_FN_NO 0 /* default fn 0 */
+
+#define EP_CONFIG_VAL(bus_no, slot, fn, where) \
+ (((bus_no) << CFG_ADDR_BUS_NUM_SHIFT) | \
+ ((slot) << CFG_ADDR_DEV_NUM_SHIFT) | \
+ ((fn) << CFG_ADDR_FUNC_NUM_SHIFT) | \
+ ((where) & CFG_ADDR_REG_NUM_MASK) | \
+ (1 & CFG_ADDR_CFG_TYPE_MASK))
+
+/* PAXB security offset */
+#define PAXB_SECURITY_IDM_OFFSET 0x1c
+#define PAXB_SECURITY_APB_OFFSET 0x24
+#define PAXB_SECURITY_ECAM_OFFSET 0x3c
+
+#define paxb_get_config(type) paxb_get_##type##_config()
+
+static unsigned int paxb_sec_reg_offset[] = {
+ 0x0c, /* PAXB0 AXI */
+ 0x10, /* PAXB1 AXI */
+ 0x14, /* PAXB2 AXI */
+ 0x18, /* PAXB3 AXI */
+ 0x20, /* PAXB4 AXI */
+ 0x28, /* PAXB5 AXI */
+ 0x2c, /* PAXB6 AXI */
+ 0x30, /* PAXB7 AXI */
+ 0x24, /* PAXB APB */
+};
+
+const paxb_cfg *paxb;
+
+/*
+ * Given a PIPEMUX strap and PCIe core index, this function returns 1 if a
+ * PCIe core needs to be enabled
+ */
+int pcie_core_needs_enable(unsigned int core_idx)
+{
+ if (paxb->core_needs_enable)
+ return paxb->core_needs_enable(core_idx);
+
+ return 0;
+}
+
+static void pcie_set_default_tx_coeff(uint32_t core_idx, uint32_t link_width)
+{
+ unsigned int lanes = 0;
+ uint32_t data, addr;
+
+ addr = CFG_RC_COEFF_ADDR;
+ for (lanes = 0; lanes < link_width; lanes = lanes + 2) {
+ data = paxb_rc_cfg_read(core_idx, addr);
+ data &= 0xf0f0f0f0;
+ data |= (7 & 0xf);
+ data |= (7 & 0xf) << 8;
+ data |= (7 & 0xf) << 16;
+ data |= (7 & 0xf) << 24;
+
+ paxb_rc_cfg_write(core_idx, addr, data);
+ addr += 4;
+ }
+}
+
+static int paxb_rc_link_init(void)
+{
+ uint32_t val, link_speed;
+ unsigned int link_width;
+ uint32_t core_idx;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ link_width = paxb->get_link_width(core_idx);
+ if (!link_width) {
+ ERROR("Unsupported PIPEMUX\n");
+ return -EOPNOTSUPP;
+ }
+
+ link_speed = paxb->get_link_speed();
+ /* program RC's link cap reg to advertise proper link width */
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
+ val &= ~CFG_RC_LINK_CAP_WIDTH_MASK;
+ val |= (link_width << CFG_RC_LINK_CAP_WIDTH_SHIFT);
+ paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
+
+ /* program RC's link cap reg to advertise proper link speed */
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
+ val &= ~CFG_RC_LINK_CAP_SPEED_MASK;
+ val |= link_speed << CFG_RC_LINK_CAP_SPEED_SHIFT;
+ paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
+
+ /* also need to program RC's link status control register */
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_STATUS_CTRL_2);
+ val &= ~(CFG_RC_LINK_SPEED_MASK);
+ val |= link_speed << CFG_RC_LINK_SPEED_SHIFT;
+ paxb_rc_cfg_write(core_idx, CFG_RC_LINK_STATUS_CTRL_2, val);
+
+#ifdef WAR_PLX_PRESET_PARITY_FAIL
+ /* WAR to avoid crash with PLX switch in GEN3*/
+ /* While PRESET, PLX switch is not fixing parity so disabled */
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_REG_PHY_CTL_10);
+ val &= ~(PHY_CTL_10_GEN3_MATCH_PARITY);
+ paxb_rc_cfg_write(core_idx, CFG_RC_REG_PHY_CTL_10, val);
+#endif
+ pcie_set_default_tx_coeff(core_idx, link_width);
+ }
+ return 0;
+}
+
+#ifdef PAXB_LINKUP
+static void paxb_perst_ctrl(unsigned int core_idx, bool assert)
+{
+ uint32_t clk_ctrl = PAXB_OFFSET(core_idx) + PAXB_CLK_CTRL_OFFSET;
+
+ if (assert) {
+ mmio_clrbits_32(clk_ctrl, PAXB_EP_PERST_SRC_SEL_MASK |
+ PAXB_EP_MODE_PERST_MASK |
+ PAXB_RC_PCIE_RST_OUT_MASK);
+ udelay(250);
+ } else {
+ mmio_setbits_32(clk_ctrl, PAXB_RC_PCIE_RST_OUT_MASK);
+ mdelay(100);
+ }
+}
+
+static void paxb_start_link_up(void)
+{
+ unsigned int core_idx;
+ uint32_t val, timeout;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ /* toggle PERST */
+ paxb_perst_ctrl(core_idx, true);
+ paxb_perst_ctrl(core_idx, false);
+
+ timeout = DL_LINK_UP_TIMEOUT_MS;
+ /* wait for Link up */
+ do {
+ val = mmio_read_32(PAXB_OFFSET(core_idx) +
+ PAXB_CFG_LINK_STATUS_OFFSET);
+ if (val & PAXB_CFG_DL_ACTIVE_MASK)
+ break;
+
+ mdelay(1);
+ } while (--timeout);
+
+ if (!timeout)
+ ERROR("PAXB core %u link is down\n", core_idx);
+ }
+}
+#endif
+
+static void pcie_core_soft_reset(unsigned int core_idx)
+{
+ uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
+ uintptr_t ctrl = (uintptr_t)(PCIE_CORE_SOFT_RST_CFG_BASE + offset);
+
+ /* Put PCIe core in soft reset */
+ mmio_clrbits_32(ctrl, PCIE_CORE_SOFT_RST);
+
+ /* Wait for 1 us before pulling PCIe core out of soft reset */
+ udelay(PCIE_CORE_SOFT_RST_DELAY_US);
+
+ mmio_setbits_32(ctrl, PCIE_CORE_SOFT_RST);
+}
+
+static int pcie_core_pwron_switch(uintptr_t ctrl, uintptr_t status,
+ uint32_t mask)
+{
+ uint32_t val;
+ unsigned int timeout = PCIE_CORE_PWR_TIMEOUT_MS;
+
+ /* enable switch */
+ mmio_setbits_32(ctrl, mask);
+
+ /* now wait for it to stabilize */
+ do {
+ val = mmio_read_32(status);
+ if ((val & mask) == mask)
+ return 0;
+ mdelay(1);
+ } while (--timeout);
+
+ return -EIO;
+}
+
+static int pcie_core_pwr_seq(uintptr_t ctrl, uintptr_t status)
+{
+ int ret;
+
+ /*
+ * Enable the switch with the following sequence:
+ * 1. Array weak switch output switch
+ * 2. Array strong switch
+ * 3. Weak switch output acknowledge
+ * 4. Strong switch output acknowledge
+ */
+ ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWERON);
+ if (ret)
+ return ret;
+
+ ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWEROK);
+ if (ret)
+ return ret;
+
+ ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWERON);
+ if (ret)
+ return ret;
+
+ ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWEROK);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * This function enables PCIe core and PAXB memory buffer power, and then
+ * remove the PCIe core from isolation
+ */
+static int pcie_core_pwr_init(unsigned int core_idx)
+{
+ int ret;
+ uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
+ uintptr_t ctrl, status;
+
+ /* enable mem power to PCIe core */
+ ctrl = (uintptr_t)(PCIE_CORE_MEM_PWR_BASE + offset);
+ status = (uintptr_t)(PCIE_CORE_MEM_PWR_STATUS_BASE + offset);
+ ret = pcie_core_pwr_seq(ctrl, status);
+ if (ret) {
+ ERROR("PCIe core mem power failed\n");
+ return ret;
+ }
+
+ /* now enable mem power to PAXB wrapper */
+ ctrl = (uintptr_t)(PCIE_PAXB_MEM_PWR_BASE + offset);
+ status = (uintptr_t)(PCIE_PAXB_MEM_PWR_STATUS_BASE + offset);
+ ret = pcie_core_pwr_seq(ctrl, status);
+ if (ret) {
+ ERROR("PAXB mem power failed\n");
+ return ret;
+ }
+
+ /* now remove power isolation */
+ ctrl = (uintptr_t)(PCIE_CORE_ISO_CFG_BASE + offset);
+ mmio_clrbits_32(ctrl, PCIE_CORE_ISO | PCIE_CORE_MEM_ISO);
+
+ return 0;
+}
+
+static void pcie_ss_reset(void)
+{
+ mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
+ 1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R);
+}
+
+/*
+ * This function reads the PIPEMUX strap, figures out all the PCIe cores that
+ * need to be enabled and enable the mem power for those cores
+ */
+static int pcie_cores_init(void)
+{
+ int ret = 0;
+ uint32_t core_idx;
+
+ if (paxb->pipemux_init) {
+ ret = paxb->pipemux_init();
+ if (ret)
+ return ret;
+ }
+
+ /* bring PCIe subsystem out of reset */
+ pcie_ss_reset();
+
+ /* power up all PCIe cores that will be used as RC */
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ ret = pcie_core_pwr_init(core_idx);
+ if (ret) {
+ ERROR("PCIe core %u power up failed\n", core_idx);
+ return ret;
+ }
+
+ pcie_core_soft_reset(core_idx);
+
+ VERBOSE("PCIe core %u is powered up\n", core_idx);
+ }
+
+ return ret;
+}
+
+void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
+ uint32_t val)
+{
+ mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
+ (where & PAXB_CFG_IND_ADDR_MASK) |
+ PAXB_CFG_CFG_TYPE_MASK);
+ mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET, val);
+}
+
+unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where)
+{
+ unsigned int val;
+
+ mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
+ (where & PAXB_CFG_IND_ADDR_MASK) |
+ PAXB_CFG_CFG_TYPE_MASK);
+ val = mmio_read_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET);
+
+ return val;
+}
+
+static void paxb_cfg_mps(void)
+{
+ uint32_t val, core_idx, mps;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_DEVICE_CAP);
+ val &= ~CFG_RC_DEVICE_CAP_MPS_MASK;
+ mps = CFG_RC_DEVICE_CAP_MPS_256B;
+ if (core_idx == 0 || core_idx == 1 ||
+ core_idx == 6 || core_idx == 7) {
+ mps = CFG_RC_DEVICE_CAP_MPS_512B;
+ }
+ val |= mps;
+ paxb_rc_cfg_write(core_idx, CFG_RC_DEVICE_CAP, val);
+ }
+}
+
+static void paxb_cfg_dev_id(void)
+{
+ uint32_t val, core_idx;
+ uint32_t device_id;
+
+ device_id = paxb->device_id;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ /* Set Core in RC mode */
+ mmio_setbits_32(PCIE_CORE_USER_CFG +
+ (core_idx * PCIE_CORE_PWR_OFFSET), 1);
+
+ /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
+ val = paxb_rc_cfg_read(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET);
+ val &= ~PCI_CLASS_BRIDGE_MASK;
+ val |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
+ paxb_rc_cfg_write(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET, val);
+
+ val = (VENDOR_ID << 16) | device_id;
+ paxb_rc_cfg_write(core_idx, CFG_RC_DEV_ID, val);
+
+ val = (device_id << 16) | VENDOR_ID;
+ paxb_rc_cfg_write(core_idx, CFG_RC_DEV_SUBID, val);
+ }
+}
+
+static void paxb_cfg_tgt_trn(void)
+{
+ uint32_t val, core_idx;
+
+ /*
+ * Disable all mem Rd/Wr size check so it allows target read/write
+ * transactions to be more than stipulated DW. As a result, PAXB root
+ * complex will not abort these read/write transcations beyond
+ * stipulated limit
+ */
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_TL_CTRL_0);
+ val &= ~(RC_MEM_DW_CHK_MASK);
+ paxb_rc_cfg_write(core_idx, CFG_RC_TL_CTRL_0, val);
+ }
+}
+
+static void paxb_cfg_pdl_ctrl(void)
+{
+ uint32_t val, core_idx;
+ uint32_t nph, ph, pd;
+
+ /* increase the credit counter to 4 for non-posted header */
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ nph = NPH_FC_INIT;
+ ph = PH_INIT;
+ pd = PD_FC_INIT;
+
+ if (core_idx == 0 || core_idx == 1 ||
+ core_idx == 6 || core_idx == 7) {
+ nph = SRP_NPH_FC_INIT;
+ ph = SRP_PH_INIT;
+ pd = SRP_PD_FC_INIT;
+ }
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_4);
+ val &= ~NPH_FC_INIT_MASK;
+ val &= ~PD_FC_INIT_MASK;
+ val = val | (nph << NPH_FC_INIT_SHIFT);
+ val = val | (pd << PD_FC_INIT_SHIFT);
+ paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_4, val);
+
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_5);
+ val &= ~PH_INIT_MASK;
+ val = val | (ph << PH_INIT_SHIFT);
+ paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_5, val);
+
+ /*
+ * ASIC to give more optmized value after further investigation.
+ * till then this is important to have to get similar
+ * performance on all the slots.
+ */
+ paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_NP_LIMIT,
+ CFG_RC_TL_FCIMM_NP_VAL);
+
+ paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_P_LIMIT,
+ CFG_RC_TL_FCIMM_P_VAL);
+ }
+}
+
+static void paxb_cfg_clkreq(void)
+{
+ uint32_t val, core_idx;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ val = paxb_rc_cfg_read(core_idx, CFG_RC_CLKREQ_ENABLED);
+ val &= ~CFG_RC_CLKREQ_ENABLED_MASK;
+ paxb_rc_cfg_write(core_idx, CFG_RC_CLKREQ_ENABLED, val);
+ }
+}
+
+static void paxb_cfg_dl_active(bool enable)
+{
+ uint32_t val, core_idx;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ val = paxb_rc_cfg_read(core_idx, CFG_LINK_CAP_RC);
+ if (enable)
+ val |= CFG_RC_DL_ACTIVE_MASK;
+ else
+ val &= ~CFG_RC_DL_ACTIVE_MASK;
+ paxb_rc_cfg_write(core_idx, CFG_LINK_CAP_RC, val);
+ }
+}
+
+static void paxb_cfg_LTR(int enable)
+{
+ uint32_t val, core_idx;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ val = paxb_rc_cfg_read(core_idx, CFG_ROOT_CAP_RC);
+ if (enable)
+ val |= CFG_ROOT_CAP_LTR_MASK;
+ else
+ val &= ~CFG_ROOT_CAP_LTR_MASK;
+ paxb_rc_cfg_write(core_idx, CFG_ROOT_CAP_RC, val);
+ }
+}
+
+static void paxb_ib_regs_bypass(void)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < paxb->num_cores; i++) {
+ if (!pcie_core_needs_enable(i))
+ continue;
+
+ /* Configure Default IMAP window */
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP,
+ DEFAULT_ADDR_INVALID);
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXUSER,
+ IMAP_AXUSER);
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXCACHE,
+ IMAP_AXCACHE);
+
+ /* Configure MSI IMAP window */
+ mmio_setbits_32(PAXB_OFFSET(i) +
+ PAXB_IMAP0_REGS_TYPE_OFFSET,
+ 0x1);
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IARR0_BASE_OFFSET,
+ GITS_TRANSLATER | OARR_VALID);
+ for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
+ (GITS_TRANSLATER +
+ (j * PAXB_IMAP0_WINDOW_SIZE)) |
+ IMAP_VALID);
+ }
+ }
+}
+
+static void paxb_ib_regs_init(void)
+{
+ unsigned int core_idx;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ /* initialize IARR2 to zero */
+ mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_IARR2_LOWER_OFFSET,
+ 0x0);
+ mmio_setbits_32(PAXB_OFFSET(core_idx) +
+ PAXB_IMAP0_REGS_TYPE_OFFSET,
+ 0x1);
+ }
+}
+
+static void paxb_cfg_apb_timeout(void)
+{
+ unsigned int core_idx;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ /* allow unlimited timeout */
+ mmio_write_32(PAXB_OFFSET(core_idx) +
+ PAXB_APB_TIMEOUT_COUNT_OFFSET,
+ 0xFFFFFFFF);
+ }
+}
+
+static void paxb_smmu_cfg(void)
+{
+ unsigned int core_idx;
+ uint32_t offset;
+ uint32_t val;
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+
+ offset = core_idx * PCIE_CORE_PWR_OFFSET;
+ val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
+ val &= ~(0xFFF00);
+ val |= (PAXB_SMMU_SID_CFG_FUN_WIDTH |
+ PAXB_SMMU_SID_CFG_DEV_WIDTH |
+ PAXB_SMMU_SID_CFG_BUS_WIDTH);
+ mmio_write_32(PCIE_PAXB_SMMU_SID_CFG + offset, val);
+ val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
+ VERBOSE("smmu cfg reg 0x%x\n", val);
+ }
+}
+
+static void paxb_cfg_coherency(void)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < paxb->num_cores; i++) {
+ if (!pcie_core_needs_enable(i))
+ continue;
+
+#ifdef USE_DDR
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_OFFSET,
+ IMAP_ARCACHE | IMAP_AWCACHE);
+#endif
+
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_0_AXUSER_OFFSET,
+ IMAP_AXUSER);
+
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_AXUSER_OFFSET,
+ IMAP_AXUSER);
+
+ for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
+#ifdef USE_DDR
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP3_OFFSET(j),
+ IMAP_ARCACHE | IMAP_AWCACHE);
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP4_OFFSET(j),
+ IMAP_ARCACHE | IMAP_AWCACHE);
+#endif
+ /* zero out IMAP0 mapping windows for MSI/MSI-X */
+ mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
+ 0x0);
+
+ mmio_write_32(PAXB_OFFSET(i) +
+ PAXB_IMAP3_0_AXUSER_OFFSET(j),
+ IMAP_AXUSER);
+ mmio_write_32(PAXB_OFFSET(i) +
+ PAXB_IMAP4_0_AXUSER_OFFSET(j),
+ IMAP_AXUSER);
+ }
+ }
+}
+
+/*
+ * This function configures all PAXB related blocks to allow non-secure access
+ */
+void paxb_ns_init(enum paxb_type type)
+{
+ unsigned int reg;
+
+ switch (type) {
+ case PAXB_SR:
+ for (reg = 0; reg < ARRAY_SIZE(paxb_sec_reg_offset); reg++) {
+
+ mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE +
+ paxb_sec_reg_offset[reg], 0x1);
+ }
+ /* Enabled all PAXB's relevant IDM blocks access in non-secure mode */
+ mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE + PAXB_SECURITY_IDM_OFFSET,
+ 0xffff);
+ break;
+ case PAXB_NS3Z:
+ mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+ paxb_sec_reg_offset[0], 0x1);
+ mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+ PAXB_SECURITY_IDM_OFFSET, 0xffff);
+ mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+ PAXB_SECURITY_APB_OFFSET, 0x7);
+ mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
+ PAXB_SECURITY_ECAM_OFFSET, 0x1);
+ break;
+ }
+}
+
+static int paxb_set_config(void)
+{
+ paxb = paxb_get_config(sr);
+ if (paxb)
+ return 0;
+
+ return -ENODEV;
+}
+
+void paxb_init(void)
+{
+ int ret;
+
+ ret = paxb_set_config();
+ if (ret)
+ return;
+
+ paxb_ns_init(paxb->type);
+
+ ret = pcie_cores_init();
+ if (ret)
+ return;
+
+ if (paxb->phy_init) {
+ ret = paxb->phy_init();
+ if (ret)
+ return;
+ }
+
+ paxb_cfg_dev_id();
+ paxb_cfg_tgt_trn();
+ paxb_cfg_pdl_ctrl();
+ if (paxb->type == PAXB_SR) {
+ paxb_ib_regs_init();
+ paxb_cfg_coherency();
+ } else
+ paxb_ib_regs_bypass();
+
+ paxb_cfg_apb_timeout();
+ paxb_smmu_cfg();
+ paxb_cfg_clkreq();
+ paxb_rc_link_init();
+
+ /* Stingray Doesn't support LTR */
+ paxb_cfg_LTR(false);
+ paxb_cfg_dl_active(true);
+
+ paxb_cfg_mps();
+
+#ifdef PAXB_LINKUP
+ paxb_start_link_up();
+#endif
+ INFO("PAXB init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/paxc.c b/plat/brcm/board/stingray/src/paxc.c
new file mode 100644
index 0000000..44af4b0
--- /dev/null
+++ b/plat/brcm/board/stingray/src/paxc.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <iommu.h>
+#include <platform_def.h>
+#include <sr_utils.h>
+
+#define PAXC_BASE 0x60400000
+#define PAXC_AXI_CFG_PF 0x10
+#define PAXC_AXI_CFG_PF_OFFSET(pf) (PAXC_AXI_CFG_PF + (pf) * 4)
+#define PAXC_ARPROT_PF_CFG 0x40
+#define PAXC_AWPROT_PF_CFG 0x44
+
+#define PAXC_ARQOS_PF_CFG 0x48
+#define PAXC_ARQOS_VAL 0xaaaaaaaa
+
+#define PAXC_AWQOS_PF_CFG 0x4c
+#define PAXC_AWQOS_VAL 0xeeeeeeee
+
+#define PAXC_CFG_IND_ADDR_OFFSET 0x1f0
+#define PAXC_CFG_IND_ADDR_MASK 0xffc
+#define PAXC_CFG_IND_DATA_OFFSET 0x1f4
+
+/* offsets for PAXC root complex configuration space registers */
+
+#define PAXC_CFG_ID_OFFSET 0x434
+#define PAXC_RC_VENDOR_ID 0x14e4
+#define PAXC_RC_VENDOR_ID_SHIFT 16
+
+#define PAXC_RC_DEVICE_ID 0xd750
+
+#define PAXC_CFG_LINK_CAP_OFFSET 0x4dc
+#define PAXC_RC_LINK_CAP_SPD_SHIFT 0
+#define PAXC_RC_LINK_CAP_SPD_MASK (0xf << PAXC_RC_LINK_CAP_SPD_SHIFT)
+#define PAXC_RC_LINK_CAP_SPD 3
+#define PAXC_RC_LINK_CAP_WIDTH_SHIFT 4
+#define PAXC_RC_LINK_CAP_WIDTH_MASK (0x1f << PAXC_RC_LINK_CAP_WIDTH_SHIFT)
+#define PAXC_RC_LINK_CAP_WIDTH 16
+
+/* offsets for MHB registers */
+
+#define MHB_BASE 0x60401000
+#define MHB_MEM_PWR_STATUS_PAXC (MHB_BASE + 0x1c0)
+#define MHB_PWR_ARR_POWERON 0x8
+#define MHB_PWR_ARR_POWEROK 0x4
+#define MHB_PWR_POWERON 0x2
+#define MHB_PWR_POWEROK 0x1
+#define MHB_PWR_STATUS_MASK (MHB_PWR_ARR_POWERON | \
+ MHB_PWR_ARR_POWEROK | \
+ MHB_PWR_POWERON | \
+ MHB_PWR_POWEROK)
+
+/* max number of PFs from Nitro that PAXC sees */
+#define MAX_NR_NITRO_PF 8
+
+#ifdef EMULATION_SETUP
+static void paxc_reg_dump(void)
+{
+}
+#else
+/* total number of PAXC registers */
+#define NR_PAXC_REGS 53
+static void paxc_reg_dump(void)
+{
+ uint32_t idx, offset = 0;
+
+ VERBOSE("PAXC register dump start\n");
+ for (idx = 0; idx < NR_PAXC_REGS; idx++, offset += 4)
+ VERBOSE("offset: 0x%x val: 0x%x\n", offset,
+ mmio_read_32(PAXC_BASE + offset));
+ VERBOSE("PAXC register dump end\n");
+}
+#endif /* EMULATION_SETUP */
+
+#ifdef EMULATION_SETUP
+static void mhb_reg_dump(void)
+{
+}
+#else
+#define NR_MHB_REGS 227
+static void mhb_reg_dump(void)
+{
+ uint32_t idx, offset = 0;
+
+ VERBOSE("MHB register dump start\n");
+ for (idx = 0; idx < NR_MHB_REGS; idx++, offset += 4)
+ VERBOSE("offset: 0x%x val: 0x%x\n", offset,
+ mmio_read_32(MHB_BASE + offset));
+ VERBOSE("MHB register dump end\n");
+}
+#endif /* EMULATION_SETUP */
+
+static void paxc_rc_cfg_write(uint32_t where, uint32_t val)
+{
+ mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
+ where & PAXC_CFG_IND_ADDR_MASK);
+ mmio_write_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET, val);
+}
+
+static uint32_t paxc_rc_cfg_read(uint32_t where)
+{
+ mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
+ where & PAXC_CFG_IND_ADDR_MASK);
+ return mmio_read_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET);
+}
+
+/*
+ * Function to program PAXC root complex link capability register
+ */
+static void paxc_cfg_link_cap(void)
+{
+ uint32_t val;
+
+ val = paxc_rc_cfg_read(PAXC_CFG_LINK_CAP_OFFSET);
+ val &= ~(PAXC_RC_LINK_CAP_SPD_MASK | PAXC_RC_LINK_CAP_WIDTH_MASK);
+ val |= (PAXC_RC_LINK_CAP_SPD << PAXC_RC_LINK_CAP_SPD_SHIFT) |
+ (PAXC_RC_LINK_CAP_WIDTH << PAXC_RC_LINK_CAP_WIDTH_SHIFT);
+ paxc_rc_cfg_write(PAXC_CFG_LINK_CAP_OFFSET, val);
+}
+
+/*
+ * Function to program PAXC root complex vendor ID and device ID
+ */
+static void paxc_cfg_id(void)
+{
+ uint32_t val;
+
+ val = (PAXC_RC_VENDOR_ID << PAXC_RC_VENDOR_ID_SHIFT) |
+ PAXC_RC_DEVICE_ID;
+ paxc_rc_cfg_write(PAXC_CFG_ID_OFFSET, val);
+}
+
+void paxc_init(void)
+{
+ unsigned int pf_index;
+ unsigned int val;
+
+ val = mmio_read_32(MHB_MEM_PWR_STATUS_PAXC);
+ if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) {
+ INFO("PAXC not powered\n");
+ return;
+ }
+
+ paxc_cfg_id();
+ paxc_cfg_link_cap();
+
+ paxc_reg_dump();
+ mhb_reg_dump();
+
+#ifdef USE_DDR
+ /*
+ * Set AWCACHE and ARCACHE to 0xff (Cacheable write-back,
+ * allocate on both reads and writes) per
+ * recommendation from the ASIC team
+ */
+ val = 0xff;
+#else
+ /* disable IO cache if non-DDR memory is used, e.g., external SRAM */
+ val = 0x0;
+#endif
+ for (pf_index = 0; pf_index < MAX_NR_NITRO_PF; pf_index++)
+ mmio_write_32(PAXC_BASE + PAXC_AXI_CFG_PF_OFFSET(pf_index),
+ val);
+
+ /*
+ * Set ARPROT and AWPROT to enable non-secure access from
+ * PAXC to all PFs, PF0 to PF7
+ */
+ mmio_write_32(PAXC_BASE + PAXC_ARPROT_PF_CFG, 0x22222222);
+ mmio_write_32(PAXC_BASE + PAXC_AWPROT_PF_CFG, 0x22222222);
+
+ mmio_write_32(PAXC_BASE + PAXC_ARQOS_PF_CFG, PAXC_ARQOS_VAL);
+ mmio_write_32(PAXC_BASE + PAXC_AWQOS_PF_CFG, PAXC_AWQOS_VAL);
+
+ INFO("PAXC init done\n");
+}
+
+/*
+ * These defines do not match the regfile but they are renamed in a way such
+ * that they are much more readible
+ */
+
+#define MHB_NIC_SECURITY_BASE 0x60500000
+#define MHB_NIC_PAXC_AXI_NS 0x0008
+#define MHB_NIC_IDM_NS 0x000c
+#define MHB_NIC_MHB_APB_NS 0x0010
+#define MHB_NIC_NITRO_AXI_NS 0x0014
+#define MHB_NIC_PCIE_AXI_NS 0x0018
+#define MHB_NIC_PAXC_APB_NS 0x001c
+#define MHB_NIC_EP_APB_NS 0x0020
+
+#define MHB_NIC_PAXC_APB_S_IDM_SHIFT 5
+#define MHB_NIC_EP_APB_S_IDM_SHIFT 4
+#define MHB_NIC_MHB_APB_S_IDM_SHIFT 3
+#define MHB_NIC_PAXC_AXI_S_IDM_SHIFT 2
+#define MHB_NIC_PCIE_AXI_S_IDM_SHIFT 1
+#define MHB_NIC_NITRO_AXI_S_IDM_SHIFT 0
+
+#define NIC400_NITRO_TOP_NIC_SECURITY_BASE 0x60d00000
+
+#define NITRO_NIC_SECURITY_3_SHIFT 0x14
+#define NITRO_NIC_SECURITY_4_SHIFT 0x18
+#define NITRO_NIC_SECURITY_5_SHIFT 0x1c
+#define NITRO_NIC_SECURITY_6_SHIFT 0x20
+
+void paxc_mhb_ns_init(void)
+{
+ unsigned int val;
+ uintptr_t mhb_nic_gpv = MHB_NIC_SECURITY_BASE;
+#ifndef NITRO_SECURE_ACCESS
+ uintptr_t nic400_nitro_gpv = NIC400_NITRO_TOP_NIC_SECURITY_BASE;
+#endif /* NITRO_SECURE_ACCESS */
+
+ /* set PAXC AXI to allow non-secure access */
+ val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS);
+ val |= 0x1;
+ mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS, val);
+
+ /* set various MHB IDM interfaces to allow non-secure access */
+ val = mmio_read_32(mhb_nic_gpv + MHB_NIC_IDM_NS);
+ val |= (0x1 << MHB_NIC_PAXC_APB_S_IDM_SHIFT);
+ val |= (0x1 << MHB_NIC_EP_APB_S_IDM_SHIFT);
+ val |= (0x1 << MHB_NIC_MHB_APB_S_IDM_SHIFT);
+ val |= (0x1 << MHB_NIC_PAXC_AXI_S_IDM_SHIFT);
+ val |= (0x1 << MHB_NIC_PCIE_AXI_S_IDM_SHIFT);
+ val |= (0x1 << MHB_NIC_NITRO_AXI_S_IDM_SHIFT);
+ mmio_write_32(mhb_nic_gpv + MHB_NIC_IDM_NS, val);
+
+ /* set MHB APB to allow non-secure access */
+ val = mmio_read_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS);
+ val |= 0x1;
+ mmio_write_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS, val);
+
+ /* set Nitro AXI to allow non-secure access */
+ val = mmio_read_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS);
+ val |= 0x1;
+ mmio_write_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS, val);
+
+ /* set PCIe AXI to allow non-secure access */
+ val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS);
+ val |= 0x1;
+ mmio_write_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS, val);
+
+ /* set PAXC APB to allow non-secure access */
+ val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS);
+ val |= 0x1;
+ mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS, val);
+
+ /* set EP APB to allow non-secure access */
+ val = mmio_read_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS);
+ val |= 0x1;
+ mmio_write_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS, val);
+
+#ifndef NITRO_SECURE_ACCESS
+ /* Set NIC400 to allow non-secure access */
+ mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_3_SHIFT, 0x1);
+ mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_4_SHIFT, 0x1);
+ mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_5_SHIFT, 0x1);
+ mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_6_SHIFT, 0x1);
+#endif /* NITRO_SECURE_ACCESS */
+}
diff --git a/plat/brcm/board/stingray/src/pm.c b/plat/brcm/board/stingray/src/pm.c
new file mode 100644
index 0000000..a5ac2e7
--- /dev/null
+++ b/plat/brcm/board/stingray/src/pm.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/ccn.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+
+#ifdef USE_PAXC
+#include <chimp.h>
+#endif
+#include <cmn_plat_util.h>
+#include <ihost_pm.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+static uint64_t plat_sec_entrypoint;
+
+/*******************************************************************************
+ * SR handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int brcm_pwr_domain_on(u_register_t mpidr)
+{
+ int cpuid;
+
+ cpuid = plat_brcm_calc_core_pos(mpidr);
+ INFO("mpidr :%lu, cpuid:%d\n", mpidr, cpuid);
+
+#ifdef USE_SINGLE_CLUSTER
+ if (cpuid > 1)
+ return PSCI_E_INTERN_FAIL;
+#endif
+
+ ihost_power_on_cluster(mpidr);
+
+ ihost_power_on_secondary_core(mpidr, plat_sec_entrypoint);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * SR handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
+
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
+ PLAT_LOCAL_STATE_OFF) {
+ INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id);
+ ccn_enter_snoop_dvm_domain(1 << cluster_id);
+ }
+
+ /* Enable the gic cpu interface */
+ plat_brcm_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_brcm_gic_cpuif_enable();
+
+ INFO("Gic Initialization done for this affinity instance\n");
+}
+
+static void __dead2 brcm_system_reset(void)
+{
+ uint32_t reset_type = SOFT_SYS_RESET_L1;
+
+#ifdef USE_PAXC
+ if (bcm_chimp_is_nic_mode())
+ reset_type = SOFT_RESET_L3;
+#endif
+ INFO("System rebooting - L%d...\n", reset_type);
+
+ plat_soft_reset(reset_type);
+
+ /* Prevent the function to return due to the attribute */
+ while (1)
+ ;
+}
+
+static int brcm_system_reset2(int is_vendor, int reset_type,
+ u_register_t cookie)
+{
+ INFO("System rebooting - L%d...\n", reset_type);
+
+ plat_soft_reset(reset_type);
+
+ /*
+ * plat_soft_reset cannot return (it is a __dead function),
+ * but brcm_system_reset2 has to return some value, even in
+ * this case.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard
+ * platform will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+const plat_psci_ops_t plat_brcm_psci_pm_ops = {
+ .pwr_domain_on = brcm_pwr_domain_on,
+ .pwr_domain_on_finish = brcm_pwr_domain_on_finish,
+ .system_reset = brcm_system_reset,
+ .system_reset2 = brcm_system_reset2
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_brcm_psci_pm_ops;
+ plat_sec_entrypoint = sec_entrypoint;
+
+ return 0;
+}
diff --git a/plat/brcm/board/stingray/src/scp_cmd.c b/plat/brcm/board/stingray/src/scp_cmd.c
new file mode 100644
index 0000000..2aa9519
--- /dev/null
+++ b/plat/brcm/board/stingray/src/scp_cmd.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <drivers/delay_timer.h>
+
+#include <platform_def.h>
+#include <scp.h>
+#include <scp_cmd.h>
+
+#include "m0_ipc.h"
+
+/*
+ * Reads a response from CRMU MAILBOX
+ * Assumes that access has been granted and locked.
+ * Note that this is just a temporary implementation until
+ * channels are introduced
+ */
+static void scp_read_response(crmu_response_t *resp)
+{
+ uint32_t code;
+
+ code = mmio_read_32(CRMU_MAIL_BOX0);
+ resp->completed = code & MCU_IPC_CMD_DONE_MASK;
+ resp->cmd = code & SCP_CMD_MASK;
+ resp->ret = (code & MCU_IPC_CMD_REPLY_MASK) >> MCU_IPC_CMD_REPLY_SHIFT;
+}
+
+/*
+ * Send a command to SCP and wait for timeout us.
+ * Return: 0 on success
+ * -1 if there was no proper reply from SCP
+ * >0 if there was a response from MCU, but
+ * command completed with an error.
+ */
+int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout)
+{
+ int ret = -1;
+
+ mmio_write_32(CRMU_MAIL_BOX0, cmd);
+ mmio_write_32(CRMU_MAIL_BOX1, param);
+ do {
+ crmu_response_t scp_resp;
+
+ udelay(1);
+ scp_read_response(&scp_resp);
+ if (scp_resp.completed &&
+ (scp_resp.cmd == cmd)) {
+ /* This command has completed */
+ ret = scp_resp.ret;
+ break;
+ }
+ } while (--timeout);
+
+ return ret;
+}
diff --git a/plat/brcm/board/stingray/src/scp_utils.c b/plat/brcm/board/stingray/src/scp_utils.c
new file mode 100644
index 0000000..1d82cef
--- /dev/null
+++ b/plat/brcm/board/stingray/src/scp_utils.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2017-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <bcm_elog_ddr.h>
+#include <brcm_mhu.h>
+#include <brcm_scpi.h>
+#include <chimp.h>
+#include <cmn_plat_util.h>
+#include <ddr_init.h>
+#include <scp.h>
+#include <scp_cmd.h>
+#include <scp_utils.h>
+
+#include "m0_cfg.h"
+#include "m0_ipc.h"
+
+#ifdef BCM_ELOG
+static void prepare_elog(void)
+{
+#if (CLEAN_DDR && !defined(MMU_DISABLED))
+ /*
+ * Now DDR has been initialized. We want to copy all the logs in SRAM
+ * into DDR so we will have much more space to store the logs in the
+ * next boot stage
+ */
+ bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE,
+ MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE)
+ );
+
+ /*
+ * We are almost at the end of BL2, and we can stop log here so we do
+ * not need to add 'bcm_elog_exit' to the standard BL2 code. The
+ * benefit of capturing BL2 logs after this is very minimal in a
+ * production system.
+ */
+ bcm_elog_exit();
+#endif
+
+ /*
+ * Notify CRMU that now it should pull logs from DDR instead of from
+ * FS4 SRAM.
+ */
+ SCP_WRITE_CFG(flash_log.can_use_ddr, 1);
+}
+#endif
+
+bool is_crmu_alive(void)
+{
+ return (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, SCP_CMD_DEFAULT_TIMEOUT_US)
+ == 0);
+}
+
+bool bcm_scp_issue_sys_reset(void)
+{
+ return (scp_send_cmd(MCU_IPC_MCU_CMD_L1_RESET, 0,
+ SCP_CMD_DEFAULT_TIMEOUT_US));
+}
+
+/*
+ * Note that this is just a temporary implementation until
+ * channels are introduced
+ */
+
+int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ int scp_patch_activated, scp_patch_version;
+#ifndef EMULATION_SETUP
+ uint8_t active_ch_bitmap, i;
+#endif
+ uint32_t reset_state = 0;
+ uint32_t mcu_ap_init_param = 0;
+
+ /*
+ * First check if SCP patch has already been loaded
+ * Send NOP command and see if there is a valid response
+ */
+ scp_patch_activated =
+ (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0,
+ SCP_CMD_DEFAULT_TIMEOUT_US) == 0);
+ if (scp_patch_activated) {
+ INFO("SCP Patch is already active.\n");
+
+ reset_state = SCP_READ_CFG(board_cfg.reset_state);
+ mcu_ap_init_param = SCP_READ_CFG(board_cfg.mcu_init_param);
+
+ /* Clear reset state, it's been already read */
+ SCP_WRITE_CFG(board_cfg.reset_state, 0);
+
+ if (mcu_ap_init_param & MCU_PATCH_LOADED_BY_NITRO) {
+ /*
+ * Reset "MCU_PATCH_LOADED_BY_NITRO" flag, but
+ * Preserve any other flags we don't deal with here
+ */
+ INFO("AP booted by Nitro\n");
+ SCP_WRITE_CFG(
+ board_cfg.mcu_init_param,
+ mcu_ap_init_param &
+ ~MCU_PATCH_LOADED_BY_NITRO
+ );
+ }
+ } else {
+ /*
+ * MCU Patch not loaded, so load it.
+ * MCU patch stamps critical points in REG9 (debug test-point)
+ * Display its last content here. This helps to locate
+ * where crash occurred if a CRMU watchdog kicked in.
+ */
+ int ret;
+
+ INFO("MCU Patch Point: 0x%x\n",
+ mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9));
+
+ ret = download_scp_patch((void *)scp_bl2_image_info->image_base,
+ scp_bl2_image_info->image_size);
+ if (ret != 0)
+ return ret;
+
+ VERBOSE("SCP Patch loaded OK.\n");
+
+ ret = scp_send_cmd(MCU_IPC_MCU_CMD_INIT,
+ MCU_PATCH_LOADED_BY_AP,
+ SCP_CMD_SCP_BOOT_TIMEOUT_US);
+ if (ret) {
+ ERROR("SCP Patch could not initialize; error %d\n",
+ ret);
+ return ret;
+ }
+
+ INFO("SCP Patch successfully initialized.\n");
+ }
+
+ scp_patch_version = scp_send_cmd(MCU_IPC_MCU_CMD_GET_FW_VERSION, 0,
+ SCP_CMD_DEFAULT_TIMEOUT_US);
+ INFO("SCP Patch version :0x%x\n", scp_patch_version);
+
+ /* Next block just reports current AVS voltages (if applicable) */
+ {
+ uint16_t vcore_mv, ihost03_mv, ihost12_mv;
+
+ vcore_mv = SCP_READ_CFG16(vcore.millivolts) +
+ SCP_READ_CFG8(vcore.avs_cfg.additive_margin);
+ ihost03_mv = SCP_READ_CFG16(ihost03.millivolts) +
+ SCP_READ_CFG8(ihost03.avs_cfg.additive_margin);
+ ihost12_mv = SCP_READ_CFG16(ihost12.millivolts) +
+ SCP_READ_CFG8(ihost12.avs_cfg.additive_margin);
+
+ if (vcore_mv || ihost03_mv || ihost12_mv) {
+ INFO("AVS voltages from cfg (including margin)\n");
+ if (vcore_mv > 0)
+ INFO("%s\tVCORE: %dmv\n",
+ SCP_READ_CFG8(vcore.avs_cfg.avs_set) ?
+ "*" : "n/a", vcore_mv);
+ if (ihost03_mv > 0)
+ INFO("%s\tIHOST03: %dmv\n",
+ SCP_READ_CFG8(ihost03.avs_cfg.avs_set) ?
+ "*" : "n/a", ihost03_mv);
+ if (ihost12_mv > 0)
+ INFO("%s\tIHOST12: %dmv\n",
+ SCP_READ_CFG8(ihost12.avs_cfg.avs_set) ?
+ "*" : "n/a", ihost12_mv);
+ } else {
+ INFO("AVS settings not applicable\n");
+ }
+ }
+
+#if (CLEAN_DDR && !defined(MMU_DISABLED) && !defined(EMULATION_SETUP))
+ /* This will clean the DDR and enable ECC if set */
+ check_ddr_clean();
+#endif
+
+#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
+ elog_init_ddr_log();
+#endif
+
+#ifdef BCM_ELOG
+ /* Prepare ELOG to use DDR */
+ prepare_elog();
+#endif
+
+#ifndef EMULATION_SETUP
+ /* Ask ddr_init to save obtained DDR information into DDR */
+ ddr_info_save();
+#endif
+
+ /*
+ * Configure TMON DDR address.
+ * This cfg is common for all cases
+ */
+ SCP_WRITE_CFG(tmon_cfg.ddr_desc, TMON_SHARED_DDR_ADDRESS);
+
+ if (reset_state == SOFT_RESET_L3 && !mcu_ap_init_param) {
+ INFO("SCP configuration after L3 RESET done.\n");
+ return 0;
+ }
+
+ if (bcm_chimp_is_nic_mode())
+ /* Configure AP WDT to not reset the NIC interface */
+ SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
+
+#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
+ /* When AP WDog triggers perform L3 reset if DDR err logging enabled */
+ SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
+#endif
+
+#ifndef EMULATION_SETUP
+
+#ifdef DDR_SCRUB_ENA
+ ddr_scrub_enable();
+#endif
+ /* Fill the Active channel information */
+ active_ch_bitmap = get_active_ddr_channel();
+ for (i = 0; i < MAX_NR_DDR_CH; i++)
+ SCP_WRITE_CFG(ddr_cfg.ddr_cfg[i],
+ (active_ch_bitmap & BIT(i)) ? 1 : 0);
+#endif
+ return 0;
+}
diff --git a/plat/brcm/board/stingray/src/sdio.c b/plat/brcm/board/stingray/src/sdio.c
new file mode 100644
index 0000000..aa2b71a
--- /dev/null
+++ b/plat/brcm/board/stingray/src/sdio.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <sdio.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+const SDIO_CFG sr_sdio0_cfg = {
+ .cfg_base = SR_IPROC_SDIO0_CFG_BASE,
+ .sid_base = SR_IPROC_SDIO0_SID_BASE,
+ .io_ctrl_base = SR_IPROC_SDIO0_IOCTRL_BASE,
+ .pad_base = SR_IPROC_SDIO0_PAD_BASE,
+};
+const SDIO_CFG sr_sdio1_cfg = {
+ .cfg_base = SR_IPROC_SDIO1_CFG_BASE,
+ .sid_base = SR_IPROC_SDIO1_SID_BASE,
+ .io_ctrl_base = SR_IPROC_SDIO1_IOCTRL_BASE,
+ .pad_base = SR_IPROC_SDIO1_PAD_BASE,
+};
+
+void brcm_stingray_sdio_init(void)
+{
+ unsigned int val;
+ const SDIO_CFG *sdio0_cfg, *sdio1_cfg;
+
+ sdio0_cfg = &sr_sdio0_cfg;
+ sdio1_cfg = &sr_sdio1_cfg;
+
+ INFO("set sdio0 caps\n");
+ /* SDIO0 CAPS0 */
+ val = SDIO0_CAP0_CFG;
+ INFO("caps0 0x%x\n", val);
+ mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP0, val);
+
+ /* SDIO0 CAPS1 */
+ val = SDIO0_CAP1_CFG;
+ INFO("caps1 0x%x\n", val);
+ mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP1, val);
+
+ mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
+ SDIO_PRESETVAL0);
+ mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
+ SDIO_PRESETVAL1);
+ mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
+ SDIO_PRESETVAL2);
+ mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
+ SDIO_PRESETVAL3);
+ mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
+ SDIO_PRESETVAL4);
+
+ val = SR_SID_VAL(0x3, 0x0, 0x2) << SDIO_SID_SHIFT;
+ mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
+ mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
+
+ val = mmio_read_32(sdio0_cfg->io_ctrl_base);
+ val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
+ val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
+ mmio_write_32(sdio0_cfg->io_ctrl_base, val);
+
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CLK,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA0,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA1,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA2,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA3,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA4,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA5,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA6,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA7,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CMD,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+
+ INFO("set sdio1 caps\n");
+
+ /* SDIO1 CAPS0 */
+ val = SDIO1_CAP0_CFG;
+ INFO("caps0 0x%x\n", val);
+ mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP0, val);
+ /* SDIO1 CAPS1 */
+ val = SDIO1_CAP1_CFG;
+ INFO("caps1 0x%x\n", val);
+ mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP1, val);
+
+ mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
+ SDIO_PRESETVAL0);
+ mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
+ SDIO_PRESETVAL1);
+ mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
+ SDIO_PRESETVAL2);
+ mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
+ SDIO_PRESETVAL3);
+ mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
+ SDIO_PRESETVAL4);
+
+ val = SR_SID_VAL(0x3, 0x0, 0x3) << SDIO_SID_SHIFT;
+ mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
+ mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
+
+ val = mmio_read_32(sdio1_cfg->io_ctrl_base);
+ val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
+ val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
+ mmio_write_32(sdio1_cfg->io_ctrl_base, val);
+
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CLK,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA0,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA1,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA2,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA3,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA4,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA5,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA6,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA7,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+ mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CMD,
+ PAD_SDIO_MASK, PAD_SDIO_VALUE);
+
+ INFO("sdio init done\n");
+}
diff --git a/plat/brcm/board/stingray/src/sr_paxb_phy.c b/plat/brcm/board/stingray/src/sr_paxb_phy.c
new file mode 100644
index 0000000..7380e09
--- /dev/null
+++ b/plat/brcm/board/stingray/src/sr_paxb_phy.c
@@ -0,0 +1,806 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <paxb.h>
+#include <sr_def.h>
+#include <sr_utils.h>
+
+/* total number of PCIe Phys */
+#define NUM_OF_PCIE_SERDES 8
+
+#define CFG_RC_PMI_ADDR 0x1130
+#define PMI_RX_TERM_SEQ ((0x1 << 27) | (0x1ff << 16) | (0xd090))
+#define PMI_RX_TERM_VAL 0x4c00
+#define PMI_PLL_CTRL_4 0xd0b4
+#define PMI_SERDES_CLK_ENABLE (1 << 12)
+
+#define WAR_PLX_PRESET_PARITY_FAIL
+
+#define CFG_RC_REG_PHY_CTL_10 0x1838
+#define PHY_CTL_10_GEN3_MATCH_PARITY (1 << 15)
+
+#define PMI_X8_CORE0_7_PATCH_SEQ ((0x1 << 27) | (0x1ff << 16) | (0xd2a5))
+#define PMI_X8_CORE0_7_PATCH_VAL 0xd864
+
+#define PMI_ADDR_BCAST(addr) ((0x1 << 27) | (0x1ff << 16) | (addr))
+#define PMI_ADDR_LANE0(addr) ((0x1 << 27) | (addr))
+#define PMI_ADDR_LANE1(addr) ((0x1 << 27) | (0x1 << 16) | (addr))
+
+#define MERLIN16_PCIE_BLK2_PWRMGMT_7 ((0x1 << 27) | (0x1ff << 16) | 0x1208)
+#define MERLIN16_PCIE_BLK2_PWRMGMT_8 ((0x1 << 27) | (0x1ff << 16) | 0x1209)
+#define MERLIN16_AMS_TX_CTRL_5 ((0x1 << 27) | (0x1ff << 16) | 0xd0a5)
+#define MERLIN16_AMS_TX_CTRL_5_VAL \
+ ((1 << 13) | (1 << 12) | (1 << 11) | (1 << 10))
+#define MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL 0x96
+#define MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL 0x12c
+
+#define CFG_RC_PMI_WDATA 0x1134
+#define CFG_RC_WCMD_SHIFT 31
+#define CFG_RC_WCMD_MASK ((uint32_t)1U << CFG_RC_WCMD_SHIFT)
+#define CFG_RC_RCMD_SHIFT 30
+#define CFG_RC_RCMD_MASK ((uint32_t)1U << CFG_RC_RCMD_SHIFT)
+#define CFG_RC_RWCMD_MASK (CFG_RC_RCMD_MASK | CFG_RC_WCMD_MASK)
+#define CFG_RC_PMI_RDATA 0x1138
+#define CFG_RC_RACK_SHIFT 31
+#define CFG_RC_RACK_MASK ((uint32_t)1U << CFG_RC_RACK_SHIFT)
+
+/* allow up to 5 ms for PMI write to finish */
+#define PMI_TIMEOUT_MS 5
+
+/* in 2x8 RC mode, one needs to patch up Serdes 3 and 7 for link to come up */
+#define SERDES_PATCH_PIPEMUX_INDEX 0x3
+#define SERDES_PATCH_INDEX 0x8
+
+#define DSC_UC_CTRL 0xd00d
+#define DSC_UC_CTRL_RDY_CMD (1 << 7)
+#define LANE_DBG_RST_CTRL 0xd164
+#define UC_A_CLK_CTRL0 0xd200
+#define UC_A_RST_CTRL0 0xd201
+#define UC_A_AHB_CTRL0 0xd202
+#define UC_A_AHB_STAT0 0xd203
+#define UC_A_AHB_WADDR_LSW 0xd204
+#define UC_A_AHB_WADDR_MSW 0xd205
+#define UC_A_AHB_WDATA_LSW 0xd206
+#define UC_A_AHB_WDATA_MSW 0xd207
+#define UC_A_AHB_RADDR_LSW 0xd208
+#define UC_A_AHB_RADDR_MSW 0xd209
+#define UC_A_AHB_RDATA_LSW 0xd20a
+#define UC_A_AHB_RDATA_MSW 0xd20b
+#define UC_VERSION_NUM 0xd230
+#define DSC_SM_CTL22 0xd267
+#define UC_DBG1 0xd251
+
+#define LOAD_UC_CHECK 0
+#define UC_RAM_INIT_TIMEOUT 100
+#define UC_RAM_CONTROL 0xd225
+#define UC_INIT_TIMEOUT 100
+#define SIZE_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#define SZ_4 4
+#define GET_2_BYTES(p, i) ((uint16_t)p[i] | (uint16_t)p[i+1] << 8)
+
+/*
+ * List of PCIe LCPLL related registers
+ *
+ * LCPLL channel 0 provides the Serdes pad clock when running in RC mode
+ */
+#define PCIE_LCPLL_BASE 0x40000000
+
+#define PCIE_LCPLL_CTRL0_OFFSET 0x00
+#define PCIE_LCPLL_RESETB_SHIFT 31
+#define PCIE_LCPLL_RESETB_MASK BIT(PCIE_LCPLL_RESETB_SHIFT)
+#define PCIE_LCPLL_P_RESETB_SHIFT 30
+#define PCIE_LCPLL_P_RESETB_MASK BIT(PCIE_LCPLL_P_RESETB_SHIFT)
+
+#define PCIE_LCPLL_CTRL3_OFFSET 0x0c
+#define PCIE_LCPLL_EN_CTRL_SHIFT 16
+#define PCIE_LCPLL_CM_ENA 0x1a
+#define PCIE_LCPLL_CM_BUF_ENA 0x18
+#define PCIE_LCPLL_D2C2_ENA 0x2
+#define PCIE_LCPLL_REF_CLK_SHIFT 1
+#define PCIE_LCPLL_REF_CLK_MASK BIT(PCIE_LCPLL_REF_CLK_SHIFT)
+#define PCIE_LCPLL_CTRL13_OFFSET 0x34
+#define PCIE_LCPLL_D2C2_CTRL_SHIFT 16
+#define PCIE_LCPLL_D2C2_TERM_DISC 0xe0
+
+#define PCIE_LCPLL_STATUS_OFFSET 0x40
+#define PCIE_LCPLL_LOCK_SHIFT 12
+#define PCIE_LCPLL_LOCK_MASK BIT(PCIE_LCPLL_LOCK_SHIFT)
+
+#define PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG 0x114
+#define PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG 0x11c
+
+/* wait 500 microseconds for PCIe LCPLL to power up */
+#define PCIE_LCPLL_DELAY_US 500
+
+/* allow up to 5 ms for PCIe LCPLL VCO to lock */
+#define PCIE_LCPLL_TIMEOUT_MS 5
+
+#define PCIE_PIPE_MUX_CONFIGURATION_CFG 0x4000010c
+
+#define PCIE_PIPEMUX_SHIFT 19
+#define PCIE_PIPEMUX_MASK 0xf
+
+/* keep track of PIPEMUX index to use */
+static unsigned int pipemux_idx;
+
+/*
+ * PCIe PIPEMUX lookup table
+ *
+ * Each array index represents a PIPEMUX strap setting
+ * The array element represents a bitmap where a set bit means the PCIe core
+ * needs to be enabled as RC
+ */
+static uint8_t pipemux_table[] = {
+ /* PIPEMUX = 0, EP 1x16 */
+ 0x00,
+ /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+ 0x80,
+ /* PIPEMUX = 2, EP 4x4 */
+ 0x00,
+ /* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+ 0x81,
+ /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+ 0xc3,
+ /* PIPEMUX = 5, RC 8x2, all 8 cores */
+ 0xff,
+ /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+ 0xcd,
+ /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+ 0xfd,
+ /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+ 0xf0,
+ /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+ 0xc0,
+ /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+ 0x42,
+ /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+ 0x3c,
+ /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+ 0xfc,
+ /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+ 0x4c,
+};
+
+/*
+ * Return 1 if pipemux strap is supported
+ */
+static int pipemux_strap_is_valid(uint32_t pipemux)
+{
+ if (pipemux < ARRAY_SIZE(pipemux_table))
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * Read the PCIe PIPEMUX from strap
+ */
+static uint32_t pipemux_strap_read(void)
+{
+ uint32_t pipemux;
+
+ pipemux = mmio_read_32(PCIE_PIPE_MUX_CONFIGURATION_CFG);
+ pipemux &= PCIE_PIPEMUX_MASK;
+ if (pipemux == PCIE_PIPEMUX_MASK) {
+ /* read the PCIe PIPEMUX strap setting */
+ pipemux = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
+ pipemux >>= PCIE_PIPEMUX_SHIFT;
+ pipemux &= PCIE_PIPEMUX_MASK;
+ }
+
+ return pipemux;
+}
+
+/*
+ * Store the PIPEMUX index (set for each boot)
+ */
+static void pipemux_save_index(unsigned int idx)
+{
+ pipemux_idx = idx;
+}
+
+static int paxb_sr_core_needs_enable(unsigned int core_idx)
+{
+ return !!((pipemux_table[pipemux_idx] >> core_idx) & 0x1);
+}
+
+static int pipemux_sr_init(void)
+{
+ uint32_t pipemux;
+
+ /* read the PCIe PIPEMUX strap setting */
+ pipemux = pipemux_strap_read();
+ if (!pipemux_strap_is_valid(pipemux)) {
+ ERROR("Invalid PCIe PIPEMUX strap %u\n", pipemux);
+ return -EIO;
+ }
+
+ /* no PCIe RC is needed */
+ if (!pipemux_table[pipemux]) {
+ WARN("PIPEMUX indicates no PCIe RC required\n");
+ return -ENODEV;
+ }
+
+ /* save the PIPEMUX strap */
+ pipemux_save_index(pipemux);
+
+ return 0;
+}
+
+/*
+ * PCIe RC serdes link width
+ *
+ * The array is first organized in rows as indexed by the PIPEMUX setting.
+ * Within each row, eight lane width entries are specified -- one entry
+ * per PCIe core, from 0 to 7.
+ *
+ * Note: The EP lanes/cores are not mapped in this table! EP cores are
+ * controlled and thus configured by Nitro.
+ */
+static uint8_t link_width_table[][NUM_OF_SR_PCIE_CORES] = {
+ /* PIPEMUX = 0, EP 1x16 */
+ {0, 0, 0, 0, 0, 0, 0, 0},
+ /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+ {0, 0, 0, 0, 0, 0, 0, 8},
+ /* PIPEMUX = 2, EP 4x4 */
+ {0, 0, 0, 0, 0, 0, 0, 0},
+ /* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+ {8, 0, 0, 0, 0, 0, 0, 8},
+ /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+ {4, 4, 0, 0, 0, 0, 4, 4},
+ /* PIPEMUX = 5, RC 8x2, all 8 cores */
+ {2, 2, 2, 2, 2, 2, 2, 2},
+ /* PIPEMUX = 6, RC 3x4 (cores 0, 6, 7), RC 2x2 (cores 2, 3) */
+ {4, 0, 2, 2, 0, 0, 4, 4},
+ /* PIPEMUX = 7, RC 1x4 (core 0), RC 6x2 (cores 2, 3, 4, 5, 6, 7 */
+ {4, 0, 2, 2, 2, 2, 2, 2},
+ /* PIPEMUX = 8, EP 1x8 + RC 4x2 (cores 4, 5, 6, 7) */
+ {0, 0, 0, 0, 2, 2, 2, 2},
+ /* PIPEMUX = 9, EP 1x8 + RC 2x4 (cores 6, 7) */
+ {0, 0, 0, 0, 0, 0, 4, 4},
+ /* PIPEMUX = 10, EP 2x4 + RC 2x4 (cores 1, 6) */
+ {0, 4, 0, 0, 0, 0, 4, 0},
+ /* PIPEMUX = 11, EP 2x4 + RC 4x2 (cores 2, 3, 4, 5) */
+ {0, 0, 2, 2, 2, 2, 0, 0},
+ /* PIPEMUX = 12, EP 1x4 + RC 6x2 (cores 2, 3, 4, 5, 6, 7) */
+ {0, 0, 2, 2, 2, 2, 2, 2},
+ /* PIPEMUX = 13, EP 2x4 + RC 1x4 (core 6) + RC 2x2 (cores 2, 3) */
+ {0, 0, 2, 2, 0, 0, 4, 0}
+};
+
+/*
+ * function for writes to the Serdes registers through the PMI interface
+ */
+static int paxb_pmi_write(unsigned int core_idx, uint32_t pmi, uint32_t val)
+{
+ uint32_t status;
+ unsigned int timeout = PMI_TIMEOUT_MS;
+
+ paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
+
+ val &= ~CFG_RC_RWCMD_MASK;
+ val |= CFG_RC_WCMD_MASK;
+ paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, val);
+
+ do {
+ status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_WDATA);
+
+ /* wait for write command bit to clear */
+ if ((status & CFG_RC_WCMD_MASK) == 0)
+ return 0;
+ } while (--timeout);
+
+ return -EIO;
+}
+
+/*
+ * function for reads from the Serdes registers through the PMI interface
+ */
+static int paxb_pmi_read(unsigned int core_idx, uint32_t pmi, uint32_t *val)
+{
+ uint32_t status;
+ unsigned int timeout = PMI_TIMEOUT_MS;
+
+ paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
+
+ paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, CFG_RC_RCMD_MASK);
+
+ do {
+ status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
+
+ /* wait for read ack bit set */
+ if ((status & CFG_RC_RACK_MASK)) {
+ *val = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
+ return 0;
+ }
+ } while (--timeout);
+
+ return -EIO;
+}
+
+
+#ifndef BOARD_PCIE_EXT_CLK
+/*
+ * PCIe Override clock lookup table
+ *
+ * Each array index represents pcie override clock has been done
+ * by CFW or not.
+ */
+static uint8_t pcie_override_clk_table[] = {
+ /* PIPEMUX = 0, EP 1x16 */
+ 0x0,
+ /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+ 0x1,
+ /* PIPEMUX = 2, EP 4x4 */
+ 0x0,
+ /* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+ 0x0,
+ /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+ 0x0,
+ /* PIPEMUX = 5, RC 8x2, all 8 cores */
+ 0x0,
+ /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+ 0x0,
+ /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+ 0x0,
+ /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+ 0x0,
+ /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+ 0x0,
+ /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+ 0x0,
+ /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+ 0x0,
+ /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+ 0x0,
+ /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+ 0x0,
+};
+
+/*
+ * Bring up LCPLL channel 0 reference clock for PCIe serdes used in RC mode
+ */
+static int pcie_lcpll_init(void)
+{
+ uintptr_t reg;
+ unsigned int timeout = PCIE_LCPLL_TIMEOUT_MS;
+ uint32_t val;
+
+ if (pcie_override_clk_table[pipemux_idx]) {
+ /*
+ * Check rc_mode_override again to avoid halt
+ * because of cfw uninitialized lcpll.
+ */
+ reg = (uintptr_t)(PCIE_LCPLL_BASE +
+ PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG);
+ val = mmio_read_32(reg);
+ if (val & 0x1)
+ return 0;
+ else
+ return -ENODEV;
+ }
+
+ /* power on PCIe LCPLL and its LDO */
+ reg = (uintptr_t)CRMU_AON_CTRL1;
+ mmio_setbits_32(reg, CRMU_PCIE_LCPLL_PWR_ON_MASK |
+ CRMU_PCIE_LCPLL_PWRON_LDO_MASK);
+ udelay(PCIE_LCPLL_DELAY_US);
+
+ /* remove isolation */
+ mmio_clrbits_32(reg, CRMU_PCIE_LCPLL_ISO_IN_MASK);
+ udelay(PCIE_LCPLL_DELAY_US);
+
+ /* disconnect termination */
+ reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL13_OFFSET);
+ mmio_setbits_32(reg, PCIE_LCPLL_D2C2_TERM_DISC <<
+ PCIE_LCPLL_D2C2_CTRL_SHIFT);
+
+ /* enable CML buf1/2 and D2C2 */
+ reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET);
+ mmio_setbits_32(reg, PCIE_LCPLL_CM_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
+
+ /* select diff clock mux out as ref clock */
+ mmio_clrbits_32(reg, PCIE_LCPLL_REF_CLK_MASK);
+
+ /* delay for 500 microseconds per ASIC spec for PCIe LCPLL */
+ udelay(PCIE_LCPLL_DELAY_US);
+
+ /* now bring PCIe LCPLL out of reset */
+ reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL0_OFFSET);
+ mmio_setbits_32(reg, PCIE_LCPLL_RESETB_MASK);
+
+ /* wait for PLL to lock */
+ reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_STATUS_OFFSET);
+ do {
+ val = mmio_read_32(reg);
+ if ((val & PCIE_LCPLL_LOCK_MASK) == PCIE_LCPLL_LOCK_MASK) {
+ /* now bring the post divider out of reset */
+ reg = (uintptr_t)(PCIE_LCPLL_BASE +
+ PCIE_LCPLL_CTRL0_OFFSET);
+ mmio_setbits_32(reg, PCIE_LCPLL_P_RESETB_MASK);
+ VERBOSE("PCIe LCPLL locked\n");
+ return 0;
+ }
+ mdelay(1);
+ } while (--timeout);
+
+ ERROR("PCIe LCPLL failed to lock\n");
+ return -EIO;
+}
+#else
+/*
+ * Bring up EXT CLK reference clock for PCIe serdes used in RC mode
+ * XTAL_BYPASS (3 << 0)
+ * INTR_LC_REF (5 << 0)
+ * PD_CML_LC_REF_OUT (1 << 4)
+ * PD_CML_REF_CH_OUT (1 << 8)
+ * CLK_MASTER_SEL (1 << 11)
+ * CLK_MASTER_CTRL_A (1 << 12)
+ * CLK_MASTER_CTRL_B (2 << 14)
+ */
+static const uint16_t pcie_ext_clk[][NUM_OF_PCIE_SERDES] = {
+ /* PIPEMUX = 0, EP 1x16 */
+ {0},
+ /* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
+ {0},
+ /* PIPEMUX = 2, EP 4x4 */
+ {0},
+ /* PIPEMUX = 3, RC 2x8, cores 0, 7 */
+ {0x8803, 0x9115, 0x9115, 0x1115, 0x8803, 0x9115, 0x9115, 0x1115},
+ /* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
+ {0x8803, 0x1115, 0x8915, 0x1115, 0x8803, 0x1115, 0x8915, 0x1115,},
+ /* PIPEMUX = 5, RC 8x2, all 8 cores */
+ {0x0803, 0x0915, 0x0915, 0x0915, 0x0803, 0x0915, 0x0915, 0x0915,},
+ /* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
+ {0},
+ /* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
+ {0},
+ /* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
+ {0},
+ /* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
+ {0},
+ /* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
+ {0},
+ /* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
+ {0},
+ /* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
+ {0},
+ /* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
+ {0},
+};
+
+static void pcie_ext_clk_init(void)
+{
+ unsigned int serdes;
+ uint32_t val;
+
+ for (serdes = 0; serdes < NUM_OF_PCIE_SERDES; serdes++) {
+ val = pcie_ext_clk[pipemux_idx][serdes];
+ if (!val)
+ return;
+ mmio_write_32(PCIE_CORE_RESERVED_CFG +
+ serdes * PCIE_CORE_PWR_OFFSET, val);
+ }
+ /* disable CML buf1/2 and enable D2C2 */
+ mmio_clrsetbits_32((PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET),
+ PCIE_LCPLL_CM_BUF_ENA << PCIE_LCPLL_EN_CTRL_SHIFT,
+ PCIE_LCPLL_D2C2_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
+ mmio_write_32(PCIE_LCPLL_BASE + PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG, 1);
+ INFO("Overriding Clocking - using REF clock from PAD...\n");
+}
+#endif
+
+static int load_uc(unsigned int core_idx)
+{
+ return 0;
+}
+
+static int paxb_serdes_gate_clock(unsigned int core_idx, int gate_clk)
+{
+ unsigned int link_width, serdes, nr_serdes;
+ uintptr_t pmi_base;
+ unsigned int rdata;
+ uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
+
+ link_width = paxb->get_link_width(core_idx);
+ if (!link_width) {
+ ERROR("Unsupported PIPEMUX\n");
+ return -EOPNOTSUPP;
+ }
+
+ nr_serdes = link_width / 2;
+ pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
+
+ for (serdes = 0; serdes < nr_serdes; serdes++) {
+ mmio_write_32(pmi_base, serdes);
+ paxb_pmi_read(core_idx, PMI_ADDR_LANE0(PMI_PLL_CTRL_4), &rdata);
+ if (!gate_clk)
+ rdata |= PMI_SERDES_CLK_ENABLE;
+ else
+ rdata &= ~PMI_SERDES_CLK_ENABLE;
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(PMI_PLL_CTRL_4), rdata);
+ }
+ return 0;
+}
+
+static int paxb_gen3_serdes_init(unsigned int core_idx, uint32_t nSerdes)
+{
+ uint32_t rdata;
+ int serdes;
+ uintptr_t pmi_base;
+ unsigned int timeout;
+ unsigned int reg_d230, reg_d267;
+
+
+ pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE +
+ (core_idx * PCIE_CORE_PWR_OFFSET));
+
+ for (serdes = 0; serdes < nSerdes; serdes++) {
+ /* select the PMI interface */
+ mmio_write_32(pmi_base, serdes);
+
+ /* Clock enable */
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_CLK_CTRL0),
+ 0x3);
+
+ /* Release reset of master */
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+ 0x1);
+
+ /* clearing PRAM memory */
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
+ 0x100);
+
+ timeout = UC_RAM_INIT_TIMEOUT;
+ do {
+ paxb_pmi_read(core_idx,
+ PMI_ADDR_LANE0(UC_A_AHB_STAT0),
+ &rdata);
+ } while ((rdata & 0x01) == 0 && timeout--);
+
+ if (!timeout)
+ return -EIO;
+
+ timeout = UC_RAM_INIT_TIMEOUT;
+ do {
+ paxb_pmi_read(core_idx,
+ PMI_ADDR_LANE1(UC_A_AHB_STAT0),
+ &rdata);
+ } while ((rdata & 0x01) == 0 && timeout--);
+
+ if (!timeout)
+ return -EIO;
+
+ /* clearing PRAM memory */
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
+ 0);
+
+ /* to identify 2 lane serdes */
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_DBG1), 0x1);
+
+ /* De-Assert Pram & master resets */
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+ 0x9);
+
+ if (load_uc(core_idx))
+ return -EIO;
+
+ /* UC UC ready for command */
+ paxb_pmi_read(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
+ &rdata);
+ rdata |= DSC_UC_CTRL_RDY_CMD;
+ paxb_pmi_write(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
+ rdata);
+
+ paxb_pmi_read(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
+ &rdata);
+ rdata |= DSC_UC_CTRL_RDY_CMD;
+ paxb_pmi_write(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
+ rdata);
+
+ /* Lane reset */
+ paxb_pmi_write(core_idx,
+ PMI_ADDR_BCAST(LANE_DBG_RST_CTRL), 0x3);
+
+ /* De-Assert Core and Master resets */
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
+ 0x3);
+
+ timeout = UC_INIT_TIMEOUT;
+ while (timeout--) {
+ paxb_pmi_read(core_idx,
+ PMI_ADDR_LANE0(UC_VERSION_NUM),
+ &reg_d230);
+ paxb_pmi_read(core_idx,
+ PMI_ADDR_LANE0(DSC_SM_CTL22),
+ &reg_d267);
+
+ if (((reg_d230 & 0xffff) != 0) &
+ ((reg_d267 & 0xc000) == 0xc000)) {
+ break;
+ }
+ mdelay(1);
+ }
+
+ if (!timeout)
+ return -EIO;
+
+ timeout = UC_INIT_TIMEOUT;
+ while (timeout--) {
+ paxb_pmi_read(core_idx,
+ PMI_ADDR_LANE1(UC_VERSION_NUM),
+ &reg_d230);
+ paxb_pmi_read(core_idx,
+ PMI_ADDR_LANE1(DSC_SM_CTL22),
+ &reg_d267);
+
+ if (((reg_d230 & 0xffff) != 0) &
+ ((reg_d267 & 0xc000) == 0xc000)) {
+ break;
+ }
+ mdelay(1);
+ }
+
+ if (!timeout)
+ return -EIO;
+ }
+ return 0;
+}
+
+static int pcie_serdes_requires_patch(unsigned int serdes_idx)
+{
+ if (pipemux_idx != SERDES_PATCH_PIPEMUX_INDEX)
+ return 0;
+
+ return !!((SERDES_PATCH_INDEX >> serdes_idx) & 0x1);
+}
+
+static void pcie_tx_coeff_p7(unsigned int core_idx)
+{
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11b), 0x00aa);
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11c), 0x1155);
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11d), 0x2449);
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11e), 0x000f);
+ paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd307), 0x0001);
+}
+
+
+static unsigned int paxb_sr_get_rc_link_width(unsigned int core_idx)
+{
+ return link_width_table[pipemux_idx][core_idx];
+}
+
+static uint32_t paxb_sr_get_rc_link_speed(void)
+{
+ return GEN3_LINK_SPEED;
+}
+
+
+static int paxb_serdes_init(unsigned int core_idx, unsigned int nr_serdes)
+{
+ uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
+ unsigned int serdes;
+ uintptr_t pmi_base;
+ int ret;
+
+ /*
+ * Each serdes has a x2 link width
+ *
+ * Use PAXB to patch the serdes for proper RX termination through the
+ * PMI interface
+ */
+ pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
+ for (serdes = 0; serdes < nr_serdes; serdes++) {
+ /* select the PMI interface */
+ mmio_write_32(pmi_base, serdes);
+
+ /* patch Serdes for RX termination */
+ ret = paxb_pmi_write(core_idx, PMI_RX_TERM_SEQ,
+ PMI_RX_TERM_VAL);
+ if (ret)
+ goto err_pmi;
+
+ ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_7,
+ MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL);
+ if (ret)
+ goto err_pmi;
+
+ ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_8,
+ MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL);
+ if (ret)
+ goto err_pmi;
+
+ ret = paxb_pmi_write(core_idx, MERLIN16_AMS_TX_CTRL_5,
+ MERLIN16_AMS_TX_CTRL_5_VAL);
+ if (ret)
+ goto err_pmi;
+
+ pcie_tx_coeff_p7(core_idx);
+
+ if (pcie_serdes_requires_patch(serdes)) {
+ if (((core_idx == 0) || (core_idx == 7))) {
+ ret = paxb_pmi_write(core_idx,
+ PMI_X8_CORE0_7_PATCH_SEQ,
+ PMI_X8_CORE0_7_PATCH_VAL);
+ if (ret)
+ goto err_pmi;
+ }
+ }
+ }
+
+ return 0;
+
+err_pmi:
+ ERROR("PCIe PMI write failed\n");
+ return ret;
+}
+
+static int paxb_sr_phy_init(void)
+{
+ int ret;
+ unsigned int core_idx;
+
+#ifndef BOARD_PCIE_EXT_CLK
+ ret = pcie_lcpll_init();
+ if (ret)
+ return ret;
+#else
+ pcie_ext_clk_init();
+#endif
+
+ for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
+ if (!pcie_core_needs_enable(core_idx))
+ continue;
+ unsigned int link_width;
+
+ paxb_serdes_gate_clock(core_idx, 0);
+
+ link_width = paxb->get_link_width(core_idx);
+ if (!link_width) {
+ ERROR("Unsupported PIPEMUX\n");
+ return -EOPNOTSUPP;
+ }
+
+ ret = paxb_serdes_init(core_idx, link_width / 2);
+ if (ret) {
+ ERROR("PCIe serdes initialization failed for core %u\n",
+ core_idx);
+ return ret;
+ }
+
+
+ ret = paxb_gen3_serdes_init(core_idx, link_width / 2);
+ if (ret) {
+ ERROR("PCIe GEN3 serdes initialization failed\n");
+ return ret;
+ }
+
+ }
+ return 0;
+}
+
+const paxb_cfg sr_paxb_cfg = {
+ .type = PAXB_SR,
+ .device_id = SR_B0_DEVICE_ID,
+ .pipemux_init = pipemux_sr_init,
+ .phy_init = paxb_sr_phy_init,
+ .core_needs_enable = paxb_sr_core_needs_enable,
+ .num_cores = NUM_OF_SR_PCIE_CORES,
+ .get_link_width = paxb_sr_get_rc_link_width,
+ .get_link_speed = paxb_sr_get_rc_link_speed,
+};
+
+const paxb_cfg *paxb_get_sr_config(void)
+{
+ return &sr_paxb_cfg;
+}
diff --git a/plat/brcm/board/stingray/src/topology.c b/plat/brcm/board/stingray/src/topology.c
new file mode 100644
index 0000000..24718e5
--- /dev/null
+++ b/plat/brcm/board/stingray/src/topology.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019-2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdint.h>
+
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+/*
+ * On Stingray, the system power level is the highest power level.
+ * The first entry in the power domain descriptor specifies the
+ * number of system power domains i.e. 1.
+ */
+#define SR_PWR_DOMAINS_AT_MAX_PWR_LVL 1
+
+/*
+ * The Stingray power domain tree descriptor. The cluster power domains
+ * are arranged so that when the PSCI generic code creates the power
+ * domain tree, the indices of the CPU power domain nodes it allocates
+ * match the linear indices returned by plat_core_pos_by_mpidr()
+ * i.e. CLUSTER0 CPUs are allocated indices from 0 to 1 and the higher
+ * indices for other Cluster CPUs.
+ */
+const unsigned char sr_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ SR_PWR_DOMAINS_AT_MAX_PWR_LVL,
+ /* No of children for the root node */
+ BRCM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT,
+ /* No of children for the third cluster node */
+ PLATFORM_CLUSTER2_CORE_COUNT,
+ /* No of children for the fourth cluster node */
+ PLATFORM_CLUSTER3_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the Stingray topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return sr_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ return plat_brcm_calc_core_pos(mpidr);
+}
diff --git a/plat/brcm/board/stingray/src/tz_sec.c b/plat/brcm/board/stingray/src/tz_sec.c
new file mode 100644
index 0000000..07b12a7
--- /dev/null
+++ b/plat/brcm/board/stingray/src/tz_sec.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/tzc400.h>
+#include <lib/mmio.h>
+
+#include <cmn_sec.h>
+#include <platform_def.h>
+
+/*
+ * Trust Zone controllers
+ */
+#define TZC400_FS_SRAM_ROOT 0x66d84000
+
+/*
+ * TZPC Master configure registers
+ */
+
+/* TZPC_TZPCDECPROT0set */
+#define TZPC0_MASTER_NS_BASE 0x68b40804
+#define TZPC0_SATA3_BIT 5
+#define TZPC0_SATA2_BIT 4
+#define TZPC0_SATA1_BIT 3
+#define TZPC0_SATA0_BIT 2
+#define TZPC0_USB3H1_BIT 1
+#define TZPC0_USB3H0_BIT 0
+#define TZPC0_MASTER_SEC_DEFAULT 0
+
+/* TZPC_TZPCDECPROT1set */
+#define TZPC1_MASTER_NS_BASE 0x68b40810
+#define TZPC1_SDIO1_BIT 6
+#define TZPC1_SDIO0_BIT 5
+#define TZPC1_AUDIO0_BIT 4
+#define TZPC1_USB2D_BIT 3
+#define TZPC1_USB2H1_BIT 2
+#define TZPC1_USB2H0_BIT 1
+#define TZPC1_AMAC0_BIT 0
+#define TZPC1_MASTER_SEC_DEFAULT 0
+
+
+struct tz_sec_desc {
+ uintptr_t addr;
+ uint32_t val;
+};
+
+static const struct tz_sec_desc tz_master_defaults[] = {
+{ TZPC0_MASTER_NS_BASE, TZPC0_MASTER_SEC_DEFAULT },
+{ TZPC1_MASTER_NS_BASE, TZPC1_MASTER_SEC_DEFAULT }
+};
+
+/*
+ * Initialize the TrustZone Controller for SRAM partitioning.
+ */
+static void bcm_tzc_setup(void)
+{
+ VERBOSE("Configuring SRAM TrustZone Controller\n");
+
+ /* Init the TZASC controller */
+ tzc400_init(TZC400_FS_SRAM_ROOT);
+
+ /*
+ * Close the entire SRAM space
+ * Region 0 covers the entire SRAM space
+ * None of the NS device can access it.
+ */
+ tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+
+ /* Do raise an exception if a NS device tries to access secure memory */
+ tzc400_set_action(TZC_ACTION_ERR);
+}
+
+/*
+ * Configure TZ Master as NS_MASTER or SECURE_MASTER
+ * To set a Master to non-secure, use *_SET registers
+ * To set a Master to secure, use *_CLR registers (set + 0x4 address)
+ */
+static void tz_master_set(uint32_t base, uint32_t value, uint32_t ns)
+{
+ if (ns == SECURE_MASTER) {
+ mmio_write_32(base + 4, value);
+ } else {
+ mmio_write_32(base, value);
+ }
+}
+
+/*
+ * Initialize the secure environment for sdio.
+ */
+void plat_tz_sdio_ns_master_set(uint32_t ns)
+{
+ tz_master_set(TZPC1_MASTER_NS_BASE,
+ 1 << TZPC1_SDIO0_BIT,
+ ns);
+}
+
+/*
+ * Initialize the secure environment for usb.
+ */
+void plat_tz_usb_ns_master_set(uint32_t ns)
+{
+ tz_master_set(TZPC1_MASTER_NS_BASE,
+ 1 << TZPC1_USB2H0_BIT,
+ ns);
+}
+
+/*
+ * Set masters to default configuration.
+ *
+ * DMA security settings are programmed into the PL-330 controller and
+ * are not set by iProc TZPC registers.
+ * DMA always comes up as secure master (*NS bit is 0).
+ *
+ * Because the default reset values of TZPC are 0 (== Secure),
+ * ARM Verilog code makes all masters, including PCIe, come up as
+ * secure.
+ * However, SOTP has a bit called SOTP_ALLMASTER_NS that overrides
+ * TZPC and makes all masters non-secure for AB devices.
+ *
+ * Hence we first set all the TZPC bits to program all masters,
+ * including PCIe, as non-secure, then set the CLEAR_ALLMASTER_NS bit
+ * so that the SOTP_ALLMASTER_NS cannot override TZPC.
+ * now security settings for each masters come from TZPC
+ * (which makes all masters other than DMA as non-secure).
+ *
+ * During the boot, all masters other than DMA Ctrlr + list
+ * are non-secure in an AB Prod/AB Dev/AB Pending device.
+ *
+ */
+void plat_tz_master_default_cfg(void)
+{
+ int i;
+
+ /* Configure default secure and non-secure TZ Masters */
+ for (i = 0; i < ARRAY_SIZE(tz_master_defaults); i++) {
+ tz_master_set(tz_master_defaults[i].addr,
+ tz_master_defaults[i].val,
+ SECURE_MASTER);
+ tz_master_set(tz_master_defaults[i].addr,
+ ~tz_master_defaults[i].val,
+ NS_MASTER);
+ }
+
+ /* Clear all master NS */
+ mmio_setbits_32(SOTP_CHIP_CTRL,
+ 1 << SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS);
+
+ /* Initialize TZ controller and Set SRAM to secure */
+ bcm_tzc_setup();
+}
diff --git a/plat/brcm/common/brcm_bl2_mem_params_desc.c b/plat/brcm/common/brcm_bl2_mem_params_desc.c
new file mode 100644
index 0000000..aed99d9
--- /dev/null
+++ b/plat/brcm/common/brcm_bl2_mem_params_desc.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = PLAT_MAX_SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg3 = BRCM_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+#ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+#else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+#endif
+ },
+
+#ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+#endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+#ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#else
+ .ep_info.pc = PLAT_BRCM_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_BRCM_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = BRCM_DRAM1_SIZE,
+#endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/brcm/common/brcm_bl2_setup.c b/plat/brcm/common/brcm_bl2_setup.c
new file mode 100644
index 0000000..9a7153b
--- /dev/null
+++ b/plat/brcm/common/brcm_bl2_setup.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <lib/mmio.h>
+
+#include <bcm_console.h>
+#include <platform_def.h>
+#include <plat/brcm/common/plat_brcm.h>
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/* Weak definitions may be overridden in specific BRCM platform */
+#pragma weak plat_bcm_bl2_platform_setup
+#pragma weak plat_bcm_bl2_plat_arch_setup
+#pragma weak plat_bcm_security_setup
+#pragma weak plat_bcm_bl2_plat_handle_scp_bl2
+#pragma weak plat_bcm_bl2_early_platform_setup
+
+void plat_bcm_bl2_early_platform_setup(void)
+{
+}
+
+void plat_bcm_bl2_platform_setup(void)
+{
+}
+
+void plat_bcm_bl2_plat_arch_setup(void)
+{
+}
+
+void plat_bcm_security_setup(void)
+{
+}
+
+void bcm_bl2_early_platform_setup(uintptr_t tb_fw_config,
+ meminfo_t *mem_layout)
+{
+ /* Initialize the console to provide early debug support */
+ bcm_console_boot_init();
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_brcm_io_setup();
+
+ /* Log HW reset event */
+ INFO("RESET: 0x%x\n",
+ mmio_read_32(CRMU_RESET_EVENT_LOG));
+}
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ /* SoC specific setup */
+ plat_bcm_bl2_early_platform_setup();
+
+ /* Initialize delay timer driver using SP804 dual timer 0 */
+ sp804_timer_init(SP804_TIMER0_BASE,
+ SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV);
+
+ /* BRCM platforms generic setup */
+ bcm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
+}
+
+/*
+ * Perform Broadcom platform setup.
+ */
+void bcm_bl2_platform_setup(void)
+{
+ /* Initialize the secure environment */
+ plat_bcm_security_setup();
+}
+
+void bl2_platform_setup(void)
+{
+ bcm_bl2_platform_setup();
+ plat_bcm_bl2_platform_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bcm_bl2_plat_arch_setup(void)
+{
+#ifndef MMU_DISABLED
+ if (!(read_sctlr_el1() & SCTLR_M_BIT)) {
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END -
+ BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_brcm_get_mmap());
+ enable_mmu_el1(0);
+ }
+#endif
+}
+
+void bl2_plat_arch_setup(void)
+{
+#ifdef ENA_MMU_BEFORE_DDR_INIT
+ /*
+ * Once MMU is enabled before DDR, MEMORY TESTS
+ * get affected as read/write transaction might occures from
+ * caches. So For running memory test, one should not set this
+ * flag.
+ */
+ bcm_bl2_plat_arch_setup();
+ plat_bcm_bl2_plat_arch_setup();
+#else
+ plat_bcm_bl2_plat_arch_setup();
+ bcm_bl2_plat_arch_setup();
+#endif
+}
+
+int bcm_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+ bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl32_entry();
+ break;
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl33_entry();
+ break;
+
+#ifdef SCP_BL2_BASE
+ case SCP_BL2_IMAGE_ID:
+ /* The subsequent handling of SCP_BL2 is platform specific */
+ err = bcm_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+ if (err)
+ WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+ break;
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bcm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return bcm_bl2_handle_post_image_load(image_id);
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return bcm_bl2_plat_handle_post_image_load(image_id);
+}
+
+#ifdef SCP_BL2_BASE
+int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ return 0;
+}
+
+int bcm_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ return plat_bcm_bl2_plat_handle_scp_bl2(scp_bl2_image_info);
+}
+#endif
diff --git a/plat/brcm/common/brcm_bl31_setup.c b/plat/brcm/common/brcm_bl31_setup.c
new file mode 100644
index 0000000..d3fa83d
--- /dev/null
+++ b/plat/brcm/common/brcm_bl31_setup.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <bcm_console.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+#ifdef BL33_SHARED_DDR_BASE
+struct bl33_info *bl33_info = (struct bl33_info *)BL33_SHARED_DDR_BASE;
+#endif
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* Weak definitions may be overridden in specific BRCM platform */
+#pragma weak plat_bcm_bl31_early_platform_setup
+#pragma weak plat_brcm_pwrc_setup
+#pragma weak plat_brcm_security_setup
+
+void plat_brcm_security_setup(void)
+{
+
+}
+
+void plat_brcm_pwrc_setup(void)
+{
+
+}
+
+void plat_bcm_bl31_early_platform_setup(void *from_bl2,
+ bl_params_t *plat_params_from_bl2)
+{
+
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup common to ARM standard platforms.
+ * Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be
+ * done before the MMU is initialized so that the memory layout can be used
+ * while creating page tables. BL2 has flushed this information to memory, so
+ * we are guaranteed to pick up good data.
+ ******************************************************************************/
+void __init brcm_bl31_early_platform_setup(void *from_bl2,
+ uintptr_t soc_fw_config,
+ uintptr_t hw_config,
+ void *plat_params_from_bl2)
+{
+ /* Initialize the console to provide early debug support */
+ bcm_console_boot_init();
+
+ /* Initialize delay timer driver using SP804 dual timer 0 */
+ sp804_timer_init(SP804_TIMER0_BASE,
+ SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV);
+
+#if RESET_TO_BL31
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(from_bl2 == NULL);
+ assert(plat_params_from_bl2 == NULL);
+
+# ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = brcm_get_spsr_for_bl32_entry();
+# endif /* BL32_BASE */
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+
+ bl33_image_ep_info.spsr = brcm_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+# if ARM_LINUX_KERNEL_AS_BL33
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ */
+ bl33_image_ep_info.args.arg0 = (u_register_t)PRELOADED_DTB_BASE;
+ bl33_image_ep_info.args.arg1 = 0U;
+ bl33_image_ep_info.args.arg2 = 0U;
+ bl33_image_ep_info.args.arg3 = 0U;
+# endif
+
+#else /* RESET_TO_BL31 */
+
+ /*
+ * In debug builds, we pass a special value in 'plat_params_from_bl2'
+ * to verify platform parameters from BL2 to BL31.
+ * In release builds, it's not used.
+ */
+ assert(((unsigned long long)plat_params_from_bl2) ==
+ BRCM_BL31_PLAT_PARAM_VAL);
+
+ /*
+ * Check params passed from BL2 should not be NULL
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params != NULL) {
+ if (bl_params->image_id == BL32_IMAGE_ID &&
+ bl_params->image_info->h.attr != IMAGE_ATTRIB_SKIP_LOADING)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0U)
+ panic();
+#endif /* RESET_TO_BL31 */
+
+#ifdef BL33_SHARED_DDR_BASE
+ /* Pass information to BL33 thorugh x0 */
+ bl33_image_ep_info.args.arg0 = (u_register_t)BL33_SHARED_DDR_BASE;
+ bl33_image_ep_info.args.arg1 = 0ULL;
+ bl33_image_ep_info.args.arg2 = 0ULL;
+ bl33_image_ep_info.args.arg3 = 0ULL;
+#endif
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+#ifdef BL31_LOG_LEVEL
+ SET_LOG_LEVEL(BL31_LOG_LEVEL);
+#endif
+
+ brcm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+ plat_bcm_bl31_early_platform_setup((void *)arg0, (void *)arg3);
+
+#ifdef DRIVER_CC_ENABLE
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_brcm_interconnect_init();
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this (e.g. Trusted
+ * Firmware's BL1 does it) but we can't assume so. There is no harm in
+ * executing this code twice anyway.
+ * Platform specific PSCI code will enable coherency for other
+ * clusters.
+ */
+ plat_brcm_interconnect_enter_coherency();
+#endif
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ ******************************************************************************/
+void brcm_bl31_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ plat_brcm_gic_driver_init();
+ plat_brcm_gic_init();
+
+ /* Initialize power controller before setting up topology */
+ plat_brcm_pwrc_setup();
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM
+ * standard platforms
+ * Perform BL31 platform setup
+ ******************************************************************************/
+void brcm_bl31_plat_runtime_setup(void)
+{
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+
+ /* Initialize the runtime console */
+ bcm_console_runtime_init();
+}
+
+void bl31_platform_setup(void)
+{
+ brcm_bl31_platform_setup();
+
+ /* Initialize the secure environment */
+ plat_brcm_security_setup();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ brcm_bl31_plat_runtime_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ ******************************************************************************/
+void __init brcm_bl31_plat_arch_setup(void)
+{
+#ifndef MMU_DISABLED
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_brcm_get_mmap());
+
+ enable_mmu_el3(0);
+#endif
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+ brcm_bl31_plat_arch_setup();
+}
diff --git a/plat/brcm/common/brcm_ccn.c b/plat/brcm/common/brcm_ccn.c
new file mode 100644
index 0000000..9396aaa
--- /dev/null
+++ b/plat/brcm/common/brcm_ccn.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <drivers/arm/ccn.h>
+
+#include <platform_def.h>
+
+static const unsigned char master_to_rn_id_map[] = {
+ PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP
+};
+
+static const ccn_desc_t bcm_ccn_desc = {
+ .periphbase = PLAT_BRCM_CCN_BASE,
+ .num_masters = ARRAY_SIZE(master_to_rn_id_map),
+ .master_to_rn_id_map = master_to_rn_id_map
+};
+
+void plat_brcm_interconnect_init(void)
+{
+ ccn_init(&bcm_ccn_desc);
+}
+
+void plat_brcm_interconnect_enter_coherency(void)
+{
+ ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+void plat_brcm_interconnect_exit_coherency(void)
+{
+ ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/brcm/common/brcm_common.c b/plat/brcm/common/brcm_common.c
new file mode 100644
index 0000000..f23719d
--- /dev/null
+++ b/plat/brcm/common/brcm_common.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+/* Weak definitions may be overridden in specific BRCM platform */
+#pragma weak plat_get_ns_image_entrypoint
+#pragma weak plat_brcm_get_mmap
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return PLAT_BRCM_NS_IMAGE_OFFSET;
+#endif
+}
+
+uint32_t brcm_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+uint32_t brcm_get_spsr_for_bl33_entry(void)
+{
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = el_implemented(2) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+const mmap_region_t *plat_brcm_get_mmap(void)
+{
+ return plat_brcm_mmap;
+}
diff --git a/plat/brcm/common/brcm_gicv3.c b/plat/brcm/common/brcm_gicv3.c
new file mode 100644
index 0000000..c4137c0
--- /dev/null
+++ b/plat/brcm/common/brcm_gicv3.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/gicv3.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t brcm_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t brcm_interrupt_props[] = {
+ /* G1S interrupts */
+ PLAT_BRCM_G1S_IRQ_PROPS(INTR_GROUP1S),
+ /* G0 interrupts */
+ PLAT_BRCM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ * - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int brcm_gicv3_mpidr_hash(u_register_t mpidr)
+{
+ mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+static const gicv3_driver_data_t brcm_gic_data = {
+ .gicd_base = PLAT_BRCM_GICD_BASE,
+ .gicr_base = PLAT_BRCM_GICR_BASE,
+ .interrupt_props = brcm_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(brcm_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = brcm_rdistif_base_addrs,
+ .mpidr_to_core_pos = brcm_gicv3_mpidr_hash
+};
+
+void plat_brcm_gic_driver_init(void)
+{
+ /* TODO Check if this is required to be initialized here
+ * after getting initialized in EL3, should we re-init this here
+ * in S-EL1
+ */
+ gicv3_driver_init(&brcm_gic_data);
+}
+
+void plat_brcm_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_brcm_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_brcm_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void plat_brcm_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+void plat_brcm_gic_redistif_on(void)
+{
+ gicv3_rdistif_on(plat_my_core_pos());
+}
+
+void plat_brcm_gic_redistif_off(void)
+{
+ gicv3_rdistif_off(plat_my_core_pos());
+}
diff --git a/plat/brcm/common/brcm_image_load.c b/plat/brcm/common/brcm_image_load.c
new file mode 100644
index 0000000..ba02bda
--- /dev/null
+++ b/plat/brcm/common/brcm_image_load.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#pragma weak plat_flush_next_bl_params
+#pragma weak plat_get_bl_image_load_info
+#pragma weak plat_get_next_bl_params
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+struct bl_load_info *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+ bl_params_t *next_bl_params = get_next_bl_params_from_mem_params_desc();
+
+ populate_next_bl_params_config(next_bl_params);
+ return next_bl_params;
+}
diff --git a/plat/brcm/common/brcm_io_storage.c b/plat/brcm/common/brcm_io_storage.c
new file mode 100644
index 0000000..66ec292
--- /dev/null
+++ b/plat/brcm/common/brcm_io_storage.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <cmn_plat_def.h>
+#include <cmn_plat_util.h>
+#include <plat_brcm.h>
+#include <platform_def.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+ .offset = PLAT_BRCM_FIP_BASE,
+ .length = PLAT_BRCM_FIP_MAX_SIZE
+};
+
+static const io_block_spec_t qspi_fip_block_spec = {
+ .offset = PLAT_BRCM_FIP_QSPI_BASE,
+ .length = PLAT_BRCM_FIP_MAX_SIZE
+};
+
+static const io_block_spec_t nand_fip_block_spec = {
+ .offset = PLAT_BRCM_FIP_NAND_BASE,
+ .length = PLAT_BRCM_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t scp_bl2_uuid_spec = {
+ .uuid = UUID_SCP_FIRMWARE_SCP_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+static const io_uuid_spec_t tb_fw_config_uuid_spec = {
+ .uuid = UUID_TB_FW_CONFIG,
+};
+
+static const io_uuid_spec_t hw_config_uuid_spec = {
+ .uuid = UUID_HW_CONFIG,
+};
+
+static const io_uuid_spec_t soc_fw_config_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONFIG,
+};
+
+static const io_uuid_spec_t tos_fw_config_uuid_spec = {
+ .uuid = UUID_TOS_FW_CONFIG,
+};
+
+static const io_uuid_spec_t nt_fw_config_uuid_spec = {
+ .uuid = UUID_NT_FW_CONFIG,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+static int open_qspi(const uintptr_t spec);
+static int open_nand(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, BRCM platforms load images from the FIP */
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [SCP_BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+ [TB_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_config_uuid_spec,
+ open_fip
+ },
+ [HW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&hw_config_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_config_uuid_spec,
+ open_fip
+ },
+ [TOS_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_config_uuid_spec,
+ open_fip
+ },
+ [NT_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_config_uuid_spec,
+ open_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ open_fip
+ },
+ [SCP_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [SCP_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ open_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+/* By default, BRCM platforms load images from the FIP */
+static const struct plat_io_policy boot_source_policies[] = {
+ [BOOT_SOURCE_QSPI] = {
+ &memmap_dev_handle,
+ (uintptr_t)&qspi_fip_block_spec,
+ open_qspi
+ },
+ [BOOT_SOURCE_NAND] = {
+ &memmap_dev_handle,
+ (uintptr_t)&nand_fip_block_spec,
+ open_nand
+ },
+};
+
+/* Weak definitions may be overridden in specific brcm platform */
+#pragma weak plat_brcm_io_setup
+#pragma weak plat_brcm_process_flags
+
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+static int open_qspi(const uintptr_t spec)
+{
+ return open_memmap(spec);
+}
+
+static int open_nand(const uintptr_t spec)
+{
+ return open_memmap(spec);
+}
+
+
+void brcm_io_setup(void)
+{
+ int io_result;
+ uint32_t boot_source;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ assert(io_result == 0);
+
+ boot_source = boot_source_get();
+ switch (boot_source) {
+ case BOOT_SOURCE_QSPI:
+ case BOOT_SOURCE_NAND:
+ default:
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+ break;
+ }
+ assert(io_result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)io_result;
+}
+
+void plat_brcm_io_setup(void)
+{
+ brcm_io_setup();
+}
+
+void plat_brcm_process_flags(uint16_t plat_toc_flags __unused)
+{
+ WARN("%s not implemented\n", __func__);
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+ uint32_t boot_source;
+ uint16_t lcl_plat_toc_flg;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ boot_source = boot_source_get();
+ if (image_id == FIP_IMAGE_ID)
+ policy = &boot_source_policies[boot_source];
+ else
+ policy = &policies[image_id];
+
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ if (image_id == TRUSTED_BOOT_FW_CERT_ID) {
+ /*
+ * Process the header flags to perform
+ * such custom actions as speeding up PLL.
+ * CERT seems to be the first image accessed
+ * by BL1 so this is where we process the flags.
+ */
+ fip_dev_get_plat_toc_flag((io_dev_info_t *)fip_dev_handle,
+ &lcl_plat_toc_flg);
+ plat_brcm_process_flags(lcl_plat_toc_flg);
+ }
+ }
+
+ return result;
+}
diff --git a/plat/brcm/common/brcm_mhu.c b/plat/brcm/common/brcm_mhu.c
new file mode 100644
index 0000000..56f44e0
--- /dev/null
+++ b/plat/brcm/common/brcm_mhu.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+
+#include <brcm_mhu.h>
+#include <platform_def.h>
+
+#include "m0_ipc.h"
+
+#define PLAT_MHU_INTR_REG AP_TO_SCP_MAILBOX1
+
+/* SCP MHU secure channel registers */
+#define SCP_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG11
+#define SCP_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG11
+#define SCP_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG11
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG10
+#define CPU_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG10
+#define CPU_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG10
+
+static DEFINE_BAKERY_LOCK(bcm_lock);
+
+/*
+ * Slot 31 is reserved because the MHU hardware uses this register bit to
+ * indicate a non-secure access attempt. The total number of available slots is
+ * therefore 31 [30:0].
+ */
+#define MHU_MAX_SLOT_ID 30
+
+void mhu_secure_message_start(unsigned int slot_id)
+{
+ int iter = 1000000;
+
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+
+ bakery_lock_get(&bcm_lock);
+ /* Make sure any previous command has finished */
+ do {
+ if (!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
+ (1 << slot_id)))
+ break;
+
+ udelay(1);
+
+ } while (--iter);
+
+ assert(iter != 0);
+}
+
+void mhu_secure_message_send(unsigned int slot_id)
+{
+ uint32_t response, iter = 1000000;
+
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+ assert(!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
+ (1 << slot_id)));
+
+ /* Send command to SCP */
+ mmio_setbits_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
+ mmio_write_32(CRMU_MAIL_BOX0, MCU_IPC_MCU_CMD_SCPI);
+ mmio_write_32(PLAT_BRCM_MHU_BASE + PLAT_MHU_INTR_REG, 0x1);
+
+ /* Wait until IPC transport acknowledges reception of SCP command */
+ do {
+ response = mmio_read_32(CRMU_MAIL_BOX0);
+ if ((response & ~MCU_IPC_CMD_REPLY_MASK) ==
+ (MCU_IPC_CMD_DONE_MASK | MCU_IPC_MCU_CMD_SCPI))
+ break;
+
+ udelay(1);
+
+ } while (--iter);
+
+ assert(iter != 0);
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+ /* Wait for response from SCP */
+ uint32_t response, iter = 1000000;
+
+ do {
+ response = mmio_read_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT);
+ if (!response)
+ break;
+
+ udelay(1);
+ } while (--iter);
+ assert(iter != 0);
+
+ return response;
+}
+
+void mhu_secure_message_end(unsigned int slot_id)
+{
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+
+ /*
+ * Clear any response we got by writing one in the relevant slot bit to
+ * the CLEAR register
+ */
+ mmio_clrbits_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
+ bakery_lock_release(&bcm_lock);
+}
+
+void mhu_secure_init(void)
+{
+ bakery_lock_init(&bcm_lock);
+
+ /*
+ * The STAT register resets to zero. Ensure it is in the expected state,
+ * as a stale or garbage value would make us think it's a message we've
+ * already sent.
+ */
+ mmio_write_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT, 0);
+ mmio_write_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT, 0);
+}
+
+void plat_brcm_pwrc_setup(void)
+{
+ mhu_secure_init();
+}
diff --git a/plat/brcm/common/brcm_mhu.h b/plat/brcm/common/brcm_mhu.h
new file mode 100644
index 0000000..6c89a34
--- /dev/null
+++ b/plat/brcm/common/brcm_mhu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BRCM_MHU_H
+#define BRCM_MHU_H
+
+#include <stdint.h>
+
+void mhu_secure_message_start(unsigned int slot_id);
+void mhu_secure_message_send(unsigned int slot_id);
+uint32_t mhu_secure_message_wait(void);
+void mhu_secure_message_end(unsigned int slot_id);
+
+void mhu_secure_init(void);
+
+#endif /* BRCM_MHU_H */
diff --git a/plat/brcm/common/brcm_scpi.c b/plat/brcm/common/brcm_scpi.c
new file mode 100644
index 0000000..0a703cb
--- /dev/null
+++ b/plat/brcm/common/brcm_scpi.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <brcm_mhu.h>
+#include <brcm_scpi.h>
+#include <platform_def.h>
+
+#define SCPI_SHARED_MEM_SCP_TO_AP (PLAT_SCP_COM_SHARED_MEM_BASE)
+#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SCP_COM_SHARED_MEM_BASE \
+ + 0x100)
+
+/* Header and payload addresses for commands from AP to SCP */
+#define SCPI_CMD_HEADER_AP_TO_SCP \
+ ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
+#define SCPI_CMD_PAYLOAD_AP_TO_SCP \
+ ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
+
+/* Header and payload addresses for responses from SCP to AP */
+#define SCPI_RES_HEADER_SCP_TO_AP \
+ ((scpi_cmd_t *) SCPI_SHARED_MEM_SCP_TO_AP)
+#define SCPI_RES_PAYLOAD_SCP_TO_AP \
+ ((void *) (SCPI_SHARED_MEM_SCP_TO_AP + sizeof(scpi_cmd_t)))
+
+/* ID of the MHU slot used for the SCPI protocol */
+#define SCPI_MHU_SLOT_ID 0
+
+static void scpi_secure_message_start(void)
+{
+ mhu_secure_message_start(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_send(size_t payload_size)
+{
+ /*
+ * Ensure that any write to the SCPI payload area is seen by SCP before
+ * we write to the MHU register. If these 2 writes were reordered by
+ * the CPU then SCP would read stale payload data
+ */
+ dmbst();
+
+ mhu_secure_message_send(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_receive(scpi_cmd_t *cmd)
+{
+ uint32_t mhu_status;
+
+ assert(cmd != NULL);
+
+ mhu_status = mhu_secure_message_wait();
+
+ /* Expect an SCPI message, reject any other protocol */
+ if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
+ ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
+ mhu_status);
+ panic();
+ }
+
+ /*
+ * Ensure that any read to the SCPI payload area is done after reading
+ * the MHU register. If these 2 reads were reordered then the CPU would
+ * read invalid payload data
+ */
+ dmbld();
+
+ memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
+}
+
+static void scpi_secure_message_end(void)
+{
+ mhu_secure_message_end(SCPI_MHU_SLOT_ID);
+}
+
+int scpi_wait_ready(void)
+{
+ scpi_cmd_t scpi_cmd;
+
+ VERBOSE("Waiting for SCP_READY command...\n");
+
+ /* Get a message from the SCP */
+ scpi_secure_message_start();
+ scpi_secure_message_receive(&scpi_cmd);
+ scpi_secure_message_end();
+
+ /* We are expecting 'SCP Ready', produce correct error if it's not */
+ scpi_status_t status = SCP_OK;
+
+ if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
+ ERROR("Unexpected SCP command: expected #%u, received #%u\n",
+ SCPI_CMD_SCP_READY, scpi_cmd.id);
+ status = SCP_E_SUPPORT;
+ } else if (scpi_cmd.size != 0) {
+ ERROR("SCP_READY cmd has incorrect size: expected 0, got %u\n",
+ scpi_cmd.size);
+ status = SCP_E_SIZE;
+ }
+
+ VERBOSE("Sending response for SCP_READY command\n");
+
+ /*
+ * Send our response back to SCP.
+ * We are using the same SCPI header, just update the status field.
+ */
+ scpi_cmd.status = status;
+ scpi_secure_message_start();
+ memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd));
+ scpi_secure_message_send(0);
+ scpi_secure_message_end();
+
+ return status == SCP_OK ? 0 : -1;
+}
+
+void scpi_set_brcm_power_state(unsigned int mpidr,
+ scpi_power_state_t cpu_state, scpi_power_state_t cluster_state,
+ scpi_power_state_t brcm_state)
+{
+ scpi_cmd_t *cmd;
+ uint32_t state = 0;
+ uint32_t *payload_addr;
+
+#if ARM_PLAT_MT
+ /*
+ * The current SCPI driver only caters for single-threaded platforms.
+ * Hence we ignore the thread ID (which is always 0) for such platforms.
+ */
+ state |= (mpidr >> MPIDR_AFF1_SHIFT) & 0x0f; /* CPU ID */
+ state |= ((mpidr >> MPIDR_AFF2_SHIFT) & 0x0f) << 4; /* Cluster ID */
+#else
+ state |= mpidr & 0x0f; /* CPU ID */
+ state |= (mpidr & 0xf00) >> 4; /* Cluster ID */
+#endif /* ARM_PLAT_MT */
+
+ state |= cpu_state << 8;
+ state |= cluster_state << 12;
+ state |= brcm_state << 16;
+
+ scpi_secure_message_start();
+
+ /* Populate the command header */
+ cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+ cmd->id = SCPI_CMD_SET_POWER_STATE;
+ cmd->set = SCPI_SET_NORMAL;
+ cmd->sender = 0;
+ cmd->size = sizeof(state);
+ /* Populate the command payload */
+ payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+ *payload_addr = state;
+ scpi_secure_message_send(sizeof(state));
+
+ /*
+ * SCP does not reply to this command in order to avoid MHU interrupts
+ * from the sender, which could interfere with its power state request.
+ */
+ scpi_secure_message_end();
+}
+
+/*
+ * Query and obtain power state from SCP.
+ *
+ * In response to the query, SCP returns power states of all CPUs in all
+ * clusters of the system. The returned response is then filtered based on the
+ * supplied MPIDR. Power states of requested cluster and CPUs within are updated
+ * via. supplied non-NULL pointer arguments.
+ *
+ * Returns 0 on success, or -1 on errors.
+ */
+int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
+ unsigned int *cluster_state_p)
+{
+ scpi_cmd_t *cmd;
+ scpi_cmd_t response;
+ int power_state, cpu, cluster, rc = -1;
+
+ /*
+ * Extract CPU and cluster membership of the given MPIDR. SCPI caters
+ * for only up to 0xf clusters, and 8 CPUs per cluster
+ */
+ cpu = mpidr & MPIDR_AFFLVL_MASK;
+ cluster = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ if (cpu >= 8 || cluster >= 0xf)
+ return -1;
+
+ scpi_secure_message_start();
+
+ /* Populate request headers */
+ zeromem(SCPI_CMD_HEADER_AP_TO_SCP, sizeof(*cmd));
+ cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+ cmd->id = SCPI_CMD_GET_POWER_STATE;
+
+ /*
+ * Send message and wait for SCP's response
+ */
+ scpi_secure_message_send(0);
+ scpi_secure_message_receive(&response);
+
+ if (response.status != SCP_OK)
+ goto exit;
+
+ /* Validate SCP response */
+ if (!CHECK_RESPONSE(response, cluster))
+ goto exit;
+
+ /* Extract power states for required cluster */
+ power_state = *(((uint16_t *) SCPI_RES_PAYLOAD_SCP_TO_AP) + cluster);
+ if (CLUSTER_ID(power_state) != cluster)
+ goto exit;
+
+ /* Update power state via. pointers */
+ if (cluster_state_p)
+ *cluster_state_p = CLUSTER_POWER_STATE(power_state);
+ if (cpu_state_p)
+ *cpu_state_p = CPU_POWER_STATE(power_state);
+ rc = 0;
+
+exit:
+ scpi_secure_message_end();
+ return rc;
+}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+ scpi_cmd_t *cmd;
+ uint8_t *payload_addr;
+
+ scpi_secure_message_start();
+
+ /* Populate the command header */
+ cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+ cmd->id = SCPI_CMD_SYS_POWER_STATE;
+ cmd->set = 0;
+ cmd->sender = 0;
+ cmd->size = sizeof(*payload_addr);
+ /* Populate the command payload */
+ payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+ *payload_addr = system_state & 0xff;
+ scpi_secure_message_send(sizeof(*payload_addr));
+
+ scpi_secure_message_end();
+
+ return SCP_OK;
+}
diff --git a/plat/brcm/common/brcm_scpi.h b/plat/brcm/common/brcm_scpi.h
new file mode 100644
index 0000000..f3b658f
--- /dev/null
+++ b/plat/brcm/common/brcm_scpi.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BRCM_SCPI_H
+#define BRCM_SCPI_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * An SCPI command consists of a header and a payload.
+ * The following structure describes the header. It is 64-bit long.
+ */
+typedef struct {
+ /* Command ID */
+ uint32_t id : 7;
+ /* Set ID. Identifies whether this is a standard or extended command. */
+ uint32_t set : 1;
+ /* Sender ID to match a reply. The value is sender specific. */
+ uint32_t sender : 8;
+ /* Size of the payload in bytes (0 - 511) */
+ uint32_t size : 9;
+ uint32_t reserved : 7;
+ /*
+ * Status indicating the success of a command.
+ * See the enum below.
+ */
+ uint32_t status;
+} scpi_cmd_t;
+
+typedef enum {
+ SCPI_SET_NORMAL = 0, /* Normal SCPI commands */
+ SCPI_SET_EXTENDED /* Extended SCPI commands */
+} scpi_set_t;
+
+enum {
+ SCP_OK = 0, /* Success */
+ SCP_E_PARAM, /* Invalid parameter(s) */
+ SCP_E_ALIGN, /* Invalid alignment */
+ SCP_E_SIZE, /* Invalid size */
+ SCP_E_HANDLER, /* Invalid handler or callback */
+ SCP_E_ACCESS, /* Invalid access or permission denied */
+ SCP_E_RANGE, /* Value out of range */
+ SCP_E_TIMEOUT, /* Time out has ocurred */
+ SCP_E_NOMEM, /* Invalid memory area or pointer */
+ SCP_E_PWRSTATE, /* Invalid power state */
+ SCP_E_SUPPORT, /* Feature not supported or disabled */
+ SCPI_E_DEVICE, /* Device error */
+ SCPI_E_BUSY, /* Device is busy */
+};
+
+typedef uint32_t scpi_status_t;
+typedef enum {
+ SCPI_CMD_SCP_READY = 0x01,
+ SCPI_CMD_SET_POWER_STATE = 0x03,
+ SCPI_CMD_GET_POWER_STATE = 0x04,
+ SCPI_CMD_SYS_POWER_STATE = 0x05
+} scpi_command_t;
+
+/*
+ * Macros to parse SCP response to GET_POWER_STATE command
+ *
+ * [3:0] : cluster ID
+ * [7:4] : cluster state: 0 = on; 3 = off; rest are reserved
+ * [15:8]: on/off state for individual CPUs in the cluster
+ *
+ * Payload is in little-endian
+ */
+#define CLUSTER_ID(_resp) ((_resp) & 0xf)
+#define CLUSTER_POWER_STATE(_resp) (((_resp) >> 4) & 0xf)
+
+/* Result is a bit mask of CPU on/off states in the cluster */
+#define CPU_POWER_STATE(_resp) (((_resp) >> 8) & 0xff)
+
+/*
+ * For GET_POWER_STATE, SCP returns the power states of every cluster. The
+ * size of response depends on the number of clusters in the system. The
+ * SCP-to-AP payload contains 2 bytes per cluster. Make sure the response is
+ * large enough to contain power states of a given cluster
+ */
+#define CHECK_RESPONSE(_resp, _clus) (_resp.size >= (((_clus) + 1) * 2))
+
+typedef enum {
+ scpi_power_on = 0,
+ scpi_power_retention = 1,
+ scpi_power_off = 3,
+} scpi_power_state_t;
+
+typedef enum {
+ scpi_system_shutdown = 0,
+ scpi_system_reboot = 1,
+ scpi_system_reset = 2
+} scpi_system_state_t;
+
+extern int scpi_wait_ready(void);
+extern void scpi_set_brcm_power_state(unsigned int mpidr,
+ scpi_power_state_t cpu_state,
+ scpi_power_state_t cluster_state,
+ scpi_power_state_t css_state);
+int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
+ unsigned int *cluster_state_p);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+
+#endif /* BRCM_SCPI_H */
diff --git a/plat/common/aarch32/crash_console_helpers.S b/plat/common/aarch32/crash_console_helpers.S
new file mode 100644
index 0000000..ea04f56
--- /dev/null
+++ b/plat/common/aarch32/crash_console_helpers.S
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * If a platform wishes to use the functions in this file it has to be added to
+ * the Makefile of the platform. It is not included in the common Makefile.
+ */
+
+#include <asm_macros.S>
+#include <drivers/console.h>
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+
+ /* -----------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Use normal console by default. Switch it to crash
+ * mode so serial consoles become active again.
+ * NOTE: This default implementation will only work for
+ * crashes that occur after a normal console (marked
+ * valid for the crash state) has been registered with
+ * the console framework. To debug crashes that occur
+ * earlier, the platform has to override these functions
+ * with an implementation that initializes a console
+ * driver with hardcoded parameters. See
+ * docs/porting-guide.rst for more information.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_init
+#if defined(IMAGE_BL1)
+ /*
+ * BL1 code can possibly crash so early that the data segment is not yet
+ * accessible. Don't risk undefined behavior by trying to run the normal
+ * console framework. Platforms that want to debug BL1 will need to
+ * override this with custom functions that can run from registers only.
+ */
+ mov r0, #0
+ bx lr
+#else /* IMAGE_BL1 */
+ mov r3, lr
+ mov r0, #CONSOLE_FLAG_CRASH
+ bl console_switch_state
+ mov r0, #1
+ bx r3
+#endif
+endfunc plat_crash_console_init
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_putc(int character)
+ * Output through the normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_putc
+ b console_putc
+endfunc plat_crash_console_putc
+
+ /* -----------------------------------------------------
+ * void plat_crash_console_flush(void)
+ * Flush normal console by default.
+ * -----------------------------------------------------
+ */
+func plat_crash_console_flush
+ b console_flush
+endfunc plat_crash_console_flush
diff --git a/plat/common/aarch32/plat_common.c b/plat/common/aarch32/plat_common.c
new file mode 100644
index 0000000..2c1a8fa
--- /dev/null
+++ b/plat/common/aarch32/plat_common.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+
+/*
+ * The following platform setup functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak bl32_plat_enable_mmu
+
+
+void bl32_plat_enable_mmu(uint32_t flags)
+{
+ enable_mmu_svc_mon(flags);
+}
diff --git a/plat/common/aarch32/plat_sp_min_common.c b/plat/common/aarch32/plat_sp_min_common.c
new file mode 100644
index 0000000..9493587
--- /dev/null
+++ b/plat/common/aarch32/plat_sp_min_common.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/console.h>
+#include <plat/common/platform.h>
+#include <platform_sp_min.h>
+
+/*
+ * The following platform setup functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak sp_min_plat_runtime_setup
+
+void sp_min_plat_runtime_setup(void)
+{
+ /*
+ * Finish the use of console driver in SP_MIN so that any runtime logs
+ * from SP_MIN will be suppressed.
+ */
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S
new file mode 100644
index 0000000..75cc456
--- /dev/null
+++ b/plat/common/aarch32/platform_helpers.S
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+ .weak plat_report_exception
+ .weak plat_report_prefetch_abort
+ .weak plat_report_data_abort
+ .weak plat_reset_handler
+ .weak plat_disable_acp
+ .weak bl1_plat_prepare_exit
+ .weak platform_mem_init
+ .weak plat_panic_handler
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_report_exception
+ bx lr
+endfunc plat_report_exception
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_report_prefetch_abort
+ bx lr
+endfunc plat_report_prefetch_abort
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_report_data_abort
+ bx lr
+endfunc plat_report_data_abort
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ bx lr
+endfunc plat_reset_handler
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_disable_acp
+ bx lr
+endfunc plat_disable_acp
+
+ /* ---------------------------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ bx lr
+endfunc platform_mem_init
+
+ /* -----------------------------------------------------
+ * void bl1_plat_prepare_exit(entry_point_info_t *ep_info);
+ * Called before exiting BL1. Default: do nothing
+ * -----------------------------------------------------
+ */
+func bl1_plat_prepare_exit
+ bx lr
+endfunc bl1_plat_prepare_exit
+
+ /* -----------------------------------------------------
+ * void plat_panic_handler(void) __dead2;
+ * Endless loop by default.
+ * -----------------------------------------------------
+ */
+func plat_panic_handler
+ b plat_panic_handler
+endfunc plat_panic_handler
diff --git a/plat/common/aarch32/platform_mp_stack.S b/plat/common/aarch32/platform_mp_stack.S
new file mode 100644
index 0000000..6c3d08d
--- /dev/null
+++ b/plat/common/aarch32/platform_mp_stack.S
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .weak plat_get_my_stack
+ .weak plat_set_my_stack
+
+ /* -----------------------------------------------------
+ * uintptr_t plat_get_my_stack (u_register_t mpidr)
+ *
+ * For a given CPU, this function returns the stack
+ * pointer for a stack allocated in device memory.
+ * -----------------------------------------------------
+ */
+func plat_get_my_stack
+ push {r4, lr}
+ get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+ pop {r4, pc}
+endfunc plat_get_my_stack
+
+ /* -----------------------------------------------------
+ * void plat_set_my_stack ()
+ *
+ * For the current CPU, this function sets the stack
+ * pointer to a stack allocated in normal memory.
+ * -----------------------------------------------------
+ */
+func plat_set_my_stack
+ mov r4, lr
+ get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+ mov sp, r0
+ bx r4
+endfunc plat_set_my_stack
+
+ /* -----------------------------------------------------
+ * Per-cpu stacks in normal memory. Each cpu gets a
+ * stack of PLATFORM_STACK_SIZE bytes.
+ * -----------------------------------------------------
+ */
+declare_stack platform_normal_stacks, tzfw_normal_stacks, \
+ PLATFORM_STACK_SIZE, PLATFORM_CORE_COUNT
diff --git a/plat/common/aarch32/platform_up_stack.S b/plat/common/aarch32/platform_up_stack.S
new file mode 100644
index 0000000..836c13a
--- /dev/null
+++ b/plat/common/aarch32/platform_up_stack.S
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .weak plat_get_my_stack
+ .weak plat_set_my_stack
+
+ /* -----------------------------------------------------
+ * unsigned long plat_get_my_stack ()
+ *
+ * For cold-boot BL images, only the primary CPU needs
+ * a stack. This function returns the stack pointer for
+ * a stack allocated in normal memory.
+ * -----------------------------------------------------
+ */
+func plat_get_my_stack
+ get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+ bx lr
+endfunc plat_get_my_stack
+
+ /* -----------------------------------------------------
+ * void plat_set_my_stack ()
+ *
+ * For cold-boot BL images, only the primary CPU needs
+ * a stack. This function sets the stack pointer to a
+ * stack allocated in normal memory.
+ * -----------------------------------------------------
+ */
+func plat_set_my_stack
+ get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+ mov sp, r0
+ bx lr
+endfunc plat_set_my_stack
+
+ /* -----------------------------------------------------
+ * Per-cpu stacks in normal memory. Each cpu gets a
+ * stack of PLATFORM_STACK_SIZE bytes.
+ * -----------------------------------------------------
+ */
+declare_stack platform_normal_stacks, tzfw_normal_stacks, \
+ PLATFORM_STACK_SIZE, 1, CACHE_WRITEBACK_GRANULE
diff --git a/plat/common/aarch64/crash_console_helpers.S b/plat/common/aarch64/crash_console_helpers.S
new file mode 100644
index 0000000..e2950f5
--- /dev/null
+++ b/plat/common/aarch64/crash_console_helpers.S
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * If a platform wishes to use the functions in this file it has to be added to
+ * the Makefile of the platform. It is not included in the common Makefile.
+ */
+
+#include <asm_macros.S>
+#include <drivers/console.h>
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+
+ /*
+ * Spinlock to syncronize access to crash_console_triggered. We cannot
+ * acquire spinlocks when the cache is disabled, so in some cases (like
+ * late during CPU suspend) some risk remains.
+ */
+.section .data.crash_console_spinlock
+ define_asm_spinlock crash_console_spinlock
+
+ /*
+ * Flag to make sure that only one CPU can write a crash dump even if
+ * multiple crash at the same time. Interleaving crash dumps on the same
+ * console would just make the output unreadable, so it's better to only
+ * get a single but uncorrupted dump. This also means that we don't have
+ * to duplicate the reg_stash below for each CPU.
+ */
+.section .data.crash_console_triggered
+ crash_console_triggered: .byte 0
+
+ /*
+ * Space to stash away some register values while we're calling into
+ * console drivers and don't have a real stack available. We need x14,
+ * x15 and x30 for bookkeeping within the plat_crash_console functions
+ * themselves, and some console drivers use x16 and x17 as additional
+ * scratch space that is not preserved by the main crash reporting
+ * framework. (Note that x16 and x17 should really never be expected to
+ * retain their values across any function call, even between carefully
+ * designed assembly functions, since the linker is always free to
+ * insert a function call veneer that uses these registers as scratch
+ * space at any time. The current crash reporting framework doesn't
+ * really respect that, but since TF is usually linked as a single
+ * contiguous binary of less than 128MB, it seems to work in practice.)
+ */
+.section .data.crash_console_reg_stash
+ .align 3
+ crash_console_reg_stash: .quad 0, 0, 0, 0, 0
+
+ /* --------------------------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Takes the crash console spinlock (if possible) and checks the trigger
+ * flag to make sure we're the first CPU to dump. If not, return an
+ * error (so crash dumping will fail but the CPU will still call
+ * plat_panic_handler() which may do important platform-specific tasks
+ * that may be needed on all crashing CPUs). In either case, the lock
+ * will be released so other CPUs can make forward progress on this.
+ * Clobbers: x0 - x4, x30
+ * --------------------------------------------------------------------
+ */
+func plat_crash_console_init
+#if defined(IMAGE_BL31)
+ mov x4, x30 /* x3 and x4 are not clobbered by spin_lock() */
+ mov x3, #0 /* return value */
+
+ mrs x1, sctlr_el3
+ tst x1, #SCTLR_C_BIT
+ beq skip_spinlock /* can't synchronize when cache disabled */
+
+ adrp x0, crash_console_spinlock
+ add x0, x0, :lo12:crash_console_spinlock
+ bl spin_lock
+
+skip_spinlock:
+ adrp x1, crash_console_triggered
+ add x1, x1, :lo12:crash_console_triggered
+ ldarb w2, [x1]
+ cmp w2, #0
+ bne init_error
+
+ mov x3, #1 /* set return value to success */
+ stlrb w3, [x1]
+
+init_error:
+ bl spin_unlock /* harmless if we didn't acquire the lock */
+ mov x0, x3
+ ret x4
+#else /* Only one CPU in BL1/BL2, no need to synchronize anything */
+ mov x0, #1
+ ret
+#endif
+endfunc plat_crash_console_init
+
+ /* --------------------------------------------------------------------
+ * int plat_crash_console_putc(char c)
+ * Prints the character on all consoles registered with the console
+ * framework that have CONSOLE_FLAG_CRASH set. Note that this is only
+ * helpful for crashes that occur after the platform intialization code
+ * has registered a console. Platforms using this implementation need to
+ * ensure that all console drivers they use that have the CRASH flag set
+ * support this (i.e. are written in assembly and comply to the register
+ * clobber requirements of plat_crash_console_putc().
+ * --------------------------------------------------------------------
+ */
+func plat_crash_console_putc
+ adrp x1, crash_console_reg_stash
+ add x1, x1, :lo12:crash_console_reg_stash
+ stp x14, x15, [x1]
+ stp x16, x17, [x1, #16]
+ str x30, [x1, #32]
+
+ mov w14, w0 /* W14 = character to print */
+ adrp x15, console_list
+ ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */
+
+putc_loop:
+ cbz x15, putc_done
+ ldr w1, [x15, #CONSOLE_T_FLAGS]
+ tst w1, #CONSOLE_FLAG_CRASH
+ b.eq putc_continue
+ ldr x2, [x15, #CONSOLE_T_PUTC]
+ cbz x2, putc_continue
+ cmp w14, #'\n'
+ b.ne putc
+ tst w1, #CONSOLE_FLAG_TRANSLATE_CRLF
+ b.eq putc
+ mov x1, x15
+ mov w0, #'\r'
+ blr x2
+ ldr x2, [x15, #CONSOLE_T_PUTC]
+putc:
+ mov x1, x15
+ mov w0, w14
+ blr x2
+putc_continue:
+ ldr x15, [x15] /* X15 = next struct */
+ b putc_loop
+
+putc_done:
+ adrp x1, crash_console_reg_stash
+ add x1, x1, :lo12:crash_console_reg_stash
+ ldp x14, x15, [x1]
+ ldp x16, x17, [x1, #16]
+ ldr x30, [x1, #32]
+ ret
+endfunc plat_crash_console_putc
+
+ /* --------------------------------------------------------------------
+ * int plat_crash_console_flush(char c)
+ * Flushes all consoles registered with the console framework that have
+ * CONSOLE_FLAG_CRASH set. Same requirements as putc().
+ * --------------------------------------------------------------------
+ */
+func plat_crash_console_flush
+ adrp x1, crash_console_reg_stash
+ add x1, x1, :lo12:crash_console_reg_stash
+ stp x30, x15, [x1]
+ stp x16, x17, [x1, #16]
+
+ adrp x15, console_list
+ ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */
+
+flush_loop:
+ cbz x15, flush_done
+ ldr w1, [x15, #CONSOLE_T_FLAGS]
+ tst w1, #CONSOLE_FLAG_CRASH
+ b.eq flush_continue
+ ldr x2, [x15, #CONSOLE_T_FLUSH]
+ cbz x2, flush_continue
+ mov x0, x15
+ blr x2
+flush_continue:
+ ldr x15, [x15] /* X15 = next struct */
+ b flush_loop
+
+flush_done:
+ adrp x1, crash_console_reg_stash
+ add x1, x1, :lo12:crash_console_reg_stash
+ ldp x30, x15, [x1]
+ ldp x16, x17, [x1, #16]
+ ret
+endfunc plat_crash_console_flush
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
new file mode 100644
index 0000000..8ce1d6c
--- /dev/null
+++ b/plat/common/aarch64/plat_common.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#if RAS_EXTENSION
+#include <lib/extensions/ras.h>
+#endif
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+
+/*
+ * The following platform setup functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak bl31_plat_runtime_setup
+
+#if SDEI_SUPPORT
+#pragma weak plat_sdei_handle_masked_trigger
+#pragma weak plat_sdei_validate_entry_point
+#endif
+
+#pragma weak plat_ea_handler = plat_default_ea_handler
+
+void bl31_plat_runtime_setup(void)
+{
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
+
+/*
+ * Helper function for platform_get_pos() when platform compatibility is
+ * disabled. This is to enable SPDs using the older platform API to continue
+ * to work.
+ */
+unsigned int platform_core_pos_helper(unsigned long mpidr)
+{
+ int idx = plat_core_pos_by_mpidr(mpidr);
+ assert(idx >= 0);
+ return idx;
+}
+
+#if SDEI_SUPPORT
+/*
+ * Function that handles spurious SDEI interrupts while events are masked.
+ */
+void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr)
+{
+ WARN("Spurious SDEI interrupt %u on masked PE %" PRIx64 "\n", intr, mpidr);
+}
+
+/*
+ * Default Function to validate SDEI entry point, which returns success.
+ * Platforms may override this with their own validation mechanism.
+ */
+int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode)
+{
+ return 0;
+}
+#endif
+
+const char *get_el_str(unsigned int el)
+{
+ if (el == MODE_EL3) {
+ return "EL3";
+ } else if (el == MODE_EL2) {
+ return "EL2";
+ }
+ return "EL1";
+}
+
+/* RAS functions common to AArch64 ARM platforms */
+void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags)
+{
+#if RAS_EXTENSION
+ /* Call RAS EA handler */
+ int handled = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+ if (handled != 0)
+ return;
+#endif
+ unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
+
+ ERROR_NL();
+ ERROR("Unhandled External Abort received on 0x%lx from %s\n",
+ read_mpidr_el1(), get_el_str(level));
+ ERROR("exception reason=%u syndrome=0x%" PRIx64 "\n", ea_reason, syndrome);
+#if HANDLE_EA_EL3_FIRST_NS
+ /* Skip backtrace for lower EL */
+ if (level != MODE_EL3) {
+ console_flush();
+ do_panic();
+ }
+#endif
+ panic();
+}
diff --git a/plat/common/aarch64/plat_ehf.c b/plat/common/aarch64/plat_ehf.c
new file mode 100644
index 0000000..da76884
--- /dev/null
+++ b/plat/common/aarch64/plat_ehf.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Broadcom
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl31/ehf.h>
+
+#include <platform_def.h>
+
+/*
+ * Enumeration of priority levels on ARM platforms.
+ */
+ehf_pri_desc_t plat_exceptions[] = {
+#if RAS_EXTENSION
+ /* RAS Priority */
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_RAS_PRI),
+#endif
+
+#if SDEI_SUPPORT
+ /* Critical priority SDEI */
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_CRITICAL_PRI),
+
+ /* Normal priority SDEI */
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI),
+#endif
+#if SPM_MM
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
+#endif
+ /* Plaform specific exceptions description */
+#ifdef PLAT_EHF_DESC
+ PLAT_EHF_DESC,
+#endif
+};
+
+/* Plug in ARM exceptions to Exception Handling Framework. */
+EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), PLAT_PRI_BITS);
diff --git a/plat/common/aarch64/platform_helpers.S b/plat/common/aarch64/platform_helpers.S
new file mode 100644
index 0000000..bc650c9
--- /dev/null
+++ b/plat/common/aarch64/platform_helpers.S
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/console.h>
+#include <platform_def.h>
+
+ .weak plat_report_exception
+ .weak plat_reset_handler
+ .weak plat_disable_acp
+ .weak bl1_plat_prepare_exit
+ .weak plat_panic_handler
+ .weak bl31_plat_enable_mmu
+ .weak bl32_plat_enable_mmu
+
+ .weak plat_handle_uncontainable_ea
+ .weak plat_handle_double_fault
+ .weak plat_handle_el3_ea
+
+#define MPIDR_RES_BIT_MASK 0xff000000
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform.
+ * -----------------------------------------------------
+ */
+func plat_report_exception
+ ret
+endfunc plat_report_exception
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform. This function should preserve x19 - x29.
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ ret
+endfunc plat_reset_handler
+
+ /* -----------------------------------------------------
+ * Placeholder function which should be redefined by
+ * each platform. This function is allowed to use
+ * registers x0 - x17.
+ * -----------------------------------------------------
+ */
+func plat_disable_acp
+ ret
+endfunc plat_disable_acp
+
+ /* -----------------------------------------------------
+ * void bl1_plat_prepare_exit(entry_point_info_t *ep_info);
+ * Called before exiting BL1. Default: do nothing
+ * -----------------------------------------------------
+ */
+func bl1_plat_prepare_exit
+ ret
+endfunc bl1_plat_prepare_exit
+
+ /* -----------------------------------------------------
+ * void plat_panic_handler(void) __dead2;
+ * Endless loop by default.
+ * -----------------------------------------------------
+ */
+func plat_panic_handler
+ wfi
+ b plat_panic_handler
+endfunc plat_panic_handler
+
+ /* -----------------------------------------------------
+ * void bl31_plat_enable_mmu(uint32_t flags);
+ *
+ * Enable MMU in BL31.
+ * -----------------------------------------------------
+ */
+func bl31_plat_enable_mmu
+ b enable_mmu_direct_el3
+endfunc bl31_plat_enable_mmu
+
+ /* -----------------------------------------------------
+ * void bl32_plat_enable_mmu(uint32_t flags);
+ *
+ * Enable MMU in BL32.
+ * -----------------------------------------------------
+ */
+func bl32_plat_enable_mmu
+ b enable_mmu_direct_el1
+endfunc bl32_plat_enable_mmu
+
+
+ /* -----------------------------------------------------
+ * Platform handler for Uncontainable External Abort.
+ *
+ * x0: EA reason
+ * x1: EA syndrome
+ * -----------------------------------------------------
+ */
+func plat_handle_uncontainable_ea
+ b report_unhandled_exception
+endfunc plat_handle_uncontainable_ea
+
+ /* -----------------------------------------------------
+ * Platform handler for Double Fault.
+ *
+ * x0: EA reason
+ * x1: EA syndrome
+ * -----------------------------------------------------
+ */
+func plat_handle_double_fault
+ b report_unhandled_exception
+endfunc plat_handle_double_fault
+
+ /* -----------------------------------------------------
+ * Platform handler for EL3 External Abort.
+ * -----------------------------------------------------
+ */
+func plat_handle_el3_ea
+ b report_unhandled_exception
+endfunc plat_handle_el3_ea
diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S
new file mode 100644
index 0000000..c0668ea
--- /dev/null
+++ b/plat/common/aarch64/platform_mp_stack.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014-2020, 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 <platform_def.h>
+
+ .local platform_normal_stacks
+ .weak plat_get_my_stack
+ .weak plat_set_my_stack
+
+ /* ---------------------------------------------------------------------
+ * When the compatibility layer is disabled, the platform APIs
+ * plat_get_my_stack() and plat_set_my_stack() are supported by the
+ * platform and the previous APIs platform_get_stack() and
+ * platform_set_stack() are defined in terms of new APIs making use of
+ * the fact that they are only ever invoked for the current CPU. This
+ * is to enable components of Trusted Firmware like SPDs using the old
+ * platform APIs to continue to work.
+ * --------------------------------------------------------------------
+ */
+
+ /* -----------------------------------------------------
+ * uintptr_t plat_get_my_stack ()
+ *
+ * For the current CPU, this function returns the stack
+ * pointer for a stack allocated in device memory.
+ * -----------------------------------------------------
+ */
+func plat_get_my_stack
+ mov x10, x30
+ get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+ ret x10
+endfunc plat_get_my_stack
+
+ /* -----------------------------------------------------
+ * void plat_set_my_stack ()
+ *
+ * For the current CPU, this function sets the stack
+ * pointer to a stack allocated in normal memory.
+ * -----------------------------------------------------
+ */
+func plat_set_my_stack
+ mov x9, x30
+ bl plat_get_my_stack
+ mov sp, x0
+ ret x9
+endfunc plat_set_my_stack
+
+ /* -----------------------------------------------------
+ * Per-CPU stacks in normal memory. Each CPU gets a
+ * stack of PLATFORM_STACK_SIZE bytes.
+ * -----------------------------------------------------
+ */
+declare_stack platform_normal_stacks, tzfw_normal_stacks, \
+ PLATFORM_STACK_SIZE, PLATFORM_CORE_COUNT, \
+ CACHE_WRITEBACK_GRANULE
diff --git a/plat/common/aarch64/platform_up_stack.S b/plat/common/aarch64/platform_up_stack.S
new file mode 100644
index 0000000..c6e5e2d
--- /dev/null
+++ b/plat/common/aarch64/platform_up_stack.S
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+
+ .local platform_normal_stacks
+ .weak plat_set_my_stack
+ .weak plat_get_my_stack
+
+ /* -----------------------------------------------------
+ * uintptr_t plat_get_my_stack ()
+ *
+ * For cold-boot BL images, only the primary CPU needs a
+ * stack. This function returns the stack pointer for a
+ * stack allocated in device memory.
+ * -----------------------------------------------------
+ */
+func plat_get_my_stack
+ get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+ ret
+endfunc plat_get_my_stack
+
+ /* -----------------------------------------------------
+ * void plat_set_my_stack ()
+ *
+ * For cold-boot BL images, only the primary CPU needs a
+ * stack. This function sets the stack pointer to a stack
+ * allocated in normal memory.
+ * -----------------------------------------------------
+ */
+func plat_set_my_stack
+ get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE
+ mov sp, x0
+ ret
+endfunc plat_set_my_stack
+
+ /* -----------------------------------------------------
+ * Single cpu stack in normal memory.
+ * Used for C code during boot, PLATFORM_STACK_SIZE bytes
+ * are allocated
+ * -----------------------------------------------------
+ */
+declare_stack platform_normal_stacks, tzfw_normal_stacks, \
+ PLATFORM_STACK_SIZE, 1, CACHE_WRITEBACK_GRANULE
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
new file mode 100644
index 0000000..bcf9f89
--- /dev/null
+++ b/plat/common/plat_bl1_common.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+/*
+ * The following platform functions are weakly defined. They
+ * are default implementations that allow BL1 to compile in
+ * absence of real definitions. The Platforms may override
+ * with more complex definitions.
+ */
+#pragma weak bl1_plat_get_next_image_id
+#pragma weak bl1_plat_set_ep_info
+#pragma weak bl1_plat_get_image_desc
+#pragma weak bl1_plat_fwu_done
+#pragma weak bl1_plat_handle_pre_image_load
+#pragma weak bl1_plat_handle_post_image_load
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ /* BL2 load will be done by default. */
+ return BL2_IMAGE_ID;
+}
+
+void bl1_plat_set_ep_info(unsigned int image_id,
+ struct entry_point_info *ep_info)
+{
+
+}
+
+int bl1_plat_handle_pre_image_load(unsigned int image_id)
+{
+ return 0;
+}
+
+/*
+ * Following is the default definition that always
+ * returns BL2 image details.
+ */
+struct image_desc *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ static image_desc_t bl2_img_desc = BL2_IMAGE_DESC;
+ return &bl2_img_desc;
+}
+
+__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
+{
+ while (true)
+ wfi();
+}
+
+/*
+ * The Platforms must override with real definition.
+ */
+#pragma weak bl1_plat_mem_check
+
+int bl1_plat_mem_check(uintptr_t mem_base, unsigned int mem_size,
+ unsigned int flags)
+{
+ assert(0);
+ return -ENOMEM;
+}
+
+/*
+ * Default implementation for bl1_plat_handle_post_image_load(). This function
+ * populates the default arguments to BL2. The BL2 memory layout structure
+ * is allocated and the calculated layout is populated in arg1 to BL2.
+ */
+int bl1_plat_handle_post_image_load(unsigned int image_id)
+{
+ meminfo_t *bl2_secram_layout;
+ meminfo_t *bl1_secram_layout;
+ image_desc_t *image_desc;
+ entry_point_info_t *ep_info;
+
+ if (image_id != BL2_IMAGE_ID)
+ return 0;
+
+ /* Get the image descriptor */
+ image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+ assert(image_desc != NULL);
+
+ /* Get the entry point info */
+ ep_info = &image_desc->ep_info;
+
+ /* Find out how much free trusted ram remains after BL1 load */
+ bl1_secram_layout = bl1_plat_sec_mem_layout();
+
+ /*
+ * Create a new layout of memory for BL2 as seen by BL1 i.e.
+ * tell it the amount of total and free memory available.
+ * This layout is created at the first free address visible
+ * to BL2. BL2 will read the memory layout before using its
+ * memory for other purposes.
+ */
+ bl2_secram_layout = (meminfo_t *) bl1_secram_layout->total_base;
+
+ bl1_calc_bl2_mem_layout(bl1_secram_layout, bl2_secram_layout);
+
+ ep_info->args.arg1 = (uintptr_t)bl2_secram_layout;
+
+ VERBOSE("BL1: BL2 memory layout address = %p\n",
+ (void *) bl2_secram_layout);
+ return 0;
+}
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
new file mode 100644
index 0000000..89b77ba
--- /dev/null
+++ b/plat/common/plat_bl_common.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
+#include <smccc_helpers.h>
+#include <tools_share/firmware_encrypted.h>
+
+/*
+ * The following platform functions are weakly defined. The Platforms
+ * may redefine with strong definition.
+ */
+#pragma weak bl2_el3_plat_prepare_exit
+#pragma weak plat_error_handler
+#pragma weak bl2_plat_preload_setup
+#pragma weak bl2_plat_handle_pre_image_load
+#pragma weak bl2_plat_handle_post_image_load
+#pragma weak plat_try_next_boot_source
+#pragma weak plat_get_enc_key_info
+#pragma weak plat_is_smccc_feature_available
+#pragma weak plat_get_soc_version
+#pragma weak plat_get_soc_revision
+
+int32_t plat_get_soc_version(void)
+{
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
+int32_t plat_get_soc_revision(void)
+{
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
+int32_t plat_is_smccc_feature_available(u_register_t fid __unused)
+{
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
+void bl2_el3_plat_prepare_exit(void)
+{
+}
+
+void __dead2 plat_error_handler(int err)
+{
+ while (1)
+ wfi();
+}
+
+void bl2_plat_preload_setup(void)
+{
+}
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ return 0;
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return 0;
+}
+
+int plat_try_next_boot_source(void)
+{
+ return 0;
+}
+
+/*
+ * Weak implementation to provide dummy decryption key only for test purposes,
+ * platforms must override this API for any real world firmware encryption
+ * use-case.
+ */
+int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
+ size_t *key_len, unsigned int *flags,
+ const uint8_t *img_id, size_t img_id_len)
+{
+#define DUMMY_FIP_ENC_KEY { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
+ 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
+ 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \
+ 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }
+
+ const uint8_t dummy_key[] = DUMMY_FIP_ENC_KEY;
+
+ assert(*key_len >= sizeof(dummy_key));
+
+ *key_len = sizeof(dummy_key);
+ memcpy(key, dummy_key, *key_len);
+ *flags = 0;
+
+ return 0;
+}
+
+/*
+ * Set up the page tables for the generic and platform-specific memory regions.
+ * The size of the Trusted SRAM seen by the BL image must be specified as well
+ * as an array specifying the generic memory regions which can be;
+ * - Code section;
+ * - Read-only data section;
+ * - Init code section, if applicable
+ * - Coherent memory region, if applicable.
+ */
+
+void __init setup_page_tables(const mmap_region_t *bl_regions,
+ const mmap_region_t *plat_regions)
+{
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ const mmap_region_t *regions = bl_regions;
+
+ while (regions->size != 0U) {
+ VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n",
+ regions->base_va,
+ regions->base_va + regions->size,
+ regions->attr);
+ regions++;
+ }
+#endif
+ /*
+ * Map the Trusted SRAM with appropriate memory attributes.
+ * Subsequent mappings will adjust the attributes for specific regions.
+ */
+ mmap_add(bl_regions);
+
+ /* Now (re-)map the platform-specific memory regions */
+ mmap_add(plat_regions);
+
+ /* Create the page tables to reflect the above mappings */
+ init_xlat_tables();
+}
diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c
new file mode 100644
index 0000000..0f988dc
--- /dev/null
+++ b/plat/common/plat_gicv2.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <bl31/interrupt_mgmt.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <plat/common/platform.h>
+
+/*
+ * The following platform GIC functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak plat_ic_get_pending_interrupt_type
+#pragma weak plat_ic_acknowledge_interrupt
+#pragma weak plat_ic_get_interrupt_type
+#pragma weak plat_ic_end_of_interrupt
+#pragma weak plat_interrupt_type_to_line
+
+#pragma weak plat_ic_get_running_priority
+#pragma weak plat_ic_is_spi
+#pragma weak plat_ic_is_ppi
+#pragma weak plat_ic_is_sgi
+#pragma weak plat_ic_get_interrupt_active
+#pragma weak plat_ic_enable_interrupt
+#pragma weak plat_ic_disable_interrupt
+#pragma weak plat_ic_set_interrupt_priority
+#pragma weak plat_ic_set_interrupt_type
+#pragma weak plat_ic_raise_el3_sgi
+#pragma weak plat_ic_raise_ns_sgi
+#pragma weak plat_ic_raise_s_el1_sgi
+#pragma weak plat_ic_set_spi_routing
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller
+ */
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+ unsigned int id;
+
+ id = gicv2_get_pending_interrupt_id();
+ if (id == GIC_SPURIOUS_INTERRUPT)
+ return INTR_ID_UNAVAILABLE;
+
+ return id;
+}
+
+/*
+ * This function returns the type of the highest priority pending interrupt
+ * at the Interrupt controller. In the case of GICv2, the Highest Priority
+ * Pending interrupt register (`GICC_HPPIR`) is read to determine the id of
+ * the pending interrupt. The type of interrupt depends upon the id value
+ * as follows.
+ * 1. id < PENDING_G1_INTID (1022) is reported as a S-EL1 interrupt
+ * 2. id = PENDING_G1_INTID (1022) is reported as a Non-secure interrupt.
+ * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt
+ * type.
+ */
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+ unsigned int id;
+
+ id = gicv2_get_pending_interrupt_type();
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ if (id < PENDING_G1_INTID) {
+#if GICV2_G0_FOR_EL3
+ return INTR_TYPE_EL3;
+#else
+ return INTR_TYPE_S_EL1;
+#endif
+ }
+
+ if (id == GIC_SPURIOUS_INTERRUPT)
+ return INTR_TYPE_INVAL;
+
+ return INTR_TYPE_NS;
+}
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller and indicates to the Interrupt controller
+ * that the interrupt processing has started.
+ */
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+ return gicv2_acknowledge_interrupt();
+}
+
+/*
+ * This function returns the type of the interrupt `id`, depending on how
+ * the interrupt has been configured in the interrupt controller
+ */
+uint32_t plat_ic_get_interrupt_type(uint32_t id)
+{
+ unsigned int type;
+
+ type = gicv2_get_interrupt_group(id);
+
+ /* Assume that all secure interrupts are S-EL1 interrupts */
+ return (type == GICV2_INTR_GROUP1) ? INTR_TYPE_NS :
+#if GICV2_G0_FOR_EL3
+ INTR_TYPE_EL3;
+#else
+ INTR_TYPE_S_EL1;
+#endif
+}
+
+/*
+ * This functions is used to indicate to the interrupt controller that
+ * the processing of the interrupt corresponding to the `id` has
+ * finished.
+ */
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+ gicv2_end_of_interrupt(id);
+}
+
+/*
+ * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
+ * The interrupt controller knows which pin/line it uses to signal a type of
+ * interrupt. It lets the interrupt management framework determine
+ * for a type of interrupt and security state, which line should be used in the
+ * SCR_EL3 to control its routing to EL3. The interrupt line is represented
+ * as the bit position of the IRQ or FIQ bit in the SCR_EL3.
+ */
+uint32_t plat_interrupt_type_to_line(uint32_t type,
+ uint32_t security_state)
+{
+ assert((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_EL3) ||
+ (type == INTR_TYPE_NS));
+
+ assert(sec_state_is_valid(security_state));
+
+ /* Non-secure interrupts are signaled on the IRQ line always */
+ if (type == INTR_TYPE_NS)
+ return __builtin_ctz(SCR_IRQ_BIT);
+
+ /*
+ * Secure interrupts are signaled using the IRQ line if the FIQ is
+ * not enabled else they are signaled using the FIQ line.
+ */
+ return ((gicv2_is_fiq_enabled() != 0U) ? __builtin_ctz(SCR_FIQ_BIT) :
+ __builtin_ctz(SCR_IRQ_BIT));
+}
+
+unsigned int plat_ic_get_running_priority(void)
+{
+ return gicv2_get_running_priority();
+}
+
+int plat_ic_is_spi(unsigned int id)
+{
+ return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID);
+}
+
+int plat_ic_is_ppi(unsigned int id)
+{
+ return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID);
+}
+
+int plat_ic_is_sgi(unsigned int id)
+{
+ return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID);
+}
+
+unsigned int plat_ic_get_interrupt_active(unsigned int id)
+{
+ return gicv2_get_interrupt_active(id);
+}
+
+void plat_ic_enable_interrupt(unsigned int id)
+{
+ gicv2_enable_interrupt(id);
+}
+
+void plat_ic_disable_interrupt(unsigned int id)
+{
+ gicv2_disable_interrupt(id);
+}
+
+void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority)
+{
+ gicv2_set_interrupt_priority(id, priority);
+}
+
+int plat_ic_has_interrupt_type(unsigned int type)
+{
+ int has_interrupt_type = 0;
+
+ switch (type) {
+#if GICV2_G0_FOR_EL3
+ case INTR_TYPE_EL3:
+#else
+ case INTR_TYPE_S_EL1:
+#endif
+ case INTR_TYPE_NS:
+ has_interrupt_type = 1;
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return has_interrupt_type;
+}
+
+void plat_ic_set_interrupt_type(unsigned int id, unsigned int type)
+{
+ unsigned int gicv2_type = 0U;
+
+ /* Map canonical interrupt type to GICv2 type */
+ switch (type) {
+#if GICV2_G0_FOR_EL3
+ case INTR_TYPE_EL3:
+#else
+ case INTR_TYPE_S_EL1:
+#endif
+ gicv2_type = GICV2_INTR_GROUP0;
+ break;
+ case INTR_TYPE_NS:
+ gicv2_type = GICV2_INTR_GROUP1;
+ break;
+ default:
+ assert(0); /* Unreachable */
+ break;
+ }
+
+ gicv2_set_interrupt_type(id, gicv2_type);
+}
+
+void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target)
+{
+#if GICV2_G0_FOR_EL3
+ int id;
+
+ /* Target must be a valid MPIDR in the system */
+ id = plat_core_pos_by_mpidr(target);
+ assert(id >= 0);
+
+ /* Verify that this is a secure SGI */
+ assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_EL3);
+
+ gicv2_raise_sgi(sgi_num, false, id);
+#else
+ assert(false);
+#endif
+}
+
+void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target)
+{
+ int id;
+
+ /* Target must be a valid MPIDR in the system */
+ id = plat_core_pos_by_mpidr(target);
+ assert(id >= 0);
+
+ /* Verify that this is a non-secure SGI */
+ assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_NS);
+
+ gicv2_raise_sgi(sgi_num, true, id);
+}
+
+void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target)
+{
+#if GICV2_G0_FOR_EL3
+ assert(false);
+#else
+ int id;
+
+ /* Target must be a valid MPIDR in the system */
+ id = plat_core_pos_by_mpidr(target);
+ assert(id >= 0);
+
+ /* Verify that this is a secure EL1 SGI */
+ assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_S_EL1);
+
+ gicv2_raise_sgi(sgi_num, false, id);
+#endif
+}
+
+void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
+ u_register_t mpidr)
+{
+ int proc_num = 0;
+
+ switch (routing_mode) {
+ case INTR_ROUTING_MODE_PE:
+ proc_num = plat_core_pos_by_mpidr(mpidr);
+ assert(proc_num >= 0);
+ break;
+ case INTR_ROUTING_MODE_ANY:
+ /* Bit mask selecting all 8 CPUs as candidates */
+ proc_num = -1;
+ break;
+ default:
+ assert(0); /* Unreachable */
+ break;
+ }
+
+ gicv2_set_spi_routing(id, proc_num);
+}
+
+void plat_ic_set_interrupt_pending(unsigned int id)
+{
+ gicv2_set_interrupt_pending(id);
+}
+
+void plat_ic_clear_interrupt_pending(unsigned int id)
+{
+ gicv2_clear_interrupt_pending(id);
+}
+
+unsigned int plat_ic_set_priority_mask(unsigned int mask)
+{
+ return gicv2_set_pmr(mask);
+}
+
+unsigned int plat_ic_get_interrupt_id(unsigned int raw)
+{
+ unsigned int id = (raw & INT_ID_MASK);
+
+ if (id == GIC_SPURIOUS_INTERRUPT)
+ id = INTR_ID_UNAVAILABLE;
+
+ return id;
+}
diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c
new file mode 100644
index 0000000..e1420bb
--- /dev/null
+++ b/plat/common/plat_gicv3.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <bl31/interrupt_mgmt.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/cassert.h>
+#include <plat/common/platform.h>
+
+#ifdef IMAGE_BL31
+
+/*
+ * The following platform GIC functions are weakly defined. They
+ * provide typical implementations that may be re-used by multiple
+ * platforms but may also be overridden by a platform if required.
+ */
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak plat_ic_get_pending_interrupt_type
+#pragma weak plat_ic_acknowledge_interrupt
+#pragma weak plat_ic_get_interrupt_type
+#pragma weak plat_ic_end_of_interrupt
+#pragma weak plat_interrupt_type_to_line
+
+#pragma weak plat_ic_get_running_priority
+#pragma weak plat_ic_is_spi
+#pragma weak plat_ic_is_ppi
+#pragma weak plat_ic_is_sgi
+#pragma weak plat_ic_get_interrupt_active
+#pragma weak plat_ic_enable_interrupt
+#pragma weak plat_ic_disable_interrupt
+#pragma weak plat_ic_set_interrupt_priority
+#pragma weak plat_ic_set_interrupt_type
+#pragma weak plat_ic_raise_el3_sgi
+#pragma weak plat_ic_raise_ns_sgi
+#pragma weak plat_ic_raise_s_el1_sgi
+#pragma weak plat_ic_set_spi_routing
+#pragma weak plat_ic_set_interrupt_pending
+#pragma weak plat_ic_clear_interrupt_pending
+
+CASSERT((INTR_TYPE_S_EL1 == INTR_GROUP1S) &&
+ (INTR_TYPE_NS == INTR_GROUP1NS) &&
+ (INTR_TYPE_EL3 == INTR_GROUP0), assert_interrupt_type_mismatch);
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller
+ */
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+ unsigned int irqnr;
+
+ assert(IS_IN_EL3());
+ irqnr = gicv3_get_pending_interrupt_id();
+ return gicv3_is_intr_id_special_identifier(irqnr) ?
+ INTR_ID_UNAVAILABLE : irqnr;
+}
+
+/*
+ * This function returns the type of the highest priority pending interrupt
+ * at the Interrupt controller. In the case of GICv3, the Highest Priority
+ * Pending interrupt system register (`ICC_HPPIR0_EL1`) is read to determine
+ * the id of the pending interrupt. The type of interrupt depends upon the
+ * id value as follows.
+ * 1. id = PENDING_G1S_INTID (1020) is reported as a S-EL1 interrupt
+ * 2. id = PENDING_G1NS_INTID (1021) is reported as a Non-secure interrupt.
+ * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt
+ * type.
+ * 4. All other interrupt id's are reported as EL3 interrupt.
+ */
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+ unsigned int irqnr;
+ uint32_t type;
+
+ assert(IS_IN_EL3());
+ irqnr = gicv3_get_pending_interrupt_type();
+
+ switch (irqnr) {
+ case PENDING_G1S_INTID:
+ type = INTR_TYPE_S_EL1;
+ break;
+ case PENDING_G1NS_INTID:
+ type = INTR_TYPE_NS;
+ break;
+ case GIC_SPURIOUS_INTERRUPT:
+ type = INTR_TYPE_INVAL;
+ break;
+ default:
+ type = INTR_TYPE_EL3;
+ break;
+ }
+
+ return type;
+}
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller and indicates to the Interrupt controller
+ * that the interrupt processing has started.
+ */
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+ assert(IS_IN_EL3());
+ return gicv3_acknowledge_interrupt();
+}
+
+/*
+ * This function returns the type of the interrupt `id`, depending on how
+ * the interrupt has been configured in the interrupt controller
+ */
+uint32_t plat_ic_get_interrupt_type(uint32_t id)
+{
+ assert(IS_IN_EL3());
+ return gicv3_get_interrupt_type(id, plat_my_core_pos());
+}
+
+/*
+ * This functions is used to indicate to the interrupt controller that
+ * the processing of the interrupt corresponding to the `id` has
+ * finished.
+ */
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+ assert(IS_IN_EL3());
+ gicv3_end_of_interrupt(id);
+}
+
+/*
+ * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins.
+ * The interrupt controller knows which pin/line it uses to signal a type of
+ * interrupt. It lets the interrupt management framework determine for a type of
+ * interrupt and security state, which line should be used in the SCR_EL3 to
+ * control its routing to EL3. The interrupt line is represented as the bit
+ * position of the IRQ or FIQ bit in the SCR_EL3.
+ */
+uint32_t plat_interrupt_type_to_line(uint32_t type,
+ uint32_t security_state)
+{
+ assert((type == INTR_TYPE_S_EL1) ||
+ (type == INTR_TYPE_EL3) ||
+ (type == INTR_TYPE_NS));
+
+ assert(sec_state_is_valid(security_state));
+ assert(IS_IN_EL3());
+
+ switch (type) {
+ case INTR_TYPE_S_EL1:
+ /*
+ * The S-EL1 interrupts are signaled as IRQ in S-EL0/1 contexts
+ * and as FIQ in the NS-EL0/1/2 contexts
+ */
+ if (security_state == SECURE)
+ return __builtin_ctz(SCR_IRQ_BIT);
+ else
+ return __builtin_ctz(SCR_FIQ_BIT);
+ assert(0); /* Unreachable */
+ case INTR_TYPE_NS:
+ /*
+ * The Non secure interrupts will be signaled as FIQ in S-EL0/1
+ * contexts and as IRQ in the NS-EL0/1/2 contexts.
+ */
+ if (security_state == SECURE)
+ return __builtin_ctz(SCR_FIQ_BIT);
+ else
+ return __builtin_ctz(SCR_IRQ_BIT);
+ assert(0); /* Unreachable */
+ case INTR_TYPE_EL3:
+ /*
+ * The EL3 interrupts are signaled as FIQ in both S-EL0/1 and
+ * NS-EL0/1/2 contexts
+ */
+ return __builtin_ctz(SCR_FIQ_BIT);
+ default:
+ panic();
+ }
+}
+
+unsigned int plat_ic_get_running_priority(void)
+{
+ return gicv3_get_running_priority();
+}
+
+int plat_ic_is_spi(unsigned int id)
+{
+ return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID);
+}
+
+int plat_ic_is_ppi(unsigned int id)
+{
+ return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID);
+}
+
+int plat_ic_is_sgi(unsigned int id)
+{
+ return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID);
+}
+
+unsigned int plat_ic_get_interrupt_active(unsigned int id)
+{
+ return gicv3_get_interrupt_active(id, plat_my_core_pos());
+}
+
+void plat_ic_enable_interrupt(unsigned int id)
+{
+ gicv3_enable_interrupt(id, plat_my_core_pos());
+}
+
+void plat_ic_disable_interrupt(unsigned int id)
+{
+ gicv3_disable_interrupt(id, plat_my_core_pos());
+}
+
+void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority)
+{
+ gicv3_set_interrupt_priority(id, plat_my_core_pos(), priority);
+}
+
+int plat_ic_has_interrupt_type(unsigned int type)
+{
+ assert((type == INTR_TYPE_EL3) || (type == INTR_TYPE_S_EL1) ||
+ (type == INTR_TYPE_NS));
+ return 1;
+}
+
+void plat_ic_set_interrupt_type(unsigned int id, unsigned int type)
+{
+ gicv3_set_interrupt_type(id, plat_my_core_pos(), type);
+}
+
+void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target)
+{
+ /* Target must be a valid MPIDR in the system */
+ assert(plat_core_pos_by_mpidr(target) >= 0);
+
+ /* Verify that this is a secure EL3 SGI */
+ assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) ==
+ INTR_TYPE_EL3);
+
+ gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G0, target);
+}
+
+void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target)
+{
+ /* Target must be a valid MPIDR in the system */
+ assert(plat_core_pos_by_mpidr(target) >= 0);
+
+ /* Verify that this is a non-secure SGI */
+ assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) ==
+ INTR_TYPE_NS);
+
+ gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1NS, target);
+}
+
+void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target)
+{
+ /* Target must be a valid MPIDR in the system */
+ assert(plat_core_pos_by_mpidr(target) >= 0);
+
+ /* Verify that this is a secure EL1 SGI */
+ assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) ==
+ INTR_TYPE_S_EL1);
+
+ gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1S, target);
+}
+
+void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode,
+ u_register_t mpidr)
+{
+ unsigned int irm = 0;
+
+ switch (routing_mode) {
+ case INTR_ROUTING_MODE_PE:
+ assert(plat_core_pos_by_mpidr(mpidr) >= 0);
+ irm = GICV3_IRM_PE;
+ break;
+ case INTR_ROUTING_MODE_ANY:
+ irm = GICV3_IRM_ANY;
+ break;
+ default:
+ assert(0); /* Unreachable */
+ break;
+ }
+
+ gicv3_set_spi_routing(id, irm, mpidr);
+}
+
+void plat_ic_set_interrupt_pending(unsigned int id)
+{
+ /* Disallow setting SGIs pending */
+ assert(id >= MIN_PPI_ID);
+ gicv3_set_interrupt_pending(id, plat_my_core_pos());
+}
+
+void plat_ic_clear_interrupt_pending(unsigned int id)
+{
+ /* Disallow setting SGIs pending */
+ assert(id >= MIN_PPI_ID);
+ gicv3_clear_interrupt_pending(id, plat_my_core_pos());
+}
+
+unsigned int plat_ic_set_priority_mask(unsigned int mask)
+{
+ return gicv3_set_pmr(mask);
+}
+
+unsigned int plat_ic_get_interrupt_id(unsigned int raw)
+{
+ unsigned int id = raw & INT_ID_MASK;
+
+ return gicv3_is_intr_id_special_identifier(id) ?
+ INTR_ID_UNAVAILABLE : id;
+}
+#endif
+#ifdef IMAGE_BL32
+
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak plat_ic_acknowledge_interrupt
+#pragma weak plat_ic_end_of_interrupt
+
+/* In AArch32, the secure group1 interrupts are targeted to Secure PL1 */
+#ifndef __aarch64__
+#define IS_IN_EL1() IS_IN_SECURE()
+#endif
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller
+ */
+uint32_t plat_ic_get_pending_interrupt_id(void)
+{
+ unsigned int irqnr;
+
+ assert(IS_IN_EL1());
+ irqnr = gicv3_get_pending_interrupt_id_sel1();
+ return (irqnr == GIC_SPURIOUS_INTERRUPT) ?
+ INTR_ID_UNAVAILABLE : irqnr;
+}
+
+/*
+ * This function returns the highest priority pending interrupt at
+ * the Interrupt controller and indicates to the Interrupt controller
+ * that the interrupt processing has started.
+ */
+uint32_t plat_ic_acknowledge_interrupt(void)
+{
+ assert(IS_IN_EL1());
+ return gicv3_acknowledge_interrupt_sel1();
+}
+
+/*
+ * This functions is used to indicate to the interrupt controller that
+ * the processing of the interrupt corresponding to the `id` has
+ * finished.
+ */
+void plat_ic_end_of_interrupt(uint32_t id)
+{
+ assert(IS_IN_EL1());
+ gicv3_end_of_interrupt_sel1(id);
+}
+#endif
diff --git a/plat/common/plat_log_common.c b/plat/common/plat_log_common.c
new file mode 100644
index 0000000..66b9758
--- /dev/null
+++ b/plat/common/plat_log_common.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+/* Allow platforms to override the log prefix string */
+#pragma weak plat_log_get_prefix
+
+static const char *plat_prefix_str[] = {
+ "ERROR: ", "NOTICE: ", "WARNING: ", "INFO: ", "VERBOSE: "};
+
+const char *plat_log_get_prefix(unsigned int log_level)
+{
+ unsigned int level;
+
+ if (log_level < LOG_LEVEL_ERROR) {
+ level = LOG_LEVEL_ERROR;
+ } else if (log_level > LOG_LEVEL_VERBOSE) {
+ level = LOG_LEVEL_VERBOSE;
+ } else {
+ level = log_level;
+ }
+
+ return plat_prefix_str[(level / 10U) - 1U];
+}
diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c
new file mode 100644
index 0000000..c32e59f
--- /dev/null
+++ b/plat/common/plat_psci_common.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <lib/pmf/pmf.h>
+#include <lib/psci/psci.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+
+#if ENABLE_PSCI_STAT && ENABLE_PMF
+#pragma weak plat_psci_stat_accounting_start
+#pragma weak plat_psci_stat_accounting_stop
+#pragma weak plat_psci_stat_get_residency
+
+/* Maximum time-stamp value read from architectural counters */
+#ifdef __aarch64__
+#define MAX_TS UINT64_MAX
+#else
+#define MAX_TS UINT32_MAX
+#endif
+
+/* Following are used as ID's to capture time-stamp */
+#define PSCI_STAT_ID_ENTER_LOW_PWR 0
+#define PSCI_STAT_ID_EXIT_LOW_PWR 1
+#define PSCI_STAT_TOTAL_IDS 2
+
+PMF_DECLARE_CAPTURE_TIMESTAMP(psci_svc)
+PMF_DECLARE_GET_TIMESTAMP(psci_svc)
+PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID, PSCI_STAT_TOTAL_IDS,
+ PMF_STORE_ENABLE)
+
+/*
+ * This function calculates the stats residency in microseconds,
+ * taking in account the wrap around condition.
+ */
+static u_register_t calc_stat_residency(unsigned long long pwrupts,
+ unsigned long long pwrdnts)
+{
+ /* The divisor to use to convert raw timestamp into microseconds. */
+ u_register_t residency_div;
+ u_register_t res;
+
+ /*
+ * Calculate divisor so that it can be directly used to
+ * convert time-stamp into microseconds.
+ */
+ residency_div = read_cntfrq_el0() / MHZ_TICKS_PER_SEC;
+ assert(residency_div > 0U);
+
+ if (pwrupts < pwrdnts)
+ res = MAX_TS - pwrdnts + pwrupts;
+ else
+ res = pwrupts - pwrdnts;
+
+ return res / residency_div;
+}
+
+/*
+ * Capture timestamp before entering a low power state.
+ * Cache maintenance may be needed when reading these timestamps.
+ */
+void plat_psci_stat_accounting_start(
+ __unused const psci_power_state_t *state_info)
+{
+ assert(state_info != NULL);
+ PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
+ PMF_CACHE_MAINT);
+}
+
+/*
+ * Capture timestamp after exiting a low power state.
+ * Cache maintenance may be needed when reading these timestamps.
+ */
+void plat_psci_stat_accounting_stop(
+ __unused const psci_power_state_t *state_info)
+{
+ assert(state_info != NULL);
+ PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
+ PMF_CACHE_MAINT);
+}
+
+/*
+ * Calculate the residency for the given level and power state
+ * information.
+ */
+u_register_t plat_psci_stat_get_residency(unsigned int lvl,
+ const psci_power_state_t *state_info,
+ unsigned int last_cpu_idx)
+{
+ plat_local_state_t state;
+ unsigned long long pwrup_ts = 0, pwrdn_ts = 0;
+ unsigned int pmf_flags;
+
+ assert((lvl >= PSCI_CPU_PWR_LVL) && (lvl <= PLAT_MAX_PWR_LVL));
+ assert(state_info != NULL);
+ assert(last_cpu_idx <= PLATFORM_CORE_COUNT);
+
+ if (lvl == PSCI_CPU_PWR_LVL)
+ assert(last_cpu_idx == plat_my_core_pos());
+
+ /*
+ * If power down is requested, then timestamp capture will
+ * be with caches OFF. Hence we have to do cache maintenance
+ * when reading the timestamp.
+ */
+ state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL];
+ if (is_local_state_off(state) != 0) {
+ pmf_flags = PMF_CACHE_MAINT;
+ } else {
+ assert(is_local_state_retn(state) == 1);
+ pmf_flags = PMF_NO_CACHE_MAINT;
+ }
+
+ PMF_GET_TIMESTAMP_BY_INDEX(psci_svc,
+ PSCI_STAT_ID_ENTER_LOW_PWR,
+ last_cpu_idx,
+ pmf_flags,
+ pwrdn_ts);
+
+ PMF_GET_TIMESTAMP_BY_INDEX(psci_svc,
+ PSCI_STAT_ID_EXIT_LOW_PWR,
+ plat_my_core_pos(),
+ pmf_flags,
+ pwrup_ts);
+
+ return calc_stat_residency(pwrup_ts, pwrdn_ts);
+}
+#endif /* ENABLE_PSCI_STAT && ENABLE_PMF */
+
+/*
+ * The PSCI generic code uses this API to let the platform participate in state
+ * coordination during a power management operation. It compares the platform
+ * specific local power states requested by each cpu for a given power domain
+ * and returns the coordinated target power state that the domain should
+ * enter. A platform assigns a number to a local power state. This default
+ * implementation assumes that the platform assigns these numbers in order of
+ * increasing depth of the power state i.e. for two power states X & Y, if X < Y
+ * then X represents a shallower power state than Y. As a result, the
+ * coordinated target local power state for a power domain will be the minimum
+ * of the requested local power states.
+ */
+plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
+ const plat_local_state_t *states,
+ unsigned int ncpu)
+{
+ plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
+ const plat_local_state_t *st = states;
+ unsigned int n = ncpu;
+
+ assert(ncpu > 0U);
+
+ do {
+ temp = *st;
+ st++;
+ if (temp < target)
+ target = temp;
+ n--;
+ } while (n > 0U);
+
+ return target;
+}
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
new file mode 100644
index 0000000..b1fc13c
--- /dev/null
+++ b/plat/common/plat_spmd_manifest.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libfdt.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+#include <services/spm_core_manifest.h>
+
+#define ATTRIBUTE_ROOT_NODE_STR "attribute"
+
+/*******************************************************************************
+ * SPMC attribute node parser
+ ******************************************************************************/
+static int manifest_parse_attribute(spmc_manifest_attribute_t *attr,
+ const void *fdt,
+ int node)
+{
+ uint32_t val32;
+ int rc;
+
+ assert((attr != NULL) && (fdt != NULL));
+
+ rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
+ if (rc != 0) {
+ ERROR("Missing FFA %s version in SPM Core manifest.\n",
+ "major");
+ return rc;
+ }
+
+ rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
+ if (rc != 0) {
+ ERROR("Missing FFA %s version in SPM Core manifest.\n",
+ "minor");
+ return rc;
+ }
+
+ rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
+ if (rc != 0) {
+ ERROR("Missing SPMC ID in manifest.\n");
+ return rc;
+ }
+
+ attr->spmc_id = val32 & 0xffff;
+
+ rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
+ if (rc != 0) {
+ NOTICE("%s not specified in SPM Core manifest.\n",
+ "Execution state");
+ }
+
+ rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
+ if (rc != 0) {
+ NOTICE("%s not specified in SPM Core manifest.\n",
+ "Binary size");
+ }
+
+ rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
+ if (rc != 0) {
+ NOTICE("%s not specified in SPM Core manifest.\n",
+ "Load address");
+ }
+
+ rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
+ if (rc != 0) {
+ NOTICE("%s not specified in SPM Core manifest.\n",
+ "Entry point");
+ }
+
+ VERBOSE("SPM Core manifest attribute section:\n");
+ VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version);
+ VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id);
+ VERBOSE(" binary_size: 0x%x\n", attr->binary_size);
+ VERBOSE(" load_address: 0x%" PRIx64 "\n", attr->load_address);
+ VERBOSE(" entrypoint: 0x%" PRIx64 "\n", attr->entrypoint);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Root node handler
+ ******************************************************************************/
+static int manifest_parse_root(spmc_manifest_attribute_t *manifest,
+ const void *fdt,
+ int root)
+{
+ int node;
+
+ assert(manifest != NULL);
+
+ node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR,
+ sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1);
+ if (node < 0) {
+ ERROR("Root node doesn't contain subnode '%s'\n",
+ ATTRIBUTE_ROOT_NODE_STR);
+ return node;
+ }
+
+ return manifest_parse_attribute(manifest, fdt, node);
+}
+
+/*******************************************************************************
+ * Platform handler to parse a SPM Core manifest.
+ ******************************************************************************/
+int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
+ const void *pm_addr)
+{
+ int rc, unmap_ret;
+ uintptr_t pm_base, pm_base_align;
+ size_t mapped_size;
+
+ assert(manifest != NULL);
+ assert(pm_addr != NULL);
+
+ /*
+ * Assume TOS_FW_CONFIG is not necessarily aligned to a page
+ * boundary, thus calculate the remaining space between SPMC
+ * manifest start address and upper page limit.
+ *
+ */
+ pm_base = (uintptr_t)pm_addr;
+ pm_base_align = page_align(pm_base, UP);
+
+ if (pm_base == pm_base_align) {
+ /* Page aligned */
+ mapped_size = PAGE_SIZE;
+ } else {
+ mapped_size = pm_base_align - pm_base;
+ }
+
+ /* Check space within the page at least maps the FDT header */
+ if (mapped_size < sizeof(struct fdt_header)) {
+ ERROR("Error while mapping SPM Core manifest.\n");
+ return -EINVAL;
+ }
+
+ /* Map first SPMC manifest page in the SPMD translation regime */
+ pm_base_align = page_align(pm_base, DOWN);
+ rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
+ pm_base_align,
+ PAGE_SIZE,
+ MT_RO_DATA);
+ if (rc != 0) {
+ ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
+ return rc;
+ }
+
+ rc = fdt_check_header(pm_addr);
+ if (rc != 0) {
+ ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
+ goto exit_unmap;
+ }
+
+ /* Check SPMC manifest fits within the upper mapped page boundary */
+ if (mapped_size < fdt_totalsize(pm_addr)) {
+ ERROR("SPM Core manifest too large.\n");
+ rc = -EINVAL;
+ goto exit_unmap;
+ }
+
+ VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
+
+ rc = fdt_node_offset_by_compatible(pm_addr, -1,
+ "arm,ffa-core-manifest-1.0");
+ if (rc < 0) {
+ ERROR("Unrecognized SPM Core manifest\n");
+ goto exit_unmap;
+ }
+
+ rc = manifest_parse_root(manifest, pm_addr, rc);
+
+exit_unmap:
+ unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
+ if (unmap_ret != 0) {
+ ERROR("Error while unmapping SPM Core manifest (%d).\n",
+ unmap_ret);
+ if (rc == 0) {
+ rc = unmap_ret;
+ }
+ }
+
+ return rc;
+}
diff --git a/plat/common/tbbr/plat_tbbr.c b/plat/common/tbbr/plat_tbbr.c
new file mode 100644
index 0000000..12ab0a9
--- /dev/null
+++ b/plat/common/tbbr/plat_tbbr.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <drivers/auth/auth_mod.h>
+#include <plat/common/platform.h>
+#if USE_TBBR_DEFS
+#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+
+/*
+ * Store a new non-volatile counter value. This implementation
+ * only allows updating of the platform's Trusted NV counter when a
+ * certificate protected by the Trusted NV counter is signed with
+ * the ROT key. This avoids a compromised secondary certificate from
+ * updating the platform's Trusted NV counter, which could lead to the
+ * platform becoming unusable. The function is suitable for all TBBR
+ * compliant platforms.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc,
+ unsigned int nv_ctr)
+{
+ int trusted_nv_ctr;
+
+ assert(cookie != NULL);
+ assert(img_desc != NULL);
+
+ trusted_nv_ctr = strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0;
+
+ /*
+ * Only update the Trusted NV Counter if the certificate
+ * has been signed with the ROT key. Non Trusted NV counter
+ * updates are unconditional.
+ */
+ if (!trusted_nv_ctr || img_desc->parent == NULL)
+ return plat_set_nv_ctr(cookie, nv_ctr);
+
+ /*
+ * Trusted certificates not signed with the ROT key are not
+ * allowed to update the Trusted NV Counter.
+ */
+ return 1;
+}
diff --git a/plat/common/ubsan.c b/plat/common/ubsan.c
new file mode 100644
index 0000000..45b0f7c
--- /dev/null
+++ b/plat/common/ubsan.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2019, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <arch_helpers.h>
+#include <context.h>
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+struct source_location {
+ const char *file_name;
+ uint32_t line;
+ uint32_t column;
+};
+
+struct type_descriptor {
+ uint16_t type_kind;
+ uint16_t type_info;
+ char type_name[1];
+};
+
+struct type_mismatch_data {
+ struct source_location loc;
+ struct type_descriptor *type;
+ unsigned long alignment;
+ unsigned char type_check_kind;
+};
+
+struct overflow_data {
+ struct source_location loc;
+ struct type_descriptor *type;
+};
+
+struct shift_out_of_bounds_data {
+ struct source_location loc;
+ struct type_descriptor *lhs_type;
+ struct type_descriptor *rhs_type;
+};
+
+struct out_of_bounds_data {
+ struct source_location loc;
+ struct type_descriptor *array_type;
+ struct type_descriptor *index_type;
+};
+
+struct unreachable_data {
+ struct source_location loc;
+};
+
+struct vla_bound_data {
+ struct source_location loc;
+ struct type_descriptor *type;
+};
+
+struct invalid_value_data {
+ struct source_location loc;
+ struct type_descriptor *type;
+};
+
+struct nonnull_arg_data {
+ struct source_location loc;
+};
+
+/*
+ * When compiling with -fsanitize=undefined the compiler expects functions
+ * with the following signatures. The functions are never called directly,
+ * only when undefined behavior is detected in instrumented code.
+ */
+void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data,
+ unsigned long ptr);
+void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data,
+ unsigned long ptr);
+void __ubsan_handle_add_overflow_abort(struct overflow_data *data,
+ unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_sub_overflow_abort(struct overflow_data *data,
+ unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_mul_overflow_abort(struct overflow_data *data,
+ unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_negate_overflow_abort(struct overflow_data *data,
+ unsigned long old_val);
+void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data,
+ unsigned long old_val);
+void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data,
+ unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data,
+ unsigned long lhs, unsigned long rhs);
+void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data,
+ unsigned long idx);
+void __ubsan_handle_unreachable_abort(struct unreachable_data *data);
+void __ubsan_handle_missing_return_abort(struct unreachable_data *data);
+void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data,
+ unsigned long bound);
+void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data,
+ unsigned long val);
+void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data
+#if __GCC_VERSION < 60000
+ , size_t arg_no
+#endif
+ );
+
+static void print_loc(const char *func, struct source_location *loc)
+{
+ ERROR("Undefined behavior at %s:%d col %d (%s)",
+ loc->file_name, loc->line, loc->column, func);
+}
+
+
+void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data,
+ unsigned long ptr __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data,
+ unsigned long ptr __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_add_overflow_abort(struct overflow_data *data,
+ unsigned long lhs __unused,
+ unsigned long rhs __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_sub_overflow_abort(struct overflow_data *data,
+ unsigned long lhs __unused,
+ unsigned long rhs __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_mul_overflow_abort(struct overflow_data *data,
+ unsigned long lhs __unused,
+ unsigned long rhs __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_negate_overflow_abort(struct overflow_data *data,
+ unsigned long old_val __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data,
+ unsigned long old_val __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data,
+ unsigned long lhs __unused,
+ unsigned long rhs __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data,
+ unsigned long lhs __unused,
+ unsigned long rhs __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data,
+ unsigned long idx __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_unreachable_abort(struct unreachable_data *data)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_missing_return_abort(struct unreachable_data *data)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data,
+ unsigned long bound __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data,
+ unsigned long val __unused)
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
+
+void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data
+#if __GCC_VERSION < 60000
+ , size_t arg_no __unused
+#endif
+ )
+{
+ print_loc(__func__, &data->loc);
+ plat_panic_handler();
+}
diff --git a/plat/hisilicon/hikey/aarch64/hikey_common.c b/plat/hisilicon/hikey/aarch64/hikey_common.c
new file mode 100644
index 0000000..702fc2d
--- /dev/null
+++ b/plat/hisilicon/hikey/aarch64/hikey_common.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+
+#include <hikey_def.h>
+#include <hikey_layout.h>
+
+#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \
+ DDR_SIZE - DDR_SEC_SIZE, \
+ MT_DEVICE | MT_RW | MT_NS)
+
+#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \
+ DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \
+ TSP_SEC_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_ROM_PARAM MAP_REGION_FLAT(XG2RAM0_BASE, \
+ BL1_XG2RAM0_OFFSET, \
+ MT_DEVICE | MT_RO | MT_SECURE)
+
+#define MAP_SRAM MAP_REGION_FLAT(SRAM_BASE, \
+ SRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * BL1 needs to access the areas of MMC_SRAM.
+ * BL1 loads BL2 from eMMC into SRAM before DDR initialized.
+ */
+#define MAP_MMC_SRAM MAP_REGION_FLAT(HIKEY_BL1_MMC_DESC_BASE, \
+ HIKEY_BL1_MMC_DESC_SIZE + \
+ HIKEY_BL1_MMC_DATA_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * hikey_init_mmu_elx() will give the available subset of that,
+ */
+#ifdef IMAGE_BL1
+static const mmap_region_t hikey_mmap[] = {
+ MAP_DEVICE,
+ MAP_ROM_PARAM,
+ MAP_MMC_SRAM,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL2
+static const mmap_region_t hikey_mmap[] = {
+ MAP_DDR,
+ MAP_DEVICE,
+ MAP_TSP_MEM,
+ MAP_SRAM,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL31
+static const mmap_region_t hikey_mmap[] = {
+ MAP_DEVICE,
+ MAP_SRAM,
+ MAP_TSP_MEM,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL32
+static const mmap_region_t hikey_mmap[] = {
+ MAP_DEVICE,
+ MAP_DDR,
+ {0}
+};
+#endif
+
+/*
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ */
+#define HIKEY_CONFIGURE_MMU_EL(_el) \
+ void hikey_init_mmu_el##_el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(hikey_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el##_el(0); \
+ }
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+HIKEY_CONFIGURE_MMU_EL(1)
+HIKEY_CONFIGURE_MMU_EL(3)
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+ return HIKEY_NS_IMAGE_OFFSET;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return 1200000;
+}
diff --git a/plat/hisilicon/hikey/aarch64/hikey_helpers.S b/plat/hisilicon/hikey/aarch64/hikey_helpers.S
new file mode 100644
index 0000000..82a404a
--- /dev/null
+++ b/plat/hisilicon/hikey/aarch64/hikey_helpers.S
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <hikey_def.h>
+
+ .globl plat_my_core_pos
+ .globl platform_mem_init
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_report_exception
+ .globl plat_reset_handler
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * void platform_mem_init(void);
+ *
+ * We don't need to carry out any memory initialization
+ * on HIKEY. The Secure RAM is accessible straight away.
+ * -----------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, CRASH_CONSOLE_BASE
+ mov_imm x1, PL011_UART_CLK_IN_HZ
+ mov_imm x2, PL011_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, CRASH_CONSOLE_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, CRASH_CONSOLE_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * void plat_report_exception(unsigned int type)
+ * Function to report an unhandled exception
+ * with platform-specific means.
+ * On HIKEY platform, it updates the LEDs
+ * to indicate where we are
+ * ---------------------------------------------
+ */
+func plat_report_exception
+ mov x8, x30
+
+ /* Turn on LED according to x0 (0 -- f) */
+ ldr x2, =0xf7020000
+ and x1, x0, #1
+ str w1, [x2, #4]
+ and x1, x0, #2
+ str w1, [x2, #8]
+ and x1, x0, #4
+ str w1, [x2, #16]
+ and x1, x0, #8
+ str w1, [x2, #32]
+
+ mrs x2, currentel
+ and x2, x2, #0xc0
+ /* Check EL1 */
+ cmp x2, #0x04
+ beq plat_report_el1
+
+ adr x4, plat_err_str
+ bl asm_print_str
+
+ adr x4, esr_el3_str
+ bl asm_print_str
+
+ mrs x4, esr_el3
+ bl asm_print_hex
+
+ adr x4, elr_el3_str
+ bl asm_print_str
+
+ mrs x4, elr_el3
+ bl asm_print_hex
+ b plat_report_end
+
+plat_report_el1:
+ adr x4, plat_err_str
+ bl asm_print_str
+
+ adr x4, esr_el1_str
+ bl asm_print_str
+
+ mrs x4, esr_el1
+ bl asm_print_hex
+
+ adr x4, elr_el1_str
+ bl asm_print_str
+
+ mrs x4, elr_el1
+ bl asm_print_hex
+plat_report_end:
+ mov x30, x8
+ ret
+endfunc plat_report_exception
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler(void);
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ ret
+endfunc plat_reset_handler
+
+.section .rodata.rev_err_str, "aS"
+plat_err_str:
+ .asciz "\nPlatform exception reporting:"
+esr_el3_str:
+ .asciz "\nESR_EL3: "
+elr_el3_str:
+ .asciz "\nELR_EL3: "
+esr_el1_str:
+ .asciz "\nESR_EL1: "
+elr_el1_str:
+ .asciz "\nELR_EL1: "
diff --git a/plat/hisilicon/hikey/hikey_bl1_setup.c b/plat/hisilicon/hikey/hikey_bl1_setup.c
new file mode 100644
index 0000000..31ff820
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_bl1_setup.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <bl1/tbbr/tbbr_img_desc.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/mmc.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <hi6220.h>
+#include <hikey_def.h>
+#include <hikey_layout.h>
+
+#include "hikey_private.h"
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+static console_t console;
+static struct mmc_device_info mmc_info;
+
+enum {
+ BOOT_NORMAL = 0,
+ BOOT_USB_DOWNLOAD,
+ BOOT_UART_DOWNLOAD,
+};
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+/*
+ * Perform any BL1 specific platform actions.
+ */
+void bl1_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = BL1_RW_BASE;
+ bl1_tzram_layout.total_size = BL1_RW_SIZE;
+
+ INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
+ BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */
+}
+
+/*
+ * Perform the very early platform specific architecture setup here. At the
+ * moment this only does basic initialization. Later architectural setup
+ * (bl1_arch_setup()) does not do anything platform specific.
+ */
+void bl1_plat_arch_setup(void)
+{
+ hikey_init_mmu_el3(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL1_RO_BASE,
+ BL1_RO_LIMIT,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+/*
+ * Function which will perform any remaining platform-specific setup that can
+ * occur after the MMU and data cache have been enabled.
+ */
+void bl1_platform_setup(void)
+{
+ dw_mmc_params_t params;
+
+ assert((HIKEY_BL1_MMC_DESC_BASE >= SRAM_BASE) &&
+ ((SRAM_BASE + SRAM_SIZE) >=
+ (HIKEY_BL1_MMC_DATA_BASE + HIKEY_BL1_MMC_DATA_SIZE)));
+ hikey_sp804_init();
+ hikey_gpio_init();
+ hikey_pmussi_init();
+ hikey_hi6553_init();
+
+ hikey_rtc_init();
+
+ hikey_mmc_pll_init();
+
+ memset(&params, 0, sizeof(dw_mmc_params_t));
+ params.reg_base = DWMMC0_BASE;
+ params.desc_base = HIKEY_BL1_MMC_DESC_BASE;
+ params.desc_size = 1 << 20;
+ params.clk_rate = 24 * 1000 * 1000;
+ params.bus_width = MMC_BUS_WIDTH_8;
+ params.flags = MMC_FLAG_CMD23;
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ dw_mmc_init(&params, &mmc_info);
+
+ hikey_io_setup();
+}
+
+/*
+ * The following function checks if Firmware update is needed,
+ * by checking if TOC in FIP image is valid or not.
+ */
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ int32_t boot_mode;
+ unsigned int ret;
+
+ boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE);
+ switch (boot_mode) {
+ case BOOT_USB_DOWNLOAD:
+ case BOOT_UART_DOWNLOAD:
+ ret = NS_BL1U_IMAGE_ID;
+ break;
+ default:
+ WARN("Invalid boot mode is found:%d\n", boot_mode);
+ panic();
+ }
+ return ret;
+}
+
+image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ unsigned int index = 0;
+
+ while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) {
+ if (bl1_tbbr_image_descs[index].image_id == image_id)
+ return &bl1_tbbr_image_descs[index];
+
+ index++;
+ }
+
+ return NULL;
+}
+
+void bl1_plat_set_ep_info(unsigned int image_id,
+ entry_point_info_t *ep_info)
+{
+ uint64_t data = 0;
+
+ if (image_id == BL2_IMAGE_ID)
+ panic();
+ inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE);
+ __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data));
+ do {
+ data |= 3 << 20;
+ __asm__ volatile ("msr cpacr_el1, %0" : : "r"(data));
+ __asm__ volatile ("mrs %0, cpacr_el1" : "=r"(data));
+ } while ((data & (3 << 20)) != (3 << 20));
+ INFO("cpacr_el1:0x%" PRIx64 "\n", data);
+
+ ep_info->args.arg0 = 0xffff & read_mpidr();
+ ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+}
diff --git a/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c b/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c
new file mode 100644
index 0000000..d029703
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h> /* also includes hikey_def.h and hikey_layout.h*/
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = HIKEY_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the pager
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the paged
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = HIKEY_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = HIKEY_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = HIKEY_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = HIKEY_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = 0x200000 /* 2MB */,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
new file mode 100644
index 0000000..a90f12c
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h> /* also includes hikey_def.h and hikey_layout.h*/
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/delay_timer.h>
+#include <drivers/mmc.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <lib/mmio.h>
+#ifdef SPD_opteed
+#include <lib/optee_utils.h>
+#endif
+#include <plat/common/platform.h>
+
+#include <hi6220.h>
+#include <hisi_mcu.h>
+#include <hisi_sram_map.h>
+#include "hikey_private.h"
+
+#define BL2_RW_BASE (BL_CODE_END)
+
+static meminfo_t bl2_el3_tzram_layout;
+static console_t console;
+static struct mmc_device_info mmc_info;
+
+enum {
+ BOOT_MODE_RECOVERY = 0,
+ BOOT_MODE_NORMAL,
+ BOOT_MODE_MASK = 1,
+};
+
+/*******************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int plat_hikey_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ /* Enable MCU SRAM */
+ hisi_mcu_enable_sram();
+
+ /* Load MCU binary into SRAM */
+ hisi_mcu_load_image(scp_bl2_image_info->image_base,
+ scp_bl2_image_info->image_size);
+ /* Let MCU running */
+ hisi_mcu_start_run();
+
+ INFO("%s: MCU PC is at 0x%x\n",
+ __func__, mmio_read_32(AO_SC_MCU_SUBSYS_STAT2));
+ INFO("%s: AO_SC_PERIPH_CLKSTAT4 is 0x%x\n",
+ __func__, mmio_read_32(AO_SC_PERIPH_CLKSTAT4));
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t hikey_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL3-2 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifdef __aarch64__
+uint32_t hikey_get_spsr_for_bl33_entry(void)
+{
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#else
+uint32_t hikey_get_spsr_for_bl33_entry(void)
+{
+ unsigned int hyp_status, mode, spsr;
+
+ hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+ mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#endif /* __aarch64__ */
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ return hikey_set_fip_addr(image_id, "fastboot");
+}
+
+int hikey_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+ assert(bl_mem_params);
+
+ switch (image_id) {
+#ifdef __aarch64__
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+#endif
+ bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl32_entry();
+ break;
+#endif
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = hikey_get_spsr_for_bl33_entry();
+ break;
+
+#ifdef SCP_BL2_BASE
+ case SCP_BL2_IMAGE_ID:
+ /* The subsequent handling of SCP_BL2 is platform specific */
+ err = plat_hikey_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+ if (err) {
+ WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+ }
+ break;
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return hikey_bl2_handle_post_image_load(image_id);
+}
+
+static void reset_dwmmc_clk(void)
+{
+ unsigned int data;
+
+ /* disable mmc0 bus clock */
+ mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (data & PERI_CLK0_MMC0);
+ /* enable mmc0 bus clock */
+ mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (!(data & PERI_CLK0_MMC0));
+ /* reset mmc0 clock domain */
+ mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
+
+ /* bypass mmc0 clock phase */
+ data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
+ data |= 3;
+ mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
+
+ /* disable low power */
+ data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
+ data |= 1 << 3;
+ mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+ } while (!(data & PERI_RST0_MMC0));
+
+ /* unreset mmc0 clock domain */
+ mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+ } while (data & PERI_RST0_MMC0);
+}
+
+static void hikey_boardid_init(void)
+{
+ u_register_t midr;
+
+ midr = read_midr();
+ mmio_write_32(MEMORY_AXI_CHIP_ADDR, midr);
+ INFO("[BDID] [%x] midr: 0x%x\n", MEMORY_AXI_CHIP_ADDR,
+ (unsigned int)midr);
+
+ mmio_write_32(MEMORY_AXI_BOARD_TYPE_ADDR, 0);
+ mmio_write_32(MEMORY_AXI_BOARD_ID_ADDR, 0x2b);
+
+ mmio_write_32(ACPU_ARM64_FLAGA, 0x1234);
+ mmio_write_32(ACPU_ARM64_FLAGB, 0x5678);
+}
+
+static void hikey_sd_init(void)
+{
+ /* switch pinmux to SD */
+ mmio_write_32(IOMG_SD_CLK, IOMG_MUX_FUNC0);
+ mmio_write_32(IOMG_SD_CMD, IOMG_MUX_FUNC0);
+ mmio_write_32(IOMG_SD_DATA0, IOMG_MUX_FUNC0);
+ mmio_write_32(IOMG_SD_DATA1, IOMG_MUX_FUNC0);
+ mmio_write_32(IOMG_SD_DATA2, IOMG_MUX_FUNC0);
+ mmio_write_32(IOMG_SD_DATA3, IOMG_MUX_FUNC0);
+
+ mmio_write_32(IOCG_SD_CLK, IOCG_INPUT_16MA);
+ mmio_write_32(IOCG_SD_CMD, IOCG_INPUT_12MA);
+ mmio_write_32(IOCG_SD_DATA0, IOCG_INPUT_12MA);
+ mmio_write_32(IOCG_SD_DATA1, IOCG_INPUT_12MA);
+ mmio_write_32(IOCG_SD_DATA2, IOCG_INPUT_12MA);
+ mmio_write_32(IOCG_SD_DATA3, IOCG_INPUT_12MA);
+
+ /* set SD Card detect as nopull */
+ mmio_write_32(IOCG_GPIO8, 0);
+}
+
+static void hikey_jumper_init(void)
+{
+ /* set jumper detect as nopull */
+ mmio_write_32(IOCG_GPIO24, 0);
+ /* set jumper detect as GPIO */
+ mmio_write_32(IOMG_GPIO24, IOMG_MUX_FUNC0);
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+ /*
+ * Allow BL2 to see the whole Trusted RAM.
+ */
+ bl2_el3_tzram_layout.total_base = BL2_RW_BASE;
+ bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE;
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ hikey_init_mmu_el3(bl2_el3_tzram_layout.total_base,
+ bl2_el3_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+void bl2_platform_setup(void)
+{
+ dw_mmc_params_t params;
+
+ hikey_sp804_init();
+ hikey_gpio_init();
+ hikey_pmussi_init();
+ hikey_hi6553_init();
+ /* Clear SRAM since it'll be used by MCU right now. */
+ memset((void *)SRAM_BASE, 0, SRAM_SIZE);
+
+ dsb();
+ hikey_ddr_init(DDR_FREQ_800M);
+ hikey_security_setup();
+
+ hikey_boardid_init();
+ init_acpu_dvfs();
+ hikey_rtc_init();
+ hikey_sd_init();
+ hikey_jumper_init();
+
+ hikey_mmc_pll_init();
+
+ /* Clean SRAM before MCU used */
+ clean_dcache_range(SRAM_BASE, SRAM_SIZE);
+
+ reset_dwmmc_clk();
+ memset(&params, 0, sizeof(dw_mmc_params_t));
+ params.reg_base = DWMMC0_BASE;
+ params.desc_base = HIKEY_MMC_DESC_BASE;
+ params.desc_size = 1 << 20;
+ params.clk_rate = 24 * 1000 * 1000;
+ params.bus_width = MMC_BUS_WIDTH_8;
+ params.flags = MMC_FLAG_CMD23;
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ dw_mmc_init(&params, &mmc_info);
+
+ hikey_io_setup();
+}
diff --git a/plat/hisilicon/hikey/hikey_bl31_setup.c b/plat/hisilicon/hikey/hikey_bl31_setup.c
new file mode 100644
index 0000000..7d008e7
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_bl31_setup.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/pl011.h>
+#include <lib/mmio.h>
+
+#include <hi6220.h>
+#include <hikey_def.h>
+#include <hisi_ipc.h>
+#include <hisi_pwrc.h>
+
+#include "hikey_private.h"
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+static console_t console;
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t g0_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+/*
+ * Ideally `arm_gic_data` structure definition should be a `const` but it is
+ * kept as modifiable for overwriting with different GICD and GICC base when
+ * running on FVP with VE memory map.
+ */
+gicv2_driver_data_t hikey_gic_data = {
+ .gicd_base = PLAT_ARM_GICD_BASE,
+ .gicc_base = PLAT_ARM_GICC_BASE,
+ .interrupt_props = g0_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props),
+};
+
+static const int cci_map[] = {
+ CCI400_SL_IFACE3_CLUSTER_IX,
+ CCI400_SL_IFACE4_CLUSTER_IX
+};
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ return NULL;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ void *from_bl2;
+
+ from_bl2 = (void *) arg0;
+
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(CONSOLE_BASE, PL011_UART_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Initialize CCI driver */
+ cci_init(CCI400_BASE, cci_map, ARRAY_SIZE(cci_map));
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_ep_info.pc == 0)
+ panic();
+}
+
+void bl31_plat_arch_setup(void)
+{
+ hikey_init_mmu_el3(BL31_BASE,
+ BL31_LIMIT - BL31_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+/* Initialize EDMAC controller with non-secure mode. */
+static void hikey_edma_init(void)
+{
+ int i;
+ uint32_t non_secure;
+
+ non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC;
+ mmio_write_32(EDMAC_SEC_CTRL, non_secure);
+
+ for (i = 0; i < EDMAC_CHANNEL_NUMS; i++) {
+ mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18));
+ }
+}
+
+void bl31_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ gicv2_driver_init(&hikey_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ hikey_edma_init();
+
+ hisi_ipc_init();
+ hisi_pwrc_setup();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+}
diff --git a/plat/hisilicon/hikey/hikey_bl_common.c b/plat/hisilicon/hikey/hikey_bl_common.c
new file mode 100644
index 0000000..d062de4
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_bl_common.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <drivers/arm/pl061_gpio.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <drivers/gpio.h>
+#include <lib/mmio.h>
+
+#include <hi6220.h>
+#include <hi6553.h>
+#include "hikey_private.h"
+
+void hikey_sp804_init(void)
+{
+ uint32_t data;
+
+ /* select the clock of dual timer0 */
+ data = mmio_read_32(AO_SC_TIMER_EN0);
+ while (data & 3) {
+ data &= ~3;
+ data |= 3 << 16;
+ mmio_write_32(AO_SC_TIMER_EN0, data);
+ data = mmio_read_32(AO_SC_TIMER_EN0);
+ }
+ /* enable the pclk of dual timer0 */
+ data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
+ while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) {
+ mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0);
+ data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
+ }
+ /* reset dual timer0 */
+ data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+ mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0);
+ do {
+ data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+ } while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0));
+ /* unreset dual timer0 */
+ mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0);
+ do {
+ data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+ } while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0));
+
+ sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
+}
+
+void hikey_gpio_init(void)
+{
+ pl061_gpio_init();
+ pl061_gpio_register(GPIO0_BASE, 0);
+ pl061_gpio_register(GPIO1_BASE, 1);
+ pl061_gpio_register(GPIO2_BASE, 2);
+ pl061_gpio_register(GPIO3_BASE, 3);
+ pl061_gpio_register(GPIO4_BASE, 4);
+ pl061_gpio_register(GPIO5_BASE, 5);
+ pl061_gpio_register(GPIO6_BASE, 6);
+ pl061_gpio_register(GPIO7_BASE, 7);
+ pl061_gpio_register(GPIO8_BASE, 8);
+ pl061_gpio_register(GPIO9_BASE, 9);
+ pl061_gpio_register(GPIO10_BASE, 10);
+ pl061_gpio_register(GPIO11_BASE, 11);
+ pl061_gpio_register(GPIO12_BASE, 12);
+ pl061_gpio_register(GPIO13_BASE, 13);
+ pl061_gpio_register(GPIO14_BASE, 14);
+ pl061_gpio_register(GPIO15_BASE, 15);
+ pl061_gpio_register(GPIO16_BASE, 16);
+ pl061_gpio_register(GPIO17_BASE, 17);
+ pl061_gpio_register(GPIO18_BASE, 18);
+ pl061_gpio_register(GPIO19_BASE, 19);
+
+ /* Power on indicator LED (USER_LED1). */
+ gpio_set_direction(32, GPIO_DIR_OUT); /* LED1 */
+ gpio_set_value(32, GPIO_LEVEL_HIGH);
+ gpio_set_direction(33, GPIO_DIR_OUT); /* LED2 */
+ gpio_set_value(33, GPIO_LEVEL_LOW);
+ gpio_set_direction(34, GPIO_DIR_OUT); /* LED3 */
+ gpio_set_direction(35, GPIO_DIR_OUT); /* LED4 */
+}
+
+void hikey_pmussi_init(void)
+{
+ uint32_t data;
+
+ /* Initialize PWR_HOLD GPIO */
+ gpio_set_direction(0, GPIO_DIR_OUT);
+ gpio_set_value(0, GPIO_LEVEL_LOW);
+
+ /*
+ * After reset, PMUSSI stays in reset mode.
+ * Now make it out of reset.
+ */
+ mmio_write_32(AO_SC_PERIPH_RSTDIS4,
+ AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
+ do {
+ data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
+ } while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
+
+ /* Set PMUSSI clock latency for read operation. */
+ data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3);
+ data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
+ data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3;
+ mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data);
+
+ /* enable PMUSSI clock */
+ data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU |
+ AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU;
+ mmio_write_32(AO_SC_PERIPH_CLKEN5, data);
+ data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI;
+ mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
+
+ gpio_set_value(0, GPIO_LEVEL_HIGH);
+}
+
+void hikey_hi6553_init(void)
+{
+ uint8_t data;
+
+ mmio_write_8(HI6553_PERI_EN_MARK, 0x1e);
+ mmio_write_8(HI6553_NP_REG_ADJ1, 0);
+ data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC |
+ DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2;
+ mmio_write_8(HI6553_DISABLE6_XO_CLK, data);
+
+ /* configure BUCK0 & BUCK1 */
+ mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e);
+ mmio_write_8(HI6553_BUCK0_CTRL7, 0x10);
+ mmio_write_8(HI6553_BUCK1_CTRL7, 0x10);
+ mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e);
+ mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e);
+ mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc);
+ mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc);
+
+ /* configure BUCK2 */
+ mmio_write_8(HI6553_BUCK2_REG1, 0x4f);
+ mmio_write_8(HI6553_BUCK2_REG5, 0x99);
+ mmio_write_8(HI6553_BUCK2_REG6, 0x45);
+ mdelay(1);
+ mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22);
+ mdelay(1);
+
+ /* configure BUCK3 */
+ mmio_write_8(HI6553_BUCK3_REG3, 0x02);
+ mmio_write_8(HI6553_BUCK3_REG5, 0x99);
+ mmio_write_8(HI6553_BUCK3_REG6, 0x41);
+ mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02);
+ mdelay(1);
+
+ /* configure BUCK4 */
+ mmio_write_8(HI6553_BUCK4_REG2, 0x9a);
+ mmio_write_8(HI6553_BUCK4_REG5, 0x99);
+ mmio_write_8(HI6553_BUCK4_REG6, 0x45);
+
+ /* configure LDO20 */
+ mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50);
+
+ mmio_write_8(HI6553_NP_REG_CHG, 0x0f);
+ mmio_write_8(HI6553_CLK_TOP0, 0x06);
+ mmio_write_8(HI6553_CLK_TOP3, 0xc0);
+ mmio_write_8(HI6553_CLK_TOP4, 0x00);
+
+ /* configure LDO7 & LDO10 for SD slot */
+ /* enable LDO7 */
+ data = mmio_read_8(HI6553_LDO7_REG_ADJ);
+ data = (data & 0xf8) | 0x2;
+ mmio_write_8(HI6553_LDO7_REG_ADJ, data);
+ mdelay(5);
+ mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6);
+ mdelay(5);
+ /* enable LDO10 */
+ data = mmio_read_8(HI6553_LDO10_REG_ADJ);
+ data = (data & 0xf8) | 0x5;
+ mmio_write_8(HI6553_LDO10_REG_ADJ, data);
+ mdelay(5);
+ mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1);
+ mdelay(5);
+ /* enable LDO15 */
+ data = mmio_read_8(HI6553_LDO15_REG_ADJ);
+ data = (data & 0xf8) | 0x4;
+ mmio_write_8(HI6553_LDO15_REG_ADJ, data);
+ mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6);
+ mdelay(5);
+ /* enable LDO19 */
+ data = mmio_read_8(HI6553_LDO19_REG_ADJ);
+ data |= 0x7;
+ mmio_write_8(HI6553_LDO19_REG_ADJ, data);
+ mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2);
+ mdelay(5);
+ /* enable LDO21 */
+ data = mmio_read_8(HI6553_LDO21_REG_ADJ);
+ data = (data & 0xf8) | 0x3;
+ mmio_write_8(HI6553_LDO21_REG_ADJ, data);
+ mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4);
+ mdelay(5);
+ /* enable LDO22 */
+ data = mmio_read_8(HI6553_LDO22_REG_ADJ);
+ data = (data & 0xf8) | 0x7;
+ mmio_write_8(HI6553_LDO22_REG_ADJ, data);
+ mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5);
+ mdelay(5);
+
+ /* select 32.764KHz */
+ mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01);
+
+ /* Disable vbus_det interrupts */
+ data = mmio_read_8(HI6553_IRQ2_MASK);
+ data = data | 0x3;
+ mmio_write_8(HI6553_IRQ2_MASK, data);
+}
+
+void init_mmc0_pll(void)
+{
+ unsigned int data;
+
+ /* select SYSPLL as the source of MMC0 */
+ /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
+ mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21);
+ do {
+ data = mmio_read_32(PERI_SC_CLK_SEL0);
+ } while (!(data & (1 << 5)));
+ /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
+ mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29);
+ do {
+ data = mmio_read_32(PERI_SC_CLK_SEL0);
+ } while (data & (1 << 13));
+
+ mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0));
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (!(data & (1 << 0)));
+
+ data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
+ data |= 1 << 1;
+ mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
+
+ do {
+ mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb);
+ data = mmio_read_32(PERI_SC_CLKCFG8BIT1);
+ } while ((data & 0xb) != 0xb);
+}
+
+void reset_mmc0_clk(void)
+{
+ unsigned int data;
+
+ /* disable mmc0 bus clock */
+ mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (data & PERI_CLK0_MMC0);
+ /* enable mmc0 bus clock */
+ mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (!(data & PERI_CLK0_MMC0));
+ /* reset mmc0 clock domain */
+ mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
+
+ /* bypass mmc0 clock phase */
+ data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
+ data |= 3;
+ mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
+
+ /* disable low power */
+ data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
+ data |= 1 << 3;
+ mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+ } while (!(data & PERI_RST0_MMC0));
+
+ /* unreset mmc0 clock domain */
+ mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+ } while (data & PERI_RST0_MMC0);
+}
+
+void init_media_clk(void)
+{
+ unsigned int data, value;
+
+ data = mmio_read_32(PMCTRL_MEDPLLCTRL);
+ data |= 1;
+ mmio_write_32(PMCTRL_MEDPLLCTRL, data);
+
+ for (;;) {
+ data = mmio_read_32(PMCTRL_MEDPLLCTRL);
+ value = 1 << 28;
+ if ((data & value) == value)
+ break;
+ }
+
+ data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
+ data = 1 << 10;
+ mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
+}
+
+void init_mmc1_pll(void)
+{
+ uint32_t data;
+
+ /* select SYSPLL as the source of MMC1 */
+ /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
+ mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27);
+ do {
+ data = mmio_read_32(PERI_SC_CLK_SEL0);
+ } while (!(data & (1 << 11)));
+ /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
+ mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30);
+ do {
+ data = mmio_read_32(PERI_SC_CLK_SEL0);
+ } while (data & (1 << 14));
+
+ mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1));
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (!(data & (1 << 1)));
+
+ data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
+ data |= 1 << 2;
+ mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
+
+ do {
+ /* 1.2GHz / 50 = 24MHz */
+ mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7));
+ data = mmio_read_32(PERI_SC_CLKCFG8BIT2);
+ } while ((data & 0x31) != 0x31);
+}
+
+void reset_mmc1_clk(void)
+{
+ unsigned int data;
+
+ /* disable mmc1 bus clock */
+ mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (data & PERI_CLK0_MMC1);
+ /* enable mmc1 bus clock */
+ mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
+ } while (!(data & PERI_CLK0_MMC1));
+ /* reset mmc1 clock domain */
+ mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1);
+
+ /* bypass mmc1 clock phase */
+ data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
+ data |= 3 << 2;
+ mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
+
+ /* disable low power */
+ data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
+ data |= 1 << 4;
+ mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+ } while (!(data & PERI_RST0_MMC1));
+
+ /* unreset mmc0 clock domain */
+ mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1);
+ do {
+ data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
+ } while (data & PERI_RST0_MMC1);
+}
+
+/* Initialize PLL of both eMMC and SD controllers. */
+void hikey_mmc_pll_init(void)
+{
+ init_mmc0_pll();
+ reset_mmc0_clk();
+ init_media_clk();
+
+ dsb();
+
+ init_mmc1_pll();
+ reset_mmc1_clk();
+}
+
+void hikey_rtc_init(void)
+{
+ uint32_t data;
+
+ data = mmio_read_32(AO_SC_PERIPH_CLKEN4);
+ data |= AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N;
+ mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
+}
diff --git a/plat/hisilicon/hikey/hikey_ddr.c b/plat/hisilicon/hikey/hikey_ddr.c
new file mode 100644
index 0000000..cd9e9a2
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_ddr.c
@@ -0,0 +1,1451 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <lib/mmio.h>
+
+#include <hi6220.h>
+#include <hi6553.h>
+#include <hisi_sram_map.h>
+#include "hikey_private.h"
+
+static void init_pll(void)
+{
+ unsigned int data;
+
+ data = mmio_read_32((0xf7032000 + 0x000));
+ data |= 0x1;
+ mmio_write_32((0xf7032000 + 0x000), data);
+ do {
+ data = mmio_read_32((0xf7032000 + 0x000));
+ } while (!(data & (1 << 28)));
+
+ data = mmio_read_32((0xf7800000 + 0x000));
+ data &= ~0x007;
+ data |= 0x004;
+ mmio_write_32((0xf7800000 + 0x000), data);
+ do {
+ data = mmio_read_32((0xf7800000 + 0x014));
+ data &= 0x007;
+ } while (data != 0x004);
+
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(0xf7032000 + 0x02c, 0x5110103e);
+ dsb();
+ isb();
+ udelay(10);
+ data = mmio_read_32(0xf7032000 + 0x050);
+ data |= 1 << 28;
+ mmio_write_32(0xf7032000 + 0x050, data);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2101);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2001);
+ dsb();
+ isb();
+ udelay(10);
+ mmio_write_32(PERI_SC_PERIPH_CTRL14, 0x2201);
+ dsb();
+ isb();
+ udelay(10);
+}
+
+static void init_freq(void)
+{
+ unsigned int data, tmp;
+ unsigned int cpuext_cfg, ddr_cfg;
+
+ mmio_write_32((0xf7032000 + 0x374), 0x4a);
+ mmio_write_32((0xf7032000 + 0x368), 0xda);
+ mmio_write_32((0xf7032000 + 0x36c), 0x01);
+ mmio_write_32((0xf7032000 + 0x370), 0x01);
+ mmio_write_32((0xf7032000 + 0x360), 0x60);
+ mmio_write_32((0xf7032000 + 0x364), 0x60);
+
+ mmio_write_32((0xf7032000 + 0x114), 0x1000);
+
+ data = mmio_read_32((0xf7032000 + 0x110));
+ data |= (3 << 12);
+ mmio_write_32((0xf7032000 + 0x110), data);
+
+ data = mmio_read_32((0xf7032000 + 0x110));
+ data |= (1 << 4);
+ mmio_write_32((0xf7032000 + 0x110), data);
+
+
+ data = mmio_read_32((0xf7032000 + 0x110));
+ data &= ~0x7;
+ data |= 0x5;
+ mmio_write_32((0xf7032000 + 0x110), data);
+ dsb();
+ mdelay(10);
+
+
+ do {
+ data = mmio_read_32((0xf6504000 + 0x008));
+ data &= (3 << 20);
+ } while (data != (3 << 20));
+ dsb();
+ mdelay(10);
+
+
+ data = mmio_read_32((0xf6504000 + 0x054));
+ data &= ~((1 << 0) | (1 << 11));
+ mmio_write_32((0xf6504000 + 0x054), data);
+ mdelay(10);
+
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= ~(3 << 8);
+ data |= (1 << 8);
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ data = mmio_read_32((0xf7032000 + 0x100));
+ data |= (1 << 0);
+ mmio_write_32((0xf7032000 + 0x100), data);
+ dsb();
+
+ do {
+ data = mmio_read_32((0xf7032000 + 0x100));
+ data &= (1 << 2);
+ } while (data != (1 << 2));
+
+ data = mmio_read_32((0xf6504000 + 0x06c));
+ data &= ~0xffff;
+ data |= 0x56;
+ mmio_write_32((0xf6504000 + 0x06c), data);
+
+ data = mmio_read_32((0xf6504000 + 0x06c));
+ data &= ~(0xffffffu << 8);
+ data |= 0xc7a << 8;
+ mmio_write_32((0xf6504000 + 0x06c), data);
+
+ data = mmio_read_32((0xf6504000 + 0x058));
+ data &= ((1 << 13) - 1);
+ data |= 0xccb;
+ mmio_write_32((0xf6504000 + 0x058), data);
+
+ mmio_write_32((0xf6504000 + 0x060), 0x1fff);
+ mmio_write_32((0xf6504000 + 0x064), 0x1ffffff);
+ mmio_write_32((0xf6504000 + 0x068), 0x7fffffff);
+ mmio_write_32((0xf6504000 + 0x05c), 0x1);
+
+ data = mmio_read_32((0xf6504000 + 0x054));
+ data &= ~(0xf << 12);
+ data |= 1 << 12;
+ mmio_write_32((0xf6504000 + 0x054), data);
+ dsb();
+
+
+ data = mmio_read_32((0xf7032000 + 0x000));
+ data &= ~(1 << 0);
+ mmio_write_32((0xf7032000 + 0x000), data);
+
+ mmio_write_32((0xf7032000 + 0x004), 0x5110207d);
+ mmio_write_32((0xf7032000 + 0x134), 0x10000005);
+ data = mmio_read_32((0xf7032000 + 0x134));
+
+
+ data = mmio_read_32((0xf7032000 + 0x000));
+ data |= (1 << 0);
+ mmio_write_32((0xf7032000 + 0x000), data);
+
+ mmio_write_32((0xf7032000 + 0x368), 0x100da);
+ data = mmio_read_32((0xf7032000 + 0x378));
+ data &= ~((1 << 7) - 1);
+ data |= 0x6b;
+ mmio_write_32((0xf7032000 + 0x378), data);
+ dsb();
+ do {
+ data = mmio_read_32((0xf7032000 + 0x378));
+ tmp = data & 0x7f;
+ data = (data & (0x7f << 8)) >> 8;
+ if (data != tmp)
+ continue;
+ data = mmio_read_32((0xf7032000 + 0x37c));
+ } while (!(data & 1));
+
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= ~((3 << 0) |
+ (3 << 8));
+ cpuext_cfg = 1;
+ ddr_cfg = 1;
+ data |= cpuext_cfg | (ddr_cfg << 8);
+ mmio_write_32((0xf7032000 + 0x104), data);
+ dsb();
+
+ do {
+ data = mmio_read_32((0xf7032000 + 0x104));
+ tmp = (data & (3 << 16)) >> 16;
+ if (cpuext_cfg != tmp)
+ continue;
+ tmp = (data & (3 << 24)) >> 24;
+ if (ddr_cfg != tmp)
+ continue;
+ data = mmio_read_32((0xf7032000 + 0x000));
+ data &= 1 << 28;
+ } while (!data);
+
+ data = mmio_read_32((0xf7032000 + 0x100));
+ data &= ~(1 << 0);
+ mmio_write_32((0xf7032000 + 0x100), data);
+ dsb();
+ do {
+ data = mmio_read_32((0xf7032000 + 0x100));
+ data &= (1 << 1);
+ } while (data != (1 << 1));
+ mdelay(1000);
+
+ data = mmio_read_32((0xf6504000 + 0x054));
+ data &= ~(1 << 28);
+ mmio_write_32((0xf6504000 + 0x054), data);
+ dsb();
+
+ data = mmio_read_32((0xf7032000 + 0x110));
+ data &= ~((1 << 4) |
+ (3 << 12));
+ mmio_write_32((0xf7032000 + 0x110), data);
+}
+
+int cat_533mhz_800mhz(void)
+{
+ unsigned int data, i;
+ unsigned int bdl[5];
+
+
+ data = mmio_read_32((0xf712c000 + 0x1c8));
+ data &= 0xfffff0f0;
+ data |= 0x100f01;
+ mmio_write_32((0xf712c000 + 0x1c8), data);
+
+ for (i = 0; i < 0x20; i++) {
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ data = (i << 0x10) + i;
+ mmio_write_32((0xf712c000 + 0x140), data);
+ mmio_write_32((0xf712c000 + 0x144), data);
+ mmio_write_32((0xf712c000 + 0x148), data);
+ mmio_write_32((0xf712c000 + 0x14c), data);
+ mmio_write_32((0xf712c000 + 0x150), data);
+
+
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data |= 0x80000;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xfff7ffff;
+ mmio_write_32((0xf712c000 + 0x070), data);
+
+
+ mmio_write_32((0xf712c000 + 0x004), 0x8000);
+ mmio_write_32((0xf712c000 + 0x004), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x801);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if ((data & 0x400) == 0) {
+ mdelay(10);
+ return 0;
+ }
+ WARN("lpddr3 cat fail\n");
+ data = mmio_read_32((0xf712c000 + 0x1d4));
+ if ((data & 0x1f00) && ((data & 0x1f) == 0)) {
+ bdl[0] = mmio_read_32((0xf712c000 + 0x140));
+ bdl[1] = mmio_read_32((0xf712c000 + 0x144));
+ bdl[2] = mmio_read_32((0xf712c000 + 0x148));
+ bdl[3] = mmio_read_32((0xf712c000 + 0x14c));
+ bdl[4] = mmio_read_32((0xf712c000 + 0x150));
+ if ((!(bdl[0] & 0x1f001f)) || (!(bdl[1] & 0x1f001f)) ||
+ (!(bdl[2] & 0x1f001f)) || (!(bdl[3] & 0x1f001f)) ||
+ (!(bdl[4] & 0x1f001f))) {
+ WARN("lpddr3 cat deskew error\n");
+ if (i == 0x1f) {
+ WARN("addrnbdl is max\n");
+ return -EINVAL;
+ }
+ mmio_write_32((0xf712c000 + 0x008), 0x400);
+ } else {
+ WARN("lpddr3 cat other error1\n");
+ return -EINVAL;
+ }
+ } else {
+ WARN("lpddr3 cat other error2\n");
+ return -EINVAL;
+ }
+ }
+ return -EINVAL;
+}
+
+static void ddrx_rdet(void)
+{
+ unsigned int data, rdet, bdl[4];
+
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= 0xf800ffff;
+ data |= 0x8f0000;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+
+ data = mmio_read_32((0xf712c000 + 0x0dc));
+ data &= 0xfffffff0;
+ data |= 0xf;
+ mmio_write_32((0xf712c000 + 0x0dc), data);
+
+
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data |= 0x80000;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xfff7ffff;
+ mmio_write_32((0xf712c000 + 0x070), data);
+
+ mmio_write_32((0xf712c000 + 0x004), 0x8000);
+ mmio_write_32((0xf712c000 + 0x004), 0);
+
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= ~0xf0000000;
+ data |= 0x80000000;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+
+ mmio_write_32((0xf712c000 + 0x004), 0x101);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (!(data & 1));
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x100)
+ WARN("rdet lbs fail\n");
+
+ bdl[0] = mmio_read_32((0xf712c000 + 0x22c)) & 0x7f;
+ bdl[1] = mmio_read_32((0xf712c000 + 0x2ac)) & 0x7f;
+ bdl[2] = mmio_read_32((0xf712c000 + 0x32c)) & 0x7f;
+ bdl[3] = mmio_read_32((0xf712c000 + 0x3ac)) & 0x7f;
+ do {
+ data = mmio_read_32((0xf712c000 + 0x22c));
+ data &= ~0x7f;
+ data |= bdl[0];
+ mmio_write_32((0xf712c000 + 0x22c), data);
+ data = mmio_read_32((0xf712c000 + 0x2ac));
+ data &= ~0x7f;
+ data |= bdl[1];
+ mmio_write_32((0xf712c000 + 0x2ac), data);
+ data = mmio_read_32((0xf712c000 + 0x32c));
+ data &= ~0x7f;
+ data |= bdl[2];
+ mmio_write_32((0xf712c000 + 0x32c), data);
+ data = mmio_read_32((0xf712c000 + 0x3ac));
+ data &= ~0x7f;
+ data |= bdl[3];
+ mmio_write_32((0xf712c000 + 0x3ac), data);
+
+
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data |= 0x80000;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xfff7ffff;
+ mmio_write_32((0xf712c000 + 0x070), data);
+
+ mmio_write_32((0xf712c000 + 0x004), 0x8000);
+ mmio_write_32((0xf712c000 + 0x004), 0);
+
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= ~0xf0000000;
+ data |= 0x40000000;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x101);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ rdet = data & 0x100;
+ if (rdet) {
+ INFO("rdet ds fail\n");
+ mmio_write_32((0xf712c000 + 0x008), 0x100);
+ }
+ bdl[0]++;
+ bdl[1]++;
+ bdl[2]++;
+ bdl[3]++;
+ } while (rdet);
+
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= ~0xf0000000;
+ data |= 0x30000000;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+
+ mmio_write_32((0xf712c000 + 0x004), 0x101);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x100)
+ INFO("rdet rbs av fail\n");
+}
+
+static void ddrx_wdet(void)
+{
+ unsigned int data, wdet, zero_bdl = 0, dq[4];
+ int i;
+
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= ~0xf;
+ data |= 0xf;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data |= 0x80000;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= ~0x80000;
+ mmio_write_32((0xf712c000 + 0x070), data);
+
+ mmio_write_32((0xf712c000 + 0x004), 0x8000);
+ mmio_write_32((0xf712c000 + 0x004), 0);
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= ~0xf000;
+ data |= 0x8000;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x201);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x200)
+ INFO("wdet lbs fail\n");
+
+ dq[0] = mmio_read_32((0xf712c000 + 0x234)) & 0x1f00;
+ dq[1] = mmio_read_32((0xf712c000 + 0x2b4)) & 0x1f00;
+ dq[2] = mmio_read_32((0xf712c000 + 0x334)) & 0x1f00;
+ dq[3] = mmio_read_32((0xf712c000 + 0x3b4)) & 0x1f00;
+
+ do {
+ mmio_write_32((0xf712c000 + 0x234), dq[0]);
+ mmio_write_32((0xf712c000 + 0x2b4), dq[1]);
+ mmio_write_32((0xf712c000 + 0x334), dq[2]);
+ mmio_write_32((0xf712c000 + 0x3b4), dq[3]);
+
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data |= 0x80000;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= ~0x80000;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x8000);
+ mmio_write_32((0xf712c000 + 0x004), 0);
+
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= ~0xf000;
+ data |= 0x4000;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x201);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ wdet = data & 0x200;
+ if (wdet) {
+ INFO("wdet ds fail\n");
+ mmio_write_32((0xf712c000 + 0x008), 0x200);
+ }
+ mdelay(10);
+
+ for (i = 0; i < 4; i++) {
+ data = mmio_read_32((0xf712c000 + 0x210 + i * 0x80));
+ if ((!(data & 0x1f)) || (!(data & 0x1f00)) ||
+ (!(data & 0x1f0000)) || (!(data & 0x1f000000)))
+ zero_bdl = 1;
+ data = mmio_read_32((0xf712c000 + 0x214 + i * 0x80));
+ if ((!(data & 0x1f)) || (!(data & 0x1f00)) ||
+ (!(data & 0x1f0000)) || (!(data & 0x1f000000)))
+ zero_bdl = 1;
+ data = mmio_read_32((0xf712c000 + 0x218 + i * 0x80));
+ if (!(data & 0x1f))
+ zero_bdl = 1;
+ if (zero_bdl) {
+ if (i == 0)
+ dq[0] = dq[0] - 0x100;
+ if (i == 1)
+ dq[1] = dq[1] - 0x100;
+ if (i == 2)
+ dq[2] = dq[2] - 0x100;
+ if (i == 3)
+ dq[3] = dq[3] - 0x100;
+ }
+ }
+ } while (wdet);
+
+ data = mmio_read_32((0xf712c000 + 0x0d0));
+ data &= ~0xf000;
+ data |= 0x3000;
+ mmio_write_32((0xf712c000 + 0x0d0), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x201);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x200)
+ INFO("wdet rbs av fail\n");
+}
+
+void set_ddrc_150mhz(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7032000 + 0x580), 0x1);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x7);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= 0xfffffcff;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x31);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f);
+ mmio_write_32((0xf712c000 + 0x00c), 0xf0f);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x7200000);
+ mmio_write_32((0xf712c000 + 0x258), 0x720);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x358), 0x720);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0x30c82355);
+ mmio_write_32((0xf712c000 + 0x034), 0x62112bb);
+ mmio_write_32((0xf712c000 + 0x038), 0x20041022);
+ mmio_write_32((0xf712c000 + 0x03c), 0x63177497);
+ mmio_write_32((0xf712c000 + 0x040), 0x3008407);
+ mmio_write_32((0xf712c000 + 0x064), 0x10483);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x184;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= 0xbfffffff;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= ~0x10;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= ~0x2000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0x90420880);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x146d);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb3290d08);
+ mmio_write_32((0xf7128000 + 0x104), 0x9621821);
+ mmio_write_32((0xf7128000 + 0x108), 0x45009023);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf44c145);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x11080806);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 8) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x8)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 150mhz\n");
+}
+
+void set_ddrc_266mhz(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7032000 + 0x580), 0x3);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x1003);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= 0xfffffcff;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x31);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f);
+ mmio_write_32((0xf712c000 + 0x00c), 0xf0f);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x7200000);
+ mmio_write_32((0xf712c000 + 0x258), 0x720);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x358), 0x720);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0x510d4455);
+ mmio_write_32((0xf712c000 + 0x034), 0x8391ebb);
+ mmio_write_32((0xf712c000 + 0x038), 0x2005103c);
+ mmio_write_32((0xf712c000 + 0x03c), 0x6329950b);
+ mmio_write_32((0xf712c000 + 0x040), 0x300858c);
+ mmio_write_32((0xf712c000 + 0x064), 0x10483);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x184;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= 0xbfffffff;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= ~0x10;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= ~0x2000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0x90420880);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x146d);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb441d50d);
+ mmio_write_32((0xf7128000 + 0x104), 0xf721839);
+ mmio_write_32((0xf7128000 + 0x108), 0x5500f03f);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf486145);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x12080d06);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 8) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x8)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 266mhz\n");
+}
+
+void set_ddrc_400mhz(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7032000 + 0x580), 0x2);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x1003);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= 0xfffffcff;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x31);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x80000f0f);
+ mmio_write_32((0xf712c000 + 0x00c), 0xf0f);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x7200000);
+ mmio_write_32((0xf712c000 + 0x258), 0x720);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x358), 0x720);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x720);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0x75525655);
+ mmio_write_32((0xf712c000 + 0x034), 0xa552abb);
+ mmio_write_32((0xf712c000 + 0x038), 0x20071059);
+ mmio_write_32((0xf712c000 + 0x03c), 0x633e8591);
+ mmio_write_32((0xf712c000 + 0x040), 0x3008691);
+ mmio_write_32((0xf712c000 + 0x064), 0x10483);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x184;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= 0xbfffffff;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= ~0x10;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= ~0x2000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0x90420880);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x146d);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb55a9d12);
+ mmio_write_32((0xf7128000 + 0x104), 0x17721855);
+ mmio_write_32((0xf7128000 + 0x108), 0x7501505f);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf4ca245);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x13081306);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 8) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x8)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 400mhz\n");
+}
+
+void set_ddrc_533mhz(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7032000 + 0x580), 0x3);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x11111);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data |= 0x100;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x30);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x400);
+ mmio_write_32((0xf712c000 + 0x00c), 0x400);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x6400000);
+ mmio_write_32((0xf712c000 + 0x258), 0x640);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x640);
+ mmio_write_32((0xf712c000 + 0x358), 0x640);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x640);
+ mmio_write_32((0xf712c000 + 0x018), 0x0);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0x9dd87855);
+ mmio_write_32((0xf712c000 + 0x034), 0xa7138bb);
+ mmio_write_32((0xf712c000 + 0x038), 0x20091477);
+ mmio_write_32((0xf712c000 + 0x03c), 0x84534e16);
+ mmio_write_32((0xf712c000 + 0x040), 0x3008817);
+ mmio_write_32((0xf712c000 + 0x064), 0x106c3);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x305;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 0x40000000;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= ~0x10;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= ~0x2000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0xd0420900);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x0);
+ mmio_write_32((0xf712c000 + 0x004), 0x140f);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe) {
+ NOTICE("failed to init lpddr3 rank0 dram phy\n");
+ return;
+ }
+ cat_533mhz_800mhz();
+
+ mmio_write_32((0xf712c000 + 0x004), 0xf1);
+ mmio_write_32((0xf7128000 + 0x050), 0x100123);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0xb77b6718);
+ mmio_write_32((0xf7128000 + 0x104), 0x1e82a071);
+ mmio_write_32((0xf7128000 + 0x108), 0x9501c07e);
+ mmio_write_32((0xf7128000 + 0x10c), 0xaf50c255);
+ mmio_write_32((0xf7128000 + 0x110), 0x10b00000);
+ mmio_write_32((0xf7128000 + 0x114), 0x13181908);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+ ddrx_rdet();
+ ddrx_wdet();
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 533mhz\n");
+}
+
+void set_ddrc_800mhz(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7032000 + 0x580), 0x2);
+ mmio_write_32((0xf7032000 + 0x5a8), 0x1003);
+ data = mmio_read_32((0xf7032000 + 0x104));
+ data &= 0xfffffcff;
+ mmio_write_32((0xf7032000 + 0x104), data);
+
+ mmio_write_32((0xf7030000 + 0x050), 0x30);
+ mmio_write_32((0xf7030000 + 0x240), 0x5ffff);
+ mmio_write_32((0xf7030000 + 0x344), 0xf5ff);
+ mmio_write_32((0xf712c000 + 0x00c), 0x400);
+ mmio_write_32((0xf712c000 + 0x00c), 0x400);
+ mmio_write_32((0xf712c000 + 0x018), 0x7);
+ mmio_write_32((0xf712c000 + 0x090), 0x5400000);
+ mmio_write_32((0xf712c000 + 0x258), 0x540);
+ mmio_write_32((0xf712c000 + 0x2d8), 0x540);
+ mmio_write_32((0xf712c000 + 0x358), 0x540);
+ mmio_write_32((0xf712c000 + 0x3d8), 0x540);
+ mmio_write_32((0xf712c000 + 0x018), 0x0);
+ mmio_write_32((0xf712c000 + 0x0b0), 0xf00000f);
+ mmio_write_32((0xf712c000 + 0x0b4), 0xf);
+ mmio_write_32((0xf712c000 + 0x088), 0x3fff801);
+ mmio_write_32((0xf712c000 + 0x070), 0x8940000);
+
+ data = mmio_read_32((0xf712c000 + 0x078));
+ data |= 4;
+ mmio_write_32((0xf712c000 + 0x078), data);
+ mmio_write_32((0xf712c000 + 0x01c), 0x8000080);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xfffffffe;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ mmio_write_32((0xf712c000 + 0x1d4), 0xc0000);
+ mmio_write_32((0xf712c000 + 0x010), 0x500000f);
+ mmio_write_32((0xf712c000 + 0x014), 0x10);
+ data = mmio_read_32((0xf712c000 + 0x1e4));
+ data &= 0xffffff00;
+ mmio_write_32((0xf712c000 + 0x1e4), data);
+ mmio_write_32((0xf712c000 + 0x030), 0xe663ab77);
+ mmio_write_32((0xf712c000 + 0x034), 0xea952db);
+ mmio_write_32((0xf712c000 + 0x038), 0x200d1cb1);
+ mmio_write_32((0xf712c000 + 0x03c), 0xc67d0721);
+ mmio_write_32((0xf712c000 + 0x040), 0x3008aa1);
+ mmio_write_32((0xf712c000 + 0x064), 0x11a43);
+ mmio_write_32((0xf712c000 + 0x068), 0xff0a0000);
+ data = mmio_read_32((0xf712c000 + 0x070));
+ data &= 0xffff0000;
+ data |= 0x507;
+ mmio_write_32((0xf712c000 + 0x070), data);
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 0x40000000;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ data = mmio_read_32((0xf712c000 + 0x020));
+ data &= 0xffffffef;
+ mmio_write_32((0xf712c000 + 0x020), data);
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= 0xffffdfff;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf712c000 + 0x270), 0x3);
+ mmio_write_32((0xf712c000 + 0x2f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x370), 0x3);
+ mmio_write_32((0xf712c000 + 0x3f0), 0x3);
+ mmio_write_32((0xf712c000 + 0x048), 0xd0420900);
+
+ mmio_write_32((0xf7128000 + 0x040), 0x2001);
+ mmio_write_32((0xf712c000 + 0x004), 0x140f);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe) {
+ WARN("failed to init lpddr3 rank0 dram phy\n");
+ return;
+ }
+ cat_533mhz_800mhz();
+
+ mmio_write_32((0xf712c000 + 0x004), 0xf1);
+ mmio_write_32((0xf7128000 + 0x050), 0x100023);
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7128000 + 0x200), 0xa1000);
+
+ mmio_write_32((0xf7128000 + 0x100), 0x755a9d12);
+ mmio_write_32((0xf7128000 + 0x104), 0x1753b055);
+ mmio_write_32((0xf7128000 + 0x108), 0x7401505f);
+ mmio_write_32((0xf7128000 + 0x10c), 0x578ca244);
+ mmio_write_32((0xf7128000 + 0x110), 0x10700000);
+ mmio_write_32((0xf7128000 + 0x114), 0x13141306);
+ mmio_write_32((0xf7128000 + 0x118), 0x44);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe) {
+ NOTICE("fail to init ddr3 rank0\n");
+ return;
+ }
+ ddrx_rdet();
+ ddrx_wdet();
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data |= 1;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ mmio_write_32((0xf712c000 + 0x004), 0x21);
+ do {
+ data = mmio_read_32((0xf712c000 + 0x004));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf712c000 + 0x008));
+ if (data & 0x7fe)
+ NOTICE("ddr3 rank1 init failure\n");
+ else
+ INFO("ddr3 rank1 init pass\n");
+
+ data = mmio_read_32((0xf712c000 + 0x048));
+ data &= ~0xf;
+ mmio_write_32((0xf712c000 + 0x048), data);
+ INFO("succeed to set ddrc 800mhz\n");
+}
+
+static void ddrc_common_init(int freq)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7120000 + 0x020), 0x1);
+ mmio_write_32((0xf7120000 + 0x100), 0x1700);
+ mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+ mmio_write_32((0xf7121400 + 0x104), 0xf);
+ mmio_write_32((0xf7121800 + 0x104), 0xf);
+ mmio_write_32((0xf7121c00 + 0x104), 0xf);
+ mmio_write_32((0xf7122000 + 0x104), 0xf);
+ mmio_write_32((0xf7128000 + 0x02c), 0x6);
+ mmio_write_32((0xf7128000 + 0x020), 0x30003);
+ mmio_write_32((0xf7128000 + 0x028), 0x310201);
+ mmio_write_32((0xf712c000 + 0x1e4), 0xfe007600);
+ mmio_write_32((0xf7128000 + 0x01c), 0xaf001);
+
+
+ data = mmio_read_32((0xf7128000 + 0x280));
+ data |= 1 << 7;
+ mmio_write_32((0xf7128000 + 0x280), data);
+ mmio_write_32((0xf7128000 + 0x244), 0x3);
+
+ if (freq == DDR_FREQ_800M)
+ mmio_write_32((0xf7128000 + 0x240), 167 * (freq / 2) / 1024);
+ else
+ mmio_write_32((0xf7128000 + 0x240), 167 * freq / 1024);
+
+ data = mmio_read_32((0xf712c000 + 0x080));
+ data &= 0xffff;
+ data |= 0x4002000;
+ mmio_write_32((0xf712c000 + 0x080), data);
+ mmio_write_32((0xf7128000 + 0x000), 0x0);
+ do {
+ data = mmio_read_32((0xf7128000 + 0x294));
+ } while (data & 1);
+ mmio_write_32((0xf7128000 + 0x000), 0x2);
+}
+
+
+static int dienum_det_and_rowcol_cfg(void)
+{
+ unsigned int data;
+
+ mmio_write_32((0xf7128000 + 0x210), 0x87);
+ mmio_write_32((0xf7128000 + 0x218), 0x10000);
+ mmio_write_32((0xf7128000 + 0x00c), 0x1);
+ do {
+ data = mmio_read_32((0xf7128000 + 0x00c));
+ } while (data & 1);
+ data = mmio_read_32((0xf7128000 + 0x4a8)) & 0xfc;
+ switch (data) {
+ case 0x18:
+ mmio_write_32((0xf7128000 + 0x060), 0x132);
+ mmio_write_32((0xf7128000 + 0x064), 0x132);
+ mmio_write_32((0xf7120000 + 0x100), 0x1600);
+ mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x40000000);
+ break;
+ case 0x1c:
+ mmio_write_32((0xf7128000 + 0x060), 0x142);
+ mmio_write_32((0xf7128000 + 0x064), 0x142);
+ mmio_write_32((0xf7120000 + 0x100), 0x1700);
+ mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000);
+ break;
+ case 0x58:
+ mmio_write_32((0xf7128000 + 0x060), 0x133);
+ mmio_write_32((0xf7128000 + 0x064), 0x133);
+ mmio_write_32((0xf7120000 + 0x100), 0x1700);
+ mmio_write_32((0xf7120000 + 0x104), 0x71040004);
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000);
+ break;
+ default:
+ mmio_write_32(MEMORY_AXI_DDR_CAPACITY_ADDR, 0x80000000);
+ break;
+ }
+ if (!data)
+ return -EINVAL;
+ return 0;
+}
+
+static int detect_ddr_chip_info(void)
+{
+ unsigned int data, mr5, mr6, mr7;
+
+ mmio_write_32((0xf7128000 + 0x210), 0x57);
+ mmio_write_32((0xf7128000 + 0x218), 0x10000);
+ mmio_write_32((0xf7128000 + 0x00c), 0x1);
+
+ do {
+ data = mmio_read_32((0xf7128000 + 0x00c));
+ } while (data & 1);
+
+ data = mmio_read_32((0xf7128000 + 0x4a8));
+ mr5 = data & 0xff;
+ switch (mr5) {
+ case 1:
+ INFO("Samsung DDR\n");
+ break;
+ case 6:
+ INFO("Hynix DDR\n");
+ break;
+ case 3:
+ INFO("Elpida DDR\n");
+ break;
+ default:
+ INFO("DDR from other vendors\n");
+ break;
+ }
+
+ mmio_write_32((0xf7128000 + 0x210), 0x67);
+ mmio_write_32((0xf7128000 + 0x218), 0x10000);
+ mmio_write_32((0xf7128000 + 0x00c), 0x1);
+ do {
+ data = mmio_read_32((0xf7128000 + 0x00c));
+ } while (data & 1);
+ data = mmio_read_32((0xf7128000 + 0x4a8));
+ mr6 = data & 0xff;
+ mmio_write_32((0xf7128000 + 0x210), 0x77);
+ mmio_write_32((0xf7128000 + 0x218), 0x10000);
+ mmio_write_32((0xf7128000 + 0x00c), 0x1);
+ do {
+ data = mmio_read_32((0xf7128000 + 0x00c));
+ } while (data & 1);
+ data = mmio_read_32((0xf7128000 + 0x4a8));
+ mr7 = data & 0xff;
+ data = mr5 + (mr6 << 8) + (mr7 << 16);
+ return data;
+}
+
+void ddr_phy_reset(void)
+{
+ mmio_write_32(0xf7030340, 0xa000);
+ mmio_write_32(0xf7030344, 0xa000);
+}
+
+void lpddrx_save_ddl_para_bypass(uint32_t *ddr_ddl_para, unsigned int index)
+{
+ uint32_t value;
+ uint32_t cnt = index;
+ uint32_t i;
+
+ for (i = 0; i < 4; i++) {
+ value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ }
+}
+
+void lpddrx_save_ddl_para_mission(uint32_t *ddr_ddl_para, unsigned int index)
+{
+ uint32_t value;
+ uint32_t cnt = index;
+ uint32_t i;
+
+ value = mmio_read_32(0xf712c000 + 0x140);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x144);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x148);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x14c);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x150);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x1d4);
+ ddr_ddl_para[cnt++] = value;
+ for (i = 0; i < 4; i++) {
+ value = mmio_read_32(0xf712c000 + 0x210 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x214 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x218 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x21c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x220 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x224 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x228 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x22c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x230 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x234 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x238 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x23c + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x240 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x640 + i * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ }
+ value = mmio_read_32(0xf712c000 + 0x168);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x24c + 0 * 0x80);
+ ddr_ddl_para[cnt++] = value;
+ value = mmio_read_32(0xf712c000 + 0x24c + 2 * 0x80);
+ ddr_ddl_para[cnt++] = value;
+}
+
+int lpddr3_freq_init(int freq)
+{
+ set_ddrc_150mhz();
+ lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR, 0);
+ if (freq > DDR_FREQ_150M) {
+ ddr_phy_reset();
+ set_ddrc_266mhz();
+ lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16);
+ }
+ if (freq > DDR_FREQ_266M) {
+ ddr_phy_reset();
+ set_ddrc_400mhz();
+ lpddrx_save_ddl_para_bypass((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16 * 2);
+ }
+ if (freq > DDR_FREQ_400M) {
+ ddr_phy_reset();
+ set_ddrc_533mhz();
+ lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16 * 3);
+ }
+ if (freq > DDR_FREQ_533M) {
+ ddr_phy_reset();
+ set_ddrc_800mhz();
+ lpddrx_save_ddl_para_mission((uint32_t *)MEMORY_AXI_DDR_DDL_ADDR,
+ 16 * 3 + 61);
+ }
+ return 0;
+}
+
+static void init_ddr(int freq)
+{
+ unsigned int data;
+ int ret;
+
+
+ data = mmio_read_32((0xf7032000 + 0x030));
+ data |= 1;
+ mmio_write_32((0xf7032000 + 0x030), data);
+ data = mmio_read_32((0xf7032000 + 0x010));
+ data |= 1;
+ mmio_write_32((0xf7032000 + 0x010), data);
+
+ udelay(300);
+ do {
+ data = mmio_read_32((0xf7032000 + 0x030));
+ data &= 3 << 28;
+ } while (data != (3 << 28));
+ do {
+ data = mmio_read_32((0xf7032000 + 0x010));
+ data &= 3 << 28;
+ } while (data != (3 << 28));
+
+ ret = lpddr3_freq_init(freq);
+ if (ret)
+ return;
+}
+
+static void init_ddrc_qos(void)
+{
+ unsigned int port, data;
+
+ mmio_write_32((0xf7124000 + 0x088), 1);
+
+ port = 0;
+ mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210);
+ mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x11111111);
+ mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x11111111);
+ mmio_write_32((0xf7120000 + 0x400 + 0 * 0x10), 0x001d0007);
+
+ for (port = 3; port <= 4; port++) {
+ mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x1210);
+ mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x77777777);
+ mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x77777777);
+ }
+
+ port = 1;
+ mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000);
+ mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567);
+ mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567);
+
+ mmio_write_32((0xf7124000 + 0x1f0), 0);
+ mmio_write_32((0xf7124000 + 0x0bc), 0x3020100);
+ mmio_write_32((0xf7124000 + 0x0d0), 0x3020100);
+ mmio_write_32((0xf7124000 + 0x1f4), 0x01000100);
+ mmio_write_32((0xf7124000 + 0x08c + 0 * 4), 0xd0670402);
+ mmio_write_32((0xf7124000 + 0x068 + 0 * 4), 0x31);
+ mmio_write_32((0xf7124000 + 0x000), 0x7);
+
+ data = mmio_read_32((0xf7124000 + 0x09c));
+ data &= ~0xff0000;
+ data |= 0x400000;
+ mmio_write_32((0xf7124000 + 0x09c), data);
+ data = mmio_read_32((0xf7124000 + 0x0ac));
+ data &= ~0xff0000;
+ data |= 0x400000;
+ mmio_write_32((0xf7124000 + 0x0ac), data);
+ port = 2;
+ mmio_write_32((0xf7120000 + 0x200 + port * 0x10), 0x30000);
+ mmio_write_32((0xf7120000 + 0x204 + port * 0x10), 0x1234567);
+ mmio_write_32((0xf7120000 + 0x208 + port * 0x10), 0x1234567);
+
+
+ mmio_write_32((0xf7124000 + 0x09c), 0xff7fff);
+ mmio_write_32((0xf7124000 + 0x0a0), 0xff);
+ mmio_write_32((0xf7124000 + 0x0ac), 0xff7fff);
+ mmio_write_32((0xf7124000 + 0x0b0), 0xff);
+ mmio_write_32((0xf7124000 + 0x0bc), 0x3020100);
+ mmio_write_32((0xf7124000 + 0x0d0), 0x3020100);
+}
+
+void hikey_ddr_init(unsigned int ddr_freq)
+{
+ uint32_t data;
+
+ assert((ddr_freq == DDR_FREQ_150M) || (ddr_freq == DDR_FREQ_266M) ||
+ (ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_533M) ||
+ (ddr_freq == DDR_FREQ_800M));
+ init_pll();
+ init_freq();
+
+ init_ddr(ddr_freq);
+
+ ddrc_common_init(ddr_freq);
+ dienum_det_and_rowcol_cfg();
+ detect_ddr_chip_info();
+
+ if ((ddr_freq == DDR_FREQ_400M) || (ddr_freq == DDR_FREQ_800M)) {
+ data = mmio_read_32(0xf7032000 + 0x010);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x010, data);
+ } else if ((ddr_freq == DDR_FREQ_266M) || (ddr_freq == DDR_FREQ_533M)) {
+ data = mmio_read_32(0xf7032000 + 0x030);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x030, data);
+ } else {
+ data = mmio_read_32(0xf7032000 + 0x010);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x010, data);
+ data = mmio_read_32(0xf7032000 + 0x030);
+ data &= ~0x1;
+ mmio_write_32(0xf7032000 + 0x030, data);
+ }
+ dsb();
+ isb();
+
+ /*
+ * Test memory access. Do not use address 0x0 because the compiler
+ * may assume it is not a valid address and generate incorrect code
+ * (GCC 4.9.1 without -fno-delete-null-pointer-checks for instance).
+ */
+ mmio_write_32(0x4, 0xa5a55a5a);
+ INFO("ddr test value:0x%x\n", mmio_read_32(0x4));
+ init_ddrc_qos();
+}
diff --git a/plat/hisilicon/hikey/hikey_image_load.c b/plat/hisilicon/hikey/hikey_image_load.c
new file mode 100644
index 0000000..0ab1ca4
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_image_load.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/hisilicon/hikey/hikey_io_storage.c b/plat/hisilicon/hikey/hikey_io_storage.c
new file mode 100644
index 0000000..fd610d8
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_io_storage.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <lib/mmio.h>
+#include <lib/semihosting.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "hikey_private.h"
+
+#define EMMC_BLOCK_SHIFT 9
+
+/* Page 1024, since only a few pages before 2048 are used as partition table */
+#define SERIALNO_EMMC_OFFSET (1024 * 512)
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const io_dev_connector_t *emmc_dev_con;
+static uintptr_t emmc_dev_handle;
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+
+static int check_emmc(const uintptr_t spec);
+static int check_fip(const uintptr_t spec);
+
+static io_block_spec_t emmc_fip_spec;
+
+static const io_block_spec_t emmc_gpt_spec = {
+ .offset = 0,
+ .length = PLAT_PARTITION_BLOCK_SIZE *
+ (PLAT_PARTITION_MAX_ENTRIES / 4 + 2),
+};
+
+static const io_block_dev_spec_t emmc_dev_spec = {
+ /* It's used as temp buffer in block driver. */
+#ifdef IMAGE_BL1
+ .buffer = {
+ .offset = HIKEY_BL1_MMC_DATA_BASE,
+ .length = HIKEY_BL1_MMC_DATA_SIZE,
+ },
+#else
+ .buffer = {
+ .offset = HIKEY_MMC_DATA_BASE,
+ .length = HIKEY_MMC_DATA_SIZE,
+ },
+#endif
+ .ops = {
+ .read = mmc_read_blocks,
+ .write = mmc_write_blocks,
+ },
+ .block_size = MMC_BLOCK_SIZE,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+static const io_uuid_spec_t scp_bl2_uuid_spec = {
+ .uuid = UUID_SCP_FIRMWARE_SCP_BL2,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &emmc_dev_handle,
+ (uintptr_t)&emmc_fip_spec,
+ check_emmc
+ },
+ [SCP_BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_bl2_uuid_spec,
+ check_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ check_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ check_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ check_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ check_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ check_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ check_fip
+ },
+ [SCP_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [SCP_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_cert_uuid_spec,
+ check_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
+ check_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ check_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ check_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+ [GPT_IMAGE_ID] = {
+ &emmc_dev_handle,
+ (uintptr_t)&emmc_gpt_spec,
+ check_emmc
+ },
+};
+
+static int check_emmc(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_handle;
+
+ result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(emmc_dev_handle, spec, &local_handle);
+ if (result == 0)
+ io_close(local_handle);
+ }
+ return result;
+}
+
+static int check_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+void hikey_io_setup(void)
+{
+ int result;
+
+ result = register_io_dev_block(&emmc_dev_con);
+ assert(result == 0);
+
+ result = register_io_dev_fip(&fip_dev_con);
+ assert(result == 0);
+
+ result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec,
+ &emmc_dev_handle);
+ assert(result == 0);
+
+ result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
+ assert(result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)result;
+}
+
+int hikey_set_fip_addr(unsigned int image_id, const char *name)
+{
+ const partition_entry_t *entry;
+
+ if (emmc_fip_spec.length == 0) {
+ partition_init(GPT_IMAGE_ID);
+ entry = get_partition_entry(name);
+ if (entry == NULL) {
+ ERROR("Could NOT find the %s partition!\n", name);
+ return -ENOENT;
+ }
+ emmc_fip_spec.offset = entry->start;
+ emmc_fip_spec.length = entry->length;
+ }
+ return 0;
+}
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ assert(result == 0);
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ return result;
+}
diff --git a/plat/hisilicon/hikey/hikey_pm.c b/plat/hisilicon/hikey/hikey_pm.c
new file mode 100644
index 0000000..05c1e7f
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_pm.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <hi6220.h>
+#include <hikey_def.h>
+#include <hisi_ipc.h>
+#include <hisi_pwrc.h>
+#include <hisi_sram_map.h>
+
+#define CORE_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+static uintptr_t hikey_sec_entrypoint;
+
+static int hikey_pwr_domain_on(u_register_t mpidr)
+{
+ int cpu, cluster;
+ int curr_cluster;
+
+ cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ curr_cluster = MPIDR_AFFLVL1_VAL(read_mpidr());
+ if (cluster != curr_cluster)
+ hisi_ipc_cluster_on(cpu, cluster);
+
+ hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint);
+ hisi_pwrc_enable_debug(cpu, cluster);
+ hisi_ipc_cpu_on(cpu, cluster);
+
+ return 0;
+}
+
+static void hikey_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr;
+ int cpu, cluster;
+
+ mpidr = read_mpidr();
+ cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ cpu = MPIDR_AFFLVL0_VAL(mpidr);
+
+
+ /*
+ * Enable CCI coherency for this cluster.
+ * No need for locks as no other cpu is active at the moment.
+ */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ /* Zero the jump address in the mailbox for this cpu */
+ hisi_pwrc_set_core_bx_addr(cpu, cluster, 0);
+
+ /* Program the GIC per-cpu distributor or re-distributor interface */
+ gicv2_pcpu_distif_init();
+ /* Enable the GIC cpu interface */
+ gicv2_cpuif_enable();
+}
+
+void hikey_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr;
+ int cpu, cluster;
+
+ mpidr = read_mpidr();
+ cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ cpu = MPIDR_AFFLVL0_VAL(mpidr);
+
+ gicv2_cpuif_disable();
+ hisi_ipc_cpu_off(cpu, cluster);
+
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+ hisi_ipc_cluster_off(cpu, cluster);
+ }
+}
+
+static void hikey_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cpu = mpidr & MPIDR_CPU_MASK;
+ unsigned int cluster =
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+
+ /* Program the jump address for the target cpu */
+ hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint);
+
+ gicv2_cpuif_disable();
+
+ if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ hisi_ipc_cpu_suspend(cpu, cluster);
+ }
+
+ /* Perform the common cluster specific operations */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+ if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ hisi_pwrc_set_cluster_wfi(1);
+ hisi_pwrc_set_cluster_wfi(0);
+ hisi_ipc_psci_system_off();
+ } else
+ hisi_ipc_cluster_suspend(cpu, cluster);
+ }
+}
+
+static void hikey_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr;
+ unsigned int cluster, cpu;
+
+ /* Nothing to be done on waking up from retention from CPU level */
+ if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ /* Get the mpidr for this cpu */
+ mpidr = read_mpidr_el1();
+ cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT;
+ cpu = mpidr & MPIDR_CPU_MASK;
+
+ /* Enable CCI coherency for cluster */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ hisi_pwrc_set_core_bx_addr(cpu, cluster, 0);
+
+ if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+ } else {
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+ }
+}
+
+static void hikey_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+static void __dead2 hikey_system_off(void)
+{
+ NOTICE("%s: off system\n", __func__);
+
+ /* Pull down GPIO_0_0 to trigger PMIC shutdown */
+ mmio_write_32(0xF8001810, 0x2); /* Pinmux */
+ mmio_write_8(0xF8011400, 1); /* Pin direction */
+ mmio_write_8(0xF8011004, 0); /* Pin output value */
+
+ /* Wait for 2s to power off system by PMIC */
+ sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
+ mdelay(2000);
+
+ /*
+ * PMIC shutdown depends on two conditions: GPIO_0_0 (PWR_HOLD) low,
+ * and VBUS_DET < 3.6V. For HiKey, VBUS_DET is connected to VDD_4V2
+ * through Jumper 1-2. So, to complete shutdown, user needs to manually
+ * remove Jumper 1-2.
+ */
+ NOTICE("+------------------------------------------+\n");
+ NOTICE("| IMPORTANT: Remove Jumper 1-2 to shutdown |\n");
+ NOTICE("| DANGER: SoC is still burning. DANGER! |\n");
+ NOTICE("| Board will be reboot to avoid overheat |\n");
+ NOTICE("+------------------------------------------+\n");
+
+ /* Send the system reset request */
+ mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
+
+ wfi();
+ panic();
+}
+
+static void __dead2 hikey_system_reset(void)
+{
+ /* Send the system reset request */
+ mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
+ isb();
+ dsb();
+
+ wfi();
+ panic();
+}
+
+int hikey_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's possible to enter standby only on power level 0
+ * Ignore any other power level.
+ */
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] =
+ PLAT_MAX_RET_STATE;
+ } else {
+ for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ PLAT_MAX_OFF_STATE;
+ }
+
+ /*
+ * We expect the 'state id' to be zero.
+ */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+static int hikey_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
+ return PSCI_E_SUCCESS;
+
+ return PSCI_E_INVALID_ADDRESS;
+}
+
+static const plat_psci_ops_t hikey_psci_ops = {
+ .cpu_standby = NULL,
+ .pwr_domain_on = hikey_pwr_domain_on,
+ .pwr_domain_on_finish = hikey_pwr_domain_on_finish,
+ .pwr_domain_off = hikey_pwr_domain_off,
+ .pwr_domain_suspend = hikey_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = hikey_pwr_domain_suspend_finish,
+ .system_off = hikey_system_off,
+ .system_reset = hikey_system_reset,
+ .validate_power_state = hikey_validate_power_state,
+ .validate_ns_entrypoint = hikey_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = hikey_get_sys_suspend_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ hikey_sec_entrypoint = sec_entrypoint;
+
+ /*
+ * Initialize PSCI ops struct
+ */
+ *psci_ops = &hikey_psci_ops;
+ return 0;
+}
diff --git a/plat/hisilicon/hikey/hikey_private.h b/plat/hisilicon/hikey/hikey_private.h
new file mode 100644
index 0000000..b75bc72
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_private.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HIKEY_PRIVATE_H
+#define HIKEY_PRIVATE_H
+
+#include <common/bl_common.h>
+
+#define RANDOM_MAX 0x7fffffffffffffff
+#define RANDOM_MAGIC 0x9a4dbeaf
+
+enum {
+ DDR_FREQ_150M = 150 * 1000,
+ DDR_FREQ_266M = 266 * 1000,
+ DDR_FREQ_400M = 400 * 1000,
+ DDR_FREQ_533M = 533 * 1000,
+ DDR_FREQ_800M = 800 * 1000
+};
+
+struct random_serial_num {
+ uint64_t magic;
+ uint64_t data;
+ char serialno[32];
+};
+
+/*
+ * Function and variable prototypes
+ */
+void hikey_init_mmu_el1(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+void hikey_init_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+
+void hikey_ddr_init(unsigned int ddr_freq);
+void hikey_io_setup(void);
+
+void hikey_sp804_init(void);
+void hikey_gpio_init(void);
+void hikey_pmussi_init(void);
+void hikey_hi6553_init(void);
+void init_mmc0_pll(void);
+void reset_mmc0_clk(void);
+void init_media_clk(void);
+void init_mmc1_pll(void);
+void reset_mmc1_clk(void);
+void hikey_mmc_pll_init(void);
+void hikey_rtc_init(void);
+
+int hikey_get_partition_size(const char *arg, int left, char *response);
+int hikey_get_partition_type(const char *arg, int left, char *response);
+
+int hikey_erase(const char *arg);
+int hikey_flash(const char *arg);
+int hikey_oem(const char *arg);
+int hikey_reboot(const char *arg);
+void hikey_security_setup(void);
+
+const char *hikey_init_serialno(void);
+int hikey_read_serialno(struct random_serial_num *serialno);
+int hikey_write_serialno(struct random_serial_num *serialno);
+
+void init_acpu_dvfs(void);
+
+int hikey_set_fip_addr(unsigned int image_id, const char *name);
+
+#endif /* HIKEY_PRIVATE_H */
diff --git a/plat/hisilicon/hikey/hikey_rotpk.S b/plat/hisilicon/hikey/hikey_rotpk.S
new file mode 100644
index 0000000..f308eee
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_rotpk.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global hikey_rotpk_hash
+ .global hikey_rotpk_hash_end
+ .section .rodata.hikey_rotpk_hash, "a"
+hikey_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+hikey_rotpk_hash_end:
diff --git a/plat/hisilicon/hikey/hikey_security.c b/plat/hisilicon/hikey/hikey_security.c
new file mode 100644
index 0000000..4b95939
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_security.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <lib/utils_def.h>
+
+#include "hikey_private.h"
+
+#define PORTNUM_MAX 5
+
+#define MDDRC_SECURITY_BASE 0xF7121000
+
+struct int_en_reg {
+ unsigned in_en:1;
+ unsigned reserved:31;
+};
+
+struct rgn_map_reg {
+ unsigned rgn_base_addr:24;
+ unsigned rgn_size:6;
+ unsigned reserved:1;
+ unsigned rgn_en:1;
+};
+
+struct rgn_attr_reg {
+ unsigned sp:4;
+ unsigned security_inv:1;
+ unsigned reserved_0:3;
+ unsigned mid_en:1;
+ unsigned mid_inv:1;
+ unsigned reserved_1:6;
+ unsigned rgn_en:1;
+ unsigned subrgn_disable:16;
+};
+
+static volatile struct int_en_reg *get_int_en_reg(uint32_t base)
+{
+ uint64_t addr = base + 0x20;
+ return (struct int_en_reg *)addr;
+}
+
+static volatile struct rgn_map_reg *get_rgn_map_reg(uint32_t base, int region, int port)
+{
+ uint64_t addr = base + 0x100 + 0x10 * region + 0x400 * (uint64_t)port;
+ return (struct rgn_map_reg *)addr;
+}
+
+static volatile struct rgn_attr_reg *get_rgn_attr_reg(uint32_t base, int region,
+ int port)
+{
+ uint64_t addr = base + 0x104 + 0x10 * region + 0x400 * (uint64_t)port;
+ return (struct rgn_attr_reg *)addr;
+}
+
+/*
+ * Configure secure memory region
+ * region_size must be a power of 2 and at least 64KB
+ * region_base must be region_size aligned
+ */
+static void sec_protect(uint32_t region_base, uint32_t region_size,
+ int region)
+{
+ volatile struct int_en_reg *int_en;
+ volatile struct rgn_map_reg *rgn_map;
+ volatile struct rgn_attr_reg *rgn_attr;
+ uint32_t i = 0;
+
+ /* ensure secure region number is between 1-15 */
+ assert(region > 0 && region < 16);
+ /* ensure secure region size is a power of 2 >= 64KB */
+ assert(IS_POWER_OF_TWO(region_size) && region_size >= 0x10000);
+ /* ensure secure region address is aligned to region size */
+ assert(!(region_base & (region_size - 1)));
+
+ INFO("BL2: TrustZone: protecting %u bytes of memory at 0x%x\n", region_size,
+ region_base);
+
+ int_en = get_int_en_reg(MDDRC_SECURITY_BASE);
+ int_en->in_en = 0x1;
+
+ for (i = 0; i < PORTNUM_MAX; i++) {
+ rgn_map = get_rgn_map_reg(MDDRC_SECURITY_BASE, region, i);
+ rgn_attr = get_rgn_attr_reg(MDDRC_SECURITY_BASE, region, i);
+ rgn_map->rgn_base_addr = region_base >> 16;
+ rgn_attr->subrgn_disable = 0x0;
+ rgn_attr->sp = (i == 3) ? 0xC : 0x0;
+ rgn_map->rgn_size = __builtin_ffs(region_size) - 2;
+ rgn_map->rgn_en = 0x1;
+ }
+}
+
+/*******************************************************************************
+ * Initialize the secure environment.
+ ******************************************************************************/
+void hikey_security_setup(void)
+{
+ sec_protect(DDR_SEC_BASE, DDR_SEC_SIZE, 1);
+ sec_protect(DDR_SDP_BASE, DDR_SDP_SIZE, 2);
+}
diff --git a/plat/hisilicon/hikey/hikey_tbbr.c b/plat/hisilicon/hikey/hikey_tbbr.c
new file mode 100644
index 0000000..b7dda8d
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_tbbr.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char hikey_rotpk_hash[], hikey_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = hikey_rotpk_hash;
+ *key_len = hikey_rotpk_hash_end - hikey_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/hisilicon/hikey/hikey_topology.c b/plat/hisilicon/hikey/hikey_topology.c
new file mode 100644
index 0000000..7890eb7
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_topology.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <lib/psci/psci.h>
+
+/*
+ * The HiKey power domain tree descriptor. The cluster power domains
+ * are arranged so that when the PSCI generic code creates the power
+ * domain tree, the indices of the CPU power domain nodes it allocates
+ * match the linear indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char hikey_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ 1,
+ /* Number of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+ /* Number of children for the second cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+};
+
+/*******************************************************************************
+ * This function returns the HiKey topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return hikey_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
+}
diff --git a/plat/hisilicon/hikey/hisi_dvfs.c b/plat/hisilicon/hikey/hisi_dvfs.c
new file mode 100644
index 0000000..22a67fd
--- /dev/null
+++ b/plat/hisilicon/hikey/hisi_dvfs.c
@@ -0,0 +1,781 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <hi6220.h>
+#include <hi6553.h>
+#include <hisi_sram_map.h>
+
+#define ACPU_FREQ_MAX_NUM 5
+#define ACPU_OPP_NUM 7
+
+#define ACPU_VALID_VOLTAGE_MAGIC (0x5A5AC5C5)
+
+#define ACPU_WAIT_TIMEOUT (200)
+#define ACPU_WAIT_FOR_WFI_TIMOUT (2000)
+#define ACPU_DFS_STATE_CNT (0x10000)
+
+struct acpu_dvfs_sram_stru {
+ unsigned int magic;
+ unsigned int support_freq_num;
+ unsigned int support_freq_max;
+ unsigned int start_prof;
+ unsigned int vol[ACPU_OPP_NUM];
+};
+
+struct acpu_volt_cal_para {
+ unsigned int freq;
+ unsigned int ul_vol;
+ unsigned int dl_vol;
+ unsigned int core_ref_hpm;
+};
+
+struct ddr_volt_cal_para {
+ unsigned int freq;
+ unsigned int ul_vol;
+ unsigned int dl_vol;
+ unsigned int ddr_ref_hpm;
+};
+
+struct acpu_dvfs_opp_para {
+ unsigned int freq;
+ unsigned int acpu_clk_profile0;
+ unsigned int acpu_clk_profile1;
+ unsigned int acpu_vol_profile;
+ unsigned int acpu_pll_freq;
+ unsigned int acpu_pll_frac;
+};
+
+unsigned int efuse_acpu_freq[] = {
+ 1200000, 1250000, 1300000, 1350000,
+ 1400000, 1450000, 1500000, 1550000,
+ 1600000, 1650000, 1700000, 1750000,
+ 1800000, 1850000, 1900000, 1950000,
+};
+
+struct acpu_dvfs_opp_para hi6220_acpu_profile[] = {
+ { 208000, 0x61E5, 0x022, 0x3A, 0x5220102B, 0x05555555 },
+ { 432000, 0x10A6, 0x121, 0x3A, 0x5120102D, 0x10000005 },
+ { 729000, 0x2283, 0x100, 0x4A, 0x51101026, 0x10000005 },
+ { 960000, 0x1211, 0x100, 0x5B, 0x51101032, 0x10000005 },
+ { 1200000, 0x1211, 0x100, 0x6B, 0x5110207D, 0x10000005 },
+ { 1400000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 },
+ { 1500000, 0x1211, 0x100, 0x6B, 0x51101049, 0x10000005 },
+};
+
+struct acpu_dvfs_opp_para *acpu_dvfs_profile = hi6220_acpu_profile;
+struct acpu_dvfs_sram_stru *acpu_dvfs_sram_buf =
+ (struct acpu_dvfs_sram_stru *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR;
+
+static inline void write_reg_mask(uintptr_t addr,
+ uint32_t val, uint32_t mask)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(addr);
+ reg = (reg & ~(mask)) | val;
+ mmio_write_32(addr, reg);
+}
+
+static inline uint32_t read_reg_mask(uintptr_t addr,
+ uint32_t mask, uint32_t offset)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(addr);
+ reg &= (mask << offset);
+ return (reg >> offset);
+}
+
+static int acpu_dvfs_syspll_cfg(unsigned int prof_id)
+{
+ uint32_t reg0 = 0;
+ uint32_t count = 0;
+ uint32_t clk_div_status = 0;
+
+ /*
+ * step 1:
+ * - ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3;
+ * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1;
+ */
+ write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x3 << 12, 0x3 << 12);
+ write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 4, 0x1 << 4);
+
+ /*
+ * step 2:
+ * - ACPUSYSPLLCFG.acpu_syspll_div_cfg:
+ * 208MHz, set to 0x5;
+ * 500MHz, set to 0x2;
+ * other opps set to 0x1
+ */
+ if (prof_id == 0)
+ write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x5 << 0, 0x7 << 0);
+ else if (prof_id == 1)
+ write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x2 << 0, 0x7 << 0);
+ else
+ write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x1 << 0, 0x7 << 0);
+
+ /*
+ * step 3:
+ * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x3;
+ * - ACPU_SC_VD_CTRL.tune_en_dif = 0
+ * - ACPU_SC_VD_CTRL.tune_en_int = 0
+ * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1
+ * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1
+ */
+ clk_div_status = 0x3;
+ do {
+ reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3, 20);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: clk div status timeout!\n", __func__);
+ return -1;
+ }
+ } while (clk_div_status != reg0);
+
+ write_reg_mask(ACPU_SC_VD_CTRL, 0x0, (0x1 << 0) | (0x1 << 11));
+ write_reg_mask(PMCTRL_ACPUCLKDIV, 0x1 << 8, 0x3 << 8);
+ write_reg_mask(PMCTRL_ACPUPLLSEL, 0x1 << 0, 0x1 << 0);
+
+ return 0;
+}
+
+static void acpu_dvfs_clk_div_cfg(unsigned int prof_id,
+ unsigned int *cpuext_cfg,
+ unsigned int *acpu_ddr_cfg)
+{
+ if (prof_id == 0) {
+ write_reg_mask(PMCTRL_ACPUCLKDIV,
+ (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+ (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START),
+ (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+ (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START));
+ *cpuext_cfg = 0x1;
+ *acpu_ddr_cfg = 0x1;
+ } else if (prof_id == 1) {
+ write_reg_mask(PMCTRL_ACPUCLKDIV,
+ (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+ (0x1 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START),
+ (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+ (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START));
+ *cpuext_cfg = 0x1;
+ *acpu_ddr_cfg = 0x1;
+ } else {
+ /* ddr has not been inited */
+ write_reg_mask(PMCTRL_ACPUCLKDIV,
+ (0x1 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+ (0x0 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START),
+ (0x3 << SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START) |
+ (0x3 << SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START));
+ *cpuext_cfg = 0x1;
+ *acpu_ddr_cfg = 0x0;
+ }
+}
+
+static int acpu_dvfs_freq_ascend(unsigned int cur_prof, unsigned int tar_prof)
+{
+ unsigned int reg0 = 0;
+ unsigned int reg1 = 0;
+ unsigned int reg2 = 0;
+ unsigned int count = 0;
+ unsigned int cpuext_cfg_val = 0;
+ unsigned int acpu_ddr_cfg_val = 0;
+ int ret = 0;
+
+ /*
+ * step 1:
+ * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x3;
+ * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x1;
+ *
+ * step 2:
+ * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x5 (208MHz)
+ * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x2 (500MHz)
+ * - PMCTRL_ACPUSYSPLLCFG.acpu_syspll_div_cfg = 0x1 (Other OPPs)
+ *
+ * step 3:
+ * - ACPU_SC_CPU_STAT.clk_div_status_vd = 0x3;
+ * - ACPU_SC_VD_CTRL.tune_en_dif = 0x0;
+ * - ACPU_SC_VD_CTRL.tune_en_int = 0x0;
+ * - PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg = 0x1;
+ * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x1
+ */
+ ret = acpu_dvfs_syspll_cfg(cur_prof);
+ if (ret)
+ return -1;
+
+ /*
+ * step 4:
+ * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1,
+ SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: syspll sw status timeout\n", __func__);
+ return -1;
+ }
+ } while (reg0 != 0x1);
+
+ /* Enable VD functionality if > 800MHz */
+ if (acpu_dvfs_profile[tar_prof].freq > 800000) {
+
+ write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+ HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK);
+
+ /*
+ * step 5:
+ * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A;
+ * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB;
+ */
+ write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+ HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK);
+ write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL,
+ ACPU_SC_VD_MASK_PATTERN_VAL,
+ ACPU_SC_VD_MASK_PATTERN_MASK);
+
+ /*
+ * step 6:
+ * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF;
+ * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF;
+ * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF;
+ * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1;
+ */
+ mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF);
+ mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF);
+ mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF);
+ mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1);
+
+ /*
+ * step 7:
+ * - ACPU_SC_VD_CTRL.shift_table0 = 0x1;
+ * - ACPU_SC_VD_CTRL.shift_table1 = 0x3;
+ * - ACPU_SC_VD_CTRL.shift_table2 = 0x5;
+ * - ACPU_SC_VD_CTRL.shift_table3 = 0x6;
+ *
+ * step 8:
+ * - ACPU_SC_VD_CTRL.tune = 0x7;
+ */
+ write_reg_mask(ACPU_SC_VD_CTRL,
+ ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL,
+ ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK);
+ }
+
+ /* step 9: ACPUPLLCTRL.acpupll_en_cfg = 0x0 */
+ write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0,
+ 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START);
+
+ /* step 10: set PMCTRL_ACPUPLLFREQ and PMCTRL_ACPUPLLFRAC */
+ mmio_write_32(PMCTRL_ACPUPLLFREQ,
+ acpu_dvfs_profile[tar_prof].acpu_pll_freq);
+ mmio_write_32(PMCTRL_ACPUPLLFRAC,
+ acpu_dvfs_profile[tar_prof].acpu_pll_frac);
+
+ /*
+ * step 11:
+ * - wait for 1us;
+ * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1
+ */
+ count = 0;
+ while (count < ACPU_WAIT_TIMEOUT)
+ count++;
+
+ write_reg_mask(PMCTRL_ACPUPLLCTRL,
+ 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START,
+ 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START);
+
+ /* step 12: PMCTRL_ACPUVOLPMUADDR = 0x100da */
+ mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da);
+
+ /*
+ * step 13:
+ * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (208MHz);
+ * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x13 (500MHz);
+ * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x20 (798MHz);
+ * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1300MHz);
+ * - PMCTRL_ACPUDESTVOL.acpu_dest_vol = 0x3A (1500MHz);
+ */
+ write_reg_mask(PMCTRL_ACPUDESTVOL,
+ acpu_dvfs_profile[tar_prof].acpu_vol_profile,
+ ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1));
+
+ /*
+ * step 14:
+ * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol
+ * - Polling ACPUVOLTIMEOUT.acpu_vol_timeout == 0x1
+ * - Config PMCTRL_ACPUCLKDIV.acpu_ddr_clk_div_cfg
+ * - Config ACPUCLKDIV.cpuext_clk_div_cfg;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+ SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START);
+ reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+ SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START);
+ reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1,
+ SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: acpu destvol cfg timeout.\n", __func__);
+ return -1;
+ }
+ } while ((reg0 != reg1) || (reg2 != 0x1));
+
+ acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val);
+
+ /*
+ * step 15:
+ * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat;
+ * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat;
+ * - ACPUPLLCTRL.acpupll_timeout = 0x1;
+ * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+ SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START);
+ reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+ SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START);
+ reg2 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1,
+ SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: acpu clk div cfg timeout.\n", __func__);
+ return -1;
+ }
+ } while ((reg1 != cpuext_cfg_val) ||
+ (reg0 != acpu_ddr_cfg_val) ||
+ (reg2 != 0x1));
+
+ write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0,
+ 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START);
+
+ /*
+ * step 16:
+ * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1;
+ * - ACPU_SC_VD_CTRL.force_clk_en = 0x0;
+ * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0;
+ * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0;
+ * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0;
+ * - ACPU_SC_VD_CTRL.div_en_dif = 0x1;
+ * - ACPU_SC_VD_CTRL.tune_en_int = 0x1;
+ * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1;
+ * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0;
+ * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1,
+ SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: acpu pll sw status timeout.\n", __func__);
+ return -1;
+ }
+ } while (reg0 != 0x1);
+
+ if (acpu_dvfs_profile[tar_prof].freq > 800000)
+ write_reg_mask(ACPU_SC_VD_CTRL,
+ ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK);
+
+ write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0,
+ (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) |
+ (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START));
+
+ return 0;
+}
+
+static int acpu_dvfs_freq_descend(unsigned int cur_prof, unsigned int tar_prof)
+{
+ unsigned int reg0 = 0;
+ unsigned int reg1 = 0;
+ unsigned int reg2 = 0;
+ unsigned int count = 0;
+ unsigned int cpuext_cfg_val = 0;
+ unsigned int acpu_ddr_cfg_val = 0;
+ int ret = 0;
+
+ ret = acpu_dvfs_syspll_cfg(tar_prof);
+ if (ret)
+ return -1;
+
+ /*
+ * step 4:
+ * - Polling PMCTRL_ACPUPLLSEL.syspll_sw_stat == 0x1
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1, 2);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: syspll sw status timeout.\n", __func__);
+ return -1;
+ }
+ } while (reg0 != 0x1);
+
+ /*
+ * Step 5:
+ * - PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x0
+ */
+ write_reg_mask(PMCTRL_ACPUPLLCTRL, 0x0, 0x1 << 0);
+
+ /*
+ * step 6
+ * - Config PMCTRL_ACPUPLLFREQ and ACPUPLLFRAC
+ */
+ mmio_write_32(PMCTRL_ACPUPLLFREQ, acpu_dvfs_profile[tar_prof].acpu_pll_freq);
+ mmio_write_32(PMCTRL_ACPUPLLFRAC, acpu_dvfs_profile[tar_prof].acpu_pll_frac);
+
+ /*
+ * step 7:
+ * - Wait 1us;
+ * - Config PMCTRL_ACPUPLLCTRL.acpupll_en_cfg = 0x1
+ */
+ count = 0;
+ while (count < ACPU_WAIT_TIMEOUT)
+ count++;
+
+ write_reg_mask(PMCTRL_ACPUPLLCTRL,
+ 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START,
+ 0x1 << SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START);
+
+ /* Enable VD functionality if > 800MHz */
+ if (acpu_dvfs_profile[tar_prof].freq > 800000) {
+
+ write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+ HPM_OSC_DIV_VAL, HPM_OSC_DIV_MASK);
+
+ /*
+ * step 9:
+ * - ACPU_SC_VD_HPM_CTRL.hpm_dly_exp = 0xC7A;
+ * - ACPU_SC_VD_MASK_PATTERN_CTRL[12:0] = 0xCCB;
+ */
+ write_reg_mask(ACPU_SC_VD_HPM_CTRL,
+ HPM_DLY_EXP_VAL, HPM_DLY_EXP_MASK);
+ write_reg_mask(ACPU_SC_VD_MASK_PATTERN_CTRL,
+ ACPU_SC_VD_MASK_PATTERN_VAL,
+ ACPU_SC_VD_MASK_PATTERN_MASK);
+
+ /*
+ * step 10:
+ * - ACPU_SC_VD_DLY_TABLE0_CTRL = 0x1FFF;
+ * - ACPU_SC_VD_DLY_TABLE1_CTRL = 0x1FFFFFF;
+ * - ACPU_SC_VD_DLY_TABLE2_CTRL = 0x7FFFFFFF;
+ * - ACPU_SC_VD_DLY_FIXED_CTRL = 0x1;
+ */
+ mmio_write_32(ACPU_SC_VD_DLY_TABLE0_CTRL, 0x1FFF);
+ mmio_write_32(ACPU_SC_VD_DLY_TABLE1_CTRL, 0x1FFFFFF);
+ mmio_write_32(ACPU_SC_VD_DLY_TABLE2_CTRL, 0x7FFFFFFF);
+ mmio_write_32(ACPU_SC_VD_DLY_FIXED_CTRL, 0x1);
+
+ /*
+ * step 11:
+ * - ACPU_SC_VD_CTRL.shift_table0 = 0x1;
+ * - ACPU_SC_VD_CTRL.shift_table1 = 0x3;
+ * - ACPU_SC_VD_CTRL.shift_table2 = 0x5;
+ * - ACPU_SC_VD_CTRL.shift_table3 = 0x6;
+ *
+ * step 12:
+ * - ACPU_SC_VD_CTRL.tune = 0x7;
+ */
+ write_reg_mask(ACPU_SC_VD_CTRL,
+ ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL,
+ ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK);
+ }
+
+ /*
+ * step 13:
+ * - Pollig PMCTRL_ACPUPLLCTRL.acpupll_timeout == 0x1;
+ * - PMCTRL_ACPUPLLSEL.acpu_pllsw_cfg = 0x0;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUPLLCTRL, 0x1,
+ SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: acpupll timeout.\n", __func__);
+ return -1;
+ }
+ } while (reg0 != 0x1);
+
+ write_reg_mask(PMCTRL_ACPUPLLSEL, 0x0,
+ 0x1 << SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START);
+
+ /*
+ * step 14:
+ * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1;
+ * - ACPU_SC_VD_CTRL.force_clk_en = 0x0;
+ * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0;
+ * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0;
+ * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0;
+ * - ACPU_SC_VD_CTRL.div_en_dif = 0x1;
+ * - ACPU_SC_VD_CTRL.tune_en_int = 0x1;
+ * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUPLLSEL, 0x1,
+ SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: acpupll sw status timeout.\n", __func__);
+ return -1;
+ }
+ } while (reg0 != 0x1);
+
+ if (acpu_dvfs_profile[tar_prof].freq > 800000)
+ write_reg_mask(ACPU_SC_VD_CTRL,
+ ACPU_SC_VD_EN_ASIC_VAL, ACPU_SC_VD_EN_MASK);
+
+ /*
+ * step 15:
+ * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0;
+ * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0;
+ */
+ write_reg_mask(PMCTRL_ACPUSYSPLLCFG, 0x0,
+ (0x3 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START) |
+ (0x1 << SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START));
+
+ /*
+ * step 16:
+ * - Polling ACPU_SC_CPU_STAT.clk_div_status_vd == 0x0;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(ACPU_SC_CPU_STAT, 0x3,
+ ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: clk div status timeout.\n", __func__);
+ return -1;
+ }
+ } while (reg0 != 0x0);
+
+ acpu_dvfs_clk_div_cfg(tar_prof, &cpuext_cfg_val, &acpu_ddr_cfg_val);
+
+ /*
+ * step 17:
+ * - Polling PMCTRL_ACPUCLKDIV.cpuext_clk_div_stat;
+ * - Polling ACPUCLKDIV.acpu_ddr_clk_div_stat;
+ * - PMCTRL_ACPUVOLPMUADDR = 0x1006C;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+ SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START);
+ reg1 = read_reg_mask(PMCTRL_ACPUCLKDIV, 0x3,
+ SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: acpu clk div cfg timeout.\n", __func__);
+ return -1;
+ }
+ } while ((reg0 != cpuext_cfg_val) || (reg1 != acpu_ddr_cfg_val));
+
+ mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0x100da);
+
+ /*
+ * step 16:
+ * - Polling PMCTRL_ACPUPLLSEL.acpupll_sw_stat == 0x1;
+ * - ACPU_SC_VD_CTRL.force_clk_en = 0x0;
+ * - ACPU_SC_VD_CTRL.clk_dis_cnt_en = 0x0;
+ * - ACPU_SC_VD_CTRL.calibrate_en_ini = 0x0;
+ * - ACPU_SC_VD_CTRL.calibrate_en_dif = 0x0;
+ * - ACPU_SC_VD_CTRL.div_en_dif = 0x1;
+ * - ACPU_SC_VD_CTRL.tune_en_int = 0x1;
+ * - ACPU_SC_VD_CTRL.tune_en_dif = 0x1;
+ * - PMCTRL_ACPUSYSPLLCFG.acpu_subsys_clk_div_sw = 0x0;
+ * - ACPUSYSPLLCFG.acpu_syspll_clken_cfg = 0x0;
+ */
+ write_reg_mask(PMCTRL_ACPUDESTVOL,
+ acpu_dvfs_profile[tar_prof].acpu_vol_profile,
+ ((0x1 << (SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END + 1)) - 1));
+
+ /*
+ * step 19:
+ * - Polling PMCTRL_ACPUDESTVOL.acpu_vol_using == ACPUDESTVOL.acpu_dest_vol
+ * - ACPUVOLTIMEOUT.acpu_vol_timeout = 0x1;
+ */
+ count = 0;
+ do {
+ reg0 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+ SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START);
+ reg1 = read_reg_mask(PMCTRL_ACPUDESTVOL, 0x7F,
+ SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START);
+ reg2 = read_reg_mask(PMCTRL_ACPUVOLTTIMEOUT, 0x1,
+ SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START);
+ if ((count++) > ACPU_DFS_STATE_CNT) {
+ ERROR("%s: acpu destvol cfg timeout.\n", __func__);
+ return -1;
+ }
+ } while ((reg0 != reg1) || (reg2 != 0x1));
+
+ return 0;
+}
+
+int acpu_dvfs_target(unsigned int curr_prof, unsigned int target_prof)
+{
+ int ret = 0;
+
+ if (curr_prof == target_prof) {
+ INFO("%s: target_prof is equal curr_prof: is %d!\n",
+ __func__, curr_prof);
+ return 0;
+ }
+
+ if ((curr_prof >= ACPU_FREQ_MAX_NUM) ||
+ (target_prof >= ACPU_FREQ_MAX_NUM)) {
+ INFO("%s: invalid parameter %d %d\n",
+ __func__, curr_prof, target_prof);
+ return -1;
+ }
+
+ if (target_prof > acpu_dvfs_sram_buf->support_freq_num)
+ target_prof = acpu_dvfs_sram_buf->support_freq_num;
+
+ if (target_prof < curr_prof)
+ ret = acpu_dvfs_freq_descend(curr_prof, target_prof);
+ else if (target_prof > curr_prof)
+ ret = acpu_dvfs_freq_ascend(curr_prof, target_prof);
+
+ if (ret) {
+ ERROR("%s: acpu_dvfs_target failed!\n", __func__);
+ return -1;
+ }
+
+ /* Complete acpu dvfs setting and set magic number */
+ acpu_dvfs_sram_buf->start_prof = target_prof;
+ acpu_dvfs_sram_buf->magic = ACPU_VALID_VOLTAGE_MAGIC;
+
+ mmio_write_32(DDR_DFS_FREQ_ADDR, 800000);
+ return 0;
+}
+
+static int acpu_dvfs_set_freq(void)
+{
+ unsigned int i;
+ unsigned int curr_prof;
+ unsigned int target_prof;
+ unsigned int max_freq = 0;
+
+ max_freq = acpu_dvfs_sram_buf->support_freq_max;
+
+ for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++) {
+
+ if (max_freq == hi6220_acpu_profile[i].freq) {
+ target_prof = i;
+ break;
+ }
+ }
+
+ if (i == acpu_dvfs_sram_buf->support_freq_num) {
+ ERROR("%s: cannot found max freq profile\n", __func__);
+ return -1;
+ }
+
+ curr_prof = 0;
+ target_prof = i;
+
+ /* if max freq is 208MHz, do nothing */
+ if (curr_prof == target_prof)
+ return 0;
+
+ if (acpu_dvfs_target(curr_prof, target_prof)) {
+ ERROR("%s: set acpu freq failed!", __func__);
+ return -1;
+ }
+
+ INFO("%s: support freq num is %d\n",
+ __func__, acpu_dvfs_sram_buf->support_freq_num);
+ INFO("%s: start prof is 0x%x\n",
+ __func__, acpu_dvfs_sram_buf->start_prof);
+ INFO("%s: magic is 0x%x\n",
+ __func__, acpu_dvfs_sram_buf->magic);
+ INFO("%s: voltage:\n", __func__);
+ for (i = 0; i < acpu_dvfs_sram_buf->support_freq_num; i++)
+ INFO(" - %d: 0x%x\n", i, acpu_dvfs_sram_buf->vol[i]);
+
+ NOTICE("%s: set acpu freq success!", __func__);
+ return 0;
+}
+
+struct acpu_dvfs_volt_setting {
+ unsigned int magic;
+ unsigned int support_freq_num;
+ unsigned int support_freq_max;
+ unsigned int start_prof;
+ unsigned int vol[7];
+ unsigned int hmp_dly_threshold[7];
+};
+
+static void acpu_dvfs_volt_init(void)
+{
+ struct acpu_dvfs_volt_setting *volt;
+
+ /*
+ * - set default voltage;
+ * - set pmu address;
+ * - set voltage up and down step;
+ * - set voltage stable time;
+ */
+ mmio_write_32(PMCTRL_ACPUDFTVOL, 0x4a);
+ mmio_write_32(PMCTRL_ACPUVOLPMUADDR, 0xda);
+ mmio_write_32(PMCTRL_ACPUVOLUPSTEP, 0x1);
+ mmio_write_32(PMCTRL_ACPUVOLDNSTEP, 0x1);
+ mmio_write_32(PMCTRL_ACPUPMUVOLUPTIME, 0x60);
+ mmio_write_32(PMCTRL_ACPUPMUVOLDNTIME, 0x60);
+ mmio_write_32(PMCTRL_ACPUCLKOFFCFG, 0x1000);
+
+ volt = (void *)MEMORY_AXI_ACPU_FREQ_VOL_ADDR;
+ volt->magic = 0x5a5ac5c5;
+ volt->support_freq_num = 5;
+ volt->support_freq_max = 1200000;
+ volt->start_prof = 4;
+ volt->vol[0] = 0x49;
+ volt->vol[1] = 0x49;
+ volt->vol[2] = 0x50;
+ volt->vol[3] = 0x60;
+ volt->vol[4] = 0x78;
+ volt->vol[5] = 0x78;
+ volt->vol[6] = 0x78;
+
+ volt->hmp_dly_threshold[0] = 0x0;
+ volt->hmp_dly_threshold[1] = 0x0;
+ volt->hmp_dly_threshold[2] = 0x0;
+ volt->hmp_dly_threshold[3] = 0x0e8b0e45;
+ volt->hmp_dly_threshold[4] = 0x10691023;
+ volt->hmp_dly_threshold[5] = 0x10691023;
+ volt->hmp_dly_threshold[6] = 0x10691023;
+
+ INFO("%s: success!\n", __func__);
+}
+
+void init_acpu_dvfs(void)
+{
+ unsigned int i = 0;
+
+ INFO("%s: pmic version %d\n", __func__,
+ mmio_read_8(HI6553_VERSION_REG));
+
+ /* init parameters */
+ mmio_write_32(ACPU_CHIP_MAX_FREQ, efuse_acpu_freq[8]);
+ INFO("%s: ACPU_CHIP_MAX_FREQ=0x%x.\n",
+ __func__, mmio_read_32(ACPU_CHIP_MAX_FREQ));
+
+ /* set maximum support frequency to 1.2GHz */
+ for (i = 0; i < ACPU_FREQ_MAX_NUM; i++)
+ acpu_dvfs_sram_buf->vol[i] = hi6220_acpu_profile[i].acpu_vol_profile;
+
+ acpu_dvfs_sram_buf->support_freq_num = ACPU_FREQ_MAX_NUM;
+ acpu_dvfs_sram_buf->support_freq_max = 1200000;
+
+ /* init acpu dvfs */
+ acpu_dvfs_volt_init();
+ acpu_dvfs_set_freq();
+}
diff --git a/plat/hisilicon/hikey/hisi_ipc.c b/plat/hisilicon/hikey/hisi_ipc.c
new file mode 100644
index 0000000..43ee0b2
--- /dev/null
+++ b/plat/hisilicon/hikey/hisi_ipc.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <hisi_ipc.h>
+#include <hisi_sram_map.h>
+
+static int ipc_init;
+
+static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = {
+ {
+ HISI_IPC_MCU_INT_SRC_ACPU0_PD,
+ HISI_IPC_MCU_INT_SRC_ACPU1_PD,
+ HISI_IPC_MCU_INT_SRC_ACPU2_PD,
+ HISI_IPC_MCU_INT_SRC_ACPU3_PD,
+ },
+ {
+ HISI_IPC_MCU_INT_SRC_ACPU4_PD,
+ HISI_IPC_MCU_INT_SRC_ACPU5_PD,
+ HISI_IPC_MCU_INT_SRC_ACPU6_PD,
+ HISI_IPC_MCU_INT_SRC_ACPU7_PD,
+ }
+};
+
+int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu,
+ unsigned int cluster)
+{
+ unsigned int val = 0, cpu_val = 0;
+ int i;
+
+ val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+ val = val >> (cluster * 16);
+
+ for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) {
+
+ if (cpu == i)
+ continue;
+
+ cpu_val = (val >> (i * 4)) & 0xF;
+ if (cpu_val == 0x8)
+ return 0;
+ }
+
+ return 1;
+}
+
+int hisi_cpus_powered_off_besides_curr(unsigned int cpu)
+{
+ unsigned int val;
+
+ val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+ return (val == (0x8 << (cpu * 4)));
+}
+
+static void hisi_ipc_send(unsigned int ipc_num)
+{
+ if (!ipc_init) {
+ printf("error ipc base is null!!!\n");
+ return;
+ }
+
+ mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num);
+}
+
+void hisi_ipc_spin_lock(unsigned int signal)
+{
+ unsigned int hs_ctrl;
+
+ if (signal >= HISI_IPC_INT_SRC_NUM)
+ return;
+
+ do {
+ hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal));
+ } while (hs_ctrl);
+}
+
+void hisi_ipc_spin_unlock(unsigned int signal)
+{
+ if (signal >= HISI_IPC_INT_SRC_NUM)
+ return;
+
+ mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0);
+}
+
+void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster,
+ unsigned int mode)
+{
+ unsigned int val = 0;
+ unsigned int offset;
+
+ if (mode == HISI_IPC_PM_ON)
+ offset = cluster * 16 + cpu * 4;
+ else
+ offset = cluster * 16 + cpu * 4 + 1;
+
+ hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+ val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+ val |= (0x01 << offset);
+ mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
+ isb();
+ dsb();
+ hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+ hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster)
+{
+ hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON);
+}
+
+void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster)
+{
+ hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF);
+}
+
+void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster,
+ unsigned int mode)
+{
+ unsigned int val = 0;
+ unsigned int offset;
+
+ if (mode == HISI_IPC_PM_ON)
+ offset = cluster * 4;
+ else
+ offset = cluster * 4 + 1;
+
+ hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+ val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
+ val |= (0x01 << offset);
+ mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
+ isb();
+ dsb();
+ hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+ hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster)
+{
+ hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON);
+}
+
+void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster)
+{
+ hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF);
+}
+
+void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster)
+{
+ unsigned int val = 0;
+ unsigned int offset;
+
+ offset = cluster * 16 + cpu * 4 + 2;
+
+ hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+ val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
+ val |= (0x01 << offset);
+ mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
+ hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+ hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster)
+{
+ unsigned int val;
+ unsigned int offset;
+
+ offset = cluster * 4 + 1;
+
+ hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
+ if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) {
+ val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
+ val |= (0x01 << offset);
+ mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
+ }
+ hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
+
+ hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
+}
+
+void hisi_ipc_psci_system_off(void)
+{
+ hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD);
+}
+
+int hisi_ipc_init(void)
+{
+ ipc_init = 1;
+
+ mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8);
+ mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8);
+ return 0;
+}
diff --git a/plat/hisilicon/hikey/hisi_mcu.c b/plat/hisilicon/hikey/hisi_mcu.c
new file mode 100644
index 0000000..ac83bd8
--- /dev/null
+++ b/plat/hisilicon/hikey/hisi_mcu.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <hi6220.h>
+
+#define MCU_SECTION_MAX 30
+
+enum MCU_IMAGE_SEC_TYPE_ENUM {
+ MCU_IMAGE_SEC_TYPE_TEXT = 0, /* text section */
+ MCU_IMAGE_SEC_TYPE_DATA, /* data section */
+ MCU_IMAGE_SEC_TYPE_BUTT
+};
+
+enum MCU_IMAGE_SEC_LOAD_ENUM {
+ MCU_IMAGE_SEC_LOAD_STATIC = 0,
+ MCU_IMAGE_SEC_LOAD_DYNAMIC,
+ MCU_IMAGE_SEC_LOAD_BUFFER,
+ MCU_IMAGE_SEC_LOAD_MODEM_ENTRY,
+ MCU_IMAGE_SEC_LOAD_BUTT
+};
+
+struct mcu_image_sec {
+ unsigned short serial;
+ char type;
+ char load_attr;
+ uint32_t src_offset; /* offset in image */
+ uint32_t dst_offset; /* offset in memory */
+ uint32_t size;
+};
+
+struct mcu_image_head {
+ char time_stamp[24];
+ uint32_t image_size;
+ uint32_t secs_num;
+ struct mcu_image_sec secs[MCU_SECTION_MAX];
+};
+
+#define SOC_SRAM_M3_BASE_ADDR (0xF6000000)
+
+#define MCU_SRAM_SIZE (0x0000C000)
+#define MCU_CACHE_SIZE (0x00004000)
+#define MCU_CODE_SIZE (MCU_SRAM_SIZE - MCU_CACHE_SIZE)
+
+#define MCU_SYS_MEM_ADDR (0x05E00000)
+#define MCU_SYS_MEM_SIZE (0x00100000)
+
+static uint32_t mcu2ap_addr(uint32_t mcu_addr)
+{
+ if (mcu_addr < MCU_CODE_SIZE)
+ return (mcu_addr + SOC_SRAM_M3_BASE_ADDR);
+ else if ((mcu_addr >= MCU_SRAM_SIZE) &&
+ (mcu_addr < MCU_SRAM_SIZE + MCU_SYS_MEM_SIZE))
+ return mcu_addr - MCU_SRAM_SIZE + MCU_SYS_MEM_ADDR;
+ else
+ return mcu_addr;
+}
+
+static int is_binary_header_invalid(struct mcu_image_head *head,
+ unsigned int length)
+{
+ /* invalid cases */
+ if ((head->image_size == 0) ||
+ (head->image_size > length) ||
+ (head->secs_num > MCU_SECTION_MAX) ||
+ (head->secs_num == 0))
+ return 1;
+
+ return 0;
+}
+
+static int is_binary_section_invalid(struct mcu_image_sec *sec,
+ struct mcu_image_head *head)
+{
+ unsigned long ap_dst_offset = 0;
+
+ if ((sec->serial >= head->secs_num) ||
+ (sec->src_offset + sec->size > head->image_size))
+ return 1;
+
+ if ((sec->type >= MCU_IMAGE_SEC_TYPE_BUTT) ||
+ (sec->load_attr >= MCU_IMAGE_SEC_LOAD_BUTT))
+ return 1;
+
+ ap_dst_offset = mcu2ap_addr(sec->dst_offset);
+ if ((ap_dst_offset >= SOC_SRAM_M3_BASE_ADDR) &&
+ (ap_dst_offset < SOC_SRAM_M3_BASE_ADDR + 0x20000 - sec->size))
+ return 0;
+ else if ((ap_dst_offset >= MCU_SYS_MEM_ADDR) &&
+ (ap_dst_offset < MCU_SYS_MEM_ADDR + MCU_SYS_MEM_SIZE - sec->size))
+ return 0;
+ else if ((ap_dst_offset >= 0xfff8e000) &&
+ (ap_dst_offset < 0xfff91c00 - sec->size))
+ return 0;
+
+ ERROR("%s: mcu destination address invalid.\n", __func__);
+ ERROR("%s: number=%d, dst offset=%d size=%d\n",
+ __func__, sec->serial, sec->dst_offset, sec->size);
+ return 1;
+}
+
+void hisi_mcu_enable_sram(void)
+{
+ mmio_write_32(AO_SC_PERIPH_CLKEN4,
+ AO_SC_PERIPH_CLKEN4_HCLK_IPC_S |
+ AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS);
+
+ /* set register to enable dvfs which is used by mcu */
+ mmio_write_32(PERI_SC_RESERVED8_ADDR, 0x0A001022);
+
+ /* mcu mem is powered on, need de-assert reset */
+ mmio_write_32(AO_SC_PERIPH_RSTDIS4,
+ AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N);
+
+ /* enable mcu hclk */
+ mmio_write_32(AO_SC_PERIPH_CLKEN4,
+ AO_SC_PERIPH_CLKEN4_HCLK_MCU |
+ AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP);
+}
+
+void hisi_mcu_start_run(void)
+{
+ unsigned int val;
+
+ /* set mcu ddr remap configuration */
+ mmio_write_32(AO_SC_MCU_SUBSYS_CTRL2, MCU_SYS_MEM_ADDR);
+
+ /* de-assert reset for mcu and to run */
+ mmio_write_32(AO_SC_PERIPH_RSTDIS4,
+ AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N |
+ AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N |
+ AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N |
+ AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N);
+
+ val = mmio_read_32(AO_SC_SYS_CTRL2);
+ mmio_write_32(AO_SC_SYS_CTRL2,
+ val | AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR);
+
+ INFO("%s: AO_SC_SYS_CTRL2=%x\n", __func__,
+ mmio_read_32(AO_SC_SYS_CTRL2));
+}
+
+int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size)
+{
+ unsigned int i;
+ struct mcu_image_head *head;
+ char *buf;
+
+ head = (struct mcu_image_head *)image_base;
+ if (is_binary_header_invalid(head, image_size)) {
+ ERROR("Invalid %s image header.\n", head->time_stamp);
+ return -1;
+ }
+
+ buf = (char *)head;
+ for (i = 0; i < head->secs_num; i++) {
+
+ int *src, *dst;
+
+ /* check the sections */
+ if (is_binary_section_invalid(&head->secs[i], head)) {
+ ERROR("Invalid mcu section.\n");
+ return -1;
+ }
+
+ /* check if the section is static-loaded */
+ if (head->secs[i].load_attr != MCU_IMAGE_SEC_LOAD_STATIC)
+ continue;
+
+ /* copy the sections */
+ src = (int *)(intptr_t)(buf + head->secs[i].src_offset);
+ dst = (int *)(intptr_t)mcu2ap_addr(head->secs[i].dst_offset);
+
+ memcpy((void *)dst, (void *)src, head->secs[i].size);
+
+ INFO("%s: mcu sections %d:\n", __func__, i);
+ INFO("%s: src = 0x%x\n",
+ __func__, (unsigned int)(uintptr_t)src);
+ INFO("%s: dst = 0x%x\n",
+ __func__, (unsigned int)(uintptr_t)dst);
+ INFO("%s: size = %d\n", __func__, head->secs[i].size);
+
+ INFO("%s: [SRC 0x%x] 0x%x 0x%x 0x%x 0x%x\n",
+ __func__, (unsigned int)(uintptr_t)src,
+ src[0], src[1], src[2], src[3]);
+ INFO("%s: [DST 0x%x] 0x%x 0x%x 0x%x 0x%x\n",
+ __func__, (unsigned int)(uintptr_t)dst,
+ dst[0], dst[1], dst[2], dst[3]);
+ }
+
+ return 0;
+}
diff --git a/plat/hisilicon/hikey/hisi_pwrc.c b/plat/hisilicon/hikey/hisi_pwrc.c
new file mode 100644
index 0000000..e2e3db7
--- /dev/null
+++ b/plat/hisilicon/hikey/hisi_pwrc.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <hi6220_regs_acpu.h>
+#include <hi6220_regs_ao.h>
+#include <hisi_ipc.h>
+#include <hisi_pwrc.h>
+#include <hisi_sram_map.h>
+
+#define CLUSTER_CORE_COUNT (4)
+#define CLUSTER_CORE_MASK ((1 << CLUSTER_CORE_COUNT) - 1)
+
+void hisi_pwrc_set_core_bx_addr(unsigned int core, unsigned int cluster,
+ uintptr_t entry_point)
+{
+ uintptr_t *core_entry = (uintptr_t *)PWRCTRL_ACPU_ASM_D_ARM_PARA_AD;
+ unsigned int i;
+
+ if (!core_entry) {
+ INFO("%s: core entry point is null!\n", __func__);
+ return;
+ }
+
+ i = cluster * CLUSTER_CORE_COUNT + core;
+ mmio_write_64((uintptr_t)(core_entry + i), entry_point);
+}
+
+void hisi_pwrc_set_cluster_wfi(unsigned int cluster)
+{
+ unsigned int reg = 0;
+
+ if (cluster == 0) {
+ reg = mmio_read_32(ACPU_SC_SNOOP_PWD);
+ reg |= PD_DETECT_START0;
+ mmio_write_32(ACPU_SC_SNOOP_PWD, reg);
+ } else if (cluster == 1) {
+ reg = mmio_read_32(ACPU_SC_SNOOP_PWD);
+ reg |= PD_DETECT_START1;
+ mmio_write_32(ACPU_SC_SNOOP_PWD, reg);
+ }
+}
+
+void hisi_pwrc_enable_debug(unsigned int core, unsigned int cluster)
+{
+ unsigned int val, enable;
+
+ enable = 1U << (core + PDBGUP_CLUSTER1_SHIFT * cluster);
+
+ /* Enable debug module */
+ val = mmio_read_32(ACPU_SC_PDBGUP_MBIST);
+ mmio_write_32(ACPU_SC_PDBGUP_MBIST, val | enable);
+ do {
+ /* RAW barrier */
+ val = mmio_read_32(ACPU_SC_PDBGUP_MBIST);
+ } while (!(val & enable));
+}
+
+int hisi_pwrc_setup(void)
+{
+ unsigned int reg, sec_entrypoint;
+ extern char pm_asm_code[], pm_asm_code_end[];
+ extern char v7_asm[], v7_asm_end[];
+
+ sec_entrypoint = PWRCTRL_ACPU_ASM_CODE_BASE;
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(0), sec_entrypoint >> 2);
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(1), sec_entrypoint >> 2);
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(2), sec_entrypoint >> 2);
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(3), sec_entrypoint >> 2);
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(4), sec_entrypoint >> 2);
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(5), sec_entrypoint >> 2);
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(6), sec_entrypoint >> 2);
+ mmio_write_32(ACPU_SC_CPUx_RVBARADDR(7), sec_entrypoint >> 2);
+
+ memset((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, 0, 0x400);
+ memcpy((void *)PWRCTRL_ACPU_ASM_SPACE_ADDR, (void *)v7_asm,
+ v7_asm_end - v7_asm);
+
+ memcpy((void *)PWRCTRL_ACPU_ASM_CODE_BASE, (void *)pm_asm_code,
+ pm_asm_code_end - pm_asm_code);
+
+ reg = mmio_read_32(AO_SC_SYS_CTRL1);
+ /* Remap SRAM address for ACPU */
+ reg |= AO_SC_SYS_CTRL1_REMAP_SRAM_AARM |
+ AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK;
+
+ /* Enable reset signal for watchdog */
+ reg |= AO_SC_SYS_CTRL1_AARM_WD_RST_CFG |
+ AO_SC_SYS_CTRL1_AARM_WD_RST_CFG_MSK;
+ mmio_write_32(AO_SC_SYS_CTRL1, reg);
+
+ return 0;
+}
diff --git a/plat/hisilicon/hikey/hisi_pwrc_sram.S b/plat/hisilicon/hikey/hisi_pwrc_sram.S
new file mode 100644
index 0000000..62542f2
--- /dev/null
+++ b/plat/hisilicon/hikey/hisi_pwrc_sram.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cortex_a53.h>
+#include <hi6220.h>
+#include <hisi_sram_map.h>
+
+ .global pm_asm_code
+ .global pm_asm_code_end
+ .global v7_asm
+ .global v7_asm_end
+
+func pm_asm_code _align=3
+ mov x0, 0
+ msr oslar_el1, x0
+
+ mrs x0, CORTEX_A53_CPUACTLR_EL1
+ bic x0, x0, #(CORTEX_A53_CPUACTLR_EL1_RADIS | \
+ CORTEX_A53_CPUACTLR_EL1_L1RADIS)
+ orr x0, x0, #0x180000
+ orr x0, x0, #0xe000
+ msr CORTEX_A53_CPUACTLR_EL1, x0
+
+ mrs x3, actlr_el3
+ orr x3, x3, #ACTLR_EL3_L2ECTLR_BIT
+ msr actlr_el3, x3
+
+ mrs x3, actlr_el2
+ orr x3, x3, #ACTLR_EL2_L2ECTLR_BIT
+ msr actlr_el2, x3
+
+ ldr x3, =PWRCTRL_ACPU_ASM_D_ARM_PARA_AD
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+pen: ldr x4, [x3, x0, LSL #3]
+ cbz x4, pen
+
+ mov x0, #0x0
+ mov x1, #0x0
+ mov x2, #0x0
+ mov x3, #0x0
+ br x4
+
+ .ltorg
+
+pm_asm_code_end:
+endfunc pm_asm_code
+
+ /*
+ * By default, all cores in Hi6220 reset with aarch32 mode.
+ * Now hardcode ARMv7 instructions to execute warm reset for
+ * switching aarch64 mode.
+ */
+ .align 3
+ .section .rodata.v7_asm, "aS"
+v7_asm:
+ .word 0xE1A00000 // nop
+ .word 0xE3A02003 // mov r2, #3
+ .word 0xEE0C2F50 // mcr 15, 0, r2, cr12, cr0, {2}
+ .word 0xE320F003 // wfi
+
+ .ltorg
+v7_asm_end:
diff --git a/plat/hisilicon/hikey/hisi_sip_svc.c b/plat/hisilicon/hikey/hisi_sip_svc.c
new file mode 100644
index 0000000..3cd1bd0
--- /dev/null
+++ b/plat/hisilicon/hikey/hisi_sip_svc.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/pmf/pmf.h>
+#include <tools_share/uuid.h>
+
+#include <hisi_sip_svc.h>
+
+/* Hisi SiP Service UUID */
+DEFINE_SVC_UUID2(hisi_sip_svc_uid,
+ 0x74df99e5, 0x8276, 0xaa40, 0x9f, 0xf8,
+ 0xc0, 0x85, 0x52, 0xbc, 0x39, 0x3f);
+
+static int hisi_sip_setup(void)
+{
+ if (pmf_setup() != 0)
+ return 1;
+ return 0;
+}
+
+/*
+ * This function handles Hisi defined SiP Calls
+ */
+static uintptr_t hisi_sip_handler(unsigned int smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ int call_count = 0;
+
+ /*
+ * Dispatch PMF calls to PMF SMC handler and return its return
+ * value
+ */
+ if (is_pmf_fid(smc_fid)) {
+ return pmf_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+ handle, flags);
+ }
+
+ switch (smc_fid) {
+ case HISI_SIP_SVC_CALL_COUNT:
+ /* PMF calls */
+ call_count += PMF_NUM_SMC_CALLS;
+
+ /* State switch call */
+ call_count += 1;
+
+ SMC_RET1(handle, call_count);
+
+ case HISI_SIP_SVC_UID:
+ /* Return UID to the caller */
+ SMC_UUID_RET(handle, hisi_sip_svc_uid);
+
+ case HISI_SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ SMC_RET2(handle, HISI_SIP_SVC_VERSION_MAJOR, HISI_SIP_SVC_VERSION_MINOR);
+
+ default:
+ WARN("Unimplemented HISI SiP Service Call: 0x%x \n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+}
+
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ hisi_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ hisi_sip_setup,
+ hisi_sip_handler
+);
diff --git a/plat/hisilicon/hikey/include/hi6220.h b/plat/hisilicon/hikey/include/hi6220.h
new file mode 100644
index 0000000..f67ee5c
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hi6220.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI6220_H
+#define HI6220_H
+
+#include <hi6220_regs_acpu.h>
+#include <hi6220_regs_ao.h>
+#include <hi6220_regs_peri.h>
+#include <hi6220_regs_pin.h>
+#include <hi6220_regs_pmctrl.h>
+
+/*******************************************************************************
+ * Implementation defined ACTLR_EL2 bit definitions
+ ******************************************************************************/
+#define ACTLR_EL2_L2ACTLR_BIT (1 << 6)
+#define ACTLR_EL2_L2ECTLR_BIT (1 << 5)
+#define ACTLR_EL2_L2CTLR_BIT (1 << 4)
+#define ACTLR_EL2_CPUECTLR_BIT (1 << 1)
+#define ACTLR_EL2_CPUACTLR_BIT (1 << 0)
+
+/*******************************************************************************
+ * Implementation defined ACTLR_EL3 bit definitions
+ ******************************************************************************/
+#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
+#define ACTLR_EL3_L2ECTLR_BIT (1 << 5)
+#define ACTLR_EL3_L2CTLR_BIT (1 << 4)
+#define ACTLR_EL3_CPUECTLR_BIT (1 << 1)
+#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define CCI400_BASE 0xF6E90000
+#define CCI400_SL_IFACE3_CLUSTER_IX 3
+#define CCI400_SL_IFACE4_CLUSTER_IX 4
+
+#define DWMMC0_BASE 0xF723D000
+
+#define DWUSB_BASE 0xF72C0000
+
+#define EDMAC_BASE 0xf7370000
+#define EDMAC_SEC_CTRL (EDMAC_BASE + 0x694)
+#define EDMAC_AXI_CONF(x) (EDMAC_BASE + 0x820 + (x << 6))
+#define EDMAC_SEC_CTRL_INTR_SEC (1 << 1)
+#define EDMAC_SEC_CTRL_GLOBAL_SEC (1 << 0)
+#define EDMAC_CHANNEL_NUMS 16
+
+#define PMUSSI_BASE 0xF8000000
+
+#define SP804_TIMER0_BASE 0xF8008000
+
+#define GPIO0_BASE 0xF8011000
+#define GPIO1_BASE 0xF8012000
+#define GPIO2_BASE 0xF8013000
+#define GPIO3_BASE 0xF8014000
+#define GPIO4_BASE 0xF7020000
+#define GPIO5_BASE 0xF7021000
+#define GPIO6_BASE 0xF7022000
+#define GPIO7_BASE 0xF7023000
+#define GPIO8_BASE 0xF7024000
+#define GPIO9_BASE 0xF7025000
+#define GPIO10_BASE 0xF7026000
+#define GPIO11_BASE 0xF7027000
+#define GPIO12_BASE 0xF7028000
+#define GPIO13_BASE 0xF7029000
+#define GPIO14_BASE 0xF702A000
+#define GPIO15_BASE 0xF702B000
+#define GPIO16_BASE 0xF702C000
+#define GPIO17_BASE 0xF702D000
+#define GPIO18_BASE 0xF702E000
+#define GPIO19_BASE 0xF702F000
+
+#endif /* HI6220_H */
diff --git a/plat/hisilicon/hikey/include/hi6220_regs_acpu.h b/plat/hisilicon/hikey/include/hi6220_regs_acpu.h
new file mode 100644
index 0000000..a43db68
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hi6220_regs_acpu.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI6220_REGS_ACPU_H
+#define HI6220_REGS_ACPU_H
+
+#define ACPU_CTRL_BASE 0xF6504000
+
+#define ACPU_SC_CPU_CTRL (ACPU_CTRL_BASE + 0x000)
+#define ACPU_SC_CPU_STAT (ACPU_CTRL_BASE + 0x008)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2 (1 << 0)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFIL2_SHIFT (0)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0 (1 << 1)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI0_SHIFT (1)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1 (1 << 2)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI1_SHIFT (2)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2 (1 << 3)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI2_SHIFT (3)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3 (1 << 4)
+#define ACPU_SC_CPU_STAT_SC_STANDBYWFI3_SHIFT (4)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2 (1 << 8)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFIL2_SHIFT (8)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI (1 << 9)
+#define ACPU_SC_CPU_STAT_A53_1_STANDBYWFI_SHIFT (9)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE0 (1 << 16)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE0_SHIFT (16)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE1 (1 << 17)
+#define ACPU_SC_CPU_STAT_L2FLSHUDONE1_SHIFT (17)
+#define ACPU_SC_CPU_STAT_CCI400_ACTIVE (1 << 18)
+#define ACPU_SC_CPU_STAT_CCI400_ACTIVE_SHIFT (18)
+#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD (1 << 20)
+#define ACPU_SC_CPU_STAT_CLK_DIV_STATUS_VD_SHIFT (20)
+
+#define ACPU_SC_CLKEN (ACPU_CTRL_BASE + 0x00c)
+#define HPM_L2_1_CLKEN (1 << 9)
+#define G_CPU_1_CLKEN (1 << 8)
+#define HPM_L2_CLKEN (1 << 1)
+#define G_CPU_CLKEN (1 << 0)
+
+#define ACPU_SC_CLKDIS (ACPU_CTRL_BASE + 0x010)
+#define ACPU_SC_CLK_STAT (ACPU_CTRL_BASE + 0x014)
+#define ACPU_SC_RSTEN (ACPU_CTRL_BASE + 0x018)
+#define SRST_PRESET1_RSTEN (1 << 11)
+#define SRST_PRESET0_RSTEN (1 << 10)
+#define SRST_CLUSTER1_RSTEN (1 << 9)
+#define SRST_CLUSTER0_RSTEN (1 << 8)
+#define SRST_L2_HPM_1_RSTEN (1 << 5)
+#define SRST_AARM_L2_1_RSTEN (1 << 4)
+#define SRST_L2_HPM_0_RSTEN (1 << 3)
+#define SRST_AARM_L2_0_RSTEN (1 << 1)
+#define SRST_CLUSTER1 (SRST_PRESET1_RSTEN | \
+ SRST_CLUSTER1_RSTEN | \
+ SRST_L2_HPM_1_RSTEN | \
+ SRST_AARM_L2_1_RSTEN)
+#define SRST_CLUSTER0 (SRST_PRESET0_RSTEN | \
+ SRST_CLUSTER0_RSTEN | \
+ SRST_L2_HPM_0_RSTEN | \
+ SRST_AARM_L2_0_RSTEN)
+
+#define ACPU_SC_RSTDIS (ACPU_CTRL_BASE + 0x01c)
+#define ACPU_SC_RST_STAT (ACPU_CTRL_BASE + 0x020)
+#define ACPU_SC_PDBGUP_MBIST (ACPU_CTRL_BASE + 0x02c)
+#define PDBGUP_CLUSTER1_SHIFT 8
+
+#define ACPU_SC_VD_CTRL (ACPU_CTRL_BASE + 0x054)
+#define ACPU_SC_VD_MASK_PATTERN_CTRL (ACPU_CTRL_BASE + 0x058)
+#define ACPU_SC_VD_MASK_PATTERN_VAL (0xCCB << 12)
+#define ACPU_SC_VD_MASK_PATTERN_MASK ((0x1 << 13) - 1)
+
+#define ACPU_SC_VD_DLY_FIXED_CTRL (ACPU_CTRL_BASE + 0x05c)
+#define ACPU_SC_VD_DLY_TABLE0_CTRL (ACPU_CTRL_BASE + 0x060)
+#define ACPU_SC_VD_DLY_TABLE1_CTRL (ACPU_CTRL_BASE + 0x064)
+#define ACPU_SC_VD_DLY_TABLE2_CTRL (ACPU_CTRL_BASE + 0x068)
+#define ACPU_SC_VD_HPM_CTRL (ACPU_CTRL_BASE + 0x06c)
+#define ACPU_SC_A53_CLUSTER_MTCMOS_EN (ACPU_CTRL_BASE + 0x088)
+#define PW_MTCMOS_EN_A53_1_EN (1 << 1)
+#define PW_MTCMOS_EN_A53_0_EN (1 << 0)
+
+#define ACPU_SC_A53_CLUSTER_MTCMOS_STA (ACPU_CTRL_BASE + 0x090)
+#define ACPU_SC_A53_CLUSTER_ISO_EN (ACPU_CTRL_BASE + 0x098)
+#define PW_ISO_A53_1_EN (1 << 1)
+#define PW_ISO_A53_0_EN (1 << 0)
+
+#define ACPU_SC_A53_CLUSTER_ISO_DIS (ACPU_CTRL_BASE + 0x09c)
+#define ACPU_SC_A53_CLUSTER_ISO_STA (ACPU_CTRL_BASE + 0x0a0)
+#define ACPU_SC_A53_1_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0b4)
+#define ACPU_SC_A53_0_MTCMOS_TIMER (ACPU_CTRL_BASE + 0x0bc)
+#define ACPU_SC_A53_x_MTCMOS_TIMER(x) ((x) ? ACPU_SC_A53_1_MTCMOS_TIMER : ACPU_SC_A53_0_MTCMOS_TIMER)
+
+#define ACPU_SC_SNOOP_PWD (ACPU_CTRL_BASE + 0xe4)
+#define PD_DETECT_START1 (1 << 16)
+#define PD_DETECT_START0 (1 << 0)
+
+#define ACPU_SC_CPU0_CTRL (ACPU_CTRL_BASE + 0x100)
+#define CPU_CTRL_AARCH64_MODE (1 << 7)
+
+#define ACPU_SC_CPU0_STAT (ACPU_CTRL_BASE + 0x104)
+#define ACPU_SC_CPU0_CLKEN (ACPU_CTRL_BASE + 0x108)
+#define CPU_CLKEN_HPM (1 << 1)
+
+#define ACPU_SC_CPU0_CLK_STAT (ACPU_CTRL_BASE + 0x110)
+
+#define ACPU_SC_CPU0_RSTEN (ACPU_CTRL_BASE + 0x114)
+#define ACPU_SC_CPU0_RSTDIS (ACPU_CTRL_BASE + 0x118)
+#define ACPU_SC_CPU0_MTCMOS_EN (ACPU_CTRL_BASE + 0x120)
+#define CPU_MTCMOS_PW (1 << 0)
+
+#define ACPU_SC_CPU0_PW_ISOEN (ACPU_CTRL_BASE + 0x130)
+#define CPU_PW_ISO (1 << 0)
+
+#define ACPU_SC_CPU0_PW_ISODIS (ACPU_CTRL_BASE + 0x134)
+#define ACPU_SC_CPU0_PW_ISO_STAT (ACPU_CTRL_BASE + 0x138)
+#define ACPU_SC_CPU0_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x154)
+#define CPU_MTCMOS_TIMER_STA (1 << 0)
+
+#define ACPU_SC_CPU0_RVBARADDR (ACPU_CTRL_BASE + 0x158)
+#define ACPU_SC_CPU1_CTRL (ACPU_CTRL_BASE + 0x200)
+#define ACPU_SC_CPU1_STAT (ACPU_CTRL_BASE + 0x204)
+#define ACPU_SC_CPU1_CLKEN (ACPU_CTRL_BASE + 0x208)
+#define ACPU_SC_CPU1_CLK_STAT (ACPU_CTRL_BASE + 0x210)
+#define ACPU_SC_CPU1_RSTEN (ACPU_CTRL_BASE + 0x214)
+#define ACPU_SC_CPU1_RSTDIS (ACPU_CTRL_BASE + 0x218)
+#define ACPU_SC_CPU1_MTCMOS_EN (ACPU_CTRL_BASE + 0x220)
+#define ACPU_SC_CPU1_PW_ISODIS (ACPU_CTRL_BASE + 0x234)
+#define ACPU_SC_CPU1_PW_ISO_STAT (ACPU_CTRL_BASE + 0x238)
+#define ACPU_SC_CPU1_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x254)
+#define ACPU_SC_CPU1_RVBARADDR (ACPU_CTRL_BASE + 0x258)
+#define ACPU_SC_CPU2_CTRL (ACPU_CTRL_BASE + 0x300)
+#define ACPU_SC_CPU2_STAT (ACPU_CTRL_BASE + 0x304)
+#define ACPU_SC_CPU2_CLKEN (ACPU_CTRL_BASE + 0x308)
+#define ACPU_SC_CPU2_CLK_STAT (ACPU_CTRL_BASE + 0x310)
+#define ACPU_SC_CPU2_RSTEN (ACPU_CTRL_BASE + 0x314)
+#define ACPU_SC_CPU2_RSTDIS (ACPU_CTRL_BASE + 0x318)
+#define ACPU_SC_CPU2_MTCMOS_EN (ACPU_CTRL_BASE + 0x320)
+#define ACPU_SC_CPU2_PW_ISODIS (ACPU_CTRL_BASE + 0x334)
+#define ACPU_SC_CPU2_PW_ISO_STAT (ACPU_CTRL_BASE + 0x338)
+#define ACPU_SC_CPU2_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x354)
+#define ACPU_SC_CPU2_RVBARADDR (ACPU_CTRL_BASE + 0x358)
+#define ACPU_SC_CPU3_CTRL (ACPU_CTRL_BASE + 0x400)
+#define ACPU_SC_CPU3_STAT (ACPU_CTRL_BASE + 0x404)
+#define ACPU_SC_CPU3_CLKEN (ACPU_CTRL_BASE + 0x408)
+#define ACPU_SC_CPU3_CLK_STAT (ACPU_CTRL_BASE + 0x410)
+#define ACPU_SC_CPU3_RSTEN (ACPU_CTRL_BASE + 0x414)
+#define ACPU_SC_CPU3_RSTDIS (ACPU_CTRL_BASE + 0x418)
+#define ACPU_SC_CPU3_MTCMOS_EN (ACPU_CTRL_BASE + 0x420)
+#define ACPU_SC_CPU3_PW_ISODIS (ACPU_CTRL_BASE + 0x434)
+#define ACPU_SC_CPU3_PW_ISO_STAT (ACPU_CTRL_BASE + 0x438)
+#define ACPU_SC_CPU3_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x454)
+#define ACPU_SC_CPU3_RVBARADDR (ACPU_CTRL_BASE + 0x458)
+#define ACPU_SC_CPU4_CTRL (ACPU_CTRL_BASE + 0x500)
+#define ACPU_SC_CPU4_STAT (ACPU_CTRL_BASE + 0x504)
+#define ACPU_SC_CPU4_CLKEN (ACPU_CTRL_BASE + 0x508)
+#define ACPU_SC_CPU4_CLK_STAT (ACPU_CTRL_BASE + 0x510)
+#define ACPU_SC_CPU4_RSTEN (ACPU_CTRL_BASE + 0x514)
+#define ACPU_SC_CPU4_RSTDIS (ACPU_CTRL_BASE + 0x518)
+#define ACPU_SC_CPU4_MTCMOS_EN (ACPU_CTRL_BASE + 0x520)
+#define ACPU_SC_CPU4_PW_ISODIS (ACPU_CTRL_BASE + 0x534)
+#define ACPU_SC_CPU4_PW_ISO_STAT (ACPU_CTRL_BASE + 0x538)
+#define ACPU_SC_CPU4_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x554)
+#define ACPU_SC_CPU4_RVBARADDR (ACPU_CTRL_BASE + 0x558)
+#define ACPU_SC_CPU5_CTRL (ACPU_CTRL_BASE + 0x600)
+#define ACPU_SC_CPU5_STAT (ACPU_CTRL_BASE + 0x604)
+#define ACPU_SC_CPU5_CLKEN (ACPU_CTRL_BASE + 0x608)
+#define ACPU_SC_CPU5_CLK_STAT (ACPU_CTRL_BASE + 0x610)
+#define ACPU_SC_CPU5_RSTEN (ACPU_CTRL_BASE + 0x614)
+#define ACPU_SC_CPU5_RSTDIS (ACPU_CTRL_BASE + 0x618)
+#define ACPU_SC_CPU5_MTCMOS_EN (ACPU_CTRL_BASE + 0x620)
+#define ACPU_SC_CPU5_PW_ISODIS (ACPU_CTRL_BASE + 0x634)
+#define ACPU_SC_CPU5_PW_ISO_STAT (ACPU_CTRL_BASE + 0x638)
+#define ACPU_SC_CPU5_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x654)
+#define ACPU_SC_CPU5_RVBARADDR (ACPU_CTRL_BASE + 0x658)
+#define ACPU_SC_CPU6_CTRL (ACPU_CTRL_BASE + 0x700)
+#define ACPU_SC_CPU6_STAT (ACPU_CTRL_BASE + 0x704)
+#define ACPU_SC_CPU6_CLKEN (ACPU_CTRL_BASE + 0x708)
+#define ACPU_SC_CPU6_CLK_STAT (ACPU_CTRL_BASE + 0x710)
+#define ACPU_SC_CPU6_RSTEN (ACPU_CTRL_BASE + 0x714)
+#define ACPU_SC_CPU6_RSTDIS (ACPU_CTRL_BASE + 0x718)
+#define ACPU_SC_CPU6_MTCMOS_EN (ACPU_CTRL_BASE + 0x720)
+#define ACPU_SC_CPU6_PW_ISODIS (ACPU_CTRL_BASE + 0x734)
+#define ACPU_SC_CPU6_PW_ISO_STAT (ACPU_CTRL_BASE + 0x738)
+#define ACPU_SC_CPU6_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x754)
+#define ACPU_SC_CPU6_RVBARADDR (ACPU_CTRL_BASE + 0x758)
+#define ACPU_SC_CPU7_CTRL (ACPU_CTRL_BASE + 0x800)
+#define ACPU_SC_CPU7_STAT (ACPU_CTRL_BASE + 0x804)
+#define ACPU_SC_CPU7_CLKEN (ACPU_CTRL_BASE + 0x808)
+#define ACPU_SC_CPU7_CLK_STAT (ACPU_CTRL_BASE + 0x810)
+#define ACPU_SC_CPU7_RSTEN (ACPU_CTRL_BASE + 0x814)
+#define ACPU_SC_CPU7_RSTDIS (ACPU_CTRL_BASE + 0x818)
+#define ACPU_SC_CPU7_MTCMOS_EN (ACPU_CTRL_BASE + 0x820)
+#define ACPU_SC_CPU7_PW_ISODIS (ACPU_CTRL_BASE + 0x834)
+#define ACPU_SC_CPU7_PW_ISO_STAT (ACPU_CTRL_BASE + 0x838)
+#define ACPU_SC_CPU7_MTCMOS_TIMER_STAT (ACPU_CTRL_BASE + 0x854)
+#define ACPU_SC_CPU7_RVBARADDR (ACPU_CTRL_BASE + 0x858)
+#define ACPU_SC_CPUx_CTRL(x) ((x < 8) ? (ACPU_SC_CPU0_CTRL + 0x100 * x) : ACPU_SC_CPU0_CTRL)
+#define ACPU_SC_CPUx_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_STAT + 0x100 * x) : ACPU_SC_CPU0_STAT)
+#define ACPU_SC_CPUx_CLKEN(x) ((x < 8) ? (ACPU_SC_CPU0_CLKEN + 0x100 * x) : ACPU_SC_CPU0_CLKEN)
+#define ACPU_SC_CPUx_CLK_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_CLK_STAT + 0x100 * x) : ACPU_SC_CPU0_CLK_STAT)
+#define ACPU_SC_CPUx_RSTEN(x) ((x < 8) ? (ACPU_SC_CPU0_RSTEN + 0x100 * x) : ACPU_SC_CPU0_RSTEN)
+#define ACPU_SC_CPUx_RSTDIS(x) ((x < 8) ? (ACPU_SC_CPU0_RSTDIS + 0x100 * x) : ACPU_SC_CPU0_RSTDIS)
+#define ACPU_SC_CPUx_MTCMOS_EN(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_EN + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_EN)
+#define ACPU_SC_CPUx_PW_ISODIS(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISODIS + 0x100 * x) : ACPU_SC_CPU0_PW_ISODIS)
+#define ACPU_SC_CPUx_PW_ISO_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_PW_ISO_STAT + 0x100 * x) : ACPU_SC_CPU0_PW_ISO_STAT)
+#define ACPU_SC_CPUx_MTCMOS_TIMER_STAT(x) ((x < 8) ? (ACPU_SC_CPU0_MTCMOS_TIMER_STAT + 0x100 * x) : ACPU_SC_CPU0_MTCMOS_TIMER_STAT)
+#define ACPU_SC_CPUx_RVBARADDR(x) ((x < 8) ? (ACPU_SC_CPU0_RVBARADDR + 0x100 * x) : ACPU_SC_CPU0_RVBARADDR)
+
+#define ACPU_SC_CPU_STAT_CLKDIV_VD_MASK (3 << 20)
+
+#define ACPU_SC_VD_CTRL_TUNE_EN_DIF (1 << 0)
+#define ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT (0)
+#define ACPU_SC_VD_CTRL_TUNE (1 << 1)
+#define ACPU_SC_VD_CTRL_TUNE_SHIFT (1)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF (1 << 7)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT (7)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI (1 << 8)
+#define ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT (8)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR (1 << 9)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_CLR_SHIFT (9)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN (1 << 10)
+#define ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT (10)
+#define ACPU_SC_VD_CTRL_TUNE_EN_INT (1 << 11)
+#define ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT (11)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE0 (1 << 12)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_MASK (0xf << 12)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT (12)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE1 (1 << 16)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_MASK (0xf << 16)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT (16)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE2 (1 << 20)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_MASK (0xf << 20)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT (20)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE3 (1 << 24)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_MASK (0xf << 24)
+#define ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT (24)
+#define ACPU_SC_VD_CTRL_FORCE_CLK_EN (1 << 28)
+#define ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT (28)
+#define ACPU_SC_VD_CTRL_DIV_EN_DIF (1 << 29)
+#define ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT (29)
+
+#define ACPU_SC_VD_SHIFT_TABLE_TUNE_VAL \
+ ((0x1 << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \
+ (0x3 << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \
+ (0x5 << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \
+ (0x6 << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \
+ (0x7 << ACPU_SC_VD_CTRL_TUNE_SHIFT))
+
+#define ACPU_SC_VD_SHIFT_TABLE_TUNE_MASK \
+ ((0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE0_SHIFT) | \
+ (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE1_SHIFT) | \
+ (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE2_SHIFT) | \
+ (0xF << ACPU_SC_VD_CTRL_SHIFT_TABLE3_SHIFT) | \
+ (0x3F << ACPU_SC_VD_CTRL_TUNE_SHIFT))
+
+#define ACPU_SC_VD_HPM_CTRL_OSC_DIV (1 << 0)
+#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT (0)
+#define ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK (0x000000FF)
+#define ACPU_SC_VD_HPM_CTRL_DLY_EXP (1 << 8)
+#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT (8)
+#define ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK (0x001FFF00)
+
+#define HPM_OSC_DIV_VAL \
+ (0x56 << ACPU_SC_VD_HPM_CTRL_OSC_DIV_SHIFT)
+#define HPM_OSC_DIV_MASK \
+ (ACPU_SC_VD_HPM_CTRL_OSC_DIV_MASK)
+
+#define HPM_DLY_EXP_VAL \
+ (0xC7A << ACPU_SC_VD_HPM_CTRL_DLY_EXP_SHIFT)
+#define HPM_DLY_EXP_MASK \
+ (ACPU_SC_VD_HPM_CTRL_DLY_EXP_MASK)
+
+#define ACPU_SC_VD_EN_ASIC_VAL \
+ ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \
+ (0X0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \
+ (0X0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
+
+#define ACPU_SC_VD_EN_SFT_VAL \
+ ((0x0 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \
+ (0x0 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
+
+#define ACPU_SC_VD_EN_MASK \
+ ((0x1 << ACPU_SC_VD_CTRL_FORCE_CLK_EN_SHIFT) | \
+ (0x1 << ACPU_SC_VD_CTRL_CLK_DIS_CNT_EN_SHIFT) | \
+ (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_INI_SHIFT) | \
+ (0x1 << ACPU_SC_VD_CTRL_CALIBRATE_EN_DIF_SHIFT) | \
+ (0x1 << ACPU_SC_VD_CTRL_DIV_EN_DIF_SHIFT) | \
+ (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_INT_SHIFT) | \
+ (0x1 << ACPU_SC_VD_CTRL_TUNE_EN_DIF_SHIFT))
+
+#endif /* HI6220_REGS_ACPU_H */
diff --git a/plat/hisilicon/hikey/include/hi6220_regs_ao.h b/plat/hisilicon/hikey/include/hi6220_regs_ao.h
new file mode 100644
index 0000000..614eba2
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hi6220_regs_ao.h
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI6220_REGS_AO_H
+#define HI6220_REGS_AO_H
+
+#define AO_CTRL_BASE 0xF7800000
+
+#define AO_SC_SYS_CTRL0 (AO_CTRL_BASE + 0x000)
+#define AO_SC_SYS_CTRL1 (AO_CTRL_BASE + 0x004)
+#define AO_SC_SYS_CTRL2 (AO_CTRL_BASE + 0x008)
+#define AO_SC_SYS_STAT0 (AO_CTRL_BASE + 0x010)
+#define AO_SC_SYS_STAT1 (AO_CTRL_BASE + 0x014)
+#define AO_SC_MCU_IMCTRL (AO_CTRL_BASE + 0x018)
+#define AO_SC_MCU_IMSTAT (AO_CTRL_BASE + 0x01C)
+#define AO_SC_SECONDRY_INT_EN0 (AO_CTRL_BASE + 0x044)
+#define AO_SC_SECONDRY_INT_STATR0 (AO_CTRL_BASE + 0x048)
+#define AO_SC_SECONDRY_INT_STATM0 (AO_CTRL_BASE + 0x04C)
+#define AO_SC_MCU_WKUP_INT_EN6 (AO_CTRL_BASE + 0x054)
+#define AO_SC_MCU_WKUP_INT_STATR6 (AO_CTRL_BASE + 0x058)
+#define AO_SC_MCU_WKUP_INT_STATM6 (AO_CTRL_BASE + 0x05C)
+#define AO_SC_MCU_WKUP_INT_EN5 (AO_CTRL_BASE + 0x064)
+#define AO_SC_MCU_WKUP_INT_STATR5 (AO_CTRL_BASE + 0x068)
+#define AO_SC_MCU_WKUP_INT_STATM5 (AO_CTRL_BASE + 0x06C)
+#define AO_SC_MCU_WKUP_INT_EN4 (AO_CTRL_BASE + 0x094)
+#define AO_SC_MCU_WKUP_INT_STATR4 (AO_CTRL_BASE + 0x098)
+#define AO_SC_MCU_WKUP_INT_STATM4 (AO_CTRL_BASE + 0x09C)
+#define AO_SC_MCU_WKUP_INT_EN0 (AO_CTRL_BASE + 0x0A8)
+#define AO_SC_MCU_WKUP_INT_STATR0 (AO_CTRL_BASE + 0x0AC)
+#define AO_SC_MCU_WKUP_INT_STATM0 (AO_CTRL_BASE + 0x0B0)
+#define AO_SC_MCU_WKUP_INT_EN1 (AO_CTRL_BASE + 0x0B4)
+#define AO_SC_MCU_WKUP_INT_STATR1 (AO_CTRL_BASE + 0x0B8)
+#define AO_SC_MCU_WKUP_INT_STATM1 (AO_CTRL_BASE + 0x0BC)
+#define AO_SC_INT_STATR (AO_CTRL_BASE + 0x0C4)
+#define AO_SC_INT_STATM (AO_CTRL_BASE + 0x0C8)
+#define AO_SC_INT_CLEAR (AO_CTRL_BASE + 0x0CC)
+#define AO_SC_INT_EN_SET (AO_CTRL_BASE + 0x0D0)
+#define AO_SC_INT_EN_DIS (AO_CTRL_BASE + 0x0D4)
+#define AO_SC_INT_EN_STAT (AO_CTRL_BASE + 0x0D8)
+#define AO_SC_INT_STATR1 (AO_CTRL_BASE + 0x0E4)
+#define AO_SC_INT_STATM1 (AO_CTRL_BASE + 0x0E8)
+#define AO_SC_INT_CLEAR1 (AO_CTRL_BASE + 0x0EC)
+#define AO_SC_INT_EN_SET1 (AO_CTRL_BASE + 0x0F0)
+#define AO_SC_INT_EN_DIS1 (AO_CTRL_BASE + 0x0F4)
+#define AO_SC_INT_EN_STAT1 (AO_CTRL_BASE + 0x0F8)
+#define AO_SC_TIMER_EN0 (AO_CTRL_BASE + 0x1D0)
+#define AO_SC_TIMER_EN1 (AO_CTRL_BASE + 0x1D4)
+#define AO_SC_TIMER_EN4 (AO_CTRL_BASE + 0x1F0)
+#define AO_SC_TIMER_EN5 (AO_CTRL_BASE + 0x1F4)
+#define AO_SC_MCU_SUBSYS_CTRL0 (AO_CTRL_BASE + 0x400)
+#define AO_SC_MCU_SUBSYS_CTRL1 (AO_CTRL_BASE + 0x404)
+#define AO_SC_MCU_SUBSYS_CTRL2 (AO_CTRL_BASE + 0x408)
+#define AO_SC_MCU_SUBSYS_CTRL3 (AO_CTRL_BASE + 0x40C)
+#define AO_SC_MCU_SUBSYS_CTRL4 (AO_CTRL_BASE + 0x410)
+#define AO_SC_MCU_SUBSYS_CTRL5 (AO_CTRL_BASE + 0x414)
+#define AO_SC_MCU_SUBSYS_CTRL6 (AO_CTRL_BASE + 0x418)
+#define AO_SC_MCU_SUBSYS_CTRL7 (AO_CTRL_BASE + 0x41C)
+#define AO_SC_MCU_SUBSYS_STAT0 (AO_CTRL_BASE + 0x440)
+#define AO_SC_MCU_SUBSYS_STAT1 (AO_CTRL_BASE + 0x444)
+#define AO_SC_MCU_SUBSYS_STAT2 (AO_CTRL_BASE + 0x448)
+#define AO_SC_MCU_SUBSYS_STAT3 (AO_CTRL_BASE + 0x44C)
+#define AO_SC_MCU_SUBSYS_STAT4 (AO_CTRL_BASE + 0x450)
+#define AO_SC_MCU_SUBSYS_STAT5 (AO_CTRL_BASE + 0x454)
+#define AO_SC_MCU_SUBSYS_STAT6 (AO_CTRL_BASE + 0x458)
+#define AO_SC_MCU_SUBSYS_STAT7 (AO_CTRL_BASE + 0x45C)
+#define AO_SC_PERIPH_CLKEN4 (AO_CTRL_BASE + 0x630)
+#define AO_SC_PERIPH_CLKDIS4 (AO_CTRL_BASE + 0x634)
+#define AO_SC_PERIPH_CLKSTAT4 (AO_CTRL_BASE + 0x638)
+#define AO_SC_PERIPH_CLKEN5 (AO_CTRL_BASE + 0x63C)
+#define AO_SC_PERIPH_CLKDIS5 (AO_CTRL_BASE + 0x640)
+#define AO_SC_PERIPH_CLKSTAT5 (AO_CTRL_BASE + 0x644)
+#define AO_SC_PERIPH_RSTEN4 (AO_CTRL_BASE + 0x6F0)
+#define AO_SC_PERIPH_RSTDIS4 (AO_CTRL_BASE + 0x6F4)
+#define AO_SC_PERIPH_RSTSTAT4 (AO_CTRL_BASE + 0x6F8)
+#define AO_SC_PERIPH_RSTEN5 (AO_CTRL_BASE + 0x6FC)
+#define AO_SC_PERIPH_RSTDIS5 (AO_CTRL_BASE + 0x700)
+#define AO_SC_PERIPH_RSTSTAT5 (AO_CTRL_BASE + 0x704)
+#define AO_SC_PW_CLKEN0 (AO_CTRL_BASE + 0x800)
+#define AO_SC_PW_CLKDIS0 (AO_CTRL_BASE + 0x804)
+#define AO_SC_PW_CLK_STAT0 (AO_CTRL_BASE + 0x808)
+#define AO_SC_PW_RSTEN0 (AO_CTRL_BASE + 0x810)
+#define AO_SC_PW_RSTDIS0 (AO_CTRL_BASE + 0x814)
+#define AO_SC_PW_RST_STAT0 (AO_CTRL_BASE + 0x818)
+#define AO_SC_PW_ISOEN0 (AO_CTRL_BASE + 0x820)
+#define AO_SC_PW_ISODIS0 (AO_CTRL_BASE + 0x824)
+#define AO_SC_PW_ISO_STAT0 (AO_CTRL_BASE + 0x828)
+#define AO_SC_PW_MTCMOS_EN0 (AO_CTRL_BASE + 0x830)
+#define AO_SC_PW_MTCMOS_DIS0 (AO_CTRL_BASE + 0x834)
+#define AO_SC_PW_MTCMOS_STAT0 (AO_CTRL_BASE + 0x838)
+#define AO_SC_PW_MTCMOS_ACK_STAT0 (AO_CTRL_BASE + 0x83C)
+#define AO_SC_PW_MTCMOS_TIMEOUT_STAT0 (AO_CTRL_BASE + 0x840)
+#define AO_SC_PW_STAT0 (AO_CTRL_BASE + 0x850)
+#define AO_SC_PW_STAT1 (AO_CTRL_BASE + 0x854)
+#define AO_SC_SYSTEST_STAT (AO_CTRL_BASE + 0x880)
+#define AO_SC_SYSTEST_SLICER_CNT0 (AO_CTRL_BASE + 0x890)
+#define AO_SC_SYSTEST_SLICER_CNT1 (AO_CTRL_BASE + 0x894)
+#define AO_SC_PW_CTRL1 (AO_CTRL_BASE + 0x8C8)
+#define AO_SC_PW_CTRL (AO_CTRL_BASE + 0x8CC)
+#define AO_SC_MCPU_VOTEEN (AO_CTRL_BASE + 0x8D0)
+#define AO_SC_MCPU_VOTEDIS (AO_CTRL_BASE + 0x8D4)
+#define AO_SC_MCPU_VOTESTAT (AO_CTRL_BASE + 0x8D8)
+#define AO_SC_MCPU_VOTE_MSK0 (AO_CTRL_BASE + 0x8E0)
+#define AO_SC_MCPU_VOTE_MSK1 (AO_CTRL_BASE + 0x8E4)
+#define AO_SC_MCPU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x8E8)
+#define AO_SC_MCPU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x8EC)
+#define AO_SC_PERI_VOTEEN (AO_CTRL_BASE + 0x8F0)
+#define AO_SC_PERI_VOTEDIS (AO_CTRL_BASE + 0x8F4)
+#define AO_SC_PERI_VOTESTAT (AO_CTRL_BASE + 0x8F8)
+#define AO_SC_PERI_VOTE_MSK0 (AO_CTRL_BASE + 0x900)
+#define AO_SC_PERI_VOTE_MSK1 (AO_CTRL_BASE + 0x904)
+#define AO_SC_PERI_VOTESTAT0_MSK (AO_CTRL_BASE + 0x908)
+#define AO_SC_PERI_VOTESTAT1_MSK (AO_CTRL_BASE + 0x90C)
+#define AO_SC_ACPU_VOTEEN (AO_CTRL_BASE + 0x910)
+#define AO_SC_ACPU_VOTEDIS (AO_CTRL_BASE + 0x914)
+#define AO_SC_ACPU_VOTESTAT (AO_CTRL_BASE + 0x918)
+#define AO_SC_ACPU_VOTE_MSK0 (AO_CTRL_BASE + 0x920)
+#define AO_SC_ACPU_VOTE_MSK1 (AO_CTRL_BASE + 0x924)
+#define AO_SC_ACPU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x928)
+#define AO_SC_ACPU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x92C)
+#define AO_SC_MCU_VOTEEN (AO_CTRL_BASE + 0x930)
+#define AO_SC_MCU_VOTEDIS (AO_CTRL_BASE + 0x934)
+#define AO_SC_MCU_VOTESTAT (AO_CTRL_BASE + 0x938)
+#define AO_SC_MCU_VOTE_MSK0 (AO_CTRL_BASE + 0x940)
+#define AO_SC_MCU_VOTE_MSK1 (AO_CTRL_BASE + 0x944)
+#define AO_SC_MCU_VOTESTAT0_MSK (AO_CTRL_BASE + 0x948)
+#define AO_SC_MCU_VOTESTAT1_MSK (AO_CTRL_BASE + 0x94C)
+#define AO_SC_MCU_VOTE1EN (AO_CTRL_BASE + 0x960)
+#define AO_SC_MCU_VOTE1DIS (AO_CTRL_BASE + 0x964)
+#define AO_SC_MCU_VOTE1STAT (AO_CTRL_BASE + 0x968)
+#define AO_SC_MCU_VOTE1_MSK0 (AO_CTRL_BASE + 0x970)
+#define AO_SC_MCU_VOTE1_MSK1 (AO_CTRL_BASE + 0x974)
+#define AO_SC_MCU_VOTE1STAT0_MSK (AO_CTRL_BASE + 0x978)
+#define AO_SC_MCU_VOTE1STAT1_MSK (AO_CTRL_BASE + 0x97C)
+#define AO_SC_MCU_VOTE2EN (AO_CTRL_BASE + 0x980)
+#define AO_SC_MCU_VOTE2DIS (AO_CTRL_BASE + 0x984)
+#define AO_SC_MCU_VOTE2STAT (AO_CTRL_BASE + 0x988)
+#define AO_SC_MCU_VOTE2_MSK0 (AO_CTRL_BASE + 0x990)
+#define AO_SC_MCU_VOTE2_MSK1 (AO_CTRL_BASE + 0x994)
+#define AO_SC_MCU_VOTE2STAT0_MSK (AO_CTRL_BASE + 0x998)
+#define AO_SC_MCU_VOTE2STAT1_MSK (AO_CTRL_BASE + 0x99C)
+#define AO_SC_VOTE_CTRL (AO_CTRL_BASE + 0x9A0)
+#define AO_SC_VOTE_STAT (AO_CTRL_BASE + 0x9A4)
+#define AO_SC_ECONUM (AO_CTRL_BASE + 0xF00)
+#define AO_SCCHIPID (AO_CTRL_BASE + 0xF10)
+#define AO_SCSOCID (AO_CTRL_BASE + 0xF1C)
+#define AO_SC_SOC_FPGA_RTL_DEF (AO_CTRL_BASE + 0xFE0)
+#define AO_SC_SOC_FPGA_PR_DEF (AO_CTRL_BASE + 0xFE4)
+#define AO_SC_SOC_FPGA_RES_DEF0 (AO_CTRL_BASE + 0xFE8)
+#define AO_SC_SOC_FPGA_RES_DEF1 (AO_CTRL_BASE + 0xFEC)
+#define AO_SC_XTAL_CTRL0 (AO_CTRL_BASE + 0x102)
+#define AO_SC_XTAL_CTRL1 (AO_CTRL_BASE + 0x102)
+#define AO_SC_XTAL_CTRL3 (AO_CTRL_BASE + 0x103)
+#define AO_SC_XTAL_CTRL5 (AO_CTRL_BASE + 0x103)
+#define AO_SC_XTAL_STAT0 (AO_CTRL_BASE + 0x106)
+#define AO_SC_XTAL_STAT1 (AO_CTRL_BASE + 0x107)
+#define AO_SC_EFUSE_CHIPID0 (AO_CTRL_BASE + 0x108)
+#define AO_SC_EFUSE_CHIPID1 (AO_CTRL_BASE + 0x108)
+#define AO_SC_EFUSE_SYS_CTRL (AO_CTRL_BASE + 0x108)
+#define AO_SC_DEBUG_CTRL1 (AO_CTRL_BASE + 0x128)
+#define AO_SC_DBG_STAT (AO_CTRL_BASE + 0x12B)
+#define AO_SC_ARM_DBG_KEY0 (AO_CTRL_BASE + 0x12B)
+#define AO_SC_RESERVED31 (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED32 (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED33 (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED34 (AO_CTRL_BASE + 0x13A)
+#define AO_SC_RESERVED35 (AO_CTRL_BASE + 0x13B)
+#define AO_SC_RESERVED36 (AO_CTRL_BASE + 0x13B)
+#define AO_SC_RESERVED37 (AO_CTRL_BASE + 0x13B)
+#define AO_SC_RESERVED38 (AO_CTRL_BASE + 0x13B)
+#define AO_SC_ALWAYSON_SYS_CTRL0 (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL1 (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL2 (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL3 (AO_CTRL_BASE + 0x148)
+#define AO_SC_ALWAYSON_SYS_CTRL10 (AO_CTRL_BASE + 0x14A)
+#define AO_SC_ALWAYSON_SYS_CTRL11 (AO_CTRL_BASE + 0x14A)
+#define AO_SC_ALWAYSON_SYS_STAT0 (AO_CTRL_BASE + 0x14C)
+#define AO_SC_ALWAYSON_SYS_STAT1 (AO_CTRL_BASE + 0x14C)
+#define AO_SC_ALWAYSON_SYS_STAT2 (AO_CTRL_BASE + 0x14C)
+#define AO_SC_ALWAYSON_SYS_STAT3 (AO_CTRL_BASE + 0x14C)
+#define AO_SC_PWUP_TIME0 (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME1 (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME2 (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME3 (AO_CTRL_BASE + 0x188)
+#define AO_SC_PWUP_TIME4 (AO_CTRL_BASE + 0x189)
+#define AO_SC_PWUP_TIME5 (AO_CTRL_BASE + 0x189)
+#define AO_SC_PWUP_TIME6 (AO_CTRL_BASE + 0x189)
+#define AO_SC_PWUP_TIME7 (AO_CTRL_BASE + 0x189)
+#define AO_SC_SECURITY_CTRL1 (AO_CTRL_BASE + 0x1C0)
+#define AO_SC_SYSTEST_SLICER_CNT0 (AO_CTRL_BASE + 0x890)
+#define AO_SC_SYSTEST_SLICER_CNT1 (AO_CTRL_BASE + 0x894)
+
+#define AO_SC_SYS_CTRL0_MODE_NORMAL 0x004
+#define AO_SC_SYS_CTRL0_MODE_MASK 0x007
+
+#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG (1 << 0)
+#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM (1 << 1)
+#define AO_SC_SYS_CTRL1_EFUSEC_REMAP (1 << 2)
+#define AO_SC_SYS_CTRL1_EXT_PLL_SEL (1 << 3)
+#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG (1 << 4)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG (1 << 6)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG (1 << 7)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG (1 << 8)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG (1 << 9)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG (1 << 10)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1 (1 << 11)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT (1 << 12)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT (1 << 13)
+#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG (1 << 15)
+#define AO_SC_SYS_CTRL1_AARM_WD_RST_CFG_MSK (1 << 16)
+#define AO_SC_SYS_CTRL1_REMAP_SRAM_AARM_MSK (1 << 17)
+#define AO_SC_SYS_CTRL1_EFUSEC_REMAP_MSK (1 << 18)
+#define AO_SC_SYS_CTRL1_EXT_PLL_SEL_MSK (1 << 19)
+#define AO_SC_SYS_CTRL1_MCU_WDG0_RSTMCU_CFG_MSK (1 << 20)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_DE_BOUNCE_CFG_MSK (1 << 22)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_CFG_MSK (1 << 23)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_DE_BOUNCE_CFG_MSK (1 << 24)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_CFG_MSK (1 << 25)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG_MSK (1 << 26)
+#define AO_SC_SYS_CTRL1_BUS_DFS_FORE_HD_CFG1_MSK (1 << 27)
+#define AO_SC_SYS_CTRL1_USIM0_HPD_OE_SFT_MSK (1 << 28)
+#define AO_SC_SYS_CTRL1_USIM1_HPD_OE_SFT_MSK (1 << 29)
+#define AO_SC_SYS_CTRL1_MCU_CLKEN_HARDCFG_MSK (1U << 31)
+
+#define AO_SC_SYS_CTRL2_MCU_SFT_RST_STAT_CLEAR (1 << 26)
+#define AO_SC_SYS_CTRL2_MCU_WDG0_RST_STAT_CLEAR (1 << 27)
+#define AO_SC_SYS_CTRL2_TSENSOR_RST_STAT_CLEAR (1 << 28)
+#define AO_SC_SYS_CTRL2_ACPU_WDG_RST_STAT_CLEAR (1 << 29)
+#define AO_SC_SYS_CTRL2_MCU_WDG1_RST_STAT_CLEAR (1 << 30)
+#define AO_SC_SYS_CTRL2_GLB_SRST_STAT_CLEAR (1U << 31)
+
+#define AO_SC_SYS_STAT0_MCU_RST_STAT (1 << 25)
+#define AO_SC_SYS_STAT0_MCU_SOFTRST_STAT (1 << 26)
+#define AO_SC_SYS_STAT0_MCU_WDGRST_STAT (1 << 27)
+#define AO_SC_SYS_STAT0_TSENSOR_HARDRST_STAT (1 << 28)
+#define AO_SC_SYS_STAT0_ACPU_WD_GLB_RST_STAT (1 << 29)
+#define AO_SC_SYS_STAT0_CM3_WDG1_RST_STAT (1 << 30)
+#define AO_SC_SYS_STAT0_GLB_SRST_STAT (1U << 31)
+
+#define AO_SC_SYS_STAT1_MODE_STATUS (1 << 0)
+#define AO_SC_SYS_STAT1_BOOT_SEL_LOCK (1 << 16)
+#define AO_SC_SYS_STAT1_FUNC_MODE_LOCK (1 << 17)
+#define AO_SC_SYS_STAT1_BOOT_MODE_LOCK (1 << 19)
+#define AO_SC_SYS_STAT1_FUN_JTAG_MODE_OUT (1 << 20)
+#define AO_SC_SYS_STAT1_SECURITY_BOOT_FLG (1 << 27)
+#define AO_SC_SYS_STAT1_EFUSE_NANDBOOT_MSK (1 << 28)
+#define AO_SC_SYS_STAT1_EFUSE_NAND_BITWIDE (1 << 29)
+
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_ECTR_N (1 << 0)
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_SYS_N (1 << 1)
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_POR_N (1 << 2)
+#define AO_SC_PERIPH_RSTDIS4_RESET_MCU_DAP_N (1 << 3)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER0_N (1 << 4)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_TIMER1_N (1 << 5)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT0_N (1 << 6)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_CM3_WDT1_N (1 << 7)
+#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_S_N (1 << 8)
+#define AO_SC_PERIPH_RSTDIS4_HRESET_IPC_NS_N (1 << 9)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_EFUSEC_N (1 << 10)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT0_N (1 << 12)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT1_N (1 << 13)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_WDT2_N (1 << 14)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER0_N (1 << 15)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER1_N (1 << 16)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER2_N (1 << 17)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER3_N (1 << 18)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER4_N (1 << 19)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER5_N (1 << 20)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER6_N (1 << 21)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER7_N (1 << 22)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_TIMER8_N (1 << 23)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_UART0_N (1 << 24)
+#define AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N (1 << 25)
+#define AO_SC_PERIPH_RSTDIS4_RESET_RTC1_N (1 << 26)
+#define AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N (1 << 27)
+#define AO_SC_PERIPH_RSTDIS4_RESET_JTAG_AUTH_N (1 << 28)
+#define AO_SC_PERIPH_RSTDIS4_RESET_CS_DAPB_ON_N (1 << 29)
+#define AO_SC_PERIPH_RSTDIS4_MDM_SUBSYS_GLB (1 << 30)
+
+#define AO_SC_PERIPH_CLKEN4_HCLK_MCU (1 << 0)
+#define AO_SC_PERIPH_CLKEN4_CLK_MCU_DAP (1 << 3)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER0 (1 << 4)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_TIMER1 (1 << 5)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT0 (1 << 6)
+#define AO_SC_PERIPH_CLKEN4_PCLK_CM3_WDT1 (1 << 7)
+#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_S (1 << 8)
+#define AO_SC_PERIPH_CLKEN4_HCLK_IPC_NS (1 << 9)
+#define AO_SC_PERIPH_CLKEN4_PCLK_EFUSEC (1 << 10)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TZPC (1 << 11)
+#define AO_SC_PERIPH_CLKEN4_PCLK_WDT0 (1 << 12)
+#define AO_SC_PERIPH_CLKEN4_PCLK_WDT1 (1 << 13)
+#define AO_SC_PERIPH_CLKEN4_PCLK_WDT2 (1 << 14)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER0 (1 << 15)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER1 (1 << 16)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER2 (1 << 17)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER3 (1 << 18)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER4 (1 << 19)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER5 (1 << 20)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER6 (1 << 21)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER7 (1 << 22)
+#define AO_SC_PERIPH_CLKEN4_PCLK_TIMER8 (1 << 23)
+#define AO_SC_PERIPH_CLKEN4_CLK_UART0 (1 << 24)
+#define AO_SC_PERIPH_CLKEN4_CLK_RTC0 (1 << 25)
+#define AO_SC_PERIPH_CLKEN4_CLK_RTC1 (1 << 26)
+#define AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI (1 << 27)
+#define AO_SC_PERIPH_CLKEN4_CLK_JTAG_AUTH (1 << 28)
+#define AO_SC_PERIPH_CLKEN4_CLK_CS_DAPB_ON (1 << 29)
+#define AO_SC_PERIPH_CLKEN4_CLK_PDM (1 << 30)
+#define AO_SC_PERIPH_CLKEN4_CLK_SSI_PAD (1U << 31)
+
+#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU (1 << 0)
+#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_CCPU (1 << 1)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_CCPU (1 << 2)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_CCPU (1 << 3)
+#define AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU (1 << 16)
+#define AO_SC_PERIPH_CLKEN5_PCLK_EFUSEC_MCU (1 << 17)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_MCU (1 << 18)
+#define AO_SC_PERIPH_CLKEN5_HCLK_IPC_NS_MCU (1 << 19)
+
+#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_3 0x003
+#define AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK 0x007
+#define AO_SC_MCU_SUBSYS_CTRL3_CSSYS_CTRL_PROT (1 << 3)
+#define AO_SC_MCU_SUBSYS_CTRL3_TCXO_AFC_OEN_CRG (1 << 4)
+#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM1 (1 << 8)
+#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_USIM0 (1 << 9)
+#define AO_SC_MCU_SUBSYS_CTRL3_AOB_IO_SEL18_SD (1 << 10)
+#define AO_SC_MCU_SUBSYS_CTRL3_MCU_SUBSYS_CTRL3_RESERVED (1 << 11)
+
+#define PCLK_TIMER1 (1 << 16)
+#define PCLK_TIMER0 (1 << 15)
+
+#endif /* HI6220_REGS_AO_H */
diff --git a/plat/hisilicon/hikey/include/hi6220_regs_peri.h b/plat/hisilicon/hikey/include/hi6220_regs_peri.h
new file mode 100644
index 0000000..77236e8
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hi6220_regs_peri.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI6220_REGS_PERI_H
+#define HI6220_REGS_PERI_H
+
+#define PERI_BASE 0xF7030000
+
+#define PERI_SC_PERIPH_CTRL1 (PERI_BASE + 0x000)
+#define PERI_SC_PERIPH_CTRL2 (PERI_BASE + 0x004)
+#define PERI_SC_PERIPH_CTRL3 (PERI_BASE + 0x008)
+#define PERI_SC_PERIPH_CTRL4 (PERI_BASE + 0x00c)
+#define PERI_SC_PERIPH_CTRL5 (PERI_BASE + 0x010)
+#define PERI_SC_PERIPH_CTRL6 (PERI_BASE + 0x014)
+#define PERI_SC_PERIPH_CTRL8 (PERI_BASE + 0x018)
+#define PERI_SC_PERIPH_CTRL9 (PERI_BASE + 0x01c)
+#define PERI_SC_PERIPH_CTRL10 (PERI_BASE + 0x020)
+#define PERI_SC_PERIPH_CTRL12 (PERI_BASE + 0x024)
+#define PERI_SC_PERIPH_CTRL13 (PERI_BASE + 0x028)
+#define PERI_SC_PERIPH_CTRL14 (PERI_BASE + 0x02c)
+
+#define PERI_SC_DDR_CTRL0 (PERI_BASE + 0x050)
+#define PERI_SC_PERIPH_STAT1 (PERI_BASE + 0x094)
+
+#define PERI_SC_PERIPH_CLKEN0 (PERI_BASE + 0x200)
+#define PERI_SC_PERIPH_CLKDIS0 (PERI_BASE + 0x204)
+#define PERI_SC_PERIPH_CLKSTAT0 (PERI_BASE + 0x208)
+#define PERI_SC_PERIPH_CLKEN1 (PERI_BASE + 0x210)
+#define PERI_SC_PERIPH_CLKDIS1 (PERI_BASE + 0x214)
+#define PERI_SC_PERIPH_CLKSTAT1 (PERI_BASE + 0x218)
+#define PERI_SC_PERIPH_CLKEN2 (PERI_BASE + 0x220)
+#define PERI_SC_PERIPH_CLKDIS2 (PERI_BASE + 0x224)
+#define PERI_SC_PERIPH_CLKSTAT2 (PERI_BASE + 0x228)
+#define PERI_SC_PERIPH_CLKEN3 (PERI_BASE + 0x230)
+#define PERI_SC_PERIPH_CLKDIS3 (PERI_BASE + 0x234)
+#define PERI_SC_PERIPH_CLKSTAT3 (PERI_BASE + 0x238)
+#define PERI_SC_PERIPH_CLKEN8 (PERI_BASE + 0x240)
+#define PERI_SC_PERIPH_CLKDIS8 (PERI_BASE + 0x244)
+#define PERI_SC_PERIPH_CLKSTAT8 (PERI_BASE + 0x248)
+#define PERI_SC_PERIPH_CLKEN9 (PERI_BASE + 0x250)
+#define PERI_SC_PERIPH_CLKDIS9 (PERI_BASE + 0x254)
+#define PERI_SC_PERIPH_CLKSTAT9 (PERI_BASE + 0x258)
+#define PERI_SC_PERIPH_CLKEN10 (PERI_BASE + 0x260)
+#define PERI_SC_PERIPH_CLKDIS10 (PERI_BASE + 0x264)
+#define PERI_SC_PERIPH_CLKSTAT10 (PERI_BASE + 0x268)
+#define PERI_SC_PERIPH_CLKEN12 (PERI_BASE + 0x270)
+#define PERI_SC_PERIPH_CLKDIS12 (PERI_BASE + 0x274)
+#define PERI_SC_PERIPH_CLKSTAT12 (PERI_BASE + 0x278)
+
+#define PERI_SC_PERIPH_RSTEN0 (PERI_BASE + 0x300)
+#define PERI_SC_PERIPH_RSTDIS0 (PERI_BASE + 0x304)
+#define PERI_SC_PERIPH_RSTSTAT0 (PERI_BASE + 0x308)
+#define PERI_SC_PERIPH_RSTEN1 (PERI_BASE + 0x310)
+#define PERI_SC_PERIPH_RSTDIS1 (PERI_BASE + 0x314)
+#define PERI_SC_PERIPH_RSTSTAT1 (PERI_BASE + 0x318)
+#define PERI_SC_PERIPH_RSTEN2 (PERI_BASE + 0x320)
+#define PERI_SC_PERIPH_RSTDIS2 (PERI_BASE + 0x324)
+#define PERI_SC_PERIPH_RSTSTAT2 (PERI_BASE + 0x328)
+#define PERI_SC_PERIPH_RSTEN3 (PERI_BASE + 0x330)
+#define PERI_SC_PERIPH_RSTDIS3 (PERI_BASE + 0x334)
+#define PERI_SC_PERIPH_RSTSTAT3 (PERI_BASE + 0x338)
+#define PERI_SC_PERIPH_RSTEN8 (PERI_BASE + 0x340)
+#define PERI_SC_PERIPH_RSTDIS8 (PERI_BASE + 0x344)
+#define PERI_SC_PERIPH_RSTSTAT8 (PERI_BASE + 0x338)
+
+#define PERI_SC_CLK_SEL0 (PERI_BASE + 0x400)
+#define PERI_SC_CLKCFG8BIT1 (PERI_BASE + 0x494)
+#define PERI_SC_CLKCFG8BIT2 (PERI_BASE + 0x498)
+#define PERI_SC_RESERVED8_ADDR (PERI_BASE + 0xd04)
+
+/* PERI_SC_PERIPH_CTRL1 */
+#define PERI_CTRL1_ETR_AXI_CSYSREQ_N (1 << 0)
+#define PERI_CTRL1_ETR_AXI_CSYSREQ_N (1 << 0)
+#define PERI_CTRL1_HIFI_INT_MASK (1 << 1)
+#define PERI_CTRL1_HIFI_ALL_INT_MASK (1 << 2)
+#define PERI_CTRL1_ETR_AXI_CSYSREQ_N_MSK (1 << 16)
+#define PERI_CTRL1_HIFI_INT_MASK_MSK (1 << 17)
+#define PERI_CTRL1_HIFI_ALL_INT_MASK_MSK (1 << 18)
+
+/* PERI_SC_PERIPH_CTRL2 */
+#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC0 (1 << 0)
+#define PERI_CTRL2_MMC_CLK_PHASE_BYPASS_EN_MMC1 (1 << 2)
+#define PERI_CTRL2_NAND_SYS_MEM_SEL (1 << 6)
+#define PERI_CTRL2_G3D_DDRT_AXI_SEL (1 << 7)
+#define PERI_CTRL2_GU_MDM_BBP_TESTPIN_SEL (1 << 8)
+#define PERI_CTRL2_CODEC_SSI_MASTER_CHECK (1 << 9)
+#define PERI_CTRL2_FUNC_TEST_SOFT (1 << 12)
+#define PERI_CTRL2_CSSYS_TS_ENABLE (1 << 15)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_EMA (1 << 16)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAW (1 << 20)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_EMAS (1 << 22)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_RET1N (1 << 26)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_RET2N (1 << 27)
+#define PERI_CTRL2_HIFI_RAMCTRL_S_PGEN (1 << 28)
+
+/* PERI_SC_PERIPH_CTRL3 */
+#define PERI_CTRL3_HIFI_DDR_HARQMEM_ADDR (1 << 0)
+#define PERI_CTRL3_HIFI_HARQMEMRMP_EN (1 << 12)
+#define PERI_CTRL3_HARQMEM_SYS_MED_SEL (1 << 13)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP1 (1 << 14)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP2 (1 << 16)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP3 (1 << 18)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP4 (1 << 20)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP5 (1 << 22)
+#define PERI_CTRL3_SOC_AP_OCCUPY_GRP6 (1 << 24)
+
+/* PERI_SC_PERIPH_CTRL4 */
+#define PERI_CTRL4_PICO_FSELV (1 << 0)
+#define PERI_CTRL4_FPGA_EXT_PHY_SEL (1 << 3)
+#define PERI_CTRL4_PICO_REFCLKSEL (1 << 4)
+#define PERI_CTRL4_PICO_SIDDQ (1 << 6)
+#define PERI_CTRL4_PICO_SUSPENDM_SLEEPM (1 << 7)
+#define PERI_CTRL4_PICO_OGDISABLE (1 << 8)
+#define PERI_CTRL4_PICO_COMMONONN (1 << 9)
+#define PERI_CTRL4_PICO_VBUSVLDEXT (1 << 10)
+#define PERI_CTRL4_PICO_VBUSVLDEXTSEL (1 << 11)
+#define PERI_CTRL4_PICO_VATESTENB (1 << 12)
+#define PERI_CTRL4_PICO_SUSPENDM (1 << 14)
+#define PERI_CTRL4_PICO_SLEEPM (1 << 15)
+#define PERI_CTRL4_BC11_C (1 << 16)
+#define PERI_CTRL4_BC11_B (1 << 17)
+#define PERI_CTRL4_BC11_A (1 << 18)
+#define PERI_CTRL4_BC11_GND (1 << 19)
+#define PERI_CTRL4_BC11_FLOAT (1 << 20)
+#define PERI_CTRL4_OTG_PHY_SEL (1 << 21)
+#define PERI_CTRL4_USB_OTG_SS_SCALEDOWN_MODE (1 << 22)
+#define PERI_CTRL4_OTG_DM_PULLDOWN (1 << 24)
+#define PERI_CTRL4_OTG_DP_PULLDOWN (1 << 25)
+#define PERI_CTRL4_OTG_IDPULLUP (1 << 26)
+#define PERI_CTRL4_OTG_DRVBUS (1 << 27)
+#define PERI_CTRL4_OTG_SESSEND (1 << 28)
+#define PERI_CTRL4_OTG_BVALID (1 << 29)
+#define PERI_CTRL4_OTG_AVALID (1 << 30)
+#define PERI_CTRL4_OTG_VBUSVALID (1U << 31)
+
+/* PERI_SC_PERIPH_CTRL5 */
+#define PERI_CTRL5_USBOTG_RES_SEL (1 << 3)
+#define PERI_CTRL5_PICOPHY_ACAENB (1 << 4)
+#define PERI_CTRL5_PICOPHY_BC_MODE (1 << 5)
+#define PERI_CTRL5_PICOPHY_CHRGSEL (1 << 6)
+#define PERI_CTRL5_PICOPHY_VDATSRCEND (1 << 7)
+#define PERI_CTRL5_PICOPHY_VDATDETENB (1 << 8)
+#define PERI_CTRL5_PICOPHY_DCDENB (1 << 9)
+#define PERI_CTRL5_PICOPHY_IDDIG (1 << 10)
+#define PERI_CTRL5_DBG_MUX (1 << 11)
+
+/* PERI_SC_PERIPH_CTRL6 */
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMA (1 << 0)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAW (1 << 4)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_EMAS (1 << 6)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET1N (1 << 10)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_RET2N (1 << 11)
+#define PERI_CTRL6_CSSYSOFF_RAMCTRL_S_PGEN (1 << 12)
+
+/* PERI_SC_PERIPH_CTRL8 */
+#define PERI_CTRL8_PICOPHY_TXRISETUNE0 (1 << 0)
+#define PERI_CTRL8_PICOPHY_TXPREEMPAMPTUNE0 (1 << 2)
+#define PERI_CTRL8_PICOPHY_TXRESTUNE0 (1 << 4)
+#define PERI_CTRL8_PICOPHY_TXHSSVTUNE0 (1 << 6)
+#define PERI_CTRL8_PICOPHY_COMPDISTUNE0 (1 << 8)
+#define PERI_CTRL8_PICOPHY_TXPREEMPPULSETUNE0 (1 << 11)
+#define PERI_CTRL8_PICOPHY_OTGTUNE0 (1 << 12)
+#define PERI_CTRL8_PICOPHY_SQRXTUNE0 (1 << 16)
+#define PERI_CTRL8_PICOPHY_TXVREFTUNE0 (1 << 20)
+#define PERI_CTRL8_PICOPHY_TXFSLSTUNE0 (1 << 28)
+
+/* PERI_SC_PERIPH_CTRL9 */
+#define PERI_CTRL9_PICOPLY_TESTCLKEN (1 << 0)
+#define PERI_CTRL9_PICOPLY_TESTDATAOUTSEL (1 << 1)
+#define PERI_CTRL9_PICOPLY_TESTADDR (1 << 4)
+#define PERI_CTRL9_PICOPLY_TESTDATAIN (1 << 8)
+
+/*
+ * PERI_SC_PERIPH_CLKEN0
+ * PERI_SC_PERIPH_CLKDIS0
+ * PERI_SC_PERIPH_CLKSTAT0
+ */
+#define PERI_CLK0_MMC0 (1 << 0)
+#define PERI_CLK0_MMC1 (1 << 1)
+#define PERI_CLK0_MMC2 (1 << 2)
+#define PERI_CLK0_NANDC (1 << 3)
+#define PERI_CLK0_USBOTG (1 << 4)
+#define PERI_CLK0_PICOPHY (1 << 5)
+#define PERI_CLK0_PLL (1 << 6)
+
+/*
+ * PERI_SC_PERIPH_CLKEN1
+ * PERI_SC_PERIPH_CLKDIS1
+ * PERI_SC_PERIPH_CLKSTAT1
+ */
+#define PERI_CLK1_HIFI (1 << 0)
+#define PERI_CLK1_DIGACODEC (1 << 5)
+
+/*
+ * PERI_SC_PERIPH_CLKEN2
+ * PERI_SC_PERIPH_CLKDIS2
+ * PERI_SC_PERIPH_CLKSTAT2
+ */
+#define PERI_CLK2_IPF (1 << 0)
+#define PERI_CLK2_SOCP (1 << 1)
+#define PERI_CLK2_DMAC (1 << 2)
+#define PERI_CLK2_SECENG (1 << 3)
+#define PERI_CLK2_HPM0 (1 << 5)
+#define PERI_CLK2_HPM1 (1 << 6)
+#define PERI_CLK2_HPM2 (1 << 7)
+#define PERI_CLK2_HPM3 (1 << 8)
+
+/*
+ * PERI_SC_PERIPH_CLKEN3
+ * PERI_SC_PERIPH_CLKDIS3
+ * PERI_SC_PERIPH_CLKSTAT3
+ */
+#define PERI_CLK3_CSSYS (1 << 0)
+#define PERI_CLK3_I2C0 (1 << 1)
+#define PERI_CLK3_I2C1 (1 << 2)
+#define PERI_CLK3_I2C2 (1 << 3)
+#define PERI_CLK3_I2C3 (1 << 4)
+#define PERI_CLK3_UART1 (1 << 5)
+#define PERI_CLK3_UART2 (1 << 6)
+#define PERI_CLK3_UART3 (1 << 7)
+#define PERI_CLK3_UART4 (1 << 8)
+#define PERI_CLK3_SSP (1 << 9)
+#define PERI_CLK3_PWM (1 << 10)
+#define PERI_CLK3_BLPWM (1 << 11)
+#define PERI_CLK3_TSENSOR (1 << 12)
+#define PERI_CLK3_GPS (1 << 15)
+#define PERI_CLK3_TCXO_PAD0 (1 << 16)
+#define PERI_CLK3_TCXO_PAD1 (1 << 17)
+#define PERI_CLK3_DAPB (1 << 18)
+#define PERI_CLK3_HKADC (1 << 19)
+#define PERI_CLK3_CODEC_SSI (1 << 20)
+#define PERI_CLK3_TZPC_DEP (1 << 21)
+
+/*
+ * PERI_SC_PERIPH_CLKEN8
+ * PERI_SC_PERIPH_CLKDIS8
+ * PERI_SC_PERIPH_CLKSTAT8
+ */
+#define PERI_CLK8_RS0 (1 << 0)
+#define PERI_CLK8_RS2 (1 << 1)
+#define PERI_CLK8_RS3 (1 << 2)
+#define PERI_CLK8_MS0 (1 << 3)
+#define PERI_CLK8_MS2 (1 << 5)
+#define PERI_CLK8_XG2RAM0 (1 << 6)
+#define PERI_CLK8_X2SRAM (1 << 7)
+#define PERI_CLK8_SRAM (1 << 8)
+#define PERI_CLK8_ROM (1 << 9)
+#define PERI_CLK8_HARQ (1 << 10)
+#define PERI_CLK8_MMU (1 << 11)
+#define PERI_CLK8_DDRC (1 << 12)
+#define PERI_CLK8_DDRPHY (1 << 13)
+#define PERI_CLK8_DDRPHY_REF (1 << 14)
+#define PERI_CLK8_X2X_SYSNOC (1 << 15)
+#define PERI_CLK8_X2X_CCPU (1 << 16)
+#define PERI_CLK8_DDRT (1 << 17)
+#define PERI_CLK8_DDRPACK_RS (1 << 18)
+
+/*
+ * PERI_SC_PERIPH_CLKEN9
+ * PERI_SC_PERIPH_CLKDIS9
+ * PERI_SC_PERIPH_CLKSTAT9
+ */
+#define PERI_CLK9_CARM_DAP (1 << 0)
+#define PERI_CLK9_CARM_ATB (1 << 1)
+#define PERI_CLK9_CARM_LBUS (1 << 2)
+#define PERI_CLK9_CARM_KERNEL (1 << 3)
+
+/*
+ * PERI_SC_PERIPH_CLKEN10
+ * PERI_SC_PERIPH_CLKDIS10
+ * PERI_SC_PERIPH_CLKSTAT10
+ */
+#define PERI_CLK10_IPF_CCPU (1 << 0)
+#define PERI_CLK10_SOCP_CCPU (1 << 1)
+#define PERI_CLK10_SECENG_CCPU (1 << 2)
+#define PERI_CLK10_HARQ_CCPU (1 << 3)
+#define PERI_CLK10_IPF_MCU (1 << 16)
+#define PERI_CLK10_SOCP_MCU (1 << 17)
+#define PERI_CLK10_SECENG_MCU (1 << 18)
+#define PERI_CLK10_HARQ_MCU (1 << 19)
+
+/*
+ * PERI_SC_PERIPH_CLKEN12
+ * PERI_SC_PERIPH_CLKDIS12
+ * PERI_SC_PERIPH_CLKSTAT12
+ */
+#define PERI_CLK12_HIFI_SRC (1 << 0)
+#define PERI_CLK12_MMC0_SRC (1 << 1)
+#define PERI_CLK12_MMC1_SRC (1 << 2)
+#define PERI_CLK12_MMC2_SRC (1 << 3)
+#define PERI_CLK12_SYSPLL_DIV (1 << 4)
+#define PERI_CLK12_TPIU_SRC (1 << 5)
+#define PERI_CLK12_MMC0_HF (1 << 6)
+#define PERI_CLK12_MMC1_HF (1 << 7)
+#define PERI_CLK12_PLL_TEST_SRC (1 << 8)
+#define PERI_CLK12_CODEC_SOC (1 << 9)
+#define PERI_CLK12_MEDIA (1 << 10)
+
+/*
+ * PERI_SC_PERIPH_RSTEN0
+ * PERI_SC_PERIPH_RSTDIS0
+ * PERI_SC_PERIPH_RSTSTAT0
+ */
+#define PERI_RST0_MMC0 (1 << 0)
+#define PERI_RST0_MMC1 (1 << 1)
+#define PERI_RST0_MMC2 (1 << 2)
+#define PERI_RST0_NANDC (1 << 3)
+#define PERI_RST0_USBOTG_BUS (1 << 4)
+#define PERI_RST0_POR_PICOPHY (1 << 5)
+#define PERI_RST0_USBOTG (1 << 6)
+#define PERI_RST0_USBOTG_32K (1 << 7)
+
+/*
+ * PERI_SC_PERIPH_RSTEN1
+ * PERI_SC_PERIPH_RSTDIS1
+ * PERI_SC_PERIPH_RSTSTAT1
+ */
+#define PERI_RST1_HIFI (1 << 0)
+#define PERI_RST1_DIGACODEC (1 << 5)
+
+/*
+ * PERI_SC_PERIPH_RSTEN2
+ * PERI_SC_PERIPH_RSTDIS2
+ * PERI_SC_PERIPH_RSTSTAT2
+ */
+#define PERI_RST2_IPF (1 << 0)
+#define PERI_RST2_SOCP (1 << 1)
+#define PERI_RST2_DMAC (1 << 2)
+#define PERI_RST2_SECENG (1 << 3)
+#define PERI_RST2_ABB (1 << 4)
+#define PERI_RST2_HPM0 (1 << 5)
+#define PERI_RST2_HPM1 (1 << 6)
+#define PERI_RST2_HPM2 (1 << 7)
+#define PERI_RST2_HPM3 (1 << 8)
+
+/*
+ * PERI_SC_PERIPH_RSTEN3
+ * PERI_SC_PERIPH_RSTDIS3
+ * PERI_SC_PERIPH_RSTSTAT3
+ */
+#define PERI_RST3_CSSYS (1 << 0)
+#define PERI_RST3_I2C0 (1 << 1)
+#define PERI_RST3_I2C1 (1 << 2)
+#define PERI_RST3_I2C2 (1 << 3)
+#define PERI_RST3_I2C3 (1 << 4)
+#define PERI_RST3_UART1 (1 << 5)
+#define PERI_RST3_UART2 (1 << 6)
+#define PERI_RST3_UART3 (1 << 7)
+#define PERI_RST3_UART4 (1 << 8)
+#define PERI_RST3_SSP (1 << 9)
+#define PERI_RST3_PWM (1 << 10)
+#define PERI_RST3_BLPWM (1 << 11)
+#define PERI_RST3_TSENSOR (1 << 12)
+#define PERI_RST3_DAPB (1 << 18)
+#define PERI_RST3_HKADC (1 << 19)
+#define PERI_RST3_CODEC (1 << 20)
+
+/*
+ * PERI_SC_PERIPH_RSTEN8
+ * PERI_SC_PERIPH_RSTDIS8
+ * PERI_SC_PERIPH_RSTSTAT8
+ */
+#define PERI_RST8_RS0 (1 << 0)
+#define PERI_RST8_RS2 (1 << 1)
+#define PERI_RST8_RS3 (1 << 2)
+#define PERI_RST8_MS0 (1 << 3)
+#define PERI_RST8_MS2 (1 << 5)
+#define PERI_RST8_XG2RAM0 (1 << 6)
+#define PERI_RST8_X2SRAM_TZMA (1 << 7)
+#define PERI_RST8_SRAM (1 << 8)
+#define PERI_RST8_HARQ (1 << 10)
+#define PERI_RST8_DDRC (1 << 12)
+#define PERI_RST8_DDRC_APB (1 << 13)
+#define PERI_RST8_DDRPACK_APB (1 << 14)
+#define PERI_RST8_DDRT (1 << 17)
+
+#endif /* HI6220_REGS_PERI_H */
diff --git a/plat/hisilicon/hikey/include/hi6220_regs_pin.h b/plat/hisilicon/hikey/include/hi6220_regs_pin.h
new file mode 100644
index 0000000..05620ea
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hi6220_regs_pin.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI6220_REGS_PIN_H
+#define HI6220_REGS_PIN_H
+
+#define IOMG_BASE 0xF7010000
+
+#define IOMG_SD_CLK (IOMG_BASE + 0x0C)
+#define IOMG_SD_CMD (IOMG_BASE + 0x10)
+#define IOMG_SD_DATA0 (IOMG_BASE + 0x14)
+#define IOMG_SD_DATA1 (IOMG_BASE + 0x18)
+#define IOMG_SD_DATA2 (IOMG_BASE + 0x1C)
+#define IOMG_SD_DATA3 (IOMG_BASE + 0x20)
+#define IOMG_GPIO24 (IOMG_BASE + 0x140)
+
+#define IOMG_MUX_FUNC0 0
+#define IOMG_MUX_FUNC1 1
+#define IOMG_MUX_FUNC2 2
+
+#define IOCG1_BASE 0xF7010800
+#define IOCG2_BASE 0xF8001800
+
+#define IOCG_SD_CLK (IOCG1_BASE + 0x0C)
+#define IOCG_SD_CMD (IOCG1_BASE + 0x10)
+#define IOCG_SD_DATA0 (IOCG1_BASE + 0x14)
+#define IOCG_SD_DATA1 (IOCG1_BASE + 0x18)
+#define IOCG_SD_DATA2 (IOCG1_BASE + 0x1C)
+#define IOCG_SD_DATA3 (IOCG1_BASE + 0x20)
+#define IOCG_GPIO24 (IOCG1_BASE + 0x150)
+#define IOCG_GPIO8 (IOCG2_BASE + 0x30)
+
+#define IOCG_DRIVE_8MA (2 << 4)
+#define IOCG_DRIVE_10MA (3 << 4)
+#define IOCG_INPUT_16MA 0x64
+#define IOCG_INPUT_12MA 0x54
+#define IOCG_PULLDOWN (1 << 1)
+#define IOCG_PULLUP (1 << 0)
+
+#endif /* HI6220_REGS_PIN_H */
diff --git a/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h b/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h
new file mode 100644
index 0000000..404405b
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI6220_REGS_PMCTRL_H
+#define HI6220_REGS_PMCTRL_H
+
+#define PMCTRL_BASE 0xF7032000
+
+#define PMCTRL_ACPUPLLCTRL (PMCTRL_BASE + 0x000)
+#define PMCTRL_ACPUPLLFREQ (PMCTRL_BASE + 0x004)
+#define PMCTRL_DDRPLL1CTRL (PMCTRL_BASE + 0x010)
+#define PMCTRL_DDRPLL0CTRL (PMCTRL_BASE + 0x030)
+#define PMCTRL_MEDPLLCTRL (PMCTRL_BASE + 0x038)
+#define PMCTRL_ACPUPLLSEL (PMCTRL_BASE + 0x100)
+#define PMCTRL_ACPUCLKDIV (PMCTRL_BASE + 0x104)
+#define PMCTRL_ACPUSYSPLLCFG (PMCTRL_BASE + 0x110)
+#define PMCTRL_ACPUCLKOFFCFG (PMCTRL_BASE + 0x114)
+#define PMCTRL_ACPUPLLFRAC (PMCTRL_BASE + 0x134)
+#define PMCTRL_ACPUPMUVOLUPTIME (PMCTRL_BASE + 0x360)
+#define PMCTRL_ACPUPMUVOLDNTIME (PMCTRL_BASE + 0x364)
+#define PMCTRL_ACPUVOLPMUADDR (PMCTRL_BASE + 0x368)
+#define PMCTRL_ACPUVOLUPSTEP (PMCTRL_BASE + 0x36c)
+#define PMCTRL_ACPUVOLDNSTEP (PMCTRL_BASE + 0x370)
+#define PMCTRL_ACPUDFTVOL (PMCTRL_BASE + 0x374)
+#define PMCTRL_ACPUDESTVOL (PMCTRL_BASE + 0x378)
+#define PMCTRL_ACPUVOLTTIMEOUT (PMCTRL_BASE + 0x37c)
+
+#define PMCTRL_ACPUPLLCTRL_EN_CFG (1 << 0)
+
+#define PMCTRL_ACPUCLKDIV_CPUEXT_CFG_MASK (3 << 0)
+#define PMCTRL_ACPUCLKDIV_DDR_CFG_MASK (3 << 8)
+#define PMCTRL_ACPUCLKDIV_CPUEXT_STAT_MASK (3 << 16)
+#define PMCTRL_ACPUCLKDIV_DDR_STAT_MASK (3 << 24)
+
+#define PMCTRL_ACPUPLLSEL_ACPUPLL_CFG (1 << 0)
+#define PMCTRL_ACPUPLLSEL_ACPUPLL_STAT (1 << 1)
+#define PMCTRL_ACPUPLLSEL_SYSPLL_STAT (1 << 2)
+
+#define PMCTRL_ACPUSYSPLL_CLKDIV_CFG_MASK 0x7
+#define PMCTRL_ACPUSYSPLL_CLKEN_CFG (1 << 4)
+#define PMCTRL_ACPUSYSPLL_CLKDIV_SW (3 << 12)
+
+#define PMCTRL_ACPUSYSPLLCFG_SYSPLL_CLKEN (1 << 4)
+#define PMCTRL_ACPUSYSPLLCFG_CLKDIV_MASK (3 << 12)
+
+#define PMCTRL_ACPUDESTVOL_DEST_VOL_MASK 0x7f
+#define PMCTRL_ACPUDESTVOL_CURR_VOL_MASK (0x7f << 8)
+
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_START (0)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_en_cfg_END (0)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_START (2)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_rst_END (2)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_START (4)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_time_END (27)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_START (28)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_timeout_END (28)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_START (29)
+#define SOC_PMCTRL_ACPUPLLCTRL_acpupll_lock_END (29)
+
+#define SOC_PMCTRL_ACPUPLLFRAC_ADDR(base) ((base) + (0x134))
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_sw_START (12)
+
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_START (0)
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_cfg_END (0)
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_START (1)
+#define SOC_PMCTRL_ACPUPLLSEL_acpu_pllsw_stat_END (1)
+#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_START (2)
+#define SOC_PMCTRL_ACPUPLLSEL_syspll_sw_stat_END (2)
+
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_START (0)
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_cfg_END (1)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_START (8)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_cfg_END (9)
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_START (16)
+#define SOC_PMCTRL_ACPUCLKDIV_cpuext_clk_div_stat_END (17)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_START (24)
+#define SOC_PMCTRL_ACPUCLKDIV_acpu_ddr_clk_div_stat_END (25)
+
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_START (0)
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_dest_vol_END (6)
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_START (8)
+#define SOC_PMCTRL_ACPUDESTVOL_acpu_vol_using_END (14)
+
+#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_START (0)
+#define SOC_PMCTRL_ACPUVOLTIMEOUT_acpu_vol_timeout_END (0)
+
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_START (0)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_cfg_END (2)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_START (4)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_cfg_END (4)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_START (8)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_subsys_clk_div_cfg_END (9)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_START (16)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_div_stat_END (19)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_START (20)
+#define SOC_PMCTRL_ACPUSYSPLLCFG_acpu_syspll_clken_stat_END (20)
+
+#endif /* HI6220_REGS_PMCTRL_H */
diff --git a/plat/hisilicon/hikey/include/hi6553.h b/plat/hisilicon/hikey/include/hi6553.h
new file mode 100644
index 0000000..fc991f8
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hi6553.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI6553_H
+#define HI6553_H
+
+#include <lib/mmio.h>
+
+#include <hi6220.h>
+
+#define HI6553_DISABLE6_XO_CLK (PMUSSI_BASE + (0x036 << 2))
+
+#define DISABLE6_XO_CLK_BB (1 << 0)
+#define DISABLE6_XO_CLK_CONN (1 << 1)
+#define DISABLE6_XO_CLK_NFC (1 << 2)
+#define DISABLE6_XO_CLK_RF1 (1 << 3)
+#define DISABLE6_XO_CLK_RF2 (1 << 4)
+
+#define HI6553_VERSION_REG (PMUSSI_BASE + (0x000 << 2))
+#define HI6553_IRQ2_MASK (PMUSSI_BASE + (0x008 << 2))
+#define HI6553_ENABLE2_LDO1_8 (PMUSSI_BASE + (0x029 << 2))
+#define HI6553_DISABLE2_LDO1_8 (PMUSSI_BASE + (0x02a << 2))
+#define HI6553_ONOFF_STATUS2_LDO1_8 (PMUSSI_BASE + (0x02b << 2))
+#define HI6553_ENABLE3_LDO9_16 (PMUSSI_BASE + (0x02c << 2))
+#define HI6553_DISABLE3_LDO9_16 (PMUSSI_BASE + (0x02d << 2))
+#define HI6553_ONOFF_STATUS3_LDO9_16 (PMUSSI_BASE + (0x02e << 2))
+#define HI6553_ENABLE4_LDO17_22 (PMUSSI_BASE + (0x02f << 2))
+#define HI6553_DISABLE4_LDO17_22 (PMUSSI_BASE + (0x030 << 2))
+#define HI6553_ONOFF_STATUS4_LDO17_22 (PMUSSI_BASE + (0x031 << 2))
+#define HI6553_PERI_EN_MARK (PMUSSI_BASE + (0x040 << 2))
+#define HI6553_BUCK2_REG1 (PMUSSI_BASE + (0x04a << 2))
+#define HI6553_BUCK2_REG5 (PMUSSI_BASE + (0x04e << 2))
+#define HI6553_BUCK2_REG6 (PMUSSI_BASE + (0x04f << 2))
+#define HI6553_BUCK3_REG3 (PMUSSI_BASE + (0x054 << 2))
+#define HI6553_BUCK3_REG5 (PMUSSI_BASE + (0x056 << 2))
+#define HI6553_BUCK3_REG6 (PMUSSI_BASE + (0x057 << 2))
+#define HI6553_BUCK4_REG2 (PMUSSI_BASE + (0x05b << 2))
+#define HI6553_BUCK4_REG5 (PMUSSI_BASE + (0x05e << 2))
+#define HI6553_BUCK4_REG6 (PMUSSI_BASE + (0x05f << 2))
+#define HI6553_CLK_TOP0 (PMUSSI_BASE + (0x063 << 2))
+#define HI6553_CLK_TOP3 (PMUSSI_BASE + (0x066 << 2))
+#define HI6553_CLK_TOP4 (PMUSSI_BASE + (0x067 << 2))
+#define HI6553_VSET_BUCK2_ADJ (PMUSSI_BASE + (0x06d << 2))
+#define HI6553_VSET_BUCK3_ADJ (PMUSSI_BASE + (0x06e << 2))
+#define HI6553_LDO7_REG_ADJ (PMUSSI_BASE + (0x078 << 2))
+#define HI6553_LDO10_REG_ADJ (PMUSSI_BASE + (0x07b << 2))
+#define HI6553_LDO15_REG_ADJ (PMUSSI_BASE + (0x080 << 2))
+#define HI6553_LDO19_REG_ADJ (PMUSSI_BASE + (0x084 << 2))
+#define HI6553_LDO20_REG_ADJ (PMUSSI_BASE + (0x085 << 2))
+#define HI6553_LDO21_REG_ADJ (PMUSSI_BASE + (0x086 << 2))
+#define HI6553_LDO22_REG_ADJ (PMUSSI_BASE + (0x087 << 2))
+#define HI6553_DR_LED_CTRL (PMUSSI_BASE + (0x098 << 2))
+#define HI6553_DR_OUT_CTRL (PMUSSI_BASE + (0x099 << 2))
+#define HI6553_DR3_ISET (PMUSSI_BASE + (0x09a << 2))
+#define HI6553_DR3_START_DEL (PMUSSI_BASE + (0x09b << 2))
+#define HI6553_DR4_ISET (PMUSSI_BASE + (0x09c << 2))
+#define HI6553_DR4_START_DEL (PMUSSI_BASE + (0x09d << 2))
+#define HI6553_DR345_TIM_CONF0 (PMUSSI_BASE + (0x0a0 << 2))
+#define HI6553_NP_REG_ADJ1 (PMUSSI_BASE + (0x0be << 2))
+#define HI6553_NP_REG_CHG (PMUSSI_BASE + (0x0c0 << 2))
+#define HI6553_BUCK01_CTRL2 (PMUSSI_BASE + (0x0d9 << 2))
+#define HI6553_BUCK0_CTRL1 (PMUSSI_BASE + (0x0dd << 2))
+#define HI6553_BUCK0_CTRL5 (PMUSSI_BASE + (0x0e1 << 2))
+#define HI6553_BUCK0_CTRL7 (PMUSSI_BASE + (0x0e3 << 2))
+#define HI6553_BUCK1_CTRL1 (PMUSSI_BASE + (0x0e8 << 2))
+#define HI6553_BUCK1_CTRL5 (PMUSSI_BASE + (0x0ec << 2))
+#define HI6553_BUCK1_CTRL7 (PMUSSI_BASE + (0x0ef << 2))
+#define HI6553_CLK19M2_600_586_EN (PMUSSI_BASE + (0x0fe << 2))
+
+#define LED_START_DELAY_TIME 0x00
+#define LED_ELEC_VALUE 0x07
+#define LED_LIGHT_TIME 0xf0
+#define LED_GREEN_ENABLE (1 << 1)
+#define LED_OUT_CTRL 0x00
+
+#define PMU_HI6552_V300 0x30
+#define PMU_HI6552_V310 0x31
+
+#endif /* HI6553_H */
diff --git a/plat/hisilicon/hikey/include/hikey_def.h b/plat/hisilicon/hikey/include/hikey_def.h
new file mode 100644
index 0000000..590700d
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hikey_def.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HIKEY_DEF_H
+#define HIKEY_DEF_H
+
+/* Always assume DDR is 1GB size. */
+#define DDR_BASE 0x0
+#define DDR_SIZE 0x40000000
+
+#define DEVICE_BASE 0xF4000000
+#define DEVICE_SIZE 0x05800000
+
+/* Memory location options for TSP */
+#define HIKEY_SRAM_ID 0
+#define HIKEY_DRAM_ID 1
+
+/*
+ * DDR for OP-TEE (32MB from 0x3E00000-0x3FFFFFFF) is divided in several
+ * regions
+ * - Secure DDR (default is the top 16MB) used by OP-TEE
+ * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ * - Non-secure DDR (8MB) reserved for OP-TEE's future use
+ */
+#define DDR_SEC_SIZE 0x01000000
+#define DDR_SEC_BASE (DDR_BASE + DDR_SIZE - DDR_SEC_SIZE) /* 0x3F000000 */
+
+#define DDR_SDP_SIZE 0x00400000
+#define DDR_SDP_BASE (DDR_SEC_BASE - 0x400000 /* align */ - \
+ DDR_SDP_SIZE)
+
+#define SRAM_BASE 0xFFF80000
+#define SRAM_SIZE 0x00012000
+
+/*
+ * PL011 related constants
+ */
+#define PL011_UART0_BASE 0xF8015000
+#define PL011_UART2_BASE 0xF7112000
+#define PL011_UART3_BASE 0xF7113000
+#define PL011_BAUDRATE 115200
+#define PL011_UART_CLK_IN_HZ 19200000
+
+#define HIKEY_USB_DESC_BASE (DDR_BASE + 0x00800000)
+#define HIKEY_USB_DESC_SIZE 0x00100000
+#define HIKEY_USB_DATA_BASE (DDR_BASE + 0x10000000)
+#define HIKEY_USB_DATA_SIZE 0x10000000
+#define HIKEY_FB_BUFFER_BASE (HIKEY_USB_DATA_BASE)
+#define HIKEY_FB_BUFFER_SIZE HIKEY_USB_DATA_SIZE
+#define HIKEY_FB_DOWNLOAD_BASE (HIKEY_FB_BUFFER_BASE + \
+ HIKEY_FB_BUFFER_SIZE)
+#define HIKEY_FB_DOWNLOAD_SIZE HIKEY_USB_DATA_SIZE
+
+#define HIKEY_USB_DESC_IN_BASE (DDR_BASE + 0x00800000)
+#define HIKEY_USB_DESC_IN_SIZE 0x00040000
+#define HIKEY_USB_DESC_EP0_OUT_BASE (HIKEY_USB_DESC_IN_BASE + \
+ HIKEY_USB_DESC_IN_SIZE)
+#define HIKEY_USB_DESC_EP0_OUT_SIZE 0x00040000
+#define HIKEY_USB_DESC_EPX_OUT_BASE (HIKEY_USB_DESC_EP0_OUT_BASE + \
+ HIKEY_USB_DESC_EP0_OUT_SIZE)
+#define HIKEY_USB_DESC_EPX_OUT_SIZE 0x00080000
+
+#define HIKEY_MMC_DESC_BASE (DDR_BASE + 0x03000000)
+#define HIKEY_MMC_DESC_SIZE 0x00100000
+
+/*
+ * HIKEY_MMC_DATA_BASE & HIKEY_MMC_DATA_SIZE are shared between fastboot
+ * and eMMC driver. Since it could avoid to memory copy.
+ * So this SRAM region is used twice. First, it's used in BL1 as temporary
+ * buffer in eMMC driver. Second, it's used by MCU in BL2. The SRAM region
+ * needs to be clear before used in BL2.
+ */
+#define HIKEY_MMC_DATA_BASE (DDR_BASE + 0x10000000)
+#define HIKEY_MMC_DATA_SIZE 0x20000000
+#define HIKEY_NS_IMAGE_OFFSET (DDR_BASE + 0x35000000)
+#define HIKEY_BL1_MMC_DESC_BASE (SRAM_BASE)
+#define HIKEY_BL1_MMC_DESC_SIZE 0x00001000
+#define HIKEY_BL1_MMC_DATA_BASE (HIKEY_BL1_MMC_DESC_BASE + \
+ HIKEY_BL1_MMC_DESC_SIZE)
+#define HIKEY_BL1_MMC_DATA_SIZE 0x0000B000
+
+#define EMMC_BASE 0
+#define HIKEY_EMMC_RPMB_BASE (EMMC_BASE + 0)
+#define HIKEY_EMMC_RPMB_MAX_SIZE (128 << 10)
+#define HIKEY_EMMC_USERDATA_BASE (EMMC_BASE + 0)
+#define HIKEY_EMMC_USERDATA_MAX_SIZE (4 << 30)
+
+/*
+ * GIC400 interrupt handling related constants
+ */
+#define IRQ_SEC_PHY_TIMER 29
+#define IRQ_SEC_SGI_0 8
+#define IRQ_SEC_SGI_1 9
+#define IRQ_SEC_SGI_2 10
+#define IRQ_SEC_SGI_3 11
+#define IRQ_SEC_SGI_4 12
+#define IRQ_SEC_SGI_5 13
+#define IRQ_SEC_SGI_6 14
+#define IRQ_SEC_SGI_7 15
+#define IRQ_SEC_SGI_8 16
+
+#endif /* HIKEY_DEF_H */
diff --git a/plat/hisilicon/hikey/include/hikey_layout.h b/plat/hisilicon/hikey/include/hikey_layout.h
new file mode 100644
index 0000000..4b8dc53
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hikey_layout.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HIKEY_LAYOUT_H
+#define HIKEY_LAYOUT_H
+
+/*
+ * Platform memory map related constants
+ */
+#define XG2RAM0_BASE 0xF9800000
+#define XG2RAM0_SIZE 0x00400000
+
+/*
+ * BL1 is stored in XG2RAM0_HIRQ that is 784KB large (0xF980_0000~0xF98C_4000).
+ */
+#define ONCHIPROM_PARAM_BASE (XG2RAM0_BASE + 0x700)
+#define LOADER_RAM_BASE (XG2RAM0_BASE + 0x800)
+#define BL1_XG2RAM0_OFFSET 0x1000
+
+/*
+ * BL1 specific defines.
+ *
+ * Both loader and BL1_RO region stay in SRAM since they are used to simulate
+ * ROM.
+ * Loader is used to switch Hi6220 SoC from 32-bit to 64-bit mode.
+ *
+ * ++++++++++ 0xF980_0000
+ * + loader +
+ * ++++++++++ 0xF980_1000
+ * + BL1_RO +
+ * ++++++++++ 0xF981_8000
+ * + BL1_RW +
+ * ++++++++++ 0xF989_8000
+ */
+#define BL1_RO_BASE (XG2RAM0_BASE + BL1_XG2RAM0_OFFSET)
+#define BL1_RO_LIMIT (XG2RAM0_BASE + 0x18000)
+#define BL1_RW_BASE (BL1_RO_LIMIT) /* 0xf981_8000 */
+#define BL1_RW_SIZE (0x00080000)
+#define BL1_RW_LIMIT (0xF9898000)
+
+/*
+ * Non-Secure BL1U specific defines.
+ */
+#define NS_BL1U_BASE (0xf9828000)
+#define NS_BL1U_SIZE (0x00010000)
+#define NS_BL1U_LIMIT (NS_BL1U_BASE + NS_BL1U_SIZE)
+
+/*
+ * BL2 specific defines.
+ *
+ * Both loader and BL2 region stay in SRAM.
+ * Loader is used to switch Hi6220 SoC from 32-bit to 64-bit mode.
+ *
+ * ++++++++++ 0xF980_0000
+ * + loader +
+ * ++++++++++ 0xF980_1000
+ * + BL2 +
+ * ++++++++++ 0xF983_0000
+ */
+#define BL2_BASE (BL1_RO_BASE) /* 0xf980_1000 */
+#define BL2_LIMIT (0xF9830000) /* 0xf983_0000 */
+
+/*
+ * SCP_BL2 specific defines.
+ * In HiKey, SCP_BL2 means MCU firmware. It's loaded into the temporary buffer
+ * at 0x0100_0000. Then BL2 will parse the sections and loaded them into
+ * predefined separated buffers.
+ */
+#define SCP_BL2_BASE (DDR_BASE + 0x01000000)
+#define SCP_BL2_LIMIT (SCP_BL2_BASE + 0x00100000)
+#define SCP_BL2_SIZE (SCP_BL2_LIMIT - SCP_BL2_BASE)
+
+/*
+ * BL31 specific defines.
+ */
+#define BL31_BASE (0xF9858000) /* 0xf985_8000 */
+#define BL31_LIMIT (0xF9898000)
+
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM or SRAM.
+ */
+#define BL32_SRAM_BASE BL31_LIMIT
+#define BL32_SRAM_LIMIT (BL31_LIMIT+0x80000) /* 512K */
+
+#define BL32_DRAM_BASE DDR_SEC_BASE
+#define BL32_DRAM_LIMIT (DDR_SEC_BASE+DDR_SEC_SIZE)
+
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define HIKEY_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - HIKEY_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */
+#define HIKEY_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */
+#endif
+
+#if (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_DRAM_ID)
+#define TSP_SEC_MEM_BASE BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE BL32_DRAM_BASE
+#define BL32_LIMIT BL32_DRAM_LIMIT
+#elif (HIKEY_TSP_RAM_LOCATION_ID == HIKEY_SRAM_ID)
+#define TSP_SEC_MEM_BASE BL32_SRAM_BASE
+#define TSP_SEC_MEM_SIZE (BL32_SRAM_LIMIT - BL32_SRAM_BASE)
+#define BL32_BASE BL32_SRAM_BASE
+#define BL32_LIMIT BL32_SRAM_LIMIT
+#else
+#error "Currently unsupported HIKEY_TSP_LOCATION_ID value"
+#endif
+
+/* BL32 is mandatory in AArch32 */
+#ifdef __aarch64__
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
+#endif /* HIKEY_LAYOUT_H */
diff --git a/plat/hisilicon/hikey/include/hisi_ipc.h b/plat/hisilicon/hikey/include/hisi_ipc.h
new file mode 100644
index 0000000..b0c0ae8
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hisi_ipc.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HISI_IPC_H
+#define HISI_IPC_H
+
+#define HISI_IPC_CORE_ACPU 0x0
+
+#define HISI_IPC_MCU_INT_SRC_ACPU0_PD 10
+#define HISI_IPC_MCU_INT_SRC_ACPU1_PD 11
+#define HISI_IPC_MCU_INT_SRC_ACPU2_PD 12
+#define HISI_IPC_MCU_INT_SRC_ACPU3_PD 13
+#define HISI_IPC_MCU_INT_SRC_ACPU_PD 16
+#define HISI_IPC_MCU_INT_SRC_ACPU4_PD 26
+#define HISI_IPC_MCU_INT_SRC_ACPU5_PD 27
+#define HISI_IPC_MCU_INT_SRC_ACPU6_PD 28
+#define HISI_IPC_MCU_INT_SRC_ACPU7_PD 29
+
+#define HISI_IPC_SEM_CPUIDLE 27
+#define HISI_IPC_INT_SRC_NUM 32
+
+#define HISI_IPC_PM_ON 0
+#define HISI_IPC_PM_OFF 1
+
+#define HISI_IPC_OK (0)
+#define HISI_IPC_ERROR (-1)
+
+#define HISI_IPC_BASE_ADDR (0xF7510000)
+#define HISI_IPC_CPU_RAW_INT_ADDR (0xF7510420)
+#define HISI_IPC_ACPU_CTRL(i) (0xF7510800 + (i << 3))
+
+void hisi_ipc_spin_lock(unsigned int signal);
+void hisi_ipc_spin_unlock(unsigned int signal);
+void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster);
+void hisi_ipc_psci_system_off(void);
+int hisi_ipc_init(void);
+
+#endif /* HISI_IPC_H */
diff --git a/plat/hisilicon/hikey/include/hisi_mcu.h b/plat/hisilicon/hikey/include/hisi_mcu.h
new file mode 100644
index 0000000..731c51a
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hisi_mcu.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HISI_MCU_H
+#define HISI_MCU_H
+
+#include <stdint.h>
+
+extern void hisi_mcu_enable_sram(void);
+extern void hisi_mcu_start_run(void);
+extern int hisi_mcu_load_image(uintptr_t image_base, uint32_t image_size);
+
+#endif /* HISI_MCU_H */
diff --git a/plat/hisilicon/hikey/include/hisi_pwrc.h b/plat/hisilicon/hikey/include/hisi_pwrc.h
new file mode 100644
index 0000000..cbb4651
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hisi_pwrc.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HISI_PWRC_H
+#define HISI_PWRC_H
+
+#ifndef __ASSEMBLER__
+
+void hisi_pwrc_set_cluster_wfi(unsigned int id);
+void hisi_pwrc_set_core_bx_addr(unsigned int core,
+ unsigned int cluster,
+ uintptr_t entry_point);
+void hisi_pwrc_enable_debug(unsigned int core,
+ unsigned int cluster);
+int hisi_pwrc_setup(void);
+
+#endif /*__ASSEMBLER__*/
+
+#endif /* HISI_PWRC_H */
diff --git a/plat/hisilicon/hikey/include/hisi_sip_svc.h b/plat/hisilicon/hikey/include/hisi_sip_svc.h
new file mode 100644
index 0000000..a1fad7a
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hisi_sip_svc.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HISI_SIP_SVC_H
+#define HISI_SIP_SVC_H
+
+/* SMC function IDs for SiP Service queries */
+
+#define HISI_SIP_SVC_CALL_COUNT 0x8200ff00
+#define HISI_SIP_SVC_UID 0x8200ff01
+/* 0x8200ff02 is reserved */
+#define HISI_SIP_SVC_VERSION 0x8200ff03
+
+/* HISI SiP Service Calls version numbers */
+#define HISI_SIP_SVC_VERSION_MAJOR 0x0
+#define HISI_SIP_SVC_VERSION_MINOR 0x1
+
+#endif /* HISI_SIP_SVC_H */
diff --git a/plat/hisilicon/hikey/include/hisi_sram_map.h b/plat/hisilicon/hikey/include/hisi_sram_map.h
new file mode 100644
index 0000000..f93e418
--- /dev/null
+++ b/plat/hisilicon/hikey/include/hisi_sram_map.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HISI_SRAM_MAP_H
+#define HISI_SRAM_MAP_H
+
+/*
+ * SRAM Memory Region Layout
+ *
+ * +-----------------------+
+ * | Low Power Mode | 7KB
+ * +-----------------------+
+ * | Secure OS | 64KB
+ * +-----------------------+
+ * | Software Flag | 1KB
+ * +-----------------------+
+ *
+ */
+
+#define SOC_SRAM_OFF_BASE_ADDR (0xFFF80000)
+
+/* PM Section: 7KB */
+#define SRAM_PM_ADDR (SOC_SRAM_OFF_BASE_ADDR)
+#define SRAM_PM_SIZE (0x00001C00)
+
+/* TEE OS Section: 64KB */
+#define SRAM_TEEOS_ADDR (SRAM_PM_ADDR + SRAM_PM_SIZE)
+#define SRAM_TEEOS_SIZE (0x00010000)
+
+/* General Use Section: 1KB */
+#define SRAM_GENERAL_ADDR (SRAM_TEEOS_ADDR + SRAM_TEEOS_SIZE)
+#define SRAM_GENERAL_SIZE (0x00000400)
+
+/*
+ * General Usage Section Layout:
+ *
+ * +-----------------------+
+ * | AP boot flag | 64B
+ * +-----------------------+
+ * | DICC flag | 32B
+ * +-----------------------+
+ * | Soft flag | 256B
+ * +-----------------------+
+ * | Thermal flag | 128B
+ * +-----------------------+
+ * | CSHELL | 4B
+ * +-----------------------+
+ * | Uart Switching | 4B
+ * +-----------------------+
+ * | ICC | 1024B
+ * +-----------------------+
+ * | Memory Management | 1024B
+ * +-----------------------+
+ * | IFC | 32B
+ * +-----------------------+
+ * | HIFI | 32B
+ * +-----------------------+
+ * | DDR capacity | 4B
+ * +-----------------------+
+ * | Reserved |
+ * +-----------------------+
+ *
+ */
+
+/* App Core Boot Flags */
+#define MEMORY_AXI_ACPU_START_ADDR (SRAM_GENERAL_ADDR)
+#define MEMORY_AXI_ACPU_START_SIZE (64)
+
+#define MEMORY_AXI_SRESET_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0000)
+#define MEMORY_AXI_SECOND_CPU_BOOT_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0004)
+#define MEMORY_AXI_READY_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0008)
+#define MEMORY_AXI_FASTBOOT_ENTRY_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x000C)
+#define MEMORY_AXI_PD_CHARGE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0010)
+#define MEMORY_AXI_DBG_ALARM_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0014)
+#define MEMORY_AXI_CHIP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0018)
+#define MEMORY_AXI_BOARD_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x001C)
+#define MEMORY_AXI_BOARD_ID_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0020)
+#define MEMORY_AXI_CHARGETYPE_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0024)
+#define MEMORY_AXI_COLD_START_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0028)
+#define MEMORY_AXI_ANDROID_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x002C)
+#define MEMORY_AXI_ACPU_WDTRST_REBOOT_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0030)
+#define MEMORY_AXI_ABNRST_BITMAP_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0034)
+#define MEMORY_AXI_32K_CLK_TYPE_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x0038)
+#define AXI_MODEM_PANIC_FLAG_ADDR (MEMORY_AXI_ACPU_START_ADDR + 0x003C)
+#define AXI_MODEM_PANIC_FLAG (0x68697369)
+#define MEMORY_AXI_ACPU_END_ADDR (AXI_MODEM_PANIC_FLAG_ADDR + 4)
+
+/* DICC Flags */
+#define MEMORY_AXI_DICC_ADDR (MEMORY_AXI_ACPU_START_ADDR + MEMORY_AXI_ACPU_START_SIZE)
+#define MEMORY_AXI_DICC_SIZE (32)
+
+#define MEMORY_AXI_SOFT_FLAG_ADDR (MEMORY_AXI_DICC_ADDR + MEMORY_AXI_DICC_SIZE)
+#define MEMORY_AXI_SOFT_FLAG_SIZE (256)
+
+/* Thermal Flags */
+#define MEMORY_AXI_TEMP_PROTECT_ADDR (MEMORY_AXI_SOFT_FLAG_ADDR + MEMORY_AXI_SOFT_FLAG_SIZE)
+#define MEMORY_AXI_TEMP_PROTECT_SIZE (128)
+
+/* CSHELL */
+#define MEMORY_AXI_USB_CSHELL_ADDR (MEMORY_AXI_TEMP_PROTECT_ADDR + MEMORY_AXI_TEMP_PROTECT_SIZE)
+#define MEMORY_AXI_USB_CSHELL_SIZE (4)
+
+/* Uart and A/C Shell Switch Flags */
+#define MEMORY_AXI_UART_INOUT_ADDR (MEMORY_AXI_USB_CSHELL_ADDR + MEMORY_AXI_USB_CSHELL_SIZE)
+#define MEMORY_AXI_UART_INOUT_SIZE (4)
+
+/* IFC Flags */
+#define MEMORY_AXI_IFC_ADDR (MEMORY_AXI_UART_INOUT_ADDR + MEMORY_AXI_UART_INOUT_SIZE)
+#define MEMORY_AXI_IFC_SIZE (32)
+
+/* HIFI Data */
+#define MEMORY_AXI_HIFI_ADDR (MEMORY_AXI_IFC_ADDR + MEMORY_AXI_IFC_SIZE)
+#define MEMORY_AXI_HIFI_SIZE (32)
+
+/* CONFIG Flags */
+#define MEMORY_AXI_CONFIG_ADDR (MEMORY_AXI_HIFI_ADDR + MEMORY_AXI_HIFI_SIZE)
+#define MEMORY_AXI_CONFIG_SIZE (32)
+
+/* DDR Capacity Flags */
+#define MEMORY_AXI_DDR_CAPACITY_ADDR (MEMORY_AXI_CONFIG_ADDR + MEMORY_AXI_CONFIG_SIZE)
+#define MEMORY_AXI_DDR_CAPACITY_SIZE (4)
+
+/* USB Shell Flags */
+#define MEMORY_AXI_USB_SHELL_FLAG_ADDR (MEMORY_AXI_DDR_CAPACITY_ADDR + MEMORY_AXI_DDR_CAPACITY_SIZE)
+#define MEMORY_AXI_USB_SHELL_FLAG_SIZE (4)
+
+/* MCU WDT Switch Flag */
+#define MEMORY_AXI_MCU_WDT_FLAG_ADDR (MEMORY_AXI_USB_SHELL_FLAG_ADDR + MEMORY_AXI_USB_SHELL_FLAG_SIZE)
+#define MEMORY_AXI_MCU_WDT_FLAG_SIZE (4)
+
+/* TLDSP Mailbox MNTN */
+#define SRAM_DSP_MNTN_INFO_ADDR (MEMORY_AXI_MCU_WDT_FLAG_ADDR + MEMORY_AXI_MCU_WDT_FLAG_SIZE)
+#define SRAM_DSP_MNTN_SIZE (32)
+
+/* TLDSP ARM Mailbox Protect Flag */
+#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR (SRAM_DSP_MNTN_INFO_ADDR + SRAM_DSP_MNTN_SIZE)
+#define SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE (4)
+
+/* RTT Sleep Flag */
+#define SRAM_RTT_SLEEP_FLAG_ADDR (SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_ADDR + SRAM_DSP_ARM_MAILBOX_PROTECT_FLAG_SIZE)
+#define SRAM_RTT_SLEEP_FLAG_SIZE (32)
+
+/* LDSP Awake Flag */
+#define MEMORY_AXI_LDSP_AWAKE_ADDR (SRAM_RTT_SLEEP_FLAG_ADDR + SRAM_RTT_SLEEP_FLAG_SIZE)
+#define MEMORY_AXI_LDSP_AWAKE_SIZE (4)
+
+#define NVUPDATE_SUCCESS 0x5555AAAA
+#define NVUPDATE_FAILURE 0xAAAA5555
+
+/*
+ * Low Power Mode Region
+ */
+#define PWRCTRL_ACPU_ASM_SPACE_ADDR (SRAM_PM_ADDR)
+#define PWRCTRL_ACPU_ASM_SPACE_SIZE (SRAM_PM_SIZE)
+
+#define PWRCTRL_ACPU_ASM_MEM_BASE (PWRCTRL_ACPU_ASM_SPACE_ADDR)
+#define PWRCTRL_ACPU_ASM_MEM_SIZE (PWRCTRL_ACPU_ASM_SPACE_SIZE)
+#define PWRCTRL_ACPU_ASM_CODE_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0x200)
+#define PWRCTRL_ACPU_ASM_DATA_BASE (PWRCTRL_ACPU_ASM_MEM_BASE + 0xE00)
+#define PWRCTRL_ACPU_ASM_DATA_SIZE (0xE00)
+
+#define PWRCTRL_ACPU_ASM_D_C0_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE)
+#define PWRCTRL_ACPU_ASM_D_C0_MMU_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0)
+#define PWRCTRL_ACPU_ASM_D_ARM_PARA_AD (PWRCTRL_ACPU_ASM_DATA_BASE + 0x20)
+
+#define PWRCTRL_ACPU_ASM_D_COMM_ADDR (PWRCTRL_ACPU_ASM_DATA_BASE + 0x700)
+
+#define PWRCTRL_ACPU_REBOOT (PWRCTRL_ACPU_ASM_D_COMM_ADDR)
+#define PWRCTRL_ACPU_REBOOT_SIZE (0x200)
+#define PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR (PWRCTRL_ACPU_REBOOT + PWRCTRL_ACPU_REBOOT_SIZE)
+#define PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE (4)
+#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR (PWRCTRL_ACPU_ASM_SLICE_BAK_ADDR + PWRCTRL_ACPU_ASM_SLICE_BAK_SIZE)
+#define PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE (4)
+#define EXCH_A_CORE_POWRCTRL_CONV_ADDR (PWRCTRL_ACPU_ASM_DEBUG_FLAG_ADDR + PWRCTRL_ACPU_ASM_DEBUG_FLAG_SIZE)
+#define EXCH_A_CORE_POWRCTRL_CONV_SIZE (4)
+
+/*
+ * Below region memory mapping is:
+ * 4 + 12 + 16 + 28 + 28 + 16 + 28 + 12 + 24 + 20 + 64 +
+ * 4 + 4 + 4 + 4 + 12 + 4 + 4 + 4 + 4 + 16 + 4 + 0x2BC +
+ * 24 + 20 + 12 + 16
+ */
+
+#define MEMORY_AXI_CPU_IDLE_ADDR (EXCH_A_CORE_POWRCTRL_CONV_ADDR + EXCH_A_CORE_POWRCTRL_CONV_SIZE)
+#define MEMORY_AXI_CPU_IDLE_SIZE (4)
+
+#define MEMORY_AXI_CUR_FREQ_ADDR (MEMORY_AXI_CPU_IDLE_ADDR + MEMORY_AXI_CPU_IDLE_SIZE)
+#define MEMORY_AXI_CUR_FREQ_SIZE (12)
+
+#define MEMORY_AXI_ACPU_FREQ_VOL_ADDR (MEMORY_AXI_CUR_FREQ_ADDR + MEMORY_AXI_CUR_FREQ_SIZE)
+#define MEMORY_AXI_ACPU_FREQ_VOL_SIZE (16 + 28 + 28)
+
+#define MEMORY_AXI_DDR_FREQ_VOL_ADDR (MEMORY_AXI_ACPU_FREQ_VOL_ADDR + MEMORY_AXI_ACPU_FREQ_VOL_SIZE)
+#define MEMORY_AXI_DDR_FREQ_VOL_SIZE (16 + 28)
+
+#define MEMORY_AXI_ACPU_FIQ_TEST_ADDR (MEMORY_AXI_DDR_FREQ_VOL_ADDR + MEMORY_AXI_DDR_FREQ_VOL_SIZE)
+#define MEMORY_AXI_ACPU_FIQ_TEST_SIZE (12)
+
+#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_TEST_ADDR + MEMORY_AXI_ACPU_FIQ_TEST_SIZE)
+#define MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE (24)
+
+#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR (MEMORY_AXI_ACPU_FIQ_CPU_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_CPU_INFO_SIZE)
+#define MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE (20)
+
+#define MEMORY_FREQDUMP_ADDR (MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_ADDR + MEMORY_AXI_ACPU_FIQ_DEBUG_INFO_SIZE)
+#define MEMORY_FREQDUMP_SIZE (64)
+
+#define MEMORY_AXI_CCPU_LOG_ADDR (MEMORY_FREQDUMP_ADDR + MEMORY_FREQDUMP_SIZE)
+#define MEMORY_AXI_CCPU_LOG_SIZE (4)
+
+#define MEMORY_AXI_MCU_LOG_ADDR (MEMORY_AXI_CCPU_LOG_ADDR + MEMORY_AXI_CCPU_LOG_SIZE)
+#define MEMORY_AXI_MCU_LOG_SIZE (4)
+
+#define MEMORY_AXI_SEC_CORE_BOOT_ADDR (MEMORY_AXI_MCU_LOG_ADDR + MEMORY_AXI_MCU_LOG_SIZE)
+#define MEMORY_AXI_SEC_CORE_BOOT_SIZE (4)
+
+#define MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR (MEMORY_AXI_SEC_CORE_BOOT_ADDR + MEMORY_AXI_SEC_CORE_BOOT_SIZE)
+#define MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE (0x4)
+
+#define POLICY_AREA_RESERVED (MEMORY_AXI_BBP_PS_VOTE_FLAG_ADDR + MEMORY_AXI_BBP_PS_VOTE_FLAG_SIZE)
+#define POLICY_AREA_RESERVED_SIZE (12)
+
+#define DDR_POLICY_VALID_MAGIC (POLICY_AREA_RESERVED + POLICY_AREA_RESERVED_SIZE)
+#define DDR_POLICY_VALID_MAGIC_SIZE (4)
+
+#define DDR_POLICY_MAX_NUM (DDR_POLICY_VALID_MAGIC + DDR_POLICY_VALID_MAGIC_SIZE)
+#define DDR_POLICY_MAX_NUM_SIZE (4)
+
+#define DDR_POLICY_SUPPORT_NUM (DDR_POLICY_MAX_NUM + DDR_POLICY_MAX_NUM_SIZE)
+#define DDR_POLICY_SUPPORT_NUM_SIZE (4)
+
+#define DDR_POLICY_CUR_POLICY (DDR_POLICY_SUPPORT_NUM + DDR_POLICY_SUPPORT_NUM_SIZE)
+#define DDR_POLICY_CUR_POLICY_SIZE (4)
+
+#define ACPU_POLICY_VALID_MAGIC (DDR_POLICY_CUR_POLICY + DDR_POLICY_CUR_POLICY_SIZE)
+#define ACPU_POLICY_VALID_MAGIC_SIZE (4)
+
+#define ACPU_POLICY_MAX_NUM (ACPU_POLICY_VALID_MAGIC + ACPU_POLICY_VALID_MAGIC_SIZE)
+#define ACPU_POLICY_MAX_NUM_SIZE (4)
+
+#define ACPU_POLICY_SUPPORT_NUM (ACPU_POLICY_MAX_NUM + ACPU_POLICY_MAX_NUM_SIZE)
+#define ACPU_POLICY_SUPPORT_NUM_SIZE (4)
+
+#define ACPU_POLICY_CUR_POLICY (ACPU_POLICY_SUPPORT_NUM + ACPU_POLICY_SUPPORT_NUM_SIZE)
+#define ACPU_POLICY_CUR_POLICY_SIZE (4)
+
+#define LPDDR_OPTION_ADDR (ACPU_POLICY_CUR_POLICY + ACPU_POLICY_CUR_POLICY_SIZE)
+#define LPDDR_OPTION_SIZE (4)
+
+#define MEMORY_AXI_DDR_DDL_ADDR (LPDDR_OPTION_ADDR + LPDDR_OPTION_SIZE)
+#define MEMORY_AXI_DDR_DDL_SIZE (0x2BC)
+
+#define DDR_TEST_DFS_ADDR (MEMORY_AXI_DDR_DDL_ADDR + MEMORY_AXI_DDR_DDL_SIZE)
+#define DDR_TEST_DFS_ADDR_SIZE (4)
+
+#define DDR_TEST_DFS_TIMES_ADDR (DDR_TEST_DFS_ADDR + DDR_TEST_DFS_ADDR_SIZE)
+#define DDR_TEST_DFS_TIMES_ADDR_SIZE (4)
+
+#define DDR_TEST_QOS_ADDR (DDR_TEST_DFS_TIMES_ADDR + DDR_TEST_DFS_TIMES_ADDR_SIZE)
+#define DDR_TEST_QOS_ADDR_SIZE (4)
+
+#define DDR_TEST_FUN_ADDR (DDR_TEST_QOS_ADDR + DDR_TEST_QOS_ADDR_SIZE)
+#define DDR_TEST_FUN_ADDR_SIZE (4)
+
+#define BOARD_TYPE_ADDR (DDR_TEST_FUN_ADDR + DDR_TEST_FUN_ADDR_SIZE)
+#define BOARD_ADDR_SIZE (4)
+#define DDR_DFS_FREQ_ADDR (BOARD_TYPE_ADDR + BOARD_ADDR_SIZE)
+#define DDR_DFS_FREQ_SIZE (4)
+
+#define DDR_PASR_ADDR (DDR_DFS_FREQ_ADDR + DDR_DFS_FREQ_SIZE)
+#define DDR_PASR_SIZE (20)
+
+#define ACPU_DFS_FREQ_ADDR (DDR_PASR_ADDR + DDR_PASR_SIZE)
+#define ACPU_DFS_FREQ_ADDR_SIZE (12)
+
+#define ACPU_CHIP_MAX_FREQ (ACPU_DFS_FREQ_ADDR + ACPU_DFS_FREQ_ADDR_SIZE)
+#define ACPU_CHIP_MAX_FREQ_SIZE (4)
+
+#define MEMORY_MEDPLL_STATE_ADDR (ACPU_CHIP_MAX_FREQ + ACPU_CHIP_MAX_FREQ_SIZE)
+#define MEMORY_MEDPLL_STATE_SIZE (8)
+
+#define MEMORY_CCPU_LOAD_FLAG_ADDR (MEMORY_MEDPLL_STATE_ADDR + MEMORY_MEDPLL_STATE_SIZE)
+#define MEMORY_CCPU_LOAD_FLAG_SIZE (4)
+
+
+#define ACPU_CORE_BITS_ADDR (MEMORY_CCPU_LOAD_FLAG_ADDR + MEMORY_CCPU_LOAD_FLAG_SIZE)
+#define ACPU_CORE_BITS_SIZE (4)
+
+#define ACPU_CLUSTER_IDLE_ADDR (ACPU_CORE_BITS_ADDR + ACPU_CORE_BITS_SIZE)
+#define ACPU_CLUSTER_IDLE_SIZE (4)
+
+#define ACPU_A53_FLAGS_ADDR (ACPU_CLUSTER_IDLE_ADDR + ACPU_CLUSTER_IDLE_SIZE)
+#define ACPU_A53_FLAGS_SIZE (4)
+
+#define ACPU_POWER_STATE_QOS_ADDR (ACPU_A53_FLAGS_ADDR+ACPU_A53_FLAGS_SIZE)
+#define ACPU_POWER_STATE_QOS_SIZE (4)
+
+#define ACPU_UNLOCK_CORE_FLAGS_ADDR (ACPU_POWER_STATE_QOS_ADDR+ACPU_POWER_STATE_QOS_SIZE)
+#define ACPU_UNLOCK_CORE_FLAGS_SIZE (8)
+
+#define ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR (ACPU_UNLOCK_CORE_FLAGS_ADDR + ACPU_UNLOCK_CORE_FLAGS_SIZE)
+#define ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE (4)
+
+#define ACPU_CORE_POWERDOWN_FLAGS_ADDR (ACPU_SUBSYS_POWERDOWN_FLAGS_ADDR + ACPU_SUBSYS_POWERDOWN_FLAGS_SIZE)
+#define ACPU_CORE_POWERDOWN_FLAGS_SIZE (4)
+
+#define ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR (ACPU_CORE_POWERDOWN_FLAGS_ADDR + ACPU_CORE_POWERDOWN_FLAGS_SIZE)
+#define ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE (4)
+
+#define ACPU_ARM64_FLAGA (ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR + ACPU_CLUSTER_POWERDOWN_FLAGS_SIZE)
+#define ACPU_ARM64_FLAGA_SIZE (4)
+
+#define ACPU_ARM64_FLAGB (ACPU_ARM64_FLAGA + ACPU_ARM64_FLAGA_SIZE)
+#define ACPU_ARM64_FLAGB_SIZE (4)
+
+#define MCU_EXCEPTION_FLAGS_ADDR (ACPU_ARM64_FLAGB + ACPU_ARM64_FLAGB_SIZE)
+#define MCU_EXCEPTION_FLAGS_SIZE (4)
+
+#define ACPU_MASTER_CORE_STATE_ADDR (MCU_EXCEPTION_FLAGS_ADDR + MCU_EXCEPTION_FLAGS_SIZE)
+#define ACPU_MASTER_CORE_STATE_SIZE (4)
+
+#define PWRCTRL_AXI_RESERVED_ADDR (ACPU_MASTER_CORE_STATE_ADDR + ACPU_MASTER_CORE_STATE_SIZE)
+
+#endif /* HISI_SRAM_MAP_H */
diff --git a/plat/hisilicon/hikey/include/plat_macros.S b/plat/hisilicon/hikey/include/plat_macros.S
new file mode 100644
index 0000000..9cd276a
--- /dev/null
+++ b/plat/hisilicon/hikey/include/plat_macros.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <hi6220.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+/* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+ mov_imm x16, PLAT_ARM_GICD_BASE
+ mov_imm x17, PLAT_ARM_GICC_BASE
+
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to cosole */
+ bl str_in_crash_buf_print
+
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+2:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq 1f
+ bl asm_print_hex
+ adr x4, spacer
+ bl asm_print_str
+ ldr x4, [x7], #8
+ bl asm_print_hex
+ adr x4, newline
+ bl asm_print_str
+ b 2b
+1:
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (CCI400_BASE + SLAVE_IFACE_OFFSET( \
+ CCI400_SL_IFACE3_CLUSTER_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (CCI400_BASE + SLAVE_IFACE_OFFSET( \
+ CCI400_SL_IFACE4_CLUSTER_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/hisilicon/hikey/include/platform_def.h b/plat/hisilicon/hikey/include/platform_def.h
new file mode 100644
index 0000000..04ea71f
--- /dev/null
+++ b/plat/hisilicon/hikey/include/platform_def.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include <hikey_def.h>
+#include <hikey_layout.h> /* BL memory region sizes, etc */
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define HIKEY_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+/*
+ * Generic platform constants
+ */
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE 0x1000
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_CACHE_LINE_SIZE 64
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CORE_COUNT_PER_CLUSTER U(4)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
+ PLATFORM_CORE_COUNT_PER_CLUSTER)
+#define PLAT_MAX_PWR_LVL (MPIDR_AFFLVL2)
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ PLATFORM_CLUSTER_COUNT + U(1))
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+/* eMMC RPMB and eMMC User Data */
+#define MAX_IO_BLOCK_DEVICES U(2)
+
+/* GIC related constants (no GICR in GIC-400) */
+#define PLAT_ARM_GICD_BASE 0xF6801000
+#define PLAT_ARM_GICC_BASE 0xF6802000
+#define PLAT_ARM_GICH_BASE 0xF6804000
+#define PLAT_ARM_GICV_BASE 0xF6806000
+
+/*
+ * Platform specific page table and MMU setup constants
+ */
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+
+#if defined(IMAGE_BL1) || defined(IMAGE_BL32)
+#define MAX_XLAT_TABLES 3
+#endif
+
+#ifdef IMAGE_BL31
+#define MAX_XLAT_TABLES 4
+#endif
+
+#ifdef IMAGE_BL2
+#define MAX_XLAT_TABLES 4
+#endif
+
+#define MAX_MMAP_REGIONS 16
+
+/*
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ */
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk
new file mode 100644
index 0000000..2bfc582
--- /dev/null
+++ b/plat/hisilicon/hikey/platform.mk
@@ -0,0 +1,172 @@
+#
+# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Non-TF Boot ROM
+BL2_AT_EL3 := 1
+
+# On Hikey, the TSP can execute from TZC secure area in DRAM (default)
+# or SRAM.
+HIKEY_TSP_RAM_LOCATION ?= dram
+ifeq (${HIKEY_TSP_RAM_LOCATION}, dram)
+ HIKEY_TSP_RAM_LOCATION_ID = HIKEY_DRAM_ID
+else ifeq (${HIKEY_TSP_RAM_LOCATION}, sram)
+ HIKEY_TSP_RAM_LOCATION_ID = HIKEY_SRAM_ID
+else
+ $(error "Currently unsupported HIKEY_TSP_RAM_LOCATION value")
+endif
+
+CONSOLE_BASE := PL011_UART3_BASE
+CRASH_CONSOLE_BASE := PL011_UART3_BASE
+PLAT_PARTITION_MAX_ENTRIES := 12
+PLAT_PL061_MAX_GPIOS := 160
+COLD_BOOT_SINGLE_CPU := 1
+PROGRAMMABLE_RESET_ADDRESS := 1
+ENABLE_SVE_FOR_NS := 0
+
+# Process flags
+$(eval $(call add_define,HIKEY_TSP_RAM_LOCATION_ID))
+$(eval $(call add_define,CONSOLE_BASE))
+$(eval $(call add_define,CRASH_CONSOLE_BASE))
+$(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
+$(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES))
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
+USE_COHERENT_MEM := 1
+
+PLAT_INCLUDES := -Iplat/hisilicon/hikey/include
+
+PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ plat/hisilicon/hikey/aarch64/hikey_common.c
+
+BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/arm/sp804/sp804_delay_timer.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_storage.c \
+ drivers/mmc/mmc.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/hisilicon/hikey/aarch64/hikey_helpers.S \
+ plat/hisilicon/hikey/hikey_bl1_setup.c \
+ plat/hisilicon/hikey/hikey_bl_common.c \
+ plat/hisilicon/hikey/hikey_io_storage.c
+
+BL2_SOURCES += common/desc_image_load.c \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/arm/sp804/sp804_delay_timer.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_storage.c \
+ drivers/mmc/mmc.c \
+ drivers/partition/gpt.c \
+ drivers/partition/partition.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/hisilicon/hikey/aarch64/hikey_helpers.S \
+ plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c \
+ plat/hisilicon/hikey/hikey_bl2_setup.c \
+ plat/hisilicon/hikey/hikey_bl_common.c \
+ plat/hisilicon/hikey/hikey_security.c \
+ plat/hisilicon/hikey/hikey_ddr.c \
+ plat/hisilicon/hikey/hikey_image_load.c \
+ plat/hisilicon/hikey/hikey_io_storage.c \
+ plat/hisilicon/hikey/hisi_dvfs.c \
+ plat/hisilicon/hikey/hisi_mcu.c
+
+ifeq (${SPD},opteed)
+BL2_SOURCES += lib/optee/optee_utils.c
+endif
+
+include lib/zlib/zlib.mk
+PLAT_INCLUDES += -Ilib/zlib
+BL2_SOURCES += $(ZLIB_SOURCES)
+
+HIKEY_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c
+
+BL31_SOURCES += drivers/arm/cci/cci.c \
+ drivers/arm/sp804/sp804_delay_timer.c \
+ drivers/delay_timer/delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/hisilicon/hikey/aarch64/hikey_helpers.S \
+ plat/hisilicon/hikey/hikey_bl31_setup.c \
+ plat/hisilicon/hikey/hikey_pm.c \
+ plat/hisilicon/hikey/hikey_topology.c \
+ plat/hisilicon/hikey/hisi_ipc.c \
+ plat/hisilicon/hikey/hisi_pwrc.c \
+ plat/hisilicon/hikey/hisi_pwrc_sram.S \
+ ${HIKEY_GIC_SOURCES}
+ifeq (${ENABLE_PMF}, 1)
+BL31_SOURCES += plat/hisilicon/hikey/hisi_sip_svc.c \
+ lib/pmf/pmf_smc.c
+endif
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c
+
+BL1_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/hisilicon/hikey/hikey_tbbr.c \
+ plat/hisilicon/hikey/hikey_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl1.c
+
+BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/hisilicon/hikey/hikey_tbbr.c \
+ plat/hisilicon/hikey/hikey_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl1/hikey_rotpk.o: $(ROTPK_HASH)
+$(BUILD_PLAT)/bl2/hikey_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
+
+# Enable workarounds for selected Cortex-A53 errata.
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+WORKAROUND_CVE_2017_5715 := 0
+
+FIP_ALIGN := 512
diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_common.c b/plat/hisilicon/hikey960/aarch64/hikey960_common.c
new file mode 100644
index 0000000..c70286f
--- /dev/null
+++ b/plat/hisilicon/hikey960/aarch64/hikey960_common.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include "../hikey960_def.h"
+#include "../hikey960_private.h"
+
+#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \
+ DDR_SIZE - DDR_SEC_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \
+ DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_BL1_RW MAP_REGION_FLAT(BL1_RW_BASE, \
+ BL1_RW_LIMIT - BL1_RW_BASE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_UFS_DATA MAP_REGION_FLAT(HIKEY960_UFS_DATA_BASE, \
+ HIKEY960_UFS_DATA_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_UFS_DESC MAP_REGION_FLAT(HIKEY960_UFS_DESC_BASE, \
+ HIKEY960_UFS_DESC_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \
+ TSP_SEC_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * hikey960_init_mmu_elx() will give the available subset of that,
+ */
+#ifdef IMAGE_BL1
+static const mmap_region_t hikey960_mmap[] = {
+ MAP_UFS_DATA,
+ MAP_BL1_RW,
+ MAP_UFS_DESC,
+ MAP_DEVICE,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL2
+static const mmap_region_t hikey960_mmap[] = {
+ MAP_DDR,
+ MAP_DEVICE,
+ MAP_TSP_MEM,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL31
+static const mmap_region_t hikey960_mmap[] = {
+ MAP_DEVICE,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL32
+static const mmap_region_t hikey960_mmap[] = {
+ MAP_DEVICE,
+ MAP_DDR,
+ {0}
+};
+#endif
+
+/*
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ */
+#define HIKEY960_CONFIGURE_MMU_EL(_el) \
+ void hikey960_init_mmu_el##_el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(hikey960_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el##_el(0); \
+ }
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+HIKEY960_CONFIGURE_MMU_EL(1)
+HIKEY960_CONFIGURE_MMU_EL(3)
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+ return NS_BL1U_BASE;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return 1920000;
+}
diff --git a/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S
new file mode 100644
index 0000000..5381369
--- /dev/null
+++ b/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cortex_a53.h>
+#include <cortex_a73.h>
+#include "../hikey960_def.h"
+
+ .globl plat_my_core_pos
+ .globl platform_mem_init
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_report_exception
+ .globl plat_reset_handler
+ .globl clr_ex
+ .globl nop
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * void platform_mem_init(void);
+ *
+ * We don't need to carry out any memory initialization
+ * on HIKEY. The Secure RAM is accessible straight away.
+ * -----------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, CRASH_CONSOLE_BASE
+ mov_imm x1, PL011_UART_CLK_IN_HZ
+ mov_imm x2, PL011_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, CRASH_CONSOLE_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, CRASH_CONSOLE_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * void plat_report_exception(unsigned int type)
+ * Function to report an unhandled exception
+ * with platform-specific means.
+ * On HIKEY platform, it updates the LEDs
+ * to indicate where we are
+ * ---------------------------------------------
+ */
+func plat_report_exception
+ mov x8, x30
+
+ /* Turn on LED according to x0 (0 -- f) */
+ ldr x2, =0xf7020000
+ and x1, x0, #1
+ str w1, [x2, #4]
+ and x1, x0, #2
+ str w1, [x2, #8]
+ and x1, x0, #4
+ str w1, [x2, #16]
+ and x1, x0, #8
+ str w1, [x2, #32]
+
+ mrs x2, currentel
+ and x2, x2, #0x0c
+ /* Check EL1 */
+ cmp x2, #0x04
+ beq plat_report_el1
+
+ adr x4, plat_err_str
+ bl asm_print_str
+
+ adr x4, esr_el3_str
+ bl asm_print_str
+
+ mrs x4, esr_el3
+ bl asm_print_hex
+
+ adr x4, elr_el3_str
+ bl asm_print_str
+
+ mrs x4, elr_el3
+ bl asm_print_hex
+ b plat_report_end
+
+plat_report_el1:
+ adr x4, plat_err_str
+ bl asm_print_str
+
+ adr x4, esr_el1_str
+ bl asm_print_str
+
+ mrs x4, esr_el1
+ bl asm_print_hex
+
+ adr x4, elr_el1_str
+ bl asm_print_str
+
+ mrs x4, elr_el1
+ bl asm_print_hex
+plat_report_end:
+ mov x30, x8
+ ret
+endfunc plat_report_exception
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler(void);
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ ret
+endfunc plat_reset_handler
+
+ /* -----------------------------------------------------
+ * void clrex(void);
+ * -----------------------------------------------------
+ */
+func clr_ex
+ clrex
+ ret
+endfunc clr_ex
+
+ /* -----------------------------------------------------
+ * void nop(void);
+ * -----------------------------------------------------
+ */
+func nop
+ nop
+ ret
+endfunc nop
+
+.section .rodata.rev_err_str, "aS"
+plat_err_str:
+ .asciz "\nPlatform exception reporting:"
+esr_el3_str:
+ .asciz "\nESR_EL3: "
+elr_el3_str:
+ .asciz "\nELR_EL3: "
+esr_el1_str:
+ .asciz "\nESR_EL1: "
+elr_el1_str:
+ .asciz "\nELR_EL1: "
diff --git a/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c
new file mode 100644
index 0000000..a6a4949
--- /dev/null
+++ b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <hi3660.h>
+#include <hisi_ipc.h>
+#include "../../hikey960_private.h"
+
+#define IPC_MBX_SOURCE_REG(m) (IPC_BASE + ((m) << 6))
+#define IPC_MBX_DSET_REG(m) (IPC_BASE + ((m) << 6) + 0x04)
+#define IPC_MBX_DCLEAR_REG(m) (IPC_BASE + ((m) << 6) + 0x08)
+#define IPC_MBX_DSTATUS_REG(m) (IPC_BASE + ((m) << 6) + 0x0C)
+#define IPC_MBX_MODE_REG(m) (IPC_BASE + ((m) << 6) + 0x10)
+#define IPC_MBX_IMASK_REG(m) (IPC_BASE + ((m) << 6) + 0x14)
+#define IPC_MBX_ICLR_REG(m) (IPC_BASE + ((m) << 6) + 0x18)
+#define IPC_MBX_SEND_REG(m) (IPC_BASE + ((m) << 6) + 0x1C)
+#define IPC_MBX_DATA_REG(m, d) (IPC_BASE + ((m) << 6) + 0x20 + \
+ ((d) * 4))
+#define IPC_CPU_IMST_REG(m) (IPC_BASE + ((m) << 3))
+#define IPC_LOCK_REG (IPC_BASE + 0xA00)
+#define IPC_ACK_BIT_SHIFT (1 << 7)
+#define IPC_UNLOCK_VALUE (0x1ACCE551)
+
+/*********************************************************
+ *bit[31:24]:0~AP
+ *bit[23:16]:0x1~A15, 0x2~A7
+ *bit[15:8]:0~ON, 1~OFF
+ *bit[7:0]:0x3 cpu power mode
+ *********************************************************/
+#define IPC_CMD_TYPE(src_obj, cluster_obj, is_off, mode) \
+ ((src_obj << 24) | (((cluster_obj) + 1) << 16) | (is_off << 8) | (mode))
+
+/*********************************************************
+ *bit[15:8]:0~no idle, 1~idle
+ *bit[7:0]:cpux
+ *********************************************************/
+
+#define IPC_CMD_PARA(is_idle, cpu) \
+ ((is_idle << 8) | (cpu))
+
+#define IPC_STATE_IDLE 0x10
+
+enum src_id {
+ SRC_IDLE = 0,
+ SRC_A15 = 1 << 0,
+ SRC_A7 = 1 << 1,
+ SRC_IOM3 = 1 << 2,
+ SRC_LPM3 = 1 << 3
+};
+
+/*lpm3's mailboxs are 13~17*/
+enum lpm3_mbox_id {
+ LPM3_MBX0 = 13,
+ LPM3_MBX1,
+ LPM3_MBX2,
+ LPM3_MBX3,
+ LPM3_MBX4,
+};
+
+static void cpu_relax(void)
+{
+ volatile int i;
+
+ for (i = 0; i < 10; i++)
+ nop();
+}
+
+static inline void
+hisi_ipc_clear_ack(enum src_id source, enum lpm3_mbox_id mbox)
+{
+ unsigned int int_status = 0;
+
+ do {
+ int_status = mmio_read_32(IPC_MBX_MODE_REG(mbox));
+ int_status &= 0xF0;
+ cpu_relax();
+ } while (int_status != IPC_ACK_BIT_SHIFT);
+
+ mmio_write_32(IPC_MBX_ICLR_REG(mbox), source);
+}
+
+static void
+hisi_ipc_send_cmd_with_ack(enum src_id source, enum lpm3_mbox_id mbox,
+ unsigned int cmdtype, unsigned int cmdpara)
+{
+ unsigned int regval;
+ unsigned int mask;
+ unsigned int state;
+
+ mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE);
+ /* wait for idle and occupy */
+ do {
+ state = mmio_read_32(IPC_MBX_MODE_REG(mbox));
+ if (state == IPC_STATE_IDLE) {
+ mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source);
+ regval = mmio_read_32(IPC_MBX_SOURCE_REG(mbox));
+ if (regval == source)
+ break;
+ }
+ cpu_relax();
+
+ } while (1);
+
+ /* auto answer */
+ mmio_write_32(IPC_MBX_MODE_REG(mbox), 0x1);
+
+ mask = (~((int)source | SRC_LPM3) & 0x3F);
+ /* mask the other cpus */
+ mmio_write_32(IPC_MBX_IMASK_REG(mbox), mask);
+ /* set data */
+ mmio_write_32(IPC_MBX_DATA_REG(mbox, 0), cmdtype);
+ mmio_write_32(IPC_MBX_DATA_REG(mbox, 1), cmdpara);
+ /* send cmd */
+ mmio_write_32(IPC_MBX_SEND_REG(mbox), source);
+ /* wait ack and clear */
+ hisi_ipc_clear_ack(source, mbox);
+
+ /* release mailbox */
+ mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source);
+}
+
+void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster,
+ enum pm_mode mode)
+{
+ unsigned int cmdtype = 0;
+ unsigned int cmdpara = 0;
+ enum src_id source = SRC_IDLE;
+ enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
+
+ cmdtype = IPC_CMD_TYPE(0, cluster, mode, 0x3);
+ cmdpara = IPC_CMD_PARA(0, core);
+ source = cluster ? SRC_A7 : SRC_A15;
+ hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
+}
+
+void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster,
+ unsigned int affinity_level)
+{
+ unsigned int cmdtype = 0;
+ unsigned int cmdpara = 0;
+ enum src_id source = SRC_IDLE;
+ enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
+
+ if (affinity_level == 0x3)
+ cmdtype = IPC_CMD_TYPE(0, -1, 0x1, 0x3 + affinity_level);
+ else
+ cmdtype = IPC_CMD_TYPE(0, cluster, 0x1, 0x3 + affinity_level);
+
+ cmdpara = IPC_CMD_PARA(1, core);
+ source = cluster ? SRC_A7 : SRC_A15;
+ hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
+}
+
+void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster)
+{
+ unsigned int cmdtype = 0;
+ unsigned int cmdpara = 0;
+ enum src_id source = SRC_IDLE;
+ enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
+
+ cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x1, 0x0);
+ cmdpara = IPC_CMD_PARA(0, 0);
+ source = cluster ? SRC_A7 : SRC_A15;
+ hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
+}
+
+void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster,
+ unsigned int cmd_id)
+{
+ unsigned int cmdtype = 0;
+ unsigned int cmdpara = 0;
+ enum src_id source = SRC_IDLE;
+ enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core);
+
+ cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x0, 0x0);
+ cmdpara = cmd_id;
+ source = cluster ? SRC_A7 : SRC_A15;
+ hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara);
+}
+
+int hisi_ipc_init(void)
+{
+ int ret = 0;
+ enum lpm3_mbox_id i = LPM3_MBX0;
+
+ mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE);
+ for (i = LPM3_MBX0; i <= LPM3_MBX4; i++) {
+ mmio_write_32(IPC_MBX_MODE_REG(i), 1);
+ mmio_write_32(IPC_MBX_IMASK_REG(i),
+ ((int)SRC_IOM3 | (int)SRC_A15 | (int)SRC_A7));
+ mmio_write_32(IPC_MBX_ICLR_REG(i), SRC_A7);
+ }
+
+ return ret;
+}
diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c
new file mode 100644
index 0000000..91d8033
--- /dev/null
+++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <../hikey960_def.h>
+#include <hisi_ipc.h>
+#include "hisi_pwrc.h"
+
+
+/* resource lock api */
+#define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE))
+#define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE))
+#define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE))
+
+#define LOCK_BIT (0x1 << 28)
+#define LOCK_ID_MASK (0x7u << 29)
+#define CPUIDLE_LOCK_ID(core) (0x6 - (core))
+#define LOCK_UNLOCK_OFFSET 0x4
+#define LOCK_STAT_OFFSET 0x8
+
+#define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16)
+#define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20)
+
+/* cpu hotplug flag api */
+#define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR)
+#define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE))
+#define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE))
+#define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE))
+
+#define CPUIDLE_FLAG_REG(cluster) \
+ ((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \
+ REG_SCBAKDATA9_OFFSET)
+#define CLUSTER_IDLE_BIT BIT(8)
+#define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F)
+
+#define AP_SUSPEND_FLAG (1 << 16)
+
+#define CLUSTER_PWDN_IDLE (0<<28)
+#define CLUSTER_PWDN_HOTPLUG (1<<28)
+#define CLUSTER_PWDN_SR (2<<28)
+
+#define CLUSTER0_PDC_OFFSET 0x260
+#define CLUSTER1_PDC_OFFSET 0x300
+
+#define PDC_EN_OFFSET 0x0
+#define PDC_COREPWRINTEN_OFFSET 0x4
+#define PDC_COREPWRINTSTAT_OFFSET 0x8
+#define PDC_COREGICMASK_OFFSET 0xc
+#define PDC_COREPOWERUP_OFFSET 0x10
+#define PDC_COREPOWERDN_OFFSET 0x14
+#define PDC_COREPOWERSTAT_OFFSET 0x18
+
+#define PDC_COREPWRSTAT_MASK (0XFFFF)
+
+enum pdc_gic_mask {
+ PDC_MASK_GIC_WAKE_IRQ,
+ PDC_UNMASK_GIC_WAKE_IRQ
+};
+
+enum pdc_finish_int_mask {
+ PDC_DISABLE_FINISH_INT,
+ PDC_ENABLE_FINISH_INT
+};
+
+static void hisi_resource_lock(unsigned int lockid, unsigned int offset)
+{
+ unsigned int lock_id = (lockid << 29);
+ unsigned int lock_val = lock_id | LOCK_BIT;
+ unsigned int lock_state;
+
+ do {
+ mmio_write_32(offset, lock_val);
+ lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset);
+ } while ((lock_state & LOCK_ID_MASK) != lock_id);
+}
+
+static void hisi_resource_unlock(unsigned int lockid, unsigned int offset)
+{
+ unsigned int lock_val = (lockid << 29) | LOCK_BIT;
+
+ mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val);
+}
+
+
+static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core)
+{
+ unsigned int lock_id;
+
+ lock_id = (cluster << 2) + core;
+
+ hisi_resource_lock(lock_id, RES2_LOCK_BASE);
+}
+
+static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core)
+{
+ unsigned int lock_id;
+
+ lock_id = (cluster << 2) + core;
+
+ hisi_resource_unlock(lock_id, RES2_LOCK_BASE);
+}
+
+/* get the resource lock */
+void hisi_cpuidle_lock(unsigned int cluster, unsigned int core)
+{
+ unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE);
+
+ hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset);
+}
+
+/* release the resource lock */
+void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core)
+{
+ unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE);
+
+ hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset);
+}
+
+unsigned int hisi_get_cpuidle_flag(unsigned int cluster)
+{
+ unsigned int val;
+
+ val = mmio_read_32(CPUIDLE_FLAG_REG(cluster));
+ val &= 0xF;
+
+ return val;
+}
+
+void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core)
+{
+ mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core));
+}
+
+void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core)
+{
+ mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core));
+
+}
+
+int hisi_test_ap_suspend_flag(void)
+{
+ unsigned int val1;
+ unsigned int val2;
+
+ val1 = mmio_read_32(CPUIDLE_FLAG_REG(0));
+ val1 &= AP_SUSPEND_FLAG;
+
+ val2 = mmio_read_32(CPUIDLE_FLAG_REG(1));
+ val2 &= AP_SUSPEND_FLAG;
+
+ val1 |= val2;
+ return (val1 != 0);
+}
+
+void hisi_set_cluster_pwdn_flag(unsigned int cluster,
+ unsigned int core, unsigned int value)
+{
+ unsigned int val;
+
+ hisi_cpuhotplug_lock(cluster, core);
+
+ val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
+ val &= ~(0x3U << ((2 * cluster) + 28));
+ val |= (value << (2 * cluster));
+ mmio_write_32(REG_SCBAKDATA3_OFFSET, val);
+
+ hisi_cpuhotplug_unlock(cluster, core);
+}
+
+unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core)
+{
+ unsigned int val;
+
+ hisi_cpuhotplug_lock(cluster, core);
+ val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
+ val = val >> (16 + (cluster << 2));
+ val &= 0xF;
+ hisi_cpuhotplug_unlock(cluster, core);
+
+ return val;
+}
+
+unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core)
+{
+ unsigned int val;
+
+ hisi_cpuhotplug_lock(cluster, core);
+ val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
+ val = val >> (16 + (cluster << 2));
+ val &= 0xF;
+ hisi_cpuhotplug_unlock(cluster, core);
+
+ if (val)
+ return 0;
+ else
+ return 1;
+}
+
+void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core)
+{
+ unsigned int flag = BIT((cluster<<2) + core + 16);
+
+ hisi_cpuhotplug_lock(cluster, core);
+
+ mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag);
+
+ hisi_cpuhotplug_unlock(cluster, core);
+}
+
+void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core)
+{
+ unsigned int flag = BIT((cluster<<2) + core + 16);
+
+ hisi_cpuhotplug_lock(cluster, core);
+
+ mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag);
+
+ hisi_cpuhotplug_unlock(cluster, core);
+}
+
+int cluster_is_powered_on(unsigned int cluster)
+{
+ unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET);
+ int ret;
+
+ if (cluster == 0)
+ ret = val & CLUSTER0_CPUS_ONLINE_MASK;
+ else
+ ret = val & CLUSTER1_CPUS_ONLINE_MASK;
+
+ return !!ret;
+}
+
+static void *hisi_get_pdc_addr(unsigned int cluster)
+{
+ void *pdc_base_addr;
+ uintptr_t addr;
+
+ if (cluster == 0)
+ addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE);
+ else
+ addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE);
+ pdc_base_addr = (void *)addr;
+
+ return pdc_base_addr;
+}
+
+static unsigned int hisi_get_pdc_stat(unsigned int cluster)
+{
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+ unsigned int val;
+
+ val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET);
+
+ return val;
+}
+
+static int check_hotplug(unsigned int cluster, unsigned int boot_flag)
+{
+ unsigned int mask = 0xF;
+
+ if (hisi_test_ap_suspend_flag() ||
+ ((boot_flag & mask) == mask))
+ return 0;
+
+ return 1;
+}
+
+int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core)
+{
+ unsigned int mask = 0xf << (core * 4);
+ unsigned int pdc_stat = hisi_get_pdc_stat(cluster);
+ unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core);
+ unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster);
+
+ mask = (PDC_COREPWRSTAT_MASK & (~mask));
+ pdc_stat &= mask;
+
+ if ((boot_flag ^ cpuidle_flag) || pdc_stat ||
+ check_hotplug(cluster, boot_flag))
+ return 0;
+ else
+ return 1;
+}
+
+void hisi_disable_pdc(unsigned int cluster)
+{
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+
+ mmio_write_32((uintptr_t)pdc_base_addr, 0x0);
+}
+
+void hisi_enable_pdc(unsigned int cluster)
+{
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+
+ mmio_write_32((uintptr_t)pdc_base_addr, 0x1);
+}
+
+void hisi_pdc_set_intmask(void *pdc_base_addr,
+ unsigned int core,
+ enum pdc_finish_int_mask intmask)
+{
+ unsigned int val;
+
+ val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET);
+ if (intmask == PDC_ENABLE_FINISH_INT)
+ val |= BIT(core);
+ else
+ val &= ~BIT(core);
+
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val);
+}
+
+static inline void hisi_pdc_set_gicmask(void *pdc_base_addr,
+ unsigned int core,
+ enum pdc_gic_mask gicmask)
+{
+ unsigned int val;
+
+ val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET);
+ if (gicmask == PDC_MASK_GIC_WAKE_IRQ)
+ val |= BIT(core);
+ else
+ val &= ~BIT(core);
+
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val);
+}
+
+void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster)
+{
+ int i;
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+
+ for (i = 0; i < 4; i++)
+ hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ);
+}
+
+static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core,
+ enum pdc_gic_mask gicmask,
+ enum pdc_finish_int_mask intmask)
+{
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET,
+ BIT(core));
+}
+
+static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core,
+ enum pdc_gic_mask gicmask,
+ enum pdc_finish_int_mask intmask)
+{
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
+ BIT(core));
+}
+
+void hisi_powerup_core(unsigned int cluster, unsigned int core)
+{
+ hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ,
+ PDC_DISABLE_FINISH_INT);
+}
+
+void hisi_powerdn_core(unsigned int cluster, unsigned int core)
+{
+ hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ,
+ PDC_DISABLE_FINISH_INT);
+}
+
+void hisi_powerup_cluster(unsigned int cluster, unsigned int core)
+{
+ hisi_ipc_pm_on_off(core, cluster, PM_ON);
+}
+
+void hisi_powerdn_cluster(unsigned int cluster, unsigned int core)
+{
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+
+ hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG);
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET,
+ (0x10001 << core));
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
+ BIT(core));
+}
+
+void hisi_enter_core_idle(unsigned int cluster, unsigned int core)
+{
+ hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ,
+ PDC_DISABLE_FINISH_INT);
+}
+
+void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core)
+{
+ void *pdc_base_addr = hisi_get_pdc_addr(cluster);
+
+ hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE);
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET,
+ (0x10001 << core));
+ mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET,
+ BIT(core));
+}
+
+void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core)
+{
+ hisi_ipc_pm_suspend(core, cluster, 0x3);
+}
diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h
new file mode 100644
index 0000000..e0cb381
--- /dev/null
+++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HISI_PWRC_H
+#define HISI_PWRC_H
+
+#include <hi3660.h>
+#include <hi3660_crg.h>
+
+#define PCTRL_BASE (PCTRL_REG_BASE)
+#define CRG_BASE (CRG_REG_BASE)
+
+#define SOC_CRGPERIPH_A53_PDCEN_ADDR(base) ((base) + (0x260))
+#define SOC_CRGPERIPH_MAIA_PDCEN_ADDR(base) ((base) + (0x300))
+
+#define SOC_PCTRL_RESOURCE0_LOCK_ADDR(base) ((base) + (0x400))
+#define SOC_PCTRL_RESOURCE0_UNLOCK_ADDR(base) ((base) + (0x404))
+#define SOC_PCTRL_RESOURCE0_LOCK_ST_ADDR(base) ((base) + (0x408))
+#define SOC_PCTRL_RESOURCE1_LOCK_ADDR(base) ((base) + (0x40C))
+#define SOC_PCTRL_RESOURCE1_UNLOCK_ADDR(base) ((base) + (0x410))
+#define SOC_PCTRL_RESOURCE1_LOCK_ST_ADDR(base) ((base) + (0x414))
+#define SOC_PCTRL_RESOURCE2_LOCK_ADDR(base) ((base) + (0x418))
+
+#define SOC_SCTRL_SCBAKDATA3_ADDR(base) ((base) + (0x418))
+#define SOC_SCTRL_SCBAKDATA8_ADDR(base) ((base) + (0x42C))
+#define SOC_SCTRL_SCBAKDATA9_ADDR(base) ((base) + (0x430))
+
+#define SOC_ACPU_SCTRL_BASE_ADDR (0xFFF0A000)
+
+void hisi_cpuidle_lock(unsigned int cluster, unsigned int core);
+void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core);
+void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core);
+void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core);
+void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core);
+void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core);
+int cluster_is_powered_on(unsigned int cluster);
+void hisi_enter_core_idle(unsigned int cluster, unsigned int core);
+void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core);
+int hisi_test_ap_suspend_flag(void);
+void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core);
+
+
+/* pdc api */
+void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster);
+int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core);
+void hisi_disable_pdc(unsigned int cluster);
+void hisi_enable_pdc(unsigned int cluster);
+void hisi_powerup_core(unsigned int cluster, unsigned int core);
+void hisi_powerdn_core(unsigned int cluster, unsigned int core);
+void hisi_powerup_cluster(unsigned int cluster, unsigned int core);
+void hisi_powerdn_cluster(unsigned int cluster, unsigned int core);
+unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core);
+
+#endif /* HISI_PWRC_H */
diff --git a/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
new file mode 100644
index 0000000..0a2d062
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl1/tbbr/tbbr_img_desc.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/delay_timer.h>
+#include <drivers/dw_ufs.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ufs.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <hi3660.h>
+#include "hikey960_def.h"
+#include "hikey960_private.h"
+
+enum {
+ BOOT_MODE_RECOVERY = 0,
+ BOOT_MODE_NORMAL,
+ BOOT_MODE_MASK = 1,
+};
+
+/*
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted RAM
+ */
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+static console_t console;
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t g0_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+const gicv2_driver_data_t hikey960_gic_data = {
+ .gicd_base = GICD_REG_BASE,
+ .gicc_base = GICC_REG_BASE,
+ .interrupt_props = g0_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props),
+};
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+/*
+ * Perform any BL1 specific platform actions.
+ */
+void bl1_early_platform_setup(void)
+{
+ unsigned int id, uart_base;
+
+ generic_delay_timer_init();
+ hikey960_read_boardid(&id);
+ if (id == 5300)
+ uart_base = PL011_UART5_BASE;
+ else
+ uart_base = PL011_UART6_BASE;
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = BL1_RW_BASE;
+ bl1_tzram_layout.total_size = BL1_RW_SIZE;
+
+ INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
+ BL1_RAM_LIMIT - BL1_RAM_BASE); /* bl1_size */
+}
+
+/*
+ * Perform the very early platform specific architecture setup here. At the
+ * moment this only does basic initialization. Later architectural setup
+ * (bl1_arch_setup()) does not do anything platform specific.
+ */
+void bl1_plat_arch_setup(void)
+{
+ hikey960_init_mmu_el3(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL1_RO_BASE,
+ BL1_RO_LIMIT,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+static void hikey960_ufs_reset(void)
+{
+ unsigned int data, mask;
+
+ mmio_write_32(CRG_PERDIS7_REG, 1 << 14);
+ mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
+ do {
+ data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
+ } while (data & BIT_SYSCTRL_REF_CLOCK_EN);
+ /* use abb clk */
+ mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1);
+ mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN);
+ mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16));
+ mdelay(1);
+ mmio_write_32(CRG_PEREN7_REG, 1 << 14);
+ mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
+
+ mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT);
+ do {
+ data = mmio_read_32(CRG_PERRSTSTAT3_REG);
+ } while ((data & PERI_UFS_BIT) == 0);
+ mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN);
+ mdelay(1);
+ mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY);
+ mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
+ MASK_UFS_DEVICE_RESET);
+ /* clear SC_DIV_UFS_PERIBUS */
+ mask = SC_DIV_UFS_PERIBUS << 16;
+ mmio_write_32(CRG_CLKDIV17_REG, mask);
+ /* set SC_DIV_UFSPHY_CFG(3) */
+ mask = SC_DIV_UFSPHY_CFG_MASK << 16;
+ data = SC_DIV_UFSPHY_CFG(3);
+ mmio_write_32(CRG_CLKDIV16_REG, mask | data);
+ data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
+ data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ;
+ data |= 0x39;
+ mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data);
+ mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL);
+ mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG,
+ MASK_UFS_CLK_GATE_BYPASS);
+ mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS);
+
+ mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN);
+ mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL);
+ mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL);
+ mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN);
+ mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT);
+ mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N);
+ mdelay(1);
+ mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
+ MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET);
+ mdelay(20);
+ mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
+ 0x03300330);
+
+ mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT);
+ do {
+ data = mmio_read_32(CRG_PERRSTSTAT3_REG);
+ } while (data & PERI_UFS_BIT);
+}
+
+static void hikey960_ufs_init(void)
+{
+ dw_ufs_params_t ufs_params;
+
+ memset(&ufs_params, 0, sizeof(ufs_params));
+ ufs_params.reg_base = UFS_REG_BASE;
+ ufs_params.desc_base = HIKEY960_UFS_DESC_BASE;
+ ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE;
+
+ if ((ufs_params.flags & UFS_FLAGS_SKIPINIT) == 0)
+ hikey960_ufs_reset();
+ dw_ufs_init(&ufs_params);
+}
+
+/*
+ * Function which will perform any remaining platform-specific setup that can
+ * occur after the MMU and data cache have been enabled.
+ */
+void bl1_platform_setup(void)
+{
+ hikey960_clk_init();
+ hikey960_pmu_init();
+ hikey960_regulator_enable();
+ hikey960_tzc_init();
+ hikey960_peri_init();
+ hikey960_ufs_init();
+ hikey960_pinmux_init();
+ hikey960_gpio_init();
+ hikey960_io_setup();
+}
+
+/*
+ * The following function checks if Firmware update is needed,
+ * by checking if TOC in FIP image is valid or not.
+ */
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ unsigned int mode, ret;
+
+ mode = mmio_read_32(SCTRL_BAK_DATA0_REG);
+ switch (mode & BOOT_MODE_MASK) {
+ case BOOT_MODE_RECOVERY:
+ ret = NS_BL1U_IMAGE_ID;
+ break;
+ default:
+ WARN("Invalid boot mode is found:%d\n", mode);
+ panic();
+ }
+ return ret;
+}
+
+image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
+{
+ unsigned int index = 0;
+
+ while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) {
+ if (bl1_tbbr_image_descs[index].image_id == image_id)
+ return &bl1_tbbr_image_descs[index];
+ index++;
+ }
+
+ return NULL;
+}
+
+void bl1_plat_set_ep_info(unsigned int image_id,
+ entry_point_info_t *ep_info)
+{
+ unsigned int data = 0;
+ uintptr_t tmp = HIKEY960_NS_TMP_OFFSET;
+
+ if (image_id != NS_BL1U_IMAGE_ID)
+ panic();
+ /* Copy NS BL1U from 0x1AC1_8000 to 0x1AC9_8000 */
+ memcpy((void *)tmp, (void *)HIKEY960_NS_IMAGE_OFFSET,
+ NS_BL1U_SIZE);
+ memcpy((void *)NS_BL1U_BASE, (void *)tmp, NS_BL1U_SIZE);
+ inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE);
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ gicv2_driver_init(&hikey960_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+ /* CNTFRQ is read-only in EL1 */
+ write_cntfrq_el0(plat_get_syscnt_freq2());
+ data = read_cpacr_el1();
+ do {
+ data |= 3 << 20;
+ write_cpacr_el1(data);
+ data = read_cpacr_el1();
+ } while ((data & (3 << 20)) != (3 << 20));
+ INFO("cpacr_el1:0x%x\n", data);
+
+ ep_info->args.arg0 = 0xffff & read_mpidr();
+ ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+}
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c b/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c
new file mode 100644
index 0000000..e42785a
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = HIKEY960_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the pager
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the paged
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = HIKEY960_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#ifdef SPD_spmd
+ /* Fill TOS_FW_CONFIG related information */
+ {
+ .image_id = TOS_FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = DDR_SEC_CONFIG_BASE,
+ .image_info.image_max_size = DDR_SEC_CONFIG_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif
+
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = NS_BL1U_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = NS_BL1U_BASE,
+ .image_info.image_max_size = 0x200000 /* 2MB */,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
new file mode 100644
index 0000000..7334853
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/delay_timer.h>
+#include <drivers/dw_ufs.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/partition/partition.h>
+#include <drivers/ufs.h>
+#include <lib/mmio.h>
+#ifdef SPD_opteed
+#include <lib/optee_utils.h>
+#endif
+
+#include <hi3660.h>
+#include "hikey960_def.h"
+#include "hikey960_private.h"
+
+#define BL2_RW_BASE (BL_CODE_END)
+
+/* BL2 platform parameters passed to BL31 */
+static plat_params_from_bl2_t plat_params_from_bl2;
+
+static meminfo_t bl2_el3_tzram_layout;
+static console_t console;
+extern int load_lpm3(void);
+
+enum {
+ BOOT_MODE_RECOVERY = 0,
+ BOOT_MODE_NORMAL,
+ BOOT_MODE_MASK = 1,
+};
+
+/*******************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int plat_hikey960_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ int i;
+ int *buf;
+
+ assert(scp_bl2_image_info->image_size < SCP_BL2_SIZE);
+
+ INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
+
+ INFO("BL2: SCP_BL2: 0x%lx@0x%x\n",
+ scp_bl2_image_info->image_base,
+ scp_bl2_image_info->image_size);
+
+ buf = (int *)scp_bl2_image_info->image_base;
+
+ INFO("BL2: SCP_BL2 HEAD:\n");
+ for (i = 0; i < 64; i += 4)
+ INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n",
+ buf[i], buf[i+1], buf[i+2], buf[i+3]);
+
+ buf = (int *)(scp_bl2_image_info->image_base +
+ scp_bl2_image_info->image_size - 256);
+
+ INFO("BL2: SCP_BL2 TAIL:\n");
+ for (i = 0; i < 64; i += 4)
+ INFO("BL2: SCP_BL2 0x%x 0x%x 0x%x 0x%x\n",
+ buf[i], buf[i+1], buf[i+2], buf[i+3]);
+
+ INFO("BL2: SCP_BL2 transferred to SCP\n");
+
+ load_lpm3();
+ (void)buf;
+
+ return 0;
+}
+
+static void hikey960_ufs_reset(void)
+{
+ unsigned int data, mask;
+
+ mmio_write_32(CRG_PERDIS7_REG, 1 << 14);
+ mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
+ do {
+ data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
+ } while (data & BIT_SYSCTRL_REF_CLOCK_EN);
+ /* use abb clk */
+ mmio_clrbits_32(UFS_SYS_UFS_SYSCTRL_REG, BIT_UFS_REFCLK_SRC_SE1);
+ mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_REFCLK_ISO_EN);
+ mmio_write_32(PCTRL_PERI_CTRL3_REG, (1 << 0) | (1 << 16));
+ mdelay(1);
+ mmio_write_32(CRG_PEREN7_REG, 1 << 14);
+ mmio_setbits_32(UFS_SYS_PHY_CLK_CTRL_REG, BIT_SYSCTRL_REF_CLOCK_EN);
+
+ mmio_write_32(CRG_PERRSTEN3_REG, PERI_UFS_BIT);
+ do {
+ data = mmio_read_32(CRG_PERRSTSTAT3_REG);
+ } while ((data & PERI_UFS_BIT) == 0);
+ mmio_setbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_MTCMOS_EN);
+ mdelay(1);
+ mmio_setbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_PWR_READY);
+ mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
+ MASK_UFS_DEVICE_RESET);
+ /* clear SC_DIV_UFS_PERIBUS */
+ mask = SC_DIV_UFS_PERIBUS << 16;
+ mmio_write_32(CRG_CLKDIV17_REG, mask);
+ /* set SC_DIV_UFSPHY_CFG(3) */
+ mask = SC_DIV_UFSPHY_CFG_MASK << 16;
+ data = SC_DIV_UFSPHY_CFG(3);
+ mmio_write_32(CRG_CLKDIV16_REG, mask | data);
+ data = mmio_read_32(UFS_SYS_PHY_CLK_CTRL_REG);
+ data &= ~MASK_SYSCTRL_CFG_CLOCK_FREQ;
+ data |= 0x39;
+ mmio_write_32(UFS_SYS_PHY_CLK_CTRL_REG, data);
+ mmio_clrbits_32(UFS_SYS_PHY_CLK_CTRL_REG, MASK_SYSCTRL_REF_CLOCK_SEL);
+ mmio_setbits_32(UFS_SYS_CLOCK_GATE_BYPASS_REG,
+ MASK_UFS_CLK_GATE_BYPASS);
+ mmio_setbits_32(UFS_SYS_UFS_SYSCTRL_REG, MASK_UFS_SYSCTRL_BYPASS);
+
+ mmio_setbits_32(UFS_SYS_PSW_CLK_CTRL_REG, BIT_SYSCTRL_PSW_CLK_EN);
+ mmio_clrbits_32(UFS_SYS_PSW_POWER_CTRL_REG, BIT_UFS_PSW_ISO_CTRL);
+ mmio_clrbits_32(UFS_SYS_PHY_ISO_EN_REG, BIT_UFS_PHY_ISO_CTRL);
+ mmio_clrbits_32(UFS_SYS_HC_LP_CTRL_REG, BIT_SYSCTRL_LP_ISOL_EN);
+ mmio_write_32(CRG_PERRSTDIS3_REG, PERI_ARST_UFS_BIT);
+ mmio_setbits_32(UFS_SYS_RESET_CTRL_EN_REG, BIT_SYSCTRL_LP_RESET_N);
+ mdelay(1);
+ mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
+ MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET);
+ mdelay(20);
+ mmio_write_32(UFS_SYS_UFS_DEVICE_RESET_CTRL_REG,
+ 0x03300330);
+
+ mmio_write_32(CRG_PERRSTDIS3_REG, PERI_UFS_BIT);
+ do {
+ data = mmio_read_32(CRG_PERRSTSTAT3_REG);
+ } while (data & PERI_UFS_BIT);
+}
+
+static void hikey960_init_ufs(void)
+{
+ dw_ufs_params_t ufs_params;
+
+ memset(&ufs_params, 0, sizeof(ufs_params_t));
+ ufs_params.reg_base = UFS_REG_BASE;
+ ufs_params.desc_base = HIKEY960_UFS_DESC_BASE;
+ ufs_params.desc_size = HIKEY960_UFS_DESC_SIZE;
+ hikey960_ufs_reset();
+ dw_ufs_init(&ufs_params);
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t hikey960_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL3-2 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifdef __aarch64__
+uint32_t hikey960_get_spsr_for_bl33_entry(void)
+{
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#else
+uint32_t hikey960_get_spsr_for_bl33_entry(void)
+{
+ unsigned int hyp_status, mode, spsr;
+
+ hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+ mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#endif /* __aarch64__ */
+
+int hikey960_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL31_IMAGE_ID:
+ /* Pass BL2 platform parameter to BL31 */
+ bl_mem_params->ep_info.args.arg1 = (uint64_t) &plat_params_from_bl2;
+ break;
+
+#ifdef __aarch64__
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+#endif
+ bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl32_entry();
+ break;
+#endif
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = hikey960_get_spsr_for_bl33_entry();
+ break;
+
+#ifdef SCP_BL2_BASE
+ case SCP_BL2_IMAGE_ID:
+ /* The subsequent handling of SCP_BL2 is platform specific */
+ err = plat_hikey960_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+ if (err) {
+ WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+ }
+ break;
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ return hikey960_set_fip_addr(image_id, "fip");
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return hikey960_bl2_handle_post_image_load(image_id);
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ unsigned int id, uart_base;
+
+ generic_delay_timer_init();
+ hikey960_read_boardid(&id);
+ if (id == 5300)
+ uart_base = PL011_UART5_BASE;
+ else
+ uart_base = PL011_UART6_BASE;
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+ /*
+ * Allow BL2 to see the whole Trusted RAM.
+ */
+ bl2_el3_tzram_layout.total_base = BL2_RW_BASE;
+ bl2_el3_tzram_layout.total_size = BL31_LIMIT - BL2_RW_BASE;
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ hikey960_init_mmu_el3(bl2_el3_tzram_layout.total_base,
+ bl2_el3_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+void bl2_platform_setup(void)
+{
+ int ret;
+
+ /* disable WDT0 */
+ if (mmio_read_32(WDT0_REG_BASE + WDT_LOCK_OFFSET) == WDT_LOCKED) {
+ mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, WDT_UNLOCK);
+ mmio_write_32(WDT0_REG_BASE + WDT_CONTROL_OFFSET, 0);
+ mmio_write_32(WDT0_REG_BASE + WDT_LOCK_OFFSET, 0);
+ }
+ hikey960_clk_init();
+ hikey960_pmu_init();
+ hikey960_regulator_enable();
+ hikey960_tzc_init();
+ hikey960_peri_init();
+ hikey960_pinmux_init();
+ hikey960_gpio_init();
+ hikey960_init_ufs();
+ hikey960_io_setup();
+
+ /* Read serial number from storage */
+ plat_params_from_bl2.fastboot_serno = 0;
+ ret = hikey960_load_serialno(&plat_params_from_bl2.fastboot_serno);
+ if (ret != 0) {
+ ERROR("BL2: could not read serial number\n");
+ }
+ INFO("BL2: fastboot_serno %lx\n", plat_params_from_bl2.fastboot_serno);
+ flush_dcache_range((uintptr_t)&plat_params_from_bl2, sizeof(plat_params_from_bl2_t));
+}
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
new file mode 100644
index 0000000..0debe1e
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+#include <services/el3_spmc_ffa_memory.h>
+
+#include <hi3660.h>
+#include <hisi_ipc.h>
+#include "hikey960_def.h"
+#include "hikey960_private.h"
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+static console_t console;
+
+/* fastboot serial number consumed by Kinibi SPD/LP for gpd.tee.deviceID. */
+uint64_t fastboot_serno;
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t g0_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+const gicv2_driver_data_t hikey960_gic_data = {
+ .gicd_base = GICD_REG_BASE,
+ .gicc_base = GICC_REG_BASE,
+ .interrupt_props = g0_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props),
+};
+
+static const int cci_map[] = {
+ CCI400_SL_IFACE3_CLUSTER_IX,
+ CCI400_SL_IFACE4_CLUSTER_IX
+};
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ return NULL;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ unsigned int id, uart_base;
+ void *from_bl2;
+ plat_params_from_bl2_t *plat_params_from_bl2 = (plat_params_from_bl2_t *) arg1;
+
+ from_bl2 = (void *) arg0;
+
+ generic_delay_timer_init();
+ hikey960_read_boardid(&id);
+ if (id == 5300)
+ uart_base = PL011_UART5_BASE;
+ else
+ uart_base = PL011_UART6_BASE;
+
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Initialize CCI driver */
+ cci_init(CCI400_REG_BASE, cci_map, ARRAY_SIZE(cci_map));
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+
+ /* Fastboot serial number passed from BL2 as a platform parameter */
+ fastboot_serno = plat_params_from_bl2->fastboot_serno;
+ INFO("BL31: fastboot_serno %lx\n", fastboot_serno);
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_ep_info.pc == 0)
+ panic();
+}
+
+void bl31_plat_arch_setup(void)
+{
+#if SPMC_AT_EL3
+ mmap_add_region(DDR2_SEC_BASE, DDR2_SEC_BASE, DDR2_SEC_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE);
+#endif
+
+ hikey960_init_mmu_el3(BL31_BASE,
+ BL31_LIMIT - BL31_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+static void hikey960_edma_init(void)
+{
+ int i;
+ uint32_t non_secure;
+
+ non_secure = EDMAC_SEC_CTRL_INTR_SEC | EDMAC_SEC_CTRL_GLOBAL_SEC;
+ mmio_write_32(EDMAC_SEC_CTRL, non_secure);
+
+ /* Channel 0 is reserved for LPM3, keep secure */
+ for (i = 1; i < EDMAC_CHANNEL_NUMS; i++) {
+ mmio_write_32(EDMAC_AXI_CONF(i), (1 << 6) | (1 << 18));
+ }
+}
+
+static void hikey960_iomcu_dma_init(void)
+{
+ int i;
+ uint32_t non_secure;
+
+ non_secure = IOMCU_DMAC_SEC_CTRL_INTR_SEC | IOMCU_DMAC_SEC_CTRL_GLOBAL_SEC;
+ mmio_write_32(IOMCU_DMAC_SEC_CTRL, non_secure);
+
+ /* channels 0-3 are reserved */
+ for (i = 4; i < IOMCU_DMAC_CHANNEL_NUMS; i++) {
+ mmio_write_32(IOMCU_DMAC_AXI_CONF(i), IOMCU_DMAC_AXI_CONF_ARPROT_NS |
+ IOMCU_DMAC_AXI_CONF_AWPROT_NS);
+ }
+}
+
+#if SPMC_AT_EL3
+/*
+ * On the hikey960 platform when using the EL3 SPMC implementation allocate the
+ * datastore for tracking shared memory descriptors in the RAM2 DRAM section
+ * to ensure sufficient storage can be allocated.
+ * Provide an implementation of the accessor method to allow the datastore
+ * details to be retrieved by the SPMC.
+ * The SPMC will take care of initializing the memory region.
+ */
+
+#define SPMC_SHARED_MEMORY_OBJ_SIZE (512 * 1024)
+
+__section("ram2_region") uint8_t plat_spmc_shmem_datastore[SPMC_SHARED_MEMORY_OBJ_SIZE];
+
+int plat_spmc_shmem_datastore_get(uint8_t **datastore, size_t *size)
+{
+ *datastore = plat_spmc_shmem_datastore;
+ *size = SPMC_SHARED_MEMORY_OBJ_SIZE;
+ return 0;
+}
+
+/*
+ * Add dummy implementations of memory management related platform hooks.
+ * These can be used to implement platform specific functionality to support
+ * a memory sharing/lending operation.
+ *
+ * Note: The hooks must be located as part of the initial share request and
+ * final reclaim to prevent order dependencies with operations that may take
+ * place in the normal world without visibility of the SPMC.
+ */
+int plat_spmc_shmem_begin(struct ffa_mtd *desc)
+{
+ return 0;
+}
+
+int plat_spmc_shmem_reclaim(struct ffa_mtd *desc)
+{
+ return 0;
+}
+
+#endif
+
+void bl31_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ gicv2_driver_init(&hikey960_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ hikey960_edma_init();
+ hikey960_iomcu_dma_init();
+ hikey960_gpio_init();
+
+ hisi_ipc_init();
+}
+
+#ifdef SPD_none
+static uint64_t hikey_debug_fiq_handler(uint32_t id,
+ uint32_t flags,
+ void *handle,
+ void *cookie)
+{
+ int intr, intr_raw;
+
+ /* Acknowledge interrupt */
+ intr_raw = plat_ic_acknowledge_interrupt();
+ intr = plat_ic_get_interrupt_id(intr_raw);
+ ERROR("Invalid interrupt: intr=%d\n", intr);
+ console_flush();
+ panic();
+
+ return 0;
+}
+#endif
+
+void bl31_plat_runtime_setup(void)
+{
+#ifdef SPD_none
+ uint32_t flags;
+ int32_t rc;
+
+ flags = 0;
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+ hikey_debug_fiq_handler,
+ flags);
+ if (rc != 0)
+ panic();
+#endif
+}
diff --git a/plat/hisilicon/hikey960/hikey960_bl_common.c b/plat/hisilicon/hikey960/hikey960_bl_common.c
new file mode 100644
index 0000000..3c4a164
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_bl_common.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/pl061_gpio.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <hi3660.h>
+#include "hikey960_private.h"
+
+void hikey960_clk_init(void)
+{
+ /* change ldi0 sel to ppll2 */
+ mmio_write_32(0xfff350b4, 0xf0002000);
+ /* ldi0 20' */
+ mmio_write_32(0xfff350bc, 0xfc004c00);
+}
+
+void hikey960_pmu_init(void)
+{
+ /* clear np_xo_abb_dig_START bit in PMIC_CLK_TOP_CTRL7 register */
+ mmio_clrbits_32(PMU_SSI0_CLK_TOP_CTRL7_REG, NP_XO_ABB_DIG);
+}
+
+static void hikey960_enable_ppll3(void)
+{
+ /* enable ppll3 */
+ mmio_write_32(PMC_PPLL3_CTRL0_REG, 0x4904305);
+ mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x2300000);
+ mmio_write_32(PMC_PPLL3_CTRL1_REG, 0x6300000);
+}
+
+static void bus_idle_clear(unsigned int value)
+{
+ unsigned int pmc_value, value1, value2;
+ int timeout = 100;
+
+ pmc_value = value << 16;
+ pmc_value &= ~value;
+ mmio_write_32(PMC_NOC_POWER_IDLEREQ_REG, pmc_value);
+
+ for (;;) {
+ value1 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLEACK_REG);
+ value2 = (unsigned int)mmio_read_32(PMC_NOC_POWER_IDLE_REG);
+ if (((value1 & value) == 0) && ((value2 & value) == 0))
+ break;
+ udelay(1);
+ timeout--;
+ if (timeout <= 0) {
+ WARN("%s timeout\n", __func__);
+ break;
+ }
+ }
+}
+
+static void set_vivobus_power_up(void)
+{
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV20_REG, 0x00020002);
+ mmio_write_32(CRG_PEREN0_REG, 0x00001000);
+}
+
+static void set_dss_power_up(void)
+{
+ /* set edc0 133MHz = 1600MHz / 12 */
+ mmio_write_32(CRG_CLKDIV5_REG, 0x003f000b);
+ /* set ldi0 ppl0 */
+ mmio_write_32(CRG_CLKDIV3_REG, 0xf0001000);
+ /* set ldi0 133MHz, 1600MHz / 12 */
+ mmio_write_32(CRG_CLKDIV5_REG, 0xfc002c00);
+ /* mtcmos on */
+ mmio_write_32(CRG_PERPWREN_REG, 0x00000020);
+ udelay(100);
+ /* DISP CRG */
+ mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000010);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV18_REG, 0x01400140);
+ mmio_write_32(CRG_PEREN0_REG, 0x00002000);
+ mmio_write_32(CRG_PEREN3_REG, 0x0003b000);
+ udelay(1);
+ /* clk disable */
+ mmio_write_32(CRG_PERDIS3_REG, 0x0003b000);
+ mmio_write_32(CRG_PERDIS0_REG, 0x00002000);
+ mmio_write_32(CRG_CLKDIV18_REG, 0x01400000);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(CRG_ISODIS_REG, 0x00000040);
+ /* unreset */
+ mmio_write_32(CRG_PERRSTDIS4_REG, 0x00000006);
+ mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000c00);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV18_REG, 0x01400140);
+ mmio_write_32(CRG_PEREN0_REG, 0x00002000);
+ mmio_write_32(CRG_PEREN3_REG, 0x0003b000);
+ /* bus idle clear */
+ bus_idle_clear(PMC_NOC_POWER_IDLEREQ_DSS);
+ /* set edc0 400MHz for 2K 1600MHz / 4 */
+ mmio_write_32(CRG_CLKDIV5_REG, 0x003f0003);
+ /* set ldi 266MHz, 1600MHz / 6 */
+ mmio_write_32(CRG_CLKDIV5_REG, 0xfc001400);
+}
+
+static void set_vcodec_power_up(void)
+{
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV20_REG, 0x00040004);
+ mmio_write_32(CRG_PEREN0_REG, 0x00000060);
+ mmio_write_32(CRG_PEREN2_REG, 0x10000000);
+ /* unreset */
+ mmio_write_32(CRG_PERRSTDIS0_REG, 0x00000018);
+ /* bus idle clear */
+ bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VCODEC);
+}
+
+static void set_vdec_power_up(void)
+{
+ /* mtcmos on */
+ mmio_write_32(CRG_PERPWREN_REG, 0x00000004);
+ udelay(100);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV18_REG, 0x80008000);
+ mmio_write_32(CRG_PEREN2_REG, 0x20080000);
+ mmio_write_32(CRG_PEREN3_REG, 0x00000800);
+ udelay(1);
+ /* clk disable */
+ mmio_write_32(CRG_PERDIS3_REG, 0x00000800);
+ mmio_write_32(CRG_PERDIS2_REG, 0x20080000);
+ mmio_write_32(CRG_CLKDIV18_REG, 0x80000000);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(CRG_ISODIS_REG, 0x00000004);
+ /* unreset */
+ mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000200);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV18_REG, 0x80008000);
+ mmio_write_32(CRG_PEREN2_REG, 0x20080000);
+ mmio_write_32(CRG_PEREN3_REG, 0x00000800);
+ /* bus idle clear */
+ bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VDEC);
+}
+
+static void set_venc_power_up(void)
+{
+ /* set venc ppll3 */
+ mmio_write_32(CRG_CLKDIV8_REG, 0x18001000);
+ /* set venc 258MHz, 1290MHz / 5 */
+ mmio_write_32(CRG_CLKDIV8_REG, 0x07c00100);
+ /* mtcmos on */
+ mmio_write_32(CRG_PERPWREN_REG, 0x00000002);
+ udelay(100);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV19_REG, 0x00010001);
+ mmio_write_32(CRG_PEREN2_REG, 0x40000100);
+ mmio_write_32(CRG_PEREN3_REG, 0x00000400);
+ udelay(1);
+ /* clk disable */
+ mmio_write_32(CRG_PERDIS3_REG, 0x00000400);
+ mmio_write_32(CRG_PERDIS2_REG, 0x40000100);
+ mmio_write_32(CRG_CLKDIV19_REG, 0x00010000);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(CRG_ISODIS_REG, 0x00000002);
+ /* unreset */
+ mmio_write_32(CRG_PERRSTDIS3_REG, 0x00000100);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV19_REG, 0x00010001);
+ mmio_write_32(CRG_PEREN2_REG, 0x40000100);
+ mmio_write_32(CRG_PEREN3_REG, 0x00000400);
+ /* bus idle clear */
+ bus_idle_clear(PMC_NOC_POWER_IDLEREQ_VENC);
+ /* set venc 645MHz, 1290MHz / 2 */
+ mmio_write_32(CRG_CLKDIV8_REG, 0x07c00040);
+}
+
+static void set_isp_power_up(void)
+{
+ /* mtcmos on */
+ mmio_write_32(CRG_PERPWREN_REG, 0x00000001);
+ udelay(100);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV18_REG, 0x70007000);
+ mmio_write_32(CRG_CLKDIV20_REG, 0x00100010);
+ mmio_write_32(CRG_PEREN5_REG, 0x01000010);
+ mmio_write_32(CRG_PEREN3_REG, 0x0bf00000);
+ udelay(1);
+ /* clk disable */
+ mmio_write_32(CRG_PERDIS5_REG, 0x01000010);
+ mmio_write_32(CRG_PERDIS3_REG, 0x0bf00000);
+ mmio_write_32(CRG_CLKDIV18_REG, 0x70000000);
+ mmio_write_32(CRG_CLKDIV20_REG, 0x00100000);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(CRG_ISODIS_REG, 0x00000001);
+ /* unreset */
+ mmio_write_32(CRG_ISP_SEC_RSTDIS_REG, 0x0000002f);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV18_REG, 0x70007000);
+ mmio_write_32(CRG_CLKDIV20_REG, 0x00100010);
+ mmio_write_32(CRG_PEREN5_REG, 0x01000010);
+ mmio_write_32(CRG_PEREN3_REG, 0x0bf00000);
+ /* bus idle clear */
+ bus_idle_clear(PMC_NOC_POWER_IDLEREQ_ISP);
+ /* csi clk enable */
+ mmio_write_32(CRG_PEREN3_REG, 0x00700000);
+}
+
+static void set_ivp_power_up(void)
+{
+ /* set ivp ppll0 */
+ mmio_write_32(CRG_CLKDIV0_REG, 0xc0000000);
+ /* set ivp 267MHz, 1600MHz / 6 */
+ mmio_write_32(CRG_CLKDIV0_REG, 0x3c001400);
+ /* mtcmos on */
+ mmio_write_32(CRG_PERPWREN_REG, 0x00200000);
+ udelay(100);
+ /* IVP CRG unreset */
+ mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000001);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV20_REG, 0x02000200);
+ mmio_write_32(CRG_PEREN4_REG, 0x000000a8);
+ udelay(1);
+ /* clk disable */
+ mmio_write_32(CRG_PERDIS4_REG, 0x000000a8);
+ mmio_write_32(CRG_CLKDIV20_REG, 0x02000000);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(CRG_ISODIS_REG, 0x01000000);
+ /* unreset */
+ mmio_write_32(CRG_IVP_SEC_RSTDIS_REG, 0x00000002);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV20_REG, 0x02000200);
+ mmio_write_32(CRG_PEREN4_REG, 0x000000a8);
+ /* bus idle clear */
+ bus_idle_clear(PMC_NOC_POWER_IDLEREQ_IVP);
+ /* set ivp 533MHz, 1600MHz / 3 */
+ mmio_write_32(CRG_CLKDIV0_REG, 0x3c000800);
+}
+
+static void set_audio_power_up(void)
+{
+ unsigned int ret;
+ int timeout = 100;
+ /* mtcmos on */
+ mmio_write_32(SCTRL_SCPWREN_REG, 0x00000001);
+ udelay(100);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV19_REG, 0x80108010);
+ mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001);
+ mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000);
+ mmio_write_32(CRG_PEREN0_REG, 0x04000000);
+ mmio_write_32(CRG_PEREN5_REG, 0x00000080);
+ mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f);
+ udelay(1);
+ /* clk disable */
+ mmio_write_32(SCTRL_SCPERDIS1_REG, 0x0000000f);
+ mmio_write_32(SCTRL_SCPERDIS0_REG, 0x0c000000);
+ mmio_write_32(CRG_PERDIS5_REG, 0x00000080);
+ mmio_write_32(CRG_PERDIS0_REG, 0x04000000);
+ mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010000);
+ mmio_write_32(CRG_CLKDIV19_REG, 0x80100000);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(SCTRL_SCISODIS_REG, 0x00000001);
+ udelay(1);
+ /* unreset */
+ mmio_write_32(SCTRL_PERRSTDIS1_SEC_REG, 0x00000001);
+ mmio_write_32(SCTRL_SCPERRSTDIS0_REG, 0x00000780);
+ /* clk enable */
+ mmio_write_32(CRG_CLKDIV19_REG, 0x80108010);
+ mmio_write_32(SCTRL_SCCLKDIV2_REG, 0x00010001);
+ mmio_write_32(SCTRL_SCPEREN0_REG, 0x0c000000);
+ mmio_write_32(CRG_PEREN0_REG, 0x04000000);
+ mmio_write_32(CRG_PEREN5_REG, 0x00000080);
+ mmio_write_32(SCTRL_SCPEREN1_REG, 0x0000000f);
+ /* bus idle clear */
+ mmio_write_32(SCTRL_SCPERCTRL7_REG, 0x00040000);
+ for (;;) {
+ ret = mmio_read_32(SCTRL_SCPERSTAT6_REG);
+ if (((ret & (1 << 5)) == 0) && ((ret & (1 << 8)) == 0))
+ break;
+ udelay(1);
+ timeout--;
+ if (timeout <= 0) {
+ WARN("%s timeout\n", __func__);
+ break;
+ }
+ }
+ mmio_write_32(ASP_CFG_MMBUF_CTRL_REG, 0x00ff0000);
+}
+
+static void set_pcie_power_up(void)
+{
+ /* mtcmos on */
+ mmio_write_32(SCTRL_SCPWREN_REG, 0x00000010);
+ udelay(100);
+ /* clk enable */
+ mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800);
+ mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000);
+ mmio_write_32(CRG_PEREN7_REG, 0x000003a0);
+ udelay(1);
+ /* clk disable */
+ mmio_write_32(SCTRL_SCPERDIS2_REG, 0x00104000);
+ mmio_write_32(CRG_PERDIS7_REG, 0x000003a0);
+ mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000000);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(SCTRL_SCISODIS_REG, 0x00000030);
+ /* unreset */
+ mmio_write_32(CRG_PERRSTDIS3_REG, 0x8c000000);
+ /* clk enable */
+ mmio_write_32(SCTRL_SCCLKDIV6_REG, 0x08000800);
+ mmio_write_32(SCTRL_SCPEREN2_REG, 0x00104000);
+ mmio_write_32(CRG_PEREN7_REG, 0x000003a0);
+}
+
+static void ispfunc_enable(void)
+{
+ /* enable ispfunc. Otherwise powerup isp_srt causes exception. */
+ mmio_write_32(0xfff35000, 0x00000008);
+ mmio_write_32(0xfff35460, 0xc004ffff);
+ mmio_write_32(0xfff35030, 0x02000000);
+ mdelay(10);
+}
+
+static void isps_control_clock(int flag)
+{
+ unsigned int ret;
+
+ /* flag: 0 -- disable clock, 1 -- enable clock */
+ if (flag) {
+ ret = mmio_read_32(0xe8420364);
+ ret |= 1;
+ mmio_write_32(0xe8420364, ret);
+ } else {
+ ret = mmio_read_32(0xe8420364);
+ ret &= ~1;
+ mmio_write_32(0xe8420364, ret);
+ }
+}
+
+static void set_isp_srt_power_up(void)
+{
+ unsigned int ret;
+
+ ispfunc_enable();
+ /* reset */
+ mmio_write_32(0xe8420374, 0x00000001);
+ mmio_write_32(0xe8420350, 0x00000000);
+ mmio_write_32(0xe8420358, 0x00000000);
+ /* mtcmos on */
+ mmio_write_32(0xfff35150, 0x00400000);
+ udelay(100);
+ /* clk enable */
+ isps_control_clock(1);
+ udelay(1);
+ isps_control_clock(0);
+ udelay(1);
+ /* iso disable */
+ mmio_write_32(0xfff35148, 0x08000000);
+ /* unreset */
+ ret = mmio_read_32(0xe8420374);
+ ret &= ~0x1;
+ mmio_write_32(0xe8420374, ret);
+ /* clk enable */
+ isps_control_clock(1);
+ /* enable clock gating for accessing csi registers */
+ mmio_write_32(0xe8420010, ~0);
+}
+
+void hikey960_regulator_enable(void)
+{
+ set_vivobus_power_up();
+ hikey960_enable_ppll3();
+ set_dss_power_up();
+ set_vcodec_power_up();
+ set_vdec_power_up();
+ set_venc_power_up();
+ set_isp_power_up();
+ set_ivp_power_up();
+ set_audio_power_up();
+ set_pcie_power_up();
+ set_isp_srt_power_up();
+
+ /* set ISP_CORE_CTRL_S to unsecure mode */
+ mmio_write_32(0xe8583800, 0x7);
+ /* set ISP_SUB_CTRL_S to unsecure mode */
+ mmio_write_32(0xe8583804, 0xf);
+}
+
+void hikey960_tzc_init(void)
+{
+ mmio_write_32(TZC_EN0_REG, 0x7fbff066);
+ mmio_write_32(TZC_EN1_REG, 0xfffff5fc);
+ mmio_write_32(TZC_EN2_REG, 0x0007005c);
+ mmio_write_32(TZC_EN3_REG, 0x37030700);
+ mmio_write_32(TZC_EN4_REG, 0xf63fefae);
+ mmio_write_32(TZC_EN5_REG, 0x000410fd);
+ mmio_write_32(TZC_EN6_REG, 0x0063ff68);
+ mmio_write_32(TZC_EN7_REG, 0x030000f3);
+ mmio_write_32(TZC_EN8_REG, 0x00000007);
+}
+
+void hikey960_peri_init(void)
+{
+ /* unreset */
+ mmio_setbits_32(CRG_PERRSTDIS4_REG, 1);
+}
+
+void hikey960_pinmux_init(void)
+{
+ unsigned int id;
+
+ hikey960_read_boardid(&id);
+ if (id == 5301) {
+ /* hikey960 hardware v2 */
+ /* GPIO150: LED */
+ mmio_write_32(IOMG_FIX_006_REG, 0);
+ /* GPIO151: LED */
+ mmio_write_32(IOMG_FIX_007_REG, 0);
+ /* GPIO189: LED */
+ mmio_write_32(IOMG_AO_011_REG, 0);
+ /* GPIO190: LED */
+ mmio_write_32(IOMG_AO_012_REG, 0);
+ /* GPIO46 */
+ mmio_write_32(IOMG_044_REG, 0);
+ /* GPIO202 */
+ mmio_write_32(IOMG_AO_023_REG, 0);
+ /* GPIO206 */
+ mmio_write_32(IOMG_AO_026_REG, 0);
+ /* GPIO219 - PD pullup */
+ mmio_write_32(IOMG_AO_039_REG, 0);
+ mmio_write_32(IOCG_AO_043_REG, 1 << 0);
+ }
+ /* GPIO005 - PMU SSI, 10mA */
+ mmio_write_32(IOCG_006_REG, 2 << 4);
+ /* GPIO213 - PCIE_CLKREQ_N */
+ mmio_write_32(IOMG_AO_033_REG, 1);
+}
+
+void hikey960_gpio_init(void)
+{
+ pl061_gpio_init();
+ pl061_gpio_register(GPIO0_BASE, 0);
+ pl061_gpio_register(GPIO1_BASE, 1);
+ pl061_gpio_register(GPIO2_BASE, 2);
+ pl061_gpio_register(GPIO3_BASE, 3);
+ pl061_gpio_register(GPIO4_BASE, 4);
+ pl061_gpio_register(GPIO5_BASE, 5);
+ pl061_gpio_register(GPIO6_BASE, 6);
+ pl061_gpio_register(GPIO7_BASE, 7);
+ pl061_gpio_register(GPIO8_BASE, 8);
+ pl061_gpio_register(GPIO9_BASE, 9);
+ pl061_gpio_register(GPIO10_BASE, 10);
+ pl061_gpio_register(GPIO11_BASE, 11);
+ pl061_gpio_register(GPIO12_BASE, 12);
+ pl061_gpio_register(GPIO13_BASE, 13);
+ pl061_gpio_register(GPIO14_BASE, 14);
+ pl061_gpio_register(GPIO15_BASE, 15);
+ pl061_gpio_register(GPIO16_BASE, 16);
+ pl061_gpio_register(GPIO17_BASE, 17);
+ pl061_gpio_register(GPIO18_BASE, 18);
+ pl061_gpio_register(GPIO19_BASE, 19);
+ pl061_gpio_register(GPIO20_BASE, 20);
+ pl061_gpio_register(GPIO21_BASE, 21);
+ pl061_gpio_register(GPIO22_BASE, 22);
+ pl061_gpio_register(GPIO23_BASE, 23);
+ pl061_gpio_register(GPIO24_BASE, 24);
+ pl061_gpio_register(GPIO25_BASE, 25);
+ pl061_gpio_register(GPIO26_BASE, 26);
+ pl061_gpio_register(GPIO27_BASE, 27);
+ pl061_gpio_register(GPIO28_BASE, 28);
+
+ /* PCIE_PERST_N output low */
+ gpio_set_direction(89, GPIO_DIR_OUT);
+ gpio_set_value(89, GPIO_LEVEL_LOW);
+}
diff --git a/plat/hisilicon/hikey960/hikey960_boardid.c b/plat/hisilicon/hikey960/hikey960_boardid.c
new file mode 100644
index 0000000..1e1126f
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_boardid.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <hi3660.h>
+#include "hikey960_private.h"
+
+#define ADC_ADCIN0 0
+#define ADC_ADCIN1 1
+#define ADC_ADCIN2 2
+
+#define HKADC_DATA_GRADE0 0
+#define HKADC_DATA_GRADE1 100
+#define HKADC_DATA_GRADE2 300
+#define HKADC_DATA_GRADE3 500
+#define HKADC_DATA_GRADE4 700
+#define HKADC_DATA_GRADE5 900
+#define HKADC_DATA_GRADE6 1100
+#define HKADC_DATA_GRADE7 1300
+#define HKADC_DATA_GRADE8 1500
+#define HKADC_DATA_GRADE9 1700
+#define HKADC_DATA_GRADE10 1800
+
+#define BOARDID_VALUE0 0
+#define BOARDID_VALUE1 1
+#define BOARDID_VALUE2 2
+#define BOARDID_VALUE3 3
+#define BOARDID_VALUE4 4
+#define BOARDID_VALUE5 5
+#define BOARDID_VALUE6 6
+#define BOARDID_VALUE7 7
+#define BOARDID_VALUE8 8
+#define BOARDID_VALUE9 9
+#define BOARDID_UNKNOWN 0xF
+
+#define BOARDID3_BASE 5
+
+
+static void init_adc(void)
+{
+ /* reset hkadc */
+ mmio_write_32(CRG_PERRSTEN2_REG, PERRSTEN2_HKADCSSI);
+ /* wait a few clock cycles */
+ udelay(2);
+ mmio_write_32(CRG_PERRSTDIS2_REG, PERRSTEN2_HKADCSSI);
+ udelay(2);
+ /* enable hkadc clock */
+ mmio_write_32(CRG_PERDIS2_REG, PEREN2_HKADCSSI);
+ udelay(2);
+ mmio_write_32(CRG_PEREN2_REG, PEREN2_HKADCSSI);
+ udelay(2);
+}
+
+static int get_adc(unsigned int channel, unsigned int *value)
+{
+ unsigned int data, value1, value0;
+
+ if (channel > HKADC_CHANNEL_MAX) {
+ WARN("invalid channel:%d\n", channel);
+ return -EFAULT;
+ }
+ /* configure the read/write operation for external HKADC */
+ mmio_write_32(HKADC_WR01_DATA_REG, HKADC_WR01_VALUE | channel);
+ mmio_write_32(HKADC_WR23_DATA_REG, HKADC_WR23_VALUE);
+ mmio_write_32(HKADC_WR45_DATA_REG, HKADC_WR45_VALUE);
+ /* configure the number of accessing registers */
+ mmio_write_32(HKADC_WR_NUM_REG, HKADC_WR_NUM_VALUE);
+ /* configure delay of accessing registers */
+ mmio_write_32(HKADC_DELAY01_REG, HKADC_CHANNEL0_DELAY01_VALUE);
+ mmio_write_32(HKADC_DELAY23_REG, HKADC_DELAY23_VALUE);
+
+ /* start HKADC */
+ mmio_write_32(HKADC_DSP_START_REG, 1);
+ do {
+ data = mmio_read_32(HKADC_DSP_START_REG);
+ } while (data & 1);
+
+ /* convert AD result */
+ value1 = mmio_read_32(HKADC_DSP_RD2_DATA_REG) & 0xffff;
+ value0 = mmio_read_32(HKADC_DSP_RD3_DATA_REG) & 0xffff;
+
+ data = ((value1 << 4) & HKADC_VALUE_HIGH) |
+ ((value0 >> 4) & HKADC_VALUE_LOW);
+ *value = data;
+ return 0;
+}
+
+static int get_value(unsigned int channel, unsigned int *value)
+{
+ int ret;
+
+ ret = get_adc(channel, value);
+ if (ret)
+ return ret;
+
+ /* convert ADC value to micro-volt */
+ ret = ((*value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY;
+ *value = ret;
+ return 0;
+}
+
+static int adcin_data_remap(unsigned int adcin_value)
+{
+ int ret;
+
+ if (adcin_value < HKADC_DATA_GRADE1)
+ ret = BOARDID_VALUE0;
+ else if (adcin_value < HKADC_DATA_GRADE2)
+ ret = BOARDID_VALUE1;
+ else if (adcin_value < HKADC_DATA_GRADE3)
+ ret = BOARDID_VALUE2;
+ else if (adcin_value < HKADC_DATA_GRADE4)
+ ret = BOARDID_VALUE3;
+ else if (adcin_value < HKADC_DATA_GRADE5)
+ ret = BOARDID_VALUE4;
+ else if (adcin_value < HKADC_DATA_GRADE6)
+ ret = BOARDID_VALUE5;
+ else if (adcin_value < HKADC_DATA_GRADE7)
+ ret = BOARDID_VALUE6;
+ else if (adcin_value < HKADC_DATA_GRADE8)
+ ret = BOARDID_VALUE7;
+ else if (adcin_value < HKADC_DATA_GRADE9)
+ ret = BOARDID_VALUE8;
+ else if (adcin_value < HKADC_DATA_GRADE10)
+ ret = BOARDID_VALUE9;
+ else
+ ret = BOARDID_UNKNOWN;
+ return ret;
+}
+
+int hikey960_read_boardid(unsigned int *id)
+{
+ unsigned int adcin0, adcin1, adcin2;
+ unsigned int adcin0_remap, adcin1_remap, adcin2_remap;
+
+ assert(id != NULL);
+
+ init_adc();
+
+ /* read ADC channel0 data */
+ get_value(ADC_ADCIN0, &adcin0);
+ adcin0_remap = adcin_data_remap(adcin0);
+ if (adcin0_remap == BOARDID_UNKNOWN)
+ return -EINVAL;
+ /* read ADC channel1 data */
+ get_value(ADC_ADCIN1, &adcin1);
+ adcin1_remap = adcin_data_remap(adcin1);
+ if (adcin1_remap == BOARDID_UNKNOWN)
+ return -EINVAL;
+ /* read ADC channel2 data */
+ get_value(ADC_ADCIN2, &adcin2);
+ adcin2_remap = adcin_data_remap(adcin2);
+ if (adcin2_remap == BOARDID_UNKNOWN)
+ return -EINVAL;
+ *id = BOARDID3_BASE * 1000 + (adcin2_remap * 100) +
+ (adcin1_remap * 10) + adcin0_remap;
+ return 0;
+}
diff --git a/plat/hisilicon/hikey960/hikey960_def.h b/plat/hisilicon/hikey960/hikey960_def.h
new file mode 100644
index 0000000..e103cf4
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_def.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HIKEY960_DEF_H
+#define HIKEY960_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <plat/common/common_def.h>
+
+#define DDR_BASE 0x0
+#define DDR_SIZE 0xE0000000
+
+#define DEVICE_BASE 0xE0000000
+#define DEVICE_SIZE 0x20000000
+
+/* Memory location options for TSP */
+#define HIKEY960_SRAM_ID 0
+#define HIKEY960_DRAM_ID 1
+
+/*
+ * DDR for TEE (80MB from 0x3E00000-0x43000FFF) is divided into several
+ * regions:
+ * - SPMC manifest (4KB at the top) used by SPMC_AT_EL3 and the TEE
+ * - Datastore for SPMC_AT_EL3 (4MB at the top) used by BL31
+ * - Secure DDR (default is the top 60MB) used by OP-TEE
+ * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ * - Non-secure DDR (8MB) reserved for OP-TEE's future use
+ */
+#define DDR_SEC_SIZE 0x03C00000 /* reserve 60MB secure memory */
+#define DDR_SEC_BASE 0x3F000000
+#define DDR2_SEC_SIZE 0x00400000 /* SPMC_AT_EL3: 4MB for BL31 RAM2 */
+#define DDR2_SEC_BASE 0x42C00000
+#define DDR_SEC_CONFIG_SIZE 0x00001000 /* SPMC_AT_EL3: SPMC manifest */
+#define DDR_SEC_CONFIG_BASE 0x43000000
+
+#define DDR_SDP_SIZE 0x00400000
+#define DDR_SDP_BASE (DDR_SEC_BASE - 0x400000 /* align */ - \
+ DDR_SDP_SIZE)
+
+/*
+ * PL011 related constants
+ */
+#define PL011_UART5_BASE 0xFDF05000
+#define PL011_UART6_BASE 0xFFF32000
+#define PL011_BAUDRATE 115200
+#define PL011_UART_CLK_IN_HZ 19200000
+
+#define UFS_BASE 0
+
+#define HIKEY960_UFS_DESC_BASE 0x20000000
+#define HIKEY960_UFS_DESC_SIZE 0x00200000 /* 2MB */
+#define HIKEY960_UFS_DATA_BASE 0x10000000
+#define HIKEY960_UFS_DATA_SIZE 0x0A000000 /* 160MB */
+
+#if defined(SPMC_AT_EL3)
+/*
+ * Number of Secure Partitions supported.
+ * SPMC at EL3, uses this count to configure the maximum number of supported
+ * secure partitions.
+ */
+#define SECURE_PARTITION_COUNT 1
+
+/*
+ * Number of Nwld Partitions supported.
+ * SPMC at EL3, uses this count to configure the maximum number of supported
+ * nwld partitions.
+ */
+#define NS_PARTITION_COUNT 1
+/*
+ * Number of Logical Partitions supported.
+ * SPMC at EL3, uses this count to configure the maximum number of supported
+ * logical partitions.
+ */
+#define MAX_EL3_LP_DESCS_COUNT 1
+
+#endif /* SPMC_AT_EL3 */
+
+#endif /* HIKEY960_DEF_H */
diff --git a/plat/hisilicon/hikey960/hikey960_el3_spmc_logical_sp.c b/plat/hisilicon/hikey960/hikey960_el3_spmc_logical_sp.c
new file mode 100644
index 0000000..b9e4f86
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_el3_spmc_logical_sp.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <services/el3_spmc_logical_sp.h>
+#include <services/ffa_svc.h>
+#include <smccc_helpers.h>
+
+#define LP_PARTITION_ID 0xC001
+#define LP_UUID {0x47a3bf57, 0xe98e43ad, 0xb7db524f, 0x1588f4e3}
+
+/* Our Logical SP currently only supports receipt of direct messaging. */
+#define PARTITION_PROPERTIES FFA_PARTITION_DIRECT_REQ_RECV
+
+static int32_t sp_init(void)
+{
+ INFO("LSP: Init function called.\n");
+ return 0;
+}
+
+static uint64_t handle_ffa_direct_request(uint32_t smc_fid, bool secure_origin,
+ uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie,
+ void *handle, uint64_t flags)
+{
+ uint64_t ret;
+
+ /* Determine if we have a 64 or 32 direct request. */
+ if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC32) {
+ ret = FFA_MSG_SEND_DIRECT_RESP_SMC32;
+ } else if (smc_fid == FFA_MSG_SEND_DIRECT_REQ_SMC64) {
+ ret = FFA_MSG_SEND_DIRECT_RESP_SMC64;
+ } else {
+ panic(); /* Unknown SMC. */
+ }
+ /*
+ * Handle the incoming request. For testing purposes we echo the
+ * incoming message.
+ */
+ INFO("Logical Partition: Received Direct Request from %s world!\n",
+ secure_origin ? "Secure" : "Normal");
+
+ /*
+ * Logical SP's must always send a direct response so we can populate
+ * our response directly.
+ */
+ SMC_RET8(handle, ret, 0, 0, x4, 0, 0, 0, 0);
+}
+
+/* Register logical partition */
+DECLARE_LOGICAL_PARTITION(
+ my_logical_partition,
+ sp_init, /* Init Function */
+ LP_PARTITION_ID, /* FF-A Partition ID */
+ LP_UUID, /* UUID */
+ PARTITION_PROPERTIES, /* Partition Properties. */
+ handle_ffa_direct_request /* Callback for direct requests. */
+);
diff --git a/plat/hisilicon/hikey960/hikey960_image_load.c b/plat/hisilicon/hikey960/hikey960_image_load.c
new file mode 100644
index 0000000..9a5b74e
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_image_load.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+
+/*******************************************************************************
+ * ARM helper function to return the list of executable images. Since the default
+ * descriptors are allocated within BL2 RW memory, this prevents BL31/BL32
+ * overlay of BL2 memory. Hence this function also copies the descriptors to a
+ * pre-allocated memory indicated by ARM_BL2_MEM_DESC_BASE.
+ ******************************************************************************/
+struct bl_params *hikey960_get_next_bl_params(void)
+{
+ bl_params_t *next_bl_params;
+
+ next_bl_params = get_next_bl_params_from_mem_params_desc();
+ assert(next_bl_params != NULL);
+
+ populate_next_bl_params_config(next_bl_params);
+
+ return next_bl_params;
+}
+
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return hikey960_get_next_bl_params();
+}
diff --git a/plat/hisilicon/hikey960/hikey960_io_storage.c b/plat/hisilicon/hikey960/hikey960_io_storage.c
new file mode 100644
index 0000000..475e416
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_io_storage.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/ufs.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/partition/partition.h>
+#include <lib/mmio.h>
+#include <lib/semihosting.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "hikey960_def.h"
+#include "hikey960_private.h"
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const io_dev_connector_t *ufs_dev_con, *fip_dev_con;
+static uintptr_t ufs_dev_handle, fip_dev_handle;
+
+static int check_ufs(const uintptr_t spec);
+static int check_fip(const uintptr_t spec);
+size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size);
+size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size);
+
+static io_block_spec_t ufs_fip_spec;
+
+static const io_block_spec_t ufs_gpt_spec = {
+ .offset = 0,
+ .length = PLAT_PARTITION_BLOCK_SIZE *
+ (PLAT_PARTITION_MAX_ENTRIES / 4 + 2),
+};
+
+/* Fastboot serial number stored within first UFS device blocks */
+static const io_block_spec_t ufs_fastboot_spec = {
+ .offset = UFS_BASE,
+ .length = 1 << 20,
+};
+
+static const io_block_dev_spec_t ufs_dev_spec = {
+ /* It's used as temp buffer in block driver. */
+ .buffer = {
+ .offset = HIKEY960_UFS_DATA_BASE,
+ .length = HIKEY960_UFS_DATA_SIZE,
+ },
+ .ops = {
+ .read = ufs_read_lun3_blks,
+ .write = ufs_write_lun3_blks,
+ },
+ .block_size = UFS_BLOCK_SIZE,
+};
+
+static const io_uuid_spec_t scp_bl2_uuid_spec = {
+ .uuid = UUID_SCP_FIRMWARE_SCP_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+#ifdef SPD_spmd
+static const io_uuid_spec_t bl32_tos_fw_spec = {
+ .uuid = UUID_TOS_FW_CONFIG,
+};
+#endif
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &ufs_dev_handle,
+ (uintptr_t)&ufs_fip_spec,
+ check_ufs
+ },
+ [SCP_BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_bl2_uuid_spec,
+ check_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ check_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ check_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ check_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ check_fip
+ },
+
+#ifdef SPD_spmd
+ [TOS_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_tos_fw_spec,
+ check_fip
+ },
+#endif
+
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ check_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ check_fip
+ },
+ [SCP_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [SCP_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_cert_uuid_spec,
+ check_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
+ check_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ check_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ check_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+ [GPT_IMAGE_ID] = {
+ &ufs_dev_handle,
+ (uintptr_t)&ufs_gpt_spec,
+ check_ufs
+ },
+};
+
+static int check_ufs(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_handle;
+
+ result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(ufs_dev_handle, spec, &local_handle);
+ if (result == 0)
+ io_close(local_handle);
+ }
+ return result;
+}
+
+static int check_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+int hikey960_load_serialno(uint64_t *serno)
+{
+ int result;
+ size_t len = 0;
+ uintptr_t local_handle;
+ uint64_t buf[HIKEY960_SERIAL_NUMBER_SIZE / sizeof(uint64_t)];
+
+ if (serno == NULL) {
+ return -1;
+ }
+
+ result = io_dev_init(ufs_dev_handle, (uintptr_t)NULL);
+ if (result != 0) {
+ return result;
+ }
+
+ result = io_open(ufs_dev_handle,
+ (uintptr_t)&ufs_fastboot_spec, &local_handle);
+ if (result != 0) {
+ return result;
+ }
+
+ result = io_seek(local_handle, IO_SEEK_SET,
+ HIKEY960_SERIAL_NUMBER_LBA * UFS_BLOCK_SIZE);
+ if (result != 0) {
+ goto closing;
+ }
+
+ result = io_read(local_handle, (uintptr_t)buf,
+ HIKEY960_SERIAL_NUMBER_SIZE, &len);
+ if (result != 0) {
+ goto closing;
+ }
+
+ if (len != HIKEY960_SERIAL_NUMBER_SIZE) {
+ result = -1;
+ goto closing;
+ }
+
+ /* UEFI fastboot app stores a 16 bytes blob */
+ /* We extract only relevant 8 bytes serial number */
+ *serno = buf[1];
+
+closing:
+ io_close(local_handle);
+ return result;
+}
+
+void hikey960_io_setup(void)
+{
+ int result;
+
+ result = register_io_dev_block(&ufs_dev_con);
+ assert(result == 0);
+
+ result = register_io_dev_fip(&fip_dev_con);
+ assert(result == 0);
+
+ result = io_dev_open(ufs_dev_con, (uintptr_t)&ufs_dev_spec,
+ &ufs_dev_handle);
+ assert(result == 0);
+
+ result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
+ assert(result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)result;
+}
+
+int hikey960_set_fip_addr(unsigned int image_id, const char *name)
+{
+ const partition_entry_t *entry;
+
+ if (ufs_fip_spec.length == 0) {
+ partition_init(GPT_IMAGE_ID);
+ entry = get_partition_entry(name);
+ if (entry == NULL) {
+ ERROR("Could NOT find the %s partition!\n", name);
+ return -ENOENT;
+ }
+ ufs_fip_spec.offset = entry->start;
+ ufs_fip_spec.length = entry->length;
+ }
+ return 0;
+}
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ assert(result == 0);
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ return result;
+}
+
+size_t ufs_read_lun3_blks(int lba, uintptr_t buf, size_t size)
+{
+ return ufs_read_blocks(3, lba, buf, size);
+}
+
+size_t ufs_write_lun3_blks(int lba, const uintptr_t buf, size_t size)
+{
+ return ufs_write_blocks(3, lba, buf, size);
+}
diff --git a/plat/hisilicon/hikey960/hikey960_mcu_load.c b/plat/hisilicon/hikey960/hikey960_mcu_load.c
new file mode 100644
index 0000000..b9ae313
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_mcu_load.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <hi3660.h>
+
+#define ADDR_CONVERT(addr) ((addr) < 0x40000 ? \
+ (addr) + 0xFFF30000 : \
+ (addr) + 0x40000000)
+
+static void fw_data_init(void)
+{
+ unsigned long data_head_addr;
+ unsigned int *data_addr;
+
+ data_head_addr = mmio_read_32((uintptr_t) HISI_DATA_HEAD_BASE) + 0x14;
+ data_addr = (unsigned int *) ADDR_CONVERT(data_head_addr);
+
+ memcpy((void *)HISI_DATA0_BASE,
+ (const void *)(unsigned long)ADDR_CONVERT(data_addr[0]),
+ HISI_DATA0_SIZE);
+ memcpy((void *)HISI_DATA1_BASE,
+ (const void *)(unsigned long)ADDR_CONVERT(data_addr[1]),
+ HISI_DATA1_SIZE);
+}
+
+int load_lpm3(void)
+{
+ INFO("start fw loading\n");
+
+ fw_data_init();
+
+ flush_dcache_range((uintptr_t)HISI_RESERVED_MEM_BASE,
+ HISI_RESERVED_MEM_SIZE);
+
+ sev();
+ sev();
+
+ INFO("fw load success\n");
+
+ return 0;
+}
diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c
new file mode 100644
index 0000000..f836508
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_pm.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/arm/pl061_gpio.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <hi3660.h>
+#include <hi3660_crg.h>
+
+#include "drivers/pwrc/hisi_pwrc.h"
+#include "hikey960_def.h"
+#include "hikey960_private.h"
+
+#define CORE_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+#define DMAC_GLB_REG_SEC 0x694
+#define AXI_CONF_BASE 0x820
+
+static unsigned int uart_base;
+static console_t console;
+static uintptr_t hikey960_sec_entrypoint;
+
+static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
+{
+ unsigned long scr;
+
+ scr = read_scr_el3();
+
+ /* Enable Physical IRQ and FIQ to wake the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+ /* Add barrier before CPU enter WFI state */
+ isb();
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR to the original value, synchronisazion of
+ * scr_el3 is done by eret while el3_exit to save some
+ * execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+static int hikey960_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core = mpidr & MPIDR_CPU_MASK;
+ unsigned int cluster =
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+ int cluster_stat = cluster_is_powered_on(cluster);
+
+ hisi_set_cpu_boot_flag(cluster, core);
+
+ mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
+ hikey960_sec_entrypoint >> 2);
+
+ if (cluster_stat)
+ hisi_powerup_core(cluster, core);
+ else
+ hisi_powerup_cluster(cluster, core);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void
+hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+void hikey960_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int core = mpidr & MPIDR_CPU_MASK;
+ unsigned int cluster =
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ clr_ex();
+ isb();
+ dsbsy();
+
+ gicv2_cpuif_disable();
+
+ hisi_clear_cpu_boot_flag(cluster, core);
+ hisi_powerdn_core(cluster, core);
+
+ /* check if any core is powered up */
+ if (hisi_test_cpu_down(cluster, core)) {
+
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+
+ isb();
+ dsbsy();
+
+ hisi_powerdn_cluster(cluster, core);
+ }
+}
+
+static void __dead2 hikey960_system_off(void)
+{
+ gpio_set_direction(176, GPIO_DIR_OUT);
+ gpio_set_value(176, GPIO_LEVEL_LOW);
+ panic();
+}
+
+static void __dead2 hikey960_system_reset(void)
+{
+ dsb();
+ isb();
+ mdelay(2000);
+ mmio_write_32(SCTRL_SCPEREN1_REG,
+ SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS);
+ mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef);
+ panic();
+}
+
+int hikey960_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's possible to enter standby only on power level 0
+ * Ignore any other power level.
+ */
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] =
+ PLAT_MAX_RET_STATE;
+ } else {
+ for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ PLAT_MAX_OFF_STATE;
+ }
+
+ /*
+ * We expect the 'state id' to be zero.
+ */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
+ return PSCI_E_SUCCESS;
+
+ return PSCI_E_INVALID_ADDRESS;
+}
+
+static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int core = mpidr & MPIDR_CPU_MASK;
+ unsigned int cluster =
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ clr_ex();
+ isb();
+ dsbsy();
+
+ gicv2_cpuif_disable();
+
+ hisi_cpuidle_lock(cluster, core);
+ hisi_set_cpuidle_flag(cluster, core);
+ hisi_cpuidle_unlock(cluster, core);
+
+ mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
+ hikey960_sec_entrypoint >> 2);
+
+ hisi_enter_core_idle(cluster, core);
+ }
+
+ /* Perform the common cluster specific operations */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ hisi_cpuidle_lock(cluster, core);
+ hisi_disable_pdc(cluster);
+
+ /* check if any core is powered up */
+ if (hisi_test_pwrdn_allcores(cluster, core)) {
+
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ isb();
+ dsbsy();
+
+ /* mask the pdc wakeup irq, then
+ * enable pdc to power down the core
+ */
+ hisi_pdc_mask_cluster_wakeirq(cluster);
+ hisi_enable_pdc(cluster);
+
+ hisi_cpuidle_unlock(cluster, core);
+
+ /* check the SR flag bit to determine
+ * CLUSTER_IDLE_IPC or AP_SR_IPC to send
+ */
+ if (hisi_test_ap_suspend_flag())
+ hisi_enter_ap_suspend(cluster, core);
+ else
+ hisi_enter_cluster_idle(cluster, core);
+ } else {
+ /* enable pdc */
+ hisi_enable_pdc(cluster);
+ hisi_cpuidle_unlock(cluster, core);
+ }
+ }
+}
+
+static void hikey960_sr_dma_reinit(void)
+{
+ unsigned int ctr = 0;
+
+ mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3);
+
+ /* 1~15 channel is set non_secure */
+ for (ctr = 1; ctr <= 15; ctr++)
+ mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40),
+ (1 << 6) | (1 << 18));
+}
+
+static void
+hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int core = mpidr & MPIDR_CPU_MASK;
+ unsigned int cluster =
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ /* Nothing to be done on waking up from retention from CPU level */
+ if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ hisi_cpuidle_lock(cluster, core);
+ hisi_clear_cpuidle_flag(cluster, core);
+ hisi_cpuidle_unlock(cluster, core);
+
+ if (hisi_test_ap_suspend_flag()) {
+ hikey960_sr_dma_reinit();
+ gicv2_cpuif_enable();
+ console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+ }
+
+ hikey960_pwr_domain_on_finish(target_state);
+}
+
+static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+static const plat_psci_ops_t hikey960_psci_ops = {
+ .cpu_standby = hikey960_pwr_domain_standby,
+ .pwr_domain_on = hikey960_pwr_domain_on,
+ .pwr_domain_on_finish = hikey960_pwr_domain_on_finish,
+ .pwr_domain_off = hikey960_pwr_domain_off,
+ .pwr_domain_suspend = hikey960_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = hikey960_pwr_domain_suspend_finish,
+ .system_off = hikey960_system_off,
+ .system_reset = hikey960_system_reset,
+ .validate_power_state = hikey960_validate_power_state,
+ .validate_ns_entrypoint = hikey960_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = hikey960_get_sys_suspend_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ unsigned int id = 0;
+ int ret;
+
+ ret = hikey960_read_boardid(&id);
+ if (ret == 0) {
+ if (id == 5300U)
+ uart_base = PL011_UART5_BASE;
+ else
+ uart_base = PL011_UART6_BASE;
+ } else {
+ uart_base = PL011_UART6_BASE;
+ }
+
+ hikey960_sec_entrypoint = sec_entrypoint;
+
+ INFO("%s: sec_entrypoint=0x%lx\n", __func__,
+ (unsigned long)hikey960_sec_entrypoint);
+
+ /*
+ * Initialize PSCI ops struct
+ */
+ *psci_ops = &hikey960_psci_ops;
+ return 0;
+}
diff --git a/plat/hisilicon/hikey960/hikey960_private.h b/plat/hisilicon/hikey960/hikey960_private.h
new file mode 100644
index 0000000..742725c
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_private.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HIKEY960_PRIVATE_H
+#define HIKEY960_PRIVATE_H
+
+#include <common/bl_common.h>
+
+/* Fastboot serial number */
+#define HIKEY960_SERIAL_NUMBER_LBA (UFS_BASE + 20)
+#define HIKEY960_SERIAL_NUMBER_SIZE 16
+
+/*
+ * Function and variable prototypes
+ */
+void hikey960_init_mmu_el1(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+void hikey960_init_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+void hikey960_io_setup(void);
+int hikey960_read_boardid(unsigned int *id);
+int hikey960_set_fip_addr(unsigned int image_id, const char *name);
+int hikey960_load_serialno(uint64_t *serno);
+void hikey960_clk_init(void);
+void hikey960_pmu_init(void);
+void hikey960_regulator_enable(void);
+void hikey960_tzc_init(void);
+void hikey960_peri_init(void);
+void hikey960_pinmux_init(void);
+void hikey960_gpio_init(void);
+void set_retention_ticks(unsigned int val);
+void clr_retention_ticks(unsigned int val);
+void clr_ex(void);
+void nop(void);
+
+/*******************************************************************************
+ * Struct for parameters received from BL2
+ ******************************************************************************/
+typedef struct plat_params_from_bl2 {
+ /* Fastboot serial number gathered from UFS */
+ uint64_t fastboot_serno;
+} plat_params_from_bl2_t;
+
+#endif /* HIKEY960_PRIVATE_H */
diff --git a/plat/hisilicon/hikey960/hikey960_rotpk.S b/plat/hisilicon/hikey960/hikey960_rotpk.S
new file mode 100644
index 0000000..f230ed6
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_rotpk.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global hikey960_rotpk_hash
+ .global hikey960_rotpk_hash_end
+ .section .rodata.hikey960_rotpk_hash, "a"
+hikey960_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+hikey960_rotpk_hash_end:
diff --git a/plat/hisilicon/hikey960/hikey960_tbbr.c b/plat/hisilicon/hikey960/hikey960_tbbr.c
new file mode 100644
index 0000000..ed4da3b
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_tbbr.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char hikey960_rotpk_hash[], hikey960_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = hikey960_rotpk_hash;
+ *key_len = hikey960_rotpk_hash_end - hikey960_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/hisilicon/hikey960/hikey960_topology.c b/plat/hisilicon/hikey960/hikey960_topology.c
new file mode 100644
index 0000000..a242bb1
--- /dev/null
+++ b/plat/hisilicon/hikey960/hikey960_topology.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <lib/psci/psci.h>
+
+/*
+ * The HiKey power domain tree descriptor. The cluster power domains
+ * are arranged so that when the PSCI generic code creates the power
+ * domain tree, the indices of the CPU power domain nodes it allocates
+ * match the linear indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char hikey960_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ 1,
+ /* Number of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+ /* Number of children for the second cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+};
+
+/*******************************************************************************
+ * This function returns the HiKey topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return hikey960_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
+}
diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h
new file mode 100644
index 0000000..17b495f
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/hi3660.h
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef HI3660_H
+#define HI3660_H
+
+#include <hi3660_crg.h>
+#include <hi3660_hkadc.h>
+#include <hi3660_mem_map.h>
+
+#define ASP_CFG_REG_BASE 0xE804E000
+
+#define ASP_CFG_MMBUF_CTRL_REG (ASP_CFG_REG_BASE + 0x148)
+
+#define LP_RAM_BASE 0xFFF50000
+
+#define SCTRL_REG_BASE 0xFFF0A000
+
+#define SCTRL_CONTROL_REG (SCTRL_REG_BASE + 0x000)
+#define SCTRL_CONTROL_SYS_MODE(x) (((x) & 0xf) << 3)
+#define SCTRL_CONTROL_SYS_MODE_NORMAL ((1 << 2) << 3)
+#define SCTRL_CONTROL_SYS_MODE_SLOW ((1 << 1) << 3)
+#define SCTRL_CONTROL_SYS_MODE_MASK (0xf << 3)
+#define SCTRL_CONTROL_MODE_CTRL_NORMAL (1 << 2)
+#define SCTRL_CONTROL_MODE_CTRL_SLOW (1 << 1)
+#define SCTRL_CONTROL_MODE_CTRL_MASK 0x7
+
+#define SCTRL_SCSYSSTAT_REG (SCTRL_REG_BASE + 0x004)
+
+#define SCTRL_DEEPSLEEPED_REG (SCTRL_REG_BASE + 0x008)
+#define SCTRL_EFUSE_USB_MASK (1 << 30)
+#define SCTRL_EFUSE_USB_PLL (1 << 30)
+#define SCTRL_EFUSE_USB_ABB (0 << 30)
+#define SCTRL_EFUSE_UFS_MASK (3 << 6)
+#define SCTRL_EFUSE_UFS_PLL (1 << 6)
+#define SCTRL_EFUSE_UFS_ABB (0 << 6)
+
+#define SCTRL_SCISOEN_REG (SCTRL_REG_BASE + 0x040)
+#define SCTRL_SCISODIS_REG (SCTRL_REG_BASE + 0x044)
+#define SCISO_MMBUFISO (1 << 3)
+
+#define SCTRL_SCPWREN_REG (SCTRL_REG_BASE + 0x060)
+#define SCPWREN_MMBUFPWREN (1 << 3)
+
+#define SCTRL_PLL_CTRL0_REG (SCTRL_REG_BASE + 0x100)
+#define SCTRL_PLL0_POSTDIV2(x) (((x) & 0x7) << 23)
+#define SCTRL_PLL0_POSTDIV1(x) (((x) & 0x7) << 20)
+#define SCTRL_PLL0_FBDIV(x) (((x) & 0xfff) << 8)
+#define SCTRL_PLL0_REFDIV(x) (((x) & 0x3f) << 2)
+#define SCTRL_PLL0_EN (1 << 0)
+
+#define SCTRL_PLL_CTRL1_REG (SCTRL_REG_BASE + 0x104)
+#define SCTRL_PLL0_CLK_NO_GATE (1 << 26)
+#define SCTRL_PLL0_CFG_VLD (1 << 25)
+#define SCTRL_PLL0_FRACDIV(x) ((x) & 0xFFFFFF)
+
+#define SCTRL_PLL_STAT_REG (SCTRL_REG_BASE + 0x10C)
+#define SCTRL_PLL0_STAT (1 << 0)
+
+#define SCTRL_SCPEREN0_REG (SCTRL_REG_BASE + 0x160)
+#define SCTRL_SCPERDIS0_REG (SCTRL_REG_BASE + 0x164)
+#define SCTRL_SCPERSTAT0_REG (SCTRL_REG_BASE + 0x168)
+
+#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170)
+#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174)
+#define SCTRL_SCPEREN1_REG (SCTRL_REG_BASE + 0x170)
+#define SCTRL_SCPERDIS1_REG (SCTRL_REG_BASE + 0x174)
+#define SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS (1u << 31)
+#define SCPEREN_GT_PCLK_MMBUFCFG (1 << 25)
+#define SCPEREN_GT_PCLK_MMBUF (1 << 23)
+#define SCPEREN_GT_ACLK_MMBUF (1 << 22)
+#define SCPEREN_GT_CLK_NOC_AOBUS2MMBUF (1 << 6)
+
+#define SCTRL_SCPEREN2_REG (SCTRL_REG_BASE + 0x190)
+#define SCTRL_SCPERDIS2_REG (SCTRL_REG_BASE + 0x194)
+#define SCTRL_SCPERSTAT2_REG (SCTRL_REG_BASE + 0x198)
+#define SCTRL_SCPERRSTEN0_REG (SCTRL_REG_BASE + 0x200)
+#define SCTRL_SCPERRSTDIS0_REG (SCTRL_REG_BASE + 0x204)
+#define SCTRL_SCPERRSTSTAT0_REG (SCTRL_REG_BASE + 0x208)
+#define SCTRL_SCPERRSTEN1_REG (SCTRL_REG_BASE + 0x20C)
+#define SCTRL_SCPERRSTDIS1_REG (SCTRL_REG_BASE + 0x210)
+#define SCTRL_SCPERRSTSTAT1_REG (SCTRL_REG_BASE + 0x214)
+#define IP_RST_MMBUFCFG (1 << 12)
+#define IP_RST_MMBUF (1 << 11)
+
+#define SCTRL_SCPERRSTEN2_REG (SCTRL_REG_BASE + 0x218)
+#define SCTRL_SCPERRSTDIS2_REG (SCTRL_REG_BASE + 0x21C)
+#define SCTRL_SCPERRSTSTAT2_REG (SCTRL_REG_BASE + 0x220)
+
+#define SCTRL_SCCLKDIV2_REG (SCTRL_REG_BASE + 0x258)
+#define SEL_CLK_MMBUF_MASK (0x3 << 8)
+#define SEL_CLK_MMBUF_PLL0 (0x3 << 8)
+#define SCCLKDIV2_GT_PCLK_MMBUF (1 << 7)
+
+#define SCTRL_SCCLKDIV4_REG (SCTRL_REG_BASE + 0x260)
+#define GT_MMBUF_SYS (1 << 13)
+#define GT_MMBUF_FLL (1 << 12)
+#define GT_PLL_CLK_MMBUF (1 << 11)
+
+#define SCTRL_SCCLKDIV6_REG (SCTRL_REG_BASE + 0x268)
+
+#define SCTRL_SCPERCTRL7_REG (SCTRL_REG_BASE + 0x31C)
+#define SCTRL_SCPERSTAT6_REG (SCTRL_REG_BASE + 0x378)
+
+#define SCTRL_SCINNERSTAT_REG (SCTRL_REG_BASE + 0x3A0)
+#define EMMC_UFS_SEL (1 << 15)
+
+#define SCTRL_BAK_DATA0_REG (SCTRL_REG_BASE + 0x40C)
+#define SCTRL_BAK_DATA4_REG (SCTRL_REG_BASE + 0x41C)
+
+#define SCTRL_LPMCU_CLKEN_REG (SCTRL_REG_BASE + 0x480)
+#define SCTRL_LPMCU_CLKDIS_REG (SCTRL_REG_BASE + 0x484)
+#define SCTRL_LPMCU_RSTEN_REG (SCTRL_REG_BASE + 0x500)
+#define SCTRL_LPMCU_RSTDIS_REG (SCTRL_REG_BASE + 0x504)
+#define DDRC_SOFT_BIT (1 << 6)
+#define DDRC_CLK_BIT (1 << 5)
+
+#define SCTRL_SCPEREN0_SEC_REG (SCTRL_REG_BASE + 0x900)
+#define SCTRL_SCPERDIS0_SEC_REG (SCTRL_REG_BASE + 0x904)
+#define MMBUF_SEC_CTRL_MASK (0xfff << 20)
+#define MMBUF_SEC_CTRL(x) (((x) & 0xfff) << 20)
+
+#define SCTRL_PERRSTEN1_SEC_REG (SCTRL_REG_BASE + 0xA50)
+#define SCTRL_PERRSTDIS1_SEC_REG (SCTRL_REG_BASE + 0xA54)
+#define SCTRL_PERRSTSTAT1_SEC_REG (SCTRL_REG_BASE + 0xA58)
+#define RST_ASP_SUBSYS_BIT (1 << 0)
+
+#define SCTRL_PERRSTEN2_SEC_REG (SCTRL_REG_BASE + 0xB50)
+#define SCTRL_PERRSTDIS2_SEC_REG (SCTRL_REG_BASE + 0xB54)
+#define SCTRL_PERRSTSTAT2_SEC_REG (SCTRL_REG_BASE + 0xB58)
+
+#define SCTRL_HISEECLKDIV_REG (SCTRL_REG_BASE + 0xC28)
+#define SC_SEL_HISEE_PLL_MASK (1 << 4)
+#define SC_SEL_HISEE_PLL0 (1 << 4)
+#define SC_SEL_HISEE_PLL2 (0 << 4)
+#define SC_DIV_HISEE_PLL_MASK (7 << 16)
+#define SC_DIV_HISEE_PLL(x) ((x) & 0x7)
+
+#define SCTRL_SCSOCID0_REG (SCTRL_REG_BASE + 0xE00)
+
+#define PMC_REG_BASE 0xFFF31000
+#define PMC_PPLL1_CTRL0_REG (PMC_REG_BASE + 0x038)
+#define PMC_PPLL1_CTRL1_REG (PMC_REG_BASE + 0x03C)
+#define PMC_PPLL2_CTRL0_REG (PMC_REG_BASE + 0x040)
+#define PMC_PPLL2_CTRL1_REG (PMC_REG_BASE + 0x044)
+#define PMC_PPLL3_CTRL0_REG (PMC_REG_BASE + 0x048)
+#define PMC_PPLL3_CTRL1_REG (PMC_REG_BASE + 0x04C)
+#define PPLLx_LOCK (1 << 26)
+#define PPLLx_WITHOUT_CLK_GATE (1 << 26)
+#define PPLLx_CFG_VLD (1 << 25)
+#define PPLLx_INT_MOD (1 << 24)
+#define PPLLx_POSTDIV2_MASK (0x7 << 23)
+#define PPLLx_POSTDIV2(x) (((x) & 0x7) << 23)
+#define PPLLx_POSTDIV1_MASK (0x7 << 20)
+#define PPLLx_POSTDIV1(x) (((x) & 0x7) << 20)
+#define PPLLx_FRACDIV_MASK (0x00FFFFFF)
+#define PPLLx_FRACDIV(x) ((x) & 0x00FFFFFF)
+#define PPLLx_FBDIV_MASK (0xfff << 8)
+#define PPLLx_FBDIV(x) (((x) & 0xfff) << 8)
+#define PPLLx_REFDIV_MASK (0x3f << 2)
+#define PPLLx_REFDIV(x) (((x) & 0x3f) << 2)
+#define PPLLx_BP (1 << 1)
+#define PPLLx_EN (1 << 0)
+
+#define PMC_DDRLP_CTRL_REG (PMC_REG_BASE + 0x30C)
+#define DDRC_CSYSREQ_CFG(x) ((x) & 0xF)
+
+#define PMC_NOC_POWER_IDLEREQ_REG (PMC_REG_BASE + 0x380)
+#define PMC_NOC_POWER_IDLEREQ_IVP (1 << 14)
+#define PMC_NOC_POWER_IDLEREQ_DSS (1 << 13)
+#define PMC_NOC_POWER_IDLEREQ_VENC (1 << 11)
+#define PMC_NOC_POWER_IDLEREQ_VDEC (1 << 10)
+#define PMC_NOC_POWER_IDLEREQ_ISP (1 << 5)
+#define PMC_NOC_POWER_IDLEREQ_VCODEC (1 << 4)
+#define DDRPHY_BYPASS_MODE (1 << 0)
+
+#define PMC_NOC_POWER_IDLEACK_REG (PMC_REG_BASE + 0x384)
+#define PMC_NOC_POWER_IDLE_REG (PMC_REG_BASE + 0x388)
+
+#define PMU_SSI0_REG_BASE 0xFFF34000
+
+#define PMU_SSI0_LDO8_CTRL0_REG (PMU_SSI0_REG_BASE + (0x68 << 2))
+#define LDO8_CTRL0_EN_1_8V 0x02
+
+#define PMU_SSI0_CLK_TOP_CTRL7_REG (PMU_SSI0_REG_BASE + (0x10C << 2))
+#define NP_XO_ABB_DIG (1 << 1)
+
+#define LP_CONFIG_REG_BASE 0xFFF3F000
+
+#define DMAC_BASE 0xFDF30000
+
+#define CCI400_REG_BASE 0xE8100000
+#define CCI400_SL_IFACE3_CLUSTER_IX 0
+#define CCI400_SL_IFACE4_CLUSTER_IX 1
+
+#define GICD_REG_BASE 0xE82B1000
+#define GICC_REG_BASE 0xE82B2000
+/*
+ * GIC400 interrupt handling related constants
+ */
+#define IRQ_SEC_PHY_TIMER 29
+#define IRQ_SEC_SGI_0 8
+#define IRQ_SEC_SGI_1 9
+#define IRQ_SEC_SGI_2 10
+#define IRQ_SEC_SGI_3 11
+#define IRQ_SEC_SGI_4 12
+#define IRQ_SEC_SGI_5 13
+#define IRQ_SEC_SGI_6 14
+#define IRQ_SEC_SGI_7 15
+#define IRQ_SEC_SGI_8 16
+
+#define IPC_REG_BASE 0xE896A000
+#define IPC_BASE (IPC_REG_BASE)
+
+#define IOMG_REG_BASE 0xE896C000
+
+/* GPIO46: HUB 3.3V enable. active low */
+#define IOMG_044_REG (IOMG_REG_BASE + 0x0B0)
+#define IOMG_UART5_RX_REG (IOMG_REG_BASE + 0x0BC)
+#define IOMG_UART5_TX_REG (IOMG_REG_BASE + 0x0C0)
+
+#define IOCG_REG_BASE 0xE896C800
+
+/* GPIO005: PMIC SSI. (2 << 4) */
+#define IOCG_006_REG (IOCG_REG_BASE + 0x018)
+
+#define TIMER9_REG_BASE 0xE8A00000
+
+#define WDT0_REG_BASE 0xE8A06000
+#define WDT1_REG_BASE 0xE8A07000
+#define WDT_CONTROL_OFFSET 0x008
+#define WDT_LOCK_OFFSET 0xC00
+
+#define WDT_UNLOCK 0x1ACCE551
+#define WDT_LOCKED 1
+
+#define PCTRL_REG_BASE 0xE8A09000
+#define PCTRL_PERI_CTRL3_REG (PCTRL_REG_BASE + 0x010)
+#define PCTRL_PERI_CTRL24_REG (PCTRL_REG_BASE + 0x064)
+
+#define GPIO0_BASE UL(0xE8A0B000)
+#define GPIO1_BASE UL(0xE8A0C000)
+#define GPIO2_BASE UL(0xE8A0D000)
+#define GPIO3_BASE UL(0xE8A0E000)
+#define GPIO4_BASE UL(0xE8A0F000)
+#define GPIO5_BASE UL(0xE8A10000)
+#define GPIO6_BASE UL(0xE8A11000)
+#define GPIO7_BASE UL(0xE8A12000)
+#define GPIO8_BASE UL(0xE8A13000)
+#define GPIO9_BASE UL(0xE8A14000)
+#define GPIO10_BASE UL(0xE8A15000)
+#define GPIO11_BASE UL(0xE8A16000)
+#define GPIO12_BASE UL(0xE8A17000)
+#define GPIO13_BASE UL(0xE8A18000)
+#define GPIO14_BASE UL(0xE8A19000)
+#define GPIO15_BASE UL(0xE8A1A000)
+#define GPIO16_BASE UL(0xE8A1B000)
+#define GPIO17_BASE UL(0xE8A1C000)
+#define GPIO20_BASE UL(0xE8A1F000)
+#define GPIO21_BASE UL(0xE8A20000)
+#define GPIO22_BASE UL(0xFFF0B000)
+#define GPIO23_BASE UL(0xFFF0C000)
+#define GPIO24_BASE UL(0xFFF0D000)
+#define GPIO25_BASE UL(0xFFF0E000)
+#define GPIO26_BASE UL(0xFFF0F000)
+#define GPIO27_BASE UL(0xFFF10000)
+#define GPIO28_BASE UL(0xFFF1D000)
+
+#define TZC_REG_BASE 0xE8A21000
+#define TZC_STAT0_REG (TZC_REG_BASE + 0x800)
+#define TZC_EN0_REG (TZC_REG_BASE + 0x804)
+#define TZC_DIS0_REG (TZC_REG_BASE + 0x808)
+#define TZC_STAT1_REG (TZC_REG_BASE + 0x80C)
+#define TZC_EN1_REG (TZC_REG_BASE + 0x810)
+#define TZC_DIS1_REG (TZC_REG_BASE + 0x814)
+#define TZC_STAT2_REG (TZC_REG_BASE + 0x818)
+#define TZC_EN2_REG (TZC_REG_BASE + 0x81C)
+#define TZC_DIS2_REG (TZC_REG_BASE + 0x820)
+#define TZC_STAT3_REG (TZC_REG_BASE + 0x824)
+#define TZC_EN3_REG (TZC_REG_BASE + 0x828)
+#define TZC_DIS3_REG (TZC_REG_BASE + 0x82C)
+#define TZC_STAT4_REG (TZC_REG_BASE + 0x830)
+#define TZC_EN4_REG (TZC_REG_BASE + 0x834)
+#define TZC_DIS4_REG (TZC_REG_BASE + 0x838)
+#define TZC_STAT5_REG (TZC_REG_BASE + 0x83C)
+#define TZC_EN5_REG (TZC_REG_BASE + 0x840)
+#define TZC_DIS5_REG (TZC_REG_BASE + 0x844)
+#define TZC_STAT6_REG (TZC_REG_BASE + 0x848)
+#define TZC_EN6_REG (TZC_REG_BASE + 0x84C)
+#define TZC_DIS6_REG (TZC_REG_BASE + 0x850)
+#define TZC_STAT7_REG (TZC_REG_BASE + 0x854)
+#define TZC_EN7_REG (TZC_REG_BASE + 0x858)
+#define TZC_DIS7_REG (TZC_REG_BASE + 0x85C)
+#define TZC_STAT8_REG (TZC_REG_BASE + 0x860)
+#define TZC_EN8_REG (TZC_REG_BASE + 0x864)
+#define TZC_DIS8_REG (TZC_REG_BASE + 0x868)
+
+#define MMBUF_BASE 0xEA800000
+
+#define ACPU_DMCPACK0_BASE 0xEA900000
+
+#define ACPU_DMCPACK1_BASE 0xEA920000
+
+#define ACPU_DMCPACK2_BASE 0xEA940000
+
+#define ACPU_DMCPACK3_BASE 0xEA960000
+
+#define UART5_REG_BASE 0xFDF05000
+
+#define USB3OTG_REG_BASE 0xFF100000
+
+#define UFS_REG_BASE 0xFF3B0000
+
+#define UFS_SYS_REG_BASE 0xFF3B1000
+
+#define UFS_SYS_PSW_POWER_CTRL_REG (UFS_SYS_REG_BASE + 0x004)
+#define UFS_SYS_PHY_ISO_EN_REG (UFS_SYS_REG_BASE + 0x008)
+#define UFS_SYS_HC_LP_CTRL_REG (UFS_SYS_REG_BASE + 0x00C)
+#define UFS_SYS_PHY_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x010)
+#define UFS_SYS_PSW_CLK_CTRL_REG (UFS_SYS_REG_BASE + 0x014)
+#define UFS_SYS_CLOCK_GATE_BYPASS_REG (UFS_SYS_REG_BASE + 0x018)
+#define UFS_SYS_RESET_CTRL_EN_REG (UFS_SYS_REG_BASE + 0x01C)
+#define UFS_SYS_MONITOR_HH_REG (UFS_SYS_REG_BASE + 0x03C)
+#define UFS_SYS_UFS_SYSCTRL_REG (UFS_SYS_REG_BASE + 0x05C)
+#define UFS_SYS_UFS_DEVICE_RESET_CTRL_REG (UFS_SYS_REG_BASE + 0x060)
+#define UFS_SYS_UFS_APB_ADDR_MASK_REG (UFS_SYS_REG_BASE + 0x064)
+
+#define BIT_UFS_PSW_ISO_CTRL (1 << 16)
+#define BIT_UFS_PSW_MTCMOS_EN (1 << 0)
+#define BIT_UFS_REFCLK_ISO_EN (1 << 16)
+#define BIT_UFS_PHY_ISO_CTRL (1 << 0)
+#define BIT_SYSCTRL_LP_ISOL_EN (1 << 16)
+#define BIT_SYSCTRL_PWR_READY (1 << 8)
+#define BIT_SYSCTRL_REF_CLOCK_EN (1 << 24)
+#define MASK_SYSCTRL_REF_CLOCK_SEL (3 << 8)
+#define MASK_SYSCTRL_CFG_CLOCK_FREQ (0xFF)
+#define BIT_SYSCTRL_PSW_CLK_EN (1 << 4)
+#define MASK_UFS_CLK_GATE_BYPASS (0x3F)
+#define BIT_SYSCTRL_LP_RESET_N (1 << 0)
+#define BIT_UFS_REFCLK_SRC_SE1 (1 << 0)
+#define MASK_UFS_SYSCTRL_BYPASS (0x3F << 16)
+#define MASK_UFS_DEVICE_RESET (1 << 16)
+#define BIT_UFS_DEVICE_RESET (1 << 0)
+
+#define GPIO18_BASE UL(0xFF3B4000)
+#define GPIO19_BASE UL(0xFF3B5000)
+
+#define IOMG_FIX_REG_BASE 0xFF3B6000
+
+/* GPIO150: LED */
+#define IOMG_FIX_006_REG (IOMG_FIX_REG_BASE + 0x018)
+/* GPIO151: LED */
+#define IOMG_FIX_007_REG (IOMG_FIX_REG_BASE + 0x01C)
+
+#define IOMG_AO_REG_BASE 0xFFF11000
+
+/* GPIO189: LED */
+#define IOMG_AO_011_REG (IOMG_AO_REG_BASE + 0x02C)
+/* GPIO190: LED */
+#define IOMG_AO_012_REG (IOMG_AO_REG_BASE + 0x030)
+/* GPIO202: type C enable. active low */
+#define IOMG_AO_023_REG (IOMG_AO_REG_BASE + 0x05C)
+/* GPIO206: USB switch. active low */
+#define IOMG_AO_026_REG (IOMG_AO_REG_BASE + 0x068)
+/* GPIO219: PD interrupt. pull up */
+#define IOMG_AO_039_REG (IOMG_AO_REG_BASE + 0x09C)
+/* GPIO213: PCIE_CLKREQ_N */
+#define IOMG_AO_033_REG (IOMG_AO_REG_BASE + 0x084)
+
+#define IOCG_AO_REG_BASE 0xFFF1187C
+/* GPIO219: PD interrupt. pull up */
+#define IOCG_AO_043_REG (IOCG_AO_REG_BASE + 0x030)
+
+#define EDMAC_BASE 0xfdf30000
+#define EDMAC_SEC_CTRL (EDMAC_BASE + 0x694)
+#define EDMAC_AXI_CONF(x) (EDMAC_BASE + 0x820 + (x << 6))
+#define EDMAC_SEC_CTRL_INTR_SEC (1 << 1)
+#define EDMAC_SEC_CTRL_GLOBAL_SEC (1 << 0)
+#define EDMAC_CHANNEL_NUMS 16
+
+#define IOMCU_DMAC_BASE 0xffd77000
+#define IOMCU_DMAC_SEC_CTRL (IOMCU_DMAC_BASE + 0x694)
+#define IOMCU_DMAC_AXI_CONF(x) (IOMCU_DMAC_BASE + 0x820 + ((x) << 6))
+#define IOMCU_DMAC_AXI_CONF_ARPROT_NS (1 << 6)
+#define IOMCU_DMAC_AXI_CONF_AWPROT_NS (1 << 18)
+#define IOMCU_DMAC_SEC_CTRL_INTR_SEC (1 << 1)
+#define IOMCU_DMAC_SEC_CTRL_GLOBAL_SEC (1 << 0)
+#define IOMCU_DMAC_CHANNEL_NUMS 8
+
+#endif /* HI3660_H */
diff --git a/plat/hisilicon/hikey960/include/hi3660_crg.h b/plat/hisilicon/hikey960/include/hi3660_crg.h
new file mode 100644
index 0000000..eb5a6c5
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/hi3660_crg.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef HI3660_CRG_H
+#define HI3660_CRG_H
+
+#define CRG_REG_BASE 0xFFF35000
+
+#define CRG_PEREN0_REG (CRG_REG_BASE + 0x000)
+#define CRG_PERDIS0_REG (CRG_REG_BASE + 0x004)
+#define CRG_PERSTAT0_REG (CRG_REG_BASE + 0x008)
+#define PEREN0_GT_CLK_AOMM (1U << 31)
+
+#define CRG_PEREN1_REG (CRG_REG_BASE + 0x010)
+#define CRG_PERDIS1_REG (CRG_REG_BASE + 0x014)
+#define CRG_PERSTAT1_REG (CRG_REG_BASE + 0x018)
+#define CRG_PEREN2_REG (CRG_REG_BASE + 0x020)
+#define CRG_PERDIS2_REG (CRG_REG_BASE + 0x024)
+#define CRG_PERSTAT2_REG (CRG_REG_BASE + 0x028)
+#define PEREN2_HKADCSSI (1 << 24)
+
+#define CRG_PEREN3_REG (CRG_REG_BASE + 0x030)
+#define CRG_PERDIS3_REG (CRG_REG_BASE + 0x034)
+
+#define CRG_PEREN4_REG (CRG_REG_BASE + 0x040)
+#define CRG_PERDIS4_REG (CRG_REG_BASE + 0x044)
+#define CRG_PERCLKEN4_REG (CRG_REG_BASE + 0x048)
+#define CRG_PERSTAT4_REG (CRG_REG_BASE + 0x04C)
+#define GT_ACLK_USB3OTG (1 << 1)
+#define GT_CLK_USB3OTG_REF (1 << 0)
+
+#define CRG_PEREN5_REG (CRG_REG_BASE + 0x050)
+#define CRG_PERDIS5_REG (CRG_REG_BASE + 0x054)
+#define CRG_PERSTAT5_REG (CRG_REG_BASE + 0x058)
+#define CRG_PERRSTEN0_REG (CRG_REG_BASE + 0x060)
+#define CRG_PERRSTDIS0_REG (CRG_REG_BASE + 0x064)
+#define CRG_PERRSTSTAT0_REG (CRG_REG_BASE + 0x068)
+#define CRG_PERRSTEN1_REG (CRG_REG_BASE + 0x06C)
+#define CRG_PERRSTDIS1_REG (CRG_REG_BASE + 0x070)
+#define CRG_PERRSTSTAT1_REG (CRG_REG_BASE + 0x074)
+#define CRG_PERRSTEN2_REG (CRG_REG_BASE + 0x078)
+#define CRG_PERRSTDIS2_REG (CRG_REG_BASE + 0x07C)
+#define CRG_PERRSTSTAT2_REG (CRG_REG_BASE + 0x080)
+#define PERRSTEN2_HKADCSSI (1 << 24)
+
+#define CRG_PERRSTEN3_REG (CRG_REG_BASE + 0x084)
+#define CRG_PERRSTDIS3_REG (CRG_REG_BASE + 0x088)
+#define CRG_PERRSTSTAT3_REG (CRG_REG_BASE + 0x08C)
+#define CRG_PERRSTEN4_REG (CRG_REG_BASE + 0x090)
+#define CRG_PERRSTDIS4_REG (CRG_REG_BASE + 0x094)
+#define CRG_PERRSTSTAT4_REG (CRG_REG_BASE + 0x098)
+#define IP_RST_USB3OTG_MUX (1 << 8)
+#define IP_RST_USB3OTG_AHBIF (1 << 7)
+#define IP_RST_USB3OTG_32K (1 << 6)
+#define IP_RST_USB3OTG (1 << 5)
+#define IP_RST_USB3OTGPHY_POR (1 << 3)
+
+#define CRG_PERRSTEN5_REG (CRG_REG_BASE + 0x09C)
+#define CRG_PERRSTDIS5_REG (CRG_REG_BASE + 0x0A0)
+#define CRG_PERRSTSTAT5_REG (CRG_REG_BASE + 0x0A4)
+
+/* bit fields in CRG_PERI */
+#define PERI_PCLK_PCTRL_BIT (1U << 31)
+#define PERI_TIMER12_BIT (1 << 25)
+#define PERI_TIMER11_BIT (1 << 24)
+#define PERI_TIMER10_BIT (1 << 23)
+#define PERI_TIMER9_BIT (1 << 22)
+#define PERI_UART5_BIT (1 << 15)
+#define PERI_UFS_BIT (1 << 12)
+#define PERI_ARST_UFS_BIT (1 << 7)
+#define PERI_PPLL2_EN_CPU (1 << 3)
+#define PERI_PWM_BIT (1 << 0)
+#define PERI_DDRC_BIT (1 << 0)
+#define PERI_DDRC_D_BIT (1 << 4)
+#define PERI_DDRC_C_BIT (1 << 3)
+#define PERI_DDRC_B_BIT (1 << 2)
+#define PERI_DDRC_A_BIT (1 << 1)
+#define PERI_DDRC_DMUX_BIT (1 << 0)
+
+#define CRG_CLKDIV0_REG (CRG_REG_BASE + 0x0A0)
+#define SC_DIV_LPMCU_MASK ((0x1F << 5) << 16)
+#define SC_DIV_LPMCU(x) (((x) & 0x1F) << 5)
+
+#define CRG_CLKDIV1_REG (CRG_REG_BASE + 0x0B0)
+#define SEL_LPMCU_PLL_MASK ((1 << 1) << 16)
+#define SEL_SYSBUS_MASK ((1 << 0) << 16)
+#define SEL_LPMCU_PLL1 (1 << 1)
+#define SEL_LPMCU_PLL0 (0 << 1)
+#define SEL_SYSBUS_PLL0 (1 << 0)
+#define SEL_SYSBUS_PLL1 (0 << 0)
+
+#define CRG_CLKDIV3_REG (CRG_REG_BASE + 0x0B4)
+#define CRG_CLKDIV5_REG (CRG_REG_BASE + 0x0BC)
+#define CRG_CLKDIV8_REG (CRG_REG_BASE + 0x0C8)
+
+#define CRG_CLKDIV12_REG (CRG_REG_BASE + 0x0D8)
+#define SC_DIV_A53HPM_MASK (0x7 << 13)
+#define SC_DIV_A53HPM(x) (((x) & 0x7) << 13)
+
+#define CRG_CLKDIV16_REG (CRG_REG_BASE + 0x0E8)
+#define DDRC_CLK_SW_REQ_CFG_MASK (0x3 << 12)
+#define DDRC_CLK_SW_REQ_CFG(x) (((x) & 0x3) << 12)
+#define SC_DIV_UFSPHY_CFG_MASK (0x3 << 9)
+#define SC_DIV_UFSPHY_CFG(x) (((x) & 0x3) << 9)
+#define DDRCPLL_SW (1 << 8)
+
+#define CRG_CLKDIV17_REG (CRG_REG_BASE + 0x0EC)
+#define SC_DIV_UFS_PERIBUS (1 << 14)
+
+#define CRG_CLKDIV18_REG (CRG_REG_BASE + 0x0F0)
+#define CRG_CLKDIV19_REG (CRG_REG_BASE + 0x0F4)
+#define CRG_CLKDIV20_REG (CRG_REG_BASE + 0x0F8)
+#define CLKDIV20_GT_CLK_AOMM (1 << 3)
+
+#define CRG_CLKDIV22_REG (CRG_REG_BASE + 0x100)
+#define SEL_PLL_320M_MASK (1 << 16)
+#define SEL_PLL2_320M (1 << 0)
+#define SEL_PLL0_320M (0 << 0)
+
+#define CRG_CLKDIV23_REG (CRG_REG_BASE + 0x104)
+#define PERI_DDRC_SW_BIT (1 << 13)
+#define DIV_CLK_DDRSYS_MASK (0x3 << 10)
+#define DIV_CLK_DDRSYS(x) (((x) & 0x3) << 10)
+#define GET_DIV_CLK_DDRSYS(x) (((x) & DIV_CLK_DDRSYS_MASK) >> 10)
+#define DIV_CLK_DDRCFG_MASK (0x6 << 5)
+#define DIV_CLK_DDRCFG(x) (((x) & 0x6) << 5)
+#define GET_DIV_CLK_DDRCFG(x) (((x) & DIV_CLK_DDRCFG_MASK) >> 5)
+#define DIV_CLK_DDRC_MASK 0x1F
+#define DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK)
+#define GET_DIV_CLK_DDRC(x) ((x) & DIV_CLK_DDRC_MASK)
+
+#define CRG_CLKDIV25_REG (CRG_REG_BASE + 0x10C)
+#define DIV_SYSBUS_PLL_MASK (0xF << 16)
+#define DIV_SYSBUS_PLL(x) ((x) & 0xF)
+
+#define CRG_PERI_CTRL2_REG (CRG_REG_BASE + 0x128)
+#define PERI_TIME_STAMP_CLK_MASK (0x7 << 28)
+#define PERI_TIME_STAMP_CLK_DIV(x) (((x) & 0x7) << 22)
+
+#define CRG_ISODIS_REG (CRG_REG_BASE + 0x148)
+#define CRG_PERPWREN_REG (CRG_REG_BASE + 0x150)
+
+#define CRG_PEREN7_REG (CRG_REG_BASE + 0x420)
+#define CRG_PERDIS7_REG (CRG_REG_BASE + 0x424)
+#define CRG_PERSTAT7_REG (CRG_REG_BASE + 0x428)
+#define GT_CLK_UFSPHY_CFG (1 << 14)
+
+#define CRG_PEREN8_REG (CRG_REG_BASE + 0x430)
+#define CRG_PERDIS8_REG (CRG_REG_BASE + 0x434)
+#define CRG_PERSTAT8_REG (CRG_REG_BASE + 0x438)
+#define PERI_DMC_D_BIT (1 << 22)
+#define PERI_DMC_C_BIT (1 << 21)
+#define PERI_DMC_B_BIT (1 << 20)
+#define PERI_DMC_A_BIT (1 << 19)
+#define PERI_DMC_BIT (1 << 18)
+
+#define CRG_PEREN11_REG (CRG_REG_BASE + 0x460)
+#define PPLL1_GATE_CPU (1 << 18)
+
+#define CRG_PERSTAT11_REG (CRG_REG_BASE + 0x46C)
+#define PPLL3_EN_STAT (1 << 21)
+#define PPLL2_EN_STAT (1 << 20)
+#define PPLL1_EN_STAT (1 << 19)
+
+#define CRG_IVP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC04)
+#define CRG_ISP_SEC_RSTDIS_REG (CRG_REG_BASE + 0xC84)
+
+#define CRG_RVBAR(c, n) (0xE00 + (0x10 * c) + (0x4 * n))
+#define CRG_GENERAL_SEC_RSTEN_REG (CRG_REG_BASE + 0xE20)
+#define CRG_GENERAL_SEC_RSTDIS_REG (CRG_REG_BASE + 0xE24)
+#define IP_RST_GPIO0_SEC (1 << 2)
+
+#define CRG_GENERAL_SEC_CLKDIV0_REG (CRG_REG_BASE + 0xE90)
+#define SC_DIV_AO_HISE_MASK 3
+#define SC_DIV_AO_HISE(x) ((x) & 0x3)
+
+#endif /* HI3660_CRG_H */
diff --git a/plat/hisilicon/hikey960/include/hi3660_hkadc.h b/plat/hisilicon/hikey960/include/hi3660_hkadc.h
new file mode 100644
index 0000000..dc9e813
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/hi3660_hkadc.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef HI3660_HKADC_H
+#define HI3660_HKADC_H
+
+#define HKADC_SSI_REG_BASE 0xE82B8000
+
+#define HKADC_DSP_START_REG (HKADC_SSI_REG_BASE + 0x000)
+#define HKADC_WR_NUM_REG (HKADC_SSI_REG_BASE + 0x008)
+#define HKADC_DSP_START_CLR_REG (HKADC_SSI_REG_BASE + 0x01C)
+#define HKADC_WR01_DATA_REG (HKADC_SSI_REG_BASE + 0x020)
+
+#define WR1_WRITE_MODE (1U << 31)
+#define WR1_READ_MODE (0 << 31)
+#define WR1_ADDR(x) (((x) & 0x7F) << 24)
+#define WR1_DATA(x) (((x) & 0xFF) << 16)
+#define WR0_WRITE_MODE (1 << 15)
+#define WR0_READ_MODE (0 << 15)
+#define WR0_ADDR(x) (((x) & 0x7F) << 8)
+#define WR0_DATA(x) ((x) & 0xFF)
+
+#define HKADC_WR23_DATA_REG (HKADC_SSI_REG_BASE + 0x024)
+#define HKADC_WR45_DATA_REG (HKADC_SSI_REG_BASE + 0x028)
+#define HKADC_DELAY01_REG (HKADC_SSI_REG_BASE + 0x030)
+#define HKADC_DELAY23_REG (HKADC_SSI_REG_BASE + 0x034)
+#define HKADC_DELAY45_REG (HKADC_SSI_REG_BASE + 0x038)
+#define HKADC_DSP_RD2_DATA_REG (HKADC_SSI_REG_BASE + 0x048)
+#define HKADC_DSP_RD3_DATA_REG (HKADC_SSI_REG_BASE + 0x04C)
+
+/* HKADC Internal Registers */
+#define HKADC_CTRL_ADDR 0x00
+#define HKADC_START_ADDR 0x01
+#define HKADC_DATA1_ADDR 0x03 /* high 8 bits */
+#define HKADC_DATA0_ADDR 0x04 /* low 8 bits */
+#define HKADC_MODE_CFG 0x0A
+
+#define HKADC_VALUE_HIGH 0x0FF0
+#define HKADC_VALUE_LOW 0x000F
+#define HKADC_VALID_VALUE 0x0FFF
+
+#define HKADC_CHANNEL_MAX 15
+#define HKADC_VREF_1V8 1800
+#define HKADC_ACCURACY 0x0FFF
+
+#define HKADC_WR01_VALUE ((HKADC_START_ADDR << 24) | \
+ (0x1 << 16))
+#define HKADC_WR23_VALUE ((0x1u << 31) | \
+ (HKADC_DATA0_ADDR << 24) | \
+ (1 << 15) | \
+ (HKADC_DATA1_ADDR << 8))
+#define HKADC_WR45_VALUE (0x80)
+#define HKADC_CHANNEL0_DELAY01_VALUE ((0x0700 << 16) | 0xFFFF)
+#define HKADC_DELAY01_VALUE ((0x0700 << 16) | 0x0200)
+#define HKADC_DELAY23_VALUE ((0x00C8 << 16) | 0x00C8)
+#define START_DELAY_TIMEOUT 2000
+#define HKADC_WR_NUM_VALUE 4
+
+#endif /* HI3660_HKADC_H */
diff --git a/plat/hisilicon/hikey960/include/hi3660_mem_map.h b/plat/hisilicon/hikey960/include/hi3660_mem_map.h
new file mode 100644
index 0000000..cadc4a4
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/hi3660_mem_map.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI3660_MEM_MAP_H
+#define HI3660_MEM_MAP_H
+
+#define HISI_DATA_HEAD_BASE (0x89C44400)
+
+#define HISI_RESERVED_MEM_BASE (0x89C80000)
+#define HISI_RESERVED_MEM_SIZE (0x00040000)
+
+#define HISI_DATA0_BASE (0x89C96180)
+#define HISI_DATA0_SIZE (0x000003A0)
+#define HISI_DATA1_BASE (0x89C93480)
+#define HISI_DATA1_SIZE (0x00002D00)
+
+#endif /* HI3660_MEM_MAP_H */
diff --git a/plat/hisilicon/hikey960/include/hisi_ipc.h b/plat/hisilicon/hikey960/include/hisi_ipc.h
new file mode 100644
index 0000000..6a97968
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/hisi_ipc.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HISI_IPC_H
+#define HISI_IPC_H
+
+enum pm_mode {
+ PM_ON = 0,
+ PM_OFF,
+};
+
+void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster,
+ enum pm_mode mode);
+void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster,
+ unsigned int affinity_level);
+void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster);
+void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster,
+ unsigned int cmd_id);
+int hisi_ipc_init(void);
+
+#endif /* HISI_IPC_H */
diff --git a/plat/hisilicon/hikey960/include/plat.ld.S b/plat/hisilicon/hikey960/include/plat.ld.S
new file mode 100644
index 0000000..0cc25cd
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/plat.ld.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_LD_S
+#define PLAT_LD_S
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+MEMORY {
+ RAM2 (rw): ORIGIN = DDR2_SEC_BASE, LENGTH = DDR2_SEC_SIZE
+}
+
+SECTIONS
+{
+ ram2_region (NOLOAD) : {
+ *(ram2_region)
+ }>RAM2
+}
+
+#endif /* PLAT_LD_S */
diff --git a/plat/hisilicon/hikey960/include/plat_macros.S b/plat/hisilicon/hikey960/include/plat_macros.S
new file mode 100644
index 0000000..8765562
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/plat_macros.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <hi3660.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+/* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+ mov_imm x16, GICD_REG_BASE
+ mov_imm x17, GICC_REG_BASE
+
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to cosole */
+ bl str_in_crash_buf_print
+
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+2:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq 1f
+ bl asm_print_hex
+ adr x4, spacer
+ bl asm_print_str
+ ldr x4, [x7], #8
+ bl asm_print_hex
+ adr x4, newline
+ bl asm_print_str
+ b 2b
+1:
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \
+ CCI400_SL_IFACE3_CLUSTER_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (CCI400_REG_BASE + SLAVE_IFACE_OFFSET( \
+ CCI400_SL_IFACE4_CLUSTER_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h
new file mode 100644
index 0000000..10eff01
--- /dev/null
+++ b/plat/hisilicon/hikey960/include/platform_def.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "../hikey960_def.h"
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define HIKEY960_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+/*
+ * Generic platform constants
+ */
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE 0x1000
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_CACHE_LINE_SIZE 64
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CORE_COUNT_PER_CLUSTER U(4)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
+ PLATFORM_CORE_COUNT_PER_CLUSTER)
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ PLATFORM_CLUSTER_COUNT + 1)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+/* UFS RPMB and UFS User Data */
+#define MAX_IO_BLOCK_DEVICES U(2)
+
+
+/*
+ * Platform memory map related constants
+ */
+
+/*
+ * BL1 specific defines.
+ */
+#define BL1_RO_BASE (0x1AC00000)
+#define BL1_RO_LIMIT (BL1_RO_BASE + 0x20000)
+#define BL1_RW_BASE (BL1_RO_LIMIT) /* 1AC2_0000 */
+#define BL1_RW_SIZE (0x00188000)
+#define BL1_RW_LIMIT (0x1B000000)
+
+/*
+ * BL2 specific defines.
+ */
+#define BL2_BASE (0x1AC00000)
+#define BL2_LIMIT (BL2_BASE + 0x58000) /* 1AC5_8000 */
+
+/*
+ * BL31 specific defines.
+ */
+#define BL31_BASE (BL2_LIMIT) /* 1AC5_8000 */
+#define BL31_LIMIT (BL31_BASE + 0x40000) /* 1AC9_8000 */
+
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM.
+ */
+#define BL32_DRAM_BASE DDR_SEC_BASE
+#define BL32_DRAM_LIMIT (DDR_SEC_BASE+DDR_SEC_SIZE)
+
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define HIKEY960_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x3FC0_0000 */
+#define HIKEY960_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */
+#endif
+
+#if (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_DRAM_ID)
+#define TSP_SEC_MEM_BASE BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE BL32_DRAM_BASE
+#define BL32_LIMIT BL32_DRAM_LIMIT
+#elif (HIKEY960_TSP_RAM_LOCATION_ID == HIKEY960_SRAM_ID)
+#error "SRAM storage of TSP payload is currently unsupported"
+#else
+#error "Currently unsupported HIKEY960_TSP_LOCATION_ID value"
+#endif
+
+/* BL32 is mandatory in AArch32 */
+#ifdef __aarch64__
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
+#define NS_BL1U_BASE (BL31_LIMIT) /* 1AC9_8000 */
+#define NS_BL1U_SIZE (0x00100000)
+#define NS_BL1U_LIMIT (NS_BL1U_BASE + NS_BL1U_SIZE)
+
+#define HIKEY960_NS_IMAGE_OFFSET (0x1AC28000) /* offset in l-loader */
+#define HIKEY960_NS_TMP_OFFSET (0x1AE00000)
+
+#define SCP_BL2_BASE (0x89C80000)
+#define SCP_BL2_SIZE (0x00040000)
+
+/*
+ * Platform specific page table and MMU setup constants
+ */
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
+
+#if defined(IMAGE_BL1) || defined(IMAGE_BL32)
+#define MAX_XLAT_TABLES 3
+#endif
+
+#if defined(IMAGE_BL2)
+#define MAX_XLAT_TABLES 5
+#endif
+
+#if defined(IMAGE_BL31)
+#if defined(SPMC_AT_EL3)
+#define MAX_XLAT_TABLES 17
+#else
+#define MAX_XLAT_TABLES 5
+#endif
+#endif
+
+#define MAX_MMAP_REGIONS 16
+
+/*
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ */
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
new file mode 100644
index 0000000..4c3c817
--- /dev/null
+++ b/plat/hisilicon/hikey960/platform.mk
@@ -0,0 +1,182 @@
+#
+# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Non-TF Boot ROM
+BL2_AT_EL3 := 1
+
+# On Hikey960, the TSP can execute from TZC secure area in DRAM.
+HIKEY960_TSP_RAM_LOCATION ?= dram
+ifeq (${HIKEY960_TSP_RAM_LOCATION}, dram)
+ HIKEY960_TSP_RAM_LOCATION_ID = HIKEY960_DRAM_ID
+else ifeq (${HIKEY960_TSP_RAM_LOCATION}, sram)
+ HIKEY960_TSP_RAM_LOCATION_ID = HIKEY960_SRAM_ID
+else
+ $(error "Currently unsupported HIKEY960_TSP_RAM_LOCATION value")
+endif
+
+CRASH_CONSOLE_BASE := PL011_UART6_BASE
+COLD_BOOT_SINGLE_CPU := 1
+PLAT_PL061_MAX_GPIOS := 232
+PROGRAMMABLE_RESET_ADDRESS := 1
+ENABLE_SVE_FOR_NS := 0
+PLAT_PARTITION_BLOCK_SIZE := 4096
+
+# Process flags
+$(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID))
+$(eval $(call add_define,CRASH_CONSOLE_BASE))
+$(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
+$(eval $(call add_define,PLAT_PARTITION_BLOCK_SIZE))
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
+USE_COHERENT_MEM := 1
+
+PLAT_INCLUDES := -Iplat/hisilicon/hikey960/include
+
+PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ plat/hisilicon/hikey960/aarch64/hikey960_common.c \
+ plat/hisilicon/hikey960/hikey960_boardid.c
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+HIKEY960_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c
+
+BL1_SOURCES += bl1/tbbr/tbbr_img_desc.c \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_storage.c \
+ drivers/synopsys/ufs/dw_ufs.c \
+ drivers/ufs/ufs.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \
+ plat/hisilicon/hikey960/hikey960_bl1_setup.c \
+ plat/hisilicon/hikey960/hikey960_bl_common.c \
+ plat/hisilicon/hikey960/hikey960_io_storage.c \
+ ${HIKEY960_GIC_SOURCES}
+
+BL2_SOURCES += common/desc_image_load.c \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_storage.c \
+ drivers/partition/gpt.c \
+ drivers/partition/partition.c \
+ drivers/synopsys/ufs/dw_ufs.c \
+ drivers/ufs/ufs.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \
+ plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c \
+ plat/hisilicon/hikey960/hikey960_bl2_setup.c \
+ plat/hisilicon/hikey960/hikey960_bl_common.c \
+ plat/hisilicon/hikey960/hikey960_image_load.c \
+ plat/hisilicon/hikey960/hikey960_io_storage.c \
+ plat/hisilicon/hikey960/hikey960_mcu_load.c
+
+ifeq (${SPD},opteed)
+BL2_SOURCES += lib/optee/optee_utils.c
+endif
+
+include lib/zlib/zlib.mk
+PLAT_INCLUDES += -Ilib/zlib
+BL2_SOURCES += $(ZLIB_SOURCES)
+
+BL31_SOURCES += drivers/arm/cci/cci.c \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/gpio/gpio.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/cpus/aarch64/cortex_a73.S \
+ plat/common/plat_psci_common.c \
+ plat/hisilicon/hikey960/aarch64/hikey960_helpers.S \
+ plat/hisilicon/hikey960/hikey960_bl31_setup.c \
+ plat/hisilicon/hikey960/hikey960_bl_common.c \
+ plat/hisilicon/hikey960/hikey960_pm.c \
+ plat/hisilicon/hikey960/hikey960_topology.c \
+ plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c \
+ plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c \
+ ${HIKEY960_GIC_SOURCES}
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c
+
+BL1_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/hisilicon/hikey960/hikey960_tbbr.c \
+ plat/hisilicon/hikey960/hikey960_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl1.c
+
+BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/hisilicon/hikey960/hikey960_tbbr.c \
+ plat/hisilicon/hikey960/hikey960_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl1/hikey960_rotpk.o: $(ROTPK_HASH)
+$(BUILD_PLAT)/bl2/hikey960_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
+
+# Enable workarounds for selected Cortex-A53 errata.
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+FIP_ALIGN := 512
+
+# SPM dispatcher
+ifeq (${SPD},spmd)
+ifeq (${SPMC_AT_EL3},1)
+# include device tree helper library
+include lib/libfdt/libfdt.mk
+BL31_SOURCES += common/fdt_wrappers.c \
+ ${LIBFDT_SRCS} \
+ common/uuid.c
+
+# Add support for platform supplied linker script for BL31 build
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+endif
+
+ifeq ($(PLAT_SP_MANIFEST_DTS),)
+ $(error "Error: A SP manifest is required for the SPMC.")
+endif
+FDT_SOURCES += ${PLAT_SP_MANIFEST_DTS}
+endif
diff --git a/plat/hisilicon/poplar/aarch64/platform_common.c b/plat/hisilicon/poplar/aarch64/platform_common.c
new file mode 100644
index 0000000..fcd0a8b
--- /dev/null
+++ b/plat/hisilicon/poplar/aarch64/platform_common.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "platform_def.h"
+
+#define MAP_DDR MAP_REGION_FLAT(DDR_BASE, \
+ DDR_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_DEVICE MAP_REGION_FLAT(DEVICE_BASE, \
+ DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \
+ TSP_SEC_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#ifdef SPD_opteed
+#define MAP_OPTEE_PAGEABLE MAP_REGION_FLAT( \
+ POPLAR_OPTEE_PAGEABLE_LOAD_BASE, \
+ POPLAR_OPTEE_PAGEABLE_LOAD_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
+static const mmap_region_t poplar_mmap[] = {
+ MAP_DDR,
+ MAP_DEVICE,
+ MAP_TSP_MEM,
+#ifdef SPD_opteed
+ MAP_OPTEE_PAGEABLE,
+#endif
+ {0}
+};
+
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void plat_configure_mmu_el##_el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(poplar_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el##_el(0); \
+ }
+
+DEFINE_CONFIGURE_MMU_EL(3)
+DEFINE_CONFIGURE_MMU_EL(1)
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/hisilicon/poplar/aarch64/poplar_helpers.S b/plat/hisilicon/poplar/aarch64/poplar_helpers.S
new file mode 100644
index 0000000..063ee64
--- /dev/null
+++ b/plat/hisilicon/poplar/aarch64/poplar_helpers.S
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_my_core_pos
+ .globl poplar_calc_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl platform_mem_init
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses poplar_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b poplar_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int poplar_calc_core_pos(u_register_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 4) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func poplar_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc poplar_calc_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, POPLAR_CRASH_UART_BASE
+ mov_imm x1, POPLAR_CRASH_UART_CLK_IN_HZ
+ mov_imm x2, POPLAR_CONSOLE_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, POPLAR_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : r0
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, POPLAR_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on ARM
+ * platforms. The Secure RAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
diff --git a/plat/hisilicon/poplar/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c
new file mode 100644
index 0000000..acc1f0e
--- /dev/null
+++ b/plat/hisilicon/poplar/bl1_plat_setup.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/arm/pl061_gpio.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+/* Data structure which holds the extents of the trusted RAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+static meminfo_t bl2_tzram_layout;
+static console_t console;
+
+#if !POPLAR_RECOVERY
+static struct mmc_device_info mmc_info;
+#endif
+
+/*
+ * Cannot use default weak implementation in bl1_main.c because BL1 RW data is
+ * not at the top of the secure memory.
+ */
+int bl1_plat_handle_post_image_load(unsigned int image_id)
+{
+ image_desc_t *image_desc;
+ entry_point_info_t *ep_info;
+
+ if (image_id != BL2_IMAGE_ID)
+ return 0;
+
+ /* Get the image descriptor */
+ image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+ assert(image_desc != NULL);
+
+ /* Get the entry point info */
+ ep_info = &image_desc->ep_info;
+
+ bl2_tzram_layout.total_base = BL2_BASE;
+ bl2_tzram_layout.total_size = BL32_LIMIT - BL2_BASE;
+
+ flush_dcache_range((uintptr_t)&bl2_tzram_layout, sizeof(meminfo_t));
+
+ ep_info->args.arg1 = (uintptr_t)&bl2_tzram_layout;
+
+ VERBOSE("BL1: BL2 memory layout address = %p\n",
+ (void *)&bl2_tzram_layout);
+
+ return 0;
+}
+
+void bl1_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = BL1_RW_BASE;
+ bl1_tzram_layout.total_size = BL1_RW_SIZE;
+
+ INFO("BL1: 0x%lx - 0x%lx [size = %zu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
+ BL1_RAM_LIMIT - BL1_RAM_BASE);
+}
+
+void bl1_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL1_RO_BASE, /* l-loader and BL1 ROM */
+ BL1_RO_LIMIT,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+void bl1_platform_setup(void)
+{
+ int i;
+#if !POPLAR_RECOVERY
+ dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE);
+#endif
+
+ generic_delay_timer_init();
+
+ pl061_gpio_init();
+ for (i = 0; i < GPIO_MAX; i++)
+ pl061_gpio_register(GPIO_BASE(i), i);
+
+#if !POPLAR_RECOVERY
+ /* SoC-specific emmc register are initialized/configured by bootrom */
+ INFO("BL1: initializing emmc\n");
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ dw_mmc_init(&params, &mmc_info);
+#endif
+
+ plat_io_setup();
+}
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+ return BL2_IMAGE_ID;
+}
diff --git a/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c b/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c
new file mode 100644
index 0000000..9bda02e
--- /dev/null
+++ b/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = POPLAR_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the pager
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the paged
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = POPLAR_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = POPLAR_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = PLAT_POPLAR_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_POPLAR_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = DDR_BASE + DDR_SIZE -
+ PLAT_POPLAR_NS_IMAGE_OFFSET,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c
new file mode 100644
index 0000000..ee46772
--- /dev/null
+++ b/plat/hisilicon/poplar/bl2_plat_setup.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/partition/partition.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <drivers/mmc.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+static console_t console;
+#if !POPLAR_RECOVERY
+static struct mmc_device_info mmc_info;
+#endif
+
+/*******************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ ******************************************************************************/
+int plat_poplar_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ /*
+ * This platform has no SCP_BL2 yet
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t poplar_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL3-2 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifdef __aarch64__
+uint32_t poplar_get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#else
+uint32_t poplar_get_spsr_for_bl33_entry(void)
+{
+ unsigned int hyp_status, mode, spsr;
+
+ hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+ mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#endif /* __aarch64__ */
+
+int poplar_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+#ifdef __aarch64__
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+
+ /*
+ * OP-TEE expect to receive DTB address in x2.
+ * This will be copied into x2 by dispatcher.
+ * Set this (arg3) if necessary
+ */
+ /* bl_mem_params->ep_info.args.arg3 = PLAT_HIKEY_DT_BASE; */
+#endif
+ bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl32_entry();
+ break;
+#endif
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = poplar_get_spsr_for_bl33_entry();
+ break;
+
+#ifdef SCP_BL2_BASE
+ case SCP_BL2_IMAGE_ID:
+ /* The subsequent handling of SCP_BL2 is platform specific */
+ err = plat_poplar_bl2_handle_scp_bl2(&bl_mem_params->image_info);
+ if (err) {
+ WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+ }
+ break;
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return poplar_bl2_handle_post_image_load(image_id);
+}
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct meminfo *mem_layout = (struct meminfo *)arg1;
+#if !POPLAR_RECOVERY
+ dw_mmc_params_t params = EMMC_INIT_PARAMS(POPLAR_EMMC_DESC_BASE);
+#endif
+
+ console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Enable arch timer */
+ generic_delay_timer_init();
+
+ bl2_tzram_layout = *mem_layout;
+
+#if !POPLAR_RECOVERY
+ /* SoC-specific emmc register are initialized/configured by bootrom */
+ INFO("BL2: initializing emmc\n");
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ dw_mmc_init(&params, &mmc_info);
+#endif
+
+ plat_io_setup();
+}
+
+void bl2_plat_arch_setup(void)
+{
+ plat_configure_mmu_el1(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return PLAT_POPLAR_NS_IMAGE_OFFSET;
+#endif
+}
diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
new file mode 100644
index 0000000..fe60ddc
--- /dev/null
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <cortex_a53.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+#define TZPC_SEC_ATTR_CTRL_VALUE (0x9DB98D45)
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static console_t console;
+
+static void hisi_tzpc_sec_init(void)
+{
+ mmio_write_32(HISI_TZPC_SEC_ATTR_CTRL, TZPC_SEC_ATTR_CTRL_VALUE);
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup common to ARM standard platforms.
+ * Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be
+ * done before the MMU is initialized so that the memory layout can be used
+ * while creating page tables. BL2 has flushed this information to memory, so
+ * we are guaranteed to pick up good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ void *from_bl2;
+
+ from_bl2 = (void *) arg0;
+
+ console_pl011_register(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ,
+ PL011_BAUDRATE, &console);
+
+ /* Init console for crash report */
+ plat_crash_console_init();
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0)
+ panic();
+}
+
+void bl31_platform_setup(void)
+{
+ /* Init arch timer */
+ generic_delay_timer_init();
+
+ /* Init GIC distributor and CPU interface */
+ poplar_gic_driver_init();
+ poplar_gic_init();
+
+ /* Init security properties of IP blocks */
+ hisi_tzpc_sec_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ /* do nothing */
+}
+
+void bl31_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(BL31_BASE,
+ (BL31_LIMIT - BL31_BASE),
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+
+ INFO("Boot BL33 from 0x%lx for %" PRIu64 " Bytes\n",
+ bl33_image_ep_info.pc, bl33_image_ep_info.args.arg2);
+}
diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h
new file mode 100644
index 0000000..e31f4b3
--- /dev/null
+++ b/plat/hisilicon/poplar/include/hi3798cv200.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HI3798CV200_H
+#define HI3798CV200_H
+
+#include <lib/utils_def.h>
+
+/* PL011 */
+#define PL011_UART0_BASE (0xF8B00000)
+#define PL011_BAUDRATE (115200)
+#define PL011_UART0_CLK_IN_HZ (75000000)
+
+/* Sys Counter */
+#define SYS_COUNTER_FREQ_IN_TICKS (24000000)
+#define SYS_COUNTER_FREQ_IN_MHZ (24)
+
+/* Timer */
+#define SEC_TIMER0_BASE (0xF8008000)
+#define TIMER00_LOAD (SEC_TIMER0_BASE + 0x000)
+#define TIMER00_VALUE (SEC_TIMER0_BASE + 0x004)
+#define TIMER00_CONTROL (SEC_TIMER0_BASE + 0x008)
+#define TIMER00_BGLOAD (SEC_TIMER0_BASE + 0x018)
+
+#define SEC_TIMER2_BASE (0xF8009000)
+#define TIMER20_LOAD (SEC_TIMER2_BASE + 0x000)
+#define TIMER20_VALUE (SEC_TIMER2_BASE + 0x004)
+#define TIMER20_CONTROL (SEC_TIMER2_BASE + 0x008)
+#define TIMER20_BGLOAD (SEC_TIMER2_BASE + 0x018)
+
+/* GPIO */
+#define GPIO_MAX (13)
+#define GPIO_BASE(x) (x != 5 ? \
+ 0xf820000 + x * 0x1000 : 0xf8004000)
+
+/* SCTL */
+#define REG_BASE_SCTL (0xF8000000)
+#define REG_SC_GEN12 (0x00B0)
+
+/* CRG */
+#define REG_BASE_CRG (0xF8A22000)
+#define REG_CPU_LP (0x48)
+#define REG_CPU_RST (0x50)
+#define REG_PERI_CRG39 (0x9C)
+#define REG_PERI_CRG40 (0xA0)
+
+/* MCI */
+#define REG_BASE_MCI (0xF9830000)
+#define MCI_CDETECT (0x50)
+#define MCI_VERID (0x6C)
+#define MCI_VERID_VALUE (0x5342250A)
+#define MCI_VERID_VALUE2 (0x5342270A)
+
+/* EMMC */
+#define REG_EMMC_PERI_CRG REG_PERI_CRG40
+#define REG_SDCARD_PERI_CRG REG_PERI_CRG39
+#define EMMC_CLK_MASK (0x7 << 8)
+#define EMMC_SRST_REQ (0x1 << 4)
+#define EMMC_CKEN (0x1 << 1)
+#define EMMC_BUS_CKEN (0x1 << 0)
+#define EMMC_CLK_100M (0 << 8)
+#define EMMC_CLK_50M (1 << 8)
+#define EMMC_CLK_25M (2 << 8)
+
+#define EMMC_DESC_SIZE U(0x00100000) /* 1MB */
+#define EMMC_INIT_PARAMS(base) \
+ { .bus_width = MMC_BUS_WIDTH_8, \
+ .clk_rate = 25 * 1000 * 1000, \
+ .desc_base = (base), \
+ .desc_size = EMMC_DESC_SIZE, \
+ .flags = MMC_FLAG_CMD23, \
+ .reg_base = REG_BASE_MCI, \
+ }
+
+/* GIC-400 */
+#define GICD_BASE (0xF1001000)
+#define GICC_BASE (0xF1002000)
+#define GICR_BASE (0xF1000000)
+
+/* FIQ platform related define */
+#define HISI_IRQ_SEC_SGI_0 8
+#define HISI_IRQ_SEC_SGI_1 9
+#define HISI_IRQ_SEC_SGI_2 10
+#define HISI_IRQ_SEC_SGI_3 11
+#define HISI_IRQ_SEC_SGI_4 12
+#define HISI_IRQ_SEC_SGI_5 13
+#define HISI_IRQ_SEC_SGI_6 14
+#define HISI_IRQ_SEC_SGI_7 15
+#define HISI_IRQ_SEC_PPI_0 29
+#define HISI_IRQ_SEC_TIMER0 60
+#define HISI_IRQ_SEC_TIMER1 50
+#define HISI_IRQ_SEC_TIMER2 52
+#define HISI_IRQ_SEC_TIMER3 88
+#define HISI_IRQ_SEC_AXI 110
+
+/* Watchdog */
+#define HISI_WDG0_BASE (0xF8A2C000)
+
+#define HISI_TZPC_BASE (0xF8A80000)
+#define HISI_TZPC_SEC_ATTR_CTRL (HISI_TZPC_BASE + 0x10)
+
+#endif /* HI3798CV200_H */
diff --git a/plat/hisilicon/poplar/include/plat_macros.S b/plat/hisilicon/poplar/include/plat_macros.S
new file mode 100644
index 0000000..82d10c1
--- /dev/null
+++ b/plat/hisilicon/poplar/include/plat_macros.S
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+.section .rodata.gic_reg_name, "aS"
+ .macro plat_crash_print_regs
+ nop
+ .endm
diff --git a/plat/hisilicon/poplar/include/plat_private.h b/plat/hisilicon/poplar/include/plat_private.h
new file mode 100644
index 0000000..a34f138
--- /dev/null
+++ b/plat/hisilicon/poplar/include/plat_private.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+#include <common/bl_common.h>
+
+#include "hi3798cv200.h"
+
+void plat_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+
+void plat_configure_mmu_el1(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+
+void plat_io_setup(void);
+
+unsigned int poplar_calc_core_pos(u_register_t mpidr);
+
+void poplar_gic_driver_init(void);
+void poplar_gic_init(void);
+void poplar_gic_cpuif_enable(void);
+void poplar_gic_pcpu_init(void);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h
new file mode 100644
index 0000000..ce0fbbc
--- /dev/null
+++ b/plat/hisilicon/poplar/include/platform_def.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/interrupt_props.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "hi3798cv200.h"
+#include "poplar_layout.h" /* BL memory region sizes, etc */
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define POPLAR_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define POPLAR_CRASH_UART_BASE PL011_UART0_BASE
+#define POPLAR_CRASH_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ
+#define POPLAR_CONSOLE_BAUDRATE PL011_BAUDRATE
+
+/* Generic platform constants */
+#define PLATFORM_STACK_SIZE (0x800)
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+#define BOOT_EMMC_NAME "l-loader.bin"
+
+#define PLATFORM_CACHE_LINE_SIZE (64)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CORE_COUNT U(4)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+
+/* IO framework user */
+#define MAX_IO_DEVICES (4)
+#define MAX_IO_HANDLES (4)
+#define MAX_IO_BLOCK_DEVICES U(2)
+
+/* Memory size options */
+#define POPLAR_DRAM_SIZE_1G 0
+#define POPLAR_DRAM_SIZE_2G 1
+
+/* Memory map related constants */
+#define DDR_BASE (0x00000000)
+
+#if (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_2G)
+#define DDR_SIZE (0x80000000)
+#elif (POPLAR_DRAM_SIZE_ID == POPLAR_DRAM_SIZE_1G)
+#define DDR_SIZE (0x40000000)
+#else
+#error "Currently unsupported POPLAR_DRAM_SIZE_ID value"
+#endif
+
+#define DEVICE_BASE (0xF0000000)
+#define DEVICE_SIZE (0x0F000000)
+
+#define TEE_SEC_MEM_BASE (0x70000000)
+#define TEE_SEC_MEM_SIZE (0x10000000)
+
+/* Memory location options for TSP */
+#define POPLAR_SRAM_ID 0
+#define POPLAR_DRAM_ID 1
+
+/*
+ * DDR for OP-TEE (26MB from 0x02400000 -0x04000000) is divided in several
+ * regions:
+ * - Secure DDR (default is the top 16MB) used by OP-TEE
+ * - Non-secure DDR (4MB) reserved for OP-TEE's future use
+ * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature
+ * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB)
+ */
+#define DDR_SEC_SIZE 0x01000000
+#define DDR_SEC_BASE 0x03000000
+
+/*
+ * BL3-2 specific defines.
+ */
+
+/*
+ * The TSP currently executes from TZC secured area of DRAM.
+ */
+#define BL32_DRAM_BASE 0x03000000
+#define BL32_DRAM_LIMIT 0x04000000
+
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define POPLAR_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 /* 4MB */
+#define POPLAR_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - POPLAR_OPTEE_PAGEABLE_LOAD_SIZE) /* 0x03C0_0000 */
+#endif
+
+#if (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_DRAM_ID)
+#define TSP_SEC_MEM_BASE BL32_DRAM_BASE
+#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE)
+#define BL32_BASE BL32_DRAM_BASE
+#define BL32_LIMIT BL32_DRAM_LIMIT
+#elif (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_SRAM_ID)
+#error "SRAM storage of TSP payload is currently unsupported"
+#else
+#error "Currently unsupported POPLAR_TSP_LOCATION_ID value"
+#endif
+
+/* BL32 is mandatory in AArch32 */
+#ifdef __aarch64__
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+#endif
+
+#define POPLAR_EMMC_DATA_BASE U(0x02200000)
+#define POPLAR_EMMC_DATA_SIZE EMMC_DESC_SIZE
+#define POPLAR_EMMC_DESC_BASE (POPLAR_EMMC_DATA_BASE + POPLAR_EMMC_DATA_SIZE)
+#define POPLAR_EMMC_DESC_SIZE EMMC_DESC_SIZE
+
+#define PLAT_POPLAR_NS_IMAGE_OFFSET 0x37000000
+
+/* Page table and MMU setup constants */
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES (4)
+#define MAX_MMAP_REGIONS (16)
+
+#define CACHE_WRITEBACK_SHIFT (6)
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/* Power states */
+#define PLAT_MAX_PWR_LVL (MPIDR_AFFLVL1)
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+/* Interrupt controller */
+#define POPLAR_GICD_BASE GICD_BASE
+#define POPLAR_GICC_BASE GICC_BASE
+
+#define POPLAR_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_TIMER3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(HISI_IRQ_SEC_AXI, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define POPLAR_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/hisilicon/poplar/include/poplar_layout.h b/plat/hisilicon/poplar/include/poplar_layout.h
new file mode 100644
index 0000000..03047f9
--- /dev/null
+++ b/plat/hisilicon/poplar/include/poplar_layout.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POPLAR_LAYOUT_H
+#define POPLAR_LAYOUT_H
+
+/*
+ * Boot memory layout definitions for the HiSilicon Poplar board
+ */
+
+/*
+ * When Poplar is powered on, boot ROM verifies the initial content of
+ * boot media, loads it into low memory, and begins executing it
+ * in 32-bit mode. The image loaded is "l-loader.bin", which contains
+ * a small amount code along with an embedded ARM Trusted Firmware
+ * BL1 image. The main purpose of "l-loader" is to prepare the
+ * processor to execute the BL1 image in 64-bit mode, and to trigger
+ * that execution.
+ *
+ * Also embedded in "l-loader.bin" is a FIP image that contains
+ * other ARM Trusted Firmware images: BL2; BL31; and for BL33,
+ * U-Boot. When BL1 executes, it unpacks the BL2 image from the FIP
+ * image into a region of memory set aside to hold it. Similarly,
+ * BL2 unpacks BL31 into memory reserved for it, and unpacks U-Boot
+ * into high memory.
+ *
+ * Because the BL1 code is embedded in "l-loader", its base address
+ * in memory is derived from the base address of the "l-loader"
+ * text section, together with an offset. Memory space for BL2 is
+ * reserved immediately following BL1, and memory space is reserved
+ * for BL31 after that. ARM Trusted Firmware requires each of these
+ * memory regions to be aligned on page boundaries, so the size of
+ * each region is a multiple of a page size (ending in 000). Note
+ * that ARM Trusted Firmware requires the read-only and read-write
+ * regions of memory used for BL1 to be defined separately.
+ *
+ * ---------------------
+ * | (unused memory) |
+ * +-------------------+ - - - - -
+ * | (l-loader text) | \
+ * +-------------------+ \
+ * | BL1 (read-only) | \ \
+ * |- - - - - - - - - -| | |
+ * | BL1 (read-write) | | |
+ * +-------------------+ > BL Memory |
+ * | Reserved for BL2 | | > "l-loader.bin" image
+ * +-------------------+ | |
+ * | Reserved for BL31 | / |
+ * +-------------------+ |
+ * . . . /
+ * +-------------------+ /
+ * | FIP | /
+ * +-------------------+ - - - - -
+ * . . .
+ * | (unused memory) |
+ * . . .
+ * +-------------------+
+ * |Reserved for U-Boot|
+ * +-------------------+
+ * . . .
+ * | (unused memory) |
+ * ---------------------
+ *
+ * The size of each of these regions is defined below. The base
+ * address of the "l-loader" TEXT section and the offset of the BL1
+ * image within that serve as anchors for defining the positions of
+ * all other regions. The FIP is placed in a section of its own.
+ *
+ * A "BASE" is the memory address of the start of a region; a "LIMIT"
+ * marks its end. A "SIZE" is the size of a region (in bytes). An
+ * "OFFSET" is an offset to the start of a region relative to the
+ * base of the "l-loader" TEXT section (also a multiple of page size).
+ */
+#define LLOADER_TEXT_BASE 0x02001000 /* page aligned */
+#define BL1_OFFSET 0x0000D000 /* page multiple */
+#define FIP_BASE 0x02040000
+
+/*
+ * FIP_BASE_EMMC = 0x40000 - 0x1000
+ * = fip.bin offset - l-loader text offset
+ * in l-loader.bin
+ */
+#define FIP_BASE_EMMC 0x0003f000
+
+#define BL1_RO_SIZE 0x00008000 /* page multiple */
+#define BL1_RW_SIZE 0x00008000 /* page multiple */
+#define BL1_SIZE (BL1_RO_SIZE + BL1_RW_SIZE)
+#define BL2_SIZE 0x0000d000 /* page multiple */
+#define BL31_SIZE 0x00014000
+#if !POPLAR_RECOVERY
+/*
+ * emmc partition1 4096KB
+ * - l-loader.bin 1984KB
+ * |- l-loader + bl1.bin 256KB
+ * |- fip.bin 1728KB (0x001b0000)
+ * - u-boot persistent data 64KB
+ * - uefi persistent data 2048KB
+ */
+#define FIP_SIZE 0x001b0000 /* absolute max */
+#else
+/*
+ * same as above, but bootrom can only load an image (l-loader.bin) of
+ * 1024KB max, so after deducting the size of l-loader + bl1.bin (256KB),
+ * that leaves 768KB (0x000c0000) for fip.bin
+ */
+#define FIP_SIZE 0x000c0000 /* absolute max */
+#endif
+
+ /* BL1_OFFSET */ /* (Defined above) */
+#define BL1_BASE (LLOADER_TEXT_BASE + BL1_OFFSET)
+#define BL1_LIMIT (BL1_BASE + BL1_SIZE)
+
+#define BL1_RO_OFFSET (BL1_OFFSET)
+#define BL1_RO_BASE (LLOADER_TEXT_BASE + BL1_RO_OFFSET)
+#define BL1_RO_LIMIT (BL1_RO_BASE + BL1_RO_SIZE)
+
+#define BL1_RW_OFFSET (BL1_RO_OFFSET + BL1_RO_SIZE)
+#define BL1_RW_BASE (LLOADER_TEXT_BASE + BL1_RW_OFFSET)
+#define BL1_RW_LIMIT (BL1_RW_BASE + BL1_RW_SIZE)
+
+#define BL2_OFFSET (BL1_OFFSET + BL1_SIZE)
+#define BL2_BASE (LLOADER_TEXT_BASE + BL2_OFFSET)
+#define BL2_LIMIT (BL2_BASE + BL2_SIZE)
+
+#define BL31_OFFSET (BL2_OFFSET + BL2_SIZE)
+#define BL31_BASE (LLOADER_TEXT_BASE + BL31_OFFSET)
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+#endif /* POPLAR_LAYOUT_H */
diff --git a/plat/hisilicon/poplar/plat_pm.c b/plat/hisilicon/poplar/plat_pm.c
new file mode 100644
index 0000000..67ebca1
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_pm.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include "hi3798cv200.h"
+#include "plat_private.h"
+
+#define REG_PERI_CPU_RVBARADDR 0xF8A80034
+#define REG_PERI_CPU_AARCH_MODE 0xF8A80030
+
+#define REG_CPU_LP_CPU_SW_BEGIN 10
+#define CPU_REG_COREPO_SRST 12
+#define CPU_REG_CORE_SRST 8
+
+static void poplar_cpu_standby(plat_local_state_t cpu_state)
+{
+ dsb();
+ wfi();
+}
+
+static int poplar_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int cpu = plat_core_pos_by_mpidr(mpidr);
+ unsigned int regval, regval_bak;
+
+ /* Select 400MHz before start slave cores */
+ regval_bak = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x206);
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), 0x606);
+
+ /* Clear the slave cpu arm_por_srst_req reset */
+ regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
+ regval &= ~(1 << (cpu + CPU_REG_COREPO_SRST));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
+
+ /* Clear the slave cpu reset */
+ regval = mmio_read_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST));
+ regval &= ~(1 << (cpu + CPU_REG_CORE_SRST));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_RST), regval);
+
+ /* Restore cpu frequency */
+ regval = regval_bak & (~(1 << REG_CPU_LP_CPU_SW_BEGIN));
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval);
+ mmio_write_32((uintptr_t)(REG_BASE_CRG + REG_CPU_LP), regval_bak);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void poplar_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+static void poplar_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+static void poplar_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_MAX_OFF_STATE);
+
+ /* Enable the gic cpu interface */
+ poplar_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ poplar_gic_cpuif_enable();
+}
+
+static void poplar_pwr_domain_suspend_finish(
+ const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+static void __dead2 poplar_system_off(void)
+{
+ ERROR("Poplar System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 poplar_system_reset(void)
+{
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551);
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0), 0x00000100);
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000003);
+
+ wfi();
+ ERROR("Poplar System Reset: operation not handled.\n");
+ panic();
+}
+
+static int32_t poplar_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+ int pstate = psci_get_pstate_type(power_state);
+
+ assert(req_state);
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY)
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ else
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+static int poplar_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint >= DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
+ return PSCI_E_SUCCESS;
+
+ return PSCI_E_INVALID_ADDRESS;
+}
+
+static void poplar_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+static const plat_psci_ops_t poplar_plat_psci_ops = {
+ .cpu_standby = poplar_cpu_standby,
+ .pwr_domain_on = poplar_pwr_domain_on,
+ .pwr_domain_off = poplar_pwr_domain_off,
+ .pwr_domain_suspend = poplar_pwr_domain_suspend,
+ .pwr_domain_on_finish = poplar_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = poplar_pwr_domain_suspend_finish,
+ .system_off = poplar_system_off,
+ .system_reset = poplar_system_reset,
+ .validate_power_state = poplar_validate_power_state,
+ .validate_ns_entrypoint = poplar_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = poplar_get_sys_suspend_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &poplar_plat_psci_ops;
+
+ mmio_write_32((uintptr_t)REG_PERI_CPU_AARCH_MODE, 0xF);
+ mmio_write_32((uintptr_t)REG_PERI_CPU_RVBARADDR, sec_entrypoint);
+ return 0;
+}
diff --git a/plat/hisilicon/poplar/plat_storage.c b/plat/hisilicon/poplar/plat_storage.c
new file mode 100644
index 0000000..a17e0f1
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_storage.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <lib/mmio.h>
+#include <lib/semihosting.h>
+#include <lib/utils.h>
+#include <tools_share/firmware_image_package.h>
+
+#if !POPLAR_RECOVERY
+static const io_dev_connector_t *emmc_dev_con;
+static uintptr_t emmc_dev_handle;
+static int open_emmc(const uintptr_t spec);
+
+static const io_block_spec_t emmc_fip_spec = {
+ .offset = FIP_BASE_EMMC,
+ .length = FIP_SIZE
+};
+
+static const io_block_dev_spec_t emmc_dev_spec = {
+ .buffer = {
+ .offset = POPLAR_EMMC_DATA_BASE,
+ .length = POPLAR_EMMC_DATA_SIZE,
+ },
+ .ops = {
+ .read = mmc_read_blocks,
+ .write = mmc_write_blocks,
+ },
+ .block_size = MMC_BLOCK_SIZE,
+};
+#else
+static const io_dev_connector_t *mmap_dev_con;
+static uintptr_t mmap_dev_handle;
+static int open_mmap(const uintptr_t spec);
+
+static const io_block_spec_t loader_fip_spec = {
+ .offset = FIP_BASE,
+ .length = FIP_SIZE
+};
+#endif
+
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static int open_fip(const uintptr_t spec);
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+#if !POPLAR_RECOVERY
+ [FIP_IMAGE_ID] = {
+ &emmc_dev_handle,
+ (uintptr_t)&emmc_fip_spec,
+ open_emmc
+ },
+#else
+ [FIP_IMAGE_ID] = {
+ &mmap_dev_handle,
+ (uintptr_t)&loader_fip_spec,
+ open_mmap
+ },
+#endif
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+};
+
+#if !POPLAR_RECOVERY
+static int open_emmc(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(emmc_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(emmc_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ INFO("Using eMMC\n");
+ io_close(local_image_handle);
+ } else {
+ ERROR("error opening emmc\n");
+ }
+ } else {
+ ERROR("error initializing emmc\n");
+ }
+
+ return result;
+}
+#else
+static int open_mmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(mmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(mmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ INFO("Using mmap\n");
+ io_close(local_image_handle);
+ } else {
+ ERROR("error opening mmap\n");
+ }
+ } else {
+ ERROR("error initializing mmap\n");
+ }
+
+ return result;
+}
+#endif
+
+static int open_fip(const uintptr_t spec)
+{
+ uintptr_t local_image_handle;
+ int result;
+
+ result = io_dev_init(fip_dev_handle, (uintptr_t) FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ INFO("Using FIP\n");
+ io_close(local_image_handle);
+ } else {
+ ERROR("error opening fip\n");
+ }
+ } else {
+ ERROR("error initializing fip\n");
+ }
+
+ return result;
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ const struct plat_io_policy *policy;
+ int result;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ assert(result == 0);
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ return result;
+}
+
+void plat_io_setup(void)
+{
+ int result;
+
+#if !POPLAR_RECOVERY
+ result = register_io_dev_block(&emmc_dev_con);
+#else
+ result = register_io_dev_memmap(&mmap_dev_con);
+#endif
+ assert(result == 0);
+
+ result = register_io_dev_fip(&fip_dev_con);
+ assert(result == 0);
+
+#if !POPLAR_RECOVERY
+ result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+#else
+ result = io_dev_open(fip_dev_con, (uintptr_t)&loader_fip_spec,
+ &fip_dev_handle);
+#endif
+ assert(result == 0);
+
+#if !POPLAR_RECOVERY
+ result = io_dev_open(emmc_dev_con, (uintptr_t)&emmc_dev_spec,
+ &emmc_dev_handle);
+#else
+ result = io_dev_open(mmap_dev_con, (uintptr_t)NULL, &mmap_dev_handle);
+#endif
+ assert(result == 0);
+
+ (void) result;
+}
diff --git a/plat/hisilicon/poplar/plat_topology.c b/plat/hisilicon/poplar/plat_topology.c
new file mode 100644
index 0000000..764008e
--- /dev/null
+++ b/plat/hisilicon/poplar/plat_topology.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <lib/psci/psci.h>
+
+#include "plat_private.h"
+
+const unsigned char hisi_power_domain_tree_desc[] = {
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return hisi_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ if (mpidr & MPIDR_CLUSTER_MASK)
+ return -1;
+
+ if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT)
+ return -1;
+
+ return poplar_calc_core_pos(mpidr);
+}
diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk
new file mode 100644
index 0000000..b5d9867
--- /dev/null
+++ b/plat/hisilicon/poplar/platform.mk
@@ -0,0 +1,112 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# On Poplar, the TSP can execute from TZC secure area in DRAM.
+POPLAR_TSP_RAM_LOCATION ?= dram
+ifeq (${POPLAR_TSP_RAM_LOCATION}, dram)
+ POPLAR_TSP_RAM_LOCATION_ID = POPLAR_DRAM_ID
+else ifeq (${POPLAR_TSP_RAM_LOCATION}, sram)
+ POPLAR_TSP_RAM_LOCATION_ID = POPLAR_SRAM_ID
+else
+ $(error "Currently unsupported POPLAR_TSP_RAM_LOCATION value")
+endif
+$(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID))
+
+POPLAR_DRAM_SIZE ?= two_gig
+ifeq (${POPLAR_DRAM_SIZE}, two_gig)
+ POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_2G
+else ifeq (${POPLAR_DRAM_SIZE}, one_gig)
+ POPLAR_DRAM_SIZE_ID = POPLAR_DRAM_SIZE_1G
+else
+ $(error "Currently unsupported POPLAR_DRAM_SIZE value")
+endif
+$(eval $(call add_define,POPLAR_DRAM_SIZE_ID))
+
+POPLAR_RECOVERY := 0
+$(eval $(call add_define,POPLAR_RECOVERY))
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+
+NEED_BL33 := yes
+
+COLD_BOOT_SINGLE_CPU := 1
+PROGRAMMABLE_RESET_ADDRESS := 1
+CTX_INCLUDE_FPREGS := 1
+ERRATA_A53_855873 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ENABLE_SVE_FOR_NS := 0
+WORKAROUND_CVE_2017_5715 := 0
+
+PLAT_PL061_MAX_GPIOS := 104
+$(eval $(call add_define,PLAT_PL061_MAX_GPIOS))
+
+PLAT_INCLUDES := -Iplat/hisilicon/poplar/include \
+ -Iplat/hisilicon/poplar
+
+PLAT_BL_COMMON_SOURCES := \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/arm/pl011/aarch64/pl011_console.S \
+ drivers/arm/gic/v2/gicv2_main.c \
+ plat/common/plat_gicv2.c \
+ plat/hisilicon/poplar/aarch64/platform_common.c \
+ plat/hisilicon/poplar/aarch64/poplar_helpers.S \
+ plat/hisilicon/poplar/poplar_gicv2.c
+
+BL1_SOURCES += \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/mmc/mmc.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_block.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ plat/hisilicon/poplar/bl1_plat_setup.c \
+ plat/hisilicon/poplar/plat_storage.c
+
+BL2_SOURCES += \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/mmc/mmc.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/gpio/gpio.c \
+ drivers/io/io_memmap.c \
+ plat/hisilicon/poplar/bl2_plat_setup.c \
+ plat/hisilicon/poplar/plat_storage.c
+
+BL2_SOURCES += \
+ plat/hisilicon/poplar/bl2_plat_mem_params_desc.c \
+ plat/hisilicon/poplar/poplar_image_load.c \
+ common/desc_image_load.c
+
+ifeq (${SPD},opteed)
+BL2_SOURCES += \
+ lib/optee/optee_utils.c
+endif
+
+BL31_SOURCES += \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/hisilicon/poplar/bl31_plat_setup.c \
+ plat/hisilicon/poplar/plat_topology.c \
+ plat/hisilicon/poplar/plat_pm.c
diff --git a/plat/hisilicon/poplar/poplar_gicv2.c b/plat/hisilicon/poplar/poplar_gicv2.c
new file mode 100644
index 0000000..59f7b76
--- /dev/null
+++ b/plat/hisilicon/poplar/poplar_gicv2.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/arm/gicv2.h>
+#include <plat/common/platform.h>
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t poplar_interrupt_props[] = {
+ POPLAR_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ POPLAR_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t poplar_gic_data = {
+ .gicd_base = POPLAR_GICD_BASE,
+ .gicc_base = POPLAR_GICC_BASE,
+ .interrupt_props = poplar_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(poplar_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/******************************************************************************
+ * Helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void poplar_gic_driver_init(void)
+{
+ gicv2_driver_init(&poplar_gic_data);
+}
+
+void poplar_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * Helper to enable the GICv2 CPU interface
+ *****************************************************************************/
+void poplar_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * Helper to initialize the per cpu distributor interface in GICv2
+ *****************************************************************************/
+void poplar_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+}
diff --git a/plat/hisilicon/poplar/poplar_image_load.c b/plat/hisilicon/poplar/poplar_image_load.c
new file mode 100644
index 0000000..0ab1ca4
--- /dev/null
+++ b/plat/hisilicon/poplar/poplar_image_load.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/imx/common/aarch32/imx_uart_console.S b/plat/imx/common/aarch32/imx_uart_console.S
new file mode 100644
index 0000000..1a1229a
--- /dev/null
+++ b/plat/imx/common/aarch32/imx_uart_console.S
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <console_macros.S>
+#include <assert_macros.S>
+#include "imx_uart.h"
+
+ .globl console_imx_uart_register
+ .globl console_imx_uart_putc
+ .globl console_imx_uart_getc
+ .globl console_imx_uart_flush
+
+func console_imx_uart_register
+ push {r4, lr}
+ mov r4, r3
+ cmp r4, #0
+ beq register_fail
+ str r0, [r4, #CONSOLE_T_BASE]
+
+ bl console_imx_uart_core_init
+ cmp r0, #0
+ bne register_fail
+
+ mov r0, r4
+ pop {r4, lr}
+ finish_console_register imx_uart putc=1, getc=1, flush=1
+
+register_fail:
+ pop {r4, pc}
+endfunc console_imx_uart_register
+
+func console_imx_uart_putc
+ ldr r1, [r1, #CONSOLE_T_BASE]
+ b console_imx_uart_core_putc
+endfunc console_imx_uart_putc
+
+func console_imx_uart_getc
+ ldr r0, [r0, #CONSOLE_T_BASE]
+ b console_imx_uart_core_getc
+endfunc console_imx_uart_getc
+
+func console_imx_uart_flush
+ ldr r0, [r0, #CONSOLE_T_BASE]
+ b console_imx_uart_core_flush
+endfunc console_imx_uart_flush
diff --git a/plat/imx/common/imx7_clock.c b/plat/imx/common/imx7_clock.c
new file mode 100644
index 0000000..6bd2e0e
--- /dev/null
+++ b/plat/imx/common/imx7_clock.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <imx_regs.h>
+#include <imx_clock.h>
+
+static void imx7_clock_uart_init(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < MXC_MAX_UART_NUM; i++)
+ imx_clock_disable_uart(i);
+}
+
+static void imx7_clock_wdog_init(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < MXC_MAX_WDOG_NUM; i++)
+ imx_clock_disable_wdog(i);
+}
+
+static void imx7_clock_usb_init(void)
+{
+ /* Disable the clock root */
+ imx_clock_target_clr(CCM_TRT_ID_USB_HSIC_CLK_ROOT, 0xFFFFFFFF);
+}
+
+void imx_clock_init(void)
+{
+ /*
+ * The BootROM hands off to the next stage with the internal 24 MHz XTAL
+ * crystal already clocking the main PLL, which is very handy.
+ * Here we should enable whichever peripherals are required for ATF and
+ * OPTEE.
+ *
+ * Subsequent stages in the boot process such as u-boot and Linux
+ * already have a significant and mature code-base around clocks, so our
+ * objective should be to enable what we need for ATF/OPTEE without
+ * breaking any existing upstream code in Linux and u-boot.
+ */
+
+ /* Initialize UART clocks */
+ imx7_clock_uart_init();
+
+ /* Watchdog clocks */
+
+ imx7_clock_wdog_init();
+
+ /* USB clocks */
+ imx7_clock_usb_init();
+
+}
diff --git a/plat/imx/common/imx8_helpers.S b/plat/imx/common/imx8_helpers.S
new file mode 100644
index 0000000..19293bf
--- /dev/null
+++ b/plat/imx/common/imx8_helpers.S
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <cortex_a35.h>
+
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_calc_core_pos
+ .globl plat_reset_handler
+ .globl plat_get_my_entrypoint
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl platform_mem_init
+ .globl imx_mailbox_init
+
+ /* --------------------------------------------------------------------
+ * Helper macro that reads the part number of the current CPU and jumps
+ * to the given label if it matches the CPU MIDR provided.
+ *
+ * Clobbers x0.
+ * --------------------------------------------------------------------
+ */
+ .macro jump_if_cpu_midr _cpu_midr, _label
+
+ mrs x0, midr_el1
+ ubfx x0, x0, MIDR_PN_SHIFT, #12
+ cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+ b.eq \_label
+
+ .endm
+
+ /* ----------------------------------------------
+ * The mailbox_base is used to distinguish warm/cold
+ * reset. The mailbox_base is in the data section, not
+ * in .bss, this allows function to start using this
+ * variable before the runtime memory is initialized.
+ * ----------------------------------------------
+ */
+ .section .data.mailbox_base
+ .align 3
+ mailbox_base: .quad 0x0
+
+ /* ----------------------------------------------
+ * unsigned int plat_is_my_cpu_primary(void);
+ * This function checks if this is the primary CPU
+ * ----------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* ----------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This Function uses the plat_calc_core_pos()
+ * to get the index of the calling CPU.
+ * ----------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+ /*
+ * unsigned int plat_calc_core_pos(uint64_t mpidr)
+ * helper function to calculate the core position.
+ * With this function.
+ */
+func plat_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_calc_core_pos
+
+ /* ---------------------------------------------
+ * function to get the entrypoint.
+ * ---------------------------------------------
+ */
+func plat_get_my_entrypoint
+ adrp x1, mailbox_base
+ ldr x0, [x1, :lo12:mailbox_base]
+ ret
+endfunc plat_get_my_entrypoint
+
+func imx_mailbox_init
+ adrp x1, mailbox_base
+ str x0, [x1, :lo12:mailbox_base]
+ ret
+endfunc imx_mailbox_init
+
+func plat_secondary_cold_boot_setup
+ b .
+endfunc plat_secondary_cold_boot_setup
+
+func plat_crash_console_init
+ mov x0, #1
+ ret
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+ ret
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+ mov x0, #0
+ ret
+endfunc plat_crash_console_flush
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
diff --git a/plat/imx/common/imx8_psci.c b/plat/imx/common/imx8_psci.c
new file mode 100644
index 0000000..91d3370
--- /dev/null
+++ b/plat/imx/common/imx8_psci.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <plat_imx8.h>
+#include <sci/sci.h>
+
+void __dead2 imx_system_off(void)
+{
+ sc_pm_set_sys_power_mode(ipc_handle, SC_PM_PW_MODE_OFF);
+ wfi();
+ ERROR("power off failed.\n");
+ panic();
+}
+
+void __dead2 imx_system_reset(void)
+{
+ sc_pm_reset(ipc_handle, SC_PM_RESET_TYPE_BOARD);
+ wfi();
+ ERROR("system reset failed.\n");
+ panic();
+}
+
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int pwr_type = psci_get_pstate_type(power_state);
+ int state_id = psci_get_pstate_id(power_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ if (pwr_type == PSTATE_TYPE_POWERDOWN) {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+ if (!state_id)
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_RET_STATE;
+ else
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = PLAT_MAX_OFF_STATE;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ /* CPU & cluster off, system in retention */
+ for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE;
+}
+
diff --git a/plat/imx/common/imx8_topology.c b/plat/imx/common/imx8_topology.c
new file mode 100644
index 0000000..5e14d17
--- /dev/null
+++ b/plat/imx/common/imx8_topology.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+const unsigned char imx_power_domain_tree_desc[] = {
+ PWR_DOMAIN_AT_MAX_LVL,
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ PLATFORM_CLUSTER1_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return imx_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (cluster_id > PLATFORM_CLUSTER_COUNT ||
+ cpu_id > PLATFORM_MAX_CPU_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
+}
diff --git a/plat/imx/common/imx_aips.c b/plat/imx/common/imx_aips.c
new file mode 100644
index 0000000..532d9c0
--- /dev/null
+++ b/plat/imx/common/imx_aips.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <imx_aips.h>
+#include <imx_regs.h>
+
+static void imx_aips_set_default_access(struct aipstz_regs *aips_regs)
+{
+ int i;
+ uintptr_t addr;
+
+ /*
+ * See section 4.7.7.1 AIPSTZ_MPR field descriptions
+ * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016
+ * 0111 ->
+ * 0: Write Access from master not buffered
+ * 1: Master is trusted for read access
+ * 1: Master is trsuted for write access
+ * 1: Access from master is not forced to user mode
+ */
+ addr = (uintptr_t)&aips_regs->aipstz_mpr;
+ mmio_write_32(addr, 0x77777777);
+
+ /*
+ * Helpfully the OPACR registers have the logical inversion of the above
+ * See section 4.7.7.1 AIPSTZ_MPR field descriptions
+ * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016
+ * 0000 ->
+ * 0: Write Access to the peripheral is not buffered by AIPSTZ
+ * 0: The peripheral does not require supervisor priv to access
+ * 0: Master is trsuted for write access
+ * 0: Access from master is not forced to user mode
+ */
+ for (i = 0; i < AIPSTZ_OAPCR_COUNT; i++) {
+ addr = (uintptr_t)&aips_regs->aipstz_opacr[i];
+ mmio_write_32(addr, 0x00000000);
+ }
+}
+
+void imx_aips_init(void)
+{
+ int i;
+ struct aipstz_regs *aips_regs[] = {
+ (struct aipstz_regs *)(AIPS1_BASE + AIPSTZ_CONFIG_OFFSET),
+ (struct aipstz_regs *)(AIPS2_BASE + AIPSTZ_CONFIG_OFFSET),
+ (struct aipstz_regs *)(AIPS3_BASE + AIPSTZ_CONFIG_OFFSET),
+ };
+
+ for (i = 0; i < ARRAY_SIZE(aips_regs); i++)
+ imx_aips_set_default_access(aips_regs[i]);
+}
diff --git a/plat/imx/common/imx_caam.c b/plat/imx/common/imx_caam.c
new file mode 100644
index 0000000..d9c141f
--- /dev/null
+++ b/plat/imx/common/imx_caam.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <lib/mmio.h>
+
+#include <imx_caam.h>
+
+void imx_caam_init(void)
+{
+ struct caam_ctrl *caam = (struct caam_ctrl *)CAAM_AIPS_BASE;
+ uint32_t reg;
+ int i;
+
+ for (i = 0; i < CAAM_NUM_JOB_RINGS; i++) {
+ reg = mmio_read_32((uintptr_t)&caam->jr[i].jrmidr_ms);
+ reg |= JROWN_NS | JROWN_MID;
+ mmio_write_32((uintptr_t)&caam->jr[i].jrmidr_ms, reg);
+ }
+}
diff --git a/plat/imx/common/imx_clock.c b/plat/imx/common/imx_clock.c
new file mode 100644
index 0000000..743de55
--- /dev/null
+++ b/plat/imx/common/imx_clock.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <arch.h>
+#include <lib/mmio.h>
+
+#include <imx_regs.h>
+#include <imx_clock.h>
+
+void imx_clock_target_set(unsigned int id, uint32_t val)
+{
+ struct ccm *ccm = ((struct ccm *)CCM_BASE);
+ uintptr_t addr;
+
+ if (id > CCM_ROOT_CTRL_NUM)
+ return;
+
+ addr = (uintptr_t)&ccm->ccm_root_ctrl[id].ccm_target_root;
+ mmio_write_32(addr, val);
+}
+
+void imx_clock_target_clr(unsigned int id, uint32_t val)
+{
+ struct ccm *ccm = ((struct ccm *)CCM_BASE);
+ uintptr_t addr;
+
+ if (id > CCM_ROOT_CTRL_NUM)
+ return;
+
+ addr = (uintptr_t)&ccm->ccm_root_ctrl[id].ccm_target_root_clr;
+ mmio_write_32(addr, val);
+}
+
+void imx_clock_gate_enable(unsigned int id, bool enable)
+{
+ struct ccm *ccm = ((struct ccm *)CCM_BASE);
+ uintptr_t addr;
+
+ if (id > CCM_CLK_GATE_CTRL_NUM)
+ return;
+
+ /* TODO: add support for more than DOMAIN0 clocks */
+ if (enable)
+ addr = (uintptr_t)&ccm->ccm_clk_gate_ctrl[id].ccm_ccgr_set;
+ else
+ addr = (uintptr_t)&ccm->ccm_clk_gate_ctrl[id].ccm_ccgr_clr;
+
+ mmio_write_32(addr, CCM_CCGR_SETTING0_DOM_CLK_ALWAYS);
+}
+
+void imx_clock_enable_uart(unsigned int uart_id, uint32_t uart_clk_en_bits)
+{
+ unsigned int ccm_trgt_id = CCM_TRT_ID_UART1_CLK_ROOT + uart_id;
+ unsigned int ccm_ccgr_id = CCM_CCGR_ID_UART1 + uart_id;
+
+ /* Check for error */
+ if (uart_id > MXC_MAX_UART_NUM)
+ return;
+
+ /* Set target register values */
+ imx_clock_target_set(ccm_trgt_id, uart_clk_en_bits);
+
+ /* Enable the clock gate */
+ imx_clock_gate_enable(ccm_ccgr_id, true);
+}
+
+void imx_clock_disable_uart(unsigned int uart_id)
+{
+ unsigned int ccm_trgt_id = CCM_TRT_ID_UART1_CLK_ROOT + uart_id;
+ unsigned int ccm_ccgr_id = CCM_CCGR_ID_UART1 + uart_id;
+
+ /* Check for error */
+ if (uart_id > MXC_MAX_UART_NUM)
+ return;
+
+ /* Disable the clock gate */
+ imx_clock_gate_enable(ccm_ccgr_id, false);
+
+ /* Clear the target */
+ imx_clock_target_clr(ccm_trgt_id, 0xFFFFFFFF);
+}
+
+void imx_clock_enable_usdhc(unsigned int usdhc_id, uint32_t usdhc_clk_en_bits)
+{
+ unsigned int ccm_trgt_id = CCM_TRT_ID_USDHC1_CLK_ROOT + usdhc_id;
+ unsigned int ccm_ccgr_id = CCM_CCGR_ID_USBHDC1 + usdhc_id;
+
+ /* Check for error */
+ if (usdhc_id > MXC_MAX_USDHC_NUM)
+ return;
+
+ /* Set target register values */
+ imx_clock_target_set(ccm_trgt_id, usdhc_clk_en_bits);
+
+ /* Enable the clock gate */
+ imx_clock_gate_enable(ccm_ccgr_id, true);
+}
+
+void imx_clock_enable_wdog(unsigned int wdog_id)
+{
+ unsigned int ccm_ccgr_id = CCM_CCGR_ID_WDOG1 + wdog_id;
+
+ /* Check for error */
+ if (wdog_id > MXC_MAX_WDOG_NUM)
+ return;
+
+ /* Enable the clock gate */
+ imx_clock_gate_enable(ccm_ccgr_id, true);
+}
+
+void imx_clock_disable_wdog(unsigned int wdog_id)
+{
+ unsigned int ccm_trgt_id = CCM_TRT_ID_WDOG_CLK_ROOT;
+ unsigned int ccm_ccgr_id = CCM_CCGR_ID_WDOG1 + wdog_id;
+
+ /* Check for error */
+ if (wdog_id > MXC_MAX_WDOG_NUM)
+ return;
+
+ /* Disable the clock gate */
+ imx_clock_gate_enable(ccm_ccgr_id, false);
+
+ /* Clear the target */
+ imx_clock_target_clr(ccm_trgt_id, 0xFFFFFFFF);
+}
+
+void imx_clock_set_wdog_clk_root_bits(uint32_t wdog_clk_root_en_bits)
+{
+ /* Enable the common clock root just once */
+ imx_clock_target_set(CCM_TRT_ID_WDOG_CLK_ROOT, wdog_clk_root_en_bits);
+}
+
+void imx_clock_enable_usb(unsigned int ccm_ccgr_usb_id)
+{
+ /* Enable the clock gate */
+ imx_clock_gate_enable(ccm_ccgr_usb_id, true);
+}
+
+void imx_clock_disable_usb(unsigned int ccm_ccgr_usb_id)
+{
+ /* Disable the clock gate */
+ imx_clock_gate_enable(ccm_ccgr_usb_id, false);
+}
+
+void imx_clock_set_usb_clk_root_bits(uint32_t usb_clk_root_en_bits)
+{
+ /* Enable the common clock root just once */
+ imx_clock_target_set(CCM_TRT_ID_USB_HSIC_CLK_ROOT, usb_clk_root_en_bits);
+}
diff --git a/plat/imx/common/imx_csu.c b/plat/imx/common/imx_csu.c
new file mode 100644
index 0000000..7e165d9
--- /dev/null
+++ b/plat/imx/common/imx_csu.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <imx_csu.h>
+#include <imx_regs.h>
+
+void imx_csu_init(void)
+{
+ int i;
+ uintptr_t *csl_reg = (uintptr_t *)CSU_BASE;
+
+ for (i = 0; i < MXC_MAX_CSU_REGS; i++, csl_reg++)
+ mmio_write_32((uintptr_t)csl_reg, CSU_CSL_OPEN_ACCESS);
+}
diff --git a/plat/imx/common/imx_ehf.c b/plat/imx/common/imx_ehf.c
new file mode 100644
index 0000000..a9396cd
--- /dev/null
+++ b/plat/imx/common/imx_ehf.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl31/ehf.h>
+
+#include <platform_def.h>
+
+ehf_pri_desc_t imx_exceptions[] = {
+#if SDEI_SUPPORT
+ /* Critical priority SDEI */
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_CRITICAL_PRI),
+
+ /* Normal priority SDEI */
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI),
+#endif
+};
+
+/* Plug in ARM exceptions to Exception Handling Framework. */
+EHF_REGISTER_PRIORITIES(imx_exceptions, ARRAY_SIZE(imx_exceptions), PLAT_PRI_BITS);
diff --git a/plat/imx/common/imx_io_mux.c b/plat/imx/common/imx_io_mux.c
new file mode 100644
index 0000000..75de5d1
--- /dev/null
+++ b/plat/imx/common/imx_io_mux.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <imx_regs.h>
+#include <imx_io_mux.h>
+
+void imx_io_muxc_set_pad_alt_function(uint32_t pad_mux_offset, uint32_t alt_function)
+{
+ uintptr_t addr = (uintptr_t)(MXC_IO_MUXC_BASE + pad_mux_offset);
+
+ mmio_write_32(addr, alt_function);
+}
+
+void imx_io_muxc_set_pad_features(uint32_t pad_feature_offset, uint32_t pad_features)
+{
+ uintptr_t addr = (uintptr_t)(MXC_IO_MUXC_BASE + pad_feature_offset);
+
+ mmio_write_32(addr, pad_features);
+}
diff --git a/plat/imx/common/imx_io_storage.c b/plat/imx/common/imx_io_storage.c
new file mode 100644
index 0000000..bb35662
--- /dev/null
+++ b/plat/imx/common/imx_io_storage.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/mmc.h>
+#include <lib/utils_def.h>
+#include <tbbr_img_def.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+
+#ifndef IMX_FIP_MMAP
+static const io_dev_connector_t *mmc_dev_con;
+static uintptr_t mmc_dev_handle;
+
+static const io_block_spec_t mmc_fip_spec = {
+ .offset = IMX_FIP_MMC_BASE,
+ .length = IMX_FIP_SIZE
+};
+
+static const io_block_dev_spec_t mmc_dev_spec = {
+ /* It's used as temp buffer in block driver. */
+ .buffer = {
+ .offset = IMX_FIP_BASE,
+ /* do we need a new value? */
+ .length = IMX_FIP_SIZE
+ },
+ .ops = {
+ .read = mmc_read_blocks,
+ .write = mmc_write_blocks,
+ },
+ .block_size = MMC_BLOCK_SIZE,
+};
+
+static int open_mmc(const uintptr_t spec);
+
+#else
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+ .offset = IMX_FIP_BASE,
+ .length = IMX_FIP_SIZE
+};
+static int open_memmap(const uintptr_t spec);
+#endif
+
+static int open_fip(const uintptr_t spec);
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_content_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* TODO: this structure is replicated multiple times. rationalize it ! */
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+#ifndef IMX_FIP_MMAP
+ [FIP_IMAGE_ID] = {
+ &mmc_dev_handle,
+ (uintptr_t)&mmc_fip_spec,
+ open_mmc
+ },
+#else
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+#endif
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_content_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ open_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+#ifndef IMX_FIP_MMAP
+static int open_mmc(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_handle;
+
+ result = io_dev_init(mmc_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(mmc_dev_handle, spec, &local_handle);
+ if (result == 0) {
+ io_close(local_handle);
+ }
+ }
+ return result;
+}
+#else
+static int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+#endif
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ assert(result == 0);
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *policy->dev_handle;
+
+ return result;
+}
+
+void plat_imx_io_setup(void)
+{
+ int result __unused;
+
+#ifndef IMX_FIP_MMAP
+ result = register_io_dev_block(&mmc_dev_con);
+ assert(result == 0);
+
+ result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_dev_spec,
+ &mmc_dev_handle);
+ assert(result == 0);
+
+#else
+ result = register_io_dev_memmap(&memmap_dev_con);
+ assert(result == 0);
+
+ result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+ assert(result == 0);
+#endif
+
+ result = register_io_dev_fip(&fip_dev_con);
+ assert(result == 0);
+
+ result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ assert(result == 0);
+}
diff --git a/plat/imx/common/imx_sdei.c b/plat/imx/common/imx_sdei.c
new file mode 100644
index 0000000..4b6033f
--- /dev/null
+++ b/plat/imx/common/imx_sdei.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* SDEI configuration for ARM platforms */
+
+#include <bl31/ehf.h>
+#include <common/debug.h>
+#include <services/sdei.h>
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+
+/* Private event mappings */
+static sdei_ev_map_t imx_sdei_private[] = {
+ SDEI_DEFINE_EVENT_0(PLAT_SDEI_SGI_PRIVATE),
+};
+
+/* Shared event mappings */
+static sdei_ev_map_t imx_sdei_shared[] = {
+};
+
+void plat_sdei_setup(void)
+{
+ INFO("SDEI platform setup\n");
+}
+
+/* Export ARM SDEI events */
+REGISTER_SDEI_MAP(imx_sdei_private, imx_sdei_shared);
diff --git a/plat/imx/common/imx_sip_handler.c b/plat/imx/common/imx_sip_handler.c
new file mode 100644
index 0000000..d4b3425
--- /dev/null
+++ b/plat/imx/common/imx_sip_handler.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2019 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <services/std_svc.h>
+#include <string.h>
+#include <platform_def.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <imx_sip_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <sci/sci.h>
+
+#if defined(PLAT_imx8qm) || defined(PLAT_imx8qx)
+
+#ifdef PLAT_imx8qm
+const static int ap_cluster_index[PLATFORM_CLUSTER_COUNT] = {
+ SC_R_A53, SC_R_A72,
+};
+#endif
+
+static int imx_srtc_set_time(uint32_t year_mon,
+ unsigned long day_hour,
+ unsigned long min_sec)
+{
+ return sc_timer_set_rtc_time(ipc_handle,
+ year_mon >> 16, year_mon & 0xffff,
+ day_hour >> 16, day_hour & 0xffff,
+ min_sec >> 16, min_sec & 0xffff);
+}
+
+int imx_srtc_handler(uint32_t smc_fid,
+ void *handle,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4)
+{
+ int ret;
+
+ switch (x1) {
+ case IMX_SIP_SRTC_SET_TIME:
+ ret = imx_srtc_set_time(x2, x3, x4);
+ break;
+ default:
+ ret = SMC_UNK;
+ }
+
+ SMC_RET1(handle, ret);
+}
+
+static void imx_cpufreq_set_target(uint32_t cluster_id, unsigned long freq)
+{
+ sc_pm_clock_rate_t rate = (sc_pm_clock_rate_t)freq;
+
+#ifdef PLAT_imx8qm
+ sc_pm_set_clock_rate(ipc_handle, ap_cluster_index[cluster_id], SC_PM_CLK_CPU, &rate);
+#endif
+#ifdef PLAT_imx8qx
+ sc_pm_set_clock_rate(ipc_handle, SC_R_A35, SC_PM_CLK_CPU, &rate);
+#endif
+}
+
+int imx_cpufreq_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3)
+{
+ switch (x1) {
+ case IMX_SIP_SET_CPUFREQ:
+ imx_cpufreq_set_target(x2, x3);
+ break;
+ default:
+ return SMC_UNK;
+ }
+
+ return 0;
+}
+
+static bool wakeup_src_irqsteer;
+
+bool imx_is_wakeup_src_irqsteer(void)
+{
+ return wakeup_src_irqsteer;
+}
+
+int imx_wakeup_src_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3)
+{
+ switch (x1) {
+ case IMX_SIP_WAKEUP_SRC_IRQSTEER:
+ wakeup_src_irqsteer = true;
+ break;
+ case IMX_SIP_WAKEUP_SRC_SCU:
+ wakeup_src_irqsteer = false;
+ break;
+ default:
+ return SMC_UNK;
+ }
+
+ return SMC_OK;
+}
+
+int imx_otp_handler(uint32_t smc_fid,
+ void *handle,
+ u_register_t x1,
+ u_register_t x2)
+{
+ int ret;
+ uint32_t fuse;
+
+ switch (smc_fid) {
+ case IMX_SIP_OTP_READ:
+ ret = sc_misc_otp_fuse_read(ipc_handle, x1, &fuse);
+ SMC_RET2(handle, ret, fuse);
+ break;
+ case IMX_SIP_OTP_WRITE:
+ ret = sc_misc_otp_fuse_write(ipc_handle, x1, x2);
+ SMC_RET1(handle, ret);
+ break;
+ default:
+ ret = SMC_UNK;
+ SMC_RET1(handle, ret);
+ break;
+ }
+
+ return ret;
+}
+
+int imx_misc_set_temp_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4)
+{
+ return sc_misc_set_temp(ipc_handle, x1, x2, x3, x4);
+}
+
+#endif /* defined(PLAT_imx8qm) || defined(PLAT_imx8qx) */
+
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq)
+int imx_src_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ void *handle)
+{
+ uint32_t val;
+
+ switch (x1) {
+ case IMX_SIP_SRC_SET_SECONDARY_BOOT:
+ if (x2 != 0U) {
+ mmio_setbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET,
+ SRC_GPR10_PERSIST_SECONDARY_BOOT);
+ } else {
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_GPR10_OFFSET,
+ SRC_GPR10_PERSIST_SECONDARY_BOOT);
+ }
+ break;
+ case IMX_SIP_SRC_IS_SECONDARY_BOOT:
+ val = mmio_read_32(IMX_SRC_BASE + SRC_GPR10_OFFSET);
+ return !!(val & SRC_GPR10_PERSIST_SECONDARY_BOOT);
+ default:
+ return SMC_UNK;
+
+ };
+
+ return 0;
+}
+#endif /* defined(PLAT_imx8mm) || defined(PLAT_imx8mq) */
+
+static uint64_t imx_get_commit_hash(u_register_t x2,
+ u_register_t x3,
+ u_register_t x4)
+{
+ /* Parse the version_string */
+ char *parse = (char *)version_string;
+ uint64_t hash = 0;
+
+ do {
+ parse = strchr(parse, '-');
+ if (parse) {
+ parse += 1;
+ if (*(parse) == 'g') {
+ /* Default is 7 hexadecimal digits */
+ memcpy((void *)&hash, (void *)(parse + 1), 7);
+ break;
+ }
+ }
+
+ } while (parse != NULL);
+
+ return hash;
+}
+
+uint64_t imx_buildinfo_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4)
+{
+ uint64_t ret;
+
+ switch (x1) {
+ case IMX_SIP_BUILDINFO_GET_COMMITHASH:
+ ret = imx_get_commit_hash(x2, x3, x4);
+ break;
+ default:
+ return SMC_UNK;
+ }
+
+ return ret;
+}
+
+int imx_kernel_entry_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4)
+{
+ static entry_point_info_t bl33_image_ep_info;
+ entry_point_info_t *next_image_info;
+ unsigned int mode;
+
+ if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000))
+ return SMC_UNK;
+
+ mode = MODE32_svc;
+
+ next_image_info = &bl33_image_ep_info;
+
+ next_image_info->pc = x1;
+
+ next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
+ (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
+
+ next_image_info->args.arg0 = 0;
+ next_image_info->args.arg1 = 0;
+ next_image_info->args.arg2 = x3;
+
+ SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+ cm_init_my_context(next_image_info);
+ cm_prepare_el3_exit(NON_SECURE);
+
+ return 0;
+}
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
new file mode 100644
index 0000000..11d02f3
--- /dev/null
+++ b/plat/imx/common/imx_sip_svc.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/pmf/pmf.h>
+#include <tools_share/uuid.h>
+#include <imx_sip_svc.h>
+
+static int32_t imx_sip_setup(void)
+{
+ return 0;
+}
+
+static uintptr_t imx_sip_handler(unsigned int smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ switch (smc_fid) {
+ case IMX_SIP_AARCH32:
+ SMC_RET1(handle, imx_kernel_entry_handler(smc_fid, x1, x2, x3, x4));
+ break;
+#if defined(PLAT_imx8mq)
+ case IMX_SIP_GET_SOC_INFO:
+ SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));
+ break;
+#endif
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+ case IMX_SIP_DDR_DVFS:
+ return dram_dvfs_handler(smc_fid, handle, x1, x2, x3);
+ case IMX_SIP_GPC:
+ SMC_RET1(handle, imx_gpc_handler(smc_fid, x1, x2, x3));
+ break;
+#endif
+#if (defined(PLAT_imx8qm) || defined(PLAT_imx8qx))
+ case IMX_SIP_SRTC:
+ return imx_srtc_handler(smc_fid, handle, x1, x2, x3, x4);
+ case IMX_SIP_CPUFREQ:
+ SMC_RET1(handle, imx_cpufreq_handler(smc_fid, x1, x2, x3));
+ break;
+ case IMX_SIP_WAKEUP_SRC:
+ SMC_RET1(handle, imx_wakeup_src_handler(smc_fid, x1, x2, x3));
+ case IMX_SIP_OTP_READ:
+ case IMX_SIP_OTP_WRITE:
+ return imx_otp_handler(smc_fid, handle, x1, x2);
+ case IMX_SIP_MISC_SET_TEMP:
+ SMC_RET1(handle, imx_misc_set_temp_handler(smc_fid, x1, x2, x3, x4));
+#endif
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq)
+ case IMX_SIP_SRC:
+ SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3, handle));
+ break;
+#endif
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+ case IMX_SIP_HAB:
+ SMC_RET1(handle, imx_hab_handler(smc_fid, x1, x2, x3, x4));
+ break;
+#endif
+ case IMX_SIP_BUILDINFO:
+ SMC_RET1(handle, imx_buildinfo_handler(smc_fid, x1, x2, x3, x4));
+ default:
+ WARN("Unimplemented i.MX SiP Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ break;
+ }
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ imx_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ imx_sip_setup,
+ imx_sip_handler
+);
diff --git a/plat/imx/common/imx_snvs.c b/plat/imx/common/imx_snvs.c
new file mode 100644
index 0000000..9b3a737
--- /dev/null
+++ b/plat/imx/common/imx_snvs.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <imx_regs.h>
+#include <imx_snvs.h>
+
+void imx_snvs_init(void)
+{
+ struct snvs *snvs = (struct snvs *)SNVS_BASE;
+ uintptr_t addr;
+ uint32_t val;
+
+ addr = (uintptr_t)&snvs->hpcomr;
+ val = mmio_read_32(addr);
+ val |= HPCOMR_NPSWA_EN;
+ mmio_write_32(addr, val);
+}
diff --git a/plat/imx/common/imx_uart_console.S b/plat/imx/common/imx_uart_console.S
new file mode 100644
index 0000000..ceeb3a7
--- /dev/null
+++ b/plat/imx/common/imx_uart_console.S
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <console_macros.S>
+#include <assert_macros.S>
+#include "imx_uart.h"
+
+#define URXD 0x0 /* Receiver Register */
+#define UTXD 0x40 /* Transmitter Register */
+#define UTS 0xb4 /* UART Test Register (mx31) */
+#define URXD_RX_DATA (0xFF)
+
+ .globl console_imx_uart_register
+ .globl console_imx_uart_init
+ .globl console_imx_uart_putc
+ .globl console_imx_uart_getc
+ .globl console_imx_uart_flush
+
+func console_imx_uart_register
+ mov x7, x30
+ mov x6, x3
+ cbz x6, register_fail
+ str x0, [x6, #CONSOLE_T_BASE]
+
+ bl console_imx_uart_init
+ cbz x0, register_fail
+
+ mov x0, x6
+ mov x30, x7
+ finish_console_register imx_uart putc=1, getc=1, flush=1
+
+register_fail:
+ ret x7
+endfunc console_imx_uart_register
+
+func console_imx_uart_init
+ mov w0, #1
+ ret
+endfunc console_imx_uart_init
+
+func console_imx_uart_putc
+ ldr x1, [x1, #CONSOLE_T_BASE]
+ cbz x1, putc_error
+
+ /* Prepare '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne 2f
+1:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #UTS]
+ tbz w2, #6, 1b
+ mov w2, #0xD
+ str w2, [x1, #UTXD]
+2:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #UTS]
+ tbz w2, #6, 2b
+ str w0, [x1, #UTXD]
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+endfunc console_imx_uart_putc
+
+func console_imx_uart_getc
+ ldr x0, [x0, #CONSOLE_T_BASE]
+ cbz x0, getc_error
+1:
+ ldr w1, [x0, #UTS]
+ tbnz w1, #5, 1b
+
+ ldr w1, [x0, #URXD]
+ and w0, w1, #URXD_RX_DATA
+
+ ret
+getc_error:
+ mov w0, #-1
+ ret
+endfunc console_imx_uart_getc
+
+func console_imx_uart_flush
+ ret
+endfunc console_imx_uart_flush
diff --git a/plat/imx/common/imx_wdog.c b/plat/imx/common/imx_wdog.c
new file mode 100644
index 0000000..af6d767
--- /dev/null
+++ b/plat/imx/common/imx_wdog.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <imx_regs.h>
+#include <imx_wdog.h>
+
+static void imx_wdog_power_down(unsigned long base)
+{
+ struct wdog_regs *wdog = (struct wdog_regs *)base;
+
+ mmio_write_16((uintptr_t)&wdog->wmcr, 0);
+}
+
+void imx_wdog_init(void)
+{
+ imx_wdog_power_down(WDOG1_BASE);
+ imx_wdog_power_down(WDOG2_BASE);
+ imx_wdog_power_down(WDOG3_BASE);
+ imx_wdog_power_down(WDOG4_BASE);
+}
diff --git a/plat/imx/common/include/imx8_iomux.h b/plat/imx/common/include/imx8_iomux.h
new file mode 100644
index 0000000..264c295
--- /dev/null
+++ b/plat/imx/common/include/imx8_iomux.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8_IOMUX_H
+#define IMX8_IOMUX_H
+
+#define PADRING_IFMUX_EN_SHIFT U(31)
+#define PADRING_IFMUX_EN_MASK (U(0x1) << PADRING_IFMUX_EN_SHIFT)
+#define PADRING_GP_EN_SHIFT U(30)
+#define PADRING_GP_EN_MASK (U(0x1) << PADRING_GP_EN_SHIFT)
+#define PADRING_IFMUX_SHIFT U(27)
+#define PADRING_IFMUX_MASK (U(0x7) << PADRING_IFMUX_SHIFT)
+#define PADRING_CONFIG_SHIFT U(25)
+#define PADRING_CONFIG_MASK (U(0x3) << PADRING_CONFIG_SHIFT)
+#define PADRING_LPCONFIG_SHIFT U(23)
+#define PADRING_LPCONFIG_MASK (U(0x3) << PADRING_LPCONFIG_SHIFT)
+#define PADRING_PULL_SHIFT U(5)
+#define PADRING_PULL_MASK (U(0x3) << PADRING_PULL_SHIFT)
+#define PADRING_DSE_SHIFT U(0)
+#define PADRING_DSE_MASK (U(0x7) << PADRING_DSE_SHIFT)
+
+#endif /* IMX8_IOMUX_H */
diff --git a/plat/imx/common/include/imx8_lpuart.h b/plat/imx/common/include/imx8_lpuart.h
new file mode 100644
index 0000000..26470e0
--- /dev/null
+++ b/plat/imx/common/include/imx8_lpuart.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8_LPUART_H
+#define IMX8_LPUART_H
+
+#include <drivers/console.h>
+
+#define VERID 0x0
+#define PARAM 0x4
+#define GLOBAL 0x8
+#define PINCFG 0xC
+#define BAUD 0x10
+#define STAT 0x14
+#define CTRL 0x18
+#define DATA 0x1C
+#define MATCH 0x20
+#define MODIR 0x24
+#define FIFO 0x28
+#define WATER 0x2c
+
+#define US1_TDRE (1 << 23)
+#define US1_RDRF (1 << 21)
+
+#define CTRL_TE (1 << 19)
+#define CTRL_RE (1 << 18)
+
+#define FIFO_TXFE 0x80
+#define FIFO_RXFE 0x40
+
+#define WATER_TXWATER_OFF 1
+#define WATER_RXWATER_OFF 16
+
+#define LPUART_CTRL_PT_MASK 0x1
+#define LPUART_CTRL_PE_MASK 0x2
+#define LPUART_CTRL_M_MASK 0x10
+
+#define LPUART_BAUD_OSR_MASK (0x1F000000U)
+#define LPUART_BAUD_OSR_SHIFT (24U)
+#define LPUART_BAUD_OSR(x) (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_OSR_SHIFT)) & LPUART_BAUD_OSR_MASK)
+
+#define LPUART_BAUD_SBR_MASK (0x1FFFU)
+#define LPUART_BAUD_SBR_SHIFT (0U)
+#define LPUART_BAUD_SBR(x) (((uint32_t)(((uint32_t)(x)) << LPUART_BAUD_SBR_SHIFT)) & LPUART_BAUD_SBR_MASK)
+
+#define LPUART_BAUD_SBNS_MASK (0x2000U)
+#define LPUART_BAUD_BOTHEDGE_MASK (0x20000U)
+#define LPUART_BAUD_M10_MASK (0x20000000U)
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+int console_lpuart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+ console_t *console);
+#endif /*__ASSEMBLER__*/
+
+#endif /* IMX8_LPUART_H */
diff --git a/plat/imx/common/include/imx8qm_pads.h b/plat/imx/common/include/imx8qm_pads.h
new file mode 100644
index 0000000..a5c1d2c
--- /dev/null
+++ b/plat/imx/common/include/imx8qm_pads.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file used to configure SoC pad list.
+ */
+
+#ifndef IMX8QM_PADS_H
+#define IMX8QM_PADS_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Pad Definitions
+ */
+/*@{*/
+#define SC_P_SIM0_CLK 0 /* DMA.SIM0.CLK, LSIO.GPIO0.IO00 */
+#define SC_P_SIM0_RST 1 /* DMA.SIM0.RST, LSIO.GPIO0.IO01 */
+#define SC_P_SIM0_IO 2 /* DMA.SIM0.IO, LSIO.GPIO0.IO02 */
+#define SC_P_SIM0_PD 3 /* DMA.SIM0.PD, DMA.I2C3.SCL, LSIO.GPIO0.IO03 */
+#define SC_P_SIM0_POWER_EN 4 /* DMA.SIM0.POWER_EN, DMA.I2C3.SDA, LSIO.GPIO0.IO04 */
+#define SC_P_SIM0_GPIO0_00 5 /* DMA.SIM0.POWER_EN, LSIO.GPIO0.IO05 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SIM 6 /* */
+#define SC_P_M40_I2C0_SCL 7 /* M40.I2C0.SCL, M40.UART0.RX, M40.GPIO0.IO02, LSIO.GPIO0.IO06 */
+#define SC_P_M40_I2C0_SDA 8 /* M40.I2C0.SDA, M40.UART0.TX, M40.GPIO0.IO03, LSIO.GPIO0.IO07 */
+#define SC_P_M40_GPIO0_00 9 /* M40.GPIO0.IO00, M40.TPM0.CH0, DMA.UART4.RX, LSIO.GPIO0.IO08 */
+#define SC_P_M40_GPIO0_01 10 /* M40.GPIO0.IO01, M40.TPM0.CH1, DMA.UART4.TX, LSIO.GPIO0.IO09 */
+#define SC_P_M41_I2C0_SCL 11 /* M41.I2C0.SCL, M41.UART0.RX, M41.GPIO0.IO02, LSIO.GPIO0.IO10 */
+#define SC_P_M41_I2C0_SDA 12 /* M41.I2C0.SDA, M41.UART0.TX, M41.GPIO0.IO03, LSIO.GPIO0.IO11 */
+#define SC_P_M41_GPIO0_00 13 /* M41.GPIO0.IO00, M41.TPM0.CH0, DMA.UART3.RX, LSIO.GPIO0.IO12 */
+#define SC_P_M41_GPIO0_01 14 /* M41.GPIO0.IO01, M41.TPM0.CH1, DMA.UART3.TX, LSIO.GPIO0.IO13 */
+#define SC_P_GPT0_CLK 15 /* LSIO.GPT0.CLK, DMA.I2C1.SCL, LSIO.KPP0.COL4, LSIO.GPIO0.IO14 */
+#define SC_P_GPT0_CAPTURE 16 /* LSIO.GPT0.CAPTURE, DMA.I2C1.SDA, LSIO.KPP0.COL5, LSIO.GPIO0.IO15 */
+#define SC_P_GPT0_COMPARE 17 /* LSIO.GPT0.COMPARE, LSIO.PWM3.OUT, LSIO.KPP0.COL6, LSIO.GPIO0.IO16 */
+#define SC_P_GPT1_CLK 18 /* LSIO.GPT1.CLK, DMA.I2C2.SCL, LSIO.KPP0.COL7, LSIO.GPIO0.IO17 */
+#define SC_P_GPT1_CAPTURE 19 /* LSIO.GPT1.CAPTURE, DMA.I2C2.SDA, LSIO.KPP0.ROW4, LSIO.GPIO0.IO18 */
+#define SC_P_GPT1_COMPARE 20 /* LSIO.GPT1.COMPARE, LSIO.PWM2.OUT, LSIO.KPP0.ROW5, LSIO.GPIO0.IO19 */
+#define SC_P_UART0_RX 21 /* DMA.UART0.RX, SCU.UART0.RX, LSIO.GPIO0.IO20 */
+#define SC_P_UART0_TX 22 /* DMA.UART0.TX, SCU.UART0.TX, LSIO.GPIO0.IO21 */
+#define SC_P_UART0_RTS_B 23 /* DMA.UART0.RTS_B, LSIO.PWM0.OUT, DMA.UART2.RX, LSIO.GPIO0.IO22 */
+#define SC_P_UART0_CTS_B 24 /* DMA.UART0.CTS_B, LSIO.PWM1.OUT, DMA.UART2.TX, LSIO.GPIO0.IO23 */
+#define SC_P_UART1_TX 25 /* DMA.UART1.TX, DMA.SPI3.SCK, LSIO.GPIO0.IO24 */
+#define SC_P_UART1_RX 26 /* DMA.UART1.RX, DMA.SPI3.SDO, LSIO.GPIO0.IO25 */
+#define SC_P_UART1_RTS_B 27 /* DMA.UART1.RTS_B, DMA.SPI3.SDI, DMA.UART1.CTS_B, LSIO.GPIO0.IO26 */
+#define SC_P_UART1_CTS_B 28 /* DMA.UART1.CTS_B, DMA.SPI3.CS0, DMA.UART1.RTS_B, LSIO.GPIO0.IO27 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH 29 /* */
+#define SC_P_SCU_PMIC_MEMC_ON 30 /* SCU.GPIO0.IOXX_PMIC_MEMC_ON */
+#define SC_P_SCU_WDOG_OUT 31 /* SCU.WDOG0.WDOG_OUT */
+#define SC_P_PMIC_I2C_SDA 32 /* SCU.PMIC_I2C.SDA */
+#define SC_P_PMIC_I2C_SCL 33 /* SCU.PMIC_I2C.SCL */
+#define SC_P_PMIC_EARLY_WARNING 34 /* SCU.PMIC_EARLY_WARNING */
+#define SC_P_PMIC_INT_B 35 /* SCU.DSC.PMIC_INT_B */
+#define SC_P_SCU_GPIO0_00 36 /* SCU.GPIO0.IO00, SCU.UART0.RX, LSIO.GPIO0.IO28 */
+#define SC_P_SCU_GPIO0_01 37 /* SCU.GPIO0.IO01, SCU.UART0.TX, LSIO.GPIO0.IO29 */
+#define SC_P_SCU_GPIO0_02 38 /* SCU.GPIO0.IO02, SCU.GPIO0.IOXX_PMIC_GPU0_ON, LSIO.GPIO0.IO30 */
+#define SC_P_SCU_GPIO0_03 39 /* SCU.GPIO0.IO03, SCU.GPIO0.IOXX_PMIC_GPU1_ON, LSIO.GPIO0.IO31 */
+#define SC_P_SCU_GPIO0_04 40 /* SCU.GPIO0.IO04, SCU.GPIO0.IOXX_PMIC_A72_ON, LSIO.GPIO1.IO00 */
+#define SC_P_SCU_GPIO0_05 41 /* SCU.GPIO0.IO05, SCU.GPIO0.IOXX_PMIC_A53_ON, LSIO.GPIO1.IO01 */
+#define SC_P_SCU_GPIO0_06 42 /* SCU.GPIO0.IO06, SCU.TPM0.CH0, LSIO.GPIO1.IO02 */
+#define SC_P_SCU_GPIO0_07 43 /* SCU.GPIO0.IO07, SCU.TPM0.CH1, SCU.DSC.RTC_CLOCK_OUTPUT_32K, LSIO.GPIO1.IO03 */
+#define SC_P_SCU_BOOT_MODE0 44 /* SCU.DSC.BOOT_MODE0 */
+#define SC_P_SCU_BOOT_MODE1 45 /* SCU.DSC.BOOT_MODE1 */
+#define SC_P_SCU_BOOT_MODE2 46 /* SCU.DSC.BOOT_MODE2 */
+#define SC_P_SCU_BOOT_MODE3 47 /* SCU.DSC.BOOT_MODE3 */
+#define SC_P_SCU_BOOT_MODE4 48 /* SCU.DSC.BOOT_MODE4, SCU.PMIC_I2C.SCL */
+#define SC_P_SCU_BOOT_MODE5 49 /* SCU.DSC.BOOT_MODE5, SCU.PMIC_I2C.SDA */
+#define SC_P_LVDS0_GPIO00 50 /* LVDS0.GPIO0.IO00, LVDS0.PWM0.OUT, LSIO.GPIO1.IO04 */
+#define SC_P_LVDS0_GPIO01 51 /* LVDS0.GPIO0.IO01, LSIO.GPIO1.IO05 */
+#define SC_P_LVDS0_I2C0_SCL 52 /* LVDS0.I2C0.SCL, LVDS0.GPIO0.IO02, LSIO.GPIO1.IO06 */
+#define SC_P_LVDS0_I2C0_SDA 53 /* LVDS0.I2C0.SDA, LVDS0.GPIO0.IO03, LSIO.GPIO1.IO07 */
+#define SC_P_LVDS0_I2C1_SCL 54 /* LVDS0.I2C1.SCL, DMA.UART2.TX, LSIO.GPIO1.IO08 */
+#define SC_P_LVDS0_I2C1_SDA 55 /* LVDS0.I2C1.SDA, DMA.UART2.RX, LSIO.GPIO1.IO09 */
+#define SC_P_LVDS1_GPIO00 56 /* LVDS1.GPIO0.IO00, LVDS1.PWM0.OUT, LSIO.GPIO1.IO10 */
+#define SC_P_LVDS1_GPIO01 57 /* LVDS1.GPIO0.IO01, LSIO.GPIO1.IO11 */
+#define SC_P_LVDS1_I2C0_SCL 58 /* LVDS1.I2C0.SCL, LVDS1.GPIO0.IO02, LSIO.GPIO1.IO12 */
+#define SC_P_LVDS1_I2C0_SDA 59 /* LVDS1.I2C0.SDA, LVDS1.GPIO0.IO03, LSIO.GPIO1.IO13 */
+#define SC_P_LVDS1_I2C1_SCL 60 /* LVDS1.I2C1.SCL, DMA.UART3.TX, LSIO.GPIO1.IO14 */
+#define SC_P_LVDS1_I2C1_SDA 61 /* LVDS1.I2C1.SDA, DMA.UART3.RX, LSIO.GPIO1.IO15 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_LVDSGPIO 62 /* */
+#define SC_P_MIPI_DSI0_I2C0_SCL 63 /* MIPI_DSI0.I2C0.SCL, LSIO.GPIO1.IO16 */
+#define SC_P_MIPI_DSI0_I2C0_SDA 64 /* MIPI_DSI0.I2C0.SDA, LSIO.GPIO1.IO17 */
+#define SC_P_MIPI_DSI0_GPIO0_00 65 /* MIPI_DSI0.GPIO0.IO00, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO18 */
+#define SC_P_MIPI_DSI0_GPIO0_01 66 /* MIPI_DSI0.GPIO0.IO01, LSIO.GPIO1.IO19 */
+#define SC_P_MIPI_DSI1_I2C0_SCL 67 /* MIPI_DSI1.I2C0.SCL, LSIO.GPIO1.IO20 */
+#define SC_P_MIPI_DSI1_I2C0_SDA 68 /* MIPI_DSI1.I2C0.SDA, LSIO.GPIO1.IO21 */
+#define SC_P_MIPI_DSI1_GPIO0_00 69 /* MIPI_DSI1.GPIO0.IO00, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO22 */
+#define SC_P_MIPI_DSI1_GPIO0_01 70 /* MIPI_DSI1.GPIO0.IO01, LSIO.GPIO1.IO23 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO 71 /* */
+#define SC_P_MIPI_CSI0_MCLK_OUT 72 /* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO1.IO24 */
+#define SC_P_MIPI_CSI0_I2C0_SCL 73 /* MIPI_CSI0.I2C0.SCL, LSIO.GPIO1.IO25 */
+#define SC_P_MIPI_CSI0_I2C0_SDA 74 /* MIPI_CSI0.I2C0.SDA, LSIO.GPIO1.IO26 */
+#define SC_P_MIPI_CSI0_GPIO0_00 75 /* MIPI_CSI0.GPIO0.IO00, DMA.I2C0.SCL, MIPI_CSI1.I2C0.SCL, LSIO.GPIO1.IO27 */
+#define SC_P_MIPI_CSI0_GPIO0_01 76 /* MIPI_CSI0.GPIO0.IO01, DMA.I2C0.SDA, MIPI_CSI1.I2C0.SDA, LSIO.GPIO1.IO28 */
+#define SC_P_MIPI_CSI1_MCLK_OUT 77 /* MIPI_CSI1.ACM.MCLK_OUT, LSIO.GPIO1.IO29 */
+#define SC_P_MIPI_CSI1_GPIO0_00 78 /* MIPI_CSI1.GPIO0.IO00, DMA.UART4.RX, LSIO.GPIO1.IO30 */
+#define SC_P_MIPI_CSI1_GPIO0_01 79 /* MIPI_CSI1.GPIO0.IO01, DMA.UART4.TX, LSIO.GPIO1.IO31 */
+#define SC_P_MIPI_CSI1_I2C0_SCL 80 /* MIPI_CSI1.I2C0.SCL, LSIO.GPIO2.IO00 */
+#define SC_P_MIPI_CSI1_I2C0_SDA 81 /* MIPI_CSI1.I2C0.SDA, LSIO.GPIO2.IO01 */
+#define SC_P_HDMI_TX0_TS_SCL 82 /* HDMI_TX0.I2C0.SCL, DMA.I2C0.SCL, LSIO.GPIO2.IO02 */
+#define SC_P_HDMI_TX0_TS_SDA 83 /* HDMI_TX0.I2C0.SDA, DMA.I2C0.SDA, LSIO.GPIO2.IO03 */
+#define SC_P_COMP_CTL_GPIO_3V3_HDMIGPIO 84 /* */
+#define SC_P_ESAI1_FSR 85 /* AUD.ESAI1.FSR, LSIO.GPIO2.IO04 */
+#define SC_P_ESAI1_FST 86 /* AUD.ESAI1.FST, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO05 */
+#define SC_P_ESAI1_SCKR 87 /* AUD.ESAI1.SCKR, LSIO.GPIO2.IO06 */
+#define SC_P_ESAI1_SCKT 88 /* AUD.ESAI1.SCKT, AUD.SAI2.RXC, AUD.SPDIF0.EXT_CLK, LSIO.GPIO2.IO07 */
+#define SC_P_ESAI1_TX0 89 /* AUD.ESAI1.TX0, AUD.SAI2.RXD, AUD.SPDIF0.RX, LSIO.GPIO2.IO08 */
+#define SC_P_ESAI1_TX1 90 /* AUD.ESAI1.TX1, AUD.SAI2.RXFS, AUD.SPDIF0.TX, LSIO.GPIO2.IO09 */
+#define SC_P_ESAI1_TX2_RX3 91 /* AUD.ESAI1.TX2_RX3, AUD.SPDIF0.RX, LSIO.GPIO2.IO10 */
+#define SC_P_ESAI1_TX3_RX2 92 /* AUD.ESAI1.TX3_RX2, AUD.SPDIF0.TX, LSIO.GPIO2.IO11 */
+#define SC_P_ESAI1_TX4_RX1 93 /* AUD.ESAI1.TX4_RX1, LSIO.GPIO2.IO12 */
+#define SC_P_ESAI1_TX5_RX0 94 /* AUD.ESAI1.TX5_RX0, LSIO.GPIO2.IO13 */
+#define SC_P_SPDIF0_RX 95 /* AUD.SPDIF0.RX, AUD.MQS.R, AUD.ACM.MCLK_IN1, LSIO.GPIO2.IO14 */
+#define SC_P_SPDIF0_TX 96 /* AUD.SPDIF0.TX, AUD.MQS.L, AUD.ACM.MCLK_OUT1, LSIO.GPIO2.IO15 */
+#define SC_P_SPDIF0_EXT_CLK 97 /* AUD.SPDIF0.EXT_CLK, DMA.DMA0.REQ_IN0, LSIO.GPIO2.IO16 */
+#define SC_P_SPI3_SCK 98 /* DMA.SPI3.SCK, LSIO.GPIO2.IO17 */
+#define SC_P_SPI3_SDO 99 /* DMA.SPI3.SDO, DMA.FTM.CH0, LSIO.GPIO2.IO18 */
+#define SC_P_SPI3_SDI 100 /* DMA.SPI3.SDI, DMA.FTM.CH1, LSIO.GPIO2.IO19 */
+#define SC_P_SPI3_CS0 101 /* DMA.SPI3.CS0, DMA.FTM.CH2, LSIO.GPIO2.IO20 */
+#define SC_P_SPI3_CS1 102 /* DMA.SPI3.CS1, LSIO.GPIO2.IO21 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB 103 /* */
+#define SC_P_ESAI0_FSR 104 /* AUD.ESAI0.FSR, LSIO.GPIO2.IO22 */
+#define SC_P_ESAI0_FST 105 /* AUD.ESAI0.FST, LSIO.GPIO2.IO23 */
+#define SC_P_ESAI0_SCKR 106 /* AUD.ESAI0.SCKR, LSIO.GPIO2.IO24 */
+#define SC_P_ESAI0_SCKT 107 /* AUD.ESAI0.SCKT, LSIO.GPIO2.IO25 */
+#define SC_P_ESAI0_TX0 108 /* AUD.ESAI0.TX0, LSIO.GPIO2.IO26 */
+#define SC_P_ESAI0_TX1 109 /* AUD.ESAI0.TX1, LSIO.GPIO2.IO27 */
+#define SC_P_ESAI0_TX2_RX3 110 /* AUD.ESAI0.TX2_RX3, LSIO.GPIO2.IO28 */
+#define SC_P_ESAI0_TX3_RX2 111 /* AUD.ESAI0.TX3_RX2, LSIO.GPIO2.IO29 */
+#define SC_P_ESAI0_TX4_RX1 112 /* AUD.ESAI0.TX4_RX1, LSIO.GPIO2.IO30 */
+#define SC_P_ESAI0_TX5_RX0 113 /* AUD.ESAI0.TX5_RX0, LSIO.GPIO2.IO31 */
+#define SC_P_MCLK_IN0 114 /* AUD.ACM.MCLK_IN0, AUD.ESAI0.RX_HF_CLK, AUD.ESAI1.RX_HF_CLK, LSIO.GPIO3.IO00 */
+#define SC_P_MCLK_OUT0 115 /* AUD.ACM.MCLK_OUT0, AUD.ESAI0.TX_HF_CLK, AUD.ESAI1.TX_HF_CLK, LSIO.GPIO3.IO01 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHC 116 /* */
+#define SC_P_SPI0_SCK 117 /* DMA.SPI0.SCK, AUD.SAI0.RXC, LSIO.GPIO3.IO02 */
+#define SC_P_SPI0_SDO 118 /* DMA.SPI0.SDO, AUD.SAI0.TXD, LSIO.GPIO3.IO03 */
+#define SC_P_SPI0_SDI 119 /* DMA.SPI0.SDI, AUD.SAI0.RXD, LSIO.GPIO3.IO04 */
+#define SC_P_SPI0_CS0 120 /* DMA.SPI0.CS0, AUD.SAI0.RXFS, LSIO.GPIO3.IO05 */
+#define SC_P_SPI0_CS1 121 /* DMA.SPI0.CS1, AUD.SAI0.TXC, LSIO.GPIO3.IO06 */
+#define SC_P_SPI2_SCK 122 /* DMA.SPI2.SCK, LSIO.GPIO3.IO07 */
+#define SC_P_SPI2_SDO 123 /* DMA.SPI2.SDO, LSIO.GPIO3.IO08 */
+#define SC_P_SPI2_SDI 124 /* DMA.SPI2.SDI, LSIO.GPIO3.IO09 */
+#define SC_P_SPI2_CS0 125 /* DMA.SPI2.CS0, LSIO.GPIO3.IO10 */
+#define SC_P_SPI2_CS1 126 /* DMA.SPI2.CS1, AUD.SAI0.TXFS, LSIO.GPIO3.IO11 */
+#define SC_P_SAI1_RXC 127 /* AUD.SAI1.RXC, AUD.SAI0.TXD, LSIO.GPIO3.IO12 */
+#define SC_P_SAI1_RXD 128 /* AUD.SAI1.RXD, AUD.SAI0.TXFS, LSIO.GPIO3.IO13 */
+#define SC_P_SAI1_RXFS 129 /* AUD.SAI1.RXFS, AUD.SAI0.RXD, LSIO.GPIO3.IO14 */
+#define SC_P_SAI1_TXC 130 /* AUD.SAI1.TXC, AUD.SAI0.TXC, LSIO.GPIO3.IO15 */
+#define SC_P_SAI1_TXD 131 /* AUD.SAI1.TXD, AUD.SAI1.RXC, LSIO.GPIO3.IO16 */
+#define SC_P_SAI1_TXFS 132 /* AUD.SAI1.TXFS, AUD.SAI1.RXFS, LSIO.GPIO3.IO17 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT 133 /* */
+#define SC_P_ADC_IN7 134 /* DMA.ADC1.IN3, DMA.SPI1.CS1, LSIO.KPP0.ROW3, LSIO.GPIO3.IO25 */
+#define SC_P_ADC_IN6 135 /* DMA.ADC1.IN2, DMA.SPI1.CS0, LSIO.KPP0.ROW2, LSIO.GPIO3.IO24 */
+#define SC_P_ADC_IN5 136 /* DMA.ADC1.IN1, DMA.SPI1.SDI, LSIO.KPP0.ROW1, LSIO.GPIO3.IO23 */
+#define SC_P_ADC_IN4 137 /* DMA.ADC1.IN0, DMA.SPI1.SDO, LSIO.KPP0.ROW0, LSIO.GPIO3.IO22 */
+#define SC_P_ADC_IN3 138 /* DMA.ADC0.IN3, DMA.SPI1.SCK, LSIO.KPP0.COL3, LSIO.GPIO3.IO21 */
+#define SC_P_ADC_IN2 139 /* DMA.ADC0.IN2, LSIO.KPP0.COL2, LSIO.GPIO3.IO20 */
+#define SC_P_ADC_IN1 140 /* DMA.ADC0.IN1, LSIO.KPP0.COL1, LSIO.GPIO3.IO19 */
+#define SC_P_ADC_IN0 141 /* DMA.ADC0.IN0, LSIO.KPP0.COL0, LSIO.GPIO3.IO18 */
+#define SC_P_MLB_SIG 142 /* CONN.MLB.SIG, AUD.SAI3.RXC, LSIO.GPIO3.IO26 */
+#define SC_P_MLB_CLK 143 /* CONN.MLB.CLK, AUD.SAI3.RXFS, LSIO.GPIO3.IO27 */
+#define SC_P_MLB_DATA 144 /* CONN.MLB.DATA, AUD.SAI3.RXD, LSIO.GPIO3.IO28 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLHT 145 /* */
+#define SC_P_FLEXCAN0_RX 146 /* DMA.FLEXCAN0.RX, LSIO.GPIO3.IO29 */
+#define SC_P_FLEXCAN0_TX 147 /* DMA.FLEXCAN0.TX, LSIO.GPIO3.IO30 */
+#define SC_P_FLEXCAN1_RX 148 /* DMA.FLEXCAN1.RX, LSIO.GPIO3.IO31 */
+#define SC_P_FLEXCAN1_TX 149 /* DMA.FLEXCAN1.TX, LSIO.GPIO4.IO00 */
+#define SC_P_FLEXCAN2_RX 150 /* DMA.FLEXCAN2.RX, LSIO.GPIO4.IO01 */
+#define SC_P_FLEXCAN2_TX 151 /* DMA.FLEXCAN2.TX, LSIO.GPIO4.IO02 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOTHR 152 /* */
+#define SC_P_USB_SS3_TC0 153 /* DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO4.IO03 */
+#define SC_P_USB_SS3_TC1 154 /* DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */
+#define SC_P_USB_SS3_TC2 155 /* DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO05 */
+#define SC_P_USB_SS3_TC3 156 /* DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */
+#define SC_P_COMP_CTL_GPIO_3V3_USB3IO 157 /* */
+#define SC_P_USDHC1_RESET_B 158 /* CONN.USDHC1.RESET_B, LSIO.GPIO4.IO07 */
+#define SC_P_USDHC1_VSELECT 159 /* CONN.USDHC1.VSELECT, LSIO.GPIO4.IO08 */
+#define SC_P_USDHC2_RESET_B 160 /* CONN.USDHC2.RESET_B, LSIO.GPIO4.IO09 */
+#define SC_P_USDHC2_VSELECT 161 /* CONN.USDHC2.VSELECT, LSIO.GPIO4.IO10 */
+#define SC_P_USDHC2_WP 162 /* CONN.USDHC2.WP, LSIO.GPIO4.IO11 */
+#define SC_P_USDHC2_CD_B 163 /* CONN.USDHC2.CD_B, LSIO.GPIO4.IO12 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP 164 /* */
+#define SC_P_ENET0_MDIO 165 /* CONN.ENET0.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO13 */
+#define SC_P_ENET0_MDC 166 /* CONN.ENET0.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO14 */
+#define SC_P_ENET0_REFCLK_125M_25M 167 /* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, LSIO.GPIO4.IO15 */
+#define SC_P_ENET1_REFCLK_125M_25M 168 /* CONN.ENET1.REFCLK_125M_25M, CONN.ENET1.PPS, LSIO.GPIO4.IO16 */
+#define SC_P_ENET1_MDIO 169 /* CONN.ENET1.MDIO, DMA.I2C4.SDA, LSIO.GPIO4.IO17 */
+#define SC_P_ENET1_MDC 170 /* CONN.ENET1.MDC, DMA.I2C4.SCL, LSIO.GPIO4.IO18 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT 171 /* */
+#define SC_P_QSPI1A_SS0_B 172 /* LSIO.QSPI1A.SS0_B, LSIO.GPIO4.IO19 */
+#define SC_P_QSPI1A_SS1_B 173 /* LSIO.QSPI1A.SS1_B, LSIO.QSPI1A.SCLK2, LSIO.GPIO4.IO20 */
+#define SC_P_QSPI1A_SCLK 174 /* LSIO.QSPI1A.SCLK, LSIO.GPIO4.IO21 */
+#define SC_P_QSPI1A_DQS 175 /* LSIO.QSPI1A.DQS, LSIO.GPIO4.IO22 */
+#define SC_P_QSPI1A_DATA3 176 /* LSIO.QSPI1A.DATA3, DMA.I2C1.SDA, CONN.USB_OTG1.OC, LSIO.GPIO4.IO23 */
+#define SC_P_QSPI1A_DATA2 177 /* LSIO.QSPI1A.DATA2, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO24 */
+#define SC_P_QSPI1A_DATA1 178 /* LSIO.QSPI1A.DATA1, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO25 */
+#define SC_P_QSPI1A_DATA0 179 /* LSIO.QSPI1A.DATA0, LSIO.GPIO4.IO26 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI1 180 /* */
+#define SC_P_QSPI0A_DATA0 181 /* LSIO.QSPI0A.DATA0 */
+#define SC_P_QSPI0A_DATA1 182 /* LSIO.QSPI0A.DATA1 */
+#define SC_P_QSPI0A_DATA2 183 /* LSIO.QSPI0A.DATA2 */
+#define SC_P_QSPI0A_DATA3 184 /* LSIO.QSPI0A.DATA3 */
+#define SC_P_QSPI0A_DQS 185 /* LSIO.QSPI0A.DQS */
+#define SC_P_QSPI0A_SS0_B 186 /* LSIO.QSPI0A.SS0_B */
+#define SC_P_QSPI0A_SS1_B 187 /* LSIO.QSPI0A.SS1_B, LSIO.QSPI0A.SCLK2 */
+#define SC_P_QSPI0A_SCLK 188 /* LSIO.QSPI0A.SCLK */
+#define SC_P_QSPI0B_SCLK 189 /* LSIO.QSPI0B.SCLK */
+#define SC_P_QSPI0B_DATA0 190 /* LSIO.QSPI0B.DATA0 */
+#define SC_P_QSPI0B_DATA1 191 /* LSIO.QSPI0B.DATA1 */
+#define SC_P_QSPI0B_DATA2 192 /* LSIO.QSPI0B.DATA2 */
+#define SC_P_QSPI0B_DATA3 193 /* LSIO.QSPI0B.DATA3 */
+#define SC_P_QSPI0B_DQS 194 /* LSIO.QSPI0B.DQS */
+#define SC_P_QSPI0B_SS0_B 195 /* LSIO.QSPI0B.SS0_B */
+#define SC_P_QSPI0B_SS1_B 196 /* LSIO.QSPI0B.SS1_B, LSIO.QSPI0B.SCLK2 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0 197 /* */
+#define SC_P_PCIE_CTRL0_CLKREQ_B 198 /* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO27 */
+#define SC_P_PCIE_CTRL0_WAKE_B 199 /* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO28 */
+#define SC_P_PCIE_CTRL0_PERST_B 200 /* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO29 */
+#define SC_P_PCIE_CTRL1_CLKREQ_B 201 /* HSIO.PCIE1.CLKREQ_B, DMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO30 */
+#define SC_P_PCIE_CTRL1_WAKE_B 202 /* HSIO.PCIE1.WAKE_B, DMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO31 */
+#define SC_P_PCIE_CTRL1_PERST_B 203 /* HSIO.PCIE1.PERST_B, DMA.I2C1.SCL, CONN.USB_OTG1.PWR, LSIO.GPIO5.IO00 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP 204 /* */
+#define SC_P_USB_HSIC0_DATA 205 /* CONN.USB_HSIC0.DATA, DMA.I2C1.SDA, LSIO.GPIO5.IO01 */
+#define SC_P_USB_HSIC0_STROBE 206 /* CONN.USB_HSIC0.STROBE, DMA.I2C1.SCL, LSIO.GPIO5.IO02 */
+#define SC_P_CALIBRATION_0_HSIC 207 /* */
+#define SC_P_CALIBRATION_1_HSIC 208 /* */
+#define SC_P_EMMC0_CLK 209 /* CONN.EMMC0.CLK, CONN.NAND.READY_B */
+#define SC_P_EMMC0_CMD 210 /* CONN.EMMC0.CMD, CONN.NAND.DQS, AUD.MQS.R, LSIO.GPIO5.IO03 */
+#define SC_P_EMMC0_DATA0 211 /* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO5.IO04 */
+#define SC_P_EMMC0_DATA1 212 /* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO5.IO05 */
+#define SC_P_EMMC0_DATA2 213 /* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO5.IO06 */
+#define SC_P_EMMC0_DATA3 214 /* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO5.IO07 */
+#define SC_P_EMMC0_DATA4 215 /* CONN.EMMC0.DATA4, CONN.NAND.DATA04, LSIO.GPIO5.IO08 */
+#define SC_P_EMMC0_DATA5 216 /* CONN.EMMC0.DATA5, CONN.NAND.DATA05, LSIO.GPIO5.IO09 */
+#define SC_P_EMMC0_DATA6 217 /* CONN.EMMC0.DATA6, CONN.NAND.DATA06, LSIO.GPIO5.IO10 */
+#define SC_P_EMMC0_DATA7 218 /* CONN.EMMC0.DATA7, CONN.NAND.DATA07, LSIO.GPIO5.IO11 */
+#define SC_P_EMMC0_STROBE 219 /* CONN.EMMC0.STROBE, CONN.NAND.CLE, LSIO.GPIO5.IO12 */
+#define SC_P_EMMC0_RESET_B 220 /* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, CONN.USDHC1.VSELECT, LSIO.GPIO5.IO13 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX 221 /* */
+#define SC_P_USDHC1_CLK 222 /* CONN.USDHC1.CLK, AUD.MQS.R */
+#define SC_P_USDHC1_CMD 223 /* CONN.USDHC1.CMD, AUD.MQS.L, LSIO.GPIO5.IO14 */
+#define SC_P_USDHC1_DATA0 224 /* CONN.USDHC1.DATA0, CONN.NAND.RE_N, LSIO.GPIO5.IO15 */
+#define SC_P_USDHC1_DATA1 225 /* CONN.USDHC1.DATA1, CONN.NAND.RE_P, LSIO.GPIO5.IO16 */
+#define SC_P_CTL_NAND_RE_P_N 226 /* */
+#define SC_P_USDHC1_DATA2 227 /* CONN.USDHC1.DATA2, CONN.NAND.DQS_N, LSIO.GPIO5.IO17 */
+#define SC_P_USDHC1_DATA3 228 /* CONN.USDHC1.DATA3, CONN.NAND.DQS_P, LSIO.GPIO5.IO18 */
+#define SC_P_CTL_NAND_DQS_P_N 229 /* */
+#define SC_P_USDHC1_DATA4 230 /* CONN.USDHC1.DATA4, CONN.NAND.CE0_B, AUD.MQS.R, LSIO.GPIO5.IO19 */
+#define SC_P_USDHC1_DATA5 231 /* CONN.USDHC1.DATA5, CONN.NAND.RE_B, AUD.MQS.L, LSIO.GPIO5.IO20 */
+#define SC_P_USDHC1_DATA6 232 /* CONN.USDHC1.DATA6, CONN.NAND.WE_B, CONN.USDHC1.WP, LSIO.GPIO5.IO21 */
+#define SC_P_USDHC1_DATA7 233 /* CONN.USDHC1.DATA7, CONN.NAND.ALE, CONN.USDHC1.CD_B, LSIO.GPIO5.IO22 */
+#define SC_P_USDHC1_STROBE 234 /* CONN.USDHC1.STROBE, CONN.NAND.CE1_B, CONN.USDHC1.RESET_B, LSIO.GPIO5.IO23 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL2 235 /* */
+#define SC_P_USDHC2_CLK 236 /* CONN.USDHC2.CLK, AUD.MQS.R, LSIO.GPIO5.IO24 */
+#define SC_P_USDHC2_CMD 237 /* CONN.USDHC2.CMD, AUD.MQS.L, LSIO.GPIO5.IO25 */
+#define SC_P_USDHC2_DATA0 238 /* CONN.USDHC2.DATA0, DMA.UART4.RX, LSIO.GPIO5.IO26 */
+#define SC_P_USDHC2_DATA1 239 /* CONN.USDHC2.DATA1, DMA.UART4.TX, LSIO.GPIO5.IO27 */
+#define SC_P_USDHC2_DATA2 240 /* CONN.USDHC2.DATA2, DMA.UART4.CTS_B, LSIO.GPIO5.IO28 */
+#define SC_P_USDHC2_DATA3 241 /* CONN.USDHC2.DATA3, DMA.UART4.RTS_B, LSIO.GPIO5.IO29 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3 242 /* */
+#define SC_P_ENET0_RGMII_TXC 243 /* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, LSIO.GPIO5.IO30 */
+#define SC_P_ENET0_RGMII_TX_CTL 244 /* CONN.ENET0.RGMII_TX_CTL, LSIO.GPIO5.IO31 */
+#define SC_P_ENET0_RGMII_TXD0 245 /* CONN.ENET0.RGMII_TXD0, LSIO.GPIO6.IO00 */
+#define SC_P_ENET0_RGMII_TXD1 246 /* CONN.ENET0.RGMII_TXD1, LSIO.GPIO6.IO01 */
+#define SC_P_ENET0_RGMII_TXD2 247 /* CONN.ENET0.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO02 */
+#define SC_P_ENET0_RGMII_TXD3 248 /* CONN.ENET0.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO03 */
+#define SC_P_ENET0_RGMII_RXC 249 /* CONN.ENET0.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO04 */
+#define SC_P_ENET0_RGMII_RX_CTL 250 /* CONN.ENET0.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO05 */
+#define SC_P_ENET0_RGMII_RXD0 251 /* CONN.ENET0.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO06 */
+#define SC_P_ENET0_RGMII_RXD1 252 /* CONN.ENET0.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO07 */
+#define SC_P_ENET0_RGMII_RXD2 253 /* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO08 */
+#define SC_P_ENET0_RGMII_RXD3 254 /* CONN.ENET0.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO09 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB 255 /* */
+#define SC_P_ENET1_RGMII_TXC 256 /* CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_OUT, CONN.ENET1.RCLK50M_IN, LSIO.GPIO6.IO10 */
+#define SC_P_ENET1_RGMII_TX_CTL 257 /* CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO6.IO11 */
+#define SC_P_ENET1_RGMII_TXD0 258 /* CONN.ENET1.RGMII_TXD0, LSIO.GPIO6.IO12 */
+#define SC_P_ENET1_RGMII_TXD1 259 /* CONN.ENET1.RGMII_TXD1, LSIO.GPIO6.IO13 */
+#define SC_P_ENET1_RGMII_TXD2 260 /* CONN.ENET1.RGMII_TXD2, DMA.UART3.TX, VPU.TSI_S1.VID, LSIO.GPIO6.IO14 */
+#define SC_P_ENET1_RGMII_TXD3 261 /* CONN.ENET1.RGMII_TXD3, DMA.UART3.RTS_B, VPU.TSI_S1.SYNC, LSIO.GPIO6.IO15 */
+#define SC_P_ENET1_RGMII_RXC 262 /* CONN.ENET1.RGMII_RXC, DMA.UART3.CTS_B, VPU.TSI_S1.DATA, LSIO.GPIO6.IO16 */
+#define SC_P_ENET1_RGMII_RX_CTL 263 /* CONN.ENET1.RGMII_RX_CTL, VPU.TSI_S0.VID, LSIO.GPIO6.IO17 */
+#define SC_P_ENET1_RGMII_RXD0 264 /* CONN.ENET1.RGMII_RXD0, VPU.TSI_S0.SYNC, LSIO.GPIO6.IO18 */
+#define SC_P_ENET1_RGMII_RXD1 265 /* CONN.ENET1.RGMII_RXD1, VPU.TSI_S0.DATA, LSIO.GPIO6.IO19 */
+#define SC_P_ENET1_RGMII_RXD2 266 /* CONN.ENET1.RGMII_RXD2, CONN.ENET1.RMII_RX_ER, VPU.TSI_S0.CLK, LSIO.GPIO6.IO20 */
+#define SC_P_ENET1_RGMII_RXD3 267 /* CONN.ENET1.RGMII_RXD3, DMA.UART3.RX, VPU.TSI_S1.CLK, LSIO.GPIO6.IO21 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA 268 /* */
+/*@}*/
+
+#endif /* IMX8QM_PADS_H */
diff --git a/plat/imx/common/include/imx8qx_pads.h b/plat/imx/common/include/imx8qx_pads.h
new file mode 100644
index 0000000..5445aa1
--- /dev/null
+++ b/plat/imx/common/include/imx8qx_pads.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file used to configure SoC pad list.
+ */
+
+#ifndef IMX8QX_PADS_H
+#define IMX8QX_PADS_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Pad Definitions
+ */
+/*@{*/
+#define SC_P_PCIE_CTRL0_PERST_B 0 /* HSIO.PCIE0.PERST_B, LSIO.GPIO4.IO00 */
+#define SC_P_PCIE_CTRL0_CLKREQ_B 1 /* HSIO.PCIE0.CLKREQ_B, LSIO.GPIO4.IO01 */
+#define SC_P_PCIE_CTRL0_WAKE_B 2 /* HSIO.PCIE0.WAKE_B, LSIO.GPIO4.IO02 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_PCIESEP 3 /* */
+#define SC_P_USB_SS3_TC0 4 /* ADMA.I2C1.SCL, CONN.USB_OTG1.PWR, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO03 */
+#define SC_P_USB_SS3_TC1 5 /* ADMA.I2C1.SCL, CONN.USB_OTG2.PWR, LSIO.GPIO4.IO04 */
+#define SC_P_USB_SS3_TC2 6 /* ADMA.I2C1.SDA, CONN.USB_OTG1.OC, CONN.USB_OTG2.OC, LSIO.GPIO4.IO05 */
+#define SC_P_USB_SS3_TC3 7 /* ADMA.I2C1.SDA, CONN.USB_OTG2.OC, LSIO.GPIO4.IO06 */
+#define SC_P_COMP_CTL_GPIO_3V3_USB3IO 8 /* */
+#define SC_P_EMMC0_CLK 9 /* CONN.EMMC0.CLK, CONN.NAND.READY_B, LSIO.GPIO4.IO07 */
+#define SC_P_EMMC0_CMD 10 /* CONN.EMMC0.CMD, CONN.NAND.DQS, LSIO.GPIO4.IO08 */
+#define SC_P_EMMC0_DATA0 11 /* CONN.EMMC0.DATA0, CONN.NAND.DATA00, LSIO.GPIO4.IO09 */
+#define SC_P_EMMC0_DATA1 12 /* CONN.EMMC0.DATA1, CONN.NAND.DATA01, LSIO.GPIO4.IO10 */
+#define SC_P_EMMC0_DATA2 13 /* CONN.EMMC0.DATA2, CONN.NAND.DATA02, LSIO.GPIO4.IO11 */
+#define SC_P_EMMC0_DATA3 14 /* CONN.EMMC0.DATA3, CONN.NAND.DATA03, LSIO.GPIO4.IO12 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX0 15 /* */
+#define SC_P_EMMC0_DATA4 16 /* CONN.EMMC0.DATA4, CONN.NAND.DATA04, CONN.EMMC0.WP, LSIO.GPIO4.IO13 */
+#define SC_P_EMMC0_DATA5 17 /* CONN.EMMC0.DATA5, CONN.NAND.DATA05, CONN.EMMC0.VSELECT, LSIO.GPIO4.IO14 */
+#define SC_P_EMMC0_DATA6 18 /* CONN.EMMC0.DATA6, CONN.NAND.DATA06, CONN.MLB.CLK, LSIO.GPIO4.IO15 */
+#define SC_P_EMMC0_DATA7 19 /* CONN.EMMC0.DATA7, CONN.NAND.DATA07, CONN.MLB.SIG, LSIO.GPIO4.IO16 */
+#define SC_P_EMMC0_STROBE 20 /* CONN.EMMC0.STROBE, CONN.NAND.CLE, CONN.MLB.DATA, LSIO.GPIO4.IO17 */
+#define SC_P_EMMC0_RESET_B 21 /* CONN.EMMC0.RESET_B, CONN.NAND.WP_B, LSIO.GPIO4.IO18 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_SD1FIX1 22 /* */
+#define SC_P_USDHC1_RESET_B 23 /* CONN.USDHC1.RESET_B, CONN.NAND.RE_N, ADMA.SPI2.SCK, LSIO.GPIO4.IO19 */
+#define SC_P_USDHC1_VSELECT 24 /* CONN.USDHC1.VSELECT, CONN.NAND.RE_P, ADMA.SPI2.SDO, CONN.NAND.RE_B, LSIO.GPIO4.IO20 */
+#define SC_P_CTL_NAND_RE_P_N 25 /* */
+#define SC_P_USDHC1_WP 26 /* CONN.USDHC1.WP, CONN.NAND.DQS_N, ADMA.SPI2.SDI, LSIO.GPIO4.IO21 */
+#define SC_P_USDHC1_CD_B 27 /* CONN.USDHC1.CD_B, CONN.NAND.DQS_P, ADMA.SPI2.CS0, CONN.NAND.DQS, LSIO.GPIO4.IO22 */
+#define SC_P_CTL_NAND_DQS_P_N 28 /* */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSELSEP 29 /* */
+#define SC_P_USDHC1_CLK 30 /* CONN.USDHC1.CLK, ADMA.UART3.RX, LSIO.GPIO4.IO23 */
+#define SC_P_USDHC1_CMD 31 /* CONN.USDHC1.CMD, CONN.NAND.CE0_B, ADMA.MQS.R, LSIO.GPIO4.IO24 */
+#define SC_P_USDHC1_DATA0 32 /* CONN.USDHC1.DATA0, CONN.NAND.CE1_B, ADMA.MQS.L, LSIO.GPIO4.IO25 */
+#define SC_P_USDHC1_DATA1 33 /* CONN.USDHC1.DATA1, CONN.NAND.RE_B, ADMA.UART3.TX, LSIO.GPIO4.IO26 */
+#define SC_P_USDHC1_DATA2 34 /* CONN.USDHC1.DATA2, CONN.NAND.WE_B, ADMA.UART3.CTS_B, LSIO.GPIO4.IO27 */
+#define SC_P_USDHC1_DATA3 35 /* CONN.USDHC1.DATA3, CONN.NAND.ALE, ADMA.UART3.RTS_B, LSIO.GPIO4.IO28 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_VSEL3 36 /* */
+#define SC_P_ENET0_RGMII_TXC 37 /* CONN.ENET0.RGMII_TXC, CONN.ENET0.RCLK50M_OUT, CONN.ENET0.RCLK50M_IN, CONN.NAND.CE1_B, LSIO.GPIO4.IO29 */
+#define SC_P_ENET0_RGMII_TX_CTL 38 /* CONN.ENET0.RGMII_TX_CTL, CONN.USDHC1.RESET_B, LSIO.GPIO4.IO30 */
+#define SC_P_ENET0_RGMII_TXD0 39 /* CONN.ENET0.RGMII_TXD0, CONN.USDHC1.VSELECT, LSIO.GPIO4.IO31 */
+#define SC_P_ENET0_RGMII_TXD1 40 /* CONN.ENET0.RGMII_TXD1, CONN.USDHC1.WP, LSIO.GPIO5.IO00 */
+#define SC_P_ENET0_RGMII_TXD2 41 /* CONN.ENET0.RGMII_TXD2, CONN.MLB.CLK, CONN.NAND.CE0_B, CONN.USDHC1.CD_B, LSIO.GPIO5.IO01 */
+#define SC_P_ENET0_RGMII_TXD3 42 /* CONN.ENET0.RGMII_TXD3, CONN.MLB.SIG, CONN.NAND.RE_B, LSIO.GPIO5.IO02 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB0 43 /* */
+#define SC_P_ENET0_RGMII_RXC 44 /* CONN.ENET0.RGMII_RXC, CONN.MLB.DATA, CONN.NAND.WE_B, CONN.USDHC1.CLK, LSIO.GPIO5.IO03 */
+#define SC_P_ENET0_RGMII_RX_CTL 45 /* CONN.ENET0.RGMII_RX_CTL, CONN.USDHC1.CMD, LSIO.GPIO5.IO04 */
+#define SC_P_ENET0_RGMII_RXD0 46 /* CONN.ENET0.RGMII_RXD0, CONN.USDHC1.DATA0, LSIO.GPIO5.IO05 */
+#define SC_P_ENET0_RGMII_RXD1 47 /* CONN.ENET0.RGMII_RXD1, CONN.USDHC1.DATA1, LSIO.GPIO5.IO06 */
+#define SC_P_ENET0_RGMII_RXD2 48 /* CONN.ENET0.RGMII_RXD2, CONN.ENET0.RMII_RX_ER, CONN.USDHC1.DATA2, LSIO.GPIO5.IO07 */
+#define SC_P_ENET0_RGMII_RXD3 49 /* CONN.ENET0.RGMII_RXD3, CONN.NAND.ALE, CONN.USDHC1.DATA3, LSIO.GPIO5.IO08 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB1 50 /* */
+#define SC_P_ENET0_REFCLK_125M_25M 51 /* CONN.ENET0.REFCLK_125M_25M, CONN.ENET0.PPS, CONN.ENET1.PPS, LSIO.GPIO5.IO09 */
+#define SC_P_ENET0_MDIO 52 /* CONN.ENET0.MDIO, ADMA.I2C3.SDA, CONN.ENET1.MDIO, LSIO.GPIO5.IO10 */
+#define SC_P_ENET0_MDC 53 /* CONN.ENET0.MDC, ADMA.I2C3.SCL, CONN.ENET1.MDC, LSIO.GPIO5.IO11 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOCT 54 /* */
+#define SC_P_ESAI0_FSR 55 /* ADMA.ESAI0.FSR, CONN.ENET1.RCLK50M_OUT, ADMA.LCDIF.D00, CONN.ENET1.RGMII_TXC, CONN.ENET1.RCLK50M_IN */
+#define SC_P_ESAI0_FST 56 /* ADMA.ESAI0.FST, CONN.MLB.CLK, ADMA.LCDIF.D01, CONN.ENET1.RGMII_TXD2, LSIO.GPIO0.IO01 */
+#define SC_P_ESAI0_SCKR 57 /* ADMA.ESAI0.SCKR, ADMA.LCDIF.D02, CONN.ENET1.RGMII_TX_CTL, LSIO.GPIO0.IO02 */
+#define SC_P_ESAI0_SCKT 58 /* ADMA.ESAI0.SCKT, CONN.MLB.SIG, ADMA.LCDIF.D03, CONN.ENET1.RGMII_TXD3, LSIO.GPIO0.IO03 */
+#define SC_P_ESAI0_TX0 59 /* ADMA.ESAI0.TX0, CONN.MLB.DATA, ADMA.LCDIF.D04, CONN.ENET1.RGMII_RXC, LSIO.GPIO0.IO04 */
+#define SC_P_ESAI0_TX1 60 /* ADMA.ESAI0.TX1, ADMA.LCDIF.D05, CONN.ENET1.RGMII_RXD3, LSIO.GPIO0.IO05 */
+#define SC_P_ESAI0_TX2_RX3 61 /* ADMA.ESAI0.TX2_RX3, CONN.ENET1.RMII_RX_ER, ADMA.LCDIF.D06, CONN.ENET1.RGMII_RXD2, LSIO.GPIO0.IO06 */
+#define SC_P_ESAI0_TX3_RX2 62 /* ADMA.ESAI0.TX3_RX2, ADMA.LCDIF.D07, CONN.ENET1.RGMII_RXD1, LSIO.GPIO0.IO07 */
+#define SC_P_ESAI0_TX4_RX1 63 /* ADMA.ESAI0.TX4_RX1, ADMA.LCDIF.D08, CONN.ENET1.RGMII_TXD0, LSIO.GPIO0.IO08 */
+#define SC_P_ESAI0_TX5_RX0 64 /* ADMA.ESAI0.TX5_RX0, ADMA.LCDIF.D09, CONN.ENET1.RGMII_TXD1, LSIO.GPIO0.IO09 */
+#define SC_P_SPDIF0_RX 65 /* ADMA.SPDIF0.RX, ADMA.MQS.R, ADMA.LCDIF.D10, CONN.ENET1.RGMII_RXD0, LSIO.GPIO0.IO10 */
+#define SC_P_SPDIF0_TX 66 /* ADMA.SPDIF0.TX, ADMA.MQS.L, ADMA.LCDIF.D11, CONN.ENET1.RGMII_RX_CTL, LSIO.GPIO0.IO11 */
+#define SC_P_SPDIF0_EXT_CLK 67 /* ADMA.SPDIF0.EXT_CLK, ADMA.LCDIF.D12, CONN.ENET1.REFCLK_125M_25M, LSIO.GPIO0.IO12 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHB 68 /* */
+#define SC_P_SPI3_SCK 69 /* ADMA.SPI3.SCK, ADMA.LCDIF.D13, LSIO.GPIO0.IO13 */
+#define SC_P_SPI3_SDO 70 /* ADMA.SPI3.SDO, ADMA.LCDIF.D14, LSIO.GPIO0.IO14 */
+#define SC_P_SPI3_SDI 71 /* ADMA.SPI3.SDI, ADMA.LCDIF.D15, LSIO.GPIO0.IO15 */
+#define SC_P_SPI3_CS0 72 /* ADMA.SPI3.CS0, ADMA.ACM.MCLK_OUT1, ADMA.LCDIF.HSYNC, LSIO.GPIO0.IO16 */
+#define SC_P_SPI3_CS1 73 /* ADMA.SPI3.CS1, ADMA.I2C3.SCL, ADMA.LCDIF.RESET, ADMA.SPI2.CS0, ADMA.LCDIF.D16 */
+#define SC_P_MCLK_IN1 74 /* ADMA.ACM.MCLK_IN1, ADMA.I2C3.SDA, ADMA.LCDIF.EN, ADMA.SPI2.SCK, ADMA.LCDIF.D17 */
+#define SC_P_MCLK_IN0 75 /* ADMA.ACM.MCLK_IN0, ADMA.ESAI0.RX_HF_CLK, ADMA.LCDIF.VSYNC, ADMA.SPI2.SDI, LSIO.GPIO0.IO19 */
+#define SC_P_MCLK_OUT0 76 /* ADMA.ACM.MCLK_OUT0, ADMA.ESAI0.TX_HF_CLK, ADMA.LCDIF.CLK, ADMA.SPI2.SDO, LSIO.GPIO0.IO20 */
+#define SC_P_UART1_TX 77 /* ADMA.UART1.TX, LSIO.PWM0.OUT, LSIO.GPT0.CAPTURE, LSIO.GPIO0.IO21 */
+#define SC_P_UART1_RX 78 /* ADMA.UART1.RX, LSIO.PWM1.OUT, LSIO.GPT0.COMPARE, LSIO.GPT1.CLK, LSIO.GPIO0.IO22 */
+#define SC_P_UART1_RTS_B 79 /* ADMA.UART1.RTS_B, LSIO.PWM2.OUT, ADMA.LCDIF.D16, LSIO.GPT1.CAPTURE, LSIO.GPT0.CLK */
+#define SC_P_UART1_CTS_B 80 /* ADMA.UART1.CTS_B, LSIO.PWM3.OUT, ADMA.LCDIF.D17, LSIO.GPT1.COMPARE, LSIO.GPIO0.IO24 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHK 81 /* */
+#define SC_P_SAI0_TXD 82 /* ADMA.SAI0.TXD, ADMA.SAI1.RXC, ADMA.SPI1.SDO, ADMA.LCDIF.D18, LSIO.GPIO0.IO25 */
+#define SC_P_SAI0_TXC 83 /* ADMA.SAI0.TXC, ADMA.SAI1.TXD, ADMA.SPI1.SDI, ADMA.LCDIF.D19, LSIO.GPIO0.IO26 */
+#define SC_P_SAI0_RXD 84 /* ADMA.SAI0.RXD, ADMA.SAI1.RXFS, ADMA.SPI1.CS0, ADMA.LCDIF.D20, LSIO.GPIO0.IO27 */
+#define SC_P_SAI0_TXFS 85 /* ADMA.SAI0.TXFS, ADMA.SPI2.CS1, ADMA.SPI1.SCK, LSIO.GPIO0.IO28 */
+#define SC_P_SAI1_RXD 86 /* ADMA.SAI1.RXD, ADMA.SAI0.RXFS, ADMA.SPI1.CS1, ADMA.LCDIF.D21, LSIO.GPIO0.IO29 */
+#define SC_P_SAI1_RXC 87 /* ADMA.SAI1.RXC, ADMA.SAI1.TXC, ADMA.LCDIF.D22, LSIO.GPIO0.IO30 */
+#define SC_P_SAI1_RXFS 88 /* ADMA.SAI1.RXFS, ADMA.SAI1.TXFS, ADMA.LCDIF.D23, LSIO.GPIO0.IO31 */
+#define SC_P_SPI2_CS0 89 /* ADMA.SPI2.CS0, LSIO.GPIO1.IO00 */
+#define SC_P_SPI2_SDO 90 /* ADMA.SPI2.SDO, LSIO.GPIO1.IO01 */
+#define SC_P_SPI2_SDI 91 /* ADMA.SPI2.SDI, LSIO.GPIO1.IO02 */
+#define SC_P_SPI2_SCK 92 /* ADMA.SPI2.SCK, LSIO.GPIO1.IO03 */
+#define SC_P_SPI0_SCK 93 /* ADMA.SPI0.SCK, ADMA.SAI0.TXC, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO04 */
+#define SC_P_SPI0_SDI 94 /* ADMA.SPI0.SDI, ADMA.SAI0.TXD, M40.TPM0.CH0, M40.GPIO0.IO02, LSIO.GPIO1.IO05 */
+#define SC_P_SPI0_SDO 95 /* ADMA.SPI0.SDO, ADMA.SAI0.TXFS, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO06 */
+#define SC_P_SPI0_CS1 96 /* ADMA.SPI0.CS1, ADMA.SAI0.RXC, ADMA.SAI1.TXD, ADMA.LCD_PWM0.OUT, LSIO.GPIO1.IO07 */
+#define SC_P_SPI0_CS0 97 /* ADMA.SPI0.CS0, ADMA.SAI0.RXD, M40.TPM0.CH1, M40.GPIO0.IO03, LSIO.GPIO1.IO08 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHT 98 /* */
+#define SC_P_ADC_IN1 99 /* ADMA.ADC.IN1, M40.I2C0.SDA, M40.GPIO0.IO01, LSIO.GPIO1.IO09 */
+#define SC_P_ADC_IN0 100 /* ADMA.ADC.IN0, M40.I2C0.SCL, M40.GPIO0.IO00, LSIO.GPIO1.IO10 */
+#define SC_P_ADC_IN3 101 /* ADMA.ADC.IN3, M40.UART0.TX, M40.GPIO0.IO03, ADMA.ACM.MCLK_OUT0, LSIO.GPIO1.IO11 */
+#define SC_P_ADC_IN2 102 /* ADMA.ADC.IN2, M40.UART0.RX, M40.GPIO0.IO02, ADMA.ACM.MCLK_IN0, LSIO.GPIO1.IO12 */
+#define SC_P_ADC_IN5 103 /* ADMA.ADC.IN5, M40.TPM0.CH1, M40.GPIO0.IO05, LSIO.GPIO1.IO13 */
+#define SC_P_ADC_IN4 104 /* ADMA.ADC.IN4, M40.TPM0.CH0, M40.GPIO0.IO04, LSIO.GPIO1.IO14 */
+#define SC_P_FLEXCAN0_RX 105 /* ADMA.FLEXCAN0.RX, ADMA.SAI2.RXC, ADMA.UART0.RTS_B, ADMA.SAI1.TXC, LSIO.GPIO1.IO15 */
+#define SC_P_FLEXCAN0_TX 106 /* ADMA.FLEXCAN0.TX, ADMA.SAI2.RXD, ADMA.UART0.CTS_B, ADMA.SAI1.TXFS, LSIO.GPIO1.IO16 */
+#define SC_P_FLEXCAN1_RX 107 /* ADMA.FLEXCAN1.RX, ADMA.SAI2.RXFS, ADMA.FTM.CH2, ADMA.SAI1.TXD, LSIO.GPIO1.IO17 */
+#define SC_P_FLEXCAN1_TX 108 /* ADMA.FLEXCAN1.TX, ADMA.SAI3.RXC, ADMA.DMA0.REQ_IN0, ADMA.SAI1.RXD, LSIO.GPIO1.IO18 */
+#define SC_P_FLEXCAN2_RX 109 /* ADMA.FLEXCAN2.RX, ADMA.SAI3.RXD, ADMA.UART3.RX, ADMA.SAI1.RXFS, LSIO.GPIO1.IO19 */
+#define SC_P_FLEXCAN2_TX 110 /* ADMA.FLEXCAN2.TX, ADMA.SAI3.RXFS, ADMA.UART3.TX, ADMA.SAI1.RXC, LSIO.GPIO1.IO20 */
+#define SC_P_UART0_RX 111 /* ADMA.UART0.RX, ADMA.MQS.R, ADMA.FLEXCAN0.RX, SCU.UART0.RX, LSIO.GPIO1.IO21 */
+#define SC_P_UART0_TX 112 /* ADMA.UART0.TX, ADMA.MQS.L, ADMA.FLEXCAN0.TX, SCU.UART0.TX, LSIO.GPIO1.IO22 */
+#define SC_P_UART2_TX 113 /* ADMA.UART2.TX, ADMA.FTM.CH1, ADMA.FLEXCAN1.TX, LSIO.GPIO1.IO23 */
+#define SC_P_UART2_RX 114 /* ADMA.UART2.RX, ADMA.FTM.CH0, ADMA.FLEXCAN1.RX, LSIO.GPIO1.IO24 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIOLH 115 /* */
+#define SC_P_MIPI_DSI0_I2C0_SCL 116 /* MIPI_DSI0.I2C0.SCL, MIPI_DSI1.GPIO0.IO02, LSIO.GPIO1.IO25 */
+#define SC_P_MIPI_DSI0_I2C0_SDA 117 /* MIPI_DSI0.I2C0.SDA, MIPI_DSI1.GPIO0.IO03, LSIO.GPIO1.IO26 */
+#define SC_P_MIPI_DSI0_GPIO0_00 118 /* MIPI_DSI0.GPIO0.IO00, ADMA.I2C1.SCL, MIPI_DSI0.PWM0.OUT, LSIO.GPIO1.IO27 */
+#define SC_P_MIPI_DSI0_GPIO0_01 119 /* MIPI_DSI0.GPIO0.IO01, ADMA.I2C1.SDA, LSIO.GPIO1.IO28 */
+#define SC_P_MIPI_DSI1_I2C0_SCL 120 /* MIPI_DSI1.I2C0.SCL, MIPI_DSI0.GPIO0.IO02, LSIO.GPIO1.IO29 */
+#define SC_P_MIPI_DSI1_I2C0_SDA 121 /* MIPI_DSI1.I2C0.SDA, MIPI_DSI0.GPIO0.IO03, LSIO.GPIO1.IO30 */
+#define SC_P_MIPI_DSI1_GPIO0_00 122 /* MIPI_DSI1.GPIO0.IO00, ADMA.I2C2.SCL, MIPI_DSI1.PWM0.OUT, LSIO.GPIO1.IO31 */
+#define SC_P_MIPI_DSI1_GPIO0_01 123 /* MIPI_DSI1.GPIO0.IO01, ADMA.I2C2.SDA, LSIO.GPIO2.IO00 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_MIPIDSIGPIO 124 /* */
+#define SC_P_JTAG_TRST_B 125 /* SCU.JTAG.TRST_B, SCU.WDOG0.WDOG_OUT */
+#define SC_P_PMIC_I2C_SCL 126 /* SCU.PMIC_I2C.SCL, SCU.GPIO0.IOXX_PMIC_A35_ON, LSIO.GPIO2.IO01 */
+#define SC_P_PMIC_I2C_SDA 127 /* SCU.PMIC_I2C.SDA, SCU.GPIO0.IOXX_PMIC_GPU_ON, LSIO.GPIO2.IO02 */
+#define SC_P_PMIC_INT_B 128 /* SCU.DSC.PMIC_INT_B */
+#define SC_P_SCU_GPIO0_00 129 /* SCU.GPIO0.IO00, SCU.UART0.RX, M40.UART0.RX, ADMA.UART3.RX, LSIO.GPIO2.IO03 */
+#define SC_P_SCU_GPIO0_01 130 /* SCU.GPIO0.IO01, SCU.UART0.TX, M40.UART0.TX, ADMA.UART3.TX, SCU.WDOG0.WDOG_OUT */
+#define SC_P_SCU_PMIC_STANDBY 131 /* SCU.DSC.PMIC_STANDBY */
+#define SC_P_SCU_BOOT_MODE0 132 /* SCU.DSC.BOOT_MODE0 */
+#define SC_P_SCU_BOOT_MODE1 133 /* SCU.DSC.BOOT_MODE1 */
+#define SC_P_SCU_BOOT_MODE2 134 /* SCU.DSC.BOOT_MODE2, SCU.PMIC_I2C.SDA */
+#define SC_P_SCU_BOOT_MODE3 135 /* SCU.DSC.BOOT_MODE3, SCU.PMIC_I2C.SCL, SCU.DSC.RTC_CLOCK_OUTPUT_32K */
+#define SC_P_CSI_D00 136 /* CI_PI.D02, ADMA.SAI0.RXC */
+#define SC_P_CSI_D01 137 /* CI_PI.D03, ADMA.SAI0.RXD */
+#define SC_P_CSI_D02 138 /* CI_PI.D04, ADMA.SAI0.RXFS */
+#define SC_P_CSI_D03 139 /* CI_PI.D05, ADMA.SAI2.RXC */
+#define SC_P_CSI_D04 140 /* CI_PI.D06, ADMA.SAI2.RXD */
+#define SC_P_CSI_D05 141 /* CI_PI.D07, ADMA.SAI2.RXFS */
+#define SC_P_CSI_D06 142 /* CI_PI.D08, ADMA.SAI3.RXC */
+#define SC_P_CSI_D07 143 /* CI_PI.D09, ADMA.SAI3.RXD */
+#define SC_P_CSI_HSYNC 144 /* CI_PI.HSYNC, CI_PI.D00, ADMA.SAI3.RXFS */
+#define SC_P_CSI_VSYNC 145 /* CI_PI.VSYNC, CI_PI.D01 */
+#define SC_P_CSI_PCLK 146 /* CI_PI.PCLK, MIPI_CSI0.I2C0.SCL, ADMA.SPI1.SCK, LSIO.GPIO3.IO00 */
+#define SC_P_CSI_MCLK 147 /* CI_PI.MCLK, MIPI_CSI0.I2C0.SDA, ADMA.SPI1.SDO, LSIO.GPIO3.IO01 */
+#define SC_P_CSI_EN 148 /* CI_PI.EN, CI_PI.I2C.SCL, ADMA.I2C3.SCL, ADMA.SPI1.SDI, LSIO.GPIO3.IO02 */
+#define SC_P_CSI_RESET 149 /* CI_PI.RESET, CI_PI.I2C.SDA, ADMA.I2C3.SDA, ADMA.SPI1.CS0, LSIO.GPIO3.IO03 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_GPIORHD 150 /* */
+#define SC_P_MIPI_CSI0_MCLK_OUT 151 /* MIPI_CSI0.ACM.MCLK_OUT, LSIO.GPIO3.IO04 */
+#define SC_P_MIPI_CSI0_I2C0_SCL 152 /* MIPI_CSI0.I2C0.SCL, MIPI_CSI0.GPIO0.IO02, LSIO.GPIO3.IO05 */
+#define SC_P_MIPI_CSI0_I2C0_SDA 153 /* MIPI_CSI0.I2C0.SDA, MIPI_CSI0.GPIO0.IO03, LSIO.GPIO3.IO06 */
+#define SC_P_MIPI_CSI0_GPIO0_01 154 /* MIPI_CSI0.GPIO0.IO01, ADMA.I2C0.SDA, LSIO.GPIO3.IO07 */
+#define SC_P_MIPI_CSI0_GPIO0_00 155 /* MIPI_CSI0.GPIO0.IO00, ADMA.I2C0.SCL, LSIO.GPIO3.IO08 */
+#define SC_P_QSPI0A_DATA0 156 /* LSIO.QSPI0A.DATA0, LSIO.GPIO3.IO09 */
+#define SC_P_QSPI0A_DATA1 157 /* LSIO.QSPI0A.DATA1, LSIO.GPIO3.IO10 */
+#define SC_P_QSPI0A_DATA2 158 /* LSIO.QSPI0A.DATA2, LSIO.GPIO3.IO11 */
+#define SC_P_QSPI0A_DATA3 159 /* LSIO.QSPI0A.DATA3, LSIO.GPIO3.IO12 */
+#define SC_P_QSPI0A_DQS 160 /* LSIO.QSPI0A.DQS, LSIO.GPIO3.IO13 */
+#define SC_P_QSPI0A_SS0_B 161 /* LSIO.QSPI0A.SS0_B, LSIO.GPIO3.IO14 */
+#define SC_P_QSPI0A_SS1_B 162 /* LSIO.QSPI0A.SS1_B, LSIO.GPIO3.IO15 */
+#define SC_P_QSPI0A_SCLK 163 /* LSIO.QSPI0A.SCLK, LSIO.GPIO3.IO16 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0A 164 /* */
+#define SC_P_QSPI0B_SCLK 165 /* LSIO.QSPI0B.SCLK, LSIO.QSPI1A.SCLK, LSIO.KPP0.COL0, LSIO.GPIO3.IO17 */
+#define SC_P_QSPI0B_DATA0 166 /* LSIO.QSPI0B.DATA0, LSIO.QSPI1A.DATA0, LSIO.KPP0.COL1, LSIO.GPIO3.IO18 */
+#define SC_P_QSPI0B_DATA1 167 /* LSIO.QSPI0B.DATA1, LSIO.QSPI1A.DATA1, LSIO.KPP0.COL2, LSIO.GPIO3.IO19 */
+#define SC_P_QSPI0B_DATA2 168 /* LSIO.QSPI0B.DATA2, LSIO.QSPI1A.DATA2, LSIO.KPP0.COL3, LSIO.GPIO3.IO20 */
+#define SC_P_QSPI0B_DATA3 169 /* LSIO.QSPI0B.DATA3, LSIO.QSPI1A.DATA3, LSIO.KPP0.ROW0, LSIO.GPIO3.IO21 */
+#define SC_P_QSPI0B_DQS 170 /* LSIO.QSPI0B.DQS, LSIO.QSPI1A.DQS, LSIO.KPP0.ROW1, LSIO.GPIO3.IO22 */
+#define SC_P_QSPI0B_SS0_B 171 /* LSIO.QSPI0B.SS0_B, LSIO.QSPI1A.SS0_B, LSIO.KPP0.ROW2, LSIO.GPIO3.IO23 */
+#define SC_P_QSPI0B_SS1_B 172 /* LSIO.QSPI0B.SS1_B, LSIO.QSPI1A.SS1_B, LSIO.KPP0.ROW3, LSIO.GPIO3.IO24 */
+#define SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0B 173 /* */
+/*@}*/
+
+#endif /* IMX8QX_PADS_H */
diff --git a/plat/imx/common/include/imx_aips.h b/plat/imx/common/include/imx_aips.h
new file mode 100644
index 0000000..1d41fe0
--- /dev/null
+++ b/plat/imx/common/include/imx_aips.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_AIPS_H
+#define IMX_AIPS_H
+
+#include <stdint.h>
+
+#define AIPSTZ_OAPCR_COUNT 0x05
+
+struct aipstz_regs {
+ uint32_t aipstz_mpr;
+ uint32_t res[15];
+ uint32_t aipstz_opacr[AIPSTZ_OAPCR_COUNT];
+};
+
+void imx_aips_init(void);
+
+#endif /* IMX_AIPS_H */
diff --git a/plat/imx/common/include/imx_caam.h b/plat/imx/common/include/imx_caam.h
new file mode 100644
index 0000000..61005b5
--- /dev/null
+++ b/plat/imx/common/include/imx_caam.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_CAAM_H
+#define IMX_CAAM_H
+
+#include <cdefs.h>
+#include <stdint.h>
+#include <arch.h>
+#include <imx_regs.h>
+
+struct caam_job_ring {
+ uint32_t jrmidr_ms;
+ uint32_t jrmidr_ls;
+};
+
+struct caam_rtic_mid {
+ uint32_t rticmidr_ms;
+ uint32_t rticmidr_ls;
+};
+
+struct caam_deco {
+ uint32_t deco_mid_ms;
+ uint32_t deco_mid_ls;
+};
+
+#define JOB_RING_OFFSET 0x10
+#define DEBUGCTL_OFFSET 0x58
+#define RES2_SIZE (DEBUGCTL_OFFSET - JOB_RING_OFFSET - \
+ (sizeof(struct caam_job_ring) * CAAM_NUM_JOB_RINGS))
+
+#define RTIC_MID_OFFSET 0x60
+#define DECORR_OFFSET 0x9C
+#define RES3_SIZE (DECORR_OFFSET - RTIC_MID_OFFSET - \
+ (sizeof(struct caam_rtic_mid) * CAAM_NUM_RTIC))
+
+#define DECO_MID_OFFSET 0xA0
+#define DAR_OFFSET 0x120
+#define RES4_SIZE (DAR_OFFSET - DECO_MID_OFFSET - \
+ (sizeof(struct caam_deco) * CAAM_NUM_DECO))
+
+struct caam_ctrl {
+ uint32_t res0;
+ uint32_t mcfgr;
+ uint32_t res1;
+ uint32_t scfgr;
+ struct caam_job_ring jr[CAAM_NUM_JOB_RINGS];
+ uint8_t res2[RES2_SIZE];
+ uint32_t debuctl;
+ uint32_t jrstartr;
+ struct caam_rtic_mid mid[CAAM_NUM_RTIC];
+ uint8_t res3[RES3_SIZE];
+ uint32_t decorr;
+ struct caam_deco deco[CAAM_NUM_DECO];
+ uint8_t res4[RES4_SIZE];
+ uint32_t dar;
+ uint32_t drr;
+} __packed;
+
+/* Job ring control bits */
+#define JROWN_NS BIT(3)
+#define JROWN_MID 0x01
+
+/* Declare CAAM API */
+void imx_caam_init(void);
+
+#endif /* IMX_CAAM_H */
diff --git a/plat/imx/common/include/imx_clock.h b/plat/imx/common/include/imx_clock.h
new file mode 100644
index 0000000..d75dcff
--- /dev/null
+++ b/plat/imx/common/include/imx_clock.h
@@ -0,0 +1,1003 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef IMX_CLOCK_H
+#define IMX_CLOCK_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+struct ccm_pll_ctrl {
+ uint32_t ccm_pll_ctrl;
+ uint32_t ccm_pll_ctrl_set;
+ uint32_t ccm_pll_ctrl_clr;
+ uint32_t ccm_pll_ctrl_tog;
+};
+
+/* Clock gate control */
+struct ccm_clk_gate_ctrl {
+ uint32_t ccm_ccgr;
+ uint32_t ccm_ccgr_set;
+ uint32_t ccm_ccgr_clr;
+ uint32_t ccm_ccgr_tog;
+};
+
+#define CCM_CCGR_SETTING0_DOM_CLK_NONE 0
+#define CCM_CCGR_SETTING0_DOM_CLK_RUN BIT(0)
+#define CCM_CCGR_SETTING0_DOM_CLK_RUN_WAIT BIT(1)
+#define CCM_CCGR_SETTING0_DOM_CLK_ALWAYS (BIT(1) | BIT(0))
+#define CCM_CCGR_SETTING1_DOM_CLK_NONE 0
+#define CCM_CCGR_SETTING1_DOM_CLK_RUN BIT(4)
+#define CCM_CCGR_SETTING1_DOM_CLK_RUN_WAIT BIT(5)
+#define CCM_CCGR_SETTING1_DOM_CLK_ALWAYS (BIT(5) | BIT(4))
+#define CCM_CCGR_SETTING2_DOM_CLK_NONE 0
+#define CCM_CCGR_SETTING2_DOM_CLK_RUN BIT(8)
+#define CCM_CCGR_SETTING2_DOM_CLK_RUN_WAIT BIT(9)
+#define CCM_CCGR_SETTING2_DOM_CLK_ALWAYS (BIT(9) | BIT(8))
+#define CCM_CCGR_SETTING3_DOM_CLK_NONE 0
+#define CCM_CCGR_SETTING3_DOM_CLK_RUN BIT(12)
+#define CCM_CCGR_SETTING3_DOM_CLK_RUN_WAIT BIT(13)
+#define CCM_CCGR_SETTING3_DOM_CLK_ALWAYS (BIT(13) | BIT(12))
+
+enum {
+ CCM_CCGR_ID_ADC = 32,
+ CCM_CCGR_ID_AIPS1TZ = 10,
+ CCM_CCGR_ID_AIPS2TZ = 11,
+ CCM_CCGR_ID_AIPS3TZ = 12,
+ CCM_CCGR_ID_APBHDMA = 20,
+ CCM_CCGR_ID_CAAM = 36,
+ CCM_CCGR_ID_CM4 = 1,
+ CCM_CCGR_ID_CSI = 73,
+ CCM_CCGR_ID_CSU = 45,
+ CCM_CCGR_ID_DAP = 47,
+ CCM_CCGR_ID_DBGMON = 46,
+ CCM_CCGR_ID_DDRC = 19,
+ CCM_CCGR_ID_ECSPI1 = 120,
+ CCM_CCGR_ID_ECSPI2 = 121,
+ CCM_CCGR_ID_ECSPI3 = 122,
+ CCM_CCGR_ID_ECSPI4 = 123,
+ CCM_CCGR_ID_EIM = 22,
+ CCM_CCGR_ID_ENET1 = 112,
+ CCM_CCGR_ID_ENET2 = 113,
+ CCM_CCGR_ID_EPDC = 74,
+ CCM_CCGR_ID_FLEXCAN1 = 116,
+ CCM_CCGR_ID_FLEXCAN2 = 117,
+ CCM_CCGR_ID_FLEXTIMER1 = 128,
+ CCM_CCGR_ID_FLEXTIMER2 = 129,
+ CCM_CCGR_ID_GPIO1 = 160,
+ CCM_CCGR_ID_GPIO2 = 161,
+ CCM_CCGR_ID_GPIO3 = 162,
+ CCM_CCGR_ID_GPIO4 = 163,
+ CCM_CCGR_ID_GPIO5 = 164,
+ CCM_CCGR_ID_GPIO6 = 165,
+ CCM_CCGR_ID_GPIO7 = 166,
+ CCM_CCGR_ID_GPT1 = 124,
+ CCM_CCGR_ID_GPT2 = 125,
+ CCM_CCGR_ID_GPT3 = 126,
+ CCM_CCGR_ID_GPT4 = 127,
+ CCM_CCGR_ID_I2C1 = 136,
+ CCM_CCGR_ID_I2C2 = 137,
+ CCM_CCGR_ID_I2C3 = 138,
+ CCM_CCGR_ID_I2C4 = 139,
+ CCM_CCGR_ID_IOMUXC1 = 168,
+ CCM_CCGR_ID_IOMUXC2 = 169,
+ CCM_CCGR_ID_KPP = 120,
+ CCM_CCGR_ID_LCDIF = 75,
+ CCM_CCGR_ID_MIPI_CSI = 100,
+ CCM_CCGR_ID_MIPI_DSI = 101,
+ CCM_CCGR_ID_MIPI_PHY = 102,
+ CCM_CCGR_ID_MU = 39,
+ CCM_CCGR_ID_OCOTP = 35,
+ CCM_CCGR_ID_OCRAM = 17,
+ CCM_CCGR_ID_OCRAM_S = 18,
+ CCM_CCGR_ID_PCIE = 96,
+ CCM_CCGR_ID_PCIE_PHY = 96,
+ CCM_CCGR_ID_PERFMON1 = 68,
+ CCM_CCGR_ID_PERFMON2 = 69,
+ CCM_CCGR_ID_PWM1 = 132,
+ CCM_CCGR_ID_PWM2 = 133,
+ CCM_CCGR_ID_PWM3 = 134,
+ CCM_CCGR_ID_PMM4 = 135,
+ CCM_CCGR_ID_PXP = 76,
+ CCM_CCGR_ID_QOS1 = 42,
+ CCM_CCGR_ID_QOS2 = 43,
+ CCM_CCGR_ID_QOS3 = 44,
+ CCM_CCGR_ID_QUADSPI = 21,
+ CCM_CCGR_ID_RDC = 38,
+ CCM_CCGR_ID_ROMCP = 16,
+ CCM_CCGR_ID_SAI1 = 140,
+ CCM_CCGR_ID_SAI2 = 141,
+ CCM_CCGR_ID_SAI3 = 142,
+ CCM_CCGR_ID_SCTR = 34,
+ CCM_CCGR_ID_SDMA = 72,
+ CCM_CCGR_ID_SEC = 49,
+ CCM_CCGR_ID_SEMA42_1 = 64,
+ CCM_CCGR_ID_SEMA42_2 = 65,
+ CCM_CCGR_ID_SIM_DISPLAY = 5,
+ CCM_CCGR_ID_SIM_ENET = 6,
+ CCM_CCGR_ID_SIM_M = 7,
+ CCM_CCGR_ID_SIM_MAIN = 4,
+ CCM_CCGR_ID_SIM_S = 8,
+ CCM_CCGR_ID_SIM_WAKEUP = 9,
+ CCM_CCGR_ID_SIM1 = 144,
+ CCM_CCGR_ID_SIM2 = 145,
+ CCM_CCGR_ID_SIM_NAND = 20,
+ CCM_CCGR_ID_DISPLAY_CM4 = 1,
+ CCM_CCGR_ID_DRAM = 19,
+ CCM_CCGR_ID_SNVS = 37,
+ CCM_CCGR_ID_SPBA = 12,
+ CCM_CCGR_ID_TRACE = 48,
+ CCM_CCGR_ID_TZASC = 19,
+ CCM_CCGR_ID_UART1 = 148,
+ CCM_CCGR_ID_UART2 = 149,
+ CCM_CCGR_ID_UART3 = 150,
+ CCM_CCGR_ID_UART4 = 151,
+ CCM_CCGR_ID_UART5 = 152,
+ CCM_CCGR_ID_UART6 = 153,
+ CCM_CCGR_ID_UART7 = 154,
+ CCM_CCGR_ID_USB_HS = 40,
+ CCM_CCGR_ID_USB_IPG = 104,
+ CCM_CCGR_ID_USB_PHY_480MCLK = 105,
+ CCM_CCGR_ID_USB_OTG1_PHY = 106,
+ CCM_CCGR_ID_USB_OTG2_PHY = 107,
+ CCM_CCGR_ID_USBHDC1 = 108,
+ CCM_CCGR_ID_USBHDC2 = 109,
+ CCM_CCGR_ID_USBHDC3 = 110,
+ CCM_CCGR_ID_WDOG1 = 156,
+ CCM_CCGR_ID_WDOG2 = 157,
+ CCM_CCGR_ID_WDOG3 = 158,
+ CCM_CCGR_ID_WDOG4 = 159,
+};
+
+/* Clock target block */
+struct ccm_target_root_ctrl {
+ uint32_t ccm_target_root;
+ uint32_t ccm_target_root_set;
+ uint32_t ccm_target_root_clr;
+ uint32_t ccm_target_root_tog;
+ uint32_t ccm_misc;
+ uint32_t ccm_misc_set;
+ uint32_t ccm_misc_clr;
+ uint32_t ccm_misc_tog;
+ uint32_t ccm_post;
+ uint32_t ccm_post_set;
+ uint32_t ccm_post_clr;
+ uint32_t ccm_post_tog;
+ uint32_t ccm_pre;
+ uint32_t ccm_pre_set;
+ uint32_t ccm_pre_clr;
+ uint32_t ccm_pre_tog;
+ uint32_t reserved[0x0c];
+ uint32_t ccm_access_ctrl;
+ uint32_t ccm_access_ctrl_set;
+ uint32_t ccm_access_ctrl_clr;
+ uint32_t ccm_access_ctrl_tog;
+};
+
+#define CCM_TARGET_ROOT_ENABLE BIT(28)
+#define CCM_TARGET_MUX(x) (((x) - 1) << 24)
+#define CCM_TARGET_PRE_PODF(x) (((x) - 1) << 16)
+#define CCM_TARGET_POST_PODF(x) ((x) - 1)
+
+/* Target root MUX values - selects the clock source for a block */
+/* ARM_A7_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_ARM_PLL BIT(24)
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_ENET_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_DDR_PLL (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_SYS_PLL_PFD0 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ARM_A7_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* ARM_M4_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_ENET_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_SYS_PLL_PFD2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_DDR_PLL_DIV2 BIT(26)
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOTV_IDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ARM_M4_CLK_ROOTUSB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* MAIN_AXI_CLK_ROOT */
+
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_SYS_PLL_PFD1 BIT(24)
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_SYS_PLL_PFD5 BIT(26)
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_MAIN_AXI_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* DISP_AXI_CLK_ROOT */
+
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_SYS_PLL_PFD1 BIT(24)
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_SYS_PLL_PFD6 BIT(26)
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_SYS_PLL_PFD7 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_DISP_AXI_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* ENET_AXI_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_SYS_PLL_PFD2 BIT(24)
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_SYS_PLL_DIV2 BIT(26)
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ENET_AXI_CLK_ROOT_SYS_PLL_PFD4 ((BIT(26) | BIT(25) | BIT(24))
+
+/* NAND_USDHC_BUS_CLK_ROOT */
+
+#define CM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AHB BIT(24)
+#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_SYS_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(26)
+#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AUDIO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* AHB_CLK_ROOT */
+
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_SYS_PLL_PFD2 BIT(24)
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_SYS_PLL_PFD0 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_ENET_PLL_DIV8 BIT(26)
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_USB_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_AHB_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* IPG_CLK_ROOT */
+#define CCM_TRGT_MUX_IPG_CLK_ROOT_AHB_CLK_ROOT 0
+
+/* DRAM_PHYM_CLK_ROOT */
+#define CCM_TRGT_MUX_DRAM_PHYM_CLK_ROOT_DDR_PLL 0
+#define CCM_TRGT_MUX_DRAM_PHYM_CLK_ROOT_DRAM_PHYM_ALT_CLK_ROOT BIT(24)
+
+/* DRAM_CLK_ROOT */
+
+#define CCM_TRGT_MUX_DRAM_CLK_ROOT_DDR_PLL 0
+#define CCM_TRGT_MUX_DRAM_CLK_ROOT_DRAM_ALT_CLK_ROOT BIT(24)
+
+/* DRAM_PHYM_ALT_CLK_ROOT */
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_DDR_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_SYS_PLL BIT(25)
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_USB_PLL BIT(26)
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_SYS_PLL_PFD7 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_DRAM_PHYM_ALT_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* DRAM_ALT_CLK_ROOT */
+
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_DDR_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_SYS_PLL BIT(25)
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_ENET_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_USB_PLL BIT(26)
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_SYS_PLL_PFD0 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_DRAM_ALT_CLK_ROOT_SYS_PLL_PFD2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* USB_HSIC_CLK_ROOT */
+
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL BIT(24)
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_USB_PLL BIT(25)
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD3 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD4 BIT(26)
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD5 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* LCDIF_PIXEL_CLK_ROOT */
+
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_SYS_PLL_PFD5 BIT(24)
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_EXT_CLK3 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_SYS_PLL_PFD4 BIT(26)
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_LCDIF_PIXEL_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* MIPI_DSI_CLK_ROOT */
+
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL_PFD5 BIT(24)
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL_PFD3 BIT(25)
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_SYS_PLL_PFD0_DIV2 BIT(26)
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_DDR_PLL_DIV2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_MIPI_DSI_CLK_ROOT_AUDIO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* MIPI_CSI_CLK_ROOT */
+
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL_PFD4 BIT(24)
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL_PFD3 BIT(25)
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_SYS_PLL_PFD0_DIV2 BIT(26)
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_DDR_PLL_DIV2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_MIPI_CSI_CLK_ROOT_AUDIO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* MIPI_DPHY_REF_CLK_ROOT */
+
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_SYS_PLL_DIV4 BIT(24)
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_SYS_PLL_PFD5 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_REF_1M BIT(26)
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_MIPI_DPHY_REF_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24))
+
+/* SAI1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_AUDIO_PLL BIT(25)
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_VIDEO_PLL BIT(26)
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_SAI1_CLK_ROOT_EXT_CLK2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* SAI2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_AUDIO_PLL BIT(25)
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_VIDEO_PLL BIT(26)
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_SAI2_CLK_ROOT_EXT_CLK2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* SAI3_CLK_ROOT */
+
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_AUDIO_PLL BIT(25)
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_VIDEO_PLL BIT(26)
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_SAI3_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24))
+
+/* ENET1_REF_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_ENET_PLL_DIV8 BIT(24)
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_ENET_PLL_DIV20 BIT(25)
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_ENET_PLL_DIV40 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_SYS_PLL_DIV4 BIT(26)
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ENET1_REF_CLK_ROOT_EXT_CLK4 ((BIT(26) | BIT(25) | BIT(24))
+
+/* ENET1_TIME_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_AUDIO_PLL BIT(25)
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK1 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK2 BIT(26)
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ENET1_TIME_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* ENET_PHY_REF_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_ENET_PLL_DIV40 BIT(24)
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_ENET_PLL_DIV20 BIT(25)
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_ENET_PLL_DIV8 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_DDR_PLL_DIV2 BIT(26)
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ENET_PHY_REF_CLK_ROOT_SYS_PLL_PFD3 ((BIT(26) | BIT(25) | BIT(24))
+
+/* EIM_CLK_ROOT */
+
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_PFD2 BIT(26)
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_SYS_PLL_PFD3 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_EIM_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* NAND_CLK_ROOT */
+
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_SYS_PLL BIT(24)
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_SYS_PLL_PFD0 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_SYS_PLL_PFD3 BIT(26)
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_ENET_PLL_DIV2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_NAND_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* QSPI_CLK_ROOT */
+
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD4 BIT(24)
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD3 BIT(26)
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_QSPI_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* USDHC1_CLK_ROOT */
+
+#define CM_TRGT_MUX_USDHC1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD0 BIT(24)
+#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD4 BIT(26)
+#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_USDHC1_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* USDHC2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD0 BIT(24)
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD4 BIT(26)
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_USDHC2_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* USDHC3_CLK_ROOT */
+
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD0 BIT(24)
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_ENET_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD4 BIT(26)
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD6 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_USDHC3_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* CAN1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_SYS_PLL_DIV4 BIT(24)
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_ENET_PLL_DIV25 BIT(26)
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_USB_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_CAN1_CLK_ROOT_EXT_CLK4 ((BIT(26) | BIT(25) | BIT(24))
+
+/* CAN2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_SYS_PLL_DIV4 BIT(24)
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_DDR_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_SYS_PLL (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_ENET_PLL_DIV25 BIT(26)
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_USB_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_CAN2_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24))
+
+/* I2C1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_SYS_PLL_DIV4 BIT(24)
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_ENET_PLL_DIV20 BIT(25)
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_USB_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_I2C1_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* I2C2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_SYS_PLL_DIV4 BIT(24)
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_ENET_PLL_DIV20 BIT(25)
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_USB_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_I2C2_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* I2C3_CLK_ROOT */
+
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_SYS_PLL_DIV4 BIT(24)
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_ENET_PLL_DIV20 BIT(25)
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_USB_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_I2C3_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* I2C4_CLK_ROOT */
+
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_SYS_PLL_DIV4 BIT(24)
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_ENET_PLL_DIV20 BIT(25)
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_USB_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_I2C4_CLK_ROOT_SYS_PLL_PFD2_DIV2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* UART1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_UART1_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* UART2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_UART2_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* UART3_CLK_ROOT */
+
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_UART3_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* UART4_CLK_ROOT */
+
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_UART4_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* UART5_CLK_ROOT */
+
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_UART5_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* UART6_CLK_ROOT */
+
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_UART6_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* UART7_CLK_ROOT */
+
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_ENET_PLL_DIV10 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_EXT_CLK4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_UART7_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* ECSPI1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ECSPI1_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* ECSPI2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ECSPI2_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* ECSPI3_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ECSPI3_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* ECSPI4_CLK_ROOT */
+
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_ENET_PLL_DIV25 BIT(25)
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL_DIV4 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL BIT(26)
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_SYS_PLL_PFD4 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_ENET_PLL_DIV4 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_ECSPI4_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* PWM1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_REF_1M (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_PWM1_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* PWM2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_EXT_CLK1 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_REF_1M (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_PWM2_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* PWM3_CLK_ROOT */
+
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_REF_1M (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_PWM3_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* PWM4_CLK_ROOT */
+
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_REF_1M (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_PWM4_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* FLEXTIMER1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_REF_1M (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_FLEXTIMER1_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* FLEXTIMER2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_AUDIO_PLL BIT(26)
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_EXT_CLK3 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_REF_1M (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_FLEXTIMER2_CLK_ROOT_VIDEO_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target SIM1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_USB_PLL BIT(26)
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_SIM1_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target SIM2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_USB_PLL BIT(26)
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_ENET_PLL_DIV8 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_SIM2_CLK_ROOT_SYS_PLL_PFD7 ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target GPT1_CLK_ROOT */
+
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_SYS_PLL_PFD0 BIT(25)
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_VIDEO_PLL BIT(26)
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_REF_1M (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_GPT1_CLK_ROOT_EXT_CLK1 ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target GPT2_CLK_ROOT */
+
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_SYS_PLL_PFD0 BIT(25)
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_VIDEO_PLL BIT(26)
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_REF_1M (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_GPT2_CLK_ROOT_EXT_CLK2 ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target GPT3_CLK_ROOT */
+
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_SYS_PLL_PFD0 BIT(25)
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_VIDEO_PLL BIT(26)
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_REF_1M (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_GPT3_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24))
+
+/*Target GPT4_CLK_ROOT */
+
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_ENET_PLL_DIV10 BIT(24)
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_SYS_PLL_PFD0 BIT(25)
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_ENET_PLL_DIV25 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_VIDEO_PLL BIT(26)
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_REF_1M (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_GPT4_CLK_ROOT_EXT_CLK4 ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target TRACE_CLK_ROOT */
+
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_ENET_PLL_DIV8 BIT(26)
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_USB_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_EXT_CLK2 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_TRACE_CLK_ROOT_EXT_CLK3 ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target WDOG_CLK_ROOT */
+
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_ENET_PLL_DIV8 BIT(26)
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_USB_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_REF_1M (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_WDOG_CLK_ROOT_SYS_PLL_PFD1_DIV2 ((BIT(26) | BIT(25) | BIT(24))
+#define WDOG_DEFAULT_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_WDOG_CLK_ROOT_OSC_24M)
+
+/* Target CSI_MCLK_CLK_ROOT */
+
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_ENET_PLL_DIV8 BIT(26)
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_CSI_MCLK_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target AUDIO_MCLK_CLK_ROOT */
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_OSC_24M 0
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_SYS_PLL_PFD2_DIV2 BIT(24)
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_SYS_PLL_DIV4 BIT(25)
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_DDR_PLL_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_ENET_PLL_DIV8 BIT(26)
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_AUDIO_MCLK_CLK_ROOT_USB_PLL ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target CCM_CLKO1 */
+#define CCM_TRGT_MUX_CCM_CLKO1_OSC_24M 0
+#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL BIT(24)
+#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL_DIV2 BIT(25)
+#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL_PFD0_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_CCM_CLKO1_SYS_PLL_PFD3 BIT(26)
+#define CCM_TRGT_MUX_CCM_CLKO1_ENET_PLL_DIV2 (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_CCM_CLKO1_DDR_PLL_DIV2 (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_CCM_CLKO1_REF_1M ((BIT(26) | BIT(25) | BIT(24))
+
+/* Target CCM_CLKO2 */
+#define CCM_TRGT_MUX_CCM_CLKO2_OSC_24M 0
+#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_DIV2 BIT(24)
+#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_PFD0 BIT(25)
+#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_PFD1_DIV2 (BIT(25) | BIT(24))
+#define CCM_TRGT_MUX_CCM_CLKO2_SYS_PLL_PFD4 BIT(26)
+#define CCM_TRGT_MUX_CCM_CLKO2_AUDIO_PLL (BIT(26) | BIT(24))
+#define CCM_TRGT_MUX_CCM_CLKO2_VIDEO_PLL (BIT(26) | BIT(25))
+#define CCM_TRGT_MUX_CCM_CLKO2_OSC_32K ((BIT(26) | BIT(25) | BIT(24))
+
+/*
+ * See Table 5-11 in i.MX7 Solo Reference manual rev 0.1
+ * The indices must be calculated by dividing the offset by
+ * sizeof (struct ccm_target_root_ctrl) => 0x80 bytes for each index
+ */
+enum {
+ CCM_TRT_ID_ARM_A7_CLK_ROOT = 0,
+ CCM_TRT_ID_ARM_M4_CLK_ROOT = 1,
+ CCM_TRT_ID_MAIN_AXI_CLK_ROOT = 16,
+ CCM_TRT_ID_DISP_AXI_CLK_ROOT = 17,
+ CCM_TRT_ID_ENET_AXI_CLK_ROOT = 18,
+ CCM_TRT_ID_NAND_USDHC_BUS_CLK_ROOT = 19,
+ CCM_TRT_ID_AHB_CLK_ROOT = 32,
+ CCM_TRT_ID_IPG_CLK_ROOT = 33,
+ CCM_TRT_ID_DRAM_PHYM_CLK_ROOT = 48,
+ CCM_TRT_ID_DRAM_CLK_ROOT = 49,
+ CCM_TRT_ID_DRAM_PHYM_ALT_CLK_ROOT = 64,
+ CCM_TRT_ID_DRAM_ALT_CLK_ROOT = 65,
+ CCM_TRT_ID_USB_HSIC_CLK_ROOT = 66,
+ CCM_TRT_ID_LCDIF_PIXEL_CLK_ROOT = 70,
+ CCM_TRT_ID_MIPI_DSI_CLK_ROOT = 71,
+ CCM_TRT_ID_MIPI_CSI_CLK_ROOT = 72,
+ CCM_TRT_ID_MIPI_DPHY_REF_CLK_ROOT = 73,
+ CCM_TRT_ID_SAI1_CLK_ROOT = 74,
+ CCM_TRT_ID_SAI2_CLK_ROOT = 75,
+ CCM_TRT_ID_SAI3_CLK_ROOT = 76,
+ CCM_TRT_ID_ENET1_REF_CLK_ROOT = 78,
+ CCM_TRT_ID_ENET1_TIME_CLK_ROOT = 79,
+ CCM_TRT_ID_ENET_PHY_REF_CLK_ROOT = 82,
+ CCM_TRT_ID_EIM_CLK_ROOT = 83,
+ CCM_TRT_ID_NAND_CLK_ROOT = 84,
+ CCM_TRT_ID_QSPI_CLK_ROOT = 85,
+ CCM_TRT_ID_USDHC1_CLK_ROOT = 86,
+ CCM_TRT_ID_USDHC2_CLK_ROOT = 87,
+ CCM_TRT_ID_USDHC3_CLK_ROOT = 88,
+ CCM_TRT_ID_CAN1_CLK_ROOT = 89,
+ CCM_TRT_ID_CAN2_CLK_ROOT = 90,
+ CCM_TRT_ID_I2C1_CLK_ROOT = 91,
+ CCM_TRT_ID_I2C2_CLK_ROOT = 92,
+ CCM_TRT_ID_I2C3_CLK_ROOT = 93,
+ CCM_TRT_ID_I2C4_CLK_ROOT = 94,
+ CCM_TRT_ID_UART1_CLK_ROOT = 95,
+ CCM_TRT_ID_UART2_CLK_ROOT = 96,
+ CCM_TRT_ID_UART3_CLK_ROOT = 97,
+ CCM_TRT_ID_UART4_CLK_ROOT = 98,
+ CCM_TRT_ID_UART5_CLK_ROOT = 99,
+ CCM_TRT_ID_UART6_CLK_ROOT = 100,
+ CCM_TRT_ID_UART7_CLK_ROOT = 101,
+ CCM_TRT_ID_ECSPI1_CLK_ROOT = 102,
+ CCM_TRT_ID_ECSPI2_CLK_ROOT = 103,
+ CCM_TRT_ID_ECSPI3_CLK_ROOT = 104,
+ CCM_TRT_ID_ECSPI4_CLK_ROOT = 105,
+ CCM_TRT_ID_PWM1_CLK_ROOT = 106,
+ CCM_TRT_ID_PWM2_CLK_ROOT = 107,
+ CCM_TRT_ID_PWM3_CLK_ROOT = 108,
+ CCM_TRT_ID_PWM4_CLK_ROOT = 109,
+ CCM_TRT_ID_FLEXTIMER1_CLK_ROOT = 110,
+ CCM_TRT_ID_FLEXTIMER2_CLK_ROOT = 111,
+ CCM_TRT_ID_SIM1_CLK_ROOT = 112,
+ CCM_TRT_ID_SIM2_CLK_ROOT = 113,
+ CCM_TRT_ID_GPT1_CLK_ROOT = 114,
+ CCM_TRT_ID_GPT2_CLK_ROOT = 115,
+ CCM_TRT_ID_GPT3_CLK_ROOT = 116,
+ CCM_TRT_ID_GPT4_CLK_ROOT = 117,
+ CCM_TRT_ID_TRACE_CLK_ROOT = 118,
+ CCM_TRT_ID_WDOG_CLK_ROOT = 119,
+ CCM_TRT_ID_CSI_MCLK_CLK_ROOT = 120,
+ CCM_TRT_ID_AUDIO_MCLK_CLK_ROOT = 121,
+ CCM_TRT_ID_CCM_CLKO1 = 123,
+ CCM_TRT_ID_CCM_CLKO2 = 124,
+};
+
+#define CCM_MISC_VIOLATE BIT(8)
+#define CCM_MISC_TIMEOUT BIT(4)
+#define CCM_MISC_AUTHEN_FAIL BIT(0)
+
+#define CCM_POST_BUSY2 BIT(31)
+#define CCM_POST_SELECT_BRANCH_A BIT(28)
+#define CCM_POST_BUSY1 BIT(7)
+#define CCM_POST_POST_PODF(x) ((x) - 1)
+
+#define CCM_PRE_BUSY4 BIT(31)
+#define CCM_PRE_ENABLE_A BIT(28)
+#define CCM_PRE_MUX_A(x) (((x) - 1) << 24)
+#define CCM_PRE_BUSY3 BIT(19)
+#define CCM_PRE_PODF_A(x) (((x) - 1) << 16)
+#define CCM_PRE_BUSY1 BIT(15)
+#define CCM_PRE_ENABLE_B BIT(12)
+#define CCM_PRE_MUX_B(x) (((x) - 1) << 8)
+#define CCM_PRE_BUSY0 BIT(3)
+#define CCM_PRE_POST_PODF(x) ((x) - 1)
+
+#define CCM_ACCESS_CTRL_LOCK BIT(31)
+#define CCM_ACCESS_SEMA_ENABLE BIT(28)
+#define CCM_ACCESS_DOM3_WHITELIST BIT(27)
+#define CCM_ACCESS_DOM2_WHITELIST BIT(26)
+#define CCM_ACCESS_DOM1_WHITELIST BIT(25)
+#define CCM_ACCESS_DOM0_WHITELIST BIT(24)
+#define CCM_ACCESS_MUTEX BIT(20)
+#define CCM_ACCESS_OWNER_ID(x) ((x) << 16)
+#define CCM_ACCESS_DOM3_INFO(x) ((x) << 12)
+#define CCM_ACCESS_DOM2_INFO(x) ((x) << 8)
+#define CCM_ACCESS_DOM1_INFO(x) ((x) << 4)
+#define CCM_ACCESS_DOM0_INFO(x) (x)
+
+#define CCM_PLL_CTRL_NUM 0x21
+#define CCM_CLK_GATE_CTRL_NUM 0xbf
+#define CCM_ROOT_CTRL_NUM 0x79
+
+struct ccm {
+ uint32_t ccm_gpr0;
+ uint32_t ccm_gpr0_set;
+ uint32_t ccm_gpr0_clr;
+ uint32_t ccm_grp0_tog;
+ uint32_t reserved[0x1fc];
+ struct ccm_pll_ctrl ccm_pll_ctrl[CCM_PLL_CTRL_NUM];
+ uint32_t reserved1[0xd7c];
+ struct ccm_clk_gate_ctrl ccm_clk_gate_ctrl[CCM_CLK_GATE_CTRL_NUM];
+ uint32_t reserved2[0xd04];
+ struct ccm_target_root_ctrl ccm_root_ctrl[CCM_ROOT_CTRL_NUM];
+};
+
+void imx_clock_target_set(unsigned int id, uint32_t val);
+void imx_clock_target_clr(unsigned int id, uint32_t val);
+void imx_clock_gate_enable(unsigned int id, bool enable);
+
+void imx_clock_init(void);
+
+void imx_clock_enable_uart(unsigned int uart_id, uint32_t uart_clk_en_bits);
+void imx_clock_disable_uart(unsigned int uart_id);
+void imx_clock_enable_usdhc(unsigned int usdhc_id, uint32_t usdhc_clk_en_bits);
+void imx_clock_set_wdog_clk_root_bits(uint32_t wdog_clk_root_en_bits);
+void imx_clock_enable_wdog(unsigned int wdog_id);
+void imx_clock_disable_wdog(unsigned int wdog_id);
+void imx_clock_enable_usb(unsigned int usb_id);
+void imx_clock_disable_usb(unsigned int usb_id);
+void imx_clock_set_usb_clk_root_bits(uint32_t usb_clk_root_en_bits);
+
+#endif /* IMX_CLOCK_H */
diff --git a/plat/imx/common/include/imx_csu.h b/plat/imx/common/include/imx_csu.h
new file mode 100644
index 0000000..879d10b
--- /dev/null
+++ b/plat/imx/common/include/imx_csu.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef IMX_CSU_H
+#define IMX_CSU_H
+
+#include <arch.h>
+
+/*
+ * Security Reference Manual for i.MX 7Dual and 7Solo Applications Processors,
+ * Rev. 0, 03/2017 Section 3.3.1
+ *
+ * Config secure level register (CSU_CSLn)
+ */
+#define CSU_CSL_LOCK_S1 BIT(24)
+#define CSU_CSL_NSW_S1 BIT(23)
+#define CSU_CSL_NUW_S1 BIT(22)
+#define CSU_CSL_SSW_S1 BIT(21)
+#define CSU_CSL_SUW_S1 BIT(20)
+#define CSU_CSL_NSR_S1 BIT(19)
+#define CSU_CSL_NUR_S1 BIT(18)
+#define CSU_CSL_SSR_S1 BIT(17)
+#define CSU_CSL_SUR_S1 BIT(16)
+#define CSU_CSL_LOCK_S2 BIT(8)
+#define CSU_CSL_NSW_S2 BIT(7)
+#define CSU_CSL_NUW_S2 BIT(6)
+#define CSU_CSL_SSW_S2 BIT(5)
+#define CSU_CSL_SUW_S2 BIT(4)
+#define CSU_CSL_NSR_S2 BIT(3)
+#define CSU_CSL_NUR_S2 BIT(2)
+#define CSU_CSL_SSR_S2 BIT(1)
+#define CSU_CSL_SUR_S2 BIT(0)
+
+#define CSU_CSL_OPEN_ACCESS (CSU_CSL_NSW_S1 | CSU_CSL_NUW_S1 | CSU_CSL_SSW_S1 |\
+ CSU_CSL_SUW_S1 | CSU_CSL_NSR_S1 | CSU_CSL_NUR_S1 |\
+ CSU_CSL_SSR_S1 | CSU_CSL_SUR_S1 | CSU_CSL_NSW_S2 |\
+ CSU_CSL_NUW_S2 | CSU_CSL_SSW_S2 | CSU_CSL_SUW_S2 |\
+ CSU_CSL_NSR_S2 | CSU_CSL_NUR_S2 | CSU_CSL_SSR_S2 |\
+ CSU_CSL_SUR_S2)
+void imx_csu_init(void);
+
+#endif /* IMX_CSU_H */
diff --git a/plat/imx/common/include/imx_hab.h b/plat/imx/common/include/imx_hab.h
new file mode 100644
index 0000000..22c0742
--- /dev/null
+++ b/plat/imx/common/include/imx_hab.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef IMX_HAB_H
+#define IMX_HAB_H
+
+#include <imx_hab_arch.h>
+#include <imx_regs.h>
+
+#define HAB_ROM_VECTOR_BASE\
+ (BOOTROM_BASE + HAB_CALLBACK_OFFSET)
+/*
+ * Section 4.5 of the High Assurance Boot Version 4 Application Programming
+ * Interface Reference Manual defines the ROM Vector table as coming after a 4
+ * byte header
+ *
+ * A series of function pointers are enumerated at fixed addresses, which are
+ * described below
+ */
+#define HAB_ROM_VECTOR_TABLE_ENTRY (HAB_ROM_VECTOR_BASE + 0x04)
+#define HAB_ROM_VECTOR_TABLE_EXIT (HAB_ROM_VECTOR_BASE + 0x08)
+#define HAB_ROM_VECTOR_TABLE_CHECK_TARGET (HAB_ROM_VECTOR_BASE + 0x0C)
+#define HAB_ROM_VECTOR_TABLE_AUTHENTICATE_IMAGE (HAB_ROM_VECTOR_BASE + 0x10)
+#define HAB_ROM_VECTOR_TABLE_RUN_DCD (HAB_ROM_VECTOR_BASE + 0x14)
+#define HAB_ROM_VECTOR_TABLE_RUN_CSF (HAB_ROM_VECTOR_BASE + 0x18)
+#define HAB_ROM_VECTOR_TABLE_ASSERT (HAB_ROM_VECTOR_BASE + 0x1C)
+#define HAB_ROM_VECTOR_TABLE_REPORT_EVENT (HAB_ROM_VECTOR_BASE + 0x20)
+#define HAB_ROM_VECTOR_TABLE_REPORT_STATUS (HAB_ROM_VECTOR_BASE + 0x24)
+#define HAB_ROM_VECTOR_TABLE_FAILSAFE (HAB_ROM_VECTOR_BASE + 0x28)
+
+#endif /* IMX_HAB_H */
diff --git a/plat/imx/common/include/imx_io_mux.h b/plat/imx/common/include/imx_io_mux.h
new file mode 100644
index 0000000..d588cfd
--- /dev/null
+++ b/plat/imx/common/include/imx_io_mux.h
@@ -0,0 +1,652 @@
+/*
+ * Copyright 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_IO_MUX_H
+#define IMX_IO_MUX_H
+
+#include <stdint.h>
+#include <lib/utils_def.h>
+
+/*
+ * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016
+ * Section 8.2.7 IOMUXC Memory Map/Register Definition
+ */
+
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO08_OFFSET 0x0014
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09_OFFSET 0x0018
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO10_OFFSET 0x001C
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO11_OFFSET 0x0020
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO12_OFFSET 0x0024
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO13_OFFSET 0x0028
+
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_OFFSET 0x002C
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_ALT1_SD3_CD_B BIT(0)
+
+#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO15_OFFSET 0x0030
+
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA00_OFFSET 0x0034
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA01_OFFSET 0x0038
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA02_OFFSET 0x003C
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA03_OFFSET 0x0040
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA04_OFFSET 0x0044
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA05_OFFSET 0x0048
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA06_OFFSET 0x004C
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA07_OFFSET 0x0050
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA08_OFFSET 0x0054
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA09_OFFSET 0x0058
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA10_OFFSET 0x005C
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA11_OFFSET 0x0060
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA12_OFFSET 0x0064
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA13_OFFSET 0x0068
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA14_OFFSET 0x006C
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_DATA15_OFFSET 0x0070
+
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCLK_OFFSET 0x0074
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDLE_OFFSET 0x0078
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDOE_OFFSET 0x007C
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDSHR_OFFSET 0x0080
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE0_OFFSET 0x0084
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE1_OFFSET 0x0088
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE2_OFFSET 0x008C
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_SDCE3_OFFSET 0x0090
+
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDCLK_OFFSET 0x0094
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDOE_OFFSET 0x0098
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDRL_OFFSET 0x009C
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_GDSP_OFFSET 0x00A0
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_BDR0_OFFSET 0x00A4
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_BDR1_OFFSET 0x00A8
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_PWR_COM_OFFSET 0x00AC
+#define IOMUXC_SW_MUX_CTL_PAD_EPDC_PWR_STAT_OFFSET 0x00B0
+
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_CLK_OFFSET 0x00B4
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_ENABLE_OFFSET 0x00B8
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_HSYNC_OFFSET 0x00BC
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_VSYNC_OFFSET 0x00C0
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_RESET_OFFSET 0x00C4
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA00_OFFSET 0x00C8
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA01_OFFSET 0x00CC
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA02_OFFSET 0x00D0
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA03_OFFSET 0x00D4
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA04_OFFSET 0x00D8
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA05_OFFSET 0x00DC
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA06_OFFSET 0x00E0
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA07_OFFSET 0x00E4
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA08_OFFSET 0x00E8
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA09_OFFSET 0x00EC
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA10_OFFSET 0x00F0
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA11_OFFSET 0x00F4
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA12_OFFSET 0x00F8
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA13_OFFSET 0x00FC
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA14_OFFSET 0x0100
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA15_OFFSET 0x0104
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA16_OFFSET 0x0108
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA17_OFFSET 0x010C
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA18_OFFSET 0x0110
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA19_OFFSET 0x0114
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA20_OFFSET 0x0118
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA21_OFFSET 0x011C
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA22_OFFSET 0x0120
+#define IOMUXC_SW_MUX_CTL_PAD_LCD_DATA23_OFFSET 0x0124
+
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_OFFSET 0x0128
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT0_UART1_RX_DATA 0x00
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT1_I2C1_SCL BIT(0)
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT2_PMIC_READY BIT(1)
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT3_ECSPI1_SS1 (BIT(1) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT4_ENET2_1588_EVENT0_IN BIT(3)
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT5_GPIO4_IO0 (BIT(2) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT6_ENET1_MDIO (BIT(2) | BIT(1))
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_SION BIT(3)
+
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_OFFSET 0x012C
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT0_UART1_TX_DATA 0x00
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT1_I2C1_SDA BIT(0)
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT2_SAI3_MCLK BIT(1)
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT3_ECSPI1_SS2 (BIT(1) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT4_ENET2_1588_EVENT0_OUT BIT(3)
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT5_GPIO4_IO1 (BIT(2) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT6_ENET1_MDC (BIT(2) | BIT(1))
+#define IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_SION BIT(3)
+
+#define IOMUXC_SW_MUX_CTL_PAD_UART2_RX_DATA_OFFSET 0x0130
+#define IOMUXC_SW_MUX_CTL_PAD_UART2_TX_DATA_OFFSET 0x0134
+#define IOMUXC_SW_MUX_CTL_PAD_UART3_RX_DATA_OFFSET 0x0138
+#define IOMUXC_SW_MUX_CTL_PAD_UART3_TX_DATA_OFFSET 0x013C
+#define IOMUXC_SW_MUX_CTL_PAD_UART3_RTS_B_OFFSET 0x0140
+#define IOMUXC_SW_MUX_CTL_PAD_UART3_CTS_B_OFFSET 0x0144
+
+#define IOMUXC_SW_MUX_CTL_PAD_I2C1_SCL_OFFSET 0x0148
+#define IOMUXC_SW_MUX_CTL_PAD_I2C1_SDA_OFFSET 0x014C
+#define IOMUXC_SW_MUX_CTL_PAD_I2C2_SCL_OFFSET 0x0150
+#define IOMUXC_SW_MUX_CTL_PAD_I2C2_SDA_OFFSET 0x0154
+#define IOMUXC_SW_MUX_CTL_PAD_I2C3_SCL_OFFSET 0x0158
+#define IOMUXC_SW_MUX_CTL_PAD_I2C3_SDA_OFFSET 0x015C
+
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_OFFSET 0x0160
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT0_I2C4_SCL 0x0
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT1_UART5_RX_DATA BIT(0)
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT2_WDOG4_WDOG_B BIT(1)
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT3_CSI_PIXCLK (BIT(1) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT4_USB_OTG1_ID BIT(2)
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT5_GPIO4_IO14 (BIT(2) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT6_EPDC_VCOM0 (BIT(2) | BIT(1))
+
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_OFFSET 0x0164
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT0_I2C4_SDA 0x0
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT1_UART5_TX_DATA BIT(0)
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT2_WDOG4_WDOG_RST_B_DEB BIT(1)
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT3_CSI_MCLK (BIT(1) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT4_USB_OTG2_ID BIT(2)
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT5_GPIO4_IO15 (BIT(1) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT6_EPDC_VCOM1 (BIT(2) | BIT(1))
+
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_OFFSET 0x0168
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT0_ECSPI1_SCLK 0x00
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT1_UART6_RX_DATA BIT(0)
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT2_SD2_DATA4 BIT(1)
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT3_CSI_DATA2 (BIT(1) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT5_GPIO4_IO16 (BIT(2) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT6_EPDC_PWR_COM (BIT(2) | (BIT(1))
+
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_OFFSET 0x016C
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT0_ECSPI1_MOSI 0x00
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT1_UART6_TX_DATA BIT(0)
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT2_SD2_DATA5 BIT(1)
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT3_CSI_DATA3 (BIT(1) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT5_GPIO4_IO17 (BIT(2) | BIT(0))
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT6_EPDC_PWR_STAT (BIT(2) | (BIT(1))
+
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MISO_OFFSET 0x0170
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SS0_OFFSET 0x0174
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_SCLK_OFFSET 0x0178
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_MOSI_OFFSET 0x017C
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_MISO_OFFSET 0x0180
+#define IOMUXC_SW_MUX_CTL_PAD_ECSPI2_SS0_OFFSET 0x0184
+
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_CD_B_OFFSET 0x0188
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_WP_OFFSET 0x018C
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_RESET_B_OFFSET 0x0190
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_CLK_OFFSET 0x0194
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_CMD_OFFSET 0x0198
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA0_OFFSET 0x019C
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA1_OFFSET 0x01A0
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2_OFFSET 0x01A4
+#define IOMUXC_SW_MUX_CTL_PAD_SD1_DATA3_OFFSET 0x01A8
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_CD_B_OFFSET 0x01AC
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_WP_OFFSET 0x01B0
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_RESET_B_OFFSET 0x01B4
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_CLK_OFFSET 0x01B8
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_CMD_OFFSET 0x01BC
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA0_OFFSET 0x01C0
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA1_OFFSET 0x01C4
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA2_OFFSET 0x01C8
+#define IOMUXC_SW_MUX_CTL_PAD_SD2_DATA3_OFFSET 0x01CC
+
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_CLK_OFFSET 0x01D0
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_CMD_OFFSET 0x01D4
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA0_OFFSET 0x01D8
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA1_OFFSET 0x01DC
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA2_OFFSET 0x01E0
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA3_OFFSET 0x01E4
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA4_OFFSET 0x01E8
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA5_OFFSET 0x01EC
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA6_OFFSET 0x01F0
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_DATA7_OFFSET 0x01F4
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_STROBE_OFFSET 0x01F8
+#define IOMUXC_SW_MUX_CTL_PAD_SD3_RESET_B_OFFSET 0x01FC
+
+#define IOMUXC_SW_MUX_CTL_PAD_SAI1_RX_DATA_OFFSET 0x0200
+#define IOMUXC_SW_MUX_CTL_PAD_SAI1_TX_BCLK_OFFSET 0x0204
+#define IOMUXC_SW_MUX_CTL_PAD_SAI1_TX_SYNC_OFFSET 0x0208
+#define IOMUXC_SW_MUX_CTL_PAD_SAI1_TX_DATA_OFFSET 0x020C
+#define IOMUXC_SW_MUX_CTL_PAD_SAI1_RX_SYNC_OFFSET 0x0210
+#define IOMUXC_SW_MUX_CTL_PAD_SAI1_RX_BCLK_OFFSET 0x0214
+#define IOMUXC_SW_MUX_CTL_PAD_SAI1_MCLK_OFFSET 0x0218
+#define IOMUXC_SW_MUX_CTL_PAD_SAI2_TX_SYNC_OFFSET 0x021C
+#define IOMUXC_SW_MUX_CTL_PAD_SAI2_TX_BCLK_OFFSET 0x0220
+#define IOMUXC_SW_MUX_CTL_PAD_SAI2_RX_DATA_OFFSET 0x0224
+#define IOMUXC_SW_MUX_CTL_PAD_SAI2_TX_DATA_OFFSET 0x0228
+
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD0_OFFSET 0x022C
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD1_OFFSET 0x0230
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD2_OFFSET 0x0234
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RD3_OFFSET 0x0238
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RX_CTL_OFFSET 0x023C
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_RXC_OFFSET 0x0240
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD0_OFFSET 0x0244
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD1_OFFSET 0x0248
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD2_OFFSET 0x024C
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TD3_OFFSET 0x0250
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TX_CTL_OFFSET 0x0254
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RGMII_TXC_OFFSET 0x0258
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_CLK_OFFSET 0x025C
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_RX_CLK_OFFSET 0x0260
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_CRS_OFFSET 0x0264
+#define IOMUXC_SW_MUX_CTL_PAD_ENET1_COL_OFFSET 0x0268
+
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO08_OFFSET 0x026C
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO09_OFFSET 0x0270
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO10_OFFSET 0x0274
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO11_OFFSET 0x0278
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO12_OFFSET 0x027C
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO13_OFFSET 0x0280
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO14_OFFSET 0x0284
+#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO15_OFFSET 0x0288
+
+#define IOMUXC_SW_PAD_CTL_PAD_JTAG_MOD_OFFSET 0x028C
+#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TCK_OFFSET 0x0290
+#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TDI_OFFSET 0x0294
+#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TDO_OFFSET 0x0298
+#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TMS_OFFSET 0x029C
+#define IOMUXC_SW_PAD_CTL_PAD_JTAG_TRST_B_OFFSET 0x02A0
+
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA00_OFFSET 0x02A4
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA01_OFFSET 0x02A8
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA02_OFFSET 0x02AC
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA03_OFFSET 0x02B0
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA04_OFFSET 0x02B4
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA05_OFFSET 0x02B8
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA06_OFFSET 0x02BC
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA07_OFFSET 0x02C0
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA08_OFFSET 0x02C4
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA09_OFFSET 0x02C8
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA10_OFFSET 0x02CC
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA11_OFFSET 0x02D0
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA12_OFFSET 0x02D4
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA13_OFFSET 0x02D8
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA14_OFFSET 0x02DC
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_DATA15_OFFSET 0x02E0
+
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCLK_OFFSET 0x02E4
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDLE_OFFSET 0x02E8
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDOE_OFFSET 0x02EC
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDSHR_OFFSET 0x02F0
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE0_OFFSET 0x02F4
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE1_OFFSET 0x02F8
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE2_OFFSET 0x02FC
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_SDCE3_OFFSET 0x0300
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDCLK_OFFSET 0x0304
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDOE_OFFSET 0x0308
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDRL_OFFSET 0x030C
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_GDSP_OFFSET 0x0310
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_BDR0_OFFSET 0x0314
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_BDR1_OFFSET 0x0318
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_PWR_COM_OFFSET 0x031C
+#define IOMUXC_SW_PAD_CTL_PAD_EPDC_PWR_STAT_OFFSET 0x0320
+
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_CLK_OFFSET 0x0324
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_ENABLE_OFFSET 0x0328
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_HSYNC_OFFSET 0x032C
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_VSYNC_OFFSET 0x0330
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_RESET_OFFSET 0x0334
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA00_OFFSET 0x0338
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA01_OFFSET 0x033C
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA02_OFFSET 0x0340
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA03_OFFSET 0x0344
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA04_OFFSET 0x0348
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA05_OFFSET 0x034C
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA06_OFFSET 0x0350
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA07_OFFSET 0x0354
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA08_OFFSET 0x0358
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA09_OFFSET 0x035C
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA10_OFFSET 0x0360
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA11_OFFSET 0x0364
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA12_OFFSET 0x0368
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA13_OFFSET 0x036C
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA14_OFFSET 0x0370
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA15_OFFSET 0x0374
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA16_OFFSET 0x0378
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA17_OFFSET 0x037C
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA18_OFFSET 0x0380
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA19_OFFSET 0x0384
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA20_OFFSET 0x0388
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA21_OFFSET 0x038C
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA22_OFFSET 0x0390
+#define IOMUXC_SW_PAD_CTL_PAD_LCD_DATA23_OFFSET 0x0394
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_OFFSET 0x0398
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_0_X1 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_1_X4 BIT(0)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_2_X2 BIT(1)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_3_X6 (BIT(1) | BIT(0))
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_SRE_FAST 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_SRE_SLOW BIT(2)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_HYS_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_HYS_EN BIT(3)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PE_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PE_EN BIT(4)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_0_100K_PD 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_1_5K_PU BIT(5)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_2_47K_PU BIT(6)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_3_100K_PU (BIT(6) | BIT(5))
+
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_OFFSET 0x039C
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_0_X1 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_1_X4 BIT(0)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_2_X2 BIT(1)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_3_X6 (BIT(1) | BIT(0))
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_SRE_FAST 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_SRE_SLOW BIT(2)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_HYS_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_HYS_EN BIT(3)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PE_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PE_EN BIT(4)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_0_100K_PD 0
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_1_5K_PU BIT(5)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_2_47K_PU BIT(6)
+#define IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_3_100K_PU (BIT(6) | BIT(5))
+
+#define IOMUXC_SW_PAD_CTL_PAD_UART2_RX_DATA_OFFSET 0x03A0
+#define IOMUXC_SW_PAD_CTL_PAD_UART2_TX_DATA_OFFSET 0x03A4
+#define IOMUXC_SW_PAD_CTL_PAD_UART3_RX_DATA_OFFSET 0x03A8
+#define IOMUXC_SW_PAD_CTL_PAD_UART3_TX_DATA_OFFSET 0x03AC
+#define IOMUXC_SW_PAD_CTL_PAD_UART3_RTS_B_OFFSET 0x03B0
+#define IOMUXC_SW_PAD_CTL_PAD_UART3_CTS_B_OFFSET 0x03B4
+
+#define IOMUXC_SW_PAD_CTL_PAD_I2C1_SCL_OFFSET 0x03B8
+#define IOMUXC_SW_PAD_CTL_PAD_I2C1_SDA_OFFSET 0x03BC
+#define IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL_OFFSET 0x03C0
+#define IOMUXC_SW_PAD_CTL_PAD_I2C2_SDA_OFFSET 0x03C4
+#define IOMUXC_SW_PAD_CTL_PAD_I2C3_SCL_OFFSET 0x03C8
+#define IOMUXC_SW_PAD_CTL_PAD_I2C3_SDA_OFFSET 0x03CC
+#define IOMUXC_SW_PAD_CTL_PAD_I2C4_SCL_OFFSET 0x03D0
+#define IOMUXC_SW_PAD_CTL_PAD_I2C4_SDA_OFFSET 0x03D4
+
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_OFFSET 0x03D8
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_0_X1 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_1_X4 BIT(0)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_2_X2 BIT(1)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_3_X6 (BIT(1) | BIT(0))
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_SRE_FAST 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_SRE_SLOW BIT(2)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_HYS_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_HYS_EN BIT(3)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PE_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PE_EN BIT(4)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_0_100K_PD 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_1_5K_PU BIT(5)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_2_47K_PU BIT(6)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_3_100K_PU (BIT(6) | BIT(5))
+
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_OFFSET 0x03DC
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_0_X1 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_1_X4 BIT(0)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_2_X2 BIT(1)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_3_X6 (BIT(1) | BIT(0))
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_SRE_FAST 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_SRE_SLOW BIT(2)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_HYS_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_HYS_EN BIT(3)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PE_DIS 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PE_EN BIT(4)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_0_100K_PD 0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_1_5K_PU BIT(5)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_2_47K_PU BIT(6)
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_3_100K_PU (BIT(6) | BIT(5))
+
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MISO_OFFSET 0x03E0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SS0_OFFSET 0x03E4
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_SCLK_OFFSET 0x03E8
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_MOSI_OFFSET 0x03EC
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_MISO_OFFSET 0x03F0
+#define IOMUXC_SW_PAD_CTL_PAD_ECSPI2_SS0_OFFSET 0x03F4
+
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_CD_B_OFFSET 0x03F8
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_WP_OFFSET 0x03FC
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_RESET_B_OFFSET 0x0400
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_CLK_OFFSET 0x0404
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_CMD_OFFSET 0x0408
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA0_OFFSET 0x040C
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA1_OFFSET 0x0410
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2_OFFSET 0x0414
+#define IOMUXC_SW_PAD_CTL_PAD_SD1_DATA3_OFFSET 0x0418
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_CD_B_OFFSET 0x041C
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_WP_OFFSET 0x0420
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_RESET_B_OFFSET 0x0424
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_CLK_OFFSET 0x0428
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_CMD_OFFSET 0x042C
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA0_OFFSET 0x0430
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA1_OFFSET 0x0434
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA2_OFFSET 0x0438
+#define IOMUXC_SW_PAD_CTL_PAD_SD2_DATA3_OFFSET 0x043C
+
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_CLK_OFFSET 0x0440
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_CMD_OFFSET 0x0444
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA0_OFFSET 0x0448
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA1_OFFSET 0x044C
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA2_OFFSET 0x0450
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA3_OFFSET 0x0454
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA4_OFFSET 0x0458
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA5_OFFSET 0x045C
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA6_OFFSET 0x0460
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DATA7_OFFSET 0x0464
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_STROBE_OFFSET 0x0468
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_RESET_B_OFFSET 0x046C
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_0_X1 0
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_1_X4 BIT(0)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_2_X2 BIT(1)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_3_X6 (BIT(1) | BIT(0))
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_1_X4 BIT(0)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_SLEW_SLOW BIT(2)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_SLEW_FAST 0
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_HYS BIT(3)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_PE BIT(4)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_PD_100K (0 << 5)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_PU_5K (1 << 5)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_PU_47K (2 << 5)
+#define IOMUXC_SW_PAD_CTL_PAD_SD3_PU_100K (3 << 5)
+
+#define IOMUXC_SW_PAD_CTL_PAD_SAI1_RX_DATA_OFFSET 0x0470
+#define IOMUXC_SW_PAD_CTL_PAD_SAI1_TX_BCLK_OFFSET 0x0474
+#define IOMUXC_SW_PAD_CTL_PAD_SAI1_TX_SYNC_OFFSET 0x0478
+#define IOMUXC_SW_PAD_CTL_PAD_SAI1_TX_DATA_OFFSET 0x047C
+#define IOMUXC_SW_PAD_CTL_PAD_SAI1_RX_SYNC_OFFSET 0x0480
+#define IOMUXC_SW_PAD_CTL_PAD_SAI1_RX_BCLK_OFFSET 0x0484
+#define IOMUXC_SW_PAD_CTL_PAD_SAI1_MCLK_OFFSET 0x0488
+#define IOMUXC_SW_PAD_CTL_PAD_SAI2_TX_SYNC_OFFSET 0x048C
+#define IOMUXC_SW_PAD_CTL_PAD_SAI2_TX_BCLK_OFFSET 0x0490
+#define IOMUXC_SW_PAD_CTL_PAD_SAI2_RX_DATA_OFFSET 0x0494
+#define IOMUXC_SW_PAD_CTL_PAD_SAI2_TX_DATA_OFFSET 0x0498
+
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD0_OFFSET 0x049C
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD1_OFFSET 0x04A0
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD2_OFFSET 0x04A4
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RD3_OFFSET 0x04A8
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RX_CTL_OFFSET 0x04AC
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_RXC_OFFSET 0x04B0
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD0_OFFSET 0x04B4
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD1_OFFSET 0x04B8
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD2_OFFSET 0x04BC
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TD3_OFFSET 0x04C0
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TX_CTL_OFFSET 0x04C4
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RGMII_TXC_OFFSET 0x04C8
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_TX_CLK_OFFSET 0x04CC
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_RX_CLK_OFFSET 0x04D0
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_CRS_OFFSET 0x04D4
+#define IOMUXC_SW_PAD_CTL_PAD_ENET1_COL_OFFSET 0x04D8
+
+#define IOMUXC_FLEXCAN1_RX_SELECT_INPUT_OFFSET 0x04DC
+#define IOMUXC_FLEXCAN2_RX_SELECT_INPUT_OFFSET 0x04E0
+
+#define IOMUXC_CCM_EXT_CLK_1_SELECT_INPUT_OFFSET 0x04E4
+#define IOMUXC_CCM_EXT_CLK_2_SELECT_INPUT_OFFSET 0x04E8
+#define IOMUXC_CCM_EXT_CLK_3_SELECT_INPUT_OFFSET 0x04EC
+#define IOMUXC_CCM_EXT_CLK_4_SELECT_INPUT_OFFSET 0x04F0
+
+#define IOMUXC_CCM_PMIC_READY_SELECT_INPUT_OFFSET 0x04F4
+
+#define IOMUXC_CSI_DATA2_SELECT_INPUT_OFFSET 0x04F8
+#define IOMUXC_CSI_DATA3_SELECT_INPUT_OFFSET 0x04FC
+#define IOMUXC_CSI_DATA4_SELECT_INPUT_OFFSET 0x0500
+#define IOMUXC_CSI_DATA5_SELECT_INPUT_OFFSET 0x0504
+#define IOMUXC_CSI_DATA6_SELECT_INPUT_OFFSET 0x0508
+#define IOMUXC_CSI_DATA7_SELECT_INPUT_OFFSET 0x050C
+#define IOMUXC_CSI_DATA8_SELECT_INPUT_OFFSET 0x0510
+#define IOMUXC_CSI_DATA9_SELECT_INPUT_OFFSET 0x0514
+#define IOMUXC_CSI_HSYNC_SELECT_INPUT_OFFSET 0x0518
+#define IOMUXC_CSI_PIXCLK_SELECT_INPUT_OFFSET 0x051C
+#define IOMUXC_CSI_VSYNC_SELECT_INPUT_OFFSET 0x0520
+
+#define IOMUXC_ECSPI1_SCLK_SELECT_INPUT_OFFSET 0x0524
+#define IOMUXC_ECSPI1_MISO_SELECT_INPUT_OFFSET 0x0528
+#define IOMUXC_ECSPI1_MOSI_SELECT_INPUT_OFFSET 0x052C
+#define IOMUXC_ECSPI1_SS0_B_SELECT_INPUT_OFFSET 0x0530
+#define IOMUXC_ECSPI2_SCLK_SELECT_INPUT_OFFSET 0x0534
+#define IOMUXC_ECSPI2_MISO_SELECT_INPUT_OFFSET 0x0538
+#define IOMUXC_ECSPI2_MOSI_SELECT_INPUT_OFFSET 0x053C
+#define IOMUXC_ECSPI2_SS0_B_SELECT_INPUT_OFFSET 0x0540
+#define IOMUXC_ECSPI3_SCLK_SELECT_INPUT_OFFSET 0x0544
+#define IOMUXC_ECSPI3_MISO_SELECT_INPUT_OFFSET 0x0548
+#define IOMUXC_ECSPI3_MOSI_SELECT_INPUT_OFFSET 0x054C
+#define IOMUXC_ECSPI3_SS0_B_SELECT_INPUT_OFFSET 0x0550
+#define IOMUXC_ECSPI4_SCLK_SELECT_INPUT_OFFSET 0x0554
+#define IOMUXC_ECSPI4_MISO_SELECT_INPUT_OFFSET 0x0558
+#define IOMUXC_ECSPI4_MOSI_SELECT_INPUT_OFFSET 0x055C
+#define IOMUXC_ECSPI4_SS0_B_SELECT_INPUT_OFFSET 0x0560
+
+#define IOMUXC_CCM_ENET1_REF_CLK_SELECT_INPUT_OFFSET 0x0564
+#define IOMUXC_ENET1_MDIO_SELECT_INPUT_OFFSET 0x0568
+#define IOMUXC_ENET1_RX_CLK_SELECT_INPUT_OFFSET 0x056C
+#define IOMUXC_CCM_ENET2_REF_CLK_SELECT_INPUT_OFFSET 0x0570
+#define IOMUXC_ENET2_MDIO_SELECT_INPUT_OFFSET 0x0574
+#define IOMUXC_ENET2_RX_CLK_SELECT_INPUT_OFFSET 0x0578
+
+#define IOMUXC_EPDC_PWR_IRQ_SELECT_INPUT_OFFSET 0x057C
+#define IOMUXC_EPDC_PWR_STAT_SELECT_INPUT_OFFSET 0x0580
+
+#define IOMUXC_FLEXTIMER1_CH0_SELECT_INPUT_OFFSET 0x0584
+#define IOMUXC_FLEXTIMER1_CH1_SELECT_INPUT_OFFSET 0x0588
+#define IOMUXC_FLEXTIMER1_CH2_SELECT_INPUT_OFFSET 0x058C
+#define IOMUXC_FLEXTIMER1_CH3_SELECT_INPUT_OFFSET 0x0590
+#define IOMUXC_FLEXTIMER1_CH4_SELECT_INPUT_OFFSET 0x0594
+#define IOMUXC_FLEXTIMER1_CH5_SELECT_INPUT_OFFSET 0x0598
+#define IOMUXC_FLEXTIMER1_CH6_SELECT_INPUT_OFFSET 0x059C
+#define IOMUXC_FLEXTIMER1_CH7_SELECT_INPUT_OFFSET 0x05A0
+#define IOMUXC_FLEXTIMER1_PHA_SELECT_INPUT_OFFSET 0x05A4
+#define IOMUXC_FLEXTIMER1_PHB_SELECT_INPUT_OFFSET 0x05A8
+#define IOMUXC_FLEXTIMER2_CH0_SELECT_INPUT_OFFSET 0x05AC
+#define IOMUXC_FLEXTIMER2_CH1_SELECT_INPUT_OFFSET 0x05B0
+#define IOMUXC_FLEXTIMER2_CH2_SELECT_INPUT_OFFSET 0x05B4
+#define IOMUXC_FLEXTIMER2_CH3_SELECT_INPUT_OFFSET 0x05B8
+#define IOMUXC_FLEXTIMER2_CH4_SELECT_INPUT_OFFSET 0x05BC
+#define IOMUXC_FLEXTIMER2_CH5_SELECT_INPUT_OFFSET 0x05C0
+#define IOMUXC_FLEXTIMER2_CH6_SELECT_INPUT_OFFSET 0x05C4
+#define IOMUXC_FLEXTIMER2_CH7_SELECT_INPUT_OFFSET 0x05C8
+#define IOMUXC_FLEXTIMER2_PHA_SELECT_INPUT_OFFSET 0x05CC
+#define IOMUXC_FLEXTIMER2_PHB_SELECT_INPUT_OFFSET 0x05D0
+
+#define IOMUXC_I2C1_SCL_SELECT_INPUT_OFFSET 0x05D4
+#define IOMUXC_I2C1_SDA_SELECT_INPUT_OFFSET 0x05D8
+#define IOMUXC_I2C2_SCL_SELECT_INPUT_OFFSET 0x05DC
+#define IOMUXC_I2C2_SDA_SELECT_INPUT_OFFSET 0x05E0
+#define IOMUXC_I2C3_SCL_SELECT_INPUT_OFFSET 0x05E4
+#define IOMUXC_I2C3_SDA_SELECT_INPUT_OFFSET 0x05E8
+#define IOMUXC_I2C4_SCL_SELECT_INPUT_OFFSET 0x05EC
+#define IOMUXC_I2C4_SDA_SELECT_INPUT_OFFSET 0x05F0
+
+#define IOMUXC_KPP_COL0_SELECT_INPUT_OFFSET 0x05F4
+#define IOMUXC_KPP_COL1_SELECT_INPUT_OFFSET 0x05F8
+#define IOMUXC_KPP_COL2_SELECT_INPUT_OFFSET 0x05FC
+#define IOMUXC_KPP_COL3_SELECT_INPUT_OFFSET 0x0600
+#define IOMUXC_KPP_COL4_SELECT_INPUT_OFFSET 0x0604
+#define IOMUXC_KPP_COL5_SELECT_INPUT_OFFSET 0x0608
+#define IOMUXC_KPP_COL6_SELECT_INPUT_OFFSET 0x060C
+#define IOMUXC_KPP_COL7_SELECT_INPUT_OFFSET 0x0610
+#define IOMUXC_KPP_ROW0_SELECT_INPUT_OFFSET 0x0614
+#define IOMUXC_KPP_ROW1_SELECT_INPUT_OFFSET 0x0618
+#define IOMUXC_KPP_ROW2_SELECT_INPUT_OFFSET 0x061C
+#define IOMUXC_KPP_ROW3_SELECT_INPUT_OFFSET 0x0620
+#define IOMUXC_KPP_ROW4_SELECT_INPUT_OFFSET 0x0624
+#define IOMUXC_KPP_ROW5_SELECT_INPUT_OFFSET 0x0628
+#define IOMUXC_KPP_ROW6_SELECT_INPUT_OFFSET 0x062C
+#define IOMUXC_KPP_ROW7_SELECT_INPUT_OFFSET 0x0630
+
+#define IOMUXC_LCD_BUSY_SELECT_INPUT_OFFSET 0x0634
+#define IOMUXC_LCD_DATA00_SELECT_INPUT_OFFSET 0x0638
+#define IOMUXC_LCD_DATA01_SELECT_INPUT_OFFSET 0x063C
+#define IOMUXC_LCD_DATA02_SELECT_INPUT_OFFSET 0x0640
+#define IOMUXC_LCD_DATA03_SELECT_INPUT_OFFSET 0x0644
+#define IOMUXC_LCD_DATA04_SELECT_INPUT_OFFSET 0x0648
+#define IOMUXC_LCD_DATA05_SELECT_INPUT_OFFSET 0x064C
+#define IOMUXC_LCD_DATA06_SELECT_INPUT_OFFSET 0x0650
+#define IOMUXC_LCD_DATA07_SELECT_INPUT_OFFSET 0x0654
+#define IOMUXC_LCD_DATA08_SELECT_INPUT_OFFSET 0x0658
+#define IOMUXC_LCD_DATA09_SELECT_INPUT_OFFSET 0x065C
+#define IOMUXC_LCD_DATA10_SELECT_INPUT_OFFSET 0x0660
+#define IOMUXC_LCD_DATA11_SELECT_INPUT_OFFSET 0x0664
+#define IOMUXC_LCD_DATA12_SELECT_INPUT_OFFSET 0x0668
+#define IOMUXC_LCD_DATA13_SELECT_INPUT_OFFSET 0x066C
+#define IOMUXC_LCD_DATA14_SELECT_INPUT_OFFSET 0x0670
+#define IOMUXC_LCD_DATA15_SELECT_INPUT_OFFSET 0x0674
+#define IOMUXC_LCD_DATA16_SELECT_INPUT_OFFSET 0x0678
+#define IOMUXC_LCD_DATA17_SELECT_INPUT_OFFSET 0x067C
+#define IOMUXC_LCD_DATA18_SELECT_INPUT_OFFSET 0x0680
+#define IOMUXC_LCD_DATA19_SELECT_INPUT_OFFSET 0x0684
+#define IOMUXC_LCD_DATA20_SELECT_INPUT_OFFSET 0x0688
+#define IOMUXC_LCD_DATA21_SELECT_INPUT_OFFSET 0x068C
+#define IOMUXC_LCD_DATA22_SELECT_INPUT_OFFSET 0x0690
+#define IOMUXC_LCD_DATA23_SELECT_INPUT_OFFSET 0x0694
+#define IOMUXC_LCD_VSYNC_SELECT_INPUT_OFFSET 0x0698
+
+#define IOMUXC_SAI1_RX_BCLK_SELECT_INPUT_OFFSET 0x069C
+#define IOMUXC_SAI1_RX_DATA_SELECT_INPUT_OFFSET 0x06A0
+#define IOMUXC_SAI1_RX_SYNC_SELECT_INPUT_OFFSET 0x06A4
+#define IOMUXC_SAI1_TX_BCLK_SELECT_INPUT_OFFSET 0x06A8
+#define IOMUXC_SAI1_TX_SYNC_SELECT_INPUT_OFFSET 0x06AC
+#define IOMUXC_SAI2_RX_BCLK_SELECT_INPUT_OFFSET 0x06B0
+#define IOMUXC_SAI2_RX_DATA_SELECT_INPUT_OFFSET 0x06B4
+#define IOMUXC_SAI2_RX_SYNC_SELECT_INPUT_OFFSET 0x06B8
+#define IOMUXC_SAI2_TX_BCLK_SELECT_INPUT_OFFSET 0x06BC
+#define IOMUXC_SAI2_TX_SYNC_SELECT_INPUT_OFFSET 0x06C0
+#define IOMUXC_SAI3_RX_BCLK_SELECT_INPUT_OFFSET 0x06C4
+#define IOMUXC_SAI3_RX_DATA_SELECT_INPUT_OFFSET 0x06C8
+#define IOMUXC_SAI3_RX_SYNC_SELECT_INPUT_OFFSET 0x06CC
+#define IOMUXC_SAI3_TX_BCLK_SELECT_INPUT_OFFSET 0x06D0
+#define IOMUXC_SAI3_TX_SYNC_SELECT_INPUT_OFFSET 0x06D4
+#define IOMUXC_SDMA_EVENTS0_SELECT_INPUT_OFFSET 0x06D8
+#define IOMUXC_SDMA_EVENTS1_SELECT_INPUT_OFFSET 0x06DC
+
+#define IOMUXC_SIM1_PORT1_PD_SELECT_INPUT_OFFSET 0x06E0
+#define IOMUXC_SIM1_PORT1_TRXD_SELECT_INPUT_OFFSET 0x06E4
+#define IOMUXC_SIM2_PORT1_PD_SELECT_INPUT_OFFSET 0x06E8
+#define IOMUXC_SIM2_PORT1_TRXD_SELECT_INPUT_OFFSET 0x06EC
+
+#define IOMUXC_UART1_RTS_B_SELECT_INPUT_OFFSET 0x06F0
+#define IOMUXC_UART1_RX_DATA_SELECT_INPUT_OFFSET 0x06F4
+#define IOMUXC_UART2_RTS_B_SELECT_INPUT_OFFSET 0x06F8
+#define IOMUXC_UART2_RX_DATA_SELECT_INPUT_OFFSET 0x06FC
+#define IOMUXC_UART3_RTS_B_SELECT_INPUT_OFFSET 0x0700
+#define IOMUXC_UART3_RX_DATA_SELECT_INPUT_OFFSET 0x0704
+#define IOMUXC_UART4_RTS_B_SELECT_INPUT_OFFSET 0x0708
+#define IOMUXC_UART4_RX_DATA_SELECT_INPUT_OFFSET 0x070C
+#define IOMUXC_UART5_RTS_B_SELECT_INPUT_OFFSET 0x0710
+
+#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_OFFSET 0x0714
+#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_I2C4_SCL_ALT1 0x00
+#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_I2C4_SDA_ALT1 BIT(0)
+#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_SAI1_RX_DATA_ALT2 BIT(1)
+#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_SAI1_TX_BCLK_ALT2 (BIT(1) | BIT(0))
+#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_GPIO1_IO06_ALT3 BIT(2)
+#define IOMUXC_UART5_RX_DATA_SELECT_INPUT_GPIO1_IO07_ALT3 (BIT(2) | BIT(1))
+
+#define IOMUXC_UART6_RTS_B_SELECT_INPUT_OFFSET 0x0718
+#define IOMUXC_UART6_RX_DATA_SELECT_INPUT_OFFSET 0x071C
+#define IOMUXC_UART7_RTS_B_SELECT_INPUT_OFFSET 0x0720
+#define IOMUXC_UART7_RX_DATA_SELECT_INPUT_OFFSET 0x0724
+
+#define IOMUXC_USB_OTG2_OC_SELECT_INPUT_OFFSET 0x0728
+#define IOMUXC_USB_OTG1_OC_SELECT_INPUT_OFFSET 0x072C
+#define IOMUXC_USB_OTG2_ID_SELECT_INPUT_OFFSET 0x0730
+#define IOMUXC_USB_OTG1_ID_SELECT_INPUT_OFFSET 0x0734
+#define IOMUXC_SD3_CD_B_SELECT_INPUT_OFFSET 0x0738
+#define IOMUXC_SD3_WP_SELECT_INPUT_OFFSET 0x073C
+
+/* Pad mux/feature set routines */
+
+void imx_io_muxc_set_pad_alt_function(uint32_t pad_mux_offset, uint32_t alt_function);
+void imx_io_muxc_set_pad_features(uint32_t pad_feature_offset, uint32_t pad_features);
+
+#endif /* IMX_IO_MUX_H */
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
new file mode 100644
index 0000000..1f45985
--- /dev/null
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __IMX_SIP_SVC_H__
+#define __IMX_SIP_SVC_H__
+
+/* SMC function IDs for SiP Service queries */
+#define IMX_SIP_GPC 0xC2000000
+
+#define IMX_SIP_CPUFREQ 0xC2000001
+#define IMX_SIP_SET_CPUFREQ 0x00
+
+#define IMX_SIP_SRTC 0xC2000002
+#define IMX_SIP_SRTC_SET_TIME 0x00
+
+#define IMX_SIP_BUILDINFO 0xC2000003
+#define IMX_SIP_BUILDINFO_GET_COMMITHASH 0x00
+
+#define IMX_SIP_DDR_DVFS 0xc2000004
+
+#define IMX_SIP_SRC 0xC2000005
+#define IMX_SIP_SRC_SET_SECONDARY_BOOT 0x10
+#define IMX_SIP_SRC_IS_SECONDARY_BOOT 0x11
+
+#define IMX_SIP_GET_SOC_INFO 0xC2000006
+
+#define IMX_SIP_HAB 0xC2000007
+#define IMX_SIP_HAB_AUTH_IMG 0x00
+#define IMX_SIP_HAB_ENTRY 0x01
+#define IMX_SIP_HAB_EXIT 0x02
+#define IMX_SIP_HAB_REPORT_EVENT 0x03
+#define IMX_SIP_HAB_REPORT_STATUS 0x04
+#define IMX_SIP_HAB_FAILSAFE 0x05
+#define IMX_SIP_HAB_CHECK_TARGET 0x06
+#define IMX_SIP_HAB_GET_VERSION 0x07
+#define IMX_SIP_HAB_AUTH_IMG_NO_DCD 0x08
+
+#define IMX_SIP_WAKEUP_SRC 0xC2000009
+#define IMX_SIP_WAKEUP_SRC_SCU 0x1
+#define IMX_SIP_WAKEUP_SRC_IRQSTEER 0x2
+
+#define IMX_SIP_OTP_READ 0xC200000A
+#define IMX_SIP_OTP_WRITE 0xC200000B
+
+#define IMX_SIP_MISC_SET_TEMP 0xC200000C
+
+#define IMX_SIP_AARCH32 0xC20000FD
+
+int imx_kernel_entry_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4);
+#if defined(PLAT_imx8mq)
+int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3);
+#endif
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+int dram_dvfs_handler(uint32_t smc_fid, void *handle,
+ u_register_t x1, u_register_t x2, u_register_t x3);
+
+int imx_gpc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3);
+#endif
+
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq)
+int imx_src_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3, void *handle);
+#endif
+
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+int imx_hab_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3, u_register_t x4);
+#endif
+
+#if (defined(PLAT_imx8qm) || defined(PLAT_imx8qx))
+int imx_cpufreq_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3);
+int imx_srtc_handler(uint32_t smc_fid, void *handle, u_register_t x1,
+ u_register_t x2, u_register_t x3, u_register_t x4);
+int imx_wakeup_src_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3);
+int imx_otp_handler(uint32_t smc_fid, void *handle,
+ u_register_t x1, u_register_t x2);
+int imx_misc_set_temp_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4);
+#endif
+uint64_t imx_buildinfo_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4);
+
+#endif /* __IMX_SIP_SVC_H__ */
diff --git a/plat/imx/common/include/imx_snvs.h b/plat/imx/common/include/imx_snvs.h
new file mode 100644
index 0000000..565c451
--- /dev/null
+++ b/plat/imx/common/include/imx_snvs.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef IMX_SNVS_H
+#define IMX_SNVS_H
+
+#include <cdefs.h>
+#include <stdint.h>
+
+#include <arch.h>
+
+struct snvs {
+ uint32_t hplr;
+ uint32_t hpcomr;
+ uint32_t hpcr;
+ uint32_t hpsicr;
+ uint32_t hpsvcr;
+ uint32_t hpsr;
+ uint32_t hpsvsr;
+ uint32_t hphacivr;
+ uint32_t hphacr;
+ uint32_t hprtcmr;
+ uint32_t hprtclr;
+ uint32_t hptamr;
+ uint32_t hptalr;
+ uint32_t lplr;
+ uint32_t lpcr;
+ uint32_t lpmkcr;
+ uint32_t lpsvcr;
+ uint32_t lptgfcr;
+ uint32_t lptdcr;
+ uint32_t lpsr;
+ uint32_t lpsrtcmr;
+ uint32_t lpsrtclr;
+ uint32_t lptar;
+ uint32_t lpsmcmr;
+ uint32_t lpsmclr;
+ uint32_t lppgdr;
+ uint32_t lpgpr0_alias;
+ uint8_t lpzmkr[32];
+ uint16_t res0;
+ uint32_t lpgpr0[4];
+ uint32_t lptdc2r;
+ uint32_t lptdsr;
+ uint32_t lptgf1cr;
+ uint32_t lptgf2cr;
+ uint32_t res1[4];
+ uint32_t lpat1cr;
+ uint32_t lpat2cr;
+ uint32_t lpat3cr;
+ uint32_t lpat4cr;
+ uint32_t lpat5cr;
+ uint32_t res2[3];
+ uint32_t lpatctlr;
+ uint32_t lpatclkr;
+ uint32_t lpatrc1r;
+ uint32_t lpatrc2r;
+ uint32_t res3[706];
+ uint32_t hpvidr1;
+ uint32_t hpvidr2;
+} __packed;
+
+/* Define the HPCOMR bits */
+#define HPCOMR_NPSWA_EN BIT(31)
+#define HPCOMR_HAC_STOP BIT(19)
+#define HPCOMR_HAC_CLEAR BIT(18)
+#define HPCOMR_HAC_LOAD BIT(17)
+#define HPCOMR_HAC_EN BIT(16)
+#define HPCOMR_MKS_EN BIT(13)
+#define HPCOMR_PROG_ZMK BIT(12)
+#define HPCOMR_SW_LPSV BIT(10)
+#define HPCOMR_SW_FSV BIT(9)
+#define HPCOMR_SW_SV BIT(8)
+#define HPCOMR_LP_SWR_DIS BIT(5)
+#define HPCOMR_LP_SWR BIT(4)
+#define HPCOMR_SSM_SFNS_DIS BIT(2)
+#define HPCOMR_SSM_ST_DIS BIT(1)
+#define HPCOMR_SSM_ST BIT(0)
+
+void imx_snvs_init(void);
+
+#endif /* IMX_SNVS_H */
diff --git a/plat/imx/common/include/imx_uart.h b/plat/imx/common/include/imx_uart.h
new file mode 100644
index 0000000..6c4d62f
--- /dev/null
+++ b/plat/imx/common/include/imx_uart.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_UART_H
+#define IMX_UART_H
+
+#include <drivers/console.h>
+
+#ifndef __ASSEMBLER__
+
+int console_imx_uart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+ console_t *console);
+#endif /*__ASSEMBLER__*/
+
+#endif /* IMX_UART_H */
diff --git a/plat/imx/common/include/imx_wdog.h b/plat/imx/common/include/imx_wdog.h
new file mode 100644
index 0000000..75a729a
--- /dev/null
+++ b/plat/imx/common/include/imx_wdog.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_WDOG_H
+#define IMX_WDOG_H
+
+#include <stdint.h>
+
+#include <arch.h>
+
+struct wdog_regs {
+ uint16_t wcr;
+ uint16_t wsr;
+ uint16_t wrsr;
+ uint16_t wicr;
+ uint16_t wmcr;
+};
+
+/* WCR bits */
+#define WCR_WDZST BIT(0)
+#define WCR_WDBG BIT(1)
+#define WCR_WDE BIT(2)
+#define WCR_WDT BIT(3)
+#define WCR_SRS BIT(4)
+#define WCR_WDA BIT(5)
+#define WCR_SRE BIT(6)
+#define WCR_WDW BIT(7)
+#define WCR_WT(x) ((x) << 8)
+
+/* WSR bits */
+#define WSR_FIRST 0x5555
+#define WSR_SECOND 0xAAAA
+
+/* WRSR bits */
+#define WRSR_SFTW BIT(0)
+#define WRSR_TOUT BIT(1)
+#define WRSR_POR BIT(4)
+
+/* WICR bits */
+static inline int wicr_calc_wict(int sec, int half_sec)
+{
+ int wict_bits;
+
+ /* Represents WICR bits 7 - 0 */
+ wict_bits = ((sec << 1) | (half_sec ? 1 : 0));
+
+ return wict_bits;
+}
+
+#define WICR_WTIS BIT(14)
+#define WICR_WIE BIT(15)
+
+/* WMCR bits */
+#define WMCR_PDE BIT(0)
+
+/* External facing API */
+void imx_wdog_init(void);
+
+#endif /* IMX_WDOG_H */
diff --git a/plat/imx/common/include/plat_imx8.h b/plat/imx/common/include/plat_imx8.h
new file mode 100644
index 0000000..be99b97
--- /dev/null
+++ b/plat/imx/common/include/plat_imx8.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_IMX8_H
+#define PLAT_IMX8_H
+
+#include <drivers/arm/gicv3.h>
+#include <lib/psci/psci.h>
+
+struct plat_gic_ctx {
+ gicv3_redist_ctx_t rdist_ctx[PLATFORM_CORE_COUNT];
+ gicv3_dist_ctx_t dist_ctx;
+};
+
+unsigned int plat_calc_core_pos(uint64_t mpidr);
+void imx_mailbox_init(uintptr_t base_addr);
+void plat_gic_driver_init(void);
+void plat_gic_init(void);
+void plat_gic_cpuif_enable(void);
+void plat_gic_cpuif_disable(void);
+void plat_gic_pcpu_init(void);
+
+void __dead2 imx_system_off(void);
+void __dead2 imx_system_reset(void);
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state);
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state);
+bool imx_is_wakeup_src_irqsteer(void);
+void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx);
+void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx);
+
+#endif /* PLAT_IMX8_H */
diff --git a/plat/imx/common/include/plat_macros.S b/plat/imx/common/include/plat_macros.S
new file mode 100644
index 0000000..30cce0a
--- /dev/null
+++ b/plat/imx/common/include/plat_macros.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * the below macros print out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL3-1
+ */
+.macro plat_print_gic_regs
+ /* TODO */
+.endm
+
+/*
+ * the below macros print out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1
+ */
+.macro plat_print_interconnect_regs
+ /* TODO */
+.endm
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+ /* TODO */
+.endm
diff --git a/plat/imx/common/include/sci/sci.h b/plat/imx/common/include/sci/sci.h
new file mode 100644
index 0000000..2c45bb8
--- /dev/null
+++ b/plat/imx/common/include/sci/sci.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCI_H
+#define SCI_H
+
+/* Defines */
+
+/* Includes */
+
+#include <sci/sci_ipc.h>
+#include <sci/svc/pad/sci_pad_api.h>
+#include <sci/svc/pm/sci_pm_api.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/svc/timer/sci_timer_api.h>
+#include <sci/svc/misc/sci_misc_api.h>
+
+#endif /* SCI_H */
diff --git a/plat/imx/common/include/sci/sci_ipc.h b/plat/imx/common/include/sci/sci_ipc.h
new file mode 100644
index 0000000..39e9012
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_ipc.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the IPC implementation.
+ */
+
+#ifndef SCI_IPC_H
+#define SCI_IPC_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+
+/* Defines */
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function opens an IPC channel.
+ *
+ * @param[out] ipc return pointer for ipc handle
+ * @param[in] id id of channel to open
+ *
+ * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_IPC
+ * otherwise).
+ *
+ * The \a id parameter is implementation specific. Could be an MU
+ * address, pointer to a driver path, channel index, etc.
+ */
+sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id);
+
+/*!
+ * This function closes an IPC channel.
+ *
+ * @param[in] ipc id of channel to close
+ */
+void sc_ipc_close(sc_ipc_t ipc);
+
+/*!
+ * This function reads a message from an IPC channel.
+ *
+ * @param[in] ipc id of channel read from
+ * @param[out] data pointer to message buffer to read
+ *
+ * This function will block if no message is available to be read.
+ */
+void sc_ipc_read(sc_ipc_t ipc, void *data);
+
+/*!
+ * This function writes a message to an IPC channel.
+ *
+ * @param[in] ipc id of channel to write to
+ * @param[in] data pointer to message buffer to write
+ *
+ * This function will block if the outgoing buffer is full.
+ */
+void sc_ipc_write(sc_ipc_t ipc, void *data);
+
+extern sc_ipc_t ipc_handle;
+
+#endif /* SCI_IPC_H */
diff --git a/plat/imx/common/include/sci/sci_rpc.h b/plat/imx/common/include/sci/sci_rpc.h
new file mode 100644
index 0000000..60dbc27
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_rpc.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the RPC implementation.
+ */
+
+#ifndef SCI_RPC_H
+#define SCI_RPC_H
+
+/* Includes */
+
+#include <stdbool.h>
+
+#include <sci/sci_types.h>
+#include <sci/sci_ipc.h>
+
+/* Defines */
+
+#define SC_RPC_VERSION 1U
+
+#define SC_RPC_MAX_MSG 8U
+
+#define RPC_VER(MSG) ((MSG)->version)
+#define RPC_SIZE(MSG) ((MSG)->size)
+#define RPC_SVC(MSG) ((MSG)->svc)
+#define RPC_FUNC(MSG) ((MSG)->func)
+#define RPC_R8(MSG) ((MSG)->func)
+#define RPC_I32(MSG, IDX) ((MSG)->DATA.i32[(IDX) / 4U])
+#define RPC_I16(MSG, IDX) ((MSG)->DATA.i16[(IDX) / 2U])
+#define RPC_I8(MSG, IDX) ((MSG)->DATA.i8[(IDX)])
+#define RPC_U32(MSG, IDX) ((MSG)->DATA.u32[(IDX) / 4U])
+#define RPC_U16(MSG, IDX) ((MSG)->DATA.u16[(IDX) / 2U])
+#define RPC_U8(MSG, IDX) ((MSG)->DATA.u8[(IDX)])
+
+#define SC_RPC_SVC_UNKNOWN 0U
+#define SC_RPC_SVC_RETURN 1U
+#define SC_RPC_SVC_PM 2U
+#define SC_RPC_SVC_RM 3U
+#define SC_RPC_SVC_TIMER 5U
+#define SC_RPC_SVC_PAD 6U
+#define SC_RPC_SVC_MISC 7U
+#define SC_RPC_SVC_IRQ 8U
+#define SC_RPC_SVC_ABORT 9U
+
+#define SC_RPC_ASYNC_STATE_RD_START 0U
+#define SC_RPC_ASYNC_STATE_RD_ACTIVE 1U
+#define SC_RPC_ASYNC_STATE_RD_DONE 2U
+#define SC_RPC_ASYNC_STATE_WR_START 3U
+#define SC_RPC_ASYNC_STATE_WR_ACTIVE 4U
+#define SC_RPC_ASYNC_STATE_WR_DONE 5U
+
+#define SC_RPC_MU_GIR_SVC 0x1U
+#define SC_RPC_MU_GIR_DBG 0x8U
+
+/* Types */
+
+typedef uint8_t sc_rpc_svc_t;
+
+typedef struct sc_rpc_msg_s {
+ uint8_t version;
+ uint8_t size;
+ uint8_t svc;
+ uint8_t func;
+ union {
+ int32_t i32[(SC_RPC_MAX_MSG - 1U)];
+ int16_t i16[(SC_RPC_MAX_MSG - 1U) * 2U];
+ int8_t i8[(SC_RPC_MAX_MSG - 1U) * 4U];
+ uint32_t u32[(SC_RPC_MAX_MSG - 1U)];
+ uint16_t u16[(SC_RPC_MAX_MSG - 1U) * 2U];
+ uint8_t u8[(SC_RPC_MAX_MSG - 1U) * 4U];
+ } DATA;
+} sc_rpc_msg_t;
+
+typedef uint8_t sc_rpc_async_state_t;
+
+typedef struct sc_rpc_async_msg_s {
+ sc_rpc_async_state_t state;
+ uint8_t wordIdx;
+ sc_rpc_msg_t msg;
+ uint32_t timeStamp;
+} sc_rpc_async_msg_t;
+
+/* Functions */
+
+/*!
+ * This is an internal function to send an RPC message over an IPC
+ * channel. It is called by client-side SCFW API function shims.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in,out] msg handle to a message
+ * @param[in] no_resp response flag
+ *
+ * If \a no_resp is SC_FALSE then this function waits for a response
+ * and returns the result in \a msg.
+ */
+void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp);
+
+/*!
+ * This is an internal function to dispath an RPC call that has
+ * arrived via IPC over an MU. It is called by server-side SCFW.
+ *
+ * @param[in] mu MU message arrived on
+ * @param[in,out] msg handle to a message
+ *
+ * The function result is returned in \a msg.
+ */
+void sc_rpc_dispatch(sc_rsrc_t mu, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates an RPC message and forwards on to the
+ * normal RPC API. It is used only by hypervisors.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in,out] msg handle to a message
+ *
+ * This function decodes a message, calls macros to translate the
+ * resources, pads, addresses, partitions, memory regions, etc. and
+ * then forwards on to the hypervisors SCFW API.Return results are
+ * translated back abd placed back into the message to be returned
+ * to the original API.
+ */
+void sc_rpc_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif /* SCI_RPC_H */
diff --git a/plat/imx/common/include/sci/sci_scfw.h b/plat/imx/common/include/sci/sci_scfw.h
new file mode 100644
index 0000000..a169f88
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_scfw.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCI_SCFW_H
+#define SCI_SCFW_H
+
+/* Includes */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/*!
+ * This type is used to declare a handle for an IPC communication
+ * channel. Its meaning is specific to the IPC implementation.
+ */
+typedef uint64_t sc_ipc_t;
+
+/*!
+ * This type is used to declare an ID for an IPC communication
+ * channel. For the reference IPC implementation, this ID
+ * selects the base address of the MU used for IPC.
+ */
+typedef uint64_t sc_ipc_id_t;
+
+
+#endif /* SCI_SCFW_H */
diff --git a/plat/imx/common/include/sci/sci_types.h b/plat/imx/common/include/sci/sci_types.h
new file mode 100644
index 0000000..6ade01c
--- /dev/null
+++ b/plat/imx/common/include/sci/sci_types.h
@@ -0,0 +1,849 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing types used across multiple service APIs.
+ */
+
+#ifndef SCI_TYPES_H
+#define SCI_TYPES_H
+
+/* Includes */
+
+#include <sci/sci_scfw.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for common frequencies
+ */
+/*@{*/
+#define SC_32KHZ 32768U /* 32KHz */
+#define SC_10MHZ 10000000U /* 10MHz */
+#define SC_20MHZ 20000000U /* 20MHz */
+#define SC_25MHZ 25000000U /* 25MHz */
+#define SC_27MHZ 27000000U /* 27MHz */
+#define SC_40MHZ 40000000U /* 40MHz */
+#define SC_45MHZ 45000000U /* 45MHz */
+#define SC_50MHZ 50000000U /* 50MHz */
+#define SC_60MHZ 60000000U /* 60MHz */
+#define SC_66MHZ 66666666U /* 66MHz */
+#define SC_74MHZ 74250000U /* 74.25MHz */
+#define SC_80MHZ 80000000U /* 80MHz */
+#define SC_83MHZ 83333333U /* 83MHz */
+#define SC_84MHZ 84375000U /* 84.37MHz */
+#define SC_100MHZ 100000000U /* 100MHz */
+#define SC_125MHZ 125000000U /* 125MHz */
+#define SC_133MHZ 133333333U /* 133MHz */
+#define SC_135MHZ 135000000U /* 135MHz */
+#define SC_150MHZ 150000000U /* 150MHz */
+#define SC_160MHZ 160000000U /* 160MHz */
+#define SC_166MHZ 166666666U /* 166MHz */
+#define SC_175MHZ 175000000U /* 175MHz */
+#define SC_180MHZ 180000000U /* 180MHz */
+#define SC_200MHZ 200000000U /* 200MHz */
+#define SC_250MHZ 250000000U /* 250MHz */
+#define SC_266MHZ 266666666U /* 266MHz */
+#define SC_300MHZ 300000000U /* 300MHz */
+#define SC_312MHZ 312500000U /* 312.5MHZ */
+#define SC_320MHZ 320000000U /* 320MHz */
+#define SC_325MHZ 325000000U /* 325MHz */
+#define SC_333MHZ 333333333U /* 333MHz */
+#define SC_350MHZ 350000000U /* 350MHz */
+#define SC_372MHZ 372000000U /* 372MHz */
+#define SC_375MHZ 375000000U /* 375MHz */
+#define SC_400MHZ 400000000U /* 400MHz */
+#define SC_500MHZ 500000000U /* 500MHz */
+#define SC_594MHZ 594000000U /* 594MHz */
+#define SC_625MHZ 625000000U /* 625MHz */
+#define SC_640MHZ 640000000U /* 640MHz */
+#define SC_650MHZ 650000000U /* 650MHz */
+#define SC_667MHZ 666666667U /* 667MHz */
+#define SC_675MHZ 675000000U /* 675MHz */
+#define SC_700MHZ 700000000U /* 700MHz */
+#define SC_720MHZ 720000000U /* 720MHz */
+#define SC_750MHZ 750000000U /* 750MHz */
+#define SC_800MHZ 800000000U /* 800MHz */
+#define SC_850MHZ 850000000U /* 850MHz */
+#define SC_900MHZ 900000000U /* 900MHz */
+#define SC_1000MHZ 1000000000U /* 1GHz */
+#define SC_1056MHZ 1056000000U /* 1.056GHz */
+#define SC_1188MHZ 1188000000U /* 1.188GHz */
+#define SC_1260MHZ 1260000000U /* 1.26GHz */
+#define SC_1280MHZ 1280000000U /* 1.28GHz */
+#define SC_1300MHZ 1300000000U /* 1.3GHz */
+#define SC_1400MHZ 1400000000U /* 1.4GHz */
+#define SC_1500MHZ 1500000000U /* 1.5GHz */
+#define SC_1600MHZ 1600000000U /* 1.6GHz */
+#define SC_1800MHZ 1800000000U /* 1.8GHz */
+#define SC_2000MHZ 2000000000U /* 2.0GHz */
+#define SC_2112MHZ 2112000000U /* 2.12GHz */
+/*@}*/
+
+/*!
+ * @name Defines for 24M related frequencies
+ */
+/*@{*/
+#define SC_8MHZ 8000000U /* 8MHz */
+#define SC_12MHZ 12000000U /* 12MHz */
+#define SC_19MHZ 19800000U /* 19.8MHz */
+#define SC_24MHZ 24000000U /* 24MHz */
+#define SC_48MHZ 48000000U /* 48MHz */
+#define SC_120MHZ 120000000U /* 120MHz */
+#define SC_132MHZ 132000000U /* 132MHz */
+#define SC_144MHZ 144000000U /* 144MHz */
+#define SC_192MHZ 192000000U /* 192MHz */
+#define SC_211MHZ 211200000U /* 211.2MHz */
+#define SC_240MHZ 240000000U /* 240MHz */
+#define SC_264MHZ 264000000U /* 264MHz */
+#define SC_352MHZ 352000000U /* 352MHz */
+#define SC_360MHZ 360000000U /* 360MHz */
+#define SC_384MHZ 384000000U /* 384MHz */
+#define SC_396MHZ 396000000U /* 396MHz */
+#define SC_432MHZ 432000000U /* 432MHz */
+#define SC_480MHZ 480000000U /* 480MHz */
+#define SC_600MHZ 600000000U /* 600MHz */
+#define SC_744MHZ 744000000U /* 744MHz */
+#define SC_792MHZ 792000000U /* 792MHz */
+#define SC_864MHZ 864000000U /* 864MHz */
+#define SC_960MHZ 960000000U /* 960MHz */
+#define SC_1056MHZ 1056000000U /* 1056MHz */
+#define SC_1200MHZ 1200000000U /* 1.2GHz */
+#define SC_1464MHZ 1464000000U /* 1.464GHz */
+#define SC_2400MHZ 2400000000U /* 2.4GHz */
+/*@}*/
+
+/*!
+ * @name Defines for A/V related frequencies
+ */
+/*@{*/
+#define SC_62MHZ 62937500U /* 62.9375MHz */
+#define SC_755MHZ 755250000U /* 755.25MHz */
+/*@}*/
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_FADDR_W 36U /* Width of sc_faddr_t */
+#define SC_BOOL_W 1U /* Width of sc_bool_t */
+#define SC_ERR_W 4U /* Width of sc_err_t */
+#define SC_RSRC_W 10U /* Width of sc_rsrc_t */
+#define SC_CTRL_W 6U /* Width of sc_ctrl_t */
+/*@}*/
+
+/*!
+ * @name Defines for sc_bool_t
+ */
+/*@{*/
+#define SC_FALSE ((sc_bool_t) 0U) /* True */
+#define SC_TRUE ((sc_bool_t) 1U) /* False */
+/*@}*/
+
+/*!
+ * @name Defines for sc_err_t.
+ */
+/*@{*/
+#define SC_ERR_NONE 0U /* Success */
+#define SC_ERR_VERSION 1U /* Incompatible API version */
+#define SC_ERR_CONFIG 2U /* Configuration error */
+#define SC_ERR_PARM 3U /* Bad parameter */
+#define SC_ERR_NOACCESS 4U /* Permission error (no access) */
+#define SC_ERR_LOCKED 5U /* Permission error (locked) */
+#define SC_ERR_UNAVAILABLE 6U /* Unavailable (out of resources) */
+#define SC_ERR_NOTFOUND 7U /* Not found */
+#define SC_ERR_NOPOWER 8U /* No power */
+#define SC_ERR_IPC 9U /* Generic IPC error */
+#define SC_ERR_BUSY 10U /* Resource is currently busy/active */
+#define SC_ERR_FAIL 11U /* General I/O failure */
+#define SC_ERR_LAST 12U
+/*@}*/
+
+/*!
+ * @name Defines for sc_rsrc_t.
+ */
+/*@{*/
+#define SC_R_A53 0U
+#define SC_R_A53_0 1U
+#define SC_R_A53_1 2U
+#define SC_R_A53_2 3U
+#define SC_R_A53_3 4U
+#define SC_R_A72 5U
+#define SC_R_A72_0 6U
+#define SC_R_A72_1 7U
+#define SC_R_A72_2 8U
+#define SC_R_A72_3 9U
+#define SC_R_CCI 10U
+#define SC_R_DB 11U
+#define SC_R_DRC_0 12U
+#define SC_R_DRC_1 13U
+#define SC_R_GIC_SMMU 14U
+#define SC_R_IRQSTR_M4_0 15U
+#define SC_R_IRQSTR_M4_1 16U
+#define SC_R_SMMU 17U
+#define SC_R_GIC 18U
+#define SC_R_DC_0_BLIT0 19U
+#define SC_R_DC_0_BLIT1 20U
+#define SC_R_DC_0_BLIT2 21U
+#define SC_R_DC_0_BLIT_OUT 22U
+#define SC_R_DC_0_CAPTURE0 23U
+#define SC_R_DC_0_CAPTURE1 24U
+#define SC_R_DC_0_WARP 25U
+#define SC_R_DC_0_INTEGRAL0 26U
+#define SC_R_DC_0_INTEGRAL1 27U
+#define SC_R_DC_0_VIDEO0 28U
+#define SC_R_DC_0_VIDEO1 29U
+#define SC_R_DC_0_FRAC0 30U
+#define SC_R_DC_0_FRAC1 31U
+#define SC_R_DC_0 32U
+#define SC_R_GPU_2_PID0 33U
+#define SC_R_DC_0_PLL_0 34U
+#define SC_R_DC_0_PLL_1 35U
+#define SC_R_DC_1_BLIT0 36U
+#define SC_R_DC_1_BLIT1 37U
+#define SC_R_DC_1_BLIT2 38U
+#define SC_R_DC_1_BLIT_OUT 39U
+#define SC_R_DC_1_CAPTURE0 40U
+#define SC_R_DC_1_CAPTURE1 41U
+#define SC_R_DC_1_WARP 42U
+#define SC_R_DC_1_INTEGRAL0 43U
+#define SC_R_DC_1_INTEGRAL1 44U
+#define SC_R_DC_1_VIDEO0 45U
+#define SC_R_DC_1_VIDEO1 46U
+#define SC_R_DC_1_FRAC0 47U
+#define SC_R_DC_1_FRAC1 48U
+#define SC_R_DC_1 49U
+#define SC_R_GPU_3_PID0 50U
+#define SC_R_DC_1_PLL_0 51U
+#define SC_R_DC_1_PLL_1 52U
+#define SC_R_SPI_0 53U
+#define SC_R_SPI_1 54U
+#define SC_R_SPI_2 55U
+#define SC_R_SPI_3 56U
+#define SC_R_UART_0 57U
+#define SC_R_UART_1 58U
+#define SC_R_UART_2 59U
+#define SC_R_UART_3 60U
+#define SC_R_UART_4 61U
+#define SC_R_EMVSIM_0 62U
+#define SC_R_EMVSIM_1 63U
+#define SC_R_DMA_0_CH0 64U
+#define SC_R_DMA_0_CH1 65U
+#define SC_R_DMA_0_CH2 66U
+#define SC_R_DMA_0_CH3 67U
+#define SC_R_DMA_0_CH4 68U
+#define SC_R_DMA_0_CH5 69U
+#define SC_R_DMA_0_CH6 70U
+#define SC_R_DMA_0_CH7 71U
+#define SC_R_DMA_0_CH8 72U
+#define SC_R_DMA_0_CH9 73U
+#define SC_R_DMA_0_CH10 74U
+#define SC_R_DMA_0_CH11 75U
+#define SC_R_DMA_0_CH12 76U
+#define SC_R_DMA_0_CH13 77U
+#define SC_R_DMA_0_CH14 78U
+#define SC_R_DMA_0_CH15 79U
+#define SC_R_DMA_0_CH16 80U
+#define SC_R_DMA_0_CH17 81U
+#define SC_R_DMA_0_CH18 82U
+#define SC_R_DMA_0_CH19 83U
+#define SC_R_DMA_0_CH20 84U
+#define SC_R_DMA_0_CH21 85U
+#define SC_R_DMA_0_CH22 86U
+#define SC_R_DMA_0_CH23 87U
+#define SC_R_DMA_0_CH24 88U
+#define SC_R_DMA_0_CH25 89U
+#define SC_R_DMA_0_CH26 90U
+#define SC_R_DMA_0_CH27 91U
+#define SC_R_DMA_0_CH28 92U
+#define SC_R_DMA_0_CH29 93U
+#define SC_R_DMA_0_CH30 94U
+#define SC_R_DMA_0_CH31 95U
+#define SC_R_I2C_0 96U
+#define SC_R_I2C_1 97U
+#define SC_R_I2C_2 98U
+#define SC_R_I2C_3 99U
+#define SC_R_I2C_4 100U
+#define SC_R_ADC_0 101U
+#define SC_R_ADC_1 102U
+#define SC_R_FTM_0 103U
+#define SC_R_FTM_1 104U
+#define SC_R_CAN_0 105U
+#define SC_R_CAN_1 106U
+#define SC_R_CAN_2 107U
+#define SC_R_DMA_1_CH0 108U
+#define SC_R_DMA_1_CH1 109U
+#define SC_R_DMA_1_CH2 110U
+#define SC_R_DMA_1_CH3 111U
+#define SC_R_DMA_1_CH4 112U
+#define SC_R_DMA_1_CH5 113U
+#define SC_R_DMA_1_CH6 114U
+#define SC_R_DMA_1_CH7 115U
+#define SC_R_DMA_1_CH8 116U
+#define SC_R_DMA_1_CH9 117U
+#define SC_R_DMA_1_CH10 118U
+#define SC_R_DMA_1_CH11 119U
+#define SC_R_DMA_1_CH12 120U
+#define SC_R_DMA_1_CH13 121U
+#define SC_R_DMA_1_CH14 122U
+#define SC_R_DMA_1_CH15 123U
+#define SC_R_DMA_1_CH16 124U
+#define SC_R_DMA_1_CH17 125U
+#define SC_R_DMA_1_CH18 126U
+#define SC_R_DMA_1_CH19 127U
+#define SC_R_DMA_1_CH20 128U
+#define SC_R_DMA_1_CH21 129U
+#define SC_R_DMA_1_CH22 130U
+#define SC_R_DMA_1_CH23 131U
+#define SC_R_DMA_1_CH24 132U
+#define SC_R_DMA_1_CH25 133U
+#define SC_R_DMA_1_CH26 134U
+#define SC_R_DMA_1_CH27 135U
+#define SC_R_DMA_1_CH28 136U
+#define SC_R_DMA_1_CH29 137U
+#define SC_R_DMA_1_CH30 138U
+#define SC_R_DMA_1_CH31 139U
+#define SC_R_UNUSED1 140U
+#define SC_R_UNUSED2 141U
+#define SC_R_UNUSED3 142U
+#define SC_R_UNUSED4 143U
+#define SC_R_GPU_0_PID0 144U
+#define SC_R_GPU_0_PID1 145U
+#define SC_R_GPU_0_PID2 146U
+#define SC_R_GPU_0_PID3 147U
+#define SC_R_GPU_1_PID0 148U
+#define SC_R_GPU_1_PID1 149U
+#define SC_R_GPU_1_PID2 150U
+#define SC_R_GPU_1_PID3 151U
+#define SC_R_PCIE_A 152U
+#define SC_R_SERDES_0 153U
+#define SC_R_MATCH_0 154U
+#define SC_R_MATCH_1 155U
+#define SC_R_MATCH_2 156U
+#define SC_R_MATCH_3 157U
+#define SC_R_MATCH_4 158U
+#define SC_R_MATCH_5 159U
+#define SC_R_MATCH_6 160U
+#define SC_R_MATCH_7 161U
+#define SC_R_MATCH_8 162U
+#define SC_R_MATCH_9 163U
+#define SC_R_MATCH_10 164U
+#define SC_R_MATCH_11 165U
+#define SC_R_MATCH_12 166U
+#define SC_R_MATCH_13 167U
+#define SC_R_MATCH_14 168U
+#define SC_R_PCIE_B 169U
+#define SC_R_SATA_0 170U
+#define SC_R_SERDES_1 171U
+#define SC_R_HSIO_GPIO 172U
+#define SC_R_MATCH_15 173U
+#define SC_R_MATCH_16 174U
+#define SC_R_MATCH_17 175U
+#define SC_R_MATCH_18 176U
+#define SC_R_MATCH_19 177U
+#define SC_R_MATCH_20 178U
+#define SC_R_MATCH_21 179U
+#define SC_R_MATCH_22 180U
+#define SC_R_MATCH_23 181U
+#define SC_R_MATCH_24 182U
+#define SC_R_MATCH_25 183U
+#define SC_R_MATCH_26 184U
+#define SC_R_MATCH_27 185U
+#define SC_R_MATCH_28 186U
+#define SC_R_LCD_0 187U
+#define SC_R_LCD_0_PWM_0 188U
+#define SC_R_LCD_0_I2C_0 189U
+#define SC_R_LCD_0_I2C_1 190U
+#define SC_R_PWM_0 191U
+#define SC_R_PWM_1 192U
+#define SC_R_PWM_2 193U
+#define SC_R_PWM_3 194U
+#define SC_R_PWM_4 195U
+#define SC_R_PWM_5 196U
+#define SC_R_PWM_6 197U
+#define SC_R_PWM_7 198U
+#define SC_R_GPIO_0 199U
+#define SC_R_GPIO_1 200U
+#define SC_R_GPIO_2 201U
+#define SC_R_GPIO_3 202U
+#define SC_R_GPIO_4 203U
+#define SC_R_GPIO_5 204U
+#define SC_R_GPIO_6 205U
+#define SC_R_GPIO_7 206U
+#define SC_R_GPT_0 207U
+#define SC_R_GPT_1 208U
+#define SC_R_GPT_2 209U
+#define SC_R_GPT_3 210U
+#define SC_R_GPT_4 211U
+#define SC_R_KPP 212U
+#define SC_R_MU_0A 213U
+#define SC_R_MU_1A 214U
+#define SC_R_MU_2A 215U
+#define SC_R_MU_3A 216U
+#define SC_R_MU_4A 217U
+#define SC_R_MU_5A 218U
+#define SC_R_MU_6A 219U
+#define SC_R_MU_7A 220U
+#define SC_R_MU_8A 221U
+#define SC_R_MU_9A 222U
+#define SC_R_MU_10A 223U
+#define SC_R_MU_11A 224U
+#define SC_R_MU_12A 225U
+#define SC_R_MU_13A 226U
+#define SC_R_MU_5B 227U
+#define SC_R_MU_6B 228U
+#define SC_R_MU_7B 229U
+#define SC_R_MU_8B 230U
+#define SC_R_MU_9B 231U
+#define SC_R_MU_10B 232U
+#define SC_R_MU_11B 233U
+#define SC_R_MU_12B 234U
+#define SC_R_MU_13B 235U
+#define SC_R_ROM_0 236U
+#define SC_R_FSPI_0 237U
+#define SC_R_FSPI_1 238U
+#define SC_R_IEE 239U
+#define SC_R_IEE_R0 240U
+#define SC_R_IEE_R1 241U
+#define SC_R_IEE_R2 242U
+#define SC_R_IEE_R3 243U
+#define SC_R_IEE_R4 244U
+#define SC_R_IEE_R5 245U
+#define SC_R_IEE_R6 246U
+#define SC_R_IEE_R7 247U
+#define SC_R_SDHC_0 248U
+#define SC_R_SDHC_1 249U
+#define SC_R_SDHC_2 250U
+#define SC_R_ENET_0 251U
+#define SC_R_ENET_1 252U
+#define SC_R_MLB_0 253U
+#define SC_R_DMA_2_CH0 254U
+#define SC_R_DMA_2_CH1 255U
+#define SC_R_DMA_2_CH2 256U
+#define SC_R_DMA_2_CH3 257U
+#define SC_R_DMA_2_CH4 258U
+#define SC_R_USB_0 259U
+#define SC_R_USB_1 260U
+#define SC_R_USB_0_PHY 261U
+#define SC_R_USB_2 262U
+#define SC_R_USB_2_PHY 263U
+#define SC_R_DTCP 264U
+#define SC_R_NAND 265U
+#define SC_R_LVDS_0 266U
+#define SC_R_LVDS_0_PWM_0 267U
+#define SC_R_LVDS_0_I2C_0 268U
+#define SC_R_LVDS_0_I2C_1 269U
+#define SC_R_LVDS_1 270U
+#define SC_R_LVDS_1_PWM_0 271U
+#define SC_R_LVDS_1_I2C_0 272U
+#define SC_R_LVDS_1_I2C_1 273U
+#define SC_R_LVDS_2 274U
+#define SC_R_LVDS_2_PWM_0 275U
+#define SC_R_LVDS_2_I2C_0 276U
+#define SC_R_LVDS_2_I2C_1 277U
+#define SC_R_M4_0_PID0 278U
+#define SC_R_M4_0_PID1 279U
+#define SC_R_M4_0_PID2 280U
+#define SC_R_M4_0_PID3 281U
+#define SC_R_M4_0_PID4 282U
+#define SC_R_M4_0_RGPIO 283U
+#define SC_R_M4_0_SEMA42 284U
+#define SC_R_M4_0_TPM 285U
+#define SC_R_M4_0_PIT 286U
+#define SC_R_M4_0_UART 287U
+#define SC_R_M4_0_I2C 288U
+#define SC_R_M4_0_INTMUX 289U
+#define SC_R_M4_0_SIM 290U
+#define SC_R_M4_0_WDOG 291U
+#define SC_R_M4_0_MU_0B 292U
+#define SC_R_M4_0_MU_0A0 293U
+#define SC_R_M4_0_MU_0A1 294U
+#define SC_R_M4_0_MU_0A2 295U
+#define SC_R_M4_0_MU_0A3 296U
+#define SC_R_M4_0_MU_1A 297U
+#define SC_R_M4_1_PID0 298U
+#define SC_R_M4_1_PID1 299U
+#define SC_R_M4_1_PID2 300U
+#define SC_R_M4_1_PID3 301U
+#define SC_R_M4_1_PID4 302U
+#define SC_R_M4_1_RGPIO 303U
+#define SC_R_M4_1_SEMA42 304U
+#define SC_R_M4_1_TPM 305U
+#define SC_R_M4_1_PIT 306U
+#define SC_R_M4_1_UART 307U
+#define SC_R_M4_1_I2C 308U
+#define SC_R_M4_1_INTMUX 309U
+#define SC_R_M4_1_SIM 310U
+#define SC_R_M4_1_WDOG 311U
+#define SC_R_M4_1_MU_0B 312U
+#define SC_R_M4_1_MU_0A0 313U
+#define SC_R_M4_1_MU_0A1 314U
+#define SC_R_M4_1_MU_0A2 315U
+#define SC_R_M4_1_MU_0A3 316U
+#define SC_R_M4_1_MU_1A 317U
+#define SC_R_SAI_0 318U
+#define SC_R_SAI_1 319U
+#define SC_R_SAI_2 320U
+#define SC_R_IRQSTR_SCU2 321U
+#define SC_R_IRQSTR_DSP 322U
+#define SC_R_UNUSED5 323U
+#define SC_R_OCRAM 324U
+#define SC_R_AUDIO_PLL_0 325U
+#define SC_R_PI_0 326U
+#define SC_R_PI_0_PWM_0 327U
+#define SC_R_PI_0_PWM_1 328U
+#define SC_R_PI_0_I2C_0 329U
+#define SC_R_PI_0_PLL 330U
+#define SC_R_PI_1 331U
+#define SC_R_PI_1_PWM_0 332U
+#define SC_R_PI_1_PWM_1 333U
+#define SC_R_PI_1_I2C_0 334U
+#define SC_R_PI_1_PLL 335U
+#define SC_R_SC_PID0 336U
+#define SC_R_SC_PID1 337U
+#define SC_R_SC_PID2 338U
+#define SC_R_SC_PID3 339U
+#define SC_R_SC_PID4 340U
+#define SC_R_SC_SEMA42 341U
+#define SC_R_SC_TPM 342U
+#define SC_R_SC_PIT 343U
+#define SC_R_SC_UART 344U
+#define SC_R_SC_I2C 345U
+#define SC_R_SC_MU_0B 346U
+#define SC_R_SC_MU_0A0 347U
+#define SC_R_SC_MU_0A1 348U
+#define SC_R_SC_MU_0A2 349U
+#define SC_R_SC_MU_0A3 350U
+#define SC_R_SC_MU_1A 351U
+#define SC_R_SYSCNT_RD 352U
+#define SC_R_SYSCNT_CMP 353U
+#define SC_R_DEBUG 354U
+#define SC_R_SYSTEM 355U
+#define SC_R_SNVS 356U
+#define SC_R_OTP 357U
+#define SC_R_VPU_PID0 358U
+#define SC_R_VPU_PID1 359U
+#define SC_R_VPU_PID2 360U
+#define SC_R_VPU_PID3 361U
+#define SC_R_VPU_PID4 362U
+#define SC_R_VPU_PID5 363U
+#define SC_R_VPU_PID6 364U
+#define SC_R_VPU_PID7 365U
+#define SC_R_VPU_UART 366U
+#define SC_R_VPUCORE 367U
+#define SC_R_VPUCORE_0 368U
+#define SC_R_VPUCORE_1 369U
+#define SC_R_VPUCORE_2 370U
+#define SC_R_VPUCORE_3 371U
+#define SC_R_DMA_4_CH0 372U
+#define SC_R_DMA_4_CH1 373U
+#define SC_R_DMA_4_CH2 374U
+#define SC_R_DMA_4_CH3 375U
+#define SC_R_DMA_4_CH4 376U
+#define SC_R_ISI_CH0 377U
+#define SC_R_ISI_CH1 378U
+#define SC_R_ISI_CH2 379U
+#define SC_R_ISI_CH3 380U
+#define SC_R_ISI_CH4 381U
+#define SC_R_ISI_CH5 382U
+#define SC_R_ISI_CH6 383U
+#define SC_R_ISI_CH7 384U
+#define SC_R_MJPEG_DEC_S0 385U
+#define SC_R_MJPEG_DEC_S1 386U
+#define SC_R_MJPEG_DEC_S2 387U
+#define SC_R_MJPEG_DEC_S3 388U
+#define SC_R_MJPEG_ENC_S0 389U
+#define SC_R_MJPEG_ENC_S1 390U
+#define SC_R_MJPEG_ENC_S2 391U
+#define SC_R_MJPEG_ENC_S3 392U
+#define SC_R_MIPI_0 393U
+#define SC_R_MIPI_0_PWM_0 394U
+#define SC_R_MIPI_0_I2C_0 395U
+#define SC_R_MIPI_0_I2C_1 396U
+#define SC_R_MIPI_1 397U
+#define SC_R_MIPI_1_PWM_0 398U
+#define SC_R_MIPI_1_I2C_0 399U
+#define SC_R_MIPI_1_I2C_1 400U
+#define SC_R_CSI_0 401U
+#define SC_R_CSI_0_PWM_0 402U
+#define SC_R_CSI_0_I2C_0 403U
+#define SC_R_CSI_1 404U
+#define SC_R_CSI_1_PWM_0 405U
+#define SC_R_CSI_1_I2C_0 406U
+#define SC_R_HDMI 407U
+#define SC_R_HDMI_I2S 408U
+#define SC_R_HDMI_I2C_0 409U
+#define SC_R_HDMI_PLL_0 410U
+#define SC_R_HDMI_RX 411U
+#define SC_R_HDMI_RX_BYPASS 412U
+#define SC_R_HDMI_RX_I2C_0 413U
+#define SC_R_ASRC_0 414U
+#define SC_R_ESAI_0 415U
+#define SC_R_SPDIF_0 416U
+#define SC_R_SPDIF_1 417U
+#define SC_R_SAI_3 418U
+#define SC_R_SAI_4 419U
+#define SC_R_SAI_5 420U
+#define SC_R_GPT_5 421U
+#define SC_R_GPT_6 422U
+#define SC_R_GPT_7 423U
+#define SC_R_GPT_8 424U
+#define SC_R_GPT_9 425U
+#define SC_R_GPT_10 426U
+#define SC_R_DMA_2_CH5 427U
+#define SC_R_DMA_2_CH6 428U
+#define SC_R_DMA_2_CH7 429U
+#define SC_R_DMA_2_CH8 430U
+#define SC_R_DMA_2_CH9 431U
+#define SC_R_DMA_2_CH10 432U
+#define SC_R_DMA_2_CH11 433U
+#define SC_R_DMA_2_CH12 434U
+#define SC_R_DMA_2_CH13 435U
+#define SC_R_DMA_2_CH14 436U
+#define SC_R_DMA_2_CH15 437U
+#define SC_R_DMA_2_CH16 438U
+#define SC_R_DMA_2_CH17 439U
+#define SC_R_DMA_2_CH18 440U
+#define SC_R_DMA_2_CH19 441U
+#define SC_R_DMA_2_CH20 442U
+#define SC_R_DMA_2_CH21 443U
+#define SC_R_DMA_2_CH22 444U
+#define SC_R_DMA_2_CH23 445U
+#define SC_R_DMA_2_CH24 446U
+#define SC_R_DMA_2_CH25 447U
+#define SC_R_DMA_2_CH26 448U
+#define SC_R_DMA_2_CH27 449U
+#define SC_R_DMA_2_CH28 450U
+#define SC_R_DMA_2_CH29 451U
+#define SC_R_DMA_2_CH30 452U
+#define SC_R_DMA_2_CH31 453U
+#define SC_R_ASRC_1 454U
+#define SC_R_ESAI_1 455U
+#define SC_R_SAI_6 456U
+#define SC_R_SAI_7 457U
+#define SC_R_AMIX 458U
+#define SC_R_MQS_0 459U
+#define SC_R_DMA_3_CH0 460U
+#define SC_R_DMA_3_CH1 461U
+#define SC_R_DMA_3_CH2 462U
+#define SC_R_DMA_3_CH3 463U
+#define SC_R_DMA_3_CH4 464U
+#define SC_R_DMA_3_CH5 465U
+#define SC_R_DMA_3_CH6 466U
+#define SC_R_DMA_3_CH7 467U
+#define SC_R_DMA_3_CH8 468U
+#define SC_R_DMA_3_CH9 469U
+#define SC_R_DMA_3_CH10 470U
+#define SC_R_DMA_3_CH11 471U
+#define SC_R_DMA_3_CH12 472U
+#define SC_R_DMA_3_CH13 473U
+#define SC_R_DMA_3_CH14 474U
+#define SC_R_DMA_3_CH15 475U
+#define SC_R_DMA_3_CH16 476U
+#define SC_R_DMA_3_CH17 477U
+#define SC_R_DMA_3_CH18 478U
+#define SC_R_DMA_3_CH19 479U
+#define SC_R_DMA_3_CH20 480U
+#define SC_R_DMA_3_CH21 481U
+#define SC_R_DMA_3_CH22 482U
+#define SC_R_DMA_3_CH23 483U
+#define SC_R_DMA_3_CH24 484U
+#define SC_R_DMA_3_CH25 485U
+#define SC_R_DMA_3_CH26 486U
+#define SC_R_DMA_3_CH27 487U
+#define SC_R_DMA_3_CH28 488U
+#define SC_R_DMA_3_CH29 489U
+#define SC_R_DMA_3_CH30 490U
+#define SC_R_DMA_3_CH31 491U
+#define SC_R_AUDIO_PLL_1 492U
+#define SC_R_AUDIO_CLK_0 493U
+#define SC_R_AUDIO_CLK_1 494U
+#define SC_R_MCLK_OUT_0 495U
+#define SC_R_MCLK_OUT_1 496U
+#define SC_R_PMIC_0 497U
+#define SC_R_PMIC_1 498U
+#define SC_R_SECO 499U
+#define SC_R_CAAM_JR1 500U
+#define SC_R_CAAM_JR2 501U
+#define SC_R_CAAM_JR3 502U
+#define SC_R_SECO_MU_2 503U
+#define SC_R_SECO_MU_3 504U
+#define SC_R_SECO_MU_4 505U
+#define SC_R_HDMI_RX_PWM_0 506U
+#define SC_R_A35 507U
+#define SC_R_A35_0 508U
+#define SC_R_A35_1 509U
+#define SC_R_A35_2 510U
+#define SC_R_A35_3 511U
+#define SC_R_DSP 512U
+#define SC_R_DSP_RAM 513U
+#define SC_R_CAAM_JR1_OUT 514U
+#define SC_R_CAAM_JR2_OUT 515U
+#define SC_R_CAAM_JR3_OUT 516U
+#define SC_R_VPU_DEC_0 517U
+#define SC_R_VPU_ENC_0 518U
+#define SC_R_CAAM_JR0 519U
+#define SC_R_CAAM_JR0_OUT 520U
+#define SC_R_PMIC_2 521U
+#define SC_R_DBLOGIC 522U
+#define SC_R_HDMI_PLL_1 523U
+#define SC_R_BOARD_R0 524U
+#define SC_R_BOARD_R1 525U
+#define SC_R_BOARD_R2 526U
+#define SC_R_BOARD_R3 527U
+#define SC_R_BOARD_R4 528U
+#define SC_R_BOARD_R5 529U
+#define SC_R_BOARD_R6 530U
+#define SC_R_BOARD_R7 531U
+#define SC_R_MJPEG_DEC_MP 532U
+#define SC_R_MJPEG_ENC_MP 533U
+#define SC_R_VPU_TS_0 534U
+#define SC_R_VPU_MU_0 535U
+#define SC_R_VPU_MU_1 536U
+#define SC_R_VPU_MU_2 537U
+#define SC_R_VPU_MU_3 538U
+#define SC_R_VPU_ENC_1 539U
+#define SC_R_VPU 540U
+#define SC_R_LAST 541U
+#define SC_R_ALL ((sc_rsrc_t) UINT16_MAX) /* All resources */
+/*@}*/
+
+/* NOTE - please add by replacing some of the UNUSED from above! */
+
+/*!
+ * Defnes for sc_ctrl_t.
+ */
+#define SC_C_TEMP 0U
+#define SC_C_TEMP_HI 1U
+#define SC_C_TEMP_LOW 2U
+#define SC_C_PXL_LINK_MST1_ADDR 3U
+#define SC_C_PXL_LINK_MST2_ADDR 4U
+#define SC_C_PXL_LINK_MST_ENB 5U
+#define SC_C_PXL_LINK_MST1_ENB 6U
+#define SC_C_PXL_LINK_MST2_ENB 7U
+#define SC_C_PXL_LINK_SLV1_ADDR 8U
+#define SC_C_PXL_LINK_SLV2_ADDR 9U
+#define SC_C_PXL_LINK_MST_VLD 10U
+#define SC_C_PXL_LINK_MST1_VLD 11U
+#define SC_C_PXL_LINK_MST2_VLD 12U
+#define SC_C_SINGLE_MODE 13U
+#define SC_C_ID 14U
+#define SC_C_PXL_CLK_POLARITY 15U
+#define SC_C_LINESTATE 16U
+#define SC_C_PCIE_G_RST 17U
+#define SC_C_PCIE_BUTTON_RST 18U
+#define SC_C_PCIE_PERST 19U
+#define SC_C_PHY_RESET 20U
+#define SC_C_PXL_LINK_RATE_CORRECTION 21U
+#define SC_C_PANIC 22U
+#define SC_C_PRIORITY_GROUP 23U
+#define SC_C_TXCLK 24U
+#define SC_C_CLKDIV 25U
+#define SC_C_DISABLE_50 26U
+#define SC_C_DISABLE_125 27U
+#define SC_C_SEL_125 28U
+#define SC_C_MODE 29U
+#define SC_C_SYNC_CTRL0 30U
+#define SC_C_KACHUNK_CNT 31U
+#define SC_C_KACHUNK_SEL 32U
+#define SC_C_SYNC_CTRL1 33U
+#define SC_C_DPI_RESET 34U
+#define SC_C_MIPI_RESET 35U
+#define SC_C_DUAL_MODE 36U
+#define SC_C_VOLTAGE 37U
+#define SC_C_PXL_LINK_SEL 38U
+#define SC_C_OFS_SEL 39U
+#define SC_C_OFS_AUDIO 40U
+#define SC_C_OFS_PERIPH 41U
+#define SC_C_OFS_IRQ 42U
+#define SC_C_RST0 43U
+#define SC_C_RST1 44U
+#define SC_C_SEL0 45U
+#define SC_C_LAST 46U
+
+#define SC_P_ALL ((sc_pad_t) UINT16_MAX) /* All pads */
+
+/* Types */
+
+/*!
+ * This type is used to store a boolean
+ */
+typedef uint8_t sc_bool_t;
+
+/*!
+ * This type is used to store a system (full-size) address.
+ */
+typedef uint64_t sc_faddr_t;
+
+/*!
+ * This type is used to indicate error response for most functions.
+ */
+typedef uint8_t sc_err_t;
+
+/*!
+ * This type is used to indicate a resource. Resources include peripherals
+ * and bus masters (but not memory regions). Note items from list should
+ * never be changed or removed (only added to at the end of the list).
+ */
+typedef uint16_t sc_rsrc_t;
+
+/*!
+ * This type is used to indicate a control.
+ */
+typedef uint8_t sc_ctrl_t;
+
+/*!
+ * This type is used to indicate a pad. Valid values are SoC specific.
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+typedef uint16_t sc_pad_t;
+
+/* Extra documentation of standard types */
+
+#ifdef DOXYGEN
+ /*!
+ * Type used to declare an 8-bit integer.
+ */
+typedef __INT8_TYPE__ int8_t;
+
+ /*!
+ * Type used to declare a 16-bit integer.
+ */
+typedef __INT16_TYPE__ int16_t;
+
+ /*!
+ * Type used to declare a 32-bit integer.
+ */
+typedef __INT32_TYPE__ int32_t;
+
+ /*!
+ * Type used to declare a 64-bit integer.
+ */
+typedef __INT64_TYPE__ int64_t;
+
+ /*!
+ * Type used to declare an 8-bit unsigned integer.
+ */
+typedef __UINT8_TYPE__ uint8_t;
+
+ /*!
+ * Type used to declare a 16-bit unsigned integer.
+ */
+typedef __UINT16_TYPE__ uint16_t;
+
+ /*!
+ * Type used to declare a 32-bit unsigned integer.
+ */
+typedef __UINT32_TYPE__ uint32_t;
+
+ /*!
+ * Type used to declare a 64-bit unsigned integer.
+ */
+typedef __UINT64_TYPE__ uint64_t;
+#endif
+
+#endif /* SCI_TYPES_H */
diff --git a/plat/imx/common/include/sci/svc/misc/sci_misc_api.h b/plat/imx/common/include/sci/svc/misc/sci_misc_api.h
new file mode 100644
index 0000000..d9dd49d
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/misc/sci_misc_api.h
@@ -0,0 +1,539 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Miscellaneous (MISC) function.
+ *
+ * @addtogroup MISC_SVC (SVC) Miscellaneous Service
+ *
+ * Module for the Miscellaneous (MISC) service.
+ *
+ * @{
+ */
+
+#ifndef SC_MISC_API_H
+#define SC_MISC_API_H
+
+/* Includes */
+
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/sci_types.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_MISC_DMA_GRP_W 5U /* Width of sc_misc_dma_group_t */
+/*@}*/
+
+/*! Max DMA channel priority group */
+#define SC_MISC_DMA_GRP_MAX 31U
+
+/*!
+ * @name Defines for sc_misc_boot_status_t
+ */
+/*@{*/
+#define SC_MISC_BOOT_STATUS_SUCCESS 0U /* Success */
+#define SC_MISC_BOOT_STATUS_SECURITY 1U /* Security violation */
+/*@}*/
+
+/*!
+ * @name Defines for sc_misc_seco_auth_cmd_t
+ */
+/*@{*/
+#define SC_MISC_SECO_AUTH_SECO_FW 0U /* SECO Firmware */
+#define SC_MISC_SECO_AUTH_HDMI_TX_FW 1U /* HDMI TX Firmware */
+#define SC_MISC_SECO_AUTH_HDMI_RX_FW 2U /* HDMI RX Firmware */
+/*@}*/
+
+/*!
+ * @name Defines for sc_misc_temp_t
+ */
+/*@{*/
+#define SC_MISC_TEMP 0U /* Temp sensor */
+#define SC_MISC_TEMP_HIGH 1U /* Temp high alarm */
+#define SC_MISC_TEMP_LOW 2U /* Temp low alarm */
+/*@}*/
+
+/*!
+ * @name Defines for sc_misc_seco_auth_cmd_t
+ */
+/*@{*/
+#define SC_MISC_AUTH_CONTAINER 0U /* Authenticate container */
+#define SC_MISC_VERIFY_IMAGE 1U /* Verify image */
+#define SC_MISC_REL_CONTAINER 2U /* Release container */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to store a DMA channel priority group.
+ */
+typedef uint8_t sc_misc_dma_group_t;
+
+/*!
+ * This type is used report boot status.
+ */
+typedef uint8_t sc_misc_boot_status_t;
+
+/*!
+ * This type is used to issue SECO authenticate commands.
+ */
+typedef uint8_t sc_misc_seco_auth_cmd_t;
+
+/*!
+ * This type is used report boot status.
+ */
+typedef uint8_t sc_misc_temp_t;
+
+/* Functions */
+
+/*!
+ * @name Control Functions
+ * @{
+ */
+
+/*!
+ * This function sets a miscellaneous control value.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource the control is associated with
+ * @param[in] ctrl control to change
+ * @param[in] val value to apply to the control
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ * of the owner
+ *
+ * Refer to the [Control List](@ref CONTROLS) for valid control values.
+ */
+sc_err_t sc_misc_set_control(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_ctrl_t ctrl, uint32_t val);
+
+/*!
+ * This function gets a miscellaneous control value.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource the control is associated with
+ * @param[in] ctrl control to get
+ * @param[out] val pointer to return the control value
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ * of the owner
+ *
+ * Refer to the [Control List](@ref CONTROLS) for valid control values.
+ */
+sc_err_t sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_ctrl_t ctrl, uint32_t *val);
+
+/* @} */
+
+/*!
+ * @name DMA Functions
+ * @{
+ */
+
+/*!
+ * This function configures the max DMA channel priority group for a
+ * partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to assign \a max
+ * @param[in] max max priority group (0-31)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent
+ * of the affected partition
+ *
+ * Valid \a max range is 0-31 with 0 being the lowest and 31 the highest.
+ * Default is the max priority group for the parent partition of \a pt.
+ */
+sc_err_t sc_misc_set_max_dma_group(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_misc_dma_group_t max);
+
+/*!
+ * This function configures the priority group for a DMA channel.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource DMA channel resource
+ * @param[in] group priority group (0-31)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the owner or parent
+ * of the owner of the DMA channel
+ *
+ * Valid \a group range is 0-31 with 0 being the lowest and 31 the highest.
+ * The max value of \a group is limited by the partition max set using
+ * sc_misc_set_max_dma_group().
+ */
+sc_err_t sc_misc_set_dma_group(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_misc_dma_group_t group);
+
+/* @} */
+
+/*!
+ * @name Security Functions
+ * @{
+ */
+
+/*!
+ * This function loads a SECO image.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] addr_src address of image source
+ * @param[in] addr_dst address of image destination
+ * @param[in] len length of image to load
+ * @param[in] fw SC_TRUE = firmware load
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_PARM if word fuse index param out of range or invalid
+ * - SC_ERR_UNAVAILABLE if SECO not available
+ *
+ * This is used to load images via the SECO. Examples include SECO
+ * Firmware and IVT/CSF data used for authentication. These are usually
+ * loaded into SECO TCM. \a addr_src is in secure memory.
+ *
+ * See the Security Reference Manual (SRM) for more info.
+ */
+sc_err_t sc_misc_seco_image_load(sc_ipc_t ipc, sc_faddr_t addr_src,
+ sc_faddr_t addr_dst, uint32_t len,
+ sc_bool_t fw);
+
+/*!
+ * This function is used to authenticate a SECO image or command.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] cmd authenticate command
+ * @param[in] addr address of/or metadata
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_PARM if word fuse index param out of range or invalid
+ * - SC_ERR_UNAVAILABLE if SECO not available
+ *
+ * This is used to authenticate a SECO image or issue a security
+ * command. \a addr often points to an container. It is also
+ * just data (or even unused) for some commands.
+ *
+ * See the Security Reference Manual (SRM) for more info.
+ */
+sc_err_t sc_misc_seco_authenticate(sc_ipc_t ipc,
+ sc_misc_seco_auth_cmd_t cmd,
+ sc_faddr_t addr);
+
+/*!
+ * This function securely writes a group of fuse words.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] addr address of message block
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_UNAVAILABLE if SECO not available
+ *
+ * Note \a addr must be a pointer to a signed message block.
+ *
+ * See the Security Reference Manual (SRM) for more info.
+ */
+sc_err_t sc_misc_seco_fuse_write(sc_ipc_t ipc, sc_faddr_t addr);
+
+/*!
+ * This function securely enables debug.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] addr address of message block
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_UNAVAILABLE if SECO not available
+ *
+ * Note \a addr must be a pointer to a signed message block.
+ *
+ * See the Security Reference Manual (SRM) for more info.
+ */
+sc_err_t sc_misc_seco_enable_debug(sc_ipc_t ipc, sc_faddr_t addr);
+
+/*!
+ * This function updates the lifecycle of the device.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] lifecycle new lifecycle
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_UNAVAILABLE if SECO not available
+ *
+ * This message is used for going from Open to NXP Closed to OEM Closed.
+ *
+ * See the Security Reference Manual (SRM) for more info.
+ */
+sc_err_t sc_misc_seco_forward_lifecycle(sc_ipc_t ipc, uint32_t lifecycle);
+
+/*!
+ * This function updates the lifecycle to one of the return lifecycles.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] addr address of message block
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_UNAVAILABLE if SECO not available
+ *
+ * Note \a addr must be a pointer to a signed message block.
+ *
+ * To switch back to NXP states (Full Field Return), message must be signed
+ * by NXP SRK. For OEM States (Partial Field Return), must be signed by OEM
+ * SRK.
+ *
+ * See the Security Reference Manual (SRM) for more info.
+ */
+sc_err_t sc_misc_seco_return_lifecycle(sc_ipc_t ipc, sc_faddr_t addr);
+
+/*!
+ * This function is used to return the SECO FW build info.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] version pointer to return build number
+ * @param[out] commit pointer to return commit ID (git SHA-1)
+ */
+void sc_misc_seco_build_info(sc_ipc_t ipc, uint32_t *version, uint32_t *commit);
+
+/*!
+ * This function is used to return SECO chip info.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] lc pointer to return lifecycle
+ * @param[out] monotonic pointer to return monotonic counter
+ * @param[out] uid_l pointer to return UID (lower 32 bits)
+ * @param[out] uid_h pointer to return UID (upper 32 bits)
+ */
+sc_err_t sc_misc_seco_chip_info(sc_ipc_t ipc, uint16_t *lc,
+ uint16_t *monotonic, uint32_t *uid_l,
+ uint32_t *uid_h);
+
+/* @} */
+
+/*!
+ * @name Debug Functions
+ * @{
+ */
+
+/*!
+ * This function is used output a debug character from the SCU UART.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] ch character to output
+ */
+void sc_misc_debug_out(sc_ipc_t ipc, uint8_t ch);
+
+/*!
+ * This function starts/stops emulation waveform capture.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] enable flag to enable/disable capture
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_UNAVAILABLE if not running on emulation
+ */
+sc_err_t sc_misc_waveform_capture(sc_ipc_t ipc, sc_bool_t enable);
+
+/*!
+ * This function is used to return the SCFW build info.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] build pointer to return build number
+ * @param[out] commit pointer to return commit ID (git SHA-1)
+ */
+void sc_misc_build_info(sc_ipc_t ipc, uint32_t *build, uint32_t *commit);
+
+/*!
+ * This function is used to return the device's unique ID.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] id_l pointer to return lower 32-bit of ID [31:0]
+ * @param[out] id_h pointer to return upper 32-bits of ID [63:32]
+ */
+void sc_misc_unique_id(sc_ipc_t ipc, uint32_t *id_l, uint32_t *id_h);
+
+/* @} */
+
+/*!
+ * @name Other Functions
+ * @{
+ */
+
+/*!
+ * This function configures the ARI match value for PCIe/SATA resources.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource match resource
+ * @param[in] resource_mst PCIe/SATA master to match
+ * @param[in] ari ARI to match
+ * @param[in] enable enable match or not
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the owner or parent
+ * of the owner of the resource and translation
+ *
+ * For PCIe, the ARI is the 16-bit value that includes the bus number,
+ * device number, and function number. For SATA, this value includes the
+ * FISType and PM_Port.
+ */
+sc_err_t sc_misc_set_ari(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rsrc_t resource_mst, uint16_t ari,
+ sc_bool_t enable);
+
+/*!
+ * This function reports boot status.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] status boot status
+ *
+ * This is used by SW partitions to report status of boot. This is
+ * normally used to report a boot failure.
+ */
+void sc_misc_boot_status(sc_ipc_t ipc, sc_misc_boot_status_t status);
+
+/*!
+ * This function tells the SCFW that a CPU is done booting.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] cpu CPU that is done booting
+ *
+ * This is called by early booting CPUs to report they are done with
+ * initialization. After starting early CPUs, the SCFW halts the
+ * booting process until they are done. During this time, early
+ * CPUs can call the SCFW with lower latency as the SCFW is idle.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the CPU owner
+ */
+sc_err_t sc_misc_boot_done(sc_ipc_t ipc, sc_rsrc_t cpu);
+
+/*!
+ * This function reads a given fuse word index.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] word fuse word index
+ * @param[out] val fuse read value
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_PARM if word fuse index param out of range or invalid
+ * - SC_ERR_NOACCESS if read operation failed
+ * - SC_ERR_LOCKED if read operation is locked
+ */
+sc_err_t sc_misc_otp_fuse_read(sc_ipc_t ipc, uint32_t word, uint32_t *val);
+
+/*!
+ * This function writes a given fuse word index.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] word fuse word index
+ * @param[in] val fuse write value
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_PARM if word fuse index param out of range or invalid
+ * - SC_ERR_NOACCESS if write operation failed
+ * - SC_ERR_LOCKED if write operation is locked
+ */
+sc_err_t sc_misc_otp_fuse_write(sc_ipc_t ipc, uint32_t word, uint32_t val);
+
+/*!
+ * This function sets a temp sensor alarm.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource with sensor
+ * @param[in] temp alarm to set
+ * @param[in] celsius whole part of temp to set
+ * @param[in] tenths fractional part of temp to set
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * This function will enable the alarm interrupt if the temp requested is
+ * not the min/max temp. This enable automatically clears when the alarm
+ * occurs and this function has to be called again to re-enable.
+ *
+ * Return errors codes:
+ * - SC_ERR_PARM if parameters invalid
+ */
+sc_err_t sc_misc_set_temp(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_misc_temp_t temp, int16_t celsius, int8_t tenths);
+
+/*!
+ * This function gets a temp sensor value.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource with sensor
+ * @param[in] temp value to get (sensor or alarm)
+ * @param[out] celsius whole part of temp to get
+ * @param[out] tenths fractional part of temp to get
+ *
+ * @return Returns and error code (SC_ERR_NONE = success).
+ *
+ * Return errors codes:
+ * - SC_ERR_PARM if parameters invalid
+ */
+sc_err_t sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_misc_temp_t temp, int16_t *celsius,
+ int8_t *tenths);
+
+/*!
+ * This function returns the boot device.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] dev pointer to return boot device
+ */
+void sc_misc_get_boot_dev(sc_ipc_t ipc, sc_rsrc_t *dev);
+
+/*!
+ * This function returns the current status of the ON/OFF button.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] status pointer to return button status
+ */
+void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status);
+
+/* @} */
+
+#endif /* SC_MISC_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/include/sci/svc/pad/sci_pad_api.h b/plat/imx/common/include/sci/svc/pad/sci_pad_api.h
new file mode 100644
index 0000000..dc23eed
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/pad/sci_pad_api.h
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Pad Control (PAD) function.
+ *
+ * @addtogroup PAD_SVC (SVC) Pad Service
+ *
+ * Module for the Pad Control (PAD) service.
+ *
+ * @details
+ *
+ * Pad configuration is managed by SC firmware. The pad configuration
+ * features supported by the SC firmware include:
+ *
+ * - Configuring the mux, input/output connection, and low-power isolation
+ mode.
+ * - Configuring the technology-specific pad setting such as drive strength,
+ * pullup/pulldown, etc.
+ * - Configuring compensation for pad groups with dual voltage capability.
+ *
+ * Pad functions fall into one of three categories. Generic functions are
+ * common to all SoCs and all process technologies. SoC functions are raw
+ * low-level functions. Technology-specific functions are specific to the
+ * process technology.
+ *
+ * The list of pads is SoC specific. Refer to the SoC [Pad List](@ref PADS)
+ * for valid pad values. Note that all pads exist on a die but may or
+ * may not be brought out by the specific package. Mapping of pads to
+ * package pins/balls is documented in the associated Data Sheet. Some pads
+ * may not be brought out because the part (die+package) is defeatured and
+ * some pads may connect to the substrate in the package.
+ *
+ * Some pads (SC_P_COMP_*) that can be specified are not individual pads
+ * but are in fact pad groups. These groups have additional configuration
+ * that can be done using the sc_pad_set_gp_28fdsoi_comp() function. More
+ * info on these can be found in the associated Reference Manual.
+ *
+ * Pads are managed as a resource by the Resource Manager (RM). They have
+ * assigned owners and only the owners can configure the pads. Some of the
+ * pads are reserved for use by the SCFW itself and this can be overriden
+ * with the implementation of board_config_sc(). Additionally, pads may
+ * be assigned to various other partitions via the implementation of
+ * board_system_config().
+ *
+ * Note muxing two input pads to the same IP functional signal will
+ * result in undefined behavior.
+ * @{
+ */
+
+#ifndef SCI_PAD_API_H
+#define SCI_PAD_API_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_PAD_MUX_W 3 /* Width of mux parameter */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_config_t
+ */
+/*@{*/
+#define SC_PAD_CONFIG_NORMAL 0U /* Normal */
+#define SC_PAD_CONFIG_OD 1U /* Open Drain */
+#define SC_PAD_CONFIG_OD_IN 2U /* Open Drain and input */
+#define SC_PAD_CONFIG_OUT_IN 3U /* Output and input */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_iso_t
+ */
+/*@{*/
+#define SC_PAD_ISO_OFF 0U /* ISO latch is transparent */
+#define SC_PAD_ISO_EARLY 1U /* Follow EARLY_ISO */
+#define SC_PAD_ISO_LATE 2U /* Follow LATE_ISO */
+#define SC_PAD_ISO_ON 3U /* ISO latched data is held */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_28fdsoi_dse_t
+ */
+/*@{*/
+#define SC_PAD_28FDSOI_DSE_18V_1MA 0U /* Drive strength of 1mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_2MA 1U /* Drive strength of 2mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_4MA 2U /* Drive strength of 4mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_6MA 3U /* Drive strength of 6mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_8MA 4U /* Drive strength of 8mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_10MA 5U /* Drive strength of 10mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_12MA 6U /* Drive strength of 12mA for 1.8v */
+#define SC_PAD_28FDSOI_DSE_18V_HS 7U /* High-speed drive strength for 1.8v */
+#define SC_PAD_28FDSOI_DSE_33V_2MA 0U /* Drive strength of 2mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_33V_4MA 1U /* Drive strength of 4mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_33V_8MA 2U /* Drive strength of 8mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_33V_12MA 3U /* Drive strength of 12mA for 3.3v */
+#define SC_PAD_28FDSOI_DSE_DV_HIGH 0U /* High drive strength for dual volt */
+#define SC_PAD_28FDSOI_DSE_DV_LOW 1U /* Low drive strength for dual volt */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_28fdsoi_ps_t
+ */
+/*@{*/
+#define SC_PAD_28FDSOI_PS_KEEPER 0U /* Bus-keeper (only valid for 1.8v) */
+#define SC_PAD_28FDSOI_PS_PU 1U /* Pull-up */
+#define SC_PAD_28FDSOI_PS_PD 2U /* Pull-down */
+#define SC_PAD_28FDSOI_PS_NONE 3U /* No pull (disabled) */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_28fdsoi_pus_t
+ */
+/*@{*/
+#define SC_PAD_28FDSOI_PUS_30K_PD 0U /* 30K pull-down */
+#define SC_PAD_28FDSOI_PUS_100K_PU 1U /* 100K pull-up */
+#define SC_PAD_28FDSOI_PUS_3K_PU 2U /* 3K pull-up */
+#define SC_PAD_28FDSOI_PUS_30K_PU 3U /* 30K pull-up */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pad_wakeup_t
+ */
+/*@{*/
+#define SC_PAD_WAKEUP_OFF 0U /* Off */
+#define SC_PAD_WAKEUP_CLEAR 1U /* Clears pending flag */
+#define SC_PAD_WAKEUP_LOW_LVL 4U /* Low level */
+#define SC_PAD_WAKEUP_FALL_EDGE 5U /* Falling edge */
+#define SC_PAD_WAKEUP_RISE_EDGE 6U /* Rising edge */
+#define SC_PAD_WAKEUP_HIGH_LVL 7U /* High-level */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to declare a pad config. It determines how the
+ * output data is driven, pull-up is controlled, and input signal is
+ * connected. Normal and OD are typical and only connect the input
+ * when the output is not driven. The IN options are less common and
+ * force an input connection even when driving the output.
+ */
+typedef uint8_t sc_pad_config_t;
+
+/*!
+ * This type is used to declare a pad low-power isolation config.
+ * ISO_LATE is the most common setting. ISO_EARLY is only used when
+ * an output pad is directly determined by another input pad. The
+ * other two are only used when SW wants to directly contol isolation.
+ */
+typedef uint8_t sc_pad_iso_t;
+
+/*!
+ * This type is used to declare a drive strength. Note it is specific
+ * to 28FDSOI. Also note that valid values depend on the pad type.
+ */
+typedef uint8_t sc_pad_28fdsoi_dse_t;
+
+/*!
+ * This type is used to declare a pull select. Note it is specific
+ * to 28FDSOI.
+ */
+typedef uint8_t sc_pad_28fdsoi_ps_t;
+
+/*!
+ * This type is used to declare a pull-up select. Note it is specific
+ * to 28FDSOI HSIC pads.
+ */
+typedef uint8_t sc_pad_28fdsoi_pus_t;
+
+/*!
+ * This type is used to declare a wakeup mode of a pad.
+ */
+typedef uint8_t sc_pad_wakeup_t;
+
+/* Functions */
+
+/*!
+ * @name Generic Functions
+ * @{
+ */
+
+/*!
+ * This function configures the mux settings for a pad. This includes
+ * the signal mux, pad config, and low-power isolation mode.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] mux mux setting
+ * @param[in] config pad config
+ * @param[in] iso low-power isolation mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Note muxing two input pads to the same IP functional signal will
+ * result in undefined behavior.
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso);
+
+/*!
+ * This function gets the mux settings for a pad. This includes
+ * the signal mux, pad config, and low-power isolation mode.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] mux pointer to return mux setting
+ * @param[out] config pointer to return pad config
+ * @param[out] iso pointer to return low-power isolation mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t *mux, sc_pad_config_t *config,
+ sc_pad_iso_t *iso);
+
+/*!
+ * This function configures the general purpose pad control. This
+ * is technology dependent and includes things like drive strength,
+ * slew rate, pull up/down, etc. Refer to the SoC Reference Manual
+ * for bit field details.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] ctrl control value to set
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl);
+
+/*!
+ * This function gets the general purpose pad control. This
+ * is technology dependent and includes things like drive strength,
+ * slew rate, pull up/down, etc. Refer to the SoC Reference Manual
+ * for bit field details.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] ctrl pointer to return control value
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl);
+
+/*!
+ * This function configures the wakeup mode of the pad.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] wakeup wakeup to set
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup);
+
+/*!
+ * This function gets the wakeup mode of a pad.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] wakeup pointer to return wakeup
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup);
+
+/*!
+ * This function configures a pad.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] mux mux setting
+ * @param[in] config pad config
+ * @param[in] iso low-power isolation mode
+ * @param[in] ctrl control value
+ * @param[in] wakeup wakeup to set
+ *
+ * @see sc_pad_set_mux().
+ * @see sc_pad_set_gp().
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Note muxing two input pads to the same IP functional signal will
+ * result in undefined behavior.
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux,
+ sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl,
+ sc_pad_wakeup_t wakeup);
+
+/*!
+ * This function gets a pad's config.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] mux pointer to return mux setting
+ * @param[out] config pointer to return pad config
+ * @param[out] iso pointer to return low-power isolation mode
+ * @param[out] ctrl pointer to return control value
+ * @param[out] wakeup pointer to return wakeup to set
+ *
+ * @see sc_pad_set_mux().
+ * @see sc_pad_set_gp().
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux,
+ sc_pad_config_t *config, sc_pad_iso_t *iso,
+ uint32_t *ctrl, sc_pad_wakeup_t *wakeup);
+
+/* @} */
+
+/*!
+ * @name SoC Specific Functions
+ * @{
+ */
+
+/*!
+ * This function configures the settings for a pad. This setting is SoC
+ * specific.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] val value to set
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val);
+
+/*!
+ * This function gets the settings for a pad. This setting is SoC
+ * specific.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] val pointer to return setting
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val);
+
+/* @} */
+
+/*!
+ * @name Technology Specific Functions
+ * @{
+ */
+
+/*!
+ * This function configures the pad control specific to 28FDSOI.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] dse drive strength
+ * @param[in] ps pull select
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t dse,
+ sc_pad_28fdsoi_ps_t ps);
+
+/*!
+ * This function gets the pad control specific to 28FDSOI.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] dse pointer to return drive strength
+ * @param[out] ps pointer to return pull select
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t *dse,
+ sc_pad_28fdsoi_ps_t *ps);
+
+/*!
+ * This function configures the pad control specific to 28FDSOI.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] dse drive strength
+ * @param[in] hys hysteresis
+ * @param[in] pus pull-up select
+ * @param[in] pke pull keeper enable
+ * @param[in] pue pull-up enable
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t dse, sc_bool_t hys,
+ sc_pad_28fdsoi_pus_t pus, sc_bool_t pke,
+ sc_bool_t pue);
+
+/*!
+ * This function gets the pad control specific to 28FDSOI.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] dse pointer to return drive strength
+ * @param[out] hys pointer to return hysteresis
+ * @param[out] pus pointer to return pull-up select
+ * @param[out] pke pointer to return pull keeper enable
+ * @param[out] pue pointer to return pull-up enable
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys,
+ sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke,
+ sc_bool_t *pue);
+
+/*!
+ * This function configures the compensation control specific to 28FDSOI.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to configure
+ * @param[in] compen compensation/freeze mode
+ * @param[in] fastfrz fast freeze
+ * @param[in] rasrcp compensation code for PMOS
+ * @param[in] rasrcn compensation code for NMOS
+ * @param[in] nasrc_sel NASRC read select
+ * @param[in] psw_ovr 2.5v override
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ *
+ * Note \a psw_ovr is only applicable to pads supporting 2.5 volt
+ * operation (e.g. some Ethernet pads).
+ */
+sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t compen, sc_bool_t fastfrz,
+ uint8_t rasrcp, uint8_t rasrcn,
+ sc_bool_t nasrc_sel, sc_bool_t psw_ovr);
+
+/*!
+ * This function gets the compensation control specific to 28FDSOI.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to query
+ * @param[out] compen pointer to return compensation/freeze mode
+ * @param[out] fastfrz pointer to return fast freeze
+ * @param[out] rasrcp pointer to return compensation code for PMOS
+ * @param[out] rasrcn pointer to return compensation code for NMOS
+ * @param[out] nasrc_sel pointer to return NASRC read select
+ * @param[out] compok pointer to return compensation status
+ * @param[out] nasrc pointer to return NASRCP/NASRCN
+ * @param[out] psw_ovr pointer to return the 2.5v override
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner,
+ * - SC_ERR_UNAVAILABLE if process not applicable
+ *
+ * Refer to the SoC [Pad List](@ref PADS) for valid pad values.
+ */
+sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t *compen, sc_bool_t *fastfrz,
+ uint8_t *rasrcp, uint8_t *rasrcn,
+ sc_bool_t *nasrc_sel, sc_bool_t *compok,
+ uint8_t *nasrc, sc_bool_t *psw_ovr);
+
+/* @} */
+
+#endif /* SCI_PAD_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/include/sci/svc/pm/sci_pm_api.h b/plat/imx/common/include/sci/svc/pm/sci_pm_api.h
new file mode 100644
index 0000000..76ca5c4
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/pm/sci_pm_api.h
@@ -0,0 +1,684 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Power Management (PM) function. This includes functions for power state
+ * control, clock control, reset control, and wake-up event control.
+ *
+ * @addtogroup PM_SVC (SVC) Power Management Service
+ *
+ * Module for the Power Management (PM) service.
+ *
+ * @{
+ */
+
+#ifndef SCI_PM_API_H
+#define SCI_PM_API_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_PM_POWER_MODE_W 2 /* Width of sc_pm_power_mode_t */
+#define SC_PM_CLOCK_MODE_W 3 /* Width of sc_pm_clock_mode_t */
+#define SC_PM_RESET_TYPE_W 2 /* Width of sc_pm_reset_type_t */
+#define SC_PM_RESET_REASON_W 3 /* Width of sc_pm_reset_reason_t */
+/*@}*/
+
+/*!
+ * @name Defines for clock indexes (sc_pm_clk_t)
+ */
+/*@{*/
+/*@}*/
+
+/*!
+ * @name Defines for ALL parameters
+ */
+/*@{*/
+#define SC_PM_CLK_ALL UINT8_MAX /* All clocks */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_power_mode_t
+ */
+/*@{*/
+#define SC_PM_PW_MODE_OFF 0U /* Power off */
+#define SC_PM_PW_MODE_STBY 1U /* Power in standby */
+#define SC_PM_PW_MODE_LP 2U /* Power in low-power */
+#define SC_PM_PW_MODE_ON 3U /* Power on */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_clk_t
+ */
+/*@{*/
+#define SC_PM_CLK_SLV_BUS 0U /* Slave bus clock */
+#define SC_PM_CLK_MST_BUS 1U /* Master bus clock */
+#define SC_PM_CLK_PER 2U /* Peripheral clock */
+#define SC_PM_CLK_PHY 3U /* Phy clock */
+#define SC_PM_CLK_MISC 4U /* Misc clock */
+#define SC_PM_CLK_MISC0 0U /* Misc 0 clock */
+#define SC_PM_CLK_MISC1 1U /* Misc 1 clock */
+#define SC_PM_CLK_MISC2 2U /* Misc 2 clock */
+#define SC_PM_CLK_MISC3 3U /* Misc 3 clock */
+#define SC_PM_CLK_MISC4 4U /* Misc 4 clock */
+#define SC_PM_CLK_CPU 2U /* CPU clock */
+#define SC_PM_CLK_PLL 4U /* PLL */
+#define SC_PM_CLK_BYPASS 4U /* Bypass clock */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_clk_mode_t
+ */
+/*@{*/
+#define SC_PM_CLK_MODE_ROM_INIT 0U /* Clock is initialized by ROM. */
+#define SC_PM_CLK_MODE_OFF 1U /* Clock is disabled */
+#define SC_PM_CLK_MODE_ON 2U /* Clock is enabled. */
+#define SC_PM_CLK_MODE_AUTOGATE_SW 3U /* Clock is in SW autogate mode */
+#define SC_PM_CLK_MODE_AUTOGATE_HW 4U /* Clock is in HW autogate mode */
+#define SC_PM_CLK_MODE_AUTOGATE_SW_HW 5U /* Clock is in SW-HW autogate mode */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_clk_parent_t
+ */
+/*@{*/
+#define SC_PM_PARENT_XTAL 0U /* Parent is XTAL. */
+#define SC_PM_PARENT_PLL0 1U /* Parent is PLL0 */
+#define SC_PM_PARENT_PLL1 2U /* Parent is PLL1 or PLL0/2 */
+#define SC_PM_PARENT_PLL2 3U /* Parent in PLL2 or PLL0/4 */
+#define SC_PM_PARENT_BYPS 4U /* Parent is a bypass clock. */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_reset_type_t
+ */
+/*@{*/
+#define SC_PM_RESET_TYPE_COLD 0U /* Cold reset */
+#define SC_PM_RESET_TYPE_WARM 1U /* Warm reset */
+#define SC_PM_RESET_TYPE_BOARD 2U /* Board reset */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_reset_cause_t
+ */
+/*@{*/
+#define SC_PM_RESET_CAUSE_TEMP 0U /* Reset due to temp panic alarm */
+#define SC_PM_RESET_CAUSE_FAULT 1U /* Reset due to fault exception */
+#define SC_PM_RESET_CAUSE_IRQ 2U /* Reset due to SCU reset IRQ */
+#define SC_PM_RESET_CAUSE_WDOG 3U /* Reset due to SW WDOG */
+#define SC_PM_RESET_CAUSE_API 4U /* Reset due to pm_reset() or monitor */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_reset_reason_t
+ */
+/*@{*/
+#define SC_PM_RESET_REASON_POR 0U /* Power on reset */
+#define SC_PM_RESET_REASON_WARM 1U /* Warm reset */
+#define SC_PM_RESET_REASON_SW 2U /* Software reset */
+#define SC_PM_RESET_REASON_WDOG 3U /* Watchdog reset */
+#define SC_PM_RESET_REASON_LOCKUP 4U /* Lockup reset */
+#define SC_PM_RESET_REASON_TAMPER 5U /* Tamper reset */
+#define SC_PM_RESET_REASON_TEMP 6U /* Temp reset */
+#define SC_PM_RESET_REASON_LOW_VOLT 7U /* Low voltage reset */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_sys_if_t
+ */
+/*@{*/
+#define SC_PM_SYS_IF_INTERCONNECT 0U /* System interconnect */
+#define SC_PM_SYS_IF_MU 1U /* AP -> SCU message units */
+#define SC_PM_SYS_IF_OCMEM 2U /* On-chip memory (ROM/OCRAM) */
+#define SC_PM_SYS_IF_DDR 3U /* DDR memory */
+/*@}*/
+
+/*!
+ * @name Defines for sc_pm_wake_src_t
+ */
+/*@{*/
+#define SC_PM_WAKE_SRC_NONE 0U /* No wake source, used for self-kill */
+#define SC_PM_WAKE_SRC_SCU 1U /* Wakeup from SCU to resume CPU (IRQSTEER & GIC powered down) */
+#define SC_PM_WAKE_SRC_IRQSTEER 2U /* Wakeup from IRQSTEER to resume CPU (GIC powered down) */
+#define SC_PM_WAKE_SRC_IRQSTEER_GIC 3U /* Wakeup from IRQSTEER+GIC to wake CPU (GIC clock gated) */
+#define SC_PM_WAKE_SRC_GIC 4U /* Wakeup from GIC to wake CPU */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to declare a power mode. Note resources only use
+ * SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON. The other modes are used only
+ * as system power modes.
+ */
+typedef uint8_t sc_pm_power_mode_t;
+
+/*!
+ * This type is used to declare a clock.
+ */
+typedef uint8_t sc_pm_clk_t;
+
+/*!
+ * This type is used to declare a clock mode.
+ */
+typedef uint8_t sc_pm_clk_mode_t;
+
+/*!
+ * This type is used to declare the clock parent.
+ */
+typedef uint8_t sc_pm_clk_parent_t;
+
+/*!
+ * This type is used to declare clock rates.
+ */
+typedef uint32_t sc_pm_clock_rate_t;
+
+/*!
+ * This type is used to declare a desired reset type.
+ */
+typedef uint8_t sc_pm_reset_type_t;
+
+/*!
+ * This type is used to declare a desired reset type.
+ */
+typedef uint8_t sc_pm_reset_cause;
+
+/*!
+ * This type is used to declare a reason for a reset.
+ */
+typedef uint8_t sc_pm_reset_reason_t;
+
+/*!
+ * This type is used to specify a system-level interface to be power managed.
+ */
+typedef uint8_t sc_pm_sys_if_t;
+
+/*!
+ * This type is used to specify a wake source for CPU resources.
+ */
+typedef uint8_t sc_pm_wake_src_t;
+
+/* Functions */
+
+/*!
+ * @name Power Functions
+ * @{
+ */
+
+/*!
+ * This function sets the system power mode. Only the owner of the
+ * SC_R_SYSTEM resource can do this.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] mode power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid mode,
+ * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM
+ *
+ * @see sc_pm_set_sys_power_mode().
+ */
+sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode);
+
+/*!
+ * This function sets the power mode of a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition
+ * @param[in] mode power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition or mode,
+ * - SC_ERR_NOACCESS if caller's partition is not the owner or
+ * parent of \a pt
+ *
+ * The power mode of the partitions is a max power any resource will
+ * be set to. Calling this will result in all resources owned
+ * by \a pt to have their power changed to the lower of \a mode or the
+ * individual resource mode set using sc_pm_set_resource_power_mode().
+ */
+sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_pm_power_mode_t mode);
+
+/*!
+ * This function gets the power mode of a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition
+ * @param[out] mode pointer to return power mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition
+ */
+sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_pm_power_mode_t *mode);
+
+/*!
+ * This function sets the power mode of a resource.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] mode power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or mode,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ * or parent of the owner
+ *
+ * This function will record the individual resource power mode
+ * and change it if the requested mode is lower than or equal to the
+ * partition power mode set with sc_pm_set_partition_power_mode().
+ * In other words, the power mode of the resource will be the minimum
+ * of the resource power mode and the partition power mode.
+ *
+ * Note some resources are still not accessible even when powered up if bus
+ * transactions go through a fabric not powered up. Examples of this are
+ * resources in display and capture subsystems which require the display
+ * controller or the imaging subsytem to be powered up first.
+ *
+ * Not that resources are grouped into power domains by the underlying
+ * hardware. If any resource in the domain is on, the entire power domain
+ * will be on. Other power domains required to access the resource will
+ * also be turned on. Clocks required to access the peripheral will be
+ * turned on. Refer to the SoC RM for more info on power domains and access
+ * infrastructure (bus fabrics, clock domains, etc.).
+ */
+sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t mode);
+
+/*!
+ * This function gets the power mode of a resource.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[out] mode pointer to return power mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Note only SC_PM_PW_MODE_OFF and SC_PM_PW_MODE_ON are valid. The value
+ * returned does not reflect the power mode of the partition..
+ */
+sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t *mode);
+
+/*!
+ * This function requests the low power mode some of the resources
+ * can enter based on their state. This API is only valid for the
+ * following resources : SC_R_A53, SC_R_A53_0, SC_R_A53_1, SC_A53_2,
+ * SC_A53_3, SC_R_A72, SC_R_A72_0, SC_R_A72_1, SC_R_CC1, SC_R_A35,
+ * SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3.
+ * For all other resources it will return SC_ERR_PARAM.
+ * This function will set the low power mode the cores, cluster
+ * and cluster associated resources will enter when all the cores
+ * in a given cluster execute WFI
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] mode power mode to apply
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ */
+sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t mode);
+
+/*!
+ * This function requests low-power mode entry for CPU/cluster
+ * resources. This API is only valid for the following resources:
+ * SC_R_A53, SC_R_A53_x, SC_R_A72, SC_R_A72_x, SC_R_A35, SC_R_A35_x,
+ * SC_R_CCI. For all other resources it will return SC_ERR_PARAM.
+ * For individual core resources, the specified power mode
+ * and wake source will be applied after the core has entered
+ * WFI. For cluster resources, the specified power mode is
+ * applied after all cores in the cluster have entered low-power mode.
+ * For multicluster resources, the specified power mode is applied
+ * after all clusters have reached low-power mode.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] mode power mode to apply
+ * @param[in] wake_src wake source for low-power exit
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ */
+sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t mode,
+ sc_pm_wake_src_t wake_src);
+
+/*!
+ * This function is used to set the resume address of a CPU.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the CPU resource
+ * @param[in] address 64-bit resume address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or address,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ * resource (CPU) owner
+ */
+sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_faddr_t address);
+
+/*!
+ * This function is used to set parameters for CPU resume from
+ * low-power mode.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the CPU resource
+ * @param[in] isPrimary set SC_TRUE if primary wake CPU
+ * @param[in] address 64-bit resume address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or address,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ * resource (CPU) owner
+ */
+sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_bool_t isPrimary, sc_faddr_t address);
+
+/*!
+ * This function requests the power mode configuration for system-level
+ * interfaces including messaging units, interconnect, and memories. This API
+ * is only valid for the following resources : SC_R_A53, SC_R_A72, and
+ * SC_R_M4_x_PID_y. For all other resources, it will return SC_ERR_PARAM.
+ * The requested power mode will be captured and applied to system-level
+ * resources as system conditions allow.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] sys_if system-level interface to be configured
+ * @param[in] hpm high-power mode for the system interface
+ * @param[in] lpm low-power mode for the system interface
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ */
+sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_sys_if_t sys_if,
+ sc_pm_power_mode_t hpm,
+ sc_pm_power_mode_t lpm);
+
+/* @} */
+
+/*!
+ * @name Clock/PLL Functions
+ * @{
+ */
+
+/*!
+ * This function sets the rate of a resource's clock/PLL.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] clk clock/PLL to affect
+ * @param[in,out] rate pointer to rate to set,
+ * return actual rate
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock/PLL,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ * or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource,
+ * - SC_ERR_LOCKED if rate locked (usually because shared clock/PLL)
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values.
+ */
+sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clock_rate_t *rate);
+
+/*!
+ * This function gets the rate of a resource's clock/PLL.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] clk clock/PLL to affect
+ * @param[out] rate pointer to return rate
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock/PLL,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ * or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock/PLL not applicable to this resource
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock/PLL values.
+ */
+sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clock_rate_t *rate);
+
+/*!
+ * This function enables/disables a resource's clock.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] clk clock to affect
+ * @param[in] enable enable if SC_TRUE; otherwise disabled
+ * @param[in] autog HW auto clock gating
+ *
+ * If \a resource is SC_R_ALL then all resources owned will be affected.
+ * No error will be returned.
+ *
+ * If \a clk is SC_PM_CLK_ALL, then an error will be returned if any
+ * of the available clocks returns an error.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ * or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock not applicable to this resource
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock values.
+ */
+sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog);
+
+/*!
+ * This function sets the parent of a resource's clock.
+ * This function should only be called when the clock is disabled.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] clk clock to affect
+ * @param[in] parent New parent of the clock.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ * or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock not applicable to this resource
+ * - SC_ERR_BUSY if clock is currently enabled.
+ * - SC_ERR_NOPOWER if resource not powered
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock values.
+ */
+sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clk_parent_t parent);
+
+/*!
+ * This function gets the parent of a resource's clock.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the resource
+ * @param[in] clk clock to affect
+ * @param[out] parent pointer to return parent of clock.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or clock,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner
+ * or parent of the owner,
+ * - SC_ERR_UNAVAILABLE if clock not applicable to this resource
+ *
+ * Refer to the [Clock List](@ref CLOCKS) for valid clock values.
+ */
+sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clk_parent_t *parent);
+
+/* @} */
+
+/*!
+ * @name Reset Functions
+ * @{
+ */
+
+/*!
+ * This function is used to reset the system. Only the owner of the
+ * SC_R_SYSTEM resource can do this.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] type reset type
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid type,
+ * - SC_ERR_NOACCESS if caller not the owner of SC_R_SYSTEM
+ *
+ * If this function returns, then the reset did not occur due to an
+ * invalid parameter.
+ */
+sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type);
+
+/*!
+ * This function gets a caller's reset reason.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] reason pointer to return reset reason
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason);
+
+/*!
+ * This function is used to boot a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to boot
+ * @param[in] resource_cpu ID of the CPU resource to start
+ * @param[in] boot_addr 64-bit boot address
+ * @param[in] resource_mu ID of the MU that must be powered
+ * @param[in] resource_dev ID of the boot device that must be powered
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition, resource, or addr,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ * partition to boot
+ */
+sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_rsrc_t resource_cpu, sc_faddr_t boot_addr,
+ sc_rsrc_t resource_mu, sc_rsrc_t resource_dev);
+
+/*!
+ * This function is used to reboot the caller's partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] type reset type
+ *
+ * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by
+ * the calling partition will be reset if possible. SC state (partitions,
+ * power, clocks, etc.) is reset. The boot SW of the booting CPU must be
+ * able to handle peripherals that that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset.
+ * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW
+ * of the booting CPU must be able to handle peripherals and SC state that
+ * that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action.
+ *
+ * If this function returns, then the reset did not occur due to an
+ * invalid parameter.
+ */
+void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type);
+
+/*!
+ * This function is used to reboot a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to reboot
+ * @param[in] type reset type
+ *
+ * If \a type is SC_PM_RESET_TYPE_COLD, then most peripherals owned by
+ * the calling partition will be reset if possible. SC state (partitions,
+ * power, clocks, etc.) is reset. The boot SW of the booting CPU must be
+ * able to handle peripherals that that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_WARM, then only the boot CPU is reset.
+ * SC state (partitions, power, clocks, etc.) are NOT reset. The boot SW
+ * of the booting CPU must be able to handle peripherals and SC state that
+ * that are not reset.
+ *
+ * If \a type is SC_PM_RESET_TYPE_BOARD, then return with no action.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid partition or type
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ *
+ * Most peripherals owned by the partition will be reset if
+ * possible. SC state (partitions, power, clocks, etc.) is reset. The
+ * boot SW of the booting CPU must be able to handle peripherals that
+ * that are not reset.
+ */
+sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_pm_reset_type_t type);
+
+/*!
+ * This function is used to start/stop a CPU.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource ID of the CPU resource
+ * @param[in] enable start if SC_TRUE; otherwise stop
+ * @param[in] address 64-bit boot address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid resource or address,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of the
+ * resource (CPU) owner
+ */
+sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable,
+ sc_faddr_t address);
+
+/* @} */
+
+#endif /* SCI_PM_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/include/sci/svc/rm/sci_rm_api.h b/plat/imx/common/include/sci/svc/rm/sci_rm_api.h
new file mode 100644
index 0000000..df1bc40
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/rm/sci_rm_api.h
@@ -0,0 +1,757 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Resource Management (RM) function. This includes functions for
+ * partitioning resources, pads, and memory regions.
+ *
+ * @addtogroup RM_SVC (SVC) Resource Management Service
+ *
+ * Module for the Resource Management (RM) service.
+ *
+ * @includedoc rm/details.dox
+ *
+ * @{
+ */
+
+#ifndef SCI_RM_API_H
+#define SCI_RM_API_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_RM_PARTITION_W 5 /* Width of sc_rm_pt_t */
+#define SC_RM_MEMREG_W 6 /* Width of sc_rm_mr_t */
+#define SC_RM_DID_W 4 /* Width of sc_rm_did_t */
+#define SC_RM_SID_W 6 /* Width of sc_rm_sid_t */
+#define SC_RM_SPA_W 2 /* Width of sc_rm_spa_t */
+#define SC_RM_PERM_W 3 /* Width of sc_rm_perm_t */
+/*@}*/
+
+/*!
+ * @name Defines for ALL parameters
+ */
+/*@{*/
+#define SC_RM_PT_ALL ((sc_rm_pt_t) UINT8_MAX) /* All partitions */
+#define SC_RM_MR_ALL ((sc_rm_mr_t) UINT8_MAX) /* All memory regions */
+/*@}*/
+
+/*!
+ * @name Defines for sc_rm_spa_t
+ */
+/*@{*/
+#define SC_RM_SPA_PASSTHRU 0U /* Pass through (attribute driven by master) */
+#define SC_RM_SPA_PASSSID 1U /* Pass through and output on SID */
+#define SC_RM_SPA_ASSERT 2U /* Assert (force to be secure/privileged) */
+#define SC_RM_SPA_NEGATE 3U /* Negate (force to be non-secure/user) */
+/*@}*/
+
+/*!
+ * @name Defines for sc_rm_perm_t
+ */
+/*@{*/
+#define SC_RM_PERM_NONE 0U /* No access */
+#define SC_RM_PERM_SEC_R 1U /* Secure RO */
+#define SC_RM_PERM_SECPRIV_RW 2U /* Secure privilege R/W */
+#define SC_RM_PERM_SEC_RW 3U /* Secure R/W */
+#define SC_RM_PERM_NSPRIV_R 4U /* Secure R/W, non-secure privilege RO */
+#define SC_RM_PERM_NS_R 5U /* Secure R/W, non-secure RO */
+#define SC_RM_PERM_NSPRIV_RW 6U /* Secure R/W, non-secure privilege R/W */
+#define SC_RM_PERM_FULL 7U /* Full access */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to declare a resource partition.
+ */
+typedef uint8_t sc_rm_pt_t;
+
+/*!
+ * This type is used to declare a memory region.
+ */
+typedef uint8_t sc_rm_mr_t;
+
+/*!
+ * This type is used to declare a resource domain ID used by the
+ * isolation HW.
+ */
+typedef uint8_t sc_rm_did_t;
+
+/*!
+ * This type is used to declare an SMMU StreamID.
+ */
+typedef uint16_t sc_rm_sid_t;
+
+/*!
+ * This type is a used to declare master transaction attributes.
+ */
+typedef uint8_t sc_rm_spa_t;
+
+/*!
+ * This type is used to declare a resource/memory region access permission.
+ * Refer to the XRDC2 Block Guide for more information.
+ */
+typedef uint8_t sc_rm_perm_t;
+
+/* Functions */
+
+/*!
+ * @name Partition Functions
+ * @{
+ */
+
+/*!
+ * This function requests that the SC create a new resource partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] pt return handle for partition; used for subsequent function
+ * calls associated with this partition
+ * @param[in] secure boolean indicating if this partition should be secure; only
+ * valid if caller is secure
+ * @param[in] isolated boolean indicating if this partition should be HW isolated
+ * via XRDC; set SC_TRUE if new DID is desired
+ * @param[in] restricted boolean indicating if this partition should be restricted; set
+ * SC_TRUE if masters in this partition cannot create new partitions
+ * @param[in] grant boolean indicating if this partition should always grant
+ * access and control to the parent
+ * @param[in] coherent boolean indicating if this partition is coherent;
+ * set SC_TRUE if only this partition will contain both AP clusters
+ * and they will be coherent via the CCI
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_ERR_PARM if caller's partition is not secure but a new secure partition is requested,
+ * - SC_ERR_LOCKED if caller's partition is locked,
+ * - SC_ERR_UNAVAILABLE if partition table is full (no more allocation space)
+ *
+ * Marking as non-secure prevents subsequent functions from configuring masters in this
+ * partition to assert the secure signal. If restricted then the new partition is limited
+ * in what functions it can call, especially those associated with managing partitions.
+ *
+ * The grant option is usually used to isolate a bus master's traffic to specific
+ * memory without isolating the peripheral interface of the master or the API
+ * controls of that master.
+ */
+sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure,
+ sc_bool_t isolated, sc_bool_t restricted,
+ sc_bool_t grant, sc_bool_t coherent);
+
+/*!
+ * This function makes a partition confidential.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition that is granting
+ * @param[in] retro retroactive
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a pt out of range,
+ * - SC_ERR_NOACCESS if caller's not allowed to change \a pt
+ * - SC_ERR_LOCKED if partition \a pt is locked
+ *
+ * Call to make a partition confidential. Confidential means only this
+ * partition should be able to grant access permissions to this partition.
+ *
+ * If retroactive, then all resources owned by other partitions will have
+ * access rights for this partition removed, even if locked.
+ */
+sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro);
+
+/*!
+ * This function frees a partition and assigns all resources to the caller.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to free
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if \a pt out of range or invalid,
+ * - SC_ERR_NOACCESS if \a pt is the SC partition,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ * - SC_ERR_LOCKED if \a pt or caller's partition is locked
+ *
+ * All resources, memory regions, and pads are assigned to the caller/parent.
+ * The partition watchdog is disabled (even if locked). DID is freed.
+ */
+sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt);
+
+/*!
+ * This function returns the DID of a partition.
+ *
+ * @param[in] ipc IPC handle
+ *
+ * @return Returns the domain ID (DID) of the caller's partition.
+ *
+ * The DID is a SoC-specific internal ID used by the HW resource
+ * protection mechanism. It is only required by clients when using the
+ * SEMA42 module as the DID is sometimes connected to the master ID.
+ */
+sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc);
+
+/*!
+ * This function forces a partition to use a specific static DID.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to assign \a did
+ * @param[in] did static DID to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if \a pt or \a did out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ * - SC_ERR_LOCKED if \a pt is locked
+ *
+ * Assumes no assigned resources or memory regions yet! The number of static
+ * DID is fixed by the SC at boot.
+ */
+sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did);
+
+/*!
+ * This function locks a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to lock
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a pt out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt
+ *
+ * If a partition is locked it cannot be freed, have resources/pads assigned
+ * to/from it, memory regions created/assigned, DID changed, or parent changed.
+ */
+sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt);
+
+/*!
+ * This function gets the partition handle of the caller.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] pt return handle for caller's partition
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt);
+
+/*!
+ * This function sets a new parent for a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition for which parent is to be
+ * changed
+ * @param[in] pt_parent handle of partition to set as parent
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the parent of \a pt,
+ * - SC_ERR_LOCKED if either partition is locked
+ */
+sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent);
+
+/*!
+ * This function moves all movable resources/pads owned by a source partition
+ * to a destination partition. It can be used to more quickly set up a new
+ * partition if a majority of the caller's resources are to be moved to a
+ * new partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt_src handle of partition from which resources should
+ * be moved from
+ * @param[in] pt_dst handle of partition to which resources should be
+ * moved to
+ * @param[in] move_rsrc boolean to indicate if resources should be moved
+ * @param[in] move_pads boolean to indicate if pads should be moved
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * By default, all resources are movable. This can be changed using the
+ * sc_rm_set_resource_movable() function. Note all masters defaulted to SMMU
+ * bypass.
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not \a pt_src or the
+ * parent of \a pt_src,
+ * - SC_ERR_LOCKED if either partition is locked
+ */
+sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst,
+ sc_bool_t move_rsrc, sc_bool_t move_pads);
+
+/* @} */
+
+/*!
+ * @name Resource Functions
+ * @{
+ */
+
+/*!
+ * This function assigns ownership of a resource to a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to which resource should be
+ * assigned
+ * @param[in] resource resource to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * This action resets the resource's master and peripheral attributes.
+ * Privilege attribute will be PASSTHRU, security attribute will be
+ * ASSERT if the partition si secure and NEGATE if it is not, and
+ * masters will defaulted to SMMU bypass. Access permissions will reset
+ * to SEC_RW for the owning partition only for secure partitions, FULL for
+ * non-secure. DEfault is no access by other partitions.
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ * of the owner,
+ * - SC_ERR_LOCKED if the owning partition or \a pt is locked
+ */
+sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource);
+
+/*!
+ * This function flags resources as movable or not.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource_fst first resource for which flag should be set
+ * @param[in] resource_lst last resource for which flag should be set
+ * @param[in] movable movable flag (SC_TRUE is movable)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if resources are out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of a resource owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function is used to determine the set of resources that will be
+ * moved using the sc_rm_move_all() function. All resources are movable
+ * by default so this function is normally used to prevent a set of
+ * resources from moving.
+ */
+sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst,
+ sc_rsrc_t resource_lst, sc_bool_t movable);
+
+/*!
+ * This function flags all of a subsystem's resources as movable
+ * or not.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource to use to identify subsystem
+ * @param[in] movable movable flag (SC_TRUE is movable)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if a function argument is out of range
+ *
+ * Note \a resource is used to find the associated subsystem. Only
+ * resources owned by the caller are set.
+ */
+sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_bool_t movable);
+
+/*!
+ * This function sets attributes for a resource which is a bus master (i.e.
+ * capable of DMA).
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource master resource for which attributes should apply
+ * @param[in] sa security attribute
+ * @param[in] pa privilege attribute
+ * @param[in] smmu_bypass SMMU bypass mode
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of the resource owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function configures how the HW isolation will see bus transactions
+ * from the specified master. Note the security attribute will only be
+ * changed if the caller's partition is secure.
+ */
+sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rm_spa_t sa, sc_rm_spa_t pa,
+ sc_bool_t smmu_bypass);
+
+/*!
+ * This function sets the StreamID for a resource which is a bus master (i.e.
+ * capable of DMA).
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource master resource for which attributes should apply
+ * @param[in] sid StreamID
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ * of the owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function configures the SID attribute associated with all bus transactions
+ * from this master. Note 0 is not a valid SID as it is reserved to indicate
+ * bypass.
+ */
+sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rm_sid_t sid);
+
+/*!
+ * This function sets access permissions for a peripheral resource.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource peripheral resource for which permissions should apply
+ * @param[in] pt handle of partition \a perm should by applied for
+ * @param[in] perm permissions to apply to \a resource for \a pt
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the resource owner or parent
+ * of the owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt
+ *
+ * This function configures how the HW isolation will restrict access to a
+ * peripheral based on the attributes of a transaction from bus master.
+ */
+sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rm_pt_t pt, sc_rm_perm_t perm);
+
+/*!
+ * This function gets ownership status of a resource.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource to check
+ *
+ * @return Returns a boolean (SC_TRUE if caller's partition owns the resource).
+ *
+ * If \a resource is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource);
+
+/*!
+ * This function is used to test if a resource is a bus master.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource to check
+ *
+ * @return Returns a boolean (SC_TRUE if the resource is a bus master).
+ *
+ * If \a resource is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource);
+
+/*!
+ * This function is used to test if a resource is a peripheral.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource to check
+ *
+ * @return Returns a boolean (SC_TRUE if the resource is a peripheral).
+ *
+ * If \a resource is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource);
+
+/*!
+ * This function is used to obtain info about a resource.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] resource resource to inquire about
+ * @param[out] sid pointer to return StreamID
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a resource is out of range
+ */
+sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rm_sid_t *sid);
+
+/* @} */
+
+/*!
+ * @name Memory Region Functions
+ * @{
+ */
+
+/*!
+ * This function requests that the SC create a new memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] mr return handle for region; used for
+ * subsequent function calls
+ * associated with this region
+ * @param[in] addr_start start address of region (physical)
+ * @param[in] addr_end end address of region (physical)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if the new memory region is misaligned,
+ * - SC_ERR_LOCKED if caller's partition is locked,
+ * - SC_ERR_PARM if the new memory region spans multiple existing regions,
+ * - SC_ERR_NOACCESS if caller's partition does not own the memory containing
+ * the new region,
+ * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation
+ * space)
+ *
+ * The area covered by the memory region must currently be owned by the caller.
+ * By default, the new region will have access permission set to allow the
+ * caller to access.
+ */
+sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr,
+ sc_faddr_t addr_start, sc_faddr_t addr_end);
+
+/*!
+ * This function requests that the SC split a memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] mr handle of memory region to split
+ * @param[out] mr_ret return handle for new region; used for
+ * subsequent function calls
+ * associated with this region
+ * @param[in] addr_start start address of region (physical)
+ * @param[in] addr_end end address of region (physical)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if the new memory region is not start/end part of mr,
+ * - SC_ERR_LOCKED if caller's partition is locked,
+ * - SC_ERR_PARM if the new memory region spans multiple existing regions,
+ * - SC_ERR_NOACCESS if caller's partition does not own the memory containing
+ * the new region,
+ * - SC_ERR_UNAVAILABLE if memory region table is full (no more allocation
+ * space)
+ *
+ * Note the new region must start or end on the split region.
+ */
+sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr,
+ sc_rm_mr_t *mr_ret, sc_faddr_t addr_start,
+ sc_faddr_t addr_end);
+
+/*!
+ * This function frees a memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] mr handle of memory region to free
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a mr out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of \a mr,
+ * - SC_ERR_LOCKED if the owning partition of \a mr is locked
+ */
+sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr);
+
+/*!
+ * Internal SC function to find a memory region.
+ *
+ * @see sc_rm_find_memreg().
+ */
+/*!
+ * This function finds a memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] mr return handle for region; used for
+ * subsequent function calls
+ * associated with this region
+ * @param[in] addr_start start address of region to search for
+ * @param[in] addr_end end address of region to search for
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOTFOUND if region not found,
+ *
+ * Searches only for regions owned by the caller. Finds first
+ * region containing the range specified.
+ */
+sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr,
+ sc_faddr_t addr_start, sc_faddr_t addr_end);
+
+/*!
+ * This function assigns ownership of a memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to which memory region
+ * should be assigned
+ * @param[in] mr handle of memory region to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the \a mr owner or parent
+ * of the owner,
+ * - SC_ERR_LOCKED if the owning partition or \a pt is locked
+ */
+sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr);
+
+/*!
+ * This function sets access permissions for a memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] mr handle of memory region for which permissions
+ * should apply
+ * @param[in] pt handle of partition \a perm should by
+ * applied for
+ * @param[in] perm permissions to apply to \a mr for \a pt
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the region owner or parent
+ * of the owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ * - SC_ERR_LOCKED if the \a pt is confidential and the caller isn't \a pt
+ *
+ * This function configures how the HW isolation will restrict access to a
+ * memory region based on the attributes of a transaction from bus master.
+ */
+sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr,
+ sc_rm_pt_t pt, sc_rm_perm_t perm);
+
+/*!
+ * This function gets ownership status of a memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] mr handle of memory region to check
+ *
+ * @return Returns a boolean (SC_TRUE if caller's partition owns the
+ * memory region).
+ *
+ * If \a mr is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr);
+
+/*!
+ * This function is used to obtain info about a memory region.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] mr handle of memory region to inquire about
+ * @param[out] addr_start pointer to return start address
+ * @param[out] addr_end pointer to return end address
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if \a mr is out of range
+ */
+sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr,
+ sc_faddr_t *addr_start, sc_faddr_t *addr_end);
+
+/* @} */
+
+/*!
+ * @name Pad Functions
+ * @{
+ */
+
+/*!
+ * This function assigns ownership of a pad to a partition.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt handle of partition to which pad should
+ * be assigned
+ * @param[in] pad pad to assign
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_NOACCESS if caller's partition is restricted,
+ * - SC_PARM if arguments out of range or invalid,
+ * - SC_ERR_NOACCESS if caller's partition is not the pad owner or parent
+ * of the owner,
+ * - SC_ERR_LOCKED if the owning partition or \a pt is locked
+ */
+sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad);
+
+/*!
+ * This function flags pads as movable or not.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad_fst first pad for which flag should be set
+ * @param[in] pad_lst last pad for which flag should be set
+ * @param[in] movable movable flag (SC_TRUE is movable)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_PARM if pads are out of range,
+ * - SC_ERR_NOACCESS if caller's partition is not a parent of a pad owner,
+ * - SC_ERR_LOCKED if the owning partition is locked
+ *
+ * This function is used to determine the set of pads that will be
+ * moved using the sc_rm_move_all() function. All pads are movable
+ * by default so this function is normally used to prevent a set of
+ * pads from moving.
+ */
+sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst,
+ sc_pad_t pad_lst, sc_bool_t movable);
+
+/*!
+ * This function gets ownership status of a pad.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pad pad to check
+ *
+ * @return Returns a boolean (SC_TRUE if caller's partition owns the pad).
+ *
+ * If \a pad is out of range then SC_FALSE is returned.
+ */
+sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad);
+
+/* @} */
+
+/*!
+ * @name Debug Functions
+ * @{
+ */
+
+/*!
+ * This function dumps the RM state for debug.
+ *
+ * @param[in] ipc IPC handle
+ */
+void sc_rm_dump(sc_ipc_t ipc);
+
+/* @} */
+
+#endif /* SCI_RM_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/include/sci/svc/timer/sci_timer_api.h b/plat/imx/common/include/sci/svc/timer/sci_timer_api.h
new file mode 100644
index 0000000..f8423ab
--- /dev/null
+++ b/plat/imx/common/include/sci/svc/timer/sci_timer_api.h
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file containing the public API for the System Controller (SC)
+ * Timer function.
+ *
+ * @addtogroup TIMER_SVC (SVC) Timer Service
+ *
+ * Module for the Timer service. This includes support for the watchdog, RTC,
+ * and system counter. Note every resource partition has a watchdog it can
+ * use.
+ *
+ * @{
+ */
+
+#ifndef SC_TIMER_API_H
+#define SC_TIMER_API_H
+
+/* Includes */
+
+#include <sci/sci_types.h>
+
+/* Defines */
+
+/*!
+ * @name Defines for type widths
+ */
+/*@{*/
+#define SC_TIMER_ACTION_W 3U /* Width of sc_timer_wdog_action_t */
+/*@}*/
+
+/*!
+ * @name Defines for sc_timer_wdog_action_t
+ */
+/*@{*/
+#define SC_TIMER_WDOG_ACTION_PARTITION 0U /* Reset partition */
+#define SC_TIMER_WDOG_ACTION_WARM 1U /* Warm reset system */
+#define SC_TIMER_WDOG_ACTION_COLD 2U /* Cold reset system */
+#define SC_TIMER_WDOG_ACTION_BOARD 3U /* Reset board */
+#define SC_TIMER_WDOG_ACTION_IRQ 4U /* Only generate IRQs */
+/*@}*/
+
+/* Types */
+
+/*!
+ * This type is used to configure the watchdog action.
+ */
+typedef uint8_t sc_timer_wdog_action_t;
+
+/*!
+ * This type is used to declare a watchdog time value in milliseconds.
+ */
+typedef uint32_t sc_timer_wdog_time_t;
+
+/* Functions */
+
+/*!
+ * @name Watchdog Functions
+ * @{
+ */
+
+/*!
+ * This function sets the watchdog timeout in milliseconds. If not
+ * set then the timeout defaults to the max. Once locked this value
+ * cannot be changed.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] timeout timeout period for the watchdog
+ *
+ * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_LOCKED
+ * = locked).
+ */
+sc_err_t sc_timer_set_wdog_timeout(sc_ipc_t ipc, sc_timer_wdog_time_t timeout);
+
+/*!
+ * This function sets the watchdog pre-timeout in milliseconds. If not
+ * set then the pre-timeout defaults to the max. Once locked this value
+ * cannot be changed.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pre_timeout pre-timeout period for the watchdog
+ *
+ * When the pre-timeout expires an IRQ will be generated. Note this timeout
+ * clears when the IRQ is triggered. An IRQ is generated for the failing
+ * partition and all of its child partitions.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_timer_set_wdog_pre_timeout(sc_ipc_t ipc,
+ sc_timer_wdog_time_t pre_timeout);
+
+/*!
+ * This function starts the watchdog.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] lock boolean indicating the lock status
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * If \a lock is set then the watchdog cannot be stopped or the timeout
+ * period changed.
+ */
+sc_err_t sc_timer_start_wdog(sc_ipc_t ipc, sc_bool_t lock);
+
+/*!
+ * This function stops the watchdog if it is not locked.
+ *
+ * @param[in] ipc IPC handle
+ *
+ * @return Returns an error code (SC_ERR_NONE = success, SC_ERR_LOCKED
+ * = locked).
+ */
+sc_err_t sc_timer_stop_wdog(sc_ipc_t ipc);
+
+/*!
+ * This function pings (services, kicks) the watchdog resetting the time
+ * before expiration back to the timeout.
+ *
+ * @param[in] ipc IPC handle
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_timer_ping_wdog(sc_ipc_t ipc);
+
+/*!
+ * This function gets the status of the watchdog. All arguments are
+ * in milliseconds.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] timeout pointer to return the timeout
+ * @param[out] max_timeout pointer to return the max timeout
+ * @param[out] remaining_time pointer to return the time remaining
+ * until trigger
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_timer_get_wdog_status(sc_ipc_t ipc,
+ sc_timer_wdog_time_t *timeout,
+ sc_timer_wdog_time_t *max_timeout,
+ sc_timer_wdog_time_t *remaining_time);
+
+/*!
+ * This function gets the status of the watchdog of a partition. All
+ * arguments are in milliseconds.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt partition to query
+ * @param[out] enb pointer to return enable status
+ * @param[out] timeout pointer to return the timeout
+ * @param[out] remaining_time pointer to return the time remaining
+ * until trigger
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_timer_pt_get_wdog_status(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_bool_t *enb,
+ sc_timer_wdog_time_t *timeout,
+ sc_timer_wdog_time_t *remaining_time);
+
+/*!
+ * This function configures the action to be taken when a watchdog
+ * expires.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] pt partition to affect
+ * @param[in] action action to take
+ *
+ * Default action is inherited from the parent.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid parameters,
+ * - SC_ERR_NOACCESS if caller's partition is not the SYSTEM owner,
+ * - SC_ERR_LOCKED if the watchdog is locked
+ */
+sc_err_t sc_timer_set_wdog_action(sc_ipc_t ipc,
+ sc_rm_pt_t pt, sc_timer_wdog_action_t action);
+
+/* @} */
+
+/*!
+ * @name Real-Time Clock (RTC) Functions
+ * @{
+ */
+
+/*!
+ * This function sets the RTC time. Only the owner of the SC_R_SYSTEM
+ * resource can set the time.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] year year (min 1970)
+ * @param[in] mon month (1-12)
+ * @param[in] day day of the month (1-31)
+ * @param[in] hour hour (0-23)
+ * @param[in] min minute (0-59)
+ * @param[in] sec second (0-59)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid time/date parameters,
+ * - SC_ERR_NOACCESS if caller's partition is not the SYSTEM owner
+ */
+sc_err_t sc_timer_set_rtc_time(sc_ipc_t ipc, uint16_t year, uint8_t mon,
+ uint8_t day, uint8_t hour, uint8_t min,
+ uint8_t sec);
+
+/*!
+ * This function gets the RTC time.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] year pointer to return year (min 1970)
+ * @param[out] mon pointer to return month (1-12)
+ * @param[out] day pointer to return day of the month (1-31)
+ * @param[out] hour pointer to return hour (0-23)
+ * @param[out] min pointer to return minute (0-59)
+ * @param[out] sec pointer to return second (0-59)
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_timer_get_rtc_time(sc_ipc_t ipc, uint16_t *year, uint8_t *mon,
+ uint8_t *day, uint8_t *hour, uint8_t *min,
+ uint8_t *sec);
+
+/*!
+ * This function gets the RTC time in seconds since 1/1/1970.
+ *
+ * @param[in] ipc IPC handle
+ * @param[out] sec pointer to return second
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_timer_get_rtc_sec1970(sc_ipc_t ipc, uint32_t *sec);
+
+/*!
+ * This function sets the RTC alarm.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] year year (min 1970)
+ * @param[in] mon month (1-12)
+ * @param[in] day day of the month (1-31)
+ * @param[in] hour hour (0-23)
+ * @param[in] min minute (0-59)
+ * @param[in] sec second (0-59)
+ *
+ * Note this alarm setting clears when the alarm is triggered.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid time/date parameters
+ */
+sc_err_t sc_timer_set_rtc_alarm(sc_ipc_t ipc, uint16_t year, uint8_t mon,
+ uint8_t day, uint8_t hour, uint8_t min,
+ uint8_t sec);
+
+/*!
+ * This function sets the RTC alarm (periodic mode).
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] sec period in seconds
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid time/date parameters
+ */
+sc_err_t sc_timer_set_rtc_periodic_alarm(sc_ipc_t ipc, uint32_t sec);
+
+/*!
+ * This function cancels the RTC alarm.
+ *
+ * @param[in] ipc IPC handle
+ *
+ * Note this alarm setting clears when the alarm is triggered.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid time/date parameters
+ */
+sc_err_t sc_timer_cancel_rtc_alarm(sc_ipc_t ipc);
+
+/*!
+ * This function sets the RTC calibration value. Only the owner of the SC_R_SYSTEM
+ * resource can set the calibration.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] count calbration count (-16 to 15)
+ *
+ * The calibration value is a 5-bit value including the sign bit, which is
+ * implemented in 2's complement. It is added or subtracted from the RTC on
+ * a perdiodic basis, once per 32768 cycles of the RTC clock.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ */
+sc_err_t sc_timer_set_rtc_calb(sc_ipc_t ipc, int8_t count);
+
+/* @} */
+
+/*!
+ * @name System Counter (SYSCTR) Functions
+ * @{
+ */
+
+/*!
+ * This function sets the SYSCTR alarm.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] ticks number of 8MHz cycles
+ *
+ * Note this alarm setting clears when the alarm is triggered.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid time/date parameters
+ */
+sc_err_t sc_timer_set_sysctr_alarm(sc_ipc_t ipc, uint64_t ticks);
+
+/*!
+ * This function sets the SYSCTR alarm (periodic mode).
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] ticks number of 8MHz cycles
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid time/date parameters
+ */
+sc_err_t sc_timer_set_sysctr_periodic_alarm(sc_ipc_t ipc, uint64_t ticks);
+
+/*!
+ * This function cancels the SYSCTR alarm.
+ *
+ * @param[in] ipc IPC handle
+ *
+ * Note this alarm setting clears when the alarm is triggered.
+ *
+ * @return Returns an error code (SC_ERR_NONE = success).
+ *
+ * Return errors:
+ * - SC_ERR_PARM if invalid time/date parameters
+ */
+sc_err_t sc_timer_cancel_sysctr_alarm(sc_ipc_t ipc);
+
+/* @} */
+
+#endif /* SC_TIMER_API_H */
+
+/**@}*/
diff --git a/plat/imx/common/lpuart_console.S b/plat/imx/common/lpuart_console.S
new file mode 100644
index 0000000..ff01e35
--- /dev/null
+++ b/plat/imx/common/lpuart_console.S
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <console_macros.S>
+#include <assert_macros.S>
+#include "imx8_lpuart.h"
+
+ .globl console_lpuart_register
+ .globl console_lpuart_init
+ .globl console_lpuart_putc
+ .globl console_lpuart_getc
+ .globl console_lpuart_flush
+
+func console_lpuart_register
+ mov x7, x30
+ mov x6, x3
+ cbz x6, register_fail
+ str x0, [x6, #CONSOLE_T_BASE]
+
+ bl console_lpuart_init
+ cbz x0, register_fail
+
+ mov x0, x6
+ mov x30, x7
+ finish_console_register lpuart putc=1, getc=1, flush=1
+
+register_fail:
+ ret x7
+endfunc console_lpuart_register
+
+func console_lpuart_init
+ mov w0, #1
+ ret
+endfunc console_lpuart_init
+
+func console_lpuart_putc
+ ldr x1, [x1, #CONSOLE_T_BASE]
+ cbz x1, putc_error
+ /* Prepare '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne 2f
+1:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #STAT]
+ tbz w2, #23, 1b
+ mov w2, #0xD
+ str w2, [x1, #DATA]
+2:
+ /* Check if the transmit FIFO is full */
+ ldr w2, [x1, #STAT]
+ tbz w2, #23, 2b
+ str w0, [x1, #DATA]
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+endfunc console_lpuart_putc
+
+func console_lpuart_getc
+ ldr x0, [x0, #CONSOLE_T_BASE]
+ cbz x0, getc_error
+ /* Check if the receive FIFO state */
+ ret
+getc_error:
+ mov w0, #-1
+ ret
+endfunc console_lpuart_getc
+
+func console_lpuart_flush
+ ret
+endfunc console_lpuart_flush
diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c
new file mode 100644
index 0000000..150e81e
--- /dev/null
+++ b/plat/imx/common/plat_imx8_gic.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/arm/arm_gicv3_common.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <plat_imx8.h>
+
+/* the GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t g01s_interrupt_props[] = {
+ INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+#if SDEI_SUPPORT
+ INTR_PROP_DESC(PLAT_SDEI_SGI_PRIVATE, PLAT_SDEI_NORMAL_PRI,
+ INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+#endif
+};
+
+static unsigned int plat_imx_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+const gicv3_driver_data_t arm_gic_data = {
+ .gicd_base = PLAT_GICD_BASE,
+ .gicr_base = PLAT_GICR_BASE,
+ .interrupt_props = g01s_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g01s_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = plat_imx_mpidr_to_core_pos,
+};
+
+void plat_gic_driver_init(void)
+{
+ /*
+ * the GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in S-EL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if IMAGE_BL31
+ gicv3_driver_init(&arm_gic_data);
+#endif
+}
+
+static __inline void plat_gicr_exit_sleep(void)
+{
+ unsigned int val = mmio_read_32(PLAT_GICR_BASE + GICR_WAKER);
+
+ /*
+ * ProcessorSleep bit can ONLY be set to zero when
+ * Quiescent bit and Sleep bit are both zero, so
+ * need to make sure Quiescent bit and Sleep bit
+ * are zero before clearing ProcessorSleep bit.
+ */
+ if (val & WAKER_QSC_BIT) {
+ mmio_write_32(PLAT_GICR_BASE + GICR_WAKER, val & ~WAKER_SL_BIT);
+ /* Wait till the WAKER_QSC_BIT changes to 0 */
+ while ((mmio_read_32(PLAT_GICR_BASE + GICR_WAKER) & WAKER_QSC_BIT) != 0U)
+ ;
+ }
+}
+
+void plat_gic_init(void)
+{
+ plat_gicr_exit_sleep();
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void plat_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void plat_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+void plat_gic_save(unsigned int proc_num, struct plat_gic_ctx *ctx)
+{
+ /* save the gic rdist/dist context */
+ for (int i = 0; i < PLATFORM_CORE_COUNT; i++)
+ gicv3_rdistif_save(i, &ctx->rdist_ctx[i]);
+ gicv3_distif_save(&ctx->dist_ctx);
+}
+
+void plat_gic_restore(unsigned int proc_num, struct plat_gic_ctx *ctx)
+{
+ /* restore the gic rdist/dist context */
+ gicv3_distif_init_restore(&ctx->dist_ctx);
+ for (int i = 0; i < PLATFORM_CORE_COUNT; i++)
+ gicv3_rdistif_init_restore(i, &ctx->rdist_ctx[i]);
+}
diff --git a/plat/imx/common/sci/imx8_mu.c b/plat/imx/common/sci/imx8_mu.c
new file mode 100644
index 0000000..66e956d
--- /dev/null
+++ b/plat/imx/common/sci/imx8_mu.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include "imx8_mu.h"
+
+void MU_Resume(uint32_t base)
+{
+ uint32_t reg, i;
+
+ reg = mmio_read_32(base + MU_ACR_OFFSET1);
+ /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+ reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1
+ | MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1);
+ mmio_write_32(base + MU_ACR_OFFSET1, reg);
+
+ /* Enable all RX interrupts */
+ for (i = 0; i < MU_RR_COUNT; i++)
+ MU_EnableRxFullInt(base, i);
+}
+
+void MU_EnableRxFullInt(uint32_t base, uint32_t index)
+{
+ uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1);
+
+ reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1);
+ reg |= MU_CR_RIE0_MASK1 >> index;
+ mmio_write_32(base + MU_ACR_OFFSET1, reg);
+}
+
+void MU_EnableGeneralInt(uint32_t base, uint32_t index)
+{
+ uint32_t reg = mmio_read_32(base + MU_ACR_OFFSET1);
+
+ reg &= ~(MU_CR_GIRn_MASK1 | MU_CR_NMI_MASK1);
+ reg |= MU_CR_GIE0_MASK1 >> index;
+ mmio_write_32(base + MU_ACR_OFFSET1, reg);
+}
+
+void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg)
+{
+ uint32_t mask = MU_SR_TE0_MASK1 >> regIndex;
+
+ /* Wait TX register to be empty. */
+ while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask))
+ ;
+ mmio_write_32(base + MU_ATR0_OFFSET1 + (regIndex * 4), msg);
+}
+
+void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg)
+{
+ uint32_t mask = MU_SR_RF0_MASK1 >> regIndex;
+
+ /* Wait RX register to be full. */
+ while (!(mmio_read_32(base + MU_ASR_OFFSET1) & mask))
+ ;
+ *msg = mmio_read_32(base + MU_ARR0_OFFSET1 + (regIndex * 4));
+}
+
+void MU_Init(uint32_t base)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(base + MU_ACR_OFFSET1);
+ /* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
+ reg &= ~(MU_CR_GIEn_MASK1 | MU_CR_RIEn_MASK1 | MU_CR_TIEn_MASK1
+ | MU_CR_GIRn_MASK1 | MU_CR_Fn_MASK1);
+ mmio_write_32(base + MU_ACR_OFFSET1, reg);
+}
diff --git a/plat/imx/common/sci/imx8_mu.h b/plat/imx/common/sci/imx8_mu.h
new file mode 100644
index 0000000..7885219
--- /dev/null
+++ b/plat/imx/common/sci/imx8_mu.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#define MU_ATR0_OFFSET1 0x0
+#define MU_ARR0_OFFSET1 0x10
+#define MU_ASR_OFFSET1 0x20
+#define MU_ACR_OFFSET1 0x24
+#define MU_TR_COUNT1 4
+#define MU_RR_COUNT1 4
+
+#define MU_CR_GIEn_MASK1 (0xFu << 28)
+#define MU_CR_RIEn_MASK1 (0xF << 24)
+#define MU_CR_TIEn_MASK1 (0xF << 20)
+#define MU_CR_GIRn_MASK1 (0xF << 16)
+#define MU_CR_NMI_MASK1 (1 << 3)
+#define MU_CR_Fn_MASK1 0x7
+
+#define MU_SR_TE0_MASK1 (1 << 23)
+#define MU_SR_RF0_MASK1 (1 << 27)
+#define MU_CR_RIE0_MASK1 (1 << 27)
+#define MU_CR_GIE0_MASK1 (1U << 31)
+
+#define MU_TR_COUNT 4
+#define MU_RR_COUNT 4
+
+void MU_Init(uint32_t base);
+void MU_SendMessage(uint32_t base, uint32_t regIndex, uint32_t msg);
+void MU_ReceiveMsg(uint32_t base, uint32_t regIndex, uint32_t *msg);
+void MU_EnableGeneralInt(uint32_t base, uint32_t index);
+void MU_EnableRxFullInt(uint32_t base, uint32_t index);
+void MU_Resume(uint32_t base);
diff --git a/plat/imx/common/sci/ipc.c b/plat/imx/common/sci/ipc.c
new file mode 100644
index 0000000..5769119
--- /dev/null
+++ b/plat/imx/common/sci/ipc.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+#include <lib/bakery_lock.h>
+
+#include <sci/sci_scfw.h>
+#include <sci/sci_ipc.h>
+#include <sci/sci_rpc.h>
+#include "imx8_mu.h"
+
+sc_ipc_t ipc_handle;
+
+DEFINE_BAKERY_LOCK(sc_ipc_bakery_lock);
+#define sc_ipc_lock_init() bakery_lock_init(&sc_ipc_bakery_lock)
+#define sc_ipc_lock() bakery_lock_get(&sc_ipc_bakery_lock)
+#define sc_ipc_unlock() bakery_lock_release(&sc_ipc_bakery_lock)
+
+void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp)
+{
+ sc_ipc_lock();
+
+ sc_ipc_write(ipc, msg);
+ if (!no_resp)
+ sc_ipc_read(ipc, msg);
+
+ sc_ipc_unlock();
+}
+
+sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id)
+{
+ uint32_t base = id;
+ uint32_t i;
+
+ /* Get MU base associated with IPC channel */
+ if ((ipc == NULL) || (base == 0))
+ return SC_ERR_IPC;
+
+ sc_ipc_lock_init();
+
+ /* Init MU */
+ MU_Init(base);
+
+ /* Enable all RX interrupts */
+ for (i = 0; i < MU_RR_COUNT; i++) {
+ MU_EnableRxFullInt(base, i);
+ }
+
+ /* Return MU address as handle */
+ *ipc = (sc_ipc_t) id;
+
+ return SC_ERR_NONE;
+}
+
+void sc_ipc_close(sc_ipc_t ipc)
+{
+ uint32_t base = ipc;
+
+ if (base != 0)
+ MU_Init(base);
+}
+
+void sc_ipc_read(sc_ipc_t ipc, void *data)
+{
+ uint32_t base = ipc;
+ sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data;
+ uint8_t count = 0;
+
+ /* Check parms */
+ if ((base == 0) || (msg == NULL))
+ return;
+
+ /* Read first word */
+ MU_ReceiveMsg(base, 0, (uint32_t *) msg);
+ count++;
+
+ /* Check size */
+ if (msg->size > SC_RPC_MAX_MSG) {
+ *((uint32_t *) msg) = 0;
+ return;
+ }
+
+ /* Read remaining words */
+ while (count < msg->size) {
+ MU_ReceiveMsg(base, count % MU_RR_COUNT,
+ &(msg->DATA.u32[count - 1]));
+ count++;
+ }
+}
+
+void sc_ipc_write(sc_ipc_t ipc, void *data)
+{
+ sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data;
+ uint32_t base = ipc;
+ uint8_t count = 0;
+
+ /* Check parms */
+ if ((base == 0) || (msg == NULL))
+ return;
+
+ /* Check size */
+ if (msg->size > SC_RPC_MAX_MSG)
+ return;
+
+ /* Write first word */
+ MU_SendMessage(base, 0, *((uint32_t *) msg));
+ count++;
+
+ /* Write remaining words */
+ while (count < msg->size) {
+ MU_SendMessage(base, count % MU_TR_COUNT,
+ msg->DATA.u32[count - 1]);
+ count++;
+ }
+}
+
diff --git a/plat/imx/common/sci/sci_api.mk b/plat/imx/common/sci/sci_api.mk
new file mode 100644
index 0000000..92c7190
--- /dev/null
+++ b/plat/imx/common/sci/sci_api.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL31_SOURCES += plat/imx/common/sci/ipc.c \
+ plat/imx/common/sci/imx8_mu.c \
+ plat/imx/common/sci/svc/pad/pad_rpc_clnt.c \
+ plat/imx/common/sci/svc/pm/pm_rpc_clnt.c \
+ plat/imx/common/sci/svc/rm/rm_rpc_clnt.c \
+ plat/imx/common/sci/svc/timer/timer_rpc_clnt.c \
+ plat/imx/common/sci/svc/misc/misc_rpc_clnt.c
diff --git a/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c b/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c
new file mode 100644
index 0000000..080de6a
--- /dev/null
+++ b/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the MISC service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup MISC_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/svc/misc/sci_misc_api.h>
+#include <sci/sci_rpc.h>
+#include <stdlib.h>
+#include "sci_misc_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_misc_set_control(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_ctrl_t ctrl, uint32_t val)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_CONTROL;
+ RPC_U32(&msg, 0U) = (uint32_t)ctrl;
+ RPC_U32(&msg, 4U) = (uint32_t)val;
+ RPC_U16(&msg, 8U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 4U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_get_control(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_ctrl_t ctrl, uint32_t *val)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_CONTROL;
+ RPC_U32(&msg, 0U) = (uint32_t)ctrl;
+ RPC_U16(&msg, 4U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (val != NULL)
+ *val = RPC_U32(&msg, 0U);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_set_max_dma_group(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_misc_dma_group_t max)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_MAX_DMA_GROUP;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)max;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_set_dma_group(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_misc_dma_group_t group)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_DMA_GROUP;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)group;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_seco_image_load(sc_ipc_t ipc, sc_faddr_t addr_src,
+ sc_faddr_t addr_dst, uint32_t len,
+ sc_bool_t fw)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_IMAGE_LOAD;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr_src >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr_src;
+ RPC_U32(&msg, 8U) = (uint32_t)(addr_dst >> 32U);
+ RPC_U32(&msg, 12U) = (uint32_t)addr_dst;
+ RPC_U32(&msg, 16U) = (uint32_t)len;
+ RPC_U8(&msg, 20U) = (uint8_t)fw;
+ RPC_SIZE(&msg) = 7U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_seco_authenticate(sc_ipc_t ipc,
+ sc_misc_seco_auth_cmd_t cmd, sc_faddr_t addr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_AUTHENTICATE;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr;
+ RPC_U8(&msg, 8U) = (uint8_t)cmd;
+ RPC_SIZE(&msg) = 4U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_seco_fuse_write(sc_ipc_t ipc, sc_faddr_t addr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_FUSE_WRITE;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_seco_enable_debug(sc_ipc_t ipc, sc_faddr_t addr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_ENABLE_DEBUG;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_seco_forward_lifecycle(sc_ipc_t ipc, uint32_t lifecycle)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_FORWARD_LIFECYCLE;
+ RPC_U32(&msg, 0U) = (uint32_t)lifecycle;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_seco_return_lifecycle(sc_ipc_t ipc, sc_faddr_t addr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_RETURN_LIFECYCLE;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+void sc_misc_seco_build_info(sc_ipc_t ipc, uint32_t *version, uint32_t *commit)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_BUILD_INFO;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (version != NULL)
+ *version = RPC_U32(&msg, 0U);
+
+ if (commit != NULL)
+ *commit = RPC_U32(&msg, 4U);
+}
+
+sc_err_t sc_misc_seco_chip_info(sc_ipc_t ipc, uint16_t *lc,
+ uint16_t *monotonic, uint32_t *uid_l,
+ uint32_t *uid_h)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SECO_CHIP_INFO;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (uid_l != NULL)
+ *uid_l = RPC_U32(&msg, 0U);
+
+ if (uid_h != NULL)
+ *uid_h = RPC_U32(&msg, 4U);
+
+ if (lc != NULL)
+ *lc = RPC_U16(&msg, 8U);
+
+ if (monotonic != NULL)
+ *monotonic = RPC_U16(&msg, 10U);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+void sc_misc_debug_out(sc_ipc_t ipc, uint8_t ch)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_DEBUG_OUT;
+ RPC_U8(&msg, 0U) = (uint8_t)ch;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+}
+
+sc_err_t sc_misc_waveform_capture(sc_ipc_t ipc, sc_bool_t enable)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_WAVEFORM_CAPTURE;
+ RPC_U8(&msg, 0U) = (uint8_t)enable;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+void sc_misc_build_info(sc_ipc_t ipc, uint32_t *build, uint32_t *commit)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_BUILD_INFO;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (build != NULL)
+ *build = RPC_U32(&msg, 0U);
+
+ if (commit != NULL)
+ *commit = RPC_U32(&msg, 4U);
+}
+
+void sc_misc_unique_id(sc_ipc_t ipc, uint32_t *id_l, uint32_t *id_h)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_UNIQUE_ID;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (id_l != NULL)
+ *id_l = RPC_U32(&msg, 0U);
+
+ if (id_h != NULL)
+ *id_h = RPC_U32(&msg, 4U);
+}
+
+sc_err_t sc_misc_set_ari(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rsrc_t resource_mst, uint16_t ari, sc_bool_t enable)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_ARI;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U16(&msg, 2U) = (uint16_t)resource_mst;
+ RPC_U16(&msg, 4U) = (uint16_t)ari;
+ RPC_U8(&msg, 6U) = (uint8_t)enable;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+void sc_misc_boot_status(sc_ipc_t ipc, sc_misc_boot_status_t status)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_BOOT_STATUS;
+ RPC_U8(&msg, 0U) = (uint8_t)status;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_TRUE);
+}
+
+sc_err_t sc_misc_boot_done(sc_ipc_t ipc, sc_rsrc_t cpu)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_BOOT_DONE;
+ RPC_U16(&msg, 0U) = (uint16_t)cpu;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_otp_fuse_read(sc_ipc_t ipc, uint32_t word, uint32_t *val)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_OTP_FUSE_READ;
+ RPC_U32(&msg, 0U) = (uint32_t)word;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (val != NULL)
+ *val = RPC_U32(&msg, 0U);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_otp_fuse_write(sc_ipc_t ipc, uint32_t word, uint32_t val)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_OTP_FUSE_WRITE;
+ RPC_U32(&msg, 0U) = (uint32_t)word;
+ RPC_U32(&msg, 4U) = (uint32_t)val;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_set_temp(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_misc_temp_t temp, int16_t celsius, int8_t tenths)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_SET_TEMP;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_I16(&msg, 2U) = (int16_t) celsius;
+ RPC_U8(&msg, 4U) = (uint8_t)temp;
+ RPC_I8(&msg, 5U) = (int8_t) tenths;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_misc_get_temp(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_misc_temp_t temp, int16_t *celsius,
+ int8_t *tenths)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_TEMP;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)temp;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (celsius != NULL)
+ *celsius = RPC_I16(&msg, 0U);
+
+ result = RPC_R8(&msg);
+ if (tenths != NULL)
+ *tenths = RPC_I8(&msg, 2U);
+
+ return (sc_err_t)result;
+}
+
+void sc_misc_get_boot_dev(sc_ipc_t ipc, sc_rsrc_t *dev)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_BOOT_DEV;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (dev != NULL)
+ *dev = RPC_U16(&msg, 0U);
+}
+
+void sc_misc_get_button_status(sc_ipc_t ipc, sc_bool_t *status)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_MISC;
+ RPC_FUNC(&msg) = (uint8_t)MISC_FUNC_GET_BUTTON_STATUS;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (status != NULL)
+ *status = RPC_U8(&msg, 0U);
+}
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/misc/sci_misc_rpc.h b/plat/imx/common/sci/svc/misc/sci_misc_rpc.h
new file mode 100644
index 0000000..03b1a51
--- /dev/null
+++ b/plat/imx/common/sci/svc/misc/sci_misc_rpc.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the MISC RPC implementation.
+ *
+ * @addtogroup MISC_SVC
+ * @{
+ */
+
+#ifndef SC_MISC_RPC_H
+#define SC_MISC_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC MISC function calls
+ */
+/*@{*/
+#define MISC_FUNC_UNKNOWN 0 /* Unknown function */
+#define MISC_FUNC_SET_CONTROL 1U /* Index for misc_set_control() RPC call */
+#define MISC_FUNC_GET_CONTROL 2U /* Index for misc_get_control() RPC call */
+#define MISC_FUNC_SET_MAX_DMA_GROUP 4U /* Index for misc_set_max_dma_group() RPC call */
+#define MISC_FUNC_SET_DMA_GROUP 5U /* Index for misc_set_dma_group() RPC call */
+#define MISC_FUNC_SECO_IMAGE_LOAD 8U /* Index for misc_seco_image_load() RPC call */
+#define MISC_FUNC_SECO_AUTHENTICATE 9U /* Index for misc_seco_authenticate() RPC call */
+#define MISC_FUNC_SECO_FUSE_WRITE 20U /* Index for misc_seco_fuse_write() RPC call */
+#define MISC_FUNC_SECO_ENABLE_DEBUG 21U /* Index for misc_seco_enable_debug() RPC call */
+#define MISC_FUNC_SECO_FORWARD_LIFECYCLE 22U /* Index for misc_seco_forward_lifecycle() RPC call */
+#define MISC_FUNC_SECO_RETURN_LIFECYCLE 23U /* Index for misc_seco_return_lifecycle() RPC call */
+#define MISC_FUNC_SECO_BUILD_INFO 24U /* Index for misc_seco_build_info() RPC call */
+#define MISC_FUNC_SECO_CHIP_INFO 25U /* Index for misc_seco_chip_info() RPC call */
+#define MISC_FUNC_DEBUG_OUT 10U /* Index for misc_debug_out() RPC call */
+#define MISC_FUNC_WAVEFORM_CAPTURE 6U /* Index for misc_waveform_capture() RPC call */
+#define MISC_FUNC_BUILD_INFO 15U /* Index for misc_build_info() RPC call */
+#define MISC_FUNC_UNIQUE_ID 19U /* Index for misc_unique_id() RPC call */
+#define MISC_FUNC_SET_ARI 3U /* Index for misc_set_ari() RPC call */
+#define MISC_FUNC_BOOT_STATUS 7U /* Index for misc_boot_status() RPC call */
+#define MISC_FUNC_BOOT_DONE 14U /* Index for misc_boot_done() RPC call */
+#define MISC_FUNC_OTP_FUSE_READ 11U /* Index for misc_otp_fuse_read() RPC call */
+#define MISC_FUNC_OTP_FUSE_WRITE 17U /* Index for misc_otp_fuse_write() RPC call */
+#define MISC_FUNC_SET_TEMP 12U /* Index for misc_set_temp() RPC call */
+#define MISC_FUNC_GET_TEMP 13U /* Index for misc_get_temp() RPC call */
+#define MISC_FUNC_GET_BOOT_DEV 16U /* Index for misc_get_boot_dev() RPC call */
+#define MISC_FUNC_GET_BUTTON_STATUS 18U /* Index for misc_get_button_status() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming MISC RPC request.
+ *
+ * @param[in] caller_pt caller partition
+ * @param[in] msg pointer to RPC message
+ */
+void misc_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an MISC RPC request.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] msg pointer to RPC message
+ */
+void misc_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif /* SC_MISC_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c b/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c
new file mode 100644
index 0000000..319d469
--- /dev/null
+++ b/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the PAD service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup PAD_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <stdlib.h>
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/svc/pad/sci_pad_api.h>
+#include <sci/sci_rpc.h>
+#include "sci_pad_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_pad_set_mux(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t mux, sc_pad_config_t config, sc_pad_iso_t iso)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_MUX;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_U8(&msg, 2U) = (uint8_t)mux;
+ RPC_U8(&msg, 3U) = (uint8_t)config;
+ RPC_U8(&msg, 4U) = (uint8_t)iso;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_mux(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t *mux, sc_pad_config_t *config,
+ sc_pad_iso_t *iso)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_MUX;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (mux != NULL) {
+ *mux = RPC_U8(&msg, 0U);
+ }
+
+ if (config != NULL) {
+ *config = RPC_U8(&msg, 1U);
+ }
+
+ if (iso != NULL) {
+ *iso = RPC_U8(&msg, 2U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t ctrl)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP;
+ RPC_U32(&msg, 0U) = (uint32_t)ctrl;
+ RPC_U16(&msg, 4U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp(sc_ipc_t ipc, sc_pad_t pad, uint32_t *ctrl)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (ctrl != NULL) {
+ *ctrl = RPC_U32(&msg, 0U);
+ }
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t wakeup)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_WAKEUP;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_U8(&msg, 2U) = (uint8_t)wakeup;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_wakeup(sc_ipc_t ipc, sc_pad_t pad, sc_pad_wakeup_t *wakeup)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_WAKEUP;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (wakeup != NULL) {
+ *wakeup = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t mux,
+ sc_pad_config_t config, sc_pad_iso_t iso, uint32_t ctrl,
+ sc_pad_wakeup_t wakeup)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_ALL;
+ RPC_U32(&msg, 0U) = (uint32_t)ctrl;
+ RPC_U16(&msg, 4U) = (uint16_t)pad;
+ RPC_U8(&msg, 6U) = (uint8_t)mux;
+ RPC_U8(&msg, 7U) = (uint8_t)config;
+ RPC_U8(&msg, 8U) = (uint8_t)iso;
+ RPC_U8(&msg, 9U) = (uint8_t)wakeup;
+ RPC_SIZE(&msg) = 4U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_all(sc_ipc_t ipc, sc_pad_t pad, uint8_t *mux,
+ sc_pad_config_t *config, sc_pad_iso_t *iso,
+ uint32_t *ctrl, sc_pad_wakeup_t *wakeup)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_ALL;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (ctrl != NULL) {
+ *ctrl = RPC_U32(&msg, 0U);
+ }
+
+ result = RPC_R8(&msg);
+ if (mux != NULL) {
+ *mux = RPC_U8(&msg, 4U);
+ }
+
+ if (config != NULL) {
+ *config = RPC_U8(&msg, 5U);
+ }
+
+ if (iso != NULL) {
+ *iso = RPC_U8(&msg, 6U);
+ }
+
+ if (wakeup != NULL) {
+ *wakeup = RPC_U8(&msg, 7U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set(sc_ipc_t ipc, sc_pad_t pad, uint32_t val)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET;
+ RPC_U32(&msg, 0U) = (uint32_t)val;
+ RPC_U16(&msg, 4U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get(sc_ipc_t ipc, sc_pad_t pad, uint32_t *val)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (val != NULL) {
+ *val = RPC_U32(&msg, 0U);
+ }
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t dse, sc_pad_28fdsoi_ps_t ps)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_U8(&msg, 2U) = (uint8_t)dse;
+ RPC_U8(&msg, 3U) = (uint8_t)ps;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp_28fdsoi(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t *dse,
+ sc_pad_28fdsoi_ps_t *ps)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (dse != NULL) {
+ *dse = RPC_U8(&msg, 0U);
+ }
+
+ if (ps != NULL) {
+ *ps = RPC_U8(&msg, 1U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t dse, sc_bool_t hys,
+ sc_pad_28fdsoi_pus_t pus, sc_bool_t pke,
+ sc_bool_t pue)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_HSIC;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_U8(&msg, 2U) = (uint8_t)dse;
+ RPC_U8(&msg, 3U) = (uint8_t)pus;
+ RPC_U8(&msg, 4U) = (uint8_t)hys;
+ RPC_U8(&msg, 5U) = (uint8_t)pke;
+ RPC_U8(&msg, 6U) = (uint8_t)pue;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp_28fdsoi_hsic(sc_ipc_t ipc, sc_pad_t pad,
+ sc_pad_28fdsoi_dse_t *dse, sc_bool_t *hys,
+ sc_pad_28fdsoi_pus_t *pus, sc_bool_t *pke,
+ sc_bool_t *pue)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_HSIC;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (dse != NULL) {
+ *dse = RPC_U8(&msg, 0U);
+ }
+
+ if (pus != NULL) {
+ *pus = RPC_U8(&msg, 1U);
+ }
+
+ if (hys != NULL) {
+ *hys = RPC_U8(&msg, 2U);
+ }
+
+ if (pke != NULL) {
+ *pke = RPC_U8(&msg, 3U);
+ }
+
+ if (pue != NULL) {
+ *pue = RPC_U8(&msg, 4U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_set_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t compen, sc_bool_t fastfrz,
+ uint8_t rasrcp, uint8_t rasrcn,
+ sc_bool_t nasrc_sel, sc_bool_t psw_ovr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_SET_GP_28FDSOI_COMP;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_U8(&msg, 2U) = (uint8_t)compen;
+ RPC_U8(&msg, 3U) = (uint8_t)rasrcp;
+ RPC_U8(&msg, 4U) = (uint8_t)rasrcn;
+ RPC_U8(&msg, 5U) = (uint8_t)fastfrz;
+ RPC_U8(&msg, 6U) = (uint8_t)nasrc_sel;
+ RPC_U8(&msg, 7U) = (uint8_t)psw_ovr;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pad_get_gp_28fdsoi_comp(sc_ipc_t ipc, sc_pad_t pad,
+ uint8_t *compen, sc_bool_t *fastfrz,
+ uint8_t *rasrcp, uint8_t *rasrcn,
+ sc_bool_t *nasrc_sel, sc_bool_t *compok,
+ uint8_t *nasrc, sc_bool_t *psw_ovr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PAD;
+ RPC_FUNC(&msg) = (uint8_t)PAD_FUNC_GET_GP_28FDSOI_COMP;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (compen != NULL) {
+ *compen = RPC_U8(&msg, 0U);
+ }
+
+ if (rasrcp != NULL) {
+ *rasrcp = RPC_U8(&msg, 1U);
+ }
+
+ if (rasrcn != NULL) {
+ *rasrcn = RPC_U8(&msg, 2U);
+ }
+
+ if (nasrc != NULL) {
+ *nasrc = RPC_U8(&msg, 3U);
+ }
+
+ if (fastfrz != NULL) {
+ *fastfrz = RPC_U8(&msg, 4U);
+ }
+
+ if (nasrc_sel != NULL) {
+ *nasrc_sel = RPC_U8(&msg, 5U);
+ }
+
+ if (compok != NULL) {
+ *compok = RPC_U8(&msg, 6U);
+ }
+
+ if (psw_ovr != NULL) {
+ *psw_ovr = RPC_U8(&msg, 7U);
+ }
+
+ return (sc_err_t)result;
+}
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/pad/sci_pad_rpc.h b/plat/imx/common/sci/svc/pad/sci_pad_rpc.h
new file mode 100644
index 0000000..8e9c4bb
--- /dev/null
+++ b/plat/imx/common/sci/svc/pad/sci_pad_rpc.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the PAD RPC implementation.
+ *
+ * @addtogroup PAD_SVC
+ * @{
+ */
+
+#ifndef SCI_PAD_RPC_H
+#define SCI_PAD_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC PAD function calls
+ */
+/*@{*/
+#define PAD_FUNC_UNKNOWN 0 /* Unknown function */
+#define PAD_FUNC_SET_MUX 1U /* Index for pad_set_mux() RPC call */
+#define PAD_FUNC_GET_MUX 6U /* Index for pad_get_mux() RPC call */
+#define PAD_FUNC_SET_GP 2U /* Index for pad_set_gp() RPC call */
+#define PAD_FUNC_GET_GP 7U /* Index for pad_get_gp() RPC call */
+#define PAD_FUNC_SET_WAKEUP 4U /* Index for pad_set_wakeup() RPC call */
+#define PAD_FUNC_GET_WAKEUP 9U /* Index for pad_get_wakeup() RPC call */
+#define PAD_FUNC_SET_ALL 5U /* Index for pad_set_all() RPC call */
+#define PAD_FUNC_GET_ALL 10U /* Index for pad_get_all() RPC call */
+#define PAD_FUNC_SET 15U /* Index for pad_set() RPC call */
+#define PAD_FUNC_GET 16U /* Index for pad_get() RPC call */
+#define PAD_FUNC_SET_GP_28FDSOI 11U /* Index for pad_set_gp_28fdsoi() RPC call */
+#define PAD_FUNC_GET_GP_28FDSOI 12U /* Index for pad_get_gp_28fdsoi() RPC call */
+#define PAD_FUNC_SET_GP_28FDSOI_HSIC 3U /* Index for pad_set_gp_28fdsoi_hsic() RPC call */
+#define PAD_FUNC_GET_GP_28FDSOI_HSIC 8U /* Index for pad_get_gp_28fdsoi_hsic() RPC call */
+#define PAD_FUNC_SET_GP_28FDSOI_COMP 13U /* Index for pad_set_gp_28fdsoi_comp() RPC call */
+#define PAD_FUNC_GET_GP_28FDSOI_COMP 14U /* Index for pad_get_gp_28fdsoi_comp() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming PAD RPC request.
+ *
+ * @param[in] caller_pt caller partition
+ * @param[in] msg pointer to RPC message
+ */
+void pad_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an PAD RPC request.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] msg pointer to RPC message
+ */
+void pad_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif /* SCI_PAD_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c b/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c
new file mode 100644
index 0000000..66a57a1
--- /dev/null
+++ b/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the PM service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup PM_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <stdlib.h>
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/svc/pm/sci_pm_api.h>
+#include <sci/sci_rpc.h>
+
+#include "sci_pm_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_pm_set_sys_power_mode(sc_ipc_t ipc, sc_pm_power_mode_t mode)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_SYS_POWER_MODE;
+ RPC_U8(&msg, 0U) = (uint8_t)mode;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_partition_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_pm_power_mode_t mode)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_PARTITION_POWER_MODE;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)mode;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_sys_power_mode(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_pm_power_mode_t *mode)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_SYS_POWER_MODE;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (mode != NULL) {
+ *mode = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t mode)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_RESOURCE_POWER_MODE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)mode;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_resource_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t *mode)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_RESOURCE_POWER_MODE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (mode != NULL) {
+ *mode = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_req_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t mode)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_LOW_POWER_MODE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)mode;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_req_cpu_low_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_power_mode_t mode,
+ sc_pm_wake_src_t wake_src)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_CPU_LOW_POWER_MODE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)mode;
+ RPC_U8(&msg, 3U) = (uint8_t)wake_src;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_cpu_resume_addr(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_faddr_t address)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME_ADDR;
+ RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)address;
+ RPC_U16(&msg, 8U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 4U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_cpu_resume(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_bool_t isPrimary, sc_faddr_t address)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CPU_RESUME;
+ RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)address;
+ RPC_U16(&msg, 8U) = (uint16_t)resource;
+ RPC_U8(&msg, 10U) = (uint8_t)isPrimary;
+ RPC_SIZE(&msg) = 4U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_req_sys_if_power_mode(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_sys_if_t sys_if,
+ sc_pm_power_mode_t hpm,
+ sc_pm_power_mode_t lpm)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REQ_SYS_IF_POWER_MODE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)sys_if;
+ RPC_U8(&msg, 3U) = (uint8_t)hpm;
+ RPC_U8(&msg, 4U) = (uint8_t)lpm;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clock_rate_t *rate)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_RATE;
+ RPC_U32(&msg, 0U) = *(uint32_t *)rate;
+ RPC_U16(&msg, 4U) = (uint16_t)resource;
+ RPC_U8(&msg, 6U) = (uint8_t)clk;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ *rate = RPC_U32(&msg, 0U);
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_clock_rate(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clock_rate_t *rate)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_RATE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)clk;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (rate != NULL) {
+ *rate = RPC_U32(&msg, 0U);
+ }
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_clock_enable(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_bool_t enable, sc_bool_t autog)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CLOCK_ENABLE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)clk;
+ RPC_U8(&msg, 3U) = (uint8_t)enable;
+ RPC_U8(&msg, 4U) = (uint8_t)autog;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_set_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clk_parent_t parent)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_SET_CLOCK_PARENT;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)clk;
+ RPC_U8(&msg, 3U) = (uint8_t)parent;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_get_clock_parent(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_pm_clk_t clk, sc_pm_clk_parent_t *parent)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_GET_CLOCK_PARENT;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)clk;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (parent != NULL) {
+ *parent = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_reset(sc_ipc_t ipc, sc_pm_reset_type_t type)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET;
+ RPC_U8(&msg, 0U) = (uint8_t)type;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_reset_reason(sc_ipc_t ipc, sc_pm_reset_reason_t *reason)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_RESET_REASON;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (reason != NULL) {
+ *reason = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_boot(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_rsrc_t resource_cpu, sc_faddr_t boot_addr,
+ sc_rsrc_t resource_mu, sc_rsrc_t resource_dev)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_BOOT;
+ RPC_U32(&msg, 0U) = (uint32_t)(boot_addr >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)boot_addr;
+ RPC_U16(&msg, 8U) = (uint16_t)resource_cpu;
+ RPC_U16(&msg, 10U) = (uint16_t)resource_mu;
+ RPC_U16(&msg, 12U) = (uint16_t)resource_dev;
+ RPC_U8(&msg, 14U) = (uint8_t)pt;
+ RPC_SIZE(&msg) = 5U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+void sc_pm_reboot(sc_ipc_t ipc, sc_pm_reset_type_t type)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT;
+ RPC_U8(&msg, 0U) = (uint8_t)type;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_TRUE);
+
+ return;
+}
+
+sc_err_t sc_pm_reboot_partition(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_pm_reset_type_t type)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_REBOOT_PARTITION;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)type;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_pm_cpu_start(sc_ipc_t ipc, sc_rsrc_t resource, sc_bool_t enable,
+ sc_faddr_t address)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_PM;
+ RPC_FUNC(&msg) = (uint8_t)PM_FUNC_CPU_START;
+ RPC_U32(&msg, 0U) = (uint32_t)(address >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)address;
+ RPC_U16(&msg, 8U) = (uint16_t)resource;
+ RPC_U8(&msg, 10U) = (uint8_t)enable;
+ RPC_SIZE(&msg) = 4U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/pm/sci_pm_rpc.h b/plat/imx/common/sci/svc/pm/sci_pm_rpc.h
new file mode 100644
index 0000000..8bad3c7
--- /dev/null
+++ b/plat/imx/common/sci/svc/pm/sci_pm_rpc.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the PM RPC implementation.
+ *
+ * @addtogroup PM_SVC
+ * @{
+ */
+
+#ifndef SCI_PM_RPC_H
+#define SCI_PM_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC PM function calls
+ */
+/*@{*/
+#define PM_FUNC_UNKNOWN 0 /* Unknown function */
+#define PM_FUNC_SET_SYS_POWER_MODE 19U /* Index for pm_set_sys_power_mode() RPC call */
+#define PM_FUNC_SET_PARTITION_POWER_MODE 1U /* Index for pm_set_partition_power_mode() RPC call */
+#define PM_FUNC_GET_SYS_POWER_MODE 2U /* Index for pm_get_sys_power_mode() RPC call */
+#define PM_FUNC_SET_RESOURCE_POWER_MODE 3U /* Index for pm_set_resource_power_mode() RPC call */
+#define PM_FUNC_GET_RESOURCE_POWER_MODE 4U /* Index for pm_get_resource_power_mode() RPC call */
+#define PM_FUNC_REQ_LOW_POWER_MODE 16U /* Index for pm_req_low_power_mode() RPC call */
+#define PM_FUNC_REQ_CPU_LOW_POWER_MODE 20U /* Index for pm_req_cpu_low_power_mode() RPC call */
+#define PM_FUNC_SET_CPU_RESUME_ADDR 17U /* Index for pm_set_cpu_resume_addr() RPC call */
+#define PM_FUNC_SET_CPU_RESUME 21U /* Index for pm_set_cpu_resume() RPC call */
+#define PM_FUNC_REQ_SYS_IF_POWER_MODE 18U /* Index for pm_req_sys_if_power_mode() RPC call */
+#define PM_FUNC_SET_CLOCK_RATE 5U /* Index for pm_set_clock_rate() RPC call */
+#define PM_FUNC_GET_CLOCK_RATE 6U /* Index for pm_get_clock_rate() RPC call */
+#define PM_FUNC_CLOCK_ENABLE 7U /* Index for pm_clock_enable() RPC call */
+#define PM_FUNC_SET_CLOCK_PARENT 14U /* Index for pm_set_clock_parent() RPC call */
+#define PM_FUNC_GET_CLOCK_PARENT 15U /* Index for pm_get_clock_parent() RPC call */
+#define PM_FUNC_RESET 13U /* Index for pm_reset() RPC call */
+#define PM_FUNC_RESET_REASON 10U /* Index for pm_reset_reason() RPC call */
+#define PM_FUNC_BOOT 8U /* Index for pm_boot() RPC call */
+#define PM_FUNC_REBOOT 9U /* Index for pm_reboot() RPC call */
+#define PM_FUNC_REBOOT_PARTITION 12U /* Index for pm_reboot_partition() RPC call */
+#define PM_FUNC_CPU_START 11U /* Index for pm_cpu_start() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming PM RPC request.
+ *
+ * @param[in] caller_pt caller partition
+ * @param[in] msg pointer to RPC message
+ */
+void pm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an PM RPC request.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] msg pointer to RPC message
+ */
+void pm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif /* SCI_PM_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c b/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c
new file mode 100644
index 0000000..16771a5
--- /dev/null
+++ b/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the RM service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup RM_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <stdlib.h>
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/sci_rpc.h>
+
+#include "sci_rm_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_rm_partition_alloc(sc_ipc_t ipc, sc_rm_pt_t *pt, sc_bool_t secure,
+ sc_bool_t isolated, sc_bool_t restricted,
+ sc_bool_t grant, sc_bool_t coherent)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_ALLOC;
+ RPC_U8(&msg, 0U) = (uint8_t)secure;
+ RPC_U8(&msg, 1U) = (uint8_t)isolated;
+ RPC_U8(&msg, 2U) = (uint8_t)restricted;
+ RPC_U8(&msg, 3U) = (uint8_t)grant;
+ RPC_U8(&msg, 4U) = (uint8_t)coherent;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (pt != NULL) {
+ *pt = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_confidential(sc_ipc_t ipc, sc_rm_pt_t pt, sc_bool_t retro)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_CONFIDENTIAL;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)retro;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_partition_free(sc_ipc_t ipc, sc_rm_pt_t pt)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_FREE;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_rm_did_t sc_rm_get_did(sc_ipc_t ipc)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_DID;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_rm_did_t) result;
+}
+
+sc_err_t sc_rm_partition_static(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_did_t did)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_STATIC;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)did;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_partition_lock(sc_ipc_t ipc, sc_rm_pt_t pt)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_PARTITION_LOCK;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_get_partition(sc_ipc_t ipc, sc_rm_pt_t *pt)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_PARTITION;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (pt != NULL) {
+ *pt = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_parent(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_pt_t pt_parent)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PARENT;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)pt_parent;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_move_all(sc_ipc_t ipc, sc_rm_pt_t pt_src, sc_rm_pt_t pt_dst,
+ sc_bool_t move_rsrc, sc_bool_t move_pads)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MOVE_ALL;
+ RPC_U8(&msg, 0U) = (uint8_t)pt_src;
+ RPC_U8(&msg, 1U) = (uint8_t)pt_dst;
+ RPC_U8(&msg, 2U) = (uint8_t)move_rsrc;
+ RPC_U8(&msg, 3U) = (uint8_t)move_pads;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_assign_resource(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rsrc_t resource)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_RESOURCE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)pt;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_resource_movable(sc_ipc_t ipc, sc_rsrc_t resource_fst,
+ sc_rsrc_t resource_lst, sc_bool_t movable)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_RESOURCE_MOVABLE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource_fst;
+ RPC_U16(&msg, 2U) = (uint16_t)resource_lst;
+ RPC_U8(&msg, 4U) = (uint8_t)movable;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_subsys_rsrc_movable(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_bool_t movable)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_SUBSYS_RSRC_MOVABLE;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)movable;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_master_attributes(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rm_spa_t sa, sc_rm_spa_t pa,
+ sc_bool_t smmu_bypass)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_ATTRIBUTES;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)sa;
+ RPC_U8(&msg, 3U) = (uint8_t)pa;
+ RPC_U8(&msg, 4U) = (uint8_t)smmu_bypass;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_master_sid(sc_ipc_t ipc, sc_rsrc_t resource, sc_rm_sid_t sid)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MASTER_SID;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U16(&msg, 2U) = (uint16_t)sid;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_peripheral_permissions(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rm_pt_t pt, sc_rm_perm_t perm)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PERIPHERAL_PERMISSIONS;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_U8(&msg, 2U) = (uint8_t)pt;
+ RPC_U8(&msg, 3U) = (uint8_t)perm;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_bool_t sc_rm_is_resource_owned(sc_ipc_t ipc, sc_rsrc_t resource)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_OWNED;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_bool_t)result;
+}
+
+sc_bool_t sc_rm_is_resource_master(sc_ipc_t ipc, sc_rsrc_t resource)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_MASTER;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_bool_t)result;
+}
+
+sc_bool_t sc_rm_is_resource_peripheral(sc_ipc_t ipc, sc_rsrc_t resource)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_RESOURCE_PERIPHERAL;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_bool_t)result;
+}
+
+sc_err_t sc_rm_get_resource_info(sc_ipc_t ipc, sc_rsrc_t resource,
+ sc_rm_sid_t *sid)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_RESOURCE_INFO;
+ RPC_U16(&msg, 0U) = (uint16_t)resource;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (sid != NULL) {
+ *sid = RPC_U16(&msg, 0U);
+ }
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_memreg_alloc(sc_ipc_t ipc, sc_rm_mr_t *mr,
+ sc_faddr_t addr_start, sc_faddr_t addr_end)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_ALLOC;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr_start;
+ RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U);
+ RPC_U32(&msg, 12U) = (uint32_t)addr_end;
+ RPC_SIZE(&msg) = 5U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (mr != NULL) {
+ *mr = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_memreg_split(sc_ipc_t ipc, sc_rm_mr_t mr,
+ sc_rm_mr_t *mr_ret, sc_faddr_t addr_start,
+ sc_faddr_t addr_end)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_SPLIT;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr_start;
+ RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U);
+ RPC_U32(&msg, 12U) = (uint32_t)addr_end;
+ RPC_U8(&msg, 16U) = (uint8_t)mr;
+ RPC_SIZE(&msg) = 6U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (mr_ret != NULL) {
+ *mr_ret = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_memreg_free(sc_ipc_t ipc, sc_rm_mr_t mr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_MEMREG_FREE;
+ RPC_U8(&msg, 0U) = (uint8_t)mr;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_find_memreg(sc_ipc_t ipc, sc_rm_mr_t *mr,
+ sc_faddr_t addr_start, sc_faddr_t addr_end)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_FIND_MEMREG;
+ RPC_U32(&msg, 0U) = (uint32_t)(addr_start >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)addr_start;
+ RPC_U32(&msg, 8U) = (uint32_t)(addr_end >> 32U);
+ RPC_U32(&msg, 12U) = (uint32_t)addr_end;
+ RPC_SIZE(&msg) = 5U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ if (mr != NULL) {
+ *mr = RPC_U8(&msg, 0U);
+ }
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_assign_memreg(sc_ipc_t ipc, sc_rm_pt_t pt, sc_rm_mr_t mr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_MEMREG;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)mr;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_memreg_permissions(sc_ipc_t ipc, sc_rm_mr_t mr,
+ sc_rm_pt_t pt, sc_rm_perm_t perm)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_MEMREG_PERMISSIONS;
+ RPC_U8(&msg, 0U) = (uint8_t)mr;
+ RPC_U8(&msg, 1U) = (uint8_t)pt;
+ RPC_U8(&msg, 2U) = (uint8_t)perm;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_bool_t sc_rm_is_memreg_owned(sc_ipc_t ipc, sc_rm_mr_t mr)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_MEMREG_OWNED;
+ RPC_U8(&msg, 0U) = (uint8_t)mr;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_bool_t)result;
+}
+
+sc_err_t sc_rm_get_memreg_info(sc_ipc_t ipc, sc_rm_mr_t mr,
+ sc_faddr_t *addr_start, sc_faddr_t *addr_end)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_GET_MEMREG_INFO;
+ RPC_U8(&msg, 0U) = (uint8_t)mr;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (addr_start != NULL) {
+ *addr_start =
+ ((uint64_t) RPC_U32(&msg, 0U) << 32U) | RPC_U32(&msg, 4U);
+ }
+
+ if (addr_end != NULL) {
+ *addr_end =
+ ((uint64_t) RPC_U32(&msg, 8U) << 32U) | RPC_U32(&msg, 12U);
+ }
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_assign_pad(sc_ipc_t ipc, sc_rm_pt_t pt, sc_pad_t pad)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_ASSIGN_PAD;
+ RPC_U16(&msg, 0U) = (uint16_t)pad;
+ RPC_U8(&msg, 2U) = (uint8_t)pt;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_rm_set_pad_movable(sc_ipc_t ipc, sc_pad_t pad_fst,
+ sc_pad_t pad_lst, sc_bool_t movable)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_SET_PAD_MOVABLE;
+ RPC_U16(&msg, 0U) = (uint16_t)pad_fst;
+ RPC_U16(&msg, 2U) = (uint16_t)pad_lst;
+ RPC_U8(&msg, 4U) = (uint8_t)movable;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_bool_t sc_rm_is_pad_owned(sc_ipc_t ipc, sc_pad_t pad)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_IS_PAD_OWNED;
+ RPC_U8(&msg, 0U) = (uint8_t)pad;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_bool_t)result;
+}
+
+void sc_rm_dump(sc_ipc_t ipc)
+{
+ sc_rpc_msg_t msg;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_RM;
+ RPC_FUNC(&msg) = (uint8_t)RM_FUNC_DUMP;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ return;
+}
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/rm/sci_rm_rpc.h b/plat/imx/common/sci/svc/rm/sci_rm_rpc.h
new file mode 100644
index 0000000..45d05f9
--- /dev/null
+++ b/plat/imx/common/sci/svc/rm/sci_rm_rpc.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the RM RPC implementation.
+ *
+ * @addtogroup RM_SVC
+ * @{
+ */
+
+#ifndef SCI_RM_RPC_H
+#define SCI_RM_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC RM function calls
+ */
+/*@{*/
+#define RM_FUNC_UNKNOWN 0 /* Unknown function */
+#define RM_FUNC_PARTITION_ALLOC 1U /* Index for rm_partition_alloc() RPC call */
+#define RM_FUNC_SET_CONFIDENTIAL 31U /* Index for rm_set_confidential() RPC call */
+#define RM_FUNC_PARTITION_FREE 2U /* Index for rm_partition_free() RPC call */
+#define RM_FUNC_GET_DID 26U /* Index for rm_get_did() RPC call */
+#define RM_FUNC_PARTITION_STATIC 3U /* Index for rm_partition_static() RPC call */
+#define RM_FUNC_PARTITION_LOCK 4U /* Index for rm_partition_lock() RPC call */
+#define RM_FUNC_GET_PARTITION 5U /* Index for rm_get_partition() RPC call */
+#define RM_FUNC_SET_PARENT 6U /* Index for rm_set_parent() RPC call */
+#define RM_FUNC_MOVE_ALL 7U /* Index for rm_move_all() RPC call */
+#define RM_FUNC_ASSIGN_RESOURCE 8U /* Index for rm_assign_resource() RPC call */
+#define RM_FUNC_SET_RESOURCE_MOVABLE 9U /* Index for rm_set_resource_movable() RPC call */
+#define RM_FUNC_SET_SUBSYS_RSRC_MOVABLE 28U /* Index for rm_set_subsys_rsrc_movable() RPC call */
+#define RM_FUNC_SET_MASTER_ATTRIBUTES 10U /* Index for rm_set_master_attributes() RPC call */
+#define RM_FUNC_SET_MASTER_SID 11U /* Index for rm_set_master_sid() RPC call */
+#define RM_FUNC_SET_PERIPHERAL_PERMISSIONS 12U /* Index for rm_set_peripheral_permissions() RPC call */
+#define RM_FUNC_IS_RESOURCE_OWNED 13U /* Index for rm_is_resource_owned() RPC call */
+#define RM_FUNC_IS_RESOURCE_MASTER 14U /* Index for rm_is_resource_master() RPC call */
+#define RM_FUNC_IS_RESOURCE_PERIPHERAL 15U /* Index for rm_is_resource_peripheral() RPC call */
+#define RM_FUNC_GET_RESOURCE_INFO 16U /* Index for rm_get_resource_info() RPC call */
+#define RM_FUNC_MEMREG_ALLOC 17U /* Index for rm_memreg_alloc() RPC call */
+#define RM_FUNC_MEMREG_SPLIT 29U /* Index for rm_memreg_split() RPC call */
+#define RM_FUNC_MEMREG_FREE 18U /* Index for rm_memreg_free() RPC call */
+#define RM_FUNC_FIND_MEMREG 30U /* Index for rm_find_memreg() RPC call */
+#define RM_FUNC_ASSIGN_MEMREG 19U /* Index for rm_assign_memreg() RPC call */
+#define RM_FUNC_SET_MEMREG_PERMISSIONS 20U /* Index for rm_set_memreg_permissions() RPC call */
+#define RM_FUNC_IS_MEMREG_OWNED 21U /* Index for rm_is_memreg_owned() RPC call */
+#define RM_FUNC_GET_MEMREG_INFO 22U /* Index for rm_get_memreg_info() RPC call */
+#define RM_FUNC_ASSIGN_PAD 23U /* Index for rm_assign_pad() RPC call */
+#define RM_FUNC_SET_PAD_MOVABLE 24U /* Index for rm_set_pad_movable() RPC call */
+#define RM_FUNC_IS_PAD_OWNED 25U /* Index for rm_is_pad_owned() RPC call */
+#define RM_FUNC_DUMP 27U /* Index for rm_dump() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming RM RPC request.
+ *
+ * @param[in] caller_pt caller partition
+ * @param[in] msg pointer to RPC message
+ */
+void rm_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an RM RPC request.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] msg pointer to RPC message
+ */
+void rm_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif /* SCI_RM_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/timer/sci_timer_rpc.h b/plat/imx/common/sci/svc/timer/sci_timer_rpc.h
new file mode 100644
index 0000000..6716399
--- /dev/null
+++ b/plat/imx/common/sci/svc/timer/sci_timer_rpc.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * Header file for the TIMER RPC implementation.
+ *
+ * @addtogroup TIMER_SVC
+ * @{
+ */
+
+#ifndef SC_TIMER_RPC_H
+#define SC_TIMER_RPC_H
+
+/* Includes */
+
+/* Defines */
+
+/*!
+ * @name Defines for RPC TIMER function calls
+ */
+/*@{*/
+#define TIMER_FUNC_UNKNOWN 0 /* Unknown function */
+#define TIMER_FUNC_SET_WDOG_TIMEOUT 1U /* Index for timer_set_wdog_timeout() RPC call */
+#define TIMER_FUNC_SET_WDOG_PRE_TIMEOUT 12U /* Index for timer_set_wdog_pre_timeout() RPC call */
+#define TIMER_FUNC_START_WDOG 2U /* Index for timer_start_wdog() RPC call */
+#define TIMER_FUNC_STOP_WDOG 3U /* Index for timer_stop_wdog() RPC call */
+#define TIMER_FUNC_PING_WDOG 4U /* Index for timer_ping_wdog() RPC call */
+#define TIMER_FUNC_GET_WDOG_STATUS 5U /* Index for timer_get_wdog_status() RPC call */
+#define TIMER_FUNC_PT_GET_WDOG_STATUS 13U /* Index for timer_pt_get_wdog_status() RPC call */
+#define TIMER_FUNC_SET_WDOG_ACTION 10U /* Index for timer_set_wdog_action() RPC call */
+#define TIMER_FUNC_SET_RTC_TIME 6U /* Index for timer_set_rtc_time() RPC call */
+#define TIMER_FUNC_GET_RTC_TIME 7U /* Index for timer_get_rtc_time() RPC call */
+#define TIMER_FUNC_GET_RTC_SEC1970 9U /* Index for timer_get_rtc_sec1970() RPC call */
+#define TIMER_FUNC_SET_RTC_ALARM 8U /* Index for timer_set_rtc_alarm() RPC call */
+#define TIMER_FUNC_SET_RTC_PERIODIC_ALARM 14U /* Index for timer_set_rtc_periodic_alarm() RPC call */
+#define TIMER_FUNC_CANCEL_RTC_ALARM 15U /* Index for timer_cancel_rtc_alarm() RPC call */
+#define TIMER_FUNC_SET_RTC_CALB 11U /* Index for timer_set_rtc_calb() RPC call */
+#define TIMER_FUNC_SET_SYSCTR_ALARM 16U /* Index for timer_set_sysctr_alarm() RPC call */
+#define TIMER_FUNC_SET_SYSCTR_PERIODIC_ALARM 17U /* Index for timer_set_sysctr_periodic_alarm() RPC call */
+#define TIMER_FUNC_CANCEL_SYSCTR_ALARM 18U /* Index for timer_cancel_sysctr_alarm() RPC call */
+/*@}*/
+
+/* Types */
+
+/* Functions */
+
+/*!
+ * This function dispatches an incoming TIMER RPC request.
+ *
+ * @param[in] caller_pt caller partition
+ * @param[in] msg pointer to RPC message
+ */
+void timer_dispatch(sc_rm_pt_t caller_pt, sc_rpc_msg_t *msg);
+
+/*!
+ * This function translates and dispatches an TIMER RPC request.
+ *
+ * @param[in] ipc IPC handle
+ * @param[in] msg pointer to RPC message
+ */
+void timer_xlate(sc_ipc_t ipc, sc_rpc_msg_t *msg);
+
+#endif /* SC_TIMER_RPC_H */
+
+/**@}*/
diff --git a/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c b/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c
new file mode 100644
index 0000000..a82be96
--- /dev/null
+++ b/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2019 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*!
+ * File containing client-side RPC functions for the TIMER service. These
+ * functions are ported to clients that communicate to the SC.
+ *
+ * @addtogroup TIMER_SVC
+ * @{
+ */
+
+/* Includes */
+
+#include <sci/sci_types.h>
+#include <sci/svc/rm/sci_rm_api.h>
+#include <sci/svc/timer/sci_timer_api.h>
+#include <sci/sci_rpc.h>
+#include <stdlib.h>
+#include "sci_timer_rpc.h"
+
+/* Local Defines */
+
+/* Local Types */
+
+/* Local Functions */
+
+sc_err_t sc_timer_set_wdog_timeout(sc_ipc_t ipc, sc_timer_wdog_time_t timeout)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_WDOG_TIMEOUT;
+ RPC_U32(&msg, 0U) = (uint32_t)timeout;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_wdog_pre_timeout(sc_ipc_t ipc,
+ sc_timer_wdog_time_t pre_timeout)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_WDOG_PRE_TIMEOUT;
+ RPC_U32(&msg, 0U) = (uint32_t)pre_timeout;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_start_wdog(sc_ipc_t ipc, sc_bool_t lock)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_START_WDOG;
+ RPC_U8(&msg, 0U) = (uint8_t)lock;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_stop_wdog(sc_ipc_t ipc)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_STOP_WDOG;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_ping_wdog(sc_ipc_t ipc)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_PING_WDOG;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_get_wdog_status(sc_ipc_t ipc,
+ sc_timer_wdog_time_t *timeout,
+ sc_timer_wdog_time_t *max_timeout,
+ sc_timer_wdog_time_t *remaining_time)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_GET_WDOG_STATUS;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (timeout != NULL)
+ *timeout = RPC_U32(&msg, 0U);
+
+ if (max_timeout != NULL)
+ *max_timeout = RPC_U32(&msg, 4U);
+
+ if (remaining_time != NULL)
+ *remaining_time = RPC_U32(&msg, 8U);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_pt_get_wdog_status(sc_ipc_t ipc, sc_rm_pt_t pt,
+ sc_bool_t *enb,
+ sc_timer_wdog_time_t *timeout,
+ sc_timer_wdog_time_t *remaining_time)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_PT_GET_WDOG_STATUS;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (timeout != NULL)
+ *timeout = RPC_U32(&msg, 0U);
+
+ if (remaining_time != NULL)
+ *remaining_time = RPC_U32(&msg, 4U);
+
+ result = RPC_R8(&msg);
+ if (enb != NULL)
+ *enb = RPC_U8(&msg, 8U);
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_wdog_action(sc_ipc_t ipc,
+ sc_rm_pt_t pt, sc_timer_wdog_action_t action)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_WDOG_ACTION;
+ RPC_U8(&msg, 0U) = (uint8_t)pt;
+ RPC_U8(&msg, 1U) = (uint8_t)action;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_rtc_time(sc_ipc_t ipc, uint16_t year, uint8_t mon,
+ uint8_t day, uint8_t hour, uint8_t min,
+ uint8_t sec)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_TIME;
+ RPC_U16(&msg, 0U) = (uint16_t)year;
+ RPC_U8(&msg, 2U) = (uint8_t)mon;
+ RPC_U8(&msg, 3U) = (uint8_t)day;
+ RPC_U8(&msg, 4U) = (uint8_t)hour;
+ RPC_U8(&msg, 5U) = (uint8_t)min;
+ RPC_U8(&msg, 6U) = (uint8_t)sec;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_get_rtc_time(sc_ipc_t ipc, uint16_t *year, uint8_t *mon,
+ uint8_t *day, uint8_t *hour, uint8_t *min,
+ uint8_t *sec)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_GET_RTC_TIME;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (year != NULL)
+ *year = RPC_U16(&msg, 0U);
+
+ result = RPC_R8(&msg);
+ if (mon != NULL)
+ *mon = RPC_U8(&msg, 2U);
+
+ if (day != NULL)
+ *day = RPC_U8(&msg, 3U);
+
+ if (hour != NULL)
+ *hour = RPC_U8(&msg, 4U);
+
+ if (min != NULL)
+ *min = RPC_U8(&msg, 5U);
+
+ if (sec != NULL)
+ *sec = RPC_U8(&msg, 6U);
+
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_get_rtc_sec1970(sc_ipc_t ipc, uint32_t *sec)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_GET_RTC_SEC1970;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ if (sec != NULL)
+ *sec = RPC_U32(&msg, 0U);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_rtc_alarm(sc_ipc_t ipc, uint16_t year, uint8_t mon,
+ uint8_t day, uint8_t hour, uint8_t min,
+ uint8_t sec)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_ALARM;
+ RPC_U16(&msg, 0U) = (uint16_t)year;
+ RPC_U8(&msg, 2U) = (uint8_t)mon;
+ RPC_U8(&msg, 3U) = (uint8_t)day;
+ RPC_U8(&msg, 4U) = (uint8_t)hour;
+ RPC_U8(&msg, 5U) = (uint8_t)min;
+ RPC_U8(&msg, 6U) = (uint8_t)sec;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_rtc_periodic_alarm(sc_ipc_t ipc, uint32_t sec)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_PERIODIC_ALARM;
+ RPC_U32(&msg, 0U) = (uint32_t)sec;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_cancel_rtc_alarm(sc_ipc_t ipc)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_CANCEL_RTC_ALARM;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_rtc_calb(sc_ipc_t ipc, int8_t count)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_RTC_CALB;
+ RPC_I8(&msg, 0U) = (int8_t) count;
+ RPC_SIZE(&msg) = 2U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_sysctr_alarm(sc_ipc_t ipc, uint64_t ticks)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_SYSCTR_ALARM;
+ RPC_U32(&msg, 0U) = (uint32_t)(ticks >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)ticks;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_set_sysctr_periodic_alarm(sc_ipc_t ipc, uint64_t ticks)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_SET_SYSCTR_PERIODIC_ALARM;
+ RPC_U32(&msg, 0U) = (uint32_t)(ticks >> 32U);
+ RPC_U32(&msg, 4U) = (uint32_t)ticks;
+ RPC_SIZE(&msg) = 3U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+sc_err_t sc_timer_cancel_sysctr_alarm(sc_ipc_t ipc)
+{
+ sc_rpc_msg_t msg;
+ uint8_t result;
+
+ RPC_VER(&msg) = SC_RPC_VERSION;
+ RPC_SVC(&msg) = (uint8_t)SC_RPC_SVC_TIMER;
+ RPC_FUNC(&msg) = (uint8_t)TIMER_FUNC_CANCEL_SYSCTR_ALARM;
+ RPC_SIZE(&msg) = 1U;
+
+ sc_call_rpc(ipc, &msg, SC_FALSE);
+
+ result = RPC_R8(&msg);
+ return (sc_err_t)result;
+}
+
+/**@}*/
diff --git a/plat/imx/imx7/common/imx7.mk b/plat/imx/imx7/common/imx7.mk
new file mode 100644
index 0000000..f4f5bfc
--- /dev/null
+++ b/plat/imx/imx7/common/imx7.mk
@@ -0,0 +1,112 @@
+#
+# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Architecture
+$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING))
+
+TF_CFLAGS += -mfpu=neon
+ASFLAGS += -mfpu=neon
+
+# Platform
+PLAT_INCLUDES := -Idrivers/imx/uart \
+ -Iplat/imx/common/include \
+ -Iplat/imx/imx7/include \
+ -Idrivers/imx/timer \
+ -Idrivers/imx/usdhc \
+ -Iinclude/common/tbbr
+
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+BL2_SOURCES += common/desc_image_load.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/mmc/mmc.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ drivers/imx/timer/imx_gpt.c \
+ drivers/imx/uart/imx_uart.c \
+ drivers/imx/uart/imx_crash_uart.S \
+ lib/aarch32/arm32_aeabi_divmod.c \
+ lib/aarch32/arm32_aeabi_divmod_a32.S \
+ lib/cpus/aarch32/cortex_a7.S \
+ lib/optee/optee_utils.c \
+ plat/imx/common/imx_aips.c \
+ plat/imx/common/imx_caam.c \
+ plat/imx/common/imx_clock.c \
+ plat/imx/common/imx_csu.c \
+ plat/imx/common/imx_io_mux.c \
+ plat/imx/common/imx_snvs.c \
+ plat/imx/common/imx_wdog.c \
+ plat/imx/common/imx7_clock.c \
+ plat/imx/imx7/common/imx7_bl2_mem_params_desc.c \
+ plat/imx/imx7/common/imx7_bl2_el3_common.c \
+ plat/imx/imx7/common/imx7_helpers.S \
+ plat/imx/imx7/common/imx7_image_load.c \
+ plat/imx/common/imx_io_storage.c \
+ plat/imx/common/aarch32/imx_uart_console.S \
+ ${XLAT_TABLES_LIB_SRCS}
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c
+
+BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/imx/imx7/common/imx7_trusted_boot.c \
+ plat/imx/imx7/common/imx7_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(eval $(call MAKE_LIB_DIRS))
+
+$(BUILD_PLAT)/bl2/imx7_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ @if [ ! -f $(ROT_KEY) ]; then \
+ ${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null; \
+ fi
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
+
+# Add the build options to pack BLx images and kernel device tree
+# in the FIP if the platform requires.
+ifneq ($(BL2),)
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
+endif
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+ifneq ($(HW_CONFIG),)
+$(eval $(call TOOL_ADD_IMG,HW_CONFIG,--hw-config))
+endif
+
+# Verify build config
+# -------------------
+
+ifeq (${ARCH},aarch64)
+ $(error Error: AArch64 not supported on i.mx7)
+endif
diff --git a/plat/imx/imx7/common/imx7_bl2_el3_common.c b/plat/imx/imx7/common/imx7_bl2_el3_common.c
new file mode 100644
index 0000000..4e5028c
--- /dev/null
+++ b/plat/imx/imx7/common/imx7_bl2_el3_common.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/mmc.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <lib/utils.h>
+
+#include <imx_aips.h>
+#include <imx_caam.h>
+#include <imx_clock.h>
+#include <imx_csu.h>
+#include <imx_gpt.h>
+#include <imx_uart.h>
+#include <imx_snvs.h>
+#include <imx_wdog.h>
+#include <imx7_def.h>
+
+#ifndef AARCH32_SP_OPTEE
+#error "Must build with OPTEE support included"
+#endif
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+ return IMX7_UBOOT_BASE;
+}
+
+static uint32_t imx7_get_spsr_for_bl32_entry(void)
+{
+ return SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS);
+}
+
+static uint32_t imx7_get_spsr_for_bl33_entry(void)
+{
+ return SPSR_MODE32(MODE32_svc,
+ plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ bl_mem_params_node_t *hw_cfg_mem_params = NULL;
+
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0)
+ WARN("OPTEE header parse error.\n");
+
+ /*
+ * When ATF loads the DTB the address of the DTB is passed in
+ * arg2, if an hw config image is present use the base address
+ * as DTB address an pass it as arg2
+ */
+ hw_cfg_mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
+
+ bl_mem_params->ep_info.args.arg0 =
+ bl_mem_params->ep_info.args.arg1;
+ bl_mem_params->ep_info.args.arg1 = 0;
+ if (hw_cfg_mem_params)
+ bl_mem_params->ep_info.args.arg2 =
+ hw_cfg_mem_params->image_info.image_base;
+ else
+ bl_mem_params->ep_info.args.arg2 = 0;
+ bl_mem_params->ep_info.args.arg3 = 0;
+ bl_mem_params->ep_info.spsr = imx7_get_spsr_for_bl32_entry();
+ break;
+
+ case BL33_IMAGE_ID:
+ /* AArch32 only core: OP-TEE expects NSec EP in register LR */
+ pager_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
+ assert(pager_mem_params);
+ pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
+
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = imx7_get_spsr_for_bl33_entry();
+ break;
+
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ /* Setup the MMU here */
+}
+
+static void imx7_setup_system_counter(void)
+{
+ unsigned long freq = SYS_COUNTER_FREQ_IN_TICKS;
+
+ /* Set the frequency table index to our target frequency */
+ write_cntfrq(freq);
+
+ /* Enable system counter @ frequency table index 0, halt on debug */
+ mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0) | CNTCR_HDBG | CNTCR_EN);
+}
+
+static void imx7_setup_wdog_clocks(void)
+{
+ uint32_t wdog_en_bits = (uint32_t)WDOG_DEFAULT_CLK_SELECT;
+
+ imx_clock_set_wdog_clk_root_bits(wdog_en_bits);
+ imx_clock_enable_wdog(0);
+ imx_clock_enable_wdog(1);
+ imx_clock_enable_wdog(2);
+ imx_clock_enable_wdog(3);
+}
+
+
+/*
+ * bl2_el3_early_platform_setup()
+ * MMU off
+ */
+void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ static console_t console;
+ int console_scope = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME;
+
+ /* Initialize common components */
+ imx_aips_init();
+ imx_csu_init();
+ imx_snvs_init();
+ imx_gpt_ops_init(GPT1_BASE_ADDR);
+ imx_clock_init();
+ imx7_setup_system_counter();
+ imx7_setup_wdog_clocks();
+
+ /* Platform specific setup */
+ imx7_platform_setup(arg1, arg2, arg3, arg4);
+
+ /* Init UART, clock should be enabled in imx7_platform_setup() */
+ console_imx_uart_register(PLAT_IMX7_BOOT_UART_BASE,
+ PLAT_IMX7_BOOT_UART_CLK_IN_HZ,
+ PLAT_IMX7_CONSOLE_BAUDRATE,
+ &console);
+ console_set_scope(&console, console_scope);
+
+ /* Open handles to persistent storage */
+ plat_imx_io_setup();
+
+ /* Setup higher-level functionality CAAM, RTC etc */
+ imx_caam_init();
+ imx_wdog_init();
+
+ /* Print out the expected memory map */
+ VERBOSE("\tOPTEE 0x%08x-0x%08x\n", IMX7_OPTEE_BASE, IMX7_OPTEE_LIMIT);
+ VERBOSE("\tATF/BL2 0x%08x-0x%08x\n", BL2_RAM_BASE, BL2_RAM_LIMIT);
+ VERBOSE("\tSHRAM 0x%08x-0x%08x\n", SHARED_RAM_BASE, SHARED_RAM_LIMIT);
+ VERBOSE("\tFIP 0x%08x-0x%08x\n", IMX_FIP_BASE, IMX_FIP_LIMIT);
+ VERBOSE("\tDTB-OVERLAY 0x%08x-0x%08x\n", IMX7_DTB_OVERLAY_BASE, IMX7_DTB_OVERLAY_LIMIT);
+ VERBOSE("\tDTB 0x%08x-0x%08x\n", IMX7_DTB_BASE, IMX7_DTB_LIMIT);
+ VERBOSE("\tUBOOT/BL33 0x%08x-0x%08x\n", IMX7_UBOOT_BASE, IMX7_UBOOT_LIMIT);
+}
+
+/*
+ * bl2_platform_setup()
+ * MMU on - enabled by bl2_el3_plat_arch_setup()
+ */
+void bl2_platform_setup(void)
+{
+}
diff --git a/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c b/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c
new file mode 100644
index 0000000..f9b2983
--- /dev/null
+++ b/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, 0),
+
+ .image_info.image_base = IMX7_OPTEE_BASE,
+ .image_info.image_max_size = IMX7_OPTEE_SIZE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = IMX7_OPTEE_BASE,
+ .image_info.image_max_size = IMX7_OPTEE_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ /* This is a zero sized image so we don't set base or size */
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+ # ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ # else
+ .ep_info.pc = BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = IMX7_UBOOT_BASE,
+ .image_info.image_max_size = IMX7_UBOOT_SIZE,
+ # endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs);
diff --git a/plat/imx/imx7/common/imx7_helpers.S b/plat/imx/imx7/common/imx7_helpers.S
new file mode 100644
index 0000000..661fd29
--- /dev/null
+++ b/plat/imx/imx7/common/imx7_helpers.S
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) Linaro 2018-2019 Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <platform_def.h>
+#include <imx_hab.h>
+
+ .globl platform_mem_init
+ .globl plat_get_my_entrypoint
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_panic_handler
+
+ /* ---------------------------------------------
+ * int plat_mem_init(void)
+ * Function to initialize memory.
+ * The HAB hands off the DDR controller already
+ * setup and ready to use.
+ * Implement the mandatory function as a NOP
+ * ---------------------------------------------
+ */
+func platform_mem_init
+ bx lr
+endfunc platform_mem_init
+
+func plat_get_my_entrypoint
+ mov r0, #0
+ bx lr
+endfunc plat_get_my_entrypoint
+
+func plat_crash_console_init
+ mov_imm r0, PLAT_IMX7_BOOT_UART_BASE
+ mov_imm r1, PLAT_IMX7_BOOT_UART_CLK_IN_HZ
+ mov_imm r2, PLAT_IMX7_CONSOLE_BAUDRATE
+ b imx_crash_uart_init
+endfunc plat_crash_console_init
+
+func plat_crash_console_putc
+ mov_imm r1, PLAT_IMX7_BOOT_UART_BASE
+ b imx_crash_uart_putc
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+ /* Placeholder */
+ mov r0, #0
+ bx lr
+endfunc plat_crash_console_flush
+
+func plat_panic_handler
+ mov r3, #HAB_ROM_VECTOR_TABLE_FAILSAFE
+ ldr r3, [r3, #0]
+ blx r3
+endfunc plat_panic_handler
diff --git a/plat/imx/imx7/common/imx7_image_load.c b/plat/imx/imx7/common/imx7_image_load.c
new file mode 100644
index 0000000..c3e47b9
--- /dev/null
+++ b/plat/imx/imx7/common/imx7_image_load.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/imx/imx7/common/imx7_rotpk.S b/plat/imx/imx7/common/imx7_rotpk.S
new file mode 100644
index 0000000..8bd53c2
--- /dev/null
+++ b/plat/imx/imx7/common/imx7_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global imx7_rotpk_hash
+ .global imx7_rotpk_hash_end
+imx7_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+imx7_rotpk_hash_end:
diff --git a/plat/imx/imx7/common/imx7_trusted_boot.c b/plat/imx/imx7/common/imx7_trusted_boot.c
new file mode 100644
index 0000000..cd27128
--- /dev/null
+++ b/plat/imx/imx7/common/imx7_trusted_boot.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char imx7_rotpk_hash[], imx7_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = imx7_rotpk_hash;
+ *key_len = imx7_rotpk_hash_end - imx7_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/imx/imx7/include/imx7_def.h b/plat/imx/imx7/include/imx7_def.h
new file mode 100644
index 0000000..d92a2d1
--- /dev/null
+++ b/plat/imx/imx7/include/imx7_def.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX7_DEF_H
+#define IMX7_DEF_H
+
+#include <stdint.h>
+
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_imx_io_setup(void);
+void imx7_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4);
+
+#endif /*IMX7_DEF_H */
diff --git a/plat/imx/imx7/include/imx_hab_arch.h b/plat/imx/imx7/include/imx_hab_arch.h
new file mode 100644
index 0000000..2a34c6a
--- /dev/null
+++ b/plat/imx/imx7/include/imx_hab_arch.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef IMX_HAB_ARCH_H
+#define IMX_HAB_ARCH_H
+
+/* Define the offset the High Assurance Boot callback table is at */
+#define HAB_CALLBACK_OFFSET 0x100
+
+#endif /* IMX_HAB_ARCH_H */
diff --git a/plat/imx/imx7/include/imx_regs.h b/plat/imx/imx7/include/imx_regs.h
new file mode 100644
index 0000000..3c7e20f
--- /dev/null
+++ b/plat/imx/imx7/include/imx_regs.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_REGS_H
+#define IMX_REGS_H
+
+/* Define the processor memory map */
+
+#define OCRAM_S_ALIAS_BASE 0x00000000 /* CM4 Alias Code */
+#define ROM_HIGH_BASE 0x00008000 /* ROM high 64k */
+#define ROM_HIGH_PROT_BASE 0x00017000 /* ROM high 64k protected */
+#define CAAM_BASE 0x00020000 /* CAAM block base address */
+#define OCRAM_S_BASE 0x00180000 /* OCRAM_S */
+#define ROM_LOW_BASE 0x007f8000 /* ROM low 64k */
+#define OCRAM_BASE 0x00900000 /* OCRAM base */
+#define CM4_ALIAS_CODE_BASE 0x04000000 /* CM4 alias code */
+#define TCM_BASE 0x1fff0000 /* TCM */
+#define BOOTROM_CP_BASE 0x20020000 /* Boot ROM (all 96KB) */
+#define CM4_ALIAS_SYSTEM_BASE 0x20100000 /* CM4 Alias system */
+#define EIM_BASE 0x28000000 /* EIM */
+
+/* BootROM absolute base address */
+#define BOOTROM_BASE 0x00000000 /* BootROM */
+
+/* Peripherals like GPIO live in the AIPS range */
+#define AIPS1_BASE 0x30000000 /* AIPS1 */
+#define AIPS2_BASE 0x30400000 /* AIPS2 */
+#define AIPS3_BASE 0x30800000 /* AIPS3 */
+#define AIPS4_BASE 0x30c00000 /* AIPS4 */
+
+/* ARM peripherals like GIC */
+#define ARM_PERIPHERAL_GIC_BASE 0x31000000 /* GIC */
+
+/* Configuration ports */
+#define GPV0_BASE 0x32000000 /* Main config port */
+#define GPV1_BASE 0x32100000 /* Wakeup config port */
+#define GPV2_BASE 0x32200000 /* Per_s config port */
+#define GPV3_BASE 0x32300000 /* Per_m config port */
+#define GPV4_BASE 0x32400000 /* Enet config port */
+#define GPV5_BASE 0x32500000 /* Display config port */
+#define GPV6_BASE 0x32600000 /* M4 conig port */
+
+/* MMAP peripherals - like APBH DMA */
+#define APBH_DMA_BASE 0x33000000 /* APBH DMA block */
+
+/* QSPI RX BUFFERS */
+#define QSPI_RX_BUFFER_BASE 0x34000000 /* QSPI RX buffers */
+
+/* QSPI1 FLASH */
+#define QSPI_FLASH_BASE 0x60000000 /* QSPI1 flash */
+
+/* AIPS1 block addresses */
+#define AIPSTZ_CONFIG_OFFSET 0x001f0000
+#define CCM_BASE (AIPS1_BASE + 0x380000)
+
+/* Define the maximum number of UART blocks on this SoC */
+#define MXC_UART1_BASE (AIPS3_BASE + 0x060000)
+#define MXC_UART2_BASE (AIPS3_BASE + 0x070000)
+#define MXC_UART3_BASE (AIPS3_BASE + 0x080000)
+#define MXC_UART4_BASE (AIPS3_BASE + 0x260000)
+#define MXC_UART5_BASE (AIPS3_BASE + 0x270000)
+#define MXC_UART6_BASE (AIPS3_BASE + 0x280000)
+#define MXC_UART7_BASE (AIPS3_BASE + 0x290000)
+#define MXC_MAX_UART_NUM 0x07
+
+/* Define the maximum number of USDHCI blocks on this SoC */
+#define MXC_MAX_USDHC_NUM 3
+
+/* Define the number of CSU registers for this SoC */
+#define MXC_MAX_CSU_REGS 0x40
+#define CSU_BASE (AIPS1_BASE + 0x3E0000)
+
+/* IO Mux block base */
+#define MXC_IO_MUXC_BASE (AIPS1_BASE + 0x330000)
+
+/* SNVS base */
+#define SNVS_BASE (AIPS1_BASE + 0x370000)
+
+/* GP Timer base */
+#define GPT1_BASE_ADDR (AIPS1_BASE + 0x2d0000)
+
+/* MMC base */
+#define USDHC1_BASE (AIPS1_BASE + 0xb40000)
+#define USDHC2_BASE (AIPS1_BASE + 0xb50000)
+#define USDHC3_BASE (AIPS1_BASE + 0xb60000)
+
+/* Arm optional memory mapped counter module base address */
+#define SYS_CNTCTL_BASE (AIPS2_BASE + 0x2c0000)
+
+/* Define CAAM AIPS offset */
+#define CAAM_AIPS_BASE (AIPS3_BASE + 0x100000)
+#define CAAM_NUM_JOB_RINGS 0x03
+#define CAAM_NUM_RTIC 0x04
+#define CAAM_NUM_DECO 0x01
+
+/* Define watchdog base addresses */
+#define WDOG1_BASE (AIPS1_BASE + 0x280000)
+#define WDOG2_BASE (AIPS1_BASE + 0x290000)
+#define WDOG3_BASE (AIPS1_BASE + 0x2A0000)
+#define WDOG4_BASE (AIPS1_BASE + 0x280000)
+
+/* Define the maximum number of WDOG blocks on this SoC */
+#define MXC_MAX_WDOG_NUM 0x04
+
+#endif /* IMX_REGS_H */
diff --git a/plat/imx/imx7/picopi/include/platform_def.h b/plat/imx/imx7/picopi/include/platform_def.h
new file mode 100644
index 0000000..5f2975d
--- /dev/null
+++ b/plat/imx/imx7/picopi/include/platform_def.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_STACK_SIZE 0x1000
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define PICOPI_PRIMARY_CPU U(0)
+
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+
+#define PLAT_MAX_RET_STATE 1
+#define PLAT_MAX_OFF_STATE 2
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN 0
+
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET 1
+
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF 2
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH 4
+#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ * i.MX7 has a 32 byte cacheline size
+ * i.MX 7Dual Applications Processor Reference Manual, Rev. 1, 01/2018 pg 298
+ */
+#define CACHE_WRITEBACK_SHIFT 4
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Partition memory into secure BootROM, OCRAM_S, non-secure DRAM, secure DRAM
+ */
+#define BOOT_ROM_BASE 0x00000000
+#define BOOT_ROM_SIZE 0x00020000
+
+#define OCRAM_S_BASE 0x00180000
+#define OCRAM_S_SIZE 0x00008000
+
+/* Controller maps 2GB, board contains 512 MB. 0x80000000 - 0xa0000000 */
+#define DRAM_BASE 0x80000000
+#define DRAM_SIZE 0x20000000
+#define DRAM_LIMIT (DRAM_BASE + DRAM_SIZE)
+
+/* Place OPTEE at minus 32 MB from the end of memory. 0x9e000000 - 0xa0000000 */
+#define IMX7_OPTEE_SIZE 0x02000000
+#define IMX7_OPTEE_BASE (DRAM_LIMIT - IMX7_OPTEE_SIZE)
+#define IMX7_OPTEE_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE)
+
+/* Place ATF directly beneath OPTEE. 0x9df00000 - 0x9e000000 */
+#define BL2_RAM_SIZE 0x00100000
+#define BL2_RAM_BASE (IMX7_OPTEE_BASE - BL2_RAM_SIZE)
+#define BL2_RAM_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE)
+
+/* Optional Mailbox. Only relevant on i.MX7D. 0x9deff000 - 0x9df00000*/
+#define SHARED_RAM_SIZE 0x00001000
+#define SHARED_RAM_BASE (BL2_RAM_BASE - SHARED_RAM_SIZE)
+#define SHARED_RAM_LIMIT (SHARED_RAM_BASE + SHARED_RAM_SIZE)
+
+/* Define the absolute location of u-boot 0x87800000 - 0x87900000 */
+#define IMX7_UBOOT_SIZE 0x00100000
+#define IMX7_UBOOT_BASE (DRAM_BASE + 0x7800000)
+#define IMX7_UBOOT_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE)
+
+/* Define FIP image absolute location 0x80000000 - 0x80100000 */
+#define IMX_FIP_SIZE 0x00100000
+#define IMX_FIP_BASE (DRAM_BASE)
+#define IMX_FIP_LIMIT (IMX_FIP_BASE + IMX_FIP_SIZE)
+
+/* Define FIP image location at 1MB offset */
+#define IMX_FIP_MMC_BASE (1024 * 1024)
+
+/* Define the absolute location of DTB 0x83000000 - 0x83100000 */
+#define IMX7_DTB_SIZE 0x00100000
+#define IMX7_DTB_BASE (DRAM_BASE + 0x03000000)
+#define IMX7_DTB_LIMIT (IMX7_DTB_BASE + IMX7_DTB_SIZE)
+
+/* Define the absolute location of DTB Overlay 0x83100000 - 0x83101000 */
+#define IMX7_DTB_OVERLAY_SIZE 0x00001000
+#define IMX7_DTB_OVERLAY_BASE IMX7_DTB_LIMIT
+#define IMX7_DTB_OVERLAY_LIMIT (IMX7_DTB_OVERLAY_BASE + \
+ IMX7_DTB_OVERLAY_SIZE)
+/*
+ * BL2 specific defines.
+ *
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define BL2_BASE BL2_RAM_BASE
+#define BL2_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE)
+
+/*
+ * BL3-2/OPTEE
+ */
+# define BL32_BASE IMX7_OPTEE_BASE
+# define BL32_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE)
+
+/*
+ * BL3-3/U-BOOT
+ */
+#define BL33_BASE IMX7_UBOOT_BASE
+#define BL33_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE)
+
+/*
+ * ATF's view of memory
+ *
+ * 0xa0000000 +-----------------+
+ * | DDR | BL32/OPTEE
+ * 0x9e000000 +-----------------+
+ * | DDR | BL23 ATF
+ * 0x9df00000 +-----------------+
+ * | DDR | Shared MBOX RAM
+ * 0x9de00000 +-----------------+
+ * | DDR | Unallocated
+ * 0x87900000 +-----------------+
+ * | DDR | BL33/U-BOOT
+ * 0x87800000 +-----------------+
+ * | DDR | Unallocated
+ * 0x83100000 +-----------------+
+ * | DDR | DTB
+ * 0x83000000 +-----------------+
+ * | DDR | Unallocated
+ * 0x80100000 +-----------------+
+ * | DDR | FIP
+ * 0x80000000 +-----------------+
+ * | SOC I/0 |
+ * 0x00a00000 +-----------------+
+ * | OCRAM | Not used
+ * 0x00900000 +-----------------+
+ * | SOC I/0 |
+ * 0x00188000 +-----------------+
+ * | OCRAM_S | Not used
+ * 0x00180000 +-----------------+
+ * | SOC I/0 |
+ * 0x00020000 +-----------------+
+ * | BootROM | BL1
+ * 0x00000000 +-----------------+
+ */
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_MMAP_REGIONS 10
+#define MAX_XLAT_TABLES 6
+#define MAX_IO_DEVICES 2
+#define MAX_IO_HANDLES 3
+#define MAX_IO_BLOCK_DEVICES 1
+
+/* UART defines */
+#define PLAT_IMX7_BOOT_UART_BASE MXC_UART5_BASE
+#define PLAT_IMX7_BOOT_UART_CLK_IN_HZ 24000000
+#define PLAT_IMX7_CONSOLE_BAUDRATE 115200
+
+/* MMC defines */
+#ifndef PLAT_PICOPI_SD
+#define PLAT_PICOPI_SD 3
+#endif
+
+#if PLAT_PICOPI_SD == 1
+#define PLAT_PICOPI_BOOT_MMC_BASE USDHC1_BASE
+#endif /* PLAT_PICOPI_SD == 1 */
+
+#if PLAT_PICOPI_SD == 2
+#define PLAT_PICOPI_BOOT_MMC_BASE USDHC2_BASE
+#endif /* PLAT_PICOPI_SD == 2 */
+
+#if PLAT_PICOPI_SD == 3
+#define PLAT_PICOPI_BOOT_MMC_BASE USDHC3_BASE
+#endif /* PLAT_PICOPI_SD == 3 */
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS 8000000 /* 8 MHz */
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c b/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c
new file mode 100644
index 0000000..2df96ae
--- /dev/null
+++ b/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/mmc.h>
+#include <lib/utils.h>
+
+#include <imx_caam.h>
+#include <imx_clock.h>
+#include <imx_io_mux.h>
+#include <imx_uart.h>
+#include <imx_usdhc.h>
+#include <imx7_def.h>
+
+#define UART5_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_UART5_CLK_ROOT_OSC_24M)
+
+#define USDHC_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AHB |\
+ CCM_TARGET_POST_PODF(2))
+
+#define USB_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL)
+
+#define PICOPI_UART5_RX_MUX \
+ IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_ALT1_UART5_RX_DATA
+
+#define PICOPI_UART5_TX_MUX \
+ IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_ALT1_UART5_TX_DATA
+
+#define PICOPI_SD3_FEATURES \
+ (IOMUXC_SW_PAD_CTL_PAD_SD3_PU_47K | \
+ IOMUXC_SW_PAD_CTL_PAD_SD3_PE | \
+ IOMUXC_SW_PAD_CTL_PAD_SD3_HYS | \
+ IOMUXC_SW_PAD_CTL_PAD_SD3_SLEW_SLOW | \
+ IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_3_X6)
+
+static struct mmc_device_info mmc_info;
+
+static void picopi_setup_pinmux(void)
+{
+ /* Configure UART5 TX */
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_I2C4_SDA_OFFSET,
+ PICOPI_UART5_TX_MUX);
+ /* Configure UART5 RX */
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_I2C4_SCL_OFFSET,
+ PICOPI_UART5_RX_MUX);
+
+ /* Configure USDHC3 */
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_CLK_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_CMD_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA0_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA1_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA2_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA3_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA4_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA5_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA6_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_SD3_DATA7_OFFSET, 0);
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_OFFSET,
+ IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO14_ALT1_SD3_CD_B);
+
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_CLK_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_CMD_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA0_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA1_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA2_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA3_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA4_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA5_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA6_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_SD3_DATA7_OFFSET,
+ PICOPI_SD3_FEATURES);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO14_OFFSET,
+ PICOPI_SD3_FEATURES);
+}
+
+static void picopi_usdhc_setup(void)
+{
+ imx_usdhc_params_t params;
+
+ zeromem(&params, sizeof(imx_usdhc_params_t));
+ params.reg_base = PLAT_PICOPI_BOOT_MMC_BASE;
+ params.clk_rate = 25000000;
+ params.bus_width = MMC_BUS_WIDTH_8;
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ imx_usdhc_init(&params, &mmc_info);
+}
+
+static void picopi_setup_usb_clocks(void)
+{
+ uint32_t usb_en_bits = (uint32_t)USB_CLK_SELECT;
+
+ imx_clock_set_usb_clk_root_bits(usb_en_bits);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_IPG);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_PHY_480MCLK);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG1_PHY);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG2_PHY);
+}
+
+void imx7_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ uint32_t uart5_en_bits = (uint32_t)UART5_CLK_SELECT;
+ uint32_t usdhc_clock_sel = PLAT_PICOPI_SD - 1;
+
+ /* Initialize clocks etc */
+ imx_clock_enable_uart(4, uart5_en_bits);
+ imx_clock_enable_usdhc(usdhc_clock_sel, USDHC_CLK_SELECT);
+
+ picopi_setup_usb_clocks();
+
+ /* Setup pin-muxes */
+ picopi_setup_pinmux();
+
+ picopi_usdhc_setup();
+}
diff --git a/plat/imx/imx7/picopi/platform.mk b/plat/imx/imx7/picopi/platform.mk
new file mode 100644
index 0000000..5901001
--- /dev/null
+++ b/plat/imx/imx7/picopi/platform.mk
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Include imx7 common
+include plat/imx/imx7/common/imx7.mk
+
+# Platform
+PLAT_INCLUDES += -Iplat/imx/imx7/picopi/include \
+
+BL2_SOURCES += drivers/imx/usdhc/imx_usdhc.c \
+ plat/imx/imx7/picopi/picopi_bl2_el3_setup.c \
+
+# Build config flags
+# ------------------
+
+ARM_CORTEX_A7 := yes
+WORKAROUND_CVE_2017_5715 := 0
+
+RESET_TO_BL31 := 0
+
+# Non-TF Boot ROM
+BL2_AT_EL3 := 1
+
+# Indicate single-core
+COLD_BOOT_SINGLE_CPU := 1
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Use multi console API
+MULTI_CONSOLE_API := 1
+
+PLAT_PICOPI_UART :=5
+$(eval $(call add_define,PLAT_PICOPI_UART))
diff --git a/plat/imx/imx7/warp7/include/platform_def.h b/plat/imx/imx7/warp7/include/platform_def.h
new file mode 100644
index 0000000..683e50d
--- /dev/null
+++ b/plat/imx/imx7/warp7/include/platform_def.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_STACK_SIZE 0x1000
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \
+ PLATFORM_CLUSTER1_CORE_COUNT)
+
+#define WARP7_PRIMARY_CPU U(0)
+
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+
+#define PLAT_MAX_RET_STATE 1
+#define PLAT_MAX_OFF_STATE 2
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN 0
+
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET 1
+
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF 2
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH 4
+#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ * i.MX7 has a 32 byte cacheline size
+ * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016 pg 244
+ */
+#define CACHE_WRITEBACK_SHIFT 4
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Partition memory into secure BootROM, OCRAM_S, non-secure DRAM, secure DRAM
+ */
+#define BOOT_ROM_BASE 0x00000000
+#define BOOT_ROM_SIZE 0x00020000
+
+#define OCRAM_S_BASE 0x00180000
+#define OCRAM_S_SIZE 0x00008000
+
+/* Controller maps 2GB, board contains 512 MB. 0x80000000 - 0xa0000000 */
+#define DRAM_BASE 0x80000000
+#define DRAM_SIZE 0x20000000
+#define DRAM_LIMIT (DRAM_BASE + DRAM_SIZE)
+
+/* Place OPTEE at minus 32 MB from the end of memory. 0x9e000000 - 0xa0000000 */
+#define IMX7_OPTEE_SIZE 0x02000000
+#define IMX7_OPTEE_BASE (DRAM_LIMIT - IMX7_OPTEE_SIZE)
+#define IMX7_OPTEE_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE)
+
+/* Place ATF directly beneath OPTEE. 0x9df00000 - 0x9e000000 */
+#define BL2_RAM_SIZE 0x00100000
+#define BL2_RAM_BASE (IMX7_OPTEE_BASE - BL2_RAM_SIZE)
+#define BL2_RAM_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE)
+
+/* Optional Mailbox. Only relevant on i.MX7D. 0x9deff000 - 0x9df00000*/
+#define SHARED_RAM_SIZE 0x00001000
+#define SHARED_RAM_BASE (BL2_RAM_BASE - SHARED_RAM_SIZE)
+#define SHARED_RAM_LIMIT (SHARED_RAM_BASE + SHARED_RAM_SIZE)
+
+/* Define the absolute location of u-boot 0x87800000 - 0x87900000 */
+#define IMX7_UBOOT_SIZE 0x00100000
+#define IMX7_UBOOT_BASE (DRAM_BASE + 0x7800000)
+#define IMX7_UBOOT_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE)
+
+/* Define FIP image absolute location 0x80000000 - 0x80100000 */
+#define IMX_FIP_SIZE 0x00100000
+#define IMX_FIP_BASE (DRAM_BASE)
+#define IMX_FIP_LIMIT (IMX_FIP_BASE + IMX_FIP_SIZE)
+
+/* Define FIP image location at 1MB offset */
+#define IMX_FIP_MMC_BASE (1024 * 1024)
+
+/* Define the absolute location of DTB 0x83000000 - 0x83100000 */
+#define IMX7_DTB_SIZE 0x00100000
+#define IMX7_DTB_BASE (DRAM_BASE + 0x03000000)
+#define IMX7_DTB_LIMIT (IMX7_DTB_BASE + IMX7_DTB_SIZE)
+
+/* Define the absolute location of DTB Overlay 0x83100000 - 0x83101000 */
+#define IMX7_DTB_OVERLAY_SIZE 0x00001000
+#define IMX7_DTB_OVERLAY_BASE IMX7_DTB_LIMIT
+#define IMX7_DTB_OVERLAY_LIMIT (IMX7_DTB_OVERLAY_BASE + \
+ IMX7_DTB_OVERLAY_SIZE)
+
+/*
+ * BL2 specific defines.
+ *
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define BL2_BASE BL2_RAM_BASE
+#define BL2_LIMIT (BL2_RAM_BASE + BL2_RAM_SIZE)
+
+/*
+ * BL3-2/OPTEE
+ */
+# define BL32_BASE IMX7_OPTEE_BASE
+# define BL32_LIMIT (IMX7_OPTEE_BASE + IMX7_OPTEE_SIZE)
+
+/*
+ * BL3-3/U-BOOT
+ */
+#define BL33_BASE IMX7_UBOOT_BASE
+#define BL33_LIMIT (IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE)
+
+/*
+ * ATF's view of memory
+ *
+ * 0xa0000000 +-----------------+
+ * | DDR | BL32/OPTEE
+ * 0x9e000000 +-----------------+
+ * | DDR | BL23 ATF
+ * 0x9df00000 +-----------------+
+ * | DDR | Shared MBOX RAM
+ * 0x9de00000 +-----------------+
+ * | DDR | Unallocated
+ * 0x87900000 +-----------------+
+ * | DDR | BL33/U-BOOT
+ * 0x87800000 +-----------------+
+ * | DDR | Unallocated
+ * 0x83101000 +-----------------+
+ * | DDR | DTB Overlay
+ * 0x83100000 +-----------------+
+ * | DDR | DTB
+ * 0x83000000 +-----------------+
+ * | DDR | Unallocated
+ * 0x80100000 +-----------------+
+ * | DDR | FIP
+ * 0x80000000 +-----------------+
+ * | SOC I/0 |
+ * 0x00a00000 +-----------------+
+ * | OCRAM | Not used
+ * 0x00900000 +-----------------+
+ * | SOC I/0 |
+ * 0x00188000 +-----------------+
+ * | OCRAM_S | Not used
+ * 0x00180000 +-----------------+
+ * | SOC I/0 |
+ * 0x00020000 +-----------------+
+ * | BootROM | BL1
+ * 0x00000000 +-----------------+
+ */
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_MMAP_REGIONS 10
+#define MAX_XLAT_TABLES 6
+#define MAX_IO_DEVICES 2
+#define MAX_IO_HANDLES 3
+#define MAX_IO_BLOCK_DEVICES 1U
+
+/* UART defines */
+#if PLAT_WARP7_UART == 1
+#define PLAT_WARP7_UART_BASE MXC_UART1_BASE
+#elif PLAT_WARP7_UART == 6
+#define IMX_UART_DTE
+#define PLAT_WARP7_UART_BASE MXC_UART6_BASE
+#else
+#error "define PLAT_WARP7_UART=1 or PLAT_WARP7_UART=6"
+#endif
+
+#define PLAT_IMX7_BOOT_UART_BASE PLAT_WARP7_UART_BASE
+#define PLAT_IMX7_BOOT_UART_CLK_IN_HZ 24000000
+#define PLAT_IMX7_CONSOLE_BAUDRATE 115200
+
+/* MMC defines */
+#ifndef PLAT_WARP7_SD
+#define PLAT_WARP7_SD 3
+#endif
+
+#if PLAT_WARP7_SD == 1
+#define PLAT_WARP7_BOOT_MMC_BASE USDHC1_BASE
+#endif /* PLAT_WARP7_SD == 1 */
+
+#if PLAT_WARP7_SD == 2
+#define PLAT_WARP7_BOOT_MMC_BASE USDHC2_BASE
+#endif /* PLAT_WARP7_SD == 2 */
+
+#if PLAT_WARP7_SD == 3
+#define PLAT_WARP7_BOOT_MMC_BASE USDHC3_BASE
+#endif /* PLAT_WARP7_SD == 3 */
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS 8000000 /* 8 MHz */
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/imx/imx7/warp7/platform.mk b/plat/imx/imx7/warp7/platform.mk
new file mode 100644
index 0000000..ea0f001
--- /dev/null
+++ b/plat/imx/imx7/warp7/platform.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Include imx7 common
+include plat/imx/imx7/common/imx7.mk
+
+# Platform
+PLAT_INCLUDES += -Iplat/imx/imx7/warp7/include
+
+BL2_SOURCES += drivers/imx/usdhc/imx_usdhc.c \
+ plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
+
+# Build config flags
+# ------------------
+
+ARM_CORTEX_A7 := yes
+WORKAROUND_CVE_2017_5715 := 0
+
+RESET_TO_BL31 := 0
+
+# Non-TF Boot ROM
+BL2_AT_EL3 := 1
+
+# Indicate single-core
+COLD_BOOT_SINGLE_CPU := 1
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+PLAT_WARP7_UART :=1
+$(eval $(call add_define,PLAT_WARP7_UART))
diff --git a/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c b/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
new file mode 100644
index 0000000..ec13ade
--- /dev/null
+++ b/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/mmc.h>
+#include <lib/utils.h>
+
+#include <imx_caam.h>
+#include <imx_clock.h>
+#include <imx_io_mux.h>
+#include <imx_uart.h>
+#include <imx_usdhc.h>
+#include <imx7_def.h>
+
+#define UART1_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_UART1_CLK_ROOT_OSC_24M)
+
+#define UART6_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_UART6_CLK_ROOT_OSC_24M)
+
+#define USDHC_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_NAND_USDHC_BUS_CLK_ROOT_AHB |\
+ CCM_TARGET_POST_PODF(2))
+
+#define USB_CLK_SELECT (CCM_TARGET_ROOT_ENABLE |\
+ CCM_TRGT_MUX_USB_HSIC_CLK_ROOT_SYS_PLL)
+
+#define WARP7_UART1_TX_MUX \
+ IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_ALT0_UART1_TX_DATA
+
+#define WARP7_UART1_TX_FEATURES \
+ (IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PS_3_100K_PU | \
+ IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_PE_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_HYS_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_DSE_1_X4)
+
+#define WARP7_UART1_RX_MUX \
+ IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_ALT0_UART1_RX_DATA
+
+#define WARP7_UART1_RX_FEATURES \
+ (IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PS_3_100K_PU | \
+ IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_PE_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_HYS_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_DSE_1_X4)
+
+#define WARP7_UART6_TX_MUX \
+ IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_ALT1_UART6_TX_DATA
+
+#define WARP7_UART6_TX_FEATURES \
+ (IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PS_3_100K_PU | \
+ IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_PE_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_HYS_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_DSE_1_X4)
+
+#define WARP7_UART6_RX_MUX \
+ IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_ALT1_UART6_RX_DATA
+
+#define WARP7_UART6_RX_FEATURES \
+ (IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PS_3_100K_PU | \
+ IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_PE_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_HYS_EN | \
+ IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_1_X4)
+
+static struct mmc_device_info mmc_info;
+
+static void warp7_setup_pinmux(void)
+{
+ /* Configure UART1 TX */
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA_OFFSET,
+ WARP7_UART1_TX_MUX);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_UART1_TX_DATA_OFFSET,
+ WARP7_UART1_TX_FEATURES);
+
+ /* Configure UART1 RX */
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA_OFFSET,
+ WARP7_UART1_RX_MUX);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_UART1_RX_DATA_OFFSET,
+ WARP7_UART1_RX_FEATURES);
+
+ /* Configure UART6 TX */
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_ECSPI1_MOSI_OFFSET,
+ WARP7_UART6_TX_MUX);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_ECSPI1_MOSI_OFFSET,
+ WARP7_UART6_TX_FEATURES);
+
+ /* Configure UART6 RX */
+ imx_io_muxc_set_pad_alt_function(IOMUXC_SW_MUX_CTL_PAD_ECSPI1_SCLK_OFFSET,
+ WARP7_UART6_RX_MUX);
+ imx_io_muxc_set_pad_features(IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_OFFSET,
+ WARP7_UART6_RX_FEATURES);
+}
+
+static void warp7_usdhc_setup(void)
+{
+ imx_usdhc_params_t params;
+
+ zeromem(&params, sizeof(imx_usdhc_params_t));
+ params.reg_base = PLAT_WARP7_BOOT_MMC_BASE;
+ params.clk_rate = 25000000;
+ params.bus_width = MMC_BUS_WIDTH_8;
+ mmc_info.mmc_dev_type = MMC_IS_EMMC;
+ imx_usdhc_init(&params, &mmc_info);
+}
+
+static void warp7_setup_usb_clocks(void)
+{
+ uint32_t usb_en_bits = (uint32_t)USB_CLK_SELECT;
+
+ imx_clock_set_usb_clk_root_bits(usb_en_bits);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_IPG);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_PHY_480MCLK);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG1_PHY);
+ imx_clock_enable_usb(CCM_CCGR_ID_USB_OTG2_PHY);
+}
+
+void imx7_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ uint32_t uart1_en_bits = (uint32_t)UART1_CLK_SELECT;
+ uint32_t uart6_en_bits = (uint32_t)UART6_CLK_SELECT;
+ uint32_t usdhc_clock_sel = PLAT_WARP7_SD - 1;
+
+ /* Initialize clocks etc */
+ imx_clock_enable_uart(0, uart1_en_bits);
+ imx_clock_enable_uart(5, uart6_en_bits);
+
+ imx_clock_enable_usdhc(usdhc_clock_sel, USDHC_CLK_SELECT);
+
+ warp7_setup_usb_clocks();
+
+ /* Setup pin-muxes */
+ warp7_setup_pinmux();
+
+ warp7_usdhc_setup();
+}
diff --git a/plat/imx/imx8m/ddr/clock.c b/plat/imx/imx8m/ddr/clock.c
new file mode 100644
index 0000000..7fb5730
--- /dev/null
+++ b/plat/imx/imx8m/ddr/clock.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define IMX_CCM_IP_BASE (IMX_CCM_BASE + 0xa000)
+#define DRAM_SEL_CFG (IMX_CCM_BASE + 0x9800)
+#define CCM_IP_CLK_ROOT_GEN_TAGET(i) (IMX_CCM_IP_BASE + 0x80 * (i) + 0x00)
+#define CCM_IP_CLK_ROOT_GEN_TAGET_SET(i) (IMX_CCM_IP_BASE + 0x80 * (i) + 0x04)
+#define CCM_IP_CLK_ROOT_GEN_TAGET_CLR(i) (IMX_CCM_IP_BASE + 0x80 * (i) + 0x08)
+#define PLL_FREQ_800M U(0x00ece580)
+#define PLL_FREQ_400M U(0x00ec6984)
+#define PLL_FREQ_167M U(0x00f5a406)
+
+void ddr_pll_bypass_100mts(void)
+{
+ /* change the clock source of dram_alt_clk_root to source 2 --100MHz */
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16));
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x2 << 24));
+
+ /* change the clock source of dram_apb_clk_root to source 2 --40MHz/2 */
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x2 << 24) | (0x1 << 16));
+
+ /* configure pll bypass mode */
+ mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24));
+}
+
+void ddr_pll_bypass_400mts(void)
+{
+ /* change the clock source of dram_alt_clk_root to source 1 --400MHz */
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(0), (0x7 << 24) | (0x7 << 16));
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(0), (0x1 << 24) | (0x1 << 16));
+
+ /* change the clock source of dram_apb_clk_root to source 3 --160MHz/2 */
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x3 << 24) | (0x1 << 16));
+
+ /* configure pll bypass mode */
+ mmio_write_32(DRAM_SEL_CFG + 0x4, BIT(24));
+}
+
+void ddr_pll_unbypass(void)
+{
+ mmio_write_32(DRAM_SEL_CFG + 0x8, BIT(24));
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(1), (0x7 << 24) | (0x7 << 16));
+ /* to source 4 --800MHz/5 */
+ mmio_write_32(CCM_IP_CLK_ROOT_GEN_TAGET_SET(1), (0x4 << 24) | (0x4 << 16));
+}
+
+#if defined(PLAT_imx8mq)
+void dram_pll_init(unsigned int drate)
+{
+ /* bypass the PLL */
+ mmio_setbits_32(HW_DRAM_PLL_CFG0, 0x30);
+
+ switch (drate) {
+ case 3200:
+ mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_800M);
+ break;
+ case 1600:
+ mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_400M);
+ break;
+ case 667:
+ mmio_write_32(HW_DRAM_PLL_CFG2, PLL_FREQ_167M);
+ break;
+ default:
+ break;
+ }
+
+ /* unbypass the PLL */
+ mmio_clrbits_32(HW_DRAM_PLL_CFG0, 0x30);
+ while (!(mmio_read_32(HW_DRAM_PLL_CFG0) & (1 << 31))) {
+ ;
+ }
+}
+#else
+void dram_pll_init(unsigned int drate)
+{
+ /* bypass the PLL */
+ mmio_setbits_32(DRAM_PLL_CTRL, (1 << 16));
+ mmio_clrbits_32(DRAM_PLL_CTRL, (1 << 9));
+
+ switch (drate) {
+ case 2400:
+ mmio_write_32(DRAM_PLL_CTRL + 0x4, (300 << 12) | (3 << 4) | 2);
+ break;
+ case 1600:
+ mmio_write_32(DRAM_PLL_CTRL + 0x4, (400 << 12) | (3 << 4) | 3);
+ break;
+ case 1066:
+ mmio_write_32(DRAM_PLL_CTRL + 0x4, (266 << 12) | (3 << 4) | 3);
+ break;
+ case 667:
+ mmio_write_32(DRAM_PLL_CTRL + 0x4, (334 << 12) | (3 << 4) | 4);
+ break;
+ default:
+ break;
+ }
+
+ mmio_setbits_32(DRAM_PLL_CTRL, BIT(9));
+ /* wait for PLL locked */
+ while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) {
+ ;
+ }
+
+ /* unbypass the PLL */
+ mmio_clrbits_32(DRAM_PLL_CTRL, BIT(16));
+}
+#endif
+
+/* change the dram clock frequency */
+void dram_clock_switch(unsigned int target_drate, bool bypass_mode)
+{
+ if (bypass_mode) {
+ switch (target_drate) {
+ case 400:
+ ddr_pll_bypass_400mts();
+ break;
+ case 100:
+ ddr_pll_bypass_100mts();
+ break;
+ default:
+ ddr_pll_unbypass();
+ break;
+ }
+ } else {
+ dram_pll_init(target_drate);
+ }
+}
diff --git a/plat/imx/imx8m/ddr/ddr4_dvfs.c b/plat/imx/imx8m/ddr/ddr4_dvfs.c
new file mode 100644
index 0000000..cdc7dc2
--- /dev/null
+++ b/plat/imx/imx8m/ddr/ddr4_dvfs.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <dram.h>
+
+void ddr4_mr_write(uint32_t mr, uint32_t data, uint32_t mr_type, uint32_t rank)
+{
+ uint32_t val, mr_mirror, data_mirror;
+
+ /*
+ * 1. Poll MRSTAT.mr_wr_busy until it is 0 to make sure
+ * that there is no outstanding MR transAction.
+ */
+ while (mmio_read_32(DDRC_MRSTAT(0)) & 0x1) {
+ ;
+ }
+
+ /*
+ * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank
+ * and (for MRWs) MRCTRL1.mr_data to define the MR transaction.
+ */
+ val = mmio_read_32(DDRC_DIMMCTL(0));
+ if ((val & 0x2) && (rank == 0x2)) {
+ mr_mirror = (mr & 0x4) | ((mr & 0x1) << 1) | ((mr & 0x2) >> 1); /* BA0, BA1 swap */
+ data_mirror = (data & 0x1607) | ((data & 0x8) << 1) | ((data & 0x10) >> 1) |
+ ((data & 0x20) << 1) | ((data & 0x40) >> 1) | ((data & 0x80) << 1) |
+ ((data & 0x100) >> 1) | ((data & 0x800) << 2) | ((data & 0x2000) >> 2) ;
+ } else {
+ mr_mirror = mr;
+ data_mirror = data;
+ }
+
+ mmio_write_32(DDRC_MRCTRL0(0), mr_type | (mr_mirror << 12) | (rank << 4));
+ mmio_write_32(DDRC_MRCTRL1(0), data_mirror);
+
+ /*
+ * 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1.
+ * This bit is self-clearing, and triggers the MR transaction.
+ * The uMCTL2 then asserts the MRSTAT.mr_wr_busy while it performs
+ * the MR transaction to SDRAM, and no further accesses can be
+ * initiated until it is deasserted.
+ */
+ mmio_setbits_32(DDRC_MRCTRL0(0), BIT(31));
+
+ while (mmio_read_32(DDRC_MRSTAT(0))) {
+ ;
+ }
+}
+
+void dram_cfg_all_mr(struct dram_info *info, uint32_t pstate)
+{
+ uint32_t num_rank = info->num_rank;
+ /*
+ * 15. Perform MRS commands as required to re-program
+ * timing registers in the SDRAM for the new frequency
+ * (in particular, CL, CWL and WR may need to be changed).
+ */
+
+ for (int i = 1; i <= num_rank; i++) {
+ for (int j = 0; j < 6; j++) {
+ ddr4_mr_write(j, info->mr_table[pstate][j], 0, i);
+ }
+ ddr4_mr_write(6, info->mr_table[pstate][7], 0, i);
+ }
+}
+
+void sw_pstate(uint32_t pstate, uint32_t drate)
+{
+ uint32_t val;
+
+ mmio_write_32(DDRC_SWCTL(0), 0x0);
+
+ /*
+ * Update any registers which may be required to
+ * change for the new frequency.
+ */
+ mmio_write_32(DDRC_MSTR2(0), pstate);
+ mmio_setbits_32(DDRC_MSTR(0), (0x1 << 29));
+
+ /*
+ * Toggle RFSHCTL3.refresh_update_level to allow the
+ * new refresh-related register values to propagate
+ * to the refresh logic.
+ */
+ val = mmio_read_32(DDRC_RFSHCTL3(0));
+ if (val & 0x2) {
+ mmio_write_32(DDRC_RFSHCTL3(0), val & 0xFFFFFFFD);
+ } else {
+ mmio_write_32(DDRC_RFSHCTL3(0), val | 0x2);
+ }
+
+ /*
+ * 19. If required, trigger the initialization in the PHY.
+ * If using the gen2 multiPHY, PLL initialization should
+ * be triggered at this point. See the PHY databook for
+ * details about the frequency change procedure.
+ */
+ mmio_write_32(DDRC_DFIMISC(0), 0x00000000 | (pstate << 8));
+ mmio_write_32(DDRC_DFIMISC(0), 0x00000020 | (pstate << 8));
+
+ /* wait DFISTAT.dfi_init_complete to 0 */
+ while (mmio_read_32(DDRC_DFISTAT(0)) & 0x1) {
+ ;
+ }
+
+ /* change the clock to the target frequency */
+ dram_clock_switch(drate, false);
+
+ mmio_write_32(DDRC_DFIMISC(0), 0x00000000 | (pstate << 8));
+
+ /* wait DFISTAT.dfi_init_complete to 1 */
+ while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
+ ;
+ }
+
+ /*
+ * When changing frequencies the controller may violate the JEDEC
+ * requirement that no more than 16 refreshes should be issued within
+ * 2*tREFI. These extra refreshes are not expected to cause a problem
+ * in the SDRAM. This issue can be avoided by waiting for at least 2*tREFI
+ * before exiting self-refresh in step 19.
+ */
+ udelay(14);
+
+ /* 14. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */
+ mmio_clrbits_32(DDRC_PWRCTL(0), (1 << 5));
+
+ while ((mmio_read_32(DDRC_STAT(0)) & 0x3f) == 0x23) {
+ ;
+ }
+}
+
+void ddr4_swffc(struct dram_info *info, unsigned int pstate)
+{
+ uint32_t drate = info->timing_info->fsp_table[pstate];
+
+ /*
+ * 1. set SWCTL.sw_done to disable quasi-dynamic register
+ * programming outside reset.
+ */
+ mmio_write_32(DDRC_SWCTL(0), 0x0);
+
+ /*
+ * 2. Write 0 to PCTRL_n.port_en. This blocks AXI port(s)
+ * from taking any transaction (blocks traffic on AXI ports).
+ */
+ mmio_write_32(DDRC_PCTRL_0(0), 0x0);
+
+ /*
+ * 3. Poll PSTAT.rd_port_busy_n=0 and PSTAT.wr_port_busy_n=0.
+ * Wait until all AXI ports are idle (the uMCTL2 core has to
+ * be idle).
+ */
+ while (mmio_read_32(DDRC_PSTAT(0)) & 0x10001) {
+ ;
+ }
+
+ /*
+ * 4. Write 0 to SBRCTL.scrub_en. Disable SBR, required only if
+ * SBR instantiated.
+ * 5. Poll SBRSTAT.scrub_busy=0.
+ * 6. Set DERATEEN.derate_enable = 0, if DERATEEN.derate_eanble = 1
+ * and the read latency (RL) value needs to change after the frequency
+ * change (LPDDR2/3/4 only).
+ * 7. Set DBG1.dis_hif=1 so that no new commands will be accepted by the uMCTL2.
+ */
+ mmio_setbits_32(DDRC_DBG1(0), (0x1 << 1));
+
+ /*
+ * 8. Poll DBGCAM.dbg_wr_q_empty and DBGCAM.dbg_rd_q_empty to ensure
+ * that write and read data buffers are empty.
+ */
+ while ((mmio_read_32(DDRC_DBGCAM(0)) & 0x06000000) != 0x06000000) {
+ ;
+ }
+
+ /*
+ * 9. For DDR4, update MR6 with the new tDLLK value via the Mode
+ * Register Write signals
+ * 10. Set DFILPCFG0.dfi_lp_en_sr = 0, if DFILPCFG0.dfi_lp_en_sr = 1,
+ * and wait until DFISTAT.dfi_lp_ack
+ * 11. If DFI PHY Master interface is active in uMCTL2, then disable it
+ * 12. Wait until STAT.operating_mode[1:0]!=11 indicating that the
+ * controller is not in self-refresh mode.
+ */
+ while ((mmio_read_32(DDRC_STAT(0)) & 0x3) == 0x3) {
+ ;
+ }
+
+ /*
+ * 13. Assert PWRCTL.selfref_sw for the DWC_ddr_umctl2 core to enter
+ * the self-refresh mode.
+ */
+ mmio_setbits_32(DDRC_PWRCTL(0), (1 << 5));
+
+ /*
+ * 14. Wait until STAT.operating_mode[1:0]==11 indicating that the
+ * controller core is in self-refresh mode.
+ */
+ while ((mmio_read_32(DDRC_STAT(0)) & 0x3f) != 0x23) {
+ ;
+ }
+
+ sw_pstate(pstate, drate);
+ dram_cfg_all_mr(info, pstate);
+
+ /* 23. Enable HIF commands by setting DBG1.dis_hif=0. */
+ mmio_clrbits_32(DDRC_DBG1(0), (0x1 << 1));
+
+ /*
+ * 24. Reset DERATEEN.derate_enable = 1 if DERATEEN.derate_enable
+ * has been set to 0 in step 6.
+ * 25. If DFI PHY Master interface was active before step 11 then
+ * enable it back by programming DFIPHYMSTR.phymstr_en = 1'b1.
+ * 26. Write 1 to PCTRL_n.port_en. AXI port(s) are no longer blocked
+ * from taking transactions (Re-enable traffic on AXI ports)
+ */
+ mmio_write_32(DDRC_PCTRL_0(0), 0x1);
+
+ /*
+ * 27. Write 1 to SBRCTL.scrub_en. Enable SBR if desired, only
+ * required if SBR instantiated.
+ */
+
+ /*
+ * set SWCTL.sw_done to enable quasi-dynamic register programming
+ * outside reset.
+ */
+ mmio_write_32(DDRC_SWCTL(0), 0x1);
+
+ /* wait SWSTAT.sw_done_ack to 1 */
+ while (!(mmio_read_32(DDRC_SWSTAT(0)) & 0x1)) {
+ ;
+ }
+}
diff --git a/plat/imx/imx8m/ddr/dram.c b/plat/imx/imx8m/ddr/dram.c
new file mode 100644
index 0000000..8ea9ba1
--- /dev/null
+++ b/plat/imx/imx8m/ddr/dram.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl31/interrupt_mgmt.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+
+#include <dram.h>
+
+#define IMX_SIP_DDR_DVFS_GET_FREQ_COUNT 0x10
+#define IMX_SIP_DDR_DVFS_GET_FREQ_INFO 0x11
+
+struct dram_info dram_info;
+
+/* lock used for DDR DVFS */
+spinlock_t dfs_lock;
+
+static volatile uint32_t wfe_done;
+static volatile bool wait_ddrc_hwffc_done = true;
+static unsigned int dev_fsp = 0x1;
+
+static uint32_t fsp_init_reg[3][4] = {
+ { DDRC_INIT3(0), DDRC_INIT4(0), DDRC_INIT6(0), DDRC_INIT7(0) },
+ { DDRC_FREQ1_INIT3(0), DDRC_FREQ1_INIT4(0), DDRC_FREQ1_INIT6(0), DDRC_FREQ1_INIT7(0) },
+ { DDRC_FREQ2_INIT3(0), DDRC_FREQ2_INIT4(0), DDRC_FREQ2_INIT6(0), DDRC_FREQ2_INIT7(0) },
+};
+
+static void get_mr_values(uint32_t (*mr_value)[8])
+{
+ uint32_t init_val;
+ unsigned int i, fsp_index;
+
+ for (fsp_index = 0U; fsp_index < 3U; fsp_index++) {
+ for (i = 0U; i < 4U; i++) {
+ init_val = mmio_read_32(fsp_init_reg[fsp_index][i]);
+ mr_value[fsp_index][2*i] = init_val >> 16;
+ mr_value[fsp_index][2*i + 1] = init_val & 0xFFFF;
+ }
+ }
+}
+
+/* Restore the ddrc configs */
+void dram_umctl2_init(struct dram_timing_info *timing)
+{
+ struct dram_cfg_param *ddrc_cfg = timing->ddrc_cfg;
+ unsigned int i;
+
+ for (i = 0U; i < timing->ddrc_cfg_num; i++) {
+ mmio_write_32(ddrc_cfg->reg, ddrc_cfg->val);
+ ddrc_cfg++;
+ }
+
+ /* set the default fsp to P0 */
+ mmio_write_32(DDRC_MSTR2(0), 0x0);
+}
+
+/* Restore the dram PHY config */
+void dram_phy_init(struct dram_timing_info *timing)
+{
+ struct dram_cfg_param *cfg = timing->ddrphy_cfg;
+ unsigned int i;
+
+ /* Restore the PHY init config */
+ cfg = timing->ddrphy_cfg;
+ for (i = 0U; i < timing->ddrphy_cfg_num; i++) {
+ dwc_ddrphy_apb_wr(cfg->reg, cfg->val);
+ cfg++;
+ }
+
+ /* Restore the DDR PHY CSRs */
+ cfg = timing->ddrphy_trained_csr;
+ for (i = 0U; i < timing->ddrphy_trained_csr_num; i++) {
+ dwc_ddrphy_apb_wr(cfg->reg, cfg->val);
+ cfg++;
+ }
+
+ /* Load the PIE image */
+ cfg = timing->ddrphy_pie;
+ for (i = 0U; i < timing->ddrphy_pie_num; i++) {
+ dwc_ddrphy_apb_wr(cfg->reg, cfg->val);
+ cfg++;
+ }
+}
+
+/* EL3 SGI-8 IPI handler for DDR Dynamic frequency scaling */
+static uint64_t waiting_dvfs(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+ uint32_t irq;
+
+ irq = plat_ic_acknowledge_interrupt();
+ if (irq < 1022U) {
+ plat_ic_end_of_interrupt(irq);
+ }
+
+ /* set the WFE done status */
+ spin_lock(&dfs_lock);
+ wfe_done |= (1 << cpu_id * 8);
+ dsb();
+ spin_unlock(&dfs_lock);
+
+ while (1) {
+ /* ddr frequency change done */
+ if (!wait_ddrc_hwffc_done)
+ break;
+
+ wfe();
+ }
+
+ return 0;
+}
+
+void dram_info_init(unsigned long dram_timing_base)
+{
+ uint32_t ddrc_mstr, current_fsp;
+ unsigned int idx = 0;
+ uint32_t flags = 0;
+ uint32_t rc;
+ unsigned int i;
+
+ /* Get the dram type & rank */
+ ddrc_mstr = mmio_read_32(DDRC_MSTR(0));
+
+ dram_info.dram_type = ddrc_mstr & DDR_TYPE_MASK;
+ dram_info.num_rank = (ddrc_mstr >> 24) & ACTIVE_RANK_MASK;
+
+ /* Get current fsp info */
+ current_fsp = mmio_read_32(DDRC_DFIMISC(0)) & 0xf;
+ dram_info.boot_fsp = current_fsp;
+ dram_info.current_fsp = current_fsp;
+
+ get_mr_values(dram_info.mr_table);
+
+ dram_info.timing_info = (struct dram_timing_info *)dram_timing_base;
+
+ /* get the num of supported fsp */
+ for (i = 0U; i < 4U; ++i) {
+ if (!dram_info.timing_info->fsp_table[i]) {
+ break;
+ }
+ idx = i;
+ }
+ dram_info.num_fsp = i;
+
+ /* check if has bypass mode support */
+ if (dram_info.timing_info->fsp_table[idx] < 666) {
+ dram_info.bypass_mode = true;
+ } else {
+ dram_info.bypass_mode = false;
+ }
+
+ /* Register the EL3 handler for DDR DVFS */
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_EL3, waiting_dvfs, flags);
+ if (rc != 0) {
+ panic();
+ }
+}
+
+
+/*
+ * For each freq return the following info:
+ *
+ * r1: data rate
+ * r2: 1 + dram_core parent
+ * r3: 1 + dram_alt parent index
+ * r4: 1 + dram_apb parent index
+ *
+ * The parent indices can be used by an OS who manages source clocks to enabled
+ * them ahead of the switch.
+ *
+ * A parent value of "0" means "don't care".
+ *
+ * Current implementation of freq switch is hardcoded in
+ * plat/imx/common/imx8m/clock.c but in theory this can be enhanced to support
+ * a wide variety of rates.
+ */
+int dram_dvfs_get_freq_info(void *handle, u_register_t index)
+{
+ switch (index) {
+ case 0:
+ SMC_RET4(handle, dram_info.timing_info->fsp_table[0],
+ 1, 0, 5);
+ case 1:
+ if (!dram_info.bypass_mode) {
+ SMC_RET4(handle, dram_info.timing_info->fsp_table[1],
+ 1, 0, 0);
+ }
+ SMC_RET4(handle, dram_info.timing_info->fsp_table[1],
+ 2, 2, 4);
+ case 2:
+ if (!dram_info.bypass_mode) {
+ SMC_RET4(handle, dram_info.timing_info->fsp_table[2],
+ 1, 0, 0);
+ }
+ SMC_RET4(handle, dram_info.timing_info->fsp_table[2],
+ 2, 3, 3);
+ case 3:
+ SMC_RET4(handle, dram_info.timing_info->fsp_table[3],
+ 1, 0, 0);
+ default:
+ SMC_RET1(handle, -3);
+ }
+}
+
+int dram_dvfs_handler(uint32_t smc_fid, void *handle,
+ u_register_t x1, u_register_t x2, u_register_t x3)
+{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+ unsigned int fsp_index = x1;
+ uint32_t online_cores = x2;
+
+ if (x1 == IMX_SIP_DDR_DVFS_GET_FREQ_COUNT) {
+ SMC_RET1(handle, dram_info.num_fsp);
+ } else if (x1 == IMX_SIP_DDR_DVFS_GET_FREQ_INFO) {
+ return dram_dvfs_get_freq_info(handle, x2);
+ } else if (x1 < 4) {
+ wait_ddrc_hwffc_done = true;
+ dsb();
+
+ /* trigger the SGI IPI to info other cores */
+ for (int i = 0; i < PLATFORM_CORE_COUNT; i++) {
+ if (cpu_id != i && (online_cores & (0x1 << (i * 8)))) {
+ plat_ic_raise_el3_sgi(0x8, i);
+ }
+ }
+
+ /* make sure all the core in WFE */
+ online_cores &= ~(0x1 << (cpu_id * 8));
+ while (1) {
+ if (online_cores == wfe_done) {
+ break;
+ }
+ }
+
+ /* flush the L1/L2 cache */
+ dcsw_op_all(DCCSW);
+
+ if (dram_info.dram_type == DDRC_LPDDR4) {
+ lpddr4_swffc(&dram_info, dev_fsp, fsp_index);
+ dev_fsp = (~dev_fsp) & 0x1;
+ } else if (dram_info.dram_type == DDRC_DDR4) {
+ ddr4_swffc(&dram_info, fsp_index);
+ }
+
+ dram_info.current_fsp = fsp_index;
+ wait_ddrc_hwffc_done = false;
+ wfe_done = 0;
+ dsb();
+ sev();
+ isb();
+ }
+
+ SMC_RET1(handle, 0);
+}
diff --git a/plat/imx/imx8m/ddr/dram_retention.c b/plat/imx/imx8m/ddr/dram_retention.c
new file mode 100644
index 0000000..7d4f823
--- /dev/null
+++ b/plat/imx/imx8m/ddr/dram_retention.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <lib/mmio.h>
+
+#include <dram.h>
+#include <platform_def.h>
+
+#define SRC_DDR1_RCR (IMX_SRC_BASE + 0x1000)
+#define SRC_DDR2_RCR (IMX_SRC_BASE + 0x1004)
+
+#define PU_PGC_UP_TRG 0xf8
+#define PU_PGC_DN_TRG 0x104
+#define GPC_PU_PWRHSK (IMX_GPC_BASE + 0x01FC)
+#define CCM_SRC_CTRL_OFFSET (IMX_CCM_BASE + 0x800)
+#define CCM_CCGR_OFFSET (IMX_CCM_BASE + 0x4000)
+#define CCM_SRC_CTRL(n) (CCM_SRC_CTRL_OFFSET + 0x10 * (n))
+#define CCM_CCGR(n) (CCM_CCGR_OFFSET + 0x10 * (n))
+
+#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50)
+
+#define DBGCAM_EMPTY 0x36000000
+
+void dram_enter_retention(void)
+{
+ /* Wait DBGCAM to be empty */
+ while (mmio_read_32(DDRC_DBGCAM(0)) != DBGCAM_EMPTY) {
+ ;
+ }
+
+ /* Block AXI ports from taking anymore transactions */
+ mmio_write_32(DDRC_PCTRL_0(0), 0x0);
+ /* Wait until all AXI ports are idle */
+ while (mmio_read_32(DDRC_PSTAT(0)) & 0x10001) {
+ ;
+ }
+
+ /* Enter self refresh */
+ mmio_write_32(DDRC_PWRCTL(0), 0xaa);
+
+ /* LPDDR4 & DDR4/DDR3L need to check different status */
+ if (dram_info.dram_type == DDRC_LPDDR4) {
+ while (0x223 != (mmio_read_32(DDRC_STAT(0)) & 0x33f)) {
+ ;
+ }
+ } else {
+ while (0x23 != (mmio_read_32(DDRC_STAT(0)) & 0x3f)) {
+ ;
+ }
+ }
+
+ mmio_write_32(DDRC_DFIMISC(0), 0x0);
+ mmio_write_32(DDRC_SWCTL(0), 0x0);
+ mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
+ mmio_write_32(DDRC_DFIMISC(0), 0x1f20);
+
+ while (mmio_read_32(DDRC_DFISTAT(0)) & 0x1) {
+ ;
+ }
+
+ mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
+ /* wait DFISTAT.dfi_init_complete to 1 */
+ while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
+ ;
+ }
+
+ mmio_write_32(DDRC_SWCTL(0), 0x1);
+
+ /* should check PhyInLP3 pub reg */
+ dwc_ddrphy_apb_wr(0xd0000, 0x0);
+ if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
+ INFO("PhyInLP3 = 1\n");
+ }
+ dwc_ddrphy_apb_wr(0xd0000, 0x1);
+
+#if defined(PLAT_imx8mq)
+ /* pwrdnreqn_async adbm/adbs of ddr */
+ mmio_clrbits_32(GPC_PU_PWRHSK, BIT(1));
+ while (mmio_read_32(GPC_PU_PWRHSK) & BIT(18)) {
+ ;
+ }
+ mmio_setbits_32(GPC_PU_PWRHSK, BIT(1));
+#else
+ /* pwrdnreqn_async adbm/adbs of ddr */
+ mmio_clrbits_32(GPC_PU_PWRHSK, BIT(2));
+ while (mmio_read_32(GPC_PU_PWRHSK) & BIT(20)) {
+ ;
+ }
+ mmio_setbits_32(GPC_PU_PWRHSK, BIT(2));
+#endif
+ /* remove PowerOk */
+ mmio_write_32(SRC_DDR1_RCR, 0x8F000008);
+
+ mmio_write_32(CCM_CCGR(5), 0);
+ mmio_write_32(CCM_SRC_CTRL(15), 2);
+
+ /* enable the phy iso */
+ mmio_setbits_32(IMX_GPC_BASE + 0xd40, 1);
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, BIT(5));
+
+ VERBOSE("dram enter retention\n");
+}
+
+void dram_exit_retention(void)
+{
+ VERBOSE("dram exit retention\n");
+ /* assert all reset */
+#if defined(PLAT_imx8mq)
+ mmio_write_32(SRC_DDR2_RCR, 0x8F000003);
+ mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
+ mmio_write_32(SRC_DDR2_RCR, 0x8F000000);
+#else
+ mmio_write_32(SRC_DDR1_RCR, 0x8F00001F);
+ mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
+#endif
+ mmio_write_32(CCM_CCGR(5), 2);
+ mmio_write_32(CCM_SRC_CTRL(15), 2);
+
+ /* disable iso */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, BIT(5));
+ mmio_write_32(SRC_DDR1_RCR, 0x8F000006);
+
+ /* wait dram pll locked */
+ while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) {
+ ;
+ }
+
+ /* ddrc re-init */
+ dram_umctl2_init(dram_info.timing_info);
+
+ /*
+ * Skips the DRAM init routine and starts up in selfrefresh mode
+ * Program INIT0.skip_dram_init = 2'b11
+ */
+ mmio_setbits_32(DDRC_INIT0(0), 0xc0000000);
+ /* Keeps the controller in self-refresh mode */
+ mmio_write_32(DDRC_PWRCTL(0), 0xaa);
+ mmio_write_32(DDRC_DBG1(0), 0x0);
+ mmio_write_32(SRC_DDR1_RCR, 0x8F000004);
+ mmio_write_32(SRC_DDR1_RCR, 0x8F000000);
+
+ /* before write Dynamic reg, sw_done should be 0 */
+ mmio_write_32(DDRC_SWCTL(0), 0x0);
+
+#if !PLAT_imx8mn
+ if (dram_info.dram_type == DDRC_LPDDR4) {
+ mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */
+ }
+#endif /* !PLAT_imx8mn */
+
+ mmio_write_32(DDRC_DFIMISC(0), 0x0);
+
+ /* dram phy re-init */
+ dram_phy_init(dram_info.timing_info);
+
+ /* DWC_DDRPHYA_APBONLY0_MicroContMuxSel */
+ dwc_ddrphy_apb_wr(0xd0000, 0x0);
+ while (dwc_ddrphy_apb_rd(0x20097)) {
+ ;
+ }
+ dwc_ddrphy_apb_wr(0xd0000, 0x1);
+
+ /* before write Dynamic reg, sw_done should be 0 */
+ mmio_write_32(DDRC_SWCTL(0), 0x0);
+ mmio_write_32(DDRC_DFIMISC(0), 0x20);
+ /* wait DFISTAT.dfi_init_complete to 1 */
+ while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
+ ;
+ }
+
+ /* clear DFIMISC.dfi_init_start */
+ mmio_write_32(DDRC_DFIMISC(0), 0x0);
+ /* set DFIMISC.dfi_init_complete_en */
+ mmio_write_32(DDRC_DFIMISC(0), 0x1);
+
+ /* set SWCTL.sw_done to enable quasi-dynamic register programming */
+ mmio_write_32(DDRC_SWCTL(0), 0x1);
+ /* wait SWSTAT.sw_done_ack to 1 */
+ while (!(mmio_read_32(DDRC_SWSTAT(0)) & 0x1)) {
+ ;
+ }
+
+ mmio_write_32(DDRC_PWRCTL(0), 0x88);
+ /* wait STAT to normal state */
+ while (0x1 != (mmio_read_32(DDRC_STAT(0)) & 0x7)) {
+ ;
+ }
+
+ mmio_write_32(DDRC_PCTRL_0(0), 0x1);
+ /* dis_auto-refresh is set to 0 */
+ mmio_write_32(DDRC_RFSHCTL3(0), 0x0);
+
+ /* should check PhyInLP3 pub reg */
+ dwc_ddrphy_apb_wr(0xd0000, 0x0);
+ if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
+ VERBOSE("PHYInLP3 = 0\n");
+ }
+ dwc_ddrphy_apb_wr(0xd0000, 0x1);
+}
diff --git a/plat/imx/imx8m/ddr/lpddr4_dvfs.c b/plat/imx/imx8m/ddr/lpddr4_dvfs.c
new file mode 100644
index 0000000..2b4f300
--- /dev/null
+++ b/plat/imx/imx8m/ddr/lpddr4_dvfs.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <dram.h>
+
+static void lpddr4_mr_write(uint32_t mr_rank, uint32_t mr_addr, uint32_t mr_data)
+{
+ /*
+ * 1. Poll MRSTAT.mr_wr_busy until it is 0. This checks that there
+ * is no outstanding MR transaction. No
+ * writes should be performed to MRCTRL0 and MRCTRL1 if MRSTAT.mr_wr_busy = 1.
+ */
+ while (mmio_read_32(DDRC_MRSTAT(0)) & 0x1)
+ ;
+
+ /*
+ * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr,
+ * MRCTRL0.mr_rank and (for MRWs)
+ * MRCTRL1.mr_data to define the MR transaction.
+ */
+ mmio_write_32(DDRC_MRCTRL0(0), (mr_rank << 4));
+ mmio_write_32(DDRC_MRCTRL1(0), (mr_addr << 8) | mr_data);
+ mmio_setbits_32(DDRC_MRCTRL0(0), BIT(31));
+}
+
+void lpddr4_swffc(struct dram_info *info, unsigned int init_fsp,
+ unsigned int fsp_index)
+
+{
+ uint32_t mr, emr, emr2, emr3;
+ uint32_t mr11, mr12, mr22, mr14;
+ uint32_t val;
+ uint32_t derate_backup[3];
+ uint32_t (*mr_data)[8];
+
+ /* 1. program targetd UMCTL2_REGS_FREQ1/2/3,already done, skip it. */
+
+ /* 2. MR13.FSP-WR=1, MRW to update MR registers */
+ mr_data = info->mr_table;
+ mr = mr_data[fsp_index][0];
+ emr = mr_data[fsp_index][1];
+ emr2 = mr_data[fsp_index][2];
+ emr3 = mr_data[fsp_index][3];
+ mr11 = mr_data[fsp_index][4];
+ mr12 = mr_data[fsp_index][5];
+ mr22 = mr_data[fsp_index][6];
+ mr14 = mr_data[fsp_index][7];
+
+ val = (init_fsp == 1) ? 0x2 << 6 : 0x1 << 6;
+ emr3 = (emr3 & 0x003f) | val | 0x0d00;
+
+ /* 12. set PWRCTL.selfref_en=0 */
+ mmio_clrbits_32(DDRC_PWRCTL(0), 0xf);
+
+ /* It is more safe to config it here */
+ mmio_clrbits_32(DDRC_DFIPHYMSTR(0), 0x1);
+
+ lpddr4_mr_write(3, 13, emr3);
+ lpddr4_mr_write(3, 1, mr);
+ lpddr4_mr_write(3, 2, emr);
+ lpddr4_mr_write(3, 3, emr2);
+ lpddr4_mr_write(3, 11, mr11);
+ lpddr4_mr_write(3, 12, mr12);
+ lpddr4_mr_write(3, 14, mr14);
+ lpddr4_mr_write(3, 22, mr22);
+
+ do {
+ val = mmio_read_32(DDRC_MRSTAT(0));
+ } while (val & 0x1);
+
+ /* 3. disable AXI ports */
+ mmio_write_32(DDRC_PCTRL_0(0), 0x0);
+
+ /* 4.Poll PSTAT.rd_port_busy_n=0 and PSTAT.wr_port_busy_n=0. */
+ do {
+ val = mmio_read_32(DDRC_PSTAT(0));
+ } while (val != 0);
+
+ /* 6.disable SBRCTL.scrub_en, skip if never enable it */
+ /* 7.poll SBRSTAT.scrub_busy Q2: should skip phy master if never enable it */
+ /* Disable phy master */
+#ifdef DFILP_SPT
+ /* 8. disable DFI LP */
+ /* DFILPCFG0.dfi_lp_en_sr */
+ val = mmio_read_32(DDRC_DFILPCFG0(0));
+ if (val & 0x100) {
+ mmio_write_32(DDRC_DFILPCFG0(0), 0x0);
+ do {
+ val = mmio_read_32(DDRC_DFISTAT(0)); // dfi_lp_ack
+ val2 = mmio_read_32(DDRC_STAT(0)); // operating_mode
+ } while (((val & 0x2) == 0x2) && ((val2 & 0x7) == 3));
+ }
+#endif
+ /* 9. wait until in normal or power down states */
+ do {
+ /* operating_mode */
+ val = mmio_read_32(DDRC_STAT(0));
+ } while (((val & 0x7) != 1) && ((val & 0x7) != 2));
+
+ /* 10. Disable automatic derating: derate_enable */
+ val = mmio_read_32(DDRC_DERATEEN(0));
+ derate_backup[0] = val;
+ mmio_clrbits_32(DDRC_DERATEEN(0), 0x1);
+
+ val = mmio_read_32(DDRC_FREQ1_DERATEEN(0));
+ derate_backup[1] = val;
+ mmio_clrbits_32(DDRC_FREQ1_DERATEEN(0), 0x1);
+
+ val = mmio_read_32(DDRC_FREQ2_DERATEEN(0));
+ derate_backup[2] = val;
+ mmio_clrbits_32(DDRC_FREQ2_DERATEEN(0), 0x1);
+
+ /* 11. disable automatic ZQ calibration */
+ mmio_setbits_32(DDRC_ZQCTL0(0), BIT(31));
+ mmio_setbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(31));
+ mmio_setbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(31));
+
+ /* 12. set PWRCTL.selfref_en=0 */
+ mmio_clrbits_32(DDRC_PWRCTL(0), 0x1);
+
+ /* 13.Poll STAT.operating_mode is in "Normal" (001) or "Power-down" (010) */
+ do {
+ val = mmio_read_32(DDRC_STAT(0));
+ } while (((val & 0x7) != 1) && ((val & 0x7) != 2));
+
+ /* 14-15. trigger SW SR */
+ /* bit 5: selfref_sw, bit 6: stay_in_selfref */
+ mmio_setbits_32(DDRC_PWRCTL(0), 0x60);
+
+ /* 16. Poll STAT.selfref_state in "Self Refresh 1" */
+ do {
+ val = mmio_read_32(DDRC_STAT(0));
+ } while ((val & 0x300) != 0x100);
+
+ /* 17. disable dq */
+ mmio_setbits_32(DDRC_DBG1(0), 0x1);
+
+ /* 18. Poll DBGCAM.wr_data_pipeline_empty and DBGCAM.rd_data_pipeline_empty */
+ do {
+ val = mmio_read_32(DDRC_DBGCAM(0));
+ val &= 0x30000000;
+ } while (val != 0x30000000);
+
+ /* 19. change MR13.FSP-OP to new FSP and MR13.VRCG to high current */
+ emr3 = (((~init_fsp) & 0x1) << 7) | (0x1 << 3) | (emr3 & 0x0077) | 0x0d00;
+ lpddr4_mr_write(3, 13, emr3);
+
+ /* 20. enter SR Power Down */
+ mmio_clrsetbits_32(DDRC_PWRCTL(0), 0x60, 0x20);
+
+ /* 21. Poll STAT.selfref_state is in "SR Power down" */
+ do {
+ val = mmio_read_32(DDRC_STAT(0));
+ } while ((val & 0x300) != 0x200);
+
+ /* 22. set dfi_init_complete_en = 0 */
+
+ /* 23. switch clock */
+ /* set SWCTL.dw_done to 0 */
+ mmio_write_32(DDRC_SWCTL(0), 0x0000);
+
+ /* 24. program frequency mode=1(bit 29), target_frequency=target_freq (bit 29) */
+ mmio_write_32(DDRC_MSTR2(0), fsp_index);
+
+ /* 25. DBICTL for FSP-OP[1], skip it if never enable it */
+
+ /* 26.trigger initialization in the PHY */
+
+ /* Q3: if refresh level is updated, then should program */
+ /* as updating refresh, need to toggle refresh_update_level signal */
+ val = mmio_read_32(DDRC_RFSHCTL3(0));
+ val = val ^ 0x2;
+ mmio_write_32(DDRC_RFSHCTL3(0), val);
+
+ /* Q4: only for legacy PHY, so here can skipped */
+
+ /* dfi_frequency -> 0x1x */
+ val = mmio_read_32(DDRC_DFIMISC(0));
+ val &= 0xFE;
+ val |= (fsp_index << 8);
+ mmio_write_32(DDRC_DFIMISC(0), val);
+ /* dfi_init_start */
+ val |= 0x20;
+ mmio_write_32(DDRC_DFIMISC(0), val);
+
+ /* polling dfi_init_complete de-assert */
+ do {
+ val = mmio_read_32(DDRC_DFISTAT(0));
+ } while ((val & 0x1) == 0x1);
+
+ /* change the clock frequency */
+ dram_clock_switch(info->timing_info->fsp_table[fsp_index], info->bypass_mode);
+
+ /* dfi_init_start de-assert */
+ mmio_clrbits_32(DDRC_DFIMISC(0), 0x20);
+
+ /* polling dfi_init_complete re-assert */
+ do {
+ val = mmio_read_32(DDRC_DFISTAT(0));
+ } while ((val & 0x1) == 0x0);
+
+ /* 27. set ZQCTL0.dis_srx_zqcl = 1 */
+ if (fsp_index == 0) {
+ mmio_setbits_32(DDRC_ZQCTL0(0), BIT(30));
+ } else if (fsp_index == 1) {
+ mmio_setbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(30));
+ } else {
+ mmio_setbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(30));
+ }
+
+ /* 28,29. exit "self refresh power down" to stay "self refresh 2" */
+ /* exit SR power down */
+ mmio_clrsetbits_32(DDRC_PWRCTL(0), 0x60, 0x40);
+ /* 30. Poll STAT.selfref_state in "Self refresh 2" */
+ do {
+ val = mmio_read_32(DDRC_STAT(0));
+ } while ((val & 0x300) != 0x300);
+
+ /* 31. change MR13.VRCG to normal */
+ emr3 = (emr3 & 0x00f7) | 0x0d00;
+ lpddr4_mr_write(3, 13, emr3);
+
+ /* enable PHY master */
+ mmio_write_32(DDRC_DFIPHYMSTR(0), 0x1);
+
+ /* 32. issue ZQ if required: zq_calib_short, bit 4 */
+ /* polling zq_calib_short_busy */
+ mmio_setbits_32(DDRC_DBGCMD(0), 0x10);
+
+ do {
+ val = mmio_read_32(DDRC_DBGSTAT(0));
+ } while ((val & 0x10) != 0x0);
+
+ /* 33. Reset ZQCTL0.dis_srx_zqcl=0 */
+ if (fsp_index == 1)
+ mmio_clrbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(30));
+ else if (fsp_index == 2)
+ mmio_clrbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(30));
+ else
+ mmio_clrbits_32(DDRC_ZQCTL0(0), BIT(30));
+
+ /* set SWCTL.dw_done to 1 and poll SWSTAT.sw_done_ack=1 */
+ mmio_write_32(DDRC_SWCTL(0), 0x1);
+
+ /* wait SWSTAT.sw_done_ack to 1 */
+ do {
+ val = mmio_read_32(DDRC_SWSTAT(0));
+ } while ((val & 0x1) == 0x0);
+
+ /* 34. set PWRCTL.stay_in_selfreh=0, exit SR */
+ mmio_clrbits_32(DDRC_PWRCTL(0), 0x40);
+ /* wait tXSR */
+
+ /* 35. Poll STAT.selfref_state in "Idle" */
+ do {
+ val = mmio_read_32(DDRC_STAT(0));
+ } while ((val & 0x300) != 0x0);
+
+#ifdef DFILP_SPT
+ /* 36. restore dfi_lp.dfi_lp_en_sr */
+ mmio_setbits_32(DDRC_DFILPCFG0(0), BIT(8));
+#endif
+
+ /* 37. re-enable CAM: dis_dq */
+ mmio_clrbits_32(DDRC_DBG1(0), 0x1);
+
+ /* 38. re-enable automatic SR: selfref_en */
+ mmio_setbits_32(DDRC_PWRCTL(0), 0x1);
+
+ /* 39. re-enable automatic ZQ: dis_auto_zq=0 */
+ /* disable automatic ZQ calibration */
+ if (fsp_index == 1)
+ mmio_clrbits_32(DDRC_FREQ1_ZQCTL0(0), BIT(31));
+ else if (fsp_index == 2)
+ mmio_clrbits_32(DDRC_FREQ2_ZQCTL0(0), BIT(31));
+ else
+ mmio_clrbits_32(DDRC_ZQCTL0(0), BIT(31));
+ /* 40. re-emable automatic derating: derate_enable */
+ mmio_write_32(DDRC_DERATEEN(0), derate_backup[0]);
+ mmio_write_32(DDRC_FREQ1_DERATEEN(0), derate_backup[1]);
+ mmio_write_32(DDRC_FREQ2_DERATEEN(0), derate_backup[2]);
+
+ /* 41. write 1 to PCTRL.port_en */
+ mmio_write_32(DDRC_PCTRL_0(0), 0x1);
+
+ /* 42. enable SBRCTL.scrub_en, skip if never enable it */
+}
diff --git a/plat/imx/imx8m/gpc_common.c b/plat/imx/imx8m/gpc_common.c
new file mode 100644
index 0000000..e674d7a
--- /dev/null
+++ b/plat/imx/imx8m/gpc_common.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+#define MAX_PLL_NUM U(10)
+
+static uint32_t gpc_imr_offset[] = { IMR1_CORE0_A53, IMR1_CORE1_A53, IMR1_CORE2_A53, IMR1_CORE3_A53, };
+
+DEFINE_BAKERY_LOCK(gpc_lock);
+
+#define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03
+
+#pragma weak imx_set_cpu_pwr_off
+#pragma weak imx_set_cpu_pwr_on
+#pragma weak imx_set_cpu_lpm
+#pragma weak imx_set_cluster_powerdown
+
+void imx_set_cpu_secure_entry(unsigned int core_id, uintptr_t sec_entrypoint)
+{
+ uint64_t temp_base;
+
+ temp_base = (uint64_t) sec_entrypoint;
+ temp_base >>= 2;
+
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3),
+ ((uint32_t)(temp_base >> 22) & 0xffff));
+ mmio_write_32(IMX_SRC_BASE + SRC_GPR1_OFFSET + (core_id << 3) + 4,
+ ((uint32_t)temp_base & 0x003fffff));
+}
+
+void imx_set_cpu_pwr_off(unsigned int core_id)
+{
+
+ bakery_lock_get(&gpc_lock);
+
+ /* enable the wfi power down of the core */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id));
+
+ bakery_lock_release(&gpc_lock);
+
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+}
+
+void imx_set_cpu_pwr_on(unsigned int core_id)
+{
+ bakery_lock_get(&gpc_lock);
+
+ /* clear the wfi power down bit of the core */
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id));
+
+ bakery_lock_release(&gpc_lock);
+
+ /* assert the ncpuporeset */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ /* sw power up the core */
+ mmio_setbits_32(IMX_GPC_BASE + CPU_PGC_UP_TRG, (1 << core_id));
+
+ /* wait for the power up finished */
+ while ((mmio_read_32(IMX_GPC_BASE + CPU_PGC_UP_TRG) & (1 << core_id)) != 0)
+ ;
+
+ /* deassert the pcg pcr bit of the core */
+ mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ /* deassert the ncpuporeset */
+ mmio_setbits_32(IMX_SRC_BASE + SRC_A53RCR1, (1 << core_id));
+}
+
+void imx_set_cpu_lpm(unsigned int core_id, bool pdn)
+{
+ bakery_lock_get(&gpc_lock);
+
+ if (pdn) {
+ /* enable the core WFI PDN & IRQ PUP */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ COREx_IRQ_WUP(core_id));
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ } else {
+ /* disbale CORE WFI PDN & IRQ PUP */
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ COREx_IRQ_WUP(core_id));
+ /* deassert the pcg pcr bit of the core */
+ mmio_clrbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ }
+
+ bakery_lock_release(&gpc_lock);
+}
+
+/*
+ * the plat and noc can only be power up & down by slot method,
+ * slot0: plat power down; slot1: noc power down; slot2: noc power up;
+ * slot3: plat power up. plat's pup&pdn ack is used by default. if
+ * noc is config to power down, then noc's pdn ack should be used.
+ */
+static void imx_a53_plat_slot_config(bool pdn)
+{
+ if (pdn) {
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), PLAT_PDN_SLT_CTRL);
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(3), PLAT_PUP_SLT_CTRL);
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_PLAT_PDN_ACK |
+ A53_PLAT_PUP_ACK);
+ mmio_setbits_32(IMX_GPC_BASE + PLAT_PGC_PCR, 0x1);
+ } else {
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), PLAT_PDN_SLT_CTRL);
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(3), PLAT_PUP_SLT_CTRL);
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK |
+ A53_DUMMY_PDN_ACK);
+ mmio_clrbits_32(IMX_GPC_BASE + PLAT_PGC_PCR, 0x1);
+ }
+}
+
+void imx_set_cluster_standby(bool enter)
+{
+ /*
+ * Enable BIT 6 of A53 AD register to make sure system
+ * don't enter LPM mode.
+ */
+ if (enter)
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+ else
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, (1 << 6));
+}
+
+/* i.mx8mq need to override it */
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state)
+{
+ uint32_t val;
+
+ if (!is_local_state_run(power_state)) {
+ /* config C0~1's LPM, enable a53 clock off in LPM */
+ mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, A53_CLK_ON_LPM,
+ LPM_MODE(power_state));
+ /* config C2-3's LPM */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, LPM_MODE(power_state));
+
+ /* enable PLAT/SCU power down */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+ val &= ~EN_L2_WFI_PDN;
+ /* L2 cache memory is on in WAIT mode */
+ if (is_local_state_off(power_state)) {
+ val |= (L2PGE | EN_PLAT_PDN);
+ imx_a53_plat_slot_config(true);
+ }
+
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+ } else {
+ /* clear the slot and ack for cluster power down */
+ imx_a53_plat_slot_config(false);
+ /* reverse the cluster level setting */
+ mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, 0xf, A53_CLK_ON_LPM);
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, 0xf);
+
+ /* clear PLAT/SCU power down */
+ mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_AD, (L2PGE | EN_PLAT_PDN),
+ EN_L2_WFI_PDN);
+ }
+}
+
+static unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
+{
+ unsigned int n = id >> ISENABLER_SHIFT;
+
+ return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+/*
+ * gic's clock will be gated in system suspend, so gic has no ability to
+ * to wakeup the system, we need to config the imr based on the irq
+ * enable status in gic, then gpc will monitor the wakeup irq
+ */
+void imx_set_sys_wakeup(unsigned int last_core, bool pdn)
+{
+ uint32_t irq_mask;
+ uintptr_t gicd_base = PLAT_GICD_BASE;
+
+ if (pdn)
+ mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, A53_CORE_WUP_SRC(last_core),
+ IRQ_SRC_A53_WUP);
+ else
+ mmio_clrsetbits_32(IMX_GPC_BASE + LPCR_A53_BSC, IRQ_SRC_A53_WUP,
+ A53_CORE_WUP_SRC(last_core));
+
+ /* clear last core's IMR based on GIC's mask setting */
+ for (int i = 0; i < IRQ_IMR_NUM; i++) {
+ if (pdn)
+ /* set the wakeup irq base GIC */
+ irq_mask = ~gicd_read_isenabler(gicd_base, 32 * (i + 1));
+ else
+ irq_mask = IMR_MASK_ALL;
+
+ mmio_write_32(IMX_GPC_BASE + gpc_imr_offset[last_core] + i * 4,
+ irq_mask);
+ }
+}
+
+#pragma weak imx_noc_slot_config
+/*
+ * this function only need to be override by platform
+ * that support noc power down, for example: imx8mm.
+ * otherwize, keep it empty.
+ */
+void imx_noc_slot_config(bool pdn)
+{
+
+}
+
+/* this is common for all imx8m soc */
+void imx_set_sys_lpm(unsigned int last_core, bool retention)
+{
+ uint32_t val;
+
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val &= ~(SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+ SLPCR_BYPASS_PMIC_READY | SLPCR_A53_FASTWUP_STOP_MODE);
+
+ if (retention)
+ val |= (SLPCR_EN_DSM | SLPCR_VSTBY | SLPCR_SBYOS |
+ SLPCR_BYPASS_PMIC_READY | SLPCR_A53_FASTWUP_STOP_MODE);
+
+ mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+ /* config the noc power down */
+ imx_noc_slot_config(retention);
+
+ /* config wakeup irqs' mask in gpc */
+ imx_set_sys_wakeup(last_core, retention);
+}
+
+void imx_set_rbc_count(void)
+{
+ mmio_setbits_32(IMX_GPC_BASE + SLPCR, SLPCR_RBC_EN |
+ (0x8 << SLPCR_RBC_COUNT_SHIFT));
+}
+
+void imx_clear_rbc_count(void)
+{
+ mmio_clrbits_32(IMX_GPC_BASE + SLPCR, SLPCR_RBC_EN |
+ (0x3f << SLPCR_RBC_COUNT_SHIFT));
+}
+
+struct pll_override {
+ uint32_t reg;
+ uint32_t override_mask;
+};
+
+struct pll_override pll[MAX_PLL_NUM] = {
+ {.reg = 0x0, .override_mask = (1 << 12) | (1 << 8), },
+ {.reg = 0x14, .override_mask = (1 << 12) | (1 << 8), },
+ {.reg = 0x28, .override_mask = (1 << 12) | (1 << 8), },
+ {.reg = 0x50, .override_mask = (1 << 12) | (1 << 8), },
+ {.reg = 0x64, .override_mask = (1 << 10) | (1 << 8), },
+ {.reg = 0x74, .override_mask = (1 << 10) | (1 << 8), },
+ {.reg = 0x84, .override_mask = (1 << 10) | (1 << 8), },
+ {.reg = 0x94, .override_mask = 0x5555500, },
+ {.reg = 0x104, .override_mask = 0x5555500, },
+ {.reg = 0x114, .override_mask = 0x500, },
+};
+
+#define PLL_BYPASS BIT(4)
+void imx_anamix_override(bool enter)
+{
+ unsigned int i;
+
+ /*
+ * bypass all the plls & enable the override bit before
+ * entering DSM mode.
+ */
+ for (i = 0U; i < MAX_PLL_NUM; i++) {
+ if (enter) {
+ mmio_setbits_32(IMX_ANAMIX_BASE + pll[i].reg, PLL_BYPASS);
+ mmio_setbits_32(IMX_ANAMIX_BASE + pll[i].reg, pll[i].override_mask);
+ } else {
+ mmio_clrbits_32(IMX_ANAMIX_BASE + pll[i].reg, PLL_BYPASS);
+ mmio_clrbits_32(IMX_ANAMIX_BASE + pll[i].reg, pll[i].override_mask);
+ }
+ }
+}
+
+int imx_gpc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3)
+{
+ switch (x1) {
+ case FSL_SIP_CONFIG_GPC_PM_DOMAIN:
+ imx_gpc_pm_domain_enable(x2, x3);
+ break;
+ default:
+ return SMC_UNK;
+ }
+
+ return 0;
+}
diff --git a/plat/imx/imx8m/imx8m_caam.c b/plat/imx/imx8m/imx8m_caam.c
new file mode 100644
index 0000000..a491550
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_caam.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019-2022 NXP. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <imx8m_caam.h>
+
+#define HAB_JR0_DID U(0x8011)
+
+void imx8m_caam_init(void)
+{
+ uint32_t sm_cmd;
+
+ /* Dealloc part 0 and 2 with current DID */
+ sm_cmd = (0 << SMC_PART_SHIFT | SMC_CMD_DEALLOC_PART);
+ mmio_write_32(SM_CMD, sm_cmd);
+
+ sm_cmd = (2 << SMC_PART_SHIFT | SMC_CMD_DEALLOC_PART);
+ mmio_write_32(SM_CMD, sm_cmd);
+
+ /* config CAAM JRaMID set MID to Cortex A */
+ if (mmio_read_32(CAAM_JR0MID) == HAB_JR0_DID) {
+ NOTICE("Do not release JR0 to NS as it can be used by HAB\n");
+ } else {
+ mmio_write_32(CAAM_JR0MID, CAAM_NS_MID);
+ }
+
+ mmio_write_32(CAAM_JR1MID, CAAM_NS_MID);
+ mmio_write_32(CAAM_JR2MID, CAAM_NS_MID);
+
+ /* Alloc partition 0 writing SMPO and SMAGs */
+ mmio_write_32(SM_P0_PERM, 0xff);
+ mmio_write_32(SM_P0_SMAG2, 0xffffffff);
+ mmio_write_32(SM_P0_SMAG1, 0xffffffff);
+
+ /* Allocate page 0 and 1 to partition 0 with DID set */
+ sm_cmd = (0 << SMC_PAGE_SHIFT | 0 << SMC_PART_SHIFT |
+ SMC_CMD_ALLOC_PAGE);
+ mmio_write_32(SM_CMD, sm_cmd);
+
+ sm_cmd = (1 << SMC_PAGE_SHIFT | 0 << SMC_PART_SHIFT |
+ SMC_CMD_ALLOC_PAGE);
+ mmio_write_32(SM_CMD, sm_cmd);
+}
diff --git a/plat/imx/imx8m/imx8m_csu.c b/plat/imx/imx8m/imx8m_csu.c
new file mode 100644
index 0000000..2b3a7d9
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_csu.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <imx8m_csu.h>
+
+void imx_csu_init(const struct imx_csu_cfg *csu_cfg)
+{
+ const struct imx_csu_cfg *csu = csu_cfg;
+ uint32_t val;
+
+ while (csu->type != CSU_INVALID) {
+ switch (csu->type) {
+ case CSU_CSL:
+ val = mmio_read_32(CSLx_REG(csu->idx));
+ if (val & CSLx_LOCK(csu->idx)) {
+ break;
+ }
+ mmio_clrsetbits_32(CSLx_REG(csu->idx), CSLx_CFG(0xff, csu->idx),
+ CSLx_CFG(csu->csl_level | (csu->lock << 8), csu->idx));
+ break;
+ case CSU_HP:
+ val = mmio_read_32(CSU_HP_REG(csu->idx));
+ if (val & CSU_HP_LOCK(csu->idx)) {
+ break;
+ }
+ mmio_clrsetbits_32(CSU_HP_REG(csu->idx), CSU_HP_CFG(0x1, csu->idx),
+ CSU_HP_CFG(csu->hp | (csu->lock << 0x1), csu->idx));
+ break;
+ case CSU_SA:
+ val = mmio_read_32(CSU_SA_REG(csu->idx));
+ if (val & CSU_SA_LOCK(csu->idx)) {
+ break;
+ }
+ mmio_clrsetbits_32(CSU_SA_REG(csu->idx), CSU_SA_CFG(0x1, csu->idx),
+ CSU_SA_CFG(csu->sa | (csu->lock << 0x1), csu->idx));
+ break;
+ case CSU_HPCONTROL:
+ val = mmio_read_32(CSU_HPCONTROL_REG(csu->idx));
+ if (val & CSU_HPCONTROL_LOCK(csu->idx)) {
+ break;
+ }
+ mmio_clrsetbits_32(CSU_HPCONTROL_REG(csu->idx), CSU_HPCONTROL_CFG(0x1, csu->idx),
+ CSU_HPCONTROL_CFG(csu->hpctrl | (csu->lock << 0x1), csu->idx));
+ break;
+ default:
+ break;
+ }
+
+ csu++;
+ }
+}
diff --git a/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c b/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c
new file mode 100644
index 0000000..5d65ef2
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, Linaro.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#if MEASURED_BOOT
+#include <common/desc_image_load.h>
+#endif
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+#include <platform_def.h>
+
+#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
+#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
+
+#if MEASURED_BOOT
+
+static int imx8m_event_log_fdt_init_overlay(uintptr_t dt_base, int dt_size)
+{
+ int ret;
+ int offset;
+ void *dtb = (void *)dt_base;
+
+ ret = fdt_create_empty_tree(dtb, dt_size);
+ if (ret < 0) {
+ ERROR("cannot create empty dtb tree: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+
+ offset = fdt_path_offset(dtb, "/");
+ if (offset < 0) {
+ ERROR("cannot find root of the tree: %s\n",
+ fdt_strerror(offset));
+ return offset;
+ }
+
+ offset = fdt_add_subnode(dtb, offset, "fragment@0");
+ if (offset < 0) {
+ ERROR("cannot add fragment node: %s\n",
+ fdt_strerror(offset));
+ return offset;
+ }
+
+ ret = fdt_setprop_string(dtb, offset, "target-path", "/");
+ if (ret < 0) {
+ ERROR("cannot set target-path property: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+
+ offset = fdt_add_subnode(dtb, offset, "__overlay__");
+ if (offset < 0) {
+ ERROR("cannot add __overlay__ node: %s\n",
+ fdt_strerror(offset));
+ return ret;
+ }
+
+ offset = fdt_add_subnode(dtb, offset, "tpm_event_log");
+ if (offset < 0) {
+ ERROR("cannot add tpm_event_log node: %s\n",
+ fdt_strerror(offset));
+ return offset;
+ }
+
+ ret = fdt_setprop_string(dtb, offset, "compatible",
+ "arm,tpm_event_log");
+ if (ret < 0) {
+ ERROR("cannot set compatible property: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+
+ ret = fdt_setprop_u64(dtb, offset, "tpm_event_log_addr", 0);
+ if (ret < 0) {
+ ERROR("cannot set tpm_event_log_addr property: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+
+ ret = fdt_setprop_u32(dtb, offset, "tpm_event_log_size", 0);
+ if (ret < 0) {
+ ERROR("cannot set tpm_event_log_size property: %s\n",
+ fdt_strerror(ret));
+ return ret;
+ }
+
+ return ret;
+}
+
+/*
+ * Write the Event Log address and its size in the DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+static int imx8m_set_event_log_info(uintptr_t config_base,
+ uintptr_t log_addr, size_t log_size)
+{
+ /* As libfdt uses void *, we can't avoid this cast */
+ void *dtb = (void *)config_base;
+ const char *compatible_tpm = "arm,tpm_event_log";
+ uint64_t base = cpu_to_fdt64(log_addr);
+ uint32_t sz = cpu_to_fdt32(log_size);
+ int err, node;
+
+ err = fdt_open_into(dtb, dtb, PLAT_IMX8M_DTO_MAX_SIZE);
+ if (err < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
+ return err;
+ }
+
+ /*
+ * Verify that the DTB is valid, before attempting to write to it,
+ * and get the DTB root node.
+ */
+
+ /* Check if the pointer to DT is correct */
+ err = fdt_check_header(dtb);
+ if (err < 0) {
+ WARN("Invalid DTB file passed\n");
+ return err;
+ }
+
+ /*
+ * Find the TPM node in device tree.
+ */
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_tpm);
+ if (node < 0) {
+ ERROR("The compatible property '%s' not%s", compatible_tpm,
+ " found in the config\n");
+ return node;
+ }
+
+ err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_ADDR, &base, 8);
+ if (err < 0) {
+ ERROR("Failed to add log addr err %d\n", err);
+ return err;
+ }
+
+ err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_SIZE, &sz, 4);
+ if (err < 0) {
+ ERROR("Failed to add log addr err %d\n", err);
+ return err;
+ }
+
+ err = fdt_pack(dtb);
+ if (err < 0) {
+ ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, err);
+ return err;
+ }
+
+ /*
+ * Ensure that the info written to the DTB is visible
+ * to other images.
+ */
+ flush_dcache_range(config_base, fdt_totalsize(dtb));
+
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the QEMU DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr)
+{
+ uintptr_t ns_addr;
+ int err;
+
+ assert(ns_log_addr != NULL);
+
+ ns_addr = PLAT_IMX8M_DTO_BASE + PLAT_IMX8M_DTO_MAX_SIZE;
+
+ imx8m_event_log_fdt_init_overlay(PLAT_IMX8M_DTO_BASE,
+ PLAT_IMX8M_DTO_MAX_SIZE);
+
+ /* Write the Event Log address and its size in the DTB */
+ err = imx8m_set_event_log_info(PLAT_IMX8M_DTO_BASE,
+ ns_addr, log_size);
+
+ /* Return Event Log address in Non-secure memory */
+ *ns_log_addr = (err < 0) ? 0UL : ns_addr;
+ return err;
+}
+
+#endif /* MEASURED_BOOT */
diff --git a/plat/imx/imx8m/imx8m_image_load.c b/plat/imx/imx8m/imx8m_image_load.c
new file mode 100644
index 0000000..3a03069
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_image_load.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+
+#include <platform_def.h>
+#include <plat/common/platform.h>
+
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/imx/imx8m/imx8m_measured_boot.c b/plat/imx/imx8m/imx8m_measured_boot.c
new file mode 100644
index 0000000..ec61606
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_measured_boot.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Linaro.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include "./include/imx8m_measured_boot.h"
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* Event Log data */
+static uint8_t event_log[PLAT_IMX_EVENT_LOG_MAX_SIZE];
+
+/* FVP table with platform specific image IDs, names and PCRs */
+static const event_log_metadata_t imx8m_event_log_metadata[] = {
+ { BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 },
+ { BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 },
+ { BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 },
+ { BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 },
+ { BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 },
+ { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+const event_log_metadata_t *plat_event_log_get_metadata(void)
+{
+ return imx8m_event_log_metadata;
+}
+
+int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
+{
+ /* Calculate image hash and record data in Event Log */
+ int err = event_log_measure_and_record(image_data->image_base,
+ image_data->image_size,
+ image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "Failed to ", "record", image_id, err);
+ return err;
+ }
+
+ return 0;
+}
+
+void bl2_plat_mboot_init(void)
+{
+ event_log_init(event_log, event_log + sizeof(event_log));
+ event_log_write_header();
+}
+
+void bl2_plat_mboot_finish(void)
+{
+ int rc = 0;
+
+ /* Event Log address in Non-Secure memory */
+ uintptr_t ns_log_addr;
+
+ /* Event Log filled size */
+ size_t event_log_cur_size;
+
+ event_log_cur_size = event_log_get_cur_size(event_log);
+
+ rc = imx8m_set_nt_fw_info(event_log_cur_size, &ns_log_addr);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "NT");
+ /*
+ * It is a fatal error because on i.MX U-boot assumes that
+ * a valid event log exists and will use it to record the
+ * measurements into the fTPM.
+ */
+ panic();
+ }
+
+ /* Copy Event Log to Non-secure memory */
+ (void)memcpy((void *)ns_log_addr, (const void *)event_log,
+ event_log_cur_size);
+
+ /* Ensure that the Event Log is visible in Non-secure memory */
+ flush_dcache_range(ns_log_addr, event_log_cur_size);
+
+ dump_event_log((uint8_t *)event_log, event_log_cur_size);
+}
diff --git a/plat/imx/imx8m/imx8m_psci_common.c b/plat/imx/imx8m/imx8m_psci_common.c
new file mode 100644
index 0000000..8f545d6
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_psci_common.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <dram.h>
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+/*
+ * below callback functions need to be override by i.mx8mq,
+ * for other i.mx8m soc, if no special requirement,
+ * reuse below ones.
+ */
+#pragma weak imx_validate_power_state
+#pragma weak imx_domain_suspend
+#pragma weak imx_domain_suspend_finish
+#pragma weak imx_get_sys_suspend_power_state
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+ /* The non-secure entrypoint should be in RAM space */
+ if (ns_entrypoint < PLAT_NS_IMAGE_OFFSET)
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core_id;
+ uint64_t base_addr = BL31_START;
+
+ core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ imx_set_cpu_secure_entry(core_id, base_addr);
+ imx_set_cpu_pwr_on(core_id);
+
+ return PSCI_E_SUCCESS;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ plat_gic_pcpu_init();
+ plat_gic_cpuif_enable();
+}
+
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ plat_gic_cpuif_disable();
+ imx_set_cpu_pwr_off(core_id);
+}
+
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int pwr_type = psci_get_pstate_type(power_state);
+ int state_id = psci_get_pstate_id(power_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ if (pwr_type == PSTATE_TYPE_STANDBY) {
+ CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ }
+
+ if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) {
+ CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE;
+ CLUSTER_PWR_STATE(req_state) = PLAT_WAIT_RET_STATE;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+void imx_cpu_standby(plat_local_state_t cpu_state)
+{
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+
+ wfi();
+
+ write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+ isb();
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint64_t base_addr = BL31_START;
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ plat_gic_cpuif_disable();
+ imx_set_cpu_secure_entry(core_id, base_addr);
+ imx_set_cpu_lpm(core_id, true);
+ } else {
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+ }
+
+ if (!is_local_state_run(CLUSTER_PWR_STATE(target_state)))
+ imx_set_cluster_powerdown(core_id, CLUSTER_PWR_STATE(target_state));
+
+ if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
+ imx_set_sys_lpm(core_id, true);
+ dram_enter_retention();
+ imx_anamix_override(true);
+ }
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
+ imx_anamix_override(false);
+ dram_exit_retention();
+ imx_set_sys_lpm(core_id, false);
+ }
+
+ if (!is_local_state_run(CLUSTER_PWR_STATE(target_state))) {
+ imx_clear_rbc_count();
+ imx_set_cluster_powerdown(core_id, PSCI_LOCAL_STATE_RUN);
+ }
+
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ imx_set_cpu_lpm(core_id, false);
+ plat_gic_cpuif_enable();
+ } else {
+ write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+ isb();
+ }
+}
+
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE;
+}
+
+static void __dead2 imx_wdog_restart(bool external_reset)
+{
+ uintptr_t wdog_base = IMX_WDOG_BASE;
+ unsigned int val;
+
+ val = mmio_read_16(wdog_base);
+ /*
+ * Common watchdog init flags, for additional details check
+ * 6.6.4.1 Watchdog Control Register (WDOGx_WCR)
+ *
+ * Initial bit selection:
+ * WDOG_WCR_WDE - Enable the watchdog.
+ *
+ * 0x000E mask is used to keep previous values (that could be set
+ * in SPL) of WDBG and WDE/WDT (both are write-one once-only bits).
+ */
+ val = (val & 0x000E) | WDOG_WCR_WDE;
+ if (external_reset) {
+ /*
+ * To assert WDOG_B (external reset) we have
+ * to set WDA bit 0 (already set in previous step).
+ * SRS bits are required to be set to 1 (no effect on the
+ * system).
+ */
+ val |= WDOG_WCR_SRS;
+ } else {
+ /*
+ * To assert Software Reset Signal (internal reset) we have
+ * to set SRS bit to 0 (already set in previous step).
+ * SRE bit is required to be set to 1 when used in
+ * conjunction with the Software Reset Signal before
+ * SRS asserton, otherwise SRS bit will just automatically
+ * reset to 1.
+ *
+ * Also we set WDA to 1 (no effect on system).
+ */
+ val |= WDOG_WCR_SRE | WDOG_WCR_WDA;
+ }
+
+ mmio_write_16(wdog_base, val);
+
+ mmio_write_16(wdog_base + WDOG_WSR, 0x5555);
+ mmio_write_16(wdog_base + WDOG_WSR, 0xaaaa);
+ while (1)
+ ;
+}
+
+void __dead2 imx_system_reset(void)
+{
+#ifdef IMX_WDOG_B_RESET
+ imx_wdog_restart(true);
+#else
+ imx_wdog_restart(false);
+#endif
+}
+
+int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie)
+{
+ imx_wdog_restart(false);
+
+ /*
+ * imx_wdog_restart cannot return (as it's a __dead function),
+ * however imx_system_reset2 has to return some value according
+ * to PSCI v1.1 spec.
+ */
+ return 0;
+}
+
+void __dead2 imx_system_off(void)
+{
+ uint32_t val;
+
+ val = mmio_read_32(IMX_SNVS_BASE + SNVS_LPCR);
+ val |= SNVS_LPCR_SRTC_ENV | SNVS_LPCR_DP_EN | SNVS_LPCR_TOP;
+ mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, val);
+
+ while (1)
+ ;
+}
+
+void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+ /*
+ * before enter WAIT or STOP mode with PLAT(SCU) power down,
+ * rbc count need to be enabled to make sure PLAT is
+ * power down successfully even if the the wakeup IRQ is pending
+ * early before the power down sequence. the RBC counter is
+ * drived by the 32K OSC, so delay 30us to make sure the counter
+ * is really running.
+ */
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+ imx_set_rbc_count();
+ udelay(30);
+ }
+
+ while (1)
+ wfi();
+}
diff --git a/plat/imx/imx8m/imx8mm/gpc.c b/plat/imx/imx8m/imx8mm/gpc.c
new file mode 100644
index 0000000..cc1cb10
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/gpc.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <platform_def.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_sip_svc.h>
+
+#define MIPI_PWR_REQ BIT(0)
+#define PCIE_PWR_REQ BIT(1)
+#define OTG1_PWR_REQ BIT(2)
+#define OTG2_PWR_REQ BIT(3)
+#define HSIOMIX_PWR_REQ BIT(4)
+#define GPU2D_PWR_REQ BIT(6)
+#define GPUMIX_PWR_REQ BIT(7)
+#define VPUMIX_PWR_REQ BIT(8)
+#define GPU3D_PWR_REQ BIT(9)
+#define DISPMIX_PWR_REQ BIT(10)
+#define VPU_G1_PWR_REQ BIT(11)
+#define VPU_G2_PWR_REQ BIT(12)
+#define VPU_H1_PWR_REQ BIT(13)
+
+#define HSIOMIX_ADB400_SYNC (0x3 << 5)
+#define DISPMIX_ADB400_SYNC BIT(7)
+#define VPUMIX_ADB400_SYNC BIT(8)
+#define GPU3D_ADB400_SYNC BIT(9)
+#define GPU2D_ADB400_SYNC BIT(10)
+#define GPUMIX_ADB400_SYNC BIT(11)
+#define HSIOMIX_ADB400_ACK (0x3 << 23)
+#define DISPMIX_ADB400_ACK BIT(25)
+#define VPUMIX_ADB400_ACK BIT(26)
+#define GPU3D_ADB400_ACK BIT(27)
+#define GPU2D_ADB400_ACK BIT(28)
+#define GPUMIX_ADB400_ACK BIT(29)
+
+#define MIPI_PGC 0xc00
+#define PCIE_PGC 0xc40
+#define OTG1_PGC 0xc80
+#define OTG2_PGC 0xcc0
+#define HSIOMIX_PGC 0xd00
+#define GPU2D_PGC 0xd80
+#define GPUMIX_PGC 0xdc0
+#define VPUMIX_PGC 0xe00
+#define GPU3D_PGC 0xe40
+#define DISPMIX_PGC 0xe80
+#define VPU_G1_PGC 0xec0
+#define VPU_G2_PGC 0xf00
+#define VPU_H1_PGC 0xf40
+
+enum pu_domain_id {
+ HSIOMIX,
+ PCIE,
+ OTG1,
+ OTG2,
+ GPUMIX,
+ VPUMIX,
+ VPU_G1,
+ VPU_G2,
+ VPU_H1,
+ DISPMIX,
+ MIPI,
+ /* below two domain only for ATF internal use */
+ GPU2D,
+ GPU3D,
+ MAX_DOMAINS,
+};
+
+/* PU domain */
+static struct imx_pwr_domain pu_domains[] = {
+ IMX_MIX_DOMAIN(HSIOMIX, false),
+ IMX_PD_DOMAIN(PCIE, false),
+ IMX_PD_DOMAIN(OTG1, true),
+ IMX_PD_DOMAIN(OTG2, true),
+ IMX_MIX_DOMAIN(GPUMIX, false),
+ IMX_MIX_DOMAIN(VPUMIX, false),
+ IMX_PD_DOMAIN(VPU_G1, false),
+ IMX_PD_DOMAIN(VPU_G2, false),
+ IMX_PD_DOMAIN(VPU_H1, false),
+ IMX_MIX_DOMAIN(DISPMIX, false),
+ IMX_PD_DOMAIN(MIPI, false),
+ /* below two domain only for ATF internal use */
+ IMX_MIX_DOMAIN(GPU2D, false),
+ IMX_MIX_DOMAIN(GPU3D, false),
+};
+
+static unsigned int pu_domain_status;
+
+#define GPU_RCR 0x40
+#define VPU_RCR 0x44
+
+#define VPU_CTL_BASE 0x38330000
+#define BLK_SFT_RSTN_CSR 0x0
+#define H1_SFT_RSTN BIT(2)
+#define G1_SFT_RSTN BIT(1)
+#define G2_SFT_RSTN BIT(0)
+
+#define DISP_CTL_BASE 0x32e28000
+
+void vpu_sft_reset_assert(uint32_t domain_id)
+{
+ uint32_t val;
+
+ val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+ switch (domain_id) {
+ case VPU_G1:
+ val &= ~G1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_G2:
+ val &= ~G2_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_H1:
+ val &= ~H1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ default:
+ break;
+ }
+}
+
+void vpu_sft_reset_deassert(uint32_t domain_id)
+{
+ uint32_t val;
+
+ val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+ switch (domain_id) {
+ case VPU_G1:
+ val |= G1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_G2:
+ val |= G2_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_H1:
+ val |= H1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ default:
+ break;
+ }
+}
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+ if (domain_id >= MAX_DOMAINS) {
+ return;
+ }
+
+ struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+
+ if (on) {
+ pu_domain_status |= (1 << domain_id);
+
+ if (domain_id == VPU_G1 || domain_id == VPU_G2 ||
+ domain_id == VPU_H1) {
+ vpu_sft_reset_assert(domain_id);
+ }
+
+ /* HSIOMIX has no PU bit, so skip for it */
+ if (domain_id != HSIOMIX) {
+ /* clear the PGC bit */
+ mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /* power up the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) {
+ ;
+ }
+ }
+
+ if (domain_id == VPU_G1 || domain_id == VPU_G2 ||
+ domain_id == VPU_H1) {
+ vpu_sft_reset_deassert(domain_id);
+ /* dealy for a while to make sure reset done */
+ udelay(100);
+ }
+
+ if (domain_id == GPUMIX) {
+ /* assert reset */
+ mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x1);
+
+ /* power up GPU2D */
+ mmio_clrbits_32(IMX_GPC_BASE + GPU2D_PGC, 0x1);
+
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, GPU2D_PWR_REQ);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU2D_PWR_REQ) {
+ ;
+ }
+
+ udelay(1);
+
+ /* power up GPU3D */
+ mmio_clrbits_32(IMX_GPC_BASE + GPU3D_PGC, 0x1);
+
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, GPU3D_PWR_REQ);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU3D_PWR_REQ) {
+ ;
+ }
+
+ udelay(10);
+ /* release the gpumix reset */
+ mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x0);
+ udelay(10);
+ }
+
+ /* vpu sft clock enable */
+ if (domain_id == VPUMIX) {
+ mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x1);
+ udelay(5);
+ mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x0);
+ udelay(5);
+
+ /* enable all clock */
+ mmio_write_32(VPU_CTL_BASE + 0x4, 0x7);
+ }
+
+ if (domain_id == DISPMIX) {
+ /* special setting for DISPMIX */
+ mmio_write_32(DISP_CTL_BASE + 0x4, 0x1fff);
+ mmio_write_32(DISP_CTL_BASE, 0x7f);
+ mmio_write_32(DISP_CTL_BASE + 0x8, 0x30000);
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+ /* clear adb power down request */
+ mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+ ;
+ }
+ }
+
+ if (domain_id == GPUMIX) {
+ /* power up GPU2D ADB */
+ mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU2D_ADB400_SYNC);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK)) {
+ ;
+ }
+
+ /* power up GPU3D ADB */
+ mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU3D_ADB400_SYNC);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK)) {
+ ;
+ }
+ }
+ } else {
+ pu_domain_status &= ~(1 << domain_id);
+
+ if (domain_id == OTG1 || domain_id == OTG2) {
+ return;
+ }
+
+ /* GPU2D & GPU3D ADB power down */
+ if (domain_id == GPUMIX) {
+ mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU2D_ADB400_SYNC);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU2D_ADB400_ACK)) {
+ ;
+ }
+
+ mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, GPU3D_ADB400_SYNC);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & GPU3D_ADB400_ACK)) {
+ ;
+ }
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+ /* set adb power down request */
+ mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+ ;
+ }
+ }
+
+ if (domain_id == GPUMIX) {
+ /* power down GPU2D */
+ mmio_setbits_32(IMX_GPC_BASE + GPU2D_PGC, 0x1);
+
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, GPU2D_PWR_REQ);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & GPU2D_PWR_REQ) {
+ ;
+ }
+
+ /* power down GPU3D */
+ mmio_setbits_32(IMX_GPC_BASE + GPU3D_PGC, 0x1);
+
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, GPU3D_PWR_REQ);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & GPU3D_PWR_REQ) {
+ ;
+ }
+ }
+
+ /* HSIOMIX has no PU bit, so skip for it */
+ if (domain_id != HSIOMIX) {
+ /* set the PGC bit */
+ mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /* power down the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) {
+ ;
+ }
+ }
+ }
+}
+
+void imx_gpc_init(void)
+{
+ unsigned int val;
+ int i;
+
+ /* mask all the wakeup irq by default */
+ for (i = 0; i < 4; i++) {
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+ }
+
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ /* use GIC wake_request to wakeup C0~C3 from LPM */
+ val |= 0x30c00000;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~(1 << 6);
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+ mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+ MASTER2_MAPPING));
+
+ /* set all mix/PU in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff);
+
+ /*
+ * Set the CORE & SCU power up timing:
+ * SW = 0x1, SW2ISO = 0x1;
+ * the CPU CORE and SCU power up timming counter
+ * is drived by 32K OSC, each domain's power up
+ * latency is (SW + SW2ISO) / 32768
+ */
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x81);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x81);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x81);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x81);
+ mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x81);
+ mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+ (0x59 << 10) | 0x5B | (0x2 << 20));
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+ A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+ /* clear DSM by default */
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val &= ~SLPCR_EN_DSM;
+ /* enable the fast wakeup wait mode */
+ val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+ /* clear the RBC */
+ val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+ /* set the STBY_COUNT to 0x5, (128 * 30)us */
+ val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+ val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+ mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+ /*
+ * USB PHY power up needs to make sure RESET bit in SRC is clear,
+ * otherwise, the PU power up bit in GPC will NOT self-cleared.
+ * only need to do it once.
+ */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+}
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c
new file mode 100644
index 0000000..c39dd93
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2017-2021 NXP
+ * Copyright 2021 Arm
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <context.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <lib/utils.h>
+#include <stdbool.h>
+#include <tbbr_img_def.h>
+
+#include <imx_aipstz.h>
+#include <imx_csu.h>
+#include <imx_uart.h>
+#include <imx_usdhc.h>
+#include <plat/common/platform.h>
+
+#include "imx8mm_private.h"
+#include "platform_def.h"
+
+static const struct aipstz_cfg aipstz[] = {
+ {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static void imx8mm_usdhc_setup(void)
+{
+ imx_usdhc_params_t params;
+ struct mmc_device_info info;
+
+ params.reg_base = PLAT_IMX8MM_BOOT_MMC_BASE;
+ /*
+ The imx8mm SD Card Speed modes for USDHC2
+ +--------------+--------------------+--------------+--------------+
+ |Bus Speed Mode|Max. Clock Frequency|Max. Bus Speed|Signal Voltage|
+ +--------------+--------------------+--------------+--------------+
+ |Default Speed | 25 MHz | 12.5 MB/s | 3.3V |
+ |High Speed | 50 MHz | 25 MB/s | 3.3V |
+ +--------------+--------------------+--------------+--------------+
+
+ We pick 50 Mhz here for High Speed access.
+ */
+ params.clk_rate = 50000000;
+ params.bus_width = MMC_BUS_WIDTH_1;
+ params.flags = 0;
+ info.mmc_dev_type = MMC_IS_SD;
+ info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
+ imx_usdhc_init(&params, &info);
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ int i;
+ static console_t console;
+
+ /* enable CSU NS access permission */
+ for (i = 0; i < MAX_CSU_NUM; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, CSU_CSL_OPEN_ACCESS);
+ }
+
+ /* config the aips access permission */
+ imx_aipstz_init(aipstz);
+
+ console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+
+ generic_delay_timer_init();
+
+ /* select the CKIL source to 32K OSC */
+ mmio_write_32(0x30360124, 0x1);
+
+ imx8mm_usdhc_setup();
+
+ /* Open handles to a FIP image */
+ plat_imx_io_setup();
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+void bl2_plat_runtime_setup(void)
+{
+ return;
+}
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c b/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c
new file mode 100644
index 0000000..e44345d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ {
+ .image_id = BL31_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, 0),
+
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_SIZE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ /* This is a zero sized image so we don't set base or size */
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+ # ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PLAT_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ # else
+ .ep_info.pc = PLAT_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = PLAT_NS_IMAGE_SIZE,
+ # endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs);
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
new file mode 100644
index 0000000..67bfd36
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2019-2022 ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <dram.h>
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <imx8m_csu.h>
+#include <plat_imx8.h>
+
+#define TRUSTY_PARAMS_LEN_BYTES (4096*2)
+
+/*
+ * Note: DRAM region is mapped with entire size available and uses MT_RW
+ * attributes.
+ * See details in docs/plat/imx8m.rst "High Assurance Boot (HABv4)" section
+ * for explanation of this mapping scheme.
+ */
+static const mmap_region_t imx_mmap[] = {
+ MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW),
+ MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
+ MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW), /* OCRAM_S */
+ MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW), /* DDRMIX */
+ MAP_REGION_FLAT(IMX_VPUMIX_BASE, IMX_VPUMIX_SIZE, MT_DEVICE | MT_RW), /* VPUMIX */
+ MAP_REGION_FLAT(IMX_CAAM_RAM_BASE, IMX_CAAM_RAM_SIZE, MT_MEMORY | MT_RW), /* CAMM RAM */
+ MAP_REGION_FLAT(IMX_NS_OCRAM_BASE, IMX_NS_OCRAM_SIZE, MT_MEMORY | MT_RW), /* NS OCRAM */
+ MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO), /* ROM code */
+ MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), /* DRAM */
+ {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+ {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+ /* Master domain assignment */
+ RDC_MDAn(RDC_MDA_M4, DID1),
+
+ /* peripherals domain permission */
+ RDC_PDAPn(RDC_PDAP_UART4, D1R | D1W),
+ RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
+
+ /* memory region */
+
+ /* Sentinel */
+ {0},
+};
+
+static const struct imx_csu_cfg csu_cfg[] = {
+ /* peripherals csl setting */
+ CSU_CSLx(0x1, CSU_SEC_LEVEL_0, UNLOCKED),
+
+ /* master HP0~1 */
+
+ /* SA setting */
+
+ /* HP control setting */
+
+ /* Sentinel */
+ {0}
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+void bl31_tzc380_setup(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+ if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+ return;
+
+ tzc380_init(IMX_TZASC_BASE);
+
+ /*
+ * Need to substact offset 0x40000000 from CPU address when
+ * programming tzasc region for i.mx8mm.
+ */
+
+ /* Enable 1G-5G S/NS RW */
+ tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+ TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+ int i;
+
+ /* Enable CSU NS access permission */
+ for (i = 0; i < 64; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+ }
+
+ imx_aipstz_init(aipstz);
+
+ imx_rdc_init(rdc);
+
+ imx_csu_init(csu_cfg);
+
+ console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+ /* This console is only used for boot stage */
+ console_set_scope(&console, CONSOLE_FLAG_BOOT);
+
+ imx8m_caam_init();
+
+ /*
+ * tell BL3-1 where the non-secure software image is located
+ * and the entry state information.
+ */
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#if defined(SPD_opteed) || defined(SPD_trusty)
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = 0;
+
+ /* Pass TEE base and size to bl33 */
+ bl33_image_ep_info.args.arg1 = BL32_BASE;
+ bl33_image_ep_info.args.arg2 = BL32_SIZE;
+
+#ifdef SPD_trusty
+ bl32_image_ep_info.args.arg0 = BL32_SIZE;
+ bl32_image_ep_info.args.arg1 = BL32_BASE;
+#else
+ /* Make sure memory is clean */
+ mmio_write_32(BL32_FDT_OVERLAY_ADDR, 0);
+ bl33_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+ bl32_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+#endif
+#endif
+
+ bl31_tzc380_setup();
+}
+
+#define MAP_BL31_TOTAL \
+ MAP_REGION_FLAT(BL31_START, BL31_SIZE, MT_MEMORY | MT_RW | MT_SECURE)
+#define MAP_BL31_RO \
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, MT_MEMORY | MT_RO | MT_SECURE)
+#define MAP_COHERENT_MEM \
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#define MAP_BL32_TOTAL \
+ MAP_REGION_FLAT(BL32_BASE, BL32_SIZE, MT_MEMORY | MT_RW)
+
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL31_TOTAL,
+ MAP_BL31_RO,
+#if USE_COHERENT_MEM
+ MAP_COHERENT_MEM,
+#endif
+ /* Map TEE memory */
+ MAP_BL32_TOTAL,
+ {0}
+ };
+
+ setup_page_tables(bl_regions, imx_mmap);
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ generic_delay_timer_init();
+
+ /* select the CKIL source to 32K OSC */
+ mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+ /* Init the dram info */
+ dram_info_init(SAVED_DRAM_TIMING_BASE);
+
+ plat_gic_driver_init();
+ plat_gic_init();
+
+ imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ if (type == SECURE)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+#ifdef SPD_trusty
+void plat_trusty_set_boot_args(aapcs64_params_t *args)
+{
+ args->arg0 = BL32_SIZE;
+ args->arg1 = BL32_BASE;
+ args->arg2 = TRUSTY_PARAMS_LEN_BYTES;
+}
+#endif
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_psci.c b/plat/imx/imx8m/imx8mm/imx8mm_psci.c
new file mode 100644
index 0000000..815d3a2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_psci.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .validate_power_state = imx_validate_power_state,
+ .cpu_standby = imx_cpu_standby,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .system_reset = imx_system_reset,
+ .system_reset2 = imx_system_reset2,
+ .system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ /* sec_entrypoint is used for warm reset */
+ imx_mailbox_init(sec_entrypoint);
+
+ *psci_ops = &imx_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S b/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S
new file mode 100644
index 0000000..544ee8a
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global imx8mm_rotpk_hash
+ .global imx8mm_rotpk_hash_end
+imx8mm_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+imx8mm_rotpk_hash_end:
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c b/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c
new file mode 100644
index 0000000..a4384d7
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char imx8mm_rotpk_hash[], imx8mm_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = imx8mm_rotpk_hash;
+ *key_len = imx8mm_rotpk_hash_end - imx8mm_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/imx/imx8m/imx8mm/include/gpc_reg.h b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
new file mode 100644
index 0000000..1a4eae5
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x108
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x40
+#define IMR1_CORE2_A53 0x1C0
+#define IMR1_CORE3_A53 0x1D0
+#define IMR1_CORE0_M4 0x50
+#define SLT0_CFG 0xB0
+#define GPC_PU_PWRHSK 0x1FC
+#define PGC_CPU_0_1_MAPPING 0xEC
+#define CPU_PGC_UP_TRG 0xF0
+#define PU_PGC_UP_TRG 0xF8
+#define CPU_PGC_DN_TRG 0xFC
+#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(15)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(2)
+#define A53_PLAT_PUP_ACK BIT(18)
+#define NOC_PDN_SLT_CTRL BIT(10)
+#define NOC_PUP_SLT_CTRL BIT(11)
+#define NOC_PGC_PDN_ACK BIT(3)
+#define NOC_PGC_PUP_ACK BIT(19)
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#define MIPI_PWR_REQ BIT(0)
+#define PCIE_PWR_REQ BIT(1)
+#define OTG1_PWR_REQ BIT(2)
+#define OTG2_PWR_REQ BIT(3)
+#define HSIOMIX_PWR_REQ BIT(4)
+#define DDRMIX_PWR_REQ BIT(5)
+#define GPU2D_PWR_REQ BIT(6)
+#define GPUMIX_PWR_REQ BIT(7)
+#define VPUMIX_PWR_REQ BIT(8)
+#define GPU3D_PWR_REQ BIT(9)
+#define DISPMIX_PWR_REQ BIT(10)
+#define VPU_G1_PWR_REQ BIT(11)
+#define VPU_G2_PWR_REQ BIT(12)
+#define VPU_H1_PWR_REQ BIT(13)
+
+#define DDRMIX_ADB400_SYNC BIT(2)
+#define HSIOMIX_ADB400_SYNC (0x3 << 5)
+#define DISPMIX_ADB400_SYNC BIT(7)
+#define VPUMIX_ADB400_SYNC BIT(8)
+#define GPU3D_ADB400_SYNC BIT(9)
+#define GPU2D_ADB400_SYNC BIT(10)
+#define GPUMIX_ADB400_SYNC BIT(11)
+#define DDRMIX_ADB400_ACK BIT(20)
+#define HSIOMIX_ADB400_ACK (0x3 << 23)
+#define DISPMIX_ADB400_ACK BIT(25)
+#define VPUMIX_ADB400_ACK BIT(26)
+#define GPU3D_ADB400_ACK BIT(27)
+#define GPU2D_ADB400_ACK BIT(28)
+#define GPUMIX_ADB400_ACK BIT(29)
+
+#define MIPI_PGC 0xc00
+#define PCIE_PGC 0xc40
+#define OTG1_PGC 0xc80
+#define OTG2_PGC 0xcc0
+#define HSIOMIX_PGC 0xd00
+#define DDRMIX_PGC 0xd40
+#define GPU2D_PGC 0xd80
+#define GPUMIX_PGC 0xdc0
+#define VPUMIX_PGC 0xe00
+#define GPU3D_PGC 0xe40
+#define DISPMIX_PGC 0xe80
+#define VPU_G1_PGC 0xec0
+#define VPU_G2_PGC 0xf00
+#define VPU_H1_PGC 0xf40
+
+#define IRQ_IMR_NUM U(4)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mm/include/imx8mm_private.h b/plat/imx/imx8m/imx8mm/include/imx8mm_private.h
new file mode 100644
index 0000000..5e0ef97
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/imx8mm_private.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8MM_PRIVATE_H
+#define IMX8MM_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_imx_io_setup(void);
+
+#endif /* IMX8MM_PRIVATE_H */
diff --git a/plat/imx/imx8m/imx8mm/include/imx_sec_def.h b/plat/imx/imx8m/imx8mm/include/imx_sec_def.h
new file mode 100644
index 0000000..6215983
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/imx_sec_def.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_SEC_DEF_H
+#define IMX_SEC_DEF_H
+
+/* RDC MDA index */
+enum rdc_mda_idx {
+ RDC_MDA_A53 = 0,
+ RDC_MDA_M4 = 1,
+ RDC_MDA_PCIE_CTRL1 = 2,
+ RDC_MDA_SDMA3p = 3,
+ RDC_MDA_VPU_Decoders = 4,
+ RDC_MDA_LCDIF = 5,
+ RDC_MDA_CSI1 = 6,
+ RDC_MDA_SDMA3b = 7,
+ RDC_MDA_Coresight = 8,
+ RDC_MDA_DAP = 9,
+ RDC_MDA_CAAM = 10,
+ RDC_MDA_SDMA1p = 11,
+ RDC_MDA_SDMA1b = 12,
+ RDC_MDA_APBHDMA = 13,
+ RDC_MDA_NAND = 14,
+ RDC_MDA_uSDHC1 = 15,
+ RDC_MDA_uSDHC2 = 16,
+ RDC_MDA_uSDHC3 = 17,
+ RDC_MDA_GPU = 18,
+ RDC_MDA_USB1 = 19,
+ RDC_MDA_USB2 = 20,
+ RDC_MDA_TESTPORT = 21,
+ RDC_MDA_ENET1_TX = 22,
+ RDC_MDA_ENET1_RX = 23,
+ RDC_MDA_SDMA2p = 24,
+ RDC_MDA_SDMA2b = 24,
+ RDC_MDA_SDMA2_to_SPBA2 = 24,
+ RDC_MDA_SDMA3_to_SPBA2 = 25,
+ RDC_MDA_SDMA1_to_SPBA1 = 26,
+};
+
+/* RDC Peripherals index */
+enum rdc_pdap_idx {
+ RDC_PDAP_GPIO2 = 1,
+ RDC_PDAP_GPIO3 = 2,
+ RDC_PDAP_GPIO4 = 3,
+ RDC_PDAP_GPIO5 = 4,
+ RDC_PDAP_ANA_TSENSOR = 6,
+ RDC_PDAP_ANA_OSC = 7,
+ RDC_PDAP_WDOG1 = 8,
+ RDC_PDAP_WDOG2 = 9,
+ RDC_PDAP_WDOG3 = 10,
+ RDC_PDAP_SDMA3 = 11,
+ RDC_PDAP_SDMA2 = 12,
+ RDC_PDAP_GPT1 = 13,
+ RDC_PDAP_GPT2 = 14,
+ RDC_PDAP_GPT3 = 15,
+ RDC_PDAP_ROMCP = 17,
+ RDC_PDAP_IOMUXC = 19,
+ RDC_PDAP_IOMUXC_GPR = 20,
+ RDC_PDAP_OCOTP_CTRL = 21,
+ RDC_PDAP_ANA_PLL = 22,
+ RDC_PDAP_SNVS_HP = 23,
+ RDC_PDAP_CCM = 24,
+ RDC_PDAP_SRC = 25,
+ RDC_PDAP_GPC = 26,
+ RDC_PDAP_SEMAPHORE1 = 27,
+ RDC_PDAP_SEMAPHORE2 = 28,
+ RDC_PDAP_RDC = 29,
+ RDC_PDAP_CSU = 30,
+ RDC_PDAP_LCDIF = 32,
+ RDC_PDAP_MIPI_DSI = 33,
+ RDC_PDAP_CSI = 34,
+ RDC_PDAP_MIPI_CSI = 35,
+ RDC_PDAP_USB1 = 36,
+ RDC_PDAP_PWM1 = 38,
+ RDC_PDAP_PWM2 = 39,
+ RDC_PDAP_PWM3 = 40,
+ RDC_PDAP_PWM4 = 41,
+ RDC_PDAP_System_Counter_RD = 42,
+ RDC_PDAP_System_Counter_CMP = 43,
+ RDC_PDAP_System_Counter_CTRL = 44,
+ RDC_PDAP_GPT6 = 46,
+ RDC_PDAP_GPT5 = 47,
+ RDC_PDAP_GPT4 = 48,
+ RDC_PDAP_TZASC = 56,
+ RDC_PDAP_USB2 = 59,
+ RDC_PDAP_PERFMON1 = 60,
+ RDC_PDAP_PERFMON2 = 61,
+ RDC_PDAP_PLATFORM_CTRL = 62,
+ RDC_PDAP_QoSC = 63,
+ RDC_PDAP_I2C1 = 66,
+ RDC_PDAP_I2C2 = 67,
+ RDC_PDAP_I2C3 = 68,
+ RDC_PDAP_I2C4 = 69,
+ RDC_PDAP_UART4 = 70,
+ RDC_PDAP_MU_A = 74,
+ RDC_PDAP_MU_B = 75,
+ RDC_PDAP_SEMAPHORE_HS = 76,
+ RDC_PDAP_SAI1 = 78,
+ RDC_PDAP_SAI2 = 79,
+ RDC_PDAP_SAI3 = 80,
+ RDC_PDAP_SAI5 = 82,
+ RDC_PDAP_SAI6 = 83,
+ RDC_PDAP_uSDHC1 = 84,
+ RDC_PDAP_uSDHC2 = 85,
+ RDC_PDAP_uSDHC3 = 86,
+ RDC_PDAP_PCIE_PHY1 = 88,
+ RDC_PDAP_SPBA2 = 90,
+ RDC_PDAP_QSPI = 91,
+ RDC_PDAP_SDMA1 = 93,
+ RDC_PDAP_ENET1 = 94,
+ RDC_PDAP_SPDIF1 = 97,
+ RDC_PDAP_eCSPI1 = 98,
+ RDC_PDAP_eCSPI2 = 99,
+ RDC_PDAP_eCSPI3 = 100,
+ RDC_PDAP_MICFIL = 101,
+ RDC_PDAP_UART1 = 102,
+ RDC_PDAP_UART3 = 104,
+ RDC_PDAP_UART2 = 105,
+ RDC_PDAP_SPDIF2 = 106,
+ RDC_PDAP_SPBA1 = 111,
+ RDC_PDAP_CAAM = 114,
+};
+
+enum csu_csl_idx {
+ CSU_CSL_GPIO1 = 0,
+ CSU_CSL_GPIO2 = 1,
+ CSU_CSL_GPIO3 = 2,
+ CSU_CSL_GPIO4 = 3,
+ CSU_CSL_GPIO5 = 4,
+ CSU_CSL_ANA_TSENSOR = 6,
+ CSU_CSL_ANA_OSC = 7,
+ CSU_CSL_WDOG1 = 8,
+ CSU_CSL_WDOG2 = 9,
+ CSU_CSL_WDOG3 = 10,
+ CSU_CSL_SDMA2 = 12,
+ CSU_CSL_GPT1 = 13,
+ CSU_CSL_GPT2 = 14,
+ CSU_CSL_GPT3 = 15,
+ CSU_CSL_ROMCP = 17,
+ CSU_CSL_LCDIF = 18,
+ CSU_CSL_IOMUXC = 19,
+ CSU_CSL_IOMUXC_GPR = 20,
+ CSU_CSL_OCOTP_CTRL = 21,
+ CSU_CSL_ANA_PLL = 22,
+ CSU_CSL_SNVS_HP = 23,
+ CSU_CSL_CCM = 24,
+ CSU_CSL_SRC = 25,
+ CSU_CSL_GPC = 26,
+ CSU_CSL_SEMAPHORE1 = 27,
+ CSU_CSL_SEMAPHORE2 = 28,
+ CSU_CSL_RDC = 29,
+ CSU_CSL_CSU = 30,
+ CSU_CSL_DC_MST0 = 32,
+ CSU_CSL_DC_MST1 = 33,
+ CSU_CSL_DC_MST2 = 34,
+ CSU_CSL_DC_MST3 = 35,
+ CSU_CSL_PWM1 = 38,
+ CSU_CSL_PWM2 = 39,
+ CSU_CSL_PWM3 = 40,
+ CSU_CSL_PWM4 = 41,
+ CSU_CSL_System_Counter_RD = 42,
+ CSU_CSL_System_Counter_CMP = 43,
+ CSU_CSL_System_Counter_CTRL = 44,
+ CSU_CSL_GPT6 = 46,
+ CSU_CSL_GPT5 = 47,
+ CSU_CSL_GPT4 = 48,
+ CSU_CSL_TZASC = 56,
+ CSU_CSL_MTR = 59,
+ CSU_CSL_PERFMON1 = 60,
+ CSU_CSL_PERFMON2 = 61,
+ CSU_CSL_PLATFORM_CTRL = 62,
+ CSU_CSL_QoSC = 63,
+ CSU_CSL_MIPI_PHY = 64,
+ CSU_CSL_MIPI_DSI = 65,
+ CSU_CSL_I2C1 = 66,
+ CSU_CSL_I2C2 = 67,
+ CSU_CSL_I2C3 = 68,
+ CSU_CSL_I2C4 = 69,
+ CSU_CSL_UART4 = 70,
+ CSU_CSL_MIPI_CSI1 = 71,
+ CSU_CSL_MIPI_CSI_PHY1 = 72,
+ CSU_CSL_CSI1 = 73,
+ CSU_CSL_MU_A = 74,
+ CSU_CSL_MU_B = 75,
+ CSU_CSL_SEMAPHORE_HS = 76,
+ CSU_CSL_SAI1 = 78,
+ CSU_CSL_SAI6 = 80,
+ CSU_CSL_SAI5 = 81,
+ CSU_CSL_SAI4 = 82,
+ CSU_CSL_uSDHC1 = 84,
+ CSU_CSL_uSDHC2 = 85,
+ CSU_CSL_MIPI_CSI2 = 86,
+ CSU_CSL_MIPI_CSI_PHY2 = 87,
+ CSU_CSL_CSI2 = 88,
+ CSU_CSL_SPBA2 = 90,
+ CSU_CSL_QSPI = 91,
+ CSU_CSL_SDMA1 = 93,
+ CSU_CSL_ENET1 = 94,
+ CSU_CSL_SPDIF1 = 97,
+ CSU_CSL_eCSPI1 = 98,
+ CSU_CSL_eCSPI2 = 99,
+ CSU_CSL_eCSPI3 = 100,
+ CSU_CSL_UART1 = 102,
+ CSU_CSL_UART3 = 104,
+ CSU_CSL_UART2 = 105,
+ CSU_CSL_SPDIF2 = 106,
+ CSU_CSL_SAI2 = 107,
+ CSU_CSL_SAI3 = 108,
+ CSU_CSL_SPBA1 = 111,
+ CSU_CSL_CAAM = 114,
+};
+
+#endif /* IMX_SEC_DEF_H */
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
new file mode 100644
index 0000000..65749f3
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0xB00
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(4)
+#define PLAT_MAX_RET_STATE U(2)
+
+#define PLAT_WAIT_RET_STATE U(1)
+#define PLAT_STOP_OFF_STATE U(3)
+
+#define PLAT_PRI_BITS U(3)
+#define PLAT_SDEI_CRITICAL_PRI 0x10
+#define PLAT_SDEI_NORMAL_PRI 0x20
+#define PLAT_SDEI_SGI_PRIVATE U(9)
+
+#if defined(NEED_BL2)
+#define BL2_BASE U(0x920000)
+#define BL2_SIZE SZ_128K
+#define BL2_LIMIT (BL2_BASE + BL2_SIZE)
+#define BL31_BASE U(0x900000)
+#define IMX_FIP_BASE U(0x40310000)
+#define IMX_FIP_SIZE U(0x000300000)
+#define IMX_FIP_LIMIT U(FIP_BASE + FIP_SIZE)
+
+/* Define FIP image location on eMMC */
+#define IMX_FIP_MMC_BASE U(0x100000)
+
+#define PLAT_IMX8MM_BOOT_MMC_BASE U(0x30B50000) /* SD */
+#else
+#define BL31_BASE U(0x920000)
+#endif
+
+#define BL31_SIZE SZ_128K
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET U(0x40200000)
+#define PLAT_NS_IMAGE_SIZE U(0x00200000)
+
+#define BL32_FDT_OVERLAY_ADDR (PLAT_NS_IMAGE_OFFSET + 0x3000000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE U(0x38800000)
+#define PLAT_GICR_BASE U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 16
+
+#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */
+
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ 24000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define IMX_AIPSTZ1 U(0x301f0000)
+#define IMX_AIPSTZ2 U(0x305f0000)
+#define IMX_AIPSTZ3 U(0x309f0000)
+#define IMX_AIPSTZ4 U(0x32df0000)
+
+#define IMX_AIPS_BASE U(0x30000000)
+#define IMX_AIPS_SIZE U(0x3000000)
+#define IMX_GPV_BASE U(0x32000000)
+#define IMX_GPV_SIZE U(0x800000)
+#define IMX_AIPS1_BASE U(0x30200000)
+#define IMX_AIPS4_BASE U(0x32c00000)
+#define IMX_ANAMIX_BASE U(0x30360000)
+#define IMX_CCM_BASE U(0x30380000)
+#define IMX_SRC_BASE U(0x30390000)
+#define IMX_GPC_BASE U(0x303a0000)
+#define IMX_RDC_BASE U(0x303d0000)
+#define IMX_CSU_BASE U(0x303e0000)
+#define IMX_WDOG_BASE U(0x30280000)
+#define IMX_SNVS_BASE U(0x30370000)
+#define IMX_NOC_BASE U(0x32700000)
+#define IMX_TZASC_BASE U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE U(0x30340000)
+#define IMX_CAAM_BASE U(0x30900000)
+#define IMX_DDRC_BASE U(0x3d400000)
+#define IMX_DDRPHY_BASE U(0x3c000000)
+#define IMX_DDR_IPS_BASE U(0x3d000000)
+#define IMX_DDR_IPS_SIZE U(0x1800000)
+#define IMX_VPUMIX_BASE U(0x38330000)
+#define IMX_VPUMIX_SIZE U(0x100000)
+#define IMX_ROM_BASE U(0x0)
+#define IMX_ROM_SIZE U(0x40000)
+#define IMX_NS_OCRAM_BASE U(0x900000)
+#define IMX_NS_OCRAM_SIZE U(0x20000)
+#define IMX_CAAM_RAM_BASE U(0x100000)
+#define IMX_CAAM_RAM_SIZE U(0x10000)
+#define IMX_DRAM_BASE U(0x40000000)
+#define IMX_DRAM_SIZE U(0xc0000000)
+
+#define GPV_BASE U(0x32000000)
+#define GPV_SIZE U(0x800000)
+#define IMX_GIC_BASE PLAT_GICD_BASE
+#define IMX_GIC_SIZE U(0x200000)
+
+#define WDOG_WSR U(0x2)
+#define WDOG_WCR_WDZST BIT(0)
+#define WDOG_WCR_WDBG BIT(1)
+#define WDOG_WCR_WDE BIT(2)
+#define WDOG_WCR_WDT BIT(3)
+#define WDOG_WCR_SRS BIT(4)
+#define WDOG_WCR_WDA BIT(5)
+#define WDOG_WCR_SRE BIT(6)
+#define WDOG_WCR_WDW BIT(7)
+
+#define SRC_A53RCR0 U(0x4)
+#define SRC_A53RCR1 U(0x8)
+#define SRC_OTG1PHY_SCR U(0x20)
+#define SRC_OTG2PHY_SCR U(0x24)
+#define SRC_GPR1_OFFSET U(0x74)
+#define SRC_GPR10_OFFSET U(0x98)
+#define SRC_GPR10_PERSIST_SECONDARY_BOOT BIT(30)
+
+#define SNVS_LPCR U(0x38)
+#define SNVS_LPCR_SRTC_ENV BIT(0)
+#define SNVS_LPCR_DP_EN BIT(5)
+#define SNVS_LPCR_TOP BIT(6)
+
+#define IOMUXC_GPR10 U(0x28)
+#define GPR_TZASC_EN BIT(0)
+#define GPR_TZASC_EN_LOCK BIT(16)
+
+#define ANAMIX_MISC_CTL U(0x124)
+#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM U(64)
+
+#define OCRAM_S_BASE U(0x00180000)
+#define OCRAM_S_SIZE U(0x8000)
+#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY 8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define MAX_IO_HANDLES 3U
+#define MAX_IO_DEVICES 2U
+#define MAX_IO_BLOCK_DEVICES 1U
+
+#define PLAT_IMX8M_DTO_BASE 0x53000000
+#define PLAT_IMX8M_DTO_MAX_SIZE 0x1000
+#define PLAT_IMX_EVENT_LOG_MAX_SIZE UL(0x400)
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
new file mode 100644
index 0000000..7a42554
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -0,0 +1,185 @@
+#
+# Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Iplat/imx/common/include \
+ -Iplat/imx/imx8m/include \
+ -Iplat/imx/imx8m/imx8mm/include \
+ -Idrivers/imx/usdhc \
+ -Iinclude/common/tbbr \
+ -Iinclude/lib/libfdt
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+include lib/libfdt/libfdt.mk
+
+IMX_DRAM_SOURCES := plat/imx/imx8m/ddr/dram.c \
+ plat/imx/imx8m/ddr/clock.c \
+ plat/imx/imx8m/ddr/dram_retention.c \
+ plat/imx/imx8m/ddr/ddr4_dvfs.c \
+ plat/imx/imx8m/ddr/lpddr4_dvfs.c
+
+IMX_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8m/gpc_common.c \
+ plat/imx/imx8m/imx_hab.c \
+ plat/imx/imx8m/imx_aipstz.c \
+ plat/imx/imx8m/imx_rdc.c \
+ plat/imx/imx8m/imx8m_csu.c \
+ plat/imx/imx8m/imx8m_caam.c \
+ plat/imx/imx8m/imx8m_psci_common.c \
+ plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c \
+ plat/imx/imx8m/imx8mm/imx8mm_psci.c \
+ plat/imx/imx8m/imx8mm/gpc.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx_sip_handler.c \
+ plat/imx/common/imx_sip_svc.c \
+ plat/imx/common/imx_uart_console.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/tzc/tzc380.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${IMX_DRAM_SOURCES} \
+ ${IMX_GIC_SOURCES}
+
+ifeq (${NEED_BL2},yes)
+BL2_SOURCES += common/desc_image_load.c \
+ common/fdt_wrappers.c \
+ plat/imx/common/imx8_helpers.S \
+ plat/imx/common/imx_uart_console.S \
+ plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c \
+ plat/imx/imx8m/imx8mm/gpc.c \
+ plat/imx/imx8m/imx_aipstz.c \
+ plat/common/plat_psci_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${PLAT_GIC_SOURCES} \
+ ${PLAT_DRAM_SOURCES} \
+ drivers/mmc/mmc.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ drivers/imx/usdhc/imx_usdhc.c \
+ plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c \
+ plat/imx/common/imx_io_storage.c \
+ plat/imx/imx8m/imx8m_image_load.c \
+ lib/optee/optee_utils.c
+endif
+
+# Add the build options to pack BLx images and kernel device tree
+# in the FIP if the platform requires.
+ifneq ($(BL2),)
+RESET_TO_BL31 := 0
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
+endif
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+ifneq ($(HW_CONFIG),)
+$(eval $(call TOOL_ADD_IMG,HW_CONFIG,--hw-config))
+endif
+
+ifeq (${NEED_BL2},yes)
+$(eval $(call add_define,NEED_BL2))
+LOAD_IMAGE_V2 := 1
+# Non-TF Boot ROM
+BL2_AT_EL3 := 1
+endif
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c \
+ plat/imx/imx8m/imx8mm/imx8mm_rotpk.S
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(eval $(call MAKE_LIB_DIRS))
+
+$(BUILD_PLAT)/bl2/imx8mm_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ @if [ ! -f $(ROT_KEY) ]; then \
+ ${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null; \
+ fi
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
+
+ENABLE_PIE := 1
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+BL32_BASE ?= 0xbe000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE ?= 0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE ?= 0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
+
+EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT)
+ifeq (${SDEI_SUPPORT}, 1)
+BL31_SOURCES += plat/imx/common/imx_ehf.c \
+ plat/imx/common/imx_sdei.c
+endif
+
+ifeq (${MEASURED_BOOT},1)
+ MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
+ $(info Including ${MEASURED_BOOT_MK})
+ include ${MEASURED_BOOT_MK}
+
+ifneq (${MBOOT_EL_HASH_ALG}, sha256)
+ $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
+endif
+
+BL2_SOURCES += plat/imx/imx8m/imx8m_measured_boot.c \
+ plat/imx/imx8m/imx8m_dyn_cfg_helpers.c \
+ ${EVENT_LOG_SOURCES}
+endif
+
+ifeq (${SPD},trusty)
+ BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
+endif
diff --git a/plat/imx/imx8m/imx8mn/gpc.c b/plat/imx/imx8m/imx8mn/gpc.c
new file mode 100644
index 0000000..4e05297
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/gpc.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_sip_svc.h>
+#include <platform_def.h>
+
+#define CCGR(x) (0x4000 + (x) * 0x10)
+
+#define MIPI_PWR_REQ BIT(0)
+#define OTG1_PWR_REQ BIT(2)
+#define HSIOMIX_PWR_REQ BIT(4)
+#define GPUMIX_PWR_REQ BIT(7)
+#define DISPMIX_PWR_REQ BIT(10)
+
+#define HSIOMIX_ADB400_SYNC BIT(5)
+#define DISPMIX_ADB400_SYNC BIT(7)
+#define GPUMIX_ADB400_SYNC (0x5 << 9)
+#define HSIOMIX_ADB400_ACK BIT(23)
+#define DISPMIX_ADB400_ACK BIT(25)
+#define GPUMIX_ADB400_ACK (0x5 << 27)
+
+#define MIPI_PGC 0xc00
+#define OTG1_PGC 0xc80
+#define HSIOMIX_PGC 0xd00
+#define GPUMIX_PGC 0xdc0
+#define DISPMIX_PGC 0xe80
+
+enum pu_domain_id {
+ HSIOMIX,
+ OTG1 = 2,
+ GPUMIX = 4,
+ DISPMIX = 9,
+ MIPI,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[11] = {
+ [HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+ [OTG1] = IMX_PD_DOMAIN(OTG1, true),
+ [GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+ [DISPMIX] = IMX_MIX_DOMAIN(DISPMIX, false),
+ [MIPI] = IMX_PD_DOMAIN(MIPI, true),
+};
+
+static unsigned int pu_domain_status;
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+ if (domain_id > MIPI) {
+ return;
+ }
+
+ struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+
+ if (on) {
+ if (pwr_domain->need_sync) {
+ pu_domain_status |= (1 << domain_id);
+ }
+
+ /* HSIOMIX has no PU bit, so skip for it */
+ if (domain_id != HSIOMIX) {
+ /* clear the PGC bit */
+ mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /* power up the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) {
+ ;
+ }
+ }
+
+ if (domain_id == DISPMIX) {
+ /* de-reset bus_blk clk and
+ * enable bus_blk clk
+ */
+ mmio_write_32(0x32e28000, 0x100);
+ mmio_write_32(0x32e28004, 0x100);
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+ /* clear adb power down request */
+ mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+ ;
+ }
+ }
+ } else {
+ pu_domain_status &= ~(1 << domain_id);
+
+ if (domain_id == OTG1) {
+ return;
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+
+ /* set adb power down request */
+ mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
+ ;
+ }
+ }
+
+ /* HSIOMIX has no PU bit, so skip for it */
+ if (domain_id != HSIOMIX) {
+ /* set the PGC bit */
+ mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /* power down the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) {
+ ;
+ }
+ }
+ }
+}
+
+void imx_gpc_init(void)
+{
+ unsigned int val;
+ int i;
+
+ /* mask all the wakeup irq by default */
+ for (i = 0; i < 4; i++) {
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+ }
+
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ /* use GIC wake_request to wakeup C0~C3 from LPM */
+ val |= CORE_WKUP_FROM_GIC;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~MASTER0_LPM_HSK;
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+ mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+ MASTER2_MAPPING));
+
+ /* set all mix/PU in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff);
+
+ /*
+ * Set the CORE & SCU power up timing:
+ * SW = 0x1, SW2ISO = 0x1;
+ * the CPU CORE and SCU power up timming counter
+ * is drived by 32K OSC, each domain's power up
+ * latency is (SW + SW2ISO) / 32768
+ */
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+ (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+ A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+ /* clear DSM by default */
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val &= ~SLPCR_EN_DSM;
+ /* enable the fast wakeup wait mode */
+ val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+ /* clear the RBC */
+ val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+ /* set the STBY_COUNT to 0x5, (128 * 30)us */
+ val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+ val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+ mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+ /*
+ * USB PHY power up needs to make sure RESET bit in SRC is clear,
+ * otherwise, the PU power up bit in GPC will NOT self-cleared.
+ * only need to do it once.
+ */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+}
diff --git a/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
new file mode 100644
index 0000000..eff198d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <dram.h>
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <imx8m_csu.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+
+#define TRUSTY_PARAMS_LEN_BYTES (4096*2)
+
+static const mmap_region_t imx_mmap[] = {
+ GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
+ CAAM_RAM_MAP, NS_OCRAM_MAP, ROM_MAP, DRAM_MAP,
+ {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+ {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+ /* Master domain assignment */
+ RDC_MDAn(RDC_MDA_M7, DID1),
+
+ /* peripherals domain permission */
+ RDC_PDAPn(RDC_PDAP_UART4, D1R | D1W),
+ RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
+
+ /* memory region */
+ RDC_MEM_REGIONn(16, 0x0, 0x0, 0xff),
+ RDC_MEM_REGIONn(17, 0x0, 0x0, 0xff),
+ RDC_MEM_REGIONn(18, 0x0, 0x0, 0xff),
+
+ /* Sentinel */
+ {0},
+};
+
+static const struct imx_csu_cfg csu_cfg[] = {
+ /* peripherals csl setting */
+ CSU_CSLx(CSU_CSL_OCRAM, CSU_SEC_LEVEL_2, UNLOCKED),
+ CSU_CSLx(CSU_CSL_OCRAM_S, CSU_SEC_LEVEL_2, UNLOCKED),
+
+ /* master HP0~1 */
+
+ /* SA setting */
+
+ /* HP control setting */
+
+ /* Sentinel */
+ {0}
+};
+
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+static void bl31_tzc380_setup(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+ if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+ return;
+
+ tzc380_init(IMX_TZASC_BASE);
+
+ /*
+ * Need to substact offset 0x40000000 from CPU address when
+ * programming tzasc region for i.mx8mn.
+ */
+
+ /* Enable 1G-5G S/NS RW */
+ tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+ TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+ unsigned int val;
+ int i;
+
+ /* Enable CSU NS access permission */
+ for (i = 0; i < 64; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+ }
+
+ imx_aipstz_init(aipstz);
+
+ imx_rdc_init(rdc);
+
+ imx_csu_init(csu_cfg);
+
+ /* config the ocram memory range for secure access */
+ mmio_write_32(IMX_IOMUX_GPR_BASE + 0x2c, 0x4c1);
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x2c);
+ mmio_write_32(IMX_IOMUX_GPR_BASE + 0x2c, val | 0x3DFF0000);
+
+ console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+ /* This console is only used for boot stage */
+ console_set_scope(&console, CONSOLE_FLAG_BOOT);
+
+ imx8m_caam_init();
+
+ /*
+ * tell BL3-1 where the non-secure software image is located
+ * and the entry state information.
+ */
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#if defined(SPD_opteed) || defined(SPD_trusty)
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = 0;
+
+ /* Pass TEE base and size to bl33 */
+ bl33_image_ep_info.args.arg1 = BL32_BASE;
+ bl33_image_ep_info.args.arg2 = BL32_SIZE;
+
+#ifdef SPD_trusty
+ bl32_image_ep_info.args.arg0 = BL32_SIZE;
+ bl32_image_ep_info.args.arg1 = BL32_BASE;
+#else
+ /* Make sure memory is clean */
+ mmio_write_32(BL32_FDT_OVERLAY_ADDR, 0);
+ bl33_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+ bl32_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+#endif
+#endif
+
+ bl31_tzc380_setup();
+}
+
+#define MAP_BL31_TOTAL \
+ MAP_REGION_FLAT(BL31_START, BL31_SIZE, MT_MEMORY | MT_RW | MT_SECURE)
+#define MAP_BL31_RO \
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, MT_MEMORY | MT_RO | MT_SECURE)
+#define MAP_COHERENT_MEM \
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#define MAP_BL32_TOTAL \
+ MAP_REGION_FLAT(BL32_BASE, BL32_SIZE, MT_MEMORY | MT_RW)
+
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL31_TOTAL,
+ MAP_BL31_RO,
+#if USE_COHERENT_MEM
+ MAP_COHERENT_MEM,
+#endif
+ /* Map TEE memory */
+ MAP_BL32_TOTAL,
+ {0}
+ };
+
+ setup_page_tables(bl_regions, imx_mmap);
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ generic_delay_timer_init();
+
+ /* select the CKIL source to 32K OSC */
+ mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+ /* Init the dram info */
+ dram_info_init(SAVED_DRAM_TIMING_BASE);
+
+ plat_gic_driver_init();
+ plat_gic_init();
+
+ imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ if (type == SECURE)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+#ifdef SPD_trusty
+void plat_trusty_set_boot_args(aapcs64_params_t *args)
+{
+ args->arg0 = BL32_SIZE;
+ args->arg1 = BL32_BASE;
+ args->arg2 = TRUSTY_PARAMS_LEN_BYTES;
+}
+#endif
diff --git a/plat/imx/imx8m/imx8mn/imx8mn_psci.c b/plat/imx/imx8m/imx8mn/imx8mn_psci.c
new file mode 100644
index 0000000..f541fc1
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/imx8mn_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .validate_power_state = imx_validate_power_state,
+ .cpu_standby = imx_cpu_standby,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .system_reset = imx_system_reset,
+ .system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ /* sec_entrypoint is used for warm reset */
+ imx_mailbox_init(sec_entrypoint);
+
+ *psci_ops = &imx_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
new file mode 100644
index 0000000..8a81368
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x108
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x40
+#define IMR1_CORE2_A53 0x1C0
+#define IMR1_CORE3_A53 0x1D0
+#define IMR1_CORE0_M4 0x50
+#define SLT0_CFG 0xB0
+#define GPC_PU_PWRHSK 0x1FC
+#define PGC_CPU_0_1_MAPPING 0xEC
+#define CPU_PGC_UP_TRG 0xF0
+#define PU_PGC_UP_TRG 0xF8
+#define CPU_PGC_DN_TRG 0xFC
+#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(15)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(2)
+#define A53_PLAT_PUP_ACK BIT(18)
+#define NOC_PDN_SLT_CTRL BIT(10)
+#define NOC_PUP_SLT_CTRL BIT(11)
+#define NOC_PGC_PDN_ACK BIT(3)
+#define NOC_PGC_PUP_ACK BIT(19)
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#define TMR_TCD2_SHIFT 0
+#define TMC_TMR_SHIFT 10
+#define TRC1_TMC_SHIFT 20
+
+#define MIPI_PWR_REQ BIT(0)
+#define OTG1_PWR_REQ BIT(2)
+#define HSIOMIX_PWR_REQ BIT(4)
+#define DDRMIX_PWR_REQ BIT(5)
+#define GPUMIX_PWR_REQ BIT(7)
+#define DISPMIX_PWR_REQ BIT(10)
+
+#define DDRMIX_ADB400_SYNC BIT(2)
+#define HSIOMIX_ADB400_SYNC BIT(5)
+#define DISPMIX_ADB400_SYNC BIT(7)
+#define GPUMIX_ADB400_SYNC (0x5 << 9)
+#define DDRMIX_ADB400_ACK BIT(20)
+#define HSIOMIX_ADB400_ACK BIT(23)
+#define DISPMIX_ADB400_ACK BIT(25)
+#define GPUMIX_ADB400_ACK (0x5 << 27)
+
+#define MIPI_PGC 0xc00
+#define OTG1_PGC 0xc80
+#define HSIOMIX_PGC 0xd00
+#define DDRMIX_PGC 0xd40
+#define GPUMIX_PGC 0xdc0
+#define DISPMIX_PGC 0xe80
+
+#define IRQ_IMR_NUM U(4)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mn/include/imx_sec_def.h b/plat/imx/imx8m/imx8mn/include/imx_sec_def.h
new file mode 100644
index 0000000..0ef14a9
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/imx_sec_def.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_SEC_DEF_H
+#define IMX_SEC_DEF_H
+
+/* RDC MDA index */
+enum rdc_mda_idx {
+ RDC_MDA_A53 = 0,
+ RDC_MDA_M7 = 1,
+ RDC_MDA_SDMA3p = 3,
+ RDC_MDA_LCDIF = 5,
+ RDC_MDA_ISI = 6,
+ RDC_MDA_SDMA3b = 7,
+ RDC_MDA_Coresight = 8,
+ RDC_MDA_DAP = 9,
+ RDC_MDA_CAAM = 10,
+ RDC_MDA_SDMA1p = 11,
+ RDC_MDA_SDMA1b = 12,
+ RDC_MDA_APBHDMA = 13,
+ RDC_MDA_RAWNAND = 14,
+ RDC_MDA_uSDHC1 = 15,
+ RDC_MDA_uSDHC2 = 16,
+ RDC_MDA_uSDHC3 = 17,
+ RDC_MDA_GPU = 18,
+ RDC_MDA_USB1 = 19,
+ RDC_MDA_TESTPORT = 21,
+ RDC_MDA_ENET1_TX = 22,
+ RDC_MDA_ENET1_RX = 23,
+ RDC_MDA_SDMA2 = 24,
+};
+
+/* RDC Peripherals index */
+enum rdc_pdap_idx {
+ RDC_PDAP_GPIO1 = 0,
+ RDC_PDAP_GPIO2 = 1,
+ RDC_PDAP_GPIO3 = 2,
+ RDC_PDAP_GPIO4 = 3,
+ RDC_PDAP_GPIO5 = 4,
+ RDC_PDAP_ANA_TSENSOR = 6,
+ RDC_PDAP_ANA_OSC = 7,
+ RDC_PDAP_WDOG1 = 8,
+ RDC_PDAP_WDOG2 = 9,
+ RDC_PDAP_WDOG3 = 10,
+ RDC_PDAP_SDMA3 = 11,
+ RDC_PDAP_SDMA2 = 12,
+ RDC_PDAP_GPT1 = 13,
+ RDC_PDAP_GPT2 = 14,
+ RDC_PDAP_GPT3 = 15,
+ RDC_PDAP_ROMCP = 17,
+ RDC_PDAP_IOMUXC = 19,
+ RDC_PDAP_IOMUXC_GPR = 20,
+ RDC_PDAP_OCOTP_CTRL = 21,
+ RDC_PDAP_ANA_PLL = 22,
+ RDC_PDAP_SNVS_HP = 23,
+ RDC_PDAP_CCM = 24,
+ RDC_PDAP_SRC = 25,
+ RDC_PDAP_GPC = 26,
+ RDC_PDAP_SEMAPHORE1 = 27,
+ RDC_PDAP_SEMAPHORE2 = 28,
+ RDC_PDAP_RDC = 29,
+ RDC_PDAP_CSU = 30,
+ RDC_PDAP_LCDIF = 32,
+ RDC_PDAP_MIPI_DSI = 33,
+ RDC_PDAP_ISI = 34,
+ RDC_PDAP_MIPI_CSI = 35,
+ RDC_PDAP_USB1 = 36,
+ RDC_PDAP_PWM1 = 38,
+ RDC_PDAP_PWM2 = 39,
+ RDC_PDAP_PWM3 = 40,
+ RDC_PDAP_PWM4 = 41,
+ RDC_PDAP_System_Counter_RD = 42,
+ RDC_PDAP_System_Counter_CMP = 43,
+ RDC_PDAP_System_Counter_CTRL = 44,
+ RDC_PDAP_GPT6 = 46,
+ RDC_PDAP_GPT5 = 47,
+ RDC_PDAP_GPT4 = 48,
+ RDC_PDAP_TZASC = 56,
+ RDC_PDAP_PERFMON1 = 60,
+ RDC_PDAP_PERFMON2 = 61,
+ RDC_PDAP_PLATFORM_CTRL = 62,
+ RDC_PDAP_QoSC = 63,
+ RDC_PDAP_I2C1 = 66,
+ RDC_PDAP_I2C2 = 67,
+ RDC_PDAP_I2C3 = 68,
+ RDC_PDAP_I2C4 = 69,
+ RDC_PDAP_UART4 = 70,
+ RDC_PDAP_MU_A = 74,
+ RDC_PDAP_MU_B = 75,
+ RDC_PDAP_SEMAPHORE_HS = 76,
+ RDC_PDAP_SAI2 = 79,
+ RDC_PDAP_SAI3 = 80,
+ RDC_PDAP_SAI5 = 82,
+ RDC_PDAP_SAI6 = 83,
+ RDC_PDAP_uSDHC1 = 84,
+ RDC_PDAP_uSDHC2 = 85,
+ RDC_PDAP_uSDHC3 = 86,
+ RDC_PDAP_SAI7 = 87,
+ RDC_PDAP_SPBA2 = 90,
+ RDC_PDAP_QSPI = 91,
+ RDC_PDAP_SDMA1 = 93,
+ RDC_PDAP_ENET1 = 94,
+ RDC_PDAP_SPDIF1 = 97,
+ RDC_PDAP_eCSPI1 = 98,
+ RDC_PDAP_eCSPI2 = 99,
+ RDC_PDAP_eCSPI3 = 100,
+ RDC_PDAP_MICFIL = 101,
+ RDC_PDAP_UART1 = 102,
+ RDC_PDAP_UART3 = 104,
+ RDC_PDAP_UART2 = 105,
+ RDC_PDAP_ASRC = 107,
+ RDC_PDAP_SPBA1 = 111,
+ RDC_PDAP_CAAM = 114,
+};
+
+enum csu_csl_idx {
+ CSU_CSL_GPIO1 = 0,
+ CSU_CSL_GPIO2 = 1,
+ CSU_CSL_GPIO3 = 2,
+ CSU_CSL_GPIO4 = 3,
+ CSU_CSL_GPIO5 = 4,
+ CSU_CSL_ANA_TSENSOR = 6,
+ CSU_CSL_ANA_OSC = 7,
+ CSU_CSL_WDOG1 = 8,
+ CSU_CSL_WDOG2 = 9,
+ CSU_CSL_WDOG3 = 10,
+ CSU_CSL_SDMA2 = 12,
+ CSU_CSL_GPT1 = 13,
+ CSU_CSL_GPT2 = 14,
+ CSU_CSL_GPT3 = 15,
+ CSU_CSL_ROMCP = 17,
+ CSU_CSL_LCDIF = 18,
+ CSU_CSL_IOMUXC = 19,
+ CSU_CSL_IOMUXC_GPR = 20,
+ CSU_CSL_OCOTP_CTRL = 21,
+ CSU_CSL_ANA_PLL = 22,
+ CSU_CSL_SNVS_HP = 23,
+ CSU_CSL_CCM = 24,
+ CSU_CSL_SRC = 25,
+ CSU_CSL_GPC = 26,
+ CSU_CSL_SEMAPHORE1 = 27,
+ CSU_CSL_SEMAPHORE2 = 28,
+ CSU_CSL_RDC = 29,
+ CSU_CSL_CSU = 30,
+ CSU_CSL_DC_MST0 = 32,
+ CSU_CSL_DC_MST1 = 33,
+ CSU_CSL_DC_MST2 = 34,
+ CSU_CSL_DC_MST3 = 35,
+ CSU_CSL_PWM1 = 38,
+ CSU_CSL_PWM2 = 39,
+ CSU_CSL_PWM3 = 40,
+ CSU_CSL_PWM4 = 41,
+ CSU_CSL_System_Counter_RD = 42,
+ CSU_CSL_System_Counter_CMP = 43,
+ CSU_CSL_System_Counter_CTRL = 44,
+ CSU_CSL_GPT6 = 46,
+ CSU_CSL_GPT5 = 47,
+ CSU_CSL_GPT4 = 48,
+ CSU_CSL_TZASC = 56,
+ CSU_CSL_MTR = 59,
+ CSU_CSL_PERFMON1 = 60,
+ CSU_CSL_PERFMON2 = 61,
+ CSU_CSL_PLATFORM_CTRL = 62,
+ CSU_CSL_QoSC = 63,
+ CSU_CSL_MIPI_PHY = 64,
+ CSU_CSL_MIPI_DSI = 65,
+ CSU_CSL_I2C1 = 66,
+ CSU_CSL_I2C2 = 67,
+ CSU_CSL_I2C3 = 68,
+ CSU_CSL_I2C4 = 69,
+ CSU_CSL_UART4 = 70,
+ CSU_CSL_MIPI_CSI1 = 71,
+ CSU_CSL_MIPI_CSI_PHY1 = 72,
+ CSU_CSL_CSI1 = 73,
+ CSU_CSL_MU_A = 74,
+ CSU_CSL_MU_B = 75,
+ CSU_CSL_SEMAPHORE_HS = 76,
+ CSU_CSL_SAI1 = 78,
+ CSU_CSL_SAI6 = 80,
+ CSU_CSL_SAI5 = 81,
+ CSU_CSL_SAI4 = 82,
+ CSU_CSL_uSDHC1 = 84,
+ CSU_CSL_uSDHC2 = 85,
+ CSU_CSL_MIPI_CSI2 = 86,
+ CSU_CSL_MIPI_CSI_PHY2 = 87,
+ CSU_CSL_CSI2 = 88,
+ CSU_CSL_SPBA2 = 90,
+ CSU_CSL_QSPI = 91,
+ CSU_CSL_SDMA1 = 93,
+ CSU_CSL_ENET1 = 94,
+ CSU_CSL_SPDIF1 = 97,
+ CSU_CSL_eCSPI1 = 98,
+ CSU_CSL_eCSPI2 = 99,
+ CSU_CSL_eCSPI3 = 100,
+ CSU_CSL_UART1 = 102,
+ CSU_CSL_UART3 = 104,
+ CSU_CSL_UART2 = 105,
+ CSU_CSL_SPDIF2 = 106,
+ CSU_CSL_SAI2 = 107,
+ CSU_CSL_SAI3 = 108,
+ CSU_CSL_SPBA1 = 111,
+ CSU_CSL_CAAM = 114,
+ CSU_CSL_OCRAM = 118,
+ CSU_CSL_OCRAM_S = 119,
+};
+
+#endif /* IMX_SEC_DEF_H */
diff --git a/plat/imx/imx8m/imx8mn/include/platform_def.h b/plat/imx/imx8m/imx8mn/include/platform_def.h
new file mode 100644
index 0000000..c75e250
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/platform_def.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0xB00
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(4)
+#define PLAT_MAX_RET_STATE U(2)
+
+#define PLAT_WAIT_RET_STATE U(1)
+#define PLAT_STOP_OFF_STATE U(3)
+
+#define PLAT_PRI_BITS U(3)
+#define PLAT_SDEI_CRITICAL_PRI 0x10
+#define PLAT_SDEI_NORMAL_PRI 0x20
+#define PLAT_SDEI_SGI_PRIVATE U(9)
+
+#define BL31_BASE U(0x960000)
+#define BL31_SIZE SZ_128K
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET U(0x40200000)
+
+#define BL32_FDT_OVERLAY_ADDR (PLAT_NS_IMAGE_OFFSET + 0x3000000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE U(0x38800000)
+#define PLAT_GICR_BASE U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 16
+
+#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ 24000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define IMX_AIPSTZ1 U(0x301f0000)
+#define IMX_AIPSTZ2 U(0x305f0000)
+#define IMX_AIPSTZ3 U(0x309f0000)
+#define IMX_AIPSTZ4 U(0x32df0000)
+
+#define IMX_AIPS_BASE U(0x30000000)
+#define IMX_AIPS_SIZE U(0x3000000)
+#define IMX_GPV_BASE U(0x32000000)
+#define IMX_GPV_SIZE U(0x800000)
+#define IMX_AIPS1_BASE U(0x30200000)
+#define IMX_AIPS4_BASE U(0x32c00000)
+#define IMX_ANAMIX_BASE U(0x30360000)
+#define IMX_CCM_BASE U(0x30380000)
+#define IMX_SRC_BASE U(0x30390000)
+#define IMX_GPC_BASE U(0x303a0000)
+#define IMX_RDC_BASE U(0x303d0000)
+#define IMX_CSU_BASE U(0x303e0000)
+#define IMX_WDOG_BASE U(0x30280000)
+#define IMX_SNVS_BASE U(0x30370000)
+#define IMX_NOC_BASE U(0x32700000)
+#define IMX_TZASC_BASE U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE U(0x30340000)
+#define IMX_CAAM_BASE U(0x30900000)
+#define IMX_DDRC_BASE U(0x3d400000)
+#define IMX_DDRPHY_BASE U(0x3c000000)
+#define IMX_DDR_IPS_BASE U(0x3d000000)
+#define IMX_DDR_IPS_SIZE U(0x1800000)
+#define IMX_ROM_BASE U(0x0)
+#define IMX_ROM_SIZE U(0x40000)
+#define IMX_NS_OCRAM_BASE U(0x900000)
+#define IMX_NS_OCRAM_SIZE U(0x60000)
+#define IMX_CAAM_RAM_BASE U(0x100000)
+#define IMX_CAAM_RAM_SIZE U(0x10000)
+#define IMX_DRAM_BASE U(0x40000000)
+#define IMX_DRAM_SIZE U(0xc0000000)
+
+#define IMX_GIC_BASE PLAT_GICD_BASE
+#define IMX_GIC_SIZE U(0x200000)
+
+#define WDOG_WSR U(0x2)
+#define WDOG_WCR_WDZST BIT(0)
+#define WDOG_WCR_WDBG BIT(1)
+#define WDOG_WCR_WDE BIT(2)
+#define WDOG_WCR_WDT BIT(3)
+#define WDOG_WCR_SRS BIT(4)
+#define WDOG_WCR_WDA BIT(5)
+#define WDOG_WCR_SRE BIT(6)
+#define WDOG_WCR_WDW BIT(7)
+
+#define SRC_A53RCR0 U(0x4)
+#define SRC_A53RCR1 U(0x8)
+#define SRC_OTG1PHY_SCR U(0x20)
+#define SRC_GPR1_OFFSET U(0x74)
+
+#define SNVS_LPCR U(0x38)
+#define SNVS_LPCR_SRTC_ENV BIT(0)
+#define SNVS_LPCR_DP_EN BIT(5)
+#define SNVS_LPCR_TOP BIT(6)
+
+#define IOMUXC_GPR10 U(0x28)
+#define GPR_TZASC_EN BIT(0)
+#define GPR_TZASC_EN_LOCK BIT(16)
+
+#define ANAMIX_MISC_CTL U(0x124)
+#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM U(64)
+
+#define OCRAM_S_BASE U(0x00180000)
+#define OCRAM_S_SIZE U(0x8000)
+#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY 8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define GIC_MAP MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
+#define AIPS_MAP MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
+#define OCRAM_S_MAP MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW) /* OCRAM_S */
+#define DDRC_MAP MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+#define CAAM_RAM_MAP MAP_REGION_FLAT(IMX_CAAM_RAM_BASE, IMX_CAAM_RAM_SIZE, MT_MEMORY | MT_RW) /* CAMM RAM */
+#define NS_OCRAM_MAP MAP_REGION_FLAT(IMX_NS_OCRAM_BASE, IMX_NS_OCRAM_SIZE, MT_MEMORY | MT_RW) /* NS OCRAM */
+#define ROM_MAP MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO) /* ROM code */
+
+/*
+ * Note: DRAM region is mapped with entire size available and uses MT_RW
+ * attributes.
+ * See details in docs/plat/imx8m.rst "High Assurance Boot (HABv4)" section
+ * for explanation of this mapping scheme.
+ */
+#define DRAM_MAP MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS) /* DRAM */
+
+#endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mn/platform.mk b/plat/imx/imx8m/imx8mn/platform.mk
new file mode 100644
index 0000000..1c0ad4f
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/platform.mk
@@ -0,0 +1,77 @@
+#
+# Copyright 2019-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := -Iplat/imx/common/include \
+ -Iplat/imx/imx8m/include \
+ -Iplat/imx/imx8m/imx8mn/include
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_DRAM_SOURCES := plat/imx/imx8m/ddr/dram.c \
+ plat/imx/imx8m/ddr/clock.c \
+ plat/imx/imx8m/ddr/dram_retention.c \
+ plat/imx/imx8m/ddr/ddr4_dvfs.c \
+ plat/imx/imx8m/ddr/lpddr4_dvfs.c
+
+
+IMX_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8m/gpc_common.c \
+ plat/imx/imx8m/imx_hab.c \
+ plat/imx/imx8m/imx_aipstz.c \
+ plat/imx/imx8m/imx_rdc.c \
+ plat/imx/imx8m/imx8m_caam.c \
+ plat/imx/imx8m/imx8m_csu.c \
+ plat/imx/imx8m/imx8m_psci_common.c \
+ plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c \
+ plat/imx/imx8m/imx8mn/imx8mn_psci.c \
+ plat/imx/imx8m/imx8mn/gpc.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx_sip_handler.c \
+ plat/imx/common/imx_sip_svc.c \
+ plat/imx/common/imx_uart_console.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/tzc/tzc380.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${IMX_DRAM_SOURCES} \
+ ${IMX_GIC_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS}
+
+ENABLE_PIE := 1
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+BL32_BASE ?= 0xbe000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE ?= 0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE ?= 0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
+
+EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT)
+ifeq (${SDEI_SUPPORT}, 1)
+BL31_SOURCES += plat/imx/common/imx_ehf.c \
+ plat/imx/common/imx_sdei.c
+endif
+
+ifeq (${SPD},trusty)
+ BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
+endif
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
new file mode 100644
index 0000000..452e788
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_sip_svc.h>
+#include <platform_def.h>
+
+#define CCGR(x) (0x4000 + (x) * 0x10)
+#define IMR_NUM U(5)
+
+struct imx_noc_setting {
+ uint32_t domain_id;
+ uint32_t start;
+ uint32_t end;
+ uint32_t prioriy;
+ uint32_t mode;
+ uint32_t socket_qos_en;
+};
+
+enum clk_type {
+ CCM_ROOT_SLICE,
+ CCM_CCGR,
+};
+
+struct clk_setting {
+ uint32_t offset;
+ uint32_t val;
+ enum clk_type type;
+};
+
+enum pu_domain_id {
+ /* hsio ss */
+ HSIOMIX,
+ PCIE_PHY,
+ USB1_PHY,
+ USB2_PHY,
+ MLMIX,
+ AUDIOMIX,
+ /* gpu ss */
+ GPUMIX,
+ GPU2D,
+ GPU3D,
+ /* vpu ss */
+ VPUMIX,
+ VPU_G1,
+ VPU_G2,
+ VPU_H1,
+ /* media ss */
+ MEDIAMIX,
+ MEDIAMIX_ISPDWP,
+ MIPI_PHY1,
+ MIPI_PHY2,
+ /* HDMI ss */
+ HDMIMIX,
+ HDMI_PHY,
+ DDRMIX,
+ MAX_DOMAINS,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[MAX_DOMAINS] = {
+ [MIPI_PHY1] = IMX_PD_DOMAIN(MIPI_PHY1, false),
+ [PCIE_PHY] = IMX_PD_DOMAIN(PCIE_PHY, false),
+ [USB1_PHY] = IMX_PD_DOMAIN(USB1_PHY, true),
+ [USB2_PHY] = IMX_PD_DOMAIN(USB2_PHY, true),
+ [MLMIX] = IMX_MIX_DOMAIN(MLMIX, false),
+ [AUDIOMIX] = IMX_MIX_DOMAIN(AUDIOMIX, false),
+ [GPU2D] = IMX_PD_DOMAIN(GPU2D, false),
+ [GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+ [VPUMIX] = IMX_MIX_DOMAIN(VPUMIX, false),
+ [GPU3D] = IMX_PD_DOMAIN(GPU3D, false),
+ [MEDIAMIX] = IMX_MIX_DOMAIN(MEDIAMIX, false),
+ [VPU_G1] = IMX_PD_DOMAIN(VPU_G1, false),
+ [VPU_G2] = IMX_PD_DOMAIN(VPU_G2, false),
+ [VPU_H1] = IMX_PD_DOMAIN(VPU_H1, false),
+ [HDMIMIX] = IMX_MIX_DOMAIN(HDMIMIX, false),
+ [HDMI_PHY] = IMX_PD_DOMAIN(HDMI_PHY, false),
+ [MIPI_PHY2] = IMX_PD_DOMAIN(MIPI_PHY2, false),
+ [HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+ [MEDIAMIX_ISPDWP] = IMX_PD_DOMAIN(MEDIAMIX_ISPDWP, false),
+};
+
+static struct imx_noc_setting noc_setting[] = {
+ {MLMIX, 0x180, 0x180, 0x80000303, 0x0, 0x0},
+ {AUDIOMIX, 0x200, 0x200, 0x80000303, 0x0, 0x0},
+ {AUDIOMIX, 0x280, 0x480, 0x80000404, 0x0, 0x0},
+ {GPUMIX, 0x500, 0x580, 0x80000303, 0x0, 0x0},
+ {HDMIMIX, 0x600, 0x680, 0x80000202, 0x0, 0x1},
+ {HDMIMIX, 0x700, 0x700, 0x80000505, 0x0, 0x0},
+ {HSIOMIX, 0x780, 0x900, 0x80000303, 0x0, 0x0},
+ {MEDIAMIX, 0x980, 0xb80, 0x80000202, 0x0, 0x1},
+ {MEDIAMIX_ISPDWP, 0xc00, 0xd00, 0x80000505, 0x0, 0x0},
+ {VPU_G1, 0xd80, 0xd80, 0x80000303, 0x0, 0x0},
+ {VPU_G2, 0xe00, 0xe00, 0x80000303, 0x0, 0x0},
+ {VPU_H1, 0xe80, 0xe80, 0x80000303, 0x0, 0x0}
+};
+
+static struct clk_setting hsiomix_clk[] = {
+ { 0x8380, 0x0, CCM_ROOT_SLICE },
+ { 0x44d0, 0x0, CCM_CCGR },
+ { 0x45c0, 0x0, CCM_CCGR },
+};
+
+static struct aipstz_cfg aipstz5[] = {
+ {IMX_AIPSTZ5, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static unsigned int pu_domain_status;
+
+static void imx_noc_qos(unsigned int domain_id)
+{
+ unsigned int i;
+ uint32_t hurry;
+
+ if (domain_id == HDMIMIX) {
+ mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22018);
+ mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22010);
+
+ /* set GPR to make lcdif read hurry level 0x7 */
+ hurry = mmio_read_32(IMX_HDMI_CTL_BASE + TX_CONTROL0);
+ hurry |= 0x00077000;
+ mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL0, hurry);
+ }
+
+ if (domain_id == MEDIAMIX) {
+ /* handle mediamix special */
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RSTn_CSR, 0x1FFFFFF);
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + CLK_EN_CSR, 0x1FFFFFF);
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RST_DIV, 0x40030000);
+
+ /* set GPR to make lcdif read hurry level 0x7 */
+ hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL);
+ hurry |= 0xfc00;
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL, hurry);
+ /* set GPR to make isi write hurry level 0x7 */
+ hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL);
+ hurry |= 0x1ff00000;
+ mmio_write_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL, hurry);
+ }
+
+ /* set MIX NoC */
+ for (i = 0; i < ARRAY_SIZE(noc_setting); i++) {
+ if (noc_setting[i].domain_id == domain_id) {
+ udelay(50);
+ uint32_t offset = noc_setting[i].start;
+
+ while (offset <= noc_setting[i].end) {
+ mmio_write_32(IMX_NOC_BASE + offset + 0x8, noc_setting[i].prioriy);
+ mmio_write_32(IMX_NOC_BASE + offset + 0xc, noc_setting[i].mode);
+ mmio_write_32(IMX_NOC_BASE + offset + 0x18, noc_setting[i].socket_qos_en);
+ offset += 0x80;
+ }
+ }
+ }
+}
+
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+ struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+ unsigned int i;
+
+ /* validate the domain id */
+ if (domain_id >= MAX_DOMAINS) {
+ return;
+ }
+
+ if (domain_id == HSIOMIX) {
+ for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+ hsiomix_clk[i].val = mmio_read_32(IMX_CCM_BASE + hsiomix_clk[i].offset);
+ mmio_setbits_32(IMX_CCM_BASE + hsiomix_clk[i].offset,
+ hsiomix_clk[i].type == CCM_ROOT_SLICE ? BIT(28) : 0x3);
+ }
+ }
+
+ if (on) {
+ if (pwr_domain->need_sync) {
+ pu_domain_status |= (1 << domain_id);
+ }
+
+ if (domain_id == HDMIMIX) {
+ /* assert the reset */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0x0);
+ /* enable all th function clock */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+ }
+
+ /* clear the PGC bit */
+ mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /* power up the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req)
+ ;
+
+ if (domain_id == HDMIMIX) {
+ /* wait for memory repair done for HDMIMIX */
+ while (!(mmio_read_32(IMX_SRC_BASE + 0x94) & BIT(8)))
+ ;
+ /* disable all the function clock */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0x0);
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x0);
+ /* deassert the reset */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0xffffffff);
+ /* enable all the clock again */
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+ mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+ }
+
+ if (domain_id == HSIOMIX) {
+ /* enable HSIOMIX clock */
+ mmio_write_32(IMX_HSIOMIX_CTL_BASE, 0x2);
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+ /* clear adb power down request */
+ mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+ ;
+ }
+
+ imx_noc_qos(domain_id);
+
+ /* AIPS5 config is lost when audiomix is off, so need to re-init it */
+ if (domain_id == AUDIOMIX) {
+ imx_aipstz_init(aipstz5);
+ }
+ } else {
+ if (pwr_domain->always_on) {
+ return;
+ }
+
+ if (pwr_domain->need_sync) {
+ pu_domain_status &= ~(1 << domain_id);
+ }
+
+ /* handle the ADB400 sync */
+ if (pwr_domain->need_sync) {
+ /* set adb power down request */
+ mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+ /* wait for adb power request ack */
+ while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+ ;
+ }
+
+ /* set the PGC bit */
+ mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+ /*
+ * leave the G1, G2, H1 power domain on until VPUMIX power off,
+ * otherwise system will hang due to VPUMIX ACK
+ */
+ if (domain_id == VPU_H1 || domain_id == VPU_G1 || domain_id == VPU_G2) {
+ return;
+ }
+
+ if (domain_id == VPUMIX) {
+ mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, VPU_G1_PWR_REQ |
+ VPU_G2_PWR_REQ | VPU_H1_PWR_REQ);
+
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & (VPU_G1_PWR_REQ |
+ VPU_G2_PWR_REQ | VPU_H1_PWR_REQ))
+ ;
+ }
+
+ /* power down the domain */
+ mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+ /* wait for power request done */
+ while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req)
+ ;
+
+ if (domain_id == HDMIMIX) {
+ /* disable all the clocks of HDMIMIX */
+ mmio_write_32(IMX_HDMI_CTL_BASE + 0x40, 0x0);
+ mmio_write_32(IMX_HDMI_CTL_BASE + 0x50, 0x0);
+ }
+ }
+
+ if (domain_id == HSIOMIX) {
+ for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+ mmio_write_32(IMX_CCM_BASE + hsiomix_clk[i].offset, hsiomix_clk[i].val);
+ }
+ }
+}
+
+void imx_gpc_init(void)
+{
+ uint32_t val;
+ unsigned int i;
+
+ /* mask all the wakeup irq by default */
+ for (i = 0; i < IMR_NUM; i++) {
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+ }
+
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ /* use GIC wake_request to wakeup C0~C3 from LPM */
+ val |= CORE_WKUP_FROM_GIC;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~MASTER0_LPM_HSK;
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+ mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+ MASTER2_MAPPING));
+
+ /* set all mix/PU in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0x3fffff);
+
+ /*
+ * Set the CORE & SCU power up timing:
+ * SW = 0x1, SW2ISO = 0x1;
+ * the CPU CORE and SCU power up timming counter
+ * is drived by 32K OSC, each domain's power up
+ * latency is (SW + SW2ISO) / 32768
+ */
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+ mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+ (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+ A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+ /* clear DSM by default */
+ val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+ val &= ~SLPCR_EN_DSM;
+ /* enable the fast wakeup wait/stop mode */
+ val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+ val |= SLPCR_A53_FASTWUP_STOP_MODE;
+ /* clear the RBC */
+ val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+ /* set the STBY_COUNT to 0x5, (128 * 30)us */
+ val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+ val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+ mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+ /*
+ * USB PHY power up needs to make sure RESET bit in SRC is clear,
+ * otherwise, the PU power up bit in GPC will NOT self-cleared.
+ * only need to do it once.
+ */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+
+ /* enable all the power domain by default */
+ for (i = 0; i < 101; i++) {
+ mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
+ }
+
+ for (i = 0; i < 20; i++) {
+ imx_gpc_pm_domain_enable(i, true);
+ }
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c
new file mode 100644
index 0000000..08cbeeb
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <imx8m_caam.h>
+#include "imx8mp_private.h"
+#include <imx_aipstz.h>
+#include <imx_rdc.h>
+#include <imx_uart.h>
+#include <plat/common/platform.h>
+#include <plat_imx8.h>
+#include <platform_def.h>
+
+
+static const struct aipstz_cfg aipstz[] = {
+ {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+ unsigned int i;
+
+ /* Enable CSU NS access permission */
+ for (i = 0U; i < 64; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+ }
+
+ imx_aipstz_init(aipstz);
+
+ console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+
+ generic_delay_timer_init();
+
+ /* select the CKIL source to 32K OSC */
+ mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+ /* Open handles to a FIP image */
+ plat_imx_io_setup();
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+void bl2_plat_runtime_setup(void)
+{
+ return;
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c b/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c
new file mode 100644
index 0000000..f2f6808
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ {
+ .image_id = BL31_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, 0),
+
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_SIZE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ /* This is a zero sized image so we don't set base or size */
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+ # ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PLAT_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ # else
+ .ep_info.pc = PLAT_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = PLAT_NS_IMAGE_SIZE,
+ # endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs);
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
new file mode 100644
index 0000000..4c31fa2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <dram.h>
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <imx8m_csu.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+
+#define TRUSTY_PARAMS_LEN_BYTES (4096*2)
+
+static const mmap_region_t imx_mmap[] = {
+ GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
+ NOC_MAP, CAAM_RAM_MAP, NS_OCRAM_MAP,
+ ROM_MAP, DRAM_MAP,
+ {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+ {IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+ /* Master domain assignment */
+ RDC_MDAn(RDC_MDA_M7, DID1),
+
+ /* peripherals domain permission */
+ RDC_PDAPn(RDC_PDAP_UART2, D0R | D0W),
+
+ /* memory region */
+
+ /* Sentinel */
+ {0},
+};
+
+static const struct imx_csu_cfg csu_cfg[] = {
+ /* peripherals csl setting */
+ CSU_CSLx(CSU_CSL_OCRAM, CSU_SEC_LEVEL_2, UNLOCKED),
+ CSU_CSLx(CSU_CSL_OCRAM_S, CSU_SEC_LEVEL_2, UNLOCKED),
+
+ /* master HP0~1 */
+
+ /* SA setting */
+
+ /* HP control setting */
+
+ /* Sentinel */
+ {0}
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+static void bl31_tzc380_setup(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+ if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+ return;
+
+ tzc380_init(IMX_TZASC_BASE);
+
+ /*
+ * Need to substact offset 0x40000000 from CPU address when
+ * programming tzasc region for i.mx8mp.
+ */
+
+ /* Enable 1G-5G S/NS RW */
+ tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+ TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+ unsigned int val;
+ unsigned int i;
+
+ /* Enable CSU NS access permission */
+ for (i = 0; i < 64; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+ }
+
+ imx_aipstz_init(aipstz);
+
+ imx_rdc_init(rdc);
+
+ imx_csu_init(csu_cfg);
+
+ /* config the ocram memory range for secure access */
+ mmio_write_32(IMX_IOMUX_GPR_BASE + 0x2c, 0x4E1);
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x2c);
+ mmio_write_32(IMX_IOMUX_GPR_BASE + 0x2c, val | 0x3DFF0000);
+
+ console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+ /* This console is only used for boot stage */
+ console_set_scope(&console, CONSOLE_FLAG_BOOT);
+
+ imx8m_caam_init();
+
+ /*
+ * tell BL3-1 where the non-secure software image is located
+ * and the entry state information.
+ */
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#if defined(SPD_opteed) || defined(SPD_trusty)
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = 0;
+
+ /* Pass TEE base and size to bl33 */
+ bl33_image_ep_info.args.arg1 = BL32_BASE;
+ bl33_image_ep_info.args.arg2 = BL32_SIZE;
+
+#ifdef SPD_trusty
+ bl32_image_ep_info.args.arg0 = BL32_SIZE;
+ bl32_image_ep_info.args.arg1 = BL32_BASE;
+#else
+ /* Make sure memory is clean */
+ mmio_write_32(BL32_FDT_OVERLAY_ADDR, 0);
+ bl33_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+ bl32_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+#endif
+#endif
+
+ bl31_tzc380_setup();
+}
+
+#define MAP_BL31_TOTAL \
+ MAP_REGION_FLAT(BL31_START, BL31_SIZE, MT_MEMORY | MT_RW | MT_SECURE)
+#define MAP_BL31_RO \
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, MT_MEMORY | MT_RO | MT_SECURE)
+#define MAP_COHERENT_MEM \
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#define MAP_BL32_TOTAL \
+ MAP_REGION_FLAT(BL32_BASE, BL32_SIZE, MT_MEMORY | MT_RW)
+
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL31_TOTAL,
+ MAP_BL31_RO,
+#if USE_COHERENT_MEM
+ MAP_COHERENT_MEM,
+#endif
+ /* Map TEE memory */
+ MAP_BL32_TOTAL,
+ {0}
+ };
+
+ setup_page_tables(bl_regions, imx_mmap);
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ generic_delay_timer_init();
+
+ /* select the CKIL source to 32K OSC */
+ mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+ /* Init the dram info */
+ dram_info_init(SAVED_DRAM_TIMING_BASE);
+
+ plat_gic_driver_init();
+ plat_gic_init();
+
+ imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE) {
+ return &bl33_image_ep_info;
+ }
+
+ if (type == SECURE) {
+ return &bl32_image_ep_info;
+ }
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+#ifdef SPD_trusty
+void plat_trusty_set_boot_args(aapcs64_params_t *args)
+{
+ args->arg0 = BL32_SIZE;
+ args->arg1 = BL32_BASE;
+ args->arg2 = TRUSTY_PARAMS_LEN_BYTES;
+}
+#endif
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
new file mode 100644
index 0000000..bc7b246
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .validate_power_state = imx_validate_power_state,
+ .cpu_standby = imx_cpu_standby,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .system_reset = imx_system_reset,
+ .system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ /* sec_entrypoint is used for warm reset */
+ imx_mailbox_init(sec_entrypoint);
+
+ *psci_ops = &imx_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S b/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S
new file mode 100644
index 0000000..a4c7ce1
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global imx8mp_rotpk_hash
+ .global imx8mp_rotpk_hash_end
+imx8mp_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+imx8mp_rotpk_hash_end:
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c b/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c
new file mode 100644
index 0000000..5d1a6c2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char imx8mp_rotpk_hash[], imx8mp_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = imx8mp_rotpk_hash;
+ *key_len = imx8mp_rotpk_hash_end - imx8mp_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
new file mode 100644
index 0000000..7909937
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x180
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x44
+#define IMR1_CORE2_A53 0x194
+#define IMR1_CORE3_A53 0x1A8
+#define IMR1_CORE0_M4 0x58
+
+#define SLT0_CFG 0x200
+#define GPC_PU_PWRHSK 0x190
+#define PGC_CPU_0_1_MAPPING 0x1CC
+#define CPU_PGC_UP_TRG 0xD0
+#define PU_PGC_UP_TRG 0xD8
+#define CPU_PGC_DN_TRG 0xDC
+#define PU_PGC_DN_TRG 0xE4
+#define LPS_CPU1 0xEC
+
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(30)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(8)
+#define A53_PLAT_PUP_ACK BIT(9)
+
+#define NOC_PDN_SLT_CTRL BIT(12)
+#define NOC_PUP_SLT_CTRL BIT(13)
+#define NOC_PGC_PDN_ACK BIT(12)
+#define NOC_PGC_PUP_ACK BIT(13)
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#define TMR_TCD2_SHIFT 0
+#define TMC_TMR_SHIFT 10
+#define TRC1_TMC_SHIFT 20
+
+#define MIPI_PHY1_PWR_REQ BIT(0)
+#define PCIE_PHY_PWR_REQ BIT(1)
+#define USB1_PHY_PWR_REQ BIT(2)
+#define USB2_PHY_PWR_REQ BIT(3)
+#define MLMIX_PWR_REQ BIT(4)
+#define AUDIOMIX_PWR_REQ BIT(5)
+#define GPU2D_PWR_REQ BIT(6)
+#define GPUMIX_PWR_REQ BIT(7)
+#define VPUMIX_PWR_REQ BIT(8)
+#define GPU3D_PWR_REQ BIT(9)
+#define MEDIAMIX_PWR_REQ BIT(10)
+#define VPU_G1_PWR_REQ BIT(11)
+#define VPU_G2_PWR_REQ BIT(12)
+#define VPU_H1_PWR_REQ BIT(13)
+#define HDMIMIX_PWR_REQ BIT(14)
+#define HDMI_PHY_PWR_REQ BIT(15)
+#define MIPI_PHY2_PWR_REQ BIT(16)
+#define HSIOMIX_PWR_REQ BIT(17)
+#define MEDIAMIX_ISPDWP_PWR_REQ BIT(18)
+#define DDRMIX_PWR_REQ BIT(19)
+
+#define AUDIOMIX_ADB400_SYNC (BIT(4) | BIT(15))
+#define MLMIX_ADB400_SYNC (BIT(7) | BIT(8))
+#define GPUMIX_ADB400_SYNC BIT(9)
+#define VPUMIX_ADB400_SYNC BIT(10)
+#define DDRMIX_ADB400_SYNC BIT(11)
+#define HSIOMIX_ADB400_SYNC BIT(12)
+#define HDMIMIX_ADB400_SYNC BIT(13)
+#define MEDIAMIX_ADB400_SYNC BIT(14)
+
+#define AUDIOMIX_ADB400_ACK (BIT(20) | BIT(31))
+#define MLMIX_ADB400_ACK (BIT(23) | BIT(24))
+#define GPUMIX_ADB400_ACK BIT(25)
+#define VPUMIX_ADB400_ACK BIT(26)
+#define DDRMIX_ADB400_ACK BIT(27)
+#define HSIOMIX_ADB400_ACK BIT(28)
+#define HDMIMIX_ADB400_ACK BIT(29)
+#define MEDIAMIX_ADB400_ACK BIT(30)
+
+#define MIPI_PHY1_PGC 0xb00
+#define PCIE_PHY_PGC 0xb40
+#define USB1_PHY_PGC 0xb80
+#define USB2_PHY_PGC 0xbc0
+#define MLMIX_PGC 0xc00
+#define AUDIOMIX_PGC 0xc40
+#define GPU2D_PGC 0xc80
+#define GPUMIX_PGC 0xcc0
+#define VPUMIX_PGC 0xd00
+#define GPU3D_PGC 0xd40
+#define MEDIAMIX_PGC 0xd80
+#define VPU_G1_PGC 0xdc0
+#define VPU_G2_PGC 0xe00
+#define VPU_H1_PGC 0xe40
+#define HDMIMIX_PGC 0xe80
+#define HDMI_PHY_PGC 0xec0
+#define MIPI_PHY2_PGC 0xf00
+#define HSIOMIX_PGC 0xf40
+#define MEDIAMIX_ISPDWP_PGC 0xf80
+#define DDRMIX_PGC 0xfc0
+
+#define IRQ_IMR_NUM U(5)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/include/imx8mp_private.h b/plat/imx/imx8m/imx8mp/include/imx8mp_private.h
new file mode 100644
index 0000000..0a02334
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/imx8mp_private.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8MP_PRIVATE_H
+#define IMX8MP_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_imx_io_setup(void);
+
+#endif /* IMX8MP_PRIVATE_H */
diff --git a/plat/imx/imx8m/imx8mp/include/imx_sec_def.h b/plat/imx/imx8m/imx8mp/include/imx_sec_def.h
new file mode 100644
index 0000000..ba248b5
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/imx_sec_def.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_SEC_DEF_H
+#define IMX_SEC_DEF_H
+
+/* RDC MDA index */
+enum rdc_mda_idx {
+ RDC_MDA_A53 = 0,
+ RDC_MDA_M7 = 1,
+ RDC_MDA_PCIE_CTRL1 = 2,
+ RDC_MDA_SDMA3p = 3,
+ RDC_MDA_SDMA3b = 4,
+ RDC_MDA_LCDIF = 5,
+ RDC_MDA_ISI = 6,
+ RDC_MDA_NPU = 7,
+ RDC_MDA_Coresight = 8,
+ RDC_MDA_DAP = 9,
+ RDC_MDA_CAAM = 10,
+ RDC_MDA_SDMA1p = 11,
+ RDC_MDA_SDMA1b = 12,
+ RDC_MDA_APBHDMA = 13,
+ RDC_MDA_RAWNAND = 14,
+ RDC_MDA_uSDHC1 = 15,
+ RDC_MDA_uSDHC2 = 16,
+ RDC_MDA_uSDHC3 = 17,
+ RDC_MDA_AUDIO_PROCESSOR = 18,
+ RDC_MDA_USB1 = 19,
+ RDC_MDA_USB2 = 20,
+ RDC_MDA_TESTPORT = 21,
+ RDC_MDA_ENET1_TX = 22,
+ RDC_MDA_ENET1_RX = 23,
+ RDC_MDA_SDMA2 = 24,
+ RDC_MDA_SDMA3_to_SPBA2 = 25,
+ RDC_MDA_SDMA1_to_SPBA1 = 26,
+ RDC_MDA_LCDIF2 = 27,
+ RDC_MDA_HDMI_TX = 28,
+ RDC_MDA_ENET2 = 29,
+ RDC_MDA_GPU3D = 30,
+ RDC_MDA_GPU2D = 31,
+ RDC_MDA_VPU_G1 = 32,
+ RDC_MDA_VPU_G2 = 33,
+ RDC_MDA_VPU_VC8000E = 34,
+ RDC_MDA_AUDIO_EDMA = 35,
+ RDC_MDA_ISP1 = 36,
+ RDC_MDA_ISP2 = 37,
+ RDC_MDA_DEWARP = 38,
+ RDC_MDA_GIC500 = 39,
+};
+
+/* RDC Peripherals index */
+enum rdc_pdap_idx {
+ RDC_PDAP_GPIO1 = 0,
+ RDC_PDAP_GPIO2 = 1,
+ RDC_PDAP_GPIO3 = 2,
+ RDC_PDAP_GPIO4 = 3,
+ RDC_PDAP_GPIO5 = 4,
+ RDC_PDAP_MU_2_A = 5,
+ RDC_PDAP_ANA_TSENSOR = 6,
+ RDC_PDAP_ANA_OSC = 7,
+ RDC_PDAP_WDOG1 = 8,
+ RDC_PDAP_WDOG2 = 9,
+ RDC_PDAP_WDOG3 = 10,
+ RDC_PDAP_GPT1 = 13,
+ RDC_PDAP_GPT2 = 14,
+ RDC_PDAP_GPT3 = 15,
+ RDC_PDAP_MU_2_B = 16,
+ RDC_PDAP_ROMCP = 17,
+ RDC_PDAP_MU_3_A = 18,
+ RDC_PDAP_IOMUXC = 19,
+ RDC_PDAP_IOMUXC_GPR = 20,
+ RDC_PDAP_OCOTP_CTRL = 21,
+ RDC_PDAP_ANA_PLL = 22,
+ RDC_PDAP_SNVS_HP = 23,
+ RDC_PDAP_CCM = 24,
+ RDC_PDAP_SRC = 25,
+ RDC_PDAP_GPC = 26,
+ RDC_PDAP_SEMAPHORE1 = 27,
+ RDC_PDAP_SEMAPHORE2 = 28,
+ RDC_PDAP_RDC = 29,
+ RDC_PDAP_CSU = 30,
+ RDC_PDAP_MU_3_B = 31,
+ RDC_PDAP_ISI = 32,
+ RDC_PDAP_ISP0 = 33,
+ RDC_PDAP_ISP1 = 34,
+ RDC_PDAP_IPS_Dewarp = 35,
+ RDC_PDAP_MIPI_CSI0 = 36,
+ RDC_PDAP_HSIOMIX_BLK_CTL = 37,
+ RDC_PDAP_PWM1 = 38,
+ RDC_PDAP_PWM2 = 39,
+ RDC_PDAP_PWM3 = 40,
+ RDC_PDAP_PWM4 = 41,
+ RDC_PDAP_System_Counter_RD = 42,
+ RDC_PDAP_System_Counter_CMP = 43,
+ RDC_PDAP_System_Counter_CTRL = 44,
+ RDC_PDAP_I2C5 = 45,
+ RDC_PDAP_GPT6 = 46,
+ RDC_PDAP_GPT5 = 47,
+ RDC_PDAP_GPT4 = 48,
+ RDC_PDAP_MIPI_CSI1 = 49,
+ RDC_PDAP_MIPI_DSI0 = 50,
+ RDC_PDAP_MEDIAMIX_BLK_CTL = 51,
+ RDC_PDAP_LCDIF1 = 52,
+ RDC_PDAP_eDMA_Management_Page = 53,
+ RDC_PDAP_eDMA_Channels_15_0 = 54,
+ RDC_PDAP_eDMA_Channels_31_16 = 55,
+ RDC_PDAP_TZASC = 56,
+ RDC_PDAP_I2C6 = 57,
+ RDC_PDAP_CAAM = 58,
+ RDC_PDAP_LCDIF2 = 59,
+ RDC_PDAP_PERFMON1 = 60,
+ RDC_PDAP_PERFMON2 = 61,
+ RDC_PDAP_NOC_BLK_CTL = 62,
+ RDC_PDAP_QoSC = 63,
+ RDC_PDAP_LVDS0 = 64,
+ RDC_PDAP_LVDS1 = 65,
+ RDC_PDAP_I2C1 = 66,
+ RDC_PDAP_I2C2 = 67,
+ RDC_PDAP_I2C3 = 68,
+ RDC_PDAP_I2C4 = 69,
+ RDC_PDAP_UART4 = 70,
+ RDC_PDAP_HDMI_TX = 71,
+ RDC_PDAP_IRQ_STEER_Audio_Processor = 72,
+ RDC_PDAP_SDMA2 = 73,
+ RDC_PDAP_MU_1_A = 74,
+ RDC_PDAP_MU_1_B = 75,
+ RDC_PDAP_SEMAPHORE_HS = 76,
+ RDC_PDAP_SAI1 = 78,
+ RDC_PDAP_SAI2 = 79,
+ RDC_PDAP_SAI3 = 80,
+ RDC_PDAP_CAN_FD1 = 81,
+ RDC_PDAP_SAI5 = 82,
+ RDC_PDAP_SAI6 = 83,
+ RDC_PDAP_uSDHC1 = 84,
+ RDC_PDAP_uSDHC2 = 85,
+ RDC_PDAP_uSDHC3 = 86,
+ RDC_PDAP_PCIE_PHY1 = 87,
+ RDC_PDAP_HDMI_TX_AUDLNK_MSTR = 88,
+ RDC_PDAP_CAN_FD2 = 89,
+ RDC_PDAP_SPBA2 = 90,
+ RDC_PDAP_QSPI = 91,
+ RDC_PDAP_AUDIO_BLK_CTRL = 92,
+ RDC_PDAP_SDMA1 = 93,
+ RDC_PDAP_ENET1 = 94,
+ RDC_PDAP_ENET2_TSN = 95,
+ RDC_PDAP_ASRC = 97,
+ RDC_PDAP_eCSPI1 = 98,
+ RDC_PDAP_eCSPI2 = 99,
+ RDC_PDAP_eCSPI3 = 100,
+ RDC_PDAP_SAI7 = 101,
+ RDC_PDAP_UART1 = 102,
+ RDC_PDAP_UART3 = 104,
+ RDC_PDAP_UART2 = 105,
+ RDC_PDAP_PDM_MICFIL = 106,
+ RDC_PDAP_AUDIO_XCVR_RX_eARC = 107,
+ RDC_PDAP_SDMA3 = 109,
+ RDC_PDAP_SPBA1 = 111,
+};
+
+enum csu_csl_idx {
+ CSU_CSL_GPIO1 = 0,
+ CSU_CSL_GPIO2 = 1,
+ CSU_CSL_GPIO3 = 2,
+ CSU_CSL_GPIO4 = 3,
+ CSU_CSL_GPIO5 = 4,
+ CSU_CSL_MU_2_A = 5,
+ CSU_CSL_ANA_TSENSOR = 6,
+ CSU_CSL_ANA_OSC = 7,
+ CSU_CSL_WDOG1 = 8,
+ CSU_CSL_WDOG2 = 9,
+ CSU_CSL_WDOG3 = 10,
+ CSU_CSL_GPT1 = 13,
+ CSU_CSL_GPT2 = 14,
+ CSU_CSL_GPT3 = 15,
+ CSU_CSL_MU_2_B = 16,
+ CSU_CSL_ROMCP = 17,
+ CSU_CSL_MU_3_A = 18,
+ CSU_CSL_IOMUXC = 19,
+ CSU_CSL_IOMUXC_GPR = 20,
+ CSU_CSL_OCOTP_CTRL = 21,
+ CSU_CSL_ANA_PLL = 22,
+ CSU_CSL_SNVS_HP = 23,
+ CSU_CSL_CCM = 24,
+ CSU_CSL_SRC = 25,
+ CSU_CSL_GPC = 26,
+ CSU_CSL_SEMAPHORE1 = 27,
+ CSU_CSL_SEMAPHORE2 = 28,
+ CSU_CSL_RDC = 29,
+ CSU_CSL_CSU = 30,
+ CSU_CSL_MU_3_B = 31,
+ CSU_CSL_ISI = 32,
+ CSU_CSL_ISP0 = 33,
+ CSU_CSL_ISP1 = 34,
+ CSU_CSL_IPS_Dewarp = 35,
+ CSU_CSL_MIPI_CSI0 = 36,
+ CSU_CSL_HSIOMIX_BLK_CTL = 37,
+ CSU_CSL_PWM1 = 38,
+ CSU_CSL_PWM2 = 39,
+ CSU_CSL_PWM3 = 40,
+ CSU_CSL_PWM4 = 41,
+ CSU_CSL_System_Counter_RD = 42,
+ CSU_CSL_System_Counter_CMP = 43,
+ CSU_CSL_System_Counter_CTRL = 44,
+ CSU_CSL_I2C5 = 45,
+ CSU_CSL_GPT6 = 46,
+ CSU_CSL_GPT5 = 47,
+ CSU_CSL_GPT4 = 48,
+ CSU_CSL_MIPI_CSI1 = 49,
+ CSU_CSL_MIPI_DSI0 = 50,
+ CSU_CSL_MEDIAMIX_BLK_CTL = 51,
+ CSU_CSL_LCDIF1 = 52,
+ CSU_CSL_eDMA_Management_Page = 53,
+ CSU_CSL_eDMA_Channels_15_0 = 54,
+ CSU_CSL_eDMA_Channels_31_16 = 55,
+ CSU_CSL_TZASC = 56,
+ CSU_CSL_I2C6 = 57,
+ CSU_CSL_CAAM = 58,
+ CSU_CSL_LCDIF2 = 59,
+ CSU_CSL_PERFMON1 = 60,
+ CSU_CSL_PERFMON2 = 61,
+ CSU_CSL_NOC_BLK_CTL = 62,
+ CSU_CSL_QoSC = 63,
+ CSU_CSL_LVDS0 = 64,
+ CSU_CSL_LVDS1 = 65,
+ CSU_CSL_I2C1 = 66,
+ CSU_CSL_I2C2 = 67,
+ CSU_CSL_I2C3 = 68,
+ CSU_CSL_I2C4 = 69,
+ CSU_CSL_UART4 = 70,
+ CSU_CSL_HDMI_TX = 71,
+ CSU_CSL_IRQ_STEER_Audio_Processor = 72,
+ CSU_CSL_SDMA2 = 73,
+ CSU_CSL_MU_1_A = 74,
+ CSU_CSL_MU_1_B = 75,
+ CSU_CSL_SEMAPHORE_HS = 76,
+ CSU_CSL_SAI1 = 78,
+ CSU_CSL_SAI2 = 79,
+ CSU_CSL_SAI3 = 80,
+ CSU_CSL_CAN_FD1 = 81,
+ CSU_CSL_SAI5 = 82,
+ CSU_CSL_SAI6 = 83,
+ CSU_CSL_uSDHC1 = 84,
+ CSU_CSL_uSDHC2 = 85,
+ CSU_CSL_uSDHC3 = 86,
+ CSU_CSL_PCIE_PHY1 = 87,
+ CSU_CSL_HDMI_TX_AUDLNK_MSTR = 88,
+ CSU_CSL_CAN_FD2 = 89,
+ CSU_CSL_SPBA2 = 90,
+ CSU_CSL_QSPI = 91,
+ CSU_CSL_AUDIO_BLK_CTRL = 92,
+ CSU_CSL_SDMA1 = 93,
+ CSU_CSL_ENET1 = 94,
+ CSU_CSL_ENET2_TSN = 95,
+ CSU_CSL_ASRC = 97,
+ CSU_CSL_eCSPI1 = 98,
+ CSU_CSL_eCSPI2 = 99,
+ CSU_CSL_eCSPI3 = 100,
+ CSU_CSL_SAI7 = 101,
+ CSU_CSL_UART1 = 102,
+ CSU_CSL_UART3 = 104,
+ CSU_CSL_UART2 = 105,
+ CSU_CSL_PDM_MICFIL = 106,
+ CSU_CSL_AUDIO_XCVR_RX_eARC = 107,
+ CSU_CSL_SDMA3 = 109,
+ CSU_CSL_SPBA1 = 111,
+ CSU_CSL_OCRAM_A = 113,
+ CSU_CSL_OCRAM = 118,
+ CSU_CSL_OCRAM_S = 119,
+};
+
+#endif /* IMX_SEC_DEF_H */
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
new file mode 100644
index 0000000..14cb709
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0xB00
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(4)
+#define PLAT_MAX_RET_STATE U(2)
+
+#define PLAT_WAIT_RET_STATE U(1)
+#define PLAT_STOP_OFF_STATE U(3)
+
+#if defined(NEED_BL2)
+#define BL2_BASE U(0x970000)
+#define BL2_SIZE SZ_128K
+#define BL2_LIMIT (BL2_BASE + BL2_SIZE)
+#define BL31_BASE U(0x950000)
+#define IMX_FIP_BASE U(0x40310000)
+#define IMX_FIP_SIZE U(0x000300000)
+#define IMX_FIP_LIMIT U(FIP_BASE + FIP_SIZE)
+
+/* Define FIP image location on eMMC */
+#define IMX_FIP_MMC_BASE U(0x100000)
+
+#define PLAT_IMX8MP_BOOT_MMC_BASE U(0x30B50000) /* SD */
+#else
+#define BL31_BASE U(0x970000)
+#endif
+
+#define BL31_SIZE SZ_128K
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+#define PLAT_PRI_BITS U(3)
+#define PLAT_SDEI_CRITICAL_PRI 0x10
+#define PLAT_SDEI_NORMAL_PRI 0x20
+#define PLAT_SDEI_SGI_PRIVATE U(9)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET U(0x40200000)
+#define PLAT_NS_IMAGE_SIZE U(0x00200000)
+
+#define BL32_FDT_OVERLAY_ADDR (PLAT_NS_IMAGE_OFFSET + 0x3000000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE U(0x38800000)
+#define PLAT_GICR_BASE U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 16
+
+#define HAB_RVT_BASE U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ 24000000 /* Select 24MHz oscillator */
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ 24000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define IMX_AIPSTZ1 U(0x301f0000)
+#define IMX_AIPSTZ2 U(0x305f0000)
+#define IMX_AIPSTZ3 U(0x309f0000)
+#define IMX_AIPSTZ4 U(0x32df0000)
+#define IMX_AIPSTZ5 U(0x30df0000)
+
+#define IMX_AIPS_BASE U(0x30000000)
+#define IMX_AIPS_SIZE U(0x3000000)
+#define IMX_GPV_BASE U(0x32000000)
+#define IMX_GPV_SIZE U(0x800000)
+#define IMX_AIPS1_BASE U(0x30200000)
+#define IMX_AIPS4_BASE U(0x32c00000)
+#define IMX_ANAMIX_BASE U(0x30360000)
+#define IMX_CCM_BASE U(0x30380000)
+#define IMX_SRC_BASE U(0x30390000)
+#define IMX_GPC_BASE U(0x303a0000)
+#define IMX_RDC_BASE U(0x303d0000)
+#define IMX_CSU_BASE U(0x303e0000)
+#define IMX_WDOG_BASE U(0x30280000)
+#define IMX_SNVS_BASE U(0x30370000)
+#define IMX_NOC_BASE U(0x32700000)
+#define IMX_NOC_SIZE U(0x100000)
+#define IMX_TZASC_BASE U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE U(0x30340000)
+#define IMX_CAAM_BASE U(0x30900000)
+#define IMX_DDRC_BASE U(0x3d400000)
+#define IMX_DDRPHY_BASE U(0x3c000000)
+#define IMX_DDR_IPS_BASE U(0x3d000000)
+#define IMX_DDR_IPS_SIZE U(0x1800000)
+#define IMX_ROM_BASE U(0x0)
+#define IMX_ROM_SIZE U(0x40000)
+#define IMX_NS_OCRAM_BASE U(0x900000)
+#define IMX_NS_OCRAM_SIZE U(0x60000)
+#define IMX_CAAM_RAM_BASE U(0x100000)
+#define IMX_CAAM_RAM_SIZE U(0x10000)
+#define IMX_DRAM_BASE U(0x40000000)
+#define IMX_DRAM_SIZE U(0xc0000000)
+
+#define IMX_GIC_BASE PLAT_GICD_BASE
+#define IMX_GIC_SIZE U(0x200000)
+
+#define IMX_HSIOMIX_CTL_BASE U(0x32f10000)
+#define IMX_HDMI_CTL_BASE U(0x32fc0000)
+#define RTX_RESET_CTL0 U(0x20)
+#define RTX_CLK_CTL0 U(0x40)
+#define RTX_CLK_CTL1 U(0x50)
+#define TX_CONTROL0 U(0x200)
+#define TX_CONTROL1 U(0x220)
+
+#define IMX_MEDIAMIX_CTL_BASE U(0x32ec0000)
+#define RSTn_CSR U(0x0)
+#define CLK_EN_CSR U(0x4)
+#define RST_DIV U(0x8)
+#define LCDIF_ARCACHE_CTRL U(0x4c)
+#define ISI_CACHE_CTRL U(0x50)
+
+#define WDOG_WSR U(0x2)
+#define WDOG_WCR_WDZST BIT(0)
+#define WDOG_WCR_WDBG BIT(1)
+#define WDOG_WCR_WDE BIT(2)
+#define WDOG_WCR_WDT BIT(3)
+#define WDOG_WCR_SRS BIT(4)
+#define WDOG_WCR_WDA BIT(5)
+#define WDOG_WCR_SRE BIT(6)
+#define WDOG_WCR_WDW BIT(7)
+
+#define SRC_A53RCR0 U(0x4)
+#define SRC_A53RCR1 U(0x8)
+#define SRC_OTG1PHY_SCR U(0x20)
+#define SRC_OTG2PHY_SCR U(0x24)
+#define SRC_GPR1_OFFSET U(0x74)
+
+#define SNVS_LPCR U(0x38)
+#define SNVS_LPCR_SRTC_ENV BIT(0)
+#define SNVS_LPCR_DP_EN BIT(5)
+#define SNVS_LPCR_TOP BIT(6)
+
+#define IOMUXC_GPR10 U(0x28)
+#define GPR_TZASC_EN BIT(0)
+#define GPR_TZASC_EN_LOCK BIT(16)
+
+#define ANAMIX_MISC_CTL U(0x124)
+#define DRAM_PLL_CTRL (IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM U(64)
+
+#define OCRAM_S_BASE U(0x00180000)
+#define OCRAM_S_SIZE U(0x8000)
+#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY 8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define MAX_IO_HANDLES 3U
+#define MAX_IO_DEVICES 2U
+#define MAX_IO_BLOCK_DEVICES 1U
+
+#define GIC_MAP MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
+#define AIPS_MAP MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
+#define OCRAM_S_MAP MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */
+#define DDRC_MAP MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+#define NOC_MAP MAP_REGION_FLAT(IMX_NOC_BASE, IMX_NOC_SIZE, MT_DEVICE | MT_RW) /* NOC QoS */
+#define CAAM_RAM_MAP MAP_REGION_FLAT(IMX_CAAM_RAM_BASE, IMX_CAAM_RAM_SIZE, MT_MEMORY | MT_RW) /* CAMM RAM */
+#define NS_OCRAM_MAP MAP_REGION_FLAT(IMX_NS_OCRAM_BASE, IMX_NS_OCRAM_SIZE, MT_MEMORY | MT_RW) /* NS OCRAM */
+#define ROM_MAP MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO) /* ROM code */
+
+/*
+ * Note: DRAM region is mapped with entire size available and uses MT_RW
+ * attributes.
+ * See details in docs/plat/imx8m.rst "High Assurance Boot (HABv4)" section
+ * for explanation of this mapping scheme.
+ */
+#define DRAM_MAP MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS) /* DRAM */
+
+#endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
new file mode 100644
index 0000000..5414c0a
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -0,0 +1,168 @@
+#
+# Copyright 2019-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := -Iplat/imx/common/include \
+ -Iplat/imx/imx8m/include \
+ -Iplat/imx/imx8m/imx8mp/include \
+ -Idrivers/imx/usdhc \
+ -Iinclude/common/tbbr
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_DRAM_SOURCES := plat/imx/imx8m/ddr/dram.c \
+ plat/imx/imx8m/ddr/clock.c \
+ plat/imx/imx8m/ddr/dram_retention.c \
+ plat/imx/imx8m/ddr/ddr4_dvfs.c \
+ plat/imx/imx8m/ddr/lpddr4_dvfs.c
+
+IMX_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8m/gpc_common.c \
+ plat/imx/imx8m/imx_hab.c \
+ plat/imx/imx8m/imx_aipstz.c \
+ plat/imx/imx8m/imx_rdc.c \
+ plat/imx/imx8m/imx8m_caam.c \
+ plat/imx/imx8m/imx8m_csu.c \
+ plat/imx/imx8m/imx8m_psci_common.c \
+ plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c \
+ plat/imx/imx8m/imx8mp/imx8mp_psci.c \
+ plat/imx/imx8m/imx8mp/gpc.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx_sip_handler.c \
+ plat/imx/common/imx_sip_svc.c \
+ plat/imx/common/imx_uart_console.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/tzc/tzc380.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${IMX_DRAM_SOURCES} \
+ ${IMX_GIC_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS}
+
+ifeq (${NEED_BL2},yes)
+BL2_SOURCES += common/desc_image_load.c \
+ plat/imx/common/imx8_helpers.S \
+ plat/imx/common/imx_uart_console.S \
+ plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c \
+ plat/imx/imx8m/imx8mp/gpc.c \
+ plat/imx/imx8m/imx_aipstz.c \
+ plat/imx/imx8m/imx_rdc.c \
+ plat/imx/imx8m/imx8m_caam.c \
+ plat/common/plat_psci_common.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/tzc/tzc380.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${PLAT_GIC_SOURCES} \
+ ${PLAT_DRAM_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS} \
+ drivers/mmc/mmc.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ drivers/imx/usdhc/imx_usdhc.c \
+ plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c \
+ plat/imx/common/imx_io_storage.c \
+ plat/imx/imx8m/imx8m_image_load.c \
+ lib/optee/optee_utils.c
+endif
+
+# Add the build options to pack BLx images and kernel device tree
+# in the FIP if the platform requires.
+ifneq ($(BL2),)
+RESET_TO_BL31 := 0
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
+endif
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+ifneq ($(HW_CONFIG),)
+$(eval $(call TOOL_ADD_IMG,HW_CONFIG,--hw-config))
+endif
+
+ifeq (${NEED_BL2},yes)
+$(eval $(call add_define,NEED_BL2))
+LOAD_IMAGE_V2 := 1
+# Non-TF Boot ROM
+BL2_AT_EL3 := 1
+endif
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c \
+ plat/imx/imx8m/imx8mp/imx8mp_rotpk.S
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(eval $(call MAKE_LIB_DIRS))
+
+$(BUILD_PLAT)/bl2/imx8mp_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ @if [ ! -f $(ROT_KEY) ]; then \
+ ${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null; \
+ fi
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
+
+ENABLE_PIE := 1
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+BL32_BASE ?= 0x56000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE ?= 0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE ?= 0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
+
+EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT)
+ifeq (${SDEI_SUPPORT}, 1)
+BL31_SOURCES += plat/imx/common/imx_ehf.c \
+ plat/imx/common/imx_sdei.c
+endif
+
+ifeq (${SPD},trusty)
+ BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
+endif
diff --git a/plat/imx/imx8m/imx8mq/gpc.c b/plat/imx/imx8m/imx8mq/gpc.c
new file mode 100644
index 0000000..fa83324
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/gpc.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <platform_def.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+
+/* use wfi power down the core */
+void imx_set_cpu_pwr_off(unsigned int core_id)
+{
+ bakery_lock_get(&gpc_lock);
+
+ /* enable the wfi power down of the core */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ (1 << (core_id + 20)));
+
+ bakery_lock_release(&gpc_lock);
+
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+};
+
+/* if out of lpm, we need to do reverse steps */
+void imx_set_cpu_lpm(unsigned int core_id, bool pdn)
+{
+ bakery_lock_get(&gpc_lock);
+
+ if (pdn) {
+ /* enable the core WFI PDN & IRQ PUP */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ (1 << (core_id + 20)) | COREx_IRQ_WUP(core_id));
+ /* assert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ } else {
+ /* disable CORE WFI PDN & IRQ PUP */
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_AD, COREx_WFI_PDN(core_id) |
+ COREx_IRQ_WUP(core_id));
+ /* deassert the pcg pcr bit of the core */
+ mmio_setbits_32(IMX_GPC_BASE + COREx_PGC_PCR(core_id), 0x1);
+ }
+
+ bakery_lock_release(&gpc_lock);
+}
+
+void imx_pup_pdn_slot_config(int last_core, bool pdn)
+{
+ if (pdn) {
+ /* SLOT0 for A53 PLAT power down */
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(0), SLT_PLAT_PDN);
+ /* SLOT1 for A53 PLAT power up */
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(1), SLT_PLAT_PUP);
+ /* SLOT2 for A53 primary core power up */
+ mmio_setbits_32(IMX_GPC_BASE + SLTx_CFG(2), SLT_COREx_PUP(last_core));
+ /* ACK setting: PLAT ACK for PDN, CORE ACK for PUP */
+ mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF,
+ A53_PLAT_PDN_ACK | A53_PLAT_PUP_ACK);
+ } else {
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(0), 0xFFFFFFFF);
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(1), 0xFFFFFFFF);
+ mmio_clrbits_32(IMX_GPC_BASE + SLTx_CFG(2), 0xFFFFFFFF);
+ mmio_clrsetbits_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, 0xFFFFFFFF,
+ A53_DUMMY_PDN_ACK | A53_DUMMY_PUP_ACK);
+ }
+}
+
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state)
+{
+ uint32_t val;
+
+ if (is_local_state_off(power_state)) {
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val |= A53_LPM_STOP; /* enable C0-C1's STOP mode */
+ val &= ~CPU_CLOCK_ON_LPM; /* disable CPU clock in LPM mode */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* enable C2-3's STOP mode */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_STOP);
+
+ /* enable PLAT/SCU power down */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+ val &= ~EN_L2_WFI_PDN;
+ val |= L2PGE | EN_PLAT_PDN;
+ val &= ~COREx_IRQ_WUP(last_core); /* disable IRQ PUP for last core */
+ val |= COREx_LPM_PUP(last_core); /* enable LPM PUP for last core */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+
+ imx_pup_pdn_slot_config(last_core, true);
+
+ /* enable PLAT PGC */
+ mmio_setbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1);
+ } else {
+ /* clear PLAT PGC */
+ mmio_clrbits_32(IMX_GPC_BASE + A53_PLAT_PGC, 0x1);
+
+ /* clear the slot and ack for cluster power down */
+ imx_pup_pdn_slot_config(last_core, false);
+
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val &= ~A53_LPM_MASK; /* clear the C0~1 LPM */
+ val |= CPU_CLOCK_ON_LPM; /* disable cpu clock in LPM */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* set A53 LPM to RUN mode */
+ mmio_clrbits_32(IMX_GPC_BASE + LPCR_A53_BSC2, A53_LPM_MASK);
+
+ /* clear PLAT/SCU power down */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_AD);
+ val |= EN_L2_WFI_PDN;
+ val &= ~(L2PGE | EN_PLAT_PDN);
+ val &= ~COREx_LPM_PUP(last_core); /* disable C0's LPM PUP */
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_AD, val);
+ }
+}
+
+void imx_gpc_init(void)
+{
+ uint32_t val;
+ int i;
+ /* mask all the interrupt by default */
+ for (i = 0; i < 4; i++) {
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+ }
+ /* Due to the hardware design requirement, need to make
+ * sure GPR interrupt(#32) is unmasked during RUN mode to
+ * avoid entering DSM mode by mistake.
+ */
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53, 0xFFFFFFFE);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53, 0xFFFFFFFE);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53, 0xFFFFFFFE);
+ mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53, 0xFFFFFFFE);
+
+ /* use external IRQs to wakeup C0~C3 from LPM */
+ val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+ val |= IRQ_SRC_A53_WUP;
+ /* clear the MASTER0 LPM handshake */
+ val &= ~MASTER0_LPM_HSK;
+ mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+ /* mask M4 DSM trigger if M4 is NOT enabled */
+ mmio_setbits_32(IMX_GPC_BASE + LPCR_M4, DSM_MODE_MASK);
+
+ /* set all mix/PU in A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xfffd);
+
+ /* set SCU timming */
+ mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+ (0x59 << 10) | 0x5B | (0x2 << 20));
+
+ /* set DUMMY PDN/PUP ACK by default for A53 domain */
+ mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53, A53_DUMMY_PUP_ACK |
+ A53_DUMMY_PDN_ACK);
+
+ /* disable DSM mode by default */
+ mmio_clrbits_32(IMX_GPC_BASE + SLPCR, DSM_MODE_MASK);
+
+ /*
+ * USB PHY power up needs to make sure RESET bit in SRC is clear,
+ * otherwise, the PU power up bit in GPC will NOT self-cleared.
+ * only need to do it once.
+ */
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+ mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+
+ /*
+ * for USB OTG, the limitation are:
+ * 1. before system clock config, the IPG clock run at 12.5MHz, delay time
+ * should be longer than 82us.
+ * 2. after system clock config, ipg clock run at 66.5MHz, delay time
+ * be longer that 15.3 us.
+ * Add 100us to make sure the USB OTG SRC is clear safely.
+ */
+ udelay(100);
+}
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
new file mode 100644
index 0000000..59c3779
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx8m_caam.h>
+#include <plat_imx8.h>
+
+#define TRUSTY_PARAMS_LEN_BYTES (4096*2)
+
+static const mmap_region_t imx_mmap[] = {
+ MAP_REGION_FLAT(GPV_BASE, GPV_SIZE, MT_DEVICE | MT_RW), /* GPV map */
+ MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO), /* ROM map */
+ MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
+ MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), /* GIC map */
+ {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+ {AIPSTZ1_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {AIPSTZ2_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {AIPSTZ3_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {AIPSTZ4_BASE, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+ {0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+static uint32_t imx_soc_revision;
+
+int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
+ u_register_t x3)
+{
+ return imx_soc_revision;
+}
+
+#define ANAMIX_DIGPROG 0x6c
+#define ROM_SOC_INFO_A0 0x800
+#define ROM_SOC_INFO_B0 0x83C
+#define OCOTP_SOC_INFO_B1 0x40
+
+static void imx8mq_soc_info_init(void)
+{
+ uint32_t rom_version;
+ uint32_t ocotp_val;
+
+ imx_soc_revision = mmio_read_32(IMX_ANAMIX_BASE + ANAMIX_DIGPROG);
+ rom_version = mmio_read_8(IMX_ROM_BASE + ROM_SOC_INFO_A0);
+ if (rom_version == 0x10)
+ return;
+
+ rom_version = mmio_read_8(IMX_ROM_BASE + ROM_SOC_INFO_B0);
+ if (rom_version == 0x20) {
+ imx_soc_revision &= ~0xff;
+ imx_soc_revision |= rom_version;
+ return;
+ }
+
+ /* 0xff0055aa is magic number for B1 */
+ ocotp_val = mmio_read_32(IMX_OCOTP_BASE + OCOTP_SOC_INFO_B1);
+ if (ocotp_val == 0xff0055aa) {
+ imx_soc_revision &= ~0xff;
+ imx_soc_revision |= 0x21;
+ return;
+ }
+}
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+static void bl31_tz380_setup(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(IMX_IOMUX_GPR_BASE + IOMUXC_GPR10);
+ if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+ return;
+
+ tzc380_init(IMX_TZASC_BASE);
+ /*
+ * Need to substact offset 0x40000000 from CPU address when
+ * programming tzasc region for i.mx8mq. Enable 1G-5G S/NS RW
+ */
+ tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+ TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ int i;
+ /* enable CSU NS access permission */
+ for (i = 0; i < 64; i++) {
+ mmio_write_32(IMX_CSU_BASE + i * 4, 0xffffffff);
+ }
+
+ imx_aipstz_init(aipstz);
+
+#if DEBUG_CONSOLE
+ static console_t console;
+
+ console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+#endif
+
+ imx8m_caam_init();
+
+ /*
+ * tell BL3-1 where the non-secure software image is located
+ * and the entry state information.
+ */
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#if defined(SPD_opteed) || defined(SPD_trusty)
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = 0;
+
+ /* Pass TEE base and size to bl33 */
+ bl33_image_ep_info.args.arg1 = BL32_BASE;
+ bl33_image_ep_info.args.arg2 = BL32_SIZE;
+
+#ifdef SPD_trusty
+ bl32_image_ep_info.args.arg0 = BL32_SIZE;
+ bl32_image_ep_info.args.arg1 = BL32_BASE;
+#else
+ /* Make sure memory is clean */
+ mmio_write_32(BL32_FDT_OVERLAY_ADDR, 0);
+ bl33_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+ bl32_image_ep_info.args.arg3 = BL32_FDT_OVERLAY_ADDR;
+#endif
+#endif
+
+ bl31_tz380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+ mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE),
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE),
+ MT_MEMORY | MT_RO | MT_SECURE);
+
+ /* Map TEE memory */
+ mmap_add_region(BL32_BASE, BL32_BASE, BL32_SIZE, MT_MEMORY | MT_RW);
+
+ mmap_add(imx_mmap);
+
+#if USE_COHERENT_MEM
+ mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+ /* setup xlat table */
+ init_xlat_tables();
+ /* enable the MMU */
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ generic_delay_timer_init();
+
+ /* init the GICv3 cpu and distributor interface */
+ plat_gic_driver_init();
+ plat_gic_init();
+
+ /* determine SOC revision for erratas */
+ imx8mq_soc_info_init();
+
+ /* gpc init */
+ imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ if (type == SECURE)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ return;
+}
+
+#ifdef SPD_trusty
+void plat_trusty_set_boot_args(aapcs64_params_t *args)
+{
+ args->arg0 = BL32_SIZE;
+ args->arg1 = BL32_BASE;
+ args->arg2 = TRUSTY_PARAMS_LEN_BYTES;
+}
+#endif
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
new file mode 100644
index 0000000..662017d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int pwr_type = psci_get_pstate_type(power_state);
+ int state_id = psci_get_pstate_id(power_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ if (pwr_type == PSTATE_TYPE_STANDBY) {
+ CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ }
+
+ if (pwr_type == PSTATE_TYPE_POWERDOWN && state_id == 0x33) {
+ CORE_PWR_STATE(req_state) = PLAT_MAX_OFF_STATE;
+ CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint64_t base_addr = BL31_BASE;
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ /* disable the cpu interface */
+ plat_gic_cpuif_disable();
+ imx_set_cpu_secure_entry(core_id, base_addr);
+ imx_set_cpu_lpm(core_id, true);
+ } else {
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+ }
+
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+ imx_set_cluster_powerdown(core_id, true);
+ else
+ imx_set_cluster_standby(true);
+
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ imx_set_sys_lpm(core_id, true);
+ }
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ uint64_t mpidr = read_mpidr_el1();
+ unsigned int core_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* check the system level status */
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ imx_set_sys_lpm(core_id, false);
+ imx_clear_rbc_count();
+ }
+
+ /* check the cluster level power status */
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state)))
+ imx_set_cluster_powerdown(core_id, false);
+ else
+ imx_set_cluster_standby(false);
+
+ /* check the core level power status */
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ /* clear the core lpm setting */
+ imx_set_cpu_lpm(core_id, false);
+ /* enable the gic cpu interface */
+ plat_gic_cpuif_enable();
+ } else {
+ write_scr_el3(read_scr_el3() & (~0x4));
+ isb();
+ }
+}
+
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ for (i = IMX_PWR_LVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE;
+
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE;
+}
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .validate_power_state = imx_validate_power_state,
+ .cpu_standby = imx_cpu_standby,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .system_reset = imx_system_reset,
+ .system_reset2 = imx_system_reset2,
+ .system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ imx_mailbox_init(sec_entrypoint);
+ /* sec_entrypoint is used for warm reset */
+ *psci_ops = &imx_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/imx/imx8m/imx8mq/include/gpc_reg.h b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
new file mode 100644
index 0000000..f171bd9
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC 0x0
+#define LPCR_A53_BSC2 0x108
+#define LPCR_A53_AD 0x4
+#define LPCR_M4 0x8
+#define SLPCR 0x14
+#define MST_CPU_MAPPING 0x18
+#define MLPCR 0x20
+#define PGC_ACK_SEL_A53 0x24
+#define IMR1_CORE0_A53 0x30
+#define IMR1_CORE1_A53 0x40
+#define IMR1_CORE2_A53 0x1C0
+#define IMR1_CORE3_A53 0x1D0
+#define IMR1_CORE0_M4 0x50
+#define SLT0_CFG 0xB0
+#define GPC_PU_PWRHSK 0x1FC
+#define PGC_CPU_0_1_MAPPING 0xEC
+#define CPU_PGC_UP_TRG 0xF0
+#define PU_PGC_UP_TRG 0xF8
+#define CPU_PGC_DN_TRG 0xFC
+#define PU_PGC_DN_TRG 0x104
+#define LPS_CPU1 0x114
+#define A53_CORE0_PGC 0x800
+#define A53_PLAT_PGC 0x900
+#define PLAT_PGC_PCR 0x900
+#define NOC_PGC_PCR 0xa40
+#define PGC_SCU_TIMING 0x910
+
+#define MASK_DSM_TRIGGER_A53 BIT(31)
+#define IRQ_SRC_A53_WUP BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT 30
+#define IRQ_SRC_C1 BIT(29)
+#define IRQ_SRC_C0 BIT(28)
+#define IRQ_SRC_C3 BIT(23)
+#define IRQ_SRC_C2 BIT(22)
+#define CPU_CLOCK_ON_LPM BIT(14)
+#define A53_CLK_ON_LPM BIT(14)
+#define MASTER0_LPM_HSK BIT(6)
+#define MASTER1_LPM_HSK BIT(7)
+#define MASTER2_LPM_HSK BIT(8)
+
+#define L2PGE BIT(31)
+#define EN_L2_WFI_PDN BIT(5)
+#define EN_PLAT_PDN BIT(4)
+
+#define SLPCR_EN_DSM BIT(31)
+#define SLPCR_RBC_EN BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE BIT(16)
+#define SLPCR_VSTBY BIT(2)
+#define SLPCR_SBYOS BIT(1)
+#define SLPCR_BYPASS_PMIC_READY BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT 24
+#define SLPCR_STBY_COUNT_SHFT 3
+
+#define A53_DUMMY_PDN_ACK BIT(15)
+#define A53_DUMMY_PUP_ACK BIT(31)
+#define A53_PLAT_PDN_ACK BIT(2)
+#define A53_PLAT_PUP_ACK BIT(18)
+#define NOC_PDN_SLT_CTRL BIT(10)
+#define NOC_PUP_SLT_CTRL BIT(11)
+#define NOC_PGC_PDN_ACK BIT(3)
+#define NOC_PGC_PUP_ACK BIT(19)
+
+#define DDRMIX_PWR_REQ BIT(5)
+#define DDRMIX_ADB400_SYNC BIT(1)
+#define DDRMIX_ADB400_ACK BIT(18)
+#define DDRMIX_PGC 0xd40
+
+#define PLAT_PUP_SLT_CTRL BIT(9)
+#define PLAT_PDN_SLT_CTRL BIT(8)
+
+#define SLT_PLAT_PDN BIT(8)
+#define SLT_PLAT_PUP BIT(9)
+
+#define MASTER1_MAPPING BIT(1)
+#define MASTER2_MAPPING BIT(2)
+
+#define IRQ_IMR_NUM U(4)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mq/include/imx_sec_def.h b/plat/imx/imx8m/imx8mq/include/imx_sec_def.h
new file mode 100644
index 0000000..0f77141
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/imx_sec_def.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_SEC_DEF_H
+#define IMX_SEC_DEF_H
+
+/* RDC MDA index */
+enum rdc_mda_idx {
+ RDC_MDA_A53 = 0,
+ RDC_MDA_M4 = 1,
+ RDC_MDA_PCIE_CTRL1 = 2,
+ RDC_MDA_PCIE_CTRL2 = 3,
+ RDC_MDA_VPU_DEC = 4,
+ RDC_MDA_LCDIF = 5,
+ RDC_MDA_CSI1 = 6,
+ RDC_MDA_CSI2 = 7,
+ RDC_MDA_Coresight = 8,
+ RDC_MDA_DAP = 9,
+ RDC_MDA_CAAM = 10,
+ RDC_MDA_SDMAp = 11,
+ RDC_MDA_SDMAb = 12,
+ RDC_MDA_APBHDMA = 13,
+ RDC_MDA_RAWNAND = 14,
+ RDC_MDA_uSDHC1 = 15,
+ RDC_MDA_uSDHC2 = 16,
+ RDC_MDA_DCSS = 17,
+ RDC_MDA_GPU = 18,
+ RDC_MDA_USB1 = 19,
+ RDC_MDA_USB2 = 20,
+ RDC_MDA_TESTPORT = 21,
+ RDC_MDA_ENET1_TX = 22,
+ RDC_MDA_ENET1_RX = 23,
+ RDC_MDA_SDMA2 = 24,
+ RDC_MDA_SDMA1 = 26,
+};
+
+/* RDC Peripherals index */
+enum rdc_pdap_idx {
+ RDC_PDAP_GPIO1 = 0,
+ RDC_PDAP_GPIO2 = 1,
+ RDC_PDAP_GPIO3 = 2,
+ RDC_PDAP_GPIO4 = 3,
+ RDC_PDAP_GPIO5 = 4,
+ RDC_PDAP_ANA_TSENSOR = 6,
+ RDC_PDAP_ANA_OSC = 7,
+ RDC_PDAP_WDOG1 = 8,
+ RDC_PDAP_WDOG2 = 9,
+ RDC_PDAP_WDOG3 = 10,
+ RDC_PDAP_SDMA2 = 12,
+ RDC_PDAP_GPT1 = 13,
+ RDC_PDAP_GPT2 = 14,
+ RDC_PDAP_GPT3 = 15,
+ RDC_PDAP_ROMCP = 17,
+ RDC_PDAP_LCDIF = 18,
+ RDC_PDAP_IOMUXC = 19,
+ RDC_PDAP_IOMUXC_GPR = 20,
+ RDC_PDAP_OCOTP_CTRL = 21,
+ RDC_PDAP_ANATOP_PLL = 22,
+ RDC_PDAP_SNVS_HP = 23,
+ RDC_PDAP_CCM = 24,
+ RDC_PDAP_SRC = 25,
+ RDC_PDAP_GPC = 26,
+ RDC_PDAP_SEMAPHORE1 = 27,
+ RDC_PDAP_SEMAPHORE2 = 28,
+ RDC_PDAP_RDC = 29,
+ RDC_PDAP_CSU = 30,
+ RDC_PDAP_MST0 = 32,
+ RDC_PDAP_MST1 = 33,
+ RDC_PDAP_MST2 = 34,
+ RDC_PDAP_MST3 = 35,
+ RDC_PDAP_HDMI_SEC = 36,
+ RDC_PDAP_PWM1 = 38,
+ RDC_PDAP_PWM2 = 39,
+ RDC_PDAP_PWM3 = 40,
+ RDC_PDAP_PWM4 = 41,
+ RDC_PDAP_SysCounter_RD = 42,
+ RDC_PDAP_SysCounter_CMP = 43,
+ RDC_PDAP_SysCounter_CTRL = 44,
+ RDC_PDAP_HDMI_CTRL = 45,
+ RDC_PDAP_GPT6 = 46,
+ RDC_PDAP_GPT5 = 47,
+ RDC_PDAP_GPT4 = 48,
+ RDC_PDAP_TZASC = 56,
+ RDC_PDAP_MTR = 59,
+ RDC_PDAP_PERFMON1 = 60,
+ RDC_PDAP_PERFMON2 = 61,
+ RDC_PDAP_PLATFORM_CTRL = 62,
+ RDC_PDAP_QoSC = 63,
+ RDC_PDAP_MIPI_PHY = 64,
+ RDC_PDAP_MIPI_DSI = 65,
+ RDC_PDAP_I2C1 = 66,
+ RDC_PDAP_I2C2 = 67,
+ RDC_PDAP_I2C3 = 68,
+ RDC_PDAP_I2C4 = 69,
+ RDC_PDAP_UART4 = 70,
+ RDC_PDAP_MIPI_CSI1 = 71,
+ RDC_PDAP_MIPI_CSI_PHY1 = 72,
+ RDC_PDAP_CSI1 = 73,
+ RDC_PDAP_MU_A = 74,
+ RDC_PDAP_MU_B = 75,
+ RDC_PDAP_SEMAPHORE_HS = 76,
+ RDC_PDAP_SAI1 = 78,
+ RDC_PDAP_SAI6 = 80,
+ RDC_PDAP_SAI5 = 81,
+ RDC_PDAP_SAI4 = 82,
+ RDC_PDAP_USDHC1 = 84,
+ RDC_PDAP_USDHC2 = 85,
+ RDC_PDAP_MIPI_CSI2 = 86,
+ RDC_PDAP_MIPI_CSI_PHY2 = 87,
+ RDC_PDAP_CSI2 = 88,
+ RDC_PDAP_QSPI = 91,
+ RDC_PDAP_SDMA1 = 93,
+ RDC_PDAP_ENET1 = 94,
+ RDC_PDAP_SPDIF1 = 97,
+ RDC_PDAP_ECSPI1 = 98,
+ RDC_PDAP_ECSPI2 = 99,
+ RDC_PDAP_ECSPI3 = 100,
+ RDC_PDAP_UART1 = 102,
+ RDC_PDAP_UART3 = 104,
+ RDC_PDAP_UART2 = 105,
+ RDC_PDAP_SPDIF2 = 106,
+ RDC_PDAP_SAI2 = 107,
+ RDC_PDAP_SAI3 = 108,
+ RDC_PDAP_SPBA1 = 111,
+ RDC_PDAP_CAAM = 114,
+ RDC_PDAP_DDRC_SEC = 115,
+ RDC_PDAP_GIC_EXSC = 116,
+ RDC_PDAP_USB_EXSC = 117,
+ RDC_PDAP_OCRAM_TZ = 118,
+ RDC_PDAP_OCRAM_S_TZ = 119,
+ RDC_PDAP_VPU_SEC = 120,
+ RDC_PDAP_DAP_EXSC = 121,
+ RDC_PDAP_ROMCP_SEC = 122,
+ RDC_PDAP_APBHDMA_SEC = 123,
+ RDC_PDAP_M4_SEC = 124,
+ RDC_PDAP_QSPI_SEC = 125,
+ RDC_PDAP_GPU_EXSC = 126,
+ RDC_PDAP_PCIE = 127,
+};
+
+enum csu_csl_idx {
+ CSU_CSL_GPIO1 = 0,
+ CSU_CSL_GPIO2 = 1,
+ CSU_CSL_GPIO3 = 2,
+ CSU_CSL_GPIO4 = 3,
+ CSU_CSL_GPIO5 = 4,
+ CSU_CSL_ANA_TSENSOR = 6,
+ CSU_CSL_ANA_OSC = 7,
+ CSU_CSL_WDOG1 = 8,
+ CSU_CSL_WDOG2 = 9,
+ CSU_CSL_WDOG3 = 10,
+ CSU_CSL_SDMA2 = 12,
+ CSU_CSL_GPT1 = 13,
+ CSU_CSL_GPT2 = 14,
+ CSU_CSL_GPT3 = 15,
+ CSU_CSL_ROMCP = 17,
+ CSU_CSL_LCDIF = 18,
+ CSU_CSL_IOMUXC = 19,
+ CSU_CSL_IOMUXC_GPR = 20,
+ CSU_CSL_OCOTP_CTRL = 21,
+ CSU_CSL_ANATOP_PLL = 22,
+ CSU_CSL_SNVS_HP = 23,
+ CSU_CSL_CCM = 24,
+ CSU_CSL_SRC = 25,
+ CSU_CSL_GPC = 26,
+ CSU_CSL_SEMAPHORE1 = 27,
+ CSU_CSL_SEMAPHORE2 = 28,
+ CSU_CSL_RDC = 29,
+ CSU_CSL_CSU = 30,
+ CSU_CSL_MST0 = 32,
+ CSU_CSL_MST1 = 33,
+ CSU_CSL_MST2 = 34,
+ CSU_CSL_MST3 = 35,
+ CSU_CSL_HDMI_SEC = 36,
+ CSU_CSL_PWM1 = 38,
+ CSU_CSL_PWM2 = 39,
+ CSU_CSL_PWM3 = 40,
+ CSU_CSL_PWM4 = 41,
+ CSU_CSL_SysCounter_RD = 42,
+ CSU_CSL_SysCounter_CMP = 43,
+ CSU_CSL_SysCounter_CTRL = 44,
+ CSU_CSL_HDMI_CTRL = 45,
+ CSU_CSL_GPT6 = 46,
+ CSU_CSL_GPT5 = 47,
+ CSU_CSL_GPT4 = 48,
+ CSU_CSL_TZASC = 56,
+ CSU_CSL_MTR = 59,
+ CSU_CSL_PERFMON1 = 60,
+ CSU_CSL_PERFMON2 = 61,
+ CSU_CSL_PLATFORM_CTRL = 62,
+ CSU_CSL_QoSC = 63,
+ CSU_CSL_MIPI_PHY = 64,
+ CSU_CSL_MIPI_DSI = 65,
+ CSU_CSL_I2C1 = 66,
+ CSU_CSL_I2C2 = 67,
+ CSU_CSL_I2C3 = 68,
+ CSU_CSL_I2C4 = 69,
+ CSU_CSL_UART4 = 70,
+ CSU_CSL_MIPI_CSI1 = 71,
+ CSU_CSL_MIPI_CSI_PHY1 = 72,
+ CSU_CSL_CSI1 = 73,
+ CSU_CSL_MU_A = 74,
+ CSU_CSL_MU_B = 75,
+ CSU_CSL_SEMAPHORE_HS = 76,
+ CSU_CSL_SAI1 = 78,
+ CSU_CSL_SAI6 = 80,
+ CSU_CSL_SAI5 = 81,
+ CSU_CSL_SAI4 = 82,
+ CSU_CSL_USDHC1 = 84,
+ CSU_CSL_USDHC2 = 85,
+ CSU_CSL_MIPI_CSI2 = 86,
+ CSU_CSL_MIPI_CSI_PHY2 = 87,
+ CSU_CSL_CSI2 = 88,
+ CSU_CSL_QSPI = 91,
+ CSU_CSL_SDMA1 = 93,
+ CSU_CSL_ENET1 = 94,
+ CSU_CSL_SPDIF1 = 97,
+ CSU_CSL_ECSPI1 = 98,
+ CSU_CSL_ECSPI2 = 99,
+ CSU_CSL_ECSPI3 = 100,
+ CSU_CSL_UART1 = 102,
+ CSU_CSL_UART3 = 104,
+ CSU_CSL_UART2 = 105,
+ CSU_CSL_SPDIF2 = 106,
+ CSU_CSL_SAI2 = 107,
+ CSU_CSL_SAI3 = 108,
+ CSU_CSL_SPBA1 = 111,
+ CSU_CSL_MOD_EN3 = 112,
+ CSU_CSL_MOD_EN0 = 113,
+ CSU_CSL_CAAM = 114,
+ CSU_CSL_DDRC_SEC = 115,
+ CSU_CSL_GIC_EXSC = 116,
+ CSU_CSL_USB_EXSC = 117,
+ CSU_CSL_OCRAM_TZ = 118,
+ CSU_CSL_OCRAM_S_TZ = 119,
+ CSU_CSL_VPU_SEC = 120,
+ CSU_CSL_DAP_EXSC = 121,
+ CSU_CSL_ROMCP_SEC = 122,
+ CSU_CSL_APBHDMA_SEC = 123,
+ CSU_CSL_M4_SEC = 124,
+ CSU_CSL_QSPI_SEC = 125,
+ CSU_CSL_GPU_EXSC = 126,
+ CSU_CSL_PCIE = 127,
+};
+
+#endif /* IMX_SEC_DEF_H */
diff --git a/plat/imx/imx8m/imx8mq/include/platform_def.h b/plat/imx/imx8m/imx8mq/include/platform_def.h
new file mode 100644
index 0000000..1dd22d9
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/platform_def.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0x800
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(4)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define PLAT_WAIT_RET_STATE PLAT_MAX_RET_STATE
+#define PLAT_WAIT_OFF_STATE U(2)
+#define PLAT_STOP_OFF_STATE U(3)
+
+#define BL31_BASE U(0x910000)
+#define BL31_LIMIT U(0x920000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET U(0x40200000)
+#define BL32_FDT_OVERLAY_ADDR (PLAT_NS_IMAGE_OFFSET + 0x3000000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE U(0x38800000)
+#define PLAT_GICR_BASE U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+
+#ifdef SPD_trusty
+#define MAX_XLAT_TABLES 5
+#define MAX_MMAP_REGIONS 15
+#else
+#define MAX_XLAT_TABLES 4
+#define MAX_MMAP_REGIONS 14
+#endif
+
+#define HAB_RVT_BASE U(0x00000880) /* HAB_RVT for i.MX8MQ */
+
+#define IMX_BOOT_UART_BASE U(0x30860000)
+#define IMX_BOOT_UART_CLK_IN_HZ 25000000 /* Select 25Mhz oscillator */
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ 25000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define IMX_AIPS_BASE U(0x30200000)
+#define IMX_AIPS_SIZE U(0xC00000)
+#define IMX_AIPS1_BASE U(0x30200000)
+#define IMX_AIPS3_ARB_BASE U(0x30800000)
+#define IMX_OCOTP_BASE U(0x30350000)
+#define IMX_ANAMIX_BASE U(0x30360000)
+#define IMX_CCM_BASE U(0x30380000)
+#define IMX_SRC_BASE U(0x30390000)
+#define IMX_GPC_BASE U(0x303a0000)
+#define IMX_RDC_BASE U(0x303d0000)
+#define IMX_CSU_BASE U(0x303e0000)
+#define IMX_WDOG_BASE U(0x30280000)
+#define IMX_SNVS_BASE U(0x30370000)
+#define IMX_NOC_BASE U(0x32700000)
+#define IMX_TZASC_BASE U(0x32F80000)
+#define IMX_CAAM_BASE U(0x30900000)
+#define IMX_IOMUX_GPR_BASE U(0x30340000)
+#define IMX_DDRC_BASE U(0x3d400000)
+#define IMX_DDRPHY_BASE U(0x3c000000)
+#define IMX_DDR_IPS_BASE U(0x3d000000)
+
+#define IMX_ROM_BASE U(0x00000000)
+#define IMX_ROM_SIZE U(0x20000)
+
+#define AIPSTZ1_BASE U(0x301f0000)
+#define AIPSTZ2_BASE U(0x305f0000)
+#define AIPSTZ3_BASE U(0x309f0000)
+#define AIPSTZ4_BASE U(0x32df0000)
+
+#define GPV_BASE U(0x32000000)
+#define GPV_SIZE U(0x800000)
+#define IMX_GIC_BASE PLAT_GICD_BASE
+#define IMX_GIC_SIZE U(0x200000)
+
+#define WDOG_WSR U(0x2)
+#define WDOG_WCR_WDZST BIT(0)
+#define WDOG_WCR_WDBG BIT(1)
+#define WDOG_WCR_WDE BIT(2)
+#define WDOG_WCR_WDT BIT(3)
+#define WDOG_WCR_SRS BIT(4)
+#define WDOG_WCR_WDA BIT(5)
+#define WDOG_WCR_SRE BIT(6)
+#define WDOG_WCR_WDW BIT(7)
+
+#define SRC_A53RCR0 U(0x4)
+#define SRC_A53RCR1 U(0x8)
+#define SRC_OTG1PHY_SCR U(0x20)
+#define SRC_OTG2PHY_SCR U(0x24)
+#define SRC_GPR1_OFFSET U(0x74)
+#define SRC_GPR10_OFFSET U(0x98)
+#define SRC_GPR10_PERSIST_SECONDARY_BOOT BIT(30)
+
+#define SNVS_LPCR U(0x38)
+#define SNVS_LPCR_SRTC_ENV BIT(0)
+#define SNVS_LPCR_DP_EN BIT(5)
+#define SNVS_LPCR_TOP BIT(6)
+
+
+#define IOMUXC_GPR10 U(0x28)
+#define GPR_TZASC_EN BIT(0)
+#define GPR_TZASC_EN_LOCK BIT(16)
+
+#define OCRAM_S_BASE U(0x00180000)
+#define OCRAM_S_SIZE U(0x8000)
+#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
+
+#define COUNTER_FREQUENCY 8333333 /* 25MHz / 3 */
+
+#define DEBUG_CONSOLE 0
+#define IMX_WDOG_B_RESET
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
new file mode 100644
index 0000000..7b6df92
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Iplat/imx/common/include \
+ -Iplat/imx/imx8m/include \
+ -Iplat/imx/imx8m/imx8mq/include
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c \
+ plat/imx/imx8m/imx8mq/imx8mq_psci.c \
+ plat/imx/imx8m/gpc_common.c \
+ plat/imx/imx8m/imx_aipstz.c \
+ plat/imx/imx8m/imx8m_caam.c \
+ plat/imx/imx8m/imx8m_psci_common.c \
+ plat/imx/imx8m/imx8mq/gpc.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx_sip_handler.c \
+ plat/imx/common/imx_sip_svc.c \
+ plat/imx/common/imx_uart_console.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ drivers/arm/tzc/tzc380.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${IMX_GIC_SOURCES}
+
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+BL32_BASE ?= 0xfe000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE ?= 0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+ifeq (${SPD},trusty)
+ BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
+endif
diff --git a/plat/imx/imx8m/imx_aipstz.c b/plat/imx/imx8m/imx_aipstz.c
new file mode 100644
index 0000000..ecf8b1d
--- /dev/null
+++ b/plat/imx/imx8m/imx_aipstz.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <imx_aipstz.h>
+
+void imx_aipstz_init(const struct aipstz_cfg *aipstz_cfg)
+{
+ const struct aipstz_cfg *aipstz = aipstz_cfg;
+
+ while (aipstz->base != 0U) {
+ mmio_write_32(aipstz->base + AIPSTZ_MPR0, aipstz->mpr0);
+ mmio_write_32(aipstz->base + AIPSTZ_MPR1, aipstz->mpr1);
+
+ for (int i = 0; i < AIPSTZ_OPACR_NUM; i++)
+ mmio_write_32(aipstz->base + OPACR_OFFSET(i), aipstz->opacr[i]);
+
+ aipstz++;
+ }
+}
diff --git a/plat/imx/imx8m/imx_hab.c b/plat/imx/imx8m/imx_hab.c
new file mode 100644
index 0000000..222046f
--- /dev/null
+++ b/plat/imx/imx8m/imx_hab.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017-2020 NXP
+ * Copyright 2022 Leica Geosystems AG
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/runtime_svc.h>
+#include <imx_sip_svc.h>
+
+#define HAB_CID_ATF U(2) /* TF-A Caller ID */
+
+/* HAB Status definitions */
+enum hab_status {
+ HAB_STS_ANY = 0x00, /* Match any status in report_event() */
+ HAB_FAILURE = 0x33, /* Operation failed */
+ HAB_WARNING = 0x69, /* Operation completed with warning */
+ HAB_SUCCESS = 0xf0 /* Operation completed successfully */
+};
+
+/* HAB Configuration definitions */
+enum hab_config {
+ HAB_CFG_RETURN = 0x33, /* Field Return IC */
+ HAB_CFG_OPEN = 0xf0, /* Non-secure IC */
+ HAB_CFG_CLOSED = 0xcc /* Secure IC */
+};
+
+/* HAB State definitions */
+enum hab_state {
+ HAB_STATE_INITIAL = 0x33, /* Initializing state (transitory) */
+ HAB_STATE_CHECK = 0x55, /* Check state (non-secure) */
+ HAB_STATE_NONSECURE = 0x66, /* Non-secure state */
+ HAB_STATE_TRUSTED = 0x99, /* Trusted state */
+ HAB_STATE_SECURE = 0xaa, /* Secure state */
+ HAB_STATE_FAIL_SOFT = 0xcc, /* Soft fail state */
+ HAB_STATE_FAIL_HARD = 0xff, /* Hard fail state (terminal) */
+ HAB_STATE_NONE = 0xf0 /* No security state machine */
+};
+
+/* HAB Verification Target definitions */
+enum hab_target {
+ HAB_TGT_MEMORY = 0x0f, /* Check memory allowed list */
+ HAB_TGT_PERIPHERAL = 0xf0, /* Check peripheral allowed list */
+ HAB_TGT_ANY = 0x55 /* Check memory & peripheral allowed list */
+};
+
+/* Authenticate Image Loader Callback prototype */
+typedef enum hab_status hab_loader_callback_f_t(void **, size_t *, const void *);
+
+/*
+ * HAB Rom VectorTable (RVT) structure.
+ * This table provides function pointers into the HAB library in ROM for
+ * use by post-ROM boot sequence components.
+ * Functions are ordered in the structure below based on the offsets in ROM
+ * image, and shall not be changed!
+ * Details on API allocation offsets and function description could be
+ * found in following documents from NXP:
+ * - High Assurance Boot Version 4 Application Programming Interface
+ * Reference Manual (available in CST package)
+ * - HABv4 RVT Guidelines and Recommendations (AN12263)
+ */
+struct hab_rvt_api {
+ uint64_t hdr;
+ enum hab_status (*entry)(void);
+ enum hab_status (*exit)(void);
+ enum hab_status (*check_target)(enum hab_target type, const void *start, size_t bytes);
+ void* (*authenticate_image)(uint8_t cid, long ivt_offset, void **start,
+ size_t *bytes, hab_loader_callback_f_t loader);
+ enum hab_status (*run_dcd)(const uint8_t *dcd);
+ enum hab_status (*run_csf)(const uint8_t *csf, uint8_t cid, uint32_t srkmask);
+ enum hab_status (*assert)(long type, const void *data, uint32_t count);
+ enum hab_status (*report_event)(enum hab_status status, uint32_t index,
+ uint8_t *event, size_t *bytes);
+ enum hab_status (*report_status)(enum hab_config *config, enum hab_state *state);
+ void (*failsafe)(void);
+ void* (*authenticate_image_no_dcd)(uint8_t cid, long ivt_offset, void **start,
+ size_t *bytes, hab_loader_callback_f_t loader);
+ uint32_t (*get_version)(void);
+ enum hab_status (*authenticate_container)(uint8_t cid, long ivt_offset, void **start,
+ size_t *bytes, hab_loader_callback_f_t loader, uint32_t srkmask, int skip_dcd);
+};
+
+struct hab_rvt_api *g_hab_rvt_api = (struct hab_rvt_api *)HAB_RVT_BASE;
+
+/*******************************************************************************
+ * Handler for servicing HAB SMC calls
+ ******************************************************************************/
+int imx_hab_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4)
+{
+ switch (x1) {
+ case IMX_SIP_HAB_ENTRY:
+ return g_hab_rvt_api->entry();
+ case IMX_SIP_HAB_EXIT:
+ return g_hab_rvt_api->exit();
+ case IMX_SIP_HAB_CHECK_TARGET:
+ return g_hab_rvt_api->check_target((enum hab_target)x2,
+ (const void *)x3, (size_t)x4);
+ case IMX_SIP_HAB_AUTH_IMG:
+ return (unsigned long)g_hab_rvt_api->authenticate_image(HAB_CID_ATF,
+ x2, (void **)x3, (size_t *)x4, NULL);
+ case IMX_SIP_HAB_REPORT_EVENT:
+ return g_hab_rvt_api->report_event(HAB_FAILURE,
+ (uint32_t)x2, (uint8_t *)x3, (size_t *)x4);
+ case IMX_SIP_HAB_REPORT_STATUS:
+ return g_hab_rvt_api->report_status((enum hab_config *)x2,
+ (enum hab_state *)x3);
+ case IMX_SIP_HAB_FAILSAFE:
+ g_hab_rvt_api->failsafe();
+ break;
+ case IMX_SIP_HAB_AUTH_IMG_NO_DCD:
+ return (unsigned long)g_hab_rvt_api->authenticate_image_no_dcd(
+ HAB_CID_ATF, x2, (void **)x3, (size_t *)x4, NULL);
+ case IMX_SIP_HAB_GET_VERSION:
+ return g_hab_rvt_api->get_version();
+ default:
+ return SMC_UNK;
+ };
+
+ return SMC_OK;
+}
diff --git a/plat/imx/imx8m/imx_rdc.c b/plat/imx/imx8m/imx_rdc.c
new file mode 100644
index 0000000..85de191
--- /dev/null
+++ b/plat/imx/imx8m/imx_rdc.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, NXP. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <imx_rdc.h>
+
+void imx_rdc_init(const struct imx_rdc_cfg *rdc_cfg)
+{
+ const struct imx_rdc_cfg *rdc = rdc_cfg;
+
+ while (rdc->type != RDC_INVALID) {
+ switch (rdc->type) {
+ case RDC_MDA:
+ /* MDA config */
+ mmio_write_32(MDAn(rdc->index), rdc->setting.rdc_mda);
+ break;
+ case RDC_PDAP:
+ /* peripheral access permission config */
+ mmio_write_32(PDAPn(rdc->index), rdc->setting.rdc_pdap);
+ break;
+ case RDC_MEM_REGION:
+ /* memory region access permission config */
+ mmio_write_32(MRSAn(rdc->index), rdc->setting.rdc_mem_region[0]);
+ mmio_write_32(MREAn(rdc->index), rdc->setting.rdc_mem_region[1]);
+ mmio_write_32(MRCn(rdc->index), rdc->setting.rdc_mem_region[2]);
+ break;
+ default:
+ break;
+ }
+
+ rdc++;
+ }
+}
diff --git a/plat/imx/imx8m/include/ddrc.h b/plat/imx/imx8m/include/ddrc.h
new file mode 100644
index 0000000..55af3ff
--- /dev/null
+++ b/plat/imx/imx8m/include/ddrc.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_DDRC_H
+#define IMX_DDRC_H
+
+#define DDRC_IPS_BASE_ADDR(X) (0x3d400000 + ((X) * 0x2000000))
+#define DDRC_DDR_SS_GPR0 0x3d000000
+
+/* DWC ddr umctl2 REGs offset*/
+/**********************/
+#define DDRC_MSTR(X) (DDRC_IPS_BASE_ADDR(X) + 0x00)
+#define DDRC_STAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x04)
+#define DDRC_MSTR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x08)
+#define DDRC_MRCTRL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x10)
+#define DDRC_MRCTRL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x14)
+#define DDRC_MRSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x18)
+#define DDRC_MRCTRL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1c)
+#define DDRC_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x20)
+#define DDRC_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x24)
+#define DDRC_MSTR2(X) (DDRC_IPS_BASE_ADDR(X) + 0x28)
+#define DDRC_PWRCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x30)
+#define DDRC_PWRTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x34)
+#define DDRC_HWLPCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x38)
+#define DDRC_HWFFCCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x3c)
+#define DDRC_HWFFCSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x40)
+#define DDRC_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x50)
+#define DDRC_RFSHCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x54)
+#define DDRC_RFSHCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x58)
+#define DDRC_RFSHCTL3(X) (DDRC_IPS_BASE_ADDR(X) + 0x60)
+#define DDRC_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x64)
+#define DDRC_ECCCFG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x70)
+#define DDRC_ECCCFG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x74)
+#define DDRC_ECCSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x78)
+#define DDRC_ECCCLR(X) (DDRC_IPS_BASE_ADDR(X) + 0x7c)
+#define DDRC_ECCERRCNT(X) (DDRC_IPS_BASE_ADDR(X) + 0x80)
+#define DDRC_ECCCADDR0(X) (DDRC_IPS_BASE_ADDR(X) + 0x84)
+#define DDRC_ECCCADDR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x88)
+#define DDRC_ECCCSYN0(X) (DDRC_IPS_BASE_ADDR(X) + 0x8c)
+#define DDRC_ECCCSYN1(X) (DDRC_IPS_BASE_ADDR(X) + 0x90)
+#define DDRC_ECCCSYN2(X) (DDRC_IPS_BASE_ADDR(X) + 0x94)
+#define DDRC_ECCBITMASK0(X) (DDRC_IPS_BASE_ADDR(X) + 0x98)
+#define DDRC_ECCBITMASK1(X) (DDRC_IPS_BASE_ADDR(X) + 0x9c)
+#define DDRC_ECCBITMASK2(X) (DDRC_IPS_BASE_ADDR(X) + 0xa0)
+#define DDRC_ECCUADDR0(X) (DDRC_IPS_BASE_ADDR(X) + 0xa4)
+#define DDRC_ECCUADDR1(X) (DDRC_IPS_BASE_ADDR(X) + 0xa8)
+#define DDRC_ECCUSYN0(X) (DDRC_IPS_BASE_ADDR(X) + 0xac)
+#define DDRC_ECCUSYN1(X) (DDRC_IPS_BASE_ADDR(X) + 0xb0)
+#define DDRC_ECCUSYN2(X) (DDRC_IPS_BASE_ADDR(X) + 0xb4)
+#define DDRC_ECCPOISONADDR0(X) (DDRC_IPS_BASE_ADDR(X) + 0xb8)
+#define DDRC_ECCPOISONADDR1(X) (DDRC_IPS_BASE_ADDR(X) + 0xbc)
+#define DDRC_CRCPARCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0xc0)
+#define DDRC_CRCPARCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0xc4)
+#define DDRC_CRCPARCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0xc8)
+#define DDRC_CRCPARSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0xcc)
+#define DDRC_INIT0(X) (DDRC_IPS_BASE_ADDR(X) + 0xd0)
+#define DDRC_INIT1(X) (DDRC_IPS_BASE_ADDR(X) + 0xd4)
+#define DDRC_INIT2(X) (DDRC_IPS_BASE_ADDR(X) + 0xd8)
+#define DDRC_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0xdc)
+#define DDRC_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0xe0)
+#define DDRC_INIT5(X) (DDRC_IPS_BASE_ADDR(X) + 0xe4)
+#define DDRC_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0xe8)
+#define DDRC_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0xec)
+#define DDRC_DIMMCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0xf0)
+#define DDRC_RANKCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0xf4)
+#define DDRC_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x100)
+#define DDRC_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x104)
+#define DDRC_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x108)
+#define DDRC_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x10c)
+#define DDRC_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x110)
+#define DDRC_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x114)
+#define DDRC_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x118)
+#define DDRC_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x11c)
+#define DDRC_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x120)
+#define DDRC_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x124)
+#define DDRC_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x128)
+#define DDRC_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x12c)
+#define DDRC_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x130)
+#define DDRC_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x134)
+#define DDRC_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x138)
+#define DDRC_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x13C)
+#define DDRC_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x140)
+#define DDRC_DRAMTMG17(X) (DDRC_IPS_BASE_ADDR(X) + 0x144)
+
+#define DDRC_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x180)
+#define DDRC_ZQCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x184)
+#define DDRC_ZQCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x188)
+#define DDRC_ZQSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x18c)
+#define DDRC_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x190)
+#define DDRC_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x194)
+#define DDRC_DFILPCFG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x198)
+#define DDRC_DFILPCFG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x19c)
+#define DDRC_DFIUPD0(X) (DDRC_IPS_BASE_ADDR(X) + 0x1a0)
+#define DDRC_DFIUPD1(X) (DDRC_IPS_BASE_ADDR(X) + 0x1a4)
+#define DDRC_DFIUPD2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1a8)
+#define DDRC_DFIMISC(X) (DDRC_IPS_BASE_ADDR(X) + 0x1b0)
+#define DDRC_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1b4)
+#define DDRC_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x1b8)
+#define DDRC_DFISTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x1bc)
+
+#define DDRC_DBICTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x1c0)
+#define DDRC_DFIPHYMSTR(X) (DDRC_IPS_BASE_ADDR(X) + 0x1c4)
+#define DDRC_TRAINCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x1d0)
+#define DDRC_TRAINCTL1(X) (DDRC_IPS_BASE_ADDR(X) + 0x1d4)
+#define DDRC_TRAINCTL2(X) (DDRC_IPS_BASE_ADDR(X) + 0x1d8)
+#define DDRC_TRAINSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x1dc)
+#define DDRC_ADDRMAP0(X) (DDRC_IPS_BASE_ADDR(X) + 0x200)
+#define DDRC_ADDRMAP1(X) (DDRC_IPS_BASE_ADDR(X) + 0x204)
+#define DDRC_ADDRMAP2(X) (DDRC_IPS_BASE_ADDR(X) + 0x208)
+#define DDRC_ADDRMAP3(X) (DDRC_IPS_BASE_ADDR(X) + 0x20c)
+#define DDRC_ADDRMAP4(X) (DDRC_IPS_BASE_ADDR(X) + 0x210)
+#define DDRC_ADDRMAP5(X) (DDRC_IPS_BASE_ADDR(X) + 0x214)
+#define DDRC_ADDRMAP6(X) (DDRC_IPS_BASE_ADDR(X) + 0x218)
+#define DDRC_ADDRMAP7(X) (DDRC_IPS_BASE_ADDR(X) + 0x21c)
+#define DDRC_ADDRMAP8(X) (DDRC_IPS_BASE_ADDR(X) + 0x220)
+#define DDRC_ADDRMAP9(X) (DDRC_IPS_BASE_ADDR(X) + 0x224)
+#define DDRC_ADDRMAP10(X) (DDRC_IPS_BASE_ADDR(X) + 0x228)
+#define DDRC_ADDRMAP11(X) (DDRC_IPS_BASE_ADDR(X) + 0x22c)
+
+#define DDRC_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x240)
+#define DDRC_ODTMAP(X) (DDRC_IPS_BASE_ADDR(X) + 0x244)
+#define DDRC_SCHED(X) (DDRC_IPS_BASE_ADDR(X) + 0x250)
+#define DDRC_SCHED1(X) (DDRC_IPS_BASE_ADDR(X) + 0x254)
+#define DDRC_PERFHPR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x25c)
+#define DDRC_PERFLPR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x264)
+#define DDRC_PERFWR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x26c)
+#define DDRC_PERFVPR1(X) (DDRC_IPS_BASE_ADDR(X) + 0x274)
+
+#define DDRC_PERFVPW1(X) (DDRC_IPS_BASE_ADDR(X) + 0x278)
+
+#define DDRC_DQMAP0(X) (DDRC_IPS_BASE_ADDR(X) + 0x280)
+#define DDRC_DQMAP1(X) (DDRC_IPS_BASE_ADDR(X) + 0x284)
+#define DDRC_DQMAP2(X) (DDRC_IPS_BASE_ADDR(X) + 0x288)
+#define DDRC_DQMAP3(X) (DDRC_IPS_BASE_ADDR(X) + 0x28c)
+#define DDRC_DQMAP4(X) (DDRC_IPS_BASE_ADDR(X) + 0x290)
+#define DDRC_DQMAP5(X) (DDRC_IPS_BASE_ADDR(X) + 0x294)
+#define DDRC_DBG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x300)
+#define DDRC_DBG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x304)
+#define DDRC_DBGCAM(X) (DDRC_IPS_BASE_ADDR(X) + 0x308)
+#define DDRC_DBGCMD(X) (DDRC_IPS_BASE_ADDR(X) + 0x30c)
+#define DDRC_DBGSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x310)
+
+#define DDRC_SWCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x320)
+#define DDRC_SWSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x324)
+#define DDRC_OCPARCFG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x330)
+#define DDRC_OCPARCFG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x334)
+#define DDRC_OCPARCFG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x338)
+#define DDRC_OCPARCFG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x33c)
+#define DDRC_OCPARSTAT0(X) (DDRC_IPS_BASE_ADDR(X) + 0x340)
+#define DDRC_OCPARSTAT1(X) (DDRC_IPS_BASE_ADDR(X) + 0x344)
+#define DDRC_OCPARWLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x348)
+#define DDRC_OCPARWLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x34c)
+#define DDRC_OCPARWLOG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x350)
+#define DDRC_OCPARAWLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x354)
+#define DDRC_OCPARAWLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x358)
+#define DDRC_OCPARRLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x35c)
+#define DDRC_OCPARRLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x360)
+#define DDRC_OCPARARLOG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x364)
+#define DDRC_OCPARARLOG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x368)
+#define DDRC_POISONCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x36C)
+#define DDRC_POISONSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x370)
+#define DDRC_ADVECCINDEX(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ADVECCSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT1(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_ECCPOISONPAT2(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+#define DDRC_HIFCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0x3)
+
+#define DDRC_PSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0x3fc)
+#define DDRC_PCCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x400)
+#define DDRC_PCFGR_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x404)
+#define DDRC_PCFGR_1(X) (DDRC_IPS_BASE_ADDR(X) + 1 * 0xb0 + 0x404)
+#define DDRC_PCFGR_2(X) (DDRC_IPS_BASE_ADDR(X) + 2 * 0xb0 + 0x404)
+#define DDRC_PCFGR_3(X) (DDRC_IPS_BASE_ADDR(X) + 3 * 0xb0 + 0x404)
+#define DDRC_PCFGW_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x408)
+#define DDRC_PCFGW_1(X) (DDRC_IPS_BASE_ADDR(X) + 1 * 0xb0 + 0x408)
+#define DDRC_PCFGW_2(X) (DDRC_IPS_BASE_ADDR(X) + 2 * 0xb0 + 0x408)
+#define DDRC_PCFGW_3(X) (DDRC_IPS_BASE_ADDR(X) + 3 * 0xb0 + 0x408)
+#define DDRC_PCFGC_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x40c)
+#define DDRC_PCFGIDMASKCH(X) (DDRC_IPS_BASE_ADDR(X) + 0x410)
+#define DDRC_PCFGIDVALUECH(X) (DDRC_IPS_BASE_ADDR(X) + 0x414)
+#define DDRC_PCTRL_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x490)
+#define DDRC_PCTRL_1(X) (DDRC_IPS_BASE_ADDR(X) + 0x490 + 1 * 0xb0)
+#define DDRC_PCTRL_2(X) (DDRC_IPS_BASE_ADDR(X) + 0x490 + 2 * 0xb0)
+#define DDRC_PCTRL_3(X) (DDRC_IPS_BASE_ADDR(X) + 0x490 + 3 * 0xb0)
+#define DDRC_PCFGQOS0_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x494)
+#define DDRC_PCFGQOS1_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x498)
+#define DDRC_PCFGWQOS0_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x49c)
+#define DDRC_PCFGWQOS1_0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4a0)
+#define DDRC_SARBASE0(X) (DDRC_IPS_BASE_ADDR(X) + 0xf04)
+#define DDRC_SARSIZE0(X) (DDRC_IPS_BASE_ADDR(X) + 0xf08)
+#define DDRC_SBRCTL(X) (DDRC_IPS_BASE_ADDR(X) + 0xf24)
+#define DDRC_SBRSTAT(X) (DDRC_IPS_BASE_ADDR(X) + 0xf28)
+#define DDRC_SBRWDATA0(X) (DDRC_IPS_BASE_ADDR(X) + 0xf2c)
+#define DDRC_SBRWDATA1(X) (DDRC_IPS_BASE_ADDR(X) + 0xf30)
+#define DDRC_PDCH(X) (DDRC_IPS_BASE_ADDR(X) + 0xf34)
+
+/* SHADOW registers */
+#define DDRC_FREQ1_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x2020)
+#define DDRC_FREQ1_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x2024)
+#define DDRC_FREQ1_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2050)
+#define DDRC_FREQ1_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x2064)
+#define DDRC_FREQ1_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0x20dc)
+#define DDRC_FREQ1_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0x20e0)
+#define DDRC_FREQ1_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0x20e8)
+#define DDRC_FREQ1_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0x20ec)
+#define DDRC_FREQ1_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2100)
+#define DDRC_FREQ1_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x2104)
+#define DDRC_FREQ1_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x2108)
+#define DDRC_FREQ1_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x210c)
+#define DDRC_FREQ1_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x2110)
+#define DDRC_FREQ1_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x2114)
+#define DDRC_FREQ1_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x2118)
+#define DDRC_FREQ1_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x211c)
+#define DDRC_FREQ1_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x2120)
+#define DDRC_FREQ1_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x2124)
+#define DDRC_FREQ1_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x2128)
+#define DDRC_FREQ1_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x212c)
+#define DDRC_FREQ1_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x2130)
+#define DDRC_FREQ1_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x2134)
+#define DDRC_FREQ1_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x2138)
+#define DDRC_FREQ1_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x213C)
+#define DDRC_FREQ1_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x2140)
+#define DDRC_FREQ1_DRAMTMG17(X) (DDRC_IPS_BASE_ADDR(X) + 0x2144)
+#define DDRC_FREQ1_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2180)
+#define DDRC_FREQ1_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x2190)
+#define DDRC_FREQ1_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x2194)
+#define DDRC_FREQ1_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b4)
+#define DDRC_FREQ1_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b8)
+#define DDRC_FREQ1_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x2240)
+
+#define DDRC_FREQ2_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x3020)
+#define DDRC_FREQ2_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x3024)
+#define DDRC_FREQ2_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3050)
+#define DDRC_FREQ2_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x3064)
+#define DDRC_FREQ2_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0x30dc)
+#define DDRC_FREQ2_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0x30e0)
+#define DDRC_FREQ2_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0x30e8)
+#define DDRC_FREQ2_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0x30ec)
+#define DDRC_FREQ2_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3100)
+#define DDRC_FREQ2_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x3104)
+#define DDRC_FREQ2_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x3108)
+#define DDRC_FREQ2_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x310c)
+#define DDRC_FREQ2_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x3110)
+#define DDRC_FREQ2_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x3114)
+#define DDRC_FREQ2_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x3118)
+#define DDRC_FREQ2_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x311c)
+#define DDRC_FREQ2_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x3120)
+#define DDRC_FREQ2_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x3124)
+#define DDRC_FREQ2_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x3128)
+#define DDRC_FREQ2_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x312c)
+#define DDRC_FREQ2_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x3130)
+#define DDRC_FREQ2_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x3134)
+#define DDRC_FREQ2_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x3138)
+#define DDRC_FREQ2_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x313C)
+#define DDRC_FREQ2_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x3140)
+#define DDRC_FREQ2_DRAMTMG17(X) (DDRC_IPS_BASE_ADDR(X) + 0x3144)
+#define DDRC_FREQ2_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3180)
+#define DDRC_FREQ2_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x3190)
+#define DDRC_FREQ2_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x3194)
+#define DDRC_FREQ2_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x31b4)
+#define DDRC_FREQ2_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x31b8)
+#define DDRC_FREQ2_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x3240)
+
+#define DDRC_FREQ3_DERATEEN(X) (DDRC_IPS_BASE_ADDR(X) + 0x4020)
+#define DDRC_FREQ3_DERATEINT(X) (DDRC_IPS_BASE_ADDR(X) + 0x4024)
+#define DDRC_FREQ3_RFSHCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4050)
+#define DDRC_FREQ3_RFSHTMG(X) (DDRC_IPS_BASE_ADDR(X) + 0x4064)
+#define DDRC_FREQ3_INIT3(X) (DDRC_IPS_BASE_ADDR(X) + 0x40dc)
+#define DDRC_FREQ3_INIT4(X) (DDRC_IPS_BASE_ADDR(X) + 0x40e0)
+#define DDRC_FREQ3_INIT6(X) (DDRC_IPS_BASE_ADDR(X) + 0x40e8)
+#define DDRC_FREQ3_INIT7(X) (DDRC_IPS_BASE_ADDR(X) + 0x40ec)
+#define DDRC_FREQ3_DRAMTMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4100)
+#define DDRC_FREQ3_DRAMTMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x4104)
+#define DDRC_FREQ3_DRAMTMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x4108)
+#define DDRC_FREQ3_DRAMTMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x410c)
+#define DDRC_FREQ3_DRAMTMG4(X) (DDRC_IPS_BASE_ADDR(X) + 0x4110)
+#define DDRC_FREQ3_DRAMTMG5(X) (DDRC_IPS_BASE_ADDR(X) + 0x4114)
+#define DDRC_FREQ3_DRAMTMG6(X) (DDRC_IPS_BASE_ADDR(X) + 0x4118)
+#define DDRC_FREQ3_DRAMTMG7(X) (DDRC_IPS_BASE_ADDR(X) + 0x411c)
+#define DDRC_FREQ3_DRAMTMG8(X) (DDRC_IPS_BASE_ADDR(X) + 0x4120)
+#define DDRC_FREQ3_DRAMTMG9(X) (DDRC_IPS_BASE_ADDR(X) + 0x4124)
+#define DDRC_FREQ3_DRAMTMG10(X) (DDRC_IPS_BASE_ADDR(X) + 0x4128)
+#define DDRC_FREQ3_DRAMTMG11(X) (DDRC_IPS_BASE_ADDR(X) + 0x412c)
+#define DDRC_FREQ3_DRAMTMG12(X) (DDRC_IPS_BASE_ADDR(X) + 0x4130)
+#define DDRC_FREQ3_DRAMTMG13(X) (DDRC_IPS_BASE_ADDR(X) + 0x4134)
+#define DDRC_FREQ3_DRAMTMG14(X) (DDRC_IPS_BASE_ADDR(X) + 0x4138)
+#define DDRC_FREQ3_DRAMTMG15(X) (DDRC_IPS_BASE_ADDR(X) + 0x413C)
+#define DDRC_FREQ3_DRAMTMG16(X) (DDRC_IPS_BASE_ADDR(X) + 0x4140)
+
+#define DDRC_FREQ3_ZQCTL0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4180)
+#define DDRC_FREQ3_DFITMG0(X) (DDRC_IPS_BASE_ADDR(X) + 0x4190)
+#define DDRC_FREQ3_DFITMG1(X) (DDRC_IPS_BASE_ADDR(X) + 0x4194)
+#define DDRC_FREQ3_DFITMG2(X) (DDRC_IPS_BASE_ADDR(X) + 0x41b4)
+#define DDRC_FREQ3_DFITMG3(X) (DDRC_IPS_BASE_ADDR(X) + 0x41b8)
+#define DDRC_FREQ3_ODTCFG(X) (DDRC_IPS_BASE_ADDR(X) + 0x4240)
+#define DDRC_DFITMG0_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x2190)
+#define DDRC_DFITMG1_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x2194)
+#define DDRC_DFITMG2_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b4)
+#define DDRC_DFITMG3_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x21b8)
+#define DDRC_ODTCFG_SHADOW(X) (DDRC_IPS_BASE_ADDR(X) + 0x2240)
+
+#define DRC_PERF_MON_BASE_ADDR(X) (0x3d800000 + ((X) * 0x2000000))
+#define DRC_PERF_MON_CNT0_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x0)
+#define DRC_PERF_MON_CNT1_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x4)
+#define DRC_PERF_MON_CNT2_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x8)
+#define DRC_PERF_MON_CNT3_CTL(X) (DRC_PERF_MON_BASE_ADDR(X) + 0xC)
+#define DRC_PERF_MON_CNT0_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x20)
+#define DRC_PERF_MON_CNT1_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x24)
+#define DRC_PERF_MON_CNT2_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x28)
+#define DRC_PERF_MON_CNT3_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x2C)
+#define DRC_PERF_MON_DPCR_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x30)
+#define DRC_PERF_MON_MRR0_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x40)
+#define DRC_PERF_MON_MRR1_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x44)
+#define DRC_PERF_MON_MRR2_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x48)
+#define DRC_PERF_MON_MRR3_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x4C)
+#define DRC_PERF_MON_MRR4_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x50)
+#define DRC_PERF_MON_MRR5_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x54)
+#define DRC_PERF_MON_MRR6_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x58)
+#define DRC_PERF_MON_MRR7_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x5C)
+#define DRC_PERF_MON_MRR8_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x60)
+#define DRC_PERF_MON_MRR9_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x64)
+#define DRC_PERF_MON_MRR10_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x68)
+#define DRC_PERF_MON_MRR11_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x6C)
+#define DRC_PERF_MON_MRR12_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x70)
+#define DRC_PERF_MON_MRR13_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x74)
+#define DRC_PERF_MON_MRR14_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x78)
+#define DRC_PERF_MON_MRR15_DAT(X) (DRC_PERF_MON_BASE_ADDR(X) + 0x7C)
+
+#define dwc_ddrphy_apb_rd(addr) mmio_read_32(IMX_DDRPHY_BASE + 4 * (addr))
+#define dwc_ddrphy_apb_wr(addr, val) mmio_write_32(IMX_DDRPHY_BASE + 4 * (addr), val)
+
+#endif /*IMX_DDRC_H */
diff --git a/plat/imx/imx8m/include/dram.h b/plat/imx/imx8m/include/dram.h
new file mode 100644
index 0000000..ad11a27
--- /dev/null
+++ b/plat/imx/imx8m/include/dram.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DRAM_H
+#define DRAM_H
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <lib/utils_def.h>
+
+#include <ddrc.h>
+#include <platform_def.h>
+
+#define DDRC_LPDDR4 BIT(5)
+#define DDRC_DDR4 BIT(4)
+#define DDRC_DDR3L BIT(0)
+#define DDR_TYPE_MASK U(0x3f)
+#define ACTIVE_RANK_MASK U(0x3)
+
+/* reg & config param */
+struct dram_cfg_param {
+ unsigned int reg;
+ unsigned int val;
+};
+
+struct dram_timing_info {
+ /* umctl2 config */
+ struct dram_cfg_param *ddrc_cfg;
+ unsigned int ddrc_cfg_num;
+ /* ddrphy config */
+ struct dram_cfg_param *ddrphy_cfg;
+ unsigned int ddrphy_cfg_num;
+ /* ddr fsp train info */
+ struct dram_fsp_msg *fsp_msg;
+ unsigned int fsp_msg_num;
+ /* ddr phy trained CSR */
+ struct dram_cfg_param *ddrphy_trained_csr;
+ unsigned int ddrphy_trained_csr_num;
+ /* ddr phy PIE */
+ struct dram_cfg_param *ddrphy_pie;
+ unsigned int ddrphy_pie_num;
+ /* initialized fsp table */
+ unsigned int fsp_table[4];
+};
+
+struct dram_info {
+ int dram_type;
+ unsigned int num_rank;
+ uint32_t num_fsp;
+ int current_fsp;
+ int boot_fsp;
+ bool bypass_mode;
+ struct dram_timing_info *timing_info;
+ /* mr, emr, emr2, emr3, mr11, mr12, mr22, mr14 */
+ uint32_t mr_table[3][8];
+};
+
+extern struct dram_info dram_info;
+
+void dram_info_init(unsigned long dram_timing_base);
+void dram_umctl2_init(struct dram_timing_info *timing);
+void dram_phy_init(struct dram_timing_info *timing);
+
+/* dram retention */
+void dram_enter_retention(void);
+void dram_exit_retention(void);
+
+void dram_clock_switch(unsigned int target_drate, bool bypass_mode);
+
+/* dram frequency change */
+void lpddr4_swffc(struct dram_info *info, unsigned int init_fsp, unsigned int fsp_index);
+void ddr4_swffc(struct dram_info *dram_info, unsigned int pstate);
+
+#endif /* DRAM_H */
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
new file mode 100644
index 0000000..a41030e
--- /dev/null
+++ b/plat/imx/imx8m/include/gpc.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8M_GPC_H
+#define IMX8M_GPC_H
+
+#include <gpc_reg.h>
+
+/* helper macro */
+#define A53_LPM_MASK U(0xF)
+#define A53_LPM_WAIT U(0x5)
+#define A53_LPM_STOP U(0xA)
+#define LPM_MODE(local_state) ((local_state) == PLAT_WAIT_RET_STATE ? A53_LPM_WAIT : A53_LPM_STOP)
+
+#define DSM_MODE_MASK BIT(31)
+#define CORE_WKUP_FROM_GIC (IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
+#define A53_CORE_WUP_SRC(core_id) (1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2))
+#define COREx_PGC_PCR(core_id) (0x800 + (core_id) * 0x40)
+#define COREx_WFI_PDN(core_id) (1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16))
+#define COREx_IRQ_WUP(core_id) ((core_id) < 2 ? (1 << ((core_id) * 2 + 8)) : (1 << ((core_id) * 2 + 20)))
+#define COREx_LPM_PUP(core_id) ((core_id) < 2 ? (1 << ((core_id) * 2 + 9)) : (1 << ((core_id) * 2 + 21)))
+#define SLTx_CFG(n) ((SLT0_CFG + ((n) * 4)))
+#define SLT_COREx_PUP(core_id) (0x2 << ((core_id) * 2))
+
+#define IMR_MASK_ALL 0xffffffff
+
+#define IMX_PD_DOMAIN(name, on) \
+ { \
+ .pwr_req = name##_PWR_REQ, \
+ .pgc_offset = name##_PGC, \
+ .need_sync = false, \
+ .always_on = (on), \
+ }
+
+#define IMX_MIX_DOMAIN(name, on) \
+ { \
+ .pwr_req = name##_PWR_REQ, \
+ .pgc_offset = name##_PGC, \
+ .adb400_sync = name##_ADB400_SYNC, \
+ .adb400_ack = name##_ADB400_ACK, \
+ .need_sync = true, \
+ .always_on = (on), \
+ }
+
+struct imx_pwr_domain {
+ uint32_t pwr_req;
+ uint32_t adb400_sync;
+ uint32_t adb400_ack;
+ uint32_t pgc_offset;
+ bool need_sync;
+ bool always_on;
+};
+
+DECLARE_BAKERY_LOCK(gpc_lock);
+
+/* function declare */
+void imx_gpc_init(void);
+void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
+void imx_set_cpu_pwr_off(unsigned int core_index);
+void imx_set_cpu_pwr_on(unsigned int core_index);
+void imx_set_cpu_lpm(unsigned int core_index, bool pdn);
+void imx_set_cluster_standby(bool retention);
+void imx_set_cluster_powerdown(unsigned int last_core, uint8_t power_state);
+void imx_noc_slot_config(bool pdn);
+void imx_set_sys_wakeup(unsigned int last_core, bool pdn);
+void imx_set_sys_lpm(unsigned last_core, bool retention);
+void imx_set_rbc_count(void);
+void imx_clear_rbc_count(void);
+void imx_anamix_override(bool enter);
+void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on);
+
+#endif /*IMX8M_GPC_H */
diff --git a/plat/imx/imx8m/include/imx8m_caam.h b/plat/imx/imx8m/include/imx8m_caam.h
new file mode 100644
index 0000000..84725b1
--- /dev/null
+++ b/plat/imx/imx8m/include/imx8m_caam.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, NXP. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8M_CAAM_H
+#define IMX8M_CAAM_H
+
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+
+#define CAAM_JR0MID (IMX_CAAM_BASE + 0x10)
+#define CAAM_JR1MID (IMX_CAAM_BASE + 0x18)
+#define CAAM_JR2MID (IMX_CAAM_BASE + 0x20)
+#define CAAM_NS_MID (0x1)
+
+#define JR0_BASE (IMX_CAAM_BASE + 0x1000)
+
+#define SM_P0_PERM (JR0_BASE + 0xa04)
+#define SM_P0_SMAG2 (JR0_BASE + 0xa08)
+#define SM_P0_SMAG1 (JR0_BASE + 0xa0c)
+#define SM_CMD (JR0_BASE + 0xbe4)
+
+/* secure memory command */
+#define SMC_PAGE_SHIFT 16
+#define SMC_PART_SHIFT 8
+
+#define SMC_CMD_ALLOC_PAGE 0x01 /* allocate page to this partition */
+#define SMC_CMD_DEALLOC_PART 0x03 /* deallocate partition */
+
+void imx8m_caam_init(void);
+
+#endif /* IMX8M_CAAM_H */
diff --git a/plat/imx/imx8m/include/imx8m_csu.h b/plat/imx/imx8m/include/imx8m_csu.h
new file mode 100644
index 0000000..dc634ed
--- /dev/null
+++ b/plat/imx/imx8m/include/imx8m_csu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_CSU_H
+#define IMX_CSU_H
+
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+
+#define CSU_SEC_LEVEL_0 0xff
+#define CSU_SEC_LEVEL_1 0xbb
+#define CSU_SEC_LEVEL_2 0x3f
+#define CSU_SEC_LEVEL_3 0x3b
+#define CSU_SEC_LEVEL_4 0x33
+#define CSU_SEC_LEVEL_5 0x22
+#define CSU_SEC_LEVEL_6 0x03
+#define CSU_SEC_LEVEL_7 0x0
+
+#define LOCKED 0x1
+#define UNLOCKED 0x0
+
+#define CSLx_REG(x) (IMX_CSU_BASE + ((x) / 2) * 4)
+#define CSLx_LOCK(x) ((0x1 << (((x) % 2) * 16 + 8)))
+#define CSLx_CFG(x, n) ((x) << (((n) % 2) * 16))
+
+#define CSU_HP_REG(x) (IMX_CSU_BASE + ((x) / 16) * 4 + 0x200)
+#define CSU_HP_LOCK(x) ((0x1 << (((x) % 16) * 2 + 1)))
+#define CSU_HP_CFG(x, n) ((x) << (((n) % 16) * 2))
+
+#define CSU_SA_REG(x) (IMX_CSU_BASE + 0x218)
+#define CSU_SA_LOCK(x) ((0x1 << (((x) % 16) * 2 + 1)))
+#define CSU_SA_CFG(x, n) ((x) << (((n) % 16) * 2))
+
+#define CSU_HPCONTROL_REG(x) (IMX_CSU_BASE + (((x) / 16) * 4) + 0x358)
+#define CSU_HPCONTROL_LOCK(x) ((0x1 << (((x) % 16) * 2 + 1)))
+#define CSU_HPCONTROL_CFG(x, n) ((x) << (((n) % 16) * 2))
+
+enum csu_cfg_type {
+ CSU_INVALID,
+ CSU_CSL,
+ CSU_HP,
+ CSU_SA,
+ CSU_HPCONTROL,
+};
+
+struct imx_csu_cfg {
+ enum csu_cfg_type type;
+ uint16_t idx;
+ uint16_t lock : 1;
+ uint16_t csl_level : 8;
+ uint16_t hp : 1;
+ uint16_t sa : 1;
+ uint16_t hpctrl : 1;
+};
+
+#define CSU_CSLx(i, level, lk) \
+ {CSU_CSL, .idx = (i), .csl_level = (level), .lock = (lk),}
+
+#define CSU_HPx(i, val, lk) \
+ {CSU_HP, .idx = (i), .hp = (val), .lock = (lk), }
+
+#define CSU_SA(i, val, lk) \
+ {CSU_SA, .idx = (i), .sa = (val), .lock = (lk), }
+
+#define CSU_HPCTRL(i, val, lk) \
+ {CSU_HPCONTROL, .idx = (i), .hpctrl = (val), .lock = (lk), }
+
+void imx_csu_init(const struct imx_csu_cfg *csu_cfg);
+
+#endif /* IMX_CSU_H */
diff --git a/plat/imx/imx8m/include/imx8m_measured_boot.h b/plat/imx/imx8m/include/imx8m_measured_boot.h
new file mode 100644
index 0000000..2ec0c46
--- /dev/null
+++ b/plat/imx/imx8m/include/imx8m_measured_boot.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2022, Linaro
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8M_MEASURED_BOOT_H
+#define IMX8M_MEASURED_BOOT_H
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+
+int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr);
+
+#endif /* IMX8M_MEASURED_BOOT_H */
diff --git a/plat/imx/imx8m/include/imx8m_psci.h b/plat/imx/imx8m/include/imx8m_psci.h
new file mode 100644
index 0000000..7d14d11
--- /dev/null
+++ b/plat/imx/imx8m/include/imx8m_psci.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8M_PSCI_H
+#define IMX8M_PSCI_H
+
+#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+int imx_pwr_domain_on(u_register_t mpidr);
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state);
+void imx_pwr_domain_off(const psci_power_state_t *target_state);
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint);
+void imx_cpu_standby(plat_local_state_t cpu_state);
+void imx_domain_suspend(const psci_power_state_t *target_state);
+void imx_domain_suspend_finish(const psci_power_state_t *target_state);
+void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state);
+int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie);
+
+#endif /* IMX8M_PSCI_H */
diff --git a/plat/imx/imx8m/include/imx_aipstz.h b/plat/imx/imx8m/include/imx_aipstz.h
new file mode 100644
index 0000000..7616862
--- /dev/null
+++ b/plat/imx/imx8m/include/imx_aipstz.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_AIPSTZ_H
+#define IMX_AIPSTZ_H
+
+#include <lib/utils_def.h>
+
+#define AIPSTZ_MPR0 U(0x0)
+#define AIPSTZ_MPR1 U(0x4)
+
+#define AIPSTZ_OPACR_NUM U(0x5)
+#define OPACR_OFFSET(i) U((i) * 4 + 0x40)
+
+struct aipstz_cfg {
+ uintptr_t base;
+ uint32_t mpr0;
+ uint32_t mpr1;
+ uint32_t opacr[AIPSTZ_OPACR_NUM];
+};
+
+void imx_aipstz_init(const struct aipstz_cfg *aipstz_cfg);
+
+#endif /* IMX_AIPSTZ_H */
diff --git a/plat/imx/imx8m/include/imx_rdc.h b/plat/imx/imx8m/include/imx_rdc.h
new file mode 100644
index 0000000..a6e10a7
--- /dev/null
+++ b/plat/imx/imx8m/include/imx_rdc.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019-2022 NXP. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX_RDC_H
+#define IMX_RDC_H
+
+#include <lib/utils_def.h>
+
+#include <imx_sec_def.h>
+#include <platform_def.h>
+
+#define MDAn(x) (IMX_RDC_BASE + 0x200 + (x) * 4)
+#define PDAPn(x) (IMX_RDC_BASE + 0x400 + (x) * 4)
+#define MRSAn(x) (IMX_RDC_BASE + 0x800 + (x) * 0x10)
+#define MREAn(x) (IMX_RDC_BASE + 0x804 + (x) * 0x10)
+#define MRCn(x) (IMX_RDC_BASE + 0x808 + (x) * 0x10)
+
+#define LCK BIT(31)
+#define SREQ BIT(30)
+#define ENA BIT(30)
+
+#define DID0 U(0x0)
+#define DID1 U(0x1)
+#define DID2 U(0x2)
+#define DID3 U(0x3)
+
+#define D3R BIT(7)
+#define D3W BIT(6)
+#define D2R BIT(5)
+#define D2W BIT(4)
+#define D1R BIT(3)
+#define D1W BIT(2)
+#define D0R BIT(1)
+#define D0W BIT(0)
+
+union rdc_setting {
+ uint32_t rdc_mda; /* Master Domain Assignment */
+ uint32_t rdc_pdap; /* Peripheral Domain Access Permissions */
+ uint32_t rdc_mem_region[3]; /* Memory Region Access Control */
+};
+
+enum rdc_type {
+ RDC_INVALID,
+ RDC_MDA,
+ RDC_PDAP,
+ RDC_MEM_REGION,
+};
+
+struct imx_rdc_cfg {
+ enum rdc_type type; /* config type Master, Peripheral or Memory region */
+ int index;
+ union rdc_setting setting;
+};
+
+#define RDC_MDAn(i, mda) \
+ {RDC_MDA, (i), .setting.rdc_mda = (mda), }
+#define RDC_PDAPn(i, pdap) \
+ {RDC_PDAP, (i), .setting.rdc_pdap = (pdap), }
+
+#define RDC_MEM_REGIONn(i, msa, mea, mrc) \
+ { RDC_MEM_REGION, (i), \
+ .setting.rdc_mem_region[0] = (msa), \
+ .setting.rdc_mem_region[1] = (mea), \
+ .setting.rdc_mem_region[2] = (mrc), \
+ }
+
+void imx_rdc_init(const struct imx_rdc_cfg *cfg);
+
+#endif /* IMX_RDC_H */
+
diff --git a/plat/imx/imx8qm/imx8qm_bl31_setup.c b/plat/imx/imx8qm/imx8qm_bl31_setup.c
new file mode 100644
index 0000000..68eb534
--- /dev/null
+++ b/plat/imx/imx8qm/imx8qm_bl31_setup.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <context.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/console.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <imx8qm_pads.h>
+#include <imx8_iomux.h>
+#include <imx8_lpuart.h>
+#include <plat_imx8.h>
+#include <sci/sci.h>
+#include <sec_rsrc.h>
+
+static const unsigned long BL31_COHERENT_RAM_START = BL_COHERENT_RAM_BASE;
+static const unsigned long BL31_COHERENT_RAM_END = BL_COHERENT_RAM_END;
+static const unsigned long BL31_RO_START = BL_CODE_BASE;
+static const unsigned long BL31_RO_END = BL_CODE_END;
+static const unsigned long BL31_RW_END = BL_END;
+
+IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START);
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \
+ (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \
+ (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
+ (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \
+ (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT))
+
+#if defined(IMX_USE_UART0)
+#define IMX_RES_UART SC_R_UART_0
+#define IMX_PAD_UART_RX SC_P_UART0_RX
+#define IMX_PAD_UART_TX SC_P_UART0_TX
+#define IMX_PAD_UART_RTS_B SC_P_UART0_RTS_B
+#define IMX_PAD_UART_CTS_B SC_P_UART0_CTS_B
+#elif defined(IMX_USE_UART1)
+#define IMX_RES_UART SC_R_UART_1
+#define IMX_PAD_UART_RX SC_P_UART1_RX
+#define IMX_PAD_UART_TX SC_P_UART1_TX
+#define IMX_PAD_UART_RTS_B SC_P_UART1_RTS_B
+#define IMX_PAD_UART_CTS_B SC_P_UART1_CTS_B
+#else
+#error "Provide proper UART number in IMX_DEBUG_UART"
+#endif
+
+const static int imx8qm_cci_map[] = {
+ CLUSTER0_CCI_SLVAE_IFACE,
+ CLUSTER1_CCI_SLVAE_IFACE
+};
+
+static const mmap_region_t imx_mmap[] = {
+ MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW),
+ {0}
+};
+
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+
+ return spsr;
+}
+
+#if DEBUG_CONSOLE_A53
+static void lpuart32_serial_setbrg(unsigned int base, int baudrate)
+{
+ unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr;
+ unsigned int diff1, diff2, tmp, rate;
+
+ if (baudrate == 0)
+ panic();
+
+ sc_pm_get_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate);
+
+ baud_diff = baudrate;
+ osr = 0;
+ sbr = 0;
+ for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+ tmp_sbr = (rate / (baudrate * tmp_osr));
+ if (tmp_sbr == 0)
+ tmp_sbr = 1;
+
+ /* calculate difference in actual baud w/ current values */
+ diff1 = rate / (tmp_osr * tmp_sbr) - baudrate;
+ diff2 = rate / (tmp_osr * (tmp_sbr + 1));
+
+ /* select best values between sbr and sbr+1 */
+ if (diff1 > (baudrate - diff2)) {
+ diff1 = baudrate - diff2;
+ tmp_sbr++;
+ }
+
+ if (diff1 <= baud_diff) {
+ baud_diff = diff1;
+ osr = tmp_osr;
+ sbr = tmp_sbr;
+ }
+ }
+
+ tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD);
+
+ if ((osr > 3) && (osr < 8))
+ tmp |= LPUART_BAUD_BOTHEDGE_MASK;
+
+ tmp &= ~LPUART_BAUD_OSR_MASK;
+ tmp |= LPUART_BAUD_OSR(osr - 1);
+ tmp &= ~LPUART_BAUD_SBR_MASK;
+ tmp |= LPUART_BAUD_SBR(sbr);
+
+ /* explicitly disable 10 bit mode & set 1 stop bit */
+ tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp);
+}
+
+static int lpuart32_serial_init(unsigned int base)
+{
+ unsigned int tmp;
+
+ /* disable TX & RX before enabling clocks */
+ tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+ tmp &= ~(CTRL_TE | CTRL_RE);
+ mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0);
+ mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE));
+
+ mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0);
+
+ /* provide data bits, parity, stop bit, etc */
+ lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE);
+
+ /* eight data bits no parity bit */
+ tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+ tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK);
+ mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+ mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+ mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A);
+
+ return 0;
+}
+#endif
+
+void mx8_partition_resources(void)
+{
+ sc_rm_pt_t secure_part, os_part;
+ sc_rm_mr_t mr, mr_record = 64;
+ sc_faddr_t start, end;
+ bool owned, owned2;
+ sc_err_t err;
+ int i;
+
+ err = sc_rm_get_partition(ipc_handle, &secure_part);
+
+ err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false,
+ false, false, false);
+
+ err = sc_rm_set_parent(ipc_handle, os_part, secure_part);
+
+ /* set secure resources to NOT-movable */
+ for (i = 0; i < ARRAY_SIZE(secure_rsrcs); i++) {
+ err = sc_rm_set_resource_movable(ipc_handle, secure_rsrcs[i],
+ secure_rsrcs[i], false);
+ if (err)
+ ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+ secure_rsrcs[i], err);
+ }
+
+ owned = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_0_PID0);
+ if (owned) {
+ err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0,
+ SC_R_M4_0_PID0, false);
+ if (err)
+ ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+ SC_R_M4_0_PID0, err);
+ }
+
+ owned2 = sc_rm_is_resource_owned(ipc_handle, SC_R_M4_1_PID0);
+ if (owned2) {
+ err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0,
+ SC_R_M4_1_PID0, false);
+ if (err)
+ ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+ SC_R_M4_1_PID0, err);
+ }
+ /* move all movable resources and pins to non-secure partition */
+ err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true);
+ if (err)
+ ERROR("sc_rm_move_all: %u\n", err);
+
+ /* iterate through peripherals to give NS OS part access */
+ for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) {
+ err = sc_rm_set_peripheral_permissions(ipc_handle, ns_access_allowed[i],
+ os_part, SC_RM_PERM_FULL);
+ if (err)
+ ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \
+ ret %u\n", ns_access_allowed[i], err);
+ }
+
+ if (owned) {
+ err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_0_PID0,
+ SC_R_M4_0_PID0, true);
+ if (err)
+ ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+ SC_R_M4_0_PID0, err);
+ err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_0_PID0);
+ if (err)
+ ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n",
+ SC_R_M4_0_PID0, err);
+ }
+ if (owned2) {
+ err = sc_rm_set_resource_movable(ipc_handle, SC_R_M4_1_PID0,
+ SC_R_M4_1_PID0, true);
+ if (err)
+ ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+ SC_R_M4_1_PID0, err);
+ err = sc_rm_assign_resource(ipc_handle, os_part, SC_R_M4_1_PID0);
+ if (err)
+ ERROR("sc_rm_assign_resource: rsrc %u, ret %u\n",
+ SC_R_M4_1_PID0, err);
+ }
+
+ /*
+ * sc_rm_set_peripheral_permissions
+ * sc_rm_set_memreg_permissions
+ * sc_rm_set_pin_movable
+ */
+
+ for (mr = 0; mr < 64; mr++) {
+ owned = sc_rm_is_memreg_owned(ipc_handle, mr);
+ if (owned) {
+ err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end);
+ if (err)
+ ERROR("Memreg get info failed, %u\n", mr);
+ NOTICE("Memreg %u 0x%" PRIx64 " -- 0x%" PRIx64 "\n", mr, start, end);
+ if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) {
+ mr_record = mr; /* Record the mr for ATF running */
+ } else {
+ err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+ if (err)
+ ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 ", \
+ err %d\n", start, end, err);
+ }
+ }
+ }
+
+ if (mr_record != 64) {
+ err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end);
+ if (err)
+ ERROR("Memreg get info failed, %u\n", mr_record);
+ if ((BL31_LIMIT - 1) < end) {
+ err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end);
+ if (err)
+ ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ (sc_faddr_t)BL31_LIMIT, end);
+ err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+ if (err)
+ ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ (sc_faddr_t)BL31_LIMIT, end);
+ }
+
+ if (start < (BL31_BASE - 1)) {
+ err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1);
+ if (err)
+ ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ start, (sc_faddr_t)BL31_BASE - 1);
+ err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+ if (err)
+ ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ start, (sc_faddr_t)BL31_BASE - 1);
+ }
+ }
+
+ if (err)
+ NOTICE("Partitioning Failed\n");
+ else
+ NOTICE("Non-secure Partitioning Succeeded\n");
+
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+#if DEBUG_CONSOLE
+ static console_t console;
+#endif
+ if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
+ panic();
+
+#if DEBUG_CONSOLE_A53
+ sc_pm_set_resource_power_mode(ipc_handle, IMX_RES_UART,
+ SC_PM_PW_MODE_ON);
+ sc_pm_clock_rate_t rate = 80000000;
+ sc_pm_set_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate);
+ sc_pm_clock_enable(ipc_handle, IMX_RES_UART, 2, true, false);
+
+ /* configure UART pads */
+ sc_pad_set(ipc_handle, IMX_PAD_UART_RX, UART_PAD_CTRL);
+ sc_pad_set(ipc_handle, IMX_PAD_UART_TX, UART_PAD_CTRL);
+ sc_pad_set(ipc_handle, IMX_PAD_UART_RTS_B, UART_PAD_CTRL);
+ sc_pad_set(ipc_handle, IMX_PAD_UART_CTS_B, UART_PAD_CTRL);
+ lpuart32_serial_init(IMX_BOOT_UART_BASE);
+#endif
+
+#if DEBUG_CONSOLE
+ console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+#endif
+
+ /* turn on MU1 for non-secure OS/Hypervisor */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
+ /* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT_LPCG_BASE, mmio_read_32(IMX_GPT_LPCG_BASE) | (1 << 25));
+
+ /*
+ * create new partition for non-secure OS/Hypervisor
+ * uses global structs defined in sec_rsrc.h
+ */
+ mx8_partition_resources();
+
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ /* init the first cluster's cci slave interface */
+ cci_init(PLAT_CCI_BASE, imx8qm_cci_map, PLATFORM_CLUSTER_COUNT);
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+void bl31_plat_arch_setup(void)
+{
+ unsigned long ro_start = BL31_RO_START;
+ unsigned long ro_size = BL31_RO_END - BL31_RO_START;
+ unsigned long rw_start = BL31_RW_START;
+ unsigned long rw_size = BL31_RW_END - BL31_RW_START;
+#if USE_COHERENT_MEM
+ unsigned long coh_start = BL31_COHERENT_RAM_START;
+ unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START;
+#endif
+
+ mmap_add_region(ro_start, ro_start, ro_size,
+ MT_RO | MT_MEMORY | MT_SECURE);
+ mmap_add_region(rw_start, rw_start, rw_size,
+ MT_RW | MT_MEMORY | MT_SECURE);
+ mmap_add(imx_mmap);
+
+#if USE_COHERENT_MEM
+ mmap_add_region(coh_start, coh_start, coh_size,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+ /* setup xlat table */
+ init_xlat_tables();
+ /* enable the MMU */
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ plat_gic_driver_init();
+ plat_gic_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ if (type == SECURE)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ return;
+}
diff --git a/plat/imx/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c
new file mode 100644
index 0000000..bdba37c
--- /dev/null
+++ b/plat/imx/imx8qm/imx8qm_psci.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <plat_imx8.h>
+#include <sci/sci.h>
+
+#include "../../common/sci/imx8_mu.h"
+
+#define CORE_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+const static int ap_core_index[PLATFORM_CORE_COUNT] = {
+ SC_R_A53_0, SC_R_A53_1, SC_R_A53_2,
+ SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
+};
+
+/* save gic dist/redist context when GIC is poewr down */
+static struct plat_gic_ctx imx_gicv3_ctx;
+static unsigned int gpt_lpcg, gpt_reg[2];
+
+static void imx_enable_irqstr_wakeup(void)
+{
+ uint32_t irq_mask;
+ gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx;
+
+ /* put IRQSTR into ON mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* enable the irqsteer to handle wakeup irq */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1);
+ for (int i = 0; i < 15; i++) {
+ irq_mask = dist_ctx->gicd_isenabler[i];
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
+ }
+
+ /* set IRQSTR low power mode */
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
+ else
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+static void imx_disable_irqstr_wakeup(void)
+{
+ /* put IRQSTR into ON from STBY mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* disable the irqsteer */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0);
+ for (int i = 0; i < 16; i++)
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0);
+
+ /* put IRQSTR into OFF mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+ int ret = PSCI_E_SUCCESS;
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ sc_pm_set_resource_power_mode(ipc_handle, cluster_id == 0 ?
+ SC_R_A53 : SC_R_A72, SC_PM_PW_MODE_ON);
+
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+
+ if (sc_pm_set_resource_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
+ ERROR("core %d power on failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id);
+ ret = PSCI_E_INTERN_FAIL;
+ }
+
+ if (sc_pm_cpu_start(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ true, BL31_BASE) != SC_ERR_NONE) {
+ ERROR("boot core %d failed!\n", cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id);
+ ret = PSCI_E_INTERN_FAIL;
+ }
+
+ return ret;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ uint64_t mpidr = read_mpidr_el1();
+
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ plat_gic_pcpu_init();
+ plat_gic_cpuif_enable();
+}
+
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ plat_gic_cpuif_disable();
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE);
+
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+ cci_disable_snoop_dvm_reqs(cluster_id);
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ }
+ printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id);
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ plat_gic_cpuif_disable();
+ sc_pm_set_cpu_resume(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ true, BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+ } else {
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+ }
+
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ }
+
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ plat_gic_cpuif_disable();
+
+ /* save gic context */
+ plat_gic_save(cpu_id, &imx_gicv3_ctx);
+ /* enable the irqsteer for wakeup */
+ imx_enable_irqstr_wakeup();
+
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ /* Put GIC in LP mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
+ /* Save GPT clock and registers, then turn off its power */
+ gpt_lpcg = mmio_read_32(IMX_GPT_LPCG_BASE);
+ gpt_reg[0] = mmio_read_32(IMX_GPT_BASE);
+ gpt_reg[1] = mmio_read_32(IMX_GPT_BASE + 0x4);
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
+ sc_pm_set_cpu_resume(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ true, BL31_BASE);
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ else
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ }
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ /* check the system level status */
+ if (is_local_state_retn(SYSTEM_PWR_STATE(target_state))) {
+ MU_Resume(SC_IPC_BASE);
+
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+
+ /* Put GIC/IRQSTR back to high power mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON);
+
+ /* Turn GPT power and restore its clock and registers */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT_BASE, gpt_reg[0]);
+ mmio_write_32(IMX_GPT_BASE + 0x4, gpt_reg[1]);
+ mmio_write_32(IMX_GPT_LPCG_BASE, gpt_lpcg);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
+
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
+
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ /* restore gic context */
+ plat_gic_restore(cpu_id, &imx_gicv3_ctx);
+ /* disable the irqsteer wakeup */
+ imx_disable_irqstr_wakeup();
+
+ plat_gic_cpuif_enable();
+ }
+
+ /* check the cluster level power status */
+ if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ if (cluster_id == 1)
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+ }
+
+ /* check the core level power status */
+ if (is_local_state_off(CORE_PWR_STATE(target_state))) {
+ sc_pm_set_cpu_resume(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ false, BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + PLATFORM_CLUSTER0_CORE_COUNT * cluster_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+ plat_gic_cpuif_enable();
+ } else {
+ write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+ isb();
+ }
+}
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+ return PSCI_E_SUCCESS;
+}
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .validate_power_state = imx_validate_power_state,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .system_off = imx_system_off,
+ .system_reset = imx_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ imx_mailbox_init(sec_entrypoint);
+ *psci_ops = &imx_plat_psci_ops;
+
+ /* make sure system sources power ON in low power mode by default */
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_ON);
+
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+
+ return 0;
+}
diff --git a/plat/imx/imx8qm/include/platform_def.h b/plat/imx/imx8qm/include/platform_def.h
new file mode 100644
index 0000000..671c77f
--- /dev/null
+++ b/plat/imx/imx8qm/include/platform_def.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0X400
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(2)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \
+ PLATFORM_CLUSTER1_CORE_COUNT)
+
+#define IMX_PWR_LVL0 MPIDR_AFFLVL0
+#define IMX_PWR_LVL1 MPIDR_AFFLVL1
+#define IMX_PWR_LVL2 MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define BL31_BASE 0x80000000
+#define BL31_LIMIT 0x80020000
+
+#define PLAT_GICD_BASE 0x51a00000
+#define PLAT_GICR_BASE 0x51b00000
+#define PLAT_CCI_BASE 0x52090000
+#define CLUSTER0_CCI_SLVAE_IFACE 3
+#define CLUSTER1_CCI_SLVAE_IFACE 4
+
+/* UART */
+#if defined(IMX_USE_UART0)
+#define IMX_BOOT_UART_BASE 0x5a060000
+#elif defined(IMX_USE_UART1)
+#define IMX_BOOT_UART_BASE 0x5a070000
+#else
+#error "Provide proper UART number in IMX_DEBUG_UART"
+#endif
+
+#define IMX_BOOT_UART_BAUDRATE 115200
+#define IMX_BOOT_UART_CLK_IN_HZ 24000000
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT__CRASH_UART_CLK_IN_HZ 24000000
+#define IMX_CONSOLE_BAUDRATE 115200
+
+#define SC_IPC_BASE 0x5d1b0000
+#define IMX_GPT_LPCG_BASE 0x5d540000
+#define IMX_GPT_BASE 0x5d140000
+#define IMX_WUP_IRQSTR_BASE 0x51090000
+#define IMX_REG_BASE 0x50000000
+#define IMX_REG_SIZE 0x10000000
+
+#define COUNTER_FREQUENCY 8000000 /* 8MHz */
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET 0x80020000
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 12
+
+#define DEBUG_CONSOLE_A53 DEBUG_CONSOLE
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/imx/imx8qm/include/sec_rsrc.h b/plat/imx/imx8qm/include/sec_rsrc.h
new file mode 100644
index 0000000..d16d051
--- /dev/null
+++ b/plat/imx/imx8qm/include/sec_rsrc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* resources that are going to stay in secure partition */
+sc_rsrc_t secure_rsrcs[] = {
+ SC_R_MU_0A,
+ SC_R_A53,
+ SC_R_A53_0,
+ SC_R_A53_1,
+ SC_R_A53_2,
+ SC_R_A53_3,
+ SC_R_A72,
+ SC_R_A72_0,
+ SC_R_A72_1,
+ SC_R_GIC,
+ SC_R_GIC_SMMU,
+ SC_R_CCI,
+ SC_R_SYSTEM,
+ SC_R_IRQSTR_SCU2,
+ SC_R_GPT_0
+};
+
+/* resources that have register access for non-secure domain */
+sc_rsrc_t ns_access_allowed[] = {
+ SC_R_GIC,
+ SC_R_GIC_SMMU,
+ SC_R_CCI,
+ SC_R_GPT_0
+};
diff --git a/plat/imx/imx8qm/platform.mk b/plat/imx/imx8qm/platform.mk
new file mode 100644
index 0000000..c57edbe
--- /dev/null
+++ b/plat/imx/imx8qm/platform.mk
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Iplat/imx/imx8qm/include \
+ -Iplat/imx/common/include \
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/lpuart_console.S \
+ plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8qm/imx8qm_bl31_setup.c \
+ plat/imx/imx8qm/imx8qm_psci.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx8_psci.c \
+ plat/imx/common/imx_sip_svc.c \
+ plat/imx/common/imx_sip_handler.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ drivers/arm/cci/cci.c \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${IMX_GIC_SOURCES} \
+
+include plat/imx/common/sci/sci_api.mk
+
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+ERRATA_A72_859971 := 1
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+IMX_DEBUG_UART ?= 0
+$(eval $(call add_define,IMX_USE_UART${IMX_DEBUG_UART}))
+
+DEBUG_CONSOLE ?= 0
+$(eval $(call add_define,DEBUG_CONSOLE))
diff --git a/plat/imx/imx8qx/imx8qx_bl31_setup.c b/plat/imx/imx8qx/imx8qx_bl31_setup.c
new file mode 100644
index 0000000..1da8d29
--- /dev/null
+++ b/plat/imx/imx8qx/imx8qx_bl31_setup.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/cci.h>
+#include <drivers/console.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <imx8qx_pads.h>
+#include <imx8_iomux.h>
+#include <imx8_lpuart.h>
+#include <plat_imx8.h>
+#include <sci/sci.h>
+#include <sec_rsrc.h>
+
+static const unsigned long BL31_COHERENT_RAM_START = BL_COHERENT_RAM_BASE;
+static const unsigned long BL31_COHERENT_RAM_END = BL_COHERENT_RAM_END;
+static const unsigned long BL31_RO_START = BL_CODE_BASE;
+static const unsigned long BL31_RO_END = BL_CODE_END;
+static const unsigned long BL31_RW_END = BL_END;
+
+IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START);
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* Default configuration for i.MX8QM/QXP MEK */
+#if defined(IMX_USE_UART0)
+#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \
+ (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \
+ (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
+ (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \
+ (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT))
+#define IMX_RES_UART SC_R_UART_0
+#define IMX_PAD_UART_RX SC_P_UART0_RX
+#define IMX_PAD_UART_TX SC_P_UART0_TX
+
+/*
+ * On Toradex Colibri i.MX8QXP UART3 on the FLEXCAN2.
+ * Use custom pad control for this
+ */
+#elif defined(IMX_USE_UART3)
+/*
+ * FLEXCAN2_RX/TX pads are muxed to ADMA_UART3_RX/TX,
+ * For ref:
+ * 000b - ADMA_FLEXCAN2_RX
+ * 001b - ADMA_SAI3_RXD
+ * 010b - ADMA_UART3_RX
+ * 011b - ADMA_SAI1_RXFS
+ * 100b - LSIO_GPIO1_IO19
+ */
+#define UART_PAD_CTRL (PADRING_IFMUX_EN_MASK | PADRING_GP_EN_MASK | \
+ (SC_PAD_CONFIG_OUT_IN << PADRING_CONFIG_SHIFT) | \
+ (2U << PADRING_IFMUX_SHIFT) | \
+ (SC_PAD_ISO_OFF << PADRING_LPCONFIG_SHIFT) | \
+ (SC_PAD_28FDSOI_DSE_DV_LOW << PADRING_DSE_SHIFT) | \
+ (SC_PAD_28FDSOI_PS_PD << PADRING_PULL_SHIFT))
+#define IMX_RES_UART SC_R_UART_3
+#define IMX_PAD_UART_RX SC_P_FLEXCAN2_RX
+#define IMX_PAD_UART_TX SC_P_FLEXCAN2_TX
+#else
+#error "Provide proper UART configuration in IMX_DEBUG_UART"
+#endif
+
+static const mmap_region_t imx_mmap[] = {
+ MAP_REGION_FLAT(IMX_REG_BASE, IMX_REG_SIZE, MT_DEVICE | MT_RW),
+ {0}
+};
+
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned long mode;
+ uint32_t spsr;
+
+ /* figure out what mode we enter the non-secure world */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+#if DEBUG_CONSOLE_A35
+static void lpuart32_serial_setbrg(unsigned int base, int baudrate)
+{
+ unsigned int sbr, osr, baud_diff, tmp_osr, tmp_sbr;
+ unsigned int diff1, diff2, tmp, rate;
+
+ if (baudrate == 0)
+ panic();
+
+ sc_pm_get_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate);
+
+ baud_diff = baudrate;
+ osr = 0;
+ sbr = 0;
+ for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+ tmp_sbr = (rate / (baudrate * tmp_osr));
+ if (tmp_sbr == 0)
+ tmp_sbr = 1;
+
+ /* calculate difference in actual baud w/ current values */
+ diff1 = rate / (tmp_osr * tmp_sbr) - baudrate;
+ diff2 = rate / (tmp_osr * (tmp_sbr + 1));
+
+ /* select best values between sbr and sbr+1 */
+ if (diff1 > (baudrate - diff2)) {
+ diff1 = baudrate - diff2;
+ tmp_sbr++;
+ }
+
+ if (diff1 <= baud_diff) {
+ baud_diff = diff1;
+ osr = tmp_osr;
+ sbr = tmp_sbr;
+ }
+ }
+
+ tmp = mmio_read_32(IMX_BOOT_UART_BASE + BAUD);
+
+ if ((osr > 3) && (osr < 8))
+ tmp |= LPUART_BAUD_BOTHEDGE_MASK;
+
+ tmp &= ~LPUART_BAUD_OSR_MASK;
+ tmp |= LPUART_BAUD_OSR(osr - 1);
+ tmp &= ~LPUART_BAUD_SBR_MASK;
+ tmp |= LPUART_BAUD_SBR(sbr);
+
+ /* explicitly disable 10 bit mode & set 1 stop bit */
+ tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + BAUD, tmp);
+}
+
+static int lpuart32_serial_init(unsigned int base)
+{
+ unsigned int tmp;
+
+ /* disable TX & RX before enabling clocks */
+ tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+ tmp &= ~(CTRL_TE | CTRL_RE);
+ mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + MODIR, 0);
+ mmio_write_32(IMX_BOOT_UART_BASE + FIFO, ~(FIFO_TXFE | FIFO_RXFE));
+
+ mmio_write_32(IMX_BOOT_UART_BASE + MATCH, 0);
+
+ /* provide data bits, parity, stop bit, etc */
+ lpuart32_serial_setbrg(base, IMX_BOOT_UART_BAUDRATE);
+
+ /* eight data bits no parity bit */
+ tmp = mmio_read_32(IMX_BOOT_UART_BASE + CTRL);
+ tmp &= ~(LPUART_CTRL_PE_MASK | LPUART_CTRL_PT_MASK | LPUART_CTRL_M_MASK);
+ mmio_write_32(IMX_BOOT_UART_BASE + CTRL, tmp);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + CTRL, CTRL_RE | CTRL_TE);
+
+ mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+ mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x55);
+ mmio_write_32(IMX_BOOT_UART_BASE + DATA, 0x0A);
+
+ return 0;
+}
+#endif
+
+void imx8_partition_resources(void)
+{
+ sc_rm_pt_t secure_part, os_part;
+ sc_rm_mr_t mr, mr_record = 64;
+ sc_faddr_t start, end;
+ sc_err_t err;
+ bool owned;
+ int i;
+
+ err = sc_rm_get_partition(ipc_handle, &secure_part);
+ if (err)
+ ERROR("sc_rm_get_partition failed: %u\n", err);
+
+ err = sc_rm_partition_alloc(ipc_handle, &os_part, false, false,
+ false, false, false);
+ if (err)
+ ERROR("sc_rm_partition_alloc failed: %u\n", err);
+
+ err = sc_rm_set_parent(ipc_handle, os_part, secure_part);
+ if (err)
+ ERROR("sc_rm_set_parent: %u\n", err);
+
+ /* set secure resources to NOT-movable */
+ for (i = 0; i < (ARRAY_SIZE(secure_rsrcs)); i++) {
+ err = sc_rm_set_resource_movable(ipc_handle,
+ secure_rsrcs[i], secure_rsrcs[i], false);
+ if (err)
+ ERROR("sc_rm_set_resource_movable: rsrc %u, ret %u\n",
+ secure_rsrcs[i], err);
+ }
+
+ /* move all movable resources and pins to non-secure partition */
+ err = sc_rm_move_all(ipc_handle, secure_part, os_part, true, true);
+ if (err)
+ ERROR("sc_rm_move_all: %u\n", err);
+
+ /* iterate through peripherals to give NS OS part access */
+ for (i = 0; i < ARRAY_SIZE(ns_access_allowed); i++) {
+ err = sc_rm_set_peripheral_permissions(ipc_handle,
+ ns_access_allowed[i], os_part, SC_RM_PERM_FULL);
+ if (err)
+ ERROR("sc_rm_set_peripheral_permissions: rsrc %u, \
+ ret %u\n", ns_access_allowed[i], err);
+ }
+
+ /*
+ * sc_rm_set_peripheral_permissions
+ * sc_rm_set_memreg_permissions
+ * sc_rm_set_pin_movable
+ */
+ for (mr = 0; mr < 64; mr++) {
+ owned = sc_rm_is_memreg_owned(ipc_handle, mr);
+ if (owned) {
+ err = sc_rm_get_memreg_info(ipc_handle, mr, &start, &end);
+ if (err)
+ ERROR("Memreg get info failed, %u\n", mr);
+
+ NOTICE("Memreg %u 0x%" PRIx64 " -- 0x%" PRIx64 "\n", mr, start, end);
+ if (BL31_BASE >= start && (BL31_LIMIT - 1) <= end) {
+ mr_record = mr; /* Record the mr for ATF running */
+ } else {
+ err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+ if (err)
+ ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 ", \
+ err %d\n", start, end, err);
+ }
+ }
+ }
+
+ if (mr_record != 64) {
+ err = sc_rm_get_memreg_info(ipc_handle, mr_record, &start, &end);
+ if (err)
+ ERROR("Memreg get info failed, %u\n", mr_record);
+ if ((BL31_LIMIT - 1) < end) {
+ err = sc_rm_memreg_alloc(ipc_handle, &mr, BL31_LIMIT, end);
+ if (err)
+ ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ (sc_faddr_t)BL31_LIMIT, end);
+ err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+ if (err)
+ ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ (sc_faddr_t)BL31_LIMIT, end);
+ }
+
+ if (start < (BL31_BASE - 1)) {
+ err = sc_rm_memreg_alloc(ipc_handle, &mr, start, BL31_BASE - 1);
+ if (err)
+ ERROR("sc_rm_memreg_alloc failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ start, (sc_faddr_t)BL31_BASE - 1);
+ err = sc_rm_assign_memreg(ipc_handle, os_part, mr);
+ if (err)
+ ERROR("Memreg assign failed, 0x%" PRIx64 " -- 0x%" PRIx64 "\n",
+ start, (sc_faddr_t)BL31_BASE - 1);
+ }
+ }
+
+ if (err)
+ NOTICE("Partitioning Failed\n");
+ else
+ NOTICE("Non-secure Partitioning Succeeded\n");
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+#if DEBUG_CONSOLE
+ static console_t console;
+#endif
+ if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
+ panic();
+
+#if DEBUG_CONSOLE_A35
+ sc_pm_set_resource_power_mode(ipc_handle, IMX_RES_UART,
+ SC_PM_PW_MODE_ON);
+ sc_pm_clock_rate_t rate = 80000000;
+ sc_pm_set_clock_rate(ipc_handle, IMX_RES_UART, 2, &rate);
+ sc_pm_clock_enable(ipc_handle, IMX_RES_UART, 2, true, false);
+
+ /* Configure UART pads */
+ sc_pad_set(ipc_handle, IMX_PAD_UART_RX, UART_PAD_CTRL);
+ sc_pad_set(ipc_handle, IMX_PAD_UART_TX, UART_PAD_CTRL);
+ lpuart32_serial_init(IMX_BOOT_UART_BASE);
+#endif
+
+#if DEBUG_CONSOLE
+ console_lpuart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+ IMX_CONSOLE_BAUDRATE, &console);
+#endif
+ /* Turn on MU1 for non-secure OS/Hypervisor */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_MU_1A, SC_PM_PW_MODE_ON);
+
+ /* Turn on GPT_0's power & clock for non-secure OS/Hypervisor */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT0_LPCG_BASE, mmio_read_32(IMX_GPT0_LPCG_BASE) | (1 << 25));
+
+ /*
+ * create new partition for non-secure OS/Hypervisor
+ * uses global structs defined in sec_rsrc.h
+ */
+ imx8_partition_resources();
+
+ bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+ bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ unsigned long ro_start = BL31_RO_START;
+ unsigned long ro_size = BL31_RO_END - BL31_RO_START;
+ unsigned long rw_start = BL31_RW_START;
+ unsigned long rw_size = BL31_RW_END - BL31_RW_START;
+#if USE_COHERENT_MEM
+ unsigned long coh_start = BL31_COHERENT_RAM_START;
+ unsigned long coh_size = BL31_COHERENT_RAM_END - BL31_COHERENT_RAM_START;
+#endif
+
+ mmap_add_region(ro_start, ro_start, ro_size,
+ MT_RO | MT_MEMORY | MT_SECURE);
+ mmap_add_region(rw_start, rw_start, rw_size,
+ MT_RW | MT_MEMORY | MT_SECURE);
+ mmap_add(imx_mmap);
+
+#if USE_COHERENT_MEM
+ mmap_add_region(coh_start, coh_start, coh_size,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ plat_gic_driver_init();
+ plat_gic_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+ if (type == SECURE)
+ return &bl32_image_ep_info;
+
+ return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return COUNTER_FREQUENCY;
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ return;
+}
diff --git a/plat/imx/imx8qx/imx8qx_psci.c b/plat/imx/imx8qx/imx8qx_psci.c
new file mode 100644
index 0000000..aab3a2d
--- /dev/null
+++ b/plat/imx/imx8qx/imx8qx_psci.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <plat_imx8.h>
+#include <sci/sci.h>
+
+#include "../../common/sci/imx8_mu.h"
+
+const static int ap_core_index[PLATFORM_CORE_COUNT] = {
+ SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3
+};
+
+/* save gic dist/redist context when GIC is power down */
+static struct plat_gic_ctx imx_gicv3_ctx;
+static unsigned int gpt_lpcg, gpt_reg[2];
+
+static void imx_enable_irqstr_wakeup(void)
+{
+ uint32_t irq_mask;
+ gicv3_dist_ctx_t *dist_ctx = &imx_gicv3_ctx.dist_ctx;
+
+ /* put IRQSTR into ON mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* enable the irqsteer to handle wakeup irq */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x1);
+ for (int i = 0; i < 15; i++) {
+ irq_mask = dist_ctx->gicd_isenabler[i];
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x3c - 0x4 * i, irq_mask);
+ }
+
+ /* set IRQSTR low power mode */
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_STBY);
+ else
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+static void imx_disable_irqstr_wakeup(void)
+{
+ /* Put IRQSTEER back to ON mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_ON);
+
+ /* disable the irqsteer */
+ mmio_write_32(IMX_WUP_IRQSTR_BASE, 0x0);
+ for (int i = 0; i < 16; i++)
+ mmio_write_32(IMX_WUP_IRQSTR_BASE + 0x4 + 0x4 * i, 0x0);
+
+ /* Put IRQSTEER into OFF mode */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_IRQSTR_SCU2, SC_PM_PW_MODE_OFF);
+}
+
+int imx_pwr_domain_on(u_register_t mpidr)
+{
+ int ret = PSCI_E_SUCCESS;
+ unsigned int cpu_id;
+
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ printf("imx_pwr_domain_on cpu_id %d\n", cpu_id);
+
+ if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
+ ERROR("core %d power on failed!\n", cpu_id);
+ ret = PSCI_E_INTERN_FAIL;
+ }
+
+ if (sc_pm_cpu_start(ipc_handle, ap_core_index[cpu_id],
+ true, BL31_BASE) != SC_ERR_NONE) {
+ ERROR("boot core %d failed!\n", cpu_id);
+ ret = PSCI_E_INTERN_FAIL;
+ }
+
+ return ret;
+}
+
+void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ plat_gic_pcpu_init();
+ plat_gic_cpuif_enable();
+}
+
+int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
+{
+ return PSCI_E_SUCCESS;
+}
+
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ plat_gic_cpuif_disable();
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE);
+ printf("turn off core:%d\n", cpu_id);
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) {
+ plat_gic_cpuif_disable();
+ sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+ } else {
+ dsb();
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+ isb();
+ }
+
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1]))
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+
+ if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+ plat_gic_cpuif_disable();
+
+ /* save gic context */
+ plat_gic_save(cpu_id, &imx_gicv3_ctx);
+ /* enable the irqsteer for wakeup */
+ imx_enable_irqstr_wakeup();
+
+ /* Save GPT clock and registers, then turn off its power */
+ gpt_lpcg = mmio_read_32(IMX_GPT0_LPCG_BASE);
+ gpt_reg[0] = mmio_read_32(IMX_GPT0_BASE);
+ gpt_reg[1] = mmio_read_32(IMX_GPT0_BASE + 0x4);
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_OFF);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_OFF);
+
+ /* Put GIC in OFF mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_OFF);
+ sc_pm_set_cpu_resume(ipc_handle, ap_core_index[cpu_id], true, BL31_BASE);
+ if (imx_is_wakeup_src_irqsteer())
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_IRQSTEER);
+ else
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_SCU);
+ }
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (is_local_state_retn(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL])) {
+ MU_Resume(SC_IPC_BASE);
+
+ sc_pm_req_low_power_mode(ipc_handle, ap_core_index[cpu_id], SC_PM_PW_MODE_ON);
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+
+ /* Put GIC back to high power mode. */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GIC, SC_PM_PW_MODE_ON);
+
+ /* restore gic context */
+ plat_gic_restore(cpu_id, &imx_gicv3_ctx);
+
+ /* Turn on GPT power and restore its clock and registers */
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_GPT_0, SC_PM_PW_MODE_ON);
+ sc_pm_clock_enable(ipc_handle, SC_R_GPT_0, SC_PM_CLK_PER, true, 0);
+ mmio_write_32(IMX_GPT0_BASE, gpt_reg[0]);
+ mmio_write_32(IMX_GPT0_BASE + 0x4, gpt_reg[1]);
+ mmio_write_32(IMX_GPT0_LPCG_BASE, gpt_lpcg);
+
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+
+ /* disable the irqsteer wakeup */
+ imx_disable_irqstr_wakeup();
+
+ plat_gic_cpuif_enable();
+ }
+
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL1]))
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
+
+ if (is_local_state_off(target_state->pwr_domain_state[MPIDR_AFFLVL0])) {
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_ON, SC_PM_WAKE_SRC_GIC);
+ plat_gic_cpuif_enable();
+ } else {
+ write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
+ isb();
+ }
+}
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+ .pwr_domain_on = imx_pwr_domain_on,
+ .pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .system_off = imx_system_off,
+ .system_reset = imx_system_reset,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .validate_power_state = imx_validate_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ imx_mailbox_init(sec_entrypoint);
+ *psci_ops = &imx_plat_psci_ops;
+
+ /* make sure system sources power ON in low power mode by default */
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_ON);
+
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_DDR,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_MU,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35, SC_PM_SYS_IF_INTERCONNECT,
+ SC_PM_PW_MODE_ON, SC_PM_PW_MODE_ON);
+
+ return 0;
+}
diff --git a/plat/imx/imx8qx/include/platform_def.h b/plat/imx/imx8qx/include/platform_def.h
new file mode 100644
index 0000000..b880e1b
--- /dev/null
+++ b/plat/imx/imx8qx/include/platform_def.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+#define PLATFORM_STACK_SIZE 0x400
+#define CACHE_WRITEBACK_GRANULE 64
+
+#define PLAT_PRIMARY_CPU U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+
+#define PWR_DOMAIN_AT_MAX_LVL U(1)
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define BL31_BASE 0x80000000
+#define BL31_LIMIT 0x80020000
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 8
+
+#define PLAT_GICD_BASE 0x51a00000
+#define PLAT_GICR_BASE 0x51b00000
+
+#if defined(IMX_USE_UART0)
+#define IMX_BOOT_UART_BASE 0x5a060000
+#elif defined(IMX_USE_UART3)
+#define IMX_BOOT_UART_BASE 0x5a090000
+#else
+#error "Provide proper UART configuration in IMX_DEBUG_UART"
+#endif
+
+#define IMX_BOOT_UART_BAUDRATE 115200
+#define IMX_BOOT_UART_CLK_IN_HZ 24000000
+#define PLAT_CRASH_UART_BASE IMX_BOOT_UART_BASE
+#define PLAT__CRASH_UART_CLK_IN_HZ 24000000
+#define IMX_CONSOLE_BAUDRATE 115200
+#define SC_IPC_BASE 0x5d1b0000
+#define IMX_GPT0_LPCG_BASE 0x5d540000
+#define IMX_GPT0_BASE 0x5d140000
+#define IMX_WUP_IRQSTR_BASE 0x51090000
+#define IMX_REG_BASE 0x50000000
+#define IMX_REG_SIZE 0x10000000
+
+#define COUNTER_FREQUENCY 8000000
+
+/* non-secure u-boot base */
+#define PLAT_NS_IMAGE_OFFSET 0x80020000
+#define DEBUG_CONSOLE_A35 DEBUG_CONSOLE
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/imx/imx8qx/include/sec_rsrc.h b/plat/imx/imx8qx/include/sec_rsrc.h
new file mode 100644
index 0000000..b7fe0e8
--- /dev/null
+++ b/plat/imx/imx8qx/include/sec_rsrc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* resources that are going to stay in secure partition */
+sc_rsrc_t secure_rsrcs[] = {
+ SC_R_MU_0A,
+ SC_R_A35,
+ SC_R_A35_0,
+ SC_R_A35_1,
+ SC_R_A35_2,
+ SC_R_A35_3,
+ SC_R_GIC,
+ SC_R_SYSTEM,
+ SC_R_IRQSTR_SCU2,
+ SC_R_GPT_0
+};
+
+/* resources that have register access for non-secure domain */
+sc_rsrc_t ns_access_allowed[] = {
+ SC_R_GIC,
+ SC_R_GPT_0
+};
diff --git a/plat/imx/imx8qx/platform.mk b/plat/imx/imx8qx/platform.mk
new file mode 100644
index 0000000..85b5f3d
--- /dev/null
+++ b/plat/imx/imx8qx/platform.mk
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Iplat/imx/imx8qx/include \
+ -Iplat/imx/common/include \
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES += plat/imx/common/lpuart_console.S \
+ plat/imx/common/imx8_helpers.S \
+ plat/imx/imx8qx/imx8qx_bl31_setup.c \
+ plat/imx/imx8qx/imx8qx_psci.c \
+ plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx8_psci.c \
+ plat/imx/common/imx_sip_svc.c \
+ plat/imx/common/imx_sip_handler.c \
+ plat/common/plat_psci_common.c \
+ lib/cpus/aarch64/cortex_a35.S \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${IMX_GIC_SOURCES} \
+
+include plat/imx/common/sci/sci_api.mk
+
+USE_COHERENT_MEM := 1
+RESET_TO_BL31 := 1
+
+IMX_DEBUG_UART ?= 0
+$(eval $(call add_define,IMX_USE_UART${IMX_DEBUG_UART}))
+
+DEBUG_CONSOLE ?= 0
+$(eval $(call add_define,DEBUG_CONSOLE))
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
new file mode 100644
index 0000000..211a7b7
--- /dev/null
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include "agilex_mmc.h"
+#include "agilex_clock_manager.h"
+#include "agilex_memory_controller.h"
+#include "agilex_pinmux.h"
+#include "ccu/ncore_ccu.h"
+#include "qspi/cadence_qspi.h"
+#include "socfpga_emac.h"
+#include "socfpga_f2sdram_manager.h"
+#include "socfpga_handoff.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_private.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_system_manager.h"
+#include "wdt/watchdog.h"
+
+static struct mmc_device_info mmc_info;
+
+const mmap_region_t agilex_plat_mmap[] = {
+ MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE,
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ {0},
+};
+
+boot_source_type boot_source = BOOT_SOURCE;
+
+void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
+ u_register_t x2, u_register_t x4)
+{
+ static console_t console;
+ handoff reverse_handoff_ptr;
+
+ generic_delay_timer_init();
+
+ if (socfpga_get_handoff(&reverse_handoff_ptr))
+ return;
+ config_pinmux(&reverse_handoff_ptr);
+ config_clkmgr_handoff(&reverse_handoff_ptr);
+
+ enable_nonsecure_access();
+ deassert_peripheral_reset();
+ config_hps_hs_before_warm_reset();
+
+ watchdog_init(get_wdt_clk());
+
+ console_16550_register(PLAT_INTEL_UART_BASE, get_uart_clk(),
+ PLAT_BAUDRATE, &console);
+
+ socfpga_delay_timer_init();
+ init_ncore_ccu();
+ socfpga_emac_init();
+ init_hard_memory_controller();
+ mailbox_init();
+ agx_mmc_init();
+
+ if (!intel_mailbox_is_fpga_not_ready()) {
+ socfpga_bridges_enable(SOC2FPGA_MASK | LWHPS2FPGA_MASK |
+ FPGA2SOC_MASK);
+ }
+}
+
+
+void bl2_el3_plat_arch_setup(void)
+{
+
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL2_BASE, BL2_END - BL2_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM_BAR
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ {0},
+ };
+
+ setup_page_tables(bl_regions, agilex_plat_mmap);
+
+ enable_mmu_el3(0);
+
+ dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000, get_mmc_clk());
+
+ mmc_info.mmc_dev_type = MMC_IS_SD;
+ mmc_info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
+
+ /* Request ownership and direct access to QSPI */
+ mailbox_hps_qspi_enable();
+
+ switch (boot_source) {
+ case BOOT_SOURCE_SDMMC:
+ dw_mmc_init(&params, &mmc_info);
+ socfpga_io_setup(boot_source);
+ break;
+
+ case BOOT_SOURCE_QSPI:
+ cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
+ QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
+ QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
+ socfpga_io_setup(boot_source);
+ break;
+
+ default:
+ ERROR("Unsupported boot source\n");
+ panic();
+ break;
+ }
+}
+
+uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL33_IMAGE_ID:
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = get_spsr_for_bl33_entry();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl2_platform_setup(void)
+{
+}
+
diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c
new file mode 100644
index 0000000..b1b9514
--- /dev/null
+++ b/plat/intel/soc/agilex/bl31_plat_setup.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include "ccu/ncore_ccu.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_private.h"
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ?
+ &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY);
+
+ console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK,
+ PLAT_BAUDRATE, &console);
+ /*
+ * Check params passed from BL31 should not be NULL,
+ */
+ void *from_bl2 = (void *) arg0;
+
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+ assert(params_from_bl2 != NULL);
+
+ /*
+ * Copy BL32 (if populated by BL31) and BL33 entry point information.
+ * They are stored in Secure RAM, in BL31's address space.
+ */
+
+ if (params_from_bl2->h.type == PARAM_BL_PARAMS &&
+ params_from_bl2->h.version >= VERSION_2) {
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ while (bl_params) {
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+ } else {
+ struct socfpga_bl31_params *arg_from_bl2 =
+ (struct socfpga_bl31_params *) from_bl2;
+
+ assert(arg_from_bl2->h.type == PARAM_BL31);
+ assert(arg_from_bl2->h.version >= VERSION_1);
+
+ bl32_image_ep_info = *arg_from_bl2->bl32_ep_info;
+ bl33_image_ep_info = *arg_from_bl2->bl33_ep_info;
+ }
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+static const interrupt_prop_t s10_interrupt_props[] = {
+ PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t plat_gicv2_gic_data = {
+ .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE,
+ .gicc_base = PLAT_INTEL_SOCFPGA_GICC_BASE,
+ .interrupt_props = s10_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(s10_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ socfpga_delay_timer_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ gicv2_driver_init(&plat_gicv2_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
+ mmio_write_64(PLAT_CPU_RELEASE_ADDR,
+ (uint64_t)plat_secondary_cpus_bl31_entry);
+
+ mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
+
+ ncore_enable_ocram_firewall();
+}
+
+const mmap_region_t plat_agilex_mmap[] = {
+ MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE,
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE, MT_DEVICE | MT_RW | MT_NS),
+ {0}
+};
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_agilex_mmap);
+ enable_mmu_el3(0);
+}
+
diff --git a/plat/intel/soc/agilex/include/agilex_clock_manager.h b/plat/intel/soc/agilex/include/agilex_clock_manager.h
new file mode 100644
index 0000000..f39d475
--- /dev/null
+++ b/plat/intel/soc/agilex/include/agilex_clock_manager.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CLOCKMANAGER_H
+#define CLOCKMANAGER_H
+
+#include "socfpga_handoff.h"
+
+/* Clock Manager Registers */
+#define CLKMGR_OFFSET 0xffd10000
+
+#define CLKMGR_CTRL 0x0
+#define CLKMGR_STAT 0x4
+#define CLKMGR_INTRCLR 0x14
+
+/* Main PLL Group */
+#define CLKMGR_MAINPLL 0xffd10024
+#define CLKMGR_MAINPLL_EN 0x0
+#define CLKMGR_MAINPLL_BYPASS 0xc
+#define CLKMGR_MAINPLL_MPUCLK 0x18
+#define CLKMGR_MAINPLL_NOCCLK 0x1c
+#define CLKMGR_MAINPLL_NOCDIV 0x20
+#define CLKMGR_MAINPLL_PLLGLOB 0x24
+#define CLKMGR_MAINPLL_FDBCK 0x28
+#define CLKMGR_MAINPLL_MEM 0x2c
+#define CLKMGR_MAINPLL_MEMSTAT 0x30
+#define CLKMGR_MAINPLL_PLLC0 0x34
+#define CLKMGR_MAINPLL_PLLC1 0x38
+#define CLKMGR_MAINPLL_VCOCALIB 0x3c
+#define CLKMGR_MAINPLL_PLLC2 0x40
+#define CLKMGR_MAINPLL_PLLC3 0x44
+#define CLKMGR_MAINPLL_PLLM 0x48
+#define CLKMGR_MAINPLL_LOSTLOCK 0x54
+
+/* Peripheral PLL Group */
+#define CLKMGR_PERPLL 0xffd1007c
+#define CLKMGR_PERPLL_EN 0x0
+#define CLKMGR_PERPLL_BYPASS 0xc
+#define CLKMGR_PERPLL_EMACCTL 0x18
+#define CLKMGR_PERPLL_GPIODIV 0x1c
+#define CLKMGR_PERPLL_PLLGLOB 0x20
+#define CLKMGR_PERPLL_FDBCK 0x24
+#define CLKMGR_PERPLL_MEM 0x28
+#define CLKMGR_PERPLL_MEMSTAT 0x2c
+#define CLKMGR_PERPLL_PLLC0 0x30
+#define CLKMGR_PERPLL_PLLC1 0x34
+#define CLKMGR_PERPLL_VCOCALIB 0x38
+#define CLKMGR_PERPLL_PLLC2 0x3c
+#define CLKMGR_PERPLL_PLLC3 0x40
+#define CLKMGR_PERPLL_PLLM 0x44
+#define CLKMGR_PERPLL_LOSTLOCK 0x50
+
+/* Altera Group */
+#define CLKMGR_ALTERA 0xffd100d0
+#define CLKMGR_ALTERA_JTAG 0x0
+#define CLKMGR_ALTERA_EMACACTR 0x4
+#define CLKMGR_ALTERA_EMACBCTR 0x8
+#define CLKMGR_ALTERA_EMACPTPCTR 0xc
+#define CLKMGR_ALTERA_GPIODBCTR 0x10
+#define CLKMGR_ALTERA_SDMMCCTR 0x14
+#define CLKMGR_ALTERA_S2FUSER0CTR 0x18
+#define CLKMGR_ALTERA_S2FUSER1CTR 0x1c
+#define CLKMGR_ALTERA_PSIREFCTR 0x20
+#define CLKMGR_ALTERA_EXTCNTRST 0x24
+
+/* Membus */
+#define CLKMGR_MEM_REQ BIT(24)
+#define CLKMGR_MEM_WR BIT(25)
+#define CLKMGR_MEM_ERR BIT(26)
+#define CLKMGR_MEM_WDAT_OFFSET 16
+#define CLKMGR_MEM_ADDR 0x4027
+#define CLKMGR_MEM_WDAT 0x80
+
+/* Clock Manager Macros */
+#define CLKMGR_CTRL_BOOTMODE_SET_MSK 0x00000001
+#define CLKMGR_STAT_BUSY_E_BUSY 0x1
+#define CLKMGR_STAT_BUSY(x) (((x) & 0x00000001) >> 0)
+#define CLKMGR_STAT_MAINPLLLOCKED(x) (((x) & 0x00000100) >> 8)
+#define CLKMGR_STAT_PERPLLLOCKED(x) (((x) & 0x00010000) >> 16)
+#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK 0x00000004
+#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK 0x00000008
+#define CLKMGR_INTOSC_HZ 460000000
+
+/* Main PLL Macros */
+#define CLKMGR_MAINPLL_EN_RESET 0x000000ff
+
+/* Peripheral PLL Macros */
+#define CLKMGR_PERPLL_EN_RESET 0x00000fff
+#define CLKMGR_PERPLL_EN_SDMMCCLK BIT(5)
+#define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x) (((x) << 0) & 0x0000ffff)
+
+/* Altera Macros */
+#define CLKMGR_ALTERA_EXTCNTRST_RESET 0xff
+
+/* Shared Macros */
+#define CLKMGR_PSRC(x) (((x) & 0x00030000) >> 16)
+#define CLKMGR_PSRC_MAIN 0
+#define CLKMGR_PSRC_PER 1
+
+#define CLKMGR_PLLGLOB_PSRC_EOSC1 0x0
+#define CLKMGR_PLLGLOB_PSRC_INTOSC 0x1
+#define CLKMGR_PLLGLOB_PSRC_F2S 0x2
+
+#define CLKMGR_PLLM_MDIV(x) ((x) & 0x000003ff)
+#define CLKMGR_PLLGLOB_PD_SET_MSK 0x00000001
+#define CLKMGR_PLLGLOB_RST_SET_MSK 0x00000002
+
+#define CLKMGR_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8)
+#define CLKMGR_PLLGLOB_AREFCLKDIV(x) (((x) & 0x00000f00) >> 8)
+#define CLKMGR_PLLGLOB_DREFCLKDIV(x) (((x) & 0x00003000) >> 12)
+
+#define CLKMGR_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000003ff)
+#define CLKMGR_VCOCALIB_MSCNT_SET(x) (((x) << 16) & 0x00ff0000)
+
+#define CLKMGR_CLR_LOSTLOCK_BYPASS 0x20000000
+
+typedef struct {
+ uint32_t clk_freq_of_eosc1;
+ uint32_t clk_freq_of_f2h_free;
+ uint32_t clk_freq_of_cb_intosc_ls;
+} CLOCK_SOURCE_CONFIG;
+
+void config_clkmgr_handoff(handoff *hoff_ptr);
+uint32_t get_wdt_clk(void);
+uint32_t get_uart_clk(void);
+uint32_t get_mmc_clk(void);
+
+#endif
diff --git a/plat/intel/soc/agilex/include/agilex_memory_controller.h b/plat/intel/soc/agilex/include/agilex_memory_controller.h
new file mode 100644
index 0000000..3746d92
--- /dev/null
+++ b/plat/intel/soc/agilex/include/agilex_memory_controller.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AGX_MEMORYCONTROLLER_H
+#define AGX_MEMORYCONTROLLER_H
+
+#define AGX_MPFE_IOHMC_REG_DRAMADDRW 0xf80100a8
+#define AGX_MPFE_IOHMC_CTRLCFG0 0xf8010028
+#define AGX_MPFE_IOHMC_CTRLCFG1 0xf801002c
+#define AGX_MPFE_IOHMC_CTRLCFG2 0xf8010030
+#define AGX_MPFE_IOHMC_CTRLCFG3 0xf8010034
+#define AGX_MPFE_IOHMC_DRAMADDRW 0xf80100a8
+#define AGX_MPFE_IOHMC_DRAMTIMING0 0xf8010050
+#define AGX_MPFE_IOHMC_CALTIMING0 0xf801007c
+#define AGX_MPFE_IOHMC_CALTIMING1 0xf8010080
+#define AGX_MPFE_IOHMC_CALTIMING2 0xf8010084
+#define AGX_MPFE_IOHMC_CALTIMING3 0xf8010088
+#define AGX_MPFE_IOHMC_CALTIMING4 0xf801008c
+#define AGX_MPFE_IOHMC_CALTIMING9 0xf80100a0
+#define AGX_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(x) (((x) & 0x000000ff) >> 0)
+#define AGX_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(value) \
+ (((value) & 0x00000060) >> 5)
+
+#define AGX_MPFE_HMC_ADP_ECCCTRL1 0xf8011100
+#define AGX_MPFE_HMC_ADP_ECCCTRL2 0xf8011104
+#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT 0xf8011218
+#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE 0x000000ff
+#define AGX_MPFE_HMC_ADP_RSTHANDSHAKECTRL 0xf8011214
+
+
+#define AGX_MPFE_IOHMC_REG_CTRLCFG1 0xf801002c
+
+#define AGX_MPFE_IOHMC_REG_NIOSRESERVE0_OFST 0xf8010110
+
+#define IOHMC_DRAMADDRW_COL_ADDR_WIDTH(x) (((x) & 0x0000001f) >> 0)
+#define IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(x) (((x) & 0x000003e0) >> 5)
+#define IOHMC_DRAMADDRW_CS_ADDR_WIDTH(x) (((x) & 0x00070000) >> 16)
+#define IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(x) (((x) & 0x0000c000) >> 14)
+#define IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(x) (((x) & 0x00003c00) >> 10)
+
+#define AGX_MPFE_DDR(x) (0xf8000000 + x)
+#define AGX_MPFE_HMC_ADP_DDRCALSTAT 0xf801100c
+#define AGX_MPFE_DDR_MAIN_SCHED 0xf8000400
+#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF 0xf8000408
+#define AGX_MPFE_DDR_MAIN_SCHED_DDRTIMING 0xf800040c
+#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK 0x0000001f
+#define AGX_MPFE_DDR_MAIN_SCHED_DDRMODE 0xf8000410
+#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV 0xf800043c
+#define AGX_MPFE_DDR_MAIN_SCHED_READLATENCY 0xf8000414
+#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE 0xf8000438
+#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST 10
+#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST 4
+#define AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST 0
+#define AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(x) (((x) << 0) & 0x0000001f)
+#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST 0
+#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK (BIT(0) | BIT(1))
+#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST 2
+#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK (BIT(2) | BIT(3))
+#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST 4
+#define AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK (BIT(4) | BIT(5))
+
+#define AGX_MPFE_HMC_ADP(x) (0xf8011000 + (x))
+#define AGX_MPFE_HMC_ADP_HPSINTFCSEL 0xf8011210
+#define AGX_MPFE_HMC_ADP_DDRIOCTRL 0xf8011008
+#define HMC_ADP_DDRIOCTRL 0x8
+#define HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0)
+#define HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(x) (((x) & 0x00003e00) >> 9)
+#define ADP_DRAMADDRWIDTH 0xe0
+
+#define ACT_TO_ACT_DIFF_BANK(value) (((value) & 0x00fc0000) >> 18)
+#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12)
+#define ACT_TO_RDWR(value) (((value) & 0x0000003f) >> 0)
+#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12)
+
+/* timing 2 */
+#define RD_TO_RD_DIFF_CHIP(value) (((value) & 0x00000fc0) >> 6)
+#define RD_TO_WR_DIFF_CHIP(value) (((value) & 0x3f000000) >> 24)
+#define RD_TO_WR(value) (((value) & 0x00fc0000) >> 18)
+#define RD_TO_PCH(value) (((value) & 0x00000fc0) >> 6)
+
+/* timing 3 */
+#define CALTIMING3_WR_TO_RD_DIFF_CHIP(value) (((value) & 0x0003f000) >> 12)
+#define CALTIMING3_WR_TO_RD(value) (((value) & 0x00000fc0) >> 6)
+
+/* timing 4 */
+#define PCH_TO_VALID(value) (((value) & 0x00000fc0) >> 6)
+
+#define DDRTIMING_BWRATIO_OFST 31
+#define DDRTIMING_WRTORD_OFST 26
+#define DDRTIMING_RDTOWR_OFST 21
+#define DDRTIMING_BURSTLEN_OFST 18
+#define DDRTIMING_WRTOMISS_OFST 12
+#define DDRTIMING_RDTOMISS_OFST 6
+#define DDRTIMING_ACTTOACT_OFST 0
+
+#define ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x3) >> 0)
+
+#define DDRMODE_AUTOPRECHARGE_OFST 1
+#define DDRMODE_BWRATIOEXTENDED_OFST 0
+
+
+#define AGX_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(x) (((x) & 0x7f) >> 0)
+#define AGX_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(x) (((x) & 0x0f) >> 0)
+
+#define AGX_CCU_CPU0_MPRT_DDR 0xf7004400
+#define AGX_CCU_CPU0_MPRT_MEM0 0xf70045c0
+#define AGX_CCU_CPU0_MPRT_MEM1A 0xf70045e0
+#define AGX_CCU_CPU0_MPRT_MEM1B 0xf7004600
+#define AGX_CCU_CPU0_MPRT_MEM1C 0xf7004620
+#define AGX_CCU_CPU0_MPRT_MEM1D 0xf7004640
+#define AGX_CCU_CPU0_MPRT_MEM1E 0xf7004660
+#define AGX_CCU_IOM_MPRT_MEM0 0xf7018560
+#define AGX_CCU_IOM_MPRT_MEM1A 0xf7018580
+#define AGX_CCU_IOM_MPRT_MEM1B 0xf70185a0
+#define AGX_CCU_IOM_MPRT_MEM1C 0xf70185c0
+#define AGX_CCU_IOM_MPRT_MEM1D 0xf70185e0
+#define AGX_CCU_IOM_MPRT_MEM1E 0xf7018600
+
+#define AGX_NOC_FW_DDR_SCR 0xf8020200
+#define AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT 0xf802021c
+#define AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT 0xf8020218
+#define AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT 0xf802029c
+#define AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT 0xf8020298
+
+#define AGX_SOC_NOC_FW_DDR_SCR_ENABLE 0xf8020200
+#define AGX_SOC_NOC_FW_DDR_SCR_ENABLESET 0xf8020204
+#define AGX_CCU_NOC_DI_SET_MSK 0x10
+
+#define AGX_SYSMGR_CORE_HMC_CLK 0xffd120b4
+#define AGX_SYSMGR_CORE_HMC_CLK_STATUS 0x00000001
+
+#define AGX_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0(x) (((x) & 0xffff) >> 0)
+#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK 0x00000003
+#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST 0
+#define AGX_MPFE_HMC_ADP_HPSINTFCSEL_ENABLE 0x001f1f1f
+#define AGX_IOHMC_CTRLCFG1_ENABLE_ECC_OFST 7
+
+#define AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK 0x00010000
+#define AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK 0x00000100
+#define AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK 0x00000001
+
+#define AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK 0x00000001
+#define AGX_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK 0x00010000
+#define AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK 0x00000100
+#define AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(value) (((value) & 0x1) >> 0)
+
+
+#define AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00003) >> 0)
+#define IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(x) (((x) & 0x03c00) >> 10)
+#define IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(x) (((x) & 0x0c000) >> 14)
+#define IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(x) (((x) & 0x0001f) >> 0)
+#define IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(x) (((x) & 0x70000) >> 16)
+#define IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(x) (((x) & 0x003e0) >> 5)
+
+#define AGX_SDRAM_0_LB_ADDR 0x0
+#define AGX_DDR_SIZE 0x40000000
+
+int init_hard_memory_controller(void);
+
+#endif
diff --git a/plat/intel/soc/agilex/include/agilex_mmc.h b/plat/intel/soc/agilex/include/agilex_mmc.h
new file mode 100644
index 0000000..00f4ca5
--- /dev/null
+++ b/plat/intel/soc/agilex/include/agilex_mmc.h
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+void agx_mmc_init(void);
diff --git a/plat/intel/soc/agilex/include/agilex_pinmux.h b/plat/intel/soc/agilex/include/agilex_pinmux.h
new file mode 100644
index 0000000..fe01062
--- /dev/null
+++ b/plat/intel/soc/agilex/include/agilex_pinmux.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AGX_PINMUX_H
+#define AGX_PINMUX_H
+
+#define AGX_PINMUX_PIN0SEL 0xffd13000
+#define AGX_PINMUX_IO0CTRL 0xffd13130
+#define AGX_PINMUX_PINMUX_EMAC0_USEFPGA 0xffd13300
+#define AGX_PINMUX_IO0_DELAY 0xffd13400
+
+#include "socfpga_handoff.h"
+
+void config_pinmux(handoff *handoff);
+
+#endif
+
diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h
new file mode 100644
index 0000000..b216ab1
--- /dev/null
+++ b/plat/intel/soc/agilex/include/socfpga_plat_def.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SOCFPGA_DEF_H
+#define PLAT_SOCFPGA_DEF_H
+
+#include <platform_def.h>
+
+/* Platform Setting */
+#define PLATFORM_MODEL PLAT_SOCFPGA_AGILEX
+#define BOOT_SOURCE BOOT_SOURCE_SDMMC
+
+/* FPGA config helpers */
+#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000
+#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 0x2000000
+
+/* Register Mapping */
+#define SOCFPGA_CCU_NOC_REG_BASE 0xf7000000
+#define SOCFPGA_F2SDRAMMGR_REG_BASE U(0xf8024000)
+
+#define SOCFPGA_MMC_REG_BASE 0xff808000
+
+#define SOCFPGA_RSTMGR_REG_BASE 0xffd11000
+#define SOCFPGA_SYSMGR_REG_BASE 0xffd12000
+
+#define SOCFPGA_L4_PER_SCR_REG_BASE 0xffd21000
+#define SOCFPGA_L4_SYS_SCR_REG_BASE 0xffd21100
+#define SOCFPGA_SOC2FPGA_SCR_REG_BASE 0xffd21200
+#define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE 0xffd21300
+
+/* Platform specific system counter */
+#define PLAT_SYS_COUNTER_FREQ_IN_MHZ get_cpu_clk()
+
+uint32_t get_cpu_clk(void);
+
+#endif /* PLAT_SOCFPGA_DEF_H */
diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk
new file mode 100644
index 0000000..a1e58fc
--- /dev/null
+++ b/plat/intel/soc/agilex/platform.mk
@@ -0,0 +1,83 @@
+#
+# Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := \
+ -Iplat/intel/soc/agilex/include/ \
+ -Iplat/intel/soc/common/drivers/ \
+ -Iplat/intel/soc/common/include/
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+AGX_GICv2_SOURCES := \
+ ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c
+
+
+PLAT_BL_COMMON_SOURCES := \
+ ${AGX_GICv2_SOURCES} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ plat/intel/soc/common/aarch64/platform_common.c \
+ plat/intel/soc/common/aarch64/plat_helpers.S \
+ plat/intel/soc/common/drivers/ccu/ncore_ccu.c \
+ plat/intel/soc/common/socfpga_delay_timer.c
+
+BL2_SOURCES += \
+ common/desc_image_load.c \
+ drivers/mmc/mmc.c \
+ drivers/intel/soc/stratix10/io/s10_memmap_qspi.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/partition/partition.c \
+ drivers/partition/gpt.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/intel/soc/agilex/bl2_plat_setup.c \
+ plat/intel/soc/agilex/soc/agilex_clock_manager.c \
+ plat/intel/soc/agilex/soc/agilex_memory_controller.c \
+ plat/intel/soc/agilex/soc/agilex_mmc.c \
+ plat/intel/soc/agilex/soc/agilex_pinmux.c \
+ plat/intel/soc/common/bl2_plat_mem_params_desc.c \
+ plat/intel/soc/common/socfpga_image_load.c \
+ plat/intel/soc/common/socfpga_storage.c \
+ plat/intel/soc/common/soc/socfpga_emac.c \
+ plat/intel/soc/common/soc/socfpga_firewall.c \
+ plat/intel/soc/common/soc/socfpga_handoff.c \
+ plat/intel/soc/common/soc/socfpga_mailbox.c \
+ plat/intel/soc/common/soc/socfpga_reset_manager.c \
+ plat/intel/soc/common/drivers/qspi/cadence_qspi.c \
+ plat/intel/soc/common/drivers/wdt/watchdog.c
+
+include lib/zlib/zlib.mk
+PLAT_INCLUDES += -Ilib/zlib
+BL2_SOURCES += $(ZLIB_SOURCES)
+
+BL31_SOURCES += \
+ drivers/arm/cci/cci.c \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/intel/soc/agilex/bl31_plat_setup.c \
+ plat/intel/soc/agilex/soc/agilex_clock_manager.c \
+ plat/intel/soc/common/socfpga_psci.c \
+ plat/intel/soc/common/socfpga_sip_svc.c \
+ plat/intel/soc/common/socfpga_sip_svc_v2.c \
+ plat/intel/soc/common/socfpga_topology.c \
+ plat/intel/soc/common/sip/socfpga_sip_ecc.c \
+ plat/intel/soc/common/sip/socfpga_sip_fcs.c \
+ plat/intel/soc/common/soc/socfpga_mailbox.c \
+ plat/intel/soc/common/soc/socfpga_reset_manager.c
+
+PROGRAMMABLE_RESET_ADDRESS := 0
+BL2_AT_EL3 := 1
+BL2_INV_DCACHE := 0
+MULTI_CONSOLE_API := 1
+USE_COHERENT_MEM := 1
diff --git a/plat/intel/soc/agilex/soc/agilex_clock_manager.c b/plat/intel/soc/agilex/soc/agilex_clock_manager.c
new file mode 100644
index 0000000..76b9937
--- /dev/null
+++ b/plat/intel/soc/agilex/soc/agilex_clock_manager.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <lib/mmio.h>
+
+#include "agilex_clock_manager.h"
+#include "socfpga_handoff.h"
+#include "socfpga_system_manager.h"
+
+
+uint32_t wait_pll_lock(void)
+{
+ uint32_t data;
+ uint32_t count = 0;
+
+ do {
+ data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
+ count++;
+ if (count >= 1000)
+ return -ETIMEDOUT;
+
+ } while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) ||
+ (CLKMGR_STAT_PERPLLLOCKED(data) == 0));
+ return 0;
+}
+
+uint32_t wait_fsm(void)
+{
+ uint32_t data;
+ uint32_t count = 0;
+
+ do {
+ data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
+ count++;
+ if (count >= 1000)
+ return -ETIMEDOUT;
+
+ } while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY);
+
+ return 0;
+}
+
+uint32_t pll_source_sync_config(uint32_t pll_mem_offset, uint32_t data)
+{
+ uint32_t val = 0;
+ uint32_t count = 0;
+ uint32_t req_status = 0;
+
+ val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ |
+ (data << CLKMGR_MEM_WDAT_OFFSET) | CLKMGR_MEM_ADDR);
+ mmio_write_32(pll_mem_offset, val);
+
+ do {
+ req_status = mmio_read_32(pll_mem_offset);
+ count++;
+ } while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
+
+ if (count >= 100)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+uint32_t pll_source_sync_read(uint32_t pll_mem_offset)
+{
+ uint32_t val = 0;
+ uint32_t rdata = 0;
+ uint32_t count = 0;
+ uint32_t req_status = 0;
+
+ val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR);
+ mmio_write_32(pll_mem_offset, val);
+
+ do {
+ req_status = mmio_read_32(pll_mem_offset);
+ count++;
+ } while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
+
+ if (count >= 100)
+ return -ETIMEDOUT;
+
+ rdata = mmio_read_32(pll_mem_offset + 0x4);
+ INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata);
+
+ return rdata;
+}
+
+void config_clkmgr_handoff(handoff *hoff_ptr)
+{
+ uint32_t mdiv, mscnt, hscnt;
+ uint32_t drefclk_div, refclk_div, rdata;
+
+ /* Set clock maanger into boot mode before running configuration */
+ mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_CTRL,
+ CLKMGR_CTRL_BOOTMODE_SET_MSK);
+ /* Bypass all mainpllgrp's clocks */
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7);
+ wait_fsm();
+
+ /* Bypass all perpllgrp's clocks */
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0x7f);
+ wait_fsm();
+
+ /* Put both PLL in reset and power down */
+ mmio_clrbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_SET_MSK |
+ CLKMGR_PLLGLOB_RST_SET_MSK);
+ mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_SET_MSK |
+ CLKMGR_PLLGLOB_RST_SET_MSK);
+
+ /* Setup main PLL dividers */
+ mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->main_pll_pllm);
+
+ drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
+ hoff_ptr->main_pll_pllglob);
+ refclk_div = CLKMGR_PLLGLOB_REFCLKDIV(
+ hoff_ptr->main_pll_pllglob);
+
+ mscnt = 100 / (mdiv * BIT(drefclk_div));
+ if (!mscnt)
+ mscnt = 1;
+ hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4;
+
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
+ hoff_ptr->main_pll_pllglob &
+ ~CLKMGR_PLLGLOB_RST_SET_MSK);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK,
+ hoff_ptr->main_pll_fdbck);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB,
+ CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
+ CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0,
+ hoff_ptr->main_pll_pllc0);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1,
+ hoff_ptr->main_pll_pllc1);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC2,
+ hoff_ptr->main_pll_pllc2);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC3,
+ hoff_ptr->main_pll_pllc3);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM,
+ hoff_ptr->main_pll_pllm);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MPUCLK,
+ hoff_ptr->main_pll_mpuclk);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK,
+ hoff_ptr->main_pll_nocclk);
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV,
+ hoff_ptr->main_pll_nocdiv);
+
+ /* Setup peripheral PLL dividers */
+ mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->per_pll_pllm);
+
+ drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
+ hoff_ptr->per_pll_pllglob);
+ refclk_div = CLKMGR_PLLGLOB_REFCLKDIV(
+ hoff_ptr->per_pll_pllglob);
+
+
+ mscnt = 100 / (mdiv * BIT(drefclk_div));
+ if (!mscnt)
+ mscnt = 1;
+ hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4;
+
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
+ hoff_ptr->per_pll_pllglob &
+ ~CLKMGR_PLLGLOB_RST_SET_MSK);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK,
+ hoff_ptr->per_pll_fdbck);
+
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB,
+ CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
+ CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
+
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0,
+ hoff_ptr->per_pll_pllc0);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1,
+ hoff_ptr->per_pll_pllc1);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC2,
+ hoff_ptr->per_pll_pllc2);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC3,
+ hoff_ptr->per_pll_pllc3);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM,
+ hoff_ptr->per_pll_pllm);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL,
+ hoff_ptr->per_pll_emacctl);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV,
+ hoff_ptr->per_pll_gpiodiv);
+
+ /* Take both PLL out of reset and power up */
+ mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_SET_MSK |
+ CLKMGR_PLLGLOB_RST_SET_MSK);
+ mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_SET_MSK |
+ CLKMGR_PLLGLOB_RST_SET_MSK);
+
+ rdata = pll_source_sync_read(CLKMGR_MAINPLL +
+ CLKMGR_MAINPLL_MEM);
+ pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM,
+ rdata | 0x80);
+
+ rdata = pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
+ pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM,
+ rdata | 0x80);
+
+ wait_pll_lock();
+
+ /*Configure Ping Pong counters in altera group */
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR,
+ hoff_ptr->alt_emacactr);
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACBCTR,
+ hoff_ptr->alt_emacbctr);
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACPTPCTR,
+ hoff_ptr->alt_emacptpctr);
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_GPIODBCTR,
+ hoff_ptr->alt_gpiodbctr);
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR,
+ hoff_ptr->alt_sdmmcctr);
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER0CTR,
+ hoff_ptr->alt_s2fuser0ctr);
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_S2FUSER1CTR,
+ hoff_ptr->alt_s2fuser1ctr);
+ mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_PSIREFCTR,
+ hoff_ptr->alt_psirefctr);
+
+ /* Clear lost lock bypass mode */
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_LOSTLOCK, 0x1);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_LOSTLOCK, 0x1);
+
+ mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
+ CLKMGR_CLR_LOSTLOCK_BYPASS);
+
+ mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
+ CLKMGR_CLR_LOSTLOCK_BYPASS);
+
+ /* Take all PLLs out of bypass */
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0);
+ wait_fsm();
+
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0);
+ wait_fsm();
+
+ /* Clear loss lock interrupt status register that */
+ /* might be set during configuration */
+ mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR,
+ CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK |
+ CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK);
+
+ /* Take all ping pong counters out of reset */
+ mmio_clrbits_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EXTCNTRST,
+ CLKMGR_ALTERA_EXTCNTRST_RESET);
+
+ /* Set safe mode / out of boot mode */
+ mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_CTRL,
+ CLKMGR_CTRL_BOOTMODE_SET_MSK);
+ wait_fsm();
+
+ /* Enable mainpllgrp's software-managed clock */
+ mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN,
+ CLKMGR_MAINPLL_EN_RESET);
+ mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
+ CLKMGR_PERPLL_EN_RESET);
+
+ /* Pass clock source frequency into scratch register */
+ mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1),
+ hoff_ptr->hps_osc_clk_h);
+ mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2),
+ hoff_ptr->fpga_clk_hz);
+}
+
+/* Extract reference clock from platform clock source */
+uint32_t get_ref_clk(uint32_t pllglob)
+{
+ uint32_t arefclkdiv, ref_clk;
+ uint32_t scr_reg;
+
+ switch (CLKMGR_PSRC(pllglob)) {
+ case CLKMGR_PLLGLOB_PSRC_EOSC1:
+ scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
+ ref_clk = mmio_read_32(scr_reg);
+ break;
+ case CLKMGR_PLLGLOB_PSRC_INTOSC:
+ ref_clk = CLKMGR_INTOSC_HZ;
+ break;
+ case CLKMGR_PLLGLOB_PSRC_F2S:
+ scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
+ ref_clk = mmio_read_32(scr_reg);
+ break;
+ default:
+ ref_clk = 0;
+ assert(0);
+ break;
+ }
+
+ arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob);
+ ref_clk /= arefclkdiv;
+
+ return ref_clk;
+}
+
+/* Calculate clock frequency based on parameter */
+uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc)
+{
+ uint32_t clk_psrc, mdiv, ref_clk;
+ uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg;
+
+ clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg);
+
+ switch (CLKMGR_PSRC(clk_psrc)) {
+ case CLKMGR_PSRC_MAIN:
+ pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM;
+ pllc_reg = CLKMGR_MAINPLL + main_pllc;
+ pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB;
+ break;
+ case CLKMGR_PSRC_PER:
+ pllm_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM;
+ pllc_reg = CLKMGR_PERPLL + per_pllc;
+ pllglob_reg = CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB;
+ break;
+ default:
+ return 0;
+ }
+
+ ref_clk = get_ref_clk(mmio_read_32(pllglob_reg));
+ mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg));
+ ref_clk *= mdiv;
+
+ pllc_div = mmio_read_32(pllc_reg) & 0x7ff;
+
+ return ref_clk / pllc_div;
+}
+
+/* Return L3 interconnect clock */
+uint32_t get_l3_clk(void)
+{
+ uint32_t l3_clk;
+
+ l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1,
+ CLKMGR_PERPLL_PLLC1);
+ return l3_clk;
+}
+
+/* Calculate clock frequency to be used for watchdog timer */
+uint32_t get_wdt_clk(void)
+{
+ uint32_t l3_clk, l4_sys_clk;
+
+ l3_clk = get_l3_clk();
+ l4_sys_clk = l3_clk / 4;
+
+ return l4_sys_clk;
+}
+
+/* Calculate clock frequency to be used for UART driver */
+uint32_t get_uart_clk(void)
+{
+ uint32_t data32, l3_clk, l4_sp_clk;
+
+ l3_clk = get_l3_clk();
+
+ data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV);
+ data32 = (data32 >> 16) & 0x3;
+
+ l4_sp_clk = l3_clk >> data32;
+
+ return l4_sp_clk;
+}
+
+/* Calculate clock frequency to be used for SDMMC driver */
+uint32_t get_mmc_clk(void)
+{
+ uint32_t data32, mmc_clk;
+
+ mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR,
+ CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3);
+
+ data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR);
+ data32 = (data32 & 0x7ff) + 1;
+ mmc_clk = (mmc_clk / data32) / 4;
+
+ return mmc_clk;
+}
+
+/* Get cpu freq clock */
+uint32_t get_cpu_clk(void)
+{
+ uint32_t cpu_clk;
+
+ cpu_clk = get_l3_clk()/PLAT_SYS_COUNTER_CONVERT_TO_MHZ;
+
+ return cpu_clk;
+}
diff --git a/plat/intel/soc/agilex/soc/agilex_memory_controller.c b/plat/intel/soc/agilex/soc/agilex_memory_controller.c
new file mode 100644
index 0000000..2aabe87
--- /dev/null
+++ b/plat/intel/soc/agilex/soc/agilex_memory_controller.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <platform_def.h>
+
+#include "agilex_memory_controller.h"
+
+#define ALT_CCU_NOC_DI_SET_MSK 0x10
+
+#define DDR_READ_LATENCY_DELAY 40
+#define MAX_MEM_CAL_RETRY 3
+#define PRE_CALIBRATION_DELAY 1
+#define POST_CALIBRATION_DELAY 1
+#define TIMEOUT_EMIF_CALIBRATION 1000
+#define CLEAR_EMIF_DELAY 1000
+#define CLEAR_EMIF_TIMEOUT 1000
+
+#define DDR_CONFIG(A, B, C, R) (((A) << 24) | ((B) << 16) | ((C) << 8) | (R))
+#define DDR_CONFIG_ELEMENTS (sizeof(ddr_config)/sizeof(uint32_t))
+
+/* tWR = Min. 15ns constant, see JEDEC standard eg. DDR4 is JESD79-4.pdf */
+#define tWR_IN_NS 15
+
+void configure_hmc_adaptor_regs(void);
+void configure_ddr_sched_ctrl_regs(void);
+
+/* The followring are the supported configurations */
+uint32_t ddr_config[] = {
+ /* DDR_CONFIG(Address order,Bank,Column,Row) */
+ /* List for DDR3 or LPDDR3 (pinout order > chip, row, bank, column) */
+ DDR_CONFIG(0, 3, 10, 12),
+ DDR_CONFIG(0, 3, 9, 13),
+ DDR_CONFIG(0, 3, 10, 13),
+ DDR_CONFIG(0, 3, 9, 14),
+ DDR_CONFIG(0, 3, 10, 14),
+ DDR_CONFIG(0, 3, 10, 15),
+ DDR_CONFIG(0, 3, 11, 14),
+ DDR_CONFIG(0, 3, 11, 15),
+ DDR_CONFIG(0, 3, 10, 16),
+ DDR_CONFIG(0, 3, 11, 16),
+ DDR_CONFIG(0, 3, 12, 15), /* 0xa */
+ /* List for DDR4 only (pinout order > chip, bank, row, column) */
+ DDR_CONFIG(1, 3, 10, 14),
+ DDR_CONFIG(1, 4, 10, 14),
+ DDR_CONFIG(1, 3, 10, 15),
+ DDR_CONFIG(1, 4, 10, 15),
+ DDR_CONFIG(1, 3, 10, 16),
+ DDR_CONFIG(1, 4, 10, 16),
+ DDR_CONFIG(1, 3, 10, 17),
+ DDR_CONFIG(1, 4, 10, 17),
+};
+
+static int match_ddr_conf(uint32_t ddr_conf)
+{
+ int i;
+
+ for (i = 0; i < DDR_CONFIG_ELEMENTS; i++) {
+ if (ddr_conf == ddr_config[i])
+ return i;
+ }
+ return 0;
+}
+
+static int check_hmc_clk(void)
+{
+ unsigned long timeout = 0;
+ uint32_t hmc_clk;
+
+ do {
+ hmc_clk = mmio_read_32(AGX_SYSMGR_CORE_HMC_CLK);
+ if (hmc_clk & AGX_SYSMGR_CORE_HMC_CLK_STATUS)
+ break;
+ udelay(1);
+ } while (++timeout < 1000);
+ if (timeout >= 1000)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int clear_emif(void)
+{
+ uint32_t data;
+ unsigned long timeout;
+
+ mmio_write_32(AGX_MPFE_HMC_ADP_RSTHANDSHAKECTRL, 0);
+
+ timeout = 0;
+ do {
+ data = mmio_read_32(AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT);
+ if ((data & AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE) == 0)
+ break;
+ udelay(CLEAR_EMIF_DELAY);
+ } while (++timeout < CLEAR_EMIF_TIMEOUT);
+ if (timeout >= CLEAR_EMIF_TIMEOUT)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int mem_calibration(void)
+{
+ int status;
+ uint32_t data;
+ unsigned long timeout;
+ unsigned long retry = 0;
+
+ udelay(PRE_CALIBRATION_DELAY);
+
+ do {
+ if (retry != 0)
+ INFO("DDR: Retrying DRAM calibration\n");
+
+ timeout = 0;
+ do {
+ data = mmio_read_32(AGX_MPFE_HMC_ADP_DDRCALSTAT);
+ if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 1)
+ break;
+ udelay(500);
+ } while (++timeout < TIMEOUT_EMIF_CALIBRATION);
+
+ if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) {
+ status = clear_emif();
+ if (status)
+ ERROR("Failed to clear Emif\n");
+ } else {
+ break;
+ }
+ } while (++retry < MAX_MEM_CAL_RETRY);
+
+ if (AGX_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) {
+ ERROR("DDR: DRAM calibration failed.\n");
+ status = -EIO;
+ } else {
+ INFO("DDR: DRAM calibration success.\n");
+ status = 0;
+ }
+
+ udelay(POST_CALIBRATION_DELAY);
+
+ return status;
+}
+
+int init_hard_memory_controller(void)
+{
+ int status;
+
+ status = check_hmc_clk();
+ if (status) {
+ ERROR("DDR: Error, HMC clock not running\n");
+ return status;
+ }
+
+ status = mem_calibration();
+ if (status) {
+ ERROR("DDR: Memory Calibration Failed\n");
+ return status;
+ }
+
+ configure_hmc_adaptor_regs();
+
+ return 0;
+}
+
+void configure_ddr_sched_ctrl_regs(void)
+{
+ uint32_t data, dram_addr_order, ddr_conf, bank, row, col,
+ rd_to_miss, wr_to_miss, burst_len, burst_len_ddr_clk,
+ burst_len_sched_clk, act_to_act, rd_to_wr, wr_to_rd, bw_ratio,
+ t_rtp, t_rp, t_rcd, rd_latency, tw_rin_clk_cycles,
+ bw_ratio_extended, auto_precharge = 0, act_to_act_bank, faw,
+ faw_bank, bus_rd_to_rd, bus_rd_to_wr, bus_wr_to_rd;
+
+ INFO("Init HPS NOC's DDR Scheduler.\n");
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG1);
+ dram_addr_order = AGX_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(data);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_DRAMADDRW);
+
+ col = IOHMC_DRAMADDRW_COL_ADDR_WIDTH(data);
+ row = IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(data);
+ bank = IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(data);
+
+ ddr_conf = match_ddr_conf(DDR_CONFIG(dram_addr_order, bank, col, row));
+
+ if (ddr_conf) {
+ mmio_clrsetbits_32(
+ AGX_MPFE_DDR_MAIN_SCHED_DDRCONF,
+ AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK,
+ AGX_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(ddr_conf));
+ } else {
+ ERROR("DDR: Cannot find predefined ddrConf configuration.\n");
+ }
+
+ mmio_write_32(AGX_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_DRAMTIMING0);
+ rd_latency = AGX_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(data);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING0);
+ act_to_act = ACT_TO_ACT(data);
+ t_rcd = ACT_TO_RDWR(data);
+ act_to_act_bank = ACT_TO_ACT_DIFF_BANK(data);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING1);
+ rd_to_wr = RD_TO_WR(data);
+ bus_rd_to_rd = RD_TO_RD_DIFF_CHIP(data);
+ bus_rd_to_wr = RD_TO_WR_DIFF_CHIP(data);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING2);
+ t_rtp = RD_TO_PCH(data);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING3);
+ wr_to_rd = CALTIMING3_WR_TO_RD(data);
+ bus_wr_to_rd = CALTIMING3_WR_TO_RD_DIFF_CHIP(data);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING4);
+ t_rp = PCH_TO_VALID(data);
+
+ data = mmio_read_32(AGX_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL));
+ bw_ratio = ((HMC_ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 0 : 1);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG0);
+ burst_len = HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(data);
+ burst_len_ddr_clk = burst_len / 2;
+ burst_len_sched_clk = ((burst_len/2) / 2);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG0);
+ switch (AGX_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(data)) {
+ case 1:
+ /* DDR4 - 1333MHz */
+ /* 20 (19.995) clock cycles = 15ns */
+ /* Calculate with rounding */
+ tw_rin_clk_cycles = (((tWR_IN_NS * 1333) % 1000) >= 500) ?
+ ((tWR_IN_NS * 1333) / 1000) + 1 :
+ ((tWR_IN_NS * 1333) / 1000);
+ break;
+ default:
+ /* Others - 1066MHz or slower */
+ /* 16 (15.990) clock cycles = 15ns */
+ /* Calculate with rounding */
+ tw_rin_clk_cycles = (((tWR_IN_NS * 1066) % 1000) >= 500) ?
+ ((tWR_IN_NS * 1066) / 1000) + 1 :
+ ((tWR_IN_NS * 1066) / 1000);
+ break;
+ }
+
+ rd_to_miss = t_rtp + t_rp + t_rcd - burst_len_sched_clk;
+ wr_to_miss = ((rd_latency + burst_len_ddr_clk + 2 + tw_rin_clk_cycles)
+ / 2) - rd_to_wr + t_rp + t_rcd;
+
+ mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DDRTIMING,
+ bw_ratio << DDRTIMING_BWRATIO_OFST |
+ wr_to_rd << DDRTIMING_WRTORD_OFST|
+ rd_to_wr << DDRTIMING_RDTOWR_OFST |
+ burst_len_sched_clk << DDRTIMING_BURSTLEN_OFST |
+ wr_to_miss << DDRTIMING_WRTOMISS_OFST |
+ rd_to_miss << DDRTIMING_RDTOMISS_OFST |
+ act_to_act << DDRTIMING_ACTTOACT_OFST);
+
+ data = mmio_read_32(AGX_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL));
+ bw_ratio_extended = ((ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 1 : 0);
+
+ mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DDRMODE,
+ bw_ratio_extended << DDRMODE_BWRATIOEXTENDED_OFST |
+ auto_precharge << DDRMODE_AUTOPRECHARGE_OFST);
+
+ mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_READLATENCY,
+ (rd_latency / 2) + DDR_READ_LATENCY_DELAY);
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CALTIMING9);
+ faw = AGX_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(data);
+
+ faw_bank = 1; // always 1 because we always have 4 bank DDR.
+
+ mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE,
+ faw_bank << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST |
+ faw << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST |
+ act_to_act_bank << AGX_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST);
+
+ mmio_write_32(AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV,
+ ((bus_rd_to_rd
+ << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST)
+ & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK) |
+ ((bus_rd_to_wr
+ << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST)
+ & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK) |
+ ((bus_wr_to_rd
+ << AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST)
+ & AGX_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK));
+
+}
+
+unsigned long get_physical_dram_size(void)
+{
+ uint32_t data;
+ unsigned long ram_addr_width, ram_ext_if_io_width;
+
+ data = mmio_read_32(AGX_MPFE_HMC_ADP_DDRIOCTRL);
+ switch (AGX_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(data)) {
+ case 0:
+ ram_ext_if_io_width = 16;
+ break;
+ case 1:
+ ram_ext_if_io_width = 32;
+ break;
+ case 2:
+ ram_ext_if_io_width = 64;
+ break;
+ default:
+ ram_ext_if_io_width = 0;
+ break;
+ }
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_REG_DRAMADDRW);
+ ram_addr_width = IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(data);
+
+ return (1 << ram_addr_width) * (ram_ext_if_io_width / 8);
+}
+
+
+
+void configure_hmc_adaptor_regs(void)
+{
+ uint32_t data;
+ uint32_t dram_io_width;
+
+ /* Configure DDR data rate */
+ dram_io_width = AGX_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0(
+ mmio_read_32(AGX_MPFE_IOHMC_REG_NIOSRESERVE0_OFST));
+ dram_io_width = (dram_io_width & 0xFF) >> 5;
+
+ data = mmio_read_32(AGX_MPFE_IOHMC_CTRLCFG3);
+
+ dram_io_width |= (data & 0x4);
+
+ mmio_write_32(AGX_MPFE_HMC_ADP_DDRIOCTRL, dram_io_width);
+
+ /* Copy dram addr width from IOHMC to HMC ADP */
+ data = mmio_read_32(AGX_MPFE_IOHMC_DRAMADDRW);
+ mmio_write_32(AGX_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data);
+
+ /* Enable nonsecure access to DDR */
+ data = get_physical_dram_size();
+
+ if (data < AGX_DDR_SIZE)
+ data = AGX_DDR_SIZE;
+
+ mmio_write_32(AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT, data - 1);
+ mmio_write_32(AGX_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT, 0x1f);
+
+ mmio_write_32(AGX_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT, data - 1);
+
+ mmio_write_32(AGX_SOC_NOC_FW_DDR_SCR_ENABLESET, BIT(0) | BIT(8));
+
+ /* ECC enablement */
+ data = mmio_read_32(AGX_MPFE_IOHMC_REG_CTRLCFG1);
+ if (data & (1 << AGX_IOHMC_CTRLCFG1_ENABLE_ECC_OFST)) {
+ mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL1,
+ AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK,
+ AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK);
+
+ mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL2,
+ AGX_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK,
+ AGX_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK);
+
+ mmio_clrsetbits_32(AGX_MPFE_HMC_ADP_ECCCTRL1,
+ AGX_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK |
+ AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK,
+ AGX_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK);
+ INFO("Scrubbing ECC\n");
+
+ /* ECC Scrubbing */
+ zeromem(DRAM_BASE, DRAM_SIZE);
+ } else {
+ INFO("ECC is disabled.\n");
+ }
+}
diff --git a/plat/intel/soc/agilex/soc/agilex_mmc.c b/plat/intel/soc/agilex/soc/agilex_mmc.c
new file mode 100644
index 0000000..e05d92a
--- /dev/null
+++ b/plat/intel/soc/agilex/soc/agilex_mmc.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <lib/mmio.h>
+
+#include "socfpga_system_manager.h"
+#include "agilex_clock_manager.h"
+
+void agx_mmc_init(void)
+{
+ mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
+ CLKMGR_PERPLL_EN_SDMMCCLK);
+ mmio_write_32(SOCFPGA_SYSMGR(SDMMC),
+ SYSMGR_SDMMC_SMPLSEL(0) | SYSMGR_SDMMC_DRVSEL(3));
+ mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
+ CLKMGR_PERPLL_EN_SDMMCCLK);
+}
diff --git a/plat/intel/soc/agilex/soc/agilex_pinmux.c b/plat/intel/soc/agilex/soc/agilex_pinmux.c
new file mode 100644
index 0000000..0b908cf
--- /dev/null
+++ b/plat/intel/soc/agilex/soc/agilex_pinmux.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include "agilex_pinmux.h"
+#include "socfpga_system_manager.h"
+
+const uint32_t sysmgr_pinmux_array_sel[] = {
+ 0x00000000, 0x00000001, /* usb */
+ 0x00000004, 0x00000001,
+ 0x00000008, 0x00000001,
+ 0x0000000c, 0x00000001,
+ 0x00000010, 0x00000001,
+ 0x00000014, 0x00000001,
+ 0x00000018, 0x00000001,
+ 0x0000001c, 0x00000001,
+ 0x00000020, 0x00000001,
+ 0x00000024, 0x00000001,
+ 0x00000028, 0x00000001,
+ 0x0000002c, 0x00000001,
+ 0x00000030, 0x00000000, /* emac0 */
+ 0x00000034, 0x00000000,
+ 0x00000038, 0x00000000,
+ 0x0000003c, 0x00000000,
+ 0x00000040, 0x00000000,
+ 0x00000044, 0x00000000,
+ 0x00000048, 0x00000000,
+ 0x0000004c, 0x00000000,
+ 0x00000050, 0x00000000,
+ 0x00000054, 0x00000000,
+ 0x00000058, 0x00000000,
+ 0x0000005c, 0x00000000,
+ 0x00000060, 0x00000008, /* gpio1 */
+ 0x00000064, 0x00000008,
+ 0x00000068, 0x00000005, /* uart0 tx */
+ 0x0000006c, 0x00000005, /* uart 0 rx */
+ 0x00000070, 0x00000008, /* gpio */
+ 0x00000074, 0x00000008,
+ 0x00000078, 0x00000004, /* i2c1 */
+ 0x0000007c, 0x00000004,
+ 0x00000080, 0x00000007, /* jtag */
+ 0x00000084, 0x00000007,
+ 0x00000088, 0x00000007,
+ 0x0000008c, 0x00000007,
+ 0x00000090, 0x00000001, /* sdmmc data0 */
+ 0x00000094, 0x00000001,
+ 0x00000098, 0x00000001,
+ 0x0000009c, 0x00000001,
+ 0x00000100, 0x00000001,
+ 0x00000104, 0x00000001, /* sdmmc.data3 */
+ 0x00000108, 0x00000008, /* loan */
+ 0x0000010c, 0x00000008, /* gpio */
+ 0x00000110, 0x00000008,
+ 0x00000114, 0x00000008, /* gpio1.io21 */
+ 0x00000118, 0x00000005, /* mdio0.mdio */
+ 0x0000011c, 0x00000005 /* mdio0.mdc */
+};
+
+const uint32_t sysmgr_pinmux_array_ctrl[] = {
+ 0x00000000, 0x00502c38, /* Q1_1 */
+ 0x00000004, 0x00102c38,
+ 0x00000008, 0x00502c38,
+ 0x0000000c, 0x00502c38,
+ 0x00000010, 0x00502c38,
+ 0x00000014, 0x00502c38,
+ 0x00000018, 0x00502c38,
+ 0x0000001c, 0x00502c38,
+ 0x00000020, 0x00502c38,
+ 0x00000024, 0x00502c38,
+ 0x00000028, 0x00502c38,
+ 0x0000002c, 0x00502c38,
+ 0x00000030, 0x00102c38, /* Q2_1 */
+ 0x00000034, 0x00102c38,
+ 0x00000038, 0x00502c38,
+ 0x0000003c, 0x00502c38,
+ 0x00000040, 0x00102c38,
+ 0x00000044, 0x00102c38,
+ 0x00000048, 0x00502c38,
+ 0x0000004c, 0x00502c38,
+ 0x00000050, 0x00102c38,
+ 0x00000054, 0x00102c38,
+ 0x00000058, 0x00502c38,
+ 0x0000005c, 0x00502c38,
+ 0x00000060, 0x00502c38, /* Q3_1 */
+ 0x00000064, 0x00502c38,
+ 0x00000068, 0x00102c38,
+ 0x0000006c, 0x00502c38,
+ 0x000000d0, 0x00502c38,
+ 0x000000d4, 0x00502c38,
+ 0x000000d8, 0x00542c38,
+ 0x000000dc, 0x00542c38,
+ 0x000000e0, 0x00502c38,
+ 0x000000e4, 0x00502c38,
+ 0x000000e8, 0x00102c38,
+ 0x000000ec, 0x00502c38,
+ 0x000000f0, 0x00502c38, /* Q4_1 */
+ 0x000000f4, 0x00502c38,
+ 0x000000f8, 0x00102c38,
+ 0x000000fc, 0x00502c38,
+ 0x00000100, 0x00502c38,
+ 0x00000104, 0x00502c38,
+ 0x00000108, 0x00102c38,
+ 0x0000010c, 0x00502c38,
+ 0x00000110, 0x00502c38,
+ 0x00000114, 0x00502c38,
+ 0x00000118, 0x00542c38,
+ 0x0000011c, 0x00102c38
+};
+
+const uint32_t sysmgr_pinmux_array_fpga[] = {
+ 0x00000000, 0x00000000,
+ 0x00000004, 0x00000000,
+ 0x00000008, 0x00000000,
+ 0x0000000c, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000014, 0x00000000,
+ 0x00000018, 0x00000000,
+ 0x0000001c, 0x00000000,
+ 0x00000020, 0x00000000,
+ 0x00000028, 0x00000000,
+ 0x0000002c, 0x00000000,
+ 0x00000030, 0x00000000,
+ 0x00000034, 0x00000000,
+ 0x00000038, 0x00000000,
+ 0x0000003c, 0x00000000,
+ 0x00000040, 0x00000000,
+ 0x00000044, 0x00000000,
+ 0x00000048, 0x00000000,
+ 0x00000050, 0x00000000,
+ 0x00000054, 0x00000000,
+ 0x00000058, 0x0000002a
+};
+
+const uint32_t sysmgr_pinmux_array_iodelay[] = {
+ 0x00000000, 0x00000000,
+ 0x00000004, 0x00000000,
+ 0x00000008, 0x00000000,
+ 0x0000000c, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000014, 0x00000000,
+ 0x00000018, 0x00000000,
+ 0x0000001c, 0x00000000,
+ 0x00000020, 0x00000000,
+ 0x00000024, 0x00000000,
+ 0x00000028, 0x00000000,
+ 0x0000002c, 0x00000000,
+ 0x00000030, 0x00000000,
+ 0x00000034, 0x00000000,
+ 0x00000038, 0x00000000,
+ 0x0000003c, 0x00000000,
+ 0x00000040, 0x00000000,
+ 0x00000044, 0x00000000,
+ 0x00000048, 0x00000000,
+ 0x0000004c, 0x00000000,
+ 0x00000050, 0x00000000,
+ 0x00000054, 0x00000000,
+ 0x00000058, 0x00000000,
+ 0x0000005c, 0x00000000,
+ 0x00000060, 0x00000000,
+ 0x00000064, 0x00000000,
+ 0x00000068, 0x00000000,
+ 0x0000006c, 0x00000000,
+ 0x00000070, 0x00000000,
+ 0x00000074, 0x00000000,
+ 0x00000078, 0x00000000,
+ 0x0000007c, 0x00000000,
+ 0x00000080, 0x00000000,
+ 0x00000084, 0x00000000,
+ 0x00000088, 0x00000000,
+ 0x0000008c, 0x00000000,
+ 0x00000090, 0x00000000,
+ 0x00000094, 0x00000000,
+ 0x00000098, 0x00000000,
+ 0x0000009c, 0x00000000,
+ 0x00000100, 0x00000000,
+ 0x00000104, 0x00000000,
+ 0x00000108, 0x00000000,
+ 0x0000010c, 0x00000000,
+ 0x00000110, 0x00000000,
+ 0x00000114, 0x00000000,
+ 0x00000118, 0x00000000,
+ 0x0000011c, 0x00000000
+};
+
+void config_fpgaintf_mod(void)
+{
+ mmio_write_32(SOCFPGA_SYSMGR(FPGAINTF_EN_2), 1<<8);
+}
+
+
+void config_pinmux(handoff *hoff_ptr)
+{
+ unsigned int i;
+
+ for (i = 0; i < 96; i += 2) {
+ mmio_write_32(AGX_PINMUX_PIN0SEL +
+ hoff_ptr->pinmux_sel_array[i],
+ hoff_ptr->pinmux_sel_array[i+1]);
+ }
+
+ for (i = 0; i < 96; i += 2) {
+ mmio_write_32(AGX_PINMUX_IO0CTRL +
+ hoff_ptr->pinmux_io_array[i],
+ hoff_ptr->pinmux_io_array[i+1]);
+ }
+
+ for (i = 0; i < 42; i += 2) {
+ mmio_write_32(AGX_PINMUX_PINMUX_EMAC0_USEFPGA +
+ hoff_ptr->pinmux_fpga_array[i],
+ hoff_ptr->pinmux_fpga_array[i+1]);
+ }
+
+ for (i = 0; i < 96; i += 2) {
+ mmio_write_32(AGX_PINMUX_IO0_DELAY +
+ hoff_ptr->pinmux_iodelay_array[i],
+ hoff_ptr->pinmux_iodelay_array[i+1]);
+ }
+
+ config_fpgaintf_mod();
+}
+
diff --git a/plat/intel/soc/common/aarch64/plat_helpers.S b/plat/intel/soc/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..213fd3c
--- /dev/null
+++ b/plat/intel/soc/common/aarch64/plat_helpers.S
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+#include <platform_def.h>
+#include <el3_common_macros.S>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl platform_is_primary_cpu
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl platform_mem_init
+ .globl plat_secondary_cpus_bl31_entry
+
+ .globl plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* Wait until the it gets reset signal from rstmgr gets populated */
+poll_mailbox:
+ wfi
+ mov_imm x0, PLAT_SEC_ENTRY
+ ldr x1, [x0]
+ mov_imm x2, PLAT_CPUID_RELEASE
+ ldr x3, [x2]
+ mrs x4, mpidr_el1
+ and x4, x4, #0xff
+ cmp x3, x4
+ b.ne poll_mailbox
+ br x1
+endfunc plat_secondary_cold_boot_setup
+
+func platform_is_primary_cpu
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc platform_is_primary_cpu
+
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ b platform_is_primary_cpu
+endfunc plat_is_my_cpu_primary
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
+
+func warm_reset_req
+ str xzr, [x4]
+ bl plat_is_my_cpu_primary
+ cbz x0, cpu_in_wfi
+ mov_imm x1, PLAT_SEC_ENTRY
+ str xzr, [x1]
+ mrs x1, rmr_el3
+ orr x1, x1, #0x02
+ msr rmr_el3, x1
+ isb
+ dsb sy
+cpu_in_wfi:
+ wfi
+ b cpu_in_wfi
+endfunc warm_reset_req
+
+func plat_get_my_entrypoint
+ ldr x4, =L2_RESET_DONE_REG
+ ldr x5, [x4]
+ ldr x1, =L2_RESET_DONE_STATUS
+ cmp x1, x5
+ b.eq warm_reset_req
+ mov_imm x1, PLAT_SEC_ENTRY
+ ldr x0, [x1]
+ ret
+endfunc plat_get_my_entrypoint
+
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, CRASH_CONSOLE_BASE
+ mov_imm x1, PLAT_UART_CLOCK
+ mov_imm x2, PLAT_BAUDRATE
+ b console_16550_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(void)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, CRASH_CONSOLE_BASE
+ b console_16550_core_putc
+endfunc plat_crash_console_putc
+
+func plat_crash_console_flush
+ mov_imm x0, CRASH_CONSOLE_BASE
+ b console_16550_core_flush
+endfunc plat_crash_console_flush
+
+
+ /* --------------------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * Any memory init, relocation to be done before the
+ * platform boots. Called very early in the boot process.
+ * --------------------------------------------------------
+ */
+func platform_mem_init
+ mov x0, #0
+ ret
+endfunc platform_mem_init
+
+func plat_secondary_cpus_bl31_entry
+ el3_entrypoint_common \
+ _init_sctlr=0 \
+ _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
+ _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
+ _init_memory=1 \
+ _init_c_runtime=1 \
+ _exception_vectors=runtime_exceptions \
+ _pie_fixup_size=BL31_LIMIT - BL31_BASE
+endfunc plat_secondary_cpus_bl31_entry
diff --git a/plat/intel/soc/common/aarch64/platform_common.c b/plat/intel/soc/common/aarch64/platform_common.c
new file mode 100644
index 0000000..b79a63c
--- /dev/null
+++ b/plat/intel/soc/common/aarch64/platform_common.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <platform_def.h>
+#include <plat/common/platform.h>
+
+#include "socfpga_private.h"
+
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return PLAT_SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+unsigned long socfpga_get_ns_image_entrypoint(void)
+{
+ return PLAT_NS_IMAGE_OFFSET;
+}
+
+/******************************************************************************
+ * Gets SPSR for BL32 entry
+ *****************************************************************************/
+uint32_t socfpga_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/******************************************************************************
+ * Gets SPSR for BL33 entry
+ *****************************************************************************/
+uint32_t socfpga_get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
diff --git a/plat/intel/soc/common/bl2_plat_mem_params_desc.c b/plat/intel/soc/common/bl2_plat_mem_params_desc.c
new file mode 100644
index 0000000..187c53a
--- /dev/null
+++ b/plat/intel/soc/common/bl2_plat_mem_params_desc.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <platform_def.h>
+#include <plat/common/platform.h>
+
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+#endif /* EL3_PAYLOAD_BASE */
+
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+ .ep_info.pc = PLAT_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_NS_IMAGE_OFFSET,
+ .image_info.image_max_size =
+ 0x0 + 0x40000000 - PLAT_NS_IMAGE_OFFSET,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/intel/soc/common/drivers/ccu/ncore_ccu.c b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
new file mode 100644
index 0000000..d9a238e
--- /dev/null
+++ b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <errno.h>
+#include <lib/mmio.h>
+
+#include "ncore_ccu.h"
+
+uint32_t poll_active_bit(uint32_t dir);
+
+static coh_ss_id_t subsystem_id;
+
+
+void get_subsystem_id(void)
+{
+ uint32_t snoop_filter, directory, coh_agent;
+
+ snoop_filter = CSIDR_NUM_SF(mmio_read_32(NCORE_CCU_CSR(NCORE_CSIDR)));
+ directory = CSUIDR_NUM_DIR(mmio_read_32(NCORE_CCU_CSR(NCORE_CSUIDR)));
+ coh_agent = CSUIDR_NUM_CAI(mmio_read_32(NCORE_CCU_CSR(NCORE_CSUIDR)));
+
+ subsystem_id.num_snoop_filter = snoop_filter + 1;
+ subsystem_id.num_directory = directory;
+ subsystem_id.num_coh_agent = coh_agent;
+}
+
+uint32_t directory_init(void)
+{
+ uint32_t dir_sf_mtn, dir_sf_en;
+ uint32_t dir, sf, ret;
+
+ for (dir = 0; dir < subsystem_id.num_directory; dir++) {
+ for (sf = 0; sf < subsystem_id.num_snoop_filter; sf++) {
+ dir_sf_mtn = DIRECTORY_UNIT(dir, NCORE_DIRUSFMCR);
+ dir_sf_en = DIRECTORY_UNIT(dir, NCORE_DIRUSFER);
+
+ /* Initialize All Entries */
+ mmio_write_32(dir_sf_mtn, SNOOP_FILTER_ID(dir));
+
+ /* Poll Active Bit */
+ ret = poll_active_bit(dir);
+ if (ret != 0) {
+ ERROR("Timeout during active bit polling");
+ return -ETIMEDOUT;
+ }
+
+ /* Snoope Filter Enable */
+ mmio_setbits_32(dir_sf_en, BIT(sf));
+ }
+ }
+
+ return 0;
+}
+
+uint32_t coherent_agent_intfc_init(void)
+{
+ uint32_t dir, ca, ca_id, ca_type, ca_snoop_en;
+
+ for (dir = 0; dir < subsystem_id.num_directory; dir++) {
+ for (ca = 0; ca < subsystem_id.num_coh_agent; ca++) {
+ ca_snoop_en = DIRECTORY_UNIT(ca, NCORE_DIRUCASER0);
+ ca_id = mmio_read_32(COH_AGENT_UNIT(ca, NCORE_CAIUIDR));
+
+ /* Coh Agent Snoop Enable */
+ if (CACHING_AGENT_BIT(ca_id))
+ mmio_write_32(ca_snoop_en, BIT(ca));
+
+ /* Coh Agent Snoop DVM Enable */
+ ca_type = CACHING_AGENT_TYPE(ca_id);
+ if (ca_type == ACE_W_DVM || ca_type == ACE_L_W_DVM)
+ mmio_write_32(NCORE_CCU_CSR(NCORE_CSADSER0),
+ BIT(ca));
+ }
+ }
+
+ return 0;
+}
+
+uint32_t poll_active_bit(uint32_t dir)
+{
+ uint32_t timeout = 80000;
+ uint32_t poll_dir = DIRECTORY_UNIT(dir, NCORE_DIRUSFMAR);
+
+ while (timeout > 0) {
+ if (mmio_read_32(poll_dir) == 0)
+ return 0;
+ timeout--;
+ }
+
+ return -1;
+}
+
+void bypass_ocram_firewall(void)
+{
+ mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF1),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+ mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF2),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+ mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF3),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+ mmio_clrbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF4),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+}
+
+void ncore_enable_ocram_firewall(void)
+{
+ mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF1),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+ mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF2),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+ mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF3),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+ mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF4),
+ OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+}
+
+uint32_t init_ncore_ccu(void)
+{
+ uint32_t status;
+
+ get_subsystem_id();
+ status = directory_init();
+ status = coherent_agent_intfc_init();
+ bypass_ocram_firewall();
+
+ return status;
+}
diff --git a/plat/intel/soc/common/drivers/ccu/ncore_ccu.h b/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
new file mode 100644
index 0000000..3f662ff
--- /dev/null
+++ b/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NCORE_CCU_H
+#define NCORE_CCU_H
+
+
+#define NCORE_CCU_OFFSET 0xf7000000
+
+
+/* Coherent Sub-System Address Map */
+#define NCORE_CAIU_OFFSET 0x00000
+#define NCORE_CAIU_SIZE 0x01000
+
+#define NCORE_NCBU_OFFSET 0x60000
+#define NCORE_NCBU_SIZE 0x01000
+
+#define NCORE_DIRU_OFFSET 0x80000
+#define NCORE_DIRU_SIZE 0x01000
+
+#define NCORE_CMIU_OFFSET 0xc0000
+#define NCORE_CMIU_SIZE 0x01000
+
+#define NCORE_CSR_OFFSET 0xff000
+#define NCORE_CSADSERO 0x00040
+#define NCORE_CSUIDR 0x00ff8
+#define NCORE_CSIDR 0x00ffc
+
+/* Directory Unit Register Map */
+#define NCORE_DIRUSFER 0x00010
+#define NCORE_DIRUMRHER 0x00070
+#define NCORE_DIRUSFMCR 0x00080
+#define NCORE_DIRUSFMAR 0x00084
+
+/* Coherent Agent Interface Unit Register Map */
+#define NCORE_CAIUIDR 0x00ffc
+
+/* Snoop Enable Register */
+#define NCORE_DIRUCASER0 0x00040
+#define NCORE_DIRUCASER1 0x00044
+#define NCORE_DIRUCASER2 0x00048
+#define NCORE_DIRUCASER3 0x0004c
+
+#define NCORE_CSADSER0 0x00040
+#define NCORE_CSADSER1 0x00044
+#define NCORE_CSADSER2 0x00048
+#define NCORE_CSADSER3 0x0004c
+
+/* Protocols Definition */
+#define ACE_W_DVM 0
+#define ACE_L_W_DVM 1
+#define ACE_WO_DVM 2
+#define ACE_L_WO_DVM 3
+
+/* Bypass OC Ram Firewall */
+#define NCORE_FW_OCRAM_BLK_BASE 0x100200
+#define NCORE_FW_OCRAM_BLK_CGF1 0x04
+#define NCORE_FW_OCRAM_BLK_CGF2 0x08
+#define NCORE_FW_OCRAM_BLK_CGF3 0x0c
+#define NCORE_FW_OCRAM_BLK_CGF4 0x10
+
+#define OCRAM_PRIVILEGED_MASK BIT(29)
+#define OCRAM_SECURE_MASK BIT(30)
+
+/* Macros */
+#define NCORE_CCU_REG(base) (NCORE_CCU_OFFSET + (base))
+#define NCORE_CCU_CSR(reg) (NCORE_CCU_REG(NCORE_CSR_OFFSET)\
+ + (reg))
+#define NCORE_CCU_DIR(reg) (NCORE_CCU_REG(NCORE_DIRU_OFFSET)\
+ + (reg))
+#define NCORE_CCU_CAI(reg) (NCORE_CCU_REG(NCORE_CAIU_OFFSET)\
+ + (reg))
+
+#define DIRECTORY_UNIT(x, reg) (NCORE_CCU_DIR(reg)\
+ + NCORE_DIRU_SIZE * (x))
+#define COH_AGENT_UNIT(x, reg) (NCORE_CCU_CAI(reg)\
+ + NCORE_CAIU_SIZE * (x))
+
+#define COH_CPU0_BYPASS_REG(reg) (NCORE_CCU_REG(NCORE_FW_OCRAM_BLK_BASE)\
+ + (reg))
+
+#define CSUIDR_NUM_CMI(x) (((x) & 0x3f000000) >> 24)
+#define CSUIDR_NUM_DIR(x) (((x) & 0x003f0000) >> 16)
+#define CSUIDR_NUM_NCB(x) (((x) & 0x00003f00) >> 8)
+#define CSUIDR_NUM_CAI(x) (((x) & 0x0000007f) >> 0)
+
+#define CSIDR_NUM_SF(x) (((x) & 0x007c0000) >> 18)
+
+#define SNOOP_FILTER_ID(x) (((x) << 16))
+
+#define CACHING_AGENT_BIT(x) (((x) & 0x08000) >> 15)
+#define CACHING_AGENT_TYPE(x) (((x) & 0xf0000) >> 16)
+
+
+typedef struct coh_ss_id {
+ uint8_t num_coh_mem;
+ uint8_t num_directory;
+ uint8_t num_non_coh_bridge;
+ uint8_t num_coh_agent;
+ uint8_t num_snoop_filter;
+} coh_ss_id_t;
+
+uint32_t init_ncore_ccu(void);
+void ncore_enable_ocram_firewall(void);
+
+#endif
diff --git a/plat/intel/soc/common/drivers/qspi/cadence_qspi.c b/plat/intel/soc/common/drivers/qspi/cadence_qspi.c
new file mode 100644
index 0000000..cecf560
--- /dev/null
+++ b/plat/intel/soc/common/drivers/qspi/cadence_qspi.c
@@ -0,0 +1,822 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <string.h>
+#include <drivers/delay_timer.h>
+#include <drivers/console.h>
+
+#include "cadence_qspi.h"
+
+#define LESS(a, b) (((a) < (b)) ? (a) : (b))
+#define MORE(a, b) (((a) > (b)) ? (a) : (b))
+
+
+uint32_t qspi_device_size;
+int cad_qspi_cs;
+
+int cad_qspi_idle(void)
+{
+ return (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG)
+ & CAD_QSPI_CFG_IDLE) >> 31;
+}
+
+int cad_qspi_set_baudrate_div(uint32_t div)
+{
+ if (div > 0xf)
+ return CAD_INVALID;
+
+ mmio_clrsetbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG,
+ ~CAD_QSPI_CFG_BAUDDIV_MSK,
+ CAD_QSPI_CFG_BAUDDIV(div));
+
+ return 0;
+}
+
+int cad_qspi_configure_dev_size(uint32_t addr_bytes,
+ uint32_t bytes_per_dev, uint32_t bytes_per_block)
+{
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVSZ,
+ CAD_QSPI_DEVSZ_ADDR_BYTES(addr_bytes) |
+ CAD_QSPI_DEVSZ_BYTES_PER_PAGE(bytes_per_dev) |
+ CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(bytes_per_block));
+ return 0;
+}
+
+int cad_qspi_set_read_config(uint32_t opcode, uint32_t instr_type,
+ uint32_t addr_type, uint32_t data_type,
+ uint32_t mode_bit, uint32_t dummy_clk_cycle)
+{
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVRD,
+ CAD_QSPI_DEV_OPCODE(opcode) |
+ CAD_QSPI_DEV_INST_TYPE(instr_type) |
+ CAD_QSPI_DEV_ADDR_TYPE(addr_type) |
+ CAD_QSPI_DEV_DATA_TYPE(data_type) |
+ CAD_QSPI_DEV_MODE_BIT(mode_bit) |
+ CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle));
+
+ return 0;
+}
+
+int cad_qspi_set_write_config(uint32_t opcode, uint32_t addr_type,
+ uint32_t data_type, uint32_t dummy_clk_cycle)
+{
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DEVWR,
+ CAD_QSPI_DEV_OPCODE(opcode) |
+ CAD_QSPI_DEV_ADDR_TYPE(addr_type) |
+ CAD_QSPI_DEV_DATA_TYPE(data_type) |
+ CAD_QSPI_DEV_DUMMY_CLK_CYCLE(dummy_clk_cycle));
+
+ return 0;
+}
+
+int cad_qspi_timing_config(uint32_t clkphase, uint32_t clkpol, uint32_t csda,
+ uint32_t csdads, uint32_t cseot, uint32_t cssot,
+ uint32_t rddatacap)
+{
+ uint32_t cfg = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG);
+
+ cfg &= CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK &
+ CAD_QSPI_CFG_SELCLKPOL_CLR_MSK;
+ cfg |= CAD_QSPI_SELCLKPHASE(clkphase) | CAD_QSPI_SELCLKPOL(clkpol);
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, cfg);
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_DELAY,
+ CAD_QSPI_DELAY_CSSOT(cssot) | CAD_QSPI_DELAY_CSEOT(cseot) |
+ CAD_QSPI_DELAY_CSDADS(csdads) | CAD_QSPI_DELAY_CSDA(csda));
+
+ return 0;
+}
+
+int cad_qspi_stig_cmd_helper(int cs, uint32_t cmd)
+{
+ uint32_t count = 0;
+
+ /* chip select */
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG,
+ (mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG)
+ & CAD_QSPI_CFG_CS_MSK) | CAD_QSPI_CFG_CS(cs));
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD, cmd);
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD,
+ cmd | CAD_QSPI_FLASHCMD_EXECUTE);
+
+ do {
+ uint32_t reg = mmio_read_32(CAD_QSPI_OFFSET +
+ CAD_QSPI_FLASHCMD);
+ if (!(reg & CAD_QSPI_FLASHCMD_EXECUTE_STAT))
+ break;
+ count++;
+ } while (count < CAD_QSPI_COMMAND_TIMEOUT);
+
+ if (count >= CAD_QSPI_COMMAND_TIMEOUT) {
+ ERROR("Error sending QSPI command %x, timed out\n",
+ cmd);
+ return CAD_QSPI_ERROR;
+ }
+
+ return 0;
+}
+
+int cad_qspi_stig_cmd(uint32_t opcode, uint32_t dummy)
+{
+ if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) {
+ ERROR("Faulty dummy bytes\n");
+ return -1;
+ }
+
+ return cad_qspi_stig_cmd_helper(cad_qspi_cs,
+ CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+ CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(dummy));
+}
+
+int cad_qspi_stig_read_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes,
+ uint32_t *output)
+{
+ if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) {
+ ERROR("Faulty dummy byes\n");
+ return -1;
+ }
+
+ if ((num_bytes > 8) || (num_bytes == 0))
+ return -1;
+
+ uint32_t cmd =
+ CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+ CAD_QSPI_FLASHCMD_ENRDDATA(1) |
+ CAD_QSPI_FLASHCMD_NUMRDDATABYTES(num_bytes - 1) |
+ CAD_QSPI_FLASHCMD_ENCMDADDR(0) |
+ CAD_QSPI_FLASHCMD_ENMODEBIT(0) |
+ CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) |
+ CAD_QSPI_FLASHCMD_ENWRDATA(0) |
+ CAD_QSPI_FLASHCMD_NUMWRDATABYTES(0) |
+ CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy);
+
+ if (cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd)) {
+ ERROR("failed to send stig cmd\n");
+ return -1;
+ }
+
+ output[0] = mmio_read_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_RDDATA0);
+
+ if (num_bytes > 4) {
+ output[1] = mmio_read_32(CAD_QSPI_OFFSET +
+ CAD_QSPI_FLASHCMD_RDDATA1);
+ }
+
+ return 0;
+}
+
+int cad_qspi_stig_wr_cmd(uint32_t opcode, uint32_t dummy, uint32_t num_bytes,
+ uint32_t *input)
+{
+ if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1)) {
+ ERROR("Faulty dummy byes\n");
+ return -1;
+ }
+
+ if ((num_bytes > 8) || (num_bytes == 0))
+ return -1;
+
+ uint32_t cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+ CAD_QSPI_FLASHCMD_ENRDDATA(0) |
+ CAD_QSPI_FLASHCMD_NUMRDDATABYTES(0) |
+ CAD_QSPI_FLASHCMD_ENCMDADDR(0) |
+ CAD_QSPI_FLASHCMD_ENMODEBIT(0) |
+ CAD_QSPI_FLASHCMD_NUMADDRBYTES(0) |
+ CAD_QSPI_FLASHCMD_ENWRDATA(1) |
+ CAD_QSPI_FLASHCMD_NUMWRDATABYTES(num_bytes - 1) |
+ CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy);
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA0, input[0]);
+
+ if (num_bytes > 4)
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_WRDATA1,
+ input[1]);
+
+ return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd);
+}
+
+int cad_qspi_stig_addr_cmd(uint32_t opcode, uint32_t dummy, uint32_t addr)
+{
+ uint32_t cmd;
+
+ if (dummy > ((1 << CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX) - 1))
+ return -1;
+
+ cmd = CAD_QSPI_FLASHCMD_OPCODE(opcode) |
+ CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(dummy) |
+ CAD_QSPI_FLASHCMD_ENCMDADDR(1) |
+ CAD_QSPI_FLASHCMD_NUMADDRBYTES(2);
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_FLASHCMD_ADDR, addr);
+
+ return cad_qspi_stig_cmd_helper(cad_qspi_cs, cmd);
+}
+
+int cad_qspi_device_bank_select(uint32_t bank)
+{
+ int status = 0;
+
+ status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0);
+ if (status != 0)
+ return status;
+
+ status = cad_qspi_stig_wr_cmd(CAD_QSPI_STIG_OPCODE_WREN_EXT_REG,
+ 0, 1, &bank);
+ if (status != 0)
+ return status;
+
+ return cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WRDIS, 0);
+}
+
+int cad_qspi_device_status(uint32_t *status)
+{
+ return cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDSR, 0, 1, status);
+}
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+int cad_qspi_n25q_enable(void)
+{
+ cad_qspi_set_read_config(QSPI_FAST_READ, CAD_QSPI_INST_SINGLE,
+ CAD_QSPI_ADDR_FASTREAD, CAT_QSPI_ADDR_SINGLE_IO, 1,
+ 0);
+ cad_qspi_set_write_config(QSPI_WRITE, 0, 0, 0);
+
+ return 0;
+}
+
+int cad_qspi_n25q_wait_for_program_and_erase(int program_only)
+{
+ uint32_t status, flag_sr;
+ int count = 0;
+
+ while (count < CAD_QSPI_COMMAND_TIMEOUT) {
+ status = cad_qspi_device_status(&status);
+ if (status != 0) {
+ ERROR("Error getting device status\n");
+ return -1;
+ }
+ if (!CAD_QSPI_STIG_SR_BUSY(status))
+ break;
+ count++;
+ }
+
+ if (count >= CAD_QSPI_COMMAND_TIMEOUT) {
+ ERROR("Timed out waiting for idle\n");
+ return -1;
+ }
+
+ count = 0;
+
+ while (count < CAD_QSPI_COMMAND_TIMEOUT) {
+ status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDFLGSR,
+ 0, 1, &flag_sr);
+ if (status != 0) {
+ ERROR("Error waiting program and erase.\n");
+ return status;
+ }
+
+ if ((program_only &&
+ CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(flag_sr)) ||
+ (!program_only &&
+ CAD_QSPI_STIG_FLAGSR_ERASEREADY(flag_sr)))
+ break;
+ }
+
+ if (count >= CAD_QSPI_COMMAND_TIMEOUT)
+ ERROR("Timed out waiting for program and erase\n");
+
+ if ((program_only && CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(flag_sr)) ||
+ (!program_only &&
+ CAD_QSPI_STIG_FLAGSR_ERASEERROR(flag_sr))) {
+ ERROR("Error programming/erasing flash\n");
+ cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_CLFSR, 0);
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+int cad_qspi_indirect_read_start_bank(uint32_t flash_addr, uint32_t num_bytes)
+{
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDSTADDR, flash_addr);
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRDCNT, num_bytes);
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDRD,
+ CAD_QSPI_INDRD_START |
+ CAD_QSPI_INDRD_IND_OPS_DONE);
+
+ return 0;
+}
+
+
+int cad_qspi_indirect_write_start_bank(uint32_t flash_addr,
+ uint32_t num_bytes)
+{
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRSTADDR, flash_addr);
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWRCNT, num_bytes);
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_INDWR,
+ CAD_QSPI_INDWR_START |
+ CAD_QSPI_INDWR_INDDONE);
+
+ return 0;
+}
+
+int cad_qspi_indirect_write_finish(void)
+{
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+ return cad_qspi_n25q_wait_for_program_and_erase(1);
+#else
+ return 0;
+#endif
+
+}
+
+int cad_qspi_enable(void)
+{
+ int status;
+
+ mmio_setbits_32(CAD_QSPI_OFFSET + CAD_QSPI_CFG, CAD_QSPI_CFG_ENABLE);
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+ status = cad_qspi_n25q_enable();
+ if (status != 0)
+ return status;
+#endif
+ return 0;
+}
+
+int cad_qspi_enable_subsector_bank(uint32_t addr)
+{
+ int status = 0;
+
+ status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0);
+ if (status != 0)
+ return status;
+
+ status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE, 0,
+ addr);
+ if (status != 0)
+ return status;
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+ status = cad_qspi_n25q_wait_for_program_and_erase(0);
+#endif
+ return status;
+}
+
+int cad_qspi_erase_subsector(uint32_t addr)
+{
+ int status = 0;
+
+ status = cad_qspi_device_bank_select(addr >> 24);
+ if (status != 0)
+ return status;
+
+ return cad_qspi_enable_subsector_bank(addr);
+}
+
+int cad_qspi_erase_sector(uint32_t addr)
+{
+ int status = 0;
+
+ status = cad_qspi_device_bank_select(addr >> 24);
+ if (status != 0)
+ return status;
+
+ status = cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_WREN, 0);
+ if (status != 0)
+ return status;
+
+ status = cad_qspi_stig_addr_cmd(CAD_QSPI_STIG_OPCODE_SEC_ERASE, 0,
+ addr);
+ if (status != 0)
+ return status;
+
+#if CAD_QSPI_MICRON_N25Q_SUPPORT
+ status = cad_qspi_n25q_wait_for_program_and_erase(0);
+#endif
+ return status;
+}
+
+void cad_qspi_calibration(uint32_t dev_clk, uint32_t qspi_clk_mhz)
+{
+ int status;
+ uint32_t dev_sclk_mhz = 27; /*min value to get biggest 0xF div factor*/
+ uint32_t data_cap_delay;
+ uint32_t sample_rdid;
+ uint32_t rdid;
+ uint32_t div_actual;
+ uint32_t div_bits;
+ int first_pass, last_pass;
+
+ /*1. Set divider to bigger value (slowest SCLK)
+ *2. RDID and save the value
+ */
+ div_actual = (qspi_clk_mhz + (dev_sclk_mhz - 1)) / dev_sclk_mhz;
+ div_bits = (((div_actual + 1) / 2) - 1);
+ status = cad_qspi_set_baudrate_div(0xf);
+
+ status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID,
+ 0, 3, &sample_rdid);
+ if (status != 0)
+ return;
+
+ /*3. Set divider to the intended frequency
+ *4. Set the read delay = 0
+ *5. RDID and check whether the value is same as item 2
+ *6. Increase read delay and compared the value against item 2
+ *7. Find the range of read delay that have same as
+ * item 2 and divide it to 2
+ */
+ div_actual = (qspi_clk_mhz + (dev_clk - 1)) / dev_clk;
+ div_bits = (((div_actual + 1) / 2) - 1);
+ status = cad_qspi_set_baudrate_div(div_bits);
+ if (status != 0)
+ return;
+
+ data_cap_delay = 0;
+ first_pass = -1;
+ last_pass = -1;
+
+ do {
+ if (status != 0)
+ break;
+ status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0,
+ 3, &rdid);
+ if (status != 0)
+ break;
+ if (rdid == sample_rdid) {
+ if (first_pass == -1)
+ first_pass = data_cap_delay;
+ else
+ last_pass = data_cap_delay;
+ }
+
+ data_cap_delay++;
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP,
+ CAD_QSPI_RDDATACAP_BYP(1) |
+ CAD_QSPI_RDDATACAP_DELAY(data_cap_delay));
+
+ } while (data_cap_delay < 0x10);
+
+ if (first_pass > 0) {
+ int diff = first_pass - last_pass;
+
+ data_cap_delay = first_pass + diff / 2;
+ }
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_RDDATACAP,
+ CAD_QSPI_RDDATACAP_BYP(1) |
+ CAD_QSPI_RDDATACAP_DELAY(data_cap_delay));
+ status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3, &rdid);
+
+ if (status != 0)
+ return;
+}
+
+int cad_qspi_int_disable(uint32_t mask)
+{
+ if (cad_qspi_idle() == 0)
+ return -1;
+
+ if ((CAD_QSPI_INT_STATUS_ALL & mask) == 0)
+ return -1;
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_IRQMSK, mask);
+ return 0;
+}
+
+void cad_qspi_set_chip_select(int cs)
+{
+ cad_qspi_cs = cs;
+}
+
+int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase,
+ uint32_t clk_pol, uint32_t csda, uint32_t csdads,
+ uint32_t cseot, uint32_t cssot, uint32_t rddatacap)
+{
+ int status = 0;
+ uint32_t qspi_desired_clk_freq;
+ uint32_t rdid = 0;
+ uint32_t cap_code;
+
+ INFO("Initializing Qspi\n");
+
+ if (cad_qspi_idle() == 0) {
+ ERROR("device not idle\n");
+ return -1;
+ }
+
+
+ status = cad_qspi_timing_config(clk_phase, clk_pol, csda, csdads,
+ cseot, cssot, rddatacap);
+
+ if (status != 0) {
+ ERROR("config set timing failure\n");
+ return status;
+ }
+
+ mmio_write_32(CAD_QSPI_OFFSET + CAD_QSPI_REMAPADDR,
+ CAD_QSPI_REMAPADDR_VALUE_SET(0));
+
+ status = cad_qspi_int_disable(CAD_QSPI_INT_STATUS_ALL);
+ if (status != 0) {
+ ERROR("failed disable\n");
+ return status;
+ }
+
+ cad_qspi_set_baudrate_div(0xf);
+ status = cad_qspi_enable();
+ if (status != 0) {
+ ERROR("failed enable\n");
+ return status;
+ }
+
+ qspi_desired_clk_freq = 100;
+ cad_qspi_calibration(qspi_desired_clk_freq, 50000000);
+
+ status = cad_qspi_stig_read_cmd(CAD_QSPI_STIG_OPCODE_RDID, 0, 3,
+ &rdid);
+
+ if (status != 0) {
+ ERROR("Error reading RDID\n");
+ return status;
+ }
+
+ /*
+ * NOTE: The Size code seems to be a form of BCD (binary coded decimal).
+ * The first nibble is the 10's digit and the second nibble is the 1's
+ * digit in the number of bytes.
+ *
+ * Capacity ID samples:
+ * 0x15 : 16 Mb => 2 MiB => 1 << 21 ; BCD=15
+ * 0x16 : 32 Mb => 4 MiB => 1 << 22 ; BCD=16
+ * 0x17 : 64 Mb => 8 MiB => 1 << 23 ; BCD=17
+ * 0x18 : 128 Mb => 16 MiB => 1 << 24 ; BCD=18
+ * 0x19 : 256 Mb => 32 MiB => 1 << 25 ; BCD=19
+ * 0x1a
+ * 0x1b
+ * 0x1c
+ * 0x1d
+ * 0x1e
+ * 0x1f
+ * 0x20 : 512 Mb => 64 MiB => 1 << 26 ; BCD=20
+ * 0x21 : 1024 Mb => 128 MiB => 1 << 27 ; BCD=21
+ */
+
+ cap_code = CAD_QSPI_STIG_RDID_CAPACITYID(rdid);
+
+ if (!(((cap_code >> 4) > 0x9) || ((cap_code & 0xf) > 0x9))) {
+ uint32_t decoded_cap = ((cap_code >> 4) * 10) +
+ (cap_code & 0xf);
+ qspi_device_size = 1 << (decoded_cap + 6);
+ INFO("QSPI Capacity: %x\n\n", qspi_device_size);
+
+ } else {
+ ERROR("Invalid CapacityID encountered: 0x%02x\n",
+ cap_code);
+ return -1;
+ }
+
+ cad_qspi_configure_dev_size(INTEL_QSPI_ADDR_BYTES,
+ INTEL_QSPI_BYTES_PER_DEV,
+ INTEL_BYTES_PER_BLOCK);
+
+ INFO("Flash size: %d Bytes\n", qspi_device_size);
+
+ return status;
+}
+
+int cad_qspi_indirect_page_bound_write(uint32_t offset,
+ uint8_t *buffer, uint32_t len)
+{
+ int status = 0, i;
+ uint32_t write_count, write_capacity, *write_data, space,
+ write_fill_level, sram_partition;
+
+ status = cad_qspi_indirect_write_start_bank(offset, len);
+ if (status != 0)
+ return status;
+
+ write_count = 0;
+ sram_partition = CAD_QSPI_SRAMPART_ADDR(mmio_read_32(CAD_QSPI_OFFSET +
+ CAD_QSPI_SRAMPART));
+ write_capacity = (uint32_t) CAD_QSPI_SRAM_FIFO_ENTRY_COUNT -
+ sram_partition;
+
+ while (write_count < len) {
+ write_fill_level = CAD_QSPI_SRAMFILL_INDWRPART(
+ mmio_read_32(CAD_QSPI_OFFSET +
+ CAD_QSPI_SRAMFILL));
+ space = LESS(write_capacity - write_fill_level,
+ (len - write_count) / sizeof(uint32_t));
+ write_data = (uint32_t *)(buffer + write_count);
+ for (i = 0; i < space; ++i)
+ mmio_write_32(CAD_QSPIDATA_OFST, *write_data++);
+
+ write_count += space * sizeof(uint32_t);
+ }
+ return cad_qspi_indirect_write_finish();
+}
+
+int cad_qspi_read_bank(uint8_t *buffer, uint32_t offset, uint32_t size)
+{
+ int status;
+ uint32_t read_count = 0, *read_data;
+ int level = 1, count = 0, i;
+
+ status = cad_qspi_indirect_read_start_bank(offset, size);
+
+ if (status != 0)
+ return status;
+
+ while (read_count < size) {
+ do {
+ level = CAD_QSPI_SRAMFILL_INDRDPART(
+ mmio_read_32(CAD_QSPI_OFFSET +
+ CAD_QSPI_SRAMFILL));
+ read_data = (uint32_t *)(buffer + read_count);
+ for (i = 0; i < level; ++i)
+ *read_data++ = mmio_read_32(CAD_QSPIDATA_OFST);
+
+ read_count += level * sizeof(uint32_t);
+ count++;
+ } while (level > 0);
+ }
+
+ return 0;
+}
+
+int cad_qspi_write_bank(uint32_t offset, uint8_t *buffer, uint32_t size)
+{
+ int status = 0;
+ uint32_t page_offset = offset & (CAD_QSPI_PAGE_SIZE - 1);
+ uint32_t write_size = LESS(size, CAD_QSPI_PAGE_SIZE - page_offset);
+
+ while (size) {
+ status = cad_qspi_indirect_page_bound_write(offset, buffer,
+ write_size);
+ if (status != 0)
+ break;
+
+ offset += write_size;
+ buffer += write_size;
+ size -= write_size;
+ write_size = LESS(size, CAD_QSPI_PAGE_SIZE);
+ }
+ return status;
+}
+
+int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size)
+{
+ uint32_t bank_count, bank_addr, bank_offset, copy_len;
+ uint8_t *read_data;
+ int i, status;
+
+ status = 0;
+
+ if ((offset >= qspi_device_size) ||
+ (offset + size - 1 >= qspi_device_size) ||
+ (size == 0)) {
+ ERROR("Invalid read parameter\n");
+ return -1;
+ }
+
+ if (CAD_QSPI_INDRD_RD_STAT(mmio_read_32(CAD_QSPI_OFFSET +
+ CAD_QSPI_INDRD))) {
+ ERROR("Read in progress\n");
+ return -1;
+ }
+
+ /*
+ * bank_count : Number of bank(s) affected, including partial banks.
+ * bank_addr : Aligned address of the first bank,
+ * including partial bank.
+ * bank_ofst : The offset of the bank to read.
+ * Only used when reading the first bank.
+ */
+ bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) -
+ CAD_QSPI_BANK_ADDR(offset) + 1;
+ bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK;
+ bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1);
+
+ read_data = (uint8_t *)buffer;
+
+ copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset);
+
+ for (i = 0; i < bank_count; ++i) {
+ status = cad_qspi_device_bank_select(CAD_QSPI_BANK_ADDR(
+ bank_addr));
+ if (status != 0)
+ break;
+ status = cad_qspi_read_bank(read_data, bank_offset, copy_len);
+ if (status != 0)
+ break;
+
+ bank_addr += CAD_QSPI_BANK_SIZE;
+ read_data += copy_len;
+ size -= copy_len;
+ bank_offset = 0;
+ copy_len = LESS(size, CAD_QSPI_BANK_SIZE);
+ }
+
+ return status;
+}
+
+int cad_qspi_erase(uint32_t offset, uint32_t size)
+{
+ int status = 0;
+ uint32_t subsector_offset = offset & (CAD_QSPI_SUBSECTOR_SIZE - 1);
+ uint32_t erase_size = LESS(size,
+ CAD_QSPI_SUBSECTOR_SIZE - subsector_offset);
+
+ while (size) {
+ status = cad_qspi_erase_subsector(offset);
+ if (status != 0)
+ break;
+
+ offset += erase_size;
+ size -= erase_size;
+ erase_size = LESS(size, CAD_QSPI_SUBSECTOR_SIZE);
+ }
+ return status;
+}
+
+int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size)
+{
+ int status, i;
+ uint32_t bank_count, bank_addr, bank_offset, copy_len;
+ uint8_t *write_data;
+
+ status = 0;
+
+ if ((offset >= qspi_device_size) ||
+ (offset + size - 1 >= qspi_device_size) ||
+ (size == 0)) {
+ return -2;
+ }
+
+ if (CAD_QSPI_INDWR_RDSTAT(mmio_read_32(CAD_QSPI_OFFSET +
+ CAD_QSPI_INDWR))) {
+ ERROR("QSPI Error: Write in progress\n");
+ return -1;
+ }
+
+ bank_count = CAD_QSPI_BANK_ADDR(offset + size - 1) -
+ CAD_QSPI_BANK_ADDR(offset) + 1;
+ bank_addr = offset & CAD_QSPI_BANK_ADDR_MSK;
+ bank_offset = offset & (CAD_QSPI_BANK_SIZE - 1);
+
+ write_data = buffer;
+
+ copy_len = LESS(size, CAD_QSPI_BANK_SIZE - bank_offset);
+
+ for (i = 0; i < bank_count; ++i) {
+ status = cad_qspi_device_bank_select(
+ CAD_QSPI_BANK_ADDR(bank_addr));
+ if (status != 0)
+ break;
+
+ status = cad_qspi_write_bank(bank_offset, write_data,
+ copy_len);
+ if (status != 0)
+ break;
+
+ bank_addr += CAD_QSPI_BANK_SIZE;
+ write_data += copy_len;
+ size -= copy_len;
+ bank_offset = 0;
+
+ copy_len = LESS(size, CAD_QSPI_BANK_SIZE);
+ }
+ return status;
+}
+
+int cad_qspi_update(void *Buffer, uint32_t offset, uint32_t size)
+{
+ int status = 0;
+
+ status = cad_qspi_erase(offset, size);
+ if (status != 0)
+ return status;
+
+ return cad_qspi_write(Buffer, offset, size);
+}
+
+void cad_qspi_reset(void)
+{
+ cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_EN, 0);
+ cad_qspi_stig_cmd(CAD_QSPI_STIG_OPCODE_RESET_MEM, 0);
+}
+
diff --git a/plat/intel/soc/common/drivers/qspi/cadence_qspi.h b/plat/intel/soc/common/drivers/qspi/cadence_qspi.h
new file mode 100644
index 0000000..cfef585
--- /dev/null
+++ b/plat/intel/soc/common/drivers/qspi/cadence_qspi.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CAD_QSPI_H
+#define CAD_QSPI_H
+
+#define CAD_QSPI_MICRON_N25Q_SUPPORT 1
+
+#define CAD_QSPI_OFFSET 0xff8d2000
+
+#define CAD_INVALID -1
+#define CAD_QSPI_ERROR -2
+
+#define CAD_QSPI_ADDR_FASTREAD 0
+#define CAD_QSPI_ADDR_FASTREAD_DUAL_IO 1
+#define CAD_QSPI_ADDR_FASTREAD_QUAD_IO 2
+#define CAT_QSPI_ADDR_SINGLE_IO 0
+#define CAT_QSPI_ADDR_DUAL_IO 1
+#define CAT_QSPI_ADDR_QUAD_IO 2
+
+#define CAD_QSPI_BANK_ADDR(x) ((x) >> 24)
+#define CAD_QSPI_BANK_ADDR_MSK 0xff000000
+
+#define CAD_QSPI_COMMAND_TIMEOUT 0x10000000
+
+#define CAD_QSPI_CFG 0x0
+#define CAD_QSPI_CFG_BAUDDIV_MSK 0xff87ffff
+#define CAD_QSPI_CFG_BAUDDIV(x) (((x) << 19) & 0x780000)
+#define CAD_QSPI_CFG_CS_MSK ~0x3c00
+#define CAD_QSPI_CFG_CS(x) (((x) << 11))
+#define CAD_QSPI_CFG_ENABLE (1 << 0)
+#define CAD_QSPI_CFG_ENDMA_CLR_MSK 0xffff7fff
+#define CAD_QSPI_CFG_IDLE (1U << 31)
+#define CAD_QSPI_CFG_SELCLKPHASE_CLR_MSK 0xfffffffb
+#define CAD_QSPI_CFG_SELCLKPOL_CLR_MSK 0xfffffffd
+
+#define CAD_QSPIDATA_OFST 0xff900000
+
+#define CAD_QSPI_DELAY 0xc
+#define CAD_QSPI_DELAY_CSSOT(x) (((x) & 0xff) << 0)
+#define CAD_QSPI_DELAY_CSEOT(x) (((x) & 0xff) << 8)
+#define CAD_QSPI_DELAY_CSDADS(x) (((x) & 0xff) << 16)
+#define CAD_QSPI_DELAY_CSDA(x) (((x) & 0xff) << 24)
+
+#define CAD_QSPI_DEVSZ 0x14
+#define CAD_QSPI_DEVSZ_ADDR_BYTES(x) ((x) << 0)
+#define CAD_QSPI_DEVSZ_BYTES_PER_PAGE(x) ((x) << 4)
+#define CAD_QSPI_DEVSZ_BYTES_PER_BLOCK(x) ((x) << 16)
+
+#define CAD_QSPI_DEVWR 0x8
+#define CAD_QSPI_DEVRD 0x4
+#define CAD_QSPI_DEV_OPCODE(x) (((x) & 0xff) << 0)
+#define CAD_QSPI_DEV_INST_TYPE(x) (((x) & 0x03) << 8)
+#define CAD_QSPI_DEV_ADDR_TYPE(x) (((x) & 0x03) << 12)
+#define CAD_QSPI_DEV_DATA_TYPE(x) (((x) & 0x03) << 16)
+#define CAD_QSPI_DEV_MODE_BIT(x) (((x) & 0x01) << 20)
+#define CAD_QSPI_DEV_DUMMY_CLK_CYCLE(x) (((x) & 0x0f) << 24)
+
+#define CAD_QSPI_FLASHCMD 0x90
+#define CAD_QSPI_FLASHCMD_ADDR 0x94
+#define CAD_QSPI_FLASHCMD_EXECUTE 0x1
+#define CAD_QSPI_FLASHCMD_EXECUTE_STAT 0x2
+#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES_MAX 5
+#define CAD_QSPI_FLASHCMD_NUM_DUMMYBYTES(x) (((x) << 7) & 0x000f80)
+#define CAD_QSPI_FLASHCMD_OPCODE(x) (((x) & 0xff) << 24)
+#define CAD_QSPI_FLASHCMD_ENRDDATA(x) (((x) & 1) << 23)
+#define CAD_QSPI_FLASHCMD_NUMRDDATABYTES(x) (((x) & 0xf) << 20)
+#define CAD_QSPI_FLASHCMD_ENCMDADDR(x) (((x) & 1) << 19)
+#define CAD_QSPI_FLASHCMD_ENMODEBIT(x) (((x) & 1) << 18)
+#define CAD_QSPI_FLASHCMD_NUMADDRBYTES(x) (((x) & 0x3) << 16)
+#define CAD_QSPI_FLASHCMD_ENWRDATA(x) (((x) & 1) << 15)
+#define CAD_QSPI_FLASHCMD_NUMWRDATABYTES(x) (((x) & 0x7) << 12)
+#define CAD_QSPI_FLASHCMD_NUMDUMMYBYTES(x) (((x) & 0x1f) << 7)
+#define CAD_QSPI_FLASHCMD_RDDATA0 0xa0
+#define CAD_QSPI_FLASHCMD_RDDATA1 0xa4
+#define CAD_QSPI_FLASHCMD_WRDATA0 0xa8
+#define CAD_QSPI_FLASHCMD_WRDATA1 0xac
+
+#define CAD_QSPI_RDDATACAP 0x10
+#define CAD_QSPI_RDDATACAP_BYP(x) (((x) & 1) << 0)
+#define CAD_QSPI_RDDATACAP_DELAY(x) (((x) & 0xf) << 1)
+
+#define CAD_QSPI_REMAPADDR 0x24
+#define CAD_QSPI_REMAPADDR_VALUE_SET(x) (((x) & 0xffffffff) << 0)
+
+#define CAD_QSPI_SRAMPART 0x18
+#define CAD_QSPI_SRAMFILL 0x2c
+#define CAD_QSPI_SRAMPART_ADDR(x) (((x) >> 0) & 0x3ff)
+#define CAD_QSPI_SRAM_FIFO_ENTRY_COUNT (512 / sizeof(uint32_t))
+#define CAD_QSPI_SRAMFILL_INDWRPART(x) (((x) >> 16) & 0x00ffff)
+#define CAD_QSPI_SRAMFILL_INDRDPART(x) (((x) >> 0) & 0x00ffff)
+
+#define CAD_QSPI_SELCLKPHASE(x) (((x) & 1) << 2)
+#define CAD_QSPI_SELCLKPOL(x) (((x) & 1) << 1)
+
+#define CAD_QSPI_STIG_FLAGSR_PROGRAMREADY(x) (((x) >> 7) & 1)
+#define CAD_QSPI_STIG_FLAGSR_ERASEREADY(x) (((x) >> 7) & 1)
+#define CAD_QSPI_STIG_FLAGSR_ERASEERROR(x) (((x) >> 5) & 1)
+#define CAD_QSPI_STIG_FLAGSR_PROGRAMERROR(x) (((x) >> 4) & 1)
+#define CAD_QSPI_STIG_OPCODE_CLFSR 0x50
+#define CAD_QSPI_STIG_OPCODE_RDID 0x9f
+#define CAD_QSPI_STIG_OPCODE_WRDIS 0x4
+#define CAD_QSPI_STIG_OPCODE_WREN 0x6
+#define CAD_QSPI_STIG_OPCODE_SUBSEC_ERASE 0x20
+#define CAD_QSPI_STIG_OPCODE_SEC_ERASE 0xd8
+#define CAD_QSPI_STIG_OPCODE_WREN_EXT_REG 0xc5
+#define CAD_QSPI_STIG_OPCODE_DIE_ERASE 0xc4
+#define CAD_QSPI_STIG_OPCODE_BULK_ERASE 0xc7
+#define CAD_QSPI_STIG_OPCODE_RDSR 0x5
+#define CAD_QSPI_STIG_OPCODE_RDFLGSR 0x70
+#define CAD_QSPI_STIG_OPCODE_RESET_EN 0x66
+#define CAD_QSPI_STIG_OPCODE_RESET_MEM 0x99
+#define CAD_QSPI_STIG_RDID_CAPACITYID(x) (((x) >> 16) & 0xff)
+#define CAD_QSPI_STIG_SR_BUSY(x) (((x) >> 0) & 1)
+
+
+#define CAD_QSPI_INST_SINGLE 0
+#define CAD_QSPI_INST_DUAL 1
+#define CAD_QSPI_INST_QUAD 2
+
+#define CAD_QSPI_INDRDSTADDR 0x68
+#define CAD_QSPI_INDRDCNT 0x6c
+#define CAD_QSPI_INDRD 0x60
+#define CAD_QSPI_INDRD_RD_STAT(x) (((x) >> 2) & 1)
+#define CAD_QSPI_INDRD_START 1
+#define CAD_QSPI_INDRD_IND_OPS_DONE 0x20
+
+#define CAD_QSPI_INDWR 0x70
+#define CAD_QSPI_INDWR_RDSTAT(x) (((x) >> 2) & 1)
+#define CAD_QSPI_INDWRSTADDR 0x78
+#define CAD_QSPI_INDWRCNT 0x7c
+#define CAD_QSPI_INDWR 0x70
+#define CAD_QSPI_INDWR_START 0x1
+#define CAD_QSPI_INDWR_INDDONE 0x20
+
+#define CAD_QSPI_INT_STATUS_ALL 0x0000ffff
+
+#define CAD_QSPI_N25Q_DIE_SIZE 0x02000000
+#define CAD_QSPI_BANK_SIZE 0x01000000
+#define CAD_QSPI_PAGE_SIZE 0x00000100
+
+#define CAD_QSPI_IRQMSK 0x44
+
+#define CAD_QSPI_SUBSECTOR_SIZE 0x1000
+
+#define INTEL_QSPI_ADDR_BYTES 2
+#define INTEL_QSPI_BYTES_PER_DEV 256
+#define INTEL_BYTES_PER_BLOCK 16
+
+#define QSPI_FAST_READ 0xb
+
+#define QSPI_WRITE 0x2
+
+// QSPI CONFIGURATIONS
+
+#define QSPI_CONFIG_CPOL 1
+#define QSPI_CONFIG_CPHA 1
+
+#define QSPI_CONFIG_CSSOT 0x14
+#define QSPI_CONFIG_CSEOT 0x14
+#define QSPI_CONFIG_CSDADS 0xff
+#define QSPI_CONFIG_CSDA 0xc8
+
+int cad_qspi_init(uint32_t desired_clk_freq, uint32_t clk_phase,
+ uint32_t clk_pol, uint32_t csda, uint32_t csdads,
+ uint32_t cseot, uint32_t cssot, uint32_t rddatacap);
+void cad_qspi_set_chip_select(int cs);
+int cad_qspi_erase(uint32_t offset, uint32_t size);
+int cad_qspi_write(void *buffer, uint32_t offset, uint32_t size);
+int cad_qspi_read(void *buffer, uint32_t offset, uint32_t size);
+int cad_qspi_update(void *buffer, uint32_t offset, uint32_t size);
+
+#endif
+
diff --git a/plat/intel/soc/common/drivers/wdt/watchdog.c b/plat/intel/soc/common/drivers/wdt/watchdog.c
new file mode 100644
index 0000000..651189b
--- /dev/null
+++ b/plat/intel/soc/common/drivers/wdt/watchdog.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include "watchdog.h"
+
+
+/* Reset watchdog timer */
+void watchdog_sw_rst(void)
+{
+ mmio_write_32(WDT_CRR, WDT_SW_RST);
+}
+
+/* Print component information */
+void watchdog_info(void)
+{
+ INFO("Component Type : %x\r\n", mmio_read_32(WDT_COMP_VERSION));
+ INFO("Component Version : %x\r\n", mmio_read_32(WDT_COMP_TYPE));
+}
+
+/* Check watchdog current status */
+void watchdog_status(void)
+{
+ if (mmio_read_32(WDT_CR) & 1) {
+ INFO("Watchdog Timer is currently enabled\n");
+ INFO("Current Counter : 0x%x\r\n", mmio_read_32(WDT_CCVR));
+ } else {
+ INFO("Watchdog Timer is currently disabled\n");
+ }
+}
+
+/* Initialize & enable watchdog */
+void watchdog_init(int watchdog_clk)
+{
+ uint8_t cycles_i = 0;
+ uint32_t wdt_cycles = WDT_MIN_CYCLES;
+ uint32_t top_init_cycles = WDT_PERIOD * watchdog_clk;
+
+ while ((cycles_i < 15) && (wdt_cycles < top_init_cycles)) {
+ wdt_cycles = (wdt_cycles << 1);
+ cycles_i++;
+ }
+
+ mmio_write_32(WDT_TORR, (cycles_i << 4) | cycles_i);
+
+ mmio_write_32(WDT_CR, WDT_CR_RMOD|WDT_CR_EN);
+}
diff --git a/plat/intel/soc/common/drivers/wdt/watchdog.h b/plat/intel/soc/common/drivers/wdt/watchdog.h
new file mode 100644
index 0000000..2c72463
--- /dev/null
+++ b/plat/intel/soc/common/drivers/wdt/watchdog.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CAD_WATCHDOG_H
+#define CAD_WATCHDOG_H
+
+#define WDT_BASE (0xFFD00200)
+#define WDT_REG_SIZE_OFFSET (0x4)
+#define WDT_MIN_CYCLES (65536)
+#define WDT_PERIOD (20)
+
+#define WDT_CR (WDT_BASE + 0x0)
+#define WDT_TORR (WDT_BASE + 0x4)
+
+#define WDT_CRR (WDT_BASE + 0xC)
+
+#define WDT_CCVR (WDT_BASE + 0x8)
+#define WDT_STAT (WDT_BASE + 0x10)
+#define WDT_EOI (WDT_BASE + 0x14)
+
+#define WDT_COMP_PARAM_1 (WDT_BASE + 0xF4)
+#define WDT_COMP_VERSION (WDT_BASE + 0xF8)
+#define WDT_COMP_TYPE (WDT_BASE + 0XFC)
+
+#define WDT_CR_RMOD (0x0)
+#define WDT_CR_EN (0x1)
+
+#define WDT_SW_RST (0x76)
+
+
+void watchdog_init(int watchdog_clk);
+void watchdog_info(void);
+void watchdog_status(void);
+void watchdog_sw_rst(void);
+
+#endif
diff --git a/plat/intel/soc/common/include/plat_macros.S b/plat/intel/soc/common/include/plat_macros.S
new file mode 100644
index 0000000..43db9a2
--- /dev/null
+++ b/plat/intel/soc/common/include/plat_macros.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h
new file mode 100644
index 0000000..2b3f144
--- /dev/null
+++ b/plat/intel/soc/common/include/platform_def.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/interrupt_props.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <plat/common/common_def.h>
+
+/* Platform Type */
+#define PLAT_SOCFPGA_STRATIX10 1
+#define PLAT_SOCFPGA_AGILEX 2
+#define PLAT_SOCFPGA_N5X 3
+#define PLAT_SOCFPGA_EMULATOR 0
+
+/* sysmgr.boot_scratch_cold4 & 5 used for CPU release address for SPL */
+#define PLAT_CPU_RELEASE_ADDR 0xffd12210
+
+/*
+ * sysmgr.boot_scratch_cold6 & 7 (64bit) are used to indicate L2 reset
+ * is done and HPS should trigger warm reset via RMR_EL3.
+ */
+#define L2_RESET_DONE_REG 0xFFD12218
+
+/* Magic word to indicate L2 reset is completed */
+#define L2_RESET_DONE_STATUS 0x1228E5E7
+
+/* Define next boot image name and offset */
+#define PLAT_NS_IMAGE_OFFSET 0x10000000
+#define PLAT_HANDOFF_OFFSET 0xFFE3F000
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/* SoCFPGA supports up to 124GB RAM */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 39)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 39)
+
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLAT_PRIMARY_CPU 0
+#define PLAT_SECONDARY_ENTRY_BASE 0x01f78bf0
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE 0x2000
+
+/* PSCI related constant */
+#define PLAT_NUM_POWER_DOMAINS 5
+#define PLAT_MAX_PWR_LVL 1
+#define PLAT_MAX_RET_STATE 1
+#define PLAT_MAX_OFF_STATE 2
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+
+/* Interrupt related constant */
+
+#define INTEL_SOCFPGA_IRQ_SEC_PHY_TIMER 29
+
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_0 8
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_1 9
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_2 10
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_3 11
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_4 12
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_5 13
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_6 14
+#define INTEL_SOCFPGA_IRQ_SEC_SGI_7 15
+
+#define TSP_IRQ_SEC_PHY_TIMER INTEL_SOCFPGA_IRQ_SEC_PHY_TIMER
+#define TSP_SEC_MEM_BASE BL32_BASE
+#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1)
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define DRAM_BASE (0x0)
+#define DRAM_SIZE (0x80000000)
+
+#define OCRAM_BASE (0xFFE00000)
+#define OCRAM_SIZE (0x00040000)
+
+#define MEM64_BASE (0x0100000000)
+#define MEM64_SIZE (0x1F00000000)
+
+#define DEVICE1_BASE (0x80000000)
+#define DEVICE1_SIZE (0x60000000)
+
+#define DEVICE2_BASE (0xF7000000)
+#define DEVICE2_SIZE (0x08E00000)
+
+#define DEVICE3_BASE (0xFFFC0000)
+#define DEVICE3_SIZE (0x00008000)
+
+#define DEVICE4_BASE (0x2000000000)
+#define DEVICE4_SIZE (0x0100000000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define BL1_RO_BASE (0xffe00000)
+#define BL1_RO_LIMIT (0xffe0f000)
+#define BL1_RW_BASE (0xffe10000)
+#define BL1_RW_LIMIT (0xffe1ffff)
+#define BL1_RW_SIZE (0x14000)
+
+#define BL2_BASE (0xffe00000)
+#define BL2_LIMIT (0xffe1b000)
+
+#define BL31_BASE (0x1000)
+#define BL31_LIMIT (0x81000)
+
+#define BL_DATA_LIMIT PLAT_HANDOFF_OFFSET
+
+#define PLAT_CPUID_RELEASE (BL_DATA_LIMIT - 16)
+#define PLAT_SEC_ENTRY (BL_DATA_LIMIT - 8)
+
+#define PLAT_SEC_WARM_ENTRY 0
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#define PLAT_GIC_BASE (0xFFFC0000)
+#define PLAT_GICC_BASE (PLAT_GIC_BASE + 0x2000)
+#define PLAT_GICD_BASE (PLAT_GIC_BASE + 0x1000)
+#define PLAT_GICR_BASE 0
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define PLAT_UART0_BASE (0xFFC02000)
+#define PLAT_UART1_BASE (0xFFC02100)
+
+#define CRASH_CONSOLE_BASE PLAT_UART0_BASE
+#define PLAT_INTEL_UART_BASE PLAT_UART0_BASE
+
+#if PLAT_SOCFPGA_EMULATOR
+#define PLAT_BAUDRATE (4800)
+#define PLAT_UART_CLOCK (76800)
+#else
+#define PLAT_BAUDRATE (115200)
+#define PLAT_UART_CLOCK (100000000)
+#endif
+
+/*******************************************************************************
+ * PHY related constants
+ ******************************************************************************/
+
+#define EMAC0_PHY_MODE PHY_INTERFACE_MODE_RGMII
+#define EMAC1_PHY_MODE PHY_INTERFACE_MODE_RGMII
+#define EMAC2_PHY_MODE PHY_INTERFACE_MODE_RGMII
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define PLAT_SYS_COUNTER_FREQ_IN_TICKS (400000000)
+#define PLAT_SYS_COUNTER_CONVERT_TO_MHZ (1000000)
+
+#define PLAT_INTEL_SOCFPGA_GICD_BASE PLAT_GICD_BASE
+#define PLAT_INTEL_SOCFPGA_GICC_BASE PLAT_GICC_BASE
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_PHY_TIMER, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_0, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_1, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_2, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_3, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_4, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_5, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_6, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(INTEL_SOCFPGA_IRQ_SEC_SGI_7, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_EDGE)
+
+#define PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(grp)
+
+#define MAX_IO_HANDLES 4
+#define MAX_IO_DEVICES 4
+#define MAX_IO_BLOCK_DEVICES 2
+
+#ifndef __ASSEMBLER__
+struct socfpga_bl31_params {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+};
+#endif
+
+#endif /* PLATFORM_DEF_H */
+
diff --git a/plat/intel/soc/common/include/socfpga_emac.h b/plat/intel/soc/common/include/socfpga_emac.h
new file mode 100644
index 0000000..5b98006
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_emac.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_EMAC_H
+#define SOCFPGA_EMAC_H
+
+/* EMAC PHY Mode */
+
+#define PHY_INTERFACE_MODE_GMII_MII 0
+#define PHY_INTERFACE_MODE_RGMII 1
+#define PHY_INTERFACE_MODE_RMII 2
+#define PHY_INTERFACE_MODE_RESET 3
+
+/* Mask Definitions */
+
+#define PHY_INTF_SEL_MSK 0x3
+#define FPGAINTF_EN_3_EMAC_MSK(x) (1 << (x * 8))
+
+void socfpga_emac_init(void);
+
+#endif /* SOCFPGA_EMAC_H */
diff --git a/plat/intel/soc/common/include/socfpga_f2sdram_manager.h b/plat/intel/soc/common/include/socfpga_f2sdram_manager.h
new file mode 100644
index 0000000..82bb6cb
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_f2sdram_manager.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_F2SDRAMMANAGER_H
+#define SOCFPGA_F2SDRAMMANAGER_H
+
+#include "socfpga_plat_def.h"
+
+/* FPGA2SDRAM Register Map */
+#define SOCFPGA_F2SDRAMMGR_SIDEBANDMGR_FLAGINSTATUS0 0x14
+#define SOCFPGA_F2SDRAMMGR_SIDEBANDMGR_FLAGOUTCLR0 0x54
+#define SOCFPGA_F2SDRAMMGR_SIDEBANDMGR_FLAGOUTSET0 0x50
+
+#define FLAGOUTSETCLR_F2SDRAM0_ENABLE (BIT(1))
+#define FLAGOUTSETCLR_F2SDRAM1_ENABLE (BIT(4))
+#define FLAGOUTSETCLR_F2SDRAM2_ENABLE (BIT(7))
+
+#define FLAGOUTSETCLR_F2SDRAM0_IDLEREQ (BIT(0))
+#define FLAGOUTSETCLR_F2SDRAM1_IDLEREQ (BIT(3))
+#define FLAGOUTSETCLR_F2SDRAM2_IDLEREQ (BIT(6))
+#define FLAGINTSTATUS_F2SDRAM0_IDLEACK (BIT(1))
+#define FLAGINTSTATUS_F2SDRAM1_IDLEACK (BIT(5))
+#define FLAGINTSTATUS_F2SDRAM2_IDLEACK (BIT(9))
+#define FLAGOUTSETCLR_F2SDRAM0_FORCE_DRAIN (BIT(2))
+#define FLAGOUTSETCLR_F2SDRAM1_FORCE_DRAIN (BIT(5))
+#define FLAGOUTSETCLR_F2SDRAM2_FORCE_DRAIN (BIT(8))
+
+#define FLAGINTSTATUS_F2SOC_RESPEMPTY (BIT(3))
+#define FLAGINTSTATUS_F2SDRAM0_RESPEMPTY (BIT(3))
+#define FLAGINTSTATUS_F2SDRAM1_RESPEMPTY (BIT(7))
+#define FLAGINTSTATUS_F2SDRAM2_RESPEMPTY (BIT(11))
+
+#define SOCFPGA_F2SDRAMMGR(_reg) (SOCFPGA_F2SDRAMMGR_REG_BASE \
+ + (SOCFPGA_F2SDRAMMGR_##_reg))
+
+#endif /* SOCFPGA_F2SDRAMMGR_H */
diff --git a/plat/intel/soc/common/include/socfpga_fcs.h b/plat/intel/soc/common/include/socfpga_fcs.h
new file mode 100644
index 0000000..893551d
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_fcs.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_FCS_H
+#define SOCFPGA_FCS_H
+
+/* FCS Definitions */
+
+#define FCS_RANDOM_WORD_SIZE 8U
+#define FCS_PROV_DATA_WORD_SIZE 44U
+#define FCS_SHA384_WORD_SIZE 12U
+
+#define FCS_RANDOM_BYTE_SIZE (FCS_RANDOM_WORD_SIZE * 4U)
+#define FCS_RANDOM_EXT_MAX_WORD_SIZE 1020U
+#define FCS_PROV_DATA_BYTE_SIZE (FCS_PROV_DATA_WORD_SIZE * 4U)
+#define FCS_SHA384_BYTE_SIZE (FCS_SHA384_WORD_SIZE * 4U)
+
+#define FCS_RANDOM_EXT_OFFSET 3
+
+#define FCS_MODE_DECRYPT 0x0
+#define FCS_MODE_ENCRYPT 0x1
+#define FCS_ENCRYPTION_DATA_0 0x10100
+#define FCS_DECRYPTION_DATA_0 0x10102
+#define FCS_OWNER_ID_OFFSET 0xC
+#define FCS_CRYPTION_CRYPTO_HEADER 0x07000000
+#define FCS_CRYPTION_RESP_WORD_SIZE 4U
+#define FCS_CRYPTION_RESP_SIZE_OFFSET 3U
+
+#define PSGSIGMA_TEARDOWN_MAGIC 0xB852E2A4
+#define PSGSIGMA_SESSION_ID_ONE 0x1
+#define PSGSIGMA_UNKNOWN_SESSION 0xFFFFFFFF
+
+#define RESERVED_AS_ZERO 0x0
+/* FCS Single cert */
+
+#define FCS_BIG_CNTR_SEL 0x1
+
+#define FCS_SVN_CNTR_0_SEL 0x2
+#define FCS_SVN_CNTR_1_SEL 0x3
+#define FCS_SVN_CNTR_2_SEL 0x4
+#define FCS_SVN_CNTR_3_SEL 0x5
+
+#define FCS_BIG_CNTR_VAL_MAX 495U
+#define FCS_SVN_CNTR_VAL_MAX 64U
+
+/* FCS Attestation Cert Request Parameter */
+
+#define FCS_ATTEST_FIRMWARE_CERT 0x01
+#define FCS_ATTEST_DEV_ID_SELF_SIGN_CERT 0x02
+#define FCS_ATTEST_DEV_ID_ENROLL_CERT 0x04
+#define FCS_ATTEST_ENROLL_SELF_SIGN_CERT 0x08
+#define FCS_ATTEST_ALIAS_CERT 0x10
+#define FCS_ATTEST_CERT_MAX_REQ_PARAM 0xFF
+
+/* FCS Crypto Service */
+
+#define FCS_CS_KEY_OBJ_MAX_WORD_SIZE 88U
+#define FCS_CS_KEY_INFO_MAX_WORD_SIZE 36U
+#define FCS_CS_KEY_RESP_STATUS_MASK 0xFF
+#define FCS_CS_KEY_RESP_STATUS_OFFSET 16U
+
+#define FCS_CS_FIELD_SIZE_MASK 0xFFFF
+#define FCS_CS_FIELD_FLAG_OFFSET 24
+#define FCS_CS_FIELD_FLAG_INIT BIT(0)
+#define FCS_CS_FIELD_FLAG_UPDATE BIT(1)
+#define FCS_CS_FIELD_FLAG_FINALIZE BIT(2)
+
+#define FCS_AES_MAX_DATA_SIZE 0x10000000 /* 256 MB */
+#define FCS_AES_MIN_DATA_SIZE 0x20 /* 32 Byte */
+#define FCS_AES_CMD_MAX_WORD_SIZE 15U
+
+#define FCS_GET_DIGEST_CMD_MAX_WORD_SIZE 7U
+#define FCS_GET_DIGEST_RESP_MAX_WORD_SIZE 19U
+#define FCS_MAC_VERIFY_CMD_MAX_WORD_SIZE 23U
+#define FCS_MAC_VERIFY_RESP_MAX_WORD_SIZE 4U
+#define FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET 8U
+
+#define FCS_ECDSA_GET_PUBKEY_MAX_WORD_SIZE 5U
+#define FCS_ECDSA_SHA2_DATA_SIGN_CMD_MAX_WORD_SIZE 7U
+#define FCS_ECDSA_SHA2_DATA_SIG_VERIFY_CMD_MAX_WORD_SIZE 43U
+#define FCS_ECDSA_HASH_SIGN_CMD_MAX_WORD_SIZE 17U
+#define FCS_ECDSA_HASH_SIG_VERIFY_CMD_MAX_WORD_SIZE 52U
+#define FCS_ECDH_REQUEST_CMD_MAX_WORD_SIZE 29U
+/* FCS Payload Structure */
+typedef struct fcs_rng_payload_t {
+ uint32_t session_id;
+ uint32_t context_id;
+ uint32_t crypto_header;
+ uint32_t size;
+} fcs_rng_payload;
+
+typedef struct fcs_encrypt_payload_t {
+ uint32_t first_word;
+ uint32_t src_addr;
+ uint32_t src_size;
+ uint32_t dst_addr;
+ uint32_t dst_size;
+} fcs_encrypt_payload;
+
+typedef struct fcs_decrypt_payload_t {
+ uint32_t first_word;
+ uint32_t owner_id[2];
+ uint32_t src_addr;
+ uint32_t src_size;
+ uint32_t dst_addr;
+ uint32_t dst_size;
+} fcs_decrypt_payload;
+
+typedef struct fcs_encrypt_ext_payload_t {
+ uint32_t session_id;
+ uint32_t context_id;
+ uint32_t crypto_header;
+ uint32_t src_addr;
+ uint32_t src_size;
+ uint32_t dst_addr;
+ uint32_t dst_size;
+} fcs_encrypt_ext_payload;
+
+typedef struct fcs_decrypt_ext_payload_t {
+ uint32_t session_id;
+ uint32_t context_id;
+ uint32_t crypto_header;
+ uint32_t owner_id[2];
+ uint32_t src_addr;
+ uint32_t src_size;
+ uint32_t dst_addr;
+ uint32_t dst_size;
+} fcs_decrypt_ext_payload;
+
+typedef struct psgsigma_teardown_msg_t {
+ uint32_t reserved_word;
+ uint32_t magic_word;
+ uint32_t session_id;
+} psgsigma_teardown_msg;
+
+typedef struct fcs_cntr_set_preauth_payload_t {
+ uint32_t first_word;
+ uint32_t counter_value;
+} fcs_cntr_set_preauth_payload;
+
+typedef struct fcs_cs_key_payload_t {
+ uint32_t session_id;
+ uint32_t reserved0;
+ uint32_t reserved1;
+ uint32_t key_id;
+} fcs_cs_key_payload;
+
+typedef struct fcs_crypto_service_data_t {
+ uint32_t session_id;
+ uint32_t context_id;
+ uint32_t key_id;
+ uint32_t crypto_param_size;
+ uint64_t crypto_param;
+ uint8_t is_updated;
+} fcs_crypto_service_data;
+
+typedef struct fcs_crypto_service_aes_data_t {
+ uint32_t session_id;
+ uint32_t context_id;
+ uint32_t param_size;
+ uint32_t key_id;
+ uint32_t crypto_param[7];
+ uint8_t is_updated;
+} fcs_crypto_service_aes_data;
+
+/* Functions Definitions */
+
+uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
+ uint32_t *mbox_error);
+int intel_fcs_random_number_gen_ext(uint32_t session_id, uint32_t context_id,
+ uint32_t size, uint32_t *send_id);
+uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size,
+ uint32_t *send_id);
+uint32_t intel_fcs_get_provision_data(uint32_t *send_id);
+uint32_t intel_fcs_cntr_set_preauth(uint8_t counter_type,
+ int32_t counter_value,
+ uint32_t test_bit,
+ uint32_t *mbox_error);
+uint32_t intel_fcs_encryption(uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t dst_size,
+ uint32_t *send_id);
+
+uint32_t intel_fcs_decryption(uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t dst_size,
+ uint32_t *send_id);
+
+int intel_fcs_encryption_ext(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+int intel_fcs_decryption_ext(uint32_t sesion_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+
+int intel_fcs_sigma_teardown(uint32_t session_id, uint32_t *mbox_error);
+int intel_fcs_chip_id(uint32_t *id_low, uint32_t *id_high, uint32_t *mbox_error);
+int intel_fcs_attestation_subkey(uint64_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+int intel_fcs_get_measurement(uint64_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+uint32_t intel_fcs_get_rom_patch_sha384(uint64_t addr, uint64_t *ret_size,
+ uint32_t *mbox_error);
+
+int intel_fcs_create_cert_on_reload(uint32_t cert_request,
+ uint32_t *mbox_error);
+int intel_fcs_get_attestation_cert(uint32_t cert_request, uint64_t dst_addr,
+ uint32_t *dst_size, uint32_t *mbox_error);
+
+int intel_fcs_open_crypto_service_session(uint32_t *session_id,
+ uint32_t *mbox_error);
+int intel_fcs_close_crypto_service_session(uint32_t session_id,
+ uint32_t *mbox_error);
+
+int intel_fcs_import_crypto_service_key(uint64_t src_addr, uint32_t src_size,
+ uint32_t *mbox_error);
+int intel_fcs_export_crypto_service_key(uint32_t session_id, uint32_t key_id,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+int intel_fcs_remove_crypto_service_key(uint32_t session_id, uint32_t key_id,
+ uint32_t *mbox_error);
+int intel_fcs_get_crypto_service_key_info(uint32_t session_id, uint32_t key_id,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+
+int intel_fcs_get_digest_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error);
+int intel_fcs_get_digest_update_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint8_t is_finalised, uint32_t *mbox_error);
+
+int intel_fcs_mac_verify_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error);
+int intel_fcs_mac_verify_update_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t data_size, uint8_t is_finalised,
+ uint32_t *mbox_error);
+
+int intel_fcs_ecdsa_hash_sign_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error);
+int intel_fcs_ecdsa_hash_sign_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+
+int intel_fcs_ecdsa_hash_sig_verify_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error);
+int intel_fcs_ecdsa_hash_sig_verify_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+
+int intel_fcs_ecdsa_sha2_data_sign_init(uint32_t session_id,
+ uint32_t context_id, uint32_t key_id,
+ uint32_t param_size, uint64_t param_data,
+ uint32_t *mbox_error);
+int intel_fcs_ecdsa_sha2_data_sign_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint32_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t *dst_size, uint8_t is_finalised,
+ uint32_t *mbox_error);
+
+int intel_fcs_ecdsa_sha2_data_sig_verify_init(uint32_t session_id,
+ uint32_t context_id, uint32_t key_id,
+ uint32_t param_size, uint64_t param_data,
+ uint32_t *mbox_error);
+int intel_fcs_ecdsa_sha2_data_sig_verify_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint32_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t *dst_size, uint32_t data_size,
+ uint8_t is_finalised, uint32_t *mbox_error);
+
+int intel_fcs_ecdsa_get_pubkey_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error);
+int intel_fcs_ecdsa_get_pubkey_finalize(uint32_t session_id, uint32_t context_id,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+
+int intel_fcs_ecdh_request_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error);
+int intel_fcs_ecdh_request_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error);
+
+int intel_fcs_aes_crypt_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint64_t param_addr,
+ uint32_t param_size, uint32_t *mbox_error);
+int intel_fcs_aes_crypt_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint64_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t dst_size, uint8_t is_finalised,
+ uint32_t *send_id);
+
+#endif /* SOCFPGA_FCS_H */
diff --git a/plat/intel/soc/common/include/socfpga_handoff.h b/plat/intel/soc/common/include/socfpga_handoff.h
new file mode 100644
index 0000000..ba0f7f3
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_handoff.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef HANDOFF_H
+#define HANDOFF_H
+
+#define HANDOFF_MAGIC_HEADER 0x424f4f54 /* BOOT */
+#define HANDOFF_MAGIC_PINMUX_SEL 0x504d5558 /* PMUX */
+#define HANDOFF_MAGIC_IOCTLR 0x494f4354 /* IOCT */
+#define HANDOFF_MAGIC_FPGA 0x46504741 /* FPGA */
+#define HANDOFF_MAGIC_IODELAY 0x444c4159 /* DLAY */
+#define HANDOFF_MAGIC_CLOCK 0x434c4b53 /* CLKS */
+#define HANDOFF_MAGIC_MISC 0x4d495343 /* MISC */
+
+#include <socfpga_plat_def.h>
+
+typedef struct handoff_t {
+ /* header */
+ uint32_t header_magic;
+ uint32_t header_device;
+ uint32_t _pad_0x08_0x10[2];
+
+ /* pinmux configuration - select */
+ uint32_t pinmux_sel_magic;
+ uint32_t pinmux_sel_length;
+ uint32_t _pad_0x18_0x20[2];
+ uint32_t pinmux_sel_array[96]; /* offset, value */
+
+ /* pinmux configuration - io control */
+ uint32_t pinmux_io_magic;
+ uint32_t pinmux_io_length;
+ uint32_t _pad_0x1a8_0x1b0[2];
+ uint32_t pinmux_io_array[96]; /* offset, value */
+
+ /* pinmux configuration - use fpga switch */
+ uint32_t pinmux_fpga_magic;
+ uint32_t pinmux_fpga_length;
+ uint32_t _pad_0x338_0x340[2];
+ uint32_t pinmux_fpga_array[42]; /* offset, value */
+ uint32_t _pad_0x3e8_0x3f0[2];
+
+ /* pinmux configuration - io delay */
+ uint32_t pinmux_delay_magic;
+ uint32_t pinmux_delay_length;
+ uint32_t _pad_0x3f8_0x400[2];
+ uint32_t pinmux_iodelay_array[96]; /* offset, value */
+
+ /* clock configuration */
+
+#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10
+ uint32_t clock_magic;
+ uint32_t clock_length;
+ uint32_t _pad_0x588_0x590[2];
+ uint32_t main_pll_mpuclk;
+ uint32_t main_pll_nocclk;
+ uint32_t main_pll_cntr2clk;
+ uint32_t main_pll_cntr3clk;
+ uint32_t main_pll_cntr4clk;
+ uint32_t main_pll_cntr5clk;
+ uint32_t main_pll_cntr6clk;
+ uint32_t main_pll_cntr7clk;
+ uint32_t main_pll_cntr8clk;
+ uint32_t main_pll_cntr9clk;
+ uint32_t main_pll_nocdiv;
+ uint32_t main_pll_pllglob;
+ uint32_t main_pll_fdbck;
+ uint32_t main_pll_pllc0;
+ uint32_t main_pll_pllc1;
+ uint32_t _pad_0x5cc_0x5d0[1];
+ uint32_t per_pll_cntr2clk;
+ uint32_t per_pll_cntr3clk;
+ uint32_t per_pll_cntr4clk;
+ uint32_t per_pll_cntr5clk;
+ uint32_t per_pll_cntr6clk;
+ uint32_t per_pll_cntr7clk;
+ uint32_t per_pll_cntr8clk;
+ uint32_t per_pll_cntr9clk;
+ uint32_t per_pll_emacctl;
+ uint32_t per_pll_gpiodiv;
+ uint32_t per_pll_pllglob;
+ uint32_t per_pll_fdbck;
+ uint32_t per_pll_pllc0;
+ uint32_t per_pll_pllc1;
+ uint32_t hps_osc_clk_h;
+ uint32_t fpga_clk_hz;
+#elif PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX
+ uint32_t clock_magic;
+ uint32_t clock_length;
+ uint32_t _pad_0x588_0x590[2];
+ uint32_t main_pll_mpuclk;
+ uint32_t main_pll_nocclk;
+ uint32_t main_pll_nocdiv;
+ uint32_t main_pll_pllglob;
+ uint32_t main_pll_fdbck;
+ uint32_t main_pll_pllc0;
+ uint32_t main_pll_pllc1;
+ uint32_t main_pll_pllc2;
+ uint32_t main_pll_pllc3;
+ uint32_t main_pll_pllm;
+ uint32_t per_pll_emacctl;
+ uint32_t per_pll_gpiodiv;
+ uint32_t per_pll_pllglob;
+ uint32_t per_pll_fdbck;
+ uint32_t per_pll_pllc0;
+ uint32_t per_pll_pllc1;
+ uint32_t per_pll_pllc2;
+ uint32_t per_pll_pllc3;
+ uint32_t per_pll_pllm;
+ uint32_t alt_emacactr;
+ uint32_t alt_emacbctr;
+ uint32_t alt_emacptpctr;
+ uint32_t alt_gpiodbctr;
+ uint32_t alt_sdmmcctr;
+ uint32_t alt_s2fuser0ctr;
+ uint32_t alt_s2fuser1ctr;
+ uint32_t alt_psirefctr;
+ uint32_t hps_osc_clk_h;
+ uint32_t fpga_clk_hz;
+ uint32_t _pad_0x604_0x610[3];
+#endif
+ /* misc configuration */
+ uint32_t misc_magic;
+ uint32_t misc_length;
+ uint32_t _pad_0x618_0x620[2];
+} handoff;
+
+int verify_handoff_image(handoff *hoff_ptr, handoff *reverse_hoff_ptr);
+int socfpga_get_handoff(handoff *hoff_ptr);
+
+#endif
+
+
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
new file mode 100644
index 0000000..1f4b2a4
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_MBOX_H
+#define SOCFPGA_MBOX_H
+
+#include <lib/utils_def.h>
+
+
+#define MBOX_OFFSET 0xffa30000
+
+#define MBOX_ATF_CLIENT_ID 0x1U
+#define MBOX_MAX_JOB_ID 0xFU
+#define MBOX_MAX_IND_JOB_ID (MBOX_MAX_JOB_ID - 1U)
+#define MBOX_JOB_ID MBOX_MAX_JOB_ID
+#define MBOX_TEST_BIT BIT(31)
+
+/* Mailbox Shared Memory Register Map */
+#define MBOX_CIN 0x00
+#define MBOX_ROUT 0x04
+#define MBOX_URG 0x08
+#define MBOX_INT 0x0C
+#define MBOX_COUT 0x20
+#define MBOX_RIN 0x24
+#define MBOX_STATUS 0x2C
+#define MBOX_CMD_BUFFER 0x40
+#define MBOX_RESP_BUFFER 0xC0
+
+/* Mailbox SDM doorbell */
+#define MBOX_DOORBELL_TO_SDM 0x400
+#define MBOX_DOORBELL_FROM_SDM 0x480
+
+
+/* Mailbox commands */
+
+#define MBOX_CMD_NOOP 0x00
+#define MBOX_CMD_SYNC 0x01
+#define MBOX_CMD_RESTART 0x02
+#define MBOX_CMD_CANCEL 0x03
+#define MBOX_CMD_VAB_SRC_CERT 0x0B
+#define MBOX_CMD_GET_IDCODE 0x10
+#define MBOX_CMD_GET_USERCODE 0x13
+#define MBOX_CMD_GET_CHIPID 0x12
+#define MBOX_CMD_REBOOT_HPS 0x47
+
+/* Reconfiguration Commands */
+#define MBOX_CONFIG_STATUS 0x04
+#define MBOX_RECONFIG 0x06
+#define MBOX_RECONFIG_DATA 0x08
+#define MBOX_RECONFIG_STATUS 0x09
+
+/* HWMON Commands */
+#define MBOX_HWMON_READVOLT 0x18
+#define MBOX_HWMON_READTEMP 0x19
+
+
+/* QSPI Commands */
+#define MBOX_CMD_QSPI_OPEN 0x32
+#define MBOX_CMD_QSPI_CLOSE 0x33
+#define MBOX_CMD_QSPI_SET_CS 0x34
+#define MBOX_CMD_QSPI_DIRECT 0x3B
+
+/* RSU Commands */
+#define MBOX_GET_SUBPARTITION_TABLE 0x5A
+#define MBOX_RSU_STATUS 0x5B
+#define MBOX_RSU_UPDATE 0x5C
+#define MBOX_HPS_STAGE_NOTIFY 0x5D
+
+/* FCS Command */
+#define MBOX_FCS_GET_PROVISION 0x7B
+#define MBOX_FCS_CNTR_SET_PREAUTH 0x7C
+#define MBOX_FCS_ENCRYPT_REQ 0x7E
+#define MBOX_FCS_DECRYPT_REQ 0x7F
+#define MBOX_FCS_RANDOM_GEN 0x80
+#define MBOX_FCS_AES_CRYPT_REQ 0x81
+#define MBOX_FCS_GET_DIGEST_REQ 0x82
+#define MBOX_FCS_MAC_VERIFY_REQ 0x83
+#define MBOX_FCS_ECDSA_HASH_SIGN_REQ 0x84
+#define MBOX_FCS_ECDSA_SHA2_DATA_SIGN_REQ 0x85
+#define MBOX_FCS_ECDSA_HASH_SIG_VERIFY 0x86
+#define MBOX_FCS_ECDSA_SHA2_DATA_SIGN_VERIFY 0x87
+#define MBOX_FCS_ECDSA_GET_PUBKEY 0x88
+#define MBOX_FCS_ECDH_REQUEST 0x89
+#define MBOX_FCS_OPEN_CS_SESSION 0xA0
+#define MBOX_FCS_CLOSE_CS_SESSION 0xA1
+#define MBOX_FCS_IMPORT_CS_KEY 0xA5
+#define MBOX_FCS_EXPORT_CS_KEY 0xA6
+#define MBOX_FCS_REMOVE_CS_KEY 0xA7
+#define MBOX_FCS_GET_CS_KEY_INFO 0xA8
+
+/* PSG SIGMA Commands */
+#define MBOX_PSG_SIGMA_TEARDOWN 0xD5
+
+/* Attestation Commands */
+#define MBOX_CREATE_CERT_ON_RELOAD 0x180
+#define MBOX_GET_ATTESTATION_CERT 0x181
+#define MBOX_ATTESTATION_SUBKEY 0x182
+#define MBOX_GET_MEASUREMENT 0x183
+
+/* Miscellaneous commands */
+#define MBOX_GET_ROM_PATCH_SHA384 0x1B0
+
+/* Mailbox Definitions */
+
+#define CMD_DIRECT 0
+#define CMD_INDIRECT 1
+#define CMD_CASUAL 0
+#define CMD_URGENT 1
+
+#define MBOX_WORD_BYTE 4U
+#define MBOX_RESP_BUFFER_SIZE 16
+#define MBOX_CMD_BUFFER_SIZE 32
+#define MBOX_INC_HEADER_MAX_WORD_SIZE 1024U
+
+/* Execution states for HPS_STAGE_NOTIFY */
+#define HPS_EXECUTION_STATE_FSBL 0
+#define HPS_EXECUTION_STATE_SSBL 1
+#define HPS_EXECUTION_STATE_OS 2
+
+/* Status Response */
+#define MBOX_RET_OK 0
+#define MBOX_RET_ERROR -1
+#define MBOX_NO_RESPONSE -2
+#define MBOX_WRONG_ID -3
+#define MBOX_BUFFER_FULL -4
+#define MBOX_BUSY -5
+#define MBOX_TIMEOUT -2047
+
+/* Reconfig Status Response */
+#define RECONFIG_STATUS_STATE 0
+#define RECONFIG_STATUS_PIN_STATUS 2
+#define RECONFIG_STATUS_SOFTFUNC_STATUS 3
+#define PIN_STATUS_NSTATUS (U(1) << 31)
+#define SOFTFUNC_STATUS_SEU_ERROR (1 << 3)
+#define SOFTFUNC_STATUS_INIT_DONE (1 << 1)
+#define SOFTFUNC_STATUS_CONF_DONE (1 << 0)
+#define MBOX_CFGSTAT_STATE_IDLE 0x00000000
+#define MBOX_CFGSTAT_STATE_CONFIG 0x10000000
+#define MBOX_CFGSTAT_STATE_FAILACK 0x08000000
+#define MBOX_CFGSTAT_STATE_ERROR_INVALID 0xf0000001
+#define MBOX_CFGSTAT_STATE_ERROR_CORRUPT 0xf0000002
+#define MBOX_CFGSTAT_STATE_ERROR_AUTH 0xf0000003
+#define MBOX_CFGSTAT_STATE_ERROR_CORE_IO 0xf0000004
+#define MBOX_CFGSTAT_STATE_ERROR_HARDWARE 0xf0000005
+#define MBOX_CFGSTAT_STATE_ERROR_FAKE 0xf0000006
+#define MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO 0xf0000007
+#define MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR 0xf0000008
+
+
+/* Mailbox Macros */
+
+#define MBOX_ENTRY_TO_ADDR(_buf, ptr) (MBOX_OFFSET + (MBOX_##_buf##_BUFFER) \
+ + MBOX_WORD_BYTE * (ptr))
+
+/* Mailbox interrupt flags and masks */
+#define MBOX_INT_FLAG_COE 0x1
+#define MBOX_INT_FLAG_RIE 0x2
+#define MBOX_INT_FLAG_UAE 0x100
+#define MBOX_COE_BIT(INTERRUPT) ((INTERRUPT) & 0x3)
+#define MBOX_UAE_BIT(INTERRUPT) (((INTERRUPT) & (1<<8)))
+
+/* Mailbox response and status */
+#define MBOX_RESP_ERR(BUFFER) ((BUFFER) & 0x000007ff)
+#define MBOX_RESP_LEN(BUFFER) (((BUFFER) & 0x007ff000) >> 12)
+#define MBOX_RESP_CLIENT_ID(BUFFER) (((BUFFER) & 0xf0000000) >> 28)
+#define MBOX_RESP_JOB_ID(BUFFER) (((BUFFER) & 0x0f000000) >> 24)
+#define MBOX_STATUS_UA_MASK (1<<8)
+
+/* Mailbox command and response */
+#define MBOX_CLIENT_ID_CMD(CLIENT_ID) ((CLIENT_ID) << 28)
+#define MBOX_JOB_ID_CMD(JOB_ID) (JOB_ID<<24)
+#define MBOX_CMD_LEN_CMD(CMD_LEN) ((CMD_LEN) << 12)
+#define MBOX_INDIRECT(val) ((val) << 11)
+#define MBOX_CMD_MASK(header) ((header) & 0x7ff)
+
+/* Mailbox payload */
+#define MBOX_DATA_MAX_LEN 0x3ff
+#define MBOX_PAYLOAD_FLAG_BUSY BIT(0)
+
+/* RSU Macros */
+#define RSU_VERSION_ACMF BIT(8)
+#define RSU_VERSION_ACMF_MASK 0xff00
+
+/* Config Status Macros */
+#define CONFIG_STATUS_WORD_SIZE 16U
+#define CONFIG_STATUS_FW_VER_OFFSET 1
+#define CONFIG_STATUS_FW_VER_MASK 0x00FFFFFF
+
+/* Data structure */
+
+typedef struct mailbox_payload {
+ uint32_t header;
+ uint32_t data[MBOX_DATA_MAX_LEN];
+} mailbox_payload_t;
+
+typedef struct mailbox_container {
+ uint32_t flag;
+ uint32_t index;
+ mailbox_payload_t *payload;
+} mailbox_container_t;
+
+/* Mailbox Function Definitions */
+
+void mailbox_set_int(uint32_t interrupt_input);
+int mailbox_init(void);
+void mailbox_set_qspi_close(void);
+void mailbox_hps_qspi_enable(void);
+
+int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args,
+ unsigned int len, uint32_t urgent, uint32_t *response,
+ unsigned int *resp_len);
+int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args,
+ unsigned int len, unsigned int indirect);
+int mailbox_send_cmd_async_ext(uint32_t header_cmd, uint32_t *args,
+ unsigned int len);
+int mailbox_read_response(uint32_t *job_id, uint32_t *response,
+ unsigned int *resp_len);
+int mailbox_read_response_async(uint32_t *job_id, uint32_t *header,
+ uint32_t *response, unsigned int *resp_len,
+ uint8_t ignore_client_id);
+int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
+ unsigned int *resp_len);
+
+void mailbox_reset_cold(void);
+void mailbox_clear_response(void);
+
+int intel_mailbox_get_config_status(uint32_t cmd, bool init_done);
+int intel_mailbox_is_fpga_not_ready(void);
+
+int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len);
+int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len);
+int mailbox_rsu_update(uint32_t *flash_offset);
+int mailbox_hps_stage_notify(uint32_t execution_stage);
+int mailbox_hwmon_readtemp(uint32_t chan, uint32_t *resp_buf);
+int mailbox_hwmon_readvolt(uint32_t chan, uint32_t *resp_buf);
+
+#endif /* SOCFPGA_MBOX_H */
diff --git a/plat/intel/soc/common/include/socfpga_noc.h b/plat/intel/soc/common/include/socfpga_noc.h
new file mode 100644
index 0000000..e3c0f73
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_noc.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_NOC_H
+#define SOCFPGA_NOC_H
+
+/* Macros */
+#define SCR_AXI_AP_MASK BIT(24)
+#define SCR_FPGA2SOC_MASK BIT(16)
+#define SCR_MPU_MASK BIT(0)
+#define DISABLE_L4_FIREWALL (SCR_AXI_AP_MASK | SCR_FPGA2SOC_MASK \
+ | SCR_MPU_MASK)
+#define DISABLE_BRIDGE_FIREWALL 0x0ffe0101
+
+#define SOCFPGA_CCU_NOC(_ctrl, _dev) (SOCFPGA_CCU_NOC_REG_BASE \
+ + (SOCFPGA_CCU_NOC_##_ctrl##_##_dev))
+
+#define SOCFPGA_L4_PER_SCR(_reg) (SOCFPGA_L4_PER_SCR_REG_BASE \
+ + (SOCFPGA_NOC_FW_L4_PER_SCR_##_reg))
+
+#define SOCFPGA_L4_SYS_SCR(_reg) (SOCFPGA_L4_SYS_SCR_REG_BASE \
+ + (SOCFPGA_NOC_FW_L4_SYS_SCR_##_reg))
+
+/* L3 Interconnect Register Map */
+#define SOCFPGA_NOC_FW_L4_PER_SCR_NAND_REGISTER 0x0000
+#define SOCFPGA_NOC_FW_L4_PER_SCR_NAND_DATA 0x0004
+#define SOCFPGA_NOC_FW_L4_PER_SCR_USB0_REGISTER 0x000c
+#define SOCFPGA_NOC_FW_L4_PER_SCR_USB1_REGISTER 0x0010
+#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_MASTER0 0x001c
+#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_MASTER1 0x0020
+#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_SLAVE0 0x0024
+#define SOCFPGA_NOC_FW_L4_PER_SCR_SPI_SLAVE1 0x0028
+#define SOCFPGA_NOC_FW_L4_PER_SCR_EMAC0 0x002c
+#define SOCFPGA_NOC_FW_L4_PER_SCR_EMAC1 0x0030
+#define SOCFPGA_NOC_FW_L4_PER_SCR_EMAC2 0x0034
+#define SOCFPGA_NOC_FW_L4_PER_SCR_SDMMC 0x0040
+#define SOCFPGA_NOC_FW_L4_PER_SCR_GPIO0 0x0044
+#define SOCFPGA_NOC_FW_L4_PER_SCR_GPIO1 0x0048
+#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C0 0x0050
+#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C1 0x0054
+#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C2 0x0058
+#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C3 0x005c
+#define SOCFPGA_NOC_FW_L4_PER_SCR_I2C4 0x0060
+#define SOCFPGA_NOC_FW_L4_PER_SCR_SP_TIMER0 0x0064
+#define SOCFPGA_NOC_FW_L4_PER_SCR_SP_TIMER1 0x0068
+#define SOCFPGA_NOC_FW_L4_PER_SCR_UART0 0x006c
+#define SOCFPGA_NOC_FW_L4_PER_SCR_UART1 0x0070
+
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_DMA_ECC 0x0008
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC0RX_ECC 0x000c
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC0TX_ECC 0x0010
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC1RX_ECC 0x0014
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC1TX_ECC 0x0018
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC2RX_ECC 0x001c
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_EMAC2TX_ECC 0x0020
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_NAND_ECC 0x002c
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_NAND_READ_ECC 0x0030
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_NAND_WRITE_ECC 0x0034
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_OCRAM_ECC 0x0038
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_SDMMC_ECC 0x0040
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_USB0_ECC 0x0044
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_USB1_ECC 0x0048
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_CLK_MGR 0x004c
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_IO_MGR 0x0054
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_RST_MGR 0x0058
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_SYS_MGR 0x005c
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_OSC0_TIMER 0x0060
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_OSC1_TIMER 0x0064
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG0 0x0068
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG1 0x006c
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG2 0x0070
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_WATCHDOG3 0x0074
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_DAP 0x0078
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_L4_NOC_PROBES 0x0090
+#define SOCFPGA_NOC_FW_L4_SYS_SCR_L4_NOC_QOS 0x0094
+
+/* CCU NOC Register Map */
+
+#define SOCFPGA_CCU_NOC_CPU0_RAM0 0x04688
+#define SOCFPGA_CCU_NOC_IOM_RAM0 0x18628
+
+#define SOCFPGA_CCU_NOC_ADMASK_P_MASK BIT(0)
+#define SOCFPGA_CCU_NOC_ADMASK_NS_MASK BIT(1)
+
+/* Function Definitions */
+
+void enable_ns_peripheral_access(void);
+void enable_ns_bridge_access(void);
+void enable_ns_ocram_access(void);
+void enable_ocram_firewall(void);
+
+#endif
diff --git a/plat/intel/soc/common/include/socfpga_private.h b/plat/intel/soc/common/include/socfpga_private.h
new file mode 100644
index 0000000..9d389e3
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_private.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_PRIVATE_H
+#define SOCFPGA_PRIVATE_H
+
+#include "socfpga_plat_def.h"
+
+#define EMMC_DESC_SIZE (1<<20)
+
+#define EMMC_INIT_PARAMS(base, clk) \
+ { .bus_width = MMC_BUS_WIDTH_4, \
+ .clk_rate = (clk), \
+ .desc_base = (base), \
+ .desc_size = EMMC_DESC_SIZE, \
+ .flags = 0, \
+ .reg_base = SOCFPGA_MMC_REG_BASE \
+ }
+
+typedef enum {
+ BOOT_SOURCE_FPGA = 0,
+ BOOT_SOURCE_SDMMC,
+ BOOT_SOURCE_NAND,
+ BOOT_SOURCE_RSVD,
+ BOOT_SOURCE_QSPI
+} boot_source_type;
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+void enable_nonsecure_access(void);
+
+void socfpga_io_setup(int boot_source);
+
+void socfgpa_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+
+
+void socfpga_configure_mmu_el1(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit);
+
+void socfpga_delay_timer_init(void);
+
+void socfpga_gic_driver_init(void);
+
+void socfpga_delay_timer_init_args(void);
+
+uint32_t socfpga_get_spsr_for_bl32_entry(void);
+
+uint32_t socfpga_get_spsr_for_bl33_entry(void);
+
+unsigned long socfpga_get_ns_image_entrypoint(void);
+
+void plat_secondary_cpus_bl31_entry(void);
+
+#endif /* SOCFPGA_PRIVATE_H */
diff --git a/plat/intel/soc/common/include/socfpga_reset_manager.h b/plat/intel/soc/common/include/socfpga_reset_manager.h
new file mode 100644
index 0000000..cce16ab
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_reset_manager.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_RESETMANAGER_H
+#define SOCFPGA_RESETMANAGER_H
+
+#include "socfpga_plat_def.h"
+
+#define SOCFPGA_BRIDGE_ENABLE BIT(0)
+#define SOCFPGA_BRIDGE_HAS_MASK BIT(1)
+
+#define SOC2FPGA_MASK (1<<0)
+#define LWHPS2FPGA_MASK (1<<1)
+#define FPGA2SOC_MASK (1<<2)
+#define F2SDRAM0_MASK (1<<3)
+#define F2SDRAM1_MASK (1<<4)
+#define F2SDRAM2_MASK (1<<5)
+
+/* Register Mapping */
+
+#define SOCFPGA_RSTMGR_STAT 0x000
+#define SOCFPGA_RSTMGR_HDSKEN 0x010
+#define SOCFPGA_RSTMGR_HDSKREQ 0x014
+#define SOCFPGA_RSTMGR_HDSKACK 0x018
+#define SOCFPGA_RSTMGR_MPUMODRST 0x020
+#define SOCFPGA_RSTMGR_PER0MODRST 0x024
+#define SOCFPGA_RSTMGR_PER1MODRST 0x028
+#define SOCFPGA_RSTMGR_BRGMODRST 0x02c
+#define SOCFPGA_RSTMGR_COLDMODRST 0x034
+#define SOCFPGA_RSTMGR_HDSKTIMEOUT 0x064
+
+/* Field Mapping */
+
+#define RSTMGR_PER0MODRST_EMAC0 0x00000001
+#define RSTMGR_PER0MODRST_EMAC1 0x00000002
+#define RSTMGR_PER0MODRST_EMAC2 0x00000004
+#define RSTMGR_PER0MODRST_USB0 0x00000008
+#define RSTMGR_PER0MODRST_USB1 0x00000010
+#define RSTMGR_PER0MODRST_NAND 0x00000020
+#define RSTMGR_PER0MODRST_SDMMC 0x00000080
+#define RSTMGR_PER0MODRST_EMAC0OCP 0x00000100
+#define RSTMGR_PER0MODRST_EMAC1OCP 0x00000200
+#define RSTMGR_PER0MODRST_EMAC2OCP 0x00000400
+#define RSTMGR_PER0MODRST_USB0OCP 0x00000800
+#define RSTMGR_PER0MODRST_USB1OCP 0x00001000
+#define RSTMGR_PER0MODRST_NANDOCP 0x00002000
+#define RSTMGR_PER0MODRST_SDMMCOCP 0x00008000
+#define RSTMGR_PER0MODRST_DMA 0x00010000
+#define RSTMGR_PER0MODRST_SPIM0 0x00020000
+#define RSTMGR_PER0MODRST_SPIM1 0x00040000
+#define RSTMGR_PER0MODRST_SPIS0 0x00080000
+#define RSTMGR_PER0MODRST_SPIS1 0x00100000
+#define RSTMGR_PER0MODRST_DMAOCP 0x00200000
+#define RSTMGR_PER0MODRST_EMACPTP 0x00400000
+#define RSTMGR_PER0MODRST_DMAIF0 0x01000000
+#define RSTMGR_PER0MODRST_DMAIF1 0x02000000
+#define RSTMGR_PER0MODRST_DMAIF2 0x04000000
+#define RSTMGR_PER0MODRST_DMAIF3 0x08000000
+#define RSTMGR_PER0MODRST_DMAIF4 0x10000000
+#define RSTMGR_PER0MODRST_DMAIF5 0x20000000
+#define RSTMGR_PER0MODRST_DMAIF6 0x40000000
+#define RSTMGR_PER0MODRST_DMAIF7 0x80000000
+
+#define RSTMGR_PER1MODRST_WATCHDOG0 0x00000001
+#define RSTMGR_PER1MODRST_WATCHDOG1 0x00000002
+#define RSTMGR_PER1MODRST_WATCHDOG2 0x00000004
+#define RSTMGR_PER1MODRST_WATCHDOG3 0x00000008
+#define RSTMGR_PER1MODRST_L4SYSTIMER0 0x00000010
+#define RSTMGR_PER1MODRST_L4SYSTIMER1 0x00000020
+#define RSTMGR_PER1MODRST_SPTIMER0 0x00000040
+#define RSTMGR_PER1MODRST_SPTIMER1 0x00000080
+#define RSTMGR_PER1MODRST_I2C0 0x00000100
+#define RSTMGR_PER1MODRST_I2C1 0x00000200
+#define RSTMGR_PER1MODRST_I2C2 0x00000400
+#define RSTMGR_PER1MODRST_I2C3 0x00000800
+#define RSTMGR_PER1MODRST_I2C4 0x00001000
+#define RSTMGR_PER1MODRST_UART0 0x00010000
+#define RSTMGR_PER1MODRST_UART1 0x00020000
+#define RSTMGR_PER1MODRST_GPIO0 0x01000000
+#define RSTMGR_PER1MODRST_GPIO1 0x02000000
+
+#define RSTMGR_HDSKEN_FPGAHSEN 0x00000004
+#define RSTMGR_HDSKEN_ETRSTALLEN 0x00000008
+#define RSTMGR_HDSKEN_L2FLUSHEN 0x00000100
+#define RSTMGR_HDSKEN_L3NOC_DBG 0x00010000
+#define RSTMGR_HDSKEN_DEBUG_L3NOC 0x00020000
+#define RSTMGR_HDSKEN_SDRSELFREFEN 0x00000001
+
+#define RSTMGR_HDSKEQ_FPGAHSREQ 0x4
+
+#define RSTMGR_BRGMODRST_SOC2FPGA 0x1
+#define RSTMGR_BRGMODRST_LWHPS2FPGA 0x2
+#define RSTMGR_BRGMODRST_FPGA2SOC 0x4
+#define RSTMGR_BRGMODRST_F2SSDRAM0 0x8
+#define RSTMGR_BRGMODRST_F2SSDRAM1 0x10
+#define RSTMGR_BRGMODRST_F2SSDRAM2 0x20
+#define RSTMGR_BRGMODRST_MPFE 0x40
+#define RSTMGR_BRGMODRST_DDRSCH 0x40
+
+#define RSTMGR_HDSKREQ_FPGAHSREQ (BIT(2))
+#define RSTMGR_HDSKACK_FPGAHSACK_MASK (BIT(2))
+
+/* Definitions */
+
+#define RSTMGR_L2_MODRST 0x0100
+#define RSTMGR_HDSKEN_SET 0x010D
+
+/* Macros */
+
+#define SOCFPGA_RSTMGR(_reg) (SOCFPGA_RSTMGR_REG_BASE \
+ + (SOCFPGA_RSTMGR_##_reg))
+#define RSTMGR_FIELD(_reg, _field) (RSTMGR_##_reg##MODRST_##_field)
+
+/* Function Declarations */
+
+void deassert_peripheral_reset(void);
+void config_hps_hs_before_warm_reset(void);
+
+int socfpga_bridges_enable(uint32_t mask);
+int socfpga_bridges_disable(uint32_t mask);
+
+#endif /* SOCFPGA_RESETMANAGER_H */
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
new file mode 100644
index 0000000..0803eb5
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_SIP_SVC_H
+#define SOCFPGA_SIP_SVC_H
+
+
+/* SiP status response */
+#define INTEL_SIP_SMC_STATUS_OK 0
+#define INTEL_SIP_SMC_STATUS_BUSY 0x1
+#define INTEL_SIP_SMC_STATUS_REJECTED 0x2
+#define INTEL_SIP_SMC_STATUS_NO_RESPONSE 0x3
+#define INTEL_SIP_SMC_STATUS_ERROR 0x4
+#define INTEL_SIP_SMC_RSU_ERROR 0x7
+
+/* SiP mailbox error code */
+#define GENERIC_RESPONSE_ERROR 0x3FF
+
+/* SiP V2 command code range */
+#define INTEL_SIP_SMC_CMD_MASK 0xFFFF
+#define INTEL_SIP_SMC_CMD_V2_RANGE_BEGIN 0x400
+#define INTEL_SIP_SMC_CMD_V2_RANGE_END 0x4FF
+
+/* SiP V2 protocol header */
+#define INTEL_SIP_SMC_HEADER_JOB_ID_MASK 0xF
+#define INTEL_SIP_SMC_HEADER_JOB_ID_OFFSET 0U
+#define INTEL_SIP_SMC_HEADER_CID_MASK 0xF
+#define INTEL_SIP_SMC_HEADER_CID_OFFSET 4U
+#define INTEL_SIP_SMC_HEADER_VERSION_MASK 0xF
+#define INTEL_SIP_SMC_HEADER_VERSION_OFFSET 60U
+
+/* SMC SiP service function identifier for version 1 */
+
+/* FPGA Reconfig */
+#define INTEL_SIP_SMC_FPGA_CONFIG_START 0xC2000001
+#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE 0x42000002
+#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE 0xC2000003
+#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE 0xC2000004
+#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM 0xC2000005
+
+/* FPGA Bitstream Flag */
+#define FLAG_PARTIAL_CONFIG BIT(0)
+#define FLAG_AUTHENTICATION BIT(1)
+#define CONFIG_TEST_FLAG(_flag, _type) (((flag) & FLAG_##_type) \
+ == FLAG_##_type)
+
+/* Secure Register Access */
+#define INTEL_SIP_SMC_REG_READ 0xC2000007
+#define INTEL_SIP_SMC_REG_WRITE 0xC2000008
+#define INTEL_SIP_SMC_REG_UPDATE 0xC2000009
+
+/* Remote System Update */
+#define INTEL_SIP_SMC_RSU_STATUS 0xC200000B
+#define INTEL_SIP_SMC_RSU_UPDATE 0xC200000C
+#define INTEL_SIP_SMC_RSU_NOTIFY 0xC200000E
+#define INTEL_SIP_SMC_RSU_RETRY_COUNTER 0xC200000F
+#define INTEL_SIP_SMC_RSU_DCMF_VERSION 0xC2000010
+#define INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION 0xC2000011
+#define INTEL_SIP_SMC_RSU_MAX_RETRY 0xC2000012
+#define INTEL_SIP_SMC_RSU_COPY_MAX_RETRY 0xC2000013
+#define INTEL_SIP_SMC_RSU_DCMF_STATUS 0xC2000014
+#define INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS 0xC2000015
+
+/* Hardware monitor */
+#define INTEL_SIP_SMC_HWMON_READTEMP 0xC2000020
+#define INTEL_SIP_SMC_HWMON_READVOLT 0xC2000021
+#define TEMP_CHANNEL_MAX (1 << 15)
+#define VOLT_CHANNEL_MAX (1 << 15)
+
+/* ECC */
+#define INTEL_SIP_SMC_ECC_DBE 0xC200000D
+
+/* Generic Command */
+#define INTEL_SIP_SMC_SERVICE_COMPLETED 0xC200001E
+#define INTEL_SIP_SMC_FIRMWARE_VERSION 0xC200001F
+#define INTEL_SIP_SMC_HPS_SET_BRIDGES 0xC2000032
+#define INTEL_SIP_SMC_GET_ROM_PATCH_SHA384 0xC2000040
+
+#define SERVICE_COMPLETED_MODE_ASYNC 0x00004F4E
+
+/* Mailbox Command */
+#define INTEL_SIP_SMC_MBOX_SEND_CMD 0xC200003C
+#define INTEL_SIP_SMC_GET_USERCODE 0xC200003D
+
+/* FPGA Crypto Services */
+#define INTEL_SIP_SMC_FCS_RANDOM_NUMBER 0xC200005A
+#define INTEL_SIP_SMC_FCS_RANDOM_NUMBER_EXT 0x4200008F
+#define INTEL_SIP_SMC_FCS_CRYPTION 0x4200005B
+#define INTEL_SIP_SMC_FCS_CRYPTION_EXT 0xC2000090
+#define INTEL_SIP_SMC_FCS_SERVICE_REQUEST 0x4200005C
+#define INTEL_SIP_SMC_FCS_SEND_CERTIFICATE 0x4200005D
+#define INTEL_SIP_SMC_FCS_GET_PROVISION_DATA 0x4200005E
+#define INTEL_SIP_SMC_FCS_CNTR_SET_PREAUTH 0xC200005F
+#define INTEL_SIP_SMC_FCS_PSGSIGMA_TEARDOWN 0xC2000064
+#define INTEL_SIP_SMC_FCS_CHIP_ID 0xC2000065
+#define INTEL_SIP_SMC_FCS_ATTESTATION_SUBKEY 0xC2000066
+#define INTEL_SIP_SMC_FCS_ATTESTATION_MEASUREMENTS 0xC2000067
+#define INTEL_SIP_SMC_FCS_GET_ATTESTATION_CERT 0xC2000068
+#define INTEL_SIP_SMC_FCS_CREATE_CERT_ON_RELOAD 0xC2000069
+#define INTEL_SIP_SMC_FCS_OPEN_CS_SESSION 0xC200006E
+#define INTEL_SIP_SMC_FCS_CLOSE_CS_SESSION 0xC200006F
+#define INTEL_SIP_SMC_FCS_IMPORT_CS_KEY 0x42000070
+#define INTEL_SIP_SMC_FCS_EXPORT_CS_KEY 0xC2000071
+#define INTEL_SIP_SMC_FCS_REMOVE_CS_KEY 0xC2000072
+#define INTEL_SIP_SMC_FCS_GET_CS_KEY_INFO 0xC2000073
+#define INTEL_SIP_SMC_FCS_AES_CRYPT_INIT 0xC2000074
+#define INTEL_SIP_SMC_FCS_AES_CRYPT_UPDATE 0x42000075
+#define INTEL_SIP_SMC_FCS_AES_CRYPT_FINALIZE 0x42000076
+#define INTEL_SIP_SMC_FCS_GET_DIGEST_INIT 0xC2000077
+#define INTEL_SIP_SMC_FCS_GET_DIGEST_UPDATE 0xC2000078
+#define INTEL_SIP_SMC_FCS_GET_DIGEST_FINALIZE 0xC2000079
+#define INTEL_SIP_SMC_FCS_MAC_VERIFY_INIT 0xC200007A
+#define INTEL_SIP_SMC_FCS_MAC_VERIFY_UPDATE 0xC200007B
+#define INTEL_SIP_SMC_FCS_MAC_VERIFY_FINALIZE 0xC200007C
+#define INTEL_SIP_SMC_FCS_ECDSA_HASH_SIGN_INIT 0xC200007D
+#define INTEL_SIP_SMC_FCS_ECDSA_HASH_SIGN_FINALIZE 0xC200007F
+#define INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIGN_INIT 0xC2000080
+#define INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIGN_UPDATE 0xC2000081
+#define INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIGN_FINALIZE 0xC2000082
+#define INTEL_SIP_SMC_FCS_ECDSA_HASH_SIG_VERIFY_INIT 0xC2000083
+#define INTEL_SIP_SMC_FCS_ECDSA_HASH_SIG_VERIFY_FINALIZE 0xC2000085
+#define INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_INIT 0xC2000086
+#define INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_UPDATE 0xC2000087
+#define INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_FINALIZE 0xC2000088
+#define INTEL_SIP_SMC_FCS_ECDSA_GET_PUBKEY_INIT 0xC2000089
+#define INTEL_SIP_SMC_FCS_ECDSA_GET_PUBKEY_FINALIZE 0xC200008B
+#define INTEL_SIP_SMC_FCS_ECDH_REQUEST_INIT 0xC200008C
+#define INTEL_SIP_SMC_FCS_ECDH_REQUEST_FINALIZE 0xC200008E
+
+#define INTEL_SIP_SMC_FCS_SHA_MODE_MASK 0xF
+#define INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK 0xF
+#define INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET 4U
+#define INTEL_SIP_SMC_FCS_ECC_ALGO_MASK 0xF
+
+/* ECC DBE */
+#define WARM_RESET_WFI_FLAG BIT(31)
+#define SYSMGR_ECC_DBE_COLD_RST_MASK (SYSMGR_ECC_OCRAM_MASK |\
+ SYSMGR_ECC_DDR0_MASK |\
+ SYSMGR_ECC_DDR1_MASK)
+
+/* Non-mailbox SMC Call */
+#define INTEL_SIP_SMC_SVC_VERSION 0xC2000200
+
+/**
+ * SMC SiP service function identifier for version 2
+ * Command code from 0x400 ~ 0x4FF
+ */
+
+/* V2: Non-mailbox function identifier */
+#define INTEL_SIP_SMC_V2_GET_SVC_VERSION 0xC2000400
+#define INTEL_SIP_SMC_V2_REG_READ 0xC2000401
+#define INTEL_SIP_SMC_V2_REG_WRITE 0xC2000402
+#define INTEL_SIP_SMC_V2_REG_UPDATE 0xC2000403
+#define INTEL_SIP_SMC_V2_HPS_SET_BRIDGES 0xC2000404
+
+/* V2: Mailbox function identifier */
+#define INTEL_SIP_SMC_V2_MAILBOX_SEND_COMMAND 0xC2000420
+#define INTEL_SIP_SMC_V2_MAILBOX_POLL_RESPONSE 0xC2000421
+
+/* SMC function IDs for SiP Service queries */
+#define SIP_SVC_CALL_COUNT 0x8200ff00
+#define SIP_SVC_UID 0x8200ff01
+#define SIP_SVC_VERSION 0x8200ff03
+
+/* SiP Service Calls version numbers */
+#define SIP_SVC_VERSION_MAJOR 1
+#define SIP_SVC_VERSION_MINOR 0
+
+
+/* Structure Definitions */
+struct fpga_config_info {
+ uint32_t addr;
+ int size;
+ int size_written;
+ uint32_t write_requested;
+ int subblocks_sent;
+ int block_number;
+};
+
+typedef enum {
+ NO_REQUEST = 0,
+ RECONFIGURATION,
+ BITSTREAM_AUTH
+} config_type;
+
+/* Function Definitions */
+bool is_size_4_bytes_aligned(uint32_t size);
+bool is_address_in_ddr_range(uint64_t addr, uint64_t size);
+
+/* ECC DBE */
+bool cold_reset_for_ecc_dbe(void);
+uint32_t intel_ecc_dbe_notification(uint64_t dbe_value);
+
+/* Secure register access */
+uint32_t intel_secure_reg_read(uint64_t reg_addr, uint32_t *retval);
+uint32_t intel_secure_reg_write(uint64_t reg_addr, uint32_t val,
+ uint32_t *retval);
+uint32_t intel_secure_reg_update(uint64_t reg_addr, uint32_t mask,
+ uint32_t val, uint32_t *retval);
+
+/* Miscellaneous HPS services */
+uint32_t intel_hps_set_bridges(uint64_t enable, uint64_t mask);
+
+/* SiP Service handler for version 2 */
+uintptr_t sip_smc_handler_v2(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags);
+
+#endif /* SOCFPGA_SIP_SVC_H */
diff --git a/plat/intel/soc/common/include/socfpga_system_manager.h b/plat/intel/soc/common/include/socfpga_system_manager.h
new file mode 100644
index 0000000..7f67313
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_system_manager.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_SYSTEMMANAGER_H
+#define SOCFPGA_SYSTEMMANAGER_H
+
+#include "socfpga_plat_def.h"
+
+/* System Manager Register Map */
+
+#define SOCFPGA_SYSMGR_SDMMC 0x28
+
+#define SOCFPGA_SYSMGR_FPGAINTF_EN_2 0x6c
+
+#define SOCFPGA_SYSMGR_EMAC_0 0x44
+#define SOCFPGA_SYSMGR_EMAC_1 0x48
+#define SOCFPGA_SYSMGR_EMAC_2 0x4c
+#define SOCFPGA_SYSMGR_FPGAINTF_EN_3 0x70
+
+#define SOCFPGA_SYSMGR_NOC_TIMEOUT 0xc0
+#define SOCFPGA_SYSMGR_NOC_IDLEREQ_SET 0xc4
+#define SOCFPGA_SYSMGR_NOC_IDLEREQ_CLR 0xc8
+#define SOCFPGA_SYSMGR_NOC_IDLEREQ_VAL 0xcc
+#define SOCFPGA_SYSMGR_NOC_IDLEACK 0xd0
+#define SOCFPGA_SYSMGR_NOC_IDLESTATUS 0xd4
+
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_0 0x200
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_1 0x204
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_2 0x208
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8 0x220
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9 0x224
+
+/* Field Masking */
+
+#define SYSMGR_SDMMC_DRVSEL(x) (((x) & 0x7) << 0)
+#define SYSMGR_SDMMC_SMPLSEL(x) (((x) & 0x7) << 4)
+
+#define IDLE_DATA_LWSOC2FPGA BIT(4)
+#define IDLE_DATA_SOC2FPGA BIT(0)
+#define IDLE_DATA_MASK (IDLE_DATA_LWSOC2FPGA | IDLE_DATA_SOC2FPGA)
+
+#define SYSMGR_ECC_OCRAM_MASK BIT(1)
+#define SYSMGR_ECC_DDR0_MASK BIT(16)
+#define SYSMGR_ECC_DDR1_MASK BIT(17)
+
+/* Macros */
+
+#define SOCFPGA_SYSMGR(_reg) (SOCFPGA_SYSMGR_REG_BASE \
+ + (SOCFPGA_SYSMGR_##_reg))
+
+#endif /* SOCFPGA_SYSTEMMANAGER_H */
diff --git a/plat/intel/soc/common/sip/socfpga_sip_ecc.c b/plat/intel/soc/common/sip/socfpga_sip_ecc.c
new file mode 100644
index 0000000..c4e06a6
--- /dev/null
+++ b/plat/intel/soc/common/sip/socfpga_sip_ecc.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <tools_share/uuid.h>
+
+#include "socfpga_fcs.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_sip_svc.h"
+#include "socfpga_system_manager.h"
+
+uint32_t intel_ecc_dbe_notification(uint64_t dbe_value)
+{
+ dbe_value &= WARM_RESET_WFI_FLAG;
+
+ /* Trap CPUs in WFI if warm reset flag is set */
+ if (dbe_value > 0) {
+ while (1) {
+ wfi();
+ }
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+bool cold_reset_for_ecc_dbe(void)
+{
+ uint32_t dbe_int_status;
+
+ dbe_int_status = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8));
+
+ /* Trigger cold reset only for error in critical memory (DDR/OCRAM) */
+ dbe_int_status &= SYSMGR_ECC_DBE_COLD_RST_MASK;
+
+ if (dbe_int_status > 0) {
+ return true;
+ }
+
+ return false;
+}
diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
new file mode 100644
index 0000000..facee0f
--- /dev/null
+++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
@@ -0,0 +1,1739 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+
+#include "socfpga_fcs.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_sip_svc.h"
+
+/* FCS static variables */
+static fcs_crypto_service_aes_data fcs_aes_init_payload;
+static fcs_crypto_service_data fcs_sha_get_digest_param;
+static fcs_crypto_service_data fcs_sha_mac_verify_param;
+static fcs_crypto_service_data fcs_ecdsa_hash_sign_param;
+static fcs_crypto_service_data fcs_ecdsa_hash_sig_verify_param;
+static fcs_crypto_service_data fcs_sha2_data_sign_param;
+static fcs_crypto_service_data fcs_sha2_data_sig_verify_param;
+static fcs_crypto_service_data fcs_ecdsa_get_pubkey_param;
+static fcs_crypto_service_data fcs_ecdh_request_param;
+
+bool is_size_4_bytes_aligned(uint32_t size)
+{
+ if ((size % MBOX_WORD_BYTE) != 0U) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static bool is_8_bytes_aligned(uint32_t data)
+{
+ if ((data % (MBOX_WORD_BYTE * 2U)) != 0U) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static bool is_32_bytes_aligned(uint32_t data)
+{
+ if ((data % (8U * MBOX_WORD_BYTE)) != 0U) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+static int intel_fcs_crypto_service_init(uint32_t session_id,
+ uint32_t context_id, uint32_t key_id,
+ uint32_t param_size, uint64_t param_data,
+ fcs_crypto_service_data *data_addr,
+ uint32_t *mbox_error)
+{
+ if (mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (param_size != 4) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ memset(data_addr, 0, sizeof(fcs_crypto_service_data));
+
+ data_addr->session_id = session_id;
+ data_addr->context_id = context_id;
+ data_addr->key_id = key_id;
+ data_addr->crypto_param_size = param_size;
+ data_addr->crypto_param = param_data;
+
+ data_addr->is_updated = 0;
+
+ *mbox_error = 0;
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ unsigned int i;
+ unsigned int resp_len = FCS_RANDOM_WORD_SIZE;
+ uint32_t random_data[FCS_RANDOM_WORD_SIZE] = {0U};
+
+ if (!is_address_in_ddr_range(addr, FCS_RANDOM_BYTE_SIZE)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_RANDOM_GEN, NULL, 0U,
+ CMD_CASUAL, random_data, &resp_len);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (resp_len != FCS_RANDOM_WORD_SIZE) {
+ *mbox_error = GENERIC_RESPONSE_ERROR;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *ret_size = FCS_RANDOM_BYTE_SIZE;
+
+ for (i = 0U; i < FCS_RANDOM_WORD_SIZE; i++) {
+ mmio_write_32(addr, random_data[i]);
+ addr += MBOX_WORD_BYTE;
+ }
+
+ flush_dcache_range(addr - *ret_size, *ret_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_random_number_gen_ext(uint32_t session_id, uint32_t context_id,
+ uint32_t size, uint32_t *send_id)
+{
+ int status;
+ uint32_t payload_size;
+ uint32_t crypto_header;
+
+ if (size > (FCS_RANDOM_EXT_MAX_WORD_SIZE *
+ MBOX_WORD_BYTE) || size == 0U) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ crypto_header = (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_FINALIZE) <<
+ FCS_CS_FIELD_FLAG_OFFSET;
+
+ fcs_rng_payload payload = {
+ session_id,
+ context_id,
+ crypto_header,
+ size
+ };
+
+ payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd_async(send_id, MBOX_FCS_RANDOM_GEN,
+ (uint32_t *) &payload, payload_size,
+ CMD_INDIRECT);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size,
+ uint32_t *send_id)
+{
+ int status;
+
+ if (!is_address_in_ddr_range(addr, size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd_async(send_id, MBOX_CMD_VAB_SRC_CERT,
+ (uint32_t *)addr, size / MBOX_WORD_BYTE,
+ CMD_DIRECT);
+
+ flush_dcache_range(addr, size);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_get_provision_data(uint32_t *send_id)
+{
+ int status;
+
+ status = mailbox_send_cmd_async(send_id, MBOX_FCS_GET_PROVISION,
+ NULL, 0U, CMD_DIRECT);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_cntr_set_preauth(uint8_t counter_type, int32_t counter_value,
+ uint32_t test_bit, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t first_word;
+ uint32_t payload_size;
+
+ if ((test_bit != MBOX_TEST_BIT) &&
+ (test_bit != 0)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if ((counter_type < FCS_BIG_CNTR_SEL) ||
+ (counter_type > FCS_SVN_CNTR_3_SEL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if ((counter_type == FCS_BIG_CNTR_SEL) &&
+ (counter_value > FCS_BIG_CNTR_VAL_MAX)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if ((counter_type >= FCS_SVN_CNTR_0_SEL) &&
+ (counter_type <= FCS_SVN_CNTR_3_SEL) &&
+ (counter_value > FCS_SVN_CNTR_VAL_MAX)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ first_word = test_bit | counter_type;
+ fcs_cntr_set_preauth_payload payload = {
+ first_word,
+ counter_value
+ };
+
+ payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_CNTR_SET_PREAUTH,
+ (uint32_t *) &payload, payload_size,
+ CMD_CASUAL, NULL, NULL);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_encryption(uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t dst_size, uint32_t *send_id)
+{
+ int status;
+ uint32_t load_size;
+
+ fcs_encrypt_payload payload = {
+ FCS_ENCRYPTION_DATA_0,
+ src_addr,
+ src_size,
+ dst_addr,
+ dst_size };
+ load_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd_async(send_id, MBOX_FCS_ENCRYPT_REQ,
+ (uint32_t *) &payload, load_size,
+ CMD_INDIRECT);
+ inv_dcache_range(dst_addr, dst_size);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_decryption(uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t dst_size, uint32_t *send_id)
+{
+ int status;
+ uint32_t load_size;
+ uintptr_t id_offset;
+
+ id_offset = src_addr + FCS_OWNER_ID_OFFSET;
+ fcs_decrypt_payload payload = {
+ FCS_DECRYPTION_DATA_0,
+ {mmio_read_32(id_offset),
+ mmio_read_32(id_offset + MBOX_WORD_BYTE)},
+ src_addr,
+ src_size,
+ dst_addr,
+ dst_size };
+ load_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd_async(send_id, MBOX_FCS_DECRYPT_REQ,
+ (uint32_t *) &payload, load_size,
+ CMD_INDIRECT);
+ inv_dcache_range(dst_addr, dst_size);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_encryption_ext(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t payload_size;
+ uint32_t resp_len = FCS_CRYPTION_RESP_WORD_SIZE;
+ uint32_t resp_data[FCS_CRYPTION_RESP_WORD_SIZE] = {0U};
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ fcs_encrypt_ext_payload payload = {
+ session_id,
+ context_id,
+ FCS_CRYPTION_CRYPTO_HEADER,
+ src_addr,
+ src_size,
+ dst_addr,
+ *dst_size
+ };
+
+ payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ENCRYPT_REQ,
+ (uint32_t *) &payload, payload_size,
+ CMD_CASUAL, resp_data, &resp_len);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (resp_len != FCS_CRYPTION_RESP_WORD_SIZE) {
+ *mbox_error = MBOX_RET_ERROR;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_data[FCS_CRYPTION_RESP_SIZE_OFFSET];
+ inv_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_decryption_ext(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint32_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
+{
+ int status;
+ uintptr_t id_offset;
+ uint32_t payload_size;
+ uint32_t resp_len = FCS_CRYPTION_RESP_WORD_SIZE;
+ uint32_t resp_data[FCS_CRYPTION_RESP_WORD_SIZE] = {0U};
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ id_offset = src_addr + FCS_OWNER_ID_OFFSET;
+ fcs_decrypt_ext_payload payload = {
+ session_id,
+ context_id,
+ FCS_CRYPTION_CRYPTO_HEADER,
+ {mmio_read_32(id_offset),
+ mmio_read_32(id_offset + MBOX_WORD_BYTE)},
+ src_addr,
+ src_size,
+ dst_addr,
+ *dst_size
+ };
+
+ payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_DECRYPT_REQ,
+ (uint32_t *) &payload, payload_size,
+ CMD_CASUAL, resp_data, &resp_len);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (resp_len != FCS_CRYPTION_RESP_WORD_SIZE) {
+ *mbox_error = MBOX_RET_ERROR;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_data[FCS_CRYPTION_RESP_SIZE_OFFSET];
+ inv_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_sigma_teardown(uint32_t session_id, uint32_t *mbox_error)
+{
+ int status;
+
+ if ((session_id != PSGSIGMA_SESSION_ID_ONE) &&
+ (session_id != PSGSIGMA_UNKNOWN_SESSION)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ psgsigma_teardown_msg message = {
+ RESERVED_AS_ZERO,
+ PSGSIGMA_TEARDOWN_MAGIC,
+ session_id
+ };
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_PSG_SIGMA_TEARDOWN,
+ (uint32_t *) &message, sizeof(message) / MBOX_WORD_BYTE,
+ CMD_CASUAL, NULL, NULL);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_chip_id(uint32_t *id_low, uint32_t *id_high, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t load_size;
+ uint32_t chip_id[2];
+
+ load_size = sizeof(chip_id) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_GET_CHIPID, NULL,
+ 0U, CMD_CASUAL, (uint32_t *) chip_id, &load_size);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *id_low = chip_id[0];
+ *id_high = chip_id[1];
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_attestation_subkey(uint64_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t send_size = src_size / MBOX_WORD_BYTE;
+ uint32_t ret_size = *dst_size / MBOX_WORD_BYTE;
+
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_ATTESTATION_SUBKEY,
+ (uint32_t *) src_addr, send_size, CMD_CASUAL,
+ (uint32_t *) dst_addr, &ret_size);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = ret_size * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_get_measurement(uint64_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t send_size = src_size / MBOX_WORD_BYTE;
+ uint32_t ret_size = *dst_size / MBOX_WORD_BYTE;
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_MEASUREMENT,
+ (uint32_t *) src_addr, send_size, CMD_CASUAL,
+ (uint32_t *) dst_addr, &ret_size);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = ret_size * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_get_rom_patch_sha384(uint64_t addr, uint64_t *ret_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ unsigned int resp_len = FCS_SHA384_WORD_SIZE;
+
+ if (!is_address_in_ddr_range(addr, FCS_SHA384_BYTE_SIZE)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_ROM_PATCH_SHA384, NULL, 0U,
+ CMD_CASUAL, (uint32_t *) addr, &resp_len);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (resp_len != FCS_SHA384_WORD_SIZE) {
+ *mbox_error = GENERIC_RESPONSE_ERROR;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *ret_size = FCS_SHA384_BYTE_SIZE;
+
+ flush_dcache_range(addr, *ret_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_get_attestation_cert(uint32_t cert_request, uint64_t dst_addr,
+ uint32_t *dst_size, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t ret_size = *dst_size / MBOX_WORD_BYTE;
+
+ if (mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (cert_request < FCS_ATTEST_FIRMWARE_CERT ||
+ cert_request > FCS_ATTEST_CERT_MAX_REQ_PARAM) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_ATTESTATION_CERT,
+ (uint32_t *) &cert_request, 1U, CMD_CASUAL,
+ (uint32_t *) dst_addr, &ret_size);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = ret_size * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_create_cert_on_reload(uint32_t cert_request,
+ uint32_t *mbox_error)
+{
+ int status;
+
+ if (mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (cert_request < FCS_ATTEST_FIRMWARE_CERT ||
+ cert_request > FCS_ATTEST_CERT_MAX_REQ_PARAM) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CREATE_CERT_ON_RELOAD,
+ (uint32_t *) &cert_request, 1U, CMD_CASUAL,
+ NULL, NULL);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_open_crypto_service_session(uint32_t *session_id,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t resp_len = 1U;
+
+ if ((session_id == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_OPEN_CS_SESSION,
+ NULL, 0U, CMD_CASUAL, session_id, &resp_len);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_close_crypto_service_session(uint32_t session_id,
+ uint32_t *mbox_error)
+{
+ int status;
+
+ if (mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_CLOSE_CS_SESSION,
+ &session_id, 1U, CMD_CASUAL, NULL, NULL);
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_import_crypto_service_key(uint64_t src_addr, uint32_t src_size,
+ uint32_t *send_id)
+{
+ int status;
+
+ if (src_size > (FCS_CS_KEY_OBJ_MAX_WORD_SIZE *
+ MBOX_WORD_BYTE)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ status = mailbox_send_cmd_async(send_id, MBOX_FCS_IMPORT_CS_KEY,
+ (uint32_t *)src_addr, src_size / MBOX_WORD_BYTE,
+ CMD_INDIRECT);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_export_crypto_service_key(uint32_t session_id, uint32_t key_id,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t i;
+ uint32_t payload_size;
+ uint32_t resp_len = FCS_CS_KEY_OBJ_MAX_WORD_SIZE;
+ uint32_t resp_data[FCS_CS_KEY_OBJ_MAX_WORD_SIZE] = {0U};
+ uint32_t op_status = 0U;
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ fcs_cs_key_payload payload = {
+ session_id,
+ RESERVED_AS_ZERO,
+ RESERVED_AS_ZERO,
+ key_id
+ };
+
+ payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_EXPORT_CS_KEY,
+ (uint32_t *) &payload, payload_size,
+ CMD_CASUAL, resp_data, &resp_len);
+
+ if (resp_len > 0) {
+ op_status = resp_data[0] & FCS_CS_KEY_RESP_STATUS_MASK;
+ }
+
+ if (status < 0) {
+ *mbox_error = (-status) | (op_status << FCS_CS_KEY_RESP_STATUS_OFFSET);
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (resp_len > 1) {
+
+ /* Export key object is start at second response data */
+ *dst_size = (resp_len - 1) * MBOX_WORD_BYTE;
+
+ for (i = 1U; i < resp_len; i++) {
+ mmio_write_32(dst_addr, resp_data[i]);
+ dst_addr += MBOX_WORD_BYTE;
+ }
+
+ flush_dcache_range(dst_addr - *dst_size, *dst_size);
+
+ } else {
+
+ /* Unexpected response, missing key object in response */
+ *mbox_error = MBOX_RET_ERROR;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_remove_crypto_service_key(uint32_t session_id, uint32_t key_id,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t payload_size;
+ uint32_t resp_len = 1U;
+ uint32_t resp_data = 0U;
+ uint32_t op_status = 0U;
+
+ if (mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ fcs_cs_key_payload payload = {
+ session_id,
+ RESERVED_AS_ZERO,
+ RESERVED_AS_ZERO,
+ key_id
+ };
+
+ payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_REMOVE_CS_KEY,
+ (uint32_t *) &payload, payload_size,
+ CMD_CASUAL, &resp_data, &resp_len);
+
+ if (resp_len > 0) {
+ op_status = resp_data & FCS_CS_KEY_RESP_STATUS_MASK;
+ }
+
+ if (status < 0) {
+ *mbox_error = (-status) | (op_status << FCS_CS_KEY_RESP_STATUS_OFFSET);
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_get_crypto_service_key_info(uint32_t session_id, uint32_t key_id,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t payload_size;
+ uint32_t resp_len = FCS_CS_KEY_INFO_MAX_WORD_SIZE;
+ uint32_t op_status = 0U;
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ fcs_cs_key_payload payload = {
+ session_id,
+ RESERVED_AS_ZERO,
+ RESERVED_AS_ZERO,
+ key_id
+ };
+
+ payload_size = sizeof(payload) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_GET_CS_KEY_INFO,
+ (uint32_t *) &payload, payload_size,
+ CMD_CASUAL, (uint32_t *) dst_addr, &resp_len);
+
+ if (resp_len > 0) {
+ op_status = mmio_read_32(dst_addr) &
+ FCS_CS_KEY_RESP_STATUS_MASK;
+ }
+
+ if (status < 0) {
+ *mbox_error = (-status) | (op_status << FCS_CS_KEY_RESP_STATUS_OFFSET);
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_get_digest_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_sha_get_digest_param,
+ mbox_error);
+}
+
+int intel_fcs_get_digest_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint32_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t *dst_size, uint8_t is_finalised,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t i;
+ uint32_t flag;
+ uint32_t crypto_header;
+ uint32_t resp_len;
+ uint32_t payload[FCS_GET_DIGEST_CMD_MAX_WORD_SIZE] = {0U};
+
+ if (dst_size == NULL || mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_sha_get_digest_param.session_id != session_id ||
+ fcs_sha_get_digest_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ /* Source data must be 8 bytes aligned */
+ if (!is_8_bytes_aligned(src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = *dst_size / MBOX_WORD_BYTE;
+
+ /* Prepare crypto header */
+ flag = 0;
+
+ if (fcs_sha_get_digest_param.is_updated) {
+ fcs_sha_get_digest_param.crypto_param_size = 0;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_INIT;
+ }
+
+ if (is_finalised != 0U) {
+ flag |= FCS_CS_FIELD_FLAG_FINALIZE;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_UPDATE;
+ fcs_sha_get_digest_param.is_updated = 1;
+ }
+
+ crypto_header = ((flag << FCS_CS_FIELD_FLAG_OFFSET) |
+ (fcs_sha_get_digest_param.crypto_param_size &
+ FCS_CS_FIELD_SIZE_MASK));
+
+ /* Prepare command payload */
+ i = 0;
+ payload[i] = fcs_sha_get_digest_param.session_id;
+ i++;
+ payload[i] = fcs_sha_get_digest_param.context_id;
+ i++;
+ payload[i] = crypto_header;
+ i++;
+
+ if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
+ FCS_CS_FIELD_FLAG_INIT) {
+ payload[i] = fcs_sha_get_digest_param.key_id;
+ i++;
+ /* Crypto parameters */
+ payload[i] = fcs_sha_get_digest_param.crypto_param
+ & INTEL_SIP_SMC_FCS_SHA_MODE_MASK;
+ payload[i] |= ((fcs_sha_get_digest_param.crypto_param
+ >> INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET)
+ & INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK)
+ << FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET;
+ i++;
+ }
+ /* Data source address and size */
+ payload[i] = src_addr;
+ i++;
+ payload[i] = src_size;
+ i++;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_GET_DIGEST_REQ,
+ payload, i, CMD_CASUAL,
+ (uint32_t *) dst_addr, &resp_len);
+
+ if (is_finalised != 0U) {
+ memset((void *)&fcs_sha_get_digest_param, 0,
+ sizeof(fcs_crypto_service_data));
+ }
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_mac_verify_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_sha_mac_verify_param,
+ mbox_error);
+}
+
+int intel_fcs_mac_verify_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint32_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t *dst_size, uint32_t data_size,
+ uint8_t is_finalised, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t i;
+ uint32_t flag;
+ uint32_t crypto_header;
+ uint32_t resp_len;
+ uint32_t payload[FCS_MAC_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
+ uintptr_t mac_offset;
+
+ if (dst_size == NULL || mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_sha_mac_verify_param.session_id != session_id ||
+ fcs_sha_mac_verify_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (data_size > src_size) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(src_size) ||
+ !is_8_bytes_aligned(data_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = *dst_size / MBOX_WORD_BYTE;
+
+ /* Prepare crypto header */
+ flag = 0;
+
+ if (fcs_sha_mac_verify_param.is_updated) {
+ fcs_sha_mac_verify_param.crypto_param_size = 0;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_INIT;
+ }
+
+ if (is_finalised) {
+ flag |= FCS_CS_FIELD_FLAG_FINALIZE;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_UPDATE;
+ fcs_sha_mac_verify_param.is_updated = 1;
+ }
+
+ crypto_header = ((flag << FCS_CS_FIELD_FLAG_OFFSET) |
+ (fcs_sha_mac_verify_param.crypto_param_size &
+ FCS_CS_FIELD_SIZE_MASK));
+
+ /* Prepare command payload */
+ i = 0;
+ payload[i] = fcs_sha_mac_verify_param.session_id;
+ i++;
+ payload[i] = fcs_sha_mac_verify_param.context_id;
+ i++;
+ payload[i] = crypto_header;
+ i++;
+
+ if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
+ FCS_CS_FIELD_FLAG_INIT) {
+ payload[i] = fcs_sha_mac_verify_param.key_id;
+ i++;
+ /* Crypto parameters */
+ payload[i] = ((fcs_sha_mac_verify_param.crypto_param
+ >> INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET)
+ & INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK)
+ << FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET;
+ i++;
+ }
+ /* Data source address and size */
+ payload[i] = src_addr;
+ i++;
+ payload[i] = data_size;
+ i++;
+
+ if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
+ FCS_CS_FIELD_FLAG_FINALIZE) {
+ /* Copy mac data to command */
+ mac_offset = src_addr + data_size;
+ memcpy((uint8_t *) &payload[i], (uint8_t *) mac_offset,
+ src_size - data_size);
+
+ i += (src_size - data_size) / MBOX_WORD_BYTE;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_MAC_VERIFY_REQ,
+ payload, i, CMD_CASUAL,
+ (uint32_t *) dst_addr, &resp_len);
+
+ if (is_finalised) {
+ memset((void *)&fcs_sha_mac_verify_param, 0,
+ sizeof(fcs_crypto_service_data));
+ }
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_ecdsa_hash_sign_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_ecdsa_hash_sign_param,
+ mbox_error);
+}
+
+int intel_fcs_ecdsa_hash_sign_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t i;
+ uint32_t payload[FCS_ECDSA_HASH_SIGN_CMD_MAX_WORD_SIZE] = {0U};
+ uint32_t resp_len;
+ uintptr_t hash_data_addr;
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_ecdsa_hash_sign_param.session_id != session_id ||
+ fcs_ecdsa_hash_sign_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = *dst_size / MBOX_WORD_BYTE;
+
+ /* Prepare command payload */
+ /* Crypto header */
+ i = 0;
+ payload[i] = fcs_ecdsa_hash_sign_param.session_id;
+ i++;
+ payload[i] = fcs_ecdsa_hash_sign_param.context_id;
+
+ i++;
+ payload[i] = fcs_ecdsa_hash_sign_param.crypto_param_size
+ & FCS_CS_FIELD_SIZE_MASK;
+ payload[i] |= (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_UPDATE
+ | FCS_CS_FIELD_FLAG_FINALIZE)
+ << FCS_CS_FIELD_FLAG_OFFSET;
+ i++;
+ payload[i] = fcs_ecdsa_hash_sign_param.key_id;
+
+ /* Crypto parameters */
+ i++;
+ payload[i] = fcs_ecdsa_hash_sign_param.crypto_param
+ & INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
+
+ /* Hash Data */
+ i++;
+ hash_data_addr = src_addr;
+ memcpy((uint8_t *) &payload[i], (uint8_t *) hash_data_addr,
+ src_size);
+
+ i += src_size / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDSA_HASH_SIGN_REQ,
+ payload, i, CMD_CASUAL, (uint32_t *) dst_addr,
+ &resp_len);
+
+ memset((void *) &fcs_ecdsa_hash_sign_param,
+ 0, sizeof(fcs_crypto_service_data));
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_ecdsa_hash_sig_verify_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_ecdsa_hash_sig_verify_param,
+ mbox_error);
+}
+
+int intel_fcs_ecdsa_hash_sig_verify_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t i = 0;
+ uint32_t payload[FCS_ECDSA_HASH_SIG_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
+ uint32_t resp_len;
+ uintptr_t hash_sig_pubkey_addr;
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_ecdsa_hash_sig_verify_param.session_id != session_id ||
+ fcs_ecdsa_hash_sig_verify_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = *dst_size / MBOX_WORD_BYTE;
+
+ /* Prepare command payload */
+ /* Crypto header */
+ i = 0;
+ payload[i] = fcs_ecdsa_hash_sig_verify_param.session_id;
+
+ i++;
+ payload[i] = fcs_ecdsa_hash_sig_verify_param.context_id;
+
+ i++;
+ payload[i] = fcs_ecdsa_hash_sig_verify_param.crypto_param_size
+ & FCS_CS_FIELD_SIZE_MASK;
+ payload[i] |= (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_UPDATE
+ | FCS_CS_FIELD_FLAG_FINALIZE)
+ << FCS_CS_FIELD_FLAG_OFFSET;
+
+ i++;
+ payload[i] = fcs_ecdsa_hash_sig_verify_param.key_id;
+
+ /* Crypto parameters */
+ i++;
+ payload[i] = fcs_ecdsa_hash_sig_verify_param.crypto_param
+ & INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
+
+ /* Hash Data Word, Signature Data Word and Public Key Data word */
+ i++;
+ hash_sig_pubkey_addr = src_addr;
+ memcpy((uint8_t *) &payload[i],
+ (uint8_t *) hash_sig_pubkey_addr, src_size);
+
+ i += (src_size / MBOX_WORD_BYTE);
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDSA_HASH_SIG_VERIFY,
+ payload, i, CMD_CASUAL, (uint32_t *) dst_addr,
+ &resp_len);
+
+ memset((void *)&fcs_ecdsa_hash_sig_verify_param,
+ 0, sizeof(fcs_crypto_service_data));
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_ecdsa_sha2_data_sign_init(uint32_t session_id,
+ uint32_t context_id, uint32_t key_id,
+ uint32_t param_size, uint64_t param_data,
+ uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_sha2_data_sign_param,
+ mbox_error);
+}
+
+int intel_fcs_ecdsa_sha2_data_sign_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint32_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t *dst_size, uint8_t is_finalised,
+ uint32_t *mbox_error)
+{
+ int status;
+ int i;
+ uint32_t flag;
+ uint32_t crypto_header;
+ uint32_t payload[FCS_ECDSA_SHA2_DATA_SIGN_CMD_MAX_WORD_SIZE] = {0U};
+ uint32_t resp_len;
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_sha2_data_sign_param.session_id != session_id ||
+ fcs_sha2_data_sign_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ /* Source data must be 8 bytes aligned */
+ if (!is_8_bytes_aligned(src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = *dst_size / MBOX_WORD_BYTE;
+
+ /* Prepare crypto header */
+ flag = 0;
+ if (fcs_sha2_data_sign_param.is_updated) {
+ fcs_sha2_data_sign_param.crypto_param_size = 0;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_INIT;
+ }
+
+ if (is_finalised != 0U) {
+ flag |= FCS_CS_FIELD_FLAG_FINALIZE;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_UPDATE;
+ fcs_sha2_data_sign_param.is_updated = 1;
+ }
+ crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
+ fcs_sha2_data_sign_param.crypto_param_size;
+
+ /* Prepare command payload */
+ i = 0;
+ payload[i] = fcs_sha2_data_sign_param.session_id;
+ i++;
+ payload[i] = fcs_sha2_data_sign_param.context_id;
+ i++;
+ payload[i] = crypto_header;
+ i++;
+
+ if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
+ FCS_CS_FIELD_FLAG_INIT) {
+ payload[i] = fcs_sha2_data_sign_param.key_id;
+ /* Crypto parameters */
+ i++;
+ payload[i] = fcs_sha2_data_sign_param.crypto_param
+ & INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
+ i++;
+ }
+
+ /* Data source address and size */
+ payload[i] = src_addr;
+ i++;
+ payload[i] = src_size;
+ i++;
+ status = mailbox_send_cmd(MBOX_JOB_ID,
+ MBOX_FCS_ECDSA_SHA2_DATA_SIGN_REQ, payload,
+ i, CMD_CASUAL, (uint32_t *) dst_addr,
+ &resp_len);
+
+ if (is_finalised != 0U) {
+ memset((void *)&fcs_sha2_data_sign_param, 0,
+ sizeof(fcs_crypto_service_data));
+ }
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_ecdsa_sha2_data_sig_verify_init(uint32_t session_id,
+ uint32_t context_id, uint32_t key_id,
+ uint32_t param_size, uint64_t param_data,
+ uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_sha2_data_sig_verify_param,
+ mbox_error);
+}
+
+int intel_fcs_ecdsa_sha2_data_sig_verify_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint32_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t *dst_size, uint32_t data_size,
+ uint8_t is_finalised, uint32_t *mbox_error)
+{
+ int status;
+ uint32_t i;
+ uint32_t flag;
+ uint32_t crypto_header;
+ uint32_t payload[FCS_ECDSA_SHA2_DATA_SIG_VERIFY_CMD_MAX_WORD_SIZE] = {0U};
+ uint32_t resp_len;
+ uintptr_t sig_pubkey_offset;
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_sha2_data_sig_verify_param.session_id != session_id ||
+ fcs_sha2_data_sig_verify_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(src_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_8_bytes_aligned(data_size) ||
+ !is_8_bytes_aligned(src_addr)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = *dst_size / MBOX_WORD_BYTE;
+
+ /* Prepare crypto header */
+ flag = 0;
+ if (fcs_sha2_data_sig_verify_param.is_updated)
+ fcs_sha2_data_sig_verify_param.crypto_param_size = 0;
+ else
+ flag |= FCS_CS_FIELD_FLAG_INIT;
+
+ if (is_finalised != 0U)
+ flag |= FCS_CS_FIELD_FLAG_FINALIZE;
+ else {
+ flag |= FCS_CS_FIELD_FLAG_UPDATE;
+ fcs_sha2_data_sig_verify_param.is_updated = 1;
+ }
+ crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
+ fcs_sha2_data_sig_verify_param.crypto_param_size;
+
+ /* Prepare command payload */
+ i = 0;
+ payload[i] = fcs_sha2_data_sig_verify_param.session_id;
+ i++;
+ payload[i] = fcs_sha2_data_sig_verify_param.context_id;
+ i++;
+ payload[i] = crypto_header;
+ i++;
+
+ if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
+ FCS_CS_FIELD_FLAG_INIT) {
+ payload[i] = fcs_sha2_data_sig_verify_param.key_id;
+ i++;
+ /* Crypto parameters */
+ payload[i] = fcs_sha2_data_sig_verify_param.crypto_param
+ & INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
+ i++;
+ }
+
+ /* Data source address and size */
+ payload[i] = src_addr;
+ i++;
+ payload[i] = data_size;
+ i++;
+
+ if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
+ FCS_CS_FIELD_FLAG_FINALIZE) {
+ /* Signature + Public Key Data */
+ sig_pubkey_offset = src_addr + data_size;
+ memcpy((uint8_t *) &payload[i], (uint8_t *) sig_pubkey_offset,
+ src_size - data_size);
+
+ i += (src_size - data_size) / MBOX_WORD_BYTE;
+ }
+
+ status = mailbox_send_cmd(MBOX_JOB_ID,
+ MBOX_FCS_ECDSA_SHA2_DATA_SIGN_VERIFY, payload, i,
+ CMD_CASUAL, (uint32_t *) dst_addr, &resp_len);
+
+ if (is_finalised != 0U) {
+ memset((void *) &fcs_sha2_data_sig_verify_param, 0,
+ sizeof(fcs_crypto_service_data));
+ }
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_ecdsa_get_pubkey_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_ecdsa_get_pubkey_param,
+ mbox_error);
+}
+
+int intel_fcs_ecdsa_get_pubkey_finalize(uint32_t session_id, uint32_t context_id,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ int i;
+ uint32_t crypto_header;
+ uint32_t ret_size;
+ uint32_t payload[FCS_ECDSA_GET_PUBKEY_MAX_WORD_SIZE] = {0U};
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_ecdsa_get_pubkey_param.session_id != session_id ||
+ fcs_ecdsa_get_pubkey_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ ret_size = *dst_size / MBOX_WORD_BYTE;
+
+ crypto_header = ((FCS_CS_FIELD_FLAG_INIT |
+ FCS_CS_FIELD_FLAG_UPDATE |
+ FCS_CS_FIELD_FLAG_FINALIZE) <<
+ FCS_CS_FIELD_FLAG_OFFSET) |
+ fcs_ecdsa_get_pubkey_param.crypto_param_size;
+ i = 0;
+ /* Prepare command payload */
+ payload[i] = session_id;
+ i++;
+ payload[i] = context_id;
+ i++;
+ payload[i] = crypto_header;
+ i++;
+ payload[i] = fcs_ecdsa_get_pubkey_param.key_id;
+ i++;
+ payload[i] = (uint32_t) fcs_ecdsa_get_pubkey_param.crypto_param &
+ INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
+ i++;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDSA_GET_PUBKEY,
+ payload, i, CMD_CASUAL,
+ (uint32_t *) dst_addr, &ret_size);
+
+ memset((void *) &fcs_ecdsa_get_pubkey_param, 0,
+ sizeof(fcs_crypto_service_data));
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = ret_size * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_ecdh_request_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint32_t param_size,
+ uint64_t param_data, uint32_t *mbox_error)
+{
+ return intel_fcs_crypto_service_init(session_id, context_id,
+ key_id, param_size, param_data,
+ (void *) &fcs_ecdh_request_param,
+ mbox_error);
+}
+
+int intel_fcs_ecdh_request_finalize(uint32_t session_id, uint32_t context_id,
+ uint32_t src_addr, uint32_t src_size,
+ uint64_t dst_addr, uint32_t *dst_size,
+ uint32_t *mbox_error)
+{
+ int status;
+ uint32_t i;
+ uint32_t payload[FCS_ECDH_REQUEST_CMD_MAX_WORD_SIZE] = {0U};
+ uint32_t resp_len;
+ uintptr_t pubkey;
+
+ if ((dst_size == NULL) || (mbox_error == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (fcs_ecdh_request_param.session_id != session_id ||
+ fcs_ecdh_request_param.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(src_addr, src_size) ||
+ !is_address_in_ddr_range(dst_addr, *dst_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = *dst_size / MBOX_WORD_BYTE;
+
+ /* Prepare command payload */
+ i = 0;
+ /* Crypto header */
+ payload[i] = fcs_ecdh_request_param.session_id;
+ i++;
+ payload[i] = fcs_ecdh_request_param.context_id;
+ i++;
+ payload[i] = fcs_ecdh_request_param.crypto_param_size
+ & FCS_CS_FIELD_SIZE_MASK;
+ payload[i] |= (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_UPDATE
+ | FCS_CS_FIELD_FLAG_FINALIZE)
+ << FCS_CS_FIELD_FLAG_OFFSET;
+ i++;
+ payload[i] = fcs_ecdh_request_param.key_id;
+ i++;
+ /* Crypto parameters */
+ payload[i] = fcs_ecdh_request_param.crypto_param
+ & INTEL_SIP_SMC_FCS_ECC_ALGO_MASK;
+ i++;
+ /* Public key data */
+ pubkey = src_addr;
+ memcpy((uint8_t *) &payload[i], (uint8_t *) pubkey, src_size);
+ i += src_size / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDH_REQUEST,
+ payload, i, CMD_CASUAL, (uint32_t *) dst_addr,
+ &resp_len);
+
+ memset((void *)&fcs_ecdh_request_param, 0,
+ sizeof(fcs_crypto_service_data));
+
+ if (status < 0) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *dst_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(dst_addr, *dst_size);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_aes_crypt_init(uint32_t session_id, uint32_t context_id,
+ uint32_t key_id, uint64_t param_addr,
+ uint32_t param_size, uint32_t *mbox_error)
+{
+ if (mbox_error == NULL) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ memset((void *)&fcs_aes_init_payload, 0U, sizeof(fcs_aes_init_payload));
+
+ fcs_aes_init_payload.session_id = session_id;
+ fcs_aes_init_payload.context_id = context_id;
+ fcs_aes_init_payload.param_size = param_size;
+ fcs_aes_init_payload.key_id = key_id;
+
+ memcpy((uint8_t *) fcs_aes_init_payload.crypto_param,
+ (uint8_t *) param_addr, param_size);
+
+ fcs_aes_init_payload.is_updated = 0;
+
+ *mbox_error = 0;
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+int intel_fcs_aes_crypt_update_finalize(uint32_t session_id,
+ uint32_t context_id, uint64_t src_addr,
+ uint32_t src_size, uint64_t dst_addr,
+ uint32_t dst_size, uint8_t is_finalised,
+ uint32_t *send_id)
+{
+ int status;
+ int i;
+ uint32_t flag;
+ uint32_t crypto_header;
+ uint32_t fcs_aes_crypt_payload[FCS_AES_CMD_MAX_WORD_SIZE];
+
+ if (fcs_aes_init_payload.session_id != session_id ||
+ fcs_aes_init_payload.context_id != context_id) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if ((!is_8_bytes_aligned(src_addr)) ||
+ (!is_32_bytes_aligned(src_size)) ||
+ (!is_address_in_ddr_range(src_addr, src_size))) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if ((!is_8_bytes_aligned(dst_addr)) ||
+ (!is_32_bytes_aligned(dst_size))) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if ((dst_size > FCS_AES_MAX_DATA_SIZE ||
+ dst_size < FCS_AES_MIN_DATA_SIZE) ||
+ (src_size > FCS_AES_MAX_DATA_SIZE ||
+ src_size < FCS_AES_MIN_DATA_SIZE)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ /* Prepare crypto header*/
+ flag = 0;
+ if (fcs_aes_init_payload.is_updated) {
+ fcs_aes_init_payload.param_size = 0;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_INIT;
+ }
+
+ if (is_finalised != 0U) {
+ flag |= FCS_CS_FIELD_FLAG_FINALIZE;
+ } else {
+ flag |= FCS_CS_FIELD_FLAG_UPDATE;
+ fcs_aes_init_payload.is_updated = 1;
+ }
+ crypto_header = (flag << FCS_CS_FIELD_FLAG_OFFSET) |
+ fcs_aes_init_payload.param_size;
+
+ i = 0U;
+ fcs_aes_crypt_payload[i] = session_id;
+ i++;
+ fcs_aes_crypt_payload[i] = context_id;
+ i++;
+ fcs_aes_crypt_payload[i] = crypto_header;
+ i++;
+
+ if ((crypto_header >> FCS_CS_FIELD_FLAG_OFFSET) &
+ FCS_CS_FIELD_FLAG_INIT) {
+ fcs_aes_crypt_payload[i] = fcs_aes_init_payload.key_id;
+ i++;
+
+ memcpy((uint8_t *) &fcs_aes_crypt_payload[i],
+ (uint8_t *) fcs_aes_init_payload.crypto_param,
+ fcs_aes_init_payload.param_size);
+
+ i += fcs_aes_init_payload.param_size / MBOX_WORD_BYTE;
+ }
+
+ fcs_aes_crypt_payload[i] = (uint32_t) src_addr;
+ i++;
+ fcs_aes_crypt_payload[i] = src_size;
+ i++;
+ fcs_aes_crypt_payload[i] = (uint32_t) dst_addr;
+ i++;
+ fcs_aes_crypt_payload[i] = dst_size;
+ i++;
+
+ status = mailbox_send_cmd_async(send_id, MBOX_FCS_AES_CRYPT_REQ,
+ fcs_aes_crypt_payload, i,
+ CMD_INDIRECT);
+
+ if (is_finalised != 0U) {
+ memset((void *)&fcs_aes_init_payload, 0,
+ sizeof(fcs_aes_init_payload));
+ }
+
+ if (status < 0U) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
diff --git a/plat/intel/soc/common/soc/socfpga_emac.c b/plat/intel/soc/common/soc/socfpga_emac.c
new file mode 100644
index 0000000..cacfd53
--- /dev/null
+++ b/plat/intel/soc/common/soc/socfpga_emac.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include "socfpga_emac.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_system_manager.h"
+
+void socfpga_emac_init(void)
+{
+ mmio_setbits_32(SOCFPGA_RSTMGR(PER0MODRST),
+ RSTMGR_PER0MODRST_EMAC0 |
+ RSTMGR_PER0MODRST_EMAC1 |
+ RSTMGR_PER0MODRST_EMAC2);
+
+ mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_0),
+ PHY_INTF_SEL_MSK, EMAC0_PHY_MODE);
+ mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_1),
+ PHY_INTF_SEL_MSK, EMAC1_PHY_MODE);
+ mmio_clrsetbits_32(SOCFPGA_SYSMGR(EMAC_2),
+ PHY_INTF_SEL_MSK, EMAC2_PHY_MODE);
+
+ mmio_clrbits_32(SOCFPGA_SYSMGR(FPGAINTF_EN_3),
+ FPGAINTF_EN_3_EMAC_MSK(0) |
+ FPGAINTF_EN_3_EMAC_MSK(1) |
+ FPGAINTF_EN_3_EMAC_MSK(2));
+
+ mmio_clrbits_32(SOCFPGA_RSTMGR(PER0MODRST),
+ RSTMGR_PER0MODRST_EMAC0 |
+ RSTMGR_PER0MODRST_EMAC1 |
+ RSTMGR_PER0MODRST_EMAC2);
+}
+
diff --git a/plat/intel/soc/common/soc/socfpga_firewall.c b/plat/intel/soc/common/soc/socfpga_firewall.c
new file mode 100644
index 0000000..515784b
--- /dev/null
+++ b/plat/intel/soc/common/soc/socfpga_firewall.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "socfpga_noc.h"
+#include "socfpga_plat_def.h"
+#include "socfpga_system_manager.h"
+
+void enable_nonsecure_access(void)
+{
+ enable_ns_peripheral_access();
+ enable_ns_bridge_access();
+}
+
+void enable_ns_peripheral_access(void)
+{
+ mmio_write_32(SOCFPGA_L4_PER_SCR(NAND_REGISTER), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(NAND_DATA), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(NAND_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(NAND_READ_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(NAND_WRITE_ECC),
+ DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(USB0_REGISTER), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(USB1_REGISTER), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(USB0_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(USB1_ECC), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_MASTER0), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_MASTER1), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_SLAVE0), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(SPI_SLAVE1), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(EMAC0), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(EMAC1), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(EMAC2), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC0RX_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC0TX_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC1RX_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC1TX_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC2RX_ECC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(EMAC2TX_ECC), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(SDMMC), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(SDMMC_ECC), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(GPIO0), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(GPIO1), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(I2C0), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(I2C1), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(I2C2), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(I2C3), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(I2C4), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(SP_TIMER1), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_PER_SCR(UART0), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_PER_SCR(UART1), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(DMA_ECC), DISABLE_L4_FIREWALL);
+
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(OCRAM_ECC), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(CLK_MGR), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(IO_MGR), DISABLE_L4_FIREWALL);
+
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(RST_MGR), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(SYS_MGR), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(OSC0_TIMER), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(OSC1_TIMER), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG0), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG1), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG2), DISABLE_L4_FIREWALL);
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(WATCHDOG3), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(DAP), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(L4_NOC_PROBES), DISABLE_L4_FIREWALL);
+
+ mmio_write_32(SOCFPGA_L4_SYS_SCR(L4_NOC_QOS), DISABLE_L4_FIREWALL);
+
+#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10
+ enable_ns_ocram_access();
+ mmio_write_32(SOCFPGA_SYSMGR(SDMMC), SYSMGR_SDMMC_DRVSEL(3));
+#endif
+
+}
+
+void enable_ns_ocram_access(void)
+{
+ mmio_clrbits_32(SOCFPGA_CCU_NOC(CPU0, RAM0),
+ SOCFPGA_CCU_NOC_ADMASK_P_MASK | SOCFPGA_CCU_NOC_ADMASK_NS_MASK);
+ mmio_clrbits_32(SOCFPGA_CCU_NOC(IOM, RAM0),
+ SOCFPGA_CCU_NOC_ADMASK_P_MASK | SOCFPGA_CCU_NOC_ADMASK_NS_MASK);
+}
+
+void enable_ns_bridge_access(void)
+{
+ mmio_write_32(SOCFPGA_SOC2FPGA_SCR_REG_BASE, DISABLE_BRIDGE_FIREWALL);
+ mmio_write_32(SOCFPGA_LWSOC2FPGA_SCR_REG_BASE, DISABLE_BRIDGE_FIREWALL);
+}
+
+void enable_ocram_firewall(void)
+{
+ mmio_setbits_32(SOCFPGA_CCU_NOC(CPU0, RAM0),
+ SOCFPGA_CCU_NOC_ADMASK_P_MASK | SOCFPGA_CCU_NOC_ADMASK_NS_MASK);
+ mmio_setbits_32(SOCFPGA_CCU_NOC(IOM, RAM0),
+ SOCFPGA_CCU_NOC_ADMASK_P_MASK | SOCFPGA_CCU_NOC_ADMASK_NS_MASK);
+}
diff --git a/plat/intel/soc/common/soc/socfpga_handoff.c b/plat/intel/soc/common/soc/socfpga_handoff.c
new file mode 100644
index 0000000..4bb3a96
--- /dev/null
+++ b/plat/intel/soc/common/soc/socfpga_handoff.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include "socfpga_handoff.h"
+
+#define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | \
+ (((x) & 0x0000FF00) << 8) | ((x) << 24))
+
+int socfpga_get_handoff(handoff *reverse_hoff_ptr)
+{
+ int i;
+ uint32_t *buffer;
+ handoff *handoff_ptr = (handoff *) PLAT_HANDOFF_OFFSET;
+
+ memcpy(reverse_hoff_ptr, handoff_ptr, sizeof(handoff));
+ buffer = (uint32_t *)reverse_hoff_ptr;
+
+ /* convert big endian to little endian */
+ for (i = 0; i < sizeof(handoff) / 4; i++)
+ buffer[i] = SWAP_UINT32(buffer[i]);
+
+ if (reverse_hoff_ptr->header_magic != HANDOFF_MAGIC_HEADER)
+ return -1;
+ if (reverse_hoff_ptr->pinmux_sel_magic != HANDOFF_MAGIC_PINMUX_SEL)
+ return -1;
+ if (reverse_hoff_ptr->pinmux_io_magic != HANDOFF_MAGIC_IOCTLR)
+ return -1;
+ if (reverse_hoff_ptr->pinmux_fpga_magic != HANDOFF_MAGIC_FPGA)
+ return -1;
+ if (reverse_hoff_ptr->pinmux_delay_magic != HANDOFF_MAGIC_IODELAY)
+ return -1;
+
+ return 0;
+}
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
new file mode 100644
index 0000000..79817e6
--- /dev/null
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include "socfpga_mailbox.h"
+#include "socfpga_sip_svc.h"
+
+static mailbox_payload_t mailbox_resp_payload;
+static mailbox_container_t mailbox_resp_ctr = {0, 0, &mailbox_resp_payload};
+
+static bool is_mailbox_cmdbuf_full(uint32_t cin)
+{
+ uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
+
+ return (((cin + 1U) % MBOX_CMD_BUFFER_SIZE) == cout);
+}
+
+static bool is_mailbox_cmdbuf_empty(uint32_t cin)
+{
+ uint32_t cout = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
+
+ return (((cout + 1U) % MBOX_CMD_BUFFER_SIZE) == cin);
+}
+
+static int wait_for_mailbox_cmdbuf_empty(uint32_t cin)
+{
+ unsigned int timeout = 200U;
+
+ do {
+ if (is_mailbox_cmdbuf_empty(cin)) {
+ break;
+ }
+ mdelay(10U);
+ } while (--timeout != 0U);
+
+ if (timeout == 0U) {
+ return MBOX_TIMEOUT;
+ }
+
+ return MBOX_RET_OK;
+}
+
+static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout,
+ uint32_t data,
+ bool *is_doorbell_triggered)
+{
+ unsigned int timeout = 100U;
+
+ do {
+ if (is_mailbox_cmdbuf_full(*cin)) {
+ if (!(*is_doorbell_triggered)) {
+ mmio_write_32(MBOX_OFFSET +
+ MBOX_DOORBELL_TO_SDM, 1U);
+ *is_doorbell_triggered = true;
+ }
+ mdelay(10U);
+ } else {
+ mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data);
+ *cin %= MBOX_CMD_BUFFER_SIZE;
+ mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin);
+ break;
+ }
+ } while (--timeout != 0U);
+
+ if (timeout == 0U) {
+ return MBOX_TIMEOUT;
+ }
+
+ if (*is_doorbell_triggered) {
+ int ret = wait_for_mailbox_cmdbuf_empty(*cin);
+ return ret;
+ }
+
+ return MBOX_RET_OK;
+}
+
+static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
+ unsigned int len)
+{
+ uint32_t sdm_read_offset, cmd_free_offset;
+ unsigned int i;
+ int ret;
+ bool is_doorbell_triggered = false;
+
+ cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN);
+ sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
+
+ ret = write_mailbox_cmd_buffer(&cmd_free_offset, sdm_read_offset,
+ header_cmd, &is_doorbell_triggered);
+ if (ret != 0) {
+ goto restart_mailbox;
+ }
+
+ for (i = 0U; i < len; i++) {
+ is_doorbell_triggered = false;
+ ret = write_mailbox_cmd_buffer(&cmd_free_offset,
+ sdm_read_offset, args[i],
+ &is_doorbell_triggered);
+ if (ret != 0) {
+ goto restart_mailbox;
+ }
+ }
+
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
+
+ return MBOX_RET_OK;
+
+restart_mailbox:
+ /*
+ * Attempt to restart mailbox if the driver not able to write
+ * into mailbox command buffer
+ */
+ if (MBOX_CMD_MASK(header_cmd) != MBOX_CMD_RESTART) {
+ INFO("Mailbox timed out: Attempting mailbox reset\n");
+ ret = mailbox_init();
+
+ if (ret == MBOX_TIMEOUT) {
+ INFO("Error: Mailbox fail to restart\n");
+ }
+ }
+
+ return MBOX_TIMEOUT;
+}
+
+int mailbox_read_response(unsigned int *job_id, uint32_t *response,
+ unsigned int *resp_len)
+{
+ uint32_t rin;
+ uint32_t rout;
+ uint32_t resp_data;
+ unsigned int ret_resp_len;
+
+ if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
+ }
+
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
+
+ if (rout != rin) {
+ resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
+
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
+
+
+ if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) {
+ return MBOX_WRONG_ID;
+ }
+
+ *job_id = MBOX_RESP_JOB_ID(resp_data);
+
+ ret_resp_len = MBOX_RESP_LEN(resp_data);
+
+ if (iterate_resp(ret_resp_len, response, resp_len)
+ != MBOX_RET_OK) {
+ return MBOX_TIMEOUT;
+ }
+
+ if (MBOX_RESP_ERR(resp_data) > 0U) {
+ INFO("Error in response: %x\n", resp_data);
+ return -MBOX_RESP_ERR(resp_data);
+ }
+
+ return MBOX_RET_OK;
+ }
+ return MBOX_NO_RESPONSE;
+}
+
+int mailbox_read_response_async(unsigned int *job_id, uint32_t *header,
+ uint32_t *response, unsigned int *resp_len,
+ uint8_t ignore_client_id)
+{
+ uint32_t rin;
+ uint32_t rout;
+ uint32_t resp_data;
+ uint32_t ret_resp_len = 0;
+ uint8_t is_done = 0;
+
+ if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) {
+ ret_resp_len = MBOX_RESP_LEN(
+ mailbox_resp_ctr.payload->header) -
+ mailbox_resp_ctr.index;
+ }
+
+ if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
+ }
+
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
+
+ while (rout != rin && !is_done) {
+
+ resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
+
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+
+ if ((mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) != 0) {
+ mailbox_resp_ctr.payload->data[mailbox_resp_ctr.index] = resp_data;
+ mailbox_resp_ctr.index++;
+ ret_resp_len--;
+ } else {
+ if (!ignore_client_id) {
+ if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) {
+ *resp_len = 0;
+ return MBOX_WRONG_ID;
+ }
+ }
+
+ *job_id = MBOX_RESP_JOB_ID(resp_data);
+ ret_resp_len = MBOX_RESP_LEN(resp_data);
+ mailbox_resp_ctr.payload->header = resp_data;
+ mailbox_resp_ctr.flag |= MBOX_PAYLOAD_FLAG_BUSY;
+ }
+
+ if (ret_resp_len == 0) {
+ is_done = 1;
+ }
+ }
+
+ if (is_done != 0) {
+
+ /* copy header data to input address if applicable */
+ if (header != 0) {
+ *header = mailbox_resp_ctr.payload->header;
+ }
+
+ /* copy response data to input buffer if applicable */
+ ret_resp_len = MBOX_RESP_LEN(mailbox_resp_ctr.payload->header);
+ if ((ret_resp_len > 0) && (response != NULL) && (resp_len != NULL)) {
+ if (*resp_len > ret_resp_len) {
+ *resp_len = ret_resp_len;
+ }
+
+ memcpy((uint8_t *) response,
+ (uint8_t *) mailbox_resp_ctr.payload->data,
+ *resp_len * MBOX_WORD_BYTE);
+ }
+
+ /* reset async response param */
+ mailbox_resp_ctr.index = 0;
+ mailbox_resp_ctr.flag = 0;
+
+ if (MBOX_RESP_ERR(mailbox_resp_ctr.payload->header) > 0U) {
+ INFO("Error in async response: %x\n",
+ mailbox_resp_ctr.payload->header);
+ return -MBOX_RESP_ERR(mailbox_resp_ctr.payload->header);
+ }
+
+ return MBOX_RET_OK;
+ }
+
+ *resp_len = 0;
+ return (mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) ? MBOX_BUSY : MBOX_NO_RESPONSE;
+}
+
+int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response,
+ unsigned int *resp_len)
+{
+ unsigned int timeout = 40U;
+ unsigned int sdm_loop = 255U;
+ unsigned int ret_resp_len;
+ uint32_t rin;
+ uint32_t rout;
+ uint32_t resp_data;
+
+ while (sdm_loop != 0U) {
+
+ do {
+ if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM)
+ == 1U) {
+ break;
+ }
+ mdelay(10U);
+ } while (--timeout != 0U);
+
+ if (timeout == 0U) {
+ break;
+ }
+
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
+
+ if ((urgent & 1U) != 0U) {
+ mdelay(5U);
+ if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
+ MBOX_STATUS_UA_MASK) ^
+ (urgent & MBOX_STATUS_UA_MASK)) {
+ mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
+ return MBOX_RET_OK;
+ }
+
+ mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
+ INFO("Error: Mailbox did not get UA");
+ return MBOX_RET_ERROR;
+ }
+
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
+
+ while (rout != rin) {
+ resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP,
+ (rout)++));
+
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
+
+ if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID
+ || MBOX_RESP_JOB_ID(resp_data) != job_id) {
+ continue;
+ }
+
+ ret_resp_len = MBOX_RESP_LEN(resp_data);
+
+ if (iterate_resp(ret_resp_len, response, resp_len)
+ != MBOX_RET_OK) {
+ return MBOX_TIMEOUT;
+ }
+
+ if (MBOX_RESP_ERR(resp_data) > 0U) {
+ INFO("Error in response: %x\n", resp_data);
+ return -MBOX_RESP_ERR(resp_data);
+ }
+
+ return MBOX_RET_OK;
+ }
+
+ sdm_loop--;
+ }
+
+ INFO("Timed out waiting for SDM\n");
+ return MBOX_TIMEOUT;
+}
+
+int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
+ unsigned int *resp_len)
+{
+ unsigned int timeout, total_resp_len = 0U;
+ uint32_t resp_data;
+ uint32_t rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ uint32_t rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
+
+ while (mbox_resp_len > 0U) {
+ timeout = 100U;
+ mbox_resp_len--;
+ resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
+
+ if ((resp_buf != NULL) && (resp_len != NULL)
+ && (*resp_len != 0U)) {
+ *(resp_buf + total_resp_len)
+ = resp_data;
+ *resp_len = *resp_len - 1;
+ total_resp_len++;
+ }
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
+
+ do {
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ if (rout == rin) {
+ mdelay(10U);
+ } else {
+ break;
+ }
+ timeout--;
+ } while ((mbox_resp_len > 0U) && (timeout != 0U));
+
+ if (timeout == 0U) {
+ INFO("Timed out waiting for SDM\n");
+ return MBOX_TIMEOUT;
+ }
+ }
+
+ if (resp_len)
+ *resp_len = total_resp_len;
+
+ return MBOX_RET_OK;
+}
+
+int mailbox_send_cmd_async_ext(uint32_t header_cmd, uint32_t *args,
+ unsigned int len)
+{
+ return fill_mailbox_circular_buffer(header_cmd, args, len);
+}
+
+int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args,
+ unsigned int len, unsigned int indirect)
+{
+ int status;
+
+ status = fill_mailbox_circular_buffer(
+ MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
+ MBOX_JOB_ID_CMD(*job_id) |
+ MBOX_CMD_LEN_CMD(len) |
+ MBOX_INDIRECT(indirect) |
+ cmd, args, len);
+ if (status < 0) {
+ return status;
+ }
+
+ *job_id = (*job_id + 1U) % MBOX_MAX_IND_JOB_ID;
+
+ return MBOX_RET_OK;
+}
+
+int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args,
+ unsigned int len, uint32_t urgent, uint32_t *response,
+ unsigned int *resp_len)
+{
+ int status = 0;
+
+ if (urgent != 0U) {
+ urgent |= mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
+ MBOX_STATUS_UA_MASK;
+ mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
+ }
+
+ else {
+ status = fill_mailbox_circular_buffer(
+ MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
+ MBOX_JOB_ID_CMD(job_id) |
+ MBOX_CMD_LEN_CMD(len) |
+ cmd, args, len);
+ }
+
+ if (status != 0) {
+ return status;
+ }
+
+ status = mailbox_poll_response(job_id, urgent, response, resp_len);
+
+ return status;
+}
+
+void mailbox_clear_response(void)
+{
+ mmio_write_32(MBOX_OFFSET + MBOX_ROUT,
+ mmio_read_32(MBOX_OFFSET + MBOX_RIN));
+}
+
+void mailbox_set_int(uint32_t interrupt)
+{
+
+ mmio_write_32(MBOX_OFFSET+MBOX_INT, MBOX_COE_BIT(interrupt) |
+ MBOX_UAE_BIT(interrupt));
+}
+
+
+void mailbox_set_qspi_open(void)
+{
+ mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
+ mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, NULL, 0U,
+ CMD_CASUAL, NULL, NULL);
+}
+
+void mailbox_set_qspi_direct(void)
+{
+ mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, NULL, 0U,
+ CMD_CASUAL, NULL, NULL);
+}
+
+void mailbox_set_qspi_close(void)
+{
+ mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
+ mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, NULL, 0U,
+ CMD_CASUAL, NULL, NULL);
+}
+
+void mailbox_qspi_set_cs(uint32_t device_select)
+{
+ uint32_t cs_setting;
+
+ /* QSPI device select settings at 31:28 */
+ cs_setting = (device_select << 28);
+ mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
+ mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting,
+ 1U, CMD_CASUAL, NULL, NULL);
+}
+
+void mailbox_hps_qspi_enable(void)
+{
+ mailbox_set_qspi_open();
+ mailbox_set_qspi_direct();
+}
+
+void mailbox_reset_cold(void)
+{
+ mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
+ mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, NULL, 0U,
+ CMD_CASUAL, NULL, NULL);
+}
+
+int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, unsigned int resp_buf_len)
+{
+ return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE,
+ NULL, 0U, CMD_CASUAL, resp_buf,
+ &resp_buf_len);
+}
+
+struct rsu_status_info {
+ uint64_t current_image;
+ uint64_t fail_image;
+ uint32_t state;
+ uint32_t version;
+ uint32_t error_location;
+ uint32_t error_details;
+ uint32_t retry_counter;
+};
+
+int mailbox_rsu_status(uint32_t *resp_buf, unsigned int resp_buf_len)
+{
+ int ret;
+ struct rsu_status_info *info = (struct rsu_status_info *)resp_buf;
+
+ info->retry_counter = ~0U;
+
+ ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0U,
+ CMD_CASUAL, resp_buf,
+ &resp_buf_len);
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (info->retry_counter != ~0U) {
+ if ((info->version & RSU_VERSION_ACMF_MASK) == 0U) {
+ info->version |= RSU_VERSION_ACMF;
+ }
+ }
+
+ return ret;
+}
+
+int mailbox_rsu_update(uint32_t *flash_offset)
+{
+ return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
+ flash_offset, 2U,
+ CMD_CASUAL, NULL, NULL);
+}
+
+int mailbox_hps_stage_notify(uint32_t execution_stage)
+{
+ return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY,
+ &execution_stage, 1U, CMD_CASUAL,
+ NULL, NULL);
+}
+
+int mailbox_init(void)
+{
+ int status;
+
+ mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
+ MBOX_INT_FLAG_UAE);
+ mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
+
+ status = mailbox_send_cmd(0U, MBOX_CMD_RESTART, NULL, 0U,
+ CMD_URGENT, NULL, NULL);
+
+ if (status != 0) {
+ return status;
+ }
+
+ mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
+ MBOX_INT_FLAG_UAE);
+
+ return MBOX_RET_OK;
+}
+
+int intel_mailbox_get_config_status(uint32_t cmd, bool init_done)
+{
+ int status;
+ uint32_t res, response[6];
+ unsigned int resp_len = ARRAY_SIZE(response);
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, cmd, NULL, 0U, CMD_CASUAL,
+ response, &resp_len);
+
+ if (status < 0) {
+ return status;
+ }
+
+ res = response[RECONFIG_STATUS_STATE];
+ if ((res != 0U) && (res != MBOX_CFGSTAT_STATE_CONFIG)) {
+ return res;
+ }
+
+ res = response[RECONFIG_STATUS_PIN_STATUS];
+ if ((res & PIN_STATUS_NSTATUS) == 0U) {
+ return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
+ }
+
+ res = response[RECONFIG_STATUS_SOFTFUNC_STATUS];
+ if ((res & SOFTFUNC_STATUS_SEU_ERROR) != 0U) {
+ return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
+ }
+
+ if ((res & SOFTFUNC_STATUS_CONF_DONE) == 0U) {
+ return MBOX_CFGSTAT_STATE_CONFIG;
+ }
+
+ if (init_done && (res & SOFTFUNC_STATUS_INIT_DONE) == 0U) {
+ return MBOX_CFGSTAT_STATE_CONFIG;
+ }
+
+ return MBOX_RET_OK;
+}
+
+int intel_mailbox_is_fpga_not_ready(void)
+{
+ int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true);
+
+ if ((ret != MBOX_RET_OK) && (ret != MBOX_CFGSTAT_STATE_CONFIG)) {
+ ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS,
+ false);
+ }
+
+ return ret;
+}
+
+int mailbox_hwmon_readtemp(uint32_t chan, uint32_t *resp_buf)
+{
+ unsigned int resp_len = sizeof(resp_buf);
+
+ return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READTEMP, &chan, 1U,
+ CMD_CASUAL, resp_buf,
+ &resp_len);
+
+}
+
+int mailbox_hwmon_readvolt(uint32_t chan, uint32_t *resp_buf)
+{
+ unsigned int resp_len = sizeof(resp_buf);
+
+ return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HWMON_READVOLT, &chan, 1U,
+ CMD_CASUAL, resp_buf,
+ &resp_len);
+}
diff --git a/plat/intel/soc/common/soc/socfpga_reset_manager.c b/plat/intel/soc/common/soc/socfpga_reset_manager.c
new file mode 100644
index 0000000..bb4efab
--- /dev/null
+++ b/plat/intel/soc/common/soc/socfpga_reset_manager.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include "socfpga_f2sdram_manager.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_system_manager.h"
+
+
+void deassert_peripheral_reset(void)
+{
+ mmio_clrbits_32(SOCFPGA_RSTMGR(PER1MODRST),
+ RSTMGR_FIELD(PER1, WATCHDOG0) |
+ RSTMGR_FIELD(PER1, WATCHDOG1) |
+ RSTMGR_FIELD(PER1, WATCHDOG2) |
+ RSTMGR_FIELD(PER1, WATCHDOG3) |
+ RSTMGR_FIELD(PER1, L4SYSTIMER0) |
+ RSTMGR_FIELD(PER1, L4SYSTIMER1) |
+ RSTMGR_FIELD(PER1, SPTIMER0) |
+ RSTMGR_FIELD(PER1, SPTIMER1) |
+ RSTMGR_FIELD(PER1, I2C0) |
+ RSTMGR_FIELD(PER1, I2C1) |
+ RSTMGR_FIELD(PER1, I2C2) |
+ RSTMGR_FIELD(PER1, I2C3) |
+ RSTMGR_FIELD(PER1, I2C4) |
+ RSTMGR_FIELD(PER1, UART0) |
+ RSTMGR_FIELD(PER1, UART1) |
+ RSTMGR_FIELD(PER1, GPIO0) |
+ RSTMGR_FIELD(PER1, GPIO1));
+
+ mmio_clrbits_32(SOCFPGA_RSTMGR(PER0MODRST),
+ RSTMGR_FIELD(PER0, EMAC0OCP) |
+ RSTMGR_FIELD(PER0, EMAC1OCP) |
+ RSTMGR_FIELD(PER0, EMAC2OCP) |
+ RSTMGR_FIELD(PER0, USB0OCP) |
+ RSTMGR_FIELD(PER0, USB1OCP) |
+ RSTMGR_FIELD(PER0, NANDOCP) |
+ RSTMGR_FIELD(PER0, SDMMCOCP) |
+ RSTMGR_FIELD(PER0, DMAOCP));
+
+ mmio_clrbits_32(SOCFPGA_RSTMGR(PER0MODRST),
+ RSTMGR_FIELD(PER0, EMAC0) |
+ RSTMGR_FIELD(PER0, EMAC1) |
+ RSTMGR_FIELD(PER0, EMAC2) |
+ RSTMGR_FIELD(PER0, USB0) |
+ RSTMGR_FIELD(PER0, USB1) |
+ RSTMGR_FIELD(PER0, NAND) |
+ RSTMGR_FIELD(PER0, SDMMC) |
+ RSTMGR_FIELD(PER0, DMA) |
+ RSTMGR_FIELD(PER0, SPIM0) |
+ RSTMGR_FIELD(PER0, SPIM1) |
+ RSTMGR_FIELD(PER0, SPIS0) |
+ RSTMGR_FIELD(PER0, SPIS1) |
+ RSTMGR_FIELD(PER0, EMACPTP) |
+ RSTMGR_FIELD(PER0, DMAIF0) |
+ RSTMGR_FIELD(PER0, DMAIF1) |
+ RSTMGR_FIELD(PER0, DMAIF2) |
+ RSTMGR_FIELD(PER0, DMAIF3) |
+ RSTMGR_FIELD(PER0, DMAIF4) |
+ RSTMGR_FIELD(PER0, DMAIF5) |
+ RSTMGR_FIELD(PER0, DMAIF6) |
+ RSTMGR_FIELD(PER0, DMAIF7));
+
+#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX
+ mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST),
+ RSTMGR_FIELD(BRG, MPFE));
+#endif
+}
+
+void config_hps_hs_before_warm_reset(void)
+{
+ uint32_t or_mask = 0;
+
+ or_mask |= RSTMGR_HDSKEN_SDRSELFREFEN;
+ or_mask |= RSTMGR_HDSKEN_FPGAHSEN;
+ or_mask |= RSTMGR_HDSKEN_ETRSTALLEN;
+ or_mask |= RSTMGR_HDSKEN_L2FLUSHEN;
+ or_mask |= RSTMGR_HDSKEN_L3NOC_DBG;
+ or_mask |= RSTMGR_HDSKEN_DEBUG_L3NOC;
+
+ mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN), or_mask);
+}
+
+static int poll_idle_status(uint32_t addr, uint32_t mask, uint32_t match)
+{
+ int time_out = 300;
+
+ while (time_out--) {
+ if ((mmio_read_32(addr) & mask) == match) {
+ return 0;
+ }
+ udelay(1000);
+ }
+ return -ETIMEDOUT;
+}
+
+static void socfpga_s2f_bridge_mask(uint32_t mask,
+ uint32_t *brg_mask,
+ uint32_t *noc_mask)
+{
+ *brg_mask = 0;
+ *noc_mask = 0;
+
+ if ((mask & SOC2FPGA_MASK) != 0U) {
+ *brg_mask |= RSTMGR_FIELD(BRG, SOC2FPGA);
+ *noc_mask |= IDLE_DATA_SOC2FPGA;
+ }
+
+ if ((mask & LWHPS2FPGA_MASK) != 0U) {
+ *brg_mask |= RSTMGR_FIELD(BRG, LWHPS2FPGA);
+ *noc_mask |= IDLE_DATA_LWSOC2FPGA;
+ }
+}
+
+static void socfpga_f2s_bridge_mask(uint32_t mask,
+ uint32_t *brg_mask,
+ uint32_t *f2s_idlereq,
+ uint32_t *f2s_force_drain,
+ uint32_t *f2s_en,
+ uint32_t *f2s_idleack,
+ uint32_t *f2s_respempty)
+{
+ *brg_mask = 0;
+ *f2s_idlereq = 0;
+ *f2s_force_drain = 0;
+ *f2s_en = 0;
+ *f2s_idleack = 0;
+ *f2s_respempty = 0;
+
+#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10
+ if ((mask & FPGA2SOC_MASK) != 0U) {
+ *brg_mask |= RSTMGR_FIELD(BRG, FPGA2SOC);
+ }
+ if ((mask & F2SDRAM0_MASK) != 0U) {
+ *brg_mask |= RSTMGR_FIELD(BRG, F2SSDRAM0);
+ *f2s_idlereq |= FLAGOUTSETCLR_F2SDRAM0_IDLEREQ;
+ *f2s_force_drain |= FLAGOUTSETCLR_F2SDRAM0_FORCE_DRAIN;
+ *f2s_en |= FLAGOUTSETCLR_F2SDRAM0_ENABLE;
+ *f2s_idleack |= FLAGINTSTATUS_F2SDRAM0_IDLEACK;
+ *f2s_respempty |= FLAGINTSTATUS_F2SDRAM0_RESPEMPTY;
+ }
+ if ((mask & F2SDRAM1_MASK) != 0U) {
+ *brg_mask |= RSTMGR_FIELD(BRG, F2SSDRAM1);
+ *f2s_idlereq |= FLAGOUTSETCLR_F2SDRAM1_IDLEREQ;
+ *f2s_force_drain |= FLAGOUTSETCLR_F2SDRAM1_FORCE_DRAIN;
+ *f2s_en |= FLAGOUTSETCLR_F2SDRAM1_ENABLE;
+ *f2s_idleack |= FLAGINTSTATUS_F2SDRAM1_IDLEACK;
+ *f2s_respempty |= FLAGINTSTATUS_F2SDRAM1_RESPEMPTY;
+ }
+ if ((mask & F2SDRAM2_MASK) != 0U) {
+ *brg_mask |= RSTMGR_FIELD(BRG, F2SSDRAM2);
+ *f2s_idlereq |= FLAGOUTSETCLR_F2SDRAM2_IDLEREQ;
+ *f2s_force_drain |= FLAGOUTSETCLR_F2SDRAM2_FORCE_DRAIN;
+ *f2s_en |= FLAGOUTSETCLR_F2SDRAM2_ENABLE;
+ *f2s_idleack |= FLAGINTSTATUS_F2SDRAM2_IDLEACK;
+ *f2s_respempty |= FLAGINTSTATUS_F2SDRAM2_RESPEMPTY;
+ }
+#else
+ if ((mask & FPGA2SOC_MASK) != 0U) {
+ *brg_mask |= RSTMGR_FIELD(BRG, FPGA2SOC);
+ *f2s_idlereq |= FLAGOUTSETCLR_F2SDRAM0_IDLEREQ;
+ *f2s_force_drain |= FLAGOUTSETCLR_F2SDRAM0_FORCE_DRAIN;
+ *f2s_en |= FLAGOUTSETCLR_F2SDRAM0_ENABLE;
+ *f2s_idleack |= FLAGINTSTATUS_F2SDRAM0_IDLEACK;
+ *f2s_respempty |= FLAGINTSTATUS_F2SDRAM0_RESPEMPTY;
+ }
+#endif
+}
+
+int socfpga_bridges_enable(uint32_t mask)
+{
+ int ret = 0;
+ uint32_t brg_mask = 0;
+ uint32_t noc_mask = 0;
+ uint32_t f2s_idlereq = 0;
+ uint32_t f2s_force_drain = 0;
+ uint32_t f2s_en = 0;
+ uint32_t f2s_idleack = 0;
+ uint32_t f2s_respempty = 0;
+
+ /* Enable s2f bridge */
+ socfpga_s2f_bridge_mask(mask, &brg_mask, &noc_mask);
+ if (brg_mask != 0U) {
+ /* Clear idle request */
+ mmio_setbits_32(SOCFPGA_SYSMGR(NOC_IDLEREQ_CLR),
+ noc_mask);
+
+ /* De-assert all bridges */
+ mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST), brg_mask);
+
+ /* Wait until idle ack becomes 0 */
+ ret = poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLEACK),
+ noc_mask, 0);
+ if (ret < 0) {
+ ERROR("S2F bridge enable: "
+ "Timeout waiting for idle ack\n");
+ }
+ }
+
+ /* Enable f2s bridge */
+ socfpga_f2s_bridge_mask(mask, &brg_mask, &f2s_idlereq,
+ &f2s_force_drain, &f2s_en,
+ &f2s_idleack, &f2s_respempty);
+ if (brg_mask != 0U) {
+ mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST), brg_mask);
+
+ mmio_clrbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTSET0),
+ f2s_idlereq);
+
+ ret = poll_idle_status(SOCFPGA_F2SDRAMMGR(
+ SIDEBANDMGR_FLAGINSTATUS0), f2s_idleack, 0);
+ if (ret < 0) {
+ ERROR("F2S bridge enable: "
+ "Timeout waiting for idle ack");
+ }
+
+ mmio_clrbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTSET0),
+ f2s_force_drain);
+ udelay(5);
+
+ mmio_setbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTSET0),
+ f2s_en);
+ udelay(5);
+ }
+
+ return ret;
+}
+
+int socfpga_bridges_disable(uint32_t mask)
+{
+ int ret = 0;
+ int timeout = 300;
+ uint32_t brg_mask = 0;
+ uint32_t noc_mask = 0;
+ uint32_t f2s_idlereq = 0;
+ uint32_t f2s_force_drain = 0;
+ uint32_t f2s_en = 0;
+ uint32_t f2s_idleack = 0;
+ uint32_t f2s_respempty = 0;
+
+ /* Disable s2f bridge */
+ socfpga_s2f_bridge_mask(mask, &brg_mask, &noc_mask);
+ if (brg_mask != 0U) {
+ mmio_setbits_32(SOCFPGA_SYSMGR(NOC_IDLEREQ_SET),
+ noc_mask);
+
+ mmio_write_32(SOCFPGA_SYSMGR(NOC_TIMEOUT), 1);
+
+ ret = poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLEACK),
+ noc_mask, noc_mask);
+ if (ret < 0) {
+ ERROR("S2F Bridge disable: "
+ "Timeout waiting for idle ack\n");
+ }
+
+ ret = poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLESTATUS),
+ noc_mask, noc_mask);
+ if (ret < 0) {
+ ERROR("S2F Bridge disable: "
+ "Timeout waiting for idle status\n");
+ }
+
+ mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST), brg_mask);
+
+ mmio_write_32(SOCFPGA_SYSMGR(NOC_TIMEOUT), 0);
+ }
+
+ /* Disable f2s bridge */
+ socfpga_f2s_bridge_mask(mask, &brg_mask, &f2s_idlereq,
+ &f2s_force_drain, &f2s_en,
+ &f2s_idleack, &f2s_respempty);
+ if (brg_mask != 0U) {
+ mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN),
+ RSTMGR_HDSKEN_FPGAHSEN);
+
+ mmio_setbits_32(SOCFPGA_RSTMGR(HDSKREQ),
+ RSTMGR_HDSKREQ_FPGAHSREQ);
+
+ poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_FPGAHSACK_MASK,
+ RSTMGR_HDSKACK_FPGAHSACK_MASK);
+
+ mmio_clrbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTSET0),
+ f2s_en);
+ udelay(5);
+
+ mmio_setbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTSET0),
+ f2s_force_drain);
+ udelay(5);
+
+ do {
+ /* Read response queue status to ensure it is empty */
+ uint32_t idle_status;
+
+ idle_status = mmio_read_32(SOCFPGA_F2SDRAMMGR(
+ SIDEBANDMGR_FLAGINSTATUS0));
+ if ((idle_status & f2s_respempty) != 0U) {
+ idle_status = mmio_read_32(SOCFPGA_F2SDRAMMGR(
+ SIDEBANDMGR_FLAGINSTATUS0));
+ if ((idle_status & f2s_respempty) != 0U) {
+ break;
+ }
+ }
+ udelay(1000);
+ } while (timeout-- > 0);
+
+#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10
+ /* Software must never write a 0x1 to FPGA2SOC_MASK bit */
+ mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
+ brg_mask & ~RSTMGR_FIELD(BRG, FPGA2SOC));
+#else
+ mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
+ brg_mask);
+#endif
+ mmio_clrbits_32(SOCFPGA_RSTMGR(HDSKREQ),
+ RSTMGR_HDSKEQ_FPGAHSREQ);
+
+ mmio_setbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTCLR0),
+ f2s_idlereq);
+ }
+
+ return ret;
+}
diff --git a/plat/intel/soc/common/socfpga_delay_timer.c b/plat/intel/soc/common/socfpga_delay_timer.c
new file mode 100644
index 0000000..dcd51e2
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_delay_timer.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include "socfpga_plat_def.h"
+
+#define SOCFPGA_GLOBAL_TIMER 0xffd01000
+#define SOCFPGA_GLOBAL_TIMER_EN 0x3
+
+static timer_ops_t plat_timer_ops;
+/********************************************************************
+ * The timer delay function
+ ********************************************************************/
+static uint32_t socfpga_get_timer_value(void)
+{
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. We apply bitwise NOT operator to the tick values returned
+ * by read_cntpct_el0() to simulate the down counter. The value is
+ * clipped from 64 to 32 bits.
+ */
+ return (uint32_t)(~read_cntpct_el0());
+}
+
+void socfpga_delay_timer_init_args(void)
+{
+ plat_timer_ops.get_timer_value = socfpga_get_timer_value;
+ plat_timer_ops.clk_mult = 1;
+ plat_timer_ops.clk_div = PLAT_SYS_COUNTER_FREQ_IN_MHZ;
+
+ timer_init(&plat_timer_ops);
+
+}
+
+void socfpga_delay_timer_init(void)
+{
+ socfpga_delay_timer_init_args();
+ mmio_write_32(SOCFPGA_GLOBAL_TIMER, SOCFPGA_GLOBAL_TIMER_EN);
+
+ asm volatile("msr cntp_ctl_el0, %0" : : "r" (SOCFPGA_GLOBAL_TIMER_EN));
+ asm volatile("msr cntp_tval_el0, %0" : : "r" (~0));
+
+}
diff --git a/plat/intel/soc/common/socfpga_image_load.c b/plat/intel/soc/common/socfpga_image_load.c
new file mode 100644
index 0000000..a5c3279
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_image_load.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ unsigned int count;
+ unsigned int img_id = 0U;
+ unsigned int link_index = 0U;
+ bl_params_node_t *bl_exec_node = NULL;
+ bl_mem_params_node_t *desc_ptr;
+
+ /* If there is no image to start with, return NULL */
+ if (bl_mem_params_desc_num == 0U)
+ return NULL;
+
+ /* Clean next_params_info in BL image node */
+ for (count = 0U; count < bl_mem_params_desc_num; count++) {
+
+ desc_ptr = &bl_mem_params_desc_ptr[link_index];
+ bl_exec_node = &desc_ptr->params_node_mem;
+ bl_exec_node->next_params_info = NULL;
+
+ /* If no next hand-off image then break out */
+ img_id = desc_ptr->next_handoff_image_id;
+ if (img_id == INVALID_IMAGE_ID)
+ break;
+
+ /* Get the index for the next hand-off image */
+ link_index = get_bl_params_node_index(img_id);
+ }
+
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
new file mode 100644
index 0000000..5fd6559
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include "socfpga_mailbox.h"
+#include "socfpga_plat_def.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_sip_svc.h"
+
+
+/*******************************************************************************
+ * plat handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+void socfpga_cpu_standby(plat_local_state_t cpu_state)
+{
+ /*
+ * Enter standby state
+ * dsb is good practice before using wfi to enter low power states
+ */
+ VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state);
+ dsb();
+ wfi();
+}
+
+/*******************************************************************************
+ * plat handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+int socfpga_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
+
+ if (cpu_id == -1)
+ return PSCI_E_INTERN_FAIL;
+
+ mmio_write_64(PLAT_CPUID_RELEASE, cpu_id);
+
+ /* release core reset */
+ mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * plat handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void socfpga_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+}
+
+/*******************************************************************************
+ * plat handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void socfpga_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ unsigned int cpu_id = plat_my_core_pos();
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+
+ /* assert core reset */
+ mmio_setbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
+
+}
+
+/*******************************************************************************
+ * plat handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void socfpga_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+
+ /* Enable the gic cpu interface */
+ gicv2_cpuif_enable();
+}
+
+/*******************************************************************************
+ * plat handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+void socfpga_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ unsigned int cpu_id = plat_my_core_pos();
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+
+ /* release core reset */
+ mmio_clrbits_32(SOCFPGA_RSTMGR(MPUMODRST), 1 << cpu_id);
+}
+
+/*******************************************************************************
+ * plat handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 socfpga_system_off(void)
+{
+ wfi();
+ ERROR("System Off: operation not handled.\n");
+ panic();
+}
+
+extern uint64_t intel_rsu_update_address;
+
+static void __dead2 socfpga_system_reset(void)
+{
+ uint32_t addr_buf[2];
+
+ memcpy(addr_buf, &intel_rsu_update_address,
+ sizeof(intel_rsu_update_address));
+
+ if (intel_rsu_update_address)
+ mailbox_rsu_update(addr_buf);
+ else
+ mailbox_reset_cold();
+
+ while (1)
+ wfi();
+}
+
+static int socfpga_system_reset2(int is_vendor, int reset_type,
+ u_register_t cookie)
+{
+ if (cold_reset_for_ecc_dbe()) {
+ mailbox_reset_cold();
+ }
+ /* disable cpuif */
+ gicv2_cpuif_disable();
+
+ /* Store magic number */
+ mmio_write_32(L2_RESET_DONE_REG, L2_RESET_DONE_STATUS);
+
+ /* Increase timeout */
+ mmio_write_32(SOCFPGA_RSTMGR(HDSKTIMEOUT), 0xffffff);
+
+ /* Enable handshakes */
+ mmio_setbits_32(SOCFPGA_RSTMGR(HDSKEN), RSTMGR_HDSKEN_SET);
+
+ /* Reset L2 module */
+ mmio_setbits_32(SOCFPGA_RSTMGR(COLDMODRST), 0x100);
+
+ while (1)
+ wfi();
+
+ /* Should not reach here */
+ return 0;
+}
+
+int socfpga_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+ return PSCI_E_SUCCESS;
+}
+
+int socfpga_validate_ns_entrypoint(unsigned long ns_entrypoint)
+{
+ VERBOSE("%s: ns_entrypoint: 0x%lx\n", __func__, ns_entrypoint);
+ return PSCI_E_SUCCESS;
+}
+
+void socfpga_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+const plat_psci_ops_t socfpga_psci_pm_ops = {
+ .cpu_standby = socfpga_cpu_standby,
+ .pwr_domain_on = socfpga_pwr_domain_on,
+ .pwr_domain_off = socfpga_pwr_domain_off,
+ .pwr_domain_suspend = socfpga_pwr_domain_suspend,
+ .pwr_domain_on_finish = socfpga_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = socfpga_pwr_domain_suspend_finish,
+ .system_off = socfpga_system_off,
+ .system_reset = socfpga_system_reset,
+ .system_reset2 = socfpga_system_reset2,
+ .validate_power_state = socfpga_validate_power_state,
+ .validate_ns_entrypoint = socfpga_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = socfpga_get_sys_suspend_power_state
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ /* Save warm boot entrypoint.*/
+ mmio_write_64(PLAT_SEC_ENTRY, sec_entrypoint);
+ *psci_ops = &socfpga_psci_pm_ops;
+
+ return 0;
+}
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
new file mode 100644
index 0000000..f079349
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -0,0 +1,1131 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <tools_share/uuid.h>
+
+#include "socfpga_fcs.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_sip_svc.h"
+
+
+/* Total buffer the driver can hold */
+#define FPGA_CONFIG_BUFFER_SIZE 4
+
+static config_type request_type = NO_REQUEST;
+static int current_block, current_buffer;
+static int read_block, max_blocks;
+static uint32_t send_id, rcv_id;
+static uint32_t bytes_per_block, blocks_submitted;
+static bool bridge_disable;
+
+/* RSU static variables */
+static uint32_t rsu_dcmf_ver[4] = {0};
+static uint16_t rsu_dcmf_stat[4] = {0};
+static uint32_t rsu_max_retry;
+
+/* SiP Service UUID */
+DEFINE_SVC_UUID2(intl_svc_uid,
+ 0xa85273b0, 0xe85a, 0x4862, 0xa6, 0x2a,
+ 0xfa, 0x88, 0x88, 0x17, 0x68, 0x81);
+
+static uint64_t socfpga_sip_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
+
+struct fpga_config_info fpga_config_buffers[FPGA_CONFIG_BUFFER_SIZE];
+
+static int intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer)
+{
+ uint32_t args[3];
+
+ while (max_blocks > 0 && buffer->size > buffer->size_written) {
+ args[0] = (1<<8);
+ args[1] = buffer->addr + buffer->size_written;
+ if (buffer->size - buffer->size_written <= bytes_per_block) {
+ args[2] = buffer->size - buffer->size_written;
+ current_buffer++;
+ current_buffer %= FPGA_CONFIG_BUFFER_SIZE;
+ } else {
+ args[2] = bytes_per_block;
+ }
+
+ buffer->size_written += args[2];
+ mailbox_send_cmd_async(&send_id, MBOX_RECONFIG_DATA, args,
+ 3U, CMD_INDIRECT);
+
+ buffer->subblocks_sent++;
+ max_blocks--;
+ }
+
+ return !max_blocks;
+}
+
+static int intel_fpga_sdm_write_all(void)
+{
+ for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
+ if (intel_fpga_sdm_write_buffer(
+ &fpga_config_buffers[current_buffer])) {
+ break;
+ }
+ }
+ return 0;
+}
+
+static uint32_t intel_mailbox_fpga_config_isdone(void)
+{
+ uint32_t ret;
+
+ switch (request_type) {
+ case RECONFIGURATION:
+ ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS,
+ true);
+ break;
+ case BITSTREAM_AUTH:
+ ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS,
+ false);
+ break;
+ default:
+ ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS,
+ false);
+ break;
+ }
+
+ if (ret != 0U) {
+ if (ret == MBOX_CFGSTAT_STATE_CONFIG) {
+ return INTEL_SIP_SMC_STATUS_BUSY;
+ } else {
+ request_type = NO_REQUEST;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+ }
+
+ if (bridge_disable != 0U) {
+ socfpga_bridges_enable(~0); /* Enable bridge */
+ bridge_disable = false;
+ }
+ request_type = NO_REQUEST;
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static int mark_last_buffer_xfer_completed(uint32_t *buffer_addr_completed)
+{
+ int i;
+
+ for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
+ if (fpga_config_buffers[i].block_number == current_block) {
+ fpga_config_buffers[i].subblocks_sent--;
+ if (fpga_config_buffers[i].subblocks_sent == 0
+ && fpga_config_buffers[i].size <=
+ fpga_config_buffers[i].size_written) {
+ fpga_config_buffers[i].write_requested = 0;
+ current_block++;
+ *buffer_addr_completed =
+ fpga_config_buffers[i].addr;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+static int intel_fpga_config_completed_write(uint32_t *completed_addr,
+ uint32_t *count, uint32_t *job_id)
+{
+ uint32_t resp[5];
+ unsigned int resp_len = ARRAY_SIZE(resp);
+ int status = INTEL_SIP_SMC_STATUS_OK;
+ int all_completed = 1;
+ *count = 0;
+
+ while (*count < 3) {
+
+ status = mailbox_read_response(job_id,
+ resp, &resp_len);
+
+ if (status < 0) {
+ break;
+ }
+
+ max_blocks++;
+
+ if (mark_last_buffer_xfer_completed(
+ &completed_addr[*count]) == 0) {
+ *count = *count + 1;
+ } else {
+ break;
+ }
+ }
+
+ if (*count <= 0) {
+ if (status != MBOX_NO_RESPONSE &&
+ status != MBOX_TIMEOUT && resp_len != 0) {
+ mailbox_clear_response();
+ request_type = NO_REQUEST;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *count = 0;
+ }
+
+ intel_fpga_sdm_write_all();
+
+ if (*count > 0) {
+ status = INTEL_SIP_SMC_STATUS_OK;
+ } else if (*count == 0) {
+ status = INTEL_SIP_SMC_STATUS_BUSY;
+ }
+
+ for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
+ if (fpga_config_buffers[i].write_requested != 0) {
+ all_completed = 0;
+ break;
+ }
+ }
+
+ if (all_completed == 1) {
+ return INTEL_SIP_SMC_STATUS_OK;
+ }
+
+ return status;
+}
+
+static int intel_fpga_config_start(uint32_t flag)
+{
+ uint32_t argument = 0x1;
+ uint32_t response[3];
+ int status = 0;
+ unsigned int size = 0;
+ unsigned int resp_len = ARRAY_SIZE(response);
+
+ request_type = RECONFIGURATION;
+
+ if (!CONFIG_TEST_FLAG(flag, PARTIAL_CONFIG)) {
+ bridge_disable = true;
+ }
+
+ if (CONFIG_TEST_FLAG(flag, AUTHENTICATION)) {
+ size = 1;
+ bridge_disable = false;
+ request_type = BITSTREAM_AUTH;
+ }
+
+ mailbox_clear_response();
+
+ mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_CANCEL, NULL, 0U,
+ CMD_CASUAL, NULL, NULL);
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RECONFIG, &argument, size,
+ CMD_CASUAL, response, &resp_len);
+
+ if (status < 0) {
+ bridge_disable = false;
+ request_type = NO_REQUEST;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ max_blocks = response[0];
+ bytes_per_block = response[1];
+
+ for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
+ fpga_config_buffers[i].size = 0;
+ fpga_config_buffers[i].size_written = 0;
+ fpga_config_buffers[i].addr = 0;
+ fpga_config_buffers[i].write_requested = 0;
+ fpga_config_buffers[i].block_number = 0;
+ fpga_config_buffers[i].subblocks_sent = 0;
+ }
+
+ blocks_submitted = 0;
+ current_block = 0;
+ read_block = 0;
+ current_buffer = 0;
+
+ /* Disable bridge on full reconfiguration */
+ if (bridge_disable) {
+ socfpga_bridges_disable(~0);
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static bool is_fpga_config_buffer_full(void)
+{
+ for (int i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
+ if (!fpga_config_buffers[i].write_requested) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool is_address_in_ddr_range(uint64_t addr, uint64_t size)
+{
+ if (!addr && !size) {
+ return true;
+ }
+ if (size > (UINT64_MAX - addr)) {
+ return false;
+ }
+ if (addr < BL31_LIMIT) {
+ return false;
+ }
+ if (addr + size > DRAM_BASE + DRAM_SIZE) {
+ return false;
+ }
+
+ return true;
+}
+
+static uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size)
+{
+ int i;
+
+ intel_fpga_sdm_write_all();
+
+ if (!is_address_in_ddr_range(mem, size) ||
+ is_fpga_config_buffer_full()) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ for (i = 0; i < FPGA_CONFIG_BUFFER_SIZE; i++) {
+ int j = (i + current_buffer) % FPGA_CONFIG_BUFFER_SIZE;
+
+ if (!fpga_config_buffers[j].write_requested) {
+ fpga_config_buffers[j].addr = mem;
+ fpga_config_buffers[j].size = size;
+ fpga_config_buffers[j].size_written = 0;
+ fpga_config_buffers[j].write_requested = 1;
+ fpga_config_buffers[j].block_number =
+ blocks_submitted++;
+ fpga_config_buffers[j].subblocks_sent = 0;
+ break;
+ }
+ }
+
+ if (is_fpga_config_buffer_full()) {
+ return INTEL_SIP_SMC_STATUS_BUSY;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static int is_out_of_sec_range(uint64_t reg_addr)
+{
+#if DEBUG
+ return 0;
+#endif
+
+ switch (reg_addr) {
+ case(0xF8011100): /* ECCCTRL1 */
+ case(0xF8011104): /* ECCCTRL2 */
+ case(0xF8011110): /* ERRINTEN */
+ case(0xF8011114): /* ERRINTENS */
+ case(0xF8011118): /* ERRINTENR */
+ case(0xF801111C): /* INTMODE */
+ case(0xF8011120): /* INTSTAT */
+ case(0xF8011124): /* DIAGINTTEST */
+ case(0xF801112C): /* DERRADDRA */
+ case(0xFFD12028): /* SDMMCGRP_CTRL */
+ case(0xFFD12044): /* EMAC0 */
+ case(0xFFD12048): /* EMAC1 */
+ case(0xFFD1204C): /* EMAC2 */
+ case(0xFFD12090): /* ECC_INT_MASK_VALUE */
+ case(0xFFD12094): /* ECC_INT_MASK_SET */
+ case(0xFFD12098): /* ECC_INT_MASK_CLEAR */
+ case(0xFFD1209C): /* ECC_INTSTATUS_SERR */
+ case(0xFFD120A0): /* ECC_INTSTATUS_DERR */
+ case(0xFFD120C0): /* NOC_TIMEOUT */
+ case(0xFFD120C4): /* NOC_IDLEREQ_SET */
+ case(0xFFD120C8): /* NOC_IDLEREQ_CLR */
+ case(0xFFD120D0): /* NOC_IDLEACK */
+ case(0xFFD120D4): /* NOC_IDLESTATUS */
+ case(0xFFD12200): /* BOOT_SCRATCH_COLD0 */
+ case(0xFFD12204): /* BOOT_SCRATCH_COLD1 */
+ case(0xFFD12220): /* BOOT_SCRATCH_COLD8 */
+ case(0xFFD12224): /* BOOT_SCRATCH_COLD9 */
+ return 0;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+/* Secure register access */
+uint32_t intel_secure_reg_read(uint64_t reg_addr, uint32_t *retval)
+{
+ if (is_out_of_sec_range(reg_addr)) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *retval = mmio_read_32(reg_addr);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_secure_reg_write(uint64_t reg_addr, uint32_t val,
+ uint32_t *retval)
+{
+ if (is_out_of_sec_range(reg_addr)) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ mmio_write_32(reg_addr, val);
+
+ return intel_secure_reg_read(reg_addr, retval);
+}
+
+uint32_t intel_secure_reg_update(uint64_t reg_addr, uint32_t mask,
+ uint32_t val, uint32_t *retval)
+{
+ if (!intel_secure_reg_read(reg_addr, retval)) {
+ *retval &= ~mask;
+ *retval |= val & mask;
+ return intel_secure_reg_write(reg_addr, *retval, retval);
+ }
+
+ return INTEL_SIP_SMC_STATUS_ERROR;
+}
+
+/* Intel Remote System Update (RSU) services */
+uint64_t intel_rsu_update_address;
+
+static uint32_t intel_rsu_status(uint64_t *respbuf, unsigned int respbuf_sz)
+{
+ if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0) {
+ return INTEL_SIP_SMC_RSU_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_update(uint64_t update_address)
+{
+ intel_rsu_update_address = update_address;
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_notify(uint32_t execution_stage)
+{
+ if (mailbox_hps_stage_notify(execution_stage) < 0) {
+ return INTEL_SIP_SMC_RSU_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_retry_counter(uint32_t *respbuf, uint32_t respbuf_sz,
+ uint32_t *ret_stat)
+{
+ if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0) {
+ return INTEL_SIP_SMC_RSU_ERROR;
+ }
+
+ *ret_stat = respbuf[8];
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_copy_dcmf_version(uint64_t dcmf_ver_1_0,
+ uint64_t dcmf_ver_3_2)
+{
+ rsu_dcmf_ver[0] = dcmf_ver_1_0;
+ rsu_dcmf_ver[1] = dcmf_ver_1_0 >> 32;
+ rsu_dcmf_ver[2] = dcmf_ver_3_2;
+ rsu_dcmf_ver[3] = dcmf_ver_3_2 >> 32;
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_copy_dcmf_status(uint64_t dcmf_stat)
+{
+ rsu_dcmf_stat[0] = 0xFFFF & (dcmf_stat >> (0 * 16));
+ rsu_dcmf_stat[1] = 0xFFFF & (dcmf_stat >> (1 * 16));
+ rsu_dcmf_stat[2] = 0xFFFF & (dcmf_stat >> (2 * 16));
+ rsu_dcmf_stat[3] = 0xFFFF & (dcmf_stat >> (3 * 16));
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+/* Intel HWMON services */
+static uint32_t intel_hwmon_readtemp(uint32_t chan, uint32_t *retval)
+{
+ if (chan > TEMP_CHANNEL_MAX) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (mailbox_hwmon_readtemp(chan, retval) < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_hwmon_readvolt(uint32_t chan, uint32_t *retval)
+{
+ if (chan > VOLT_CHANNEL_MAX) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (mailbox_hwmon_readvolt(chan, retval) < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+/* Mailbox services */
+static uint32_t intel_smc_fw_version(uint32_t *fw_version)
+{
+ int status;
+ unsigned int resp_len = CONFIG_STATUS_WORD_SIZE;
+ uint32_t resp_data[CONFIG_STATUS_WORD_SIZE] = {0U};
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CONFIG_STATUS, NULL, 0U,
+ CMD_CASUAL, resp_data, &resp_len);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ if (resp_len <= CONFIG_STATUS_FW_VER_OFFSET) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *fw_version = resp_data[CONFIG_STATUS_FW_VER_OFFSET] & CONFIG_STATUS_FW_VER_MASK;
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args,
+ unsigned int len, uint32_t urgent, uint64_t response,
+ unsigned int resp_len, int *mbox_status,
+ unsigned int *len_in_resp)
+{
+ *len_in_resp = 0;
+ *mbox_status = GENERIC_RESPONSE_ERROR;
+
+ if (!is_address_in_ddr_range((uint64_t)args, sizeof(uint32_t) * len)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ int status = mailbox_send_cmd(MBOX_JOB_ID, cmd, args, len, urgent,
+ (uint32_t *) response, &resp_len);
+
+ if (status < 0) {
+ *mbox_status = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ *mbox_status = 0;
+ *len_in_resp = resp_len;
+
+ flush_dcache_range(response, resp_len * MBOX_WORD_BYTE);
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static int intel_smc_get_usercode(uint32_t *user_code)
+{
+ int status;
+ unsigned int resp_len = sizeof(user_code) / MBOX_WORD_BYTE;
+
+ status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_GET_USERCODE, NULL,
+ 0U, CMD_CASUAL, user_code, &resp_len);
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_smc_service_completed(uint64_t addr, uint32_t size,
+ uint32_t mode, uint32_t *job_id,
+ uint32_t *ret_size, uint32_t *mbox_error)
+{
+ int status = 0;
+ uint32_t resp_len = size / MBOX_WORD_BYTE;
+
+ if (resp_len > MBOX_DATA_MAX_LEN) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_address_in_ddr_range(addr, size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (mode == SERVICE_COMPLETED_MODE_ASYNC) {
+ status = mailbox_read_response_async(job_id,
+ NULL, (uint32_t *) addr, &resp_len, 0);
+ } else {
+ status = mailbox_read_response(job_id,
+ (uint32_t *) addr, &resp_len);
+
+ if (status == MBOX_NO_RESPONSE) {
+ status = MBOX_BUSY;
+ }
+ }
+
+ if (status == MBOX_NO_RESPONSE) {
+ return INTEL_SIP_SMC_STATUS_NO_RESPONSE;
+ }
+
+ if (status == MBOX_BUSY) {
+ return INTEL_SIP_SMC_STATUS_BUSY;
+ }
+
+ *ret_size = resp_len * MBOX_WORD_BYTE;
+ flush_dcache_range(addr, *ret_size);
+
+ if (status != MBOX_RET_OK) {
+ *mbox_error = -status;
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+/* Miscellaneous HPS services */
+uint32_t intel_hps_set_bridges(uint64_t enable, uint64_t mask)
+{
+ int status = 0;
+
+ if ((enable & SOCFPGA_BRIDGE_ENABLE) != 0U) {
+ if ((enable & SOCFPGA_BRIDGE_HAS_MASK) != 0U) {
+ status = socfpga_bridges_enable((uint32_t)mask);
+ } else {
+ status = socfpga_bridges_enable(~0);
+ }
+ } else {
+ if ((enable & SOCFPGA_BRIDGE_HAS_MASK) != 0U) {
+ status = socfpga_bridges_disable((uint32_t)mask);
+ } else {
+ status = socfpga_bridges_disable(~0);
+ }
+ }
+
+ if (status < 0) {
+ return INTEL_SIP_SMC_STATUS_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
+/*
+ * This function is responsible for handling all SiP calls from the NS world
+ */
+
+uintptr_t sip_smc_handler_v1(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t retval = 0, completed_addr[3];
+ uint32_t retval2 = 0;
+ uint32_t mbox_error = 0;
+ uint64_t retval64, rsu_respbuf[9];
+ int status = INTEL_SIP_SMC_STATUS_OK;
+ int mbox_status;
+ unsigned int len_in_resp;
+ u_register_t x5, x6, x7;
+
+ switch (smc_fid) {
+ case SIP_SVC_UID:
+ /* Return UID to the caller */
+ SMC_UUID_RET(handle, intl_svc_uid);
+
+ case INTEL_SIP_SMC_FPGA_CONFIG_ISDONE:
+ status = intel_mailbox_fpga_config_isdone();
+ SMC_RET4(handle, status, 0, 0, 0);
+
+ case INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM:
+ SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK,
+ INTEL_SIP_SMC_FPGA_CONFIG_ADDR,
+ INTEL_SIP_SMC_FPGA_CONFIG_SIZE -
+ INTEL_SIP_SMC_FPGA_CONFIG_ADDR);
+
+ case INTEL_SIP_SMC_FPGA_CONFIG_START:
+ status = intel_fpga_config_start(x1);
+ SMC_RET4(handle, status, 0, 0, 0);
+
+ case INTEL_SIP_SMC_FPGA_CONFIG_WRITE:
+ status = intel_fpga_config_write(x1, x2);
+ SMC_RET4(handle, status, 0, 0, 0);
+
+ case INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE:
+ status = intel_fpga_config_completed_write(completed_addr,
+ &retval, &rcv_id);
+ switch (retval) {
+ case 1:
+ SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
+ completed_addr[0], 0, 0);
+
+ case 2:
+ SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
+ completed_addr[0],
+ completed_addr[1], 0);
+
+ case 3:
+ SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK,
+ completed_addr[0],
+ completed_addr[1],
+ completed_addr[2]);
+
+ case 0:
+ SMC_RET4(handle, status, 0, 0, 0);
+
+ default:
+ mailbox_clear_response();
+ SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR);
+ }
+
+ case INTEL_SIP_SMC_REG_READ:
+ status = intel_secure_reg_read(x1, &retval);
+ SMC_RET3(handle, status, retval, x1);
+
+ case INTEL_SIP_SMC_REG_WRITE:
+ status = intel_secure_reg_write(x1, (uint32_t)x2, &retval);
+ SMC_RET3(handle, status, retval, x1);
+
+ case INTEL_SIP_SMC_REG_UPDATE:
+ status = intel_secure_reg_update(x1, (uint32_t)x2,
+ (uint32_t)x3, &retval);
+ SMC_RET3(handle, status, retval, x1);
+
+ case INTEL_SIP_SMC_RSU_STATUS:
+ status = intel_rsu_status(rsu_respbuf,
+ ARRAY_SIZE(rsu_respbuf));
+ if (status) {
+ SMC_RET1(handle, status);
+ } else {
+ SMC_RET4(handle, rsu_respbuf[0], rsu_respbuf[1],
+ rsu_respbuf[2], rsu_respbuf[3]);
+ }
+
+ case INTEL_SIP_SMC_RSU_UPDATE:
+ status = intel_rsu_update(x1);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_RSU_NOTIFY:
+ status = intel_rsu_notify(x1);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_RSU_RETRY_COUNTER:
+ status = intel_rsu_retry_counter((uint32_t *)rsu_respbuf,
+ ARRAY_SIZE(rsu_respbuf), &retval);
+ if (status) {
+ SMC_RET1(handle, status);
+ } else {
+ SMC_RET2(handle, status, retval);
+ }
+
+ case INTEL_SIP_SMC_RSU_DCMF_VERSION:
+ SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK,
+ ((uint64_t)rsu_dcmf_ver[1] << 32) | rsu_dcmf_ver[0],
+ ((uint64_t)rsu_dcmf_ver[3] << 32) | rsu_dcmf_ver[2]);
+
+ case INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION:
+ status = intel_rsu_copy_dcmf_version(x1, x2);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_RSU_DCMF_STATUS:
+ SMC_RET2(handle, INTEL_SIP_SMC_STATUS_OK,
+ ((uint64_t)rsu_dcmf_stat[3] << 48) |
+ ((uint64_t)rsu_dcmf_stat[2] << 32) |
+ ((uint64_t)rsu_dcmf_stat[1] << 16) |
+ rsu_dcmf_stat[0]);
+
+ case INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS:
+ status = intel_rsu_copy_dcmf_status(x1);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_RSU_MAX_RETRY:
+ SMC_RET2(handle, INTEL_SIP_SMC_STATUS_OK, rsu_max_retry);
+
+ case INTEL_SIP_SMC_RSU_COPY_MAX_RETRY:
+ rsu_max_retry = x1;
+ SMC_RET1(handle, INTEL_SIP_SMC_STATUS_OK);
+
+ case INTEL_SIP_SMC_ECC_DBE:
+ status = intel_ecc_dbe_notification(x1);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_SERVICE_COMPLETED:
+ status = intel_smc_service_completed(x1, x2, x3, &rcv_id,
+ &len_in_resp, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x1, len_in_resp);
+
+ case INTEL_SIP_SMC_FIRMWARE_VERSION:
+ status = intel_smc_fw_version(&retval);
+ SMC_RET2(handle, status, retval);
+
+ case INTEL_SIP_SMC_MBOX_SEND_CMD:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_mbox_send_cmd(x1, (uint32_t *)x2, x3, x4, x5, x6,
+ &mbox_status, &len_in_resp);
+ SMC_RET3(handle, status, mbox_status, len_in_resp);
+
+ case INTEL_SIP_SMC_GET_USERCODE:
+ status = intel_smc_get_usercode(&retval);
+ SMC_RET2(handle, status, retval);
+
+ case INTEL_SIP_SMC_FCS_CRYPTION:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+
+ if (x1 == FCS_MODE_DECRYPT) {
+ status = intel_fcs_decryption(x2, x3, x4, x5, &send_id);
+ } else if (x1 == FCS_MODE_ENCRYPT) {
+ status = intel_fcs_encryption(x2, x3, x4, x5, &send_id);
+ } else {
+ status = INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ SMC_RET3(handle, status, x4, x5);
+
+ case INTEL_SIP_SMC_FCS_CRYPTION_EXT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
+
+ if (x3 == FCS_MODE_DECRYPT) {
+ status = intel_fcs_decryption_ext(x1, x2, x4, x5, x6,
+ (uint32_t *) &x7, &mbox_error);
+ } else if (x3 == FCS_MODE_ENCRYPT) {
+ status = intel_fcs_encryption_ext(x1, x2, x4, x5, x6,
+ (uint32_t *) &x7, &mbox_error);
+ } else {
+ status = INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ SMC_RET4(handle, status, mbox_error, x6, x7);
+
+ case INTEL_SIP_SMC_FCS_RANDOM_NUMBER:
+ status = intel_fcs_random_number_gen(x1, &retval64,
+ &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x1, retval64);
+
+ case INTEL_SIP_SMC_FCS_RANDOM_NUMBER_EXT:
+ status = intel_fcs_random_number_gen_ext(x1, x2, x3,
+ &send_id);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_FCS_SEND_CERTIFICATE:
+ status = intel_fcs_send_cert(x1, x2, &send_id);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_FCS_GET_PROVISION_DATA:
+ status = intel_fcs_get_provision_data(&send_id);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_FCS_CNTR_SET_PREAUTH:
+ status = intel_fcs_cntr_set_preauth(x1, x2, x3,
+ &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_HPS_SET_BRIDGES:
+ status = intel_hps_set_bridges(x1, x2);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_HWMON_READTEMP:
+ status = intel_hwmon_readtemp(x1, &retval);
+ SMC_RET2(handle, status, retval);
+
+ case INTEL_SIP_SMC_HWMON_READVOLT:
+ status = intel_hwmon_readvolt(x1, &retval);
+ SMC_RET2(handle, status, retval);
+
+ case INTEL_SIP_SMC_FCS_PSGSIGMA_TEARDOWN:
+ status = intel_fcs_sigma_teardown(x1, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_CHIP_ID:
+ status = intel_fcs_chip_id(&retval, &retval2, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, retval, retval2);
+
+ case INTEL_SIP_SMC_FCS_ATTESTATION_SUBKEY:
+ status = intel_fcs_attestation_subkey(x1, x2, x3,
+ (uint32_t *) &x4, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x3, x4);
+
+ case INTEL_SIP_SMC_FCS_ATTESTATION_MEASUREMENTS:
+ status = intel_fcs_get_measurement(x1, x2, x3,
+ (uint32_t *) &x4, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x3, x4);
+
+ case INTEL_SIP_SMC_FCS_GET_ATTESTATION_CERT:
+ status = intel_fcs_get_attestation_cert(x1, x2,
+ (uint32_t *) &x3, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x2, x3);
+
+ case INTEL_SIP_SMC_FCS_CREATE_CERT_ON_RELOAD:
+ status = intel_fcs_create_cert_on_reload(x1, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_OPEN_CS_SESSION:
+ status = intel_fcs_open_crypto_service_session(&retval, &mbox_error);
+ SMC_RET3(handle, status, mbox_error, retval);
+
+ case INTEL_SIP_SMC_FCS_CLOSE_CS_SESSION:
+ status = intel_fcs_close_crypto_service_session(x1, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_IMPORT_CS_KEY:
+ status = intel_fcs_import_crypto_service_key(x1, x2, &send_id);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_FCS_EXPORT_CS_KEY:
+ status = intel_fcs_export_crypto_service_key(x1, x2, x3,
+ (uint32_t *) &x4, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x3, x4);
+
+ case INTEL_SIP_SMC_FCS_REMOVE_CS_KEY:
+ status = intel_fcs_remove_crypto_service_key(x1, x2,
+ &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_GET_CS_KEY_INFO:
+ status = intel_fcs_get_crypto_service_key_info(x1, x2, x3,
+ (uint32_t *) &x4, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x3, x4);
+
+ case INTEL_SIP_SMC_FCS_GET_DIGEST_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_get_digest_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_GET_DIGEST_UPDATE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_get_digest_update_finalize(x1, x2, x3,
+ x4, x5, (uint32_t *) &x6, false,
+ &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_GET_DIGEST_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_get_digest_update_finalize(x1, x2, x3,
+ x4, x5, (uint32_t *) &x6, true,
+ &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_MAC_VERIFY_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_mac_verify_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_MAC_VERIFY_UPDATE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
+ status = intel_fcs_mac_verify_update_finalize(x1, x2, x3,
+ x4, x5, (uint32_t *) &x6, x7,
+ false, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_MAC_VERIFY_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
+ status = intel_fcs_mac_verify_update_finalize(x1, x2, x3,
+ x4, x5, (uint32_t *) &x6, x7,
+ true, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIGN_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_ecdsa_sha2_data_sign_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIGN_UPDATE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_ecdsa_sha2_data_sign_update_finalize(x1, x2,
+ x3, x4, x5, (uint32_t *) &x6, false,
+ &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIGN_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_ecdsa_sha2_data_sign_update_finalize(x1, x2,
+ x3, x4, x5, (uint32_t *) &x6, true,
+ &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_HASH_SIGN_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_ecdsa_hash_sign_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_HASH_SIGN_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_ecdsa_hash_sign_finalize(x1, x2, x3,
+ x4, x5, (uint32_t *) &x6, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_HASH_SIG_VERIFY_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_ecdsa_hash_sig_verify_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_HASH_SIG_VERIFY_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_ecdsa_hash_sig_verify_finalize(x1, x2, x3,
+ x4, x5, (uint32_t *) &x6, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_ecdsa_sha2_data_sig_verify_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_UPDATE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
+ status = intel_fcs_ecdsa_sha2_data_sig_verify_update_finalize(
+ x1, x2, x3, x4, x5, (uint32_t *) &x6,
+ x7, false, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ x7 = SMC_GET_GP(handle, CTX_GPREG_X7);
+ status = intel_fcs_ecdsa_sha2_data_sig_verify_update_finalize(
+ x1, x2, x3, x4, x5, (uint32_t *) &x6,
+ x7, true, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_GET_PUBKEY_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_ecdsa_get_pubkey_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_ECDSA_GET_PUBKEY_FINALIZE:
+ status = intel_fcs_ecdsa_get_pubkey_finalize(x1, x2, x3,
+ (uint32_t *) &x4, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x3, x4);
+
+ case INTEL_SIP_SMC_FCS_ECDH_REQUEST_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_ecdh_request_init(x1, x2, x3,
+ x4, x5, &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_ECDH_REQUEST_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_ecdh_request_finalize(x1, x2, x3,
+ x4, x5, (uint32_t *) &x6, &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x5, x6);
+
+ case INTEL_SIP_SMC_FCS_AES_CRYPT_INIT:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ status = intel_fcs_aes_crypt_init(x1, x2, x3, x4, x5,
+ &mbox_error);
+ SMC_RET2(handle, status, mbox_error);
+
+ case INTEL_SIP_SMC_FCS_AES_CRYPT_UPDATE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_aes_crypt_update_finalize(x1, x2, x3, x4,
+ x5, x6, false, &send_id);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_FCS_AES_CRYPT_FINALIZE:
+ x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+ x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+ status = intel_fcs_aes_crypt_update_finalize(x1, x2, x3, x4,
+ x5, x6, true, &send_id);
+ SMC_RET1(handle, status);
+
+ case INTEL_SIP_SMC_GET_ROM_PATCH_SHA384:
+ status = intel_fcs_get_rom_patch_sha384(x1, &retval64,
+ &mbox_error);
+ SMC_RET4(handle, status, mbox_error, x1, retval64);
+
+ case INTEL_SIP_SMC_SVC_VERSION:
+ SMC_RET3(handle, INTEL_SIP_SMC_STATUS_OK,
+ SIP_SVC_VERSION_MAJOR,
+ SIP_SVC_VERSION_MINOR);
+
+ default:
+ return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ }
+}
+
+uintptr_t sip_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t cmd = smc_fid & INTEL_SIP_SMC_CMD_MASK;
+
+ if (cmd >= INTEL_SIP_SMC_CMD_V2_RANGE_BEGIN &&
+ cmd <= INTEL_SIP_SMC_CMD_V2_RANGE_END) {
+ return sip_smc_handler_v2(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ } else {
+ return sip_smc_handler_v1(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ }
+}
+
+DECLARE_RT_SVC(
+ socfpga_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ sip_smc_handler
+);
+
+DECLARE_RT_SVC(
+ socfpga_sip_svc_std,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_YIELD,
+ NULL,
+ sip_smc_handler
+);
diff --git a/plat/intel/soc/common/socfpga_sip_svc_v2.c b/plat/intel/soc/common/socfpga_sip_svc_v2.c
new file mode 100644
index 0000000..791c714
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_sip_svc_v2.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include "socfpga_mailbox.h"
+#include "socfpga_sip_svc.h"
+
+static uint32_t intel_v2_mbox_send_cmd(uint32_t req_header,
+ uint32_t *data, uint32_t data_size)
+{
+ uint32_t value;
+ uint32_t len;
+
+ if ((data == NULL) || (data_size == 0)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (data_size > (MBOX_INC_HEADER_MAX_WORD_SIZE * MBOX_WORD_BYTE)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(data_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ /* Make sure client id align in SMC SiP V2 header and mailbox header */
+ value = (req_header >> INTEL_SIP_SMC_HEADER_CID_OFFSET) &
+ INTEL_SIP_SMC_HEADER_CID_MASK;
+
+ if (value != MBOX_RESP_CLIENT_ID(data[0])) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ /* Make sure job id align in SMC SiP V2 header and mailbox header */
+ value = (req_header >> INTEL_SIP_SMC_HEADER_JOB_ID_OFFSET) &
+ INTEL_SIP_SMC_HEADER_JOB_ID_MASK;
+
+ if (value != MBOX_RESP_JOB_ID(data[0])) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ /*
+ * Make sure data length align in SMC SiP V2 header and
+ * mailbox header
+ */
+ len = (data_size / MBOX_WORD_BYTE) - 1;
+
+ if (len != MBOX_RESP_LEN(data[0])) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ return mailbox_send_cmd_async_ext(data[0], &data[1], len);
+}
+
+static uint32_t intel_v2_mbox_poll_resp(uint64_t req_header,
+ uint32_t *data, uint32_t *data_size,
+ uint64_t *resp_header)
+{
+ int status = 0;
+ uint32_t resp_len;
+ uint32_t job_id = 0;
+ uint32_t client_id = 0;
+ uint32_t version;
+
+ if ((data == NULL) || (data_size == NULL) || (resp_header == NULL)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ if (!is_size_4_bytes_aligned(*data_size)) {
+ return INTEL_SIP_SMC_STATUS_REJECTED;
+ }
+
+ resp_len = (*data_size / MBOX_WORD_BYTE) - 1;
+ status = mailbox_read_response_async(&job_id, &data[0], &data[1],
+ &resp_len, 1);
+
+ if (status == MBOX_BUSY) {
+ status = INTEL_SIP_SMC_STATUS_BUSY;
+ } else if (status == MBOX_NO_RESPONSE) {
+ status = INTEL_SIP_SMC_STATUS_NO_RESPONSE;
+ } else {
+ *data_size = 0;
+
+ if (resp_len > 0) {
+ /*
+ * Fill in the final response length,
+ * the length include both mailbox header and payload
+ */
+ *data_size = (resp_len + 1) * MBOX_WORD_BYTE;
+
+ /* Extract the client id from mailbox header */
+ client_id = MBOX_RESP_CLIENT_ID(data[0]);
+ }
+
+ /*
+ * Extract SMC SiP V2 protocol version from
+ * SMC request header
+ */
+ version = (req_header >> INTEL_SIP_SMC_HEADER_VERSION_OFFSET) &
+ INTEL_SIP_SMC_HEADER_VERSION_MASK;
+
+ /* Fill in SMC SiP V2 protocol response header */
+ *resp_header = 0;
+ *resp_header |= (((uint64_t)job_id) &
+ INTEL_SIP_SMC_HEADER_JOB_ID_MASK) <<
+ INTEL_SIP_SMC_HEADER_JOB_ID_OFFSET;
+ *resp_header |= (((uint64_t)client_id) &
+ INTEL_SIP_SMC_HEADER_CID_MASK) <<
+ INTEL_SIP_SMC_HEADER_CID_OFFSET;
+ *resp_header |= (((uint64_t)version) &
+ INTEL_SIP_SMC_HEADER_VERSION_MASK) <<
+ INTEL_SIP_SMC_HEADER_VERSION_OFFSET;
+ }
+
+ return status;
+}
+
+uintptr_t sip_smc_handler_v2(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t retval = 0;
+ uint64_t retval64 = 0;
+ int status = INTEL_SIP_SMC_STATUS_OK;
+
+ switch (smc_fid) {
+ case INTEL_SIP_SMC_V2_GET_SVC_VERSION:
+ SMC_RET4(handle, INTEL_SIP_SMC_STATUS_OK, x1,
+ SIP_SVC_VERSION_MAJOR,
+ SIP_SVC_VERSION_MINOR);
+
+ case INTEL_SIP_SMC_V2_REG_READ:
+ status = intel_secure_reg_read(x2, &retval);
+ SMC_RET4(handle, status, x1, retval, x2);
+
+ case INTEL_SIP_SMC_V2_REG_WRITE:
+ status = intel_secure_reg_write(x2, (uint32_t)x3, &retval);
+ SMC_RET4(handle, status, x1, retval, x2);
+
+ case INTEL_SIP_SMC_V2_REG_UPDATE:
+ status = intel_secure_reg_update(x2, (uint32_t)x3,
+ (uint32_t)x4, &retval);
+ SMC_RET4(handle, status, x1, retval, x2);
+
+ case INTEL_SIP_SMC_V2_HPS_SET_BRIDGES:
+ status = intel_hps_set_bridges(x2, x3);
+ SMC_RET2(handle, status, x1);
+
+ case INTEL_SIP_SMC_V2_MAILBOX_SEND_COMMAND:
+ status = intel_v2_mbox_send_cmd(x1, (uint32_t *)x2, x3);
+ SMC_RET2(handle, status, x1);
+
+ case INTEL_SIP_SMC_V2_MAILBOX_POLL_RESPONSE:
+ status = intel_v2_mbox_poll_resp(x1, (uint32_t *)x2,
+ (uint32_t *) &x3, &retval64);
+ SMC_RET4(handle, status, retval64, x2, x3);
+
+ default:
+ ERROR("%s: unhandled SMC V2 (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/intel/soc/common/socfpga_storage.c b/plat/intel/soc/common/socfpga_storage.c
new file mode 100644
index 0000000..a2f2c18
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_storage.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <lib/mmio.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "socfpga_private.h"
+
+#define PLAT_FIP_BASE (0)
+#define PLAT_FIP_MAX_SIZE (0x1000000)
+#define PLAT_MMC_DATA_BASE (0xffe3c000)
+#define PLAT_MMC_DATA_SIZE (0x2000)
+#define PLAT_QSPI_DATA_BASE (0x3C00000)
+#define PLAT_QSPI_DATA_SIZE (0x1000000)
+
+
+static const io_dev_connector_t *fip_dev_con;
+static const io_dev_connector_t *boot_dev_con;
+
+static uintptr_t fip_dev_handle;
+static uintptr_t boot_dev_handle;
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+uintptr_t a2_lba_offset;
+const char a2[] = {0xa2, 0x0};
+
+static const io_block_spec_t gpt_block_spec = {
+ .offset = 0,
+ .length = MMC_BLOCK_SIZE
+};
+
+static int check_fip(const uintptr_t spec);
+static int check_dev(const uintptr_t spec);
+
+static io_block_dev_spec_t boot_dev_spec;
+static int (*register_io_dev)(const io_dev_connector_t **);
+
+static io_block_spec_t fip_spec = {
+ .offset = PLAT_FIP_BASE,
+ .length = PLAT_FIP_MAX_SIZE,
+};
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &boot_dev_handle,
+ (uintptr_t)&fip_spec,
+ check_dev
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ check_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ check_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t) &bl33_uuid_spec,
+ check_fip
+ },
+ [GPT_IMAGE_ID] = {
+ &boot_dev_handle,
+ (uintptr_t) &gpt_block_spec,
+ check_dev
+ },
+};
+
+static int check_dev(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_handle;
+
+ result = io_dev_init(boot_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(boot_dev_handle, spec, &local_handle);
+ if (result == 0)
+ io_close(local_handle);
+ }
+ return result;
+}
+
+static int check_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0)
+ io_close(local_image_handle);
+ }
+ return result;
+}
+
+void socfpga_io_setup(int boot_source)
+{
+ int result;
+
+ switch (boot_source) {
+ case BOOT_SOURCE_SDMMC:
+ register_io_dev = &register_io_dev_block;
+ boot_dev_spec.buffer.offset = PLAT_MMC_DATA_BASE;
+ boot_dev_spec.buffer.length = MMC_BLOCK_SIZE;
+ boot_dev_spec.ops.read = mmc_read_blocks;
+ boot_dev_spec.ops.write = mmc_write_blocks;
+ boot_dev_spec.block_size = MMC_BLOCK_SIZE;
+ break;
+
+ case BOOT_SOURCE_QSPI:
+ register_io_dev = &register_io_dev_memmap;
+ fip_spec.offset = fip_spec.offset + PLAT_QSPI_DATA_BASE;
+ break;
+
+ default:
+ ERROR("Unsupported boot source\n");
+ panic();
+ break;
+ }
+
+ result = (*register_io_dev)(&boot_dev_con);
+ assert(result == 0);
+
+ result = register_io_dev_fip(&fip_dev_con);
+ assert(result == 0);
+
+ result = io_dev_open(boot_dev_con, (uintptr_t)&boot_dev_spec,
+ &boot_dev_handle);
+ assert(result == 0);
+
+ result = io_dev_open(fip_dev_con, (uintptr_t)NULL, &fip_dev_handle);
+ assert(result == 0);
+
+ if (boot_source == BOOT_SOURCE_SDMMC) {
+ partition_init(GPT_IMAGE_ID);
+ fip_spec.offset = get_partition_entry(a2)->start;
+ }
+
+ (void)result;
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ assert(result == 0);
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ return result;
+}
diff --git a/plat/intel/soc/common/socfpga_topology.c b/plat/intel/soc/common/socfpga_topology.c
new file mode 100644
index 0000000..ca1a91e
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_topology.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <lib/psci/psci.h>
+
+static const unsigned char plat_power_domain_tree_desc[] = {1, 4};
+
+/*******************************************************************************
+ * This function returns the default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return plat_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
+}
+
diff --git a/plat/intel/soc/n5x/bl31_plat_setup.c b/plat/intel/soc/n5x/bl31_plat_setup.c
new file mode 100644
index 0000000..5ca1a71
--- /dev/null
+++ b/plat/intel/soc/n5x/bl31_plat_setup.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include "ccu/ncore_ccu.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_private.h"
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ?
+ &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ mmio_write_64(PLAT_SEC_ENTRY, 0);
+
+ console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK,
+ PLAT_BAUDRATE, &console);
+ /*
+ * Check params passed from BL31 should not be NULL,
+ */
+ void *from_bl2 = (void *) arg0;
+
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+ assert(params_from_bl2 != NULL);
+
+ /*
+ * Copy BL32 (if populated by BL31) and BL33 entry point information.
+ * They are stored in Secure RAM, in BL31's address space.
+ */
+
+ if (params_from_bl2->h.type == PARAM_BL_PARAMS &&
+ params_from_bl2->h.version >= VERSION_2) {
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ while (bl_params != NULL) {
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+ } else {
+ struct socfpga_bl31_params *arg_from_bl2 =
+ (struct socfpga_bl31_params *) from_bl2;
+
+ assert(arg_from_bl2->h.type == PARAM_BL31);
+ assert(arg_from_bl2->h.version >= VERSION_1);
+
+ bl32_image_ep_info = *arg_from_bl2->bl32_ep_info;
+ bl33_image_ep_info = *arg_from_bl2->bl33_ep_info;
+ }
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+static const interrupt_prop_t s10_interrupt_props[] = {
+ PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t plat_gicv2_gic_data = {
+ .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE,
+ .gicc_base = PLAT_INTEL_SOCFPGA_GICC_BASE,
+ .interrupt_props = s10_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(s10_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ socfpga_delay_timer_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ gicv2_driver_init(&plat_gicv2_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
+ mmio_write_64(PLAT_CPU_RELEASE_ADDR,
+ (uint64_t)plat_secondary_cpus_bl31_entry);
+
+ mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
+
+ ncore_enable_ocram_firewall();
+}
+
+const mmap_region_t plat_dm_mmap[] = {
+ MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE,
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ {0}
+};
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_dm_mmap);
+ enable_mmu_el3(0);
+}
diff --git a/plat/intel/soc/n5x/include/socfpga_plat_def.h b/plat/intel/soc/n5x/include/socfpga_plat_def.h
new file mode 100644
index 0000000..4c36f91
--- /dev/null
+++ b/plat/intel/soc/n5x/include/socfpga_plat_def.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SOCFPGA_DEF_H
+#define PLAT_SOCFPGA_DEF_H
+
+#include <platform_def.h>
+
+/* Platform Setting */
+#define PLATFORM_MODEL PLAT_SOCFPGA_N5X
+#define BOOT_SOURCE BOOT_SOURCE_SDMMC
+
+/* FPGA config helpers */
+#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000
+#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 0x2000000
+
+/* Register Mapping */
+#define SOCFPGA_CCU_NOC_REG_BASE U(0xf7000000)
+#define SOCFPGA_F2SDRAMMGR_REG_BASE U(0xf8024000)
+
+#define SOCFPGA_MMC_REG_BASE U(0xff808000)
+
+#define SOCFPGA_RSTMGR_REG_BASE U(0xffd11000)
+#define SOCFPGA_SYSMGR_REG_BASE U(0xffd12000)
+
+#define SOCFPGA_L4_PER_SCR_REG_BASE U(0xffd21000)
+#define SOCFPGA_L4_SYS_SCR_REG_BASE U(0xffd21100)
+#define SOCFPGA_SOC2FPGA_SCR_REG_BASE U(0xffd21200)
+#define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE U(0xffd21300)
+
+/* Platform specific system counter */
+/*
+ * In N5X the clk init is done in Uboot SPL.
+ * BL31 shall bypass the clk init and only provides other APIs.
+ */
+#define PLAT_SYS_COUNTER_FREQ_IN_MHZ (400)
+
+#endif /* PLAT_SOCFPGA_DEF_H */
diff --git a/plat/intel/soc/n5x/platform.mk b/plat/intel/soc/n5x/platform.mk
new file mode 100644
index 0000000..be1ad8c
--- /dev/null
+++ b/plat/intel/soc/n5x/platform.mk
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := \
+ -Iplat/intel/soc/n5x/include/ \
+ -Iplat/intel/soc/common/drivers/ \
+ -Iplat/intel/soc/common/include/
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+DM_GICv2_SOURCES := \
+ ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c
+
+
+PLAT_BL_COMMON_SOURCES := \
+ ${DM_GICv2_SOURCES} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ plat/intel/soc/common/aarch64/platform_common.c \
+ plat/intel/soc/common/aarch64/plat_helpers.S \
+ plat/intel/soc/common/socfpga_delay_timer.c \
+ plat/intel/soc/common/drivers/ccu/ncore_ccu.c
+
+BL2_SOURCES +=
+
+BL31_SOURCES += \
+ drivers/arm/cci/cci.c \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/intel/soc/n5x/bl31_plat_setup.c \
+ plat/intel/soc/common/socfpga_psci.c \
+ plat/intel/soc/common/socfpga_sip_svc.c \
+ plat/intel/soc/common/socfpga_sip_svc_v2.c \
+ plat/intel/soc/common/socfpga_topology.c \
+ plat/intel/soc/common/sip/socfpga_sip_ecc.c \
+ plat/intel/soc/common/sip/socfpga_sip_fcs.c \
+ plat/intel/soc/common/soc/socfpga_mailbox.c \
+ plat/intel/soc/common/soc/socfpga_reset_manager.c
+
+PROGRAMMABLE_RESET_ADDRESS := 0
+BL2_AT_EL3 := 1
+BL2_INV_DCACHE := 0
+MULTI_CONSOLE_API := 1
+USE_COHERENT_MEM := 1
diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c
new file mode 100644
index 0000000..73e3216
--- /dev/null
+++ b/plat/intel/soc/stratix10/bl2_plat_setup.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/synopsys/dw_mmc.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include "qspi/cadence_qspi.h"
+#include "socfpga_emac.h"
+#include "socfpga_f2sdram_manager.h"
+#include "socfpga_handoff.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_private.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_system_manager.h"
+#include "s10_clock_manager.h"
+#include "s10_memory_controller.h"
+#include "s10_mmc.h"
+#include "s10_pinmux.h"
+#include "wdt/watchdog.h"
+
+static struct mmc_device_info mmc_info;
+
+const mmap_region_t plat_stratix10_mmap[] = {
+ MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE,
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ {0},
+};
+
+boot_source_type boot_source = BOOT_SOURCE;
+
+void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
+ u_register_t x2, u_register_t x4)
+{
+ static console_t console;
+ handoff reverse_handoff_ptr;
+
+ generic_delay_timer_init();
+
+ if (socfpga_get_handoff(&reverse_handoff_ptr))
+ return;
+ config_pinmux(&reverse_handoff_ptr);
+
+ config_clkmgr_handoff(&reverse_handoff_ptr);
+ enable_nonsecure_access();
+ deassert_peripheral_reset();
+ config_hps_hs_before_warm_reset();
+
+ watchdog_init(get_wdt_clk());
+
+ console_16550_register(PLAT_INTEL_UART_BASE, get_uart_clk(),
+ PLAT_BAUDRATE, &console);
+
+ socfpga_emac_init();
+ socfpga_delay_timer_init();
+ init_hard_memory_controller();
+ mailbox_init();
+ s10_mmc_init();
+
+ if (!intel_mailbox_is_fpga_not_ready()) {
+ socfpga_bridges_enable(SOC2FPGA_MASK | LWHPS2FPGA_MASK |
+ FPGA2SOC_MASK | F2SDRAM0_MASK | F2SDRAM1_MASK |
+ F2SDRAM2_MASK);
+ }
+}
+
+
+void bl2_el3_plat_arch_setup(void)
+{
+
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL2_BASE, BL2_END - BL2_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM_BAR
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ {0},
+ };
+
+ setup_page_tables(bl_regions, plat_stratix10_mmap);
+
+ enable_mmu_el3(0);
+
+ dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000, get_mmc_clk());
+
+ mmc_info.mmc_dev_type = MMC_IS_SD;
+ mmc_info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
+
+ /* Request ownership and direct access to QSPI */
+ mailbox_hps_qspi_enable();
+
+ switch (boot_source) {
+ case BOOT_SOURCE_SDMMC:
+ dw_mmc_init(&params, &mmc_info);
+ socfpga_io_setup(boot_source);
+ break;
+
+ case BOOT_SOURCE_QSPI:
+ cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
+ QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
+ QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
+ socfpga_io_setup(boot_source);
+ break;
+
+ default:
+ ERROR("Unsupported boot source\n");
+ panic();
+ break;
+ }
+}
+
+uint32_t get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL33_IMAGE_ID:
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = get_spsr_for_bl33_entry();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl2_platform_setup(void)
+{
+}
+
diff --git a/plat/intel/soc/stratix10/bl31_plat_setup.c b/plat/intel/soc/stratix10/bl31_plat_setup.c
new file mode 100644
index 0000000..be0fae5
--- /dev/null
+++ b/plat/intel/soc/stratix10/bl31_plat_setup.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "socfpga_mailbox.h"
+#include "socfpga_noc.h"
+#include "socfpga_private.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_system_manager.h"
+#include "s10_memory_controller.h"
+#include "s10_pinmux.h"
+#include "s10_clock_manager.h"
+
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ?
+ &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY);
+
+ console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK,
+ PLAT_BAUDRATE, &console);
+ /*
+ * Check params passed from BL31 should not be NULL,
+ */
+ void *from_bl2 = (void *) arg0;
+
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+ assert(params_from_bl2 != NULL);
+
+ /*
+ * Copy BL32 (if populated by BL31) and BL33 entry point information.
+ * They are stored in Secure RAM, in BL31's address space.
+ */
+
+ if (params_from_bl2->h.type == PARAM_BL_PARAMS &&
+ params_from_bl2->h.version >= VERSION_2) {
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ while (bl_params) {
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+ } else {
+ struct socfpga_bl31_params *arg_from_bl2 =
+ (struct socfpga_bl31_params *) from_bl2;
+
+ assert(arg_from_bl2->h.type == PARAM_BL31);
+ assert(arg_from_bl2->h.version >= VERSION_1);
+
+ bl32_image_ep_info = *arg_from_bl2->bl32_ep_info;
+ bl33_image_ep_info = *arg_from_bl2->bl33_ep_info;
+ }
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+static const interrupt_prop_t s10_interrupt_props[] = {
+ PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t plat_gicv2_gic_data = {
+ .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE,
+ .gicc_base = PLAT_INTEL_SOCFPGA_GICC_BASE,
+ .interrupt_props = s10_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(s10_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ socfpga_delay_timer_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ gicv2_driver_init(&plat_gicv2_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
+ mmio_write_64(PLAT_CPU_RELEASE_ADDR,
+ (uint64_t)plat_secondary_cpus_bl31_entry);
+
+ mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
+
+ enable_ocram_firewall();
+}
+
+const mmap_region_t plat_stratix10_mmap[] = {
+ MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE,
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ {0}
+};
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_stratix10_mmap);
+ enable_mmu_el3(0);
+}
+
diff --git a/plat/intel/soc/stratix10/include/s10_clock_manager.h b/plat/intel/soc/stratix10/include/s10_clock_manager.h
new file mode 100644
index 0000000..cf57df3
--- /dev/null
+++ b/plat/intel/soc/stratix10/include/s10_clock_manager.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CLOCKMANAGER_H__
+#define __CLOCKMANAGER_H__
+
+#include "socfpga_handoff.h"
+
+#define ALT_CLKMGR 0xffd10000
+
+#define ALT_CLKMGR_CTRL 0x0
+#define ALT_CLKMGR_STAT 0x4
+#define ALT_CLKMGR_INTRCLR 0x14
+#define ALT_CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK 0x00000004
+#define ALT_CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK 0x00000008
+
+#define ALT_CLKMGR_CTRL_BOOTMODE_SET_MSK 0x00000001
+#define ALT_CLKMGR_STAT_BUSY_E_BUSY 0x1
+#define ALT_CLKMGR_STAT_BUSY(x) (((x) & 0x00000001) >> 0)
+#define ALT_CLKMGR_STAT_MAINPLLLOCKED(x) (((x) & 0x00000100) >> 8)
+#define ALT_CLKMGR_STAT_PERPLLLOCKED(x) (((x) & 0x00000200) >> 9)
+
+#define ALT_CLKMGR_MAINPLL 0xffd10030
+#define ALT_CLKMGR_MAINPLL_EN 0x0
+#define ALT_CLKMGR_MAINPLL_BYPASS 0xc
+#define ALT_CLKMGR_MAINPLL_MPUCLK 0x18
+#define ALT_CLKMGR_MAINPLL_NOCCLK 0x1c
+#define ALT_CLKMGR_MAINPLL_CNTR2CLK 0x20
+#define ALT_CLKMGR_MAINPLL_CNTR3CLK 0x24
+#define ALT_CLKMGR_MAINPLL_CNTR4CLK 0x28
+#define ALT_CLKMGR_MAINPLL_CNTR5CLK 0x2c
+#define ALT_CLKMGR_MAINPLL_CNTR6CLK 0x30
+#define ALT_CLKMGR_MAINPLL_CNTR7CLK 0x34
+#define ALT_CLKMGR_MAINPLL_CNTR8CLK 0x38
+#define ALT_CLKMGR_MAINPLL_CNTR9CLK 0x3c
+#define ALT_CLKMGR_MAINPLL_NOCDIV 0x40
+#define ALT_CLKMGR_MAINPLL_PLLGLOB 0x44
+#define ALT_CLKMGR_MAINPLL_FDBCK 0x48
+#define ALT_CLKMGR_MAINPLL_PLLC0 0x54
+#define ALT_CLKMGR_MAINPLL_PLLC1 0x58
+#define ALT_CLKMGR_MAINPLL_VCOCALIB 0x5c
+#define ALT_CLKMGR_MAINPLL_EN_RESET 0x000000ff
+#define ALT_CLKMGR_MAINPLL_FDBCK_MDIV(x) (((x) & 0xff000000) >> 24)
+#define ALT_CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK 0x00000001
+#define ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8)
+#define ALT_CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK 0x00000002
+#define ALT_CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000000ff)
+#define ALT_CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(x) (((x) << 9) & 0x0001fe00)
+
+#define ALT_CLKMGR_PSRC(x) (((x) & 0x00030000) >> 16)
+#define ALT_CLKMGR_SRC_MAIN 0
+#define ALT_CLKMGR_SRC_PER 1
+
+#define ALT_CLKMGR_PLLGLOB_PSRC_EOSC1 0x0
+#define ALT_CLKMGR_PLLGLOB_PSRC_INTOSC 0x1
+#define ALT_CLKMGR_PLLGLOB_PSRC_F2S 0x2
+
+#define ALT_CLKMGR_PERPLL 0xffd100a4
+#define ALT_CLKMGR_PERPLL_EN 0x0
+#define ALT_CLKMGR_PERPLL_EN_SDMMCCLK BIT(5)
+#define ALT_CLKMGR_PERPLL_BYPASS 0xc
+#define ALT_CLKMGR_PERPLL_CNTR2CLK 0x18
+#define ALT_CLKMGR_PERPLL_CNTR3CLK 0x1c
+#define ALT_CLKMGR_PERPLL_CNTR4CLK 0x20
+#define ALT_CLKMGR_PERPLL_CNTR5CLK 0x24
+#define ALT_CLKMGR_PERPLL_CNTR6CLK 0x28
+#define ALT_CLKMGR_PERPLL_CNTR7CLK 0x2c
+#define ALT_CLKMGR_PERPLL_CNTR8CLK 0x30
+#define ALT_CLKMGR_PERPLL_CNTR9CLK 0x34
+#define ALT_CLKMGR_PERPLL_GPIODIV 0x3c
+#define ALT_CLKMGR_PERPLL_EMACCTL 0x38
+#define ALT_CLKMGR_PERPLL_PLLGLOB 0x40
+#define ALT_CLKMGR_PERPLL_FDBCK 0x44
+#define ALT_CLKMGR_PERPLL_PLLC0 0x50
+#define ALT_CLKMGR_PERPLL_PLLC1 0x54
+#define ALT_CLKMGR_PERPLL_EN_RESET 0x00000fff
+#define ALT_CLKMGR_PERPLL_FDBCK_MDIV(x) (((x) & 0xff000000) >> 24)
+#define ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x) (((x) << 0) & 0x0000ffff)
+#define ALT_CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK 0x00000001
+#define ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003f00) >> 8)
+#define ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV_SET(x) (((x) << 8) & 0x00003f00)
+#define ALT_CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK 0x00000002
+#define ALT_CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000000ff)
+#define ALT_CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(x) (((x) << 9) & 0x0001fe00)
+#define ALT_CLKMGR_PERPLL_VCOCALIB 0x58
+
+#define ALT_CLKMGR_INTOSC_HZ 460000000
+
+void config_clkmgr_handoff(handoff *hoff_ptr);
+uint32_t get_wdt_clk(void);
+uint32_t get_uart_clk(void);
+uint32_t get_mmc_clk(void);
+uint32_t get_l3_clk(uint32_t ref_clk);
+uint32_t get_ref_clk(uint32_t pllglob);
+
+#endif
diff --git a/plat/intel/soc/stratix10/include/s10_memory_controller.h b/plat/intel/soc/stratix10/include/s10_memory_controller.h
new file mode 100644
index 0000000..155b279
--- /dev/null
+++ b/plat/intel/soc/stratix10/include/s10_memory_controller.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __S10_MEMORYCONTROLLER_H__
+#define __S10_MEMORYCONTROLLER_H__
+
+#define S10_MPFE_IOHMC_REG_DRAMADDRW 0xf80100a8
+#define S10_MPFE_IOHMC_CTRLCFG0 0xf8010028
+#define S10_MPFE_IOHMC_CTRLCFG1 0xf801002c
+#define S10_MPFE_IOHMC_DRAMADDRW 0xf80100a8
+#define S10_MPFE_IOHMC_DRAMTIMING0 0xf8010050
+#define S10_MPFE_IOHMC_CALTIMING0 0xf801007c
+#define S10_MPFE_IOHMC_CALTIMING1 0xf8010080
+#define S10_MPFE_IOHMC_CALTIMING2 0xf8010084
+#define S10_MPFE_IOHMC_CALTIMING3 0xf8010088
+#define S10_MPFE_IOHMC_CALTIMING4 0xf801008c
+#define S10_MPFE_IOHMC_CALTIMING9 0xf80100a0
+#define S10_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(x) (((x) & 0x000000ff) >> 0)
+#define S10_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(value) \
+ (((value) & 0x00000060) >> 5)
+
+
+#define S10_MPFE_HMC_ADP_ECCCTRL1 0xf8011100
+#define S10_MPFE_HMC_ADP_ECCCTRL2 0xf8011104
+#define S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT 0xf8011218
+#define S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE 0x000000ff
+#define S10_MPFE_HMC_ADP_RSTHANDSHAKECTRL 0xf8011214
+
+
+#define S10_MPFE_IOHMC_REG_CTRLCFG1 0xf801002c
+
+#define S10_MPFE_IOHMC_REG_NIOSRESERVE0_OFST 0xf8010110
+
+#define IOHMC_DRAMADDRW_COL_ADDR_WIDTH(x) (((x) & 0x0000001f) >> 0)
+#define IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(x) (((x) & 0x000003e0) >> 5)
+#define IOHMC_DRAMADDRW_CS_ADDR_WIDTH(x) (((x) & 0x00070000) >> 16)
+#define IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(x) (((x) & 0x0000c000) >> 14)
+#define IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(x) (((x) & 0x00003c00) >> 10)
+
+#define S10_MPFE_DDR(x) (0xf8000000 + x)
+#define S10_MPFE_HMC_ADP_DDRCALSTAT 0xf801100c
+#define S10_MPFE_DDR_MAIN_SCHED 0xf8000400
+#define S10_MPFE_DDR_MAIN_SCHED_DDRCONF 0xf8000408
+#define S10_MPFE_DDR_MAIN_SCHED_DDRTIMING 0xf800040c
+#define S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK 0x0000001f
+#define S10_MPFE_DDR_MAIN_SCHED_DDRMODE 0xf8000410
+#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV 0xf800043c
+#define S10_MPFE_DDR_MAIN_SCHED_READLATENCY 0xf8000414
+#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE 0xf8000438
+#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST 10
+#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST 4
+#define S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST 0
+#define S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(x) (((x) << 0) & 0x0000001f)
+#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST 0
+#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK (BIT(0) | BIT(1))
+#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST 2
+#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK (BIT(2) | BIT(3))
+#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST 4
+#define S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK (BIT(4) | BIT(5))
+
+#define S10_MPFE_HMC_ADP(x) (0xf8011000 + (x))
+#define S10_MPFE_HMC_ADP_HPSINTFCSEL 0xf8011210
+#define S10_MPFE_HMC_ADP_DDRIOCTRL 0xf8011008
+#define HMC_ADP_DDRIOCTRL 0x8
+#define HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0)
+#define HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(x) (((x) & 0x00003e00) >> 9)
+#define ADP_DRAMADDRWIDTH 0xe0
+
+#define ACT_TO_ACT_DIFF_BANK(value) (((value) & 0x00fc0000) >> 18)
+#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12)
+#define ACT_TO_RDWR(value) (((value) & 0x0000003f) >> 0)
+#define ACT_TO_ACT(value) (((value) & 0x0003f000) >> 12)
+
+/* timing 2 */
+#define RD_TO_RD_DIFF_CHIP(value) (((value) & 0x00000fc0) >> 6)
+#define RD_TO_WR_DIFF_CHIP(value) (((value) & 0x3f000000) >> 24)
+#define RD_TO_WR(value) (((value) & 0x00fc0000) >> 18)
+#define RD_TO_PCH(value) (((value) & 0x00000fc0) >> 6)
+
+/* timing 3 */
+#define CALTIMING3_WR_TO_RD_DIFF_CHIP(value) (((value) & 0x0003f000) >> 12)
+#define CALTIMING3_WR_TO_RD(value) (((value) & 0x00000fc0) >> 6)
+
+/* timing 4 */
+#define PCH_TO_VALID(value) (((value) & 0x00000fc0) >> 6)
+
+#define DDRTIMING_BWRATIO_OFST 31
+#define DDRTIMING_WRTORD_OFST 26
+#define DDRTIMING_RDTOWR_OFST 21
+#define DDRTIMING_BURSTLEN_OFST 18
+#define DDRTIMING_WRTOMISS_OFST 12
+#define DDRTIMING_RDTOMISS_OFST 6
+#define DDRTIMING_ACTTOACT_OFST 0
+
+#define ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0)
+
+#define DDRMODE_AUTOPRECHARGE_OFST 1
+#define DDRMODE_BWRATIOEXTENDED_OFST 0
+
+
+#define S10_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(x) (((x) & 0x0000007f) >> 0)
+#define S10_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(x) (((x) & 0x0000000f) >> 0)
+
+#define S10_CCU_CPU0_MPRT_DDR 0xf7004400
+#define S10_CCU_CPU0_MPRT_MEM0 0xf70045c0
+#define S10_CCU_CPU0_MPRT_MEM1A 0xf70045e0
+#define S10_CCU_CPU0_MPRT_MEM1B 0xf7004600
+#define S10_CCU_CPU0_MPRT_MEM1C 0xf7004620
+#define S10_CCU_CPU0_MPRT_MEM1D 0xf7004640
+#define S10_CCU_CPU0_MPRT_MEM1E 0xf7004660
+#define S10_CCU_IOM_MPRT_MEM0 0xf7018560
+#define S10_CCU_IOM_MPRT_MEM1A 0xf7018580
+#define S10_CCU_IOM_MPRT_MEM1B 0xf70185a0
+#define S10_CCU_IOM_MPRT_MEM1C 0xf70185c0
+#define S10_CCU_IOM_MPRT_MEM1D 0xf70185e0
+#define S10_CCU_IOM_MPRT_MEM1E 0xf7018600
+
+#define S10_NOC_FW_DDR_SCR 0xf8020100
+#define S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT 0xf802011c
+#define S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT 0xf8020118
+#define S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT 0xf802019c
+#define S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT 0xf8020198
+
+#define S10_SOC_NOC_FW_DDR_SCR_ENABLE 0xf8020100
+#define S10_CCU_NOC_DI_SET_MSK 0x10
+
+#define S10_SYSMGR_CORE_HMC_CLK 0xffd120b4
+#define S10_SYSMGR_CORE_HMC_CLK_STATUS 0x00000001
+
+#define S10_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0(x) (((x) & 0x0000ffff) >> 0)
+#define S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK 0x00000003
+#define S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST 0
+#define S10_MPFE_HMC_ADP_HPSINTFCSEL_ENABLE 0x001f1f1f
+#define S10_IOHMC_CTRLCFG1_ENABLE_ECC_OFST 7
+
+#define S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK 0x00010000
+#define S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK 0x00000100
+#define S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK 0x00000001
+
+#define S10_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK 0x00000001
+#define S10_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK 0x00010000
+#define S10_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK 0x00000100
+#define S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(value) (((value) & 0x00000001) >> 0)
+
+
+#define S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(x) (((x) & 0x00000003) >> 0)
+#define IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(x) (((x) & 0x00003c00) >> 10)
+#define IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(x) (((x) & 0x0000c000) >> 14)
+#define IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(x) (((x) & 0x0000001f) >> 0)
+#define IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(x) (((x) & 0x00070000) >> 16)
+#define IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(x) (((x) & 0x000003e0) >> 5)
+
+#define S10_SDRAM_0_LB_ADDR 0x0
+
+int init_hard_memory_controller(void);
+
+#endif
diff --git a/plat/intel/soc/stratix10/include/s10_mmc.h b/plat/intel/soc/stratix10/include/s10_mmc.h
new file mode 100644
index 0000000..99f86f5
--- /dev/null
+++ b/plat/intel/soc/stratix10/include/s10_mmc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __S10_MMC_H__
+#define __S10_MMC_H__
+
+void s10_mmc_init(void);
+
+#endif /* S10_MMC_H */
diff --git a/plat/intel/soc/stratix10/include/s10_pinmux.h b/plat/intel/soc/stratix10/include/s10_pinmux.h
new file mode 100644
index 0000000..82367d7
--- /dev/null
+++ b/plat/intel/soc/stratix10/include/s10_pinmux.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __S10_PINMUX_H__
+#define __S10_PINMUX_H__
+
+#define S10_PINMUX_PIN0SEL 0xffd13000
+#define S10_PINMUX_IO0CTRL 0xffd13130
+#define S10_PINMUX_PINMUX_EMAC0_USEFPGA 0xffd13300
+#define S10_PINMUX_IO0_DELAY 0xffd13400
+
+#include "socfpga_handoff.h"
+
+void config_pinmux(handoff *handoff);
+
+#endif
+
diff --git a/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
new file mode 100644
index 0000000..516cc75
--- /dev/null
+++ b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SOCFPGA_DEF_H
+#define PLAT_SOCFPGA_DEF_H
+
+#include <platform_def.h>
+
+/* Platform Setting */
+#define PLATFORM_MODEL PLAT_SOCFPGA_STRATIX10
+#define BOOT_SOURCE BOOT_SOURCE_SDMMC
+
+/* FPGA config helpers */
+#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000
+#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 0x1000000
+
+/* Register Mapping */
+#define SOCFPGA_CCU_NOC_REG_BASE 0xf7000000
+#define SOCFPGA_F2SDRAMMGR_REG_BASE U(0xf8024000)
+
+#define SOCFPGA_MMC_REG_BASE 0xff808000
+
+#define SOCFPGA_RSTMGR_REG_BASE 0xffd11000
+#define SOCFPGA_SYSMGR_REG_BASE 0xffd12000
+
+#define SOCFPGA_L4_PER_SCR_REG_BASE 0xffd21000
+#define SOCFPGA_L4_SYS_SCR_REG_BASE 0xffd21100
+#define SOCFPGA_SOC2FPGA_SCR_REG_BASE 0xffd21200
+#define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE 0xffd21300
+
+/* Platform specific system counter */
+#define PLAT_SYS_COUNTER_FREQ_IN_MHZ get_cpu_clk()
+
+uint32_t get_cpu_clk(void);
+
+#endif /* PLATSOCFPGA_DEF_H */
+
diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk
new file mode 100644
index 0000000..b7eb4bd
--- /dev/null
+++ b/plat/intel/soc/stratix10/platform.mk
@@ -0,0 +1,80 @@
+#
+# Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := \
+ -Iplat/intel/soc/stratix10/include/ \
+ -Iplat/intel/soc/common/drivers/ \
+ -Iplat/intel/soc/common/include/
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+AGX_GICv2_SOURCES := \
+ ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c
+
+
+PLAT_BL_COMMON_SOURCES := \
+ ${AGX_GICv2_SOURCES} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ plat/intel/soc/common/aarch64/platform_common.c \
+ plat/intel/soc/common/aarch64/plat_helpers.S \
+ plat/intel/soc/common/socfpga_delay_timer.c \
+ plat/intel/soc/common/soc/socfpga_firewall.c
+
+BL2_SOURCES += \
+ common/desc_image_load.c \
+ drivers/mmc/mmc.c \
+ drivers/intel/soc/stratix10/io/s10_memmap_qspi.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/partition/partition.c \
+ drivers/partition/gpt.c \
+ drivers/synopsys/emmc/dw_mmc.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/intel/soc/stratix10/bl2_plat_setup.c \
+ plat/intel/soc/stratix10/soc/s10_clock_manager.c \
+ plat/intel/soc/stratix10/soc/s10_memory_controller.c \
+ plat/intel/soc/stratix10/soc/s10_mmc.c \
+ plat/intel/soc/stratix10/soc/s10_pinmux.c \
+ plat/intel/soc/common/bl2_plat_mem_params_desc.c \
+ plat/intel/soc/common/socfpga_image_load.c \
+ plat/intel/soc/common/socfpga_storage.c \
+ plat/intel/soc/common/soc/socfpga_emac.c \
+ plat/intel/soc/common/soc/socfpga_handoff.c \
+ plat/intel/soc/common/soc/socfpga_mailbox.c \
+ plat/intel/soc/common/soc/socfpga_reset_manager.c \
+ plat/intel/soc/common/drivers/qspi/cadence_qspi.c \
+ plat/intel/soc/common/drivers/wdt/watchdog.c
+
+include lib/zlib/zlib.mk
+PLAT_INCLUDES += -Ilib/zlib
+BL2_SOURCES += $(ZLIB_SOURCES)
+
+BL31_SOURCES += \
+ drivers/arm/cci/cci.c \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/intel/soc/stratix10/soc/s10_clock_manager.c \
+ plat/intel/soc/stratix10/bl31_plat_setup.c \
+ plat/intel/soc/common/socfpga_psci.c \
+ plat/intel/soc/common/socfpga_sip_svc.c \
+ plat/intel/soc/common/socfpga_sip_svc_v2.c \
+ plat/intel/soc/common/socfpga_topology.c \
+ plat/intel/soc/common/sip/socfpga_sip_ecc.c \
+ plat/intel/soc/common/sip/socfpga_sip_fcs.c \
+ plat/intel/soc/common/soc/socfpga_mailbox.c \
+ plat/intel/soc/common/soc/socfpga_reset_manager.c
+
+PROGRAMMABLE_RESET_ADDRESS := 0
+BL2_AT_EL3 := 1
+USE_COHERENT_MEM := 1
diff --git a/plat/intel/soc/stratix10/soc/s10_clock_manager.c b/plat/intel/soc/stratix10/soc/s10_clock_manager.c
new file mode 100644
index 0000000..30009f7
--- /dev/null
+++ b/plat/intel/soc/stratix10/soc/s10_clock_manager.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include "s10_clock_manager.h"
+#include "socfpga_handoff.h"
+#include "socfpga_system_manager.h"
+
+
+void wait_pll_lock(void)
+{
+ uint32_t data;
+
+ do {
+ data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT);
+ } while ((ALT_CLKMGR_STAT_MAINPLLLOCKED(data) == 0) ||
+ (ALT_CLKMGR_STAT_PERPLLLOCKED(data) == 0));
+}
+
+void wait_fsm(void)
+{
+ uint32_t data;
+
+ do {
+ data = mmio_read_32(ALT_CLKMGR + ALT_CLKMGR_STAT);
+ } while (ALT_CLKMGR_STAT_BUSY(data) == ALT_CLKMGR_STAT_BUSY_E_BUSY);
+}
+
+void config_clkmgr_handoff(handoff *hoff_ptr)
+{
+ uint32_t m_div, refclk_div, mscnt, hscnt;
+
+ /* Bypass all mainpllgrp's clocks */
+ mmio_write_32(ALT_CLKMGR_MAINPLL +
+ ALT_CLKMGR_MAINPLL_BYPASS,
+ 0x7);
+ wait_fsm();
+ /* Bypass all perpllgrp's clocks */
+ mmio_write_32(ALT_CLKMGR_PERPLL +
+ ALT_CLKMGR_PERPLL_BYPASS,
+ 0x7f);
+ wait_fsm();
+
+ /* Setup main PLL dividers */
+ m_div = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(hoff_ptr->main_pll_fdbck);
+ refclk_div = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(
+ hoff_ptr->main_pll_pllglob);
+ mscnt = 200 / ((6 + m_div) / refclk_div);
+ hscnt = (m_div + 6) * mscnt / refclk_div - 9;
+
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB,
+ hoff_ptr->main_pll_pllglob);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK,
+ hoff_ptr->main_pll_fdbck);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_VCOCALIB,
+ ALT_CLKMGR_MAINPLL_VCOCALIB_HSCNT_SET(hscnt) |
+ ALT_CLKMGR_MAINPLL_VCOCALIB_MSCNT_SET(mscnt));
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC0,
+ hoff_ptr->main_pll_pllc0);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1,
+ hoff_ptr->main_pll_pllc1);
+
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV,
+ hoff_ptr->main_pll_nocdiv);
+
+ /* Setup peripheral PLL dividers */
+ m_div = ALT_CLKMGR_PERPLL_FDBCK_MDIV(hoff_ptr->per_pll_fdbck);
+ refclk_div = ALT_CLKMGR_PERPLL_PLLGLOB_REFCLKDIV(
+ hoff_ptr->per_pll_pllglob);
+ mscnt = 200 / ((6 + m_div) / refclk_div);
+ hscnt = (m_div + 6) * mscnt / refclk_div - 9;
+
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB,
+ hoff_ptr->per_pll_pllglob);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_FDBCK,
+ hoff_ptr->per_pll_fdbck);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_VCOCALIB,
+ ALT_CLKMGR_PERPLL_VCOCALIB_HSCNT_SET(hscnt) |
+ ALT_CLKMGR_PERPLL_VCOCALIB_MSCNT_SET(mscnt));
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC0,
+ hoff_ptr->per_pll_pllc0);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1,
+ hoff_ptr->per_pll_pllc1);
+
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_GPIODIV,
+ ALT_CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(
+ hoff_ptr->per_pll_gpiodiv));
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EMACCTL,
+ hoff_ptr->per_pll_emacctl);
+
+
+ /* Take both PLL out of reset and power up */
+ mmio_setbits_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB,
+ ALT_CLKMGR_MAINPLL_PLLGLOB_PD_SET_MSK |
+ ALT_CLKMGR_MAINPLL_PLLGLOB_RST_SET_MSK);
+ mmio_setbits_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB,
+ ALT_CLKMGR_PERPLL_PLLGLOB_PD_SET_MSK |
+ ALT_CLKMGR_PERPLL_PLLGLOB_RST_SET_MSK);
+
+ wait_pll_lock();
+
+ /* Dividers for C2 to C9 only init after PLLs are lock. */
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK, 0xff);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK, 0xff);
+
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_MPUCLK,
+ hoff_ptr->main_pll_mpuclk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK,
+ hoff_ptr->main_pll_nocclk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR2CLK,
+ hoff_ptr->main_pll_cntr2clk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR3CLK,
+ hoff_ptr->main_pll_cntr3clk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR4CLK,
+ hoff_ptr->main_pll_cntr4clk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR5CLK,
+ hoff_ptr->main_pll_cntr5clk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK,
+ hoff_ptr->main_pll_cntr6clk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR7CLK,
+ hoff_ptr->main_pll_cntr7clk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR8CLK,
+ hoff_ptr->main_pll_cntr8clk);
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR9CLK,
+ hoff_ptr->main_pll_cntr9clk);
+
+ /* Peripheral PLL Clock Source and Counters/Divider */
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR2CLK,
+ hoff_ptr->per_pll_cntr2clk);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR3CLK,
+ hoff_ptr->per_pll_cntr3clk);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR4CLK,
+ hoff_ptr->per_pll_cntr4clk);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR5CLK,
+ hoff_ptr->per_pll_cntr5clk);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR6CLK,
+ hoff_ptr->per_pll_cntr6clk);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR7CLK,
+ hoff_ptr->per_pll_cntr7clk);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR8CLK,
+ hoff_ptr->per_pll_cntr8clk);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_CNTR9CLK,
+ hoff_ptr->per_pll_cntr9clk);
+
+ /* Take all PLLs out of bypass */
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_BYPASS, 0);
+ wait_fsm();
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_BYPASS, 0);
+ wait_fsm();
+
+ /* Set safe mode/ out of boot mode */
+ mmio_clrbits_32(ALT_CLKMGR + ALT_CLKMGR_CTRL,
+ ALT_CLKMGR_CTRL_BOOTMODE_SET_MSK);
+ wait_fsm();
+
+ /* 10 Enable mainpllgrp's software-managed clock */
+ mmio_write_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_EN,
+ ALT_CLKMGR_MAINPLL_EN_RESET);
+ mmio_write_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EN,
+ ALT_CLKMGR_PERPLL_EN_RESET);
+
+ /* Clear loss lock interrupt status register that */
+ /* might be set during configuration */
+ mmio_write_32(ALT_CLKMGR + ALT_CLKMGR_INTRCLR,
+ ALT_CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK |
+ ALT_CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK);
+
+ /* Pass clock source frequency into scratch register */
+ mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1),
+ hoff_ptr->hps_osc_clk_h);
+ mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2),
+ hoff_ptr->fpga_clk_hz);
+
+}
+
+/* Extract reference clock from platform clock source */
+uint32_t get_ref_clk(uint32_t pllglob)
+{
+ uint32_t data32, mdiv, refclkdiv, ref_clk;
+ uint32_t scr_reg;
+
+ switch (ALT_CLKMGR_PSRC(pllglob)) {
+ case ALT_CLKMGR_PLLGLOB_PSRC_EOSC1:
+ scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
+ ref_clk = mmio_read_32(scr_reg);
+ break;
+ case ALT_CLKMGR_PLLGLOB_PSRC_INTOSC:
+ ref_clk = ALT_CLKMGR_INTOSC_HZ;
+ break;
+ case ALT_CLKMGR_PLLGLOB_PSRC_F2S:
+ scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
+ ref_clk = mmio_read_32(scr_reg);
+ break;
+ default:
+ ref_clk = 0;
+ assert(0);
+ break;
+ }
+
+ refclkdiv = ALT_CLKMGR_MAINPLL_PLLGLOB_REFCLKDIV(pllglob);
+ data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_FDBCK);
+ mdiv = ALT_CLKMGR_MAINPLL_FDBCK_MDIV(data32);
+
+ ref_clk = (ref_clk / refclkdiv) * (6 + mdiv);
+
+ return ref_clk;
+}
+
+/* Calculate L3 interconnect main clock */
+uint32_t get_l3_clk(uint32_t ref_clk)
+{
+ uint32_t noc_base_clk, l3_clk, noc_clk, data32;
+ uint32_t pllc1_reg;
+
+ noc_clk = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCCLK);
+
+ switch (ALT_CLKMGR_PSRC(noc_clk)) {
+ case ALT_CLKMGR_SRC_MAIN:
+ pllc1_reg = ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLC1;
+ break;
+ case ALT_CLKMGR_SRC_PER:
+ pllc1_reg = ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLC1;
+ break;
+ default:
+ pllc1_reg = 0;
+ assert(0);
+ break;
+ }
+
+ data32 = mmio_read_32(pllc1_reg);
+ noc_base_clk = ref_clk / (data32 & 0xff);
+ l3_clk = noc_base_clk / (noc_clk + 1);
+
+ return l3_clk;
+}
+
+/* Calculate clock frequency to be used for watchdog timer */
+uint32_t get_wdt_clk(void)
+{
+ uint32_t data32, ref_clk, l3_clk, l4_sys_clk;
+
+ data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB);
+ ref_clk = get_ref_clk(data32);
+
+ l3_clk = get_l3_clk(ref_clk);
+
+ l4_sys_clk = l3_clk / 4;
+
+ return l4_sys_clk;
+}
+
+/* Calculate clock frequency to be used for UART driver */
+uint32_t get_uart_clk(void)
+{
+ uint32_t data32, ref_clk, l3_clk, l4_sp_clk;
+
+ data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB);
+ ref_clk = get_ref_clk(data32);
+
+ l3_clk = get_l3_clk(ref_clk);
+
+ data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_NOCDIV);
+ data32 = (data32 >> 16) & 0x3;
+ data32 = 1 << data32;
+
+ l4_sp_clk = (l3_clk / data32);
+
+ return l4_sp_clk;
+}
+
+/* Calculate clock frequency to be used for SDMMC driver */
+uint32_t get_mmc_clk(void)
+{
+ uint32_t data32, ref_clk, l3_clk, mmc_clk;
+
+ data32 = mmio_read_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_PLLGLOB);
+ ref_clk = get_ref_clk(data32);
+
+ l3_clk = get_l3_clk(ref_clk);
+
+ data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_CNTR6CLK);
+ mmc_clk = (l3_clk / (data32 + 1)) / 4;
+
+ return mmc_clk;
+}
+
+/* Get cpu freq clock */
+uint32_t get_cpu_clk(void)
+{
+ uint32_t data32, ref_clk, cpu_clk;
+
+ data32 = mmio_read_32(ALT_CLKMGR_MAINPLL + ALT_CLKMGR_MAINPLL_PLLGLOB);
+ ref_clk = get_ref_clk(data32);
+
+ cpu_clk = get_l3_clk(ref_clk)/PLAT_SYS_COUNTER_CONVERT_TO_MHZ;
+
+ return cpu_clk;
+}
diff --git a/plat/intel/soc/stratix10/soc/s10_memory_controller.c b/plat/intel/soc/stratix10/soc/s10_memory_controller.c
new file mode 100644
index 0000000..ac756ab
--- /dev/null
+++ b/plat/intel/soc/stratix10/soc/s10_memory_controller.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <platform_def.h>
+#include <string.h>
+
+#include "s10_memory_controller.h"
+#include "socfpga_reset_manager.h"
+
+#define ALT_CCU_NOC_DI_SET_MSK 0x10
+
+#define DDR_READ_LATENCY_DELAY 40
+#define MAX_MEM_CAL_RETRY 3
+#define PRE_CALIBRATION_DELAY 1
+#define POST_CALIBRATION_DELAY 1
+#define TIMEOUT_EMIF_CALIBRATION 1000
+#define CLEAR_EMIF_DELAY 1000
+#define CLEAR_EMIF_TIMEOUT 1000
+
+#define DDR_CONFIG(A, B, C, R) (((A) << 24) | ((B) << 16) | ((C) << 8) | (R))
+#define DDR_CONFIG_ELEMENTS (sizeof(ddr_config)/sizeof(uint32_t))
+
+/* tWR = Min. 15ns constant, see JEDEC standard eg. DDR4 is JESD79-4.pdf */
+#define tWR_IN_NS 15
+
+void configure_hmc_adaptor_regs(void);
+void configure_ddr_sched_ctrl_regs(void);
+
+/* The followring are the supported configurations */
+uint32_t ddr_config[] = {
+ /* DDR_CONFIG(Address order,Bank,Column,Row) */
+ /* List for DDR3 or LPDDR3 (pinout order > chip, row, bank, column) */
+ DDR_CONFIG(0, 3, 10, 12),
+ DDR_CONFIG(0, 3, 9, 13),
+ DDR_CONFIG(0, 3, 10, 13),
+ DDR_CONFIG(0, 3, 9, 14),
+ DDR_CONFIG(0, 3, 10, 14),
+ DDR_CONFIG(0, 3, 10, 15),
+ DDR_CONFIG(0, 3, 11, 14),
+ DDR_CONFIG(0, 3, 11, 15),
+ DDR_CONFIG(0, 3, 10, 16),
+ DDR_CONFIG(0, 3, 11, 16),
+ DDR_CONFIG(0, 3, 12, 15), /* 0xa */
+ /* List for DDR4 only (pinout order > chip, bank, row, column) */
+ DDR_CONFIG(1, 3, 10, 14),
+ DDR_CONFIG(1, 4, 10, 14),
+ DDR_CONFIG(1, 3, 10, 15),
+ DDR_CONFIG(1, 4, 10, 15),
+ DDR_CONFIG(1, 3, 10, 16),
+ DDR_CONFIG(1, 4, 10, 16),
+ DDR_CONFIG(1, 3, 10, 17),
+ DDR_CONFIG(1, 4, 10, 17),
+};
+
+static int match_ddr_conf(uint32_t ddr_conf)
+{
+ int i;
+
+ for (i = 0; i < DDR_CONFIG_ELEMENTS; i++) {
+ if (ddr_conf == ddr_config[i])
+ return i;
+ }
+ return 0;
+}
+
+static int check_hmc_clk(void)
+{
+ unsigned long timeout = 0;
+ uint32_t hmc_clk;
+
+ do {
+ hmc_clk = mmio_read_32(S10_SYSMGR_CORE_HMC_CLK);
+ if (hmc_clk & S10_SYSMGR_CORE_HMC_CLK_STATUS)
+ break;
+ udelay(1);
+ } while (++timeout < 1000);
+ if (timeout >= 1000)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int clear_emif(void)
+{
+ uint32_t data;
+ unsigned long timeout;
+
+ mmio_write_32(S10_MPFE_HMC_ADP_RSTHANDSHAKECTRL, 0);
+
+ timeout = 0;
+ do {
+ data = mmio_read_32(S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT);
+ if ((data & S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE) == 0)
+ break;
+ udelay(CLEAR_EMIF_DELAY);
+ } while (++timeout < CLEAR_EMIF_TIMEOUT);
+ if (timeout >= CLEAR_EMIF_TIMEOUT)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int mem_calibration(void)
+{
+ int status = 0;
+ uint32_t data;
+ unsigned long timeout;
+ unsigned long retry = 0;
+
+ udelay(PRE_CALIBRATION_DELAY);
+
+ do {
+ if (retry != 0)
+ INFO("DDR: Retrying DRAM calibration\n");
+
+ timeout = 0;
+ do {
+ data = mmio_read_32(S10_MPFE_HMC_ADP_DDRCALSTAT);
+ if (S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 1)
+ break;
+ udelay(500);
+ } while (++timeout < TIMEOUT_EMIF_CALIBRATION);
+
+ if (S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) {
+ status = clear_emif();
+ if (status)
+ ERROR("Failed to clear Emif\n");
+ } else {
+ break;
+ }
+ } while (++retry < MAX_MEM_CAL_RETRY);
+
+ if (S10_MPFE_HMC_ADP_DDRCALSTAT_CAL(data) == 0) {
+ ERROR("DDR: DRAM calibration failed.\n");
+ status = -EIO;
+ } else {
+ INFO("DDR: DRAM calibration success.\n");
+ status = 0;
+ }
+
+ udelay(POST_CALIBRATION_DELAY);
+
+ return status;
+}
+
+int init_hard_memory_controller(void)
+{
+ int status;
+
+ mmio_clrbits_32(S10_CCU_CPU0_MPRT_DDR, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM0, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1A, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1B, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1C, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1D, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_CPU0_MPRT_MEM1E, S10_CCU_NOC_DI_SET_MSK);
+
+ mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM0, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1A, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1B, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1C, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1D, S10_CCU_NOC_DI_SET_MSK);
+ mmio_clrbits_32(S10_CCU_IOM_MPRT_MEM1E, S10_CCU_NOC_DI_SET_MSK);
+
+ mmio_write_32(S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMIT, 0xFFFF0000);
+ mmio_write_32(S10_NOC_FW_DDR_SCR_MPUREGION0ADDR_LIMITEXT, 0x1F);
+
+ mmio_write_32(S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMIT, 0xFFFF0000);
+ mmio_write_32(S10_NOC_FW_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT, 0x1F);
+ mmio_write_32(S10_SOC_NOC_FW_DDR_SCR_ENABLE, BIT(0) | BIT(8));
+
+ status = check_hmc_clk();
+ if (status) {
+ ERROR("DDR: Error, HMC clock not running\n");
+ return status;
+ }
+
+ mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST), RSTMGR_FIELD(BRG, DDRSCH));
+
+ status = mem_calibration();
+ if (status) {
+ ERROR("DDR: Memory Calibration Failed\n");
+ return status;
+ }
+
+ configure_hmc_adaptor_regs();
+ configure_ddr_sched_ctrl_regs();
+
+ return 0;
+}
+
+void configure_ddr_sched_ctrl_regs(void)
+{
+ uint32_t data, dram_addr_order, ddr_conf, bank, row, col,
+ rd_to_miss, wr_to_miss, burst_len, burst_len_ddr_clk,
+ burst_len_sched_clk, act_to_act, rd_to_wr, wr_to_rd, bw_ratio,
+ t_rtp, t_rp, t_rcd, rd_latency, tw_rin_clk_cycles,
+ bw_ratio_extended, auto_precharge = 0, act_to_act_bank, faw,
+ faw_bank, bus_rd_to_rd, bus_rd_to_wr, bus_wr_to_rd;
+
+ INFO("Init HPS NOC's DDR Scheduler.\n");
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CTRLCFG1);
+ dram_addr_order = S10_MPFE_IOHMC_CTRLCFG1_CFG_ADDR_ORDER(data);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_DRAMADDRW);
+
+ col = IOHMC_DRAMADDRW_COL_ADDR_WIDTH(data);
+ row = IOHMC_DRAMADDRW_ROW_ADDR_WIDTH(data);
+ bank = IOHMC_DRAMADDRW_BANK_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_BANK_GRP_ADDR_WIDTH(data);
+
+ ddr_conf = match_ddr_conf(DDR_CONFIG(dram_addr_order, bank, col, row));
+
+ if (ddr_conf) {
+ mmio_clrsetbits_32(
+ S10_MPFE_DDR_MAIN_SCHED_DDRCONF,
+ S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET_MSK,
+ S10_MPFE_DDR_MAIN_SCHED_DDRCONF_SET(ddr_conf));
+ } else {
+ ERROR("DDR: Cannot find predefined ddrConf configuration.\n");
+ }
+
+ mmio_write_32(S10_MPFE_HMC_ADP(ADP_DRAMADDRWIDTH), data);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_DRAMTIMING0);
+ rd_latency = S10_MPFE_IOHMC_REG_DRAMTIMING0_CFG_TCL(data);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING0);
+ act_to_act = ACT_TO_ACT(data);
+ t_rcd = ACT_TO_RDWR(data);
+ act_to_act_bank = ACT_TO_ACT_DIFF_BANK(data);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING1);
+ rd_to_wr = RD_TO_WR(data);
+ bus_rd_to_rd = RD_TO_RD_DIFF_CHIP(data);
+ bus_rd_to_wr = RD_TO_WR_DIFF_CHIP(data);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING2);
+ t_rtp = RD_TO_PCH(data);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING3);
+ wr_to_rd = CALTIMING3_WR_TO_RD(data);
+ bus_wr_to_rd = CALTIMING3_WR_TO_RD_DIFF_CHIP(data);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING4);
+ t_rp = PCH_TO_VALID(data);
+
+ data = mmio_read_32(S10_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL));
+ bw_ratio = ((HMC_ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 0 : 1);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CTRLCFG0);
+ burst_len = HMC_ADP_DDRIOCTRL_CTRL_BURST_LENGTH(data);
+ burst_len_ddr_clk = burst_len / 2;
+ burst_len_sched_clk = ((burst_len/2) / 2);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CTRLCFG0);
+ switch (S10_MPFE_IOHMC_REG_CTRLCFG0_CFG_MEM_TYPE(data)) {
+ case 1:
+ /* DDR4 - 1333MHz */
+ /* 20 (19.995) clock cycles = 15ns */
+ /* Calculate with rounding */
+ tw_rin_clk_cycles = (((tWR_IN_NS * 1333) % 1000) >= 500) ?
+ ((tWR_IN_NS * 1333) / 1000) + 1 :
+ ((tWR_IN_NS * 1333) / 1000);
+ break;
+ default:
+ /* Others - 1066MHz or slower */
+ /* 16 (15.990) clock cycles = 15ns */
+ /* Calculate with rounding */
+ tw_rin_clk_cycles = (((tWR_IN_NS * 1066) % 1000) >= 500) ?
+ ((tWR_IN_NS * 1066) / 1000) + 1 :
+ ((tWR_IN_NS * 1066) / 1000);
+ break;
+ }
+
+ rd_to_miss = t_rtp + t_rp + t_rcd - burst_len_sched_clk;
+ wr_to_miss = ((rd_latency + burst_len_ddr_clk + 2 + tw_rin_clk_cycles)
+ / 2) - rd_to_wr + t_rp + t_rcd;
+
+ mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_DDRTIMING,
+ bw_ratio << DDRTIMING_BWRATIO_OFST |
+ wr_to_rd << DDRTIMING_WRTORD_OFST|
+ rd_to_wr << DDRTIMING_RDTOWR_OFST |
+ burst_len_sched_clk << DDRTIMING_BURSTLEN_OFST |
+ wr_to_miss << DDRTIMING_WRTOMISS_OFST |
+ rd_to_miss << DDRTIMING_RDTOMISS_OFST |
+ act_to_act << DDRTIMING_ACTTOACT_OFST);
+
+ data = mmio_read_32(S10_MPFE_HMC_ADP(HMC_ADP_DDRIOCTRL));
+ bw_ratio_extended = ((ADP_DDRIOCTRL_IO_SIZE(data) == 0) ? 1 : 0);
+
+ mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_DDRMODE,
+ bw_ratio_extended << DDRMODE_BWRATIOEXTENDED_OFST |
+ auto_precharge << DDRMODE_AUTOPRECHARGE_OFST);
+
+ mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_READLATENCY,
+ (rd_latency / 2) + DDR_READ_LATENCY_DELAY);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_CALTIMING9);
+ faw = S10_MPFE_IOHMC_CALTIMING9_ACT_TO_ACT(data);
+
+ faw_bank = 1; // always 1 because we always have 4 bank DDR.
+
+ mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_ACTIVATE,
+ faw_bank << S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAWBANK_OFST |
+ faw << S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_FAW_OFST |
+ act_to_act_bank << S10_MPFE_DDR_MAIN_SCHED_ACTIVATE_RRD_OFST);
+
+ mmio_write_32(S10_MPFE_DDR_MAIN_SCHED_DEVTODEV,
+ ((bus_rd_to_rd
+ << S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_OFST)
+ & S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTORD_MSK) |
+ ((bus_rd_to_wr
+ << S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_OFST)
+ & S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSRDTOWR_MSK) |
+ ((bus_wr_to_rd
+ << S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_OFST)
+ & S10_MPFE_DDR_MAIN_SCHED_DEVTODEV_BUSWRTORD_MSK));
+
+}
+
+unsigned long get_physical_dram_size(void)
+{
+ uint32_t data;
+ unsigned long ram_addr_width, ram_ext_if_io_width;
+
+ data = mmio_read_32(S10_MPFE_HMC_ADP_DDRIOCTRL);
+ switch (S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE(data)) {
+ case 0:
+ ram_ext_if_io_width = 16;
+ break;
+ case 1:
+ ram_ext_if_io_width = 32;
+ break;
+ case 2:
+ ram_ext_if_io_width = 64;
+ break;
+ default:
+ ram_ext_if_io_width = 0;
+ break;
+ }
+
+ data = mmio_read_32(S10_MPFE_IOHMC_REG_DRAMADDRW);
+ ram_addr_width = IOHMC_DRAMADDRW_CFG_COL_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_ROW_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_BANK_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_BANK_GROUP_ADDR_WIDTH(data) +
+ IOHMC_DRAMADDRW_CFG_CS_ADDR_WIDTH(data);
+
+ return (1 << ram_addr_width) * (ram_ext_if_io_width / 8);
+}
+
+
+
+void configure_hmc_adaptor_regs(void)
+{
+ uint32_t data;
+ uint32_t dram_io_width;
+
+ dram_io_width = S10_MPFE_IOHMC_NIOSRESERVE0_NIOS_RESERVE0(
+ mmio_read_32(S10_MPFE_IOHMC_REG_NIOSRESERVE0_OFST));
+
+ dram_io_width = (dram_io_width & 0xFF) >> 5;
+
+ mmio_clrsetbits_32(S10_MPFE_HMC_ADP_DDRIOCTRL,
+ S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_MSK,
+ dram_io_width << S10_MPFE_HMC_ADP_DDRIOCTRL_IO_SIZE_OFST);
+
+ mmio_write_32(S10_MPFE_HMC_ADP_HPSINTFCSEL,
+ S10_MPFE_HMC_ADP_HPSINTFCSEL_ENABLE);
+
+ data = mmio_read_32(S10_MPFE_IOHMC_REG_CTRLCFG1);
+ if (data & (1 << S10_IOHMC_CTRLCFG1_ENABLE_ECC_OFST)) {
+ mmio_clrsetbits_32(S10_MPFE_HMC_ADP_ECCCTRL1,
+ S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK,
+ S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK);
+
+ mmio_clrsetbits_32(S10_MPFE_HMC_ADP_ECCCTRL2,
+ S10_MPFE_HMC_ADP_ECCCTRL2_OVRW_RB_ECC_EN_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK,
+ S10_MPFE_HMC_ADP_ECCCTRL2_RMW_EN_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL2_AUTOWB_EN_SET_MSK);
+
+ mmio_clrsetbits_32(S10_MPFE_HMC_ADP_ECCCTRL1,
+ S10_MPFE_HMC_ADP_ECCCTRL1_AUTOWB_CNT_RST_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL1_CNT_RST_SET_MSK |
+ S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK,
+ S10_MPFE_HMC_ADP_ECCCTRL1_ECC_EN_SET_MSK);
+ INFO("Scrubbing ECC\n");
+
+ /* ECC Scrubbing */
+ zeromem(DRAM_BASE, DRAM_SIZE);
+ } else {
+ INFO("ECC is disabled.\n");
+ }
+}
+
diff --git a/plat/intel/soc/stratix10/soc/s10_mmc.c b/plat/intel/soc/stratix10/soc/s10_mmc.c
new file mode 100644
index 0000000..333bdd6
--- /dev/null
+++ b/plat/intel/soc/stratix10/soc/s10_mmc.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <lib/mmio.h>
+
+#include "s10_clock_manager.h"
+#include "socfpga_system_manager.h"
+
+void s10_mmc_init(void)
+{
+ mmio_clrbits_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EN,
+ ALT_CLKMGR_PERPLL_EN_SDMMCCLK);
+ mmio_write_32(SOCFPGA_SYSMGR(SDMMC),
+ SYSMGR_SDMMC_SMPLSEL(2) | SYSMGR_SDMMC_DRVSEL(3));
+ mmio_setbits_32(ALT_CLKMGR_PERPLL + ALT_CLKMGR_PERPLL_EN,
+ ALT_CLKMGR_PERPLL_EN_SDMMCCLK);
+}
diff --git a/plat/intel/soc/stratix10/soc/s10_pinmux.c b/plat/intel/soc/stratix10/soc/s10_pinmux.c
new file mode 100644
index 0000000..7fb4711
--- /dev/null
+++ b/plat/intel/soc/stratix10/soc/s10_pinmux.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include "s10_pinmux.h"
+
+const uint32_t sysmgr_pinmux_array_sel[] = {
+ 0x00000000, 0x00000001, /* usb */
+ 0x00000004, 0x00000001,
+ 0x00000008, 0x00000001,
+ 0x0000000c, 0x00000001,
+ 0x00000010, 0x00000001,
+ 0x00000014, 0x00000001,
+ 0x00000018, 0x00000001,
+ 0x0000001c, 0x00000001,
+ 0x00000020, 0x00000001,
+ 0x00000024, 0x00000001,
+ 0x00000028, 0x00000001,
+ 0x0000002c, 0x00000001,
+ 0x00000030, 0x00000000, /* emac0 */
+ 0x00000034, 0x00000000,
+ 0x00000038, 0x00000000,
+ 0x0000003c, 0x00000000,
+ 0x00000040, 0x00000000,
+ 0x00000044, 0x00000000,
+ 0x00000048, 0x00000000,
+ 0x0000004c, 0x00000000,
+ 0x00000050, 0x00000000,
+ 0x00000054, 0x00000000,
+ 0x00000058, 0x00000000,
+ 0x0000005c, 0x00000000,
+ 0x00000060, 0x00000008, /* gpio1 */
+ 0x00000064, 0x00000008,
+ 0x00000068, 0x00000005, /* uart0 tx */
+ 0x0000006c, 0x00000005, /* uart 0 rx */
+ 0x00000070, 0x00000008, /* gpio */
+ 0x00000074, 0x00000008,
+ 0x00000078, 0x00000004, /* i2c1 */
+ 0x0000007c, 0x00000004,
+ 0x00000080, 0x00000007, /* jtag */
+ 0x00000084, 0x00000007,
+ 0x00000088, 0x00000007,
+ 0x0000008c, 0x00000007,
+ 0x00000090, 0x00000001, /* sdmmc data0 */
+ 0x00000094, 0x00000001,
+ 0x00000098, 0x00000001,
+ 0x0000009c, 0x00000001,
+ 0x00000100, 0x00000001,
+ 0x00000104, 0x00000001, /* sdmmc.data3 */
+ 0x00000108, 0x00000008, /* loan */
+ 0x0000010c, 0x00000008, /* gpio */
+ 0x00000110, 0x00000008,
+ 0x00000114, 0x00000008, /* gpio1.io21 */
+ 0x00000118, 0x00000005, /* mdio0.mdio */
+ 0x0000011c, 0x00000005 /* mdio0.mdc */
+};
+
+const uint32_t sysmgr_pinmux_array_ctrl[] = {
+ 0x00000000, 0x00502c38, /* Q1_1 */
+ 0x00000004, 0x00102c38,
+ 0x00000008, 0x00502c38,
+ 0x0000000c, 0x00502c38,
+ 0x00000010, 0x00502c38,
+ 0x00000014, 0x00502c38,
+ 0x00000018, 0x00502c38,
+ 0x0000001c, 0x00502c38,
+ 0x00000020, 0x00502c38,
+ 0x00000024, 0x00502c38,
+ 0x00000028, 0x00502c38,
+ 0x0000002c, 0x00502c38,
+ 0x00000030, 0x00102c38, /* Q2_1 */
+ 0x00000034, 0x00102c38,
+ 0x00000038, 0x00502c38,
+ 0x0000003c, 0x00502c38,
+ 0x00000040, 0x00102c38,
+ 0x00000044, 0x00102c38,
+ 0x00000048, 0x00502c38,
+ 0x0000004c, 0x00502c38,
+ 0x00000050, 0x00102c38,
+ 0x00000054, 0x00102c38,
+ 0x00000058, 0x00502c38,
+ 0x0000005c, 0x00502c38,
+ 0x00000060, 0x00502c38, /* Q3_1 */
+ 0x00000064, 0x00502c38,
+ 0x00000068, 0x00102c38,
+ 0x0000006c, 0x00502c38,
+ 0x000000d0, 0x00502c38,
+ 0x000000d4, 0x00502c38,
+ 0x000000d8, 0x00542c38,
+ 0x000000dc, 0x00542c38,
+ 0x000000e0, 0x00502c38,
+ 0x000000e4, 0x00502c38,
+ 0x000000e8, 0x00102c38,
+ 0x000000ec, 0x00502c38,
+ 0x000000f0, 0x00502c38, /* Q4_1 */
+ 0x000000f4, 0x00502c38,
+ 0x000000f8, 0x00102c38,
+ 0x000000fc, 0x00502c38,
+ 0x00000100, 0x00502c38,
+ 0x00000104, 0x00502c38,
+ 0x00000108, 0x00102c38,
+ 0x0000010c, 0x00502c38,
+ 0x00000110, 0x00502c38,
+ 0x00000114, 0x00502c38,
+ 0x00000118, 0x00542c38,
+ 0x0000011c, 0x00102c38
+};
+
+const uint32_t sysmgr_pinmux_array_fpga[] = {
+ 0x00000000, 0x00000000,
+ 0x00000004, 0x00000000,
+ 0x00000008, 0x00000000,
+ 0x0000000c, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000014, 0x00000000,
+ 0x00000018, 0x00000000,
+ 0x0000001c, 0x00000000,
+ 0x00000020, 0x00000000,
+ 0x00000028, 0x00000000,
+ 0x0000002c, 0x00000000,
+ 0x00000030, 0x00000000,
+ 0x00000034, 0x00000000,
+ 0x00000038, 0x00000000,
+ 0x0000003c, 0x00000000,
+ 0x00000040, 0x00000000,
+ 0x00000044, 0x00000000,
+ 0x00000048, 0x00000000,
+ 0x00000050, 0x00000000,
+ 0x00000054, 0x00000000,
+ 0x00000058, 0x0000002a
+};
+
+const uint32_t sysmgr_pinmux_array_iodelay[] = {
+ 0x00000000, 0x00000000,
+ 0x00000004, 0x00000000,
+ 0x00000008, 0x00000000,
+ 0x0000000c, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000014, 0x00000000,
+ 0x00000018, 0x00000000,
+ 0x0000001c, 0x00000000,
+ 0x00000020, 0x00000000,
+ 0x00000024, 0x00000000,
+ 0x00000028, 0x00000000,
+ 0x0000002c, 0x00000000,
+ 0x00000030, 0x00000000,
+ 0x00000034, 0x00000000,
+ 0x00000038, 0x00000000,
+ 0x0000003c, 0x00000000,
+ 0x00000040, 0x00000000,
+ 0x00000044, 0x00000000,
+ 0x00000048, 0x00000000,
+ 0x0000004c, 0x00000000,
+ 0x00000050, 0x00000000,
+ 0x00000054, 0x00000000,
+ 0x00000058, 0x00000000,
+ 0x0000005c, 0x00000000,
+ 0x00000060, 0x00000000,
+ 0x00000064, 0x00000000,
+ 0x00000068, 0x00000000,
+ 0x0000006c, 0x00000000,
+ 0x00000070, 0x00000000,
+ 0x00000074, 0x00000000,
+ 0x00000078, 0x00000000,
+ 0x0000007c, 0x00000000,
+ 0x00000080, 0x00000000,
+ 0x00000084, 0x00000000,
+ 0x00000088, 0x00000000,
+ 0x0000008c, 0x00000000,
+ 0x00000090, 0x00000000,
+ 0x00000094, 0x00000000,
+ 0x00000098, 0x00000000,
+ 0x0000009c, 0x00000000,
+ 0x00000100, 0x00000000,
+ 0x00000104, 0x00000000,
+ 0x00000108, 0x00000000,
+ 0x0000010c, 0x00000000,
+ 0x00000110, 0x00000000,
+ 0x00000114, 0x00000000,
+ 0x00000118, 0x00000000,
+ 0x0000011c, 0x00000000
+};
+
+void config_pinmux(handoff *hoff_ptr)
+{
+ unsigned int i;
+
+ for (i = 0; i < 96; i += 2) {
+ mmio_write_32(S10_PINMUX_PIN0SEL +
+ hoff_ptr->pinmux_sel_array[i],
+ hoff_ptr->pinmux_sel_array[i+1]);
+ }
+
+ for (i = 0; i < 96; i += 2) {
+ mmio_write_32(S10_PINMUX_IO0CTRL +
+ hoff_ptr->pinmux_io_array[i],
+ hoff_ptr->pinmux_io_array[i+1]);
+ }
+
+ for (i = 0; i < 42; i += 2) {
+ mmio_write_32(S10_PINMUX_PINMUX_EMAC0_USEFPGA +
+ hoff_ptr->pinmux_fpga_array[i],
+ hoff_ptr->pinmux_fpga_array[i+1]);
+ }
+
+ for (i = 0; i < 96; i += 2) {
+ mmio_write_32(S10_PINMUX_IO0_DELAY +
+ hoff_ptr->pinmux_iodelay_array[i],
+ hoff_ptr->pinmux_iodelay_array[i+1]);
+ }
+
+}
+
diff --git a/plat/marvell/armada/a3k/a3700/board/pm_src.c b/plat/marvell/armada/a3k/a3700/board/pm_src.c
new file mode 100644
index 0000000..247f73b
--- /dev/null
+++ b/plat/marvell/armada/a3k/a3700/board/pm_src.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a3700_pm.h>
+#include <plat_marvell.h>
+
+/* This struct provides the PM wake up src configuration for A3720 Development Board */
+static struct pm_wake_up_src_config wake_up_src_cfg = {
+ .wake_up_src_num = 3,
+ .wake_up_src[0] = {
+ .wake_up_src_type = WAKE_UP_SRC_GPIO,
+ .wake_up_data = {
+ .gpio_data.bank_num = 0, /* North Bridge */
+ .gpio_data.gpio_num = 14
+ }
+ },
+ .wake_up_src[1] = {
+ .wake_up_src_type = WAKE_UP_SRC_GPIO,
+ .wake_up_data = {
+ .gpio_data.bank_num = 1, /* South Bridge */
+ .gpio_data.gpio_num = 2
+ }
+ },
+ .wake_up_src[2] = {
+ .wake_up_src_type = WAKE_UP_SRC_UART1,
+ }
+};
+
+struct pm_wake_up_src_config *mv_wake_up_src_config_get(void)
+{
+ return &wake_up_src_cfg;
+}
+
diff --git a/plat/marvell/armada/a3k/a3700/mvebu_def.h b/plat/marvell/armada/a3k/a3700/mvebu_def.h
new file mode 100644
index 0000000..dad1085
--- /dev/null
+++ b/plat/marvell/armada/a3k/a3700/mvebu_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a3700_plat_def.h>
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c b/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c
new file mode 100644
index 0000000..6862a86
--- /dev/null
+++ b/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+#include <dram_win.h>
+#include <io_addr_dec.h>
+#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
+
+/* This routine does MPP initialization */
+static void marvell_bl31_mpp_init(void)
+{
+ mmio_clrbits_32(MVEBU_NB_GPIO_SEL_REG, 1 << MVEBU_GPIO_TW1_GPIO_EN_OFF);
+
+ /* Set hidden GPIO setting for SPI.
+ * In north_bridge_pin_out_en_high register 13804,
+ * bit 28 is the one which enables CS, CLK pins to be
+ * output, need to set it to 1.
+ * The initial value of this bit is 1, but in UART boot mode
+ * initialization, this bit is disabled and the SPI CS and CLK pins
+ * are used for downloading image purpose; so after downloading,
+ * we should set this bit to 1 again to enable SPI CS and CLK pins.
+ * And anyway, this bit value should be 1 in all modes,
+ * so here we does not judge boot mode and set this bit to 1 always.
+ */
+ mmio_setbits_32(MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG,
+ 1 << MVEBU_GPIO_NB_SPI_PIN_MODE_OFF);
+}
+
+/* This function overruns the same function in marvell_bl31_setup.c */
+void bl31_plat_arch_setup(void)
+{
+ struct dec_win_config *io_dec_map;
+ uint32_t dec_win_num;
+ struct dram_win_map dram_wins_map;
+
+ marvell_bl31_plat_arch_setup();
+
+ /* MPP init */
+ marvell_bl31_mpp_init();
+
+ /* initialize the timer for delay functionality */
+ plat_delay_timer_init();
+
+ /* CPU address decoder windows initialization. */
+ cpu_wins_init();
+
+ /* fetch CPU-DRAM window mapping information by reading
+ * CPU-DRAM decode windows (only the enabled ones)
+ */
+ dram_win_map_build(&dram_wins_map);
+
+ /* Get IO address decoder windows */
+ if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) {
+ printf("No IO address decoder windows configurations found!\n");
+ return;
+ }
+
+ /* IO address decoder init */
+ if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) {
+ printf("IO address decoder windows initialization failed!\n");
+ return;
+ }
+}
diff --git a/plat/marvell/armada/a3k/a3700/platform.mk b/plat/marvell/armada/a3k/a3700/platform.mk
new file mode 100644
index 0000000..050af41
--- /dev/null
+++ b/plat/marvell/armada/a3k/a3700/platform.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+include plat/marvell/armada/a3k/common/a3700_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
new file mode 100644
index 0000000..b9c28de
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -0,0 +1,247 @@
+#
+# Copyright (C) 2018-2021 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+MARVELL_PLAT_BASE := plat/marvell/armada
+MARVELL_PLAT_INCLUDE_BASE := include/plat/marvell/armada
+PLAT_FAMILY := a3k
+PLAT_FAMILY_BASE := $(MARVELL_PLAT_BASE)/$(PLAT_FAMILY)
+PLAT_INCLUDE_BASE := $(MARVELL_PLAT_INCLUDE_BASE)/$(PLAT_FAMILY)
+PLAT_COMMON_BASE := $(PLAT_FAMILY_BASE)/common
+MARVELL_DRV_BASE := drivers/marvell
+MARVELL_COMMON_BASE := $(MARVELL_PLAT_BASE)/common
+ERRATA_A53_1530924 := 1
+
+include plat/marvell/marvell.mk
+
+#*********** A3700 *************
+
+# GICV3
+$(eval $(call add_define,CONFIG_GICV3))
+
+# CCI-400
+$(eval $(call add_define,USE_CCI))
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+MARVELL_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c
+
+PLAT_INCLUDES := -I$(PLAT_FAMILY_BASE)/$(PLAT) \
+ -I$(PLAT_COMMON_BASE)/include \
+ -I$(PLAT_INCLUDE_BASE)/common \
+ -I$(MARVELL_DRV_BASE) \
+ -I$/drivers/arm/gic/common/
+
+PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a3700_common.c \
+ $(PLAT_COMMON_BASE)/aarch64/a3700_clock.S \
+ $(MARVELL_DRV_BASE)/uart/a3700_console.S
+
+BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
+ lib/cpus/aarch64/cortex_a53.S
+
+MARVELL_DRV := $(MARVELL_DRV_BASE)/comphy/phy-comphy-3700.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
+ $(PLAT_COMMON_BASE)/plat_cci.c \
+ $(PLAT_COMMON_BASE)/plat_pm.c \
+ $(PLAT_COMMON_BASE)/dram_win.c \
+ $(PLAT_COMMON_BASE)/io_addr_dec.c \
+ $(PLAT_COMMON_BASE)/marvell_plat_config.c \
+ $(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \
+ $(MARVELL_COMMON_BASE)/marvell_cci.c \
+ $(MARVELL_COMMON_BASE)/marvell_ddr_info.c \
+ $(MARVELL_COMMON_BASE)/marvell_gicv3.c \
+ $(MARVELL_GIC_SOURCES) \
+ drivers/arm/cci/cci.c \
+ $(PLAT_COMMON_BASE)/a3700_sip_svc.c \
+ $(MARVELL_DRV)
+
+ifeq ($(HANDLE_EA_EL3_FIRST_NS),1)
+BL31_SOURCES += $(PLAT_COMMON_BASE)/a3700_ea.c
+endif
+
+ifeq ($(CM3_SYSTEM_RESET),1)
+BL31_SOURCES += $(PLAT_COMMON_BASE)/cm3_system_reset.c
+endif
+
+ifeq ($(A3720_DB_PM_WAKEUP_SRC),1)
+BL31_SOURCES += $(PLAT_FAMILY_BASE)/$(PLAT)/board/pm_src.c
+endif
+
+ifdef WTP
+
+# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
+$(if $(wildcard $(value WTP)/*),,$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' directory does not exist"))
+$(if $(shell git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid A3700-utils-marvell git repository"))
+
+TBB := $(WTP)/wtptp/src/TBB_Linux/release/TBB_linux
+
+BUILD_UART := uart-images
+UART_IMAGE := $(BUILD_UART).tgz.bin
+
+ifeq ($(MARVELL_SECURE_BOOT),1)
+TIM_CFG := $(BUILD_PLAT)/atf-tim.txt
+TIM_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt
+IMAGESPATH := $(WTP)/tim/trusted
+TIMN_CFG := $(BUILD_PLAT)/atf-timN.txt
+TIMN_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-timN.txt
+TIMN_SIG := $(IMAGESPATH)/timnsign.txt
+TIM2IMGARGS := -i $(TIM_CFG) -n $(TIMN_CFG)
+TIMN_UART_IMAGE := $$(grep "Image Filename:" -m 1 $(TIMN_UART_CFG) | cut -c 17-)
+else #MARVELL_SECURE_BOOT
+TIM_CFG := $(BUILD_PLAT)/atf-ntim.txt
+TIM_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-ntim.txt
+IMAGESPATH := $(WTP)/tim/untrusted
+TIM2IMGARGS := -i $(TIM_CFG)
+endif #MARVELL_SECURE_BOOT
+
+TIM_UART_IMAGE := $$(grep "Image Filename:" -m 1 $(TIM_UART_CFG) | cut -c 17-)
+
+TIMBUILD := $(WTP)/script/buildtim.sh
+TIM2IMG := $(WTP)/script/tim2img.pl
+TIMDDRTOOL := $(WTP)/tim/ddr/ddr_tool
+
+$(TIMBUILD): $(TIMDDRTOOL)
+
+# WTMI_IMG is used to specify the customized RTOS image running over
+# Service CPU (CM3 processor). By the default, it points to a
+# baremetal binary of fuse programming in A3700_utils.
+WTMI_IMG := $(WTP)/wtmi/fuse/build/fuse.bin
+
+# WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG)
+# and sys-init image.
+WTMI_MULTI_IMG := $(WTP)/wtmi/build/wtmi.bin
+
+WTMI_ENC_IMG := wtmi-enc.bin
+
+SRCPATH := $(dir $(BL33))
+
+CLOCKSPRESET ?= CPU_800_DDR_800
+
+DDR_TOPOLOGY ?= 0
+
+BOOTDEV ?= SPINOR
+PARTNUM ?= 0
+
+TIMBLDARGS := $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \
+ $(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(TIM_CFG) $(TIMN_CFG) $(TIMN_SIG) 1
+TIMBLDUARTARGS := $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \
+ $(DDR_TOPOLOGY) 0 0 $(TIM_UART_CFG) $(TIMN_UART_CFG) $(TIMN_SIG) 0
+
+UART_IMAGES := $(BUILD_UART)/$(TIM_UART_IMAGE)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+UART_IMAGES += $(BUILD_UART)/$(TIMN_UART_IMAGE)
+endif
+UART_IMAGES += $(BUILD_UART)/wtmi_h.bin $(BUILD_UART)/boot-image_h.bin
+
+CRYPTOPP_LIBDIR ?= $(CRYPTOPP_PATH)
+CRYPTOPP_INCDIR ?= $(CRYPTOPP_PATH)
+
+$(TBB): FORCE
+# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
+ $(if $(CRYPTOPP_LIBDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_LIBDIR. Please set CRYPTOPP_PATH or CRYPTOPP_LIBDIR to point to the right directory"))
+ $(if $(CRYPTOPP_INCDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_INCDIR. Please set CRYPTOPP_PATH or CRYPTOPP_INCDIR to point to the right directory"))
+ $(if $(wildcard $(CRYPTOPP_LIBDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_LIB' was set to '$(CRYPTOPP_LIBDIR)', but '$(CRYPTOPP_LIBDIR)' does not exist"))
+ $(if $(wildcard $(CRYPTOPP_INCDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_INCDIR' was set to '$(CRYPTOPP_INCDIR)', but '$(CRYPTOPP_INCDIR)' does not exist"))
+ifdef CRYPTOPP_PATH
+ $(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile
+endif
+ $(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_LIBDIR) INCDIR=$(CRYPTOPP_INCDIR)
+
+$(WTMI_MULTI_IMG): FORCE
+ $(Q)$(MAKE) --no-print-directory -C $(WTP) WTMI_IMG=$(WTMI_IMG) DDR_TOPOLOGY=$(DDR_TOPOLOGY) CLOCKSPRESET=$(CLOCKSPRESET) WTMI
+
+$(BUILD_PLAT)/wtmi.bin: $(WTMI_MULTI_IMG)
+ $(Q)cp -a $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi.bin
+
+$(TIMDDRTOOL): FORCE
+# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
+ $(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
+ $(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
+ $(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
+ $(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr
+
+$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL)
+ @$(ECHO_BLANK_LINE)
+ @echo "Building uart images"
+ $(Q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART)
+ $(Q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin
+ $(Q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE)
+ $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS)
+ $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_UART_CFG)
+ $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_UART_CFG)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+ $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_UART_CFG)
+ $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_UART_CFG)
+endif
+ $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIM_UART_CFG) -v -D
+ifeq ($(MARVELL_SECURE_BOOT),1)
+ $(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIMN_UART_CFG)
+endif
+ $(Q)tar czf $(BUILD_PLAT)/$(UART_IMAGE) -C $(BUILD_PLAT) $(UART_IMAGES)
+ @$(ECHO_BLANK_LINE)
+ @echo "Built $@ successfully"
+ @$(ECHO_BLANK_LINE)
+
+$(BUILD_PLAT)/$(FLASH_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL) $(TIM2IMG)
+ @$(ECHO_BLANK_LINE)
+ @echo "Building flash image"
+ $(Q)cd $(BUILD_PLAT) && $(TIMBUILD) $(TIMBLDARGS)
+ $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_CFG)
+ $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_CFG)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+ $(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_CFG)
+ $(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_CFG)
+ @$(ECHO_BLANK_LINE)
+ @echo "=======================================================";
+ @echo " Secure boot. Encrypting wtmi and boot-image";
+ @echo "=======================================================";
+ @$(ECHO_BLANK_LINE)
+ $(Q)cp $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/wtmi-align.bin
+ $(Q)truncate -s %16 $(BUILD_PLAT)/wtmi-align.bin
+ $(Q)${OPENSSL_BIN_PATH}/openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/wtmi-align.bin \
+ -out $(BUILD_PLAT)/$(WTMI_ENC_IMG) \
+ -K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
+ -iv `cat $(IMAGESPATH)/iv.txt` -p
+ $(Q)truncate -s %16 $(BUILD_PLAT)/$(BOOT_IMAGE);
+ $(Q)${OPENSSL_BIN_PATH}/openssl enc -aes-256-cbc -e -in $(BUILD_PLAT)/$(BOOT_IMAGE) \
+ -out $(BUILD_PLAT)/$(BOOT_ENC_IMAGE) \
+ -K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
+ -iv `cat $(IMAGESPATH)/iv.txt` -p
+endif
+ $(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIM_CFG) -v -D
+ifeq ($(MARVELL_SECURE_BOOT),1)
+ $(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIMN_CFG)
+ $(Q)sed -i 's|wtmi.bin|$(WTMI_ENC_IMG)|1' $(TIMN_CFG)
+ $(Q)sed -i 's|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1' $(TIMN_CFG)
+endif
+ $(Q)cd $(BUILD_PLAT) && $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE)
+ @$(ECHO_BLANK_LINE)
+ @echo "Built $@ successfully"
+ @$(ECHO_BLANK_LINE)
+
+clean realclean distclean: mrvl_clean
+
+.PHONY: mrvl_clean
+mrvl_clean:
+ -$(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) clean
+ -$(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak clean
+ifdef CRYPTOPP_PATH
+ -$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile clean
+endif
+
+else # WTP
+
+$(BUILD_PLAT)/$(UART_IMAGE) $(BUILD_PLAT)/$(FLASH_IMAGE):
+ $(error "Platform '${PLAT}' for target '$@' requires WTP. Please set WTP to point to the right directory")
+
+endif # WTP
+
+.PHONY: mrvl_uart
+mrvl_uart: $(BUILD_PLAT)/$(UART_IMAGE)
diff --git a/plat/marvell/armada/a3k/common/a3700_ea.c b/plat/marvell/armada/a3k/common/a3700_ea.c
new file mode 100644
index 0000000..5696b5c
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/a3700_ea.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 Repk repk@triplefau.lt
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+#include <bl31/ea_handle.h>
+
+#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002
+
+/*
+ * This source file with custom plat_ea_handler function is compiled only when
+ * building TF-A with compile option HANDLE_EA_EL3_FIRST_NS=1
+ */
+void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags)
+{
+ unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
+
+ /*
+ * Asynchronous External Abort with syndrome 0xbf000002 on Cortex A53
+ * core means SError interrupt caused by AXI SLVERR on external access.
+ *
+ * In most cases this indicates a bug in U-Boot or Linux kernel driver
+ * pci-aardvark.c which implements access to A3700 PCIe config space.
+ * Driver does not wait for PCIe PIO transfer completion and try to
+ * start a new PCIe PIO transfer while previous has not finished yet.
+ * A3700 PCIe controller in this case sends SLVERR via AXI which results
+ * in a fatal Asynchronous SError interrupt on Cortex A53 CPU.
+ *
+ * Following patches fix that bug in U-Boot and Linux kernel drivers:
+ * https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01
+ * https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7
+ *
+ * As a hacky workaround for unpatched U-Boot and Linux kernel drivers
+ * ignore all asynchronous aborts with that syndrome value received on
+ * CPU from level lower than EL3.
+ *
+ * Because these aborts are delivered on CPU asynchronously, they are
+ * imprecise and we cannot check the real reason of abort and neither
+ * who and why sent this abort. We expect that on A3700 it is always
+ * PCIe controller.
+ *
+ * Hence ignoring all aborts with this syndrome value is just a giant
+ * hack that we need only because of bugs in old U-Boot and Linux kernel
+ * versions and because it was decided that TF-A would implement this
+ * hack for U-Boot and Linux kernel it in this way. New patched U-Boot
+ * and kernel versions do not need it anymore.
+ *
+ * Links to discussion about this workaround:
+ * https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/
+ * https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/
+ * https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541
+ */
+ if (level < MODE_EL3 && ea_reason == ERROR_EA_ASYNC &&
+ syndrome == A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS) {
+ ERROR_NL();
+ ERROR("Ignoring Asynchronous External Abort with"
+ " syndrome 0x%" PRIx64 " received on 0x%lx from %s\n",
+ syndrome, read_mpidr_el1(), get_el_str(level));
+ ERROR("SError interrupt: AXI SLVERR on external access\n");
+ ERROR("This indicates a bug in pci-aardvark.c driver\n");
+ ERROR("Please update U-Boot/Linux to the latest version\n");
+ ERROR_NL();
+ console_flush();
+ return;
+ }
+
+ plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+}
diff --git a/plat/marvell/armada/a3k/common/a3700_sip_svc.c b/plat/marvell/armada/a3k/common/a3700_sip_svc.c
new file mode 100644
index 0000000..e8ac5fc
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/a3700_sip_svc.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/smccc.h>
+
+#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
+
+#include "comphy/phy-comphy-3700.h"
+
+/* Comphy related FID's */
+#define MV_SIP_COMPHY_POWER_ON 0x82000001
+#define MV_SIP_COMPHY_POWER_OFF 0x82000002
+#define MV_SIP_COMPHY_PLL_LOCK 0x82000003
+
+/* Miscellaneous FID's' */
+#define MV_SIP_DRAM_SIZE 0x82000010
+
+/* This macro is used to identify COMPHY related calls from SMC function ID */
+#define is_comphy_fid(fid) \
+ ((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_PLL_LOCK)
+
+uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ u_register_t ret;
+
+ VERBOSE("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx\n",
+ __func__, smc_fid, x1, x2);
+ if (is_comphy_fid(smc_fid)) {
+ if (x1 >= MAX_LANE_NR) {
+ ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n",
+ __func__, smc_fid, x2);
+ SMC_RET1(handle, SMC_UNK);
+ }
+ }
+
+ switch (smc_fid) {
+ /* Comphy related FID's */
+ case MV_SIP_COMPHY_POWER_ON:
+ /* x1: comphy_index, x2: comphy_mode */
+ ret = mvebu_3700_comphy_power_on(x1, x2);
+ SMC_RET1(handle, ret);
+ case MV_SIP_COMPHY_POWER_OFF:
+ /* x1: comphy_index, x2: comphy_mode */
+ ret = mvebu_3700_comphy_power_off(x1, x2);
+ SMC_RET1(handle, ret);
+ case MV_SIP_COMPHY_PLL_LOCK:
+ /* x1: comphy_index, x2: comphy_mode */
+ ret = mvebu_3700_comphy_is_pll_locked(x1, x2);
+ SMC_RET1(handle, ret);
+ /* Miscellaneous FID's' */
+ case MV_SIP_DRAM_SIZE:
+ /* x1: ap_base_addr */
+ ret = mvebu_get_dram_size(MVEBU_REGS_BASE);
+ SMC_RET1(handle, ret);
+
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ marvell_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ mrvl_sip_smc_handler
+);
diff --git a/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S b/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S
new file mode 100644
index 0000000..f79516f
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+
+/*
+ * Below address in used only for reading, therefore no problem with concurrent
+ * Linux access.
+ */
+#define MVEBU_TEST_PIN_LATCH_N (MVEBU_NB_GPIO_REG_BASE + 0x8)
+ #define MVEBU_XTAL_MODE_MASK BIT(9)
+
+ /* -----------------------------------------------------
+ * uint32_t get_ref_clk (void);
+ *
+ * returns reference clock in MHz (25 or 40)
+ * -----------------------------------------------------
+ */
+.globl get_ref_clk
+func get_ref_clk
+ mov_imm x0, MVEBU_TEST_PIN_LATCH_N
+ ldr w0, [x0]
+ tst w0, #MVEBU_XTAL_MODE_MASK
+ bne 40
+ mov w0, #25
+ ret
+40:
+ mov w0, #40
+ ret
+endfunc get_ref_clk
diff --git a/plat/marvell/armada/a3k/common/aarch64/a3700_common.c b/plat/marvell/armada/a3k/common/aarch64/a3700_common.c
new file mode 100644
index 0000000..6351285
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/aarch64/a3700_common.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+#include <plat_marvell.h>
+
+/* MMU entry for internal (register) space access */
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SHARED_RAM,
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+#if IMAGE_BL2
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SHARED_RAM,
+ MAP_DEVICE0,
+ MARVELL_MAP_DRAM,
+ {0}
+};
+#endif
+#if IMAGE_BL2U
+const mmap_region_t plat_marvell_mmap[] = {
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+#if IMAGE_BL31
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SHARED_RAM,
+ MAP_DEVICE0,
+ MARVELL_MAP_DRAM,
+ {0}
+};
+#endif
+#if IMAGE_BL32
+const mmap_region_t plat_marvell_mmap[] = {
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+
+MARVELL_CASSERT_MMAP;
diff --git a/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S b/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..90d76f0
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset. Right
+ * now this is a stub function.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ mov x0, #0
+ ret
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between cold and warm boot
+ * For a cold boot, return 0.
+ * For a warm boot, read the mailbox and return the address it contains.
+ * A magic number is placed before entrypoint to avoid mistake caused by
+ * uninitialized mailbox data area.
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* Read first word and compare it with magic num */
+ mov_imm x0, PLAT_MARVELL_MAILBOX_BASE
+ ldr x1, [x0]
+ mov_imm x2, PLAT_MARVELL_MAILBOX_MAGIC_NUM
+ cmp x1, x2
+ /* If compare failed, return 0, i.e. cold boot */
+ beq entrypoint
+ mov x0, #0
+ ret
+entrypoint:
+ /* Second word contains the jump address */
+ add x0, x0, #8
+ ldr x0, [x0]
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #MVEBU_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/marvell/armada/a3k/common/cm3_system_reset.c b/plat/marvell/armada/a3k/common/cm3_system_reset.c
new file mode 100644
index 0000000..f105d59
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/cm3_system_reset.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 Marek Behun, CZ.NIC
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mvebu_def.h>
+
+/* Cortex-M3 Secure Processor Mailbox Registers */
+#define MVEBU_RWTM_PARAM0_REG (MVEBU_RWTM_REG_BASE)
+#define MVEBU_RWTM_CMD_REG (MVEBU_RWTM_REG_BASE + 0x40)
+#define MVEBU_RWTM_HOST_INT_RESET_REG (MVEBU_RWTM_REG_BASE + 0xC8)
+#define MVEBU_RWTM_HOST_INT_MASK_REG (MVEBU_RWTM_REG_BASE + 0xCC)
+#define MVEBU_RWTM_HOST_INT_SP_COMPLETE BIT(0)
+
+#define MVEBU_RWTM_REBOOT_CMD 0x0009
+#define MVEBU_RWTM_REBOOT_MAGIC 0xDEADBEEF
+
+static inline bool rwtm_completed(void)
+{
+ return (mmio_read_32(MVEBU_RWTM_HOST_INT_RESET_REG) &
+ MVEBU_RWTM_HOST_INT_SP_COMPLETE) != 0;
+}
+
+static bool rwtm_wait(int ms)
+{
+ while (ms && !rwtm_completed()) {
+ mdelay(1);
+ --ms;
+ }
+
+ return rwtm_completed();
+}
+
+void cm3_system_reset(void)
+{
+ int tries = 5;
+
+ for (; tries > 0; --tries) {
+ mmio_clrbits_32(MVEBU_RWTM_HOST_INT_RESET_REG,
+ MVEBU_RWTM_HOST_INT_SP_COMPLETE);
+
+ mmio_write_32(MVEBU_RWTM_PARAM0_REG, MVEBU_RWTM_REBOOT_MAGIC);
+ mmio_write_32(MVEBU_RWTM_CMD_REG, MVEBU_RWTM_REBOOT_CMD);
+
+ if (rwtm_wait(10)) {
+ break;
+ }
+
+ mdelay(100);
+ }
+
+ /* If we reach here, the command is not implemented. */
+ WARN("System reset command not implemented in WTMI firmware!\n");
+}
diff --git a/plat/marvell/armada/a3k/common/dram_win.c b/plat/marvell/armada/a3k/common/dram_win.c
new file mode 100644
index 0000000..9d7b3a9
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/dram_win.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2018-2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <string.h>
+
+#include <lib/mmio.h>
+
+#include <dram_win.h>
+#include <marvell_plat_priv.h>
+#include <mvebu.h>
+#include <plat_marvell.h>
+
+/* Armada 3700 has 5 configurable windows */
+#define MV_CPU_WIN_NUM 5
+
+#define CPU_WIN_DISABLED 0
+#define CPU_WIN_ENABLED 1
+
+/*
+ * There are 2 different cpu decode window configuration cases:
+ * - DRAM size is not over 2GB;
+ * - DRAM size is 4GB.
+ */
+enum cpu_win_config_num {
+ CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB = 0,
+ CPU_WIN_CONFIG_DRAM_4GB,
+ CPU_WIN_CONFIG_MAX
+};
+
+enum cpu_win_target {
+ CPU_WIN_TARGET_DRAM = 0,
+ CPU_WIN_TARGET_INTERNAL_REG,
+ CPU_WIN_TARGET_PCIE,
+ CPU_WIN_TARGET_PCIE_OVER_MCI,
+ CPU_WIN_TARGET_BOOT_ROM,
+ CPU_WIN_TARGET_MCI_EXTERNAL,
+ CPU_WIN_TARGET_RWTM_RAM = 7,
+ CPU_WIN_TARGET_CCI400_REG
+};
+
+struct cpu_win_configuration {
+ uint32_t enabled;
+ enum cpu_win_target target;
+ uint64_t base_addr;
+ uint64_t size;
+ uint64_t remap_addr;
+};
+
+struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = {
+ /*
+ * When total dram size is not over 2GB:
+ * DDR window 0 is configured in tim header, its size may be not 512MB,
+ * but the actual dram size, no need to configure it again;
+ * other cpu windows are kept as default.
+ */
+ {
+ /* enabled
+ * target
+ * base
+ * size
+ * remap
+ */
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_DRAM,
+ 0x0,
+ 0x08000000,
+ 0x0},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_MCI_EXTERNAL,
+ 0xe0000000,
+ 0x08000000,
+ 0xe0000000},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_PCIE,
+ 0xe8000000,
+ 0x08000000,
+ 0xe8000000},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_RWTM_RAM,
+ 0xf0000000,
+ 0x00020000,
+ 0x1fff0000},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_PCIE_OVER_MCI,
+ 0x80000000,
+ 0x10000000,
+ 0x80000000},
+ },
+
+ /*
+ * If total DRAM size is more than 2GB, now there is only one case:
+ * 4GB of DRAM; to better utilize address space (for maximization of
+ * DRAM usage), we will use the configuration of CPU windows below:
+ * - Internal Regs and Boot ROM windows are kept as default;
+ * - CCI-400 is moved from its default address to another address
+ * (this is actually done even if DRAM size is not more than 2 GB,
+ * because the firmware is compiled with that address as a
+ * constant);
+ * - PCIe window is moved to another address;
+ * - Use 4 CPU decode windows for DRAM, which cover 3.75GB DRAM;
+ * DDR window 0 is configured in tim header with 2G B size, no need
+ * to configure it again here;
+ *
+ * 0xFFFFFFFF ---> +-----------------------+
+ * | Boot ROM | 1 MB
+ * | AP Boot ROM - 16 KB: |
+ * | 0xFFFF0000-0xFFFF4000 |
+ * 0xFFF00000 ---> +-----------------------+
+ * : :
+ * 0xFE010000 ---> +-----------------------+
+ * | CCI Regs | 64 KB
+ * 0xFE000000 ---> +-----------------------+
+ * : :
+ * 0xFA000000 ---> +-----------------------+
+ * | PCIE | 128 MB
+ * 0xF2000000 ---> +-----------------------+
+ * | DDR window 3 | 512 MB
+ * 0xD2000000 ---> +-----------------------+
+ * | Internal Regs | 32 MB
+ * 0xD0000000 ---> |-----------------------|
+ * | DDR window 2 | 256 MB
+ * 0xC0000000 ---> |-----------------------|
+ * | |
+ * | DDR window 1 | 1 GB
+ * | |
+ * 0x80000000 ---> |-----------------------|
+ * | |
+ * | |
+ * | DDR window 0 | 2 GB
+ * | |
+ * | |
+ * 0x00000000 ---> +-----------------------+
+ */
+ {
+ /* win_id
+ * target
+ * base
+ * size
+ * remap
+ */
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_DRAM,
+ 0x0,
+ 0x80000000,
+ 0x0},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_DRAM,
+ 0x80000000,
+ 0x40000000,
+ 0x80000000},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_DRAM,
+ 0xc0000000,
+ 0x10000000,
+ 0xc0000000},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_DRAM,
+ 0xd2000000,
+ 0x20000000,
+ 0xd2000000},
+ {CPU_WIN_ENABLED,
+ CPU_WIN_TARGET_PCIE,
+ 0xf2000000,
+ 0x08000000,
+ 0xf2000000},
+ },
+};
+
+/*
+ * dram_win_map_build
+ *
+ * This function builds cpu dram windows mapping
+ * which includes base address and window size by
+ * reading cpu dram decode windows registers.
+ *
+ * @input: N/A
+ *
+ * @output:
+ * - win_map: cpu dram windows mapping
+ *
+ * @return: N/A
+ */
+void dram_win_map_build(struct dram_win_map *win_map)
+{
+ int32_t win_id;
+ struct dram_win *win;
+ uint32_t base_reg, ctrl_reg, size_reg, enabled, target;
+
+ memset(win_map, 0, sizeof(struct dram_win_map));
+ for (win_id = 0; win_id < DRAM_WIN_MAP_NUM_MAX; win_id++) {
+ ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
+ target = (ctrl_reg & CPU_DEC_CR_WIN_TARGET_MASK) >>
+ CPU_DEC_CR_WIN_TARGET_OFFS;
+ enabled = ctrl_reg & CPU_DEC_CR_WIN_ENABLE;
+ /* Ignore invalid and non-dram windows*/
+ if ((enabled == 0) || (target != DRAM_CPU_DEC_TARGET_NUM))
+ continue;
+
+ win = win_map->dram_windows + win_map->dram_win_num;
+ base_reg = mmio_read_32(CPU_DEC_WIN_BASE_REG(win_id));
+ size_reg = mmio_read_32(CPU_DEC_WIN_SIZE_REG(win_id));
+ /* Base reg [15:0] corresponds to transaction address [39:16] */
+ win->base_addr = (base_reg & CPU_DEC_BR_BASE_MASK) >>
+ CPU_DEC_BR_BASE_OFFS;
+ win->base_addr *= CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
+ /*
+ * Size reg [15:0] is programmed from LSB to MSB as a sequence
+ * of 1s followed by a sequence of 0s and the number of 1s
+ * specifies the size of the window in 64 KB granularity,
+ * for example, a value of 00FFh specifies 256 x 64 KB = 16 MB
+ */
+ win->win_size = (size_reg & CPU_DEC_CR_WIN_SIZE_MASK) >>
+ CPU_DEC_CR_WIN_SIZE_OFFS;
+ win->win_size = (win->win_size + 1) *
+ CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
+
+ win_map->dram_win_num++;
+ }
+}
+
+static void cpu_win_set(uint32_t win_id, struct cpu_win_configuration *win_cfg)
+{
+ uint32_t base_reg, ctrl_reg, size_reg, remap_reg;
+
+ /* Disable window */
+ ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
+ ctrl_reg &= ~CPU_DEC_CR_WIN_ENABLE;
+ mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
+
+ /* For an disabled window, only disable it. */
+ if (!win_cfg->enabled)
+ return;
+
+ /* Set Base Register */
+ base_reg = (uint32_t)(win_cfg->base_addr /
+ CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
+ base_reg <<= CPU_DEC_BR_BASE_OFFS;
+ base_reg &= CPU_DEC_BR_BASE_MASK;
+ mmio_write_32(CPU_DEC_WIN_BASE_REG(win_id), base_reg);
+
+ /* Set Remap Register with the same value
+ * as the <Base> field in Base Register
+ */
+ remap_reg = (uint32_t)(win_cfg->remap_addr /
+ CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
+ remap_reg <<= CPU_DEC_RLR_REMAP_LOW_OFFS;
+ remap_reg &= CPU_DEC_RLR_REMAP_LOW_MASK;
+ mmio_write_32(CPU_DEC_REMAP_LOW_REG(win_id), remap_reg);
+
+ /* Set Size Register */
+ size_reg = (win_cfg->size / CPU_DEC_CR_WIN_SIZE_ALIGNMENT) - 1;
+ size_reg <<= CPU_DEC_CR_WIN_SIZE_OFFS;
+ size_reg &= CPU_DEC_CR_WIN_SIZE_MASK;
+ mmio_write_32(CPU_DEC_WIN_SIZE_REG(win_id), size_reg);
+
+ /* Set Control Register - set target id and enable window */
+ ctrl_reg &= ~CPU_DEC_CR_WIN_TARGET_MASK;
+ ctrl_reg |= (win_cfg->target << CPU_DEC_CR_WIN_TARGET_OFFS);
+ ctrl_reg |= CPU_DEC_CR_WIN_ENABLE;
+ mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
+}
+
+void cpu_wins_init(void)
+{
+ uint32_t cfg_idx, win_id;
+
+ if (mvebu_get_dram_size(MVEBU_REGS_BASE) <= _2GB_)
+ cfg_idx = CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB;
+ else
+ cfg_idx = CPU_WIN_CONFIG_DRAM_4GB;
+
+ /* Window 0 is configured always for DRAM in tim header
+ * already, no need to configure it again here
+ */
+ for (win_id = 1; win_id < MV_CPU_WIN_NUM; win_id++)
+ cpu_win_set(win_id, &mv_cpu_wins[cfg_idx][win_id]);
+}
+
diff --git a/plat/marvell/armada/a3k/common/include/a3700_plat_def.h b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h
new file mode 100644
index 0000000..4d45e15
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2018-2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef A3700_PLAT_DEF_H
+#define A3700_PLAT_DEF_H
+
+#include <marvell_def.h>
+
+
+#define MVEBU_MAX_CPUS_PER_CLUSTER 2
+
+#define MVEBU_PRIMARY_CPU 0x0
+
+/*
+ * The counter on A3700 is always fed from reference 25M clock (XTAL).
+ * However minimal CPU counter prescaler is 2, so the counter
+ * frequency will be divided by 2, the number is 12.5M
+ */
+#define COUNTER_FREQUENCY 12500000
+
+#define MVEBU_REGS_BASE 0xD0000000
+
+/*****************************************************************************
+ * MVEBU memory map related constants
+ *****************************************************************************
+ */
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE MVEBU_REGS_BASE
+#define DEVICE0_SIZE 0x10000000
+
+/*****************************************************************************
+ * GIC-500 & interrupt handling related constants
+ *****************************************************************************
+ */
+/* Base MVEBU compatible GIC memory map */
+#define MVEBU_GICD_BASE 0x1D00000
+#define MVEBU_GICR_BASE 0x1D40000
+#define MVEBU_GICC_BASE 0x1D80000
+
+/*
+ * CCI-400 base address
+ * This address is absolute, not relative to MVEBU_REGS_BASE.
+ * This is not the default CCI base address (that would be 0xD8000000).
+ * Rather we remap CCI to this address to better utilize the address space.
+ * (The remapping is done in plat/marvell/armada/a3k/common/plat_cci.c)
+ */
+#define MVEBU_CCI_BASE 0xFE000000
+
+/*****************************************************************************
+ * North and south bridge reset registers
+ *****************************************************************************
+ */
+#define MVEBU_NB_RESET_REG (MVEBU_REGS_BASE + 0x12400)
+#define MVEBU_NB_RESET_I2C1_N (1 << 0)
+#define MVEBU_NB_RESET_1WIRE_N (1 << 1)
+#define MVEBU_NB_RESET_SPI_N (1 << 2)
+#define MVEBU_NB_RESET_UART_N (1 << 3)
+#define MVEBU_NB_RESET_XTL_N (1 << 4)
+#define MVEBU_NB_RESET_I2C2_N (1 << 5)
+#define MVEBU_NB_RESET_UART2_N (1 << 6)
+#define MVEBU_NB_RESET_AVS_N (1 << 7)
+#define MVEBU_NB_RESET_DDR_N (1 << 10)
+#define MVEBU_NB_RESET_SETM_N (1 << 11)
+#define MVEBU_NB_RESET_DMA_N (1 << 12)
+#define MVEBU_NB_RESET_TSECM_N (1 << 13)
+#define MVEBU_NB_RESET_SDIO_N (1 << 14)
+#define MVEBU_NB_RESET_SATA_N (1 << 15)
+#define MVEBU_NB_RESET_PWRMGT_N (1 << 16)
+#define MVEBU_NB_RESET_OTP_N (1 << 17)
+#define MVEBU_NB_RESET_EIP_N (1 << 18)
+#define MVEBU_SB_RESET_REG (MVEBU_REGS_BASE + 0x18600)
+#define MVEBU_SB_RESET_MCIPHY (1 << 1)
+#define MVEBU_SB_RESET_SDIO_N (1 << 2)
+#define MVEBU_SB_RESET_PCIE_N (1 << 3)
+#define MVEBU_SB_RESET_GBE1_N (1 << 4)
+#define MVEBU_SB_RESET_GBE0_N (1 << 5)
+#define MVEBU_SB_RESET_USB2PHY (1 << 6)
+#define MVEBU_SB_RESET_USB2HPHY (1 << 7)
+#define MVEBU_SB_RESET_MCI_N (1 << 8)
+#define MVEBU_SB_RESET_PWRMGT_N (1 << 9)
+#define MVEBU_SB_RESET_EBM_N (1 << 10)
+#define MVEBU_SB_RESET_OTP_N (1 << 11)
+
+/*****************************************************************************
+ * North and south bridge register base
+ *****************************************************************************
+ */
+#define MVEBU_NB_REGS_BASE (MVEBU_REGS_BASE + 0x13000)
+#define MVEBU_SB_REGS_BASE (MVEBU_REGS_BASE + 0x18000)
+
+/*****************************************************************************
+ * GPIO registers related constants
+ *****************************************************************************
+ */
+/* North and south bridge GPIO register base address */
+#define MVEBU_NB_GPIO_REG_BASE (MVEBU_NB_REGS_BASE + 0x800)
+#define MVEBU_NB_GPIO_IRQ_REG_BASE (MVEBU_NB_REGS_BASE + 0xC00)
+#define MVEBU_SB_GPIO_REG_BASE (MVEBU_SB_REGS_BASE + 0x800)
+#define MVEBU_SB_GPIO_IRQ_REG_BASE (MVEBU_SB_REGS_BASE + 0xC00)
+#define MVEBU_NB_SB_IRQ_REG_BASE (MVEBU_REGS_BASE + 0x8A00)
+
+/* North Bridge GPIO selection register */
+#define MVEBU_NB_GPIO_SEL_REG (MVEBU_NB_GPIO_REG_BASE + 0x30)
+#define MVEBU_NB_GPIO_OUTPUT_EN_HIGH_REG (MVEBU_NB_GPIO_REG_BASE + 0x04)
+/* I2C1 GPIO Enable bit offset */
+#define MVEBU_GPIO_TW1_GPIO_EN_OFF (10)
+/* SPI pins mode bit offset */
+#define MVEBU_GPIO_NB_SPI_PIN_MODE_OFF (28)
+
+/*****************************************************************************
+ * DRAM registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_DRAM_REG_BASE (MVEBU_REGS_BASE)
+
+/*****************************************************************************
+ * SB wake-up registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_SB_WAKEUP_REG_BASE (MVEBU_REGS_BASE + 0x19000)
+
+/*****************************************************************************
+ * PMSU registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_PMSU_REG_BASE (MVEBU_REGS_BASE + 0x14000)
+
+/*****************************************************************************
+ * North Bridge Step-Down Registers
+ *****************************************************************************
+ */
+#define MVEBU_NB_STEP_DOWN_REG_BASE (MVEBU_REGS_BASE + 0x12800)
+
+/*****************************************************************************
+ * DRAM CS memory map register base
+ *****************************************************************************
+ */
+#define MVEBU_CS_MMAP_REG_BASE (MVEBU_REGS_BASE + 0x200)
+
+/*****************************************************************************
+ * CPU decoder window registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_CPU_DEC_WIN_REG_BASE (MVEBU_REGS_BASE + 0xCF00)
+
+/*****************************************************************************
+ * AVS registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_AVS_REG_BASE (MVEBU_REGS_BASE + 0x11500)
+
+
+/*****************************************************************************
+ * AVS registers related constants
+ *****************************************************************************
+ */
+#define MVEBU_COMPHY_REG_BASE (MVEBU_REGS_BASE + 0x18300)
+
+/*****************************************************************************
+ * Cortex-M3 Secure Processor Mailbox constants
+ *****************************************************************************
+ */
+#define MVEBU_RWTM_REG_BASE (MVEBU_REGS_BASE + 0xB0000)
+
+#endif /* A3700_PLAT_DEF_H */
diff --git a/plat/marvell/armada/a3k/common/include/a3700_pm.h b/plat/marvell/armada/a3k/common/include/a3700_pm.h
new file mode 100644
index 0000000..44dbb9f
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/include/a3700_pm.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016-2020 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef A3700_PM_H
+#define A3700_PM_H
+
+#include <stdint.h>
+
+/* supported wake up sources */
+enum pm_wake_up_src_type {
+ WAKE_UP_SRC_GPIO,
+ /* FOLLOWING SRC NOT SUPPORTED YET */
+ WAKE_UP_SRC_TIMER,
+ WAKE_UP_SRC_UART0,
+ WAKE_UP_SRC_UART1,
+ WAKE_UP_SRC_MAX,
+};
+
+struct pm_gpio_data {
+ /*
+ * bank 0: North bridge GPIO
+ * bank 1: South bridge GPIO
+ */
+ uint32_t bank_num;
+ uint32_t gpio_num;
+};
+
+union pm_wake_up_src_data {
+ struct pm_gpio_data gpio_data;
+ /* delay in seconds */
+ uint32_t timer_delay;
+};
+
+struct pm_wake_up_src {
+ enum pm_wake_up_src_type wake_up_src_type;
+
+ union pm_wake_up_src_data wake_up_data;
+};
+
+struct pm_wake_up_src_config {
+ uint32_t wake_up_src_num;
+ struct pm_wake_up_src wake_up_src[WAKE_UP_SRC_MAX];
+};
+
+struct pm_wake_up_src_config *mv_wake_up_src_config_get(void);
+
+void cm3_system_reset(void);
+
+#endif /* A3700_PM_H */
diff --git a/plat/marvell/armada/a3k/common/include/ddr_info.h b/plat/marvell/armada/a3k/common/include/ddr_info.h
new file mode 100644
index 0000000..254f78c
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/include/ddr_info.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef DDR_INFO_H
+#define DDR_INFO_H
+
+#define DRAM_MAX_IFACE 1
+#define DRAM_CH0_MMAP_LOW_OFFSET 0x200
+
+#endif /* DDR_INFO_H */
diff --git a/plat/marvell/armada/a3k/common/include/dram_win.h b/plat/marvell/armada/a3k/common/include/dram_win.h
new file mode 100644
index 0000000..26a0137
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/include/dram_win.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef DRAM_WIN_H
+#define DRAM_WIN_H
+
+#include <common/bl_common.h>
+
+#include <io_addr_dec.h>
+
+void dram_win_map_build(struct dram_win_map *win_map);
+void cpu_wins_init(void);
+
+#endif /* DRAM_WIN_H */
diff --git a/plat/marvell/armada/a3k/common/include/io_addr_dec.h b/plat/marvell/armada/a3k/common/include/io_addr_dec.h
new file mode 100644
index 0000000..42ef30b
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/include/io_addr_dec.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef IO_ADDR_DEC_H
+#define IO_ADDR_DEC_H
+
+#include <stdint.h>
+
+/* There are 5 configurable cpu decoder windows. */
+#define DRAM_WIN_MAP_NUM_MAX 5
+/* Target number for dram in cpu decoder windows. */
+#define DRAM_CPU_DEC_TARGET_NUM 0
+
+/*
+ * Not all configurable decode windows could be used for dram, some units have
+ * to reserve one decode window for other unit they have to communicate with;
+ * for example, DMA engineer has 3 configurable windows, but only two could be
+ * for dram while the last one has to be for pcie, so for DMA, its max_dram_win
+ * is 2.
+ */
+struct dec_win_config {
+ uint32_t dec_reg_base; /* IO address decoder register base address */
+ uint32_t win_attr; /* IO address decoder windows attributes */
+ /* How many configurable dram decoder windows that this unit has; */
+ uint32_t max_dram_win;
+ /* The decoder windows number including remapping that this unit has */
+ uint32_t max_remap;
+ /* The offset between continuous decode windows
+ * within the same unit, typically 0x10
+ */
+ uint32_t win_offset;
+};
+
+struct dram_win {
+ uintptr_t base_addr;
+ uintptr_t win_size;
+};
+
+struct dram_win_map {
+ int dram_win_num;
+ struct dram_win dram_windows[DRAM_WIN_MAP_NUM_MAX];
+};
+
+/*
+ * init_io_addr_dec
+ *
+ * This function initializes io address decoder windows by
+ * cpu dram window mapping information
+ *
+ * @input: N/A
+ * - dram_wins_map: cpu dram windows mapping
+ * - io_dec_config: io address decoder windows configuration
+ * - io_unit_num: io address decoder unit number
+ * @output: N/A
+ *
+ * @return: 0 on success and others on failure
+ */
+int init_io_addr_dec(struct dram_win_map *dram_wins_map,
+ struct dec_win_config *io_dec_config,
+ uint32_t io_unit_num);
+
+#endif /* IO_ADDR_DEC_H */
diff --git a/plat/marvell/armada/a3k/common/include/plat_macros.S b/plat/marvell/armada/a3k/common/include/plat_macros.S
new file mode 100644
index 0000000..f689b4f
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/include/plat_macros.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <marvell_macros.S>
+
+/* ---------------------------------------------
+ * The below macro prints out relevant GIC and
+ * CCI registers registers whenever an unhandled
+ * exception is taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+ mov_imm x17, MVEBU_GICC_BASE
+ mov_imm x16, MVEBU_GICD_BASE
+ marvell_print_gic_regs
+ print_cci_regs
+.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/marvell/armada/a3k/common/include/platform_def.h b/plat/marvell/armada/a3k/common/include/platform_def.h
new file mode 100644
index 0000000..f19d96b
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/include/platform_def.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2016-2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#ifndef __ASSEMBLER__
+#include <stdio.h>
+#endif /* __ASSEMBLER__ */
+
+#include <board_marvell_def.h>
+#include <mvebu_def.h>
+
+/*
+ * Most platform porting definitions provided by included headers
+ */
+
+/*
+ * DRAM Memory layout:
+ * +-----------------------+
+ * : :
+ * : Linux :
+ * 0x04X00000-->+-----------------------+
+ * | BL3-3(u-boot) |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ * |-----------------------| } |
+ * | BL3-[0,1, 2] | }---------------------------------> |
+ * |-----------------------| } || |
+ * | BL2 | }->FIP (loaded by || |
+ * |-----------------------| } BootROM to DRAM) || |
+ * | FIP_TOC | } || |
+ * 0x04120000-->|-----------------------| || |
+ * | BL1 (RO) | || |
+ * 0x04100000-->+-----------------------+ || |
+ * : : || |
+ * : Trusted SRAM section : \/ |
+ * 0x04040000-->+-----------------------+ Replaced by BL2 +----------------+ |
+ * | BL1 (RW) | <<<<<<<<<<<<<<<< | BL3-1 NOBITS | |
+ * 0x04037000-->|-----------------------| <<<<<<<<<<<<<<<< |----------------| |
+ * | | <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | |
+ * 0x04023000-->|-----------------------| +----------------+ |
+ * | BL2 | |
+ * |-----------------------| |
+ * | | |
+ * 0x04001000-->|-----------------------| |
+ * | Shared | |
+ * 0x04000000-->+-----------------------+ |
+ * : : |
+ * : Linux : |
+ * : : |
+ * |-----------------------| |
+ * | | U-Boot(BL3-3) Loaded by BL2 |
+ * | U-Boot | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ * 0x00000000-->+-----------------------+
+ *
+ * Trusted SRAM section 0x4000000..0x4200000:
+ * ----------------------------------------
+ * SRAM_BASE = 0x4001000
+ * BL2_BASE = 0x4006000
+ * BL2_LIMIT = BL31_BASE
+ * BL31_BASE = 0x4023000 = (64MB + 256KB - 0x1D000)
+ * BL31_PROGBITS_LIMIT = BL1_RW_BASE
+ * BL1_RW_BASE = 0x4037000 = (64MB + 256KB - 0x9000)
+ * BL1_RW_LIMIT = BL31_LIMIT = 0x4040000
+ *
+ *
+ * PLAT_MARVELL_FIP_BASE = 0x4120000
+ */
+
+/*
+ * Since BL33 is loaded by BL2 (and validated by BL31) to DRAM offset 0,
+ * it is allowed to load/copy images to 'NULL' pointers
+ */
+#if defined(IMAGE_BL2) || defined(IMAGE_BL31)
+#define PLAT_ALLOW_ZERO_ADDR_COPY
+#endif
+
+#define PLAT_MARVELL_ATF_BASE 0x4000000
+#define PLAT_MARVELL_ATF_LOAD_ADDR \
+ (PLAT_MARVELL_ATF_BASE + 0x100000)
+
+#define PLAT_MARVELL_FIP_BASE \
+ (PLAT_MARVELL_ATF_LOAD_ADDR + 0x20000)
+#define PLAT_MARVELL_FIP_MAX_SIZE 0x4000000
+
+#define PLAT_MARVELL_CLUSTER_CORE_COUNT U(2)
+/* DRAM[2MB..66MB] is used as Trusted ROM */
+#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR
+/* 4 MB for FIP image */
+#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000
+/* Reserve 12M for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE SHMEM follows this region
+ */
+#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_MARVELL_MAX_BL1_RW_SIZE 0xA000
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_MARVELL_MAX_BL2_SIZE 0xF000
+
+/*
+ * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_MARVEL_MAX_BL31_SIZE 0x5D000
+
+#define PLAT_MARVELL_CPU_ENTRY_ADDR BL1_RO_BASE
+
+/* GIC related definitions */
+#define PLAT_MARVELL_GICD_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE)
+#define PLAT_MARVELL_GICR_BASE (MVEBU_REGS_BASE + MVEBU_GICR_BASE)
+#define PLAT_MARVELL_GICC_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE)
+
+#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, \
+ GIC_HIGHEST_SEC_PRIORITY, grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+
+#define PLAT_MARVELL_SHARED_RAM_CACHED 1
+
+/* CCI related constants */
+#define PLAT_MARVELL_CCI_BASE MVEBU_CCI_BASE
+#define PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX 3
+#define PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX 4
+
+/*
+ * Load address of BL3-3 for this platform port
+ */
+#define PLAT_MARVELL_NS_IMAGE_OFFSET 0x0
+
+/* System Reference Clock*/
+#define PLAT_REF_CLK_IN_HZ COUNTER_FREQUENCY
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_MARVELL_UART_BASE (MVEBU_REGS_BASE + 0x12000)
+
+/* Required platform porting definitions */
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+
+/* System timer related constants */
+#define PLAT_MARVELL_NSTIMER_FRAME_ID 1
+
+/* Mailbox base address */
+#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE + 0x400)
+#define PLAT_MARVELL_MAILBOX_SIZE 0x100
+#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */
+
+/* DRAM CS memory map registers related constants */
+#define MVEBU_CS_MMAP_LOW(cs_num) \
+ (MVEBU_CS_MMAP_REG_BASE + (cs_num) * 0x8)
+#define MVEBU_CS_MMAP_ENABLE 0x1
+#define MVEBU_CS_MMAP_AREA_LEN_OFFS 16
+#define MVEBU_CS_MMAP_AREA_LEN_MASK \
+ (0x1f << MVEBU_CS_MMAP_AREA_LEN_OFFS)
+#define MVEBU_CS_MMAP_START_ADDR_LOW_OFFS 23
+#define MVEBU_CS_MMAP_START_ADDR_LOW_MASK \
+ (0x1ff << MVEBU_CS_MMAP_START_ADDR_LOW_OFFS)
+
+#define MVEBU_CS_MMAP_HIGH(cs_num) \
+ (MVEBU_CS_MMAP_REG_BASE + 0x4 + (cs_num) * 0x8)
+
+/* DRAM max CS number */
+#define MVEBU_MAX_CS_MMAP_NUM (2)
+
+/* CPU decoder window related constants */
+#define CPU_DEC_WIN_CTRL_REG(win_num) \
+ (MVEBU_CPU_DEC_WIN_REG_BASE + (win_num) * 0x10)
+#define CPU_DEC_CR_WIN_ENABLE 0x1
+#define CPU_DEC_CR_WIN_TARGET_OFFS 4
+#define CPU_DEC_CR_WIN_TARGET_MASK \
+ (0xf << CPU_DEC_CR_WIN_TARGET_OFFS)
+
+#define CPU_DEC_WIN_SIZE_REG(win_num) \
+ (MVEBU_CPU_DEC_WIN_REG_BASE + 0x4 + (win_num) * 0x10)
+#define CPU_DEC_CR_WIN_SIZE_OFFS 0
+#define CPU_DEC_CR_WIN_SIZE_MASK \
+ (0xffff << CPU_DEC_CR_WIN_SIZE_OFFS)
+#define CPU_DEC_CR_WIN_SIZE_ALIGNMENT 0x10000
+
+#define CPU_DEC_WIN_BASE_REG(win_num) \
+ (MVEBU_CPU_DEC_WIN_REG_BASE + 0x8 + (win_num) * 0x10)
+#define CPU_DEC_BR_BASE_OFFS 0
+#define CPU_DEC_BR_BASE_MASK \
+ (0xffff << CPU_DEC_BR_BASE_OFFS)
+
+#define CPU_DEC_REMAP_LOW_REG(win_num) \
+ (MVEBU_CPU_DEC_WIN_REG_BASE + 0xC + (win_num) * 0x10)
+#define CPU_DEC_RLR_REMAP_LOW_OFFS 0
+#define CPU_DEC_RLR_REMAP_LOW_MASK \
+ (0xffff << CPU_DEC_BR_BASE_OFFS)
+
+#define CPU_DEC_CCI_BASE_REG (MVEBU_CPU_DEC_WIN_REG_BASE + 0xe0)
+
+/* Securities */
+#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/marvell/armada/a3k/common/io_addr_dec.c b/plat/marvell/armada/a3k/common/io_addr_dec.c
new file mode 100644
index 0000000..fea7f81
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/io_addr_dec.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <io_addr_dec.h>
+#include <plat_marvell.h>
+
+#define MVEBU_DEC_WIN_CTRL_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
+ (win) * (off))
+#define MVEBU_DEC_WIN_BASE_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
+ (win) * (off) + 0x4)
+#define MVEBU_DEC_WIN_REMAP_REG(base, win, off) (MVEBU_REGS_BASE + (base) + \
+ (win) * (off) + 0x8)
+
+#define MVEBU_DEC_WIN_CTRL_SIZE_OFF (16)
+#define MVEBU_DEC_WIN_ENABLE (0x1)
+#define MVEBU_DEC_WIN_CTRL_ATTR_OFF (8)
+#define MVEBU_DEC_WIN_CTRL_TARGET_OFF (4)
+#define MVEBU_DEC_WIN_CTRL_EN_OFF (0)
+#define MVEBU_DEC_WIN_BASE_OFF (16)
+
+#define MVEBU_WIN_BASE_SIZE_ALIGNMENT (0x10000)
+
+/* There are up to 14 IO unit which need address decode in Armada-3700 */
+#define IO_UNIT_NUM_MAX (14)
+
+#define MVEBU_MAX_ADDRSS_4GB (0x100000000ULL)
+
+
+static void set_io_addr_dec_win(int win_id, uintptr_t base_addr,
+ uintptr_t win_size,
+ struct dec_win_config *dec_win)
+{
+ uint32_t ctrl = 0;
+ uint32_t base = 0;
+
+ /* set size */
+ ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) <<
+ MVEBU_DEC_WIN_CTRL_SIZE_OFF;
+ /* set attr according to IO decode window */
+ ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF;
+ /* set target */
+ ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF;
+ /* set base */
+ base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) <<
+ MVEBU_DEC_WIN_BASE_OFF;
+
+ /* set base address*/
+ mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
+ win_id, dec_win->win_offset),
+ base);
+ /* set remap window, some unit does not have remap window */
+ if (win_id < dec_win->max_remap)
+ mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
+ win_id, dec_win->win_offset), base);
+ /* set control register */
+ mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
+ win_id, dec_win->win_offset), ctrl);
+ /* enable the address decode window at last to make it effective */
+ ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF;
+ mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
+ win_id, dec_win->win_offset), ctrl);
+
+ INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n",
+ win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
+ win_id, dec_win->win_offset)),
+ mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
+ win_id, dec_win->win_offset)),
+ (win_id < dec_win->max_remap) ?
+ mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
+ win_id, dec_win->win_offset)) : 0);
+}
+
+/* Set io decode window */
+static int set_io_addr_dec(struct dram_win_map *win_map,
+ struct dec_win_config *dec_win)
+{
+ struct dram_win *win;
+ int id;
+
+ /* disable all windows first */
+ for (id = 0; id < dec_win->max_dram_win; id++)
+ mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id,
+ dec_win->win_offset), 0);
+
+ /* configure IO decode windows for DRAM, inheritate DRAM size,
+ * base and target from CPU-DRAM decode window and others
+ * from hard coded IO decode window settings array.
+ */
+ if (win_map->dram_win_num > dec_win->max_dram_win) {
+ /*
+ * If cpu dram windows number exceeds the io decode windows
+ * max number, then fill the first io decode window
+ * with base(0) and size(4GB).
+ */
+ set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win);
+
+ return 0;
+ }
+
+ for (id = 0; id < win_map->dram_win_num; id++, win++) {
+ win = &win_map->dram_windows[id];
+ set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win);
+ }
+
+ return 0;
+}
+
+/*
+ * init_io_addr_dec
+ *
+ * This function initializes io address decoder windows by
+ * cpu dram window mapping information
+ *
+ * @input: N/A
+ * - dram_wins_map: cpu dram windows mapping
+ * - io_dec_config: io address decoder windows configuration
+ * - io_unit_num: io address decoder unit number
+ * @output: N/A
+ *
+ * @return: 0 on success and others on failure
+ */
+int init_io_addr_dec(struct dram_win_map *dram_wins_map,
+ struct dec_win_config *io_dec_config, uint32_t io_unit_num)
+{
+ int32_t index;
+ struct dec_win_config *io_dec_win;
+ int32_t ret;
+
+ INFO("Initializing IO address decode windows\n");
+
+ if (io_dec_config == NULL || io_unit_num == 0) {
+ ERROR("No IO address decoder windows configurations!\n");
+ return -1;
+ }
+
+ if (io_unit_num > IO_UNIT_NUM_MAX) {
+ ERROR("IO address decoder windows number %d is over max %d\n",
+ io_unit_num, IO_UNIT_NUM_MAX);
+ return -1;
+ }
+
+ if (dram_wins_map == NULL) {
+ ERROR("No cpu dram decoder windows map!\n");
+ return -1;
+ }
+
+ for (index = 0; index < dram_wins_map->dram_win_num; index++)
+ INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n",
+ index, dram_wins_map->dram_windows[index].base_addr,
+ dram_wins_map->dram_windows[index].win_size);
+
+ /* Set address decode window for each IO */
+ for (index = 0; index < io_unit_num; index++) {
+ io_dec_win = io_dec_config + index;
+ ret = set_io_addr_dec(dram_wins_map, io_dec_win);
+ if (ret) {
+ ERROR("Failed to set IO address decode\n");
+ return -1;
+ }
+ INFO("Set IO decode window successfully, base(0x%x)"
+ " win_attr(%x) max_dram_win(%d) max_remap(%d)"
+ " win_offset(%d)\n", io_dec_win->dec_reg_base,
+ io_dec_win->win_attr, io_dec_win->max_dram_win,
+ io_dec_win->max_remap, io_dec_win->win_offset);
+ }
+
+ return 0;
+}
diff --git a/plat/marvell/armada/a3k/common/marvell_plat_config.c b/plat/marvell/armada/a3k/common/marvell_plat_config.c
new file mode 100644
index 0000000..3bf3d96
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/marvell_plat_config.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/bl_common.h>
+
+#include <io_addr_dec.h>
+#include <mvebu_def.h>
+
+struct dec_win_config io_dec_win_conf[] = {
+ /* dec_reg_base win_attr max_dram_win max_remap win_offset */
+ {0xc000, 0x3d, 2, 0, 0x08}, /* USB */
+ {0xc100, 0x3d, 3, 0, 0x10}, /* USB3 */
+ {0xc200, 0x3d, 2, 0, 0x10}, /* DMA */
+ {0xc300, 0x3d, 2, 0, 0x10}, /* NETA0 */
+ {0xc400, 0x3d, 2, 0, 0x10}, /* NETA1 */
+ {0xc500, 0x3d, 2, 0, 0x10}, /* PCIe */
+ {0xc800, 0x3d, 3, 0, 0x10}, /* SATA */
+ {0xca00, 0x3d, 3, 0, 0x08}, /* SD */
+ {0xcb00, 0x3d, 3, 0, 0x10}, /* eMMC */
+ {0xce00, 0x3d, 2, 0, 0x08}, /* EIP97 */
+};
+
+int marvell_get_io_dec_win_conf(struct dec_win_config **win, uint32_t *size)
+{
+ *win = io_dec_win_conf;
+ *size = sizeof(io_dec_win_conf)/sizeof(struct dec_win_config);
+
+ return 0;
+}
+
diff --git a/plat/marvell/armada/a3k/common/plat_cci.c b/plat/marvell/armada/a3k/common/plat_cci.c
new file mode 100644
index 0000000..56f091f
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/plat_cci.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 Marek Behun <marek.behun@nic.cz>
+ *
+ * Based on plat/marvell/armada/common/marvell_cci.c
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <drivers/arm/cci.h>
+#include <lib/mmio.h>
+
+#include <plat_marvell.h>
+
+static const int cci_map[] = {
+ PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX
+};
+
+/*
+ * This redefines the weak definition in
+ * plat/marvell/armada/common/marvell_cci.c
+ */
+void plat_marvell_interconnect_init(void)
+{
+ /*
+ * To better utilize the address space, we remap CCI base address from
+ * the default (0xD8000000) to MVEBU_CCI_BASE.
+ * This has to be done here, rather than in cpu_wins_init(), because
+ * cpu_wins_init() is called later.
+ */
+ mmio_write_32(CPU_DEC_CCI_BASE_REG, MVEBU_CCI_BASE >> 20);
+
+ cci_init(PLAT_MARVELL_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+}
diff --git a/plat/marvell/armada/a3k/common/plat_pm.c b/plat/marvell/armada/a3k/common/plat_pm.c
new file mode 100644
index 0000000..e2d15ab
--- /dev/null
+++ b/plat/marvell/armada/a3k/common/plat_pm.c
@@ -0,0 +1,822 @@
+/*
+ * Copyright (C) 2018-2020 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/debug.h>
+#ifdef USE_CCI
+#include <drivers/arm/cci.h>
+#endif
+#include <lib/psci/psci.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <a3700_pm.h>
+#include <arch_helpers.h>
+#include <armada_common.h>
+#include <dram_win.h>
+#include <io_addr_dec.h>
+#include <mvebu.h>
+#include <mvebu_def.h>
+#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
+
+/* Warm reset register */
+#define MVEBU_WARM_RESET_REG (MVEBU_NB_REGS_BASE + 0x840)
+#define MVEBU_WARM_RESET_MAGIC 0x1D1E
+
+/* North Bridge GPIO1 SEL register */
+#define MVEBU_NB_GPIO1_SEL_REG (MVEBU_NB_REGS_BASE + 0x830)
+ #define MVEBU_NB_GPIO1_UART1_SEL BIT(19)
+ #define MVEBU_NB_GPIO1_GPIO_25_26_EN BIT(17)
+ #define MVEBU_NB_GPIO1_GPIO_19_EN BIT(14)
+ #define MVEBU_NB_GPIO1_GPIO_18_EN BIT(13)
+
+/* CPU 1 reset register */
+#define MVEBU_CPU_1_RESET_VECTOR (MVEBU_REGS_BASE + 0x14044)
+#define MVEBU_CPU_1_RESET_REG (MVEBU_REGS_BASE + 0xD00C)
+#define MVEBU_CPU_1_RESET_BIT 31
+
+/* IRQ register */
+#define MVEBU_NB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE)
+#define MVEBU_NB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
+ 0x10)
+#define MVEBU_NB_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
+ 0x18)
+#define MVEBU_SB_IRQ_STATUS_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
+ 0x40)
+#define MVEBU_SB_IRQ_STATUS_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
+ 0x50)
+#define MVEBU_NB_GPIO_IRQ_MASK_1_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
+ 0xC8)
+#define MVEBU_NB_GPIO_IRQ_MASK_2_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
+ 0xD8)
+#define MVEBU_SB_GPIO_IRQ_MASK_REG (MVEBU_NB_SB_IRQ_REG_BASE + \
+ 0xE8)
+#define MVEBU_NB_GPIO_IRQ_EN_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE)
+#define MVEBU_NB_GPIO_IRQ_EN_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+ 0x04)
+#define MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+ 0x10)
+#define MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+ 0x14)
+#define MVEBU_NB_GPIO_IRQ_WK_LOW_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+ 0x18)
+#define MVEBU_NB_GPIO_IRQ_WK_HIGH_REG (MVEBU_NB_GPIO_IRQ_REG_BASE + \
+ 0x1C)
+#define MVEBU_SB_GPIO_IRQ_EN_REG (MVEBU_SB_GPIO_IRQ_REG_BASE)
+#define MVEBU_SB_GPIO_IRQ_STATUS_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \
+ 0x10)
+#define MVEBU_SB_GPIO_IRQ_WK_REG (MVEBU_SB_GPIO_IRQ_REG_BASE + \
+ 0x18)
+
+/* PMU registers */
+#define MVEBU_PM_NB_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE)
+ #define MVEBU_PM_PWR_DN_CNT_SEL BIT(28)
+ #define MVEBU_PM_SB_PWR_DWN BIT(4)
+ #define MVEBU_PM_INTERFACE_IDLE BIT(0)
+#define MVEBU_PM_NB_CPU_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x4)
+ #define MVEBU_PM_L2_FLUSH_EN BIT(22)
+#define MVEBU_PM_NB_PWR_OPTION_REG (MVEBU_PMSU_REG_BASE + 0x8)
+ #define MVEBU_PM_DDR_SR_EN BIT(29)
+ #define MVEBU_PM_DDR_CLK_DIS_EN BIT(28)
+ #define MVEBU_PM_WARM_RESET_EN BIT(27)
+ #define MVEBU_PM_DDRPHY_PWRDWN_EN BIT(23)
+ #define MVEBU_PM_DDRPHY_PAD_PWRDWN_EN BIT(22)
+ #define MVEBU_PM_OSC_OFF_EN BIT(21)
+ #define MVEBU_PM_TBG_OFF_EN BIT(20)
+ #define MVEBU_PM_CPU_VDDV_OFF_EN BIT(19)
+ #define MVEBU_PM_AVS_DISABLE_MODE BIT(14)
+ #define MVEBU_PM_AVS_VDD2_MODE BIT(13)
+ #define MVEBU_PM_AVS_HOLD_MODE BIT(12)
+ #define MVEBU_PM_L2_SRAM_LKG_PD_EN BIT(8)
+ #define MVEBU_PM_EIP_SRAM_LKG_PD_EN BIT(7)
+ #define MVEBU_PM_DDRMC_SRAM_LKG_PD_EN BIT(6)
+ #define MVEBU_PM_MCI_SRAM_LKG_PD_EN BIT(5)
+ #define MVEBU_PM_MMC_SRAM_LKG_PD_EN BIT(4)
+ #define MVEBU_PM_SATA_SRAM_LKG_PD_EN BIT(3)
+ #define MVEBU_PM_DMA_SRAM_LKG_PD_EN BIT(2)
+ #define MVEBU_PM_SEC_SRAM_LKG_PD_EN BIT(1)
+ #define MVEBU_PM_CPU_SRAM_LKG_PD_EN BIT(0)
+ #define MVEBU_PM_NB_SRAM_LKG_PD_EN (MVEBU_PM_L2_SRAM_LKG_PD_EN |\
+ MVEBU_PM_EIP_SRAM_LKG_PD_EN | MVEBU_PM_DDRMC_SRAM_LKG_PD_EN |\
+ MVEBU_PM_MCI_SRAM_LKG_PD_EN | MVEBU_PM_MMC_SRAM_LKG_PD_EN |\
+ MVEBU_PM_SATA_SRAM_LKG_PD_EN | MVEBU_PM_DMA_SRAM_LKG_PD_EN |\
+ MVEBU_PM_SEC_SRAM_LKG_PD_EN | MVEBU_PM_CPU_SRAM_LKG_PD_EN)
+#define MVEBU_PM_NB_PWR_DEBUG_REG (MVEBU_PMSU_REG_BASE + 0xC)
+ #define MVEBU_PM_NB_FORCE_CLK_ON BIT(30)
+ #define MVEBU_PM_IGNORE_CM3_SLEEP BIT(21)
+ #define MVEBU_PM_IGNORE_CM3_DEEP BIT(20)
+#define MVEBU_PM_NB_WAKE_UP_EN_REG (MVEBU_PMSU_REG_BASE + 0x2C)
+ #define MVEBU_PM_SB_WKP_NB_EN BIT(31)
+ #define MVEBU_PM_NB_GPIO_WKP_EN BIT(27)
+ #define MVEBU_PM_SOC_TIMER_WKP_EN BIT(26)
+ #define MVEBU_PM_UART_WKP_EN BIT(25)
+ #define MVEBU_PM_UART2_WKP_EN BIT(19)
+ #define MVEBU_PM_CPU_TIMER_WKP_EN BIT(17)
+ #define MVEBU_PM_NB_WKP_EN BIT(16)
+ #define MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN BIT(13)
+ #define MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN BIT(12)
+#define MVEBU_PM_CPU_0_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x34)
+#define MVEBU_PM_CPU_1_PWR_CTRL_REG (MVEBU_PMSU_REG_BASE + 0x38)
+ #define MVEBU_PM_CORE_SOC_PD BIT(2)
+ #define MVEBU_PM_CORE_PROC_PD BIT(1)
+ #define MVEBU_PM_CORE_PD BIT(0)
+#define MVEBU_PM_CORE_1_RETURN_ADDR_REG (MVEBU_PMSU_REG_BASE + 0x44)
+#define MVEBU_PM_CPU_VDD_OFF_INFO_1_REG (MVEBU_PMSU_REG_BASE + 0x48)
+#define MVEBU_PM_CPU_VDD_OFF_INFO_2_REG (MVEBU_PMSU_REG_BASE + 0x4C)
+ #define MVEBU_PM_LOW_POWER_STATE BIT(0)
+#define MVEBU_PM_CPU_WAKE_UP_CONF_REG (MVEBU_PMSU_REG_BASE + 0x54)
+ #define MVEBU_PM_CORE1_WAKEUP BIT(13)
+ #define MVEBU_PM_CORE0_WAKEUP BIT(12)
+#define MVEBU_PM_WAIT_DDR_RDY_VALUE (0x15)
+#define MVEBU_PM_SB_CPU_PWR_CTRL_REG (MVEBU_SB_WAKEUP_REG_BASE)
+ #define MVEBU_PM_SB_PM_START BIT(0)
+#define MVEBU_PM_SB_PWR_OPTION_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x4)
+ #define MVEBU_PM_SDIO_PHY_PDWN_EN BIT(17)
+ #define MVEBU_PM_SB_VDDV_OFF_EN BIT(16)
+ #define MVEBU_PM_EBM_SRAM_LKG_PD_EN BIT(11)
+ #define MVEBU_PM_PCIE_SRAM_LKG_PD_EN BIT(10)
+ #define MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN BIT(9)
+ #define MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN BIT(8)
+ #define MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN BIT(7)
+ #define MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN BIT(6)
+ #define MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN BIT(5)
+ #define MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN BIT(4)
+ #define MVEBU_PM_SDIO_SRAM_LKG_PD_EN BIT(3)
+ #define MVEBU_PM_USB2_SRAM_LKG_PD_EN BIT(2)
+ #define MVEBU_PM_USB3_H_SRAM_LKG_PD_EN BIT(1)
+ #define MVEBU_PM_SB_SRAM_LKG_PD_EN (MVEBU_PM_EBM_SRAM_LKG_PD_EN |\
+ MVEBU_PM_PCIE_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_TX_SRAM_LKG_PD_EN |\
+ MVEBU_PM_GBE1_RX_SRAM_LKG_PD_EN | MVEBU_PM_GBE1_MIB_SRAM_LKG_PD_EN |\
+ MVEBU_PM_GBE0_TX_SRAM_LKG_PD_EN | MVEBU_PM_GBE0_RX_SRAM_LKG_PD_EN |\
+ MVEBU_PM_GBE0_MIB_SRAM_LKG_PD_EN | MVEBU_PM_SDIO_SRAM_LKG_PD_EN |\
+ MVEBU_PM_USB2_SRAM_LKG_PD_EN | MVEBU_PM_USB3_H_SRAM_LKG_PD_EN)
+#define MVEBU_PM_SB_WK_EN_REG (MVEBU_SB_WAKEUP_REG_BASE + 0x10)
+ #define MVEBU_PM_SB_GPIO_WKP_EN BIT(24)
+ #define MVEBU_PM_SB_WKP_EN BIT(20)
+
+/* DRAM registers */
+#define MVEBU_DRAM_STATS_CH0_REG (MVEBU_DRAM_REG_BASE + 0x4)
+ #define MVEBU_DRAM_WCP_EMPTY BIT(19)
+#define MVEBU_DRAM_CMD_0_REG (MVEBU_DRAM_REG_BASE + 0x20)
+ #define MVEBU_DRAM_CH0_CMD0 BIT(28)
+ #define MVEBU_DRAM_CS_CMD0 BIT(24)
+ #define MVEBU_DRAM_WCB_DRAIN_REQ BIT(1)
+#define MVEBU_DRAM_PWR_CTRL_REG (MVEBU_DRAM_REG_BASE + 0x54)
+ #define MVEBU_DRAM_PHY_CLK_GATING_EN BIT(1)
+ #define MVEBU_DRAM_PHY_AUTO_AC_OFF_EN BIT(0)
+
+/* AVS registers */
+#define MVEBU_AVS_CTRL_2_REG (MVEBU_AVS_REG_BASE + 0x8)
+ #define MVEBU_LOW_VDD_MODE_EN BIT(6)
+
+/* Clock registers */
+#define MVEBU_NB_CLOCK_SEL_REG (MVEBU_NB_REGS_BASE + 0x10)
+ #define MVEBU_A53_CPU_CLK_SEL BIT(15)
+
+/* North Bridge Step-Down Registers */
+#define MVEBU_NB_STEP_DOWN_INT_EN_REG MVEBU_NB_STEP_DOWN_REG_BASE
+ #define MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK BIT(8)
+
+#define MVEBU_NB_GPIO_18 18
+#define MVEBU_NB_GPIO_19 19
+#define MVEBU_NB_GPIO_25 25
+#define MVEBU_NB_GPIO_26 26
+
+typedef int (*wake_up_src_func)(union pm_wake_up_src_data *);
+
+struct wake_up_src_func_map {
+ enum pm_wake_up_src_type type;
+ wake_up_src_func func;
+};
+
+void marvell_psci_arch_init(int die_index)
+{
+}
+
+static void a3700_pm_ack_irq(void)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_1_REG);
+ if (reg)
+ mmio_write_32(MVEBU_NB_IRQ_STATUS_1_REG, reg);
+
+ reg = mmio_read_32(MVEBU_NB_IRQ_STATUS_2_REG);
+ if (reg)
+ mmio_write_32(MVEBU_NB_IRQ_STATUS_2_REG, reg);
+
+ reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_1_REG);
+ if (reg)
+ mmio_write_32(MVEBU_SB_IRQ_STATUS_1_REG, reg);
+
+ reg = mmio_read_32(MVEBU_SB_IRQ_STATUS_2_REG);
+ if (reg)
+ mmio_write_32(MVEBU_SB_IRQ_STATUS_2_REG, reg);
+
+ reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG);
+ if (reg)
+ mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_LOW_REG, reg);
+
+ reg = mmio_read_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG);
+ if (reg)
+ mmio_write_32(MVEBU_NB_GPIO_IRQ_STATUS_HIGH_REG, reg);
+
+ reg = mmio_read_32(MVEBU_SB_GPIO_IRQ_STATUS_REG);
+ if (reg)
+ mmio_write_32(MVEBU_SB_GPIO_IRQ_STATUS_REG, reg);
+}
+
+/*****************************************************************************
+ * A3700 handler called to check the validity of the power state
+ * parameter.
+ *****************************************************************************
+ */
+int a3700_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ ERROR("%s needs to be implemented\n", __func__);
+ panic();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a CPU is about to enter standby.
+ *****************************************************************************
+ */
+void a3700_cpu_standby(plat_local_state_t cpu_state)
+{
+ ERROR("%s needs to be implemented\n", __func__);
+ panic();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ *****************************************************************************
+ */
+int a3700_pwr_domain_on(u_register_t mpidr)
+{
+ /* Set barrier */
+ dsbsy();
+
+ /* Set the cpu start address to BL1 entry point */
+ mmio_write_32(MVEBU_CPU_1_RESET_VECTOR,
+ PLAT_MARVELL_CPU_ENTRY_ADDR >> 2);
+
+ /* Get the cpu out of reset */
+ mmio_clrbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT));
+ mmio_setbits_32(MVEBU_CPU_1_RESET_REG, BIT(MVEBU_CPU_1_RESET_BIT));
+
+ return 0;
+}
+
+/*****************************************************************************
+ * A3700 handler called to validate the entry point.
+ *****************************************************************************
+ */
+int a3700_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ return PSCI_E_SUCCESS;
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ *****************************************************************************
+ */
+void a3700_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_marvell_gic_cpuif_disable();
+
+ /* Core can not be powered down with pending IRQ,
+ * acknowledge all the pending IRQ
+ */
+ a3700_pm_ack_irq();
+}
+
+static void a3700_set_gen_pwr_off_option(void)
+{
+ /* Enable L2 flush -> processor state-machine option */
+ mmio_setbits_32(MVEBU_PM_NB_CPU_PWR_CTRL_REG, MVEBU_PM_L2_FLUSH_EN);
+
+ /*
+ * North bridge cannot be VDD off (always ON).
+ * The NB state machine support low power mode by its state machine.
+ * This bit MUST be set for north bridge power down, e.g.,
+ * OSC input cutoff(NOT TEST), SRAM power down, PMIC, etc.
+ * It is not related to CPU VDD OFF!!
+ */
+ mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_CPU_VDDV_OFF_EN);
+
+ /*
+ * MUST: Switch CPU/AXI clock to OSC
+ * NB state machine clock is always connected to OSC (slow clock).
+ * But Core0/1/processor state machine's clock are connected to AXI
+ * clock. Now, AXI clock takes the TBG as clock source.
+ * If using AXI clock, Core0/1/processor state machine may much faster
+ * than NB state machine. It will cause problem in this case if cores
+ * are released before north bridge gets ready.
+ */
+ mmio_clrbits_32(MVEBU_NB_CLOCK_SEL_REG, MVEBU_A53_CPU_CLK_SEL);
+
+ /*
+ * These register bits will trigger north bridge
+ * power-down state machine regardless CM3 status.
+ */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_SLEEP);
+ mmio_setbits_32(MVEBU_PM_NB_PWR_DEBUG_REG, MVEBU_PM_IGNORE_CM3_DEEP);
+
+ /*
+ * SRAM => controlled by north bridge state machine.
+ * Core VDD OFF is not related to CPU SRAM power down.
+ */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_NB_SRAM_LKG_PD_EN);
+
+ /*
+ * Idle AXI interface in order to get L2_WFI
+ * L2 WFI is only asserted after CORE-0 and CORE-1 WFI asserted.
+ * (only both core-0/1in WFI, L2 WFI will be issued by CORE.)
+ * Once L2 WFI asserted, this bit is used for signalling assertion
+ * to AXI IO masters.
+ */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_INTERFACE_IDLE);
+
+ /* Enable core0 and core1 VDD_OFF */
+ mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PD);
+ mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PD);
+
+ /* Enable North bridge power down -
+ * Both Cores MUST enable this bit to power down north bridge!
+ */
+ mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD);
+ mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_SOC_PD);
+
+ /* CA53 (processor domain) power down */
+ mmio_setbits_32(MVEBU_PM_CPU_0_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD);
+ mmio_setbits_32(MVEBU_PM_CPU_1_PWR_CTRL_REG, MVEBU_PM_CORE_PROC_PD);
+}
+
+static void a3700_en_ddr_self_refresh(void)
+{
+ /*
+ * Both count is 16 bits and configurable. By default, osc stb cnt
+ * is 0xFFF for lower 12 bits.
+ * Thus, powerdown count is smaller than osc count.
+ * This count is used for exiting DDR SR mode on wakeup event.
+ * The powerdown count also has impact on the following
+ * state changes: idle -> count-down -> ... (power-down, vdd off, etc)
+ * Here, make stable counter shorter
+ * Use power down count value instead of osc_stb_cnt to speed up
+ * DDR self refresh exit
+ */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_PWR_DN_CNT_SEL);
+
+ /*
+ * Enable DDR SR mode => controlled by north bridge state machine
+ * Therefore, we must powerdown north bridge to trigger the DDR SR
+ * mode switching.
+ */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_SR_EN);
+ /* Disable DDR clock, otherwise DDR will not enter into SR mode. */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDR_CLK_DIS_EN);
+ /* Power down DDR PHY (PAD) */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_DDRPHY_PWRDWN_EN);
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG,
+ MVEBU_PM_DDRPHY_PAD_PWRDWN_EN);
+
+ /* Set wait time for DDR ready in ROM code */
+ mmio_write_32(MVEBU_PM_CPU_VDD_OFF_INFO_1_REG,
+ MVEBU_PM_WAIT_DDR_RDY_VALUE);
+
+ /* DDR flush write buffer - mandatory */
+ mmio_write_32(MVEBU_DRAM_CMD_0_REG, MVEBU_DRAM_CH0_CMD0 |
+ MVEBU_DRAM_CS_CMD0 | MVEBU_DRAM_WCB_DRAIN_REQ);
+ while ((mmio_read_32(MVEBU_DRAM_STATS_CH0_REG) &
+ MVEBU_DRAM_WCP_EMPTY) != MVEBU_DRAM_WCP_EMPTY)
+ ;
+
+ /* Trigger PHY reset after ddr out of self refresh =>
+ * supply reset pulse for DDR phy after wake up
+ */
+ mmio_setbits_32(MVEBU_DRAM_PWR_CTRL_REG, MVEBU_DRAM_PHY_CLK_GATING_EN |
+ MVEBU_DRAM_PHY_AUTO_AC_OFF_EN);
+}
+
+static void a3700_pwr_dn_avs(void)
+{
+ /*
+ * AVS power down - controlled by north bridge statemachine
+ * Enable AVS power down by clear the AVS disable bit.
+ */
+ mmio_clrbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_DISABLE_MODE);
+ /*
+ * Should set BIT[12:13] to powerdown AVS.
+ * 1. Enable AVS VDD2 mode
+ * 2. After power down AVS, we must hold AVS output voltage.
+ * 3. We can choose the lower VDD for AVS power down.
+ */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_VDD2_MODE);
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_AVS_HOLD_MODE);
+
+ /* Enable low VDD mode, AVS will set CPU to lowest core VDD 747mV */
+ mmio_setbits_32(MVEBU_AVS_CTRL_2_REG, MVEBU_LOW_VDD_MODE_EN);
+}
+
+static void a3700_pwr_dn_tbg(void)
+{
+ /* Power down TBG */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_TBG_OFF_EN);
+}
+
+static void a3700_pwr_dn_sb(void)
+{
+ /* Enable south bridge power down option */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_CTRL_REG, MVEBU_PM_SB_PWR_DWN);
+
+ /* Enable SDIO_PHY_PWRDWN */
+ mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SDIO_PHY_PDWN_EN);
+
+ /* Enable SRAM LRM on SB */
+ mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_SRAM_LKG_PD_EN);
+
+ /* Enable SB Power Off */
+ mmio_setbits_32(MVEBU_PM_SB_PWR_OPTION_REG, MVEBU_PM_SB_VDDV_OFF_EN);
+
+ /* Kick off South Bridge Power Off */
+ mmio_setbits_32(MVEBU_PM_SB_CPU_PWR_CTRL_REG, MVEBU_PM_SB_PM_START);
+}
+
+static void a3700_set_pwr_off_option(void)
+{
+ /* Set general power off option */
+ a3700_set_gen_pwr_off_option();
+
+ /* Enable DDR self refresh in low power mode */
+ a3700_en_ddr_self_refresh();
+
+ /* Power down AVS */
+ a3700_pwr_dn_avs();
+
+ /* Power down TBG */
+ a3700_pwr_dn_tbg();
+
+ /* Power down south bridge, pay attention south bridge setting
+ * should be done before
+ */
+ a3700_pwr_dn_sb();
+}
+
+static void a3700_set_wake_up_option(void)
+{
+ /*
+ * Enable the wakeup event for NB SOC => north-bridge
+ * state-machine enablement on wake-up event
+ */
+ mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_WKP_EN);
+
+ /* Enable both core0 and core1 wakeup on demand */
+ mmio_setbits_32(MVEBU_PM_CPU_WAKE_UP_CONF_REG,
+ MVEBU_PM_CORE1_WAKEUP | MVEBU_PM_CORE0_WAKEUP);
+
+ /* Enable warm reset in low power mode */
+ mmio_setbits_32(MVEBU_PM_NB_PWR_OPTION_REG, MVEBU_PM_WARM_RESET_EN);
+}
+
+static void a3700_pm_en_nb_gpio(uint32_t gpio)
+{
+ /* For GPIO1 interrupt -- North bridge only */
+ if (gpio >= 32) {
+ /* GPIO int mask */
+ mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_2_REG, BIT(gpio - 32));
+
+ /* NB_CPU_WAKE-up ENABLE GPIO int */
+ mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_HIGH_REG, BIT(gpio - 32));
+ } else {
+ /* GPIO int mask */
+ mmio_clrbits_32(MVEBU_NB_GPIO_IRQ_MASK_1_REG, BIT(gpio));
+
+ /* NB_CPU_WAKE-up ENABLE GPIO int */
+ mmio_setbits_32(MVEBU_NB_GPIO_IRQ_EN_LOW_REG, BIT(gpio));
+ }
+
+ mmio_setbits_32(MVEBU_NB_STEP_DOWN_INT_EN_REG,
+ MVEBU_NB_GPIO_INT_WAKE_WCPU_CLK);
+
+ /* Enable using GPIO as wakeup event
+ * (actually not only for north bridge)
+ */
+ mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_NB_GPIO_WKP_EN |
+ MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN |
+ MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN);
+}
+
+static void a3700_pm_en_sb_gpio(uint32_t gpio)
+{
+ /* Enable using GPIO as wakeup event */
+ mmio_setbits_32(MVEBU_PM_NB_WAKE_UP_EN_REG, MVEBU_PM_SB_WKP_NB_EN |
+ MVEBU_PM_NB_WKP_EN | MVEBU_PM_CORE1_FIQ_IRQ_WKP_EN |
+ MVEBU_PM_CORE0_FIQ_IRQ_WKP_EN);
+
+ /* SB GPIO Wake UP | South Bridge Wake Up Enable */
+ mmio_setbits_32(MVEBU_PM_SB_WK_EN_REG, MVEBU_PM_SB_GPIO_WKP_EN |
+ MVEBU_PM_SB_GPIO_WKP_EN);
+
+ /* GPIO int mask */
+ mmio_clrbits_32(MVEBU_SB_GPIO_IRQ_MASK_REG, BIT(gpio));
+
+ /* NB_CPU_WAKE-up ENABLE GPIO int */
+ mmio_setbits_32(MVEBU_SB_GPIO_IRQ_EN_REG, BIT(gpio));
+}
+
+int a3700_pm_src_gpio(union pm_wake_up_src_data *src_data)
+{
+ if (src_data->gpio_data.bank_num == 0)
+ /* North Bridge GPIO */
+ a3700_pm_en_nb_gpio(src_data->gpio_data.gpio_num);
+ else
+ a3700_pm_en_sb_gpio(src_data->gpio_data.gpio_num);
+ return 0;
+}
+
+int a3700_pm_src_uart1(union pm_wake_up_src_data *src_data)
+{
+ /* Clear Uart1 select */
+ mmio_clrbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_UART1_SEL);
+ /* set pin 19 gpio usage*/
+ mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_19_EN);
+ /* Enable gpio wake-up*/
+ a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_19);
+ /* set pin 18 gpio usage*/
+ mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_18_EN);
+ /* Enable gpio wake-up*/
+ a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_18);
+
+ return 0;
+}
+
+int a3700_pm_src_uart0(union pm_wake_up_src_data *src_data)
+{
+ /* set pin 25/26 gpio usage*/
+ mmio_setbits_32(MVEBU_NB_GPIO1_SEL_REG, MVEBU_NB_GPIO1_GPIO_25_26_EN);
+ /* Enable gpio wake-up*/
+ a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_25);
+ /* Enable gpio wake-up*/
+ a3700_pm_en_nb_gpio(MVEBU_NB_GPIO_26);
+
+ return 0;
+}
+
+struct wake_up_src_func_map src_func_table[WAKE_UP_SRC_MAX] = {
+ {WAKE_UP_SRC_GPIO, a3700_pm_src_gpio},
+ {WAKE_UP_SRC_UART1, a3700_pm_src_uart1},
+ {WAKE_UP_SRC_UART0, a3700_pm_src_uart0},
+ /* FOLLOWING SRC NOT SUPPORTED YET */
+ {WAKE_UP_SRC_TIMER, NULL}
+};
+
+static wake_up_src_func a3700_get_wake_up_src_func(
+ enum pm_wake_up_src_type type)
+{
+ uint32_t loop;
+
+ for (loop = 0; loop < WAKE_UP_SRC_MAX; loop++) {
+ if (src_func_table[loop].type == type)
+ return src_func_table[loop].func;
+ }
+ return NULL;
+}
+
+#pragma weak mv_wake_up_src_config_get
+struct pm_wake_up_src_config *mv_wake_up_src_config_get(void)
+{
+ static struct pm_wake_up_src_config wake_up_src_cfg = {};
+ return &wake_up_src_cfg;
+}
+
+static void a3700_set_wake_up_source(void)
+{
+ struct pm_wake_up_src_config *wake_up_src;
+ uint32_t loop;
+ wake_up_src_func src_func = NULL;
+
+ wake_up_src = mv_wake_up_src_config_get();
+ for (loop = 0; loop < wake_up_src->wake_up_src_num; loop++) {
+ src_func = a3700_get_wake_up_src_func(
+ wake_up_src->wake_up_src[loop].wake_up_src_type);
+ if (src_func)
+ src_func(
+ &(wake_up_src->wake_up_src[loop].wake_up_data));
+ }
+}
+
+static void a3700_pm_save_lp_flag(void)
+{
+ /* Save the flag for enter the low power mode */
+ mmio_setbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG,
+ MVEBU_PM_LOW_POWER_STATE);
+}
+
+static void a3700_pm_clear_lp_flag(void)
+{
+ /* Clear the flag for enter the low power mode */
+ mmio_clrbits_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG,
+ MVEBU_PM_LOW_POWER_STATE);
+}
+
+static uint32_t a3700_pm_get_lp_flag(void)
+{
+ /* Get the flag for enter the low power mode */
+ return mmio_read_32(MVEBU_PM_CPU_VDD_OFF_INFO_2_REG) &
+ MVEBU_PM_LOW_POWER_STATE;
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ *****************************************************************************
+ */
+void a3700_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_marvell_gic_cpuif_disable();
+
+ /* Save IRQ states */
+ plat_marvell_gic_irq_save();
+
+ /* Set wake up options */
+ a3700_set_wake_up_option();
+
+ /* Set wake up sources */
+ a3700_set_wake_up_source();
+
+ /* SoC can not be powered down with pending IRQ,
+ * acknowledge all the pending IRQ
+ */
+ a3700_pm_ack_irq();
+
+ /* Set power off options */
+ a3700_set_pwr_off_option();
+
+ /* Save the flag for enter the low power mode */
+ a3700_pm_save_lp_flag();
+
+ isb();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ *****************************************************************************
+ */
+void a3700_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* arch specific configuration */
+ marvell_psci_arch_init(0);
+
+ /* Per-CPU interrupt initialization */
+ plat_marvell_gic_pcpu_init();
+ plat_marvell_gic_cpuif_enable();
+
+ /* Restore the per-cpu IRQ state */
+ if (a3700_pm_get_lp_flag())
+ plat_marvell_gic_irq_pcpu_restore();
+}
+
+/*****************************************************************************
+ * A3700 handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ *****************************************************************************
+ */
+void a3700_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ struct dec_win_config *io_dec_map;
+ uint32_t dec_win_num;
+ struct dram_win_map dram_wins_map;
+
+ /* arch specific configuration */
+ marvell_psci_arch_init(0);
+
+ /* Interrupt initialization */
+ plat_marvell_gic_init();
+
+ /* Restore IRQ states */
+ plat_marvell_gic_irq_restore();
+
+ /*
+ * Initialize CCI for this cluster after resume from suspend state.
+ * No need for locks as no other CPU is active.
+ */
+ plat_marvell_interconnect_init();
+ /*
+ * Enable CCI coherency for the primary CPU's cluster.
+ * Platform specific PSCI code will enable coherency for other
+ * clusters.
+ */
+ plat_marvell_interconnect_enter_coherency();
+
+ /* CPU address decoder windows initialization. */
+ cpu_wins_init();
+
+ /* fetch CPU-DRAM window mapping information by reading
+ * CPU-DRAM decode windows (only the enabled ones)
+ */
+ dram_win_map_build(&dram_wins_map);
+
+ /* Get IO address decoder windows */
+ if (marvell_get_io_dec_win_conf(&io_dec_map, &dec_win_num)) {
+ printf("No IO address decoder windows configurations found!\n");
+ return;
+ }
+
+ /* IO address decoder init */
+ if (init_io_addr_dec(&dram_wins_map, io_dec_map, dec_win_num)) {
+ printf("IO address decoder windows initialization failed!\n");
+ return;
+ }
+
+ /* Clear low power mode flag */
+ a3700_pm_clear_lp_flag();
+}
+
+/*****************************************************************************
+ * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND
+ * call to get the `power_state` parameter. This allows the platform to encode
+ * the appropriate State-ID field within the `power_state` parameter which can
+ * be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
+ *****************************************************************************
+ */
+void a3700_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ /* lower affinities use PLAT_MAX_OFF_STATE */
+ for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+/*****************************************************************************
+ * A3700 handlers to shutdown/reboot the system
+ *****************************************************************************
+ */
+static void __dead2 a3700_system_off(void)
+{
+ ERROR("%s needs to be implemented\n", __func__);
+ panic();
+}
+
+#pragma weak cm3_system_reset
+void cm3_system_reset(void)
+{
+}
+
+/*****************************************************************************
+ * A3700 handlers to reset the system
+ *****************************************************************************
+ */
+static void __dead2 a3700_system_reset(void)
+{
+ /* Clean the mailbox magic number to let it as act like cold boot */
+ mmio_write_32(PLAT_MARVELL_MAILBOX_BASE, 0x0);
+
+ dsbsy();
+
+ /* Flush data cache if the mail box shared RAM is cached */
+#if PLAT_MARVELL_SHARED_RAM_CACHED
+ flush_dcache_range((uintptr_t)PLAT_MARVELL_MAILBOX_BASE,
+ 2 * sizeof(uint64_t));
+#endif
+
+ /* Use Cortex-M3 secure coprocessor for system reset */
+ cm3_system_reset();
+
+ /* Trigger the warm reset */
+ mmio_write_32(MVEBU_WARM_RESET_REG, MVEBU_WARM_RESET_MAGIC);
+
+ /* Shouldn't get to this point */
+ panic();
+}
+
+/*****************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ *****************************************************************************
+ */
+const plat_psci_ops_t plat_arm_psci_pm_ops = {
+ .cpu_standby = a3700_cpu_standby,
+ .pwr_domain_on = a3700_pwr_domain_on,
+ .pwr_domain_off = a3700_pwr_domain_off,
+ .pwr_domain_suspend = a3700_pwr_domain_suspend,
+ .pwr_domain_on_finish = a3700_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = a3700_pwr_domain_suspend_finish,
+ .get_sys_suspend_power_state = a3700_get_sys_suspend_power_state,
+ .system_off = a3700_system_off,
+ .system_reset = a3700_system_reset,
+ .validate_power_state = a3700_validate_power_state,
+ .validate_ns_entrypoint = a3700_validate_ns_entrypoint
+};
diff --git a/plat/marvell/armada/a8k/a70x0/board/dram_port.c b/plat/marvell/armada/a8k/a70x0/board/dram_port.c
new file mode 100644
index 0000000..355770b
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0/board/dram_port.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mv_ddr_if.h>
+#include <plat_marvell.h>
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+}
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+/* FIXME: MISL board 2CS 4Gb x8 devices of micron - 2133P */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2133P, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_4GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ /* Return the board topology as defined in the board code */
+ return &board_topology_map;
+}
diff --git a/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
new file mode 100644
index 0000000..a409261
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+ /* CP0 SPI1 CS0 Direct Mode access */
+ {0xf900, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win,
+ uint32_t *size, uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO_WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#ifndef IMAGE_BLE
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map[] = {
+ /* PEX1_X1 window */
+ {0x00000000f7000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000f8000000, 0x1000000, PEX2_TID},
+ {0x00000000c0000000, 0x30000000, PEX2_TID},
+ {0x0000000800000000, 0x100000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x1000000, PEX0_TID},
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000f9000000, 0x1000000, RUNIT_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = iob_memory_map;
+ *size = ARRAY_SIZE(iob_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = { /* IO window */
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID},
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+#if PLAT_RECOVERY_IMAGE_ENABLE
+struct skip_image skip_im = {
+ .detection_method = GPIO,
+ .info.gpio.num = 33,
+ .info.gpio.button_state = HIGH,
+ .info.test.cp_ap = CP,
+ .info.test.cp_index = 0,
+};
+
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* Return the skip_image configurations */
+ return &skip_im;
+}
+#endif
+#endif
diff --git a/plat/marvell/armada/a8k/a70x0/mvebu_def.h b/plat/marvell/armada/a8k/a70x0/mvebu_def.h
new file mode 100644
index 0000000..72bca12
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0/mvebu_def.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 1 /* A70x0 has single CP0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a70x0/platform.mk b/plat/marvell/armada/a8k/a70x0/platform.mk
new file mode 100644
index 0000000..39eb712
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c b/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c
new file mode 100644
index 0000000..9c8c97e
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mv_ddr_if.h>
+#include <plat_marvell.h>
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+}
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+/* FIXME: MISL board 2CS 8Gb x8 devices of micron - 2133P */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2400T, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ /* Return the board topology as defined in the board code */
+ return &board_topology_map;
+}
diff --git a/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
new file mode 100644
index 0000000..3b68e91
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win *amb_memory_map;
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#ifndef IMAGE_BLE
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map[] = {
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x6000000, PEX0_TID},
+ {0x00000000c0000000, 0x30000000, PEX0_TID},
+ {0x0000000800000000, 0x200000000, PEX0_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = iob_memory_map;
+ *size = ARRAY_SIZE(iob_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID},
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x200000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifdef IMAGE_BLE
+
+struct pci_hw_cfg *plat_get_pcie_hw_data(void)
+{
+ return NULL;
+}
+
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+#if PLAT_RECOVERY_IMAGE_ENABLE
+struct skip_image skip_im = {
+ .detection_method = GPIO,
+ .info.gpio.num = 33,
+ .info.gpio.button_state = HIGH,
+ .info.test.cp_ap = CP,
+ .info.test.cp_index = 0,
+};
+
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* Return the skip_image configurations */
+ return &skip_im;
+}
+#endif
+#endif
diff --git a/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h b/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h
new file mode 100644
index 0000000..cedf323
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 1 /* A70x0 has single CP0 */
+
+/***********************************************************************
+ * Required platform porting definitions common to all
+ * Management Compute SubSystems (MSS)
+ ***********************************************************************
+ */
+/*
+ * Load address of SCP_BL2
+ * SCP_BL2 is loaded to the same place as BL31.
+ * Once SCP_BL2 is transferred to the SCP,
+ * it is discarded and BL31 is loaded over the top.
+ */
+#ifdef SCP_IMAGE
+#define SCP_BL2_BASE BL31_BASE
+#endif
+
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a70x0_amc/platform.mk b/plat/marvell/armada/a8k/a70x0_amc/platform.mk
new file mode 100644
index 0000000..39eb712
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_amc/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c b/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c
new file mode 100644
index 0000000..68d335b
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2021 Sartura Ltd.
+ * Copyright (C) 2021 Globalscale technologies, Inc.
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mv_ddr_if.h>
+#include <plat_marvell.h>
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+}
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+#if DDR_TOPOLOGY == 0
+static struct mv_ddr_topology_map board_topology_map_2g = {
+/* 1CS 4Gb x4 devices of Samsung K4A4G085WF */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2400R, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_4GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ BUS_MASK_32BIT, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+#endif
+
+#if DDR_TOPOLOGY == 1
+static struct mv_ddr_topology_map board_topology_map_4g = {
+/* 1CS 8Gb x4 devices of Samsung K4A8G085WC-BCTD */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0},
+ {0x1, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2400R, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ BUS_MASK_32BIT, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+#endif
+
+#if DDR_TOPOLOGY == 2
+static struct mv_ddr_topology_map board_topology_map_8g = {
+/* 2CS 8Gb x8 devices of Micron MT40A1G8WE-083E IT */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0},
+ {0x3, 0x2, 0, 0} },
+ SPEED_BIN_DDR_2400R, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ BUS_MASK_32BIT, /* subphys mask */
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+#endif
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+/* a70x0_mochabin board supports 3 DDR4 models (2G/1CS, 4G/1CS, 8G/2CS) */
+#if DDR_TOPOLOGY == 0
+ return &board_topology_map_2g;
+#elif DDR_TOPOLOGY == 1
+ return &board_topology_map_4g;
+#elif DDR_TOPOLOGY == 2
+ return &board_topology_map_8g;
+#else
+ #error "Unknown DDR topology"
+#endif
+}
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c
new file mode 100644
index 0000000..1ed6323
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 Sartura Ltd.
+ * Copyright (C) 2021 Globalscale technologies, Inc.
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+ /* CP0 SPI1 CS0 Direct Mode access */
+ {0xf900, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win,
+ uint32_t *size, uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO_WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#ifndef IMAGE_BLE
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map[] = {
+ /* PEX1_X1 window */
+ {0x00000000f7000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000f8000000, 0x1000000, PEX2_TID},
+ {0x00000000c0000000, 0x30000000, PEX2_TID},
+ {0x0000000800000000, 0x100000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x1000000, PEX0_TID},
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000f9000000, 0x1000000, RUNIT_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = iob_memory_map;
+ *size = ARRAY_SIZE(iob_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = { /* IO window */
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID},
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+#if PLAT_RECOVERY_IMAGE_ENABLE
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* No recovery button on a70x0_mochabin board */
+ return NULL;
+}
+#endif
+#endif
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h b/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h
new file mode 100644
index 0000000..ab76c31
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 Sartura Ltd.
+ * Copyright (C) 2021 Globalscale technologies, Inc.
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __PHY_PORTING_LAYER_H
+#define __PHY_PORTING_LAYER_H
+
+#define MAX_LANE_NR 6
+
+static const struct xfi_params
+ xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ /* AP0 */
+ {
+ /* CP 0 */
+ {
+ { 0 }, /* Comphy0 */
+ { 0 }, /* Comphy1 */
+ { 0 }, /* Comphy2 */
+ { 0 }, /* Comphy3 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf, .align90 = 0x60,
+ .g1_dfe_res = 0x1, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1, .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+ },
+ },
+};
+
+static const struct sata_params
+ sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ /* AP0 */
+ {
+ /* CP 0 */
+ {
+ { 0 }, /* Comphy0 */
+ { 0 }, /* Comphy1 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy2 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1, .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1, .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0, .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1, .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4, .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3, .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0, .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1, .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0, .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy3 */
+ { 0 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+ },
+ },
+};
+
+static const struct usb_params
+ usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = {
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT
+ },
+};
+
+#endif /* __PHY_PORTING_LAYER_H */
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h b/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h
new file mode 100644
index 0000000..768f735
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 1 /* A70x0 has single CP0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk b/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk
new file mode 100644
index 0000000..2495591
--- /dev/null
+++ b/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2021 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/a80x0/board/dram_port.c b/plat/marvell/armada/a8k/a80x0/board/dram_port.c
new file mode 100644
index 0000000..47bc0a8
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0/board/dram_port.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/mentor/mi2cv.h>
+#include <lib/mmio.h>
+
+#include <mv_ddr_if.h>
+#include <mvebu_def.h>
+#include <plat_marvell.h>
+
+#define MVEBU_AP_MPP_CTRL0_7_REG MVEBU_AP_MPP_REGS(0)
+#define MVEBU_AP_MPP_CTRL4_OFFS 16
+#define MVEBU_AP_MPP_CTRL5_OFFS 20
+#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA 0x3
+#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA 0x3
+
+#define MVEBU_CP_MPP_CTRL37_OFFS 20
+#define MVEBU_CP_MPP_CTRL38_OFFS 24
+#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
+#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
+
+#define MVEBU_MPP_CTRL_MASK 0xf
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+ /* MISL board with 1CS 8Gb x4 devices of Micron 2400T */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0} },
+ /* TODO: double check if the speed bin is 2400T */
+ SPEED_BIN_DDR_2400T, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+#if DDR32
+ MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+#else
+ MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+#endif
+ MV_DDR_CFG_SPD, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ /* Return the board topology as defined in the board code */
+ return &board_topology_map;
+}
+
+static void mpp_config(void)
+{
+ uintptr_t reg;
+ uint32_t val;
+
+ reg = MVEBU_CP_MPP_REGS(0, 4);
+ /* configure CP0 MPP 37 and 38 to i2c */
+ val = mmio_read_32(reg);
+ val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
+ val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA <<
+ MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA <<
+ MVEBU_CP_MPP_CTRL38_OFFS);
+ mmio_write_32(reg, val);
+}
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ INFO("Gathering DRAM information\n");
+
+ if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ /* configure MPPs to enable i2c */
+ mpp_config();
+
+ /* initialize i2c */
+ i2c_init((void *)MVEBU_CP0_I2C_BASE);
+
+ /* select SPD memory page 0 to access DRAM configuration */
+ i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
+
+ /* read data from spd */
+ i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
+ sizeof(tm->spd_data.all_bytes));
+ }
+}
diff --git a/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
new file mode 100644
index 0000000..4ccda14
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+ /* CP1 SPI1 CS0 Direct Mode access */
+ {0xf900, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+ /* CP1 (MCI0) internal regs */
+ {0x00000000f4000000, 0x2000000, MCI_0_TID},
+#ifndef IMAGE_BLE
+ /* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
+ {0x00000000f9000000, 0x2000000, MCI_0_TID},
+ /* PCIe1 on CP1*/
+ {0x00000000fb000000, 0x1000000, MCI_0_TID},
+ /* PCIe2 on CP1*/
+ {0x00000000fc000000, 0x1000000, MCI_0_TID},
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+ /* CP0 */
+ /* PEX1_X1 window */
+ {0x00000000f7000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000f8000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x1000000, PEX0_TID},
+ {0x00000000c0000000, 0x30000000, PEX0_TID},
+ {0x0000000800000000, 0x100000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+ /* CP1 */
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000f9000000, 0x1000000, RUNIT_TID},
+ /* PEX1_X1 window */
+ {0x00000000fb000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000fc000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000fa000000, 0x1000000, PEX0_TID}
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = iob_memory_map_cp0;
+ *size = ARRAY_SIZE(iob_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = iob_memory_map_cp1;
+ *size = ARRAY_SIZE(iob_memory_map_cp1);
+ return 0;
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * SoC PM configuration
+ *****************************************************************************
+ */
+/* CP GPIO should be used and the GPIOs should be within same GPIO register */
+struct power_off_method pm_cfg = {
+ .type = PMIC_GPIO,
+ .cfg.gpio.pin_count = 1,
+ .cfg.gpio.info = {{0, 35} },
+ .cfg.gpio.step_count = 7,
+ .cfg.gpio.seq = {1, 0, 1, 0, 1, 0, 1},
+ .cfg.gpio.delay_ms = 10,
+};
+
+void *plat_marvell_get_pm_cfg(void)
+{
+ /* Return the PM configurations */
+ return &pm_cfg;
+}
+
+/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
+#else
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+#if PLAT_RECOVERY_IMAGE_ENABLE
+struct skip_image skip_im = {
+ .detection_method = GPIO,
+ .info.gpio.num = 33,
+ .info.gpio.button_state = HIGH,
+ .info.test.cp_ap = CP,
+ .info.test.cp_index = 0,
+};
+
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* Return the skip_image configurations */
+ return &skip_im;
+}
+#endif
+#endif
diff --git a/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h b/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h
new file mode 100644
index 0000000..afa3be1
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef PHY_PORTING_LAYER_H
+#define PHY_PORTING_LAYER_H
+
+#define MAX_LANE_NR 6
+
+static const struct xfi_params
+ xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ /* AP0 */
+ {
+ /* CP 0 */
+ {
+ { 0 }, /* Comphy0 */
+ { 0 }, /* Comphy1 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+ .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 0x1 }, /* Comphy2 */
+ { 0 }, /* Comphy3 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+ .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 0x1 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+ },
+
+ /* CP 1 */
+ {
+ { 0 }, /* Comphy0 */
+ { 0 }, /* Comphy1 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+ .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 0x1 }, /* Comphy2 */
+ { 0 }, /* Comphy3 */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c, .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1, .g1_tx_emph = 0x0,
+ .g1_rx_selmuff = 0x1, .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 0x1 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+ },
+ },
+};
+
+static const struct sata_params
+ sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ /* AP0 */
+ {
+ /* CP 0 */
+ {
+ { 0 }, /* Comphy0 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1,
+ .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
+ .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
+ .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
+ .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
+ .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
+ .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
+ .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
+ .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
+ .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy1 */
+ { 0 }, /* Comphy2 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1,
+ .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
+ .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
+ .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
+ .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
+ .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
+ .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
+ .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
+ .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
+ .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy3 */
+ { 0 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+ },
+
+ /* CP 1 */
+ {
+ { 0 }, /* Comphy0 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1,
+ .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
+ .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
+ .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
+ .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
+ .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
+ .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
+ .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
+ .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
+ .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy1 */
+ { 0 }, /* Comphy2 */
+ { .g1_amp = 0x8, .g2_amp = 0xa, .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2, .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1,
+ .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
+ .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
+ .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
+ .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
+ .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
+ .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
+ .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
+ .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
+ .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ }, /* Comphy3 */
+ { 0 }, /* Comphy4 */
+ { 0 }, /* Comphy5 */
+
+ },
+ },
+};
+
+static const struct usb_params
+ usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = {
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT
+ },
+};
+#endif /* PHY_PORTING_LAYER_H */
diff --git a/plat/marvell/armada/a8k/a80x0/mvebu_def.h b/plat/marvell/armada/a8k/a80x0/mvebu_def.h
new file mode 100644
index 0000000..3fa119a
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0/mvebu_def.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */
+#define I2C_SPD_ADDR 0x53 /* Access SPD data */
+#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a80x0/platform.mk b/plat/marvell/armada/a8k/a80x0/platform.mk
new file mode 100644
index 0000000..115dd4a
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 2
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c
new file mode 100644
index 0000000..85c931c
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/mentor/mi2cv.h>
+#include <lib/mmio.h>
+
+#include <mv_ddr_if.h>
+#include <mvebu_def.h>
+#include <plat_marvell.h>
+
+#define MVEBU_CP_MPP_CTRL37_OFFS 20
+#define MVEBU_CP_MPP_CTRL38_OFFS 24
+#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
+#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
+
+#define MVEBU_MPP_CTRL_MASK 0xf
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+ /* Board with 1CS 8Gb x4 devices of Micron 2400T */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0} },
+ /* TODO: double check if the speed bin is 2400T */
+ SPEED_BIN_DDR_2400T, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ MV_DDR_64BIT_BUS_MASK, /* subphys mask */
+ MV_DDR_CFG_SPD, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ /* Return the board topology as defined in the board code */
+ return &board_topology_map;
+}
+
+static void mpp_config(void)
+{
+ uint32_t val;
+ uintptr_t reg = MVEBU_CP_MPP_REGS(0, 4);
+
+ /* configure CP0 MPP 37 and 38 to i2c */
+ val = mmio_read_32(reg);
+ val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
+ val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA << MVEBU_CP_MPP_CTRL38_OFFS);
+ mmio_write_32(reg, val);
+}
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ INFO("Gathering DRAM information\n");
+
+ if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ /* configure MPPs to enable i2c */
+ mpp_config();
+ /* initialize the i2c */
+ i2c_init((void *)MVEBU_CP0_I2C_BASE);
+ /* select SPD memory page 0 to access DRAM configuration */
+ i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
+ /* read data from spd */
+ i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
+ sizeof(tm->spd_data.all_bytes));
+ }
+}
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
new file mode 100644
index 0000000..75a1b0c
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * GPIO Configuration
+ *****************************************************************************
+ */
+#define MPP_CONTROL_REGISTER 0xf2440018
+#define MPP_CONTROL_MPP_SEL_52_MASK 0xf0000
+#define GPIO_DATA_OUT1_REGISTER 0xf2440140
+#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144
+#define GPIO52_MASK 0x100000
+
+/* Reset PCIe via GPIO number 52 */
+int marvell_gpio_config(void)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(MPP_CONTROL_REGISTER);
+ reg |= MPP_CONTROL_MPP_SEL_52_MASK;
+ mmio_write_32(MPP_CONTROL_REGISTER, reg);
+
+ reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER);
+ reg |= GPIO52_MASK;
+ mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg);
+
+ reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER);
+ reg &= ~GPIO52_MASK;
+ mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg);
+ udelay(100);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+ /* CP1 SPI1 CS0 Direct Mode access */
+ {0xf900, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+ /* CP1 (MCI0) internal regs */
+ {0x00000000f4000000, 0x2000000, MCI_0_TID},
+#ifndef IMAGE_BLE
+ /* PCIe0-2 and SPI1_CS0 (RUNIT) on CP1*/
+ {0x00000000f9000000, 0x4000000, MCI_0_TID},
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+ /* CP0 */
+ /* PEX1_X1 window */
+ {0x00000000f7000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000f8000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x1000000, PEX0_TID},
+ {0x00000000c0000000, 0x30000000, PEX0_TID},
+ {0x0000000800000000, 0x100000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+ /* CP1 */
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000f9000000, 0x1000000, RUNIT_TID},
+ /* PEX1_X1 window */
+ {0x00000000fb000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000fc000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000fa000000, 0x1000000, PEX0_TID}
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = iob_memory_map_cp0;
+ *size = ARRAY_SIZE(iob_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = iob_memory_map_cp1;
+ *size = ARRAY_SIZE(iob_memory_map_cp1);
+ return 0;
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ /* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+ * and changes the window target to SRAM_TID.
+ */
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
+
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* No recovery button on A8k-MCBIN board */
+ return NULL;
+}
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h b/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h
new file mode 100644
index 0000000..3fa119a
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */
+#define I2C_SPD_ADDR 0x53 /* Access SPD data */
+#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk b/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk
new file mode 100644
index 0000000..115dd4a
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 2
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
new file mode 100644
index 0000000..1d8e9d2
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/mentor/mi2cv.h>
+#include <lib/mmio.h>
+
+#include <mv_ddr_if.h>
+#include <mvebu_def.h>
+#include <plat_marvell.h>
+
+#define MVEBU_AP_MPP_CTRL0_7_REG MVEBU_AP_MPP_REGS(0)
+#define MVEBU_AP_MPP_CTRL4_OFFS 16
+#define MVEBU_AP_MPP_CTRL5_OFFS 20
+#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA 0x3
+#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA 0x3
+
+#define MVEBU_CP_MPP_CTRL37_OFFS 20
+#define MVEBU_CP_MPP_CTRL38_OFFS 24
+#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
+#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
+
+#define MVEBU_MPP_CTRL_MASK 0xf
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+static struct mv_ddr_topology_map board_topology_map = {
+ /* Board with 1CS 8Gb x4 devices of Micron 2400T */
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x0, 0, 0}, /* FIXME: change the cs mask for all 64 bit */
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0} },
+ /* TODO: double check if the speed bin is 2400T */
+ SPEED_BIN_DDR_2400T, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+ MV_DDR_64BIT_BUS_MASK, /* subphys mask */
+ MV_DDR_CFG_SPD, /* ddr configuration data source */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ {
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4, /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1 /* rtt_park 2cs */
+ },
+ {
+ MV_DDR_RTT_WR_DYN_ODT_OFF, /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_RZQ_DIV2 /* rtt_wr 2cs */
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON, /* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_read */
+ },
+ }
+};
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ /* Return the board topology as defined in the board code */
+ return &board_topology_map;
+}
+
+static void mpp_config(void)
+{
+ uint32_t val;
+ uintptr_t reg;
+
+ /* configure ap mmps 4, 5 to I2C */
+ reg = MVEBU_AP_MPP_CTRL0_7_REG;
+
+ val = mmio_read_32(reg);
+ val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL4_OFFS) |
+ (MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL5_OFFS));
+ val |= ((MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA << MVEBU_AP_MPP_CTRL4_OFFS) |
+ (MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA << MVEBU_AP_MPP_CTRL5_OFFS));
+
+ mmio_write_32(reg, val);
+}
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ INFO("Gathering DRAM information\n");
+
+ if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ /* configure MPPs to enable i2c */
+ mpp_config();
+ /* initialize the MVEBU_AP_I2C_BASE I2C bus */
+ i2c_init((void *)MVEBU_AP_I2C_BASE);
+ /* select SPD memory page 0 to access DRAM configuration */
+ i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
+ /* read data from spd */
+ i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
+ sizeof(tm->spd_data.all_bytes));
+ }
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
new file mode 100644
index 0000000..0edc977
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#include <mvebu_def.h>
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * GPIO Configuration
+ *****************************************************************************
+ */
+#define MPP_CONTROL_REGISTER 0xf2440018
+#define MPP_CONTROL_MPP_SEL_52_MASK 0xf0000
+#define GPIO_DATA_OUT1_REGISTER 0xf2440140
+#define GPIO_DATA_OUT_EN_CTRL1_REGISTER 0xf2440144
+#define GPIO52_MASK 0x100000
+
+/* Reset PCIe via GPIO number 52 */
+int marvell_gpio_config(void)
+{
+ uint32_t reg;
+
+ reg = mmio_read_32(MPP_CONTROL_REGISTER);
+ reg |= MPP_CONTROL_MPP_SEL_52_MASK;
+ mmio_write_32(MPP_CONTROL_REGISTER, reg);
+
+ reg = mmio_read_32(GPIO_DATA_OUT1_REGISTER);
+ reg |= GPIO52_MASK;
+ mmio_write_32(GPIO_DATA_OUT1_REGISTER, reg);
+
+ reg = mmio_read_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER);
+ reg &= ~GPIO52_MASK;
+ mmio_write_32(GPIO_DATA_OUT_EN_CTRL1_REGISTER, reg);
+ udelay(100);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map[] = {
+ /* CP1 SPI1 CS0 Direct Mode access */
+ {0xf900, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ *win = amb_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(amb_memory_map);
+
+ return 0;
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+ /* CP1 (MCI0) internal regs */
+ {0x00000000f4000000, 0x2000000, MCI_0_TID},
+#ifndef IMAGE_BLE
+ /* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
+ {0x00000000f9000000, 0x2000000, MCI_0_TID},
+ /* PCIe1 on CP1*/
+ {0x00000000fb000000, 0x1000000, MCI_0_TID},
+ /* PCIe2 on CP1*/
+ {0x00000000fc000000, 0x1000000, MCI_0_TID},
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+ /* CP0 */
+ /* PEX1_X1 window */
+ {0x00000000f7000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000f8000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000f6000000, 0x1000000, PEX0_TID},
+ {0x00000000c0000000, 0x30000000, PEX0_TID},
+ {0x0000000800000000, 0x100000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+ /* CP1 */
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000f9000000, 0x1000000, RUNIT_TID},
+ /* PEX1_X1 window */
+ {0x00000000fb000000, 0x1000000, PEX1_TID},
+ /* PEX2_X1 window */
+ {0x00000000fc000000, 0x1000000, PEX2_TID},
+ /* PEX0_X4 window */
+ {0x00000000fa000000, 0x1000000, PEX0_TID}
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = iob_memory_map_cp0;
+ *size = ARRAY_SIZE(iob_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = iob_memory_map_cp1;
+ *size = ARRAY_SIZE(iob_memory_map_cp1);
+ return 0;
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x4000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+/* In reference to #ifndef IMAGE_BLE, this part is used for BLE only. */
+
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_marvell_get_skip_image_data(void)
+{
+ /* No recovery button on A8k-MCBIN board */
+ return NULL;
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
new file mode 100644
index 0000000..eb00874
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Sartura Ltd.
+ * Author: Luka Kovacic <luka.kovacic@sartura.hr>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <drivers/console.h>
+#include <plat_marvell.h>
+
+/*****************************************************************************
+ * Platform specific power off functions
+ * Power off PSU / Send command to power management MCU / ...
+ *****************************************************************************
+ */
+
+unsigned char add_xor_checksum(unsigned char *buf, unsigned char xor_len)
+{
+ unsigned char xor_sum = 0;
+ unsigned int i;
+
+ for (i = 0; i < xor_len; i++)
+ xor_sum ^= buf[i];
+
+ return xor_sum;
+}
+
+int system_power_off(void)
+{
+ static console_t console;
+
+ /* WT61P803 MCU system_off_now command */
+ unsigned char system_off_now[4] = { '@', 'C', '0' };
+ int i, len;
+
+ len = sizeof(system_off_now);
+ system_off_now[len - 1] = add_xor_checksum(system_off_now, len);
+
+ console_16550_register(PLAT_MARVELL_UART_BASE + 0x100,
+ PLAT_MARVELL_UART_CLK_IN_HZ, 115200, &console);
+
+ /* Send system_off_now to console */
+ for (i = 0; i < len; i++) {
+ console.putc(system_off_now[i], &console);
+ udelay(1000);
+ }
+
+ console.flush(&console);
+ (void)console_unregister(&console);
+
+ mdelay(100);
+
+ return 0;
+}
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h b/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
new file mode 100644
index 0000000..3fa119a
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MVEBU_DEF_H
+#define MVEBU_DEF_H
+
+#include <a8k_plat_def.h>
+
+#define CP_COUNT 2 /* A80x0 has both CP0 & CP1 */
+#define I2C_SPD_ADDR 0x53 /* Access SPD data */
+#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
+
+#endif /* MVEBU_DEF_H */
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
new file mode 100644
index 0000000..3378d53
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 2
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_8K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/apn806_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
new file mode 100644
index 0000000..4d8a87f
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -0,0 +1,192 @@
+#
+# Copyright (C) 2016 - 2020 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+
+PLAT_FAMILY := a8k
+PLAT_INCLUDE_BASE := include/plat/marvell/armada/$(PLAT_FAMILY)
+PLAT_COMMON_BASE := plat/marvell/armada/a8k/common
+MARVELL_DRV_BASE := drivers/marvell
+MARVELL_COMMON_BASE := plat/marvell/armada/common
+
+MARVELL_SVC_TEST := 0
+$(eval $(call add_define,MARVELL_SVC_TEST))
+
+ERRATA_A72_859971 := 1
+
+# Enable MSS support for a8k family
+MSS_SUPPORT := 1
+$(eval $(call add_define,MSS_SUPPORT))
+
+# Disable EL3 cache for power management
+BL31_CACHE_DISABLE := 0
+$(eval $(call add_define,BL31_CACHE_DISABLE))
+
+$(eval $(call add_define,PCI_EP_SUPPORT))
+$(eval $(call assert_boolean,PCI_EP_SUPPORT))
+
+AP_NUM := 1
+$(eval $(call add_define,AP_NUM))
+
+DOIMAGEPATH ?= tools/marvell/doimage
+DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
+
+include plat/marvell/marvell.mk
+include tools/marvell/doimage/doimage.mk
+
+ifeq (${MARVELL_SECURE_BOOT},1)
+DOIMAGE_SEC_FLAGS := -c $(DOIMAGE_SEC)
+DOIMAGE_LIBS_CHECK = \
+ if ! [ -d "/usr/include/mbedtls" ]; then \
+ echo "****************************************" >&2; \
+ echo "Missing mbedTLS installation! " >&2; \
+ echo "Please download it from \"tls.mbed.org\"" >&2; \
+ echo "Alternatively on Debian/Ubuntu system install" >&2; \
+ echo "\"libmbedtls-dev\" package" >&2; \
+ echo "Make sure to use version 2.1.0 or later" >&2; \
+ echo "****************************************" >&2; \
+ exit 1; \
+ else if ! [ -f "/usr/include/libconfig.h" ]; then \
+ echo "********************************************************" >&2; \
+ echo "Missing Libconfig installation!" >&2; \
+ echo "Please download it from \"www.hyperrealm.com/libconfig/\"" >&2; \
+ echo "Alternatively on Debian/Ubuntu system install packages" >&2; \
+ echo "\"libconfig8\" and \"libconfig8-dev\"" >&2; \
+ echo "********************************************************" >&2; \
+ exit 1; \
+ fi \
+ fi
+else #MARVELL_SECURE_BOOT
+DOIMAGE_LIBS_CHECK =
+DOIMAGE_SEC_FLAGS =
+endif #MARVELL_SECURE_BOOT
+
+ROM_BIN_EXT ?= $(BUILD_PLAT)/ble.bin
+DOIMAGE_FLAGS += -b $(ROM_BIN_EXT) $(NAND_DOIMAGE_FLAGS) $(DOIMAGE_SEC_FLAGS)
+
+# Check whether to build system_power.c for the platform
+ifneq ("$(wildcard $(BOARD_DIR)/board/system_power.c)","")
+SYSTEM_POWER_SUPPORT = 1
+else
+SYSTEM_POWER_SUPPORT = 0
+endif
+
+# This define specifies DDR type for BLE
+$(eval $(call add_define,CONFIG_DDR4))
+
+# This define specifies DDR topology for BLE
+DDR_TOPOLOGY ?= 0
+$(eval $(call add_define,DDR_TOPOLOGY))
+
+MARVELL_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ plat/common/plat_gicv2.c
+
+PLAT_INCLUDES += -I$(BOARD_DIR) \
+ -I$(BOARD_DIR)/board \
+ -I$(CURDIR)/drivers/marvell \
+ -I$(PLAT_COMMON_BASE)/include \
+ -I$(PLAT_INCLUDE_BASE)/common
+
+PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a8k_common.c \
+ drivers/ti/uart/aarch64/16550_console.S
+
+ifndef BLE_PORTING_SOURCES
+BLE_PORTING_SOURCES := $(BOARD_DIR)/board/dram_port.c \
+ $(BOARD_DIR)/board/marvell_plat_config.c
+endif
+
+MARVELL_MOCHI_DRV += $(MARVELL_DRV_BASE)/mochi/cp110_setup.c
+
+BLE_SOURCES := drivers/mentor/i2c/mi2cv.c \
+ $(PLAT_COMMON_BASE)/plat_ble_setup.c \
+ $(MARVELL_MOCHI_DRV) \
+ $(PLAT_COMMON_BASE)/plat_pm.c \
+ $(MARVELL_DRV_BASE)/ap807_clocks_init.c \
+ $(MARVELL_DRV_BASE)/thermal.c \
+ $(PLAT_COMMON_BASE)/plat_thermal.c \
+ $(BLE_PORTING_SOURCES) \
+ $(MARVELL_DRV_BASE)/ccu.c \
+ $(MARVELL_DRV_BASE)/io_win.c
+
+BL1_SOURCES += $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
+ lib/cpus/aarch64/cortex_a72.S
+
+MARVELL_DRV := $(MARVELL_DRV_BASE)/io_win.c \
+ $(MARVELL_DRV_BASE)/iob.c \
+ $(MARVELL_DRV_BASE)/mci.c \
+ $(MARVELL_DRV_BASE)/amb_adec.c \
+ $(MARVELL_DRV_BASE)/ccu.c \
+ $(MARVELL_DRV_BASE)/cache_llc.c \
+ $(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
+ $(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
+ $(MARVELL_DRV_BASE)/secure_dfx_access/armada_thermal.c \
+ $(MARVELL_DRV_BASE)/secure_dfx_access/misc_dfx.c \
+ $(MARVELL_DRV_BASE)/ddr_phy_access.c \
+ drivers/rambus/trng_ip_76.c
+
+ifeq (${MSS_SUPPORT}, 1)
+MARVELL_DRV += $(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
+endif
+
+ifndef BL31_PORTING_SOURCES
+BL31_PORTING_SOURCES := $(BOARD_DIR)/board/marvell_plat_config.c
+endif
+
+ifeq ($(SYSTEM_POWER_SUPPORT),1)
+BL31_PORTING_SOURCES += $(BOARD_DIR)/board/system_power.c
+endif
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \
+ $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
+ $(PLAT_COMMON_BASE)/aarch64/plat_arch_config.c \
+ $(PLAT_COMMON_BASE)/plat_pm.c \
+ $(PLAT_COMMON_BASE)/plat_bl31_setup.c \
+ $(MARVELL_COMMON_BASE)/marvell_gicv2.c \
+ $(MARVELL_COMMON_BASE)/mrvl_sip_svc.c \
+ $(MARVELL_COMMON_BASE)/marvell_ddr_info.c \
+ $(BL31_PORTING_SOURCES) \
+ $(MARVELL_DRV) \
+ $(MARVELL_MOCHI_DRV) \
+ $(MARVELL_GIC_SOURCES)
+
+# Add trace functionality for PM
+BL31_SOURCES += $(PLAT_COMMON_BASE)/plat_pm_trace.c
+
+
+ifeq (${MSS_SUPPORT}, 1)
+# Force builds with BL2 image on a80x0 platforms
+ifndef SCP_BL2
+ $(error "Error: SCP_BL2 image is mandatory for a8k family")
+endif
+
+# MSS (SCP) build
+include $(PLAT_COMMON_BASE)/mss/mss_a8k.mk
+endif
+
+# BLE (ROM context execution code, AKA binary extension)
+BLE_PATH ?= $(PLAT_COMMON_BASE)/ble
+
+include ${BLE_PATH}/ble.mk
+$(eval $(call MAKE_BL,ble))
+
+clean realclean distclean: mrvl_clean
+
+.PHONY: mrvl_clean
+mrvl_clean:
+ @echo " Doimage CLEAN"
+ ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${DOIMAGEPATH} clean
+
+${DOIMAGETOOL}: FORCE
+ @$(DOIMAGE_LIBS_CHECK)
+ ${Q}${MAKE} --no-print-directory -C ${DOIMAGEPATH}
+
+${BUILD_PLAT}/${FLASH_IMAGE}: ${ROM_BIN_EXT} ${BUILD_PLAT}/${BOOT_IMAGE} ${DOIMAGETOOL}
+ @${ECHO_BLANK_LINE}
+ @echo "Building flash image"
+ ${Q}${DOIMAGETOOL} ${DOIMAGE_FLAGS} ${BUILD_PLAT}/${BOOT_IMAGE} ${BUILD_PLAT}/${FLASH_IMAGE}
+ @${ECHO_BLANK_LINE}
+ @echo "Built $@ successfully"
+ @${ECHO_BLANK_LINE}
diff --git a/plat/marvell/armada/a8k/common/aarch64/a8k_common.c b/plat/marvell/armada/a8k/common/aarch64/a8k_common.c
new file mode 100644
index 0000000..4332a76
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/aarch64/a8k_common.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <plat_marvell.h>
+
+
+/* MMU entry for internal (register) space access */
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SECURE_RAM,
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+#if IMAGE_BL2
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SECURE_RAM,
+ MAP_DEVICE0,
+ MARVELL_MAP_DRAM,
+#ifdef SPD_opteed
+ MARVELL_MAP_OPTEE_CORE_MEM,
+ MARVELL_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
+ {0}
+};
+#endif
+
+#if IMAGE_BL2U
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SECURE_RAM,
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+
+#if IMAGE_BLE
+const mmap_region_t plat_marvell_mmap[] = {
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SECURE_RAM,
+ MAP_DEVICE0,
+ MARVELL_MAP_DRAM,
+ {0}
+};
+#endif
+#if IMAGE_BL32
+const mmap_region_t plat_marvell_mmap[] = {
+ MARVELL_MAP_SECURE_RAM,
+ MAP_DEVICE0,
+ {0}
+};
+#endif
+
+MARVELL_CASSERT_MMAP;
diff --git a/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c b/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
new file mode 100644
index 0000000..d576514
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/marvell/cache_llc.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#define CCU_HTC_ASET (MVEBU_CCU_BASE(MVEBU_AP0) + 0x264)
+#define MVEBU_IO_AFFINITY (0xF00)
+#define MVEBU_SF_REG (MVEBU_REGS_BASE + 0x40)
+#define MVEBU_SF_EN BIT(8)
+#define MVEBU_DFX_REG(cluster_id) (MVEBU_REGS_BASE + 0x6F82A0 + \
+ (cluster_id) * 0x4)
+#define MVEBU_DFX_CLK_EN_POS 0x3
+#define MVEBU_DFX_CL0_CLK_OFFS 16
+#define MVEBU_DFX_CL0_CLK_MASK (0xF << MVEBU_DFX_CL0_CLK_OFFS)
+#define MVEBU_DFX_CL1_CLK_OFFS 8
+#define MVEBU_DFX_CL1_CLK_MASK (0xF << MVEBU_DFX_CL1_CLK_OFFS)
+
+#ifdef MVEBU_SOC_AP807
+static void plat_enable_snoop_filter(void)
+{
+ int cpu_id = plat_my_core_pos();
+
+ /* Snoop filter needs to be enabled once per cluster */
+ if (cpu_id % 2)
+ return;
+
+ mmio_setbits_32(MVEBU_SF_REG, MVEBU_SF_EN);
+}
+#endif
+
+#ifndef MVEBU_SOC_AP807
+static void plat_config_dfx_clock(void)
+{
+ int cluster_id = plat_my_core_pos();
+ uint32_t val;
+
+ /* DFX clock needs to be configured once per cluster */
+ if ((cluster_id % PLAT_MAX_CPUS_PER_CLUSTER) != 0) {
+ return;
+ }
+
+ val = mmio_read_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER));
+ if (cluster_id == 0) {
+ val &= ~MVEBU_DFX_CL0_CLK_MASK;
+ val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL0_CLK_OFFS);
+ } else {
+ val &= ~MVEBU_DFX_CL1_CLK_MASK;
+ val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL1_CLK_OFFS);
+ }
+ mmio_write_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER), val);
+}
+#endif
+
+static void plat_enable_affinity(void)
+{
+ int cluster_id;
+ int affinity;
+
+ /* set CPU Affinity */
+ cluster_id = plat_my_core_pos() / PLAT_MARVELL_CLUSTER_CORE_COUNT;
+ affinity = (MVEBU_IO_AFFINITY | (1 << cluster_id));
+ mmio_write_32(CCU_HTC_ASET, affinity);
+
+ /* set barier */
+ isb();
+}
+
+void marvell_psci_arch_init(int die_index)
+{
+#if LLC_ENABLE
+ /* check if LLC is in exclusive mode
+ * as L2 is configured to UniqueClean eviction
+ * (in a8k reset handler)
+ */
+ if (llc_is_exclusive(0) == 0)
+ ERROR("LLC should be configured to exclusice mode\n");
+#endif
+
+ /* Enable Affinity */
+ plat_enable_affinity();
+
+#ifdef MVEBU_SOC_AP807
+ plat_enable_snoop_filter();
+#else
+ plat_config_dfx_clock();
+#endif
+}
diff --git a/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S b/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..fadc4c2
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <marvell_pm.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_reset_handler
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset. Right
+ * now this is a stub function.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ mov x0, #0
+ ret
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish
+ * between a cold and warm boot
+ * For a cold boot, return 0.
+ * For a warm boot, read the mailbox and return the address it contains.
+ *
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ /* Read first word and compare it with magic num */
+ mov_imm x0, PLAT_MARVELL_MAILBOX_BASE
+ ldr x1, [x0]
+ mov_imm x2, MVEBU_MAILBOX_MAGIC_NUM
+ cmp x1, x2
+ beq warm_boot /* If compare failed, return 0, i.e. cold boot */
+ mov x0, #0
+ ret
+warm_boot:
+ mov_imm x1, MBOX_IDX_SEC_ADDR /* Get the jump address */
+ subs x1, x1, #1
+ mov x2, #(MBOX_IDX_SEC_ADDR * 8)
+ lsl x3, x2, x1
+ add x0, x0, x3
+ ldr x0, [x0]
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #MVEBU_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler (void);
+ *
+ * Platform specific configuration right after cpu is
+ * is our of reset.
+ *
+ * The plat_reset_handler can clobber x0 - x18, x30.
+ * -----------------------------------------------------
+ */
+func plat_reset_handler
+ /*
+ * Note: the configurations below should be done before MMU,
+ * I Cache and L2are enabled.
+ * The reset handler is executed right after reset
+ * and before Caches are enabled.
+ */
+
+ /* Enable L1/L2 ECC and Parity */
+ mrs x5, s3_1_c11_c0_2 /* L2 Ctrl */
+ orr x5, x5, #(1 << 21) /* Enable L1/L2 cache ECC & Parity */
+ msr s3_1_c11_c0_2, x5 /* L2 Ctrl */
+
+#if LLC_ENABLE
+ /*
+ * Enable L2 UniqueClean evictions
+ * Note: this configuration assumes that LLC is configured
+ * in exclusive mode.
+ * Later on in the code this assumption will be validated
+ */
+ mrs x5, s3_1_c15_c0_0 /* L2 Ctrl */
+ orr x5, x5, #(1 << 14) /* Enable UniqueClean evictions with data */
+ msr s3_1_c15_c0_0, x5 /* L2 Ctrl */
+#endif
+
+ /* Instruction Barrier to allow msr command completion */
+ isb
+
+ ret
+endfunc plat_reset_handler
diff --git a/plat/marvell/armada/a8k/common/ble/ble.ld.S b/plat/marvell/armada/a8k/common/ble/ble.ld.S
new file mode 100644
index 0000000..d7a0592
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/ble/ble.ld.S
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <platform_def.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+ENTRY(ble_main)
+
+MEMORY {
+ RAM (rwx): ORIGIN = BLE_BASE, LENGTH = BLE_LIMIT - BLE_BASE
+}
+
+SECTIONS
+{
+ . = BLE_BASE;
+
+ ro . : {
+ __RO_START__ = .;
+ *ble_main.o(.entry*)
+ *(.text*)
+ *(.rodata*)
+ __RO_END_UNALIGNED__ = .;
+ __RO_END__ = .;
+ } >RAM
+
+ /*
+ * Define a linker symbol to mark start of the RW memory area for this
+ * image.
+ */
+ __RW_START__ = . ;
+
+ .data . : {
+ __DATA_START__ = .;
+ *(.data*)
+ __DATA_END__ = .;
+ } >RAM
+
+ stacks . (NOLOAD) : {
+ __STACKS_START__ = .;
+ *(tzfw_normal_stacks)
+ __STACKS_END__ = .;
+ } >RAM
+
+ .bss : {
+ __BSS_START__ = .;
+ *(.bss*)
+ __BSS_END__ = .;
+ } >RAM
+
+ /*
+ * Extend the BLE binary to the maximum size allocated for it in platform
+ * definition files and prevent overlapping between BLE BSS section and
+ * additional extensions that can follow the BLE in flash image preamble.
+ * This situation happens for instance when secure extension is added to
+ * the image preamble.
+ */
+ .fill LOADADDR(.bss) + SIZEOF(.bss) : {
+ FILL(0xDEADC0DE);
+ . = ORIGIN(RAM) + LENGTH(RAM) - 1;
+ BYTE(0x00)
+ } >RAM
+
+ /*
+ * Define a linker symbol to mark end of the RW memory area for this
+ * image.
+ */
+ __RW_END__ = .;
+ __BLE_END__ = .;
+
+ __BSS_SIZE__ = SIZEOF(.bss);
+}
diff --git a/plat/marvell/armada/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk
new file mode 100644
index 0000000..160e98f
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/ble/ble.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+
+MV_DDR_LIB = $(BUILD_PLAT)/ble/mv_ddr_lib.a
+LIBC_LIB = $(BUILD_PLAT)/lib/libc.a
+BLE_LIBS = $(MV_DDR_LIB) $(LIBC_LIB)
+PLAT_MARVELL = plat/marvell/armada
+
+BLE_SOURCES += $(BLE_PATH)/ble_main.c \
+ $(BLE_PATH)/ble_mem.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/marvell/iob.c \
+ $(PLAT_MARVELL)/common/aarch64/marvell_helpers.S \
+ $(PLAT_MARVELL)/common/plat_delay_timer.c \
+ $(PLAT_MARVELL)/common/marvell_console.c
+
+MV_DDR_INCLUDES := -I$(CURDIR)/include \
+ -I$(CURDIR)/include/arch/aarch64 \
+ -I$(CURDIR)/include/lib/libc \
+ -I$(CURDIR)/include/lib/libc/aarch64
+
+BLE_LINKERFILE := $(BLE_PATH)/ble.ld.S
+
+BLE_OBJS := $(addprefix $(BUILD_PLAT)/ble/,$(call SOURCES_TO_OBJS,$(BLE_SOURCES)))
+$(BLE_OBJS): PLAT_INCLUDES += -I$(MV_DDR_PATH)
+$(BLE_OBJS): $(MV_DDR_LIB)
+
+$(MV_DDR_LIB): FORCE
+# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
+ $(if $(value MV_DDR_PATH),,$(error "Platform '$(PLAT)' for BLE requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
+ $(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
+ $(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
+ @+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(MV_DDR_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble
diff --git a/plat/marvell/armada/a8k/common/ble/ble_main.c b/plat/marvell/armada/a8k/common/ble/ble_main.c
new file mode 100644
index 0000000..5b3acec
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/ble/ble_main.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+
+#include <marvell_plat_priv.h>
+#include <marvell_pm.h>
+#include <plat_marvell.h>
+
+#define BR_FLAG_SILENT 0x1
+#define SKIP_IMAGE_CODE 0xDEADB002
+
+void mailbox_clean(void)
+{
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ memset(mailbox, 0, PLAT_MARVELL_MAILBOX_SIZE);
+}
+
+int exec_ble_main(int bootrom_flags)
+{
+ int skip = 0;
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ /*
+ * In some situations, like boot from UART, bootrom will
+ * request to avoid printing to console. in that case don't
+ * initialize the console and prints will be ignored
+ */
+ if ((bootrom_flags & BR_FLAG_SILENT) == 0)
+ marvell_console_boot_init();
+
+ NOTICE("Starting binary extension\n");
+
+ /* initialize time (for delay functionality) */
+ plat_delay_timer_init();
+
+ ble_plat_setup(&skip);
+
+ /* if there's skip image request, bootrom will load from the image
+ * saved on the next address of the flash
+ */
+ if (skip)
+ return SKIP_IMAGE_CODE;
+
+ /*
+ * Check if the mailbox magic number is stored at index MBOX_IDX_MAGIC
+ * and the suspend to RAM magic number at index MBOX_IDX_SUSPEND_MAGIC.
+ * If the above is true, this is the recovery from suspend to RAM state.
+ * In such case the mailbox should remain intact, since it stores the
+ * warm boot jump address to be used by the TF-A in BL31.
+ * Othervise the mailbox should be cleaned from a garbage data.
+ */
+ if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM ||
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE) {
+ NOTICE("Cold boot\n");
+ mailbox_clean();
+ } else {
+ void (*bootrom_exit)(void) =
+ (void (*)(void))mailbox[MBOX_IDX_ROM_EXIT_ADDR];
+
+ INFO("Recovery...\n");
+ /*
+ * If this is recovery from suspend, two things has to be done:
+ * 1. Define the DRAM region as executable memory for preparing
+ * jump to TF-A
+ * 2. Instead of returning control to the BootROM, invalidate
+ * and flush caches, and continue execution at address stored
+ * in the mailbox.
+ * This should be done until the BootROM have a native support
+ * for the system restore flow.
+ */
+ marvell_ble_prepare_exit();
+ bootrom_exit();
+ }
+
+ return 0;
+}
+
+/* NOTE: don't notify this function, all code must be added to exec_ble_main
+ * in order to keep the end of ble_main as a fixed address.
+ */
+int __attribute__ ((section(".entry"))) ble_main(int bootrom_flags)
+{
+ volatile int ret;
+
+ ret = exec_ble_main(bootrom_flags);
+ return ret;
+}
diff --git a/plat/marvell/armada/a8k/common/ble/ble_mem.S b/plat/marvell/armada/a8k/common/ble/ble_mem.S
new file mode 100644
index 0000000..a48d546
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/ble/ble_mem.S
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <asm_macros.S>
+#include <marvell_def.h>
+#include <platform_def.h>
+
+#define PTE_NON_EXEC_OFF 54 /* XN - eXecute Never bit offset - see VMSAv8-64 */
+
+ .globl marvell_ble_prepare_exit
+
+func marvell_ble_prepare_exit
+ /*
+ * Read the page table base and set the first page to be executable.
+ * This is required for jumping to DRAM for further execution.
+ */
+ mrs x0, ttbr0_el3
+ ldr x1, [x0]
+ mov x2, #1
+ bic x1, x1, x2, lsl #PTE_NON_EXEC_OFF
+ str x1, [x0]
+ tlbi alle3
+ dsb sy
+ isb
+ ret
+endfunc marvell_ble_prepare_exit
diff --git a/plat/marvell/armada/a8k/common/include/a8k_plat_def.h b/plat/marvell/armada/a8k/common/include/a8k_plat_def.h
new file mode 100644
index 0000000..3a0fd4b
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/include/a8k_plat_def.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef A8K_PLAT_DEF_H
+#define A8K_PLAT_DEF_H
+
+#include <marvell_def.h>
+
+#define MVEBU_PRIMARY_CPU 0x0
+#define MVEBU_AP0 0x0
+
+/* APN806 revision ID */
+#define MVEBU_CSS_GWD_CTRL_IIDR2_REG (MVEBU_REGS_BASE + 0x610FCC)
+#define GWD_IIDR2_REV_ID_OFFSET 12
+#define GWD_IIDR2_REV_ID_MASK 0xF
+#define GWD_IIDR2_CHIP_ID_OFFSET 20
+#define GWD_IIDR2_CHIP_ID_MASK (0xFFFu << GWD_IIDR2_CHIP_ID_OFFSET)
+
+#define CHIP_ID_AP806 0x806
+#define CHIP_ID_AP807 0x807
+
+#define COUNTER_FREQUENCY 25000000
+
+#define MVEBU_REGS_BASE 0xF0000000
+#define MVEBU_REGS_BASE_MASK 0xF0000000
+#define MVEBU_REGS_BASE_AP(ap) MVEBU_REGS_BASE
+#define MVEBU_AP_IO_BASE(ap) 0xF2000000
+#define MVEBU_CP_OFFSET 0x2000000
+#define MVEBU_CP_REGS_BASE(cp_index) (MVEBU_AP_IO_BASE(0) + \
+ (cp_index) * MVEBU_CP_OFFSET)
+#define MVEBU_RFU_BASE (MVEBU_REGS_BASE + 0x6F0000)
+#define MVEBU_IO_WIN_BASE(ap_index) (MVEBU_RFU_BASE)
+#define MVEBU_IO_WIN_GCR_OFFSET (0x70)
+#define MVEBU_IO_WIN_MAX_WINS (7)
+
+/* Misc SoC configurations Base */
+#define MVEBU_MISC_SOC_BASE (MVEBU_REGS_BASE + 0x6F4300)
+
+#define MVEBU_CCU_BASE(ap_index) (MVEBU_REGS_BASE + 0x4000)
+#define MVEBU_CCU_MAX_WINS (8)
+
+#define MVEBU_LLC_BASE(ap_index) (MVEBU_REGS_BASE + 0x8000)
+#define MVEBU_DRAM_MAC_BASE (MVEBU_REGS_BASE + 0x20000)
+#define MVEBU_DRAM_PHY_BASE (MVEBU_REGS_BASE + 0x20000)
+#define MVEBU_SMMU_BASE (MVEBU_REGS_BASE + 0x100000)
+#define MVEBU_CP_MPP_REGS(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \
+ 0x440000 + ((n) << 2))
+#define MVEBU_PM_MPP_REGS(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \
+ 0x440000 + ((n / 8) << 2))
+#define MVEBU_CP_GPIO_DATA_OUT(cp_index, n) \
+ (MVEBU_CP_REGS_BASE(cp_index) + \
+ 0x440100 + ((n > 31) ? 0x40 : 0x00))
+#define MVEBU_CP_GPIO_DATA_OUT_EN(cp_index, n) \
+ (MVEBU_CP_REGS_BASE(cp_index) + \
+ 0x440104 + ((n > 31) ? 0x40 : 0x00))
+#define MVEBU_CP_GPIO_DATA_IN(cp_index, n) (MVEBU_CP_REGS_BASE(cp_index) + \
+ 0x440110 + ((n > 31) ? 0x40 : 0x00))
+#define MVEBU_AP_MPP_REGS(n) (MVEBU_RFU_BASE + 0x4000 + ((n) << 2))
+#define MVEBU_AP_GPIO_REGS (MVEBU_RFU_BASE + 0x5040)
+#define MVEBU_AP_GPIO_DATA_IN (MVEBU_AP_GPIO_REGS + 0x10)
+#define MVEBU_AP_I2C_BASE (MVEBU_REGS_BASE + 0x511000)
+#define MVEBU_CP0_I2C_BASE (MVEBU_CP_REGS_BASE(0) + 0x701000)
+#define MVEBU_AP_GEN_MGMT_BASE (MVEBU_RFU_BASE + 0x8000)
+#define MVEBU_AP_EXT_TSEN_BASE (MVEBU_AP_GEN_MGMT_BASE + 0x84)
+
+#define MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap, win) (MVEBU_REGS_BASE_AP(ap) + \
+ 0x20080 + ((win) * 0x8))
+#define MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap, win) (MVEBU_REGS_BASE_AP(ap) + \
+ 0x20084 + ((win) * 0x8))
+
+/* MCI indirect access definitions */
+#define MCI_MAX_UNIT_ID 2
+/* SoC RFU / IHBx4 Control */
+#define MCIX4_REG_START_ADDRESS_REG(unit_id) (MVEBU_RFU_BASE + \
+ 0x4218 + (unit_id * 0x20))
+#define MCI_REMAP_OFF_SHIFT 8
+
+#define MVEBU_MCI_REG_BASE_REMAP(index) (0xFD000000 + \
+ ((index) * 0x1000000))
+
+#define MVEBU_PCIE_X4_MAC_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x600000)
+#define MVEBU_COMPHY_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x441000)
+#define MVEBU_HPIPE_BASE(x) (MVEBU_CP_REGS_BASE(x) + 0x120000)
+#define MVEBU_CP_DFX_OFFSET (0x400200)
+
+/*****************************************************************************
+ * MVEBU memory map related constants
+ *****************************************************************************
+ */
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE MVEBU_REGS_BASE
+#define DEVICE0_SIZE 0x10000000
+
+/*****************************************************************************
+ * GIC-400 & interrupt handling related constants
+ *****************************************************************************
+ */
+/* Base MVEBU compatible GIC memory map */
+#define MVEBU_GICD_BASE 0x210000
+#define MVEBU_GICC_BASE 0x220000
+
+
+/*****************************************************************************
+ * AXI Configuration
+ *****************************************************************************
+ */
+#define MVEBU_AXI_ATTR_ARCACHE_OFFSET 4
+#define MVEBU_AXI_ATTR_ARCACHE_MASK (0xF << \
+ MVEBU_AXI_ATTR_ARCACHE_OFFSET)
+#define MVEBU_AXI_ATTR_ARDOMAIN_OFFSET 12
+#define MVEBU_AXI_ATTR_ARDOMAIN_MASK (0x3 << \
+ MVEBU_AXI_ATTR_ARDOMAIN_OFFSET)
+#define MVEBU_AXI_ATTR_AWCACHE_OFFSET 20
+#define MVEBU_AXI_ATTR_AWCACHE_MASK (0xF << \
+ MVEBU_AXI_ATTR_AWCACHE_OFFSET)
+#define MVEBU_AXI_ATTR_AWDOMAIN_OFFSET 28
+#define MVEBU_AXI_ATTR_AWDOMAIN_MASK (0x3 << \
+ MVEBU_AXI_ATTR_AWDOMAIN_OFFSET)
+
+/* SATA MBUS to AXI configuration */
+#define MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET 1
+#define MVEBU_SATA_M2A_AXI_ARCACHE_MASK (0xF << \
+ MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET)
+#define MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET 5
+#define MVEBU_SATA_M2A_AXI_AWCACHE_MASK (0xF << \
+ MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET)
+
+/* ARM cache attributes */
+#define CACHE_ATTR_BUFFERABLE 0x1
+#define CACHE_ATTR_CACHEABLE 0x2
+#define CACHE_ATTR_READ_ALLOC 0x4
+#define CACHE_ATTR_WRITE_ALLOC 0x8
+/* Domain */
+#define DOMAIN_NON_SHAREABLE 0x0
+#define DOMAIN_INNER_SHAREABLE 0x1
+#define DOMAIN_OUTER_SHAREABLE 0x2
+#define DOMAIN_SYSTEM_SHAREABLE 0x3
+
+/************************************************************************
+ * Required platform porting definitions common to all
+ * Management Compute SubSystems (MSS)
+ ************************************************************************
+ */
+/*
+ * Load address of SCP_BL2
+ * SCP_BL2 is loaded to the same place as BL31.
+ * Once SCP_BL2 is transferred to the SCP,
+ * it is discarded and BL31 is loaded over the top.
+ */
+#ifdef SCP_IMAGE
+#define SCP_BL2_BASE BL31_BASE
+#define SCP_BL2_SIZE BL31_LIMIT
+#endif
+
+#ifndef __ASSEMBLER__
+enum ap806_sar_target_dev {
+ SAR_PIDI_MCIX2 = 0x0,
+ SAR_MCIX4 = 0x1,
+ SAR_SPI = 0x2,
+ SAR_SD = 0x3,
+ SAR_PIDI_MCIX2_BD = 0x4, /* BootRom disabled */
+ SAR_MCIX4_DB = 0x5, /* BootRom disabled */
+ SAR_SPI_DB = 0x6, /* BootRom disabled */
+ SAR_EMMC = 0x7
+};
+
+enum io_win_target_ids {
+ MCI_0_TID = 0x0,
+ MCI_1_TID = 0x1,
+ MCI_2_TID = 0x2,
+ PIDI_TID = 0x3,
+ SPI_TID = 0x4,
+ STM_TID = 0x5,
+ BOOTROM_TID = 0x6,
+ IO_WIN_MAX_TID
+};
+
+enum ccu_target_ids {
+ IO_0_TID = 0x00,
+ DRAM_0_TID = 0x03,
+ IO_1_TID = 0x0F,
+ CFG_REG_TID = 0x10,
+ RAR_TID = 0x20,
+ SRAM_TID = 0x40,
+ DRAM_1_TID = 0xC0,
+ CCU_MAX_TID,
+ INVALID_TID = 0xFF
+};
+#endif /* __ASSEMBLER__ */
+
+#endif /* A8K_PLAT_DEF_H */
diff --git a/plat/marvell/armada/a8k/common/include/ddr_info.h b/plat/marvell/armada/a8k/common/include/ddr_info.h
new file mode 100644
index 0000000..e19036a
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/include/ddr_info.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#define DRAM_MAX_IFACE 1
+#define DRAM_CH0_MMAP_LOW_OFFSET 0x20200
diff --git a/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h b/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h
new file mode 100644
index 0000000..e03c448
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+/* This driver provides I2C support for Marvell A8K and compatible SoCs */
+
+#ifndef MENTOR_I2C_PLAT_H
+#define MENTOR_I2C_PLAT_H
+
+#define CONFIG_SYS_TCLK 250000000
+#define CONFIG_SYS_I2C_SPEED 100000
+#define CONFIG_SYS_I2C_SLAVE 0x0
+
+#define I2C_CAN_UNSTUCK
+
+struct mentor_i2c_regs {
+ uint32_t slave_address;
+ uint32_t data;
+ uint32_t control;
+ union {
+ uint32_t status; /* when reading */
+ uint32_t baudrate; /* when writing */
+ };
+ uint32_t xtnd_slave_addr;
+ uint32_t reserved[2];
+ uint32_t soft_reset;
+ uint8_t reserved2[0xa0 - 0x20];
+ uint32_t unstuck;
+};
+
+#endif /* MENTOR_I2C_PLAT_H */
diff --git a/plat/marvell/armada/a8k/common/include/plat_macros.S b/plat/marvell/armada/a8k/common/include/plat_macros.S
new file mode 100644
index 0000000..8faccf0
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/include/plat_macros.S
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <marvell_macros.S>
+
+/*
+ * Required platform porting macros
+ * (Provided by included headers)
+ */
+.macro plat_crash_print_regs
+.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/marvell/armada/a8k/common/include/platform_def.h b/plat/marvell/armada/a8k/common/include/platform_def.h
new file mode 100644
index 0000000..45860ba
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/include/platform_def.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#ifndef __ASSEMBLER__
+#include <stdio.h>
+#endif /* __ASSEMBLER__ */
+
+#include <common/interrupt_props.h>
+#include <drivers/arm/gic_common.h>
+
+#include <board_marvell_def.h>
+#include <mvebu_def.h>
+
+/*
+ * Most platform porting definitions provided by included headers
+ */
+
+/*
+ * DRAM Memory layout:
+ * +-----------------------+
+ * : :
+ * : Linux :
+ * 0x04X00000-->+-----------------------+
+ * | BL3-3(u-boot) |>>}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ * |-----------------------| } |
+ * | BL3-[0,1, 2] | }---------------------------------> |
+ * |-----------------------| } || |
+ * | BL2 | }->FIP (loaded by || |
+ * |-----------------------| } BootROM to DRAM) || |
+ * | FIP_TOC | } || |
+ * 0x04120000-->|-----------------------| || |
+ * | BL1 (RO) | || |
+ * 0x04100000-->+-----------------------+ || |
+ * : : || |
+ * : Trusted SRAM section : \/ |
+ * 0x04040000-->+-----------------------+ Replaced by BL2 +----------------+ |
+ * | BL1 (RW) | <<<<<<<<<<<<<<<< | BL3-1 NOBITS | |
+ * 0x04037000-->|-----------------------| <<<<<<<<<<<<<<<< |----------------| |
+ * | | <<<<<<<<<<<<<<<< | BL3-1 PROGBITS | |
+ * 0x04023000-->|-----------------------| +----------------+ |
+ * | BL2 | |
+ * |-----------------------| |
+ * | | |
+ * 0x04001000-->|-----------------------| |
+ * | Shared | |
+ * 0x04000000-->+-----------------------+ |
+ * : : |
+ * : Linux : |
+ * : : |
+ * |-----------------------| |
+ * | | U-Boot(BL3-3) Loaded by BL2 |
+ * | U-Boot | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ * 0x00000000-->+-----------------------+
+ *
+ * Trusted SRAM section 0x4000000..0x4200000:
+ * ----------------------------------------
+ * SRAM_BASE = 0x4001000
+ * BL2_BASE = 0x4006000
+ * BL2_LIMIT = BL31_BASE
+ * BL31_BASE = 0x4023000 = (64MB + 256KB - 0x1D000)
+ * BL31_PROGBITS_LIMIT = BL1_RW_BASE
+ * BL1_RW_BASE = 0x4037000 = (64MB + 256KB - 0x9000)
+ * BL1_RW_LIMIT = BL31_LIMIT = 0x4040000
+ *
+ *
+ * PLAT_MARVELL_FIP_BASE = 0x4120000
+ */
+
+#define PLAT_MARVELL_SRAM_BASE 0xFFE1C048
+#define PLAT_MARVELL_SRAM_END 0xFFE78000
+
+#define PLAT_MARVELL_ATF_BASE 0x4000000
+#define PLAT_MARVELL_ATF_LOAD_ADDR (PLAT_MARVELL_ATF_BASE + \
+ 0x100000)
+
+#define PLAT_MARVELL_FIP_BASE (PLAT_MARVELL_ATF_LOAD_ADDR + \
+ 0x20000)
+#define PLAT_MARVELL_FIP_MAX_SIZE 0x4000000
+
+#define PLAT_MARVELL_NORTHB_COUNT 1
+
+#define PLAT_MARVELL_CLUSTER_COUNT U(2)
+#define PLAT_MARVELL_CLUSTER_CORE_COUNT U(2)
+
+#define PLAT_MARVELL_CORE_COUNT (PLAT_MARVELL_CLUSTER_COUNT * \
+ PLAT_MARVELL_CLUSTER_CORE_COUNT)
+
+#define PLAT_MAX_CPUS_PER_CLUSTER PLAT_MARVELL_CLUSTER_CORE_COUNT
+
+/* Part of DRAM that is used as Trusted ROM */
+#define PLAT_MARVELL_TRUSTED_ROM_BASE PLAT_MARVELL_ATF_LOAD_ADDR
+/* 4 MB for FIP image */
+#define PLAT_MARVELL_TRUSTED_ROM_SIZE 0x00400000
+/* Reserve 12MB for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE 4MB SHMEM follows this region
+ */
+#define PLAT_MARVELL_TRUSTED_RAM_BASE 0x04400000
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE 0x00C00000 /* 12 MB DRAM */
+
+#define PLAT_MARVELL_LLC_SRAM_BASE 0x05400000
+#define PLAT_MARVELL_LLC_SRAM_SIZE 0x00100000 /* 1 MB SRAM */
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_MARVELL_MAX_BL1_RW_SIZE 0xA000
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_MARVELL_MAX_BL2_SIZE 0xF000
+
+/*
+ * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define PLAT_MARVEL_MAX_BL31_SIZE 0x5D000
+
+#define PLAT_MARVELL_CPU_ENTRY_ADDR BL1_RO_BASE
+
+/* GIC related definitions */
+#define PLAT_MARVELL_GICD_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE)
+#define PLAT_MARVELL_GICC_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE)
+
+#define PLAT_MARVELL_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_PIC0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_MARVELL_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(MARVELL_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_MARVELL_SHARED_RAM_CACHED 1
+
+/*
+ * Load address of BL3-3 for this platform port
+ */
+#define PLAT_MARVELL_NS_IMAGE_OFFSET 0x0
+
+/* System Reference Clock*/
+#define PLAT_REF_CLK_IN_HZ COUNTER_FREQUENCY
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_MARVELL_UART_BASE (MVEBU_REGS_BASE + 0x512000)
+#define PLAT_MARVELL_UART_CLK_IN_HZ 200000000
+
+/* Recovery image enable */
+#define PLAT_RECOVERY_IMAGE_ENABLE 0
+
+/* Required platform porting definitions */
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+
+/* System timer related constants */
+#define PLAT_MARVELL_NSTIMER_FRAME_ID 1
+
+/* Mailbox base address (note the lower memory space
+ * is reserved for BLE data)
+ */
+#define PLAT_MARVELL_MAILBOX_BASE (MARVELL_SHARED_RAM_BASE \
+ + 0x400)
+#define PLAT_MARVELL_MAILBOX_SIZE 0x100
+#define PLAT_MARVELL_MAILBOX_MAGIC_NUM 0x6D72766C /* mrvl */
+
+/* Securities */
+#define IRQ_SEC_OS_TICK_INT MARVELL_IRQ_SEC_PHY_TIMER
+
+#define MVEBU_PMU_IRQ_WA
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/marvell/armada/a8k/common/mss/mss_a8k.mk b/plat/marvell/armada/a8k/common/mss/mss_a8k.mk
new file mode 100644
index 0000000..315fc87
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/mss/mss_a8k.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PLAT_MARVELL := plat/marvell/armada
+A8K_MSS_SOURCE := $(PLAT_MARVELL)/a8k/common/mss
+
+BL2_SOURCES += $(A8K_MSS_SOURCE)/mss_bl2_setup.c \
+ $(MARVELL_MOCHI_DRV)
+
+BL31_SOURCES += $(A8K_MSS_SOURCE)/mss_pm_ipc.c \
+ $(A8K_MSS_SOURCE)/mss_bl31_setup.c
+
+PLAT_INCLUDES += -I$(A8K_MSS_SOURCE)
+
+ifneq (${SCP_BL2},)
+# This define is used to inidcate the SCP image is present
+$(eval $(call add_define,SCP_IMAGE))
+endif
diff --git a/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
new file mode 100644
index 0000000..dee2d5b
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/marvell/ccu.h>
+#include <drivers/marvell/mochi/ap_setup.h>
+#include <drivers/marvell/mochi/cp110_setup.h>
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+#include <marvell_plat_priv.h> /* timer functionality */
+#include "mss_defs.h"
+#include "mss_scp_bootloader.h"
+
+/* MSS windows configuration */
+#define MSS_AEBR(base) (base + 0x160)
+#define MSS_AIBR(base) (base + 0x164)
+#define MSS_AEBR_MASK 0xFFF
+#define MSS_AIBR_MASK 0xFFF
+
+#define MSS_EXTERNAL_SPACE 0x50000000
+#define MSS_EXTERNAL_ACCESS_BIT 28
+#define MSS_EXTERNAL_ADDR_MASK 0xfffffff
+#define MSS_INTERNAL_ACCESS_BIT 28
+
+struct addr_map_win ccu_mem_map[] = {
+ {MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
+};
+
+/* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors,
+ * the access to cp0 and cp1 need to be provided. More precisely it is
+ * required to:
+ * - get the information about device id which is stored in CP0 registers
+ * (to distinguish between cases where we have cp0 and cp1 or standalone cp0)
+ * - get the access to cp which is needed for loading fw for cp0/cp1
+ * coprocessors
+ * This function configures ccu windows accordingly.
+ *
+ * Note: there is no need to restore previous ccu configuration, since in next
+ * phase (BL31) the init_ccu will be called (via apn806_init/
+ * bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten.
+ */
+static int bl2_plat_mmap_init(void)
+{
+ int cfg_num, win_id, cfg_idx, cp;
+
+ cfg_num = ARRAY_SIZE(ccu_mem_map);
+
+ /* CCU window-0 should not be counted - it's already used */
+ if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) {
+ ERROR("BL2: %s: trying to open too many windows\n", __func__);
+ return -1;
+ }
+
+ /* Enable required CCU windows
+ * Do not touch CCU window 0,
+ * it's used for the internal registers access
+ */
+ for (cfg_idx = 0, win_id = 1;
+ (win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) {
+ /* Skip already enabled CCU windows */
+ if (ccu_is_win_enabled(MVEBU_AP0, win_id))
+ continue;
+ /* Enable required CCU windows */
+ ccu_win_check(&ccu_mem_map[cfg_idx]);
+ ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
+ cfg_idx++;
+ }
+
+ /* Config address for each cp other than cp0 */
+ for (cp = 1; cp < CP_COUNT; cp++)
+ update_cp110_default_win(cp);
+
+ /* There is need to configure IO_WIN windows again to overwrite
+ * temporary configuration done during update_cp110_default_win
+ */
+ init_io_win(MVEBU_AP0);
+
+ /* Open AMB bridge required for MG access */
+ for (cp = 0; cp < CP_COUNT; cp++)
+ cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
+
+ return 0;
+}
+
+/*****************************************************************************
+ * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
+ * Return 0 on success, -1 otherwise.
+ *****************************************************************************
+ */
+int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
+{
+ int ret;
+
+ INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
+
+ /* initialize time (for delay functionality) */
+ plat_delay_timer_init();
+
+ ret = bl2_plat_mmap_init();
+ if (ret != 0)
+ return ret;
+
+ ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base,
+ scp_bl2_image_info->image_size);
+
+ if (ret == 0)
+ INFO("BL2: SCP_BL2 transferred to SCP\n");
+ else
+ ERROR("BL2: SCP_BL2 transfer failure\n");
+
+ return ret;
+}
+
+uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
+{
+ return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
+}
+
+uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
+{
+ return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
+}
+
+uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
+{
+ return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
+}
+
+uint32_t bl2_plat_get_cp_count(int ap_idx)
+{
+ uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
+ /* A8040: two CPs.
+ * A7040: one CP.
+ */
+ if (revision == MVEBU_80X0_DEV_ID ||
+ revision == MVEBU_80X0_CP115_DEV_ID)
+ return 2;
+ else if (revision == MVEBU_CN9130_DEV_ID)
+ return CP_COUNT;
+ else
+ return 1;
+}
+
+uint32_t bl2_plat_get_ap_count(void)
+{
+ /* A8040 and A7040 have only one AP */
+ return 1;
+}
+
+void bl2_plat_configure_mss_windows(uintptr_t mss_regs)
+{
+ /* set AXI External and Internal Address Bus extension */
+ mmio_write_32(MSS_AEBR(mss_regs),
+ ((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK));
+ mmio_write_32(MSS_AIBR(mss_regs),
+ ((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK));
+}
diff --git a/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c b/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c
new file mode 100644
index 0000000..52a8929
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+
+#include "mss_defs.h"
+
+void mss_start_cp_cm3(int cp)
+{
+ uint32_t magic;
+ uintptr_t sram = MVEBU_CP_REGS_BASE(cp) + MSS_CP_SRAM_OFFSET;
+ uintptr_t regs = MVEBU_CP_REGS_BASE(cp) + MSS_CP_REGS_OFFSET;
+
+ magic = mmio_read_32(sram);
+
+ /* Make sure the FW was loaded */
+ if (magic != MSS_FW_READY_MAGIC) {
+ return;
+ }
+
+ NOTICE("Starting CP%d MSS CPU\n", cp);
+ /* remove the magic */
+ mmio_write_32(sram, 0);
+ /* Release M3 from reset */
+ mmio_write_32(MSS_M3_RSTCR(regs),
+ (MSS_M3_RSTCR_RST_OFF << MSS_M3_RSTCR_RST_OFFSET));
+}
diff --git a/plat/marvell/armada/a8k/common/mss/mss_defs.h b/plat/marvell/armada/a8k/common/mss/mss_defs.h
new file mode 100644
index 0000000..6956461
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/mss/mss_defs.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MSS_DEFS_H
+#define MSS_DEFS_H
+
+#define MSS_DMA_SRCBR(base) (base + 0xC0)
+#define MSS_DMA_DSTBR(base) (base + 0xC4)
+#define MSS_DMA_CTRLR(base) (base + 0xC8)
+#define MSS_M3_RSTCR(base) (base + 0xFC)
+
+#define MSS_DMA_CTRLR_SIZE_OFFSET (0)
+#define MSS_DMA_CTRLR_REQ_OFFSET (15)
+#define MSS_DMA_CTRLR_REQ_SET (1)
+#define MSS_DMA_CTRLR_ACK_OFFSET (12)
+#define MSS_DMA_CTRLR_ACK_MASK (0x1)
+#define MSS_DMA_CTRLR_ACK_READY (1)
+#define MSS_M3_RSTCR_RST_OFFSET (0)
+#define MSS_M3_RSTCR_RST_OFF (1)
+
+#define MSS_FW_READY_MAGIC 0x46575144 /* FWRD */
+
+#define MSS_AP_REGS_OFFSET 0x00580000
+#define MSS_CP_SRAM_OFFSET 0x00220000
+#define MSS_CP_REGS_OFFSET 0x00280000
+
+void mss_start_cp_cm3(int cp);
+
+#endif /* MSS_DEFS_H */
diff --git a/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c
new file mode 100644
index 0000000..a070583
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/psci/psci.h>
+#include <lib/mmio.h>
+
+#include <mss_pm_ipc.h>
+
+/*
+ * SISR is 32 bit interrupt register representing 32 interrupts
+ *
+ * +======+=============+=============+
+ * + Bits + 31 + 30 - 00 +
+ * +======+=============+=============+
+ * + Desc + MSS Msg Int + Reserved +
+ * +======+=============+=============+
+ */
+#define MSS_SISR (MVEBU_REGS_BASE + 0x5800D0)
+#define MSS_SISTR (MVEBU_REGS_BASE + 0x5800D8)
+
+#define MSS_MSG_INT_MASK (0x80000000)
+#define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110)
+#define MSS_TRIGGER_TIMEOUT (2000)
+
+/*****************************************************************************
+ * mss_pm_ipc_msg_send
+ *
+ * DESCRIPTION: create and transmit IPC message
+ *****************************************************************************
+ */
+int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
+ const psci_power_state_t *target_state)
+{
+ /* Transmit IPC message */
+#ifndef DISABLE_CLUSTER_LEVEL
+ mv_pm_ipc_msg_tx(channel_id, msg_id,
+ (unsigned int)target_state->pwr_domain_state[
+ MPIDR_AFFLVL1]);
+#else
+ mv_pm_ipc_msg_tx(channel_id, msg_id, 0);
+#endif
+
+ return 0;
+}
+
+/*****************************************************************************
+ * mss_pm_ipc_msg_trigger
+ *
+ * DESCRIPTION: Trigger IPC message interrupt to MSS
+ *****************************************************************************
+ */
+int mss_pm_ipc_msg_trigger(void)
+{
+ unsigned int timeout;
+ unsigned int t_end;
+ unsigned int t_start = mmio_read_32(MSS_TIMER_BASE);
+
+ mmio_write_32(MSS_SISR, MSS_MSG_INT_MASK);
+
+ do {
+ /* wait while SCP process incoming interrupt */
+ if (mmio_read_32(MSS_SISTR) != MSS_MSG_INT_MASK)
+ break;
+
+ /* check timeout */
+ t_end = mmio_read_32(MSS_TIMER_BASE);
+
+ timeout = ((t_start > t_end) ?
+ (t_start - t_end) : (t_end - t_start));
+ if (timeout > MSS_TRIGGER_TIMEOUT) {
+ ERROR("PM MSG Trigger Timeout\n");
+ break;
+ }
+
+ } while (1);
+
+ return 0;
+}
diff --git a/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h
new file mode 100644
index 0000000..1dfa9fa
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MSS_PM_IPC_H
+#define MSS_PM_IPC_H
+
+#include <mss_ipc_drv.h>
+
+/* Currently MSS does not support Cluster level Power Down */
+#define DISABLE_CLUSTER_LEVEL
+
+
+/*****************************************************************************
+ * mss_pm_ipc_msg_send
+ *
+ * DESCRIPTION: create and transmit IPC message
+ *****************************************************************************
+ */
+int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
+ const psci_power_state_t *target_state);
+
+/*****************************************************************************
+ * mss_pm_ipc_msg_trigger
+ *
+ * DESCRIPTION: Trigger IPC message interrupt to MSS
+ *****************************************************************************
+ */
+int mss_pm_ipc_msg_trigger(void);
+
+
+#endif /* MSS_PM_IPC_H */
diff --git a/plat/marvell/armada/a8k/common/plat_bl1_setup.c b/plat/marvell/armada/a8k/common/plat_bl1_setup.c
new file mode 100644
index 0000000..f9521c8
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/plat_bl1_setup.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <lib/mmio.h>
+
+#include <plat_marvell.h>
+
+void marvell_bl1_setup_mpps(void)
+{
+ /* Enable UART MPPs.
+ ** In a normal system, this is done by Bootrom.
+ */
+ mmio_write_32(MVEBU_AP_MPP_REGS(1), 0x3000);
+ mmio_write_32(MVEBU_AP_MPP_REGS(2), 0x3000);
+}
diff --git a/plat/marvell/armada/a8k/common/plat_bl31_setup.c b/plat/marvell/armada/a8k/common/plat_bl31_setup.c
new file mode 100644
index 0000000..db85cce
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/plat_bl31_setup.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/debug.h>
+#include <drivers/marvell/mci.h>
+#include <drivers/marvell/mochi/ap_setup.h>
+#include <drivers/marvell/mochi/cp110_setup.h>
+#include <lib/mmio.h>
+
+#include <armada_common.h>
+#include <marvell_plat_priv.h>
+#include <marvell_pm.h>
+#include <mc_trustzone/mc_trustzone.h>
+#include <plat_marvell.h>
+#if MSS_SUPPORT
+#include <mss_ipc_drv.h>
+#include <mss_mem.h>
+#include <mss_defs.h>
+#endif
+
+/* In Armada-8k family AP806/AP807, CP0 connected to PIDI
+ * and CP1 connected to IHB via MCI #0
+ */
+#define MVEBU_MCI0 0
+
+static _Bool pm_fw_running;
+
+/* Set a weak stub for platforms that don't need to configure GPIO */
+#pragma weak marvell_gpio_config
+int marvell_gpio_config(void)
+{
+ return 0;
+}
+
+static void marvell_bl31_mpp_init(int cp)
+{
+ uint32_t reg;
+
+ /* need to do for CP#0 only */
+ if (cp)
+ return;
+
+
+ /*
+ * Enable CP0 I2C MPPs (MPP: 37-38)
+ * U-Boot rely on proper MPP settings for I2C EEPROM usage
+ * (only for CP0)
+ */
+ reg = mmio_read_32(MVEBU_CP_MPP_REGS(0, 4));
+ mmio_write_32(MVEBU_CP_MPP_REGS(0, 4), reg | 0x2200000);
+}
+
+#if MSS_SUPPORT
+void marvell_bl31_mss_init(void)
+{
+ struct mss_pm_ctrl_block *mss_pm_crtl =
+ (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE;
+
+ /* Check that the image was loaded successfully */
+ if (mss_pm_crtl->handshake != HOST_ACKNOWLEDGMENT) {
+ NOTICE("MSS PM is not supported in this build\n");
+ return;
+ }
+
+ /* If we got here it means that the PM firmware is running */
+ pm_fw_running = 1;
+
+ INFO("MSS IPC init\n");
+
+ if (mss_pm_crtl->ipc_state == IPC_INITIALIZED)
+ mv_pm_ipc_init(mss_pm_crtl->ipc_base_address | MVEBU_REGS_BASE);
+}
+#endif
+
+_Bool is_pm_fw_running(void)
+{
+ return pm_fw_running;
+}
+
+/* For TrusTzone we treat the "target" field of addr_map_win
+ * struct as attribute
+ */
+static const struct addr_map_win tz_map[] = {
+ {PLAT_MARVELL_ATF_BASE, 0x200000, TZ_PERM_ABORT}
+};
+
+/* Configure MC TrustZone regions */
+static void marvell_bl31_security_setup(void)
+{
+ int tz_nr, win_id;
+
+ tz_nr = ARRAY_SIZE(tz_map);
+
+ for (win_id = 0; win_id < tz_nr; win_id++)
+ tz_enable_win(MVEBU_AP0, tz_map, win_id);
+}
+
+/* This function overruns the same function in marvell_bl31_setup.c */
+void bl31_plat_arch_setup(void)
+{
+ int cp;
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ /* initialize the timer for mdelay/udelay functionality */
+ plat_delay_timer_init();
+
+ /* configure apn806 */
+ ap_init();
+
+ /* In marvell_bl31_plat_arch_setup, el3 mmu is configured.
+ * el3 mmu configuration MUST be called after apn806_init, if not,
+ * this will cause an hang in init_io_win
+ * (after setting the IO windows GCR values).
+ */
+ if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM ||
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE)
+ marvell_bl31_plat_arch_setup();
+
+ for (cp = 0; cp < CP_COUNT; cp++) {
+ cp110_init(MVEBU_CP_REGS_BASE(cp),
+ STREAM_ID_BASE + (cp * MAX_STREAM_ID_PER_CP));
+
+ marvell_bl31_mpp_init(cp);
+
+#if MSS_SUPPORT
+ /* Release CP MSS CPU from reset once the CP init is done */
+ mss_start_cp_cm3(cp);
+#endif
+ }
+
+ for (cp = 1; cp < CP_COUNT; cp++)
+ mci_link_tune(cp - 1);
+
+#if MSS_SUPPORT
+ /* initialize IPC between MSS and ATF */
+ if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM ||
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE)
+ marvell_bl31_mss_init();
+#endif
+ /* Configure GPIO */
+ marvell_gpio_config();
+
+ marvell_bl31_security_setup();
+}
diff --git a/plat/marvell/armada/a8k/common/plat_ble_setup.c b/plat/marvell/armada/a8k/common/plat_ble_setup.c
new file mode 100644
index 0000000..9c5ee15
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/plat_ble_setup.c
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/debug.h>
+#include <drivers/marvell/ap807_clocks_init.h>
+#include <drivers/marvell/aro.h>
+#include <drivers/marvell/ccu.h>
+#include <drivers/marvell/io_win.h>
+#include <drivers/marvell/mochi/ap_setup.h>
+#include <drivers/marvell/mochi/cp110_setup.h>
+
+#include <armada_common.h>
+#include <efuse_def.h>
+#include <mv_ddr_if.h>
+#include <mvebu_def.h>
+#include <plat_marvell.h>
+
+/* Register for skip image use */
+#define SCRATCH_PAD_REG2 0xF06F00A8
+#define SCRATCH_PAD_SKIP_VAL 0x01
+#define NUM_OF_GPIO_PER_REG 32
+
+#define MMAP_SAVE_AND_CONFIG 0
+#define MMAP_RESTORE_SAVED 1
+
+/* SAR clock settings */
+#define MVEBU_AP_SAR_REG_BASE(r) (MVEBU_AP_GEN_MGMT_BASE + 0x200 +\
+ ((r) << 2))
+
+#define SAR_CLOCK_FREQ_MODE_OFFSET (0)
+#define SAR_CLOCK_FREQ_MODE_MASK (0x1f << SAR_CLOCK_FREQ_MODE_OFFSET)
+#define SAR_PIDI_LOW_SPEED_OFFSET (20)
+#define SAR_PIDI_LOW_SPEED_MASK (1 << SAR_PIDI_LOW_SPEED_OFFSET)
+#define SAR_PIDI_LOW_SPEED_SHIFT (15)
+#define SAR_PIDI_LOW_SPEED_SET (1 << SAR_PIDI_LOW_SPEED_SHIFT)
+
+#define FREQ_MODE_AP_SAR_REG_NUM (0)
+#define SAR_CLOCK_FREQ_MODE(v) (((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \
+ SAR_CLOCK_FREQ_MODE_OFFSET)
+
+#define AVS_I2C_EEPROM_ADDR 0x57 /* EEPROM */
+#define AVS_EN_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x130)
+#define AVS_ENABLE_OFFSET (0)
+#define AVS_SOFT_RESET_OFFSET (2)
+#define AVS_TARGET_DELTA_OFFSET (21)
+
+#ifndef MVEBU_SOC_AP807
+ /* AP806 SVC bits */
+ #define AVS_LOW_VDD_LIMIT_OFFSET (4)
+ #define AVS_HIGH_VDD_LIMIT_OFFSET (12)
+ #define AVS_VDD_LOW_LIMIT_MASK (0xFF << AVS_LOW_VDD_LIMIT_OFFSET)
+ #define AVS_VDD_HIGH_LIMIT_MASK (0xFF << AVS_HIGH_VDD_LIMIT_OFFSET)
+#else
+ /* AP807 SVC bits */
+ #define AVS_LOW_VDD_LIMIT_OFFSET (3)
+ #define AVS_HIGH_VDD_LIMIT_OFFSET (13)
+ #define AVS_VDD_LOW_LIMIT_MASK (0x3FF << AVS_LOW_VDD_LIMIT_OFFSET)
+ #define AVS_VDD_HIGH_LIMIT_MASK (0x3FF << AVS_HIGH_VDD_LIMIT_OFFSET)
+#endif
+
+/* VDD limit is 0.9V for A70x0 @ CPU frequency < 1600MHz */
+#define AVS_A7K_LOW_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \
+ (0x1A << AVS_HIGH_VDD_LIMIT_OFFSET) | \
+ (0x1A << AVS_LOW_VDD_LIMIT_OFFSET) | \
+ (0x1 << AVS_SOFT_RESET_OFFSET) | \
+ (0x1 << AVS_ENABLE_OFFSET))
+/* VDD limit is 1.0V for all A80x0 devices */
+#define AVS_A8K_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \
+ (0x24 << AVS_HIGH_VDD_LIMIT_OFFSET) | \
+ (0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \
+ (0x1 << AVS_SOFT_RESET_OFFSET) | \
+ (0x1 << AVS_ENABLE_OFFSET))
+
+/* VDD is 0.88V for 2GHz clock on CN913x devices */
+#define AVS_AP807_CLK_VALUE ((0x80UL << 24) | \
+ (0x2dc << 13) | \
+ (0x2dc << 3) | \
+ (0x1 << AVS_SOFT_RESET_OFFSET) | \
+ (0x1 << AVS_ENABLE_OFFSET))
+
+/*
+ * - Identification information in the LD-0 eFuse:
+ * DRO: LD0[74:65] - Not used by the SW
+ * Revision: LD0[78:75] - Not used by the SW
+ * Bin: LD0[80:79] - Not used by the SW
+ * SW Revision: LD0[115:113]
+ * Cluster 1 PWR: LD0[193] - if set to 1, power down CPU Cluster-1
+ * resulting in 2 CPUs active only (7020)
+ */
+/* Offsets for 2 efuse fields combined into single 64-bit value [125:63] */
+#define EFUSE_AP_LD0_DRO_OFFS 2 /* LD0[74:65] */
+#define EFUSE_AP_LD0_DRO_MASK 0x3FF
+#define EFUSE_AP_LD0_REVID_OFFS 12 /* LD0[78:75] */
+#define EFUSE_AP_LD0_REVID_MASK 0xF
+#define EFUSE_AP_LD0_BIN_OFFS 16 /* LD0[80:79] */
+#define EFUSE_AP_LD0_BIN_MASK 0x3
+#define EFUSE_AP_LD0_SWREV_MASK 0x7
+
+#ifndef MVEBU_SOC_AP807
+ /* AP806 AVS work points in the LD0 eFuse
+ * SVC1 work point: LD0[88:81]
+ * SVC2 work point: LD0[96:89]
+ * SVC3 work point: LD0[104:97]
+ * SVC4 work point: LD0[112:105]
+ */
+ #define EFUSE_AP_LD0_SVC1_OFFS 18 /* LD0[88:81] */
+ #define EFUSE_AP_LD0_SVC2_OFFS 26 /* LD0[96:89] */
+ #define EFUSE_AP_LD0_SVC3_OFFS 34 /* LD0[104:97] */
+ #define EFUSE_AP_LD0_WP_MASK 0xFF
+ #define EFUSE_AP_LD0_SWREV_OFFS 50 /* LD0[115:113] */
+#else
+ /* AP807 AVS work points in the LD0 eFuse
+ * SVC1 work point: LD0[91:81]
+ * SVC2 work point: LD0[102:92]
+ * SVC3 work point: LD0[113:103]
+ */
+ #define EFUSE_AP_LD0_SVC1_OFFS 18 /* LD0[91:81] */
+ #define EFUSE_AP_LD0_SVC2_OFFS 29 /* LD0[102:92] */
+ #define EFUSE_AP_LD0_SVC3_OFFS 40 /* LD0[113:103] */
+ #define EFUSE_AP_LD0_WP_MASK 0x7FF /* 10 data,1 parity */
+ #define EFUSE_AP_LD0_SWREV_OFFS 51 /* LD0[116:114] */
+#endif
+
+#define EFUSE_AP_LD0_SVC4_OFFS 42 /* LD0[112:105] */
+
+#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4
+
+#if MARVELL_SVC_TEST
+#define MVEBU_CP_MPP_CTRL37_OFFS 20
+#define MVEBU_CP_MPP_CTRL38_OFFS 24
+#define MVEBU_CP_MPP_I2C_FUNC 2
+#define MVEBU_MPP_CTRL_MASK 0xf
+#endif
+
+/* Return the AP revision of the chip */
+static unsigned int ble_get_ap_type(void)
+{
+ unsigned int chip_rev_id;
+
+ chip_rev_id = mmio_read_32(MVEBU_CSS_GWD_CTRL_IIDR2_REG);
+ chip_rev_id = ((chip_rev_id & GWD_IIDR2_CHIP_ID_MASK) >>
+ GWD_IIDR2_CHIP_ID_OFFSET);
+
+ return chip_rev_id;
+}
+
+/******************************************************************************
+ * The routine allows to save the CCU and IO windows configuration during DRAM
+ * setup and restore them afterwards before exiting the BLE stage.
+ * Such window configuration is required since not all default settings coming
+ * from the HW and the BootROM allow access to peripherals connected to
+ * all available CPn components.
+ * For instance, when the boot device is located on CP0, the IO window to CP1
+ * is not opened automatically by the HW and if the DRAM SPD is located on CP1
+ * i2c channel, it cannot be read at BLE stage.
+ * Therefore the DRAM init procedure have to provide access to all available
+ * CPn peripherals during the BLE stage by setting the CCU IO window to all
+ * CPnph addresses and by enabling the IO windows accordingly.
+ * Additionally this function configures the CCU GCR to DRAM, which allows
+ * usage or more than 4GB DRAM as it configured by the default CCU DRAM window.
+ *
+ * IN:
+ * MMAP_SAVE_AND_CONFIG - save the existing configuration and update it
+ * MMAP_RESTORE_SAVED - restore saved configuration
+ * OUT:
+ * NONE
+ ****************************************************************************
+ */
+static void ble_plat_mmap_config(int restore)
+{
+ if (restore == MMAP_RESTORE_SAVED) {
+ /* Restore all orig. settings that were modified by BLE stage */
+ ccu_restore_win_all(MVEBU_AP0);
+ /* Restore CCU */
+ iow_restore_win_all(MVEBU_AP0);
+ return;
+ }
+
+ /* Store original values */
+ ccu_save_win_all(MVEBU_AP0);
+ /* Save CCU */
+ iow_save_win_all(MVEBU_AP0);
+
+ init_ccu(MVEBU_AP0);
+ /* The configuration saved, now all the changes can be done */
+ init_io_win(MVEBU_AP0);
+}
+
+/****************************************************************************
+ * Setup Adaptive Voltage Switching - this is required for some platforms
+ ****************************************************************************
+ */
+#if !MARVELL_SVC_TEST
+static void ble_plat_avs_config(void)
+{
+ uint32_t freq_mode, device_id;
+ uint32_t avs_val = 0;
+
+ freq_mode =
+ SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+ FREQ_MODE_AP_SAR_REG_NUM)));
+ /* Check which SoC is running and act accordingly */
+ if (ble_get_ap_type() == CHIP_ID_AP807) {
+
+ avs_val = AVS_AP807_CLK_VALUE;
+
+ } else {
+ /* Check which SoC is running and act accordingly */
+ device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
+ switch (device_id) {
+ case MVEBU_80X0_DEV_ID:
+ case MVEBU_80X0_CP115_DEV_ID:
+ /* Always fix the default AVS value on A80x0 */
+ avs_val = AVS_A8K_CLK_VALUE;
+ break;
+ case MVEBU_70X0_DEV_ID:
+ case MVEBU_70X0_CP115_DEV_ID:
+ /* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */
+ if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) &&
+ (freq_mode < CPU_DDR_RCLK_INVALID))
+ avs_val = AVS_A7K_LOW_CLK_VALUE;
+ break;
+ default:
+ ERROR("Unsupported Device ID 0x%x\n", device_id);
+ return;
+ }
+ }
+
+ if (avs_val) {
+ VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val);
+ mmio_write_32(AVS_EN_CTRL_REG, avs_val);
+ }
+}
+#endif
+/******************************************************************************
+ * Update or override current AVS work point value using data stored in EEPROM
+ * This is only required by QA/validation flows and activated by
+ * MARVELL_SVC_TEST flag.
+ *
+ * The function is expected to be called twice.
+ *
+ * First time with AVS value of 0 for testing if the EEPROM requests completely
+ * override the AVS value and bypass the eFuse test
+ *
+ * Second time - with non-zero AVS value obtained from eFuses as an input.
+ * In this case the EEPROM may contain AVS correction value (either positive
+ * or negative) that is added to the input AVS value and returned back for
+ * further processing.
+ ******************************************************************************
+ */
+static uint32_t avs_update_from_eeprom(uint32_t avs_workpoint)
+{
+ uint32_t new_wp = avs_workpoint;
+#if MARVELL_SVC_TEST
+ /* ---------------------------------------------------------------------
+ * EEPROM | Data description (avs_step)
+ * address |
+ * ---------------------------------------------------------------------
+ * 0x120 | AVS workpoint correction value
+ * | if not 0 and not 0xff, correct the AVS taken from eFuse
+ * | by the number of steps indicated by bit[6:0]
+ * | bit[7] defines correction direction.
+ * | If bit[7]=1, add the value from bit[6:0] to AVS workpoint,
+ * | othervise substruct this value from AVS workpoint.
+ * ---------------------------------------------------------------------
+ * 0x121 | AVS workpoint override value
+ * | Override the AVS workpoint with the value stored in this
+ * | byte. When running on AP806, the AVS workpoint is 7 bits
+ * | wide and override value is valid when bit[6:0] holds
+ * | value greater than zero and smaller than 0x33.
+ * | When running on AP807, the AVS workpoint is 10 bits wide.
+ * | Additional 2 MSB bits are supplied by EEPROM byte 0x122.
+ * | AVS override value is valid when byte @ 0x121 and bit[1:0]
+ * | of byte @ 0x122 combined have non-zero value.
+ * ---------------------------------------------------------------------
+ * 0x122 | Extended AVS workpoint override value
+ * | Valid only for AP807 platforms and must be less than 0x4
+ * ---------------------------------------------------------------------
+ */
+ static uint8_t avs_step[3] = {0};
+ uintptr_t reg;
+ uint32_t val;
+ unsigned int ap_type = ble_get_ap_type();
+
+ /* Always happens on second call to this function */
+ if (avs_workpoint != 0) {
+ /* Get correction steps from the EEPROM */
+ if ((avs_step[0] != 0) && (avs_step[0] != 0xff)) {
+ NOTICE("AVS request to step %s by 0x%x from old 0x%x\n",
+ avs_step[0] & 0x80 ? "DOWN" : "UP",
+ avs_step[0] & 0x7f, new_wp);
+ if (avs_step[0] & 0x80)
+ new_wp -= avs_step[0] & 0x7f;
+ else
+ new_wp += avs_step[0] & 0x7f;
+ }
+
+ return new_wp;
+ }
+
+ /* AVS values are located in EEPROM
+ * at CP0 i2c bus #0, device 0x57 offset 0x120
+ * The SDA and SCK pins of CP0 i2c-0: MPP[38:37], i2c function 0x2.
+ */
+ reg = MVEBU_CP_MPP_REGS(0, 4);
+ val = mmio_read_32(reg);
+ val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
+ val |= (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL38_OFFS);
+ mmio_write_32(reg, val);
+
+ /* Init CP0 i2c-0 */
+ i2c_init((void *)(MVEBU_CP0_I2C_BASE));
+
+ /* Read EEPROM only once at the fist call! */
+ i2c_read(AVS_I2C_EEPROM_ADDR, 0x120, 2, avs_step, 3);
+ NOTICE("== SVC test build ==\n");
+ NOTICE("EEPROM holds values 0x%x, 0x%x and 0x%x\n",
+ avs_step[0], avs_step[1], avs_step[2]);
+
+ /* Override the AVS value? */
+ if ((ap_type != CHIP_ID_AP807) && (avs_step[1] < 0x33)) {
+ /* AP806 - AVS is 7 bits */
+ new_wp = avs_step[1];
+
+ } else if (ap_type == CHIP_ID_AP807 && (avs_step[2] < 0x4)) {
+ /* AP807 - AVS is 10 bits */
+ new_wp = avs_step[2];
+ new_wp <<= 8;
+ new_wp |= avs_step[1];
+ }
+
+ if (new_wp == 0)
+ NOTICE("Ignore BAD AVS Override value in EEPROM!\n");
+ else
+ NOTICE("Override AVS by EEPROM value 0x%x\n", new_wp);
+#endif /* MARVELL_SVC_TEST */
+ return new_wp;
+}
+
+/****************************************************************************
+ * SVC flow - v0.10
+ * The feature is intended to configure AVS value according to eFuse values
+ * that are burned individually for each SoC during the test process.
+ * Primary AVS value is stored in HD efuse and processed on power on
+ * by the HW engine
+ * Secondary AVS value is located in LD efuse and contains 4 work points for
+ * various CPU frequencies.
+ * The Secondary AVS value is only taken into account if the SW Revision stored
+ * in the efuse is greater than 0 and the CPU is running in a certain speed.
+ ****************************************************************************
+ */
+static void ble_plat_svc_config(void)
+{
+ uint32_t reg_val, avs_workpoint, freq_pidi_mode;
+ uint64_t efuse;
+ uint32_t device_id, single_cluster;
+ uint16_t svc[4], perr[4], i, sw_ver;
+ uint8_t avs_data_bits, min_sw_ver, svc_fields;
+ unsigned int ap_type;
+
+ /* Get test EERPOM data */
+ avs_workpoint = avs_update_from_eeprom(0);
+ if (avs_workpoint)
+ goto set_aws_wp;
+
+ /* Set access to LD0 */
+ reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG);
+ reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_MASK;
+ mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val);
+
+ /* Obtain the value of LD0[125:63] */
+ efuse = mmio_read_32(MVEBU_AP_LDX_125_95_EFUSE_OFFS);
+ efuse <<= 32;
+ efuse |= mmio_read_32(MVEBU_AP_LDX_94_63_EFUSE_OFFS);
+
+ /* SW Revision:
+ * Starting from SW revision 1 the SVC flow is supported.
+ * SW version 0 (efuse not programmed) should follow the
+ * regular AVS update flow.
+ */
+ sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK;
+ if (sw_ver < 1) {
+ NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver);
+#if MARVELL_SVC_TEST
+ NOTICE("SVC_TEST: AVS bypassed\n");
+
+#else
+ ble_plat_avs_config();
+#endif
+ return;
+ }
+
+ /* Frequency mode from SAR */
+ freq_pidi_mode = SAR_CLOCK_FREQ_MODE(
+ mmio_read_32(
+ MVEBU_AP_SAR_REG_BASE(
+ FREQ_MODE_AP_SAR_REG_NUM)));
+
+ /* Decode all SVC work points */
+ svc[0] = (efuse >> EFUSE_AP_LD0_SVC1_OFFS) & EFUSE_AP_LD0_WP_MASK;
+ svc[1] = (efuse >> EFUSE_AP_LD0_SVC2_OFFS) & EFUSE_AP_LD0_WP_MASK;
+ svc[2] = (efuse >> EFUSE_AP_LD0_SVC3_OFFS) & EFUSE_AP_LD0_WP_MASK;
+
+ /* Fetch AP type to distinguish between AP806 and AP807 */
+ ap_type = ble_get_ap_type();
+
+ if (ap_type != CHIP_ID_AP807) {
+ svc[3] = (efuse >> EFUSE_AP_LD0_SVC4_OFFS)
+ & EFUSE_AP_LD0_WP_MASK;
+ INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x, [3]=0x%x\n",
+ svc[0], svc[1], svc[2], svc[3]);
+ avs_data_bits = 7;
+ min_sw_ver = 2; /* parity check from sw revision 2 */
+ svc_fields = 4;
+ } else {
+ INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x\n",
+ svc[0], svc[1], svc[2]);
+ avs_data_bits = 10;
+ min_sw_ver = 1; /* parity check required from sw revision 1 */
+ svc_fields = 3;
+ }
+
+ /* Validate parity of SVC workpoint values */
+ for (i = 0; i < svc_fields; i++) {
+ uint8_t parity, bit;
+ perr[i] = 0;
+
+ for (bit = 1, parity = (svc[i] & 1); bit < avs_data_bits; bit++)
+ parity ^= (svc[i] >> bit) & 1;
+
+ /* From SW version 1 or 2 (AP806/AP807), check parity */
+ if ((sw_ver >= min_sw_ver) &&
+ (parity != ((svc[i] >> avs_data_bits) & 1)))
+ perr[i] = 1; /* register the error */
+ }
+
+ single_cluster = mmio_read_32(MVEBU_AP_LDX_220_189_EFUSE_OFFS);
+ single_cluster = (single_cluster >> EFUSE_AP_LD0_CLUSTER_DOWN_OFFS) & 1;
+
+ device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
+ if (device_id == MVEBU_80X0_DEV_ID ||
+ device_id == MVEBU_80X0_CP115_DEV_ID) {
+ /* A8040/A8020 */
+ NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
+ single_cluster == 0 ? "8040" : "8020", freq_pidi_mode);
+ switch (freq_pidi_mode) {
+ case CPU_1800_DDR_1050_RCLK_1050:
+ if (perr[1])
+ goto perror;
+ avs_workpoint = svc[1];
+ break;
+ case CPU_1600_DDR_1050_RCLK_1050:
+ case CPU_1600_DDR_900_RCLK_900_2:
+ if (perr[2])
+ goto perror;
+ avs_workpoint = svc[2];
+ break;
+ case CPU_1300_DDR_800_RCLK_800:
+ case CPU_1300_DDR_650_RCLK_650:
+ if (perr[3])
+ goto perror;
+ avs_workpoint = svc[3];
+ break;
+ case CPU_2000_DDR_1200_RCLK_1200:
+ case CPU_2000_DDR_1050_RCLK_1050:
+ default:
+ if (perr[0])
+ goto perror;
+ avs_workpoint = svc[0];
+ break;
+ }
+ } else if (device_id == MVEBU_70X0_DEV_ID ||
+ device_id == MVEBU_70X0_CP115_DEV_ID) {
+ /* A7040/A7020/A6040 */
+ NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
+ single_cluster == 0 ? "7040" : "7020", freq_pidi_mode);
+ switch (freq_pidi_mode) {
+ case CPU_1400_DDR_800_RCLK_800:
+ if (single_cluster) {/* 7020 */
+ if (perr[1])
+ goto perror;
+ avs_workpoint = svc[1];
+ } else {
+ if (perr[0])
+ goto perror;
+ avs_workpoint = svc[0];
+ }
+ break;
+ case CPU_1200_DDR_800_RCLK_800:
+ if (single_cluster) {/* 7020 */
+ if (perr[2])
+ goto perror;
+ avs_workpoint = svc[2];
+ } else {
+ if (perr[1])
+ goto perror;
+ avs_workpoint = svc[1];
+ }
+ break;
+ case CPU_800_DDR_800_RCLK_800:
+ case CPU_1000_DDR_800_RCLK_800:
+ if (single_cluster) {/* 7020 */
+ if (perr[3])
+ goto perror;
+ avs_workpoint = svc[3];
+ } else {
+ if (perr[2])
+ goto perror;
+ avs_workpoint = svc[2];
+ }
+ break;
+ case CPU_600_DDR_800_RCLK_800:
+ if (perr[3])
+ goto perror;
+ avs_workpoint = svc[3]; /* Same for 6040 and 7020 */
+ break;
+ case CPU_1600_DDR_800_RCLK_800: /* 7020 only */
+ default:
+ if (single_cluster) {/* 7020 */
+ if (perr[0])
+ goto perror;
+ avs_workpoint = svc[0];
+ } else {
+#if MARVELL_SVC_TEST
+ reg_val = mmio_read_32(AVS_EN_CTRL_REG);
+ avs_workpoint = (reg_val &
+ AVS_VDD_LOW_LIMIT_MASK) >>
+ AVS_LOW_VDD_LIMIT_OFFSET;
+ NOTICE("7040 1600Mhz, avs = 0x%x\n",
+ avs_workpoint);
+#else
+ NOTICE("SVC: AVS work point not changed\n");
+ return;
+#endif
+ }
+ break;
+ }
+ } else if (device_id == MVEBU_3900_DEV_ID) {
+ NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
+ "3900", freq_pidi_mode);
+ switch (freq_pidi_mode) {
+ case CPU_1600_DDR_1200_RCLK_1200:
+ if (perr[0])
+ goto perror;
+ avs_workpoint = svc[0];
+ break;
+ case CPU_1300_DDR_800_RCLK_800:
+ if (perr[1])
+ goto perror;
+ avs_workpoint = svc[1];
+ break;
+ default:
+ if (perr[0])
+ goto perror;
+ avs_workpoint = svc[0];
+ break;
+ }
+ } else if (device_id == MVEBU_CN9130_DEV_ID) {
+ NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
+ "CN913x", freq_pidi_mode);
+ switch (freq_pidi_mode) {
+ case CPU_2200_DDR_1200_RCLK_1200:
+ if (perr[0])
+ goto perror;
+ avs_workpoint = svc[0];
+ break;
+ case CPU_2000_DDR_1200_RCLK_1200:
+ if (perr[1])
+ goto perror;
+ avs_workpoint = svc[1];
+ break;
+ case CPU_1600_DDR_1200_RCLK_1200:
+ if (perr[2])
+ goto perror;
+ avs_workpoint = svc[2];
+ break;
+ default:
+ ERROR("SVC: Unsupported Frequency 0x%x\n",
+ freq_pidi_mode);
+ return;
+
+ }
+ } else {
+ ERROR("SVC: Unsupported Device ID 0x%x\n", device_id);
+ return;
+ }
+
+ /* Set AVS control if needed */
+ if (avs_workpoint == 0) {
+ ERROR("SVC: You are using a frequency setup which is\n");
+ ERROR("Not supported by this device\n");
+ ERROR("This may result in malfunction of the device\n");
+ return;
+ }
+
+ /* Remove parity bit */
+ if (ap_type != CHIP_ID_AP807)
+ avs_workpoint &= 0x7F;
+ else
+ avs_workpoint &= 0x3FF;
+
+ /* Update WP from EEPROM if needed */
+ avs_workpoint = avs_update_from_eeprom(avs_workpoint);
+
+set_aws_wp:
+ reg_val = mmio_read_32(AVS_EN_CTRL_REG);
+ NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n",
+ (reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET,
+ avs_workpoint);
+ reg_val &= ~(AVS_VDD_LOW_LIMIT_MASK | AVS_VDD_HIGH_LIMIT_MASK);
+ reg_val |= 0x1 << AVS_ENABLE_OFFSET;
+ reg_val |= avs_workpoint << AVS_HIGH_VDD_LIMIT_OFFSET;
+ reg_val |= avs_workpoint << AVS_LOW_VDD_LIMIT_OFFSET;
+ mmio_write_32(AVS_EN_CTRL_REG, reg_val);
+ return;
+
+perror:
+ ERROR("Failed SVC WP[%d] parity check!\n", i);
+ ERROR("Ignoring the WP values\n");
+}
+
+#if PLAT_RECOVERY_IMAGE_ENABLE
+static int ble_skip_image_i2c(struct skip_image *skip_im)
+{
+ ERROR("skipping image using i2c is not supported\n");
+ /* not supported */
+ return 0;
+}
+
+static int ble_skip_image_other(struct skip_image *skip_im)
+{
+ ERROR("implementation missing for skip image request\n");
+ /* not supported, make your own implementation */
+ return 0;
+}
+
+static int ble_skip_image_gpio(struct skip_image *skip_im)
+{
+ unsigned int val;
+ unsigned int mpp_address = 0;
+ unsigned int offset = 0;
+
+ switch (skip_im->info.test.cp_ap) {
+ case(CP):
+ mpp_address = MVEBU_CP_GPIO_DATA_IN(skip_im->info.test.cp_index,
+ skip_im->info.gpio.num);
+ if (skip_im->info.gpio.num > NUM_OF_GPIO_PER_REG)
+ offset = skip_im->info.gpio.num - NUM_OF_GPIO_PER_REG;
+ else
+ offset = skip_im->info.gpio.num;
+ break;
+ case(AP):
+ mpp_address = MVEBU_AP_GPIO_DATA_IN;
+ offset = skip_im->info.gpio.num;
+ break;
+ }
+
+ val = mmio_read_32(mpp_address);
+ val &= (1 << offset);
+ if ((!val && skip_im->info.gpio.button_state == HIGH) ||
+ (val && skip_im->info.gpio.button_state == LOW)) {
+ mmio_write_32(SCRATCH_PAD_REG2, SCRATCH_PAD_SKIP_VAL);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * This function checks if there's a skip image request:
+ * return values:
+ * 1: (true) images request been made.
+ * 0: (false) no image request been made.
+ */
+static int ble_skip_current_image(void)
+{
+ struct skip_image *skip_im;
+
+ /*fetching skip image info*/
+ skip_im = (struct skip_image *)plat_marvell_get_skip_image_data();
+
+ if (skip_im == NULL)
+ return 0;
+
+ /* check if skipping image request has already been made */
+ if (mmio_read_32(SCRATCH_PAD_REG2) == SCRATCH_PAD_SKIP_VAL)
+ return 0;
+
+ switch (skip_im->detection_method) {
+ case GPIO:
+ return ble_skip_image_gpio(skip_im);
+ case I2C:
+ return ble_skip_image_i2c(skip_im);
+ case USER_DEFINED:
+ return ble_skip_image_other(skip_im);
+ }
+
+ return 0;
+}
+#endif
+
+
+int ble_plat_setup(int *skip)
+{
+ int ret, cp;
+ unsigned int freq_mode;
+
+ /* Power down unused CPUs */
+ plat_marvell_early_cpu_powerdown();
+
+ /*
+ * Save the current CCU configuration and make required changes:
+ * - Allow access to DRAM larger than 4GB
+ * - Open memory access to all CPn peripherals
+ */
+ ble_plat_mmap_config(MMAP_SAVE_AND_CONFIG);
+
+#if PLAT_RECOVERY_IMAGE_ENABLE
+ /* Check if there's a skip request to bootRom recovery Image */
+ if (ble_skip_current_image()) {
+ /* close memory access to all CPn peripherals. */
+ ble_plat_mmap_config(MMAP_RESTORE_SAVED);
+ *skip = 1;
+ return 0;
+ }
+#endif
+ /* Do required CP-110 setups for BLE stage */
+ cp110_ble_init(MVEBU_CP_REGS_BASE(0));
+
+ /* Config address for each cp other than cp0 */
+ for (cp = 1; cp < CP_COUNT; cp++)
+ update_cp110_default_win(cp);
+
+ /* Setup AVS */
+ ble_plat_svc_config();
+
+ /* read clk option from sampled-at-reset register */
+ freq_mode =
+ SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+ FREQ_MODE_AP_SAR_REG_NUM)));
+
+ /* work with PLL clock driver in AP807 */
+ if (ble_get_ap_type() == CHIP_ID_AP807)
+ ap807_clocks_init(freq_mode);
+
+ /* Do required AP setups for BLE stage */
+ ap_ble_init();
+
+ /* Update DRAM topology (scan DIMM SPDs) */
+ plat_marvell_dram_update_topology();
+
+ /* Kick it in */
+ ret = dram_init();
+
+ /* Restore the original CCU configuration before exit from BLE */
+ ble_plat_mmap_config(MMAP_RESTORE_SAVED);
+
+ return ret;
+}
diff --git a/plat/marvell/armada/a8k/common/plat_pm.c b/plat/marvell/armada/a8k/common/plat_pm.c
new file mode 100644
index 0000000..9ea9276
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/plat_pm.c
@@ -0,0 +1,853 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <drivers/marvell/cache_llc.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <armada_common.h>
+#include <marvell_pm.h>
+#if MSS_SUPPORT
+#include <mss_pm_ipc.h>
+#endif
+#include <plat_marvell.h>
+#include <plat_pm_trace.h>
+
+#define MVEBU_PRIVATE_UID_REG 0x30
+#define MVEBU_RFU_GLOBL_SW_RST 0x84
+#define MVEBU_CCU_RVBAR(cpu) (MVEBU_REGS_BASE + 0x640 + (cpu * 4))
+#define MVEBU_CCU_CPU_UN_RESET(cpu) (MVEBU_REGS_BASE + 0x650 + (cpu * 4))
+
+#define MPIDR_CPU_GET(mpidr) ((mpidr) & MPIDR_CPU_MASK)
+#define MPIDR_CLUSTER_GET(mpidr) MPIDR_AFFLVL1_VAL((mpidr))
+
+#define MVEBU_GPIO_MASK(index) (1 << (index % 32))
+#define MVEBU_MPP_MASK(index) (0xF << (4 * (index % 8)))
+#define MVEBU_GPIO_VALUE(index, value) (value << (index % 32))
+
+#define MVEBU_USER_CMD_0_REG (MVEBU_DRAM_MAC_BASE + 0x20)
+#define MVEBU_USER_CMD_CH0_OFFSET 28
+#define MVEBU_USER_CMD_CH0_MASK (1 << MVEBU_USER_CMD_CH0_OFFSET)
+#define MVEBU_USER_CMD_CH0_EN (1 << MVEBU_USER_CMD_CH0_OFFSET)
+#define MVEBU_USER_CMD_CS_OFFSET 24
+#define MVEBU_USER_CMD_CS_MASK (0xF << MVEBU_USER_CMD_CS_OFFSET)
+#define MVEBU_USER_CMD_CS_ALL (0xF << MVEBU_USER_CMD_CS_OFFSET)
+#define MVEBU_USER_CMD_SR_OFFSET 6
+#define MVEBU_USER_CMD_SR_MASK (0x3 << MVEBU_USER_CMD_SR_OFFSET)
+#define MVEBU_USER_CMD_SR_ENTER (0x1 << MVEBU_USER_CMD_SR_OFFSET)
+#define MVEBU_MC_PWR_CTRL_REG (MVEBU_DRAM_MAC_BASE + 0x54)
+#define MVEBU_MC_AC_ON_DLY_OFFSET 8
+#define MVEBU_MC_AC_ON_DLY_MASK (0xF << MVEBU_MC_AC_ON_DLY_OFFSET)
+#define MVEBU_MC_AC_ON_DLY_DEF_VAR (8 << MVEBU_MC_AC_ON_DLY_OFFSET)
+#define MVEBU_MC_AC_OFF_DLY_OFFSET 4
+#define MVEBU_MC_AC_OFF_DLY_MASK (0xF << MVEBU_MC_AC_OFF_DLY_OFFSET)
+#define MVEBU_MC_AC_OFF_DLY_DEF_VAR (0xC << MVEBU_MC_AC_OFF_DLY_OFFSET)
+#define MVEBU_MC_PHY_AUTO_OFF_OFFSET 0
+#define MVEBU_MC_PHY_AUTO_OFF_MASK (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET)
+#define MVEBU_MC_PHY_AUTO_OFF_EN (1 << MVEBU_MC_PHY_AUTO_OFF_OFFSET)
+
+/* this lock synchronize AP multiple cores execution with MSS */
+DEFINE_BAKERY_LOCK(pm_sys_lock);
+
+/* Weak definitions may be overridden in specific board */
+#pragma weak plat_marvell_get_pm_cfg
+
+/* AP806 CPU power down /power up definitions */
+enum CPU_ID {
+ CPU0,
+ CPU1,
+ CPU2,
+ CPU3
+};
+
+#define REG_WR_VALIDATE_TIMEOUT (2000)
+
+#define FEATURE_DISABLE_STATUS_REG \
+ (MVEBU_REGS_BASE + 0x6F8230)
+#define FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET 4
+#define FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK \
+ (0x1 << FEATURE_DISABLE_STATUS_CPU_CLUSTER_OFFSET)
+
+#ifdef MVEBU_SOC_AP807
+ #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 1
+ #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 0
+#else
+ #define PWRC_CPUN_CR_PWR_DN_RQ_OFFSET 0
+ #define PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET 31
+#endif
+
+#define PWRC_CPUN_CR_REG(cpu_id) \
+ (MVEBU_REGS_BASE + 0x680000 + (cpu_id * 0x10))
+#define PWRC_CPUN_CR_PWR_DN_RQ_MASK \
+ (0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET)
+#define PWRC_CPUN_CR_ISO_ENABLE_OFFSET 16
+#define PWRC_CPUN_CR_ISO_ENABLE_MASK \
+ (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)
+#define PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK \
+ (0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET)
+
+#define CCU_B_PRCRN_REG(cpu_id) \
+ (MVEBU_REGS_BASE + 0x1A50 + \
+ ((cpu_id / 2) * (0x400)) + ((cpu_id % 2) * 4))
+#define CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET 0
+#define CCU_B_PRCRN_CPUPORESET_STATIC_MASK \
+ (0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET)
+
+/* power switch fingers */
+#define AP807_PWRC_LDO_CR0_REG \
+ (MVEBU_REGS_BASE + 0x680000 + 0x100)
+#define AP807_PWRC_LDO_CR0_OFFSET 16
+#define AP807_PWRC_LDO_CR0_MASK \
+ (0xff << AP807_PWRC_LDO_CR0_OFFSET)
+#define AP807_PWRC_LDO_CR0_VAL 0xfc
+
+/*
+ * Power down CPU:
+ * Used to reduce power consumption, and avoid SoC unnecessary temperature rise.
+ */
+static int plat_marvell_cpu_powerdown(int cpu_id)
+{
+ uint32_t reg_val;
+ int exit_loop = REG_WR_VALIDATE_TIMEOUT;
+
+ INFO("Powering down CPU%d\n", cpu_id);
+
+ /* 1. Isolation enable */
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ reg_val |= 0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET;
+ mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
+
+ /* 2. Read and check Isolation enabled - verify bit set to 1 */
+ do {
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ exit_loop--;
+ } while (!(reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) &&
+ exit_loop > 0);
+
+ /* 3. Switch off CPU power */
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ reg_val &= ~PWRC_CPUN_CR_PWR_DN_RQ_MASK;
+ mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
+
+ /* 4. Read and check Switch Off - verify bit set to 0 */
+ exit_loop = REG_WR_VALIDATE_TIMEOUT;
+ do {
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ exit_loop--;
+ } while (reg_val & PWRC_CPUN_CR_PWR_DN_RQ_MASK && exit_loop > 0);
+
+ if (exit_loop <= 0)
+ goto cpu_poweroff_error;
+
+ /* 5. De-Assert power ready */
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ reg_val &= ~PWRC_CPUN_CR_LDO_BYPASS_RDY_MASK;
+ mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
+
+ /* 6. Assert CPU POR reset */
+ reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
+ reg_val &= ~CCU_B_PRCRN_CPUPORESET_STATIC_MASK;
+ mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val);
+
+ /* 7. Read and poll on Validate the CPU is out of reset */
+ exit_loop = REG_WR_VALIDATE_TIMEOUT;
+ do {
+ reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
+ exit_loop--;
+ } while (reg_val & CCU_B_PRCRN_CPUPORESET_STATIC_MASK && exit_loop > 0);
+
+ if (exit_loop <= 0)
+ goto cpu_poweroff_error;
+
+ INFO("Successfully powered down CPU%d\n", cpu_id);
+
+ return 0;
+
+cpu_poweroff_error:
+ ERROR("ERROR: Can't power down CPU%d\n", cpu_id);
+ return -1;
+}
+
+/*
+ * Power down CPUs 1-3 at early boot stage,
+ * to reduce power consumption and SoC temperature.
+ * This is triggered by BLE prior to DDR initialization.
+ *
+ * Note:
+ * All CPUs will be powered up by plat_marvell_cpu_powerup on Linux boot stage,
+ * which is triggered by PSCI ops (pwr_domain_on).
+ */
+int plat_marvell_early_cpu_powerdown(void)
+{
+ uint32_t cpu_cluster_status =
+ mmio_read_32(FEATURE_DISABLE_STATUS_REG) &
+ FEATURE_DISABLE_STATUS_CPU_CLUSTER_MASK;
+ /* if cpu_cluster_status bit is set,
+ * that means we have only single cluster
+ */
+ int cluster_count = cpu_cluster_status ? 1 : 2;
+
+ INFO("Powering off unused CPUs\n");
+
+ /* CPU1 is in AP806 cluster-0, which always exists, so power it down */
+ if (plat_marvell_cpu_powerdown(CPU1) == -1)
+ return -1;
+
+ /*
+ * CPU2-3 are in AP806 2nd cluster (cluster-1),
+ * which doesn't exists in dual-core systems.
+ * so need to check if we have dual-core (single cluster)
+ * or quad-code (2 clusters)
+ */
+ if (cluster_count == 2) {
+ /* CPU2-3 are part of 2nd cluster */
+ if (plat_marvell_cpu_powerdown(CPU2) == -1)
+ return -1;
+ if (plat_marvell_cpu_powerdown(CPU3) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Power up CPU - part of Linux boot stage
+ */
+static int plat_marvell_cpu_powerup(u_register_t mpidr)
+{
+ uint32_t reg_val;
+ int cpu_id = MPIDR_CPU_GET(mpidr),
+ cluster = MPIDR_CLUSTER_GET(mpidr);
+ int exit_loop = REG_WR_VALIDATE_TIMEOUT;
+
+ /* calculate absolute CPU ID */
+ cpu_id = cluster * PLAT_MARVELL_CLUSTER_CORE_COUNT + cpu_id;
+
+ INFO("Powering on CPU%d\n", cpu_id);
+
+#ifdef MVEBU_SOC_AP807
+ /* Activate 2 power switch fingers */
+ reg_val = mmio_read_32(AP807_PWRC_LDO_CR0_REG);
+ reg_val &= ~(AP807_PWRC_LDO_CR0_MASK);
+ reg_val |= (AP807_PWRC_LDO_CR0_VAL << AP807_PWRC_LDO_CR0_OFFSET);
+ mmio_write_32(AP807_PWRC_LDO_CR0_REG, reg_val);
+ udelay(100);
+#endif
+
+ /* 1. Switch CPU power ON */
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ reg_val |= 0x1 << PWRC_CPUN_CR_PWR_DN_RQ_OFFSET;
+ mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
+
+ /* 2. Wait for CPU on, up to 100 uSec: */
+ udelay(100);
+
+ /* 3. Assert power ready */
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ reg_val |= 0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET;
+ mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
+
+ /* 4. Read & Validate power ready
+ * used in order to generate 16 Host CPU cycles
+ */
+ do {
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ exit_loop--;
+ } while (!(reg_val & (0x1U << PWRC_CPUN_CR_LDO_BYPASS_RDY_OFFSET)) &&
+ exit_loop > 0);
+
+ if (exit_loop <= 0)
+ goto cpu_poweron_error;
+
+ /* 5. Isolation disable */
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ reg_val &= ~PWRC_CPUN_CR_ISO_ENABLE_MASK;
+ mmio_write_32(PWRC_CPUN_CR_REG(cpu_id), reg_val);
+
+ /* 6. Read and check Isolation enabled - verify bit set to 1 */
+ exit_loop = REG_WR_VALIDATE_TIMEOUT;
+ do {
+ reg_val = mmio_read_32(PWRC_CPUN_CR_REG(cpu_id));
+ exit_loop--;
+ } while ((reg_val & (0x1 << PWRC_CPUN_CR_ISO_ENABLE_OFFSET)) &&
+ exit_loop > 0);
+
+ /* 7. De Assert CPU POR reset & Core reset */
+ reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
+ reg_val |= 0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET;
+ mmio_write_32(CCU_B_PRCRN_REG(cpu_id), reg_val);
+
+ /* 8. Read & Validate CPU POR reset */
+ exit_loop = REG_WR_VALIDATE_TIMEOUT;
+ do {
+ reg_val = mmio_read_32(CCU_B_PRCRN_REG(cpu_id));
+ exit_loop--;
+ } while (!(reg_val & (0x1 << CCU_B_PRCRN_CPUPORESET_STATIC_OFFSET)) &&
+ exit_loop > 0);
+
+ if (exit_loop <= 0)
+ goto cpu_poweron_error;
+
+ INFO("Successfully powered on CPU%d\n", cpu_id);
+
+ return 0;
+
+cpu_poweron_error:
+ ERROR("ERROR: Can't power up CPU%d\n", cpu_id);
+ return -1;
+}
+
+static int plat_marvell_cpu_on(u_register_t mpidr)
+{
+ int cpu_id;
+ int cluster;
+
+ /* Set barierr */
+ dsbsy();
+
+ /* Get cpu number - use CPU ID */
+ cpu_id = MPIDR_CPU_GET(mpidr);
+
+ /* Get cluster number - use affinity level 1 */
+ cluster = MPIDR_CLUSTER_GET(mpidr);
+
+ /* Set CPU private UID */
+ mmio_write_32(MVEBU_REGS_BASE + MVEBU_PRIVATE_UID_REG, cluster + 0x4);
+
+ /* Set the cpu start address to BL1 entry point (align to 0x10000) */
+ mmio_write_32(MVEBU_CCU_RVBAR(cpu_id),
+ PLAT_MARVELL_CPU_ENTRY_ADDR >> 16);
+
+ /* Get the cpu out of reset */
+ mmio_write_32(MVEBU_CCU_CPU_UN_RESET(cpu_id), 0x10001);
+
+ return 0;
+}
+
+/*****************************************************************************
+ * A8K handler called to check the validity of the power state
+ * parameter.
+ *****************************************************************************
+ */
+static int a8k_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's possible to enter standby only on power level 0
+ * Ignore any other power level.
+ */
+ if (pwr_lvl != MARVELL_PWR_LVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MARVELL_PWR_LVL0] =
+ MARVELL_LOCAL_STATE_RET;
+ } else {
+ for (i = MARVELL_PWR_LVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ MARVELL_LOCAL_STATE_OFF;
+ }
+
+ /*
+ * We expect the 'state id' to be zero.
+ */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+/*****************************************************************************
+ * A8K handler called when a CPU is about to enter standby.
+ *****************************************************************************
+ */
+static void a8k_cpu_standby(plat_local_state_t cpu_state)
+{
+ if (!is_pm_fw_running()) {
+ ERROR("%s: needs to be implemented\n", __func__);
+ panic();
+ }
+}
+
+/*****************************************************************************
+ * A8K handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ *****************************************************************************
+ */
+static int a8k_pwr_domain_on(u_register_t mpidr)
+{
+ /* Power up CPU (CPUs 1-3 are powered off at start of BLE) */
+ plat_marvell_cpu_powerup(mpidr);
+
+#if MSS_SUPPORT
+ if (is_pm_fw_running()) {
+ unsigned int target =
+ ((mpidr & 0xFF) + (((mpidr >> 8) & 0xFF) * 2));
+
+ /*
+ * pm system synchronization - used to synchronize
+ * multiple core access to MSS
+ */
+ bakery_lock_get(&pm_sys_lock);
+
+ /* send CPU ON IPC Message to MSS */
+ mss_pm_ipc_msg_send(target, PM_IPC_MSG_CPU_ON, 0);
+
+ /* trigger IPC message to MSS */
+ mss_pm_ipc_msg_trigger();
+
+ /* pm system synchronization */
+ bakery_lock_release(&pm_sys_lock);
+
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_ON | target);
+ } else
+#endif
+ {
+ /* proprietary CPU ON exection flow */
+ plat_marvell_cpu_on(mpidr);
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ * A8K handler called to validate the entry point.
+ *****************************************************************************
+ */
+static int a8k_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ return PSCI_E_SUCCESS;
+}
+
+/*****************************************************************************
+ * A8K handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ *****************************************************************************
+ */
+static void a8k_pwr_domain_off(const psci_power_state_t *target_state)
+{
+#if MSS_SUPPORT
+ if (is_pm_fw_running()) {
+ unsigned int idx = plat_my_core_pos();
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+
+ /* pm system synchronization - used to synchronize multiple
+ * core access to MSS
+ */
+ bakery_lock_get(&pm_sys_lock);
+
+ /* send CPU OFF IPC Message to MSS */
+ mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_OFF, target_state);
+
+ /* trigger IPC message to MSS */
+ mss_pm_ipc_msg_trigger();
+
+ /* pm system synchronization */
+ bakery_lock_release(&pm_sys_lock);
+
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_OFF);
+ } else {
+ INFO("%s: is not supported without SCP\n", __func__);
+ }
+#endif
+}
+
+/* Get PM config to power off the SoC */
+void *plat_marvell_get_pm_cfg(void)
+{
+ return NULL;
+}
+
+/*
+ * This function should be called on restore from
+ * "suspend to RAM" state when the execution flow
+ * has to bypass BootROM image to RAM copy and speed up
+ * the system recovery
+ *
+ */
+static void plat_marvell_exit_bootrom(void)
+{
+ marvell_exit_bootrom(PLAT_MARVELL_TRUSTED_ROM_BASE);
+}
+
+/*
+ * Prepare for the power off of the system via GPIO
+ */
+static void plat_marvell_power_off_gpio(struct power_off_method *pm_cfg,
+ register_t *gpio_addr,
+ register_t *gpio_data)
+{
+ unsigned int gpio;
+ unsigned int idx;
+ unsigned int shift;
+ unsigned int reg;
+ unsigned int addr;
+ gpio_info_t *info;
+ unsigned int tog_bits;
+
+ assert((pm_cfg->cfg.gpio.pin_count < PMIC_GPIO_MAX_NUMBER) &&
+ (pm_cfg->cfg.gpio.step_count < PMIC_GPIO_MAX_TOGGLE_STEP));
+
+ /* Prepare GPIOs for PMIC */
+ for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) {
+ info = &pm_cfg->cfg.gpio.info[gpio];
+ /* Set PMIC GPIO to output mode */
+ reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT_EN(
+ info->cp_index, info->gpio_index));
+ mmio_write_32(MVEBU_CP_GPIO_DATA_OUT_EN(
+ info->cp_index, info->gpio_index),
+ reg & ~MVEBU_GPIO_MASK(info->gpio_index));
+
+ /* Set the appropriate MPP to GPIO mode */
+ reg = mmio_read_32(MVEBU_PM_MPP_REGS(info->cp_index,
+ info->gpio_index));
+ mmio_write_32(MVEBU_PM_MPP_REGS(info->cp_index,
+ info->gpio_index),
+ reg & ~MVEBU_MPP_MASK(info->gpio_index));
+ }
+
+ /* Wait for MPP & GPIO pre-configurations done */
+ mdelay(pm_cfg->cfg.gpio.delay_ms);
+
+ /* Toggle the GPIO values, and leave final step to be triggered
+ * after DDR self-refresh is enabled
+ */
+ for (idx = 0; idx < pm_cfg->cfg.gpio.step_count; idx++) {
+ tog_bits = pm_cfg->cfg.gpio.seq[idx];
+
+ /* The GPIOs must be within same GPIO register,
+ * thus could get the original value by first GPIO
+ */
+ info = &pm_cfg->cfg.gpio.info[0];
+ reg = mmio_read_32(MVEBU_CP_GPIO_DATA_OUT(
+ info->cp_index, info->gpio_index));
+ addr = MVEBU_CP_GPIO_DATA_OUT(info->cp_index, info->gpio_index);
+
+ for (gpio = 0; gpio < pm_cfg->cfg.gpio.pin_count; gpio++) {
+ shift = pm_cfg->cfg.gpio.info[gpio].gpio_index % 32;
+ if (GPIO_LOW == (tog_bits & (1 << gpio)))
+ reg &= ~(1 << shift);
+ else
+ reg |= (1 << shift);
+ }
+
+ /* Set the GPIO register, for last step just store
+ * register address and values to system registers
+ */
+ if (idx < pm_cfg->cfg.gpio.step_count - 1) {
+ mmio_write_32(MVEBU_CP_GPIO_DATA_OUT(
+ info->cp_index, info->gpio_index), reg);
+ mdelay(pm_cfg->cfg.gpio.delay_ms);
+ } else {
+ /* Save GPIO register and address values for
+ * finishing the power down operation later
+ */
+ *gpio_addr = addr;
+ *gpio_data = reg;
+ }
+ }
+}
+
+/*
+ * Prepare for the power off of the system
+ */
+static void plat_marvell_power_off_prepare(struct power_off_method *pm_cfg,
+ register_t *addr, register_t *data)
+{
+ switch (pm_cfg->type) {
+ case PMIC_GPIO:
+ plat_marvell_power_off_gpio(pm_cfg, addr, data);
+ break;
+ default:
+ break;
+ }
+}
+
+/*****************************************************************************
+ * A8K handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ *****************************************************************************
+ */
+static void a8k_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+#if MSS_SUPPORT
+ if (is_pm_fw_running()) {
+ unsigned int idx;
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+
+ idx = plat_my_core_pos();
+
+ /* pm system synchronization - used to synchronize multiple
+ * core access to MSS
+ */
+ bakery_lock_get(&pm_sys_lock);
+
+ /* send CPU Suspend IPC Message to MSS */
+ mss_pm_ipc_msg_send(idx, PM_IPC_MSG_CPU_SUSPEND, target_state);
+
+ /* trigger IPC message to MSS */
+ mss_pm_ipc_msg_trigger();
+
+ /* pm system synchronization */
+ bakery_lock_release(&pm_sys_lock);
+
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND);
+ } else
+#endif
+ {
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ INFO("Suspending to RAM\n");
+
+ marvell_console_runtime_end();
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] = MVEBU_MAILBOX_SUSPEND_STATE;
+ mailbox[MBOX_IDX_ROM_EXIT_ADDR] = (uintptr_t)&plat_marvell_exit_bootrom;
+
+#if PLAT_MARVELL_SHARED_RAM_CACHED
+ flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
+ MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
+ 2 * sizeof(uintptr_t));
+#endif
+ /* Flush and disable LLC before going off-power */
+ llc_disable(0);
+
+ isb();
+ /*
+ * Do not halt here!
+ * The function must return for allowing the caller function
+ * psci_power_up_finish() to do the proper context saving and
+ * to release the CPU lock.
+ */
+ }
+}
+
+/*****************************************************************************
+ * A8K handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ *****************************************************************************
+ */
+static void a8k_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* arch specific configuration */
+ marvell_psci_arch_init(0);
+
+ /* Interrupt initialization */
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+
+ if (is_pm_fw_running()) {
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_ON_FINISH);
+ }
+}
+
+/*****************************************************************************
+ * A8K handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ *****************************************************************************
+ */
+static void a8k_pwr_domain_suspend_finish(
+ const psci_power_state_t *target_state)
+{
+ if (is_pm_fw_running()) {
+ /* arch specific configuration */
+ marvell_psci_arch_init(0);
+
+ /* Interrupt initialization */
+ gicv2_cpuif_enable();
+
+ /* trace message */
+ PM_TRACE(TRACE_PWR_DOMAIN_SUSPEND_FINISH);
+ } else {
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ /* Only primary CPU requres platform init */
+ if (!plat_my_core_pos()) {
+ /* Initialize the console to provide
+ * early debug support
+ */
+ marvell_console_runtime_init();
+
+ bl31_plat_arch_setup();
+ marvell_bl31_platform_setup();
+ /*
+ * Remove suspend to RAM marker from the mailbox
+ * for treating a regular reset as a cold boot
+ */
+ mailbox[MBOX_IDX_SUSPEND_MAGIC] = 0;
+ mailbox[MBOX_IDX_ROM_EXIT_ADDR] = 0;
+#if PLAT_MARVELL_SHARED_RAM_CACHED
+ flush_dcache_range(PLAT_MARVELL_MAILBOX_BASE +
+ MBOX_IDX_SUSPEND_MAGIC * sizeof(uintptr_t),
+ 2 * sizeof(uintptr_t));
+#endif
+ }
+ }
+}
+
+/*****************************************************************************
+ * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
+ * call to get the `power_state` parameter. This allows the platform to encode
+ * the appropriate State-ID field within the `power_state` parameter which can
+ * be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
+ *****************************************************************************
+ */
+static void a8k_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ /* lower affinities use PLAT_MAX_OFF_STATE */
+ for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+static void
+__dead2 a8k_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+ struct power_off_method *pm_cfg;
+ unsigned int srcmd;
+ unsigned int sdram_reg;
+ register_t gpio_data = 0, gpio_addr = 0;
+
+ if (is_pm_fw_running()) {
+ psci_power_down_wfi();
+ panic();
+ }
+
+ pm_cfg = (struct power_off_method *)plat_marvell_get_pm_cfg();
+
+ /* Prepare for power off */
+ plat_marvell_power_off_prepare(pm_cfg, &gpio_addr, &gpio_data);
+
+ /* First step to enable DDR self-refresh
+ * to keep the data during suspend
+ */
+ mmio_write_32(MVEBU_MC_PWR_CTRL_REG, 0x8C1);
+
+ /* Save DDR self-refresh second step register
+ * and value to be issued later
+ */
+ sdram_reg = MVEBU_USER_CMD_0_REG;
+ srcmd = mmio_read_32(sdram_reg);
+ srcmd &= ~(MVEBU_USER_CMD_CH0_MASK | MVEBU_USER_CMD_CS_MASK |
+ MVEBU_USER_CMD_SR_MASK);
+ srcmd |= (MVEBU_USER_CMD_CH0_EN | MVEBU_USER_CMD_CS_ALL |
+ MVEBU_USER_CMD_SR_ENTER);
+
+ /*
+ * Wait for DRAM is done using registers access only.
+ * At this stage any access to DRAM (procedure call) will
+ * release it from the self-refresh mode
+ */
+ __asm__ volatile (
+ /* Align to a cache line */
+ " .balign 64\n\t"
+
+ /* Enter self refresh */
+ " str %[srcmd], [%[sdram_reg]]\n\t"
+
+ /*
+ * Wait 100 cycles for DDR to enter self refresh, by
+ * doing 50 times two instructions.
+ */
+ " mov x1, #50\n\t"
+ "1: subs x1, x1, #1\n\t"
+ " bne 1b\n\t"
+
+ /* Issue the command to trigger the SoC power off */
+ " str %[gpio_data], [%[gpio_addr]]\n\t"
+
+ /* Trap the processor */
+ " b .\n\t"
+ : : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg),
+ [gpio_addr] "r" (gpio_addr), [gpio_data] "r" (gpio_data)
+ : "x1");
+
+ panic();
+}
+
+/*****************************************************************************
+ * A8K handlers to shutdown/reboot the system
+ *****************************************************************************
+ */
+
+/* Set a weak stub for platforms that don't configure system power off */
+#pragma weak system_power_off
+int system_power_off(void)
+{
+ return 0;
+}
+
+static void __dead2 a8k_system_off(void)
+{
+ /* Call the platform specific system power off function */
+ system_power_off();
+
+ /* board doesn't have a system off implementation */
+ ERROR("%s: needs to be implemented\n", __func__);
+ panic();
+}
+
+void plat_marvell_system_reset(void)
+{
+ mmio_write_32(MVEBU_RFU_BASE + MVEBU_RFU_GLOBL_SW_RST, 0x0);
+}
+
+static void __dead2 a8k_system_reset(void)
+{
+ plat_marvell_system_reset();
+
+ /* we shouldn't get to this point */
+ panic();
+}
+
+/*****************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ *****************************************************************************
+ */
+const plat_psci_ops_t plat_arm_psci_pm_ops = {
+ .cpu_standby = a8k_cpu_standby,
+ .pwr_domain_on = a8k_pwr_domain_on,
+ .pwr_domain_off = a8k_pwr_domain_off,
+ .pwr_domain_suspend = a8k_pwr_domain_suspend,
+ .pwr_domain_on_finish = a8k_pwr_domain_on_finish,
+ .get_sys_suspend_power_state = a8k_get_sys_suspend_power_state,
+ .pwr_domain_suspend_finish = a8k_pwr_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = a8k_pwr_domain_pwr_down_wfi,
+ .system_off = a8k_system_off,
+ .system_reset = a8k_system_reset,
+ .validate_power_state = a8k_validate_power_state,
+ .validate_ns_entrypoint = a8k_validate_ns_entrypoint
+};
diff --git a/plat/marvell/armada/a8k/common/plat_pm_trace.c b/plat/marvell/armada/a8k/common/plat_pm_trace.c
new file mode 100644
index 0000000..e02a893
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/plat_pm_trace.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#if MSS_SUPPORT
+#include <mss_mem.h>
+
+#ifdef PM_TRACE_ENABLE
+#include <plat_pm_trace.h>
+
+/* core trace APIs */
+core_trace_func funcTbl[PLATFORM_CORE_COUNT] = {
+ pm_core_0_trace,
+ pm_core_1_trace,
+ pm_core_2_trace,
+ pm_core_3_trace};
+
+/*****************************************************************************
+ * pm_core0_trace
+ * pm_core1_trace
+ * pm_core2_trace
+ * pm_core_3trace
+ *
+ * This functions set trace info into core cyclic trace queue in MSS SRAM
+ * memory space
+ *****************************************************************************
+ */
+void pm_core_0_trace(unsigned int trace)
+{
+ unsigned int current_position_core_0 =
+ mmio_read_32(AP_MSS_ATF_CORE_0_CTRL_BASE);
+ mmio_write_32((AP_MSS_ATF_CORE_0_INFO_BASE +
+ (current_position_core_0 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ mmio_read_32(AP_MSS_TIMER_BASE));
+ mmio_write_32((AP_MSS_ATF_CORE_0_INFO_TRACE +
+ (current_position_core_0 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ trace);
+ mmio_write_32(AP_MSS_ATF_CORE_0_CTRL_BASE,
+ ((current_position_core_0 + 1) &
+ AP_MSS_ATF_TRACE_SIZE_MASK));
+}
+
+void pm_core_1_trace(unsigned int trace)
+{
+ unsigned int current_position_core_1 =
+ mmio_read_32(AP_MSS_ATF_CORE_1_CTRL_BASE);
+ mmio_write_32((AP_MSS_ATF_CORE_1_INFO_BASE +
+ (current_position_core_1 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ mmio_read_32(AP_MSS_TIMER_BASE));
+ mmio_write_32((AP_MSS_ATF_CORE_1_INFO_TRACE +
+ (current_position_core_1 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ trace);
+ mmio_write_32(AP_MSS_ATF_CORE_1_CTRL_BASE,
+ ((current_position_core_1 + 1) &
+ AP_MSS_ATF_TRACE_SIZE_MASK));
+}
+
+void pm_core_2_trace(unsigned int trace)
+{
+ unsigned int current_position_core_2 =
+ mmio_read_32(AP_MSS_ATF_CORE_2_CTRL_BASE);
+ mmio_write_32((AP_MSS_ATF_CORE_2_INFO_BASE +
+ (current_position_core_2 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ mmio_read_32(AP_MSS_TIMER_BASE));
+ mmio_write_32((AP_MSS_ATF_CORE_2_INFO_TRACE +
+ (current_position_core_2 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ trace);
+ mmio_write_32(AP_MSS_ATF_CORE_2_CTRL_BASE,
+ ((current_position_core_2 + 1) &
+ AP_MSS_ATF_TRACE_SIZE_MASK));
+}
+
+void pm_core_3_trace(unsigned int trace)
+{
+ unsigned int current_position_core_3 =
+ mmio_read_32(AP_MSS_ATF_CORE_3_CTRL_BASE);
+ mmio_write_32((AP_MSS_ATF_CORE_3_INFO_BASE +
+ (current_position_core_3 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ mmio_read_32(AP_MSS_TIMER_BASE));
+ mmio_write_32((AP_MSS_ATF_CORE_3_INFO_TRACE +
+ (current_position_core_3 * AP_MSS_ATF_CORE_ENTRY_SIZE)),
+ trace);
+ mmio_write_32(AP_MSS_ATF_CORE_3_CTRL_BASE,
+ ((current_position_core_3 + 1) &
+ AP_MSS_ATF_TRACE_SIZE_MASK));
+}
+#endif /* PM_TRACE_ENABLE */
+#endif /* MSS_SUPPORT */
diff --git a/plat/marvell/armada/a8k/common/plat_thermal.c b/plat/marvell/armada/a8k/common/plat_thermal.c
new file mode 100644
index 0000000..a2fc0d0
--- /dev/null
+++ b/plat/marvell/armada/a8k/common/plat_thermal.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/marvell/thermal.h>
+#include <lib/mmio.h>
+
+#include <mvebu_def.h>
+
+#define THERMAL_TIMEOUT 1200
+
+#define THERMAL_SEN_CTRL_LSB_STRT_OFFSET 0
+#define THERMAL_SEN_CTRL_LSB_STRT_MASK \
+ (0x1 << THERMAL_SEN_CTRL_LSB_STRT_OFFSET)
+#define THERMAL_SEN_CTRL_LSB_RST_OFFSET 1
+#define THERMAL_SEN_CTRL_LSB_RST_MASK \
+ (0x1 << THERMAL_SEN_CTRL_LSB_RST_OFFSET)
+#define THERMAL_SEN_CTRL_LSB_EN_OFFSET 2
+#define THERMAL_SEN_CTRL_LSB_EN_MASK \
+ (0x1 << THERMAL_SEN_CTRL_LSB_EN_OFFSET)
+
+#define THERMAL_SEN_CTRL_STATS_VALID_OFFSET 16
+#define THERMAL_SEN_CTRL_STATS_VALID_MASK \
+ (0x1 << THERMAL_SEN_CTRL_STATS_VALID_OFFSET)
+#define THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET 0
+#define THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK \
+ (0x3FF << THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET)
+
+#define THERMAL_SEN_OUTPUT_MSB 512
+#define THERMAL_SEN_OUTPUT_COMP 1024
+
+struct tsen_regs {
+ uint32_t ext_tsen_ctrl_lsb;
+ uint32_t ext_tsen_ctrl_msb;
+ uint32_t ext_tsen_status;
+};
+
+static int ext_tsen_probe(struct tsen_config *tsen_cfg)
+{
+ uint32_t reg, timeout = 0;
+ struct tsen_regs *base;
+
+ if (tsen_cfg == NULL && tsen_cfg->regs_base == NULL) {
+ ERROR("initial thermal sensor configuration is missing\n");
+ return -1;
+ }
+ base = (struct tsen_regs *)tsen_cfg->regs_base;
+
+ INFO("initializing thermal sensor\n");
+
+ /* initialize thermal sensor hardware reset once */
+ reg = mmio_read_32((uintptr_t)&base->ext_tsen_ctrl_lsb);
+ reg &= ~THERMAL_SEN_CTRL_LSB_RST_OFFSET; /* de-assert TSEN_RESET */
+ reg |= THERMAL_SEN_CTRL_LSB_EN_MASK; /* set TSEN_EN to 1 */
+ reg |= THERMAL_SEN_CTRL_LSB_STRT_MASK; /* set TSEN_START to 1 */
+ mmio_write_32((uintptr_t)&base->ext_tsen_ctrl_lsb, reg);
+
+ reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
+ while ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0 &&
+ timeout < THERMAL_TIMEOUT) {
+ udelay(100);
+ reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
+ timeout++;
+ }
+
+ if ((reg & THERMAL_SEN_CTRL_STATS_VALID_MASK) == 0) {
+ ERROR("thermal sensor is not ready\n");
+ return -1;
+ }
+
+ tsen_cfg->tsen_ready = 1;
+
+ VERBOSE("thermal sensor was initialized\n");
+
+ return 0;
+}
+
+static int ext_tsen_read(struct tsen_config *tsen_cfg, int *temp)
+{
+ uint32_t reg;
+ struct tsen_regs *base;
+
+ if (tsen_cfg == NULL && !tsen_cfg->tsen_ready) {
+ ERROR("thermal sensor was not initialized\n");
+ return -1;
+ }
+ base = (struct tsen_regs *)tsen_cfg->regs_base;
+
+ reg = mmio_read_32((uintptr_t)&base->ext_tsen_status);
+ reg = ((reg & THERMAL_SEN_CTRL_STATS_TEMP_OUT_MASK) >>
+ THERMAL_SEN_CTRL_STATS_TEMP_OUT_OFFSET);
+
+ /*
+ * TSEN output format is signed as a 2s complement number
+ * ranging from-512 to +511. when MSB is set, need to
+ * calculate the complement number
+ */
+ if (reg >= THERMAL_SEN_OUTPUT_MSB)
+ reg -= THERMAL_SEN_OUTPUT_COMP;
+
+ if (tsen_cfg->tsen_divisor == 0) {
+ ERROR("thermal sensor divisor cannot be zero\n");
+ return -1;
+ }
+
+ *temp = ((tsen_cfg->tsen_gain * ((int)reg)) +
+ tsen_cfg->tsen_offset) / tsen_cfg->tsen_divisor;
+
+ return 0;
+}
+
+static struct tsen_config tsen_cfg = {
+ .tsen_offset = 153400,
+ .tsen_gain = 425,
+ .tsen_divisor = 1000,
+ .tsen_ready = 0,
+ .regs_base = (void *)MVEBU_AP_EXT_TSEN_BASE,
+ .ptr_tsen_probe = ext_tsen_probe,
+ .ptr_tsen_read = ext_tsen_read
+};
+
+struct tsen_config *marvell_thermal_config_get(void)
+{
+ return &tsen_cfg;
+}
diff --git a/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
new file mode 100644
index 0000000..6c55858
--- /dev/null
+++ b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <marvell_def.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef SCP_BL2_BASE
+ /* Fill SCP_BL2 related information if it exists */
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = SCP_BL2_BASE,
+ .image_info.image_max_size = SCP_BL2_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif /* SCP_BL2_BASE */
+
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload)*/
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+#else /* EL3_PAYLOAD_BASE */
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg3 = MARVELL_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE
+ * where it is the pager image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE,
+ * where it is the paged image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = MARVELL_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = MARVELL_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = MARVELL_DRAM_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = MARVELL_DRAM_BASE,
+ .image_info.image_max_size = MARVELL_DRAM_SIZE,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/marvell/armada/common/aarch64/marvell_common.c b/plat/marvell/armada/common/aarch64/marvell_common.c
new file mode 100644
index 0000000..21a62d4
--- /dev/null
+++ b/plat/marvell/armada/common/aarch64/marvell_common.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <plat_marvell.h>
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_get_ns_image_entrypoint
+#pragma weak plat_marvell_get_mmap
+
+/*
+ * Set up the page tables for the generic and platform-specific memory regions.
+ * The extents of the generic memory regions are specified by the function
+ * arguments and consist of:
+ * - Trusted SRAM seen by the BL image;
+ * - Code section;
+ * - Read-only data section;
+ * - Coherent memory region, if applicable.
+ */
+void marvell_setup_page_tables(uintptr_t total_base,
+ size_t total_size,
+ uintptr_t code_start,
+ uintptr_t code_limit,
+ uintptr_t rodata_start,
+ uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ ,
+ uintptr_t coh_start,
+ uintptr_t coh_limit
+#endif
+ )
+{
+ /*
+ * Map the Trusted SRAM with appropriate memory attributes.
+ * Subsequent mappings will adjust the attributes for specific regions.
+ */
+ VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n",
+ (void *) total_base, (void *) (total_base + total_size));
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ /* Re-map the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *) code_start, (void *) code_limit);
+ mmap_add_region(code_start, code_start,
+ code_limit - code_start,
+ MT_CODE | MT_SECURE);
+
+ /* Re-map the read-only data section */
+ VERBOSE("Read-only data region: %p - %p\n",
+ (void *) rodata_start, (void *) rodata_limit);
+ mmap_add_region(rodata_start, rodata_start,
+ rodata_limit - rodata_start,
+ MT_RO_DATA | MT_SECURE);
+
+#if USE_COHERENT_MEM
+ /* Re-map the coherent memory region */
+ VERBOSE("Coherent region: %p - %p\n",
+ (void *) coh_start, (void *) coh_limit);
+ mmap_add_region(coh_start, coh_start,
+ coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+ /* Now (re-)map the platform-specific memory regions */
+ mmap_add(plat_marvell_get_mmap());
+
+ /* Create the page tables to reflect the above mappings */
+ init_xlat_tables();
+}
+
+unsigned long plat_get_ns_image_entrypoint(void)
+{
+ return PLAT_MARVELL_NS_IMAGE_OFFSET;
+}
+
+/*****************************************************************************
+ * Gets SPSR for BL32 entry
+ *****************************************************************************
+ */
+uint32_t marvell_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/*****************************************************************************
+ * Gets SPSR for BL33 entry
+ *****************************************************************************
+ */
+uint32_t marvell_get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+/*****************************************************************************
+ * Returns ARM platform specific memory map regions.
+ *****************************************************************************
+ */
+const mmap_region_t *plat_marvell_get_mmap(void)
+{
+ return plat_marvell_mmap;
+}
+
diff --git a/plat/marvell/armada/common/aarch64/marvell_helpers.S b/plat/marvell/armada/common/aarch64/marvell_helpers.S
new file mode 100644
index 0000000..3038ec0
--- /dev/null
+++ b/plat/marvell/armada/common/aarch64/marvell_helpers.S
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <asm_macros.S>
+#include <cortex_a72.h>
+#ifndef PLAT_a3700
+#include <drivers/marvell/ccu.h>
+#include <drivers/marvell/cache_llc.h>
+#endif
+#include <marvell_def.h>
+#include <platform_def.h>
+
+ .weak plat_marvell_calc_core_pos
+ .weak plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl platform_mem_init
+ .globl disable_mmu_dcache
+ .globl invalidate_tlb_all
+ .globl platform_unmap_sram
+ .globl disable_sram
+ .globl disable_icache
+ .globl invalidate_icache_all
+ .globl marvell_exit_bootrom
+ .globl ca72_l2_enable_unique_clean
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_marvell_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_marvell_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_marvell_calc_core_pos(uint64_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 2) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func plat_marvell_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #7
+ ret
+endfunc plat_marvell_calc_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+#ifdef PLAT_a3700
+ mov x1, x30
+ bl get_ref_clk
+ mov x30, x1
+ mov_imm x1, 1000000
+ mul x1, x0, x1
+#else
+ mov_imm x1, PLAT_MARVELL_UART_CLK_IN_HZ
+#endif
+ mov_imm x0, PLAT_MARVELL_UART_BASE
+ mov_imm x2, MARVELL_CONSOLE_BAUDRATE
+#ifdef PLAT_a3700
+ b console_a3700_core_init
+#else
+ b console_16550_core_init
+#endif
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_MARVELL_UART_BASE
+#ifdef PLAT_a3700
+
+ b console_a3700_core_putc
+#else
+ b console_16550_core_putc
+#endif
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : r0
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, PLAT_MARVELL_UART_BASE
+#ifdef PLAT_a3700
+ b console_a3700_core_flush
+#else
+ b console_16550_core_flush
+#endif
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on ARM
+ * platforms. The Secure RAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* -----------------------------------------------------
+ * Disable icache, dcache, and MMU
+ * -----------------------------------------------------
+ */
+func disable_mmu_dcache
+ mrs x0, sctlr_el3
+ bic x0, x0, 0x1 /* M bit - MMU */
+ bic x0, x0, 0x4 /* C bit - Dcache L1 & L2 */
+ msr sctlr_el3, x0
+ isb
+ b mmu_off
+mmu_off:
+ ret
+endfunc disable_mmu_dcache
+
+ /* -----------------------------------------------------
+ * Disable all TLB entries
+ * -----------------------------------------------------
+ */
+func invalidate_tlb_all
+ tlbi alle3
+ dsb sy
+ isb
+ ret
+endfunc invalidate_tlb_all
+
+ /* -----------------------------------------------------
+ * Disable the i cache
+ * -----------------------------------------------------
+ */
+func disable_icache
+ mrs x0, sctlr_el3
+ bic x0, x0, 0x1000 /* I bit - Icache L1 & L2 */
+ msr sctlr_el3, x0
+ isb
+ ret
+endfunc disable_icache
+
+ /* -----------------------------------------------------
+ * Disable all of the i caches
+ * -----------------------------------------------------
+ */
+func invalidate_icache_all
+ ic ialluis
+ isb sy
+ ret
+endfunc invalidate_icache_all
+
+ /* -----------------------------------------------------
+ * Clear the SRAM enabling bit to unmap SRAM
+ * -----------------------------------------------------
+ */
+func platform_unmap_sram
+ ldr x0, =CCU_SRAM_WIN_CR
+ str wzr, [x0]
+ ret
+endfunc platform_unmap_sram
+
+ /* -----------------------------------------------------
+ * Disable the SRAM
+ * -----------------------------------------------------
+ */
+func disable_sram
+ /* Disable the line lockings. They must be disabled expictly
+ * or the OS will have problems using the cache */
+ ldr x1, =MASTER_LLC_TC0_LOCK
+ str wzr, [x1]
+
+ /* Invalidate all ways */
+ ldr w1, =LLC_WAY_MASK
+ ldr x0, =MASTER_LLC_INV_WAY
+ str w1, [x0]
+
+ /* Finally disable LLC */
+ ldr x0, =MASTER_LLC_CTRL
+ str wzr, [x0]
+
+ ret
+endfunc disable_sram
+
+ /* -----------------------------------------------------
+ * Operation when exit bootROM:
+ * Disable the MMU
+ * Disable and invalidate the dcache
+ * Unmap and disable the SRAM
+ * Disable and invalidate the icache
+ * -----------------------------------------------------
+ */
+func marvell_exit_bootrom
+ /* Save the system restore address */
+ mov x28, x0
+
+ /* Close the caches and MMU */
+ bl disable_mmu_dcache
+
+ /*
+ * There is nothing important in the caches now,
+ * so invalidate them instead of cleaning.
+ */
+ adr x0, __RW_START__
+ adr x1, __RW_END__
+ sub x1, x1, x0
+ bl inv_dcache_range
+ bl invalidate_tlb_all
+
+ /*
+ * Clean the memory mapping of SRAM
+ * the DDR mapping will remain to enable boot image to execute
+ */
+ bl platform_unmap_sram
+
+ /* Disable the SRAM */
+ bl disable_sram
+
+ /* Disable and invalidate icache */
+ bl disable_icache
+ bl invalidate_icache_all
+
+ mov x0, x28
+ br x0
+endfunc marvell_exit_bootrom
+
+ /*
+ * Enable L2 UniqueClean evictions with data
+ */
+func ca72_l2_enable_unique_clean
+
+ mrs x0, CORTEX_A72_L2ACTLR_EL1
+ orr x0, x0, #CORTEX_A72_L2ACTLR_ENABLE_UNIQUE_CLEAN
+ msr CORTEX_A72_L2ACTLR_EL1, x0
+
+ ret
+endfunc ca72_l2_enable_unique_clean
diff --git a/plat/marvell/armada/common/marvell_bl1_setup.c b/plat/marvell/armada/common/marvell_bl1_setup.c
new file mode 100644
index 0000000..7b7cef3
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_bl1_setup.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <platform_def.h>
+
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/console.h>
+#include <plat/common/platform.h>
+
+#include <plat_marvell.h>
+
+/* Weak definitions may be overridden in specific Marvell standard platform */
+#pragma weak bl1_early_platform_setup
+#pragma weak bl1_plat_arch_setup
+#pragma weak bl1_platform_setup
+#pragma weak bl1_plat_sec_mem_layout
+
+/* Data structure which holds the extents of the RAM for BL1*/
+static meminfo_t bl1_ram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_ram_layout;
+}
+
+/*
+ * BL1 specific platform actions shared between Marvell standard platforms.
+ */
+void marvell_bl1_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ marvell_console_boot_init();
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_ram_layout.total_base = MARVELL_BL_RAM_BASE;
+ bl1_ram_layout.total_size = MARVELL_BL_RAM_SIZE;
+}
+
+void bl1_early_platform_setup(void)
+{
+ marvell_bl1_early_platform_setup();
+}
+
+/*
+ * Perform the very early platform specific architecture setup shared between
+ * MARVELL standard platforms. This only does basic initialization. Later
+ * architectural setup (bl1_arch_setup()) does not do anything platform
+ * specific.
+ */
+void marvell_bl1_plat_arch_setup(void)
+{
+ marvell_setup_page_tables(bl1_ram_layout.total_base,
+ bl1_ram_layout.total_size,
+ BL1_RO_BASE,
+ BL1_RO_LIMIT,
+ BL1_RO_DATA_BASE,
+ BL1_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+ enable_mmu_el3(0);
+}
+
+void bl1_plat_arch_setup(void)
+{
+ marvell_bl1_plat_arch_setup();
+}
+
+/*
+ * Perform the platform specific architecture setup shared between
+ * MARVELL standard platforms.
+ */
+void marvell_bl1_platform_setup(void)
+{
+ /* Initialise the IO layer and register platform IO devices */
+ plat_marvell_io_setup();
+}
+
+void bl1_platform_setup(void)
+{
+ marvell_bl1_platform_setup();
+}
+
+void bl1_plat_prepare_exit(entry_point_info_t *ep_info)
+{
+#ifdef EL3_PAYLOAD_BASE
+ /*
+ * Program the EL3 payload's entry point address into the CPUs mailbox
+ * in order to release secondary CPUs from their holding pen and make
+ * them jump there.
+ */
+ marvell_program_trusted_mailbox(ep_info->pc);
+ dsbsy();
+ sev();
+#endif
+}
diff --git a/plat/marvell/armada/common/marvell_bl2_setup.c b/plat/marvell/armada/common/marvell_bl2_setup.c
new file mode 100644
index 0000000..3dfa82e
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_bl2_setup.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/console.h>
+#include <lib/utils.h>
+
+#ifdef SPD_opteed
+#include <optee_utils.h>
+#endif
+#include <marvell_def.h>
+#include <plat_marvell.h>
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/* Weak definitions may be overridden in specific MARVELL standard platform */
+#pragma weak bl2_early_platform_setup2
+#pragma weak bl2_platform_setup
+#pragma weak bl2_plat_arch_setup
+#pragma weak bl2_plat_sec_mem_layout
+
+meminfo_t *bl2_plat_sec_mem_layout(void)
+{
+ return &bl2_tzram_layout;
+}
+
+/*****************************************************************************
+ * BL1 has passed the extents of the trusted SRAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted SRAM.
+ * Copy it to a safe location before its reclaimed by later BL2 functionality.
+ *****************************************************************************
+ */
+void marvell_bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+ /* Initialize the console to provide early debug support */
+ marvell_console_boot_init();
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_marvell_io_setup();
+}
+
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct meminfo *mem_layout = (struct meminfo *)arg1;
+
+ marvell_bl2_early_platform_setup(mem_layout);
+}
+
+void bl2_platform_setup(void)
+{
+ /* Nothing to do */
+}
+
+/*****************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ *****************************************************************************
+ */
+void marvell_bl2_plat_arch_setup(void)
+{
+ marvell_setup_page_tables(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+ enable_mmu_el1(0);
+}
+
+void bl2_plat_arch_setup(void)
+{
+ marvell_bl2_plat_arch_setup();
+}
+
+int marvell_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif /* SPD_opteed */
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0)
+ WARN("OPTEE header parse error.\n");
+#endif /* SPD_opteed */
+ bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl32_entry();
+ break;
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl33_entry();
+ break;
+#ifdef SCP_BL2_BASE
+ case SCP_BL2_IMAGE_ID:
+ /* The subsequent handling of SCP_BL2 is platform specific */
+ err = bl2_plat_handle_scp_bl2(&bl_mem_params->image_info);
+ if (err) {
+ WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
+ }
+ break;
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return marvell_bl2_handle_post_image_load(image_id);
+}
+
diff --git a/plat/marvell/armada/common/marvell_bl31_setup.c b/plat/marvell/armada/common/marvell_bl31_setup.c
new file mode 100644
index 0000000..26ba906
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_bl31_setup.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#ifdef USE_CCI
+#include <drivers/arm/cci.h>
+#endif
+#include <drivers/console.h>
+#include <plat/common/platform.h>
+
+#include <marvell_def.h>
+#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak bl31_early_platform_setup2
+#pragma weak bl31_platform_setup
+#pragma weak bl31_plat_arch_setup
+#pragma weak bl31_plat_get_next_image_ep_info
+#pragma weak plat_get_syscnt_freq2
+
+/*****************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ *****************************************************************************
+ */
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+
+ return next_image_info;
+}
+
+/*****************************************************************************
+ * Perform any BL31 early platform setup common to ARM standard platforms.
+ * Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be
+ * done before the MMU is initialized so that the memory layout can be used
+ * while creating page tables. BL2 has flushed this information to memory, so
+ * we are guaranteed to pick up good data.
+ *****************************************************************************
+ */
+void marvell_bl31_early_platform_setup(void *from_bl2,
+ uintptr_t soc_fw_config,
+ uintptr_t hw_config,
+ void *plat_params_from_bl2)
+{
+ /* Initialize the console to provide early debug support */
+ marvell_console_boot_init();
+
+#if RESET_TO_BL31
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(from_bl2 == NULL);
+ assert(plat_params_from_bl2 == NULL);
+
+#ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = marvell_get_spsr_for_bl32_entry();
+#endif /* BL32_BASE */
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = marvell_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#else
+ /*
+ * In debug builds, we pass a special value in 'plat_params_from_bl2'
+ * to verify platform parameters from BL2 to BL31.
+ * In release builds, it's not used.
+ */
+ assert(((unsigned long long)plat_params_from_bl2) ==
+ MARVELL_BL31_PLAT_PARAM_VAL);
+
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params != NULL) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+#endif
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+
+{
+ marvell_bl31_early_platform_setup((void *)arg0, arg1, arg2,
+ (void *)arg3);
+
+#ifdef USE_CCI
+ /*
+ * Initialize CCI for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ plat_marvell_interconnect_init();
+
+ /*
+ * Enable CCI coherency for the primary CPU's cluster.
+ * Platform specific PSCI code will enable coherency for other
+ * clusters.
+ */
+ plat_marvell_interconnect_enter_coherency();
+#endif
+}
+
+/*****************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ *****************************************************************************
+ */
+void marvell_bl31_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ plat_marvell_gic_driver_init();
+ plat_marvell_gic_init();
+
+ /* For Armada-8k-plus family, the SoC includes more than
+ * a single AP die, but the default die that boots is AP #0.
+ * For other families there is only one die (#0).
+ * Initialize psci arch from die 0
+ */
+ marvell_psci_arch_init(0);
+}
+
+/*****************************************************************************
+ * Perform any BL31 platform runtime setup prior to BL31 exit common to ARM
+ * standard platforms
+ *****************************************************************************
+ */
+void marvell_bl31_plat_runtime_setup(void)
+{
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+
+ /* Initialize the runtime console */
+ marvell_console_runtime_init();
+}
+
+void bl31_platform_setup(void)
+{
+ marvell_bl31_platform_setup();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ marvell_bl31_plat_runtime_setup();
+}
+
+/*****************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ *****************************************************************************
+ */
+void marvell_bl31_plat_arch_setup(void)
+{
+ marvell_setup_page_tables(BL31_BASE,
+ BL31_END - BL31_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+
+#if BL31_CACHE_DISABLE
+ enable_mmu_el3(DISABLE_DCACHE);
+ INFO("Cache is disabled in BL3\n");
+#else
+ enable_mmu_el3(0);
+#endif
+}
+
+void bl31_plat_arch_setup(void)
+{
+ marvell_bl31_plat_arch_setup();
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return PLAT_REF_CLK_IN_HZ;
+}
diff --git a/plat/marvell/armada/common/marvell_cci.c b/plat/marvell/armada/common/marvell_cci.c
new file mode 100644
index 0000000..80351ae
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_cci.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <drivers/arm/cci.h>
+
+#include <plat_marvell.h>
+
+static const int cci_map[] = {
+ PLAT_MARVELL_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_MARVELL_CCI_CLUSTER1_SL_IFACE_IX
+};
+
+/****************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way ARM CCI driver is initialised and used.
+ ****************************************************************************
+ */
+#pragma weak plat_marvell_interconnect_init
+#pragma weak plat_marvell_interconnect_enter_coherency
+#pragma weak plat_marvell_interconnect_exit_coherency
+
+
+/****************************************************************************
+ * Helper function to initialize ARM CCI driver.
+ ****************************************************************************
+ */
+void plat_marvell_interconnect_init(void)
+{
+ cci_init(PLAT_MARVELL_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+}
+
+/****************************************************************************
+ * Helper function to place current master into coherency
+ ****************************************************************************
+ */
+void plat_marvell_interconnect_enter_coherency(void)
+{
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/****************************************************************************
+ * Helper function to remove current master from coherency
+ ****************************************************************************
+ */
+void plat_marvell_interconnect_exit_coherency(void)
+{
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/marvell/armada/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk
new file mode 100644
index 0000000..f0e6edf
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_common.mk
@@ -0,0 +1,99 @@
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+
+MARVELL_PLAT_BASE := plat/marvell/armada
+MARVELL_PLAT_INCLUDE_BASE := include/plat/marvell/armada
+
+SEPARATE_CODE_AND_RODATA := 1
+
+# flag to switch from PLL to ARO
+ARO_ENABLE := 0
+$(eval $(call add_define,ARO_ENABLE))
+
+# Convert LLC to secure SRAM
+LLC_SRAM := 0
+$(eval $(call add_define,LLC_SRAM))
+
+# Enable/Disable LLC
+LLC_ENABLE := 1
+$(eval $(call add_define,LLC_ENABLE))
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES += -I$(MARVELL_PLAT_INCLUDE_BASE)/common \
+ -I$(MARVELL_PLAT_INCLUDE_BASE)/common/aarch64
+
+
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \
+ $(MARVELL_PLAT_BASE)/common/aarch64/marvell_common.c \
+ $(MARVELL_PLAT_BASE)/common/aarch64/marvell_helpers.S \
+ $(MARVELL_COMMON_BASE)/marvell_console.c
+
+BL1_SOURCES += drivers/delay_timer/delay_timer.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ $(MARVELL_PLAT_BASE)/common/marvell_bl1_setup.c \
+ $(MARVELL_PLAT_BASE)/common/marvell_io_storage.c \
+ $(MARVELL_PLAT_BASE)/common/plat_delay_timer.c
+
+ifdef EL3_PAYLOAD_BASE
+# Need the arm_program_trusted_mailbox() function to release secondary CPUs from
+# their holding pen
+endif
+
+BL2_SOURCES += drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ common/desc_image_load.c \
+ $(MARVELL_PLAT_BASE)/common/marvell_bl2_setup.c \
+ $(MARVELL_PLAT_BASE)/common/marvell_io_storage.c \
+ $(MARVELL_PLAT_BASE)/common/aarch64/marvell_bl2_mem_params_desc.c \
+ $(MARVELL_PLAT_BASE)/common/marvell_image_load.c
+
+ifeq (${SPD},opteed)
+PLAT_INCLUDES += -Iinclude/lib
+BL2_SOURCES += lib/optee/optee_utils.c
+endif
+
+BL31_SOURCES += $(MARVELL_PLAT_BASE)/common/marvell_bl31_setup.c \
+ $(MARVELL_PLAT_BASE)/common/marvell_pm.c \
+ $(MARVELL_PLAT_BASE)/common/marvell_topology.c \
+ plat/common/plat_psci_common.c \
+ $(MARVELL_PLAT_BASE)/common/plat_delay_timer.c \
+ drivers/delay_timer/delay_timer.c
+
+# PSCI functionality
+$(eval $(call add_define,CONFIG_ARM64))
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
+# MSS (SCP) build
+ifeq (${MSS_SUPPORT}, 1)
+include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk
+endif
+
+$(BUILD_PLAT)/$(BOOT_IMAGE): $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(FIP_NAME)
+ $(if $(shell find $(BUILD_PLAT)/bl1.bin -type f -size +128k),$(error "Image '$(BUILD_PLAT)/bl1.bin' is bigger than 128kB"))
+ @cp $(BUILD_PLAT)/bl1.bin $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+ @truncate -s %128K $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+ @cat $(BUILD_PLAT)/$(FIP_NAME) >> $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+ @truncate -s %4 $(BUILD_PLAT)/$(BOOT_IMAGE) || { rm -f $(BUILD_PLAT)/$(BOOT_IMAGE); false; }
+ @$(ECHO_BLANK_LINE)
+ @echo "Built $@ successfully"
+ @$(ECHO_BLANK_LINE)
+
+.PHONY: mrvl_bootimage
+mrvl_bootimage: $(BUILD_PLAT)/$(BOOT_IMAGE)
+
+.PHONY: mrvl_flash
+mrvl_flash: $(BUILD_PLAT)/$(FLASH_IMAGE)
diff --git a/plat/marvell/armada/common/marvell_console.c b/plat/marvell/armada/common/marvell_console.c
new file mode 100644
index 0000000..ef54bff
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_console.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/console.h>
+
+#include <plat_marvell.h>
+
+#ifdef PLAT_a3700
+#include <drivers/marvell/uart/a3700_console.h>
+#define PLAT_MARVELL_UART_CLK_IN_HZ (get_ref_clk() * 1000000)
+#define console_marvell_register console_a3700_register
+#else
+#include <drivers/ti/uart/uart_16550.h>
+#define console_marvell_register console_16550_register
+#endif
+
+static console_t marvell_boot_console;
+static console_t marvell_runtime_console;
+
+/*******************************************************************************
+ * Functions that set up the console
+ ******************************************************************************/
+
+/* Initialize the console to provide early debug support */
+void marvell_console_boot_init(void)
+{
+ int rc =
+ console_marvell_register(PLAT_MARVELL_UART_BASE,
+ PLAT_MARVELL_UART_CLK_IN_HZ,
+ MARVELL_CONSOLE_BAUDRATE,
+ &marvell_boot_console);
+ if (rc == 0) {
+ /*
+ * The crash console doesn't use the multi console API, it uses
+ * the core console functions directly. It is safe to call panic
+ * and let it print debug information.
+ */
+ panic();
+ }
+
+ console_set_scope(&marvell_boot_console, CONSOLE_FLAG_BOOT);
+}
+
+void marvell_console_boot_end(void)
+{
+ console_flush();
+
+ (void)console_unregister(&marvell_boot_console);
+}
+
+/* Initialize the runtime console */
+void marvell_console_runtime_init(void)
+{
+ int rc =
+ console_marvell_register(PLAT_MARVELL_UART_BASE,
+ PLAT_MARVELL_UART_CLK_IN_HZ,
+ MARVELL_CONSOLE_BAUDRATE,
+ &marvell_runtime_console);
+ if (rc == 0)
+ panic();
+
+ console_set_scope(&marvell_runtime_console, CONSOLE_FLAG_RUNTIME);
+}
+
+void marvell_console_runtime_end(void)
+{
+ console_flush();
+
+ (void)console_unregister(&marvell_runtime_console);
+}
diff --git a/plat/marvell/armada/common/marvell_ddr_info.c b/plat/marvell/armada/common/marvell_ddr_info.c
new file mode 100644
index 0000000..7340996
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_ddr_info.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <ddr_info.h>
+
+#define DRAM_CH0_MMAP_LOW_REG(iface, cs, base) \
+ (base + DRAM_CH0_MMAP_LOW_OFFSET + (iface) * 0x10000 + (cs) * 0x8)
+#define DRAM_CH0_MMAP_HIGH_REG(iface, cs, base) \
+ (DRAM_CH0_MMAP_LOW_REG(iface, cs, base) + 4)
+#define DRAM_CS_VALID_ENABLED_MASK 0x1
+#define DRAM_AREA_LENGTH_OFFS 16
+#define DRAM_AREA_LENGTH_MASK (0x1f << DRAM_AREA_LENGTH_OFFS)
+#define DRAM_START_ADDRESS_L_OFFS 23
+#define DRAM_START_ADDRESS_L_MASK \
+ (0x1ff << DRAM_START_ADDRESS_L_OFFS)
+#define DRAM_START_ADDR_HTOL_OFFS 32
+
+#define DRAM_MAX_CS_NUM 2
+
+#define DRAM_CS_ENABLED(iface, cs, base) \
+ (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \
+ DRAM_CS_VALID_ENABLED_MASK)
+#define GET_DRAM_REGION_SIZE_CODE(iface, cs, base) \
+ (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \
+ DRAM_AREA_LENGTH_MASK) >> DRAM_AREA_LENGTH_OFFS
+
+/* Mapping between DDR area length and real DDR size is specific and looks like
+ * bellow:
+ * 0 => 384 MB
+ * 1 => 768 MB
+ * 2 => 1536 MB
+ * 3 => 3 GB
+ * 4 => 6 GB
+ *
+ * 7 => 8 MB
+ * 8 => 16 MB
+ * 9 => 32 MB
+ * 10 => 64 MB
+ * 11 => 128 MB
+ * 12 => 256 MB
+ * 13 => 512 MB
+ * 14 => 1 GB
+ * 15 => 2 GB
+ * 16 => 4 GB
+ * 17 => 8 GB
+ * 18 => 16 GB
+ * 19 => 32 GB
+ * 20 => 64 GB
+ * 21 => 128 GB
+ * 22 => 256 GB
+ * 23 => 512 GB
+ * 24 => 1 TB
+ * 25 => 2 TB
+ * 26 => 4 TB
+ *
+ * to calculate real size we need to use two different formulas:
+ * -- GET_DRAM_REGION_SIZE_ODD for values 0-4 (DRAM_REGION_SIZE_ODD)
+ * -- GET_DRAM_REGION_SIZE_EVEN for values 7-26 (DRAM_REGION_SIZE_EVEN)
+ * using mentioned formulas we cover whole mapping between "Area length" value
+ * and real size (see above mapping).
+ */
+#define DRAM_REGION_SIZE_EVEN(C) (((C) >= 7) && ((C) <= 26))
+#define GET_DRAM_REGION_SIZE_EVEN(C) ((uint64_t)1 << ((C) + 16))
+#define DRAM_REGION_SIZE_ODD(C) ((C) <= 4)
+#define GET_DRAM_REGION_SIZE_ODD(C) ((uint64_t)0x18000000 << (C))
+
+
+uint64_t mvebu_get_dram_size(uint64_t ap_base_addr)
+{
+ uint64_t mem_size = 0;
+ uint8_t region_code;
+ uint8_t cs, iface;
+
+ for (iface = 0; iface < DRAM_MAX_IFACE; iface++) {
+ for (cs = 0; cs < DRAM_MAX_CS_NUM; cs++) {
+
+ /* Exit loop on first disabled DRAM CS */
+ if (!DRAM_CS_ENABLED(iface, cs, ap_base_addr))
+ break;
+
+ /* Decode area length for current CS
+ * from register value
+ */
+ region_code =
+ GET_DRAM_REGION_SIZE_CODE(iface, cs,
+ ap_base_addr);
+
+ if (DRAM_REGION_SIZE_EVEN(region_code)) {
+ mem_size +=
+ GET_DRAM_REGION_SIZE_EVEN(region_code);
+ } else if (DRAM_REGION_SIZE_ODD(region_code)) {
+ mem_size +=
+ GET_DRAM_REGION_SIZE_ODD(region_code);
+ } else {
+ WARN("%s: Invalid mem region (0x%x) CS#%d\n",
+ __func__, region_code, cs);
+ return 0;
+ }
+ }
+ }
+
+ return mem_size;
+}
diff --git a/plat/marvell/armada/common/marvell_gicv2.c b/plat/marvell/armada/common/marvell_gicv2.c
new file mode 100644
index 0000000..2505c9f
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_gicv2.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <platform_def.h>
+
+#include <bl31/interrupt_mgmt.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <plat_marvell.h>
+
+/*
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv2 driver is initialised and used.
+ */
+#pragma weak plat_marvell_gic_driver_init
+#pragma weak plat_marvell_gic_init
+
+#define A7K8K_PIC_CAUSE_REG 0xf03f0100
+#define A7K8K_PIC0_MASK_REG 0xf03f0108
+
+#define A7K8K_PIC_PMUOF_IRQ_MASK (1 << 17)
+
+#define A7K8K_PIC_MAX_IRQS 32
+#define A7K8K_PIC_MAX_IRQ_MASK ((1UL << A7K8K_PIC_MAX_IRQS) - 1)
+
+#define A7K8K_ODMIN_SET_REG 0xf0300040
+#define A7K8K_ODMI_PMU_IRQ(idx) ((2 + idx) << 12)
+
+#define A7K8K_ODMI_PMU_GIC_IRQ(idx) (130 + idx)
+
+static DEFINE_BAKERY_LOCK(a7k8k_irq_lock);
+
+/*
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ */
+static const interrupt_prop_t marvell_interrupt_props[] = {
+ PLAT_MARVELL_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ PLAT_MARVELL_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+/*
+ * Ideally `marvell_gic_data` structure definition should be a `const` but it is
+ * kept as modifiable for overwriting with different GICD and GICC base when
+ * running on FVP with VE memory map.
+ */
+static gicv2_driver_data_t marvell_gic_data = {
+ .gicd_base = PLAT_MARVELL_GICD_BASE,
+ .gicc_base = PLAT_MARVELL_GICC_BASE,
+ .interrupt_props = marvell_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/*
+ * ARM common helper to initialize the GICv2 only driver.
+ */
+void plat_marvell_gic_driver_init(void)
+{
+ gicv2_driver_init(&marvell_gic_data);
+}
+
+static uint64_t a7k8k_pmu_interrupt_handler(uint32_t id,
+ uint32_t flags,
+ void *handle,
+ void *cookie)
+{
+ unsigned int idx = plat_my_core_pos();
+ uint32_t irq;
+
+ bakery_lock_get(&a7k8k_irq_lock);
+
+ /* Acknowledge IRQ */
+ irq = plat_ic_acknowledge_interrupt();
+
+ plat_ic_end_of_interrupt(irq);
+
+ if (irq != MARVELL_IRQ_PIC0) {
+ bakery_lock_release(&a7k8k_irq_lock);
+ return 0;
+ }
+
+ /* Acknowledge PMU overflow IRQ in PIC0 */
+ mmio_setbits_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
+
+ /* Trigger ODMI Frame IRQ */
+ mmio_write_32(A7K8K_ODMIN_SET_REG, A7K8K_ODMI_PMU_IRQ(idx));
+
+ bakery_lock_release(&a7k8k_irq_lock);
+
+ return 0;
+}
+
+void mvebu_pmu_interrupt_enable(void)
+{
+ unsigned int idx;
+ uint32_t flags;
+ int32_t rc;
+
+ /* Reset PIC */
+ mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK);
+ /* Unmask PMU overflow IRQ in PIC0 */
+ mmio_clrbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
+
+ /* Configure ODMI Frame IRQs as edge triggered */
+ for (idx = 0; idx < PLATFORM_CORE_COUNT; idx++)
+ gicv2_interrupt_set_cfg(A7K8K_ODMI_PMU_GIC_IRQ(idx),
+ GIC_INTR_CFG_EDGE);
+
+ /*
+ * Register IRQ handler as INTR_TYPE_S_EL1 as its the only valid type
+ * for GICv2 in ARM-TF.
+ */
+ flags = 0U;
+ set_interrupt_rm_flag((flags), (NON_SECURE));
+ rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
+ a7k8k_pmu_interrupt_handler,
+ flags);
+ if (rc != 0)
+ panic();
+}
+
+void mvebu_pmu_interrupt_disable(void)
+{
+ /* Reset PIC */
+ mmio_write_32(A7K8K_PIC_CAUSE_REG, A7K8K_PIC_MAX_IRQ_MASK);
+ /* Mask PMU overflow IRQ in PIC0 */
+ mmio_setbits_32(A7K8K_PIC0_MASK_REG, A7K8K_PIC_PMUOF_IRQ_MASK);
+}
+
+void plat_marvell_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
diff --git a/plat/marvell/armada/common/marvell_gicv3.c b/plat/marvell/armada/common/marvell_gicv3.c
new file mode 100644
index 0000000..0bd5545
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_gicv3.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <plat/common/platform.h>
+
+#include <marvell_def.h>
+#include <plat_marvell.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ ******************************************************************************
+ */
+#pragma weak plat_marvell_gic_driver_init
+#pragma weak plat_marvell_gic_init
+#pragma weak plat_marvell_gic_cpuif_enable
+#pragma weak plat_marvell_gic_cpuif_disable
+#pragma weak plat_marvell_gic_pcpu_init
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t marvell_interrupt_props[] = {
+ PLAT_MARVELL_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_MARVELL_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * We save and restore the GICv3 context on system suspend. Allocate the
+ * data in the designated EL3 Secure carve-out memory
+ */
+static gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram");
+static gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram");
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ * - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int marvell_gicv3_mpidr_hash(u_register_t mpidr)
+{
+ mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+ return plat_marvell_calc_core_pos(mpidr);
+}
+
+const gicv3_driver_data_t marvell_gic_data = {
+ .gicd_base = PLAT_MARVELL_GICD_BASE,
+ .gicr_base = PLAT_MARVELL_GICR_BASE,
+ .interrupt_props = marvell_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(marvell_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = marvell_gicv3_mpidr_hash
+};
+
+void plat_marvell_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if IMAGE_BL31
+ gicv3_driver_init(&marvell_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * Marvell common helper to initialize the GIC. Only invoked by BL31
+ ******************************************************************************
+ */
+void plat_marvell_gic_init(void)
+{
+ /* Initialize GIC-600 Multi Chip feature,
+ * only if the maximum number of north bridges
+ * is more than 1 - otherwise no need for multi
+ * chip feature initialization
+ */
+#if (PLAT_MARVELL_NORTHB_COUNT > 1)
+ if (gic600_multi_chip_init())
+ ERROR("GIC-600 Multi Chip initialization failed\n");
+#endif
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to enable the GIC CPU interface
+ ******************************************************************************
+ */
+void plat_marvell_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to disable the GIC CPU interface
+ ******************************************************************************
+ */
+void plat_marvell_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to init. the per-cpu redistributor interface in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Marvell common helper to save SPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_save(void)
+{
+
+ /*
+ * If an ITS is available, save its context before
+ * the Redistributor using:
+ * gicv3_its_save_disable(gits_base, &its_ctx[i])
+ * Additionally, an implementation-defined sequence may
+ * be required to save the whole ITS state.
+ */
+
+ /*
+ * Save the GIC Redistributors and ITS contexts before the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to save the context of the CPU that is issuing
+ * the SYSTEM SUSPEND call, i.e. the current CPU.
+ */
+ gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+
+ /* Save the GIC Distributor context */
+ gicv3_distif_save(&dist_ctx);
+
+ /*
+ * From here, all the components of the GIC can be safely powered down
+ * as long as there is an alternate way to handle wakeup interrupt
+ * sources.
+ */
+}
+
+/******************************************************************************
+ * Marvell common helper to restore SPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_restore(void)
+{
+ /* Restore the GIC Distributor context */
+ gicv3_distif_init_restore(&dist_ctx);
+
+ /*
+ * Restore the GIC Redistributor and ITS contexts after the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to restore the context of the CPU that issued
+ * the SYSTEM SUSPEND call.
+ */
+ gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+
+ /*
+ * If an ITS is available, restore its context after
+ * the Redistributor using:
+ * gicv3_its_restore(gits_base, &its_ctx[i])
+ * An implementation-defined sequence may be required to
+ * restore the whole ITS state. The ITS must also be
+ * re-enabled after this sequence has been executed.
+ */
+}
+
+/******************************************************************************
+ * Marvell common helper to save per-cpu PPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_pcpu_save(void)
+{
+ gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+}
+
+/******************************************************************************
+ * Marvell common helper to restore per-cpu PPI irq states in GICv3
+ ******************************************************************************
+ */
+void plat_marvell_gic_irq_pcpu_restore(void)
+{
+ gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+}
diff --git a/plat/marvell/armada/common/marvell_image_load.c b/plat/marvell/armada/common/marvell_image_load.c
new file mode 100644
index 0000000..be16b08
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_image_load.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/marvell/armada/common/marvell_io_storage.c b/plat/marvell/armada/common/marvell_io_storage.c
new file mode 100644
index 0000000..2627ba4
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_io_storage.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <tools_share/firmware_image_package.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+ .offset = PLAT_MARVELL_FIP_BASE,
+ .length = PLAT_MARVELL_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t scp_bl2_uuid_spec = {
+ .uuid = UUID_SCP_FIRMWARE_SCP_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, Marvell platforms load images from the FIP */
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [SCP_BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+};
+
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_marvell_io_setup
+#pragma weak plat_marvell_get_alt_image_source
+
+
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+
+static int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+
+void marvell_io_setup(void)
+{
+ int io_result;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+ assert(io_result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)io_result;
+}
+
+void plat_marvell_io_setup(void)
+{
+ marvell_io_setup();
+}
+
+int plat_marvell_get_alt_image_source(
+ unsigned int image_id __attribute__((unused)),
+ uintptr_t *dev_handle __attribute__((unused)),
+ uintptr_t *image_spec __attribute__((unused)))
+{
+ /* By default do not try an alternative */
+ return -ENOENT;
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ } else {
+ VERBOSE("Trying alternative IO\n");
+ result = plat_marvell_get_alt_image_source(image_id, dev_handle,
+ image_spec);
+ }
+
+ return result;
+}
+
+/*
+ * See if a Firmware Image Package is available,
+ * by checking if TOC is valid or not.
+ */
+int marvell_io_is_toc_valid(void)
+{
+ int result;
+
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+
+ return result == 0;
+}
diff --git a/plat/marvell/armada/common/marvell_pm.c b/plat/marvell/armada/common/marvell_pm.c
new file mode 100644
index 0000000..3c675b2
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_pm.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+#include <marvell_pm.h>
+
+/* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */
+extern const plat_psci_ops_t plat_arm_psci_pm_ops;
+
+/*****************************************************************************
+ * Private function to program the mailbox for a cpu before it is released
+ * from reset. This function assumes that the mail box base is within
+ * the MARVELL_SHARED_RAM region
+ *****************************************************************************
+ */
+void marvell_program_mailbox(uintptr_t address)
+{
+ uintptr_t *mailbox = (void *)PLAT_MARVELL_MAILBOX_BASE;
+
+ /*
+ * Ensure that the PLAT_MARVELL_MAILBOX_BASE is within
+ * MARVELL_SHARED_RAM region.
+ */
+ assert((PLAT_MARVELL_MAILBOX_BASE >= MARVELL_SHARED_RAM_BASE) &&
+ ((PLAT_MARVELL_MAILBOX_BASE + sizeof(*mailbox)) <=
+ (MARVELL_SHARED_RAM_BASE + MARVELL_SHARED_RAM_SIZE)));
+
+ mailbox[MBOX_IDX_MAGIC] = MVEBU_MAILBOX_MAGIC_NUM;
+ mailbox[MBOX_IDX_SEC_ADDR] = address;
+
+ /* Flush data cache if the mail box shared RAM is cached */
+#if PLAT_MARVELL_SHARED_RAM_CACHED
+ flush_dcache_range((uintptr_t)PLAT_MARVELL_MAILBOX_BASE +
+ 8 * MBOX_IDX_MAGIC,
+ 2 * sizeof(uint64_t));
+#endif
+}
+
+/*****************************************************************************
+ * The ARM Standard platform definition of platform porting API
+ * `plat_setup_psci_ops`.
+ *****************************************************************************
+ */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_arm_psci_pm_ops;
+
+ /* Setup mailbox with entry point. */
+ marvell_program_mailbox(sec_entrypoint);
+ return 0;
+}
diff --git a/plat/marvell/armada/common/marvell_topology.c b/plat/marvell/armada/common/marvell_topology.c
new file mode 100644
index 0000000..a40ff6f
--- /dev/null
+++ b/plat/marvell/armada/common/marvell_topology.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <plat_marvell.h>
+
+/* The power domain tree descriptor */
+unsigned char marvell_power_domain_tree_desc[PLAT_MARVELL_CLUSTER_COUNT + 1];
+
+/*****************************************************************************
+ * This function dynamically constructs the topology according to
+ * PLAT_MARVELL_CLUSTER_COUNT and returns it.
+ *****************************************************************************
+ */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ int i;
+
+ /*
+ * The power domain tree does not have a single system level power
+ * domain i.e. a single root node. The first entry in the power domain
+ * descriptor specifies the number of power domains at the highest power
+ * level.
+ * For Marvell Platform this is the number of cluster power domains.
+ */
+ marvell_power_domain_tree_desc[0] = PLAT_MARVELL_CLUSTER_COUNT;
+
+ for (i = 0; i < PLAT_MARVELL_CLUSTER_COUNT; i++)
+ marvell_power_domain_tree_desc[i + 1] =
+ PLAT_MARVELL_CLUSTER_CORE_COUNT;
+
+ return marvell_power_domain_tree_desc;
+}
+
+/*****************************************************************************
+ * This function validates an MPIDR by checking whether it falls within the
+ * acceptable bounds. An error code (-1) is returned if an incorrect mpidr
+ * is passed.
+ *****************************************************************************
+ */
+int marvell_check_mpidr(u_register_t mpidr)
+{
+ unsigned int nb_id, cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK |
+ MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT))
+ return -1;
+
+ /* Get north bridge ID */
+ nb_id = MPIDR_AFFLVL3_VAL(mpidr);
+ cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (nb_id >= PLAT_MARVELL_CLUSTER_COUNT)
+ return -1;
+
+ if (cluster_id >= PLAT_MARVELL_CLUSTER_COUNT)
+ return -1;
+
+ if (cpu_id >= PLAT_MARVELL_CLUSTER_CORE_COUNT)
+ return -1;
+
+ return 0;
+}
+
+/*****************************************************************************
+ * This function implements a part of the critical interface between the PSCI
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ *****************************************************************************
+ */
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ if (marvell_check_mpidr(mpidr) == -1)
+ return -1;
+
+ return plat_marvell_calc_core_pos(mpidr);
+}
diff --git a/plat/marvell/armada/common/mrvl_sip_svc.c b/plat/marvell/armada/common/mrvl_sip_svc.c
new file mode 100644
index 0000000..c4c5c0e
--- /dev/null
+++ b/plat/marvell/armada/common/mrvl_sip_svc.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/marvell/cache_llc.h>
+#include <drivers/marvell/mochi/ap_setup.h>
+#include <drivers/rambus/trng_ip_76.h>
+#include <lib/smccc.h>
+
+#include <marvell_plat_priv.h>
+#include <plat_marvell.h>
+
+#include "comphy/phy-comphy-cp110.h"
+#include "secure_dfx_access/dfx.h"
+#include "ddr_phy_access.h"
+#include <stdbool.h>
+
+/* #define DEBUG_COMPHY */
+#ifdef DEBUG_COMPHY
+#define debug(format...) NOTICE(format)
+#else
+#define debug(format, arg...)
+#endif
+
+/* Comphy related FID's */
+#define MV_SIP_COMPHY_POWER_ON 0x82000001
+#define MV_SIP_COMPHY_POWER_OFF 0x82000002
+#define MV_SIP_COMPHY_PLL_LOCK 0x82000003
+#define MV_SIP_COMPHY_XFI_TRAIN 0x82000004
+#define MV_SIP_COMPHY_DIG_RESET 0x82000005
+
+/* Miscellaneous FID's' */
+#define MV_SIP_DRAM_SIZE 0x82000010
+#define MV_SIP_LLC_ENABLE 0x82000011
+#define MV_SIP_PMU_IRQ_ENABLE 0x82000012
+#define MV_SIP_PMU_IRQ_DISABLE 0x82000013
+#define MV_SIP_DFX 0x82000014
+#define MV_SIP_DDR_PHY_WRITE 0x82000015
+#define MV_SIP_DDR_PHY_READ 0x82000016
+
+/* TRNG */
+#define MV_SIP_RNG_64 0xC200FF11
+
+#define MAX_LANE_NR 6
+#define MVEBU_COMPHY_OFFSET 0x441000
+#define MVEBU_CP_BASE_MASK (~0xffffff)
+
+/* Common PHY register */
+#define COMPHY_TRX_TRAIN_CTRL_REG_0_OFFS 0x120a2c
+
+/* This macro is used to identify COMPHY related calls from SMC function ID */
+#define is_comphy_fid(fid) \
+ ((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_DIG_RESET)
+
+_Bool is_cp_range_valid(u_register_t *addr)
+{
+ int cp_nr;
+
+ *addr &= MVEBU_CP_BASE_MASK;
+ for (cp_nr = 0; cp_nr < CP_NUM; cp_nr++) {
+ if (*addr == MVEBU_CP_REGS_BASE(cp_nr))
+ return true;
+ }
+
+ return false;
+}
+
+uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ u_register_t ret, read, x5 = x1;
+ int i;
+
+ debug("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx, x3 0x%lx\n",
+ __func__, smc_fid, x1, x2, x3);
+
+ if (is_comphy_fid(smc_fid)) {
+ /* validate address passed via x1 */
+ if (!is_cp_range_valid(&x1)) {
+ ERROR("%s: Wrong smc (0x%x) address: %lx\n",
+ __func__, smc_fid, x1);
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ x5 = x1 + COMPHY_TRX_TRAIN_CTRL_REG_0_OFFS;
+ x1 += MVEBU_COMPHY_OFFSET;
+
+ if (x2 >= MAX_LANE_NR) {
+ ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n",
+ __func__, smc_fid, x2);
+ SMC_RET1(handle, SMC_UNK);
+ }
+ }
+
+ switch (smc_fid) {
+
+ /* Comphy related FID's */
+ case MV_SIP_COMPHY_POWER_ON:
+ /* x1: comphy_base, x2: comphy_index, x3: comphy_mode */
+ ret = mvebu_cp110_comphy_power_on(x1, x2, x3, x5);
+ SMC_RET1(handle, ret);
+ case MV_SIP_COMPHY_POWER_OFF:
+ /* x1: comphy_base, x2: comphy_index */
+ ret = mvebu_cp110_comphy_power_off(x1, x2, x3);
+ SMC_RET1(handle, ret);
+ case MV_SIP_COMPHY_PLL_LOCK:
+ /* x1: comphy_base, x2: comphy_index */
+ ret = mvebu_cp110_comphy_is_pll_locked(x1, x2);
+ SMC_RET1(handle, ret);
+ case MV_SIP_COMPHY_XFI_TRAIN:
+ /* x1: comphy_base, x2: comphy_index */
+ ret = mvebu_cp110_comphy_xfi_rx_training(x1, x2);
+ SMC_RET1(handle, ret);
+ case MV_SIP_COMPHY_DIG_RESET:
+ /* x1: comphy_base, x2: comphy_index, x3: mode, x4: command */
+ ret = mvebu_cp110_comphy_digital_reset(x1, x2, x3, x4);
+ SMC_RET1(handle, ret);
+
+ /* Miscellaneous FID's' */
+ case MV_SIP_DRAM_SIZE:
+ ret = mvebu_get_dram_size(MVEBU_REGS_BASE);
+ SMC_RET1(handle, ret);
+ case MV_SIP_LLC_ENABLE:
+ for (i = 0; i < ap_get_count(); i++)
+ llc_runtime_enable(i);
+
+ SMC_RET1(handle, 0);
+#ifdef MVEBU_PMU_IRQ_WA
+ case MV_SIP_PMU_IRQ_ENABLE:
+ mvebu_pmu_interrupt_enable();
+ SMC_RET1(handle, 0);
+ case MV_SIP_PMU_IRQ_DISABLE:
+ mvebu_pmu_interrupt_disable();
+ SMC_RET1(handle, 0);
+#endif
+ case MV_SIP_DFX:
+ if (x1 >= MV_SIP_DFX_THERMAL_INIT &&
+ x1 <= MV_SIP_DFX_THERMAL_SEL_CHANNEL) {
+ ret = mvebu_dfx_thermal_handle(x1, &read, x2, x3);
+ SMC_RET2(handle, ret, read);
+ }
+ if (x1 >= MV_SIP_DFX_SREAD && x1 <= MV_SIP_DFX_SWRITE) {
+ ret = mvebu_dfx_misc_handle(x1, &read, x2, x3);
+ SMC_RET2(handle, ret, read);
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+ case MV_SIP_DDR_PHY_WRITE:
+ ret = mvebu_ddr_phy_write(x1, x2);
+ SMC_RET1(handle, ret);
+ case MV_SIP_DDR_PHY_READ:
+ read = 0;
+ ret = mvebu_ddr_phy_read(x1, (uint16_t *)&read);
+ SMC_RET2(handle, ret, read);
+ case MV_SIP_RNG_64:
+ if ((x1 % 2 + 1) > sizeof(read)/4) {
+ ERROR("%s: Maximum %ld random bytes per SMC call\n",
+ __func__, sizeof(read));
+ SMC_RET1(handle, SMC_UNK);
+ }
+ ret = eip76_rng_get_random((uint8_t *)&read, 4 * (x1 % 2 + 1));
+ SMC_RET2(handle, ret, read);
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ marvell_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ mrvl_sip_smc_handler
+);
diff --git a/plat/marvell/armada/common/mss/mss_common.mk b/plat/marvell/armada/common/mss/mss_common.mk
new file mode 100644
index 0000000..4ab4359
--- /dev/null
+++ b/plat/marvell/armada/common/mss/mss_common.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+
+PLAT_MARVELL := plat/marvell/armada
+MSS_SOURCE := $(PLAT_MARVELL)/common/mss
+
+BL2_SOURCES += $(MSS_SOURCE)/mss_scp_bootloader.c \
+ $(PLAT_MARVELL)/common/plat_delay_timer.c \
+ drivers/delay_timer/delay_timer.c \
+ $(MARVELL_DRV) \
+ $(BOARD_DIR)/board/marvell_plat_config.c
+
+BL31_SOURCES += $(MSS_SOURCE)/mss_ipc_drv.c
+
+PLAT_INCLUDES += -I$(MSS_SOURCE)
diff --git a/plat/marvell/armada/common/mss/mss_ipc_drv.c b/plat/marvell/armada/common/mss/mss_ipc_drv.c
new file mode 100644
index 0000000..70ccfa5
--- /dev/null
+++ b/plat/marvell/armada/common/mss/mss_ipc_drv.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <plat_marvell.h>
+#include <mss_ipc_drv.h>
+
+#define IPC_MSG_BASE_MASK MVEBU_REGS_BASE_MASK
+
+#define IPC_CH_NUM_OF_MSG (16)
+#define IPC_CH_MSG_IDX (-1)
+
+unsigned long mv_pm_ipc_msg_base;
+unsigned int mv_pm_ipc_queue_size;
+
+unsigned int msg_sync;
+int msg_index = IPC_CH_MSG_IDX;
+
+/******************************************************************************
+ * mss_pm_ipc_init
+ *
+ * DESCRIPTION: Initialize PM IPC infrastructure
+ ******************************************************************************
+ */
+int mv_pm_ipc_init(unsigned long ipc_control_addr)
+{
+ struct mss_pm_ipc_ctrl *ipc_control =
+ (struct mss_pm_ipc_ctrl *)ipc_control_addr;
+
+ /* Initialize PM IPC control block */
+ mv_pm_ipc_msg_base = ipc_control->msg_base_address |
+ IPC_MSG_BASE_MASK;
+ mv_pm_ipc_queue_size = ipc_control->queue_size;
+
+ return 0;
+}
+
+/******************************************************************************
+ * mv_pm_ipc_queue_addr_get
+ *
+ * DESCRIPTION: Returns the IPC queue address
+ ******************************************************************************
+ */
+unsigned int mv_pm_ipc_queue_addr_get(void)
+{
+ unsigned int addr;
+
+ inv_dcache_range((uint64_t)&msg_index, sizeof(msg_index));
+ msg_index = msg_index + 1;
+ if (msg_index >= IPC_CH_NUM_OF_MSG)
+ msg_index = 0;
+
+ addr = (unsigned int)(mv_pm_ipc_msg_base +
+ (msg_index * mv_pm_ipc_queue_size));
+
+ flush_dcache_range((uint64_t)&msg_index, sizeof(msg_index));
+
+ return addr;
+}
+
+/******************************************************************************
+ * mv_pm_ipc_msg_rx
+ *
+ * DESCRIPTION: Retrieve message from IPC channel
+ ******************************************************************************
+ */
+int mv_pm_ipc_msg_rx(unsigned int channel_id, struct mss_pm_ipc_msg *msg)
+{
+ unsigned int addr = mv_pm_ipc_queue_addr_get();
+
+ msg->msg_reply = mmio_read_32(addr + IPC_MSG_REPLY_LOC);
+
+ return 0;
+}
+
+/******************************************************************************
+ * mv_pm_ipc_msg_tx
+ *
+ * DESCRIPTION: Send message via IPC channel
+ ******************************************************************************
+ */
+int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int msg_id,
+ unsigned int cluster_power_state)
+{
+ unsigned int addr = mv_pm_ipc_queue_addr_get();
+
+ /* Validate the entry for message placed by the host is free */
+ if (mmio_read_32(addr + IPC_MSG_STATE_LOC) == IPC_MSG_FREE) {
+ inv_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync));
+ msg_sync = msg_sync + 1;
+ flush_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync));
+
+ mmio_write_32(addr + IPC_MSG_SYNC_ID_LOC, msg_sync);
+ mmio_write_32(addr + IPC_MSG_ID_LOC, msg_id);
+ mmio_write_32(addr + IPC_MSG_CPU_ID_LOC, channel_id);
+ mmio_write_32(addr + IPC_MSG_POWER_STATE_LOC,
+ cluster_power_state);
+ mmio_write_32(addr + IPC_MSG_STATE_LOC, IPC_MSG_OCCUPY);
+
+ } else {
+ ERROR("%s: FAILED\n", __func__);
+ }
+
+ return 0;
+}
diff --git a/plat/marvell/armada/common/mss/mss_ipc_drv.h b/plat/marvell/armada/common/mss/mss_ipc_drv.h
new file mode 100644
index 0000000..bcb4b2d
--- /dev/null
+++ b/plat/marvell/armada/common/mss/mss_ipc_drv.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MSS_IPC_DRV_H
+#define MSS_IPC_DRV_H
+
+#include <lib/psci/psci.h>
+
+#define MV_PM_FW_IPC_VERSION_MAGIC (0xCA530000) /* Do NOT change */
+/* Increament for each version */
+#define MV_PM_FW_IPC_VERSION_SEQ (0x00000001)
+#define MV_PM_FW_IPC_VERSION (MV_PM_FW_IPC_VERSION_MAGIC | \
+ MV_PM_FW_IPC_VERSION_SEQ)
+
+#define IPC_MSG_STATE_LOC (0x0)
+#define IPC_MSG_SYNC_ID_LOC (0x4)
+#define IPC_MSG_ID_LOC (0x8)
+#define IPC_MSG_RET_CH_ID_LOC (0xC)
+#define IPC_MSG_CPU_ID_LOC (0x10)
+#define IPC_MSG_CLUSTER_ID_LOC (0x14)
+#define IPC_MSG_SYSTEM_ID_LOC (0x18)
+#define IPC_MSG_POWER_STATE_LOC (0x1C)
+#define IPC_MSG_REPLY_LOC (0x20)
+#define IPC_MSG_RESERVED_LOC (0x24)
+
+/* IPC initialization state */
+enum mss_pm_ipc_init_state {
+ IPC_UN_INITIALIZED = 1,
+ IPC_INITIALIZED = 2
+};
+
+/* IPC queue direction */
+enum mss_pm_ipc_init_msg_dir {
+ IPC_MSG_TX = 0,
+ IPC_MSG_RX = 1
+};
+
+/* IPC message state */
+enum mss_pm_ipc_msg_state {
+ IPC_MSG_FREE = 1,
+ IPC_MSG_OCCUPY = 2
+
+};
+
+/* IPC control block */
+struct mss_pm_ipc_ctrl {
+ unsigned int ctrl_base_address;
+ unsigned int msg_base_address;
+ unsigned int num_of_channels;
+ unsigned int channel_size;
+ unsigned int queue_size;
+};
+
+/* IPC message types */
+enum mss_pm_msg_id {
+ PM_IPC_MSG_CPU_SUSPEND = 1,
+ PM_IPC_MSG_CPU_OFF = 2,
+ PM_IPC_MSG_CPU_ON = 3,
+ PM_IPC_MSG_SYSTEM_RESET = 4,
+ PM_IPC_MSG_SYSTEM_SUSPEND = 5,
+ PM_IPC_MAX_MSG
+};
+
+struct mss_pm_ipc_msg {
+ unsigned int msg_sync_id; /*
+ * Sync number, validate message
+ * reply corresponding to message
+ * received
+ */
+ unsigned int msg_id; /* Message Id */
+ unsigned int ret_channel_id; /* IPC channel reply */
+ unsigned int cpu_id; /* CPU Id */
+ unsigned int cluster_id; /* Cluster Id */
+ unsigned int system_id; /* System Id */
+ unsigned int power_state;
+ unsigned int msg_reply; /* Message reply */
+};
+
+/* IPC queue */
+struct mss_pm_ipc_queue {
+ unsigned int state;
+ struct mss_pm_ipc_msg msg;
+};
+
+/* IPC channel */
+struct mss_pm_ipc_ch {
+ struct mss_pm_ipc_queue *tx_queue;
+ struct mss_pm_ipc_queue *rx_queue;
+};
+
+/*****************************************************************************
+ * mv_pm_ipc_init
+ *
+ * DESCRIPTION: Initialize PM IPC infrastructure
+ *****************************************************************************
+ */
+int mv_pm_ipc_init(unsigned long ipc_control_addr);
+
+/*****************************************************************************
+ * mv_pm_ipc_msg_rx
+ *
+ * DESCRIPTION: Retrieve message from IPC channel
+ *****************************************************************************
+ */
+int mv_pm_ipc_msg_rx(unsigned int channel_id, struct mss_pm_ipc_msg *msg);
+
+/*****************************************************************************
+ * mv_pm_ipc_msg_tx
+ *
+ * DESCRIPTION: Send message via IPC channel
+ *****************************************************************************
+ */
+int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int msg_id,
+ unsigned int cluster_power_state);
+
+#endif /* MSS_IPC_DRV_H */
diff --git a/plat/marvell/armada/common/mss/mss_mem.h b/plat/marvell/armada/common/mss/mss_mem.h
new file mode 100644
index 0000000..5d68ac7
--- /dev/null
+++ b/plat/marvell/armada/common/mss/mss_mem.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MSS_MEM_H
+#define MSS_MEM_H
+
+/* MSS SRAM Memory base */
+#define MSS_SRAM_PM_CONTROL_BASE (MVEBU_REGS_BASE + 0x520000)
+
+enum mss_pm_ctrl_handshake {
+ MSS_UN_INITIALIZED = 0,
+ MSS_COMPATIBILITY_ERROR = 1,
+ MSS_ACKNOWLEDGMENT = 2,
+ HOST_ACKNOWLEDGMENT = 3
+};
+
+enum mss_pm_ctrl_rtos_env {
+ MSS_MULTI_PROCESS_ENV = 0,
+ MSS_SINGLE_PROCESS_ENV = 1,
+ MSS_MAX_PROCESS_ENV
+};
+
+struct mss_pm_ctrl_block {
+ /* This field is used to synchronize the Host
+ * and MSS initialization sequence
+ * Valid Values
+ * 0 - Un-Initialized
+ * 1 - Compatibility Error
+ * 2 - MSS Acknowledgment
+ * 3 - Host Acknowledgment
+ */
+ unsigned int handshake;
+
+ /*
+ * This field include Host IPC version. Once received by the MSS
+ * It will be compared to MSS IPC version and set MSS Acknowledge to
+ * "compatibility error" in case there is no match
+ */
+ unsigned int ipc_version;
+ unsigned int ipc_base_address;
+ unsigned int ipc_state;
+
+ /* Following fields defines firmware core architecture */
+ unsigned int num_of_cores;
+ unsigned int num_of_clusters;
+ unsigned int num_of_cores_per_cluster;
+
+ /* Following fields define pm trace debug base address */
+ unsigned int pm_trace_ctrl_base_address;
+ unsigned int pm_trace_info_base_address;
+ unsigned int pm_trace_info_core_size;
+
+ unsigned int ctrl_blk_size;
+};
+
+#endif /* MSS_MEM_H */
diff --git a/plat/marvell/armada/common/mss/mss_scp_bl2_format.h b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
new file mode 100644
index 0000000..90913b0
--- /dev/null
+++ b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MSS_SCP_BL2_FORMAT_H
+#define MSS_SCP_BL2_FORMAT_H
+
+#define MAX_NR_OF_FILES 8
+#define FILE_MAGIC 0xddd01ff
+#define HEADER_VERSION 0x1
+
+#define MSS_IDRAM_SIZE 0x10000 /* 64KB */
+#define MSS_SRAM_SIZE 0x8000 /* 32KB */
+
+/* Types definitions */
+typedef struct file_header {
+ /* Magic specific for concatenated file (used for validation) */
+ uint32_t magic;
+ uint32_t nr_of_imgs; /* Number of images concatenated */
+} file_header_t;
+
+/* Types definitions */
+enum cm3_t {
+ MSS_AP,
+ MSS_CP0,
+ MSS_CP1,
+ MSS_CP2,
+ MSS_CP3,
+ MG_CP0,
+ MG_CP1,
+ MG_CP2,
+};
+
+typedef struct img_header {
+ uint32_t type; /* CM3 type, can be one of cm3_t */
+ uint32_t length; /* Image length */
+ uint32_t version; /* For sanity checks and future
+ * extended functionality
+ */
+} img_header_t;
+
+#endif /* MSS_SCP_BL2_FORMAT_H */
diff --git a/plat/marvell/armada/common/mss/mss_scp_bootloader.c b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
new file mode 100644
index 0000000..fbede1b
--- /dev/null
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
+#include <lib/mmio.h>
+
+#include <plat_pm_trace.h>
+#include <mss_scp_bootloader.h>
+#include <mss_ipc_drv.h>
+#include <mss_mem.h>
+#include <mss_defs.h>
+#include <mss_scp_bl2_format.h>
+
+#define MSS_DMA_TIMEOUT 1000
+#define MSS_EXTERNAL_SPACE 0x50000000
+#define MSS_EXTERNAL_ADDR_MASK 0xfffffff
+#define MSS_INTERNAL_SPACE 0x40000000
+#define MSS_INTERNAL_ADDR_MASK 0x00ffffff
+
+#define DMA_SIZE 128
+
+#define MSS_HANDSHAKE_TIMEOUT 50
+
+static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
+{
+ int timeout = MSS_HANDSHAKE_TIMEOUT;
+
+ /* Wait for SCP to signal it's ready */
+ while ((mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT) &&
+ (timeout-- > 0))
+ mdelay(1);
+
+ if (mss_pm_crtl->handshake != MSS_ACKNOWLEDGMENT)
+ return -1;
+
+ mss_pm_crtl->handshake = HOST_ACKNOWLEDGMENT;
+
+ return 0;
+}
+
+static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
+ uintptr_t mss_regs)
+{
+ uint32_t i, loop_num, timeout;
+
+ /* load image to MSS RAM using DMA */
+ loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
+ for (i = 0; i < loop_num; i++) {
+ /* write source address */
+ mmio_write_32(MSS_DMA_SRCBR(mss_regs),
+ src_addr + (i * DMA_SIZE));
+ /* write destination address */
+ mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
+ /* make sure DMA data is ready before triggering it */
+ dsb();
+ /* set the DMA control register */
+ mmio_write_32(MSS_DMA_CTRLR(mss_regs),
+ ((MSS_DMA_CTRLR_REQ_SET <<
+ MSS_DMA_CTRLR_REQ_OFFSET) |
+ (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
+ /* Poll DMA_ACK at MSS_DMACTLR until it is ready */
+ timeout = MSS_DMA_TIMEOUT;
+ while (timeout > 0U) {
+ if (((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
+ MSS_DMA_CTRLR_ACK_OFFSET) &
+ MSS_DMA_CTRLR_ACK_MASK)
+ == MSS_DMA_CTRLR_ACK_READY) {
+ break;
+ }
+ udelay(50);
+ timeout--;
+ }
+ if (timeout == 0) {
+ ERROR("\nMSS DMA failed (timeout)\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int mss_image_load(uint32_t src_addr, uint32_t size,
+ uintptr_t mss_regs, uintptr_t sram)
+{
+ uint32_t chunks = 1; /* !sram case */
+ uint32_t chunk_num;
+ int ret;
+
+ /* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
+ if (size > MSS_IDRAM_SIZE) {
+ ERROR("image is too big to fit into MSS CM3 memory\n");
+ return 1;
+ }
+
+ /* The CPx MSS DMA cannot access DRAM directly in secure boot mode
+ * Copy the MSS FW image to MSS SRAM by the CPU first, then run
+ * MSS DMA for SRAM to IRAM copy
+ */
+ if (sram != 0) {
+ chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
+ }
+
+ NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
+ sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
+ for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
+ size_t chunk_size = size;
+ uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
+ (src_addr & MSS_EXTERNAL_ADDR_MASK);
+
+ if (sram != 0) {
+ uintptr_t chunk_source =
+ src_addr + MSS_SRAM_SIZE * chunk_num;
+
+ if (chunk_num != (size / MSS_SRAM_SIZE)) {
+ chunk_size = MSS_SRAM_SIZE;
+ } else {
+ chunk_size = size % MSS_SRAM_SIZE;
+ }
+
+ if (chunk_size == 0) {
+ break;
+ }
+
+ VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
+ chunk_num, sram, chunk_source, chunk_size);
+ memcpy((void *)sram, (void *)chunk_source, chunk_size);
+ dsb();
+ img_src = MSS_INTERNAL_SPACE |
+ (sram & MSS_INTERNAL_ADDR_MASK);
+ }
+
+ ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
+ if (ret != 0) {
+ ERROR("MSS FW chunk %d load failed\n", chunk_num);
+ return ret;
+ }
+ }
+
+ bl2_plat_configure_mss_windows(mss_regs);
+
+ if (sram != 0) {
+ /* Wipe the MSS SRAM after using it as copy buffer */
+ memset((void *)sram, 0, MSS_SRAM_SIZE);
+ NOTICE("CP MSS startup is postponed\n");
+ /* FW loaded, but CPU startup postponed until final CP setup */
+ mmio_write_32(sram, MSS_FW_READY_MAGIC);
+ dsb();
+ } else {
+ /* Release M3 from reset */
+ mmio_write_32(MSS_M3_RSTCR(mss_regs),
+ (MSS_M3_RSTCR_RST_OFF <<
+ MSS_M3_RSTCR_RST_OFFSET));
+ }
+
+ NOTICE("Done\n");
+
+ return 0;
+}
+
+/* Load image to MSS AP and do PM related initialization
+ * Note that this routine is different than other CM3 loading routines, because
+ * firmware for AP is dedicated for PM and therefore some additional PM
+ * initialization is required
+ */
+static int mss_ap_load_image(uintptr_t single_img,
+ uint32_t image_size, uint32_t ap_idx)
+{
+ volatile struct mss_pm_ctrl_block *mss_pm_crtl;
+ int ret;
+
+ /* TODO: add PM Control Info from platform */
+ mss_pm_crtl = (struct mss_pm_ctrl_block *)MSS_SRAM_PM_CONTROL_BASE;
+ mss_pm_crtl->ipc_version = MV_PM_FW_IPC_VERSION;
+ mss_pm_crtl->num_of_clusters = PLAT_MARVELL_CLUSTER_COUNT;
+ mss_pm_crtl->num_of_cores_per_cluster =
+ PLAT_MARVELL_CLUSTER_CORE_COUNT;
+ mss_pm_crtl->num_of_cores = PLAT_MARVELL_CLUSTER_COUNT *
+ PLAT_MARVELL_CLUSTER_CORE_COUNT;
+ mss_pm_crtl->pm_trace_ctrl_base_address = AP_MSS_ATF_CORE_CTRL_BASE;
+ mss_pm_crtl->pm_trace_info_base_address = AP_MSS_ATF_CORE_INFO_BASE;
+ mss_pm_crtl->pm_trace_info_core_size = AP_MSS_ATF_CORE_INFO_SIZE;
+ VERBOSE("MSS Control Block = 0x%x\n", MSS_SRAM_PM_CONTROL_BASE);
+ VERBOSE("mss_pm_crtl->ipc_version = 0x%x\n",
+ mss_pm_crtl->ipc_version);
+ VERBOSE("mss_pm_crtl->num_of_cores = 0x%x\n",
+ mss_pm_crtl->num_of_cores);
+ VERBOSE("mss_pm_crtl->num_of_clusters = 0x%x\n",
+ mss_pm_crtl->num_of_clusters);
+ VERBOSE("mss_pm_crtl->num_of_cores_per_cluster = 0x%x\n",
+ mss_pm_crtl->num_of_cores_per_cluster);
+ VERBOSE("mss_pm_crtl->pm_trace_ctrl_base_address = 0x%x\n",
+ mss_pm_crtl->pm_trace_ctrl_base_address);
+ VERBOSE("mss_pm_crtl->pm_trace_info_base_address = 0x%x\n",
+ mss_pm_crtl->pm_trace_info_base_address);
+ VERBOSE("mss_pm_crtl->pm_trace_info_core_size = 0x%x\n",
+ mss_pm_crtl->pm_trace_info_core_size);
+
+ /* TODO: add checksum to image */
+ VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n");
+
+ ret = mss_image_load(single_img, image_size,
+ bl2_plat_get_ap_mss_regs(ap_idx), 0);
+ if (ret != 0) {
+ ERROR("SCP Image load failed\n");
+ return -1;
+ }
+
+ /* check that the image was loaded successfully */
+ ret = mss_check_image_ready(mss_pm_crtl);
+ if (ret != 0)
+ NOTICE("SCP Image doesn't contain PM firmware\n");
+
+ return 0;
+}
+
+/* Load CM3 image (single_img) to CM3 pointed by cm3_type */
+static int load_img_to_cm3(enum cm3_t cm3_type,
+ uintptr_t single_img, uint32_t image_size)
+{
+ int ret, ap_idx, cp_index;
+ uint32_t ap_count = bl2_plat_get_ap_count();
+
+ switch (cm3_type) {
+ case MSS_AP:
+ for (ap_idx = 0; ap_idx < ap_count; ap_idx++) {
+ NOTICE("Load image to AP%d MSS\n", ap_idx);
+ ret = mss_ap_load_image(single_img, image_size, ap_idx);
+ if (ret != 0)
+ return ret;
+ }
+ break;
+ case MSS_CP0:
+ case MSS_CP1:
+ case MSS_CP2:
+ case MSS_CP3:
+ /* MSS_AP = 0
+ * MSS_CP1 = 1
+ * .
+ * .
+ * MSS_CP3 = 4
+ * Actual CP index is MSS_CPX - 1
+ */
+ cp_index = cm3_type - 1;
+ for (ap_idx = 0; ap_idx < ap_count; ap_idx++) {
+ /* Check if we should load this image
+ * according to number of CPs
+ */
+ if (bl2_plat_get_cp_count(ap_idx) <= cp_index) {
+ NOTICE("Skipping MSS CP%d related image\n",
+ cp_index);
+ break;
+ }
+
+ NOTICE("Load image to CP%d MSS AP%d\n",
+ cp_index, ap_idx);
+ ret = mss_image_load(single_img, image_size,
+ bl2_plat_get_cp_mss_regs(
+ ap_idx, cp_index),
+ bl2_plat_get_cp_mss_sram(
+ ap_idx, cp_index));
+ if (ret != 0) {
+ ERROR("SCP Image load failed\n");
+ return -1;
+ }
+ }
+ break;
+ case MG_CP0:
+ case MG_CP1:
+ case MG_CP2:
+ cp_index = cm3_type - MG_CP0;
+ if (bl2_plat_get_cp_count(0) <= cp_index) {
+ NOTICE("Skipping MG CP%d related image\n",
+ cp_index);
+ break;
+ }
+ NOTICE("Load image to CP%d MG\n", cp_index);
+ ret = mg_image_load(single_img, image_size, cp_index);
+ if (ret != 0) {
+ ERROR("SCP Image load failed\n");
+ return -1;
+ }
+ break;
+ default:
+ ERROR("SCP_BL2 wrong img format (cm3_type=%d)\n", cm3_type);
+ break;
+ }
+
+ return 0;
+}
+
+/* The Armada 8K has 5 service CPUs and Armada 7K has 3. Therefore it was
+ * required to provide a method for loading firmware to all of the service CPUs.
+ * To achieve that, the scp_bl2 image in fact is file containing up to 5
+ * concatenated firmwares and this routine splits concatenated image into single
+ * images dedicated for appropriate service CPU and then load them.
+ */
+static int split_and_load_bl2_image(void *image)
+{
+ file_header_t *file_hdr;
+ img_header_t *img_hdr;
+ uintptr_t single_img;
+ int i;
+
+ file_hdr = (file_header_t *)image;
+
+ if (file_hdr->magic != FILE_MAGIC) {
+ ERROR("SCP_BL2 wrong img format\n");
+ return -1;
+ }
+
+ if (file_hdr->nr_of_imgs > MAX_NR_OF_FILES) {
+ ERROR("SCP_BL2 concatenated image contains too many images\n");
+ return -1;
+ }
+
+ img_hdr = (img_header_t *)((uintptr_t)image + sizeof(file_header_t));
+ single_img = (uintptr_t)image + sizeof(file_header_t) +
+ sizeof(img_header_t) * file_hdr->nr_of_imgs;
+
+ NOTICE("SCP_BL2 contains %d concatenated images\n",
+ file_hdr->nr_of_imgs);
+ for (i = 0; i < file_hdr->nr_of_imgs; i++) {
+
+ /* Before loading make sanity check on header */
+ if (img_hdr->version != HEADER_VERSION) {
+ ERROR("Wrong header, img corrupted exiting\n");
+ return -1;
+ }
+
+ load_img_to_cm3(img_hdr->type, single_img, img_hdr->length);
+
+ /* Prepare offsets for next run */
+ single_img += img_hdr->length;
+ img_hdr++;
+ }
+
+ return 0;
+}
+
+int scp_bootloader_transfer(void *image, unsigned int image_size)
+{
+#ifdef SCP_BL2_BASE
+ assert((uintptr_t) image == SCP_BL2_BASE);
+#endif
+
+ VERBOSE("Concatenated img size %d\n", image_size);
+
+ if (image_size == 0) {
+ ERROR("SCP_BL2 image size can't be 0 (current size = 0x%x)\n",
+ image_size);
+ return -1;
+ }
+
+ if (split_and_load_bl2_image(image))
+ return -1;
+
+ return 0;
+}
diff --git a/plat/marvell/armada/common/mss/mss_scp_bootloader.h b/plat/marvell/armada/common/mss/mss_scp_bootloader.h
new file mode 100644
index 0000000..d65354a
--- /dev/null
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef MSS_SCP_BOOTLOADER_H
+#define MSS_SCP_BOOTLOADER_H
+
+int scp_bootloader_transfer(void *image, unsigned int image_size);
+uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx);
+uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx);
+uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx);
+uint32_t bl2_plat_get_cp_count(int ap_idx);
+uint32_t bl2_plat_get_ap_count(void);
+void bl2_plat_configure_mss_windows(uintptr_t mss_regs);
+int bl2_plat_mss_check_image_ready(void);
+
+#endif /* MSS_SCP_BOOTLOADER_H */
diff --git a/plat/marvell/armada/common/plat_delay_timer.c b/plat/marvell/armada/common/plat_delay_timer.c
new file mode 100644
index 0000000..2539752
--- /dev/null
+++ b/plat/marvell/armada/common/plat_delay_timer.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <drivers/delay_timer.h>
+
+#include <mvebu_def.h>
+
+#define SYS_COUNTER_FREQ_IN_MHZ (COUNTER_FREQUENCY/1000000)
+
+static uint32_t plat_get_timer_value(void)
+{
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. We apply bitwise NOT operator to the tick values returned
+ * by read_cntpct_el0() to simulate the down counter.
+ */
+ return (uint32_t)(~read_cntpct_el0());
+}
+
+static const timer_ops_t plat_timer_ops = {
+ .get_timer_value = plat_get_timer_value,
+ .clk_mult = 1,
+ .clk_div = SYS_COUNTER_FREQ_IN_MHZ
+};
+
+void plat_delay_timer_init(void)
+{
+ timer_init(&plat_timer_ops);
+}
diff --git a/plat/marvell/marvell.mk b/plat/marvell/marvell.mk
new file mode 100644
index 0000000..b6a2b99
--- /dev/null
+++ b/plat/marvell/marvell.mk
@@ -0,0 +1,21 @@
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+
+# Marvell images
+BOOT_IMAGE := boot-image.bin
+BOOT_ENC_IMAGE := boot-image-enc.bin
+FLASH_IMAGE := flash-image.bin
+
+# Make non-trusted image by default
+MARVELL_SECURE_BOOT := 0
+$(eval $(call add_define,MARVELL_SECURE_BOOT))
+
+# Enable compilation for Palladium emulation platform
+PALLADIUM := 0
+$(eval $(call add_define,PALLADIUM))
+
+# Set board to work with DDR 32bit
+DDR32 := 0
+$(eval $(call add_define,DDR32))
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
new file mode 100644
index 0000000..82ce07b
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/mentor/mi2cv.h>
+#include <lib/mmio.h>
+
+#include <mv_ddr_if.h>
+#include <mvebu_def.h>
+#include <plat_marvell.h>
+
+#define MVEBU_CP_MPP_CTRL37_OFFS 20
+#define MVEBU_CP_MPP_CTRL38_OFFS 24
+#define MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA 0x2
+#define MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA 0x2
+
+#define MVEBU_MPP_CTRL_MASK 0xf
+
+/*
+ * This struct provides the DRAM training code with
+ * the appropriate board DRAM configuration
+ */
+struct mv_ddr_iface dram_iface_ap0 = {
+ .ap_base = MVEBU_REGS_BASE_AP(0),
+ .state = MV_DDR_IFACE_NRDY,
+ .validation = MV_DDR_MEMORY_CHECK,
+ .sscg = SSCG_EN,
+ .id = 0,
+ .iface_base_addr = 0,
+ .tm = {
+ DEBUG_LEVEL_ERROR,
+ 0x1, /* active interfaces */
+ /* cs_mask, mirror, dqs_swap, ck_swap X subphys */
+ { { { {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0},
+ {0x1, 0x0, 0, 0} },
+ SPEED_BIN_DDR_2400T, /* speed_bin */
+ MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
+ MV_DDR_DIE_CAP_8GBIT, /* die capacity */
+ MV_DDR_FREQ_SAR, /* frequency */
+ 0, 0, /* cas_l, cas_wl */
+ MV_DDR_TEMP_LOW} }, /* temperature */
+#if DDR32
+ MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+#else
+ MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+#endif
+ MV_DDR_CFG_SPD, /* ddr configuration data src */
+ NOT_COMBINED, /* ddr twin-die combined*/
+ { {0} }, /* raw spd data */
+ {0}, /* timing parameters */
+ { /* electrical configuration */
+ { /* memory electrical configuration */
+ MV_DDR_RTT_NOM_PARK_RZQ_DISABLE, /* rtt_nom */
+ { /* rtt_park 1cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV4,
+ /* rtt_park 2cs */
+ MV_DDR_RTT_NOM_PARK_RZQ_DIV1
+ },
+ { /* rtt_wr 1cs */
+ MV_DDR_RTT_WR_DYN_ODT_OFF,
+ /* rtt_wr 2cs */
+ MV_DDR_RTT_WR_RZQ_DIV2
+ },
+ MV_DDR_DIC_RZQ_DIV7 /* dic */
+ },
+ { /* phy electrical configuration */
+ MV_DDR_OHM_30, /* data_drv_p */
+ MV_DDR_OHM_30, /* data_drv_n */
+ MV_DDR_OHM_30, /* ctrl_drv_p */
+ MV_DDR_OHM_30, /* ctrl_drv_n */
+ {
+ MV_DDR_OHM_60, /* odt_p 1cs */
+ MV_DDR_OHM_120 /* odt_p 2cs */
+ },
+ {
+ MV_DDR_OHM_60, /* odt_n 1cs */
+ MV_DDR_OHM_120 /* odt_n 2cs */
+ },
+ },
+ { /* mac electrical configuration */
+ MV_DDR_ODT_CFG_NORMAL, /* odtcfg_pattern */
+ MV_DDR_ODT_CFG_ALWAYS_ON,/* odtcfg_write */
+ MV_DDR_ODT_CFG_NORMAL /* odtcfg_read */
+ },
+ },
+ },
+};
+
+/* Pointer to the first DRAM interface in the system */
+struct mv_ddr_iface *ptr_iface = &dram_iface_ap0;
+
+struct mv_ddr_iface *mv_ddr_iface_get(void)
+{
+ /* Return current ddr interface */
+ return ptr_iface;
+}
+
+struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
+{
+ /* Return the board topology as defined in the board code */
+ return &ptr_iface->tm;
+}
+
+static void mpp_config(void)
+{
+ uintptr_t reg;
+ uint32_t val;
+
+ reg = MVEBU_CP_MPP_REGS(0, 4);
+ /* configure CP0 MPP 37 and 38 to i2c */
+ val = mmio_read_32(reg);
+ val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
+ val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA <<
+ MVEBU_CP_MPP_CTRL37_OFFS) |
+ (MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA <<
+ MVEBU_CP_MPP_CTRL38_OFFS);
+ mmio_write_32(reg, val);
+}
+
+/*
+ * This function may modify the default DRAM parameters
+ * based on information received from SPD or bootloader
+ * configuration located on non volatile storage
+ */
+void plat_marvell_dram_update_topology(void)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ INFO("Gathering DRAM information\n");
+
+ if (tm->cfg_src == MV_DDR_CFG_SPD) {
+ /* configure MPPs to enable i2c */
+ mpp_config();
+
+ /* initialize i2c */
+ i2c_init((void *)MVEBU_CP0_I2C_BASE);
+
+ /* select SPD memory page 0 to access DRAM configuration */
+ i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 0);
+
+ /* read data from spd */
+ i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
+ sizeof(tm->spd_data.all_bytes));
+ }
+}
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c b/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c
new file mode 100644
index 0000000..fbacf54
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <mvebu_def.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map_cp0[] = {
+ /* CP0 SPI1 CS0 Direct Mode access */
+ {0xe800, 0x2000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = amb_memory_map_cp0;
+ *size = ARRAY_SIZE(amb_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ case MVEBU_CP_REGS_BASE(2):
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#if (CP_COUNT > 1)
+ /* SB (MCi0) internal regs */
+ {0x00000000f4000000, 0x2000000, MCI_0_TID},
+#if (CP_COUNT > 2)
+ /* SB (MCi1) internal regs */
+ {0x00000000f6000000, 0x2000000, MCI_1_TID},
+#endif
+#endif
+#ifndef IMAGE_BLE
+ /* SB (MCi0) PCIe0-2 on CP1 */
+ {0x00000000e2000000, 0x3000000, MCI_0_TID},
+ /* SB (MCi1) PCIe0-2 on CP2 */
+ {0x00000000e5000000, 0x3000000, MCI_1_TID},
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+/* Global Control Register - window default target */
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ /*
+ * PIDI == iMCIP AP to SB internal MoChi connection.
+ * In other words CP0
+ */
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000e8000000, 0x2000000, RUNIT_TID},
+ /* PEX2_X1 window */
+ {0x00000000e1000000, 0x1000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000e0000000, 0x1000000, PEX1_TID},
+ /* PEX0_X4 window */
+ {0x00000000c0000000, 0x20000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+
+ /* PEX2_X1 window */
+ {0x00000000e4000000, 0x1000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000e3000000, 0x1000000, PEX1_TID},
+ /* PEX0_X4 window */
+ {0x00000000e2000000, 0x1000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp2[] = {
+
+ /* PEX2_X1 window */
+ {0x00000000e7000000, 0x1000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000e6000000, 0x1000000, PEX1_TID},
+ /* PEX0_X4 window */
+ {0x00000000e5000000, 0x1000000, PEX0_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = iob_memory_map_cp0;
+ *size = ARRAY_SIZE(iob_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = iob_memory_map_cp1;
+ *size = ARRAY_SIZE(iob_memory_map_cp1);
+ return 0;
+ case MVEBU_CP_REGS_BASE(2):
+ *win = iob_memory_map_cp2;
+ *size = ARRAY_SIZE(iob_memory_map_cp2);
+ return 0;
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = { /* IO window */
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x6000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000002000000000, 0x70e000000, IO_0_TID}, /* IO for CV-OS */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_get_skip_image_data(void)
+{
+ /* No recovery button on CN-9130 board? */
+ return NULL;
+}
+#endif
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h b/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h
new file mode 100644
index 0000000..6b55407
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __PHY_PORTING_LAYER_H
+#define __PHY_PORTING_LAYER_H
+
+
+#define MAX_LANE_NR 6
+#define XFI_PARAMS static const struct xfi_params
+
+
+XFI_PARAMS xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ /* AP0 */
+ {
+ /* CP 0 */
+ {
+ { 0 }, /* Comphy0 not relevant*/
+ { 0 }, /* Comphy1 not relevant*/
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c,
+ .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1,
+ .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1 }, /* Comphy2 */
+ { 0 }, /* Comphy3 not relevant*/
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c,
+ .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1,
+ .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1 }, /* Comphy4 */
+ { 0 }, /* Comphy5 not relevant*/
+ },
+#if CP_NUM > 1
+ /* CP 1 */
+ {
+ { 0 }, /* Comphy0 not relevant*/
+ { 0 }, /* Comphy1 not relevant*/
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c,
+ .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1,
+ .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1 }, /* Comphy2 */
+ { 0 }, /* Comphy3 not relevant*/
+ /* different from defaults */
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0xc,
+ .g1_emph = 0x5,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1,
+ .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1}, /* Comphy4 */
+ { 0 }, /* Comphy5 not relevant*/
+ },
+#if CP_NUM > 2
+ /* CP 2 */
+ {
+ { 0 }, /* Comphy0 not relevant*/
+ { 0 }, /* Comphy1 not relevant*/
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c,
+ .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1,
+ .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1 }, /* Comphy2 */
+ { 0 }, /* Comphy3 not relevant*/
+ { .g1_ffe_res_sel = 0x3, .g1_ffe_cap_sel = 0xf,
+ .align90 = 0x5f,
+ .g1_dfe_res = 0x2, .g1_amp = 0x1c,
+ .g1_emph = 0xe,
+ .g1_emph_en = 0x1, .g1_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x1,
+ .g1_tx_emph = 0x0, .g1_rx_selmuff = 0x1,
+ .g1_rx_selmufi = 0x0,
+ .g1_rx_selmupf = 0x2, .g1_rx_selmupi = 0x2,
+ .valid = 1 }, /* Comphy4 */
+ { 0 }, /* Comphy5 not relevant*/
+ },
+#endif
+#endif
+ },
+};
+
+#define SATA_PARAMS static const struct sata_params
+SATA_PARAMS sata_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = {
+ .g1_amp = 0x8, .g2_amp = 0xa,
+ .g3_amp = 0x1e,
+ .g1_emph = 0x1, .g2_emph = 0x2,
+ .g3_emph = 0xe,
+ .g1_emph_en = 0x1, .g2_emph_en = 0x1,
+ .g3_emph_en = 0x1,
+ .g1_tx_amp_adj = 0x1, .g2_tx_amp_adj = 0x1,
+ .g3_tx_amp_adj = 0x1,
+ .g1_tx_emph_en = 0x0, .g2_tx_emph_en = 0x0,
+ .g3_tx_emph_en = 0x0,
+ .g1_tx_emph = 0x1, .g2_tx_emph = 0x1,
+ .g3_tx_emph = 0x1,
+ .g3_dfe_res = 0x1, .g3_ffe_res_sel = 0x4,
+ .g3_ffe_cap_sel = 0xf,
+ .align90 = 0x61,
+ .g1_rx_selmuff = 0x3, .g2_rx_selmuff = 0x3,
+ .g3_rx_selmuff = 0x3,
+ .g1_rx_selmufi = 0x0, .g2_rx_selmufi = 0x0,
+ .g3_rx_selmufi = 0x3,
+ .g1_rx_selmupf = 0x1, .g2_rx_selmupf = 0x1,
+ .g3_rx_selmupf = 0x2,
+ .g1_rx_selmupi = 0x0, .g2_rx_selmupi = 0x0,
+ .g3_rx_selmupi = 0x2,
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT,
+ .valid = 0x1
+ },
+};
+
+static const struct usb_params
+ usb_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = {
+ [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = {
+ .polarity_invert = COMPHY_POLARITY_NO_INVERT
+ },
+};
+#endif /* __PHY_PORTING_LAYER_H */
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h b/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h
new file mode 100644
index 0000000..490be73
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef __MVEBU_DEF_H__
+#define __MVEBU_DEF_H__
+
+#include <a8k_plat_def.h>
+
+/*
+ * CN-9130 has single CP0 inside the package and 2 additional one
+ * from MoChi interface. In case of db-9130-modular board the MCI interface
+ * is routed to:
+ * - on-board CP115 (MCI0)
+ * - extension board CP115 (MCI1)
+ */
+#define CP_COUNT CP_NUM
+#define MVEBU_SOC_AP807 1
+#define I2C_SPD_ADDR 0x53 /* Access SPD data */
+#define I2C_SPD_P0_ADDR 0x36 /* Select SPD data page 0 */
+
+#endif /* __MVEBU_DEF_H__ */
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/platform.mk b/plat/marvell/octeontx/otx2/t91/t9130/platform.mk
new file mode 100644
index 0000000..1e2716d
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/ap807_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
new file mode 100644
index 0000000..5bae8eb
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2021 Semihalf.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <mvebu_def.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map_cp0[] = {
+ /* CP0 SPI1 CS0 Direct Mode access */
+ {0xef00, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+struct addr_map_win amb_memory_map_cp1[] = {
+ /* CP1 SPI1 CS0 Direct Mode access */
+ {0xe800, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = amb_memory_map_cp0;
+ *size = ARRAY_SIZE(amb_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = amb_memory_map_cp1;
+ *size = ARRAY_SIZE(amb_memory_map_cp1);
+ return 0;
+ case MVEBU_CP_REGS_BASE(2):
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#if (CP_COUNT > 1)
+ /* SB (MCi0) internal regs */
+ {0x00000000f4000000, 0x2000000, MCI_0_TID},
+ /* SB (MCi0) PCIe0-2 on CP1 */
+ {0x00000000e2000000, 0x7000000, MCI_0_TID},
+ /*
+ * Due to lack of sufficient number of IO windows registers,
+ * below CP1 PCIE configuration must be performed in the
+ * later firmware stages. It should replace the MCI 0 indirect
+ * window, which becomes no longer needed.
+ */
+ /* {0x0000000890000000, 0x30000000, MCI_0_TID}, */
+#if (CP_COUNT > 2)
+ /* SB (MCi1) internal regs */
+ {0x00000000f6000000, 0x2000000, MCI_1_TID},
+ /* SB (MCi1) PCIe0-2 on CP2 */
+ {0x00000000e9000000, 0x6000000, MCI_1_TID},
+ /*
+ * Due to lack of sufficient number of IO windows registers,
+ * below CP2 PCIE configuration must be performed in the
+ * later firmware stages. It should replace the MCI 1 indirect
+ * window, which becomes no longer needed.
+ */
+ /* {0x00000008c0000000, 0x30000000, MCI_1_TID}, */
+#endif
+#endif
+#ifndef IMAGE_BLE
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+/* Global Control Register - window default target */
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ /*
+ * PIDI == iMCIP AP to SB internal MoChi connection.
+ * In other words CP0
+ */
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000ef000000, 0x1000000, RUNIT_TID},
+ /* PEX2_X1 window */
+ {0x00000000e1000000, 0x1000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000e0000000, 0x1000000, PEX1_TID},
+ /* PEX0_X4 window */
+ {0x00000000c0000000, 0x20000000, PEX0_TID},
+ {0x0000000800000000, 0x90000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000e8000000, 0x1000000, RUNIT_TID},
+ /* PEX2_X1 window */
+ {0x00000000e6000000, 0x2000000, PEX2_TID},
+ {0x00000008b0000000, 0x10000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000e4000000, 0x2000000, PEX1_TID},
+ {0x00000008a0000000, 0x10000000, PEX1_TID},
+ /* PEX0_X2 window */
+ {0x00000000e2000000, 0x2000000, PEX0_TID},
+ {0x0000000890000000, 0x10000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp2[] = {
+
+ /* PEX2_X1 window */
+ {0x00000000ed000000, 0x2000000, PEX2_TID},
+ {0x00000008e0000000, 0x10000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000eb000000, 0x2000000, PEX1_TID},
+ {0x00000008d0000000, 0x10000000, PEX1_TID},
+ /* PEX0_X1 window */
+ {0x00000000e9000000, 0x2000000, PEX0_TID},
+ {0x00000008c0000000, 0x10000000, PEX0_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = iob_memory_map_cp0;
+ *size = ARRAY_SIZE(iob_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = iob_memory_map_cp1;
+ *size = ARRAY_SIZE(iob_memory_map_cp1);
+ return 0;
+ case MVEBU_CP_REGS_BASE(2):
+ *win = iob_memory_map_cp2;
+ *size = ARRAY_SIZE(iob_memory_map_cp2);
+ return 0;
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = { /* IO window */
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x6000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+ {0x0000002000000000, 0x70e000000, IO_0_TID}, /* IO for CV-OS */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_get_skip_image_data(void)
+{
+ /* No recovery button on CN-9130 board? */
+ return NULL;
+}
+#endif
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
new file mode 100644
index 0000000..ee55455
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+# Copyright (C) 2021 Semihalf.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/ap807_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+
+#
+# CN913X CEx7 Evaluation Board shares the DRAM connectivity
+# and SerDes settings with the CN913X DB - reuse relevant
+# board-specific files.
+#
+T9130_DIR := $(BOARD_DIR)/../t9130
+PLAT_INCLUDES := -I$(T9130_DIR) \
+ -I$(T9130_DIR)/board
+BLE_PORTING_SOURCES := $(T9130_DIR)/board/dram_port.c \
+ $(BOARD_DIR)/board/marvell_plat_config.c
+
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/mediatek/build_helpers/conditional_eval_options.mk b/plat/mediatek/build_helpers/conditional_eval_options.mk
new file mode 100644
index 0000000..6bb3b4e
--- /dev/null
+++ b/plat/mediatek/build_helpers/conditional_eval_options.mk
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Conditional makefile variable assignment
+
+# Options depend on BUILD_TYPE variable
+ifeq ($(BUILD_TYPE),release)
+MTK_DEBUGSYS_LOCK := 1
+MTK_GET_PERM_DIS := 1
+ERRATA_KLEIN_2218950 := 0
+ERRATA_KLEIN_2184257 := 0
+ERRATA_KLEIN_BOOKER := 0
+ERRATA_MTH_BOOKER := 0
+ERRATA_MTHELP_BOOKER := 0
+CRASH_REPORTING := 1
+CONFIG_MTK_BL31_RAMDUMP := 0
+endif
+
+ifeq ($(BUILD_TYPE),debug)
+MTK_PTP3_PROC_DEBUG := 1
+MTK_SRAMRC_DEBUG := 1
+MTK_IOMMU_DEBUG := 1
+MTK_DCM_DEBUG := 1
+MTK_EMI_MPU_DEBUG := 1
+endif
+
+ifeq (${SPD},none)
+SPD_NONE:=1
+$(eval $(call add_define,SPD_NONE))
+endif
+
+# TEE OS config
+ifeq ($(SPD), tbase)
+CONFIG_TBASE := y
+endif
+
+# MICROTRUST OS config
+ifeq ($(SPD), teeid)
+CONFIG_MICROTRUST_TEEI := y
+endif
+
+ifeq (${CONFIG_ARCH_ARM_V8_2},y)
+ARCH_VERSION := armv8_2
+endif
+
+ifeq (${CONFIG_ARCH_ARM_V9},y)
+ARCH_VERSION := armv9
+endif
diff --git a/plat/mediatek/build_helpers/mtk_build_helpers.mk b/plat/mediatek/build_helpers/mtk_build_helpers.mk
new file mode 100644
index 0000000..fc3876e
--- /dev/null
+++ b/plat/mediatek/build_helpers/mtk_build_helpers.mk
@@ -0,0 +1,142 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Get local directory path
+define GET_LOCAL_DIR
+$(patsubst %/,%,$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
+endef
+
+# Clear module source variable
+define CLEAR_LOCAL_SRCS
+$(eval $(1) :=)
+endef
+
+define EXPAND_SUB_MAKEFILE
+include $(S)
+endef
+
+# Expand sub rules.mk
+define INCLUDE_MAKEFILE
+$(eval MODULES_SUB_MAKEFILE := $(patsubst %,%/rules.mk,$(1)))
+$(foreach S,$(MODULES_SUB_MAKEFILE),$(eval $(EXPAND_SUB_MAKEFILE)))
+endef
+
+# Determine option variable is defined or not then define it
+define add_defined_option
+ifdef $(1)
+ifeq ($(findstring $(value $(1)), $(uppercase_table)),)
+DEFINES += -D$(1)$(if $(value $(1)),=$(value $(1)),)
+else
+ifeq ($(strip $(value $(1))),y)
+DEFINES += -D$(1)$(if $(value $(1)),=1,)
+endif
+endif
+endif
+endef
+
+define EXPAND_RULES_MAKEFILE
+LOCAL_SRCS-y :=
+MODULE :=
+SUB_RULES-y :=
+include $(S)
+endef
+
+# INCLUDE_MODULES macro expand included modules rules.mk
+# Arguments:
+# $(1) = MODULES variables
+define INCLUDE_MODULES
+$(eval MODULES_TEMP := $(1))
+$(eval MODULES_MAKEFILE := $(patsubst %,%/rules.mk,$(MODULES_TEMP)))
+$(foreach S,$(MODULES_MAKEFILE),$(eval $(EXPAND_RULES_MAKEFILE)))
+endef
+
+# MAKE_LOCALS expand module source file variable to BL${BL}_SOURCES
+# Arguments:
+# $(1) = source file
+# $(2) = BL stage (1, 2, 2u, 31, 32)
+define MAKE_LOCALS
+$(eval $(call uppercase,$(2))_SOURCES += $(1))
+endef
+
+# MAKE_LINKERFILE change linker script source file name to
+# target linker script
+# $(1) = linker script source file
+# $(2) = BL stage
+define MAKE_LINKERFILE
+$(eval EXTRA_GENERATED_LINKER_SCRIPT += $(BUILD_PLAT)/$(2)/$(patsubst %.ld.S,%.ld,$(notdir $(1))))
+endef
+
+# MAKE_LINKERFILE_ITER call MAKE_LINKERFILE iteratively
+# $(1) = linker script source file
+# $(2) = BL stage
+define MAKE_LINKERFILE_ITER
+$(eval $(foreach link_src,$(1),$(call MAKE_LINKERFILE,$(link_src),$(2))))
+endef
+
+# MAKE_LD_ITER generate the linker scripts using the C preprocessor iteratively
+# $(1) = output linker script
+# $(2) = input template
+# $(3) = BL stage (1, 2, 2u, 31, 32)
+define MAKE_LD_ITER
+$(eval index_list=$(shell seq $(words $(1))))
+$(eval $(foreach i, $(index_list), \
+$(call MAKE_LD,$(word $(i), $(1)), $(word $(i), $(2)),$(3))))
+endef
+
+# MAKE_MODULE reference MAKE_OBJS.
+# Create module folder under out/bl$(BL)/$(module)
+# Arguments:
+# $(1) = module name
+# $(2) = source file
+# $(3) = BL stage
+define MAKE_MODULE
+ $(eval MODULE := $(strip $(1)))
+ $(eval BUILD_DIR := ${BUILD_PLAT}/${3})
+ $(eval SOURCES := $(2))
+ $(eval OBJS_TEMP := $(addprefix $(BUILD_DIR)/$(MODULE)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
+ $(eval MODULE_OBJS += $(OBJS_TEMP))
+ # We use sort only to get a list of unique object directory names.
+ # ordering is not relevant but sort removes duplicates.
+ $(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS_TEMP} ${LINKERFILE})))
+ # The $(dir ) function leaves a trailing / on the directory names
+ # Rip off the / to match directory names with make rule targets.
+ $(eval OBJ_DIRS := $(patsubst %/,%,$(TEMP_OBJ_DIRS)))
+
+$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
+${3}_dirs: | ${OBJ_DIRS}
+
+$(eval $(call MAKE_OBJS,$(BUILD_DIR)/$(MODULE),$(SOURCES),${3}))
+
+libraries: $(OBJS_TEMP)
+endef
+
+# Include MTK configuration files
+
+# MTK makefile variables
+ifeq (${COREBOOT},1)
+MTK_COMMON_CFG := $(MTK_PLAT)/common/coreboot_config.mk
+else
+MTK_COMMON_CFG := $(MTK_PLAT)/common/common_config.mk
+endif
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${MTK_SOC}
+MTK_PLAT_CFG := $(MTK_PLAT_SOC)/plat_config.mk
+MTK_PROJECT_CFG := $(MTK_PLAT)/project/$(PLAT)/project_config.mk
+MTK_OPTIONS := $(MTK_PLAT)/build_helpers/options.mk
+MTK_COND_EVAL := $(MTK_PLAT)/build_helpers/conditional_eval_options.mk
+
+# Indicate which BL should be built in command line
+ifeq (${NEED_BL32},yes)
+MTK_BL := bl32
+else
+MTK_BL := bl31
+endif
+# Include common, platform, board level config
+include $(MTK_COMMON_CFG)
+include $(MTK_PLAT_CFG)
+-include $(MTK_PROJECT_CFG)
+include $(MTK_COND_EVAL)
+include $(MTK_OPTIONS)
diff --git a/plat/mediatek/build_helpers/mtk_build_helpers_epilogue.mk b/plat/mediatek/build_helpers/mtk_build_helpers_epilogue.mk
new file mode 100644
index 0000000..22a546c
--- /dev/null
+++ b/plat/mediatek/build_helpers/mtk_build_helpers_epilogue.mk
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Expand include modules
+$(eval $(call INCLUDE_MODULES,$(MODULES-y)))
+
+# Make next section align to page size
+ifneq ($(MTK_EXTRA_LINKERFILE),)
+$(eval $(call MAKE_LINKERFILE_ITER,$(MTK_LINKERFILE_SOURCE),bl31))
+
+# EXTRA_GENERATED_LINKER_SCRIPT is a global variable of derived linker
+# script list(from MTK_LINKERFILE_SOURCE) after MAKE_LINKERFILE_ITER
+# function call
+EXTRA_LINKERFILE += ${EXTRA_GENERATED_LINKER_SCRIPT}
+
+# Expand derived linker script as build target
+$(eval $(call MAKE_LD_ITER, $(EXTRA_GENERATED_LINKER_SCRIPT),$(MTK_LINKERFILE_SOURCE),bl31))
+
+# mtk_align.ld MUST BE THE LAST LINKER SCRIPT!
+EXTRA_LINKERFILE += ${MTK_PLAT}/include/mtk_align.ld
+
+# bl31.ld should depend on EXTRA_LINKERFILE
+$(eval ${BUILD_PLAT}/bl31/bl31.ld: ${EXTRA_LINKERFILE})
+EXTRA_LINKERFILE := $(addprefix -T,$(EXTRA_LINKERFILE))
+else
+EXTRA_LINKERFILE :=
+endif
diff --git a/plat/mediatek/build_helpers/options.mk b/plat/mediatek/build_helpers/options.mk
new file mode 100644
index 0000000..0279648
--- /dev/null
+++ b/plat/mediatek/build_helpers/options.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# call add_defined_option to evaluate MTK defined value
+$(eval $(call add_defined_option,MTK_SIP_KERNEL_BOOT_ENABLE))
+$(eval $(call add_defined_option,PLAT_EXTRA_RODATA_INCLUDES))
+$(eval $(call add_defined_option,MTK_EXTRA_LINKERFILE))
+$(eval $(call add_defined_option,MTK_BL31_AS_BL2))
+$(eval $(call add_defined_option,MTK_BL33_IS_64BIT))
+$(eval $(call add_defined_option,PLAT_XLAT_TABLES_DYNAMIC))
+$(eval $(call add_defined_option,MTK_ADAPTED))
+$(eval $(call add_defined_option,MTK_PUBEVENT_ENABLE))
+$(eval $(call add_defined_option,MTK_SOC))
+$(eval $(call add_defined_option,UART_CLOCK))
+$(eval $(call add_defined_option,UART_BAUDRATE))
+$(eval $(call add_defined_option,CONFIG_MTK_MCUSYS))
+$(eval $(call add_defined_option,CONFIG_MTK_PM_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_CPU_PM_SUPPORT))
+$(eval $(call add_defined_option,CONFIG_MTK_SMP_EN))
+$(eval $(call add_defined_option,CONFIG_MTK_CPU_SUSPEND_EN))
+$(eval $(call add_defined_option,CONFIG_MTK_PM_ARCH))
+$(eval $(call add_defined_option,CONFIG_MTK_CPU_PM_ARCH))
diff --git a/plat/mediatek/common/common_config.mk b/plat/mediatek/common/common_config.mk
new file mode 100644
index 0000000..851eb2c
--- /dev/null
+++ b/plat/mediatek/common/common_config.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+MULTI_CONSOLE_API := 1
+COLD_BOOT_SINGLE_CPU := 1
+# Build flag to include AArch32 registers in cpu context save and restore during
+# world switch. This flag must be set to 0 for AArch64-only platforms.
+CTX_INCLUDE_AARCH32_REGS := 0
+PLAT_XLAT_TABLES_DYNAMIC := 1
+# enable this definition to print irq dump status in tf-a
+GIC_DEBUG := 0
+# Enable stack protector.
+# Allowed values are "all", "strong", "default" and "none"
+ENABLE_STACK_PROTECTOR := strong
+# AMU, Kernel will access amuserenr_el0 if PE supported
+# Firmware _must_ implement AMU support
+ENABLE_AMU := 1
+VENDOR_EXTEND_PUBEVENT_ENABLE := 1
+
+# MTK define options
+MTK_BL33_IS_64BIT := 0
+MTK_ADAPTED := 1
+
+# MTK module config
+CONFIG_MTK_INTERRUPT := y
+CONFIG_MTK_UART := y
+
+# UART baudrate
+UART_BAUDRATE := 921600
diff --git a/plat/mediatek/common/coreboot_config.mk b/plat/mediatek/common/coreboot_config.mk
new file mode 100644
index 0000000..59d18e8
--- /dev/null
+++ b/plat/mediatek/common/coreboot_config.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+COLD_BOOT_SINGLE_CPU := 1
+# Build flag to include AArch32 registers in cpu context save and restore during
+# world switch. This flag must be set to 0 for AArch64-only platforms.
+CTX_INCLUDE_AARCH32_REGS := 0
+PLAT_XLAT_TABLES_DYNAMIC := 1
+
+VENDOR_EXTEND_PUBEVENT_ENABLE := 1
diff --git a/plat/mediatek/common/lpm/mt_lp_rm.c b/plat/mediatek/common/lpm/mt_lp_rm.c
new file mode 100644
index 0000000..0bafc66
--- /dev/null
+++ b/plat/mediatek/common/lpm/mt_lp_rm.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mt_lp_rm.h>
+#include <stddef.h>
+
+struct platform_mt_resource_manager {
+ unsigned int count;
+ struct mt_resource_manager *plat_rm;
+};
+
+static struct platform_mt_resource_manager plat_mt_rm;
+
+int mt_lp_rm_register(struct mt_resource_manager *rm)
+{
+ unsigned int i;
+ struct mt_resource_constraint *const *rc;
+
+ if ((rm == NULL) || (rm->consts == NULL) ||
+ (plat_mt_rm.plat_rm != NULL)) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ for (i = 0U, rc = rm->consts; *rc != NULL; i++, rc++) {
+ if ((*rc)->init != NULL) {
+ (*rc)->init();
+ }
+ }
+
+ plat_mt_rm.plat_rm = rm;
+ plat_mt_rm.count = i;
+
+ return MT_RM_STATUS_OK;
+}
+
+int mt_lp_rm_reset_constraint(int idx, unsigned int cpuid, int stateid)
+{
+ struct mt_resource_constraint const *rc = NULL;
+
+ if ((plat_mt_rm.plat_rm == NULL) || (idx < 0) ||
+ (idx >= plat_mt_rm.count)) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ rc = plat_mt_rm.plat_rm->consts[idx];
+
+ if ((rc == NULL) || (rc->reset == NULL)) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ return rc->reset(cpuid, stateid);
+}
+
+int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
+ int stateid, void *priv)
+{
+ int i, res = MT_RM_STATUS_BAD;
+ struct mt_resource_constraint *const *rc;
+ struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
+
+ if ((rm == NULL) || (idx < 0) || (idx >= plat_mt_rm.count)) {
+ return res;
+ }
+
+ /* If subsys clk/mtcmos is on, add block-resource-off flag */
+ if (rm->update != NULL) {
+ res = rm->update(rm->consts, stateid, priv);
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) {
+ if (((*rc)->is_valid != NULL) &&
+ ((*rc)->is_valid(cpuid, stateid))) {
+ if (((*rc)->run != NULL) &&
+ ((*rc)->run(cpuid, stateid) == 0)) {
+ res = i;
+ break;
+ }
+ }
+ }
+
+ return res;
+}
+
+int mt_lp_rm_do_update(int stateid, int type, void const *p)
+{
+ int res = MT_RM_STATUS_BAD;
+ struct mt_resource_constraint *const *rc;
+ struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
+
+ if (rm == NULL) {
+ return res;
+ }
+
+ for (rc = rm->consts; *rc != NULL; rc++) {
+ if ((*rc)->update != NULL) {
+ res = (*rc)->update(stateid, type, p);
+ if (res != MT_RM_STATUS_OK) {
+ break;
+ }
+ }
+ }
+
+ return res;
+}
diff --git a/plat/mediatek/common/lpm/mt_lp_rm.h b/plat/mediatek/common/lpm/mt_lp_rm.h
new file mode 100644
index 0000000..e93dac3
--- /dev/null
+++ b/plat/mediatek/common/lpm/mt_lp_rm.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_RM_H
+#define MT_LP_RM_H
+
+#include <stdbool.h>
+
+#define MT_RM_STATUS_OK 0
+#define MT_RM_STATUS_BAD -1
+
+enum PLAT_MT_LPM_RC_TYPE {
+ PLAT_RC_UPDATE_CONDITION,
+ PLAT_RC_UPDATE_REMAIN_IRQS
+};
+
+struct mt_resource_constraint {
+ int level;
+ int (*init)(void);
+ bool (*is_valid)(unsigned int cpu, int stateid);
+ int (*update)(int stateid, int type, const void *p);
+ int (*run)(unsigned int cpu, int stateid);
+ int (*reset)(unsigned int cpu, int stateid);
+ unsigned int (*allow)(int stateid);
+};
+
+struct mt_resource_manager {
+ int (*update)(struct mt_resource_constraint **con,
+ int stateid, void *priv);
+ struct mt_resource_constraint **consts;
+};
+
+extern int mt_lp_rm_register(struct mt_resource_manager *rm);
+extern int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
+ int stateid, void *priv);
+extern int mt_lp_rm_reset_constraint(int constraint_id, unsigned int cpuid,
+ int stateid);
+extern int mt_lp_rm_do_update(int stateid, int type, void const *p);
+#endif /* MT_LP_RM_H */
diff --git a/plat/mediatek/common/lpm/rules.mk b/plat/mediatek/common/lpm/rules.mk
new file mode 100644
index 0000000..87a212a
--- /dev/null
+++ b/plat/mediatek/common/lpm/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := lpm
+LOCAL_SRCS-y := $(LOCAL_DIR)/mt_lp_rm.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/common/mtk_bl31_setup.c b/plat/mediatek/common/mtk_bl31_setup.c
new file mode 100644
index 0000000..7c9db8b
--- /dev/null
+++ b/plat/mediatek/common/mtk_bl31_setup.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#if XLAT_TABLES_LIB_V2 && PLAT_XLAT_TABLES_DYNAMIC
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#endif
+#include <plat/common/platform.h>
+
+#if COREBOOT
+#include <common/desc_image_load.h>
+
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+#include <plat_params.h>
+#endif
+
+/* MTK headers */
+#if MTK_SIP_KERNEL_BOOT_ENABLE
+#include <cold_boot.h>
+#endif
+#include <lib/mtk_init/mtk_init.h>
+#include <mtk_mmap_pool.h>
+
+IMPORT_SYM(uintptr_t, __RW_START__, RW_START);
+IMPORT_SYM(uintptr_t, __DATA_START__, DATA_START);
+
+#if COREBOOT
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+#else
+#ifndef MTK_BL31_AS_BL2
+static struct mtk_bl31_fw_config bl31_fw_config;
+#else
+struct mtk_bl31_fw_config bl31_fw_config;
+#endif
+/* In order to be accessed after MMU enable */
+static struct mtk_bl_param_t bl_param_clone;
+
+void *get_mtk_bl31_fw_config(int index)
+{
+ void *arg = NULL;
+
+ switch (index) {
+ case BOOT_ARG_FROM_BL2:
+ arg = bl31_fw_config.from_bl2;
+ break;
+ case BOOT_ARG_SOC_FW_CONFIG:
+ arg = bl31_fw_config.soc_fw_config;
+ break;
+ case BOOT_ARG_HW_CONFIG:
+ arg = bl31_fw_config.hw_config;
+ break;
+ case BOOT_ARG_RESERVED:
+ arg = bl31_fw_config.reserved;
+ break;
+ default:
+ WARN("Fail to get boot arg, index:%d", index);
+ break;
+ }
+ return arg;
+}
+#endif
+/*****************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t from_bl2,
+ u_register_t soc_fw_config,
+ u_register_t hw_config, u_register_t plat_params_from_bl2)
+
+{
+#if COREBOOT
+ static console_t console;
+
+ params_early_setup(soc_fw_config);
+ if (coreboot_serial.type) {
+ console_16550_register(coreboot_serial.baseaddr,
+ coreboot_serial.input_hertz,
+ coreboot_serial.baud,
+ &console);
+ }
+ bl31_params_parse_helper(from_bl2, &bl32_ep_info, &bl33_ep_info);
+#else
+ struct mtk_bl_param_t *p_mtk_bl_param = (struct mtk_bl_param_t *)from_bl2;
+
+ if (p_mtk_bl_param == NULL) {
+ ERROR("from_bl2 should not be NULL\n");
+ panic();
+ }
+ memcpy(&bl_param_clone, p_mtk_bl_param, sizeof(struct mtk_bl_param_t));
+ bl31_fw_config.from_bl2 = (void *)&bl_param_clone;
+ bl31_fw_config.soc_fw_config = (void *)soc_fw_config;
+ bl31_fw_config.hw_config = (void *)hw_config;
+ bl31_fw_config.reserved = (void *)plat_params_from_bl2;
+#endif
+
+ INFO("MTK BL31 start\n");
+ /* Init delay function */
+ generic_delay_timer_init();
+ /* Initialize module initcall */
+ mtk_init_one_level(MTK_INIT_LVL_EARLY_PLAT);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_BL_RO,
+ MAP_BL_RW,
+#if USE_COHERENT_MEM
+ MAP_BL_COHERENT_RAM,
+#endif
+ {0},
+ };
+
+ mtk_xlat_init(bl_regions);
+ /* Initialize module initcall */
+ mtk_init_one_level(MTK_INIT_LVL_ARCH);
+}
+
+/*****************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ ******************************************************************************/
+
+void bl31_platform_setup(void)
+{
+ mtk_init_one_level(MTK_INIT_LVL_PLAT_SETUP_0);
+ mtk_init_one_level(MTK_INIT_LVL_PLAT_SETUP_1);
+}
+
+/*******************************************************************************
+ * Operations before cold CPU leave BL31.
+ * Switch console to runtime state.
+ ******************************************************************************/
+void bl31_plat_runtime_setup(void)
+{
+ mtk_init_one_level(MTK_INIT_LVL_PLAT_RUNTIME);
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_HZ;
+}
diff --git a/plat/mediatek/common/mtk_plat_common.c b/plat/mediatek/common/mtk_plat_common.c
new file mode 100644
index 0000000..76f74a9
--- /dev/null
+++ b/plat/mediatek/common/mtk_plat_common.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
+
+#include <mtk_plat_common.h>
+#include <mtk_sip_svc.h>
+#include <plat_private.h>
+
+void clean_top_32b_of_param(uint32_t smc_fid,
+ u_register_t *px1,
+ u_register_t *px2,
+ u_register_t *px3,
+ u_register_t *px4)
+{
+ /* if parameters from SMC32. Clean top 32 bits */
+ if (GET_SMC_CC(smc_fid) == SMC_64) {
+ *px1 = *px1 & SMC32_PARAM_MASK;
+ *px2 = *px2 & SMC32_PARAM_MASK;
+ *px3 = *px3 & SMC32_PARAM_MASK;
+ *px4 = *px4 & SMC32_PARAM_MASK;
+ }
+}
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ * feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED
+ * otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
+int32_t plat_get_soc_version(void)
+{
+ uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_MTK_BKID, JEDEC_MTK_MFID);
+
+ return (int32_t)(manfid | (SOC_CHIP_ID & SOC_ID_IMPL_DEF_MASK));
+}
+
+int32_t plat_get_soc_revision(void)
+{
+ return 0;
+}
diff --git a/plat/mediatek/common/mtk_plat_common.h b/plat/mediatek/common/mtk_plat_common.h
new file mode 100644
index 0000000..4c14b9d
--- /dev/null
+++ b/plat/mediatek/common/mtk_plat_common.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef MTK_PLAT_COMMON_H
+#define MTK_PLAT_COMMON_H
+
+#include <stdint.h>
+
+#include <common/bl_common.h>
+#include <common/param_header.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+#define SMC32_PARAM_MASK (0xFFFFFFFF)
+
+#define JEDEC_MTK_BKID U(4)
+#define JEDEC_MTK_MFID U(0x26)
+
+struct mtk_bl31_params {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+};
+
+/* Declarations for mtk_plat_common.c */
+uint32_t plat_get_spsr_for_bl32_entry(void);
+uint32_t plat_get_spsr_for_bl33_entry(void);
+void clean_top_32b_of_param(uint32_t smc_fid, u_register_t *x1,
+ u_register_t *x2,
+ u_register_t *x3,
+ u_register_t *x4);
+void bl31_prepare_kernel_entry(uint64_t k32_64);
+void enable_ns_access_to_cpuectlr(void);
+void boot_to_kernel(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4);
+uint64_t get_kernel_info_pc(void);
+uint64_t get_kernel_info_r0(void);
+uint64_t get_kernel_info_r1(void);
+uint64_t get_kernel_info_r2(void);
+
+extern struct atf_arg_t gteearg;
+#endif /* MTK_PLAT_COMMON_H */
diff --git a/plat/mediatek/common/mtk_sip_svc.c b/plat/mediatek/common/mtk_sip_svc.c
new file mode 100644
index 0000000..dab0d45
--- /dev/null
+++ b/plat/mediatek/common/mtk_sip_svc.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <tools_share/uuid.h>
+
+#include <mtk_plat_common.h>
+#include <mtk_sip_svc.h>
+#include <plat_sip_calls.h>
+
+/* Mediatek SiP Service UUID */
+DEFINE_SVC_UUID2(mtk_sip_svc_uid,
+ 0xa42b58f7, 0x6242, 0x7d4d, 0x80, 0xe5,
+ 0x8f, 0x95, 0x05, 0x00, 0x0f, 0x3d);
+
+#pragma weak mediatek_plat_sip_handler
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
+
+/*
+ * This function handles Mediatek defined SiP Calls */
+uintptr_t mediatek_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t ns;
+
+ /* if parameter is sent from SMC32. Clean top 32 bits */
+ clean_top_32b_of_param(smc_fid, &x1, &x2, &x3, &x4);
+
+ /* Determine which security state this SMC originated from */
+ ns = is_caller_non_secure(flags);
+ if (!ns) {
+ /* SiP SMC service secure world's call */
+ ;
+ } else {
+ /* SiP SMC service normal world's call */
+ switch (smc_fid) {
+#if MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE
+ case MTK_SIP_SET_AUTHORIZED_SECURE_REG: {
+ /* only use ret here */
+ uint64_t ret;
+
+ ret = mt_sip_set_authorized_sreg((uint32_t)x1,
+ (uint32_t)x2);
+ SMC_RET1(handle, ret);
+ }
+#endif
+#if MTK_SIP_KERNEL_BOOT_ENABLE
+ case MTK_SIP_KERNEL_BOOT_AARCH32:
+ boot_to_kernel(x1, x2, x3, x4);
+ SMC_RET0(handle);
+#endif
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+ }
+
+ return mediatek_plat_sip_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+
+}
+
+/*
+ * This function is responsible for handling all SiP calls from the NS world
+ */
+uintptr_t sip_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ switch (smc_fid) {
+ case SIP_SVC_CALL_COUNT:
+ /* Return the number of Mediatek SiP Service Calls. */
+ SMC_RET1(handle,
+ MTK_COMMON_SIP_NUM_CALLS + MTK_PLAT_SIP_NUM_CALLS);
+
+ case SIP_SVC_UID:
+ /* Return UID to the caller */
+ SMC_UUID_RET(handle, mtk_sip_svc_uid);
+
+ case SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ SMC_RET2(handle, MTK_SIP_SVC_VERSION_MAJOR,
+ MTK_SIP_SVC_VERSION_MINOR);
+
+ default:
+ return mediatek_sip_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ }
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ mediatek_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ sip_smc_handler
+);
diff --git a/plat/mediatek/common/mtk_smc_handlers.c b/plat/mediatek/common/mtk_smc_handlers.c
new file mode 100644
index 0000000..51a960f
--- /dev/null
+++ b/plat/mediatek/common/mtk_smc_handlers.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#if MTK_SIP_KERNEL_BOOT_ENABLE
+#include <cold_boot.h>
+#endif
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <mtk_sip_svc.h>
+
+#define SMC_HANDLER_DEBUG(...) VERBOSE(__VA_ARGS__)
+#define SMC_HANDLER_DEBUG_NOT_IMP_MSG "%s[0x%x] smc handler not implemented\n"
+#define SMC_HANDLER_DEBUG_START_MSG "%s[0x%x] smc handler start, smc desc. index:%d\n"
+#define SMC_HANDLER_DEBUG_END_MSG "%s[0x%x] smc handler end\n"
+
+/*
+ * These macros below are used to identify SIP calls from Kernel,
+ * Hypervisor, or 2ndBootloader
+ */
+#define SIP_FID_ORI_MASK (0xc000)
+#define SIP_FID_ORI_SHIFT (14)
+#define SIP_FID_KERNEL (0x0)
+#define SIP_FID_KERNEL_VIA_GZ (0x1)
+#define SIP_FID_GZ (0x2)
+
+#define GET_SMC_ORI(_fid) (((_fid) & SIP_FID_ORI_MASK) >> SIP_FID_ORI_SHIFT)
+#define GET_SMC_ORI_NUM(_fid) ((_fid) & ~(SIP_FID_ORI_MASK))
+
+#define is_from_nsel2(_ori) (_ori == SIP_FID_GZ)
+#define is_from_bl33(_ori) \
+ ((_ori != SIP_FID_GZ) && (is_el1_2nd_bootloader() == 1))
+#define is_from_nsel1(_ori) \
+ (((_ori == SIP_FID_KERNEL) || \
+ (_ori == SIP_FID_KERNEL_VIA_GZ)) && \
+ (is_el1_2nd_bootloader() == 0))
+
+#define is_smc_forbidden(_ori) (_ori == SIP_FID_KERNEL_VIA_GZ)
+
+#define MASK_32_BIT (0xffffffffU)
+#define SMC_ID_EXPAND_AS_SMC_OPERATION(_smc_id, _smc_num) \
+ case _smc_id##_AARCH32: \
+ { \
+ x1 = x1 & MASK_32_BIT; \
+ x2 = x2 & MASK_32_BIT; \
+ x3 = x3 & MASK_32_BIT; \
+ x4 = x4 & MASK_32_BIT; \
+ } \
+ case _smc_id##_AARCH64: \
+ { \
+ if (_smc_id##_descriptor_index < 0) { \
+ SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_NOT_IMP_MSG, #_smc_id, smc_id); \
+ break; \
+ } \
+ if (_smc_id##_descriptor_index >= smc_id_descriptor_max) { \
+ SMC_HANDLER_DEBUG("smc descriptor index[%d] exceed max[%d]\n", \
+ _smc_id##_descriptor_index, smc_id_descriptor_max); \
+ break; \
+ } \
+ SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_START_MSG, #_smc_id, smc_id, \
+ _smc_id##_descriptor_index); \
+ ret = smc_handler_pool[_smc_id##_descriptor_index].smc_handler(x1,\
+ x2, x3, x4, handle, &smc_ret); \
+ SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_END_MSG, #_smc_id, smc_id); \
+ break; \
+ }
+
+#define SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX(_smc_id, _smc_num) \
+ short _smc_id##_descriptor_index __section("mtk_plat_ro") = -1;
+
+MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
+MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
+
+IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_START__, MTK_SMC_POOL_START);
+IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_END_UNALIGNED__, MTK_SMC_POOL_END_UNALIGNED);
+
+static const struct smc_descriptor *smc_handler_pool;
+static short smc_id_descriptor_max;
+
+#if !MTK_SIP_KERNEL_BOOT_ENABLE
+/*
+ * If there is no SMC request needs to be served in 2nd bootloader,
+ * disable the service path inherently.
+ */
+bool is_el1_2nd_bootloader(void)
+{
+ return false;
+}
+#endif
+
+static void print_smc_descriptor(const struct smc_descriptor pool[])
+{
+ const struct smc_descriptor *p_smc_desc;
+
+ INFO("print smc descriptor pool\n");
+ for (p_smc_desc = &pool[0];
+ (char *)p_smc_desc < (char *)MTK_SMC_POOL_END_UNALIGNED;
+ p_smc_desc++) {
+ INFO("descriptor name:%s\n", p_smc_desc->smc_name);
+ INFO("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index);
+ INFO("smc id 32:0x%x, smc id 64:0x%x\n",
+ p_smc_desc->smc_id_aarch32, p_smc_desc->smc_id_aarch64);
+ }
+}
+
+static int mtk_smc_handler_init(void)
+{
+ const struct smc_descriptor *iter;
+ short index_cnt;
+ int ret = 0;
+
+ smc_handler_pool = (const struct smc_descriptor *)MTK_SMC_POOL_START;
+ /* Designate descriptor index point to smc_handler_pool */
+ for (index_cnt = 0, iter = &smc_handler_pool[0];
+ (char *)iter < (char *)MTK_SMC_POOL_END_UNALIGNED;
+ iter++, index_cnt++) {
+ if (index_cnt < 0) {
+ SMC_HANDLER_DEBUG("smc handler pool index overflow!\n");
+ ret = -EPERM;
+ assert(0);
+ break;
+ }
+ *(iter->smc_descriptor_index) = index_cnt;
+ }
+ smc_id_descriptor_max = index_cnt;
+ print_smc_descriptor(smc_handler_pool);
+ return ret;
+}
+MTK_EARLY_PLAT_INIT(mtk_smc_handler_init);
+
+/* This function handles Mediatek defined SiP Calls from Bootloader */
+static uintptr_t mtk_smc_handler_bl33(uint32_t smc_id,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uintptr_t ret = MTK_SIP_E_SUCCESS;
+ struct smccc_res smc_ret = {0};
+
+ switch (smc_id) {
+ MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
+ default:
+ INFO("BL33 SMC ID:0x%x not supported\n", smc_id);
+ ret = SMC_UNK;
+ break;
+ }
+ SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
+}
+
+/* This function handles Mediatek defined SiP Calls from Kernel */
+static uintptr_t mtk_smc_handler_nsel1(uint32_t smc_id,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uintptr_t ret = MTK_SIP_E_SUCCESS;
+ struct smccc_res smc_ret = {0};
+
+ switch (smc_id) {
+ MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
+ default:
+ INFO("NSEL1 SMC ID:0x%x not supported\n", smc_id);
+ ret = SMC_UNK;
+ break;
+ }
+ SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
+}
+
+static uintptr_t mtk_smc_handler(uint32_t smc_id,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uintptr_t ret = SMC_UNK;
+ uint32_t ns;
+ uint32_t smc_ori;
+ uint32_t smc_num;
+
+ /* Get SMC Originator bit 14.15 */
+ smc_ori = GET_SMC_ORI(smc_id);
+ /* Get SMC Number. Clean bit 14.15 */
+ smc_num = GET_SMC_ORI_NUM(smc_id);
+
+ /* Determine which security state this SMC originated from */
+ ns = is_caller_non_secure(flags);
+
+ if (ns && is_smc_forbidden(smc_ori)) {
+ ERROR("%s: Forbidden SMC call (0x%x)\n", __func__, smc_id);
+ SMC_RET1(handle, ret);
+ }
+
+ if (!ns) {
+ /* SiP SMC service secure world's call */
+ INFO("Secure SMC ID:0x%x not supported\n", smc_id);
+ SMC_RET1(handle, ret);
+ }
+ if (is_from_bl33(smc_ori)) {
+ /* SiP SMC service secure bootloader's call */
+ return mtk_smc_handler_bl33(smc_num, x1, x2, x3, x4,
+ cookie, handle, flags);
+ } else if (is_from_nsel1(smc_ori)) {
+ /* SiP SMC service kernel's call */
+ return mtk_smc_handler_nsel1(smc_num, x1, x2, x3, x4,
+ cookie, handle, flags);
+ }
+ INFO("SMC ID:0x%x not supported\n", smc_id);
+ SMC_RET1(handle, ret);
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ mtk_smc_handler,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ mtk_smc_handler
+);
diff --git a/plat/mediatek/common/params_setup.c b/plat/mediatek/common/params_setup.c
new file mode 100644
index 0000000..a9df13e
--- /dev/null
+++ b/plat/mediatek/common/params_setup.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/bl_aux_params/bl_aux_params.h>
+#include <common/debug.h>
+#include <plat_params.h>
+#include <string.h>
+
+static struct bl_aux_gpio_info rst_gpio;
+
+struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void)
+{
+ return &rst_gpio;
+}
+
+static bool mtk_aux_param_handler(struct bl_aux_param_header *param)
+{
+ /* Store platform parameters for later processing if needed. */
+ switch (param->type) {
+ case BL_AUX_PARAM_MTK_RESET_GPIO:
+ rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
+ return true;
+ }
+
+ return false;
+}
+
+void params_early_setup(u_register_t plat_param_from_bl2)
+{
+ bl_aux_params_parse(plat_param_from_bl2, mtk_aux_param_handler);
+}
+
diff --git a/plat/mediatek/common/plat_params.h b/plat/mediatek/common/plat_params.h
new file mode 100644
index 0000000..828c3dc
--- /dev/null
+++ b/plat/mediatek/common/plat_params.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PARAMS_H
+#define PLAT_PARAMS_H
+
+#include <stdint.h>
+
+#include <export/plat/mediatek/common/plat_params_exp.h>
+
+struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void);
+void params_early_setup(u_register_t plat_param_from_bl2);
+
+#endif
diff --git a/plat/mediatek/common/rules.mk b/plat/mediatek/common/rules.mk
new file mode 100644
index 0000000..6acc731
--- /dev/null
+++ b/plat/mediatek/common/rules.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_common
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_bl31_setup.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/mtk_smc_handlers.c
+LOCAL_SRCS-$(MTK_SIP_KERNEL_BOOT_ENABLE) += ${LOCAL_DIR}/cold_boot.c
+
+$(eval $(call MAKE_LOCALS,$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/audio/audio.c b/plat/mediatek/drivers/audio/audio.c
new file mode 100644
index 0000000..285c565
--- /dev/null
+++ b/plat/mediatek/drivers/audio/audio.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+
+#include <audio.h>
+
+#include <mtk_sip_svc.h>
+
+#define MODULE_TAG "[AUDIO]"
+
+static u_register_t audio_smc_handler(u_register_t x1, u_register_t x2,
+ u_register_t x3, u_register_t x4,
+ void *handle, struct smccc_res *smccc_ret)
+{
+ uint32_t request_ops;
+ int ret;
+
+ request_ops = (uint32_t)x1;
+
+ switch (request_ops) {
+ case MTK_AUDIO_SMC_OP_DOMAIN_SIDEBANDS:
+ ret = set_audio_domain_sidebands();
+ break;
+ default:
+ ERROR("%s: %s: Unsupported request_ops %x\n",
+ MODULE_TAG, __func__, request_ops);
+ ret = -EIO;
+ break;
+ }
+
+ VERBOSE("%s: %s, request_ops = %x, ret = %d\n",
+ MODULE_TAG, __func__, request_ops, ret);
+ return ret;
+}
+/* Register SiP SMC service */
+DECLARE_SMC_HANDLER(MTK_SIP_AUDIO_CONTROL, audio_smc_handler);
diff --git a/plat/mediatek/drivers/audio/audio.h b/plat/mediatek/drivers/audio/audio.h
new file mode 100644
index 0000000..1598a92
--- /dev/null
+++ b/plat/mediatek/drivers/audio/audio.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AUDIO_H
+#define AUDIO_H
+
+#include <stdint.h>
+#include <lib/mmio.h>
+
+enum mtk_audio_smc_call_op {
+ MTK_AUDIO_SMC_OP_INIT = 0,
+ MTK_AUDIO_SMC_OP_DRAM_REQUEST,
+ MTK_AUDIO_SMC_OP_DRAM_RELEASE,
+ MTK_AUDIO_SMC_OP_SRAM_REQUEST,
+ MTK_AUDIO_SMC_OP_SRAM_RELEASE,
+ MTK_AUDIO_SMC_OP_ADSP_REQUEST,
+ MTK_AUDIO_SMC_OP_ADSP_RELEASE,
+ MTK_AUDIO_SMC_OP_DOMAIN_SIDEBANDS,
+ MTK_AUDIO_SMC_OP_BTCVSD_WRITE,
+ MTK_AUDIO_SMC_OP_BTCVSD_UPDATE_CTRL_CLEAR,
+ MTK_AUDIO_SMC_OP_BTCVSD_UPDATE_CTRL_UNDERFLOW,
+ MTK_AUDIO_SMC_OP_NUM,
+};
+
+int32_t set_audio_domain_sidebands(void);
+
+#endif /* AUDIO_H */
diff --git a/plat/mediatek/drivers/audio/mt8188/audio_domain.c b/plat/mediatek/drivers/audio/mt8188/audio_domain.c
new file mode 100644
index 0000000..cbafd19
--- /dev/null
+++ b/plat/mediatek/drivers/audio/mt8188/audio_domain.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <common/debug.h>
+
+#include <audio.h>
+#include <mt_audio_private.h>
+#include <mtk_mmap_pool.h>
+#include <platform_def.h>
+#include <spm_reg.h>
+
+#define MODULE_TAG "[AUDIO_DOMAIN]"
+
+int32_t set_audio_domain_sidebands(void)
+{
+ uint32_t val = mmio_read_32(PWR_STATUS);
+
+ if ((val & BIT(SPM_PWR_STATUS_AUDIO_BIT)) == 0) {
+ ERROR("%s: %s, pwr_status=0x%x, w/o [%d]AUDIO!\n",
+ MODULE_TAG, __func__, val, SPM_PWR_STATUS_AUDIO_BIT);
+ return -EIO;
+ }
+
+ mmio_write_32(AFE_SE_SECURE_CON, 0x0);
+
+ mmio_write_32(AFE_SECURE_SIDEBAND0, 0x0);
+ mmio_write_32(AFE_SECURE_SIDEBAND1, 0x0);
+ mmio_write_32(AFE_SECURE_SIDEBAND2, 0x0);
+ mmio_write_32(AFE_SECURE_SIDEBAND3, 0x0);
+
+ VERBOSE("%s: %s, SE_SECURE_CON=0x%x, SIDEBAND0/1/2/3=0x%x/0x%x/0x%x/0x%x\n",
+ MODULE_TAG, __func__,
+ mmio_read_32(AFE_SE_SECURE_CON),
+ mmio_read_32(AFE_SECURE_SIDEBAND0),
+ mmio_read_32(AFE_SECURE_SIDEBAND1),
+ mmio_read_32(AFE_SECURE_SIDEBAND2),
+ mmio_read_32(AFE_SECURE_SIDEBAND3));
+
+ return 0;
+}
diff --git a/plat/mediatek/drivers/audio/mt8188/mt_audio_private.h b/plat/mediatek/drivers/audio/mt8188/mt_audio_private.h
new file mode 100644
index 0000000..bcb1abc
--- /dev/null
+++ b/plat/mediatek/drivers/audio/mt8188/mt_audio_private.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_AUDIO_PRIVATE_H
+#define MT_AUDIO_PRIVATE_H
+
+#include <platform_def.h>
+
+#define AFE_SE_SECURE_CON (AUDIO_BASE + 0x17a8)
+#define AFE_SECURE_SIDEBAND0 (AUDIO_BASE + 0x1908)
+#define AFE_SECURE_SIDEBAND1 (AUDIO_BASE + 0x190c)
+#define AFE_SECURE_SIDEBAND2 (AUDIO_BASE + 0x1910)
+#define AFE_SECURE_SIDEBAND3 (AUDIO_BASE + 0x1914)
+
+#define SPM_PWR_STATUS_AUDIO_BIT (6)
+
+#endif /* MT_AUDIO_PRIVATE_H */
diff --git a/plat/mediatek/drivers/audio/mt8188/rules.mk b/plat/mediatek/drivers/audio/mt8188/rules.mk
new file mode 100644
index 0000000..82acbfc
--- /dev/null
+++ b/plat/mediatek/drivers/audio/mt8188/rules.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := audio_${MTK_SOC}
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/audio_domain.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/audio/rules.mk b/plat/mediatek/drivers/audio/rules.mk
new file mode 100644
index 0000000..8538a64
--- /dev/null
+++ b/plat/mediatek/drivers/audio/rules.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := audio
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/audio.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+PLAT_INCLUDES += -I${LOCAL_DIR}/$(MTK_SOC)
+
+SUB_RULES-y:= ${LOCAL_DIR}/${MTK_SOC}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
+$(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))
diff --git a/plat/mediatek/drivers/cirq/mt_cirq.c b/plat/mediatek/drivers/cirq/mt_cirq.c
new file mode 100644
index 0000000..60534a2
--- /dev/null
+++ b/plat/mediatek/drivers/cirq/mt_cirq.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
+
+#include <mt_cirq.h>
+#include <mt_gic_v3.h>
+
+static struct cirq_events cirq_all_events = {
+ .spi_start = CIRQ_SPI_START,
+};
+static uint32_t already_cloned;
+/*
+ * mt_irq_mask_restore: restore all interrupts
+ * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
+ * Return 0 for success; return negative values for failure.
+ * (This is ONLY used for the idle current measurement by the factory mode.)
+ */
+int mt_irq_mask_restore(struct mtk_irq_mask *mask)
+{
+ if (mask == NULL) {
+ return -1;
+ }
+ if (mask->header != IRQ_MASK_HEADER) {
+ return -1;
+ }
+ if (mask->footer != IRQ_MASK_FOOTER) {
+ return -1;
+ }
+
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4),
+ mask->mask1);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8),
+ mask->mask2);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc),
+ mask->mask3);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10),
+ mask->mask4);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14),
+ mask->mask5);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18),
+ mask->mask6);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c),
+ mask->mask7);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20),
+ mask->mask8);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24),
+ mask->mask9);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28),
+ mask->mask10);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c),
+ mask->mask11);
+ mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30),
+ mask->mask12);
+ /* make sure dist changes happen */
+ dsb();
+
+ return 0;
+}
+
+/*
+ * mt_irq_mask_all: disable all interrupts
+ * @mask: pointer to struct mtk_irq_mask for storing the original mask value.
+ * Return 0 for success; return negative values for failure.
+ * (This is ONLY used for the idle current measurement by the factory mode.)
+ */
+int mt_irq_mask_all(struct mtk_irq_mask *mask)
+{
+ if (mask != NULL) {
+ /* for SPI */
+ mask->mask1 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x4));
+ mask->mask2 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x8));
+ mask->mask3 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0xc));
+ mask->mask4 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x10));
+ mask->mask5 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x14));
+ mask->mask6 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x18));
+ mask->mask7 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x1c));
+ mask->mask8 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x20));
+ mask->mask9 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x24));
+ mask->mask10 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x28));
+ mask->mask11 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x2c));
+ mask->mask12 = mmio_read_32((BASE_GICD_BASE +
+ GICD_ISENABLER + 0x30));
+
+ /* for SPI */
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c),
+ 0xFFFFFFFF);
+ mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30),
+ 0xFFFFFFFF);
+ /* make sure distributor changes happen */
+ dsb();
+
+ mask->header = IRQ_MASK_HEADER;
+ mask->footer = IRQ_MASK_FOOTER;
+
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+static uint32_t mt_irq_get_pol(uint32_t irq)
+{
+#ifdef CIRQ_WITH_POLARITY
+ uint32_t reg;
+ uint32_t base = INT_POL_CTL0;
+
+ if (irq < 32U) {
+ return 0;
+ }
+
+ reg = ((irq - 32U) / 32U);
+
+ return mmio_read_32(base + reg * 4U);
+#else
+ return 0;
+#endif
+}
+
+unsigned int mt_irq_get_sens(unsigned int irq)
+{
+ unsigned int config;
+
+ /*
+ * 2'b10 edge
+ * 2'b01 level
+ */
+ config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U);
+ config = (config >> (irq % 16U) * 2U) & 0x3;
+
+ return config;
+}
+
+static void collect_all_wakeup_events(void)
+{
+ unsigned int i;
+ uint32_t gic_irq;
+ uint32_t cirq;
+ uint32_t cirq_reg;
+ uint32_t cirq_offset;
+ uint32_t mask;
+ uint32_t pol_mask;
+ uint32_t irq_offset;
+ uint32_t irq_mask;
+
+ if ((cirq_all_events.wakeup_events == NULL) ||
+ cirq_all_events.num_of_events == 0U) {
+ return;
+ }
+
+ for (i = 0U; i < cirq_all_events.num_of_events; i++) {
+ if (cirq_all_events.wakeup_events[i] > 0U) {
+ gic_irq = cirq_all_events.wakeup_events[i];
+ cirq = gic_irq - cirq_all_events.spi_start - 32U;
+ cirq_reg = cirq / 32U;
+ cirq_offset = cirq % 32U;
+ mask = 0x1 << cirq_offset;
+ irq_offset = gic_irq % 32U;
+ irq_mask = 0x1 << irq_offset;
+ /*
+ * CIRQ default masks all
+ */
+ cirq_all_events.table[cirq_reg].mask |= mask;
+ /*
+ * CIRQ default pol is low
+ */
+ pol_mask = mt_irq_get_pol(
+ cirq_all_events.wakeup_events[i])
+ & irq_mask;
+ /*
+ * 0 means rising
+ */
+ if (pol_mask == 0U) {
+ cirq_all_events.table[cirq_reg].pol |= mask;
+ }
+ /*
+ * CIRQ could monitor edge/level trigger
+ * cirq register (0: edge, 1: level)
+ */
+ if (mt_irq_get_sens(cirq_all_events.wakeup_events[i])
+ == SENS_EDGE) {
+ cirq_all_events.table[cirq_reg].sen |= mask;
+ }
+
+ cirq_all_events.table[cirq_reg].used = 1U;
+ cirq_all_events.table[cirq_reg].reg_num = cirq_reg;
+ }
+ }
+}
+
+/*
+ * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
+ * @cirq_num: the SYS_CIRQ number to set
+ * @pol: polarity to set
+ * @return:
+ * 0: set pol success
+ * -1: cirq num is out of range
+ */
+#ifdef CIRQ_WITH_POLARITY
+static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
+{
+ uint32_t base;
+ uint32_t bit = 1U << (cirq_num % 32U);
+
+ if (cirq_num >= CIRQ_IRQ_NUM) {
+ return -1;
+ }
+
+ if (pol == MT_CIRQ_POL_NEG) {
+ base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
+ } else if (pol == MT_CIRQ_POL_POS) {
+ base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
+ } else {
+ return -1;
+ }
+
+ mmio_write_32(base, bit);
+ return 0;
+}
+#endif
+
+/*
+ * mt_cirq_mask: Mask the specified SYS_CIRQ.
+ * @cirq_num: the SYS_CIRQ number to mask
+ * @return:
+ * 0: mask success
+ * -1: cirq num is out of range
+ */
+static int mt_cirq_mask(uint32_t cirq_num)
+{
+ uint32_t bit = 1U << (cirq_num % 32U);
+
+ if (cirq_num >= CIRQ_IRQ_NUM) {
+ return -1;
+ }
+
+ mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit);
+
+ return 0;
+}
+
+/*
+ * mt_cirq_unmask: Unmask the specified SYS_CIRQ.
+ * @cirq_num: the SYS_CIRQ number to unmask
+ * @return:
+ * 0: umask success
+ * -1: cirq num is out of range
+ */
+static int mt_cirq_unmask(uint32_t cirq_num)
+{
+ uint32_t bit = 1U << (cirq_num % 32U);
+
+ if (cirq_num >= CIRQ_IRQ_NUM) {
+ return -1;
+ }
+
+ mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit);
+
+ return 0;
+}
+
+uint32_t mt_irq_get_en(uint32_t irq)
+{
+ uint32_t addr, st, val;
+
+ addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U;
+ st = mmio_read_32(addr);
+
+ val = (st >> (irq % 32U)) & 1U;
+
+ return val;
+}
+
+static void __cirq_fast_clone(void)
+{
+ struct cirq_reg *reg;
+ unsigned int i;
+
+ for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
+ uint32_t cirq_bit;
+
+ reg = &cirq_all_events.table[i];
+
+ if (reg->used == 0U) {
+ continue;
+ }
+
+ mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U),
+ reg->sen);
+
+ for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
+ uint32_t val, cirq_id;
+ uint32_t gic_id;
+#ifdef CIRQ_WITH_POLARITY
+ uint32_t gic_bit, pol;
+#endif
+ uint32_t en;
+
+ val = ((1U << cirq_bit) & reg->mask);
+
+ if (val == 0U) {
+ continue;
+ }
+
+ cirq_id = (reg->reg_num << 5U) + cirq_bit;
+ gic_id = CIRQ_TO_IRQ_NUM(cirq_id);
+#ifdef CIRQ_WITH_POLARITY
+ gic_bit = (0x1U << ((gic_id - 32U) % 32U));
+ pol = mt_irq_get_pol(gic_id) & gic_bit;
+ if (pol != 0U) {
+ mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG);
+ } else {
+ mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS);
+ }
+#endif
+ en = mt_irq_get_en(gic_id);
+ if (en == 1U) {
+ mt_cirq_unmask(cirq_id);
+ } else {
+ mt_cirq_mask(cirq_id);
+ }
+ }
+ }
+}
+
+static void cirq_fast_clone(void)
+{
+ if (already_cloned == 0U) {
+ collect_all_wakeup_events();
+ already_cloned = 1U;
+ }
+ __cirq_fast_clone();
+}
+
+void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
+{
+ cirq_all_events.num_of_events = num_of_events;
+ cirq_all_events.wakeup_events = list;
+}
+/*
+ * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
+ */
+void mt_cirq_clone_gic(void)
+{
+ cirq_fast_clone();
+}
+
+uint32_t mt_irq_get_pending_vec(uint32_t start_irq)
+{
+ uint32_t base = 0U;
+ uint32_t pending_vec = 0U;
+ uint32_t reg = start_irq / 32U;
+ uint32_t LSB_num, MSB_num;
+ uint32_t LSB_vec, MSB_vec;
+
+ base = BASE_GICD_BASE;
+
+ /* if start_irq is not aligned 32, do some assembling */
+ MSB_num = start_irq % 32U;
+ if (MSB_num != 0U) {
+ LSB_num = 32U - MSB_num;
+ LSB_vec = mmio_read_32(base + GICD_ISPENDR +
+ reg * 4U) >> MSB_num;
+ MSB_vec = mmio_read_32(base + GICD_ISPENDR +
+ (reg + 1U) * 4U) << LSB_num;
+ pending_vec = MSB_vec | LSB_vec;
+ } else {
+ pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4);
+ }
+
+ return pending_vec;
+}
+
+static int mt_cirq_get_mask_vec(unsigned int i)
+{
+ return mmio_read_32((i * 4U) + CIRQ_MASK_BASE);
+}
+
+/*
+ * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
+ */
+void mt_cirq_ack_all(void)
+{
+ uint32_t ack_vec, pend_vec, mask_vec;
+ unsigned int i;
+
+ for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) {
+ /*
+ * if a irq is pending & not masked, don't ack it
+ * , since cirq start irq might not be 32 aligned with gic,
+ * need an exotic API to get proper vector of pending irq
+ */
+ pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START
+ + (i + 1U) * 32U);
+ mask_vec = mt_cirq_get_mask_vec(i);
+ /* those should be acked are: "not (pending & not masked)",
+ */
+ ack_vec = (~pend_vec) | mask_vec;
+ mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec);
+ }
+
+ /*
+ * make sure all cirq setting take effect
+ * before doing other things
+ */
+ dsb();
+}
+/*
+ * mt_cirq_enable: Enable SYS_CIRQ
+ */
+void mt_cirq_enable(void)
+{
+ uint32_t st;
+
+ /* level only */
+ mt_cirq_ack_all();
+
+ st = mmio_read_32(CIRQ_CON);
+ /*
+ * CIRQ could monitor edge/level trigger
+ */
+ st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS);
+
+ mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
+}
+
+/*
+ * mt_cirq_disable: Disable SYS_CIRQ
+ */
+void mt_cirq_disable(void)
+{
+ uint32_t st;
+
+ st = mmio_read_32(CIRQ_CON);
+ st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
+ mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
+}
+
+void mt_irq_unmask_for_sleep_ex(uint32_t irq)
+{
+ uint32_t mask;
+
+ mask = 1U << (irq % 32U);
+
+ mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER +
+ ((irq / 32U) * 4U), mask);
+}
+
+void mt_cirq_mask_all(void)
+{
+ unsigned int i;
+
+ for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
+ mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF);
+ }
+ dsb();
+}
+
+static void cirq_fast_sw_flush(void)
+{
+ struct cirq_reg *reg;
+ unsigned int i;
+
+ for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
+ uint32_t cirq_bit;
+
+ reg = &cirq_all_events.table[i];
+
+ if (reg->used == 0U) {
+ continue;
+ }
+
+ reg->pending = mmio_read_32(CIRQ_STA_BASE +
+ (reg->reg_num << 2U));
+ reg->pending &= reg->mask;
+
+ for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
+ uint32_t val, cirq_id;
+
+ val = (1U << cirq_bit) & reg->pending;
+ if (val == 0U) {
+ continue;
+ }
+
+ cirq_id = (reg->reg_num << 5U) + cirq_bit;
+ mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id));
+ if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) {
+ INFO("Set MD_WDT_IRQ pending in %s\n",
+ __func__);
+ }
+ }
+ }
+}
+
+/*
+ * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
+ */
+void mt_cirq_flush(void)
+{
+ cirq_fast_sw_flush();
+ mt_cirq_mask_all();
+ mt_cirq_ack_all();
+}
+
+void mt_cirq_sw_reset(void)
+{
+ uint32_t st;
+
+ st = mmio_read_32(CIRQ_CON);
+ st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
+ mmio_write_32(CIRQ_CON, st);
+}
diff --git a/plat/mediatek/drivers/cirq/mt_cirq.h b/plat/mediatek/drivers/cirq/mt_cirq.h
new file mode 100644
index 0000000..cb96295
--- /dev/null
+++ b/plat/mediatek/drivers/cirq/mt_cirq.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MT_CIRQ_H
+#define PLAT_MT_CIRQ_H
+
+#include <stdint.h>
+#include <platform_def.h>
+
+enum {
+ IRQ_MASK_HEADER = 0xF1F1F1F1,
+ IRQ_MASK_FOOTER = 0xF2F2F2F2
+};
+
+struct mtk_irq_mask {
+ uint32_t header; /* for error checking */
+ uint32_t mask0;
+ uint32_t mask1;
+ uint32_t mask2;
+ uint32_t mask3;
+ uint32_t mask4;
+ uint32_t mask5;
+ uint32_t mask6;
+ uint32_t mask7;
+ uint32_t mask8;
+ uint32_t mask9;
+ uint32_t mask10;
+ uint32_t mask11;
+ uint32_t mask12;
+ uint32_t footer; /* for error checking */
+};
+
+/*
+ * Define hardware register
+ */
+#define CIRQ_STA_BASE (SYS_CIRQ_BASE + U(0x000))
+#define CIRQ_ACK_BASE (SYS_CIRQ_BASE + U(0x080))
+#define CIRQ_MASK_BASE (SYS_CIRQ_BASE + U(0x100))
+#define CIRQ_MASK_SET_BASE (SYS_CIRQ_BASE + U(0x180))
+#define CIRQ_MASK_CLR_BASE (SYS_CIRQ_BASE + U(0x200))
+#define CIRQ_SENS_BASE (SYS_CIRQ_BASE + U(0x280))
+#define CIRQ_SENS_SET_BASE (SYS_CIRQ_BASE + U(0x300))
+#define CIRQ_SENS_CLR_BASE (SYS_CIRQ_BASE + U(0x380))
+#define CIRQ_POL_BASE (SYS_CIRQ_BASE + U(0x400))
+#define CIRQ_POL_SET_BASE (SYS_CIRQ_BASE + U(0x480))
+#define CIRQ_POL_CLR_BASE (SYS_CIRQ_BASE + U(0x500))
+#define CIRQ_CON (SYS_CIRQ_BASE + U(0x600))
+
+/*
+ * Register placement
+ */
+#define CIRQ_CON_EN_BITS U(0)
+#define CIRQ_CON_EDGE_ONLY_BITS U(1)
+#define CIRQ_CON_FLUSH_BITS U(2)
+#define CIRQ_CON_SW_RST_BITS U(20)
+#define CIRQ_CON_EVENT_BITS U(31)
+#define CIRQ_CON_BITS_MASK U(0x7)
+
+/*
+ * Register setting
+ */
+#define CIRQ_CON_EN U(0x1)
+#define CIRQ_CON_EDGE_ONLY U(0x1)
+#define CIRQ_CON_FLUSH U(0x1)
+#define CIRQ_SW_RESET U(0x1)
+
+/*
+ * Define constant
+ */
+#define CIRQ_CTRL_REG_NUM ((CIRQ_IRQ_NUM + 31U) / 32U)
+
+#define MT_CIRQ_POL_NEG U(0)
+#define MT_CIRQ_POL_POS U(1)
+
+#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (32U + CIRQ_SPI_START))
+#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (32U + CIRQ_SPI_START))
+
+/* GIC sensitive */
+#define SENS_EDGE U(0x2)
+#define SENS_LEVEL U(0x1)
+
+
+/*
+ * Define function prototypes.
+ */
+int mt_cirq_test(void);
+void mt_cirq_dump_reg(void);
+int mt_irq_mask_restore(struct mtk_irq_mask *mask);
+int mt_irq_mask_all(struct mtk_irq_mask *mask);
+void mt_cirq_clone_gic(void);
+void mt_cirq_enable(void);
+void mt_cirq_flush(void);
+void mt_cirq_disable(void);
+void mt_irq_unmask_for_sleep_ex(uint32_t irq);
+void set_wakeup_sources(uint32_t *list, uint32_t num_of_events);
+void mt_cirq_sw_reset(void);
+
+struct cirq_reg {
+ uint32_t reg_num;
+ uint32_t used;
+ uint32_t mask;
+ uint32_t pol;
+ uint32_t sen;
+ uint32_t pending;
+ uint32_t the_link;
+};
+
+struct cirq_events {
+ uint32_t num_reg;
+ uint32_t spi_start;
+ uint32_t num_of_events;
+ uint32_t *wakeup_events;
+ struct cirq_reg table[CIRQ_REG_NUM];
+ uint32_t dist_base;
+ uint32_t cirq_base;
+ uint32_t used_reg_head;
+};
+
+#endif /* PLAT_MT_CIRQ_H */
diff --git a/plat/mediatek/drivers/cirq/rules.mk b/plat/mediatek/drivers/cirq/rules.mk
new file mode 100644
index 0000000..710eae0
--- /dev/null
+++ b/plat/mediatek/drivers/cirq/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := cirq
+LOCAL_SRCS-y := $(LOCAL_DIR)/mt_cirq.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.c b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.c
new file mode 100644
index 0000000..313ad47
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <lib/spinlock.h>
+
+#include <lib/mtk_init/mtk_init.h>
+#include <lib/pm/mtk_pm.h>
+#include "mt_cpu_pm.h"
+#include "mt_cpu_pm_cpc.h"
+#include "mt_cpu_pm_mbox.h"
+#include <mt_lp_rm.h>
+#include "mt_smp.h"
+#include <mtk_mmap_pool.h>
+#include <platform_def.h>
+
+/*
+ * The locker must use the bakery locker when cache turns off.
+ * Using spin_lock will gain better performance.
+ */
+#ifdef MT_CPU_PM_USING_BAKERY_LOCK
+DEFINE_BAKERY_LOCK(mt_cpu_pm_lock);
+#define plat_cpu_pm_lock_init() bakery_lock_init(&mt_cpu_pm_lock)
+#define plat_cpu_pm_lock() bakery_lock_get(&mt_cpu_pm_lock)
+#define plat_cpu_pm_unlock() bakery_lock_release(&mt_cpu_pm_lock)
+#else
+spinlock_t mt_cpu_pm_lock;
+#define plat_cpu_pm_lock_init()
+#define plat_cpu_pm_lock() spin_lock(&mt_cpu_pm_lock)
+#define plat_cpu_pm_unlock() spin_unlock(&mt_cpu_pm_lock)
+#endif
+
+enum mt_pwr_node {
+ MT_PWR_NONMCUSYS = 0,
+ MT_PWR_MCUSYS_PDN,
+ MT_PWR_SUSPEND,
+ MT_PWR_SYSTEM_MEM,
+ MT_PWR_SYSTEM_PLL,
+ MT_PWR_SYSTEM_BUS,
+ MT_PWR_MAX,
+};
+
+#define CPU_PM_DEPD_INIT BIT(0)
+#define CPU_PM_DEPD_READY BIT(1)
+#define CPU_PM_PLAT_READY BIT(2)
+
+#ifdef CPU_PM_TINYSYS_SUPPORT
+#define CPU_PM_INIT_READY (CPU_PM_DEPD_INIT | CPU_PM_DEPD_READY)
+#define CPU_PM_LP_READY (CPU_PM_INIT_READY | CPU_PM_PLAT_READY)
+#else
+#define CPU_PM_LP_READY (CPU_PM_PLAT_READY)
+#endif
+
+#if CONFIG_MTK_PM_SUPPORT
+
+#if CONFIG_MTK_CPU_SUSPEND_EN || CONFIG_MTK_SMP_EN
+static void cpupm_cpu_resume_common(const struct mtk_cpupm_pwrstate *state)
+{
+ CPU_PM_ASSERT(state != NULL);
+ mtk_cpc_core_on_hint_clr(state->info.cpuid);
+}
+#endif
+
+#if CONFIG_MTK_SMP_EN
+static int cpupm_cpu_pwr_on_prepare(unsigned int cpu, uintptr_t entry)
+{
+ struct cpu_pwr_ctrl pwr_ctrl;
+
+ PER_CPU_PWR_CTRL(pwr_ctrl, cpu);
+ mt_smp_core_bootup_address_set(&pwr_ctrl, entry);
+ mt_smp_core_init_arch(0, cpu, 1, &pwr_ctrl);
+
+ return mt_smp_power_core_on(cpu, &pwr_ctrl);
+}
+
+static void cpupm_cpu_resume_smp(const struct mtk_cpupm_pwrstate *state)
+{
+ CPU_PM_ASSERT(state != NULL);
+
+ plat_cpu_pm_lock();
+ mmio_clrbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+ GIC_WAKEUP_IGNORE(state->info.cpuid));
+ plat_cpu_pm_unlock();
+ cpupm_cpu_resume_common(state);
+}
+
+static void cpupm_cpu_suspend_smp(const struct mtk_cpupm_pwrstate *state)
+{
+ struct cpu_pwr_ctrl pwr_ctrl;
+
+ CPU_PM_ASSERT(state != NULL);
+
+ PER_CPU_PWR_CTRL(pwr_ctrl, state->info.cpuid);
+ mt_smp_power_core_off(&pwr_ctrl);
+ mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+ GIC_WAKEUP_IGNORE(state->info.cpuid));
+}
+
+static void cpupm_smp_init(unsigned int cpu, uintptr_t sec_entrypoint)
+{
+ unsigned int reg;
+ struct mtk_cpupm_pwrstate state = {
+ .info = {
+ .cpuid = cpu,
+ .mode = MTK_CPU_PM_SMP,
+ },
+ .pwr = {
+ .afflv = 0,
+ .state_id = 0,
+ },
+ };
+
+ reg = mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG);
+ if ((reg & CPC_MCUSYS_CPC_RESET_PWR_ON_EN) != 0) {
+ INFO("[%s:%d][CPU_PM] reset pwr on is enabled then clear it!\n",
+ __func__, __LINE__);
+ mmio_clrbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_MCUSYS_CPC_RESET_PWR_ON_EN);
+ }
+
+ cpupm_cpu_pwr_on_prepare(cpu, sec_entrypoint);
+ cpupm_cpu_resume_smp(&state);
+}
+
+static struct mtk_cpu_smp_ops cpcv3_2_cpu_smp = {
+ .init = cpupm_smp_init,
+ .cpu_pwr_on_prepare = cpupm_cpu_pwr_on_prepare,
+ .cpu_on = cpupm_cpu_resume_smp,
+ .cpu_off = cpupm_cpu_suspend_smp,
+};
+
+#endif /* CONFIG_MTK_SMP_EN */
+
+#if CONFIG_MTK_CPU_SUSPEND_EN
+#define CPUPM_READY_MS (40000)
+#define CPUPM_ARCH_TIME_MS(ms) (ms * 1000 * SYS_COUNTER_FREQ_IN_MHZ)
+#define CPUPM_BOOTUP_TIME_THR CPUPM_ARCH_TIME_MS(CPUPM_READY_MS)
+
+static int mt_pwr_nodes[MT_PWR_MAX];
+static int plat_mt_lp_cpu_rc;
+static unsigned int cpu_pm_status;
+static unsigned int plat_prev_stateid;
+
+static int mcusys_prepare_suspend(const struct mtk_cpupm_pwrstate *state)
+{
+ unsigned int stateid = state->pwr.state_id;
+
+ if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (!IS_PLAT_SUSPEND_ID(stateid)) {
+ if (mt_pwr_nodes[MT_PWR_SYSTEM_MEM] != 0) {
+ stateid = MT_PLAT_PWR_STATE_SYSTEM_MEM;
+ } else if (mt_pwr_nodes[MT_PWR_SYSTEM_PLL] != 0) {
+ stateid = MT_PLAT_PWR_STATE_SYSTEM_PLL;
+ } else if (mt_pwr_nodes[MT_PWR_SYSTEM_BUS] != 0) {
+ stateid = MT_PLAT_PWR_STATE_SYSTEM_BUS;
+ } else if (mt_pwr_nodes[MT_PWR_SUSPEND] != 0) {
+ stateid = MT_PLAT_PWR_STATE_SUSPEND;
+ } else {
+ stateid = MT_PLAT_PWR_STATE_MCUSYS;
+ }
+ }
+
+ plat_prev_stateid = stateid;
+ plat_mt_lp_cpu_rc = mt_lp_rm_find_and_run_constraint(0, state->info.cpuid, stateid, NULL);
+
+ if (plat_mt_lp_cpu_rc < 0) {
+ goto mt_pwr_mcusysoff_reflect;
+ }
+
+#ifdef CPU_PM_TINYSYS_SUPPORT
+ mtk_set_cpu_pm_preffered_cpu(state->info.cpuid);
+#endif
+ return MTK_CPUPM_E_OK;
+
+mt_pwr_mcusysoff_reflect:
+ mtk_cpc_mcusys_off_reflect();
+mt_pwr_mcusysoff_break:
+ plat_mt_lp_cpu_rc = -1;
+
+ return MTK_CPUPM_E_FAIL;
+}
+
+static int mcusys_prepare_resume(const struct mtk_cpupm_pwrstate *state)
+{
+ if (plat_mt_lp_cpu_rc < 0) {
+ return MTK_CPUPM_E_FAIL;
+ }
+
+ mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, state->info.cpuid, plat_prev_stateid);
+ mtk_cpc_mcusys_off_reflect();
+ return MTK_CPUPM_E_OK;
+}
+
+static unsigned int cpupm_do_pstate_off(const mtk_pstate_type psci_state,
+ const struct mtk_cpupm_pwrstate *state)
+{
+ unsigned int pstate = MT_CPUPM_PWR_DOMAIN_CORE;
+
+ if (!state || (state->pwr.afflv > PLAT_MAX_PWR_LVL)) {
+ CPU_PM_ASSERT(0);
+ }
+
+ switch (state->pwr.state_id) {
+ case MT_PLAT_PWR_STATE_SYSTEM_MEM:
+ mt_pwr_nodes[MT_PWR_SYSTEM_MEM] += 1;
+ break;
+ case MT_PLAT_PWR_STATE_SYSTEM_PLL:
+ mt_pwr_nodes[MT_PWR_SYSTEM_PLL] += 1;
+ break;
+ case MT_PLAT_PWR_STATE_SYSTEM_BUS:
+ mt_pwr_nodes[MT_PWR_SYSTEM_BUS] += 1;
+ break;
+ case MT_PLAT_PWR_STATE_SUSPEND:
+ mt_pwr_nodes[MT_PWR_SUSPEND] += 1;
+ break;
+ default:
+ if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id) &&
+ !IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv)) {
+ plat_cpu_pm_lock();
+ mt_pwr_nodes[MT_PWR_NONMCUSYS] += 1;
+ flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_NONMCUSYS],
+ sizeof(mt_pwr_nodes[MT_PWR_NONMCUSYS]));
+ plat_cpu_pm_unlock();
+ }
+ break;
+ }
+
+ if ((mt_pwr_nodes[MT_PWR_NONMCUSYS] == 0) && IS_PLAT_MCUSYSOFF_AFFLV(state->pwr.afflv)) {
+ /* Prepare to power down mcusys */
+ if (mcusys_prepare_suspend(state) == MTK_CPUPM_E_OK) {
+ mt_pwr_nodes[MT_PWR_MCUSYS_PDN] += 1;
+ flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_MCUSYS_PDN],
+ sizeof(mt_pwr_nodes[MT_PWR_MCUSYS_PDN]));
+ pstate |= (MT_CPUPM_PWR_DOMAIN_MCUSYS | MT_CPUPM_PWR_DOMAIN_CLUSTER);
+ }
+ }
+
+ if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) {
+ pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER;
+ }
+
+ if (psci_get_pstate_pwrlvl(psci_state) >= PLAT_MT_CPU_SUSPEND_CLUSTER) {
+ pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU;
+ }
+
+ return pstate;
+}
+
+static unsigned int cpupm_do_pstate_on(const mtk_pstate_type psci_state,
+ const struct mtk_cpupm_pwrstate *state)
+{
+ unsigned int pstate = MT_CPUPM_PWR_DOMAIN_CORE;
+
+ CPU_PM_ASSERT(state != NULL);
+
+ if (state->pwr.afflv > PLAT_MAX_PWR_LVL) {
+ CPU_PM_ASSERT(0);
+ }
+
+ if (mt_pwr_nodes[MT_PWR_MCUSYS_PDN] != 0) {
+ mt_pwr_nodes[MT_PWR_MCUSYS_PDN] = 0;
+ flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_MCUSYS_PDN],
+ sizeof(mt_pwr_nodes[MT_PWR_MCUSYS_PDN]));
+ pstate |= (MT_CPUPM_PWR_DOMAIN_MCUSYS | MT_CPUPM_PWR_DOMAIN_CLUSTER);
+ mcusys_prepare_resume(state);
+ }
+
+ if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) {
+ pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER;
+ }
+
+ switch (state->pwr.state_id) {
+ case MT_PLAT_PWR_STATE_SYSTEM_MEM:
+ mt_pwr_nodes[MT_PWR_SYSTEM_MEM] -= 1;
+ CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_MEM] >= 0);
+ break;
+ case MT_PLAT_PWR_STATE_SYSTEM_PLL:
+ mt_pwr_nodes[MT_PWR_SYSTEM_PLL] -= 1;
+ CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_PLL] >= 0);
+ break;
+ case MT_PLAT_PWR_STATE_SYSTEM_BUS:
+ mt_pwr_nodes[MT_PWR_SYSTEM_BUS] -= 1;
+ CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_BUS] >= 0);
+ break;
+ case MT_PLAT_PWR_STATE_SUSPEND:
+ mt_pwr_nodes[MT_PWR_SUSPEND] -= 1;
+ CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SUSPEND] >= 0);
+ break;
+ default:
+ if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id) &&
+ !IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv)) {
+ plat_cpu_pm_lock();
+ mt_pwr_nodes[MT_PWR_NONMCUSYS] -= 1;
+ flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_NONMCUSYS],
+ sizeof(mt_pwr_nodes[MT_PWR_NONMCUSYS]));
+ plat_cpu_pm_unlock();
+ }
+ break;
+ }
+
+ if (IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv) ||
+ (IS_PLAT_SYSTEM_RETENTION(state->pwr.afflv) && (mt_pwr_nodes[MT_PWR_SUSPEND] > 0))) {
+ mtk_cpc_time_sync();
+ }
+
+ if (mt_pwr_nodes[MT_PWR_NONMCUSYS] < 0) {
+ CPU_PM_ASSERT(0);
+ }
+
+ pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU;
+
+ return pstate;
+}
+
+static void cpupm_cpu_resume(const struct mtk_cpupm_pwrstate *state)
+{
+ cpupm_cpu_resume_common(state);
+}
+
+static void cpupm_mcusys_resume(const struct mtk_cpupm_pwrstate *state)
+{
+ assert(state != NULL);
+}
+
+static void cpupm_mcusys_suspend(const struct mtk_cpupm_pwrstate *state)
+{
+ assert(state != NULL);
+}
+
+static unsigned int cpupm_get_pstate(enum mt_cpupm_pwr_domain domain,
+ const mtk_pstate_type psci_state,
+ const struct mtk_cpupm_pwrstate *state)
+{
+ unsigned int pstate = 0;
+
+ if (state == NULL) {
+ return 0;
+ }
+
+ if (state->info.mode == MTK_CPU_PM_SMP) {
+ pstate = MT_CPUPM_PWR_DOMAIN_CORE;
+ } else {
+ if (domain == CPUPM_PWR_OFF) {
+ pstate = cpupm_do_pstate_off(psci_state, state);
+ } else if (domain == CPUPM_PWR_ON) {
+ pstate = cpupm_do_pstate_on(psci_state, state);
+ } else {
+ INFO("[%s:%d][CPU_PM] unknown pwr domain :%d\n",
+ __func__, __LINE__, domain);
+ assert(0);
+ }
+ }
+ return pstate;
+}
+
+static int cpupm_init(void)
+{
+ int ret = MTK_CPUPM_E_OK;
+
+#ifdef CPU_PM_TINYSYS_SUPPORT
+ int status;
+
+ if ((cpu_pm_status & CPU_PM_INIT_READY) == CPU_PM_INIT_READY) {
+ return MTK_CPUPM_E_OK;
+ }
+
+ if (!(cpu_pm_status & CPU_PM_DEPD_INIT)) {
+ status = mtk_lp_depd_condition(CPUPM_MBOX_WAIT_DEV_INIT);
+ if (status == 0) {
+ plat_cpu_pm_lock();
+ cpu_pm_status |= CPU_PM_DEPD_INIT;
+ plat_cpu_pm_unlock();
+ }
+ }
+
+ if ((cpu_pm_status & CPU_PM_DEPD_INIT) && !(cpu_pm_status & CPU_PM_DEPD_READY)) {
+ status = mtk_lp_depd_condition(CPUPM_MBOX_WAIT_TASK_READY);
+ if (status == 0) {
+ plat_cpu_pm_lock();
+ cpu_pm_status |= CPU_PM_DEPD_READY;
+ plat_cpu_pm_unlock();
+ }
+ }
+
+ ret = ((cpu_pm_status & CPU_PM_INIT_READY) == CPU_PM_INIT_READY) ?
+ MTK_CPUPM_E_OK : MTK_CPUPM_E_FAIL;
+#endif
+ return ret;
+}
+
+static int cpupm_pwr_state_valid(unsigned int afflv, unsigned int state)
+{
+ if (cpu_pm_status == CPU_PM_LP_READY) {
+ return MTK_CPUPM_E_OK;
+ }
+
+ if (cpupm_init() != MTK_CPUPM_E_OK) {
+ return MTK_CPUPM_E_FAIL;
+ }
+
+ if (read_cntpct_el0() >= (uint64_t)CPUPM_BOOTUP_TIME_THR) {
+ plat_cpu_pm_lock();
+ cpu_pm_status |= CPU_PM_PLAT_READY;
+ plat_cpu_pm_unlock();
+ }
+
+ if (!IS_PLAT_SYSTEM_SUSPEND(afflv) && (cpu_pm_status & CPU_PM_PLAT_READY) == 0) {
+ return MTK_CPUPM_E_FAIL;
+ }
+
+ return MTK_CPUPM_E_OK;
+}
+
+static struct mtk_cpu_pm_ops cpcv3_2_mcdi = {
+ .get_pstate = cpupm_get_pstate,
+ .pwr_state_valid = cpupm_pwr_state_valid,
+ .cpu_resume = cpupm_cpu_resume,
+ .mcusys_suspend = cpupm_mcusys_suspend,
+ .mcusys_resume = cpupm_mcusys_resume,
+};
+#endif /* CONFIG_MTK_CPU_SUSPEND_EN */
+
+#endif /* CONFIG_MTK_PM_SUPPORT */
+
+/*
+ * Depend on mtk pm methodology, the psci op init must
+ * be invoked after cpu pm to avoid initialization fail.
+ */
+int mt_plat_cpu_pm_init(void)
+{
+ plat_cpu_pm_lock_init();
+
+ mtk_cpc_init();
+#if CONFIG_MTK_PM_SUPPORT
+
+#if CONFIG_MTK_CPU_SUSPEND_EN
+ register_cpu_pm_ops(CPU_PM_FN, &cpcv3_2_mcdi);
+#endif /* CONFIG_MTK_CPU_SUSPEND_EN */
+
+#if CONFIG_MTK_SMP_EN
+ register_cpu_smp_ops(CPU_PM_FN, &cpcv3_2_cpu_smp);
+#endif /* CONFIG_MTK_SMP_EN */
+
+#endif /* CONFIG_MTK_PM_SUPPORT */
+
+ INFO("[%s:%d] - CPU PM INIT finished\n", __func__, __LINE__);
+ return 0;
+}
+MTK_ARCH_INIT(mt_plat_cpu_pm_init);
+
+static const mmap_region_t cpu_pm_mmap[] MTK_MMAP_SECTION = {
+#ifdef CPU_PM_TINYSYS_SUPPORT
+#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN
+ MAP_REGION_FLAT(CPU_EB_TCM_BASE, CPU_EB_TCM_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+#endif
+ {0}
+};
+DECLARE_MTK_MMAP_REGIONS(cpu_pm_mmap);
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.h b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.h
new file mode 100644
index 0000000..4d99df1
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_H
+#define MT_CPU_PM_H
+
+#include <assert.h>
+#include <mcucfg.h>
+#include <platform_def.h>
+
+/*
+ * After ARM v8.2, the cache will turn off automatically when powering down CPU. Therefore, there
+ * is no doubt to use the spin_lock here.
+ */
+#if !HW_ASSISTED_COHERENCY
+#define MT_CPU_PM_USING_BAKERY_LOCK
+#endif
+
+#define CPU_PM_FN (MTK_CPUPM_FN_CPUPM_GET_PWR_STATE | \
+ MTK_CPUPM_FN_PWR_STATE_VALID | \
+ MTK_CPUPM_FN_PWR_ON_CORE_PREPARE | \
+ MTK_CPUPM_FN_RESUME_CORE | \
+ MTK_CPUPM_FN_SUSPEND_MCUSYS | \
+ MTK_CPUPM_FN_RESUME_MCUSYS | \
+ MTK_CPUPM_FN_SMP_INIT | \
+ MTK_CPUPM_FN_SMP_CORE_ON | \
+ MTK_CPUPM_FN_SMP_CORE_OFF)
+
+#define CPU_PM_ASSERT(_cond) ({ \
+ if (!(_cond)) { \
+ INFO("[%s:%d] - %s\n", __func__, __LINE__, #_cond); \
+ panic(); \
+ } })
+
+#define CPC_PWR_MASK_MCUSYS_MP0 (0xC001)
+
+#define PER_CPU_PWR_DATA(ctrl, cluster, core) \
+ do { \
+ ctrl.rvbaraddr_l = CORE_RVBRADDR_##cluster##_##core##_L; \
+ ctrl.arch_addr = MCUCFG_MP0_CLUSTER_CFG5; \
+ ctrl.pwpr = SPM_MP##cluster##_CPU##core##_PWR_CON; \
+ } while (0)
+
+#define PER_CPU_PWR_CTRL(ctrl, cpu) ({ \
+ switch (cpu) { \
+ case 0: \
+ PER_CPU_PWR_DATA(ctrl, 0, 0); \
+ break; \
+ case 1: \
+ PER_CPU_PWR_DATA(ctrl, 0, 1); \
+ break; \
+ case 2: \
+ PER_CPU_PWR_DATA(ctrl, 0, 2); \
+ break; \
+ case 3: \
+ PER_CPU_PWR_DATA(ctrl, 0, 3); \
+ break; \
+ case 4: \
+ PER_CPU_PWR_DATA(ctrl, 0, 4); \
+ break; \
+ case 5: \
+ PER_CPU_PWR_DATA(ctrl, 0, 5); \
+ break; \
+ case 6: \
+ PER_CPU_PWR_DATA(ctrl, 0, 6); \
+ break; \
+ case 7: \
+ PER_CPU_PWR_DATA(ctrl, 0, 7); \
+ break; \
+ default: \
+ assert(0); \
+ break; \
+ } })
+
+
+/* MCUSYS DREQ BIG VPROC ISO control */
+#define DREQ20_BIG_VPROC_ISO (MCUCFG_BASE + 0xad8c)
+
+/* Definition about bootup address for each core CORE_RVBRADDR_clusterid_cpuid */
+#define CORE_RVBRADDR_0_0_L (MCUCFG_BASE + 0xc900)
+#define CORE_RVBRADDR_0_1_L (MCUCFG_BASE + 0xc908)
+#define CORE_RVBRADDR_0_2_L (MCUCFG_BASE + 0xc910)
+#define CORE_RVBRADDR_0_3_L (MCUCFG_BASE + 0xc918)
+#define CORE_RVBRADDR_0_4_L (MCUCFG_BASE + 0xc920)
+#define CORE_RVBRADDR_0_5_L (MCUCFG_BASE + 0xc928)
+#define CORE_RVBRADDR_0_6_L (MCUCFG_BASE + 0xc930)
+#define CORE_RVBRADDR_0_7_L (MCUCFG_BASE + 0xc938)
+#define MCUCFG_MP0_CLUSTER_CFG5 (MCUCFG_BASE + 0xc8e4)
+
+struct cpu_pwr_ctrl {
+ unsigned int rvbaraddr_l;
+ unsigned int arch_addr;
+ unsigned int pwpr;
+};
+
+#define MCUSYS_STATUS_PDN BIT(0)
+#define MCUSYS_STATUS_CPUSYS_PROTECT BIT(8)
+#define MCUSYS_STATUS_MCUSYS_PROTECT BIT(9)
+
+/* cpu_pm function ID */
+enum mt_cpu_pm_user_id {
+ MCUSYS_STATUS,
+ CPC_COMMAND,
+};
+
+/* cpu_pm lp function ID */
+enum mt_cpu_pm_lp_smc_id {
+ LP_CPC_COMMAND,
+ IRQS_REMAIN_ALLOC,
+ IRQS_REMAIN_CTRL,
+ IRQS_REMAIN_IRQ,
+ IRQS_REMAIN_WAKEUP_CAT,
+ IRQS_REMAIN_WAKEUP_SRC,
+};
+
+#endif /* MT_CPU_PM_H */
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c
new file mode 100644
index 0000000..4cc2203
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include "mt_cpu_pm.h"
+#include "mt_cpu_pm_cpc.h"
+#include "mt_smp.h"
+#include <mt_timer.h>
+
+struct mtk_cpc_dev {
+ int auto_off;
+ unsigned int auto_thres_tick;
+};
+
+static struct mtk_cpc_dev cpc;
+
+static int mtk_cpc_last_core_prot(int prot_req, int resp_reg, int resp_ofs)
+{
+ unsigned int staus;
+ unsigned int retry = 0;
+
+ while (retry < RETRY_CNT_MAX) {
+ retry++;
+
+ mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
+
+ udelay(1);
+
+ staus = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
+
+ if (staus == PROT_SUCCESS) {
+ return CPC_SUCCESS;
+ } else if (staus == PROT_GIVEUP) {
+ return CPC_ERR_FAIL;
+ }
+ }
+
+ return CPC_ERR_TIMEOUT;
+}
+
+static int mtk_cpu_pm_mcusys_prot_aquire(void)
+{
+ return mtk_cpc_last_core_prot(MCUSYS_PROT_SET, CPC_MCUSYS_LAST_CORE_RESP, MCUSYS_RESP_OFS);
+}
+
+static void mtk_cpu_pm_mcusys_prot_release(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
+}
+
+int mtk_cpu_pm_cluster_prot_aquire(void)
+{
+ return mtk_cpc_last_core_prot(CPUSYS_PROT_SET, CPC_MCUSYS_MP_LAST_CORE_RESP,
+ CPUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_cluster_prot_release(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
+}
+
+static void mtk_cpc_cluster_cnt_backup(void)
+{
+ /* single cluster */
+ uint32_t backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
+ uint32_t curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
+
+ if ((curr_cnt & 0x7fff) == 0) {
+ curr_cnt = (curr_cnt >> 16) & 0x7fff;
+ } else {
+ curr_cnt = curr_cnt & 0x7fff;
+ }
+
+ mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
+ mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, 0x3);
+}
+
+static inline void mtk_cpc_mcusys_off_enable(bool enable)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, enable ? 1 : 0);
+}
+
+void mtk_cpc_mcusys_off_reflect(void)
+{
+ mtk_cpc_mcusys_off_enable(false);
+ mtk_cpu_pm_mcusys_prot_release();
+}
+
+int mtk_cpc_mcusys_off_prepare(void)
+{
+ if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
+ return CPC_ERR_FAIL;
+ }
+
+ mtk_cpc_cluster_cnt_backup();
+ mtk_cpc_mcusys_off_enable(true);
+
+ return CPC_SUCCESS;
+}
+
+void mtk_cpc_core_on_hint_set(int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
+}
+
+void mtk_cpc_core_on_hint_clr(int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+static void mtk_cpc_dump_timestamp(void)
+{
+ unsigned int id;
+
+ for (id = 0; id < CPC_TRACE_ID_NUM; id++) {
+ mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
+
+ memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
+ (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
+ CPC_TRACE_SIZE);
+ }
+}
+
+void mtk_cpc_time_sync(void)
+{
+ uint64_t kt;
+ uint32_t systime_l, systime_h;
+
+ kt = sched_clock();
+ systime_l = mmio_read_32(CNTSYS_L_REG);
+ systime_h = mmio_read_32(CNTSYS_H_REG);
+
+ /* sync kernel timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
+
+ /* sync system timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
+}
+
+static void mtk_cpc_config(unsigned int cfg, unsigned int data)
+{
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ if (data) {
+ mmio_setbits_32(CPC_MCUSYS_CPC_DBG_SETTING, CPC_PROF_EN);
+ } else {
+ mmio_clrbits_32(CPC_MCUSYS_CPC_DBG_SETTING, CPC_PROF_EN);
+ }
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ if (data) {
+ mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_AUTO_OFF_EN);
+ cpc.auto_off = 1;
+ } else {
+ mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_AUTO_OFF_EN);
+ cpc.auto_off = 0;
+ }
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ cpc.auto_thres_tick = US_TO_TICKS(data);
+ mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, 0x3);
+ break;
+ case CPC_SMC_CONFIG_TIME_SYNC:
+ mtk_cpc_time_sync();
+ break;
+ default:
+ break;
+ }
+}
+
+static unsigned int mtk_cpc_read_config(unsigned int cfg)
+{
+ unsigned int res = 0;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ? 1 : 0;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ res = cpc.auto_off;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ res = TICKS_TO_US(cpc.auto_thres_tick);
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ default:
+ break;
+ }
+
+ return res;
+}
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t res = 0;
+
+ switch (act) {
+ case CPC_SMC_EVENT_CPC_CONFIG:
+ mtk_cpc_config((unsigned int)arg1, (unsigned int)arg2);
+ break;
+ case CPC_SMC_EVENT_READ_CONFIG:
+ res = mtk_cpc_read_config((unsigned int)arg1);
+ break;
+ case CPC_SMC_EVENT_GIC_DPG_SET:
+ /* isolated_status = x2; */
+ default:
+ break;
+ }
+
+ return res;
+}
+
+uint64_t mtk_cpc_trace_dump(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+ switch (act) {
+ case CPC_SMC_EVENT_DUMP_TRACE_DATA:
+ mtk_cpc_dump_timestamp();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void mtk_cpc_init(void)
+{
+#if CONFIG_MTK_SMP_EN
+ mt_smp_init();
+#endif
+ mmio_setbits_32(CPC_MCUSYS_CPC_DBG_SETTING, (CPC_DBG_EN | CPC_CALC_EN));
+
+ cpc.auto_off = 1;
+ mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, (CPC_OFF_PRE_EN |
+ ((cpc.auto_off > 0) ? CPC_AUTO_OFF_EN : 0)));
+
+ mtk_cpc_config(CPC_SMC_CONFIG_AUTO_OFF_THRES, 8000);
+
+ /* enable CPC */
+ mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+ mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN);
+}
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.h b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.h
new file mode 100644
index 0000000..3004f41
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_cpc.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_CPC_H
+#define MT_CPU_PM_CPC_H
+
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <platform_def.h>
+
+#define NEED_CPUSYS_PROT_WORKAROUND (1)
+
+/* system sram registers */
+#define CPUIDLE_SRAM_REG(r) (CPU_IDLE_SRAM_BASE + (r))
+
+/* db dump */
+#define CPC_TRACE_SIZE (0x20)
+#define CPC_TRACE_ID_NUM (10)
+#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
+
+/* buckup off count */
+#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1f0)
+#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1f4)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG (0xA814): debug setting */
+#define CPC_PWR_ON_SEQ_DIS BIT(1)
+#define CPC_PWR_ON_PRIORITY BIT(2)
+#define CPC_AUTO_OFF_EN BIT(5)
+#define CPC_DORMANT_WAIT_EN BIT(14)
+#define CPC_CTRL_EN BIT(16)
+#define CPC_OFF_PRE_EN BIT(29)
+
+/* CPC_MCUSYS_LAST_CORE_REQ (0xA818) : last core protection */
+#define CPUSYS_PROT_SET BIT(0)
+#define MCUSYS_PROT_SET BIT(8)
+#define CPUSYS_PROT_CLR BIT(8)
+#define MCUSYS_PROT_CLR BIT(9)
+
+#define CPC_PROT_RESP_MASK (0x3)
+#define CPUSYS_RESP_OFS (16)
+#define MCUSYS_RESP_OFS (30)
+
+#define RETRY_CNT_MAX (1000)
+
+#define PROT_RETRY (0)
+#define PROT_SUCCESS (1)
+#define PROT_GIVEUP (2)
+
+/* CPC_MCUSYS_CPC_DBG_SETTING (0xAB00): debug setting */
+#define CPC_PROF_EN BIT(0)
+#define CPC_DBG_EN BIT(1)
+#define CPC_FREEZE BIT(2)
+#define CPC_CALC_EN BIT(3)
+
+enum mcusys_cpc_lastcore_prot_status {
+ CPC_SUCCESS = 0,
+ CPC_ERR_FAIL,
+ CPC_ERR_TIMEOUT,
+ NF_CPC_ERR,
+};
+
+enum mcusys_cpc_smc_events {
+ CPC_SMC_EVENT_DUMP_TRACE_DATA,
+ CPC_SMC_EVENT_GIC_DPG_SET,
+ CPC_SMC_EVENT_CPC_CONFIG,
+ CPC_SMC_EVENT_READ_CONFIG,
+ NF_CPC_SMC_EVENT,
+};
+
+enum mcusys_cpc_smc_config {
+ CPC_SMC_CONFIG_PROF,
+ CPC_SMC_CONFIG_AUTO_OFF,
+ CPC_SMC_CONFIG_AUTO_OFF_THRES,
+ CPC_SMC_CONFIG_CNT_CLR,
+ CPC_SMC_CONFIG_TIME_SYNC,
+ NF_CPC_SMC_CONFIG,
+};
+
+#define US_TO_TICKS(us) ((us) * 13)
+#define TICKS_TO_US(tick) ((tick) / 13)
+
+int mtk_cpu_pm_cluster_prot_aquire(void);
+void mtk_cpu_pm_cluster_prot_release(void);
+
+void mtk_cpc_mcusys_off_reflect(void);
+int mtk_cpc_mcusys_off_prepare(void);
+
+void mtk_cpc_core_on_hint_set(int cpu);
+void mtk_cpc_core_on_hint_clr(int cpu);
+void mtk_cpc_time_sync(void);
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
+uint64_t mtk_cpc_trace_dump(uint64_t act, uint64_t arg1, uint64_t arg2);
+void mtk_cpc_init(void);
+
+#endif /* MT_CPU_PM_CPC_H */
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.c b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.c
new file mode 100644
index 0000000..4d67e7b
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <lib/mmio.h>
+
+#include "mt_cpu_pm_mbox.h"
+#include <platform_def.h>
+
+#ifdef __GNUC__
+#define MCDI_LIKELY(x) __builtin_expect(!!(x), 1)
+#define MCDI_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define MCDI_LIKELY(x) (x)
+#define MCDI_UNLIKELY(x) (x)
+#endif
+
+#define MCUPM_MBOX_3_BASE (CPU_EB_TCM_BASE + CPU_EB_MBOX3_OFFSET)
+#define MCUPM_MBOX_WRITE(id, val) mmio_write_32(MCUPM_MBOX_3_BASE + 4 * (id), val)
+#define MCUPM_MBOX_READ(id) mmio_read_32(MCUPM_MBOX_3_BASE + 4 * (id))
+
+void mtk_set_mcupm_pll_mode(unsigned int mode)
+{
+ if (mode < NF_MCUPM_ARMPLL_MODE) {
+ MCUPM_MBOX_WRITE(MCUPM_MBOX_ARMPLL_MODE, mode);
+ }
+}
+
+int mtk_get_mcupm_pll_mode(void)
+{
+ return MCUPM_MBOX_READ(MCUPM_MBOX_ARMPLL_MODE);
+}
+
+void mtk_set_mcupm_buck_mode(unsigned int mode)
+{
+ if (mode < NF_MCUPM_BUCK_MODE) {
+ MCUPM_MBOX_WRITE(MCUPM_MBOX_BUCK_MODE, mode);
+ }
+}
+
+int mtk_get_mcupm_buck_mode(void)
+{
+ return MCUPM_MBOX_READ(MCUPM_MBOX_BUCK_MODE);
+}
+
+void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)
+{
+ return MCUPM_MBOX_WRITE(MCUPM_MBOX_WAKEUP_CPU, cpuid);
+}
+
+unsigned int mtk_get_cpu_pm_preffered_cpu(void)
+{
+ return MCUPM_MBOX_READ(MCUPM_MBOX_WAKEUP_CPU);
+}
+
+static int mtk_wait_mbox_init_done(void)
+{
+ int status = MCUPM_MBOX_READ(MCUPM_MBOX_TASK_STA);
+
+ if (status != MCUPM_TASK_INIT) {
+ return status;
+ }
+
+ mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
+ mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
+
+ MCUPM_MBOX_WRITE(MCUPM_MBOX_PWR_CTRL_EN, (MCUPM_MCUSYS_CTRL | MCUPM_CM_CTRL |
+ MCUPM_BUCK_CTRL | MCUPM_ARMPLL_CTRL));
+
+ return status;
+}
+
+int mtk_lp_depd_condition(enum cpupm_mbox_depd_type type)
+{
+ int status;
+
+ if (type == CPUPM_MBOX_WAIT_DEV_INIT) {
+ status = mtk_wait_mbox_init_done();
+ if (MCDI_UNLIKELY(status != MCUPM_TASK_INIT)) {
+ return -ENXIO;
+ }
+ MCUPM_MBOX_WRITE(MCUPM_MBOX_AP_READY, 1);
+ } else if (type == CPUPM_MBOX_WAIT_TASK_READY) {
+ status = MCUPM_MBOX_READ(MCUPM_MBOX_TASK_STA);
+ if (MCDI_UNLIKELY((status != MCUPM_TASK_WAIT) &&
+ (status != MCUPM_TASK_INIT_FINISH))) {
+ return -ENXIO;
+ }
+ }
+ return 0;
+}
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.h b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.h
new file mode 100644
index 0000000..72be6bd
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_cpu_pm_mbox.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_MBOX_H
+#define MT_CPU_PM_MBOX_H
+
+#include <lib/utils_def.h>
+
+/* MCUPM Mbox */
+/* AP Write */
+#define MCUPM_MBOX_AP_READY (0)
+#define MCUPM_MBOX_RESERVED_1 (1)
+#define MCUPM_MBOX_RESERVED_2 (2)
+#define MCUPM_MBOX_RESERVED_3 (3)
+#define MCUPM_MBOX_PWR_CTRL_EN (4)
+#define MCUPM_MBOX_L3_CACHE_MODE (5)
+#define MCUPM_MBOX_BUCK_MODE (6)
+#define MCUPM_MBOX_ARMPLL_MODE (7)
+/* AP Read */
+#define MCUPM_MBOX_TASK_STA (8)
+#define MCUPM_MBOX_RESERVED_9 (9)
+#define MCUPM_MBOX_RESERVED_10 (10)
+#define MCUPM_MBOX_RESERVED_11 (11)
+#define MCUPM_MBOX_WAKEUP_CPU (12)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN (4) */
+#define MCUPM_MCUSYS_CTRL BIT(0)
+#define MCUPM_BUCK_CTRL BIT(1)
+#define MCUPM_ARMPLL_CTRL BIT(2)
+#define MCUPM_CM_CTRL BIT(3)
+#define MCUPM_PWR_CTRL_MASK (BIT(3) - 1)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_L3_CACHE_MODE (5) */
+#define MCUPM_L3_OFF_MODE (0) /* default */
+#define MCUPM_L3_DORMANT_MODE (1)
+#define NF_MCUPM_L3_MODE (2)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE (6) */
+#define MCUPM_BUCK_NORMAL_MODE (0) /* default */
+#define MCUPM_BUCK_LP_MODE (1)
+#define MCUPM_BUCK_OFF_MODE (2)
+#define NF_MCUPM_BUCK_MODE (3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE (7) */
+#define MCUPM_ARMPLL_ON (0) /* default */
+#define MCUPM_ARMPLL_GATING (1)
+#define MCUPM_ARMPLL_OFF (2)
+#define NF_MCUPM_ARMPLL_MODE (3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA (9) */
+#define MCUPM_TASK_UNINIT (0)
+#define MCUPM_TASK_INIT (1)
+#define MCUPM_TASK_INIT_FINISH (2)
+#define MCUPM_TASK_WAIT (3)
+#define MCUPM_TASK_RUN (4)
+#define MCUPM_TASK_PAUSE (5)
+
+
+void mtk_set_mcupm_pll_mode(unsigned int mode);
+int mtk_get_mcupm_pll_mode(void);
+
+void mtk_set_mcupm_buck_mode(unsigned int mode);
+int mtk_get_mcupm_buck_mode(void);
+
+void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid);
+unsigned int mtk_get_cpu_pm_preffered_cpu(void);
+
+enum cpupm_mbox_depd_type {
+ CPUPM_MBOX_WAIT_DEV_INIT,
+ CPUPM_MBOX_WAIT_TASK_READY,
+};
+
+int mtk_lp_depd_condition(enum cpupm_mbox_depd_type type);
+
+#endif /* MT_CPU_PM_MBOX_H */
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c
new file mode 100644
index 0000000..a1d9c31
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <plat/common/platform.h>
+
+#include <lib/pm/mtk_pm.h>
+#include <mcucfg.h>
+#include "mt_cpu_pm.h"
+#include "mt_smp.h"
+
+static inline int is_core_power_status_on(unsigned int cpuid)
+{
+ return !!(mmio_read_32(CPU_PWR_STATUS) & BIT(cpuid));
+}
+
+void mt_smp_core_init_arch(unsigned int cluster, unsigned int cpu, int arm64,
+ struct cpu_pwr_ctrl *pwr_ctrl)
+{
+ CPU_PM_ASSERT(cluster == 0);
+ CPU_PM_ASSERT(pwr_ctrl != NULL);
+
+ /* aa64naa32 in bits[16:23] */
+ if (arm64 != 0) {
+ mmio_setbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
+ } else {
+ mmio_clrbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
+ }
+}
+
+void mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl *pwr_ctrl, uintptr_t entry)
+{
+ CPU_PM_ASSERT(pwr_ctrl != NULL);
+
+ /* Set bootup address */
+ mmio_write_32(pwr_ctrl->rvbaraddr_l, entry);
+}
+
+int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl)
+{
+ unsigned int val = is_core_power_status_on(cpu_id);
+
+ CPU_PM_ASSERT(pwr_ctrl);
+
+ mmio_clrbits_32(pwr_ctrl->pwpr, RESETPWRON_CONFIG);
+ if (val == 0) {
+ /*
+ * Set to 0 after BIG VPROC bulk powered on (configure in MCUPM) and
+ * before big core power-on sequence.
+ */
+ if (cpu_id >= PLAT_CPU_PM_B_BUCK_ISO_ID) {
+ mmio_write_32(DREQ20_BIG_VPROC_ISO, 0);
+ }
+
+ mmio_setbits_32(pwr_ctrl->pwpr, PWR_RST_B);
+ dsbsy();
+
+ /* set mp0_spmc_pwr_on_cpuX = 1 */
+ mmio_setbits_32(pwr_ctrl->pwpr, PWR_ON);
+
+ val = 0;
+ while (is_core_power_status_on(cpu_id) == 0) {
+ DO_SMP_CORE_ON_WAIT_TIMEOUT(val);
+ mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON);
+ mmio_setbits_32(pwr_ctrl->pwpr, PWR_ON);
+ }
+ } else {
+ INFO("[%s:%d] - core_%u haven been power on\n", __func__, __LINE__, cpu_id);
+ }
+
+ return MTK_CPUPM_E_OK;
+}
+
+int mt_smp_power_core_off(struct cpu_pwr_ctrl *pwr_ctrl)
+{
+ /* set mp0_spmc_pwr_on_cpuX = 1 */
+ mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON);
+ return MTK_CPUPM_E_OK;
+}
+
+void mt_smp_init(void)
+{
+ /* clear RESETPWRON_CONFIG of mcusys/cluster/core0 */
+ mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+}
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.h b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.h
new file mode 100644
index 0000000..4c2f8d2
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/mt_smp.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SMP_H
+#define MT_SMP_H
+
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define CPU_PWR_STATUS (MCUCFG_BASE + 0xA840)
+
+#define SMP_CORE_TIMEOUT_MAX (50000)
+#define DO_SMP_CORE_ON_WAIT_TIMEOUT(k_cnt) ({ \
+ CPU_PM_ASSERT(k_cnt < SMP_CORE_TIMEOUT_MAX); \
+ k_cnt++; udelay(1); })
+
+void mt_smp_core_init_arch(unsigned int cluster, unsigned int cpu, int arm64,
+ struct cpu_pwr_ctrl *pwr_ctrl);
+void mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl *pwr_ctrl, uintptr_t entry);
+int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl);
+int mt_smp_power_core_off(struct cpu_pwr_ctrl *pwr_ctrl);
+void mt_smp_init(void);
+
+#endif /* MT_SMP_H */
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv3_2/rules.mk b/plat/mediatek/drivers/cpu_pm/cpcv3_2/rules.mk
new file mode 100644
index 0000000..858cf38
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/cpcv3_2/rules.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := cpcv${CONFIG_MTK_CPU_PM_ARCH}
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/mt_cpu_pm.c ${LOCAL_DIR}/mt_cpu_pm_cpc.c
+
+LOCAL_SRCS-$(CPU_PM_TINYSYS_SUPPORT) += ${LOCAL_DIR}/mt_cpu_pm_mbox.c
+LOCAL_SRCS-$(CONFIG_MTK_SMP_EN) += ${LOCAL_DIR}/mt_smp.c
+
+$(eval $(call add_defined_option,CPU_PM_TINYSYS_SUPPORT))
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
+
diff --git a/plat/mediatek/drivers/cpu_pm/rules.mk b/plat/mediatek/drivers/cpu_pm/rules.mk
new file mode 100644
index 0000000..8df4f21
--- /dev/null
+++ b/plat/mediatek/drivers/cpu_pm/rules.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := cpu_pm
+
+SUB_RULES-${CONFIG_MTK_CPU_PM_SUPPORT} := $(LOCAL_DIR)/cpcv${CONFIG_MTK_CPU_PM_ARCH}
+
+$(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))
diff --git a/plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.c b/plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.c
new file mode 100644
index 0000000..c054de9
--- /dev/null
+++ b/plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mtk_dcm_utils.h>
+
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK BIT(17)
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | BIT(16) | BIT(17) | \
+ BIT(18) | BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | BIT(16) | BIT(17) | BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON BIT(17)
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | BIT(16) | BIT(17) | \
+ BIT(18) | BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | BIT(16) | BIT(17) | BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF (0x0 << 17)
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | (0x0 << 16) | \
+ (0x0 << 17) | (0x0 << 18) | \
+ (0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | (0x0 << 16) | \
+ (0x0 << 17) | (0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_adb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK BIT(5)
+#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK BIT(8)
+#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK BIT(16)
+#define MP_CPUSYS_TOP_APB_DCM_REG0_ON BIT(5)
+#define MP_CPUSYS_TOP_APB_DCM_REG1_ON BIT(8)
+#define MP_CPUSYS_TOP_APB_DCM_REG2_ON BIT(16)
+#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF (0x0 << 5)
+#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF (0x0 << 8)
+#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF (0x0 << 16)
+
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_apb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | BIT(24) | BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | BIT(24) | BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \
+ (0x0 << 24) | \
+ (0x0 << 25))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK BIT(0)
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON BIT(0)
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF (0x0 << 0)
+
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_core_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK (0xffff << 0)
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON (0xffff << 0)
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF (0x0 << 0)
+
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_MCSIC_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(24) | BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(24) | BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 24) | (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(24) | BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(24) | BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 24) | (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK BIT(4)
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON BIT(4)
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF (0x0 << 4)
+
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK BIT(31)
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON BIT(31)
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF (0x0U << 31)
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | (0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+ return dcm_check_state(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+}
+
+void dcm_mp_cpusys_top_misc_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK BIT(3)
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON BIT(3)
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | (0x0 << 1) | \
+ (0x0 << 2) | (0x0 << 3))
+
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ ret &= dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_mp0_qdcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF);
+ }
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | (0x0 << 1) | \
+ (0x0 << 2) | (0x0 << 3))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+ return dcm_check_state(CPCCFG_REG_EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_ON);
+}
+
+void dcm_cpccfg_reg_emi_wfifo(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+ }
+}
diff --git a/plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.h b/plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.h
new file mode 100644
index 0000000..5d758dd
--- /dev/null
+++ b/plat/mediatek/drivers/dcm/mt8188/mtk_dcm_utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_UTILS_H
+#define MTK_DCM_UTILS_H
+
+#include <stdbool.h>
+
+#include <mtk_dcm.h>
+#include <platform_def.h>
+
+/* Base */
+#define MP_CPUSYS_TOP_BASE (MCUCFG_BASE + 0x8000)
+#define CPCCFG_REG_BASE (MCUCFG_BASE + 0xA800)
+
+/* Register Definition */
+#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
+#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
+#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
+
+/* MP_CPUSYS_TOP */
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
+void dcm_mp_cpusys_top_adb_dcm(bool on);
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
+void dcm_mp_cpusys_top_apb_dcm(bool on);
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_core_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
+void dcm_mp_cpusys_top_misc_dcm(bool on);
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
+void dcm_mp_cpusys_top_mp0_qdcm(bool on);
+/* CPCCFG_REG */
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+
+#endif
diff --git a/plat/mediatek/drivers/dcm/mtk_dcm.c b/plat/mediatek/drivers/dcm/mtk_dcm.c
new file mode 100644
index 0000000..ca79a20
--- /dev/null
+++ b/plat/mediatek/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <mtk_dcm.h>
+#include <mtk_dcm_utils.h>
+
+static void dcm_armcore(bool mode)
+{
+ dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
+}
+
+static void dcm_mcusys(bool on)
+{
+ dcm_mp_cpusys_top_adb_dcm(on);
+ dcm_mp_cpusys_top_apb_dcm(on);
+ dcm_mp_cpusys_top_cpubiu_dcm(on);
+ dcm_mp_cpusys_top_misc_dcm(on);
+ dcm_mp_cpusys_top_mp0_qdcm(on);
+
+ /* CPCCFG_REG */
+ dcm_cpccfg_reg_emi_wfifo(on);
+ dcm_mp_cpusys_top_last_cor_idle_dcm(on);
+}
+
+static void dcm_stall(bool on)
+{
+ dcm_mp_cpusys_top_core_stall_dcm(on);
+ dcm_mp_cpusys_top_fcm_stall_dcm(on);
+}
+
+static bool check_dcm_state(void)
+{
+ bool ret = true;
+
+ ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
+ ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
+ ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
+
+ return ret;
+}
+
+bool dcm_check_state(uintptr_t addr, unsigned int mask, unsigned int compare)
+{
+ return ((mmio_read_32(addr) & mask) == compare);
+}
+
+int dcm_set_init(void)
+{
+ int ret;
+
+ dcm_armcore(true);
+ dcm_mcusys(true);
+ dcm_stall(true);
+
+ if (check_dcm_state() == false) {
+ ERROR("Failed to set default dcm on!!\n");
+ ret = -1;
+ } else {
+ INFO("%s, dcm pass\n", __func__);
+ ret = 0;
+ }
+
+ return ret;
+}
+MTK_PLAT_SETUP_0_INIT(dcm_set_init);
diff --git a/plat/mediatek/drivers/dcm/mtk_dcm.h b/plat/mediatek/drivers/dcm/mtk_dcm.h
new file mode 100644
index 0000000..05f8d45
--- /dev/null
+++ b/plat/mediatek/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+bool dcm_check_state(uintptr_t addr, unsigned int mask, unsigned int compare);
+int dcm_set_init(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/drivers/dcm/rules.mk b/plat/mediatek/drivers/dcm/rules.mk
new file mode 100644
index 0000000..a8ee05e
--- /dev/null
+++ b/plat/mediatek/drivers/dcm/rules.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_dcm
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_dcm.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/mtk_dcm_utils.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/dfd/dfd.c b/plat/mediatek/drivers/dfd/dfd.c
new file mode 100644
index 0000000..5770d50
--- /dev/null
+++ b/plat/mediatek/drivers/dfd/dfd.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <dfd.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static u_register_t dfd_smc_dispatcher(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3,
+ void *handle, struct smccc_res *smccc_ret)
+{
+ int ret = MTK_SIP_E_SUCCESS;
+
+ switch (arg0) {
+ case PLAT_MTK_DFD_SETUP_MAGIC:
+ INFO("[%s] DFD setup call from kernel\n", __func__);
+ dfd_setup(arg1, arg2, arg3);
+ break;
+ case PLAT_MTK_DFD_READ_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+ }
+ break;
+ case PLAT_MTK_DFD_WRITE_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ sync_writel(MISC1_CFG_BASE + arg1, arg2);
+ }
+ break;
+ default:
+ ret = MTK_SIP_E_INVALID_PARAM;
+ break;
+ }
+
+ return ret;
+}
+DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_DFD, dfd_smc_dispatcher);
diff --git a/plat/mediatek/drivers/dfd/dfd.h b/plat/mediatek/drivers/dfd/dfd.h
new file mode 100644
index 0000000..c088bd0
--- /dev/null
+++ b/plat/mediatek/drivers/dfd/dfd.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DFD_H
+#define DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+
+void dfd_resume(void);
+void dfd_setup(uint64_t base_addr, uint64_t chain_length, uint64_t cache_dump);
+
+#endif /* DFD_H */
diff --git a/plat/mediatek/drivers/dfd/mt8188/plat_dfd.c b/plat/mediatek/drivers/dfd/mt8188/plat_dfd.c
new file mode 100644
index 0000000..1aa68f5
--- /dev/null
+++ b/plat/mediatek/drivers/dfd/mt8188/plat_dfd.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <dfd.h>
+#include <plat_dfd.h>
+
+static uint64_t dfd_cache_dump;
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+
+void dfd_setup(uint64_t base_addr, uint64_t chain_length, uint64_t cache_dump)
+{
+ mmio_write_32(MTK_DRM_LATCH_CTL1, MTK_DRM_LATCH_CTL1_VAL);
+ mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_VAL);
+ mmio_write_32(MTK_WDT_LATCH_CTL2, MTK_WDT_LATCH_CTL2_VAL);
+
+ mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, BIT(2));
+ mmio_setbits_32(DFD_V50_GROUP_0_63_DIFF, 0x1);
+ sync_writel(DFD_INTERNAL_CTL, 0x5);
+ mmio_setbits_32(DFD_INTERNAL_CTL, BIT(13));
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1F << 3);
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 9);
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
+
+ mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
+ mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+ mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
+ mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
+
+ mmio_write_32(DFD_TEST_SI_0, 0x0);
+ mmio_write_32(DFD_TEST_SI_1, 0x0);
+ mmio_write_32(DFD_TEST_SI_2, 0x0);
+ mmio_write_32(DFD_TEST_SI_3, 0x0);
+
+ sync_writel(DFD_POWER_CTL, 0xF9);
+ sync_writel(DFD_READ_ADDR, DFD_READ_ADDR_VAL);
+ sync_writel(DFD_V30_CTL, 0xD);
+
+ mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
+ mmio_write_32(DFD_O_REG_0, 0);
+
+ /* setup global variables for suspend and resume */
+ dfd_enabled = true;
+ dfd_base_addr = base_addr;
+ dfd_chain_length = chain_length;
+ dfd_cache_dump = cache_dump;
+
+ if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+ mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_CACHE_VAL);
+ sync_writel(DFD_V35_ENABLE, 0x1);
+ sync_writel(DFD_V35_TAP_NUMBER, 0xB);
+ sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+ sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+ /* Cache dump only mode */
+ sync_writel(DFD_V35_CTL, 0x1);
+ mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 0xF);
+ mmio_write_32(DFD_CHAIN_LENGTH0, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH1, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH2, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH3, DFD_CHAIN_LENGTH_VAL);
+
+ if ((cache_dump & DFD_PARITY_ERR_TRIGGER) != 0UL) {
+ sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
+ }
+ }
+ dsbsy();
+}
+
+void dfd_resume(void)
+{
+ if (dfd_enabled == true) {
+ dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+ }
+}
diff --git a/plat/mediatek/drivers/dfd/mt8188/plat_dfd.h b/plat/mediatek/drivers/dfd/mt8188/plat_dfd.h
new file mode 100644
index 0000000..5b98024
--- /dev/null
+++ b/plat/mediatek/drivers/dfd/mt8188/plat_dfd.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); dsbsy(); } while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC (0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152)
+
+#define MTK_DRM_LATCH_CTL1 (DRM_BASE + 0x40)
+#define MTK_DRM_LATCH_CTL2 (DRM_BASE + 0x44)
+
+#define MTK_WDT_BASE (RGU_BASE)
+#define MTK_WDT_INTERVAL (MTK_WDT_BASE + 0x10)
+#define MTK_WDT_LATCH_CTL2 (MTK_WDT_BASE + 0x48)
+
+#define MCU_BIU_BASE (MCUCFG_BASE)
+#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040)
+#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10)
+#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C)
+#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20)
+#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24)
+#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30)
+#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34)
+#define DFD_INTERNAL_SW_NS_TRIGGER (MISC1_CFG_BASE + 0x3c)
+#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C)
+#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50)
+#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C)
+#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60)
+#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8)
+#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC)
+#define DFD_READ_ADDR (MISC1_CFG_BASE + 0x1E8)
+#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENABLE (MCU_BIU_BASE + 0xE0A8)
+#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC)
+#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0)
+#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4)
+#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0)
+#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4)
+#define DFD_V50_GROUP_0_63_DIFF (MCU_BIU_BASE + 0xE2AC)
+
+#define DFD_O_PROTECT_EN_REG (0x10001220)
+#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C)
+#define DFD_O_SET_BASEADDR_REG (0x10043000)
+#define DFD_O_REG_0 (0x10001390)
+
+#define DFD_CACHE_DUMP_ENABLE (1U)
+#define DFD_PARITY_ERR_TRIGGER (2U)
+
+#define DFD_V35_TAP_EN_VAL (0x43FF)
+#define DFD_V35_SEQ0_0_VAL (0x63668820)
+#define DFD_READ_ADDR_VAL (0x40000008)
+#define DFD_CHAIN_LENGTH_VAL (0xFFFFFFFF)
+
+#define MTK_WDT_LATCH_CTL2_VAL (0x9507FFFF)
+#define MTK_WDT_INTERVAL_VAL (0x6600000A)
+#define MTK_DRM_LATCH_CTL2_VAL (0x950607D0)
+#define MTK_DRM_LATCH_CTL2_CACHE_VAL (0x95065DC0)
+
+#define MTK_DRM_LATCH_CTL1_VAL (0x95000013)
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/drivers/dfd/rules.mk b/plat/mediatek/drivers/dfd/rules.mk
new file mode 100644
index 0000000..60fbc88
--- /dev/null
+++ b/plat/mediatek/drivers/dfd/rules.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_dfd
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/dfd.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/$(MTK_SOC)/plat_dfd.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+PLAT_INCLUDES += -I${LOCAL_DIR}/$(MTK_SOC)
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/dp/mt_dp.c b/plat/mediatek/drivers/dp/mt_dp.c
new file mode 100644
index 0000000..8aa246f
--- /dev/null
+++ b/plat/mediatek/drivers/dp/mt_dp.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <inttypes.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_dp.h>
+#include <mtk_sip_svc.h>
+#include <platform_def.h>
+
+static uint32_t dp_write_sec_reg(uint32_t is_edp, uint32_t offset,
+ uint32_t value, uint32_t mask)
+{
+ uint32_t reg = (is_edp != 0U) ? EDP_SEC_BASE : DP_SEC_BASE;
+
+ mmio_clrsetbits_32(reg + offset, mask, value);
+
+ return mmio_read_32(reg + offset);
+}
+
+int32_t dp_secure_handler(uint64_t cmd, uint64_t para, uint32_t *val)
+{
+ int32_t ret = 0L;
+ uint32_t is_edp = 0UL;
+ uint32_t regval = 0UL;
+ uint32_t regmsk = 0UL;
+ uint32_t fldmask = 0UL;
+
+ if ((cmd > DP_ATF_CMD_COUNT) || (val == NULL)) {
+ INFO("dp_secure_handler error cmd 0x%" PRIx64 "\n", cmd);
+ return MTK_SIP_E_INVALID_PARAM;
+ }
+
+ switch (cmd) {
+ case DP_ATF_DP_VIDEO_UNMUTE:
+ INFO("[%s] DP_ATF_DP_VIDEO_UNMUTE\n", __func__);
+ is_edp = DP_ATF_TYPE_DP;
+ ret = MTK_SIP_E_SUCCESS;
+ break;
+ case DP_ATF_EDP_VIDEO_UNMUTE:
+ INFO("[%s] DP_ATF_EDP_VIDEO_UNMUTE\n", __func__);
+ is_edp = DP_ATF_TYPE_EDP;
+ ret = MTK_SIP_E_SUCCESS;
+ break;
+ default:
+ ret = MTK_SIP_E_INVALID_PARAM;
+ break;
+ }
+
+ if (ret == MTK_SIP_E_SUCCESS) {
+ regmsk = (VIDEO_MUTE_SEL_SECURE_FLDMASK |
+ VIDEO_MUTE_SW_SECURE_FLDMASK);
+ if (para > 0U) {
+ fldmask = VIDEO_MUTE_SW_SECURE_FLDMASK;
+ } else {
+ fldmask = 0;
+ }
+
+ regval = (VIDEO_MUTE_SEL_SECURE_FLDMASK | fldmask);
+ *val = dp_write_sec_reg(is_edp, DP_TX_SECURE_REG11,
+ regval, regmsk);
+ }
+
+ return ret;
+}
+
+u_register_t mtk_dp_sip_handler(u_register_t x1, u_register_t x2,
+ u_register_t x3, u_register_t x4,
+ void *handle, struct smccc_res *smccc_ret)
+{
+ uint32_t ret_val;
+
+ return dp_secure_handler(x1, x2, &ret_val);
+}
+DECLARE_SMC_HANDLER(MTK_SIP_DP_CONTROL, mtk_dp_sip_handler);
diff --git a/plat/mediatek/drivers/dp/mt_dp.h b/plat/mediatek/drivers/dp/mt_dp.h
new file mode 100644
index 0000000..d5dad29
--- /dev/null
+++ b/plat/mediatek/drivers/dp/mt_dp.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_DP_H
+#define MT_DP_H
+
+#define DP_TX_SECURE_REG11 (0x2c)
+
+#define VIDEO_MUTE_SEL_SECURE_FLDMASK (0x10)
+#define VIDEO_MUTE_SW_SECURE_FLDMASK (0x8)
+
+enum DP_ATF_HW_TYPE {
+ DP_ATF_TYPE_DP = 0,
+ DP_ATF_TYPE_EDP = 1
+};
+
+enum DP_ATF_CMD {
+ DP_ATF_DP_VIDEO_UNMUTE = 0x20,
+ DP_ATF_EDP_VIDEO_UNMUTE,
+ DP_ATF_CMD_COUNT
+};
+
+int32_t dp_secure_handler(uint64_t cmd, uint64_t para, uint32_t *val);
+
+#endif
diff --git a/plat/mediatek/drivers/dp/rules.mk b/plat/mediatek/drivers/dp/rules.mk
new file mode 100644
index 0000000..786d514
--- /dev/null
+++ b/plat/mediatek/drivers/dp/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := dp
+LOCAL_SRCS-y := $(LOCAL_DIR)/mt_dp.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..66a369e
--- /dev/null
+++ b/plat/mediatek/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <emi_mpu_priv.h>
+#include <platform_def.h>
+
+#define NO_PROTECTION (0)
+#define SEC_RW (1)
+#define SEC_RW_NSEC_R (2)
+#define SEC_RW_NSEC_W (3)
+#define SEC_R_NSEC_R (4)
+#define FORBIDDEN (5)
+#define SEC_R_NSEC_RW (6)
+
+#define LOCK (1)
+#define UNLOCK (0)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = 0; \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
+ (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
+ (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
+ (((unsigned int) d1) << 3) | ((unsigned int) d0) | \
+ ((unsigned int) lock << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+ d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = \
+ (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \
+ (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \
+ (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \
+ (((unsigned int) d9) << 3) | ((unsigned int) d8); \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
+ (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
+ (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
+ (((unsigned int) d1) << 3) | ((unsigned int) d0) | \
+ ((unsigned int) lock << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+ unsigned long long start;
+ unsigned long long end;
+ unsigned int region;
+ unsigned int apc[EMI_MPU_DGROUP_NUM];
+};
+
+int emi_mpu_init(void);
+int emi_mpu_set_protection(struct emi_region_info_t *region_info);
+void set_emi_mpu_regions(void);
+
+#endif
diff --git a/plat/mediatek/drivers/emi_mpu/emi_mpu_common.c b/plat/mediatek/drivers/emi_mpu/emi_mpu_common.c
new file mode 100644
index 0000000..27b2b07
--- /dev/null
+++ b/plat/mediatek/drivers/emi_mpu/emi_mpu_common.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <emi_mpu.h>
+#include <lib/mtk_init/mtk_init.h>
+
+#if ENABLE_EMI_MPU_SW_LOCK
+static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
+#endif
+
+#define EMI_MPU_START_MASK (0x00FFFFFF)
+#define EMI_MPU_END_MASK (0x00FFFFFF)
+#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
+#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
+
+static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
+ unsigned int apc)
+{
+ unsigned int dgroup;
+ unsigned int region;
+
+ region = (start >> 24) & 0xFF;
+ start &= EMI_MPU_START_MASK;
+ dgroup = (end >> 24) & 0xFF;
+ end &= EMI_MPU_END_MASK;
+
+ if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+ WARN("invalid region, domain\n");
+ return -1;
+ }
+
+#if ENABLE_EMI_MPU_SW_LOCK
+ if (region_lock_state[region] == 1) {
+ WARN("invalid region\n");
+ return -1;
+ }
+
+ if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
+ region_lock_state[region] = 1;
+ }
+
+ apc &= EMI_MPU_APC_SW_LOCK_MASK;
+#else
+ apc &= EMI_MPU_APC_HW_LOCK_MASK;
+#endif
+
+ if ((start >= DRAM_OFFSET) && (end >= start)) {
+ start -= DRAM_OFFSET;
+ end -= DRAM_OFFSET;
+ } else {
+ WARN("invalid range\n");
+ return -1;
+ }
+
+ mmio_write_32(EMI_MPU_SA(region), start);
+ mmio_write_32(EMI_MPU_EA(region), end);
+ mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+#if defined(SUB_EMI_MPU_BASE)
+ mmio_write_32(SUB_EMI_MPU_SA(region), start);
+ mmio_write_32(SUB_EMI_MPU_EA(region), end);
+ mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
+#endif
+ return 0;
+}
+
+static void dump_emi_mpu_regions(void)
+{
+ int region, i;
+
+ /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
+ for (region = 0; region < 8; ++region) {
+ INFO("region %d:\n", region);
+ INFO("\tsa: 0x%x, ea: 0x%x\n",
+ mmio_read_32(EMI_MPU_SA(region)), mmio_read_32(EMI_MPU_EA(region)));
+
+ for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) {
+ INFO("\tapc%d: 0x%x\n", i, mmio_read_32(EMI_MPU_APC(region, i)));
+ }
+ }
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+ unsigned int start, end;
+ int i;
+
+ if (region_info->region >= EMI_MPU_REGION_NUM) {
+ WARN("invalid region\n");
+ return -1;
+ }
+
+ start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+ (region_info->region << 24);
+
+ for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+ end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
+
+ if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
+ WARN("Failed to set emi mpu protection(%d, %d, %d)\n",
+ start, end, region_info->apc[i]);
+ }
+ }
+
+ return 0;
+}
+
+int emi_mpu_init(void)
+{
+ INFO("[%s] emi mpu initialization\n", __func__);
+
+ set_emi_mpu_regions();
+ dump_emi_mpu_regions();
+
+ return 0;
+}
+MTK_PLAT_SETUP_0_INIT(emi_mpu_init);
diff --git a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
new file mode 100644
index 0000000..558533d
--- /dev/null
+++ b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <emi_mpu.h>
+
+void set_emi_mpu_regions(void)
+{
+ /* TODO: set emi mpu region */
+ INFO("%s, emi mpu is not setting currently\n", __func__);
+}
diff --git a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h
new file mode 100644
index 0000000..1ee7397
--- /dev/null
+++ b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_PRIV_H
+#define EMI_MPU_PRIV_H
+
+#define ENABLE_EMI_MPU_SW_LOCK (1)
+
+#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000)
+#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004)
+#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4))
+#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4))
+#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4))
+#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4))
+
+#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000)
+#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004)
+#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100)
+#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200)
+#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4))
+#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4))
+#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300)
+#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800)
+#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4))
+#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900)
+#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4))
+
+#define EMI_MPU_DOMAIN_NUM (16)
+#define EMI_MPU_REGION_NUM (32)
+#define EMI_MPU_ALIGN_BITS (16)
+#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
+
+#endif
diff --git a/plat/mediatek/drivers/emi_mpu/rules.mk b/plat/mediatek/drivers/emi_mpu/rules.mk
new file mode 100644
index 0000000..ed3d777
--- /dev/null
+++ b/plat/mediatek/drivers/emi_mpu/rules.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := emi_mpu
+LOCAL_SRCS-y := $(LOCAL_DIR)/emi_mpu_common.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/emi_mpu.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/gic600/mt_gic_v3.c b/plat/mediatek/drivers/gic600/mt_gic_v3.c
new file mode 100644
index 0000000..cca5d0a
--- /dev/null
+++ b/plat/mediatek/drivers/gic600/mt_gic_v3.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <mt_gic_v3.h>
+#include <mtk_plat_common.h>
+#include <plat/common/platform.h>
+#include <plat_private.h>
+#include <platform_def.h>
+
+#define SGI_MASK 0xffff
+
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT];
+
+/* we save and restore the GICv3 context on system suspend */
+gicv3_dist_ctx_t dist_ctx;
+
+static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
+{
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+gicv3_driver_data_t mt_gicv3_data = {
+ .gicd_base = MT_GIC_BASE,
+ .gicr_base = MT_GIC_RDIST_BASE,
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = mt_mpidr_to_core_pos,
+};
+
+struct gic_chip_data {
+ /* All cores share the same configuration */
+ unsigned int saved_group;
+ unsigned int saved_enable;
+ unsigned int saved_conf0;
+ unsigned int saved_conf1;
+ unsigned int saved_grpmod;
+ /* Per-core sgi */
+ unsigned int saved_sgi[PLATFORM_CORE_COUNT];
+};
+
+static struct gic_chip_data gic_data;
+
+void mt_gic_driver_init(void)
+{
+ gicv3_driver_init(&mt_gicv3_data);
+}
+
+void mt_gic_set_pending(uint32_t irq)
+{
+ gicv3_set_interrupt_pending(irq, plat_my_core_pos());
+}
+
+void mt_gic_distif_save(void)
+{
+ gicv3_distif_save(&dist_ctx);
+}
+
+void mt_gic_distif_restore(void)
+{
+ gicv3_distif_init_restore(&dist_ctx);
+}
+
+void mt_gic_rdistif_init(void)
+{
+ unsigned int proc_num;
+ unsigned int index;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+ /* set all SGI/PPI as non-secure GROUP1 by default */
+ mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0);
+
+ /* setup the default PPI/SGI priorities */
+ for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U)
+ gicr_write_ipriorityr(gicr_base, index,
+ GICD_IPRIORITYR_DEF_VAL);
+}
+
+void mt_gic_rdistif_save(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+ gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0);
+ gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0);
+ gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0);
+ gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1);
+ gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0);
+
+ rdist_has_saved[proc_num] = 1;
+}
+
+void mt_gic_rdistif_restore(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ if (rdist_has_saved[proc_num] == 1) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
+ mmio_write_32(gicr_base + GICR_ISENABLER0,
+ gic_data.saved_enable);
+ mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
+ mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0,
+ gic_data.saved_grpmod);
+ }
+}
+
+void mt_gic_rdistif_restore_all(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
+ mmio_write_32(gicr_base + GICR_ISENABLER0,
+ gic_data.saved_enable);
+ mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
+ mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0,
+ gic_data.saved_grpmod);
+ }
+}
+
+void gic_sgi_save_all(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ gic_data.saved_sgi[proc_num] =
+ mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK;
+ }
+}
+
+void gic_sgi_restore_all(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK);
+ mmio_write_32(gicr_base + GICR_ISPENDR0,
+ gic_data.saved_sgi[proc_num] & SGI_MASK);
+ }
+}
+
+void mt_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+uint32_t mt_irq_get_pending(uint32_t irq)
+{
+ uint32_t val;
+
+ val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR +
+ irq / 32 * 4);
+ val = (val >> (irq % 32)) & 1U;
+ return val;
+}
+
+
+void mt_irq_set_pending(uint32_t irq)
+{
+ uint32_t bit = 1U << (irq % 32);
+
+ mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR +
+ irq / 32 * 4, bit);
+}
+
+int mt_gic_one_init(void)
+{
+ INFO("[%s] GIC initialization\n", __func__);
+
+ /* Initialize the GIC driver, CPU and distributor interfaces */
+ mt_gic_driver_init();
+ mt_gic_init();
+
+ return 0;
+}
+MTK_PLAT_SETUP_0_INIT(mt_gic_one_init);
diff --git a/plat/mediatek/drivers/gic600/mt_gic_v3.h b/plat/mediatek/drivers/gic600/mt_gic_v3.h
new file mode 100644
index 0000000..31513ef
--- /dev/null
+++ b/plat/mediatek/drivers/gic600/mt_gic_v3.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GIC_V3_H
+#define MT_GIC_V3_H
+
+#include <drivers/arm/gicv3.h>
+#include <lib/mmio.h>
+
+void mt_gic_driver_init(void);
+void mt_gic_init(void);
+void mt_gic_set_pending(uint32_t irq);
+void mt_gic_distif_save(void);
+void mt_gic_distif_restore(void);
+void mt_gic_rdistif_init(void);
+void mt_gic_rdistif_save(void);
+void mt_gic_rdistif_restore(void);
+void mt_gic_rdistif_restore_all(void);
+void gic_sgi_save_all(void);
+void gic_sgi_restore_all(void);
+uint32_t mt_irq_get_pending(uint32_t irq);
+void mt_irq_set_pending(uint32_t irq);
+int mt_gic_one_init(void);
+
+#endif /* MT_GIC_V3_H */
diff --git a/plat/mediatek/drivers/gic600/rules.mk b/plat/mediatek/drivers/gic600/rules.mk
new file mode 100644
index 0000000..3070591
--- /dev/null
+++ b/plat/mediatek/drivers/gic600/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := gic600
+LOCAL_SRCS-y := $(LOCAL_DIR)/mt_gic_v3.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/gpio/mt8188/mtgpio.c b/plat/mediatek/drivers/gpio/mt8188/mtgpio.c
new file mode 100644
index 0000000..9e9fc5d
--- /dev/null
+++ b/plat/mediatek/drivers/gpio/mt8188/mtgpio.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+{
+ uintptr_t reg_addr = 0U;
+ struct mt_pin_info gpio_info;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ gpio_info = mt_pin_infos[pin];
+
+ switch (gpio_info.base & 0x0f) {
+ case 0:
+ reg_addr = IOCFG_RM_BASE;
+ break;
+ case 1:
+ reg_addr = IOCFG_LT_BASE;
+ break;
+ case 2:
+ reg_addr = IOCFG_LM_BASE;
+ break;
+ case 3:
+ reg_addr = IOCFG_RT_BASE;
+ break;
+ default:
+ break;
+ }
+
+ return reg_addr;
+}
diff --git a/plat/mediatek/drivers/gpio/mt8188/mtgpio.h b/plat/mediatek/drivers/gpio/mt8188/mtgpio.h
new file mode 100644
index 0000000..32a4608
--- /dev/null
+++ b/plat/mediatek/drivers/gpio/mt8188/mtgpio.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <mtgpio_common.h>
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+ GPIO_UNSUPPORTED = -1,
+ GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6,
+ GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14,
+ GPIO15, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
+ GPIO23, GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30,
+ GPIO31, GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38,
+ GPIO39, GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46,
+ GPIO47, GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54,
+ GPIO55, GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62,
+ GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70,
+ GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78,
+ GPIO79, GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86,
+ GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94,
+ GPIO95, GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102,
+ GPIO103, GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110,
+ GPIO111, GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118,
+ GPIO119, GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126,
+ GPIO127, GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134,
+ GPIO135, GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142,
+ GPIO143, GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150,
+ GPIO151, GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158,
+ GPIO159, GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166,
+ GPIO167, GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174,
+ GPIO175, GPIO176,
+ MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+static const struct mt_pin_info mt_pin_infos[] = {
+ PIN(0, 0, 6, 0x30, 0xb0),
+ PIN(1, 0, 7, 0x30, 0xb0),
+ PIN(2, 0, 8, 0x30, 0xb0),
+ PIN(3, 0, 9, 0x30, 0xb0),
+ PIN(4, 0, 10, 0x30, 0xb0),
+ PIN(5, 0, 11, 0x30, 0xb0),
+ PIN(6, 0, 12, 0x30, 0xb0),
+ PIN(7, 0, 13, 0x30, 0xb0),
+ PIN(8, 0, 14, 0x30, 0xb0),
+ PIN(9, 0, 15, 0x30, 0xb0),
+ PIN(10, 0, 16, 0x30, 0xb0),
+ PIN(11, 0, 17, 0x30, 0xb0),
+ PIN(12, 0, 12, 0x31, 0xa0),
+ PIN(13, 0, 13, 0x31, 0xa0),
+ PIN(14, 0, 14, 0x31, 0xa0),
+ PIN(15, 0, 15, 0x31, 0xa0),
+ PIN(16, 0, 1, 0x22, 0x50),
+ PIN(17, 0, 2, 0x22, 0x50),
+ PIN(18, 0, 3, 0x23, 0x60),
+ PIN(19, 0, 4, 0x23, 0x60),
+ PIN(20, 0, 5, 0x23, 0x60),
+ PIN(21, 0, 6, 0x23, 0x60),
+ PIN(22, 0, 0, 0x23, 0x60),
+ PIN(23, 0, 1, 0x23, 0x60),
+ PIN(24, 0, 2, 0x23, 0x60),
+ PIN(25, 0, 3, 0x30, 0xb0),
+ PIN(26, 0, 2, 0x30, 0xb0),
+ PIN(27, 0, 5, 0x30, 0xb0),
+ PIN(28, 0, 4, 0x30, 0xb0),
+ PIN(29, 0, 0, 0x30, 0xb0),
+ PIN(30, 0, 1, 0x30, 0xb0),
+ PIN(31, 0, 11, 0x30, 0xc0),
+ PIN(32, 0, 10, 0x30, 0xc0),
+ PIN(33, 0, 13, 0x30, 0xc0),
+ PIN(34, 0, 12, 0x30, 0xc0),
+ PIN(35, 0, 15, 0x30, 0xc0),
+ PIN(36, 0, 14, 0x30, 0xc0),
+ PIN(37, 0, 21, 0x30, 0xb0),
+ PIN(38, 0, 18, 0x30, 0xb0),
+ PIN(39, 0, 19, 0x30, 0xb0),
+ PIN(40, 0, 20, 0x30, 0xb0),
+ PIN(41, 0, 22, 0x30, 0xb0),
+ PIN(42, 1, 12, 0x31, 0xc0),
+ PIN(43, 1, 13, 0x31, 0xc0),
+ PIN(44, 1, 14, 0x31, 0xc0),
+ PIN(45, 1, 15, 0x31, 0xc0),
+ PIN(46, 0, 0, 0x22, 0x50),
+ PIN(47, 0, 25, 0x30, 0xb0),
+ PIN(48, 0, 24, 0x30, 0xb0),
+ PIN(49, 0, 23, 0x30, 0xb0),
+ PIN(50, 0, 5, 0x22, 0x50),
+ PIN(51, 0, 4, 0x22, 0x50),
+ PIN(52, 0, 3, 0x22, 0x50),
+ PIN(53, 0, 6, 0x22, 0x50),
+ PIN(54, 0, 7, 0x22, 0x50),
+ PIN(55, 0, 26, 0x30, 0xb0),
+ PIN(56, 0, 29, 0x30, 0xb0),
+ PIN(57, 0, 6, 0x31, 0xb0),
+ PIN(58, 0, 9, 0x31, 0xb0),
+ PIN(59, 0, 27, 0x30, 0xb0),
+ PIN(60, 0, 30, 0x30, 0xb0),
+ PIN(61, 0, 28, 0x30, 0xb0),
+ PIN(62, 0, 31, 0x30, 0xb0),
+ PIN(63, 0, 7, 0x31, 0xb0),
+ PIN(64, 0, 10, 0x31, 0xb0),
+ PIN(65, 0, 7, 0x23, 0x60),
+ PIN(66, 0, 9, 0x23, 0x60),
+ PIN(67, 0, 8, 0x23, 0x60),
+ PIN(68, 0, 10, 0x23, 0x60),
+ PIN(69, 0, 1, 0x30, 0xc0),
+ PIN(70, 0, 0, 0x30, 0xc0),
+ PIN(71, 0, 5, 0x30, 0xc0),
+ PIN(72, 0, 4, 0x30, 0xc0),
+ PIN(73, 0, 2, 0x30, 0xc0),
+ PIN(74, 0, 3, 0x30, 0xc0),
+ PIN(75, 0, 7, 0x30, 0xc0),
+ PIN(76, 0, 6, 0x30, 0xc0),
+ PIN(77, 0, 9, 0x30, 0xc0),
+ PIN(78, 0, 8, 0x30, 0xc0),
+ PIN(79, 0, 12, 0x23, 0x60),
+ PIN(80, 0, 11, 0x23, 0x60),
+ PIN(81, 0, 14, 0x23, 0x60),
+ PIN(82, 0, 13, 0x23, 0x60),
+ PIN(83, 0, 16, 0x31, 0xb0),
+ PIN(84, 0, 15, 0x31, 0xb0),
+ PIN(85, 0, 17, 0x31, 0xb0),
+ PIN(86, 0, 19, 0x31, 0xb0),
+ PIN(87, 0, 18, 0x31, 0xb0),
+ PIN(88, 0, 20, 0x31, 0xb0),
+ PIN(89, 0, 22, 0x31, 0xb0),
+ PIN(90, 0, 21, 0x31, 0xb0),
+ PIN(91, 0, 23, 0x31, 0xb0),
+ PIN(92, 0, 3, 0x31, 0xb0),
+ PIN(93, 0, 2, 0x31, 0xb0),
+ PIN(94, 0, 5, 0x31, 0xb0),
+ PIN(95, 0, 4, 0x31, 0xb0),
+ PIN(96, 0, 31, 0x31, 0xa0),
+ PIN(97, 0, 0, 0x31, 0xb0),
+ PIN(98, 0, 8, 0x31, 0xb0),
+ PIN(99, 0, 30, 0x31, 0xa0),
+ PIN(100, 0, 1, 0x31, 0xb0),
+ PIN(101, 0, 0, 0x31, 0xa0),
+ PIN(102, 0, 5, 0x31, 0xa0),
+ PIN(103, 0, 3, 0x31, 0xa0),
+ PIN(104, 0, 4, 0x31, 0xa0),
+ PIN(105, 0, 1, 0x31, 0xa0),
+ PIN(106, 0, 2, 0x31, 0xa0),
+ PIN(107, 0, 21, 0x31, 0xa0),
+ PIN(108, 0, 16, 0x31, 0xa0),
+ PIN(109, 0, 22, 0x31, 0xa0),
+ PIN(110, 0, 17, 0x31, 0xa0),
+ PIN(111, 0, 18, 0x31, 0xa0),
+ PIN(112, 0, 19, 0x31, 0xa0),
+ PIN(113, 0, 20, 0x31, 0xa0),
+ PIN(114, 0, 28, 0x31, 0xa0),
+ PIN(115, 0, 23, 0x31, 0xa0),
+ PIN(116, 0, 29, 0x31, 0xa0),
+ PIN(117, 0, 24, 0x31, 0xa0),
+ PIN(118, 0, 25, 0x31, 0xa0),
+ PIN(119, 0, 26, 0x31, 0xa0),
+ PIN(120, 0, 27, 0x31, 0xa0),
+ PIN(121, 0, 8, 0x22, 0x50),
+ PIN(122, 0, 11, 0x22, 0x50),
+ PIN(123, 0, 10, 0x22, 0x50),
+ PIN(124, 0, 9, 0x22, 0x50),
+ PIN(125, 0, 6, 0x31, 0xa0),
+ PIN(126, 0, 7, 0x31, 0xa0),
+ PIN(127, 0, 8, 0x31, 0xa0),
+ PIN(128, 0, 9, 0x31, 0xa0),
+ PIN(129, 0, 10, 0x31, 0xa0),
+ PIN(130, 0, 11, 0x31, 0xa0),
+ PIN(131, 1, 1, 0x30, 0xd0),
+ PIN(132, 1, 2, 0x30, 0xd0),
+ PIN(133, 1, 9, 0x30, 0xd0),
+ PIN(134, 1, 10, 0x30, 0xd0),
+ PIN(135, 1, 11, 0x30, 0xd0),
+ PIN(136, 1, 12, 0x30, 0xd0),
+ PIN(137, 1, 13, 0x30, 0xd0),
+ PIN(138, 1, 14, 0x30, 0xd0),
+ PIN(139, 1, 15, 0x30, 0xd0),
+ PIN(140, 1, 16, 0x30, 0xd0),
+ PIN(141, 1, 3, 0x30, 0xd0),
+ PIN(142, 1, 4, 0x30, 0xd0),
+ PIN(143, 1, 5, 0x30, 0xd0),
+ PIN(144, 1, 6, 0x30, 0xd0),
+ PIN(145, 1, 7, 0x30, 0xd0),
+ PIN(146, 1, 8, 0x30, 0xd0),
+ PIN(147, 1, 18, 0x30, 0xd0),
+ PIN(148, 1, 19, 0x30, 0xd0),
+ PIN(149, 1, 17, 0x30, 0xd0),
+ PIN(150, 1, 0, 0x30, 0xd0),
+ PIN(151, 1, 9, 0x31, 0xc0),
+ PIN(152, 1, 8, 0x31, 0xc0),
+ PIN(153, 1, 7, 0x31, 0xc0),
+ PIN(154, 1, 6, 0x31, 0xc0),
+ PIN(155, 1, 11, 0x31, 0xc0),
+ PIN(156, 1, 1, 0x31, 0xc0),
+ PIN(157, 1, 0, 0x31, 0xc0),
+ PIN(158, 1, 5, 0x31, 0xc0),
+ PIN(159, 1, 4, 0x31, 0xc0),
+ PIN(160, 1, 3, 0x31, 0xc0),
+ PIN(161, 1, 2, 0x31, 0xc0),
+ PIN(162, 1, 10, 0x31, 0xc0),
+ PIN(163, 1, 1, 0x23, 0x70),
+ PIN(164, 1, 0, 0x23, 0x70),
+ PIN(165, 1, 2, 0x23, 0x70),
+ PIN(166, 1, 3, 0x23, 0x70),
+ PIN(167, 1, 4, 0x23, 0x70),
+ PIN(168, 1, 5, 0x23, 0x70),
+ PIN(169, 1, 1, 0x22, 0x60),
+ PIN(170, 1, 0, 0x22, 0x60),
+ PIN(171, 1, 2, 0x22, 0x60),
+ PIN(172, 1, 3, 0x22, 0x60),
+ PIN(173, 1, 4, 0x22, 0x60),
+ PIN(174, 1, 5, 0x22, 0x60),
+ PIN(175, 0, 11, 0x31, 0xb0),
+ PIN(176, 0, 12, 0x31, 0xb0),
+};
+
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/drivers/gpio/mtgpio_common.c b/plat/mediatek/drivers/gpio/mtgpio_common.c
new file mode 100644
index 0000000..bad0190
--- /dev/null
+++ b/plat/mediatek/drivers/gpio/mtgpio_common.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/gpio.h>
+#include <lib/mmio.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ *Macro Definition
+ ******************************************************************************/
+#define GPIO_MODE_BITS 4
+#define MAX_GPIO_MODE_PER_REG 8
+#define MAX_GPIO_REG_BITS 32
+#define DIR_BASE (GPIO_BASE + 0x000)
+#define DOUT_BASE (GPIO_BASE + 0x100)
+#define DIN_BASE (GPIO_BASE + 0x200)
+#define MODE_BASE (GPIO_BASE + 0x300)
+#define SET 0x4
+#define CLR 0x8
+
+static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
+{
+ uint32_t pos, bit;
+
+ assert(pin < MAX_GPIO_PIN);
+ assert(dir < MT_GPIO_DIR_MAX);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ if (dir == MT_GPIO_DIR_IN) {
+ mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
+ } else {
+ mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
+ }
+}
+
+static int mt_get_gpio_dir_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t reg;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ reg = mmio_read_32(DIR_BASE + 0x10U * pos);
+ return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
+}
+
+static void mt_set_gpio_out_chip(uint32_t pin, int output)
+{
+ uint32_t pos, bit;
+
+ assert(pin < MAX_GPIO_PIN);
+ assert(output < MT_GPIO_OUT_MAX);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ if (output == MT_GPIO_OUT_ZERO) {
+ mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
+ } else {
+ mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
+ }
+}
+
+static int mt_get_gpio_in_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t reg;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ reg = mmio_read_32(DIN_BASE + 0x10U * pos);
+ return (((reg & (1U << bit)) != 0U) ? 1 : 0);
+}
+
+static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
+ int select)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 + (gpio_info.base & 0xf0);
+ if (enable == MT_GPIO_PULL_ENABLE) {
+ mmio_write_32(reg2 + SET, (1U << bit));
+ if (select == MT_GPIO_PULL_DOWN) {
+ mmio_write_32(reg1 + SET, (1U << bit));
+ } else {
+ mmio_write_32(reg1 + CLR, (1U << bit));
+ }
+ } else {
+ mmio_write_32(reg2 + CLR, (1U << bit));
+ mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
+ }
+}
+
+static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
+ int select)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 - (gpio_info.base & 0xf0);
+
+ if (enable == MT_GPIO_PULL_ENABLE) {
+ if (select == MT_GPIO_PULL_DOWN) {
+ mmio_write_32(reg1 + CLR, (1U << bit));
+ mmio_write_32(reg2 + SET, (1U << bit));
+ } else {
+ mmio_write_32(reg2 + CLR, (1U << bit));
+ mmio_write_32(reg1 + SET, (1U << bit));
+ }
+ } else {
+ mmio_write_32(reg1 + CLR, (1U << bit));
+ mmio_write_32(reg2 + CLR, (1U << bit));
+ }
+}
+
+static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
+ int select)
+{
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt_pin_infos[pin];
+ if (gpio_info.flag) {
+ mt_gpio_set_spec_pull_pupd(pin, enable, select);
+ } else {
+ mt_gpio_set_pull_pu_pd(pin, enable, select);
+ }
+}
+
+static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ uint32_t r0;
+ uint32_t r1;
+
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 + (gpio_info.base & 0xf0);
+
+ r0 = (mmio_read_32(reg2) >> bit) & 1U;
+ r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
+ if (r0 == 0U && r1 == 0U) {
+ return MT_GPIO_PULL_NONE;
+ } else {
+ if (mmio_read_32(reg1) & (1U << bit)) {
+ return MT_GPIO_PULL_DOWN;
+ } else {
+ return MT_GPIO_PULL_UP;
+ }
+ }
+}
+
+static int mt_gpio_get_pull_pu_pd(uint32_t pin)
+{
+ uintptr_t reg1;
+ uintptr_t reg2;
+ uint32_t pu;
+ uint32_t pd;
+
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt_pin_infos[pin];
+ uint32_t bit = gpio_info.bit;
+
+ reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
+ reg2 = reg1 - (gpio_info.base & 0xf0);
+ pu = (mmio_read_32(reg1) >> bit) & 1U;
+ pd = (mmio_read_32(reg2) >> bit) & 1U;
+ if (pu == 1U) {
+ return MT_GPIO_PULL_UP;
+ } else if (pd == 1U) {
+ return MT_GPIO_PULL_DOWN;
+ } else {
+ return MT_GPIO_PULL_NONE;
+ }
+}
+
+static int mt_gpio_get_pull_chip(uint32_t pin)
+{
+ struct mt_pin_info gpio_info;
+
+ gpio_info = mt_pin_infos[pin];
+ if (gpio_info.flag) {
+ return mt_gpio_get_spec_pull_pupd(pin);
+ } else {
+ return mt_gpio_get_pull_pu_pd(pin);
+ }
+}
+
+static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
+{
+ assert(pin < MAX_GPIO_PIN);
+
+ if (sel == MT_GPIO_PULL_NONE) {
+ mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
+ } else if (sel == MT_GPIO_PULL_UP) {
+ mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
+ } else if (sel == MT_GPIO_PULL_DOWN) {
+ mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
+ }
+}
+
+/* get pull-up or pull-down, regardless of resistor value */
+static int mt_get_gpio_pull_select_chip(uint32_t pin)
+{
+ assert(pin < MAX_GPIO_PIN);
+
+ return mt_gpio_get_pull_chip(pin);
+}
+
+static void mt_set_gpio_dir(int gpio, int direction)
+{
+ mt_set_gpio_dir_chip((uint32_t)gpio, direction);
+}
+
+static int mt_get_gpio_dir(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_dir_chip(pin);
+}
+
+static void mt_set_gpio_pull(int gpio, int pull)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ mt_set_gpio_pull_select_chip(pin, pull);
+}
+
+static int mt_get_gpio_pull(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_pull_select_chip(pin);
+}
+
+static void mt_set_gpio_out(int gpio, int value)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ mt_set_gpio_out_chip(pin, value);
+}
+
+static int mt_get_gpio_in(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_in_chip(pin);
+}
+
+const gpio_ops_t mtgpio_ops = {
+ .get_direction = mt_get_gpio_dir,
+ .set_direction = mt_set_gpio_dir,
+ .get_value = mt_get_gpio_in,
+ .set_value = mt_set_gpio_out,
+ .set_pull = mt_set_gpio_pull,
+ .get_pull = mt_get_gpio_pull,
+};
+
+int mt_gpio_init(void)
+{
+ gpio_init(&mtgpio_ops);
+
+ return 0;
+}
+MTK_PLAT_SETUP_0_INIT(mt_gpio_init);
diff --git a/plat/mediatek/drivers/gpio/mtgpio_common.h b/plat/mediatek/drivers/gpio/mtgpio_common.h
new file mode 100644
index 0000000..d6b858c
--- /dev/null
+++ b/plat/mediatek/drivers/gpio/mtgpio_common.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_COMMON_H
+#define MT_GPIO_COMMON_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <plat/common/common_def.h>
+
+/* Error Code No. */
+#define RSUCCESS 0
+#define ERACCESS 1
+#define ERINVAL 2
+#define ERWRAPPER 3
+#define MAX_GPIO_PIN MT_GPIO_BASE_MAX
+
+/* GPIO MODE CONTROL VALUE*/
+typedef enum {
+ GPIO_MODE_UNSUPPORTED = -1,
+ GPIO_MODE_GPIO = 0,
+ GPIO_MODE_00 = 0,
+ GPIO_MODE_01,
+ GPIO_MODE_02,
+ GPIO_MODE_03,
+ GPIO_MODE_04,
+ GPIO_MODE_05,
+ GPIO_MODE_06,
+ GPIO_MODE_07,
+
+ GPIO_MODE_MAX,
+ GPIO_MODE_DEFAULT = GPIO_MODE_00,
+} GPIO_MODE;
+
+/* GPIO DIRECTION */
+typedef enum {
+ MT_GPIO_DIR_UNSUPPORTED = -1,
+ MT_GPIO_DIR_OUT = 0,
+ MT_GPIO_DIR_IN = 1,
+ MT_GPIO_DIR_MAX,
+ MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN,
+} GPIO_DIR;
+
+/* GPIO PULL ENABLE*/
+typedef enum {
+ MT_GPIO_PULL_EN_UNSUPPORTED = -1,
+ MT_GPIO_PULL_DISABLE = 0,
+ MT_GPIO_PULL_ENABLE = 1,
+ MT_GPIO_PULL_ENABLE_R0 = 2,
+ MT_GPIO_PULL_ENABLE_R1 = 3,
+ MT_GPIO_PULL_ENABLE_R0R1 = 4,
+
+ MT_GPIO_PULL_EN_MAX,
+ MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE,
+} GPIO_PULL_EN;
+
+/* GPIO PULL-UP/PULL-DOWN*/
+typedef enum {
+ MT_GPIO_PULL_UNSUPPORTED = -1,
+ MT_GPIO_PULL_NONE = 0,
+ MT_GPIO_PULL_UP = 1,
+ MT_GPIO_PULL_DOWN = 2,
+ MT_GPIO_PULL_MAX,
+ MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN
+} GPIO_PULL;
+
+/* GPIO OUTPUT */
+typedef enum {
+ MT_GPIO_OUT_UNSUPPORTED = -1,
+ MT_GPIO_OUT_ZERO = 0,
+ MT_GPIO_OUT_ONE = 1,
+
+ MT_GPIO_OUT_MAX,
+ MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO,
+ MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO, /*compatible with DCT*/
+} GPIO_OUT;
+
+/* GPIO INPUT */
+typedef enum {
+ MT_GPIO_IN_UNSUPPORTED = -1,
+ MT_GPIO_IN_ZERO = 0,
+ MT_GPIO_IN_ONE = 1,
+
+ MT_GPIO_IN_MAX,
+} GPIO_IN;
+
+#define PIN(_id, _flag, _bit, _base, _offset) { \
+ .id = _id, \
+ .flag = _flag, \
+ .bit = _bit, \
+ .base = _base, \
+ .offset = _offset, \
+ }
+
+struct mt_pin_info {
+ uint8_t id;
+ uint8_t flag;
+ uint8_t bit;
+ uint16_t base;
+ uint16_t offset;
+};
+
+int mt_gpio_init(void);
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin);
+#endif /* MT_GPIO_COMMON_H */
diff --git a/plat/mediatek/drivers/gpio/rules.mk b/plat/mediatek/drivers/gpio/rules.mk
new file mode 100644
index 0000000..78061a8
--- /dev/null
+++ b/plat/mediatek/drivers/gpio/rules.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := gpio
+
+LOCAL_SRCS-y := drivers/gpio/gpio.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/mtgpio_common.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/mtgpio.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c
new file mode 100644
index 0000000..1d6863f
--- /dev/null
+++ b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mtk_iommu_plat.h>
+#include <mtk_mmap_pool.h>
+#include <platform_def.h>
+
+/* mm iommu */
+#define SMI_L0_ID (0)
+#define SMI_L1_ID (1)
+#define SMI_L2_ID (2)
+#define SMI_L3_ID (3)
+#define SMI_L4_ID (4)
+#define SMI_L5_ID (5)
+#define SMI_L6_ID (6)
+#define SMI_L7_ID (7)
+#define SMI_L9_ID (8)
+#define SMI_L10_ID (9)
+#define SMI_L11A_ID (10)
+#define SMI_L11B_ID (11)
+#define SMI_L11C_ID (12)
+#define SMI_L12_ID (13)
+#define SMI_L13_ID (14)
+#define SMI_L14_ID (15)
+#define SMI_L15_ID (16)
+#define SMI_L16A_ID (17)
+#define SMI_L16B_ID (18)
+#define SMI_L17A_ID (19)
+#define SMI_L17B_ID (20)
+#define SMI_L19_ID (21)
+#define SMI_L21_ID (22)
+#define SMI_L23_ID (23)
+#define SMI_L27_ID (24)
+#define SMI_L28_ID (25)
+
+/* infra iommu */
+#define PERI_MST_PROT (0x710)
+#define PERICFG_AO_IOMMU_1 (0x714)
+#define MMU_DEV_PCIE_0 (0)
+#define IFR_CFG_GROUP_NUM (1)
+
+static struct mtk_smi_larb_config mt8188_larb_cfg[SMI_LARB_NUM] = {
+ [SMI_L0_ID] = LARB_CFG_ENTRY(SMI_LARB_0_BASE, 7, 0),
+ [SMI_L1_ID] = LARB_CFG_ENTRY(SMI_LARB_1_BASE, 7, 0),
+ [SMI_L2_ID] = LARB_CFG_ENTRY(SMI_LARB_2_BASE, 5, 0),
+ [SMI_L3_ID] = LARB_CFG_ENTRY(SMI_LARB_3_BASE, 7, 0),
+ [SMI_L4_ID] = LARB_CFG_ENTRY(SMI_LARB_4_BASE, 7, 0),
+ [SMI_L5_ID] = LARB_CFG_ENTRY(SMI_LARB_5_BASE, 8, 0),
+ [SMI_L6_ID] = LARB_CFG_ENTRY(SMI_LARB_6_BASE, 4, 0),
+ [SMI_L7_ID] = LARB_CFG_ENTRY(SMI_LARB_7_BASE, 3, 0),
+ [SMI_L9_ID] = LARB_CFG_ENTRY(SMI_LARB_9_BASE, 25, 0),
+ [SMI_L10_ID] = LARB_CFG_ENTRY(SMI_LARB_10_BASE, 20, 0),
+ [SMI_L11A_ID] = LARB_CFG_ENTRY(SMI_LARB_11A_BASE, 30, 0),
+ [SMI_L11B_ID] = LARB_CFG_ENTRY(SMI_LARB_11B_BASE, 30, 0),
+ [SMI_L11C_ID] = LARB_CFG_ENTRY(SMI_LARB_11C_BASE, 30, 0),
+ [SMI_L12_ID] = LARB_CFG_ENTRY(SMI_LARB_12_BASE, 16, 0),
+ [SMI_L13_ID] = LARB_CFG_ENTRY(SMI_LARB_13_BASE, 24, 0),
+ [SMI_L14_ID] = LARB_CFG_ENTRY(SMI_LARB_14_BASE, 23, 0),
+ [SMI_L15_ID] = LARB_CFG_ENTRY(SMI_LARB_15_BASE, 19, 0),
+ [SMI_L16A_ID] = LARB_CFG_ENTRY(SMI_LARB_16A_BASE, 17, 0),
+ [SMI_L16B_ID] = LARB_CFG_ENTRY(SMI_LARB_16B_BASE, 17, 0),
+ [SMI_L17A_ID] = LARB_CFG_ENTRY(SMI_LARB_17A_BASE, 7, 0),
+ [SMI_L17B_ID] = LARB_CFG_ENTRY(SMI_LARB_17B_BASE, 7, 0),
+ /* venc nbm ports (5/6/11/15/16/17) to sram */
+ [SMI_L19_ID] = LARB_CFG_ENTRY_WITH_PATH(SMI_LARB_19_BASE, 27, 0, 0x38860),
+ [SMI_L21_ID] = LARB_CFG_ENTRY(SMI_LARB_21_BASE, 11, 0),
+ [SMI_L23_ID] = LARB_CFG_ENTRY(SMI_LARB_23_BASE, 9, 0),
+ [SMI_L27_ID] = LARB_CFG_ENTRY(SMI_LARB_27_BASE, 4, 0),
+ [SMI_L28_ID] = LARB_CFG_ENTRY(SMI_LARB_28_BASE, 0, 0),
+};
+
+static bool is_protected;
+
+static uint32_t mt8188_ifr_mst_cfg_base[IFR_CFG_GROUP_NUM] = {
+ PERICFG_AO_BASE,
+};
+static uint32_t mt8188_ifr_mst_cfg_offs[IFR_CFG_GROUP_NUM] = {
+ PERICFG_AO_IOMMU_1,
+};
+static struct mtk_ifr_mst_config mt8188_ifr_mst_cfg[MMU_DEV_NUM] = {
+ [MMU_DEV_PCIE_0] = IFR_MST_CFG_ENTRY(0, 18),
+};
+
+struct mtk_smi_larb_config *g_larb_cfg = &mt8188_larb_cfg[0];
+struct mtk_ifr_mst_config *g_ifr_mst_cfg = &mt8188_ifr_mst_cfg[0];
+uint32_t *g_ifr_mst_cfg_base = &mt8188_ifr_mst_cfg_base[0];
+uint32_t *g_ifr_mst_cfg_offs = &mt8188_ifr_mst_cfg_offs[0];
+
+/* Protect infra iommu enable setting registers as secure access. */
+void mtk_infra_iommu_enable_protect(void)
+{
+ if (!is_protected) {
+ mmio_write_32(PERICFG_AO_BASE + PERI_MST_PROT, 0xffffffff);
+ is_protected = true;
+ }
+}
diff --git a/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h
new file mode 100644
index 0000000..a59e0c7
--- /dev/null
+++ b/plat/mediatek/drivers/iommu/mt8188/mtk_iommu_plat.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IOMMU_PLAT_H
+#define IOMMU_PLAT_H
+
+#include <mtk_iommu_priv.h>
+
+/* mm iommu */
+#define SMI_LARB_NUM (26)
+extern struct mtk_smi_larb_config *g_larb_cfg;
+
+/* infra iommu */
+#define MMU_DEV_NUM (1)
+extern struct mtk_ifr_mst_config *g_ifr_mst_cfg;
+extern uint32_t *g_ifr_mst_cfg_base;
+extern uint32_t *g_ifr_mst_cfg_offs;
+
+extern void mtk_infra_iommu_enable_protect(void);
+
+#endif /* IOMMU_PLAT_H */
diff --git a/plat/mediatek/drivers/iommu/mtk_iommu_priv.h b/plat/mediatek/drivers/iommu/mtk_iommu_priv.h
new file mode 100644
index 0000000..3404d31
--- /dev/null
+++ b/plat/mediatek/drivers/iommu/mtk_iommu_priv.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IOMMU_PRIV_H
+#define IOMMU_PRIV_H
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+
+#define LARB_CFG_ENTRY(bs, p_nr, dom) \
+ { .base = (bs), .port_nr = (p_nr), \
+ .dom_id = (dom), .to_sram = 0, }
+
+#define LARB_CFG_ENTRY_WITH_PATH(bs, p_nr, dom, sram) \
+ { .base = (bs), .port_nr = (p_nr), \
+ .dom_id = (dom), .to_sram = (sram), }
+
+#define IFR_MST_CFG_ENTRY(idx, bit) \
+ { .cfg_addr_idx = (idx), .r_mmu_en_bit = (bit), }
+
+enum IOMMU_ATF_CMD {
+ IOMMU_ATF_CMD_CONFIG_SMI_LARB, /* For mm master to enable iommu */
+ IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU, /* For infra master to enable iommu */
+ IOMMU_ATF_CMD_COUNT,
+};
+
+struct mtk_smi_larb_config {
+ uint32_t base;
+ uint32_t port_nr;
+ uint32_t dom_id;
+ uint32_t to_sram;
+ uint32_t sec_en_msk;
+};
+
+struct mtk_ifr_mst_config {
+ uint8_t cfg_addr_idx;
+ uint8_t r_mmu_en_bit;
+};
+
+#endif /* IOMMU_PRIV_H */
diff --git a/plat/mediatek/drivers/iommu/mtk_iommu_smc.c b/plat/mediatek/drivers/iommu/mtk_iommu_smc.c
new file mode 100644
index 0000000..9762d0b
--- /dev/null
+++ b/plat/mediatek/drivers/iommu/mtk_iommu_smc.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <mtk_iommu_plat.h>
+
+/* defination */
+/* smi larb */
+#define SMI_LARB_NON_SEC_CON(port) (0x380 + ((port) << 2))
+#define PATH_SEL_MASK (0xf0000) /* to sram (INT) */
+#define SMI_LARB_SEC_CON_INT(port) (0xf00 + ((port) << 2))
+#define SMI_LARB_SEC_CON(port) (0xf80 + ((port) << 2))
+#define MMU_MASK BIT(0)
+#define MMU_EN(en) ((!!(en)) << 0)
+#define SEC_MASK BIT(1)
+#define SEC_EN(en) ((!!(en)) << 1)
+#define DOMAIN_MASK (0x1f << 4)
+#define SMI_MMU_EN(port) (0x1 << (port))
+
+/* infra master */
+#define IFR_CFG_MMU_EN_MSK(r_bit) (0x3 << (r_bit))
+
+/* smi larb configure */
+/*
+ * If multimedia security config is enabled, the SMI config register must be
+ * configurated in security world.
+ * And the SRAM path is also configurated here to enhance security.
+ */
+static void mtk_smi_larb_port_config_to_sram(
+ const struct mtk_smi_larb_config *larb,
+ uint32_t port_id)
+{
+ mmio_clrbits_32(larb->base + SMI_LARB_SEC_CON_INT(port_id),
+ MMU_MASK | SEC_MASK | DOMAIN_MASK);
+
+ mmio_setbits_32(larb->base + SMI_LARB_NON_SEC_CON(port_id),
+ PATH_SEL_MASK);
+}
+
+static void mtk_smi_port_config(const struct mtk_smi_larb_config *larb,
+ uint32_t port_id, uint8_t mmu_en, uint8_t sec_en)
+{
+ mmio_clrsetbits_32(larb->base + SMI_LARB_SEC_CON(port_id),
+ MMU_MASK | SEC_MASK | DOMAIN_MASK,
+ MMU_EN(mmu_en) | SEC_EN(sec_en));
+}
+
+static int mtk_smi_larb_port_config_sec(uint32_t larb_id, uint32_t mmu_en_msk)
+{
+ uint32_t port_id, port_nr;
+ const struct mtk_smi_larb_config *larb;
+ uint32_t to_sram;
+ uint8_t mmu_en;
+
+ if (larb_id >= SMI_LARB_NUM) {
+ return MTK_SIP_E_INVALID_PARAM;
+ }
+
+ larb = &g_larb_cfg[larb_id];
+ port_nr = larb->port_nr;
+ to_sram = larb->to_sram;
+
+ for (port_id = 0; port_id < port_nr; port_id++) {
+ if ((to_sram & BIT(port_id)) > 0U) {
+ mtk_smi_larb_port_config_to_sram(larb, port_id);
+ continue;
+ }
+ mmu_en = !!(mmu_en_msk & SMI_MMU_EN(port_id));
+ mtk_smi_port_config(larb, port_id, mmu_en, 0);
+ }
+
+ return MTK_SIP_E_SUCCESS;
+}
+
+static int mtk_infra_master_config_sec(uint32_t dev_id, uint32_t enable)
+{
+ const struct mtk_ifr_mst_config *ifr_cfg;
+ uint32_t reg_addr;
+
+ mtk_infra_iommu_enable_protect();
+
+ if (dev_id >= MMU_DEV_NUM) {
+ return MTK_SIP_E_NOT_SUPPORTED;
+ }
+
+ ifr_cfg = &g_ifr_mst_cfg[dev_id];
+ reg_addr = g_ifr_mst_cfg_base[(ifr_cfg->cfg_addr_idx)] +
+ g_ifr_mst_cfg_offs[(ifr_cfg->cfg_addr_idx)];
+
+ if (enable > 0U) {
+ mmio_setbits_32(reg_addr, IFR_CFG_MMU_EN_MSK(ifr_cfg->r_mmu_en_bit));
+ } else {
+ mmio_clrbits_32(reg_addr, IFR_CFG_MMU_EN_MSK(ifr_cfg->r_mmu_en_bit));
+ }
+
+ return MTK_SIP_E_SUCCESS;
+}
+
+static u_register_t mtk_iommu_handler(u_register_t x1, u_register_t x2,
+ u_register_t x3, u_register_t x4,
+ void *handle, struct smccc_res *smccc_ret)
+{
+ uint32_t cmd_id = x1, mdl_id = x2, val = x3;
+ int ret = MTK_SIP_E_NOT_SUPPORTED;
+
+ (void)x4;
+ (void)handle;
+
+ switch (cmd_id) {
+ case IOMMU_ATF_CMD_CONFIG_SMI_LARB:
+ ret = mtk_smi_larb_port_config_sec(mdl_id, val);
+ break;
+ case IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU:
+ ret = mtk_infra_master_config_sec(mdl_id, val);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+DECLARE_SMC_HANDLER(MTK_SIP_IOMMU_CONTROL, mtk_iommu_handler);
diff --git a/plat/mediatek/drivers/iommu/rules.mk b/plat/mediatek/drivers/iommu/rules.mk
new file mode 100644
index 0000000..5490f41
--- /dev/null
+++ b/plat/mediatek/drivers/iommu/rules.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_iommu
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_iommu_smc.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/mtk_iommu_plat.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/mcusys/mcusys.c b/plat/mediatek/drivers/mcusys/mcusys.c
new file mode 100644
index 0000000..63edb23
--- /dev/null
+++ b/plat/mediatek/drivers/mcusys/mcusys.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <mtk_mmap_pool.h>
+#include <platform_def.h>
+
+static const mmap_region_t mcusys_mmap[] MTK_MMAP_SECTION = {
+ MAP_REGION_FLAT(MCUCFG_BASE, MCUCFG_REG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ {0}
+};
+DECLARE_MTK_MMAP_REGIONS(mcusys_mmap);
diff --git a/plat/mediatek/drivers/mcusys/rules.mk b/plat/mediatek/drivers/mcusys/rules.mk
new file mode 100644
index 0000000..5438998
--- /dev/null
+++ b/plat/mediatek/drivers/mcusys/rules.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mcusys
+
+PLAT_INCLUDES += -I$(LOCAL_DIR)/$(MCUSYS_VERSION)
+
+LOCAL_SRCS-y := $(LOCAL_DIR)/mcusys.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/mcusys/v1/mcucfg.h b/plat/mediatek/drivers/mcusys/v1/mcucfg.h
new file mode 100644
index 0000000..7aced5a
--- /dev/null
+++ b/plat/mediatek/drivers/mcusys/v1/mcucfg.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCUCFG_V1_H
+#define MCUCFG_V1_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /*__ASSEMBLER__*/
+
+#include <platform_def.h>
+
+#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_BASE + 0x2290 + ((cpu) * 8))
+#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_BASE + 0x2294 + ((cpu) * 8))
+
+#define MP2_CPUCFG (MCUCFG_BASE + 0x2208)
+
+#define MP0_CPUTOP_SPMC_CTL (MCUCFG_BASE + 0x788)
+#define MP1_CPUTOP_SPMC_CTL (MCUCFG_BASE + 0x78C)
+#define MP1_CPUTOP_SPMC_SRAM_CTL (MCUCFG_BASE + 0x790)
+
+#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) (MCUCFG_BASE + 0x1C30 + \
+ (cluster) * 0x2000 + (cpu) * 4)
+
+#define CPUSYS0_CPU0_SPMC_CTL (MCUCFG_BASE + 0x1C30)
+#define CPUSYS0_CPU1_SPMC_CTL (MCUCFG_BASE + 0x1C34)
+#define CPUSYS0_CPU2_SPMC_CTL (MCUCFG_BASE + 0x1C38)
+#define CPUSYS0_CPU3_SPMC_CTL (MCUCFG_BASE + 0x1C3C)
+
+#define CPUSYS1_CPU0_SPMC_CTL (MCUCFG_BASE + 0x3C30)
+#define CPUSYS1_CPU1_SPMC_CTL (MCUCFG_BASE + 0x3C34)
+#define CPUSYS1_CPU2_SPMC_CTL (MCUCFG_BASE + 0x3C38)
+#define CPUSYS1_CPU3_SPMC_CTL (MCUCFG_BASE + 0x3C3C)
+
+/* CPC related registers */
+#define CPC_MCUSYS_CPC_OFF_THRES (MCUCFG_BASE + 0xA714)
+#define CPC_MCUSYS_PWR_CTRL (MCUCFG_BASE + 0xA804)
+#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG (MCUCFG_BASE + 0xA814)
+#define CPC_MCUSYS_LAST_CORE_REQ (MCUCFG_BASE + 0xA818)
+#define CPC_MCUSYS_MP_LAST_CORE_RESP (MCUCFG_BASE + 0xA81C)
+#define CPC_MCUSYS_LAST_CORE_RESP (MCUCFG_BASE + 0xA824)
+#define CPC_MCUSYS_PWR_ON_MASK (MCUCFG_BASE + 0xA828)
+#define CPC_SPMC_PWR_STATUS (MCUCFG_BASE + 0xA840)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_SET (MCUCFG_BASE + 0xA8A8)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR (MCUCFG_BASE + 0xA8AC)
+#define CPC_MCUSYS_CPC_DBG_SETTING (MCUCFG_BASE + 0xAB00)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE (MCUCFG_BASE + 0xAB04)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE (MCUCFG_BASE + 0xAB08)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE (MCUCFG_BASE + 0xAB0C)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE (MCUCFG_BASE + 0xAB10)
+#define CPC_MCUSYS_TRACE_SEL (MCUCFG_BASE + 0xAB14)
+#define CPC_MCUSYS_TRACE_DATA (MCUCFG_BASE + 0xAB20)
+#define CPC_MCUSYS_CLUSTER_COUNTER (MCUCFG_BASE + 0xAB70)
+#define CPC_MCUSYS_CLUSTER_COUNTER_CLR (MCUCFG_BASE + 0xAB74)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG bit control */
+#define CPC_CTRL_ENABLE BIT(16)
+#define SSPM_CORE_PWR_ON_EN BIT(7) /* for cpu-hotplug */
+#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
+
+#define CPC_MCUSYS_CPC_RESET_ON_KEEP_ON BIT(17)
+#define CPC_MCUSYS_CPC_RESET_PWR_ON_EN BIT(20)
+
+/* SPMC related registers */
+#define SPM_MCUSYS_PWR_CON (MCUCFG_BASE + 0xD200)
+#define SPM_MP0_CPUTOP_PWR_CON (MCUCFG_BASE + 0xD204)
+#define SPM_MP0_CPU0_PWR_CON (MCUCFG_BASE + 0xD208)
+#define SPM_MP0_CPU1_PWR_CON (MCUCFG_BASE + 0xD20C)
+#define SPM_MP0_CPU2_PWR_CON (MCUCFG_BASE + 0xD210)
+#define SPM_MP0_CPU3_PWR_CON (MCUCFG_BASE + 0xD214)
+#define SPM_MP0_CPU4_PWR_CON (MCUCFG_BASE + 0xD218)
+#define SPM_MP0_CPU5_PWR_CON (MCUCFG_BASE + 0xD21C)
+#define SPM_MP0_CPU6_PWR_CON (MCUCFG_BASE + 0xD220)
+#define SPM_MP0_CPU7_PWR_CON (MCUCFG_BASE + 0xD224)
+
+/* bit fields of SPM_*_PWR_CON */
+#define PWR_ON_ACK BIT(31)
+#define VPROC_EXT_OFF BIT(7)
+#define DORMANT_EN BIT(6)
+#define RESETPWRON_CONFIG BIT(5)
+#define PWR_CLK_DIS BIT(4)
+#define PWR_ON BIT(2)
+#define PWR_RST_B BIT(0)
+
+#define SPARK2LDO (MCUCFG_BASE + 0x2700)
+/* APB Module mcucfg */
+#define MP0_CA7_CACHE_CONFIG (MCUCFG_BASE + 0x000)
+#define MP0_AXI_CONFIG (MCUCFG_BASE + 0x02C)
+#define MP0_MISC_CONFIG0 (MCUCFG_BASE + 0x030)
+#define MP0_MISC_CONFIG1 (MCUCFG_BASE + 0x034)
+#define MP0_MISC_CONFIG2 (MCUCFG_BASE + 0x038)
+#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MCUCFG_BASE + 0x038 + ((cpu) * 8))
+#define MP0_MISC_CONFIG3 (MCUCFG_BASE + 0x03C)
+#define MP0_MISC_CONFIG9 (MCUCFG_BASE + 0x054)
+#define MP0_CA7_MISC_CONFIG (MCUCFG_BASE + 0x064)
+
+#define MP0_RW_RSVD0 (MCUCFG_BASE + 0x06C)
+#define MP1_CA7_CACHE_CONFIG (MCUCFG_BASE + 0x200)
+#define MP1_AXI_CONFIG (MCUCFG_BASE + 0x22C)
+#define MP1_MISC_CONFIG0 (MCUCFG_BASE + 0x230)
+#define MP1_MISC_CONFIG1 (MCUCFG_BASE + 0x234)
+#define MP1_MISC_CONFIG2 (MCUCFG_BASE + 0x238)
+#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MCUCFG_BASE + 0x238 + ((cpu) * 8))
+#define MP1_MISC_CONFIG3 (MCUCFG_BASE + 0x23C)
+#define MP1_MISC_CONFIG9 (MCUCFG_BASE + 0x254)
+#define MP1_CA7_MISC_CONFIG (MCUCFG_BASE + 0x264)
+
+#define CCI_ADB400_DCM_CONFIG (MCUCFG_BASE + 0x740)
+#define SYNC_DCM_CONFIG (MCUCFG_BASE + 0x744)
+
+#define MP0_CLUSTER_CFG0 (MCUCFG_BASE + 0xC8D0)
+
+#define MP0_SPMC (MCUCFG_BASE + 0x788)
+#define MP1_SPMC (MCUCFG_BASE + 0x78C)
+#define MP2_AXI_CONFIG (MCUCFG_BASE + 0x220C)
+#define MP2_AXI_CONFIG_ACINACTM BIT(0)
+#define MP2_AXI_CONFIG_AINACTS BIT(4)
+
+#define MPx_AXI_CONFIG_ACINACTM BIT(4)
+#define MPx_AXI_CONFIG_AINACTS BIT(5)
+
+#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
+
+#define MP0_CPU0_STANDBYWFE BIT(20)
+#define MP0_CPU1_STANDBYWFE BIT(21)
+#define MP0_CPU2_STANDBYWFE BIT(22)
+#define MP0_CPU3_STANDBYWFE BIT(23)
+
+#define MP1_CPU0_STANDBYWFE BIT(20)
+#define MP1_CPU1_STANDBYWFE BIT(21)
+#define MP1_CPU2_STANDBYWFE BIT(22)
+#define MP1_CPU3_STANDBYWFE BIT(23)
+
+#define CPUSYS0_SPARKVRETCNTRL (MCUCFG_BASE+0x1c00)
+#define CPUSYS0_SPARKEN (MCUCFG_BASE+0x1c04)
+#define CPUSYS0_AMUXSEL (MCUCFG_BASE+0x1c08)
+#define CPUSYS1_SPARKVRETCNTRL (MCUCFG_BASE+0x3c00)
+#define CPUSYS1_SPARKEN (MCUCFG_BASE+0x3c04)
+#define CPUSYS1_AMUXSEL (MCUCFG_BASE+0x3c08)
+
+#define MP2_PWR_RST_CTL (MCUCFG_BASE + 0x2008)
+#define MP2_PTP3_CPUTOP_SPMC0 (MCUCFG_BASE + 0x22A0)
+#define MP2_PTP3_CPUTOP_SPMC1 (MCUCFG_BASE + 0x22A4)
+
+#define MP2_COQ (MCUCFG_BASE + 0x22BC)
+#define MP2_COQ_SW_DIS BIT(0)
+
+#define MP2_CA15M_MON_SEL (MCUCFG_BASE + 0x2400)
+#define MP2_CA15M_MON_L (MCUCFG_BASE + 0x2404)
+
+#define CPUSYS2_CPU0_SPMC_CTL (MCUCFG_BASE + 0x2430)
+#define CPUSYS2_CPU1_SPMC_CTL (MCUCFG_BASE + 0x2438)
+#define CPUSYS2_CPU0_SPMC_STA (MCUCFG_BASE + 0x2434)
+#define CPUSYS2_CPU1_SPMC_STA (MCUCFG_BASE + 0x243C)
+
+#define MP0_CA7L_DBG_PWR_CTRL (MCUCFG_BASE + 0x068)
+#define MP1_CA7L_DBG_PWR_CTRL (MCUCFG_BASE + 0x268)
+#define BIG_DBG_PWR_CTRL (MCUCFG_BASE + 0x75C)
+
+#define MP2_SW_RST_B BIT(0)
+#define MP2_TOPAON_APB_MASK BIT(1)
+#define B_SW_HOT_PLUG_RESET BIT(30)
+#define B_SW_PD_OFFSET (18)
+#define B_SW_PD (0x3F << B_SW_PD_OFFSET)
+
+#define B_SW_SRAM_SLEEPB_OFFSET (12)
+#define B_SW_SRAM_SLEEPB (0x3F << B_SW_SRAM_SLEEPB_OFFSET)
+
+#define B_SW_SRAM_ISOINTB BIT(9)
+#define B_SW_ISO BIT(8)
+#define B_SW_LOGIC_PDB BIT(7)
+#define B_SW_LOGIC_PRE2_PDB BIT(6)
+#define B_SW_LOGIC_PRE1_PDB BIT(5)
+#define B_SW_FSM_OVERRIDE BIT(4)
+#define B_SW_PWR_ON BIT(3)
+#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
+
+#define B_FSM_STATE_OUT_OFFSET (6)
+#define B_FSM_STATE_OUT_MASK (0x1F << B_FSM_STATE_OUT_OFFSET)
+#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
+#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
+#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
+#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
+
+
+#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
+
+#ifndef __ASSEMBLER__
+/* cpu boot mode */
+enum mp0_coucfg_64bit_ctrl {
+ MP0_CPUCFG_64BIT_SHIFT = 12,
+ MP1_CPUCFG_64BIT_SHIFT = 28,
+ MP0_CPUCFG_64BIT = 0xfu << MP0_CPUCFG_64BIT_SHIFT,
+ MP1_CPUCFG_64BIT = 0xfu << MP1_CPUCFG_64BIT_SHIFT,
+};
+
+enum mp1_dis_rgu0_ctrl {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16,
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT,
+};
+
+enum mp1_ainacts_ctrl {
+ MP1_AINACTS_SHIFT = 4,
+ MP1_AINACTS = 1U << MP1_AINACTS_SHIFT,
+};
+
+enum mp1_sw_cg_gen {
+ MP1_SW_CG_GEN_SHIFT = 12,
+ MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT,
+};
+
+enum mp1_l2rstdisable {
+ MP1_L2RSTDISABLE_SHIFT = 14,
+ MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT,
+};
+#endif /*__ASSEMBLER__*/
+
+#endif /* MCUCFG_V1_H */
diff --git a/plat/mediatek/drivers/msdc/mt8186/mt_msdc_priv.h b/plat/mediatek/drivers/msdc/mt8186/mt_msdc_priv.h
new file mode 100644
index 0000000..b3337ca
--- /dev/null
+++ b/plat/mediatek/drivers/msdc/mt8186/mt_msdc_priv.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MSDC_PRIV_H
+#define MT_MSDC_PRIV_H
+
+#define MSDC_CQHCI_CFG 0x808
+#define MSDC_CQHCI_CRYPTO_ENABLE BIT(1)
+
+#endif
diff --git a/plat/mediatek/drivers/msdc/mt_msdc.c b/plat/mediatek/drivers/msdc/mt_msdc.c
new file mode 100644
index 0000000..ccf440f
--- /dev/null
+++ b/plat/mediatek/drivers/msdc/mt_msdc.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_msdc.h>
+#include <platform_def.h>
+
+uint64_t msdc_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3)
+{
+ INFO("[%s] msdc setup call from kernel\n", __func__);
+ mmio_setbits_32(MSDC0_BASE + MSDC_CQHCI_CFG, MSDC_CQHCI_CRYPTO_ENABLE);
+
+ return 0L;
+}
diff --git a/plat/mediatek/drivers/msdc/mt_msdc.h b/plat/mediatek/drivers/msdc/mt_msdc.h
new file mode 100644
index 0000000..1c500c2
--- /dev/null
+++ b/plat/mediatek/drivers/msdc/mt_msdc.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MSDC_H
+#define MT_MSDC_H
+
+#include <mt_msdc_priv.h>
+
+uint64_t msdc_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3);
+
+#endif
diff --git a/plat/mediatek/drivers/pmic/pmic.c b/plat/mediatek/drivers/pmic/pmic.c
new file mode 100644
index 0000000..a11ad9a
--- /dev/null
+++ b/plat/mediatek/drivers/pmic/pmic.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <pmic.h>
+#include <pmic_wrap_init.h>
+
+void pmic_power_off(void)
+{
+ pwrap_write(PMIC_PWRHOLD, 0x0);
+}
diff --git a/plat/mediatek/drivers/pmic/pmic.h b/plat/mediatek/drivers/pmic/pmic.h
new file mode 100644
index 0000000..6c10f65
--- /dev/null
+++ b/plat/mediatek/drivers/pmic/pmic.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_H
+#define PMIC_H
+
+#define PMIC_PWRHOLD (0xa08)
+
+/* external API */
+void pmic_power_off(void);
+
+#endif /* PMIC_H */
diff --git a/plat/mediatek/drivers/pmic/rules.mk b/plat/mediatek/drivers/pmic/rules.mk
new file mode 100644
index 0000000..e408b03
--- /dev/null
+++ b/plat/mediatek/drivers/pmic/rules.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := pmic
+
+LOCAL_SRCS-y += ${LOCAL_DIR}/pmic.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}/
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/pmic_wrap/mt8188/pmic_wrap_init.h b/plat/mediatek/drivers/pmic_wrap/mt8188/pmic_wrap_init.h
new file mode 100644
index 0000000..9027daf
--- /dev/null
+++ b/plat/mediatek/drivers/pmic_wrap/mt8188/pmic_wrap_init.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+#include <pmic_wrap_init_common.h>
+
+static struct mt8188_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* PMIC_WRAP registers */
+struct mt8188_pmic_wrap_regs {
+ uint32_t init_done;
+ uint32_t reserved[543];
+ uint32_t wacs2_cmd;
+ uint32_t wacs2_wdata;
+ uint32_t reserved1[3];
+ uint32_t wacs2_rdata;
+ uint32_t reserved2[3];
+ uint32_t wacs2_vldclr;
+ uint32_t wacs2_sta;
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c
new file mode 100644
index 0000000..0ee1c64
--- /dev/null
+++ b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <pmic_wrap_init.h>
+
+/* pmic wrap module wait_idle and read polling interval (in microseconds) */
+enum {
+ WAIT_IDLE_POLLING_DELAY_US = 1,
+ READ_POLLING_DELAY_US = 2
+};
+
+static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
+ void *wacs_register,
+ void *wacs_vldclr_register,
+ uint32_t *read_reg)
+{
+ uint32_t reg_rdata;
+ uint32_t retry;
+
+ retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
+ WAIT_IDLE_POLLING_DELAY_US;
+
+ do {
+ udelay(WAIT_IDLE_POLLING_DELAY_US);
+ reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+ /* if last read command timeout,clear vldclr bit
+ * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
+ * write:FSM_REQ-->idle
+ */
+ switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
+ RDATA_WACS_FSM_MASK)) {
+ case WACS_FSM_WFVLDCLR:
+ mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
+ ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
+ break;
+ case WACS_FSM_WFDLE:
+ ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
+ break;
+ case WACS_FSM_REQ:
+ ERROR("WACS_FSM = WACS_FSM_REQ\n");
+ break;
+ case WACS_FSM_IDLE:
+ goto done;
+ default:
+ break;
+ }
+
+ retry--;
+ } while (retry);
+
+done:
+ if (!retry) /* timeout */
+ return E_PWR_WAIT_IDLE_TIMEOUT;
+
+ if (read_reg)
+ *read_reg = reg_rdata;
+ return 0;
+}
+
+static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
+ void *wacs_register,
+ uint32_t *read_reg)
+{
+ uint32_t reg_rdata;
+ uint32_t retry;
+
+ retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
+
+ do {
+ udelay(READ_POLLING_DELAY_US);
+ reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+
+ if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
+ == WACS_FSM_WFVLDCLR)
+ break;
+
+ retry--;
+ } while (retry);
+
+ if (!retry) { /* timeout */
+ ERROR("timeout when waiting for idle\n");
+ return E_PWR_WAIT_IDLE_TIMEOUT_READ;
+ }
+
+ if (read_reg)
+ *read_reg = reg_rdata;
+ return 0;
+}
+
+static int32_t pwrap_wacs2(uint32_t write,
+ uint32_t adr,
+ uint32_t wdata,
+ uint32_t *rdata,
+ uint32_t init_check)
+{
+ uint32_t reg_rdata = 0;
+ uint32_t wacs_write = 0;
+ uint32_t wacs_adr = 0;
+ uint32_t wacs_cmd = 0;
+ uint32_t return_value = 0;
+
+ if (init_check) {
+ reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
+ /* Prevent someone to used pwrap before pwrap init */
+ if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
+ RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
+ ERROR("initialization isn't finished\n");
+ return E_PWR_NOT_INIT_DONE;
+ }
+ }
+ reg_rdata = 0;
+ /* Check IDLE in advance */
+ return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
+ &mtk_pwrap->wacs2_rdata,
+ &mtk_pwrap->wacs2_vldclr,
+ 0);
+ if (return_value != 0) {
+ ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
+ goto FAIL;
+ }
+ wacs_write = write << 31;
+ wacs_adr = (adr >> 1) << 16;
+ wacs_cmd = wacs_write | wacs_adr | wdata;
+
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd);
+ if (write == 0) {
+ if (rdata == NULL) {
+ ERROR("rdata is a NULL pointer\n");
+ return_value = E_PWR_INVALID_ARG;
+ goto FAIL;
+ }
+ return_value = wait_for_state_ready(TIMEOUT_READ,
+ &mtk_pwrap->wacs2_rdata,
+ &reg_rdata);
+ if (return_value != 0) {
+ ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
+ return_value);
+ goto FAIL;
+ }
+ *rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
+ & RDATA_WACS_RDATA_MASK);
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1);
+ }
+FAIL:
+ return return_value;
+}
+
+/* external API for pmic_wrap user */
+
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
+{
+ return pwrap_wacs2(0, adr, 0, rdata, 1);
+}
+
+int32_t pwrap_write(uint32_t adr, uint32_t wdata)
+{
+ return pwrap_wacs2(1, adr, wdata, 0, 1);
+}
diff --git a/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_common.h b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_common.h
new file mode 100644
index 0000000..4ba1f5c
--- /dev/null
+++ b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_common.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_COMMON_H
+#define PMIC_WRAP_INIT_COMMON_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+
+/* external API */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
+int32_t pwrap_write(uint32_t adr, uint32_t wdata);
+
+#define GET_WACS_FSM(x) ((x >> 1) & 0x7)
+
+/* macro for SWINF_FSM */
+#define SWINF_FSM_IDLE (0x00)
+#define SWINF_FSM_REQ (0x02)
+#define SWINF_FSM_WFDLE (0x04)
+#define SWINF_FSM_WFVLDCLR (0x06)
+#define SWINF_INIT_DONE (0x01)
+
+/* timeout setting */
+#define PWRAP_READ_US (1000)
+#define PWRAP_WAIT_IDLE_US (1000)
+
+/* error information flag */
+enum pwrap_errno {
+ E_PWR_INVALID_ARG = 1,
+ E_PWR_INVALID_RW = 2,
+ E_PWR_INVALID_ADDR = 3,
+ E_PWR_INVALID_WDAT = 4,
+ E_PWR_INVALID_OP_MANUAL = 5,
+ E_PWR_NOT_IDLE_STATE = 6,
+ E_PWR_NOT_INIT_DONE = 7,
+ E_PWR_NOT_INIT_DONE_READ = 8,
+ E_PWR_WAIT_IDLE_TIMEOUT = 9,
+ E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
+ E_PWR_INIT_SIDLY_FAIL = 11,
+ E_PWR_RESET_TIMEOUT = 12,
+ E_PWR_TIMEOUT = 13,
+ E_PWR_INIT_RESET_SPI = 20,
+ E_PWR_INIT_SIDLY = 21,
+ E_PWR_INIT_REG_CLOCK = 22,
+ E_PWR_INIT_ENABLE_PMIC = 23,
+ E_PWR_INIT_DIO = 24,
+ E_PWR_INIT_CIPHER = 25,
+ E_PWR_INIT_WRITE_TEST = 26,
+ E_PWR_INIT_ENABLE_CRC = 27,
+ E_PWR_INIT_ENABLE_DEWRAP = 28,
+ E_PWR_INIT_ENABLE_EVENT = 29,
+ E_PWR_READ_TEST_FAIL = 30,
+ E_PWR_WRITE_TEST_FAIL = 31,
+ E_PWR_SWITCH_DIO = 32,
+};
+
+#endif /* PMIC_WRAP_INIT_COMMON_H */
diff --git a/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c
new file mode 100644
index 0000000..80f55de
--- /dev/null
+++ b/plat/mediatek/drivers/pmic_wrap/pmic_wrap_init_v2.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include "platform_def.h"
+#include "pmic_wrap_init.h"
+
+/* pmic wrap module wait_idle and read polling interval (in microseconds) */
+enum pwrap_polling_interval {
+ WAIT_IDLE_POLLING_DELAY_US = 1,
+ READ_POLLING_DELAY_US = 2
+};
+
+static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us)
+{
+ uint32_t reg_rdata = 0U, retry;
+
+ retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
+ WAIT_IDLE_POLLING_DELAY_US;
+ while (retry != 0) {
+ udelay(WAIT_IDLE_POLLING_DELAY_US);
+ reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+ /* if last read command timeout,clear vldclr bit
+ * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
+ * write:FSM_REQ-->idle
+ */
+ switch (GET_WACS_FSM(reg_rdata)) {
+ case SWINF_FSM_WFVLDCLR:
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
+ INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n");
+ break;
+ case SWINF_FSM_WFDLE:
+ INFO("WACS_FSM = SWINF_FSM_WFDLE\n");
+ break;
+ case SWINF_FSM_REQ:
+ INFO("WACS_FSM = SWINF_FSM_REQ\n");
+ break;
+ case SWINF_FSM_IDLE:
+ goto done;
+ default:
+ break;
+ }
+ retry--;
+ };
+
+done:
+ if (retry == 0) {
+ /* timeout */
+ return E_PWR_WAIT_IDLE_TIMEOUT;
+ }
+
+ return 0U;
+}
+
+static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us)
+{
+ uint32_t reg_rdata = 0U, retry;
+
+ retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
+ while (retry != 0) {
+ udelay(READ_POLLING_DELAY_US);
+ reg_rdata = mmio_read_32((uintptr_t)wacs_register);
+ if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) {
+ break;
+ }
+ retry--;
+ };
+
+ if (retry == 0) {
+ /* timeout */
+ return E_PWR_WAIT_IDLE_TIMEOUT;
+ }
+
+ return 0U;
+}
+
+static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata,
+ uint32_t *rdata, uint32_t init_check)
+{
+ uint32_t reg_rdata, return_value;
+
+ if (init_check != 0) {
+ if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) {
+ ERROR("initialization isn't finished\n");
+ return E_PWR_NOT_INIT_DONE;
+ }
+ }
+
+ /* Wait for Software Interface FSM state to be IDLE. */
+ return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta,
+ PWRAP_WAIT_IDLE_US);
+ if (return_value != 0) {
+ return return_value;
+ }
+
+ /* Set the write data */
+ if (write == 1) {
+ /* Set the write data. */
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata);
+ }
+
+ /* Send the command. */
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr);
+
+ if (write == 0) {
+ /*
+ * Wait for Software Interface FSM state to be WFVLDCLR,
+ * read the data and clear the valid flag.
+ */
+ return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta,
+ PWRAP_READ_US);
+ if (return_value != 0) {
+ return return_value;
+ }
+
+ if (rdata == NULL) {
+ return E_PWR_INVALID_ARG;
+ }
+
+ reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
+ *rdata = reg_rdata;
+ mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
+ }
+
+ return return_value;
+}
+
+/* external API for pmic_wrap user */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
+{
+ return pwrap_wacs2(0, adr, 0, rdata, 1);
+}
+
+int32_t pwrap_write(uint32_t adr, uint32_t wdata)
+{
+ return pwrap_wacs2(1, adr, wdata, 0, 1);
+}
diff --git a/plat/mediatek/drivers/pmic_wrap/rules.mk b/plat/mediatek/drivers/pmic_wrap/rules.mk
new file mode 100644
index 0000000..9ba44a6
--- /dev/null
+++ b/plat/mediatek/drivers/pmic_wrap/rules.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := pmic_wrap
+
+ifeq (${USE_PMIC_WRAP_INIT_V2}, 1)
+LOCAL_SRCS-y += ${LOCAL_DIR}/pmic_wrap_init_v2.c
+else
+LOCAL_SRCS-y += ${LOCAL_DIR}/pmic_wrap_init.c
+endif
+
+PLAT_INCLUDES += -I${LOCAL_DIR}/
+PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/ptp3/mt8188/ptp3_plat.h b/plat/mediatek/drivers/ptp3/mt8188/ptp3_plat.h
new file mode 100644
index 0000000..aa7d7ca
--- /dev/null
+++ b/plat/mediatek/drivers/ptp3/mt8188/ptp3_plat.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PTP3_PLAT_H
+#define PTP3_PLAT_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <ptp3_common.h>
+
+/* CPU Info */
+#define NR_PTP3_CFG_CPU U(8)
+#define PTP3_CFG_CPU_START_ID_L U(0)
+#define PTP3_CFG_CPU_START_ID_B U(6)
+#define PTP3_CFG_CPU_END_ID U(7)
+
+#define NR_PTP3_CFG1_DATA U(2)
+#define PTP3_CFG1_MASK (0x3000)
+
+#define NR_PTP3_CFG2_DATA U(5)
+
+#define PTP3_CFG3_MASK1 (0x1180)
+#define PTP3_CFG3_MASK2 (0x35C0)
+#define PTP3_CFG3_MASK3 (0x3DC0)
+
+
+/* Central control */
+static unsigned int ptp3_cfg1[NR_PTP3_CFG1_DATA][NR_PTP3_CFG] = {
+ {0x0C53A2A0, 0x1000},
+ {0x0C53A2A4, 0x1000}
+};
+
+static unsigned int ptp3_cfg2[NR_PTP3_CFG2_DATA][NR_PTP3_CFG] = {
+ {0x0C530404, 0x3A1000},
+ {0x0C530428, 0x13E0408},
+ {0x0C530434, 0xB22800},
+ {0x0C53043C, 0x750},
+ {0x0C530440, 0x0222c4cc}
+};
+
+static unsigned int ptp3_cfg3[NR_PTP3_CFG] = {0x0C530400, 0xC00};
+static unsigned int ptp3_cfg3_ext[NR_PTP3_CFG] = {0x0C530400, 0xC00};
+
+#endif /* PTP3_PLAT_H */
diff --git a/plat/mediatek/drivers/ptp3/ptp3_common.c b/plat/mediatek/drivers/ptp3/ptp3_common.c
new file mode 100644
index 0000000..6846852
--- /dev/null
+++ b/plat/mediatek/drivers/ptp3/ptp3_common.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#if MTK_PUBEVENT_ENABLE
+#include <lib/pm/mtk_pm.h>
+#endif
+#include <ptp3_plat.h>
+
+#define PTP3_CORE_OFT(core) (0x800 * (core))
+
+static void ptp3_init(unsigned int core)
+{
+ unsigned int i, addr, value;
+
+ if (core < PTP3_CFG_CPU_START_ID_B) {
+ mmio_clrsetbits_32(ptp3_cfg1[0][PTP3_CFG_ADDR], PTP3_CFG1_MASK,
+ ptp3_cfg1[0][PTP3_CFG_VALUE]);
+ } else {
+ mmio_clrsetbits_32(ptp3_cfg1[1][PTP3_CFG_ADDR], PTP3_CFG1_MASK,
+ ptp3_cfg1[1][PTP3_CFG_VALUE]);
+ }
+
+ if (core < PTP3_CFG_CPU_START_ID_B) {
+ for (i = 0; i < NR_PTP3_CFG2_DATA; i++) {
+ addr = ptp3_cfg2[i][PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
+ value = ptp3_cfg2[i][PTP3_CFG_VALUE];
+
+ mmio_write_32(addr, value);
+ }
+ } else {
+ for (i = 0; i < NR_PTP3_CFG2_DATA; i++) {
+ addr = ptp3_cfg2[i][PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
+
+ if (i == 2) {
+ value = ptp3_cfg2[i][PTP3_CFG_VALUE] + 0x5E0;
+ } else {
+ value = ptp3_cfg2[i][PTP3_CFG_VALUE];
+ }
+ mmio_write_32(addr, value);
+ }
+ }
+
+ if (core < PTP3_CFG_CPU_START_ID_B) {
+ addr = ptp3_cfg3[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
+ value = ptp3_cfg3[PTP3_CFG_VALUE];
+ } else {
+ addr = ptp3_cfg3_ext[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
+ value = ptp3_cfg3_ext[PTP3_CFG_VALUE];
+ }
+ mmio_write_32(addr, value & PTP3_CFG3_MASK1);
+ mmio_write_32(addr, value & PTP3_CFG3_MASK2);
+ mmio_write_32(addr, value & PTP3_CFG3_MASK3);
+}
+
+static void pdp_proc_arm_write(unsigned int pdp_n)
+{
+ unsigned long v = 0;
+
+ dsb();
+ __asm__ volatile ("mrs %0, S3_6_C15_C2_0" : "=r" (v));
+ v |= (UL(0x0) << 52);
+ v |= (UL(0x1) << 53);
+ v |= (UL(0x0) << 54);
+ v |= (UL(0x0) << 48);
+ v |= (UL(0x1) << 49);
+ __asm__ volatile ("msr S3_6_C15_C2_0, %0" : : "r" (v));
+ dsb();
+}
+
+static void pdp_init(unsigned int pdp_cpu)
+{
+ if ((pdp_cpu >= PTP3_CFG_CPU_START_ID_B) && (pdp_cpu < NR_PTP3_CFG_CPU)) {
+ pdp_proc_arm_write(pdp_cpu);
+ }
+}
+
+void ptp3_core_init(unsigned int core)
+{
+ ptp3_init(core);
+ pdp_init(core);
+}
+
+void ptp3_core_deinit(unsigned int core)
+{
+ /* TBD */
+}
+
+#if MTK_PUBEVENT_ENABLE
+/* Handle for power on domain */
+void *ptp3_handle_pwr_on_event(const void *arg)
+{
+ if (arg != NULL) {
+ struct mt_cpupm_event_data *data = (struct mt_cpupm_event_data *)arg;
+
+ if ((data->pwr_domain & MT_CPUPM_PWR_DOMAIN_CORE) > 0) {
+ ptp3_core_init(data->cpuid);
+ }
+ }
+ return (void *)arg;
+}
+MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(ptp3_handle_pwr_on_event);
+
+/* Handle for power off domain */
+void *ptp3_handle_pwr_off_event(const void *arg)
+{
+ if (arg != NULL) {
+ struct mt_cpupm_event_data *data = (struct mt_cpupm_event_data *)arg;
+
+ if ((data->pwr_domain & MT_CPUPM_PWR_DOMAIN_CORE) > 0) {
+ ptp3_core_deinit(data->cpuid);
+ }
+ }
+ return (void *)arg;
+}
+MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(ptp3_handle_pwr_off_event);
+#else
+#pragma message "PSCI hint not enable"
+#endif
diff --git a/plat/mediatek/drivers/ptp3/ptp3_common.h b/plat/mediatek/drivers/ptp3/ptp3_common.h
new file mode 100644
index 0000000..83ce62b
--- /dev/null
+++ b/plat/mediatek/drivers/ptp3/ptp3_common.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PTP3_COMMON_H
+#define PTP3_COMMON_H
+
+/* config enum */
+enum PTP3_CFG {
+ PTP3_CFG_ADDR,
+ PTP3_CFG_VALUE,
+ NR_PTP3_CFG,
+};
+
+/* prototype */
+void ptp3_core_init(unsigned int core);
+void ptp3_core_deinit(unsigned int core);
+
+#endif /* PTP3_COMMON_H */
diff --git a/plat/mediatek/drivers/ptp3/rules.mk b/plat/mediatek/drivers/ptp3/rules.mk
new file mode 100644
index 0000000..81d79d2
--- /dev/null
+++ b/plat/mediatek/drivers/ptp3/rules.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_ptp3
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/ptp3_common.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+PLAT_INCLUDES += -I${LOCAL_DIR}/$(MTK_SOC)
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/rtc/mt8188/rtc.h b/plat/mediatek/drivers/rtc/mt8188/rtc.h
new file mode 100644
index 0000000..734e89f
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/mt8188/rtc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#include <rtc_mt6359p.h>
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/drivers/rtc/rtc_common.c b/plat/mediatek/drivers/rtc/rtc_common.c
new file mode 100644
index 0000000..4efddff
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/rtc_common.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <pmic_wrap_init.h>
+#include <rtc.h>
+
+/* RTC busy status polling interval and retry count */
+enum {
+ RTC_WRTGR_POLLING_DELAY_MS = 10,
+ RTC_WRTGR_POLLING_CNT = 100
+};
+
+uint16_t RTC_Read(uint32_t addr)
+{
+ uint32_t rdata = 0;
+
+ pwrap_read((uint32_t)addr, &rdata);
+ return (uint16_t)rdata;
+}
+
+void RTC_Write(uint32_t addr, uint16_t data)
+{
+ pwrap_write((uint32_t)addr, (uint32_t)data);
+}
+
+int32_t rtc_busy_wait(void)
+{
+ uint64_t retry = RTC_WRTGR_POLLING_CNT;
+
+ do {
+ mdelay(RTC_WRTGR_POLLING_DELAY_MS);
+ if (!(RTC_Read(RTC_BBPU) & RTC_BBPU_CBUSY))
+ return 1;
+ retry--;
+ } while (retry);
+
+ ERROR("[RTC] rtc cbusy time out!\n");
+ return 0;
+}
+
+int32_t RTC_Write_Trigger(void)
+{
+ RTC_Write(RTC_WRTGR, 1);
+ return rtc_busy_wait();
+}
+
+int32_t Writeif_unlock(void)
+{
+ RTC_Write(RTC_PROT, RTC_PROT_UNLOCK1);
+ if (!RTC_Write_Trigger())
+ return 0;
+ RTC_Write(RTC_PROT, RTC_PROT_UNLOCK2);
+ if (!RTC_Write_Trigger())
+ return 0;
+
+ return 1;
+}
+
diff --git a/plat/mediatek/drivers/rtc/rtc_mt6359p.c b/plat/mediatek/drivers/rtc/rtc_mt6359p.c
new file mode 100644
index 0000000..3bf4337
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/rtc_mt6359p.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <rtc.h>
+
+
+static void RTC_Config_Interface(uint32_t addr, uint16_t data,
+ uint16_t mask, uint16_t shift)
+{
+ uint16_t pmic_reg;
+
+ pmic_reg = RTC_Read(addr);
+
+ pmic_reg &= ~(mask << shift);
+ pmic_reg |= (data << shift);
+
+ RTC_Write(addr, pmic_reg);
+}
+
+static int32_t rtc_disable_2sec_reboot(void)
+{
+ uint16_t reboot;
+
+ reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
+ ~RTC_BBPU_AUTO_PDN_SEL;
+ RTC_Write(RTC_AL_SEC, reboot);
+
+ return RTC_Write_Trigger();
+}
+
+static int32_t rtc_enable_k_eosc(void)
+{
+ uint16_t alm_dow, alm_sec;
+ int16_t ret;
+
+ /* Turning on eosc cali mode clock */
+ RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0_CLR, 1,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+ alm_sec = RTC_Read(RTC_AL_SEC) & (~RTC_LPD_OPT_MASK);
+ RTC_Write(RTC_AL_SEC, alm_sec);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_EN);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_RST);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_CON, RTC_LPD_EN);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
+ RTC_Write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ /* set RTC EOSC calibration period = 8sec */
+ alm_dow = (RTC_Read(RTC_AL_DOW) & (~RTC_RG_EOSC_CALI_TD_MASK)) |
+ RTC_RG_EOSC_CALI_TD_8SEC;
+ RTC_Write(RTC_AL_DOW, alm_dow);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ RTC_Write(RTC_BBPU,
+ RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ /* Enable K EOSC mode :use solution1 of eosc cali to fix mt6359p 32K*/
+ RTC_Write(RTC_AL_YEA, (((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
+ & (~RTC_K_EOSC_RSV_1)) | (RTC_K_EOSC_RSV_2)));
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return 0;
+ }
+
+ INFO("[RTC] RTC_enable_k_eosc\n");
+
+ return 1;
+}
+
+void rtc_power_off_sequence(void)
+{
+ uint16_t bbpu;
+ int16_t ret;
+
+ ret = rtc_disable_2sec_reboot();
+ if (ret == 0) {
+ return;
+ }
+
+ ret = rtc_enable_k_eosc();
+ if (ret == 0) {
+ return;
+ }
+
+ bbpu = RTC_BBPU_KEY | RTC_BBPU_PWREN;
+
+ if (Writeif_unlock() != 0) {
+ RTC_Write(RTC_BBPU,
+ bbpu | RTC_BBPU_RESET_ALARM | RTC_BBPU_RESET_SPAR);
+ RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return;
+ }
+ mdelay(1);
+
+ bbpu = RTC_Read(RTC_BBPU);
+
+ if (((bbpu & RTC_BBPU_RESET_ALARM) > 0) ||
+ ((bbpu & RTC_BBPU_RESET_SPAR) > 0)) {
+ INFO("[RTC] timeout\n");
+ }
+
+ bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+ RTC_Write(RTC_BBPU, bbpu);
+ ret = RTC_Write_Trigger();
+ if (ret == 0) {
+ return;
+ }
+ }
+}
diff --git a/plat/mediatek/drivers/rtc/rtc_mt6359p.h b/plat/mediatek/drivers/rtc/rtc_mt6359p.h
new file mode 100644
index 0000000..199f152
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/rtc_mt6359p.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_MT6359P_H
+#define RTC_MT6359P_H
+
+/* RTC registers */
+enum {
+ RTC_BBPU = 0x0588,
+ RTC_IRQ_STA = 0x058A,
+ RTC_IRQ_EN = 0x058C,
+ RTC_CII_EN = 0x058E
+};
+
+enum {
+ RTC_AL_SEC = 0x05A0,
+ RTC_AL_MIN = 0x05A2,
+ RTC_AL_HOU = 0x05A4,
+ RTC_AL_DOM = 0x05A6,
+ RTC_AL_DOW = 0x05A8,
+ RTC_AL_MTH = 0x05AA,
+ RTC_AL_YEA = 0x05AC,
+ RTC_AL_MASK = 0x0590
+};
+
+enum {
+ RTC_OSC32CON = 0x05AE,
+ RTC_CON = 0x05C4,
+ RTC_WRTGR = 0x05C2
+};
+
+enum {
+ RTC_POWERKEY1 = 0x05B0,
+ RTC_POWERKEY2 = 0x05B2
+};
+
+enum {
+ RTC_POWERKEY1_KEY = 0xA357,
+ RTC_POWERKEY2_KEY = 0x67D2
+};
+
+enum {
+ RTC_PDN1 = 0x05B4,
+ RTC_PDN2 = 0x05B6,
+ RTC_SPAR0 = 0x05B8,
+ RTC_SPAR1 = 0x05BA,
+ RTC_PROT = 0x05BC,
+ RTC_DIFF = 0x05BE,
+ RTC_CALI = 0x05C0
+};
+
+enum {
+ RTC_OSC32CON_UNLOCK1 = 0x1A57,
+ RTC_OSC32CON_UNLOCK2 = 0x2B68
+};
+
+enum {
+ RTC_LPD_EN = 0x0406,
+ RTC_LPD_RST = 0x040E
+};
+
+enum {
+ RTC_LPD_OPT_XOSC_AND_EOSC_LPD = 0U << 13,
+ RTC_LPD_OPT_EOSC_LPD = 1U << 13,
+ RTC_LPD_OPT_XOSC_LPD = 2U << 13,
+ RTC_LPD_OPT_F32K_CK_ALIVE = 3U << 13,
+};
+
+#define RTC_LPD_OPT_MASK (3U << 13)
+
+enum {
+ RTC_PROT_UNLOCK1 = 0x586A,
+ RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+ RTC_BBPU_PWREN = 1U << 0,
+ RTC_BBPU_SPAR_SW = 1U << 1,
+ RTC_BBPU_RESET_SPAR = 1U << 2,
+ RTC_BBPU_RESET_ALARM = 1U << 3,
+ RTC_BBPU_CLRPKY = 1U << 4,
+ RTC_BBPU_RELOAD = 1U << 5,
+ RTC_BBPU_CBUSY = 1U << 6
+};
+
+enum {
+ RTC_AL_MASK_SEC = 1U << 0,
+ RTC_AL_MASK_MIN = 1U << 1,
+ RTC_AL_MASK_HOU = 1U << 2,
+ RTC_AL_MASK_DOM = 1U << 3,
+ RTC_AL_MASK_DOW = 1U << 4,
+ RTC_AL_MASK_MTH = 1U << 5,
+ RTC_AL_MASK_YEA = 1U << 6
+};
+
+enum {
+ RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
+ RTC_BBPU_2SEC_CK_SEL = 1U << 7,
+ RTC_BBPU_2SEC_EN = 1U << 8,
+ RTC_BBPU_2SEC_MODE = 0x3 << 9,
+ RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
+ RTC_BBPU_2SEC_STAT_STA = 1U << 12
+};
+
+enum {
+ RTC_BBPU_KEY = 0x43 << 8
+};
+
+enum {
+ RTC_EMBCK_SRC_SEL = 1 << 8,
+ RTC_EMBCK_SEL_MODE = 3 << 6,
+ RTC_XOSC32_ENB = 1 << 5,
+ RTC_REG_XOSC32_ENB = 1 << 15
+};
+
+enum {
+ RTC_K_EOSC_RSV_0 = 1 << 8,
+ RTC_K_EOSC_RSV_1 = 1 << 9,
+ RTC_K_EOSC_RSV_2 = 1 << 10
+};
+
+enum {
+ RTC_RG_EOSC_CALI_TD_1SEC = 3 << 5,
+ RTC_RG_EOSC_CALI_TD_2SEC = 4 << 5,
+ RTC_RG_EOSC_CALI_TD_4SEC = 5 << 5,
+ RTC_RG_EOSC_CALI_TD_8SEC = 6 << 5,
+ RTC_RG_EOSC_CALI_TD_16SEC = 7 << 5,
+ RTC_RG_EOSC_CALI_TD_MASK = 7 << 5
+};
+
+/* PMIC TOP Register Definition */
+enum {
+ PMIC_RG_TOP_CON = 0x0020,
+ PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
+ PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
+ PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
+ PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
+ PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
+ PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
+};
+
+/* PMIC SCK Register Definition */
+enum {
+ PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x0514,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x0516,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x0518,
+ PMIC_RG_EOSC_CALI_CON0 = 0x53A
+};
+
+enum {
+ PMIC_EOSC_CALI_START_ADDR = 0x53A
+};
+
+enum {
+ PMIC_EOSC_CALI_START_MASK = 0x1,
+ PMIC_EOSC_CALI_START_SHIFT = 0
+};
+
+/* PMIC DCXO Register Definition */
+enum {
+ PMIC_RG_DCXO_CW00 = 0x0788,
+ PMIC_RG_DCXO_CW02 = 0x0790,
+ PMIC_RG_DCXO_CW08 = 0x079C,
+ PMIC_RG_DCXO_CW09 = 0x079E,
+ PMIC_RG_DCXO_CW09_CLR = 0x07A2,
+ PMIC_RG_DCXO_CW10 = 0x07A4,
+ PMIC_RG_DCXO_CW12 = 0x07A8,
+ PMIC_RG_DCXO_CW13 = 0x07AA,
+ PMIC_RG_DCXO_CW15 = 0x07AE,
+ PMIC_RG_DCXO_CW19 = 0x07B6,
+};
+
+enum {
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
+ PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
+ PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
+ PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
+ PMIC_RG_XO_EN32K_MAN_SHIFT = 0
+};
+
+/* external API */
+uint16_t RTC_Read(uint32_t addr);
+void RTC_Write(uint32_t addr, uint16_t data);
+int32_t rtc_busy_wait(void);
+int32_t RTC_Write_Trigger(void);
+int32_t Writeif_unlock(void);
+void rtc_power_off_sequence(void);
+
+#endif /* RTC_MT6359P_H */
diff --git a/plat/mediatek/drivers/rtc/rules.mk b/plat/mediatek/drivers/rtc/rules.mk
new file mode 100644
index 0000000..2398f8a
--- /dev/null
+++ b/plat/mediatek/drivers/rtc/rules.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := rtc
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/rtc_common.c
+
+ifeq (${USE_RTC_MT6359P}, 1)
+LOCAL_SRCS-y += ${LOCAL_DIR}/rtc_mt6359p.c
+PLAT_INCLUDES += -I${LOCAL_DIR}
+endif
+
+PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/timer/mt_timer.c b/plat/mediatek/drivers/timer/mt_timer.c
new file mode 100644
index 0000000..11e4572
--- /dev/null
+++ b/plat/mediatek/drivers/timer/mt_timer.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <mt_timer.h>
+#include <platform_def.h>
+
+uint64_t normal_time_base;
+uint64_t atf_time_base;
+
+void sched_clock_init(uint64_t normal_base, uint64_t atf_base)
+{
+ normal_time_base += normal_base;
+ atf_time_base = atf_base;
+}
+
+uint64_t sched_clock(void)
+{
+ uint64_t cval;
+ uint64_t rel_base;
+
+ rel_base = read_cntpct_el0() - atf_time_base;
+ cval = ((rel_base * 1000U) / SYS_COUNTER_FREQ_IN_MHZ)
+ - normal_time_base;
+ return cval;
+}
+
+int mt_systimer_init(void)
+{
+ INFO("[%s] systimer initialization\n", __func__);
+
+ /* Enable access in NS mode */
+ mmio_write_32(CNTWACR_REG, CNT_WRITE_ACCESS_CTL_MASK);
+ mmio_write_32(CNTRACR_REG, CNT_READ_ACCESS_CTL_MASK);
+
+ return 0;
+}
+MTK_PLAT_SETUP_0_INIT(mt_systimer_init);
diff --git a/plat/mediatek/drivers/timer/mt_timer.h b/plat/mediatek/drivers/timer/mt_timer.h
new file mode 100644
index 0000000..1c08f90
--- /dev/null
+++ b/plat/mediatek/drivers/timer/mt_timer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_TIMER_H
+#define MT_TIMER_H
+
+#define SYSTIMER_BASE (0x10017000)
+#define CNTCR_REG (SYSTIMER_BASE + 0x0)
+#define CNTSR_REG (SYSTIMER_BASE + 0x4)
+#define CNTSYS_L_REG (SYSTIMER_BASE + 0x8)
+#define CNTSYS_H_REG (SYSTIMER_BASE + 0xc)
+#define CNTWACR_REG (SYSTIMER_BASE + 0x10)
+#define CNTRACR_REG (SYSTIMER_BASE + 0x14)
+
+#define TIEO_EN (1 << 3)
+#define COMP_15_EN (1 << 10)
+#define COMP_20_EN (1 << 11)
+#define COMP_25_EN (1 << 12)
+
+#define COMP_FEATURE_MASK (COMP_15_EN | COMP_20_EN | COMP_25_EN | TIEO_EN)
+#define COMP_15_MASK (COMP_15_EN)
+#define COMP_20_MASK (COMP_20_EN | TIEO_EN)
+#define COMP_25_MASK (COMP_20_EN | COMP_25_EN)
+
+#define CNT_WRITE_ACCESS_CTL_MASK (0x3FFFFF0U)
+#define CNT_READ_ACCESS_CTL_MASK (0x3FFFFFFU)
+
+void sched_clock_init(uint64_t normal_base, uint64_t atf_base);
+uint64_t sched_clock(void);
+int mt_systimer_init(void);
+
+#endif /* MT_TIMER_H */
diff --git a/plat/mediatek/drivers/timer/rules.mk b/plat/mediatek/drivers/timer/rules.mk
new file mode 100644
index 0000000..005cf45
--- /dev/null
+++ b/plat/mediatek/drivers/timer/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := timer
+LOCAL_SRCS-y := $(LOCAL_DIR)/mt_timer.c
+
+PLAT_INCLUDES += -I${LOCAL_DIR}
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/drivers/uart/8250_console.S b/plat/mediatek/drivers/uart/8250_console.S
new file mode 100644
index 0000000..66f998d
--- /dev/null
+++ b/plat/mediatek/drivers/uart/8250_console.S
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+#include <uart8250.h>
+
+ .globl console_core_init
+ .globl console_core_putc
+ .globl console_core_getc
+ .globl console_core_flush
+
+ /* -----------------------------------------------
+ * int console_core_init(unsigned long 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 else 0 on error
+ * Clobber list : x1, x2, x3
+ * -----------------------------------------------
+ */
+func console_core_init
+ /* Check the input base address */
+ cbz x0, core_init_fail
+ /* Check baud rate and uart clock for sanity */
+ cbz w1, core_init_fail
+ cbz w2, core_init_fail
+
+ /* Disable interrupt */
+ str wzr, [x0, #UART_IER]
+
+ /* Force DTR and RTS to high */
+ mov w3, #(UART_MCR_DTR | UART_MCR_RTS)
+ str w3, [x0, #UART_MCR]
+
+ /* Check high speed */
+ movz w3, #:abs_g1:115200
+ movk w3, #:abs_g0_nc:115200
+ cmp w2, w3
+ b.hi 1f
+
+ /* Non high speed */
+ lsl w2, w2, #4
+ mov w3, wzr
+ b 2f
+
+ /* High speed */
+1: lsl w2, w2, #2
+ mov w3, #2
+
+ /* Set high speed UART register */
+2: str w3, [x0, #UART_HIGHSPEED]
+
+ /* Calculate divisor */
+ udiv w3, w1, w2 /* divisor = uartclk / (quot * baudrate) */
+ msub w1, w3, w2, w1 /* remainder = uartclk % (quot * baudrate) */
+ lsr w2, w2, #1
+ cmp w1, w2
+ cinc w3, w3, hs
+
+ /* Set line configuration, access divisor latches */
+ mov w1, #(UART_LCR_DLAB | UART_LCR_WLS_8)
+ str w1, [x0, #UART_LCR]
+
+ /* Set the divisor */
+ and w1, w3, #0xff
+ str w1, [x0, #UART_DLL]
+ lsr w1, w3, #8
+ and w1, w1, #0xff
+ str w1, [x0, #UART_DLH]
+
+ /* Hide the divisor latches */
+ mov w1, #UART_LCR_WLS_8
+ str w1, [x0, #UART_LCR]
+
+ /* Enable FIFOs, and clear receive and transmit */
+ mov w1, #(UART_FCR_FIFO_EN | UART_FCR_CLEAR_RCVR | \
+ UART_FCR_CLEAR_XMIT)
+ str w1, [x0, #UART_FCR]
+
+ mov w0, #1
+ ret
+core_init_fail:
+ mov w0, wzr
+ ret
+endfunc console_core_init
+
+ /* --------------------------------------------------------
+ * int console_core_putc(int c, unsigned long 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 console_core_putc
+ /* Check the input parameter */
+ cbz x1, putc_error
+ /* Prepend '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne 2f
+
+ /* Check if the transmit FIFO is full */
+1: ldr w2, [x1, #UART_LSR]
+ and w2, w2, #UART_LSR_THRE
+ cbz w2, 1b
+ mov w2, #0xD
+ str w2, [x1, #UART_THR]
+
+ /* Check if the transmit FIFO is full */
+2: ldr w2, [x1, #UART_LSR]
+ and w2, w2, #UART_LSR_THRE
+ cbz w2, 2b
+ str w0, [x1, #UART_THR]
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+endfunc console_core_putc
+
+ /* ---------------------------------------------
+ * int console_core_getc(unsigned long base_addr)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on error.
+ * In : x0 - console base address
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_core_getc
+ cbz x0, getc_error
+
+ /* Check if the receive FIFO is empty */
+1: ldr w1, [x0, #UART_LSR]
+ tbz w1, #UART_LSR_DR, 1b
+ ldr w0, [x0, #UART_RBR]
+ ret
+getc_error:
+ mov w0, #-1
+ ret
+endfunc console_core_getc
+
+ /* ---------------------------------------------
+ * void console_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 : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_core_flush
+ /* Placeholder */
+ ret
+endfunc console_core_flush
diff --git a/plat/mediatek/drivers/uart/uart.c b/plat/mediatek/drivers/uart/uart.c
new file mode 100644
index 0000000..fdaa793
--- /dev/null
+++ b/plat/mediatek/drivers/uart/uart.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <uart.h>
+
+static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];
+
+static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
+ UART0_BASE,
+ UART1_BASE
+};
+
+void mt_uart_restore(void)
+{
+ int uart_idx = UART_PORT0;
+ struct mt_uart *uart;
+ unsigned long base;
+
+ /* Must NOT print any debug log before UART restore */
+ for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
+ uart_idx++) {
+
+ uart = &uart_save_addr[uart_idx];
+ base = uart->base;
+
+ mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
+ mmio_write_32(UART_EFR(base), uart->registers.efr);
+ mmio_write_32(UART_LCR(base), uart->registers.lcr);
+ mmio_write_32(UART_FCR(base), uart->registers.fcr);
+
+ /* baudrate */
+ mmio_write_32(UART_HIGHSPEED(base), uart->registers.highspeed);
+ mmio_write_32(UART_FRACDIV_L(base), uart->registers.fracdiv_l);
+ mmio_write_32(UART_FRACDIV_M(base), uart->registers.fracdiv_m);
+ mmio_write_32(UART_LCR(base),
+ uart->registers.lcr | UART_LCR_DLAB);
+ mmio_write_32(UART_DLL(base), uart->registers.dll);
+ mmio_write_32(UART_DLH(base), uart->registers.dlh);
+ mmio_write_32(UART_LCR(base), uart->registers.lcr);
+ mmio_write_32(UART_SAMPLE_COUNT(base),
+ uart->registers.sample_count);
+ mmio_write_32(UART_SAMPLE_POINT(base),
+ uart->registers.sample_point);
+ mmio_write_32(UART_GUARD(base), uart->registers.guard);
+
+ /* flow control */
+ mmio_write_32(UART_ESCAPE_EN(base), uart->registers.escape_en);
+ mmio_write_32(UART_MCR(base), uart->registers.mcr);
+ mmio_write_32(UART_IER(base), uart->registers.ier);
+ mmio_write_32(UART_SCR(base), uart->registers.scr);
+ }
+}
+
+void mt_uart_save(void)
+{
+ int uart_idx = UART_PORT0;
+ struct mt_uart *uart;
+ unsigned long base;
+
+ for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
+ uart_idx++) {
+
+ uart_save_addr[uart_idx].base = uart_base_addr[uart_idx];
+ base = uart_base_addr[uart_idx];
+ uart = &uart_save_addr[uart_idx];
+ uart->registers.lcr = mmio_read_32(UART_LCR(base));
+
+ mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
+ uart->registers.efr = mmio_read_32(UART_EFR(base));
+ mmio_write_32(UART_LCR(base), uart->registers.lcr);
+ uart->registers.fcr = mmio_read_32(UART_FCR_RD(base));
+
+ /* baudrate */
+ uart->registers.highspeed = mmio_read_32(UART_HIGHSPEED(base));
+ uart->registers.fracdiv_l = mmio_read_32(UART_FRACDIV_L(base));
+ uart->registers.fracdiv_m = mmio_read_32(UART_FRACDIV_M(base));
+ mmio_write_32(UART_LCR(base),
+ uart->registers.lcr | UART_LCR_DLAB);
+ uart->registers.dll = mmio_read_32(UART_DLL(base));
+ uart->registers.dlh = mmio_read_32(UART_DLH(base));
+ mmio_write_32(UART_LCR(base), uart->registers.lcr);
+ uart->registers.sample_count = mmio_read_32(
+ UART_SAMPLE_COUNT(base));
+ uart->registers.sample_point = mmio_read_32(
+ UART_SAMPLE_POINT(base));
+ uart->registers.guard = mmio_read_32(UART_GUARD(base));
+
+ /* flow control */
+ uart->registers.escape_en = mmio_read_32(UART_ESCAPE_EN(base));
+ uart->registers.mcr = mmio_read_32(UART_MCR(base));
+ uart->registers.ier = mmio_read_32(UART_IER(base));
+ uart->registers.scr = mmio_read_32(UART_SCR(base));
+ }
+}
+
+void mt_console_uart_cg(int on)
+{
+ if (on == 1) {
+ mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
+ } else {
+ mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
+ }
+}
+
+uint32_t mt_console_uart_cg_status(void)
+{
+ return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT;
+}
diff --git a/plat/mediatek/drivers/uart/uart.h b/plat/mediatek/drivers/uart/uart.h
new file mode 100644
index 0000000..2ca74fa
--- /dev/null
+++ b/plat/mediatek/drivers/uart/uart.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UART_H
+#define UART_H
+
+#include <platform_def.h>
+
+/* UART HW information */
+#define HW_SUPPORT_UART_PORTS 2
+#define DRV_SUPPORT_UART_PORTS 2
+
+/* console UART clock cg */
+#define UART_CLOCK_GATE_SET (INFRACFG_AO_BASE + 0x80)
+#define UART_CLOCK_GATE_CLR (INFRACFG_AO_BASE + 0x84)
+#define UART_CLOCK_GATE_STA (INFRACFG_AO_BASE + 0x90)
+#define UART0_CLOCK_GATE_BIT (1U<<22)
+#define UART1_CLOCK_GATE_BIT (1U<<23)
+
+/* UART registers */
+#define UART_RBR(_baseaddr) (_baseaddr + 0x0)
+#define UART_THR(_baseaddr) (_baseaddr + 0x0)
+#define UART_IER(_baseaddr) (_baseaddr + 0x4)
+#define UART_IIR(_baseaddr) (_baseaddr + 0x8)
+#define UART_FCR(_baseaddr) (_baseaddr + 0x8)
+#define UART_LCR(_baseaddr) (_baseaddr + 0xc)
+#define UART_MCR(_baseaddr) (_baseaddr + 0x10)
+#define UART_LSR(_baseaddr) (_baseaddr + 0x14)
+#define UART_MSR(_baseaddr) (_baseaddr + 0x18)
+#define UART_SCR(_baseaddr) (_baseaddr + 0x1c)
+#define UART_DLL(_baseaddr) (_baseaddr + 0x0)
+#define UART_DLH(_baseaddr) (_baseaddr + 0x4)
+#define UART_EFR(_baseaddr) (_baseaddr + 0x8)
+#define UART_XON1(_baseaddr) (_baseaddr + 0x10)
+#define UART_XON2(_baseaddr) (_baseaddr + 0x14)
+#define UART_XOFF1(_baseaddr) (_baseaddr + 0x18)
+#define UART_XOFF2(_baseaddr) (_baseaddr + 0x1c)
+#define UART_AUTOBAUD(_baseaddr) (_baseaddr + 0x20)
+#define UART_HIGHSPEED(_baseaddr) (_baseaddr + 0x24)
+#define UART_SAMPLE_COUNT(_baseaddr) (_baseaddr + 0x28)
+#define UART_SAMPLE_POINT(_baseaddr) (_baseaddr + 0x2c)
+#define UART_AUTOBAUD_REG(_baseaddr) (_baseaddr + 0x30)
+#define UART_RATE_FIX_REG(_baseaddr) (_baseaddr + 0x34)
+#define UART_AUTO_BAUDSAMPLE(_baseaddr) (_baseaddr + 0x38)
+#define UART_GUARD(_baseaddr) (_baseaddr + 0x3c)
+#define UART_ESCAPE_DAT(_baseaddr) (_baseaddr + 0x40)
+#define UART_ESCAPE_EN(_baseaddr) (_baseaddr + 0x44)
+#define UART_SLEEP_EN(_baseaddr) (_baseaddr + 0x48)
+#define UART_DMA_EN(_baseaddr) (_baseaddr + 0x4c)
+#define UART_RXTRI_AD(_baseaddr) (_baseaddr + 0x50)
+#define UART_FRACDIV_L(_baseaddr) (_baseaddr + 0x54)
+#define UART_FRACDIV_M(_baseaddr) (_baseaddr + 0x58)
+#define UART_FCR_RD(_baseaddr) (_baseaddr + 0x5C)
+#define UART_USB_RX_SEL(_baseaddr) (_baseaddr + 0xB0)
+#define UART_SLEEP_REQ(_baseaddr) (_baseaddr + 0xB4)
+#define UART_SLEEP_ACK(_baseaddr) (_baseaddr + 0xB8)
+#define UART_SPM_SEL(_baseaddr) (_baseaddr + 0xBC)
+#define UART_LCR_DLAB 0x0080
+#define UART_LCR_MODE_B 0x00bf
+
+enum uart_port_ID {
+ UART_PORT0 = 0,
+ UART_PORT1
+};
+
+struct mt_uart_register {
+ uint32_t dll;
+ uint32_t dlh;
+ uint32_t ier;
+ uint32_t lcr;
+ uint32_t mcr;
+ uint32_t fcr;
+ uint32_t lsr;
+ uint32_t scr;
+ uint32_t efr;
+ uint32_t highspeed;
+ uint32_t sample_count;
+ uint32_t sample_point;
+ uint32_t fracdiv_l;
+ uint32_t fracdiv_m;
+ uint32_t escape_en;
+ uint32_t guard;
+ uint32_t rx_sel;
+};
+
+struct mt_uart {
+ unsigned long base;
+ struct mt_uart_register registers;
+};
+
+/* external API */
+void mt_uart_save(void);
+void mt_uart_restore(void);
+void mt_console_uart_cg(int on);
+uint32_t mt_console_uart_cg_status(void);
+
+#endif /* __UART_H__ */
diff --git a/plat/mediatek/drivers/uart/uart8250.h b/plat/mediatek/drivers/uart/uart8250.h
new file mode 100644
index 0000000..f0541d6
--- /dev/null
+++ b/plat/mediatek/drivers/uart/uart8250.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef UART8250_H
+#define UART8250_H
+
+/* UART register */
+#define UART_RBR 0x00 /* Receive buffer register */
+#define UART_DLL 0x00 /* Divisor latch lsb */
+#define UART_THR 0x00 /* Transmit holding register */
+#define UART_DLH 0x04 /* Divisor latch msb */
+#define UART_IER 0x04 /* Interrupt enable register */
+#define UART_FCR 0x08 /* FIFO control register */
+#define UART_LCR 0x0c /* Line control register */
+#define UART_MCR 0x10 /* Modem control register */
+#define UART_LSR 0x14 /* Line status register */
+#define UART_HIGHSPEED 0x24 /* High speed UART */
+
+/* FCR */
+#define UART_FCR_FIFO_EN 0x01 /* enable FIFO */
+#define UART_FCR_CLEAR_RCVR 0x02 /* clear the RCVR FIFO */
+#define UART_FCR_CLEAR_XMIT 0x04 /* clear the XMIT FIFO */
+
+/* LCR */
+#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
+#define UART_LCR_DLAB 0x80 /* divisor latch access bit */
+
+/* MCR */
+#define UART_MCR_DTR 0x01
+#define UART_MCR_RTS 0x02
+
+/* LSR */
+#define UART_LSR_DR 0x01 /* Data ready */
+#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
+
+#endif /* UART8250_H */
diff --git a/plat/mediatek/helpers/armv8_2/arch_helpers.S b/plat/mediatek/helpers/armv8_2/arch_helpers.S
new file mode 100644
index 0000000..02d8d53
--- /dev/null
+++ b/plat/mediatek/helpers/armv8_2/arch_helpers.S
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <cpu_macros.S>
+#if CONFIG_MTK_MCUSYS
+#include <mcucfg.h>
+#endif
+#include <platform_def.h>
+ /*
+ * Declare as weak function so that can be
+ * overwritten by platform helpers
+ */
+ .weak platform_mem_init
+ .weak plat_core_pos_by_mpidr
+ .weak plat_my_core_pos
+ .weak plat_mediatek_calc_core_pos
+ .global plat_mpidr_by_core_pos
+ .global plat_reset_handler
+
+ /* -----------------------------------------------------
+ * unsigned long plat_mpidr_by_core_pos(uint32_t cpuid)
+ * This function calcuate mpidr by cpu pos if cpu
+ * topology is linear.
+ *
+ * Clobbers: x0-x1
+ * -----------------------------------------------------
+ */
+func plat_mpidr_by_core_pos
+ lsl x0, x0, #MPIDR_AFF1_SHIFT
+ mrs x1, mpidr_el1
+ and x1, x1, #MPIDR_MT_MASK
+ orr x0, x0, x1
+ ret
+endfunc plat_mpidr_by_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_arm_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * int plat_mediatek_calc_core_pos(u_register_t mpidr);
+ *
+ * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and
+ * AFF0 is thread id. There is only one cluster in ARMv8.2
+ * and one thread in current implementation.
+ *
+ * With this function: CorePos = CoreID (AFF1)
+ * we do it with x0 = (x0 >> 8) & 0xff
+ * -----------------------------------------------------
+ */
+func plat_mediatek_calc_core_pos
+ b plat_core_pos_by_mpidr
+endfunc plat_mediatek_calc_core_pos
+
+ /* ------------------------------------------------------
+ * int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
+ *
+ * This function implements a part of the critical
+ * interface between the psci generic layer and the
+ * platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index.
+ *
+ * Clobbers: x0-x1
+ * ------------------------------------------------------
+ */
+func plat_core_pos_by_mpidr
+ mov x1, #MPIDR_AFFLVL_MASK
+ and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+ ret
+endfunc plat_core_pos_by_mpidr
+
+ /* --------------------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * Any memory init, relocation to be done before the
+ * platform boots. Called very early in the boot process.
+ * --------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+func plat_reset_handler
+#if CONFIG_MTK_MCUSYS
+ mov x10, x30
+ bl plat_my_core_pos
+ mov x30, x10
+ mov w1, #0x1
+ lsl w1, w1, w0
+ ldr x0, =CPC_MCUSYS_CPU_ON_SW_HINT_SET
+ str w1, [x0]
+ dsb sy
+#endif
+
+#if CONFIG_MTK_ECC
+ mov x10, x30
+ /* enable sequence of ecc for cpus */
+ bl disable_core_ecc
+ bl ft_ecc_clear_per_core
+ bl enable_core_ecc
+ mov x30, x10
+#endif
+
+ ret
+endfunc plat_reset_handler
diff --git a/plat/mediatek/helpers/rules.mk b/plat/mediatek/helpers/rules.mk
new file mode 100644
index 0000000..ae8068e
--- /dev/null
+++ b/plat/mediatek/helpers/rules.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := helpers
+LOCAL_SRCS-y += $(LOCAL_DIR)/$(ARCH_VERSION)/arch_helpers.S
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/include/armv8_2/arch_def.h b/plat/mediatek/include/armv8_2/arch_def.h
new file mode 100644
index 0000000..61f818f
--- /dev/null
+++ b/plat/mediatek/include/armv8_2/arch_def.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ARCH_DEF_H
+#define ARCH_DEF_H
+
+/* Topology constants */
+#define PLAT_MAX_PWR_LVL (2)
+#define PLAT_MAX_RET_STATE (1)
+#define PLAT_MAX_OFF_STATE (2)
+
+#define PLATFORM_SYSTEM_COUNT (1)
+#define PLATFORM_CLUSTER_COUNT (1)
+#define PLATFORM_CLUSTER0_CORE_COUNT (8)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER (8)
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+/* Cachline size */
+#define CACHE_WRITEBACK_SHIFT (6)
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#endif /* ARCH_DEF_H */
+
diff --git a/plat/mediatek/include/lib/mtk_init/mtk_init.h b/plat/mediatek/include/lib/mtk_init/mtk_init.h
new file mode 100644
index 0000000..6f23a9b
--- /dev/null
+++ b/plat/mediatek/include/lib/mtk_init/mtk_init.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_INIT_H
+#define MTK_INIT_H
+
+#include <cdefs.h>
+#include <lib/mtk_init/mtk_init_def.h>
+
+#define INIT_CALL_EXPAND_AS_ENUMERATION(_section_enum, _section_name, _level) \
+ _section_enum = _level,
+
+#define EXPAND_AS_LINK_SECTION(_section_enum, _section_name, _level) \
+ __##_section_enum##_START__ = .; \
+ KEEP(*(_section_name##_level));
+
+#define EXPAND_AS_EXTERN(_section_enum, _section_name, _level) \
+ extern struct initcall __##_section_enum##_START__[];
+
+#define EXPAND_AS_SYMBOL_ARR(_section_enum, _section_name, _level) \
+ __##_section_enum##_START__,
+
+#define DECLARE_MTK_INITCALL(_fn, _level) \
+ const struct initcall _mtk_initcall_##_fn \
+ __used \
+ __aligned(sizeof(void *)) \
+ __section(".mtk_plat_initcall_"#_level) \
+ = { \
+ .name = #_fn, \
+ .fn = _fn \
+ }
+
+/* initcall helpers */
+#define MTK_EARLY_PLAT_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 0)
+#define MTK_ARCH_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 1)
+#define MTK_PLAT_SETUP_0_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 2)
+#define MTK_PLAT_SETUP_1_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 3)
+#define MTK_PLAT_RUNTIME_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 4)
+#define MTK_PLAT_BL33_DEFER_INIT(_fn) DECLARE_MTK_INITCALL(_fn, 5)
+
+#ifndef __ASSEMBLER__
+struct initcall {
+ const char *name;
+ int (*fn)(void);
+};
+
+enum {
+ INIT_CALL_TABLE(INIT_CALL_EXPAND_AS_ENUMERATION)
+ MTK_INIT_LVL_MAX
+};
+
+void mtk_init_one_level(unsigned int level);
+#endif
+
+#endif /* MTK_INIT_H */
diff --git a/plat/mediatek/include/lib/mtk_init/mtk_init_def.h b/plat/mediatek/include/lib/mtk_init/mtk_init_def.h
new file mode 100644
index 0000000..8aae41d
--- /dev/null
+++ b/plat/mediatek/include/lib/mtk_init/mtk_init_def.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_INIT_DEF_H
+#define MTK_INIT_DEF_H
+
+/*
+ * Define init call sections here. _func is for 2nd level expansion, init
+ * section enum, and init section name.
+ */
+#define INIT_CALL_TABLE(_func) \
+ _func(MTK_INIT_LVL_EARLY_PLAT, .mtk_plat_initcall_, 0) \
+ _func(MTK_INIT_LVL_ARCH, .mtk_plat_initcall_, 1) \
+ _func(MTK_INIT_LVL_PLAT_SETUP_0, .mtk_plat_initcall_, 2) \
+ _func(MTK_INIT_LVL_PLAT_SETUP_1, .mtk_plat_initcall_, 3) \
+ _func(MTK_INIT_LVL_PLAT_RUNTIME, .mtk_plat_initcall_, 4) \
+ _func(MTK_INIT_LVL_BL33_DEFER, .mtk_plat_initcall_, 5)
+
+#endif /* MTK_INIT_DEF_H */
diff --git a/plat/mediatek/include/mtk_mmap_pool.h b/plat/mediatek/include/mtk_mmap_pool.h
new file mode 100644
index 0000000..99d1bff
--- /dev/null
+++ b/plat/mediatek/include/mtk_mmap_pool.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_MMAP_POOL_H
+#define MTK_MMAP_POOL_H
+
+#include <cdefs.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+
+struct mtk_mmap_descriptor {
+ const char *mmap_name;
+ const mmap_region_t *mmap_ptr;
+ const uint32_t mmap_size;
+};
+
+#define MTK_MMAP_SECTION \
+ __used \
+ __aligned(sizeof(void *)) \
+ __section(".mtk_mmap_lists")
+
+#define DECLARE_MTK_MMAP_REGIONS(_mmap_array) \
+ static const struct mtk_mmap_descriptor _mtk_mmap_descriptor_##_mmap_array \
+ __used \
+ __aligned(sizeof(void *)) \
+ __section(".mtk_mmap_pool") \
+ = { \
+ .mmap_name = #_mmap_array, \
+ .mmap_ptr = _mmap_array, \
+ .mmap_size = ARRAY_SIZE(_mmap_array) \
+ }
+
+#define MAP_BL_RW MAP_REGION_FLAT( \
+ DATA_START, \
+ BL_END - DATA_START, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#if SEPARATE_CODE_AND_RODATA
+#define MAP_BL_RO \
+ MAP_REGION_FLAT( \
+ BL_CODE_BASE, \
+ BL_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE), \
+ MAP_REGION_FLAT( \
+ BL_RO_DATA_BASE, \
+ BL_RO_DATA_END - BL_RO_DATA_BASE, \
+ MT_RO_DATA | MT_SECURE)
+#else
+#define MAP_BL_RO MAP_REGION_FLAT(BL_CODE_BASE, \
+ BL_CODE_END - BL_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+#endif
+
+void mtk_xlat_init(const mmap_region_t *bl_regions);
+
+#endif /* MTK_MMAP_POOL_H */
diff --git a/plat/mediatek/include/mtk_sip_def.h b/plat/mediatek/include/mtk_sip_def.h
new file mode 100644
index 0000000..2039017
--- /dev/null
+++ b/plat/mediatek/include/mtk_sip_def.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_SIP_DEF_H
+#define MTK_SIP_DEF_H
+
+/* Define SiP SMC ID here */
+#define MTK_SIP_SMC_FROM_NS_EL1_TABLE(_func) \
+ _func(MTK_SIP_KERNEL_TIME_SYNC, 0x202) \
+ _func(MTK_SIP_KERNEL_DFD, 0x205) \
+ _func(MTK_SIP_KERNEL_MSDC, 0x273) \
+ _func(MTK_SIP_VCORE_CONTROL, 0x506) \
+ _func(MTK_SIP_IOMMU_CONTROL, 0x514) \
+ _func(MTK_SIP_AUDIO_CONTROL, 0x517) \
+ _func(MTK_SIP_APUSYS_CONTROL, 0x51E) \
+ _func(MTK_SIP_DP_CONTROL, 0x523) \
+ _func(MTK_SIP_KERNEL_GIC_OP, 0x526)
+
+#define MTK_SIP_SMC_FROM_BL33_TABLE(_func) \
+ _func(MTK_SIP_KERNEL_BOOT, 0x115)
+
+#endif /* MTK_SIP_DEF_H */
diff --git a/plat/mediatek/include/mtk_sip_svc.h b/plat/mediatek/include/mtk_sip_svc.h
new file mode 100644
index 0000000..ce51048
--- /dev/null
+++ b/plat/mediatek/include/mtk_sip_svc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_SIP_SVC_H
+#define MTK_SIP_SVC_H
+
+#include <stdint.h>
+#include <lib/smccc.h>
+#include <mtk_sip_def.h>
+
+/* SMC function IDs for SiP Service queries */
+#define SIP_SVC_CALL_COUNT U(0x8200ff00)
+#define SIP_SVC_UID U(0x8200ff01)
+/* 0x8200ff02 is reserved */
+#define SIP_SVC_VERSION U(0x8200ff03)
+
+/* MediaTek SiP Service Calls version numbers */
+#define MTK_SIP_SVC_VERSION_MAJOR U(0x0)
+#define MTK_SIP_SVC_VERSION_MINOR U(0x1)
+
+/* Number of MediaTek SiP Calls implemented */
+#define MTK_COMMON_SIP_NUM_CALLS U(4)
+
+/* MediaTek SiP Service Calls function IDs */
+#define MTK_SIP_SET_AUTHORIZED_SECURE_REG U(0x82000001)
+
+#define SMC_ID_EXPAND_AS_ENUM(_smc_id, _smc_num) \
+ _smc_id##_AARCH32 = ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+ ((0) << FUNCID_CC_SHIFT) | \
+ (OEN_SIP_START << FUNCID_OEN_SHIFT) | \
+ ((_smc_num) << FUNCID_NUM_SHIFT)), \
+ _smc_id##_AARCH64 = ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
+ ((1) << FUNCID_CC_SHIFT) | \
+ (OEN_SIP_START << FUNCID_OEN_SHIFT) | \
+ ((_smc_num) << FUNCID_NUM_SHIFT)),
+
+#define SMC_ID_EXPAND_AS_EXTERN_SMC_INDEX(_smc_id, _smc_num) \
+ extern short _smc_id##_descriptor_index;
+
+/* Bind SMC handler with SMC ID */
+#define DECLARE_SMC_HANDLER(_smc_id, _smc_handler) \
+ const struct smc_descriptor _smc_id##_descriptor \
+ __used \
+ __aligned(sizeof(void *)) \
+ __section(".mtk_smc_descriptor_pool") = { \
+ .smc_handler = _smc_handler, \
+ .smc_name = #_smc_id, \
+ .smc_id_aarch32 = _smc_id##_AARCH32, \
+ .smc_id_aarch64 = _smc_id##_AARCH64, \
+ .smc_descriptor_index = &_smc_id##_descriptor_index \
+ }
+
+MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_EXTERN_SMC_INDEX);
+MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_EXTERN_SMC_INDEX);
+
+/* Expand SiP SMC ID table as enum */
+enum {
+ MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_ENUM)
+ MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_ENUM)
+ MTK_SIP_SMC_MAX_NUMBER
+};
+
+/* MediaTek SiP Calls error code */
+enum {
+ MTK_SIP_E_SUCCESS = 0,
+ MTK_SIP_E_INVALID_PARAM = -1,
+ MTK_SIP_E_NOT_SUPPORTED = -2,
+ MTK_SIP_E_INVALID_RANGE = -3,
+ MTK_SIP_E_PERMISSION_DENY = -4,
+ MTK_SIP_E_LOCK_FAIL = -5,
+};
+
+struct smccc_res {
+ uint64_t a1;
+ uint64_t a2;
+ uint64_t a3;
+};
+
+typedef uintptr_t (*smc_handler_t)(u_register_t,
+ u_register_t,
+ u_register_t,
+ u_register_t,
+ void *,
+ struct smccc_res *);
+
+struct smc_descriptor {
+ smc_handler_t smc_handler;
+ const uint32_t smc_id_aarch32;
+ const uint32_t smc_id_aarch64;
+ const char *smc_name;
+ short *const smc_descriptor_index;
+};
+
+/*
+ * This function should be implemented in MediaTek SOC directory. It fullfills
+ * MTK_SIP_SET_AUTHORIZED_SECURE_REG SiP call by checking the sreg with the
+ * predefined secure register list, if a match was found, set val to sreg.
+ *
+ * Return MTK_SIP_E_SUCCESS on success, and MTK_SIP_E_INVALID_PARAM on failure.
+ */
+uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val);
+
+#endif /* MTK_SIP_SVC_H */
diff --git a/plat/mediatek/include/plat.ld.rodata.inc b/plat/mediatek/include/plat.ld.rodata.inc
new file mode 100644
index 0000000..06ad491
--- /dev/null
+++ b/plat/mediatek/include/plat.ld.rodata.inc
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_LD_RODATA_INC
+#define PLAT_LD_RODATA_INC
+
+#include <lib/mtk_init/mtk_init.h>
+ . = ALIGN(32);
+ INIT_CALL_TABLE(EXPAND_AS_LINK_SECTION);
+ __MTK_PLAT_INITCALL_END__ = .;
+ . = ALIGN(32);
+ __MTK_MMAP_POINTER_POOL_START__ = .;
+ KEEP(*(.mtk_mmap_pool))
+ __MTK_MMAP_POINTER_POOL_END_UNALIGNED__ = .;
+ . = ALIGN(8);
+ __MTK_MMAP_POOL_START__ = .;
+ KEEP(*(.mtk_mmap_lists))
+ __MTK_MMAP_POOL_END_UNALIGNED__ = .;
+ . = ALIGN(32);
+ __MTK_SMC_POOL_START__ = .;
+ KEEP(*(.mtk_smc_descriptor_pool))
+ __MTK_SMC_POOL_END_UNALIGNED__ = .;
+ . = ALIGN(8);
+#include <vendor_pubsub_events.h>
+ *(mtk_plat_ro)
+
+#endif /* PLAT_LD_RODATA_INC */
diff --git a/plat/mediatek/include/vendor_pubsub_events.h b/plat/mediatek/include/vendor_pubsub_events.h
new file mode 100644
index 0000000..cb8d878
--- /dev/null
+++ b/plat/mediatek/include/vendor_pubsub_events.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VENDOR_PUBSUB_EVENTS_H
+#define VENDOR_PUBSUB_EVENTS_H
+
+#include <lib/el3_runtime/pubsub.h>
+
+REGISTER_PUBSUB_EVENT(lpm_publish_event);
+REGISTER_PUBSUB_EVENT(suspend_publish_event);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_pwr_on);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_pwr_off);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_afflv_pwr_on);
+REGISTER_PUBSUB_EVENT(mt_cpupm_publish_afflv_pwr_off);
+REGISTER_PUBSUB_EVENT(publish_check_wakeup_irq);
+REGISTER_PUBSUB_EVENT(watchdog_timeout);
+
+#endif /* VENDOR_PUBSUB_EVENTS_H */
diff --git a/plat/mediatek/lib/mtk_init/mtk_init.c b/plat/mediatek/lib/mtk_init/mtk_init.c
new file mode 100644
index 0000000..2289659
--- /dev/null
+++ b/plat/mediatek/lib/mtk_init/mtk_init.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <lib/mtk_init/mtk_init.h>
+
+INIT_CALL_TABLE(EXPAND_AS_EXTERN);
+extern struct initcall __MTK_PLAT_INITCALL_END__[];
+
+struct initcall *initcall_list[] = {
+ INIT_CALL_TABLE(EXPAND_AS_SYMBOL_ARR)
+ __MTK_PLAT_INITCALL_END__
+};
+
+void mtk_init_one_level(uint32_t level)
+{
+ const struct initcall *entry;
+ int error;
+
+ if (level >= MTK_INIT_LVL_MAX) {
+ ERROR("invalid level:%u\n", level);
+ panic();
+ }
+
+ INFO("init calling level:%u\n", level);
+ for (entry = initcall_list[level];
+ (entry != NULL) && (entry < initcall_list[level + 1]);
+ entry++) {
+ INFO("calling %s\n", entry->name);
+ error = entry->fn();
+ if (error != 0) {
+ ERROR("init %s fail, errno:%d\n", entry->name, error);
+ }
+ }
+}
diff --git a/plat/mediatek/lib/mtk_init/mtk_mmap_init.c b/plat/mediatek/lib/mtk_init/mtk_mmap_init.c
new file mode 100644
index 0000000..e3dada0
--- /dev/null
+++ b/plat/mediatek/lib/mtk_init/mtk_mmap_init.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <mtk_mmap_pool.h>
+
+IMPORT_SYM(uintptr_t, __MTK_MMAP_POINTER_POOL_START__, MTK_MMAP_POINTER_POOL_START);
+IMPORT_SYM(uintptr_t, __MTK_MMAP_POINTER_POOL_END_UNALIGNED__, MTK_MMAP_POINTER_POOL_END_UNALIGNED);
+IMPORT_SYM(uintptr_t, __RW_START__, RW_START);
+IMPORT_SYM(uintptr_t, __DATA_START__, DATA_START);
+
+#define MAP_MTK_SECTIONS MAP_REGION_FLAT(RW_START, \
+ DATA_START - RW_START, \
+ MT_MEMORY | MT_RO | MT_SECURE)
+
+
+static void print_mmap(const mmap_region_t *regions)
+{
+ while (regions->size != 0U) {
+ VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n",
+ regions->base_va,
+ regions->base_va + regions->size,
+ regions->attr);
+ regions++;
+ }
+}
+
+void mtk_xlat_init(const mmap_region_t *bl_regions)
+{
+ struct mtk_mmap_descriptor *iter;
+ const mmap_region_t *regions = bl_regions;
+
+ print_mmap(regions);
+ mmap_add(bl_regions);
+ if (MTK_MMAP_POINTER_POOL_START != MTK_MMAP_POINTER_POOL_END_UNALIGNED) {
+ for (iter = (struct mtk_mmap_descriptor *)MTK_MMAP_POINTER_POOL_START;
+ (char *)iter < (char *)MTK_MMAP_POINTER_POOL_END_UNALIGNED;
+ iter++) {
+ regions = iter->mmap_ptr;
+ INFO("mmap_name: %s\n", iter->mmap_name);
+ INFO("mmap_size: 0x%x\n", iter->mmap_size);
+ print_mmap(regions);
+ mmap_add(regions);
+ }
+ }
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
diff --git a/plat/mediatek/lib/mtk_init/rules.mk b/plat/mediatek/lib/mtk_init/rules.mk
new file mode 100644
index 0000000..cc6ca95
--- /dev/null
+++ b/plat/mediatek/lib/mtk_init/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := mtk_init
+
+LOCAL_SRCS-y := $(LOCAL_DIR)/mtk_init.c
+LOCAL_SRCS-y += $(LOCAL_DIR)/mtk_mmap_init.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/lib/pm/armv8_2/pwr_ctrl.c b/plat/mediatek/lib/pm/armv8_2/pwr_ctrl.c
new file mode 100644
index 0000000..447234a
--- /dev/null
+++ b/plat/mediatek/lib/pm/armv8_2/pwr_ctrl.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/psci/psci.h>
+#include <lib/utils.h>
+#ifdef MTK_PUBEVENT_ENABLE
+#include <vendor_pubsub_events.h>
+#endif
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <dfd.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <lib/pm/mtk_pm.h>
+#include <mt_gic_v3.h>
+#include <platform_def.h>
+
+#define IS_AFFLV_PUBEVENT(_pstate) \
+ ((_pstate & (MT_CPUPM_PWR_DOMAIN_MCUSYS | MT_CPUPM_PWR_DOMAIN_CLUSTER)) != 0)
+
+#ifdef MTK_PUBEVENT_ENABLE
+#define MT_CPUPM_EVENT_PWR_ON(x) ({ \
+ PUBLISH_EVENT_ARG(mt_cpupm_publish_pwr_on, (const void *)(x)); })
+
+#define MT_CPUPM_EVENT_PWR_OFF(x) ({ \
+ PUBLISH_EVENT_ARG(mt_cpupm_publish_pwr_off, (const void *)(x)); })
+
+#define MT_CPUPM_EVENT_AFFLV_PWR_ON(x) ({ \
+ PUBLISH_EVENT_ARG(mt_cpupm_publish_afflv_pwr_on, (const void *)(x)); })
+
+#define MT_CPUPM_EVENT_AFFLV_PWR_OFF(x) ({ \
+ PUBLISH_EVENT_ARG(mt_cpupm_publish_afflv_pwr_off, (const void *)(x)); })
+
+#else
+#define MT_CPUPM_EVENT_PWR_ON(x) ({ (void)x; })
+#define MT_CPUPM_EVENT_PWR_OFF(x) ({ (void)x; })
+#define MT_CPUPM_EVENT_AFFLV_PWR_ON(x) ({ (void)x; })
+#define MT_CPUPM_EVENT_AFFLV_PWR_OFF(x) ({ (void)x; })
+#endif
+
+/*
+ * The cpu require to cluster power stattus
+ * [0] : The cpu require cluster power down
+ * [1] : The cpu require cluster power on
+ */
+#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron() coordinate_cluster(1)
+#define coordinate_cluster_pwroff() coordinate_cluster(0)
+
+/* defaultly disable all functions */
+#define MTK_CPUPM_FN_MASK_DEFAULT (0)
+
+struct mtk_cpu_pwr_ctrl {
+ unsigned int fn_mask;
+ struct mtk_cpu_pm_ops *ops;
+ struct mtk_cpu_smp_ops *smp;
+};
+
+static struct mtk_cpu_pwr_ctrl mtk_cpu_pwr = {
+ .fn_mask = MTK_CPUPM_FN_MASK_DEFAULT,
+ .ops = NULL,
+};
+
+#define IS_CPUIDLE_FN_ENABLE(x) ((mtk_cpu_pwr.ops != NULL) && ((mtk_cpu_pwr.fn_mask & x) != 0))
+#define IS_CPUSMP_FN_ENABLE(x) ((mtk_cpu_pwr.smp != NULL) && ((mtk_cpu_pwr.fn_mask & x) != 0))
+
+/* per-cpu power state */
+static unsigned int armv8_2_power_state[PLATFORM_CORE_COUNT];
+
+#define armv8_2_get_pwr_stateid(cpu) psci_get_pstate_id(armv8_2_power_state[cpu])
+
+static unsigned int get_mediatek_pstate(unsigned int domain, unsigned int psci_state,
+ struct mtk_cpupm_pwrstate *state)
+{
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_CPUPM_GET_PWR_STATE)) {
+ return mtk_cpu_pwr.ops->get_pstate(domain, psci_state, state);
+ }
+
+ return 0;
+}
+
+unsigned int armv8_2_get_pwr_afflv(const psci_power_state_t *state_info)
+{
+ int i;
+
+ for (i = (int)PLAT_MAX_PWR_LVL; i >= (int)PSCI_CPU_PWR_LVL; i--) {
+ if (is_local_state_run(state_info->pwr_domain_state[i]) == 0) {
+ return (unsigned int) i;
+ }
+ }
+
+ return PSCI_INVALID_PWR_LVL;
+}
+
+/* MediaTek mcusys power on control interface */
+static void armv8_2_mcusys_pwr_on_common(const struct mtk_cpupm_pwrstate *state)
+{
+ gicv3_distif_init();
+ mt_gic_distif_restore();
+ gic_sgi_restore_all();
+
+ dfd_resume();
+
+ /* Add code here that behavior before system enter mcusys'on */
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_RESUME_MCUSYS)) {
+ mtk_cpu_pwr.ops->mcusys_resume(state);
+ }
+}
+
+/* MediaTek mcusys power down control interface */
+static void armv8_2_mcusys_pwr_dwn_common(const struct mtk_cpupm_pwrstate *state)
+{
+ mt_gic_distif_save();
+ gic_sgi_save_all();
+
+ /* Add code here that behaves before entering mcusys off */
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_SUSPEND_MCUSYS)) {
+ mtk_cpu_pwr.ops->mcusys_suspend(state);
+ }
+}
+
+/* MediaTek Cluster power on control interface */
+static void armv8_2_cluster_pwr_on_common(const struct mtk_cpupm_pwrstate *state)
+{
+ /* Add code here that behavior before system enter cluster'on */
+#if defined(MTK_CM_MGR) && !defined(MTK_FPGA_EARLY_PORTING)
+ /* init cpu stall counter */
+ init_cpu_stall_counter_all();
+#endif
+
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_RESUME_CLUSTER)) {
+ mtk_cpu_pwr.ops->cluster_resume(state);
+ }
+}
+
+/* MediaTek Cluster power down control interface */
+static void armv8_2_cluster_pwr_dwn_common(const struct mtk_cpupm_pwrstate *state)
+{
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_SUSPEND_CLUSTER)) {
+ mtk_cpu_pwr.ops->cluster_suspend(state);
+ }
+}
+
+/* MediaTek CPU power on control interface */
+static void armv8_2_cpu_pwr_on_common(const struct mtk_cpupm_pwrstate *state, unsigned int pstate)
+{
+ coordinate_cluster_pwron();
+
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+
+ /* If MCUSYS has been powered down then restore GIC redistributor for all CPUs. */
+ if (IS_PLAT_SYSTEM_RETENTION(state->pwr.afflv)) {
+ mt_gic_rdistif_restore_all();
+ } else {
+ mt_gic_rdistif_restore();
+ }
+}
+
+/* MediaTek CPU power down control interface */
+static void armv8_2_cpu_pwr_dwn_common(const struct mtk_cpupm_pwrstate *state, unsigned int pstate)
+{
+ if ((pstate & MT_CPUPM_PWR_DOMAIN_PERCORE_DSU) != 0) {
+ coordinate_cluster_pwroff();
+ }
+
+ mt_gic_rdistif_save();
+ gicv3_cpuif_disable(plat_my_core_pos());
+ gicv3_rdistif_off(plat_my_core_pos());
+}
+
+static void armv8_2_cpu_pwr_resume(const struct mtk_cpupm_pwrstate *state, unsigned int pstate)
+{
+ armv8_2_cpu_pwr_on_common(state, pstate);
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_RESUME_CORE)) {
+ mtk_cpu_pwr.ops->cpu_resume(state);
+ }
+}
+
+static void armv8_2_cpu_pwr_suspend(const struct mtk_cpupm_pwrstate *state, unsigned int pstate)
+{
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_SUSPEND_CORE)) {
+ mtk_cpu_pwr.ops->cpu_suspend(state);
+ }
+ armv8_2_cpu_pwr_dwn_common(state, pstate);
+}
+
+static void armv8_2_cpu_pwr_on(const struct mtk_cpupm_pwrstate *state, unsigned int pstate)
+{
+ armv8_2_cpu_pwr_on_common(state, pstate);
+
+ if (IS_CPUSMP_FN_ENABLE(MTK_CPUPM_FN_SMP_CORE_ON)) {
+ mtk_cpu_pwr.smp->cpu_on(state);
+ }
+}
+
+static void armv8_2_cpu_pwr_off(const struct mtk_cpupm_pwrstate *state, unsigned int pstate)
+{
+ if (IS_CPUSMP_FN_ENABLE(MTK_CPUPM_FN_SMP_CORE_OFF)) {
+ mtk_cpu_pwr.smp->cpu_off(state);
+ }
+ armv8_2_cpu_pwr_dwn_common(state, pstate);
+}
+
+/* MediaTek PSCI power domain */
+static int armv8_2_power_domain_on(u_register_t mpidr)
+{
+ int ret = PSCI_E_SUCCESS;
+ int cpu = plat_core_pos_by_mpidr(mpidr);
+ uintptr_t entry = plat_pm_get_warm_entry();
+
+ if (IS_CPUSMP_FN_ENABLE(MTK_CPUPM_FN_PWR_ON_CORE_PREPARE)) {
+ if (mtk_cpu_pwr.smp->cpu_pwr_on_prepare(cpu, entry) != 0) {
+ ret = PSCI_E_DENIED;
+ }
+ }
+ INFO("CPU %u power domain prepare on\n", cpu);
+ return ret;
+}
+
+/* MediaTek PSCI power domain */
+static void armv8_2_power_domain_on_finish(const psci_power_state_t *state)
+{
+ struct mt_cpupm_event_data nb;
+ unsigned int pstate = (MT_CPUPM_PWR_DOMAIN_CORE | MT_CPUPM_PWR_DOMAIN_PERCORE_DSU);
+ struct mtk_cpupm_pwrstate pm_state = {
+ .info = {
+ .cpuid = plat_my_core_pos(),
+ .mode = MTK_CPU_PM_SMP,
+ },
+ .pwr = {
+ .afflv = armv8_2_get_pwr_afflv(state),
+ .state_id = 0x0,
+ },
+ };
+
+ armv8_2_cpu_pwr_on(&pm_state, pstate);
+
+ nb.cpuid = pm_state.info.cpuid;
+ nb.pwr_domain = pstate;
+ MT_CPUPM_EVENT_PWR_ON(&nb);
+
+ INFO("CPU %u power domain on finished\n", pm_state.info.cpuid);
+}
+
+/* MediaTek PSCI power domain */
+static void armv8_2_power_domain_off(const psci_power_state_t *state)
+{
+ struct mt_cpupm_event_data nb;
+ unsigned int pstate = (MT_CPUPM_PWR_DOMAIN_CORE | MT_CPUPM_PWR_DOMAIN_PERCORE_DSU);
+ struct mtk_cpupm_pwrstate pm_state = {
+ .info = {
+ .cpuid = plat_my_core_pos(),
+ .mode = MTK_CPU_PM_SMP,
+ },
+ .pwr = {
+ .afflv = armv8_2_get_pwr_afflv(state),
+ .state_id = 0x0,
+ },
+ };
+ armv8_2_cpu_pwr_off(&pm_state, pstate);
+
+ nb.cpuid = pm_state.info.cpuid;
+ nb.pwr_domain = pstate;
+ MT_CPUPM_EVENT_PWR_OFF(&nb);
+
+ INFO("CPU %u power domain off\n", pm_state.info.cpuid);
+}
+
+/* MediaTek PSCI power domain */
+static void armv8_2_power_domain_suspend(const psci_power_state_t *state)
+{
+ unsigned int pstate = 0;
+ struct mt_cpupm_event_data nb;
+ struct mtk_cpupm_pwrstate pm_state = {
+ .info = {
+ .cpuid = plat_my_core_pos(),
+ .mode = MTK_CPU_PM_CPUIDLE,
+ },
+ };
+
+ pm_state.pwr.state_id = armv8_2_get_pwr_stateid(pm_state.info.cpuid);
+ pm_state.pwr.afflv = armv8_2_get_pwr_afflv(state);
+ pm_state.pwr.raw = state;
+
+ pstate = get_mediatek_pstate(CPUPM_PWR_OFF,
+ armv8_2_power_state[pm_state.info.cpuid], &pm_state);
+
+ armv8_2_cpu_pwr_suspend(&pm_state, pstate);
+
+ if ((pstate & MT_CPUPM_PWR_DOMAIN_CLUSTER) != 0) {
+ armv8_2_cluster_pwr_dwn_common(&pm_state);
+ }
+
+ if ((pstate & MT_CPUPM_PWR_DOMAIN_MCUSYS) != 0) {
+ armv8_2_mcusys_pwr_dwn_common(&pm_state);
+ }
+
+ nb.cpuid = pm_state.info.cpuid;
+ nb.pwr_domain = pstate;
+ MT_CPUPM_EVENT_PWR_OFF(&nb);
+
+ if (IS_AFFLV_PUBEVENT(pstate)) {
+ MT_CPUPM_EVENT_AFFLV_PWR_OFF(&nb);
+ }
+}
+
+/* MediaTek PSCI power domain */
+static void armv8_2_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+ unsigned int pstate = 0;
+ struct mt_cpupm_event_data nb;
+ struct mtk_cpupm_pwrstate pm_state = {
+ .info = {
+ .cpuid = plat_my_core_pos(),
+ .mode = MTK_CPU_PM_CPUIDLE,
+ },
+ };
+
+ pm_state.pwr.state_id = armv8_2_get_pwr_stateid(pm_state.info.cpuid);
+ pm_state.pwr.afflv = armv8_2_get_pwr_afflv(state);
+ pm_state.pwr.raw = state;
+
+ pstate = get_mediatek_pstate(CPUPM_PWR_ON,
+ armv8_2_power_state[pm_state.info.cpuid], &pm_state);
+
+ if ((pstate & MT_CPUPM_PWR_DOMAIN_MCUSYS) != 0) {
+ armv8_2_mcusys_pwr_on_common(&pm_state);
+ }
+
+ if ((pstate & MT_CPUPM_PWR_DOMAIN_CLUSTER) != 0) {
+ armv8_2_cluster_pwr_on_common(&pm_state);
+ }
+
+ armv8_2_cpu_pwr_resume(&pm_state, pstate);
+
+ nb.cpuid = pm_state.info.cpuid;
+ nb.pwr_domain = pstate;
+ MT_CPUPM_EVENT_PWR_ON(&nb);
+
+ if (IS_AFFLV_PUBEVENT(pstate)) {
+ MT_CPUPM_EVENT_AFFLV_PWR_ON(&nb);
+ }
+}
+
+/* MediaTek PSCI power domain */
+static int armv8_2_validate_power_state(unsigned int power_state, psci_power_state_t *req_state)
+{
+ unsigned int i;
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int my_core_pos = plat_my_core_pos();
+
+ if (mtk_cpu_pwr.ops == NULL) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_PWR_STATE_VALID)) {
+ if (mtk_cpu_pwr.ops->pwr_state_valid(aff_lvl, pstate) != 0) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+ }
+
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+ } else {
+ for (i = PSCI_CPU_PWR_LVL; i <= aff_lvl; i++) {
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ }
+ }
+ armv8_2_power_state[my_core_pos] = power_state;
+
+ return PSCI_E_SUCCESS;
+}
+
+/* MediaTek PSCI power domain */
+#if CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND
+static void armv8_2_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+ int ret;
+ unsigned int power_state;
+ unsigned int my_core_pos = plat_my_core_pos();
+
+ ret = mtk_cpu_pwr.ops->pwr_state_valid(PLAT_MAX_PWR_LVL,
+ PSTATE_TYPE_POWERDOWN);
+
+ if (ret != MTK_CPUPM_E_OK) {
+ /* Avoid suspend due to platform is not ready. */
+ req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] =
+ PLAT_MAX_RET_STATE;
+ for (i = PSCI_CPU_PWR_LVL + 1; i <= PLAT_MAX_PWR_LVL; i++) {
+ req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
+ }
+
+ power_state = psci_make_powerstate(0, PSTATE_TYPE_STANDBY, PSCI_CPU_PWR_LVL);
+ } else {
+ for (i = PSCI_CPU_PWR_LVL; i <= PLAT_MAX_PWR_LVL; i++) {
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ }
+
+ power_state = psci_make_powerstate(MT_PLAT_PWR_STATE_SUSPEND,
+ PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+ }
+
+ armv8_2_power_state[my_core_pos] = power_state;
+ flush_dcache_range((uintptr_t)&armv8_2_power_state[my_core_pos],
+ sizeof(armv8_2_power_state[my_core_pos]));
+}
+#endif
+static void armv8_2_pm_smp_init(unsigned int cpu_id, uintptr_t entry_point)
+{
+ if (entry_point == 0) {
+ ERROR("%s, warm_entry_point is null\n", __func__);
+ panic();
+ }
+ if (IS_CPUSMP_FN_ENABLE(MTK_CPUPM_FN_SMP_INIT)) {
+ mtk_cpu_pwr.smp->init(cpu_id, entry_point);
+ }
+ INFO("[%s:%d] - Initialize finished\n", __func__, __LINE__);
+}
+
+static struct plat_pm_pwr_ctrl armv8_2_pwr_ops = {
+ .pwr_domain_suspend = armv8_2_power_domain_suspend,
+ .pwr_domain_suspend_finish = armv8_2_power_domain_suspend_finish,
+ .validate_power_state = armv8_2_validate_power_state,
+#if CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND
+ .get_sys_suspend_power_state = armv8_2_get_sys_suspend_power_state,
+#endif
+};
+
+struct plat_pm_smp_ctrl armv8_2_smp_ops = {
+ .init = armv8_2_pm_smp_init,
+ .pwr_domain_on = armv8_2_power_domain_on,
+ .pwr_domain_off = armv8_2_power_domain_off,
+ .pwr_domain_on_finish = armv8_2_power_domain_on_finish,
+};
+
+#define ISSUE_CPU_PM_REG_FAIL(_success) ({ _success = false; assert(0); })
+
+#define CPM_PM_FN_CHECK(_fns, _ops, _id, _func, _result, _flag) ({ \
+ if ((_fns & _id)) { \
+ if (_ops->_func) \
+ _flag |= _id; \
+ else { \
+ ISSUE_CPU_PM_REG_FAIL(_result); \
+ } \
+ } })
+
+int register_cpu_pm_ops(unsigned int fn_flags, struct mtk_cpu_pm_ops *ops)
+{
+ bool success = true;
+ unsigned int fns = 0;
+
+ if ((ops == NULL) || (mtk_cpu_pwr.ops != NULL)) {
+ ERROR("[%s:%d] register cpu_pm fail !!\n", __FILE__, __LINE__);
+ return MTK_CPUPM_E_ERR;
+ }
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_RESUME_CORE,
+ cpu_resume, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SUSPEND_CORE,
+ cpu_suspend, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_RESUME_CLUSTER,
+ cluster_resume, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SUSPEND_CLUSTER,
+ cluster_suspend, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_RESUME_MCUSYS,
+ mcusys_resume, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SUSPEND_MCUSYS,
+ mcusys_suspend, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_CPUPM_GET_PWR_STATE,
+ get_pstate, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_PWR_STATE_VALID,
+ pwr_state_valid, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_INIT,
+ init, success, fns);
+
+ if (success) {
+ mtk_cpu_pwr.ops = ops;
+ mtk_cpu_pwr.fn_mask |= fns;
+ plat_pm_ops_setup_pwr(&armv8_2_pwr_ops);
+ INFO("[%s:%d] CPU pwr ops register success, support:0x%x\n",
+ __func__, __LINE__, fns);
+ } else {
+ ERROR("[%s:%d] register cpu_pm ops fail !, fn:0x%x\n",
+ __func__, __LINE__, fn_flags);
+ assert(0);
+ }
+ return MTK_CPUPM_E_OK;
+}
+
+int register_cpu_smp_ops(unsigned int fn_flags, struct mtk_cpu_smp_ops *ops)
+{
+ bool success = true;
+ unsigned int fns = 0;
+
+ if ((ops == NULL) || (mtk_cpu_pwr.smp != NULL)) {
+ ERROR("[%s:%d] register cpu_smp fail !!\n", __FILE__, __LINE__);
+ return MTK_CPUPM_E_ERR;
+ }
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SMP_INIT,
+ init, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_PWR_ON_CORE_PREPARE,
+ cpu_pwr_on_prepare, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SMP_CORE_ON,
+ cpu_on, success, fns);
+
+ CPM_PM_FN_CHECK(fn_flags, ops, MTK_CPUPM_FN_SMP_CORE_OFF,
+ cpu_off, success, fns);
+
+ if (success == true) {
+ mtk_cpu_pwr.smp = ops;
+ mtk_cpu_pwr.fn_mask |= fns;
+ plat_pm_ops_setup_smp(&armv8_2_smp_ops);
+ INFO("[%s:%d] CPU smp ops register success, support:0x%x\n",
+ __func__, __LINE__, fns);
+ } else {
+ ERROR("[%s:%d] register cpu_smp ops fail !, fn:0x%x\n",
+ __func__, __LINE__, fn_flags);
+ assert(0);
+ }
+ return MTK_CPUPM_E_OK;
+}
diff --git a/plat/mediatek/lib/pm/armv8_2/rules.mk b/plat/mediatek/lib/pm/armv8_2/rules.mk
new file mode 100644
index 0000000..0e065c5
--- /dev/null
+++ b/plat/mediatek/lib/pm/armv8_2/rules.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := armv${CONFIG_MTK_PM_ARCH}
+LOCAL_SRCS-y := ${LOCAL_DIR}/pwr_ctrl.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/lib/pm/mtk_pm.c b/plat/mediatek/lib/pm/mtk_pm.c
new file mode 100644
index 0000000..3dbeb51
--- /dev/null
+++ b/plat/mediatek/lib/pm/mtk_pm.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <plat/common/platform.h>
+#include <lib/pm/mtk_pm.h>
+
+#define MTK_PM_ST_SMP_READY BIT(0)
+#define MTK_PM_ST_PWR_READY BIT(1)
+#define MTK_PM_ST_RESET_READY BIT(2)
+
+static uintptr_t mtk_secure_entrypoint;
+static plat_init_func mtk_plat_smp_init;
+static plat_psci_ops_t mtk_pm_ops;
+static unsigned int mtk_pm_status;
+
+uintptr_t plat_pm_get_warm_entry(void)
+{
+ return mtk_secure_entrypoint;
+}
+
+int plat_pm_ops_setup_pwr(struct plat_pm_pwr_ctrl *ops)
+{
+ if (!ops) {
+ return MTK_CPUPM_E_FAIL;
+ }
+
+#if CONFIG_MTK_CPU_SUSPEND_EN
+ if (!mtk_pm_ops.pwr_domain_suspend) {
+ mtk_pm_ops.pwr_domain_suspend = ops->pwr_domain_suspend;
+ }
+
+ if (!mtk_pm_ops.pwr_domain_suspend_finish) {
+ mtk_pm_ops.pwr_domain_suspend_finish = ops->pwr_domain_suspend_finish;
+ }
+
+ if (!mtk_pm_ops.validate_power_state) {
+ mtk_pm_ops.validate_power_state = ops->validate_power_state;
+ }
+
+ if (!mtk_pm_ops.get_sys_suspend_power_state) {
+ mtk_pm_ops.get_sys_suspend_power_state = ops->get_sys_suspend_power_state;
+ }
+
+ mtk_pm_status |= MTK_PM_ST_PWR_READY;
+#endif
+ return MTK_CPUPM_E_OK;
+}
+
+int plat_pm_ops_setup_smp(struct plat_pm_smp_ctrl *ops)
+{
+ if (!ops) {
+ return MTK_CPUPM_E_FAIL;
+ }
+
+#if CONFIG_MTK_SMP_EN
+ if (!mtk_pm_ops.pwr_domain_on) {
+ mtk_pm_ops.pwr_domain_on = ops->pwr_domain_on;
+ }
+
+ if (!mtk_pm_ops.pwr_domain_on_finish) {
+ mtk_pm_ops.pwr_domain_on_finish = ops->pwr_domain_on_finish;
+ }
+
+ if (!mtk_pm_ops.pwr_domain_off) {
+ mtk_pm_ops.pwr_domain_off = ops->pwr_domain_off;
+ }
+
+ if (!mtk_plat_smp_init) {
+ mtk_plat_smp_init = ops->init;
+ }
+
+ mtk_pm_status |= MTK_PM_ST_SMP_READY;
+#endif
+ return MTK_CPUPM_E_OK;
+}
+
+int plat_pm_ops_setup_reset(struct plat_pm_reset_ctrl *ops)
+{
+ if (!ops) {
+ return MTK_CPUPM_E_FAIL;
+ }
+
+ if (!mtk_pm_ops.system_off) {
+ mtk_pm_ops.system_off = ops->system_off;
+ }
+
+ if (!mtk_pm_ops.system_reset) {
+ mtk_pm_ops.system_reset = ops->system_reset;
+ }
+
+ if (!mtk_pm_ops.system_reset2) {
+ mtk_pm_ops.system_reset2 = ops->system_reset2;
+ }
+
+ mtk_pm_status |= MTK_PM_ST_RESET_READY;
+
+ return MTK_CPUPM_E_OK;
+}
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &mtk_pm_ops;
+ mtk_secure_entrypoint = sec_entrypoint;
+
+ if (mtk_plat_smp_init) {
+ unsigned int cpu_id = plat_my_core_pos();
+
+ mtk_plat_smp_init(cpu_id, mtk_secure_entrypoint);
+ }
+ INFO("%s, smp:(%d), pwr_ctrl:(%d), system_reset:(%d)\n", __func__,
+ !!(mtk_pm_status & MTK_PM_ST_SMP_READY),
+ !!(mtk_pm_status & MTK_PM_ST_PWR_READY),
+ !!(mtk_pm_status & MTK_PM_ST_RESET_READY));
+ return 0;
+}
diff --git a/plat/mediatek/lib/pm/mtk_pm.h b/plat/mediatek/lib/pm/mtk_pm.h
new file mode 100644
index 0000000..4a29439
--- /dev/null
+++ b/plat/mediatek/lib/pm/mtk_pm.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_PM_H
+#define MTK_PM_H
+#include <lib/psci/psci.h>
+
+#if MTK_PUBEVENT_ENABLE
+#include <vendor_pubsub_events.h>
+#endif
+
+#define MTK_CPUPM_E_OK (0)
+#define MTK_CPUPM_E_UNKNOWN (-1)
+#define MTK_CPUPM_E_ERR (-2)
+#define MTK_CPUPM_E_FAIL (-3)
+#define MTK_CPUPM_E_NOT_SUPPORT (-4)
+
+
+#define MTK_CPUPM_FN_PWR_LOCK_AQUIRE BIT(0)
+#define MTK_CPUPM_FN_INIT BIT(1)
+#define MTK_CPUPM_FN_PWR_STATE_VALID BIT(2)
+#define MTK_CPUPM_FN_PWR_ON_CORE_PREPARE BIT(3)
+#define MTK_CPUPM_FN_SUSPEND_CORE BIT(4)
+#define MTK_CPUPM_FN_RESUME_CORE BIT(5)
+#define MTK_CPUPM_FN_SUSPEND_CLUSTER BIT(6)
+#define MTK_CPUPM_FN_RESUME_CLUSTER BIT(7)
+#define MTK_CPUPM_FN_SUSPEND_MCUSYS BIT(8)
+#define MTK_CPUPM_FN_RESUME_MCUSYS BIT(9)
+#define MTK_CPUPM_FN_CPUPM_GET_PWR_STATE BIT(10)
+#define MTK_CPUPM_FN_SMP_INIT BIT(11)
+#define MTK_CPUPM_FN_SMP_CORE_ON BIT(12)
+#define MTK_CPUPM_FN_SMP_CORE_OFF BIT(13)
+
+enum mtk_cpupm_pstate {
+ MTK_CPUPM_CORE_ON,
+ MTK_CPUPM_CORE_OFF,
+ MTK_CPUPM_CORE_SUSPEND,
+ MTK_CPUPM_CORE_RESUME,
+ MTK_CPUPM_CLUSTER_SUSPEND,
+ MTK_CPUPM_CLUSTER_RESUME,
+ MTK_CPUPM_MCUSYS_SUSPEND,
+ MTK_CPUPM_MCUSYS_RESUME,
+};
+
+enum mtk_cpu_pm_mode {
+ MTK_CPU_PM_CPUIDLE,
+ MTK_CPU_PM_SMP,
+};
+
+#define MT_IRQ_REMAIN_MAX (32)
+#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
+
+struct mt_irqremain {
+ unsigned int count;
+ unsigned int irqs[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
+};
+
+typedef void (*plat_init_func)(unsigned int, uintptr_t);
+
+struct plat_pm_smp_ctrl {
+ plat_init_func init;
+ int (*pwr_domain_on)(u_register_t mpidr);
+ void (*pwr_domain_off)(const psci_power_state_t *target_state);
+ void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
+};
+
+struct plat_pm_pwr_ctrl {
+ void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
+ void (*pwr_domain_on_finish_late)(const psci_power_state_t *target_state);
+ void (*pwr_domain_suspend_finish)(const psci_power_state_t *target_state);
+ int (*validate_power_state)(unsigned int power_state, psci_power_state_t *req_state);
+ void (*get_sys_suspend_power_state)(psci_power_state_t *req_state);
+};
+
+struct plat_pm_reset_ctrl {
+ __dead2 void (*system_off)();
+ __dead2 void (*system_reset)();
+ int (*system_reset2)(int is_vendor, int reset_type, u_register_t cookie);
+};
+
+struct mtk_cpu_pm_info {
+ unsigned int cpuid;
+ unsigned int mode;
+};
+
+struct mtk_cpu_pm_state {
+ unsigned int afflv;
+ unsigned int state_id;
+ const psci_power_state_t *raw;
+};
+
+struct mtk_cpupm_pwrstate {
+ struct mtk_cpu_pm_info info;
+ struct mtk_cpu_pm_state pwr;
+};
+
+struct mtk_cpu_smp_ops {
+ void (*init)(unsigned int cpu, uintptr_t sec_entrypoint);
+ int (*cpu_pwr_on_prepare)(unsigned int cpu, uintptr_t entry);
+ void (*cpu_on)(const struct mtk_cpupm_pwrstate *state);
+ void (*cpu_off)(const struct mtk_cpupm_pwrstate *state);
+ int (*invoke)(unsigned int funcID, void *priv);
+};
+
+#define MT_CPUPM_PWR_DOMAIN_CORE BIT(0)
+#define MT_CPUPM_PWR_DOMAIN_PERCORE_DSU BIT(1)
+#define MT_CPUPM_PWR_DOMAIN_PERCORE_DSU_MEM BIT(2)
+#define MT_CPUPM_PWR_DOMAIN_CLUSTER BIT(3)
+#define MT_CPUPM_PWR_DOMAIN_MCUSYS BIT(4)
+#define MT_CPUPM_PWR_DOMAIN_SUSPEND BIT(5)
+
+enum mt_cpupm_pwr_domain {
+ CPUPM_PWR_ON,
+ CPUPM_PWR_OFF,
+};
+
+typedef unsigned int mtk_pstate_type;
+
+struct mtk_cpu_pm_ops {
+ void (*init)(unsigned int cpu, uintptr_t sec_entrypoint);
+ unsigned int (*get_pstate)(enum mt_cpupm_pwr_domain domain,
+ const mtk_pstate_type psci_state,
+ const struct mtk_cpupm_pwrstate *state);
+ int (*pwr_state_valid)(unsigned int afflv, unsigned int state);
+ void (*cpu_suspend)(const struct mtk_cpupm_pwrstate *state);
+ void (*cpu_resume)(const struct mtk_cpupm_pwrstate *state);
+ void (*cluster_suspend)(const struct mtk_cpupm_pwrstate *state);
+ void (*cluster_resume)(const struct mtk_cpupm_pwrstate *state);
+ void (*mcusys_suspend)(const struct mtk_cpupm_pwrstate *state);
+ void (*mcusys_resume)(const struct mtk_cpupm_pwrstate *state);
+ int (*invoke)(unsigned int funcID, void *priv);
+};
+
+int register_cpu_pm_ops(unsigned int fn_flags, struct mtk_cpu_pm_ops *ops);
+int register_cpu_smp_ops(unsigned int fn_flags, struct mtk_cpu_smp_ops *ops);
+
+struct mt_cpupm_event_data {
+ unsigned int cpuid;
+ unsigned int pwr_domain;
+};
+
+/* Extension event for platform driver */
+#if MTK_PUBEVENT_ENABLE
+/* [PUB_EVENT] Core power on */
+#define MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(_fn) \
+ SUBSCRIBE_TO_EVENT(mt_cpupm_publish_pwr_on, _fn)
+
+/* [PUB_EVENT] Core power off */
+#define MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(_fn) \
+ SUBSCRIBE_TO_EVENT(mt_cpupm_publish_pwr_off, _fn)
+
+/* [PUB_EVENT] Cluster power on */
+#define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_ON(_fn) \
+ SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_on, _fn)
+
+/* [PUB_EVENT] Cluster power off */
+#define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_OFF(_fn) \
+ SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_off, _fn)
+
+/* [PUB_EVENT] Mcusys power on */
+#define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_ON(_fn) \
+ SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_on, _fn)
+
+/* [PUB_EVENT] Mcusys power off */
+#define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_OFF(_fn) \
+ SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_off, _fn)
+
+#else
+#define MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(_fn)
+#define MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(_fn)
+#define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_ON(_fn)
+#define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_OFF(_fn)
+#define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_ON(_fn)
+#define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_OFF(_fn)
+#endif
+
+/*
+ * Definition c-state power domain.
+ * bit[7:4] (main state id):
+ * - 1: Cluster.
+ * - 2: Mcusys.
+ * - 3: Memory.
+ * - 4: System pll.
+ * - 5: System bus.
+ * - 6: SoC 26m/DCXO.
+ * - 7: Vcore buck.
+ * - 15: Suspend.
+ * bit[3:0] (reserved for state_id extension):
+ * - 4: CPU buck.
+ */
+#define MT_PLAT_PWR_STATE_CLUSTER (0x0010)
+#define MT_PLAT_PWR_STATE_MCUSYS (0x0020)
+#define MT_PLAT_PWR_STATE_MCUSYS_BUCK (0x0024)
+#define MT_PLAT_PWR_STATE_SYSTEM_MEM (0x0030)
+#define MT_PLAT_PWR_STATE_SYSTEM_PLL (0x0040)
+#define MT_PLAT_PWR_STATE_SYSTEM_BUS (0x0050)
+#define MT_PLAT_PWR_STATE_SUSPEND (0x00f0)
+
+#define IS_MT_PLAT_PWR_STATE(state, target_state) ((state & target_state) == target_state)
+#define IS_MT_PLAT_PWR_STATE_MCUSYS(state) IS_MT_PLAT_PWR_STATE(state, MT_PLAT_PWR_STATE_MCUSYS)
+
+#define PLAT_MT_SYSTEM_SUSPEND PLAT_MAX_OFF_STATE
+#define PLAT_MT_CPU_SUSPEND_CLUSTER PLAT_MAX_RET_STATE
+#define PLAT_MT_CPU_SUSPEND_MCUSYS PLAT_MAX_RET_STATE
+
+#define IS_PLAT_SYSTEM_SUSPEND(aff) (aff == PLAT_MT_SYSTEM_SUSPEND)
+#define IS_PLAT_SYSTEM_RETENTION(aff) (aff >= PLAT_MAX_RET_STATE)
+
+#define IS_PLAT_SUSPEND_ID(stateid) (stateid == MT_PLAT_PWR_STATE_SUSPEND)
+
+#define IS_PLAT_MCUSYSOFF_AFFLV(afflv) (afflv >= PLAT_MT_CPU_SUSPEND_MCUSYS)
+
+int plat_pm_ops_setup_pwr(struct plat_pm_pwr_ctrl *ops);
+int plat_pm_ops_setup_reset(struct plat_pm_reset_ctrl *ops);
+int plat_pm_ops_setup_smp(struct plat_pm_smp_ctrl *ops);
+uintptr_t plat_pm_get_warm_entry(void);
+
+#endif
diff --git a/plat/mediatek/lib/pm/rules.mk b/plat/mediatek/lib/pm/rules.mk
new file mode 100644
index 0000000..29265c4
--- /dev/null
+++ b/plat/mediatek/lib/pm/rules.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := pm
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_pm.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
+
+SUB_RULES-$(CONFIG_MTK_PM_SUPPORT) := $(LOCAL_DIR)/armv${CONFIG_MTK_PM_ARCH}
+$(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))
diff --git a/plat/mediatek/lib/system_reset/reset_cros.c b/plat/mediatek/lib/system_reset/reset_cros.c
new file mode 100644
index 0000000..40e68ba
--- /dev/null
+++ b/plat/mediatek/lib/system_reset/reset_cros.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/gpio.h>
+#include <lib/mtk_init/mtk_init.h>
+#include <lib/pm/mtk_pm.h>
+#include <plat_params.h>
+#include <pmic.h>
+#include <rtc.h>
+
+static void __dead2 mtk_system_reset_cros(void)
+{
+ struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+ INFO("MTK System Reset\n");
+
+ gpio_set_value(gpio_reset->index, gpio_reset->polarity);
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 mtk_system_off_cros(void)
+{
+ INFO("MTK System Off\n");
+
+ rtc_power_off_sequence();
+ pmic_power_off();
+
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static struct plat_pm_reset_ctrl lib_reset_ctrl = {
+ .system_off = mtk_system_off_cros,
+ .system_reset = mtk_system_reset_cros,
+ .system_reset2 = NULL,
+};
+
+static int lib_reset_ctrl_init(void)
+{
+ INFO("Reset init\n");
+
+ plat_pm_ops_setup_reset(&lib_reset_ctrl);
+
+ return 0;
+}
+MTK_ARCH_INIT(lib_reset_ctrl_init);
diff --git a/plat/mediatek/lib/system_reset/rules.mk b/plat/mediatek/lib/system_reset/rules.mk
new file mode 100644
index 0000000..4f20663
--- /dev/null
+++ b/plat/mediatek/lib/system_reset/rules.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := system_reset
+
+LOCAL_SRCS-y := ${LOCAL_DIR}/reset_cros.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/mediatek/mt8173/aarch64/plat_helpers.S b/plat/mediatek/mt8173/aarch64/plat_helpers.S
new file mode 100644
index 0000000..095dfc5
--- /dev/null
+++ b/plat/mediatek/mt8173/aarch64/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <mt8173_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_report_exception
+ .globl platform_is_primary_cpu
+ .globl plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* MT8173 Oak does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+func platform_is_primary_cpu
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #MT8173_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc platform_is_primary_cpu
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void);
+ *
+ * result: CorePos = CoreId + (ClusterId << 2)
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
diff --git a/plat/mediatek/mt8173/aarch64/platform_common.c b/plat/mediatek/mt8173/aarch64/platform_common.c
new file mode 100644
index 0000000..a2dbe3e
--- /dev/null
+++ b/plat/mediatek/mt8173/aarch64/platform_common.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include <mt8173_def.h>
+
+static const int cci_map[] = {
+ PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX
+};
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_mmap[] = {
+ /* for TF text, RO, RW */
+ MAP_REGION_FLAT(TZRAM_BASE, TZRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void plat_configure_mmu_el ## _el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(plat_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el ## _el(0); \
+ }
+
+/* Define EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(3)
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+void plat_cci_init(void)
+{
+ /* Initialize CCI driver */
+ cci_init(PLAT_MT_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+}
+
+void plat_cci_enable(void)
+{
+ /*
+ * Enable CCI coherency for this cluster.
+ * No need for locks as no other cpu is active at the moment.
+ */
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+}
+
+void plat_cci_disable(void)
+{
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+}
diff --git a/plat/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c
new file mode 100644
index 0000000..bd7d0b0
--- /dev/null
+++ b/plat/mediatek/mt8173/bl31_plat_setup.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+
+#include <mcucfg.h>
+#include <mtcmos.h>
+#include <mtk_plat_common.h>
+#include <plat_private.h>
+#include <spm.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+static void platform_setup_cpu(void)
+{
+ /* turn off all the little core's power except cpu 0 */
+ mtcmos_little_cpu_off();
+
+ /* setup big cores */
+ mmio_write_32((uintptr_t)&mt8173_mcucfg->mp1_config_res,
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK |
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK);
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_miscdbg, MP1_AINACTS);
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_clkenm_div,
+ MP1_SW_CG_GEN);
+ mmio_clrbits_32((uintptr_t)&mt8173_mcucfg->mp1_rst_ctl,
+ MP1_L2RSTDISABLE);
+
+ /* set big cores arm64 boot mode */
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_cpucfg,
+ MP1_CPUCFG_64BIT);
+
+ /* set LITTLE cores arm64 boot mode */
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp0_rv_addr[0].rv_addr_hw,
+ MP0_CPUCFG_64BIT);
+
+ /* enable dcm control */
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->bus_fabric_dcm_ctrl,
+ ADB400_GRP_DCM_EN | CCI400_GRP_DCM_EN | ADBCLK_GRP_DCM_EN |
+ EMICLK_GRP_DCM_EN | ACLK_GRP_DCM_EN | L2C_IDLE_DCM_EN |
+ INFRACLK_PSYS_DYNAMIC_CG_EN);
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->l2c_sram_ctrl,
+ L2C_SRAM_DCM_EN);
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->cci_clk_ctrl,
+ MCU_BUS_DCM_EN);
+}
+
+static void platform_setup_sram(void)
+{
+ /* protect BL31 memory from non-secure read/write access */
+ mmio_write_32(SRAMROM_SEC_ADDR, (uint32_t)(BL31_END + 0x3ff) & 0x3fc00);
+ mmio_write_32(SRAMROM_SEC_CTRL, 0x10000ff9);
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ console_16550_register(MT8173_UART0_BASE, MT8173_UART_CLOCK, MT8173_BAUDRATE, &console);
+
+ VERBOSE("bl31_setup\n");
+
+ bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ platform_setup_cpu();
+ platform_setup_sram();
+
+ generic_delay_timer_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_arm_gic_driver_init();
+ plat_arm_gic_init();
+
+ /* Initialize spm at boot time */
+ spm_boot_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_cci_init();
+ plat_cci_enable();
+
+ plat_configure_mmu_el3(BL_CODE_BASE,
+ BL_COHERENT_RAM_END - BL_CODE_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
diff --git a/plat/mediatek/mt8173/drivers/crypt/crypt.c b/plat/mediatek/mt8173/drivers/crypt/crypt.c
new file mode 100644
index 0000000..bfb3082
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/crypt/crypt.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mt8173_def.h>
+#include <mtk_sip_svc.h>
+
+#define crypt_read32(offset) \
+ mmio_read_32((uintptr_t)(CRYPT_BASE+((offset) * 4)))
+
+#define crypt_write32(offset, value) \
+ mmio_write_32((uintptr_t)(CRYPT_BASE + ((offset) * 4)), (uint32_t)value)
+
+#define GET_L32(x) ((uint32_t)(x & 0xffffffff))
+#define GET_H32(x) ((uint32_t)((x >> 32) & 0xffffffff))
+
+#define REG_INIT 0
+#define REG_MSC 4
+#define REG_TRIG 256
+#define REG_STAT 512
+#define REG_CLR 513
+#define REG_INT 514
+#define REG_P68 768
+#define REG_P69 769
+#define REG_P70 770
+#define REG_P71 771
+#define REG_P72 772
+#define REG_D20 820
+#define KEY_SIZE 160
+#define KEY_LEN 40
+
+/* Wait until crypt is completed */
+uint64_t crypt_wait(void)
+{
+ crypt_write32(REG_TRIG, 0);
+ while (crypt_read32(REG_STAT) == 0)
+ ;
+ udelay(100);
+ crypt_write32(REG_CLR, crypt_read32(REG_STAT));
+ crypt_write32(REG_INT, 0);
+ return MTK_SIP_E_SUCCESS;
+}
+
+static uint32_t record[4];
+/* Copy encrypted key to crypt engine */
+uint64_t crypt_set_hdcp_key_ex(uint64_t x1, uint64_t x2, uint64_t x3)
+{
+ uint32_t i = (uint32_t)x1;
+ uint32_t j = 0;
+
+ if (i > KEY_LEN)
+ return MTK_SIP_E_INVALID_PARAM;
+
+ if (i < KEY_LEN) {
+ crypt_write32(REG_MSC, 0x80ff3800);
+ crypt_write32(REG_INIT, 0);
+ crypt_write32(REG_INIT, 0xF);
+ crypt_write32(REG_CLR, 1);
+ crypt_write32(REG_INT, 0);
+
+ crypt_write32(REG_P68, 0x70);
+ crypt_write32(REG_P69, 0x1C0);
+ crypt_write32(REG_P70, 0x30);
+ crypt_write32(REG_P71, 0x4);
+ crypt_wait();
+
+ crypt_write32(REG_D20 + 4 * i, GET_L32(x2));
+ crypt_write32(REG_D20 + 4 * i + 1, GET_H32(x2));
+ crypt_write32(REG_D20 + 4 * i + 2, GET_L32(x3));
+ crypt_write32(REG_D20 + 4 * i + 3, GET_H32(x3));
+
+ crypt_write32(REG_P69, 0);
+ crypt_write32(REG_P68, 0x20);
+ crypt_write32(REG_P71, 0x34 + 4 * i);
+ crypt_write32(REG_P72, 0x34 + 4 * i);
+ crypt_wait();
+
+ for (j = 0; j < 4; j++) {
+ crypt_write32(REG_P68, 0x71);
+ crypt_write32(REG_P69, 0x34 + 4 * i + j);
+ crypt_write32(REG_P70, record[j]);
+ crypt_wait();
+ }
+ }
+ /* Prepare data for next iteration */
+ record[0] = GET_L32(x2);
+ record[1] = GET_H32(x2);
+ record[2] = GET_L32(x3);
+ record[3] = GET_H32(x3);
+ return MTK_SIP_E_SUCCESS;
+}
+
+/* Set key to hdcp */
+uint64_t crypt_set_hdcp_key_num(uint32_t num)
+{
+ if (num > KEY_LEN)
+ return MTK_SIP_E_INVALID_PARAM;
+
+ crypt_write32(REG_P68, 0x6A);
+ crypt_write32(REG_P69, 0x34 + 4 * num);
+ crypt_wait();
+ return MTK_SIP_E_SUCCESS;
+}
+
+/* Clear key in crypt engine */
+uint64_t crypt_clear_hdcp_key(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < KEY_SIZE; i++)
+ crypt_write32(REG_D20 + i, 0);
+ return MTK_SIP_E_SUCCESS;
+}
diff --git a/plat/mediatek/mt8173/drivers/crypt/crypt.h b/plat/mediatek/mt8173/drivers/crypt/crypt.h
new file mode 100644
index 0000000..1a691a6
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/crypt/crypt.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef CRYPT_H
+#define CRYPT_H
+
+#include <stdint.h>
+
+/* crypt function prototype */
+uint64_t crypt_set_hdcp_key_ex(uint64_t x1, uint64_t x2, uint64_t x3);
+uint64_t crypt_set_hdcp_key_num(uint32_t num);
+uint64_t crypt_clear_hdcp_key(void);
+
+#endif /* CRYPT_H */
diff --git a/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c b/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c
new file mode 100644
index 0000000..452ac22
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mt8173_def.h>
+#include <mtcmos.h>
+#include <spm.h>
+#include <spm_mcdi.h>
+
+enum {
+ SRAM_ISOINT_B = 1U << 6,
+ SRAM_CKISO = 1U << 5,
+ PWR_CLK_DIS = 1U << 4,
+ PWR_ON_2ND = 1U << 3,
+ PWR_ON = 1U << 2,
+ PWR_ISO = 1U << 1,
+ PWR_RST_B = 1U << 0
+};
+
+enum {
+ L1_PDN_ACK = 1U << 8,
+ L1_PDN = 1U << 0
+};
+
+enum {
+ LITTLE_CPU3 = 1U << 12,
+ LITTLE_CPU2 = 1U << 11,
+ LITTLE_CPU1 = 1U << 10,
+};
+
+enum {
+ SRAM_PDN = 0xf << 8,
+ DIS_SRAM_ACK = 0x1 << 12,
+ AUD_SRAM_ACK = 0xf << 12,
+};
+
+enum {
+ DIS_PWR_STA_MASK = 0x1 << 3,
+ AUD_PWR_STA_MASK = 0x1 << 24,
+};
+
+#define SPM_VDE_PWR_CON 0x0210
+#define SPM_MFG_PWR_CON 0x0214
+#define SPM_VEN_PWR_CON 0x0230
+#define SPM_ISP_PWR_CON 0x0238
+#define SPM_DIS_PWR_CON 0x023c
+#define SPM_VEN2_PWR_CON 0x0298
+#define SPM_AUDIO_PWR_CON 0x029c
+#define SPM_MFG_2D_PWR_CON 0x02c0
+#define SPM_MFG_ASYNC_PWR_CON 0x02c4
+#define SPM_USB_PWR_CON 0x02cc
+
+#define MTCMOS_CTRL_SUCCESS 0
+#define MTCMOS_CTRL_ERROR -1
+
+#define MTCMOS_CTRL_EN (0x1 << 18)
+
+#define VDE_PWR_ON 0
+#define VEN_PWR_ON 1
+#define ISP_PWR_ON 2
+#define DIS_PWR_ON 3
+#define VEN2_PWR_ON 4
+#define AUDIO_PWR_ON 5
+#define MFG_ASYNC_PWR_ON 6
+#define MFG_2D_PWR_ON 7
+#define MFG_PWR_ON 8
+#define USB_PWR_ON 9
+
+#define VDE_PWR_OFF 10
+#define VEN_PWR_OFF 11
+#define ISP_PWR_OFF 12
+#define DIS_PWR_OFF 13
+#define VEN2_PWR_OFF 14
+#define AUDIO_PWR_OFF 15
+#define MFG_ASYNC_PWR_OFF 16
+#define MFG_2D_PWR_OFF 17
+#define MFG_PWR_OFF 18
+#define USB_PWR_OFF 19
+
+#define VDE_PWR_CON_PWR_STA 7
+#define VEN_PWR_CON_PWR_STA 21
+#define ISP_PWR_CON_PWR_STA 5
+#define DIS_PWR_CON_PWR_STA 3
+#define VEN2_PWR_CON_PWR_STA 20
+#define AUDIO_PWR_CON_PWR_STA 24
+#define MFG_ASYNC_PWR_CON_PWR_STA 23
+#define MFG_2D_PWR_CON_PWR_STA 22
+#define MFG_PWR_CON_PWR_STA 4
+#define USB_PWR_CON_PWR_STA 25
+
+/*
+ * Timeout if the ack is not signled after 1 second.
+ * According to designer, one mtcmos operation should be done
+ * around 10us.
+ */
+#define MTCMOS_ACK_POLLING_MAX_COUNT 10000
+#define MTCMOS_ACK_POLLING_INTERVAL 10
+
+static void mtcmos_ctrl_little_off(unsigned int linear_id)
+{
+ uint32_t reg_pwr_con;
+ uint32_t reg_l1_pdn;
+ uint32_t bit_cpu;
+
+ switch (linear_id) {
+ case 1:
+ reg_pwr_con = SPM_CA7_CPU1_PWR_CON;
+ reg_l1_pdn = SPM_CA7_CPU1_L1_PDN;
+ bit_cpu = LITTLE_CPU1;
+ break;
+ case 2:
+ reg_pwr_con = SPM_CA7_CPU2_PWR_CON;
+ reg_l1_pdn = SPM_CA7_CPU2_L1_PDN;
+ bit_cpu = LITTLE_CPU2;
+ break;
+ case 3:
+ reg_pwr_con = SPM_CA7_CPU3_PWR_CON;
+ reg_l1_pdn = SPM_CA7_CPU3_L1_PDN;
+ bit_cpu = LITTLE_CPU3;
+ break;
+ default:
+ /* should never come to here */
+ return;
+ }
+
+ /* enable register control */
+ mmio_write_32(SPM_POWERON_CONFIG_SET,
+ (SPM_PROJECT_CODE << 16) | (1U << 0));
+
+ mmio_setbits_32(reg_pwr_con, PWR_ISO);
+ mmio_setbits_32(reg_pwr_con, SRAM_CKISO);
+ mmio_clrbits_32(reg_pwr_con, SRAM_ISOINT_B);
+ mmio_setbits_32(reg_l1_pdn, L1_PDN);
+
+ while (!(mmio_read_32(reg_l1_pdn) & L1_PDN_ACK))
+ continue;
+
+ mmio_clrbits_32(reg_pwr_con, PWR_RST_B);
+ mmio_setbits_32(reg_pwr_con, PWR_CLK_DIS);
+ mmio_clrbits_32(reg_pwr_con, PWR_ON);
+ mmio_clrbits_32(reg_pwr_con, PWR_ON_2ND);
+
+ while ((mmio_read_32(SPM_PWR_STATUS) & bit_cpu) ||
+ (mmio_read_32(SPM_PWR_STATUS_2ND) & bit_cpu))
+ continue;
+}
+
+void mtcmos_little_cpu_off(void)
+{
+ /* turn off little cpu 1 - 3 */
+ mtcmos_ctrl_little_off(1);
+ mtcmos_ctrl_little_off(2);
+ mtcmos_ctrl_little_off(3);
+}
+
+uint32_t wait_mtcmos_ack(uint32_t on, uint32_t pwr_ctrl, uint32_t spm_pwr_sta)
+{
+ int i = 0;
+ uint32_t cmp, pwr_sta, pwr_sta_2nd;
+
+ while (1) {
+ cmp = mmio_read_32(SPM_PCM_PASR_DPD_3) & pwr_ctrl;
+ pwr_sta = (mmio_read_32(SPM_PWR_STATUS) >> spm_pwr_sta) & 1;
+ pwr_sta_2nd =
+ (mmio_read_32(SPM_PWR_STATUS_2ND) >> spm_pwr_sta) & 1;
+ if (cmp && (pwr_sta == on) && (pwr_sta_2nd == on)) {
+ mmio_write_32(SPM_PCM_RESERVE2, 0);
+ return MTCMOS_CTRL_SUCCESS;
+ }
+ udelay(MTCMOS_ACK_POLLING_INTERVAL);
+ i++;
+ if (i > MTCMOS_ACK_POLLING_MAX_COUNT) {
+ INFO("MTCMOS control failed(%d), SPM_PWR_STA(%d),\n"
+ "SPM_PCM_RESERVE=0x%x,SPM_PCM_RESERVE2=0x%x,\n"
+ "SPM_PWR_STATUS=0x%x,SPM_PWR_STATUS_2ND=0x%x\n"
+ "SPM_PCM_PASR_DPD_3 = 0x%x\n",
+ on, spm_pwr_sta, mmio_read_32(SPM_PCM_RESERVE),
+ mmio_read_32(SPM_PCM_RESERVE2),
+ mmio_read_32(SPM_PWR_STATUS),
+ mmio_read_32(SPM_PWR_STATUS_2ND),
+ mmio_read_32(SPM_PCM_PASR_DPD_3));
+ mmio_write_32(SPM_PCM_RESERVE2, 0);
+ return MTCMOS_CTRL_ERROR;
+ }
+ }
+}
+
+uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num)
+{
+ uint32_t ret = MTCMOS_CTRL_SUCCESS;
+ uint32_t power_on;
+ uint32_t power_off;
+ uint32_t power_ctrl;
+ uint32_t power_status;
+
+ spm_lock_get();
+ spm_mcdi_prepare_for_mtcmos();
+ mmio_setbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN);
+
+ switch (mtcmos_num) {
+ case SPM_VDE_PWR_CON:
+ power_on = VDE_PWR_ON;
+ power_off = VDE_PWR_OFF;
+ power_status = VDE_PWR_CON_PWR_STA;
+ break;
+ case SPM_MFG_PWR_CON:
+ power_on = MFG_PWR_ON;
+ power_off = MFG_PWR_OFF;
+ power_status = MFG_PWR_CON_PWR_STA;
+ break;
+ case SPM_VEN_PWR_CON:
+ power_on = VEN_PWR_ON;
+ power_off = VEN_PWR_OFF;
+ power_status = VEN_PWR_CON_PWR_STA;
+ break;
+ case SPM_ISP_PWR_CON:
+ power_on = ISP_PWR_ON;
+ power_off = ISP_PWR_OFF;
+ power_status = ISP_PWR_CON_PWR_STA;
+ break;
+ case SPM_DIS_PWR_CON:
+ power_on = DIS_PWR_ON;
+ power_off = DIS_PWR_OFF;
+ power_status = DIS_PWR_CON_PWR_STA;
+ break;
+ case SPM_VEN2_PWR_CON:
+ power_on = VEN2_PWR_ON;
+ power_off = VEN2_PWR_OFF;
+ power_status = VEN2_PWR_CON_PWR_STA;
+ break;
+ case SPM_AUDIO_PWR_CON:
+ power_on = AUDIO_PWR_ON;
+ power_off = AUDIO_PWR_OFF;
+ power_status = AUDIO_PWR_CON_PWR_STA;
+ break;
+ case SPM_MFG_2D_PWR_CON:
+ power_on = MFG_2D_PWR_ON;
+ power_off = MFG_2D_PWR_OFF;
+ power_status = MFG_2D_PWR_CON_PWR_STA;
+ break;
+ case SPM_MFG_ASYNC_PWR_CON:
+ power_on = MFG_ASYNC_PWR_ON;
+ power_off = MFG_ASYNC_PWR_OFF;
+ power_status = MFG_ASYNC_PWR_CON_PWR_STA;
+ break;
+ case SPM_USB_PWR_CON:
+ power_on = USB_PWR_ON;
+ power_off = USB_PWR_OFF;
+ power_status = USB_PWR_CON_PWR_STA;
+ break;
+ default:
+ ret = MTCMOS_CTRL_ERROR;
+ INFO("No mapping MTCMOS(%d), ret = %d\n", mtcmos_num, ret);
+ break;
+ }
+ if (ret == MTCMOS_CTRL_SUCCESS) {
+ power_ctrl = on ? (1 << power_on) : (1 << power_off);
+ mmio_setbits_32(SPM_PCM_RESERVE2, power_ctrl);
+ ret = wait_mtcmos_ack(on, power_ctrl, power_status);
+ VERBOSE("0x%x(%d), PWR_STATUS(0x%x), ret(%d)\n",
+ power_ctrl, on, mmio_read_32(SPM_PWR_STATUS), ret);
+ }
+
+ mmio_clrbits_32(SPM_PCM_RESERVE, MTCMOS_CTRL_EN);
+ spm_lock_release();
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h b/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h
new file mode 100644
index 0000000..1e58027
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef MTCMOS_H
+#define MTCMOS_H
+
+/*
+ * This function will turn off all the little core's power except cpu 0. The
+ * cores in cluster 0 are all powered when the system power on. The System
+ * Power Manager (SPM) will do nothing if it found the core's power was on
+ * during CPU_ON psci call.
+ */
+void mtcmos_little_cpu_off(void);
+uint32_t mtcmos_non_cpu_ctrl(uint32_t on, uint32_t mtcmos_num);
+
+#endif /* MTCMOS_H */
diff --git a/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..0dffc23
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <platform_def.h>
+
+/* external API */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
+int32_t pwrap_write(uint32_t adr, uint32_t wdata);
+
+static struct mt8173_pmic_wrap_regs *const mtk_pwrap =
+ (void *)PMIC_WRAP_BASE;
+
+/* timeout setting */
+enum {
+ TIMEOUT_RESET = 50, /* us */
+ TIMEOUT_READ = 50, /* us */
+ TIMEOUT_WAIT_IDLE = 50 /* us */
+};
+
+/* PMIC_WRAP registers */
+struct mt8173_pmic_wrap_regs {
+ uint32_t mux_sel;
+ uint32_t wrap_en;
+ uint32_t dio_en;
+ uint32_t sidly;
+ uint32_t rddmy;
+ uint32_t si_ck_con;
+ uint32_t cshext_write;
+ uint32_t cshext_read;
+ uint32_t cslext_start;
+ uint32_t cslext_end;
+ uint32_t staupd_prd;
+ uint32_t staupd_grpen;
+ uint32_t reserved[4];
+ uint32_t staupd_man_trig;
+ uint32_t staupd_sta;
+ uint32_t wrap_sta;
+ uint32_t harb_init;
+ uint32_t harb_hprio;
+ uint32_t hiprio_arb_en;
+ uint32_t harb_sta0;
+ uint32_t harb_sta1;
+ uint32_t man_en;
+ uint32_t man_cmd;
+ uint32_t man_rdata;
+ uint32_t man_vldclr;
+ uint32_t wacs0_en;
+ uint32_t init_done0;
+ uint32_t wacs0_cmd;
+ uint32_t wacs0_rdata;
+ uint32_t wacs0_vldclr;
+ uint32_t wacs1_en;
+ uint32_t init_done1;
+ uint32_t wacs1_cmd;
+ uint32_t wacs1_rdata;
+ uint32_t wacs1_vldclr;
+ uint32_t wacs2_en;
+ uint32_t init_done2;
+ uint32_t wacs2_cmd;
+ uint32_t wacs2_rdata;
+ uint32_t wacs2_vldclr;
+ uint32_t int_en;
+ uint32_t int_flg_raw;
+ uint32_t int_flg;
+ uint32_t int_clr;
+ uint32_t sig_adr;
+ uint32_t sig_mode;
+ uint32_t sig_value;
+ uint32_t sig_errval;
+ uint32_t crc_en;
+ uint32_t timer_en;
+ uint32_t timer_sta;
+ uint32_t wdt_unit;
+ uint32_t wdt_src_en;
+ uint32_t wdt_flg;
+ uint32_t debug_int_sel;
+ uint32_t dvfs_adr0;
+ uint32_t dvfs_wdata0;
+ uint32_t dvfs_adr1;
+ uint32_t dvfs_wdata1;
+ uint32_t dvfs_adr2;
+ uint32_t dvfs_wdata2;
+ uint32_t dvfs_adr3;
+ uint32_t dvfs_wdata3;
+ uint32_t dvfs_adr4;
+ uint32_t dvfs_wdata4;
+ uint32_t dvfs_adr5;
+ uint32_t dvfs_wdata5;
+ uint32_t dvfs_adr6;
+ uint32_t dvfs_wdata6;
+ uint32_t dvfs_adr7;
+ uint32_t dvfs_wdata7;
+ uint32_t spminf_sta;
+ uint32_t cipher_key_sel;
+ uint32_t cipher_iv_sel;
+ uint32_t cipher_en;
+ uint32_t cipher_rdy;
+ uint32_t cipher_mode;
+ uint32_t cipher_swrst;
+ uint32_t dcm_en;
+ uint32_t dcm_dbc_prd;
+};
+
+enum {
+ RDATA_WACS_RDATA_SHIFT = 0,
+ RDATA_WACS_FSM_SHIFT = 16,
+ RDATA_WACS_REQ_SHIFT = 19,
+ RDATA_SYNC_IDLE_SHIFT,
+ RDATA_INIT_DONE_SHIFT,
+ RDATA_SYS_IDLE_SHIFT,
+};
+
+enum {
+ RDATA_WACS_RDATA_MASK = 0xffff,
+ RDATA_WACS_FSM_MASK = 0x7,
+ RDATA_WACS_REQ_MASK = 0x1,
+ RDATA_SYNC_IDLE_MASK = 0x1,
+ RDATA_INIT_DONE_MASK = 0x1,
+ RDATA_SYS_IDLE_MASK = 0x1,
+};
+
+/* WACS_FSM */
+enum {
+ WACS_FSM_IDLE = 0x00,
+ WACS_FSM_REQ = 0x02,
+ WACS_FSM_WFDLE = 0x04,
+ WACS_FSM_WFVLDCLR = 0x06,
+ WACS_INIT_DONE = 0x01,
+ WACS_SYNC_IDLE = 0x01,
+ WACS_SYNC_BUSY = 0x00
+};
+
+/* error information flag */
+enum {
+ E_PWR_INVALID_ARG = 1,
+ E_PWR_INVALID_RW = 2,
+ E_PWR_INVALID_ADDR = 3,
+ E_PWR_INVALID_WDAT = 4,
+ E_PWR_INVALID_OP_MANUAL = 5,
+ E_PWR_NOT_IDLE_STATE = 6,
+ E_PWR_NOT_INIT_DONE = 7,
+ E_PWR_NOT_INIT_DONE_READ = 8,
+ E_PWR_WAIT_IDLE_TIMEOUT = 9,
+ E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
+ E_PWR_INIT_SIDLY_FAIL = 11,
+ E_PWR_RESET_TIMEOUT = 12,
+ E_PWR_TIMEOUT = 13,
+ E_PWR_INIT_RESET_SPI = 20,
+ E_PWR_INIT_SIDLY = 21,
+ E_PWR_INIT_REG_CLOCK = 22,
+ E_PWR_INIT_ENABLE_PMIC = 23,
+ E_PWR_INIT_DIO = 24,
+ E_PWR_INIT_CIPHER = 25,
+ E_PWR_INIT_WRITE_TEST = 26,
+ E_PWR_INIT_ENABLE_CRC = 27,
+ E_PWR_INIT_ENABLE_DEWRAP = 28,
+ E_PWR_INIT_ENABLE_EVENT = 29,
+ E_PWR_READ_TEST_FAIL = 30,
+ E_PWR_WRITE_TEST_FAIL = 31,
+ E_PWR_SWITCH_DIO = 32
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8173/drivers/rtc/rtc.c b/plat/mediatek/mt8173/drivers/rtc/rtc.c
new file mode 100644
index 0000000..587886c
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/rtc/rtc.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+
+#include <mt8173_def.h>
+#include <rtc.h>
+
+void rtc_bbpu_power_down(void)
+{
+ uint16_t bbpu;
+
+ /* pull PWRBB low */
+ bbpu = RTC_BBPU_KEY | RTC_BBPU_AUTO | RTC_BBPU_PWREN;
+ if (Writeif_unlock()) {
+ RTC_Write(RTC_BBPU, bbpu);
+ if (!RTC_Write_Trigger())
+ assert(0);
+ } else {
+ assert(0);
+ }
+}
diff --git a/plat/mediatek/mt8173/drivers/rtc/rtc.h b/plat/mediatek/mt8173/drivers/rtc/rtc.h
new file mode 100644
index 0000000..f60a4c1
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/rtc/rtc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+/* RTC registers */
+enum {
+ RTC_BBPU = 0xE000,
+ RTC_IRQ_STA = 0xE002,
+ RTC_IRQ_EN = 0xE004,
+ RTC_CII_EN = 0xE006
+};
+
+enum {
+ RTC_OSC32CON = 0xE026,
+ RTC_CON = 0xE03E,
+ RTC_WRTGR = 0xE03C
+};
+
+enum {
+ RTC_PDN1 = 0xE02C,
+ RTC_PDN2 = 0xE02E,
+ RTC_SPAR0 = 0xE030,
+ RTC_SPAR1 = 0xE032,
+ RTC_PROT = 0xE036,
+ RTC_DIFF = 0xE038,
+ RTC_CALI = 0xE03A
+};
+
+enum {
+ RTC_PROT_UNLOCK1 = 0x586A,
+ RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+ RTC_BBPU_PWREN = 1U << 0,
+ RTC_BBPU_BBPU = 1U << 2,
+ RTC_BBPU_AUTO = 1U << 3,
+ RTC_BBPU_CLRPKY = 1U << 4,
+ RTC_BBPU_RELOAD = 1U << 5,
+ RTC_BBPU_CBUSY = 1U << 6
+};
+
+enum {
+ RTC_BBPU_KEY = 0x43 << 8
+};
+
+/* external API */
+uint16_t RTC_Read(uint32_t addr);
+void RTC_Write(uint32_t addr, uint16_t data);
+int32_t rtc_busy_wait(void);
+int32_t RTC_Write_Trigger(void);
+int32_t Writeif_unlock(void);
+void rtc_bbpu_power_down(void);
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/mt8173/drivers/spm/spm.c b/plat/mediatek/mt8173/drivers/spm/spm.c
new file mode 100644
index 0000000..1caab3b
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include <mt8173_def.h>
+#include <spm.h>
+#include <spm_suspend.h>
+
+/*
+ * System Power Manager (SPM) is a hardware module, which controls cpu or
+ * system power for different power scenarios using different firmware, i.e.,
+ * - spm_hotplug.c for cpu power control in cpu hotplug flow.
+ * - spm_mcdi.c for cpu power control in cpu idle power saving state.
+ * - spm_suspend.c for system power control in system suspend scenario.
+ *
+ * This file provide utility functions common to hotplug, mcdi(idle), suspend
+ * power scenarios. A bakery lock (software lock) is incoporated to protect
+ * certain critical sections to avoid kicking different SPM firmware
+ * concurrently.
+ */
+
+#define SPM_SYSCLK_SETTLE 128 /* 3.9ms */
+
+DEFINE_BAKERY_LOCK(spm_lock);
+
+static int spm_hotplug_ready __section("tzfw_coherent_mem");
+static int spm_mcdi_ready __section("tzfw_coherent_mem");
+static int spm_suspend_ready __section("tzfw_coherent_mem");
+
+void spm_lock_init(void)
+{
+ bakery_lock_init(&spm_lock);
+}
+
+void spm_lock_get(void)
+{
+ bakery_lock_get(&spm_lock);
+}
+
+void spm_lock_release(void)
+{
+ bakery_lock_release(&spm_lock);
+}
+
+int is_mcdi_ready(void)
+{
+ return spm_mcdi_ready;
+}
+
+int is_hotplug_ready(void)
+{
+ return spm_hotplug_ready;
+}
+
+int is_suspend_ready(void)
+{
+ return spm_suspend_ready;
+}
+
+void set_mcdi_ready(void)
+{
+ spm_mcdi_ready = 1;
+ spm_hotplug_ready = 0;
+ spm_suspend_ready = 0;
+}
+
+void set_hotplug_ready(void)
+{
+ spm_mcdi_ready = 0;
+ spm_hotplug_ready = 1;
+ spm_suspend_ready = 0;
+}
+
+void set_suspend_ready(void)
+{
+ spm_mcdi_ready = 0;
+ spm_hotplug_ready = 0;
+ spm_suspend_ready = 1;
+}
+
+void clear_all_ready(void)
+{
+ spm_mcdi_ready = 0;
+ spm_hotplug_ready = 0;
+ spm_suspend_ready = 0;
+}
+
+void spm_register_init(void)
+{
+ mmio_write_32(SPM_POWERON_CONFIG_SET, SPM_REGWR_CFG_KEY | SPM_REGWR_EN);
+
+ mmio_write_32(SPM_POWER_ON_VAL0, 0);
+ mmio_write_32(SPM_POWER_ON_VAL1, POWER_ON_VAL1_DEF);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+
+ mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET);
+ mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY);
+ if (mmio_read_32(SPM_PCM_FSM_STA) != PCM_FSM_STA_DEF)
+ WARN("PCM reset failed\n");
+
+ mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS);
+ mmio_write_32(SPM_PCM_CON1, CON1_CFG_KEY | CON1_EVENT_LOCK_EN |
+ CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B | CON1_MIF_APBEN);
+ mmio_write_32(SPM_PCM_IM_PTR, 0);
+ mmio_write_32(SPM_PCM_IM_LEN, 0);
+
+ mmio_write_32(SPM_CLK_CON, CC_SYSCLK0_EN_1 | CC_SYSCLK0_EN_0 |
+ CC_SYSCLK1_EN_0 | CC_SRCLKENA_MASK_0 | CC_CLKSQ1_SEL |
+ CC_CXO32K_RM_EN_MD2 | CC_CXO32K_RM_EN_MD1 | CC_MD32_DCM_EN);
+
+ mmio_write_32(SPM_SLEEP_ISR_MASK, 0xff0c);
+ mmio_write_32(SPM_SLEEP_ISR_STATUS, 0xc);
+ mmio_write_32(SPM_PCM_SW_INT_CLEAR, 0xff);
+ mmio_write_32(SPM_MD32_SRAM_CON, 0xff0);
+}
+
+void spm_reset_and_init_pcm(void)
+{
+ unsigned int con1;
+ int i = 0;
+
+ mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_PCM_SW_RESET);
+ mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY);
+ while (mmio_read_32(SPM_PCM_FSM_STA) != PCM_FSM_STA_DEF) {
+ i++;
+ if (i > 1000) {
+ i = 0;
+ WARN("PCM reset failed\n");
+ break;
+ }
+ }
+
+ mmio_write_32(SPM_PCM_CON0, CON0_CFG_KEY | CON0_IM_SLEEP_DVS);
+
+ con1 = mmio_read_32(SPM_PCM_CON1) &
+ (CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN);
+ mmio_write_32(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_EVENT_LOCK_EN |
+ CON1_SPM_SRAM_ISO_B | CON1_SPM_SRAM_SLP_B |
+ CON1_IM_NONRP_EN | CON1_MIF_APBEN);
+}
+
+void spm_init_pcm_register(void)
+{
+ mmio_write_32(SPM_PCM_REG_DATA_INI, mmio_read_32(SPM_POWER_ON_VAL0));
+ mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R0);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+
+ mmio_write_32(SPM_PCM_REG_DATA_INI, mmio_read_32(SPM_POWER_ON_VAL1));
+ mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R7);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+}
+
+void spm_set_power_control(const struct pwr_ctrl *pwrctrl)
+{
+ mmio_write_32(SPM_AP_STANBY_CON, (!pwrctrl->md32_req_mask << 21) |
+ (!pwrctrl->mfg_req_mask << 17) |
+ (!pwrctrl->disp_req_mask << 16) |
+ (!!pwrctrl->mcusys_idle_mask << 7) |
+ (!!pwrctrl->ca15top_idle_mask << 6) |
+ (!!pwrctrl->ca7top_idle_mask << 5) |
+ (!!pwrctrl->wfi_op << 4));
+ mmio_write_32(SPM_PCM_SRC_REQ, (!!pwrctrl->pcm_apsrc_req << 0));
+ mmio_write_32(SPM_PCM_PASR_DPD_2, 0);
+
+ mmio_clrsetbits_32(SPM_CLK_CON, CC_SRCLKENA_MASK_0,
+ (pwrctrl->srclkenai_mask ? CC_SRCLKENA_MASK_0 : 0));
+
+ mmio_write_32(SPM_SLEEP_CA15_WFI0_EN, !!pwrctrl->ca15_wfi0_en);
+ mmio_write_32(SPM_SLEEP_CA15_WFI1_EN, !!pwrctrl->ca15_wfi1_en);
+ mmio_write_32(SPM_SLEEP_CA15_WFI2_EN, !!pwrctrl->ca15_wfi2_en);
+ mmio_write_32(SPM_SLEEP_CA15_WFI3_EN, !!pwrctrl->ca15_wfi3_en);
+ mmio_write_32(SPM_SLEEP_CA7_WFI0_EN, !!pwrctrl->ca7_wfi0_en);
+ mmio_write_32(SPM_SLEEP_CA7_WFI1_EN, !!pwrctrl->ca7_wfi1_en);
+ mmio_write_32(SPM_SLEEP_CA7_WFI2_EN, !!pwrctrl->ca7_wfi2_en);
+ mmio_write_32(SPM_SLEEP_CA7_WFI3_EN, !!pwrctrl->ca7_wfi3_en);
+}
+
+void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
+{
+ unsigned int val, mask;
+
+ if (pwrctrl->timer_val_cust == 0)
+ val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX;
+ else
+ val = pwrctrl->timer_val_cust;
+
+ mmio_write_32(SPM_PCM_TIMER_VAL, val);
+ mmio_setbits_32(SPM_PCM_CON1, CON1_CFG_KEY);
+
+ if (pwrctrl->wake_src_cust == 0)
+ mask = pwrctrl->wake_src;
+ else
+ mask = pwrctrl->wake_src_cust;
+
+ if (pwrctrl->syspwreq_mask)
+ mask &= ~WAKE_SRC_SYSPWREQ;
+
+ mmio_write_32(SPM_SLEEP_WAKEUP_EVENT_MASK, ~mask);
+ mmio_write_32(SPM_SLEEP_ISR_MASK, 0xfe04);
+}
+
+void spm_get_wakeup_status(struct wake_status *wakesta)
+{
+ wakesta->assert_pc = mmio_read_32(SPM_PCM_REG_DATA_INI);
+ wakesta->r12 = mmio_read_32(SPM_PCM_REG12_DATA);
+ wakesta->raw_sta = mmio_read_32(SPM_SLEEP_ISR_RAW_STA);
+ wakesta->wake_misc = mmio_read_32(SPM_SLEEP_WAKEUP_MISC);
+ wakesta->timer_out = mmio_read_32(SPM_PCM_TIMER_OUT);
+ wakesta->r13 = mmio_read_32(SPM_PCM_REG13_DATA);
+ wakesta->idle_sta = mmio_read_32(SPM_SLEEP_SUBSYS_IDLE_STA);
+ wakesta->debug_flag = mmio_read_32(SPM_PCM_PASR_DPD_3);
+ wakesta->event_reg = mmio_read_32(SPM_PCM_EVENT_REG_STA);
+ wakesta->isr = mmio_read_32(SPM_SLEEP_ISR_STATUS);
+}
+
+void spm_init_event_vector(const struct pcm_desc *pcmdesc)
+{
+ /* init event vector register */
+ mmio_write_32(SPM_PCM_EVENT_VECTOR0, pcmdesc->vec0);
+ mmio_write_32(SPM_PCM_EVENT_VECTOR1, pcmdesc->vec1);
+ mmio_write_32(SPM_PCM_EVENT_VECTOR2, pcmdesc->vec2);
+ mmio_write_32(SPM_PCM_EVENT_VECTOR3, pcmdesc->vec3);
+ mmio_write_32(SPM_PCM_EVENT_VECTOR4, pcmdesc->vec4);
+ mmio_write_32(SPM_PCM_EVENT_VECTOR5, pcmdesc->vec5);
+ mmio_write_32(SPM_PCM_EVENT_VECTOR6, pcmdesc->vec6);
+ mmio_write_32(SPM_PCM_EVENT_VECTOR7, pcmdesc->vec7);
+
+ /* event vector will be enabled by PCM itself */
+}
+
+void spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc)
+{
+ unsigned int ptr = 0, len, con0;
+
+ ptr = (unsigned int)(unsigned long)(pcmdesc->base);
+ len = pcmdesc->size - 1;
+ if (mmio_read_32(SPM_PCM_IM_PTR) != ptr ||
+ mmio_read_32(SPM_PCM_IM_LEN) != len ||
+ pcmdesc->sess > 2) {
+ mmio_write_32(SPM_PCM_IM_PTR, ptr);
+ mmio_write_32(SPM_PCM_IM_LEN, len);
+ } else {
+ mmio_setbits_32(SPM_PCM_CON1, CON1_CFG_KEY | CON1_IM_SLAVE);
+ }
+
+ /* kick IM to fetch (only toggle IM_KICK) */
+ con0 = mmio_read_32(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK);
+ mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_IM_KICK);
+ mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY);
+
+ /* kick IM to fetch (only toggle PCM_KICK) */
+ con0 = mmio_read_32(SPM_PCM_CON0) & ~(CON0_IM_KICK | CON0_PCM_KICK);
+ mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY | CON0_PCM_KICK);
+ mmio_write_32(SPM_PCM_CON0, con0 | CON0_CFG_KEY);
+}
+
+void spm_set_sysclk_settle(void)
+{
+ mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE);
+
+ INFO("settle = %u\n", mmio_read_32(SPM_CLK_SETTLE));
+}
+
+void spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl)
+{
+ unsigned int con1;
+
+ con1 = mmio_read_32(SPM_PCM_CON1) &
+ ~(CON1_PCM_WDT_WAKE_MODE | CON1_PCM_WDT_EN);
+
+ mmio_write_32(SPM_PCM_CON1, CON1_CFG_KEY | con1);
+
+ if (mmio_read_32(SPM_PCM_TIMER_VAL) > PCM_TIMER_MAX)
+ mmio_write_32(SPM_PCM_TIMER_VAL, PCM_TIMER_MAX);
+
+ mmio_write_32(SPM_PCM_WDT_TIMER_VAL,
+ mmio_read_32(SPM_PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
+
+ mmio_write_32(SPM_PCM_CON1, con1 | CON1_CFG_KEY | CON1_PCM_WDT_EN);
+ mmio_write_32(SPM_PCM_PASR_DPD_0, 0);
+
+ mmio_write_32(SPM_PCM_MAS_PAUSE_MASK, 0xffffffff);
+ mmio_write_32(SPM_PCM_REG_DATA_INI, 0);
+ mmio_clrbits_32(SPM_CLK_CON, CC_DISABLE_DORM_PWR);
+
+ mmio_write_32(SPM_PCM_FLAGS, pwrctrl->pcm_flags);
+
+ mmio_clrsetbits_32(SPM_CLK_CON, CC_LOCK_INFRA_DCM,
+ (pwrctrl->infra_dcm_lock ? CC_LOCK_INFRA_DCM : 0));
+
+ mmio_write_32(SPM_PCM_PWR_IO_EN,
+ (pwrctrl->r0_ctrl_en ? PCM_PWRIO_EN_R0 : 0) |
+ (pwrctrl->r7_ctrl_en ? PCM_PWRIO_EN_R7 : 0));
+}
+
+void spm_clean_after_wakeup(void)
+{
+ mmio_clrsetbits_32(SPM_PCM_CON1, CON1_PCM_WDT_EN, CON1_CFG_KEY);
+
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+ mmio_write_32(SPM_SLEEP_CPU_WAKEUP_EVENT, 0);
+ mmio_clrsetbits_32(SPM_PCM_CON1, CON1_PCM_TIMER_EN, CON1_CFG_KEY);
+
+ mmio_write_32(SPM_SLEEP_WAKEUP_EVENT_MASK, ~0);
+ mmio_write_32(SPM_SLEEP_ISR_MASK, 0xFF0C);
+ mmio_write_32(SPM_SLEEP_ISR_STATUS, 0xC);
+ mmio_write_32(SPM_PCM_SW_INT_CLEAR, 0xFF);
+}
+
+enum wake_reason_t spm_output_wake_reason(struct wake_status *wakesta)
+{
+ enum wake_reason_t wr;
+ int i;
+
+ wr = WR_UNKNOWN;
+
+ if (wakesta->assert_pc != 0) {
+ ERROR("PCM ASSERT AT %u, r12=0x%x, r13=0x%x, debug_flag=0x%x\n",
+ wakesta->assert_pc, wakesta->r12, wakesta->r13,
+ wakesta->debug_flag);
+ return WR_PCM_ASSERT;
+ }
+
+ if (wakesta->r12 & WAKE_SRC_SPM_MERGE) {
+ if (wakesta->wake_misc & WAKE_MISC_PCM_TIMER)
+ wr = WR_PCM_TIMER;
+ if (wakesta->wake_misc & WAKE_MISC_CPU_WAKE)
+ wr = WR_WAKE_SRC;
+ }
+
+ for (i = 1; i < 32; i++) {
+ if (wakesta->r12 & (1U << i))
+ wr = WR_WAKE_SRC;
+ }
+
+ if ((wakesta->event_reg & 0x100000) == 0) {
+ INFO("pcm sleep abort!\n");
+ wr = WR_PCM_ABORT;
+ }
+
+ INFO("timer_out = %u, r12 = 0x%x, r13 = 0x%x, debug_flag = 0x%x\n",
+ wakesta->timer_out, wakesta->r12, wakesta->r13,
+ wakesta->debug_flag);
+
+ INFO("raw_sta = 0x%x, idle_sta = 0x%x, event_reg = 0x%x, isr = 0x%x\n",
+ wakesta->raw_sta, wakesta->idle_sta, wakesta->event_reg,
+ wakesta->isr);
+
+ return wr;
+}
+
+void spm_boot_init(void)
+{
+ /* set spm transaction to secure mode */
+ mmio_write_32(DEVAPC0_APC_CON, 0x0);
+ mmio_write_32(DEVAPC0_MAS_SEC_0, 0x200);
+
+ /* Only CPU0 is online during boot, initialize cpu online reserve bit */
+ mmio_write_32(SPM_PCM_RESERVE, 0xFE);
+ mmio_clrbits_32(AP_PLL_CON3, 0xFFFFF);
+ mmio_clrbits_32(AP_PLL_CON4, 0xF);
+ spm_lock_init();
+ spm_register_init();
+}
diff --git a/plat/mediatek/mt8173/drivers/spm/spm.h b/plat/mediatek/mt8173/drivers/spm/spm.h
new file mode 100644
index 0000000..0c05410
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef SPM_H
+#define SPM_H
+
+#define SPM_POWERON_CONFIG_SET (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x010)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x014)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x100)
+#define SPM_CA7_CPU1_PWR_CON (SPM_BASE + 0x218)
+#define SPM_CA7_CPU2_PWR_CON (SPM_BASE + 0x21c)
+#define SPM_CA7_CPU3_PWR_CON (SPM_BASE + 0x220)
+#define SPM_CA7_CPU1_L1_PDN (SPM_BASE + 0x264)
+#define SPM_CA7_CPU2_L1_PDN (SPM_BASE + 0x26c)
+#define SPM_CA7_CPU3_L1_PDN (SPM_BASE + 0x274)
+#define SPM_MD32_SRAM_CON (SPM_BASE + 0x2c8)
+#define SPM_PCM_CON0 (SPM_BASE + 0x310)
+#define SPM_PCM_CON1 (SPM_BASE + 0x314)
+#define SPM_PCM_IM_PTR (SPM_BASE + 0x318)
+#define SPM_PCM_IM_LEN (SPM_BASE + 0x31c)
+#define SPM_PCM_REG_DATA_INI (SPM_BASE + 0x320)
+#define SPM_PCM_EVENT_VECTOR0 (SPM_BASE + 0x340)
+#define SPM_PCM_EVENT_VECTOR1 (SPM_BASE + 0x344)
+#define SPM_PCM_EVENT_VECTOR2 (SPM_BASE + 0x348)
+#define SPM_PCM_EVENT_VECTOR3 (SPM_BASE + 0x34c)
+#define SPM_PCM_MAS_PAUSE_MASK (SPM_BASE + 0x354)
+#define SPM_PCM_PWR_IO_EN (SPM_BASE + 0x358)
+#define SPM_PCM_TIMER_VAL (SPM_BASE + 0x35c)
+#define SPM_PCM_TIMER_OUT (SPM_BASE + 0x360)
+#define SPM_PCM_REG0_DATA (SPM_BASE + 0x380)
+#define SPM_PCM_REG1_DATA (SPM_BASE + 0x384)
+#define SPM_PCM_REG2_DATA (SPM_BASE + 0x388)
+#define SPM_PCM_REG3_DATA (SPM_BASE + 0x38c)
+#define SPM_PCM_REG4_DATA (SPM_BASE + 0x390)
+#define SPM_PCM_REG5_DATA (SPM_BASE + 0x394)
+#define SPM_PCM_REG6_DATA (SPM_BASE + 0x398)
+#define SPM_PCM_REG7_DATA (SPM_BASE + 0x39c)
+#define SPM_PCM_REG8_DATA (SPM_BASE + 0x3a0)
+#define SPM_PCM_REG9_DATA (SPM_BASE + 0x3a4)
+#define SPM_PCM_REG10_DATA (SPM_BASE + 0x3a8)
+#define SPM_PCM_REG11_DATA (SPM_BASE + 0x3ac)
+#define SPM_PCM_REG12_DATA (SPM_BASE + 0x3b0)
+#define SPM_PCM_REG13_DATA (SPM_BASE + 0x3b4)
+#define SPM_PCM_REG14_DATA (SPM_BASE + 0x3b8)
+#define SPM_PCM_REG15_DATA (SPM_BASE + 0x3bc)
+#define SPM_PCM_EVENT_REG_STA (SPM_BASE + 0x3c0)
+#define SPM_PCM_FSM_STA (SPM_BASE + 0x3c4)
+#define SPM_PCM_IM_HOST_RW_PTR (SPM_BASE + 0x3c8)
+#define SPM_PCM_IM_HOST_RW_DAT (SPM_BASE + 0x3cc)
+#define SPM_PCM_EVENT_VECTOR4 (SPM_BASE + 0x3d0)
+#define SPM_PCM_EVENT_VECTOR5 (SPM_BASE + 0x3d4)
+#define SPM_PCM_EVENT_VECTOR6 (SPM_BASE + 0x3d8)
+#define SPM_PCM_EVENT_VECTOR7 (SPM_BASE + 0x3dc)
+#define SPM_PCM_SW_INT_SET (SPM_BASE + 0x3e0)
+#define SPM_PCM_SW_INT_CLEAR (SPM_BASE + 0x3e4)
+#define SPM_CLK_CON (SPM_BASE + 0x400)
+#define SPM_SLEEP_PTPOD2_CON (SPM_BASE + 0x408)
+#define SPM_APMCU_PWRCTL (SPM_BASE + 0x600)
+#define SPM_AP_DVFS_CON_SET (SPM_BASE + 0x604)
+#define SPM_AP_STANBY_CON (SPM_BASE + 0x608)
+#define SPM_PWR_STATUS (SPM_BASE + 0x60c)
+#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x610)
+#define SPM_AP_BSI_REQ (SPM_BASE + 0x614)
+#define SPM_SLEEP_TIMER_STA (SPM_BASE + 0x720)
+#define SPM_SLEEP_WAKEUP_EVENT_MASK (SPM_BASE + 0x810)
+#define SPM_SLEEP_CPU_WAKEUP_EVENT (SPM_BASE + 0x814)
+#define SPM_SLEEP_MD32_WAKEUP_EVENT_MASK (SPM_BASE + 0x818)
+#define SPM_PCM_WDT_TIMER_VAL (SPM_BASE + 0x824)
+#define SPM_PCM_WDT_TIMER_OUT (SPM_BASE + 0x828)
+#define SPM_PCM_MD32_MAILBOX (SPM_BASE + 0x830)
+#define SPM_PCM_MD32_IRQ (SPM_BASE + 0x834)
+#define SPM_SLEEP_ISR_MASK (SPM_BASE + 0x900)
+#define SPM_SLEEP_ISR_STATUS (SPM_BASE + 0x904)
+#define SPM_SLEEP_ISR_RAW_STA (SPM_BASE + 0x910)
+#define SPM_SLEEP_MD32_ISR_RAW_STA (SPM_BASE + 0x914)
+#define SPM_SLEEP_WAKEUP_MISC (SPM_BASE + 0x918)
+#define SPM_SLEEP_BUS_PROTECT_RDY (SPM_BASE + 0x91c)
+#define SPM_SLEEP_SUBSYS_IDLE_STA (SPM_BASE + 0x920)
+#define SPM_PCM_RESERVE (SPM_BASE + 0xb00)
+#define SPM_PCM_RESERVE2 (SPM_BASE + 0xb04)
+#define SPM_PCM_FLAGS (SPM_BASE + 0xb08)
+#define SPM_PCM_SRC_REQ (SPM_BASE + 0xb0c)
+#define SPM_PCM_DEBUG_CON (SPM_BASE + 0xb20)
+#define SPM_CA7_CPU0_IRQ_MASK (SPM_BASE + 0xb30)
+#define SPM_CA7_CPU1_IRQ_MASK (SPM_BASE + 0xb34)
+#define SPM_CA7_CPU2_IRQ_MASK (SPM_BASE + 0xb38)
+#define SPM_CA7_CPU3_IRQ_MASK (SPM_BASE + 0xb3c)
+#define SPM_CA15_CPU0_IRQ_MASK (SPM_BASE + 0xb40)
+#define SPM_CA15_CPU1_IRQ_MASK (SPM_BASE + 0xb44)
+#define SPM_CA15_CPU2_IRQ_MASK (SPM_BASE + 0xb48)
+#define SPM_CA15_CPU3_IRQ_MASK (SPM_BASE + 0xb4c)
+#define SPM_PCM_PASR_DPD_0 (SPM_BASE + 0xb60)
+#define SPM_PCM_PASR_DPD_1 (SPM_BASE + 0xb64)
+#define SPM_PCM_PASR_DPD_2 (SPM_BASE + 0xb68)
+#define SPM_PCM_PASR_DPD_3 (SPM_BASE + 0xb6c)
+#define SPM_SLEEP_CA7_WFI0_EN (SPM_BASE + 0xf00)
+#define SPM_SLEEP_CA7_WFI1_EN (SPM_BASE + 0xf04)
+#define SPM_SLEEP_CA7_WFI2_EN (SPM_BASE + 0xf08)
+#define SPM_SLEEP_CA7_WFI3_EN (SPM_BASE + 0xf0c)
+#define SPM_SLEEP_CA15_WFI0_EN (SPM_BASE + 0xf10)
+#define SPM_SLEEP_CA15_WFI1_EN (SPM_BASE + 0xf14)
+#define SPM_SLEEP_CA15_WFI2_EN (SPM_BASE + 0xf18)
+#define SPM_SLEEP_CA15_WFI3_EN (SPM_BASE + 0xf1c)
+
+#define AP_PLL_CON3 0x1020900c
+#define AP_PLL_CON4 0x10209010
+
+#define SPM_PROJECT_CODE 0xb16
+
+#define SPM_REGWR_EN (1U << 0)
+#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#define SPM_CPU_PDN_DIS (1U << 0)
+#define SPM_INFRA_PDN_DIS (1U << 1)
+#define SPM_DDRPHY_PDN_DIS (1U << 2)
+#define SPM_DUALVCORE_PDN_DIS (1U << 3)
+#define SPM_PASR_DIS (1U << 4)
+#define SPM_DPD_DIS (1U << 5)
+#define SPM_SODI_DIS (1U << 6)
+#define SPM_MEMPLL_RESET (1U << 7)
+#define SPM_MAINPLL_PDN_DIS (1U << 8)
+#define SPM_CPU_DVS_DIS (1U << 9)
+#define SPM_CPU_DORMANT (1U << 10)
+#define SPM_EXT_VSEL_GPIO103 (1U << 11)
+#define SPM_DDR_HIGH_SPEED (1U << 12)
+#define SPM_OPT (1U << 13)
+
+#define POWER_ON_VAL1_DEF 0x01011820
+#define PCM_FSM_STA_DEF 0x48490
+#define PCM_END_FSM_STA_DEF 0x08490
+#define PCM_END_FSM_STA_MASK 0x3fff0
+#define PCM_HANDSHAKE_SEND1 0xbeefbeef
+
+#define PCM_WDT_TIMEOUT (30 * 32768)
+#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT)
+
+#define CON0_PCM_KICK (1U << 0)
+#define CON0_IM_KICK (1U << 1)
+#define CON0_IM_SLEEP_DVS (1U << 3)
+#define CON0_PCM_SW_RESET (1U << 15)
+#define CON0_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#define CON1_IM_SLAVE (1U << 0)
+#define CON1_MIF_APBEN (1U << 3)
+#define CON1_PCM_TIMER_EN (1U << 5)
+#define CON1_IM_NONRP_EN (1U << 6)
+#define CON1_PCM_WDT_EN (1U << 8)
+#define CON1_PCM_WDT_WAKE_MODE (1U << 9)
+#define CON1_SPM_SRAM_SLP_B (1U << 10)
+#define CON1_SPM_SRAM_ISO_B (1U << 11)
+#define CON1_EVENT_LOCK_EN (1U << 12)
+#define CON1_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#define PCM_PWRIO_EN_R0 (1U << 0)
+#define PCM_PWRIO_EN_R7 (1U << 7)
+#define PCM_RF_SYNC_R0 (1U << 16)
+#define PCM_RF_SYNC_R2 (1U << 18)
+#define PCM_RF_SYNC_R6 (1U << 22)
+#define PCM_RF_SYNC_R7 (1U << 23)
+
+#define CC_SYSCLK0_EN_0 (1U << 0)
+#define CC_SYSCLK0_EN_1 (1U << 1)
+#define CC_SYSCLK1_EN_0 (1U << 2)
+#define CC_SYSCLK1_EN_1 (1U << 3)
+#define CC_SYSSETTLE_SEL (1U << 4)
+#define CC_LOCK_INFRA_DCM (1U << 5)
+#define CC_SRCLKENA_MASK_0 (1U << 6)
+#define CC_CXO32K_RM_EN_MD1 (1U << 9)
+#define CC_CXO32K_RM_EN_MD2 (1U << 10)
+#define CC_CLKSQ1_SEL (1U << 12)
+#define CC_DISABLE_DORM_PWR (1U << 14)
+#define CC_MD32_DCM_EN (1U << 18)
+
+#define WFI_OP_AND 1
+#define WFI_OP_OR 0
+
+#define WAKE_MISC_PCM_TIMER (1U << 19)
+#define WAKE_MISC_CPU_WAKE (1U << 20)
+
+/* define WAKE_SRC_XXX */
+#define WAKE_SRC_SPM_MERGE (1 << 0)
+#define WAKE_SRC_KP (1 << 2)
+#define WAKE_SRC_WDT (1 << 3)
+#define WAKE_SRC_GPT (1 << 4)
+#define WAKE_SRC_EINT (1 << 6)
+#define WAKE_SRC_LOW_BAT (1 << 9)
+#define WAKE_SRC_MD32 (1 << 10)
+#define WAKE_SRC_USB_CD (1 << 14)
+#define WAKE_SRC_USB_PDN (1 << 15)
+#define WAKE_SRC_AFE (1 << 20)
+#define WAKE_SRC_THERM (1 << 21)
+#define WAKE_SRC_CIRQ (1 << 22)
+#define WAKE_SRC_SYSPWREQ (1 << 24)
+#define WAKE_SRC_SEJ (1 << 27)
+#define WAKE_SRC_ALL_MD32 (1 << 28)
+#define WAKE_SRC_CPU_IRQ (1 << 29)
+
+enum wake_reason_t {
+ WR_NONE = 0,
+ WR_UART_BUSY = 1,
+ WR_PCM_ASSERT = 2,
+ WR_PCM_TIMER = 3,
+ WR_PCM_ABORT = 4,
+ WR_WAKE_SRC = 5,
+ WR_UNKNOWN = 6,
+};
+
+struct pwr_ctrl {
+ unsigned int pcm_flags;
+ unsigned int pcm_flags_cust;
+ unsigned int pcm_reserve;
+ unsigned int timer_val;
+ unsigned int timer_val_cust;
+ unsigned int wake_src;
+ unsigned int wake_src_cust;
+ unsigned int wake_src_md32;
+ unsigned short r0_ctrl_en;
+ unsigned short r7_ctrl_en;
+ unsigned short infra_dcm_lock;
+ unsigned short pcm_apsrc_req;
+ unsigned short mcusys_idle_mask;
+ unsigned short ca15top_idle_mask;
+ unsigned short ca7top_idle_mask;
+ unsigned short wfi_op;
+ unsigned short ca15_wfi0_en;
+ unsigned short ca15_wfi1_en;
+ unsigned short ca15_wfi2_en;
+ unsigned short ca15_wfi3_en;
+ unsigned short ca7_wfi0_en;
+ unsigned short ca7_wfi1_en;
+ unsigned short ca7_wfi2_en;
+ unsigned short ca7_wfi3_en;
+ unsigned short disp_req_mask;
+ unsigned short mfg_req_mask;
+ unsigned short md32_req_mask;
+ unsigned short syspwreq_mask;
+ unsigned short srclkenai_mask;
+};
+
+struct wake_status {
+ unsigned int assert_pc;
+ unsigned int r12;
+ unsigned int raw_sta;
+ unsigned int wake_misc;
+ unsigned int timer_out;
+ unsigned int r13;
+ unsigned int idle_sta;
+ unsigned int debug_flag;
+ unsigned int event_reg;
+ unsigned int isr;
+};
+
+struct pcm_desc {
+ const char *version; /* PCM code version */
+ const unsigned int *base; /* binary array base */
+ const unsigned int size; /* binary array size */
+ const unsigned char sess; /* session number */
+ const unsigned char replace; /* replace mode */
+
+ unsigned int vec0; /* event vector 0 config */
+ unsigned int vec1; /* event vector 1 config */
+ unsigned int vec2; /* event vector 2 config */
+ unsigned int vec3; /* event vector 3 config */
+ unsigned int vec4; /* event vector 4 config */
+ unsigned int vec5; /* event vector 5 config */
+ unsigned int vec6; /* event vector 6 config */
+ unsigned int vec7; /* event vector 7 config */
+};
+
+struct spm_lp_scen {
+ const struct pcm_desc *pcmdesc;
+ struct pwr_ctrl *pwrctrl;
+};
+
+#define EVENT_VEC(event, resume, imme, pc) \
+ (((pc) << 16) | \
+ (!!(imme) << 6) | \
+ (!!(resume) << 5) | \
+ ((event) & 0x1f))
+
+#define spm_read(addr) mmio_read_32(addr)
+#define spm_write(addr, val) mmio_write_32(addr, val)
+
+#define is_cpu_pdn(flags) (!((flags) & SPM_CPU_PDN_DIS))
+#define is_infra_pdn(flags) (!((flags) & SPM_INFRA_PDN_DIS))
+#define is_ddrphy_pdn(flags) (!((flags) & SPM_DDRPHY_PDN_DIS))
+
+static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl,
+ unsigned int flags)
+{
+ flags &= ~SPM_EXT_VSEL_GPIO103;
+
+ if (pwrctrl->pcm_flags_cust == 0)
+ pwrctrl->pcm_flags = flags;
+ else
+ pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust;
+}
+
+static inline void set_pwrctrl_pcm_data(struct pwr_ctrl *pwrctrl,
+ unsigned int data)
+{
+ pwrctrl->pcm_reserve = data;
+}
+
+void spm_reset_and_init_pcm(void);
+
+void spm_init_pcm_register(void); /* init r0 and r7 */
+void spm_set_power_control(const struct pwr_ctrl *pwrctrl);
+void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl);
+
+void spm_get_wakeup_status(struct wake_status *wakesta);
+void spm_set_sysclk_settle(void);
+void spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl);
+void spm_clean_after_wakeup(void);
+enum wake_reason_t spm_output_wake_reason(struct wake_status *wakesta);
+void spm_register_init(void);
+void spm_go_to_hotplug(void);
+void spm_init_event_vector(const struct pcm_desc *pcmdesc);
+void spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc);
+int is_mcdi_ready(void);
+int is_hotplug_ready(void);
+int is_suspend_ready(void);
+void set_mcdi_ready(void);
+void set_hotplug_ready(void);
+void set_suspend_ready(void);
+void clear_all_ready(void);
+void spm_lock_init(void);
+void spm_lock_get(void);
+void spm_lock_release(void);
+void spm_boot_init(void);
+
+#endif /* SPM_H */
diff --git a/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c b/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c
new file mode 100644
index 0000000..b2b9ada
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <lib/mmio.h>
+#include <mt8173_def.h>
+#include <plat/common/platform.h>
+
+#include <spm.h>
+#include <spm_hotplug.h>
+#include <spm_mcdi.h>
+
+/*
+ * System Power Manager (SPM) is a hardware module, which controls cpu or
+ * system power for different power scenarios using different firmware.
+ * This driver controls the cpu power in cpu hotplug flow.
+ */
+
+#define PCM_HOTPLUG_VALID_MASK 0x0000ff00
+#define PCM_HOTPLUG_VALID_SHIFT 0x8
+
+/**********************************************************
+ * PCM sequence for CPU hotplug
+ **********************************************************/
+static const unsigned int hotplug_binary[] = {
+ 0x1900001f, 0x1020020c, 0x1950001f, 0x1020020c, 0xa9400005, 0x00000001,
+ 0xe1000005, 0x1910001f, 0x10006720, 0x814c9001, 0xd82000e5, 0x17c07c1f,
+ 0x1900001f, 0x10001220, 0x1950001f, 0x10001220, 0xa15f0405, 0xe1000005,
+ 0x1900001f, 0x10001228, 0x1950001f, 0x10001228, 0x810f1401, 0xd8200244,
+ 0x17c07c1f, 0xe2e0006d, 0xe2e0002d, 0x1a00001f, 0x100062b8, 0x1910001f,
+ 0x100062b8, 0xa9000004, 0x00000001, 0xe2000004, 0x1910001f, 0x100062b8,
+ 0x81142804, 0xd8200444, 0x17c07c1f, 0xe2e0002c, 0xe2e0003c, 0xe2e0003e,
+ 0xe2e0003a, 0xe2e00032, 0x1910001f, 0x1000660c, 0x81079001, 0x1950001f,
+ 0x10006610, 0x81479401, 0xa1001404, 0xd8000584, 0x17c07c1f, 0x1900001f,
+ 0x10006404, 0x1950001f, 0x10006404, 0xa1568405, 0xe1000005, 0xf0000000,
+ 0x17c07c1f, 0x1900001f, 0x10006404, 0x1950001f, 0x10006404, 0x89400005,
+ 0x0000dfff, 0xe1000005, 0xe2e00036, 0xe2e0003e, 0x1910001f, 0x1000660c,
+ 0x81079001, 0x1950001f, 0x10006610, 0x81479401, 0x81001404, 0xd82008c4,
+ 0x17c07c1f, 0xe2e0002e, 0x1a00001f, 0x100062b8, 0x1910001f, 0x100062b8,
+ 0x89000004, 0x0000fffe, 0xe2000004, 0x1910001f, 0x100062b8, 0x81142804,
+ 0xd8000ae4, 0x17c07c1f, 0xe2e0006e, 0xe2e0004e, 0xe2e0004c, 0xe2e0004d,
+ 0x1900001f, 0x10001220, 0x1950001f, 0x10001220, 0x89400005, 0xbfffffff,
+ 0xe1000005, 0x1900001f, 0x10001228, 0x1950001f, 0x10001228, 0x810f1401,
+ 0xd8000ce4, 0x17c07c1f, 0x1900001f, 0x1020020c, 0x1950001f, 0x1020020c,
+ 0x89400005, 0xfffffffe, 0xe1000005, 0xf0000000, 0x17c07c1f, 0x1212841f,
+ 0xe2e00036, 0xe2e0003e, 0x1380201f, 0xe2e0003c, 0xe2a00000, 0x1b80001f,
+ 0x20000080, 0xe2e0007c, 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c,
+ 0xe2e0004d, 0xf0000000, 0x17c07c1f, 0xe2e0004f, 0xe2e0006f, 0xe2e0002f,
+ 0xe2a00001, 0x1b80001f, 0x20000080, 0xe2e0002e, 0xe2e0003e, 0xe2e00032,
+ 0xf0000000, 0x17c07c1f, 0x1212841f, 0xe2e00026, 0xe2e0002e, 0x1380201f,
+ 0x1a00001f, 0x100062b4, 0x1910001f, 0x100062b4, 0x81322804, 0xe2000004,
+ 0x81202804, 0xe2000004, 0x1b80001f, 0x20000034, 0x1910001f, 0x100062b4,
+ 0x81142804, 0xd8001404, 0x17c07c1f, 0xe2e0000e, 0xe2e0000c, 0xe2e0000d,
+ 0xf0000000, 0x17c07c1f, 0xe2e0002d, 0x1a00001f, 0x100062b4, 0x1910001f,
+ 0x100062b4, 0xa1002804, 0xe2000004, 0xa1122804, 0xe2000004, 0x1b80001f,
+ 0x20000080, 0x1910001f, 0x100062b4, 0x81142804, 0xd82016a4, 0x17c07c1f,
+ 0xe2e0002f, 0xe2e0002b, 0xe2e00023, 0x1380201f, 0xe2e00022, 0xf0000000,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x1840001f, 0x00000001, 0x1840001f, 0x00000001,
+ 0x1840001f, 0x00000001, 0xa1d48407, 0x1b00001f, 0x2f7be75f, 0xe8208000,
+ 0x10006354, 0xfffe7b47, 0xa1d10407, 0x1b80001f, 0x20000020, 0x17c07c1f,
+ 0x1910001f, 0x10006b00, 0x81461001, 0xb14690a1, 0xd82044e5, 0x17c07c1f,
+ 0x1910001f, 0x10006610, 0x81079001, 0xd80044e4, 0x17c07c1f, 0x1990001f,
+ 0x10006b00, 0x81421801, 0x82429801, 0x81402405, 0xd80044e5, 0x17c07c1f,
+ 0x1a40001f, 0x100062b0, 0x1280041f, 0xc24007a0, 0x17c07c1f, 0x1910001f,
+ 0x10006b00, 0x81449001, 0xd8204be5, 0x17c07c1f, 0x1910001f, 0x10006b00,
+ 0x81009001, 0xd8204984, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81051001,
+ 0xd8204be4, 0x17c07c1f, 0x1910001f, 0x10006720, 0x81489001, 0xd82046c5,
+ 0x17c07c1f, 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264, 0xc24010e0,
+ 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81051001, 0x1950001f, 0x10006610,
+ 0x81451401, 0xa1001404, 0xd8004824, 0x17c07c1f, 0xd0004b00, 0x17c07c1f,
+ 0x17c07c1f, 0x1910001f, 0x10006610, 0x81051001, 0xd8004be4, 0x17c07c1f,
+ 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264, 0xc2400ee0, 0x17c07c1f,
+ 0x1910001f, 0x10006b00, 0x89000004, 0xfffffdff, 0x1940001f, 0x10006b00,
+ 0xe1400004, 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81451001, 0xd8205305,
+ 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81011001, 0xd82050a4, 0x17c07c1f,
+ 0x1910001f, 0x10006610, 0x81059001, 0xd8205304, 0x17c07c1f, 0x1910001f,
+ 0x10006720, 0x81491001, 0xd8204de5, 0x17c07c1f, 0x1a40001f, 0x1000621c,
+ 0x1a80001f, 0x1000626c, 0xc24010e0, 0x17c07c1f, 0x1910001f, 0x1000660c,
+ 0x81059001, 0x1950001f, 0x10006610, 0x81459401, 0xa1001404, 0xd8004f44,
+ 0x17c07c1f, 0xd0005220, 0x17c07c1f, 0x17c07c1f, 0x1910001f, 0x10006610,
+ 0x81059001, 0xd8005304, 0x17c07c1f, 0x1a40001f, 0x1000621c, 0x1a80001f,
+ 0x1000626c, 0xc2400ee0, 0x17c07c1f, 0x1910001f, 0x10006b00, 0x89000004,
+ 0xfffffbff, 0x1940001f, 0x10006b00, 0xe1400004, 0x17c07c1f, 0x1910001f,
+ 0x10006b00, 0x81459001, 0xd8205a25, 0x17c07c1f, 0x1910001f, 0x10006b00,
+ 0x81019001, 0xd82057c4, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81061001,
+ 0xd8205a24, 0x17c07c1f, 0x1910001f, 0x10006720, 0x81499001, 0xd8205505,
+ 0x17c07c1f, 0x1a40001f, 0x10006220, 0x1a80001f, 0x10006274, 0xc24010e0,
+ 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81061001, 0x1950001f, 0x10006610,
+ 0x81461401, 0xa1001404, 0xd8005664, 0x17c07c1f, 0xd0005940, 0x17c07c1f,
+ 0x17c07c1f, 0x1910001f, 0x10006610, 0x81061001, 0xd8005a24, 0x17c07c1f,
+ 0x1a40001f, 0x10006220, 0x1a80001f, 0x10006274, 0xc2400ee0, 0x17c07c1f,
+ 0x1910001f, 0x10006b00, 0x89000004, 0xfffff7ff, 0x1940001f, 0x10006b00,
+ 0xe1400004, 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81461001, 0xd8206185,
+ 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81021001, 0xd8205ec4, 0x17c07c1f,
+ 0x1910001f, 0x10006610, 0x81081001, 0xd8206184, 0x17c07c1f, 0x1910001f,
+ 0x10006720, 0x814a1001, 0xd8205c25, 0x17c07c1f, 0x1a40001f, 0x100062a0,
+ 0x1280041f, 0xc2401540, 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81081001,
+ 0x1950001f, 0x10006610, 0x81481401, 0xa1001404, 0xd8005d64, 0x17c07c1f,
+ 0xd00060a0, 0x17c07c1f, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81479001,
+ 0x81881001, 0x69a00006, 0x00000000, 0x81401805, 0xd8206185, 0x17c07c1f,
+ 0x1a40001f, 0x100062a0, 0x1280041f, 0xc2401240, 0x17c07c1f, 0x1910001f,
+ 0x10006b00, 0x89000004, 0xffffefff, 0x1940001f, 0x10006b00, 0xe1400004,
+ 0x17c07c1f, 0x1910001f, 0x10006b00, 0x81469001, 0xd82068e5, 0x17c07c1f,
+ 0x1910001f, 0x10006b00, 0x81029001, 0xd8206624, 0x17c07c1f, 0x1910001f,
+ 0x10006610, 0x81089001, 0xd82068e4, 0x17c07c1f, 0x1910001f, 0x10006720,
+ 0x814a9001, 0xd8206385, 0x17c07c1f, 0x1a40001f, 0x100062a4, 0x1290841f,
+ 0xc2401540, 0x17c07c1f, 0x1910001f, 0x1000660c, 0x81089001, 0x1950001f,
+ 0x10006610, 0x81489401, 0xa1001404, 0xd80064c4, 0x17c07c1f, 0xd0006800,
+ 0x17c07c1f, 0x17c07c1f, 0x1910001f, 0x10006610, 0x81479001, 0x81889001,
+ 0x69a00006, 0x00000000, 0x81401805, 0xd82068e5, 0x17c07c1f, 0x1a40001f,
+ 0x100062a4, 0x1290841f, 0xc2401240, 0x17c07c1f, 0x1910001f, 0x10006b00,
+ 0x89000004, 0xffffdfff, 0x1940001f, 0x10006b00, 0xe1400004, 0x1910001f,
+ 0x10006610, 0x81479001, 0x81881001, 0x69600005, 0x00000000, 0xa1401805,
+ 0x81889001, 0xa1401805, 0xd8006bc5, 0x17c07c1f, 0x1910001f, 0x10006b00,
+ 0x81421001, 0x82429001, 0x82802405, 0xd8206bca, 0x17c07c1f, 0x1a40001f,
+ 0x100062b0, 0x1280041f, 0xc2400000, 0x17c07c1f, 0x1990001f, 0x10006b00,
+ 0x89800006, 0x00003f00, 0x69200006, 0x00000000, 0xd82041e4, 0x17c07c1f,
+ 0x1990001f, 0x10006320, 0x69200006, 0xbeefbeef, 0xd8006dc4, 0x17c07c1f,
+ 0xd00041e0, 0x17c07c1f, 0x1910001f, 0x10006358, 0x810b1001, 0xd8006dc4,
+ 0x17c07c1f, 0x1980001f, 0xdeaddead, 0x19c0001f, 0x01411820, 0xf0000000
+};
+static const struct pcm_desc hotplug_pcm = {
+ .version = "pcm_power_down_mt8173_V37",
+ .base = hotplug_binary,
+ .size = 888,
+ .sess = 2,
+ .replace = 0,
+};
+
+static struct pwr_ctrl hotplug_ctrl = {
+ .wake_src = 0,
+ .wake_src_md32 = 0,
+ .wfi_op = WFI_OP_OR,
+ .mcusys_idle_mask = 1,
+ .ca7top_idle_mask = 1,
+ .ca15top_idle_mask = 1,
+ .disp_req_mask = 1,
+ .mfg_req_mask = 1,
+ .md32_req_mask = 1,
+ .syspwreq_mask = 1,
+ .pcm_flags = 0,
+};
+
+static const struct spm_lp_scen spm_hotplug = {
+ .pcmdesc = &hotplug_pcm,
+ .pwrctrl = &hotplug_ctrl,
+};
+
+void spm_go_to_hotplug(void)
+{
+ const struct pcm_desc *pcmdesc = spm_hotplug.pcmdesc;
+ struct pwr_ctrl *pwrctrl = spm_hotplug.pwrctrl;
+
+ set_pwrctrl_pcm_flags(pwrctrl, 0);
+ spm_reset_and_init_pcm();
+ spm_kick_im_to_fetch(pcmdesc);
+ spm_set_power_control(pwrctrl);
+ spm_set_wakeup_event(pwrctrl);
+ spm_kick_pcm_to_run(pwrctrl);
+}
+
+void spm_clear_hotplug(void)
+{
+ /* Inform SPM that CPU wants to program CPU_WAKEUP_EVENT and
+ * DISABLE_CPU_DROM */
+
+ mmio_write_32(SPM_PCM_REG_DATA_INI, PCM_HANDSHAKE_SEND1);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+
+ /* Wait SPM's response, can't use sleep api */
+ while ((mmio_read_32(SPM_PCM_FSM_STA) & PCM_END_FSM_STA_MASK)
+ != PCM_END_FSM_STA_DEF)
+ ;
+
+ /* no hotplug pcm running */
+ clear_all_ready();
+}
+
+void spm_hotplug_on(unsigned long mpidr)
+{
+ unsigned long linear_id;
+
+ linear_id = ((mpidr & MPIDR_CLUSTER_MASK) >> 6) |
+ (mpidr & MPIDR_CPU_MASK);
+
+ spm_lock_get();
+ if (is_hotplug_ready() == 0) {
+ spm_mcdi_wakeup_all_cores();
+ mmio_clrbits_32(SPM_PCM_RESERVE, PCM_HOTPLUG_VALID_MASK);
+ spm_go_to_hotplug();
+ set_hotplug_ready();
+ }
+ /* turn on CPUx */
+ mmio_clrsetbits_32(SPM_PCM_RESERVE,
+ PCM_HOTPLUG_VALID_MASK | (1 << linear_id),
+ 1 << (linear_id + PCM_HOTPLUG_VALID_SHIFT));
+ spm_lock_release();
+}
+
+void spm_hotplug_off(unsigned long mpidr)
+{
+ unsigned long linear_id;
+
+ linear_id = ((mpidr & MPIDR_CLUSTER_MASK) >> 6) |
+ (mpidr & MPIDR_CPU_MASK);
+
+ spm_lock_get();
+ if (is_hotplug_ready() == 0) {
+ spm_mcdi_wakeup_all_cores();
+ mmio_clrbits_32(SPM_PCM_RESERVE, PCM_HOTPLUG_VALID_MASK);
+ spm_go_to_hotplug();
+ set_hotplug_ready();
+ }
+ mmio_clrsetbits_32(SPM_PCM_RESERVE, PCM_HOTPLUG_VALID_MASK,
+ (1 << linear_id) |
+ (1 << (linear_id + PCM_HOTPLUG_VALID_SHIFT)));
+ spm_lock_release();
+}
diff --git a/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h b/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h
new file mode 100644
index 0000000..00849a2
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef SPM_HOTPLUG_H
+#define SPM_HOTPLUG_H
+
+void spm_clear_hotplug(void);
+void spm_hotplug_off(unsigned long mpidr);
+void spm_hotplug_on(unsigned long mpidr);
+
+#endif /* SPM_HOTPLUG_H */
diff --git a/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c b/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c
new file mode 100644
index 0000000..ea5f2bb
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <mt8173_def.h>
+#include <spm.h>
+#include <spm_hotplug.h>
+#include <spm_mcdi.h>
+
+/*
+ * System Power Manager (SPM) is a hardware module, which controls cpu or
+ * system power for different power scenarios using different firmware.
+ * This driver controls the cpu power in cpu idle power saving state.
+ */
+
+#define WAKE_SRC_FOR_MCDI \
+ (WAKE_SRC_KP | WAKE_SRC_GPT | WAKE_SRC_EINT | \
+ WAKE_SRC_MD32 | WAKE_SRC_USB_CD | WAKE_SRC_USB_PDN | \
+ WAKE_SRC_AFE | WAKE_SRC_THERM | WAKE_SRC_CIRQ | \
+ WAKE_SRC_SYSPWREQ | WAKE_SRC_CPU_IRQ)
+#define PCM_MCDI_HANDSHAKE_SYNC 0xbeefbeef
+#define PCM_MCDI_HANDSHAKE_ACK 0xdeaddead
+#define PCM_MCDI_UPDATE_INFORM 0xabcdabcd
+#define PCM_MCDI_CKECK_DONE 0x12345678
+#define PCM_MCDI_ALL_CORE_AWAKE 0x0
+#define PCM_MCDI_OFFLOADED 0xaa55aa55
+#define PCM_MCDI_CA72_CPUTOP_PWRCTL (0x1 << 16)
+#define PCM_MCDI_CA53_CPUTOP_PWRCTL (0x1 << 17)
+#define PCM_MCDI_CA72_PWRSTA_SHIFT 16
+#define PCM_MCDI_CA53_PWRSTA_SHIFT 9
+
+static const unsigned int mcdi_binary[] = {
+ 0x1a10001f, 0x10006b04, 0x1890001f, 0x10006b6c, 0x1a40001f, 0x10006210,
+ 0x18d0001f, 0x10006210, 0x81002001, 0xd82001c4, 0x17c07c1f, 0xa0900402,
+ 0xc2401540, 0x17c07c1f, 0x81052001, 0xd8200284, 0x17c07c1f, 0xa0950402,
+ 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x10006230, 0x18d0001f, 0x10006230,
+ 0x8100a001, 0xd82003c4, 0x17c07c1f, 0xa0908402, 0xc2401540, 0x17c07c1f,
+ 0x8105a001, 0xd8200484, 0x17c07c1f, 0xa0958402, 0xc2401b80, 0x17c07c1f,
+ 0x1a40001f, 0x10006238, 0x18d0001f, 0x10006238, 0x81012001, 0xd82005c4,
+ 0x17c07c1f, 0xa0910402, 0xc2401540, 0x17c07c1f, 0x81062001, 0xd8200684,
+ 0x17c07c1f, 0xa0960402, 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x1000623c,
+ 0x18d0001f, 0x1000623c, 0x8101a001, 0xd82007c4, 0x17c07c1f, 0xa0918402,
+ 0xc2401540, 0x17c07c1f, 0x8106a001, 0xd8200884, 0x17c07c1f, 0xa0968402,
+ 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x10006298, 0x18d0001f, 0x10006298,
+ 0x81022001, 0xd82009c4, 0x17c07c1f, 0xa0920402, 0xc2401540, 0x17c07c1f,
+ 0x81072001, 0xd8200a84, 0x17c07c1f, 0xa0970402, 0xc2401b80, 0x17c07c1f,
+ 0x1a40001f, 0x1000629c, 0x18d0001f, 0x1000629c, 0x8102a001, 0xd8200bc4,
+ 0x17c07c1f, 0xa0928402, 0xc2401540, 0x17c07c1f, 0x8107a001, 0xd8200c84,
+ 0x17c07c1f, 0xa0978402, 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x100062c4,
+ 0x18d0001f, 0x100062c4, 0x81032001, 0xd8200dc4, 0x17c07c1f, 0xa0930402,
+ 0xc2401540, 0x17c07c1f, 0x81082001, 0xd8200e84, 0x17c07c1f, 0xa0980402,
+ 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x100062c0, 0x18d0001f, 0x100062c0,
+ 0x8103a001, 0xd8200fc4, 0x17c07c1f, 0xa0938402, 0xc2401540, 0x17c07c1f,
+ 0x8108a001, 0xd8201084, 0x17c07c1f, 0xa0988402, 0xc2401b80, 0x17c07c1f,
+ 0x1a40001f, 0x10006214, 0x18d0001f, 0x10006214, 0x81042001, 0xd82011c4,
+ 0x17c07c1f, 0xa0940402, 0xc2401540, 0x17c07c1f, 0x81092001, 0xd8201284,
+ 0x17c07c1f, 0xa0990402, 0xc2401b80, 0x17c07c1f, 0x1a40001f, 0x100062cc,
+ 0x18d0001f, 0x100062cc, 0x8104a001, 0xd82013c4, 0x17c07c1f, 0xa0948402,
+ 0xc2401540, 0x17c07c1f, 0x8109a001, 0xd8201484, 0x17c07c1f, 0xa0998402,
+ 0xc2401b80, 0x17c07c1f, 0x1900001f, 0x10006b6c, 0x80802002, 0xe1000002,
+ 0xf0000000, 0x17c07c1f, 0xa8c00003, 0x00000004, 0xe2400003, 0xa8c00003,
+ 0x00000008, 0xe2400003, 0x1b80001f, 0x00000020, 0x88c00003, 0xffffffef,
+ 0xe2400003, 0x88c00003, 0xfffffffd, 0xe2400003, 0xa8c00003, 0x00000001,
+ 0xe2400003, 0x88c00003, 0xfffff0ff, 0xe2400003, 0x1b80001f, 0x20000080,
+ 0x1a90001f, 0x10001220, 0x69200009, 0x1000623c, 0xd8001984, 0x17c07c1f,
+ 0x69200009, 0x10006214, 0xd8001a64, 0x17c07c1f, 0xd0001b00, 0x17c07c1f,
+ 0x1900001f, 0x10001220, 0x8a80000a, 0xfffffff9, 0xe100000a, 0xd0001b00,
+ 0x17c07c1f, 0x1900001f, 0x10001220, 0x8a80000a, 0xff1fbfff, 0xe100000a,
+ 0x1b80001f, 0x20000080, 0xf0000000, 0x17c07c1f, 0x1a90001f, 0x10001220,
+ 0x69200009, 0x1000623c, 0xd8001d04, 0x17c07c1f, 0x69200009, 0x10006214,
+ 0xd8001de4, 0x17c07c1f, 0xd0001e80, 0x17c07c1f, 0x1900001f, 0x10001220,
+ 0xaa80000a, 0x00000006, 0xe100000a, 0xd0001e80, 0x17c07c1f, 0x1900001f,
+ 0x10001220, 0xaa80000a, 0x00e04000, 0xe100000a, 0x1b80001f, 0x20000080,
+ 0x69200009, 0x10006214, 0xd8001fe4, 0x17c07c1f, 0xa8c00003, 0x00000f00,
+ 0xe2400003, 0xd0002040, 0x17c07c1f, 0xa8c00003, 0x00003f00, 0xe2400003,
+ 0x1b80001f, 0x20000080, 0xa8c00003, 0x00000002, 0xe2400003, 0x88c00003,
+ 0xfffffffe, 0xe2400003, 0xa8c00003, 0x00000010, 0xe2400003, 0x88c00003,
+ 0xfffffffb, 0xe2400003, 0x88c00003, 0xfffffff7, 0xe2400003, 0xf0000000,
+ 0x17c07c1f, 0xe2e00036, 0xe2e0003e, 0x1b80001f, 0x00000020, 0xe2e0003c,
+ 0xe8208000, 0x10006244, 0x00000000, 0x1b80001f, 0x20000080, 0xe2e0007c,
+ 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c, 0xe2e0004d, 0xf0000000,
+ 0x17c07c1f, 0xe2e0004f, 0xe2e0006f, 0xe2e0002f, 0xe8208000, 0x10006244,
+ 0x00000001, 0x1b80001f, 0x20000080, 0xe2e0002e, 0xe2e0003e, 0xe2e0003a,
+ 0xe2e00032, 0x1b80001f, 0x00000020, 0xf0000000, 0x17c07c1f, 0xe2e00036,
+ 0xe2e0003e, 0x1b80001f, 0x00000020, 0xe2e0003c, 0xe2a00000, 0x1b80001f,
+ 0x20000080, 0xe2e0007c, 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c,
+ 0xe2e0004d, 0xf0000000, 0x17c07c1f, 0xe2e0004f, 0xe2e0006f, 0xe2e0002f,
+ 0xe2a00001, 0x1b80001f, 0x20000080, 0xe2e0002e, 0xe2e0003e, 0xe2e0003a,
+ 0xe2e00032, 0xf0000000, 0x17c07c1f, 0xe2e00026, 0xe2e0002e, 0x1b80001f,
+ 0x00000020, 0x1a00001f, 0x100062b4, 0x1910001f, 0x100062b4, 0x81322804,
+ 0xe2000004, 0x81202804, 0xe2000004, 0x1b80001f, 0x20000080, 0xe2e0000e,
+ 0xe2e0000c, 0xe2e0000d, 0xf0000000, 0x17c07c1f, 0xe2e0002d, 0x1a00001f,
+ 0x100062b4, 0x1910001f, 0x100062b4, 0xa1002804, 0xe2000004, 0xa1122804,
+ 0xe2000004, 0x1b80001f, 0x20000080, 0xe2e0002f, 0xe2e0002b, 0xe2e00023,
+ 0x1b80001f, 0x00000020, 0xe2e00022, 0xf0000000, 0x17c07c1f, 0x1910001f,
+ 0x1000660c, 0x1a10001f, 0x10006610, 0xa2002004, 0x89000008, 0x00030000,
+ 0xd80036c4, 0x17c07c1f, 0x8207a001, 0xd82036c8, 0x17c07c1f, 0x1900001f,
+ 0x1020020c, 0x1a10001f, 0x1020020c, 0xaa000008, 0x00000001, 0xe1000008,
+ 0x1910001f, 0x1020020c, 0x81001001, 0xd8203184, 0x17c07c1f, 0x1910001f,
+ 0x10006720, 0x820c9001, 0xd8203228, 0x17c07c1f, 0x1900001f, 0x10001220,
+ 0x1a10001f, 0x10001220, 0xa21f0408, 0xe1000008, 0x1b80001f, 0x20000080,
+ 0xe2e0006d, 0xe2e0002d, 0x1a00001f, 0x100062b8, 0x1910001f, 0x100062b8,
+ 0xa9000004, 0x00000001, 0xe2000004, 0x1b80001f, 0x20000080, 0xe2e0002c,
+ 0xe2e0003c, 0xe2e0003e, 0xe2e0003a, 0xe2e00032, 0x1b80001f, 0x00000020,
+ 0x1900001f, 0x10006404, 0x1a10001f, 0x10006404, 0xa2168408, 0xe1000008,
+ 0xf0000000, 0x17c07c1f, 0x1a10001f, 0x10006610, 0x8207a001, 0xd8003e68,
+ 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8a000008, 0x00003030, 0xb900010c,
+ 0x01000001, 0xd8203e64, 0x17c07c1f, 0x1900001f, 0x10006404, 0x1a10001f,
+ 0x10006404, 0x8a000008, 0x0000dfff, 0xe1000008, 0xe2e00036, 0xe2e0003e,
+ 0x1b80001f, 0x00000020, 0xe2e0002e, 0x1a00001f, 0x100062b8, 0x1910001f,
+ 0x100062b8, 0x89000004, 0x0000fffe, 0xe2000004, 0x1b80001f, 0x20000080,
+ 0xe2e0006e, 0xe2e0004e, 0xe2e0004c, 0xe2e0004d, 0x1900001f, 0x10001220,
+ 0x1a10001f, 0x10001220, 0x8a000008, 0xbfffffff, 0xe1000008, 0x1b80001f,
+ 0x20000080, 0x1900001f, 0x1020020c, 0x1a10001f, 0x1020020c, 0x8a000008,
+ 0xfffffffe, 0xe1000008, 0x1910001f, 0x1020020c, 0x81001001, 0xd8003dc4,
+ 0x17c07c1f, 0xf0000000, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x1840001f, 0x00000001, 0x11407c1f, 0xe8208000,
+ 0x10006310, 0x0b160008, 0x1900001f, 0x000f7bde, 0x1a00001f, 0x10200268,
+ 0xe2000004, 0xe8208000, 0x10006600, 0x00000000, 0x69200006, 0xbeefbeef,
+ 0xd8204584, 0x17c07c1f, 0x1910001f, 0x10006358, 0x810b1001, 0xd8004244,
+ 0x17c07c1f, 0x1980001f, 0xdeaddead, 0x69200006, 0xabcdabcd, 0xd8204324,
+ 0x17c07c1f, 0x88900001, 0x10006814, 0x1910001f, 0x10006400, 0x81271002,
+ 0x1880001f, 0x10006600, 0xe0800004, 0x1910001f, 0x10006358, 0x810b1001,
+ 0xd80044a4, 0x17c07c1f, 0x1980001f, 0x12345678, 0x60a07c05, 0x89100002,
+ 0x10006600, 0x80801001, 0xd8007bc2, 0x17c07c1f, 0x1890001f, 0x10006b00,
+ 0x82090801, 0xc8800008, 0x17c07c1f, 0x1b00001f, 0x3fffe7ff, 0x8a00000c,
+ 0x3fffe7ff, 0xd82041c8, 0x17c07c1f, 0x1b80001f, 0xd0010000, 0x1a10001f,
+ 0x10006720, 0x82002001, 0x82201408, 0xd8204988, 0x17c07c1f, 0x1a40001f,
+ 0x10006200, 0x1a80001f, 0x1000625c, 0xc24028e0, 0x17c07c1f, 0xa1400405,
+ 0x1a10001f, 0x10006720, 0x8200a001, 0x82209408, 0xd8204b28, 0x17c07c1f,
+ 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264, 0xc24028e0, 0x17c07c1f,
+ 0xa1508405, 0x1a10001f, 0x10006720, 0x82012001, 0x82211408, 0xd8204cc8,
+ 0x17c07c1f, 0x1a40001f, 0x1000621c, 0x1a80001f, 0x1000626c, 0xc24028e0,
+ 0x17c07c1f, 0xa1510405, 0x1a10001f, 0x10006720, 0x8201a001, 0x82219408,
+ 0xd8204e68, 0x17c07c1f, 0x1a40001f, 0x10006220, 0x1a80001f, 0x10006274,
+ 0xc24028e0, 0x17c07c1f, 0xa1518405, 0x1a10001f, 0x10006720, 0x82022001,
+ 0x82221408, 0xd8204fe8, 0x17c07c1f, 0x1a40001f, 0x100062a0, 0x1280041f,
+ 0xc2402cc0, 0x17c07c1f, 0xa1520405, 0x1a10001f, 0x10006720, 0x8202a001,
+ 0x82229408, 0xd8205168, 0x17c07c1f, 0x1a40001f, 0x100062a4, 0x1290841f,
+ 0xc2402cc0, 0x17c07c1f, 0xa1528405, 0x1a10001f, 0x10006720, 0x82032001,
+ 0x82231408, 0xd8205248, 0x17c07c1f, 0xa1530405, 0x1a10001f, 0x10006720,
+ 0x8203a001, 0x82239408, 0xd8205328, 0x17c07c1f, 0xa1538405, 0x1a10001f,
+ 0x10006b00, 0x8108a001, 0xd8205e84, 0x17c07c1f, 0x1910001f, 0x1000660c,
+ 0x1a10001f, 0x10006610, 0xa2002004, 0x89000008, 0x00001e00, 0xd8005944,
+ 0x17c07c1f, 0x82042001, 0xd8205948, 0x17c07c1f, 0x1900001f, 0x1020002c,
+ 0x1a10001f, 0x1020002c, 0xaa000008, 0x00000010, 0xe1000008, 0x1910001f,
+ 0x10006720, 0x820c1001, 0xd8205628, 0x17c07c1f, 0x1900001f, 0x10001250,
+ 0x1a10001f, 0x10001250, 0xa2110408, 0xe1000008, 0x1b80001f, 0x20000080,
+ 0x1900001f, 0x10001220, 0x1a10001f, 0x10001220, 0xa21e8408, 0xe1000008,
+ 0x1b80001f, 0x20000080, 0x1a40001f, 0x10006208, 0xc24024e0, 0x17c07c1f,
+ 0x1a10001f, 0x10006610, 0x82042001, 0xd8005e88, 0x17c07c1f, 0x1a10001f,
+ 0x10006918, 0x8a000008, 0x00000f0f, 0xba00010c, 0x1fffe7ff, 0xd8205e88,
+ 0x17c07c1f, 0x1a40001f, 0x10006208, 0xc24022a0, 0x17c07c1f, 0x1900001f,
+ 0x10001250, 0x1a10001f, 0x10001250, 0x8a000008, 0xfffffffb, 0xe1000008,
+ 0x1b80001f, 0x20000080, 0x1900001f, 0x10001220, 0x1a10001f, 0x10001220,
+ 0x8a000008, 0xdfffffff, 0xe1000008, 0x1b80001f, 0x20000080, 0x1900001f,
+ 0x1020002c, 0x1a10001f, 0x1020002c, 0x8a000008, 0xffffffef, 0xe1000008,
+ 0x1a10001f, 0x10006b00, 0x81082001, 0xd8205fa4, 0x17c07c1f, 0x1a40001f,
+ 0x100062b0, 0xc2402f20, 0x17c07c1f, 0x1b80001f, 0x20000208, 0xd8207b8c,
+ 0x17c07c1f, 0x1a40001f, 0x100062b0, 0xc2403700, 0x17c07c1f, 0x81001401,
+ 0xd8206424, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x81002001, 0xb1042081,
+ 0xb900008c, 0x1fffe7ff, 0xd8206424, 0x17c07c1f, 0x1a40001f, 0x10006200,
+ 0x1a80001f, 0x1000625c, 0xc24026e0, 0x17c07c1f, 0x89400005, 0xfffffffe,
+ 0xe8208000, 0x10006f00, 0x00000000, 0xe8208000, 0x10006b30, 0x00000000,
+ 0xe8208000, 0x100063e0, 0x00000001, 0x81009401, 0xd82067a4, 0x17c07c1f,
+ 0x1a10001f, 0x10006918, 0x8100a001, 0xb104a081, 0xb900008c, 0x01000001,
+ 0xd82067a4, 0x17c07c1f, 0x1a40001f, 0x10006218, 0x1a80001f, 0x10006264,
+ 0xc24026e0, 0x17c07c1f, 0x89400005, 0xfffffffd, 0xe8208000, 0x10006f04,
+ 0x00000000, 0xe8208000, 0x10006b34, 0x00000000, 0xe8208000, 0x100063e0,
+ 0x00000002, 0x81011401, 0xd8206b24, 0x17c07c1f, 0x1a10001f, 0x10006918,
+ 0x81012001, 0xb1052081, 0xb900008c, 0x01000001, 0xd8206b24, 0x17c07c1f,
+ 0x1a40001f, 0x1000621c, 0x1a80001f, 0x1000626c, 0xc24026e0, 0x17c07c1f,
+ 0x89400005, 0xfffffffb, 0xe8208000, 0x10006f08, 0x00000000, 0xe8208000,
+ 0x10006b38, 0x00000000, 0xe8208000, 0x100063e0, 0x00000004, 0x81019401,
+ 0xd8206ea4, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8101a001, 0xb105a081,
+ 0xb900008c, 0x01000001, 0xd8206ea4, 0x17c07c1f, 0x1a40001f, 0x10006220,
+ 0x1a80001f, 0x10006274, 0xc24026e0, 0x17c07c1f, 0x89400005, 0xfffffff7,
+ 0xe8208000, 0x10006f0c, 0x00000000, 0xe8208000, 0x10006b3c, 0x00000000,
+ 0xe8208000, 0x100063e0, 0x00000008, 0x1a10001f, 0x10006610, 0x8207a001,
+ 0xd8207608, 0x17c07c1f, 0x81021401, 0xd82072a4, 0x17c07c1f, 0x1a10001f,
+ 0x10006918, 0x81022001, 0xb1062081, 0xb900008c, 0x01000001, 0xd82072a4,
+ 0x17c07c1f, 0x1a40001f, 0x100062a0, 0x1280041f, 0xc2402a60, 0x17c07c1f,
+ 0x89400005, 0xffffffef, 0xe8208000, 0x10006f10, 0x00000000, 0xe8208000,
+ 0x10006b40, 0x00000000, 0xe8208000, 0x100063e0, 0x00000010, 0x81029401,
+ 0xd8207604, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8102a001, 0xb106a081,
+ 0xb900008c, 0x01000001, 0xd8207604, 0x17c07c1f, 0x1a40001f, 0x100062a4,
+ 0x1290841f, 0xc2402a60, 0x17c07c1f, 0x89400005, 0xffffffdf, 0xe8208000,
+ 0x10006f14, 0x00000000, 0xe8208000, 0x10006b44, 0x00000000, 0xe8208000,
+ 0x100063e0, 0x00000020, 0x81031401, 0xd82078c4, 0x17c07c1f, 0x1a10001f,
+ 0x10006918, 0x81032001, 0xb1072081, 0xb900008c, 0x01000001, 0xd82078c4,
+ 0x17c07c1f, 0x89400005, 0xffffffbf, 0xe8208000, 0x10006f18, 0x00000000,
+ 0xe8208000, 0x10006b48, 0x00000000, 0xe8208000, 0x100063e0, 0x00000040,
+ 0x81039401, 0xd8207b84, 0x17c07c1f, 0x1a10001f, 0x10006918, 0x8103a001,
+ 0xb107a081, 0xb900008c, 0x01000001, 0xd8207b84, 0x17c07c1f, 0x89400005,
+ 0xffffff7f, 0xe8208000, 0x10006f1c, 0x00000000, 0xe8208000, 0x10006b4c,
+ 0x00000000, 0xe8208000, 0x100063e0, 0x00000080, 0xd00041c0, 0x17c07c1f,
+ 0xe8208000, 0x10006600, 0x00000000, 0x1ac0001f, 0x55aa55aa, 0x1940001f,
+ 0xaa55aa55, 0x1b80001f, 0x00001000, 0xf0000000, 0x17c07c1f
+};
+
+static const struct pcm_desc mcdi_pcm = {
+ .version = "pcm_mcdi_mt8173_20160401_v1",
+ .base = mcdi_binary,
+ .size = 1001,
+ .sess = 2,
+ .replace = 0,
+};
+
+static struct pwr_ctrl mcdi_ctrl = {
+ .wake_src = WAKE_SRC_FOR_MCDI,
+ .wake_src_md32 = 0,
+ .wfi_op = WFI_OP_OR,
+ .mcusys_idle_mask = 1,
+ .ca7top_idle_mask = 1,
+ .ca15top_idle_mask = 1,
+ .disp_req_mask = 1,
+ .mfg_req_mask = 1,
+ .md32_req_mask = 1,
+};
+
+static const struct spm_lp_scen spm_mcdi = {
+ .pcmdesc = &mcdi_pcm,
+ .pwrctrl = &mcdi_ctrl,
+};
+
+void spm_mcdi_cpu_wake_up_event(int wake_up_event, int disable_dormant_power)
+{
+ if (((mmio_read_32(SPM_SLEEP_CPU_WAKEUP_EVENT) & 0x1) == 1)
+ && ((mmio_read_32(SPM_CLK_CON) & CC_DISABLE_DORM_PWR) == 0)) {
+ /* MCDI is offload? */
+ INFO("%s: SPM_SLEEP_CPU_WAKEUP_EVENT:%x, SPM_CLK_CON %x",
+ __func__, mmio_read_32(SPM_SLEEP_CPU_WAKEUP_EVENT),
+ mmio_read_32(SPM_CLK_CON));
+ return;
+ }
+ /* Inform SPM that CPU wants to program CPU_WAKEUP_EVENT and
+ * DISABLE_CPU_DROM */
+ mmio_write_32(SPM_PCM_REG_DATA_INI, PCM_MCDI_HANDSHAKE_SYNC);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+
+ /* Wait SPM's response, can't use sleep api */
+ while (mmio_read_32(SPM_PCM_REG6_DATA) != PCM_MCDI_HANDSHAKE_ACK)
+ ;
+
+ if (disable_dormant_power) {
+ mmio_setbits_32(SPM_CLK_CON, CC_DISABLE_DORM_PWR);
+ while (mmio_read_32(SPM_CLK_CON) !=
+ (mmio_read_32(SPM_CLK_CON) | CC_DISABLE_DORM_PWR))
+ ;
+
+ } else {
+ mmio_clrbits_32(SPM_CLK_CON, CC_DISABLE_DORM_PWR);
+ while (mmio_read_32(SPM_CLK_CON) !=
+ (mmio_read_32(SPM_CLK_CON) & ~CC_DISABLE_DORM_PWR))
+ ;
+ }
+
+ mmio_write_32(SPM_SLEEP_CPU_WAKEUP_EVENT, wake_up_event);
+
+ while (mmio_read_32(SPM_SLEEP_CPU_WAKEUP_EVENT) != wake_up_event)
+ ;
+
+ /* Inform SPM to see updated setting */
+ mmio_write_32(SPM_PCM_REG_DATA_INI, PCM_MCDI_UPDATE_INFORM);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+
+ while (mmio_read_32(SPM_PCM_REG6_DATA) != PCM_MCDI_CKECK_DONE)
+ ;
+ /* END OF sequence */
+
+ mmio_write_32(SPM_PCM_REG_DATA_INI, 0x0);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, PCM_RF_SYNC_R6);
+ mmio_write_32(SPM_PCM_PWR_IO_EN, 0);
+}
+
+void spm_mcdi_wakeup_all_cores(void)
+{
+ if (is_mcdi_ready() == 0)
+ return;
+
+ spm_mcdi_cpu_wake_up_event(1, 1);
+ while (mmio_read_32(SPM_PCM_REG5_DATA) != PCM_MCDI_ALL_CORE_AWAKE)
+ ;
+ spm_mcdi_cpu_wake_up_event(1, 0);
+ while (mmio_read_32(SPM_PCM_REG5_DATA) != PCM_MCDI_OFFLOADED)
+ ;
+
+ spm_clean_after_wakeup();
+ clear_all_ready();
+}
+
+static void spm_mcdi_wfi_sel_enter(unsigned long mpidr)
+{
+ int core_id_val = mpidr & MPIDR_CPU_MASK;
+ int cluster_id = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ /* SPM WFI Select by core number */
+ if (cluster_id) {
+ switch (core_id_val) {
+ case 0:
+ mmio_write_32(SPM_CA15_CPU0_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA15_WFI0_EN, 1);
+ break;
+ case 1:
+ mmio_write_32(SPM_CA15_CPU1_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA15_WFI1_EN, 1);
+ break;
+ case 2:
+ mmio_write_32(SPM_CA15_CPU2_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA15_WFI2_EN, 1);
+ break;
+ case 3:
+ mmio_write_32(SPM_CA15_CPU3_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA15_WFI3_EN, 1);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (core_id_val) {
+ case 0:
+ mmio_write_32(SPM_CA7_CPU0_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA7_WFI0_EN, 1);
+ break;
+ case 1:
+ mmio_write_32(SPM_CA7_CPU1_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA7_WFI1_EN, 1);
+ break;
+ case 2:
+ mmio_write_32(SPM_CA7_CPU2_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA7_WFI2_EN, 1);
+ break;
+ case 3:
+ mmio_write_32(SPM_CA7_CPU3_IRQ_MASK, 1);
+ mmio_write_32(SPM_SLEEP_CA7_WFI3_EN, 1);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void spm_mcdi_wfi_sel_leave(unsigned long mpidr)
+{
+ int core_id_val = mpidr & MPIDR_CPU_MASK;
+ int cluster_id = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ /* SPM WFI Select by core number */
+ if (cluster_id) {
+ switch (core_id_val) {
+ case 0:
+ mmio_write_32(SPM_SLEEP_CA15_WFI0_EN, 0);
+ mmio_write_32(SPM_CA15_CPU0_IRQ_MASK, 0);
+ break;
+ case 1:
+ mmio_write_32(SPM_SLEEP_CA15_WFI1_EN, 0);
+ mmio_write_32(SPM_CA15_CPU1_IRQ_MASK, 0);
+ break;
+ case 2:
+ mmio_write_32(SPM_SLEEP_CA15_WFI2_EN, 0);
+ mmio_write_32(SPM_CA15_CPU2_IRQ_MASK, 0);
+ break;
+ case 3:
+ mmio_write_32(SPM_SLEEP_CA15_WFI3_EN, 0);
+ mmio_write_32(SPM_CA15_CPU3_IRQ_MASK, 0);
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (core_id_val) {
+ case 0:
+ mmio_write_32(SPM_SLEEP_CA7_WFI0_EN, 0);
+ mmio_write_32(SPM_CA7_CPU0_IRQ_MASK, 0);
+ break;
+ case 1:
+ mmio_write_32(SPM_SLEEP_CA7_WFI1_EN, 0);
+ mmio_write_32(SPM_CA7_CPU1_IRQ_MASK, 0);
+ break;
+ case 2:
+ mmio_write_32(SPM_SLEEP_CA7_WFI2_EN, 0);
+ mmio_write_32(SPM_CA7_CPU2_IRQ_MASK, 0);
+ break;
+ case 3:
+ mmio_write_32(SPM_SLEEP_CA7_WFI3_EN, 0);
+ mmio_write_32(SPM_CA7_CPU3_IRQ_MASK, 0);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void spm_mcdi_set_cputop_pwrctrl_for_cluster_off(unsigned long mpidr)
+{
+ unsigned long cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+ unsigned long cpu_id = mpidr & MPIDR_CPU_MASK;
+ unsigned int pwr_status, shift, i, flag = 0;
+
+ pwr_status = mmio_read_32(SPM_PWR_STATUS) |
+ mmio_read_32(SPM_PWR_STATUS_2ND);
+
+ if (cluster_id) {
+ for (i = 0; i < PLATFORM_CLUSTER1_CORE_COUNT; i++) {
+ if (i == cpu_id)
+ continue;
+ shift = i + PCM_MCDI_CA72_PWRSTA_SHIFT;
+ flag |= (pwr_status & (1 << shift)) >> shift;
+ }
+ if (!flag)
+ mmio_setbits_32(SPM_PCM_RESERVE,
+ PCM_MCDI_CA72_CPUTOP_PWRCTL);
+ } else {
+ for (i = 0; i < PLATFORM_CLUSTER0_CORE_COUNT; i++) {
+ if (i == cpu_id)
+ continue;
+ shift = i + PCM_MCDI_CA53_PWRSTA_SHIFT;
+ flag |= (pwr_status & (1 << shift)) >> shift;
+ }
+ if (!flag)
+ mmio_setbits_32(SPM_PCM_RESERVE,
+ PCM_MCDI_CA53_CPUTOP_PWRCTL);
+ }
+}
+
+static void spm_mcdi_clear_cputop_pwrctrl_for_cluster_on(unsigned long mpidr)
+{
+ unsigned long cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+
+ if (cluster_id)
+ mmio_clrbits_32(SPM_PCM_RESERVE,
+ PCM_MCDI_CA72_CPUTOP_PWRCTL);
+ else
+ mmio_clrbits_32(SPM_PCM_RESERVE,
+ PCM_MCDI_CA53_CPUTOP_PWRCTL);
+}
+
+void spm_mcdi_prepare_for_mtcmos(void)
+{
+ const struct pcm_desc *pcmdesc = spm_mcdi.pcmdesc;
+ struct pwr_ctrl *pwrctrl = spm_mcdi.pwrctrl;
+
+ if (is_mcdi_ready() == 0) {
+ if (is_hotplug_ready() == 1)
+ spm_clear_hotplug();
+ set_pwrctrl_pcm_flags(pwrctrl, 0);
+ spm_reset_and_init_pcm();
+ spm_kick_im_to_fetch(pcmdesc);
+ spm_set_power_control(pwrctrl);
+ spm_set_wakeup_event(pwrctrl);
+ spm_kick_pcm_to_run(pwrctrl);
+ set_mcdi_ready();
+ }
+}
+
+void spm_mcdi_prepare_for_off_state(unsigned long mpidr, unsigned int afflvl)
+{
+ const struct pcm_desc *pcmdesc = spm_mcdi.pcmdesc;
+ struct pwr_ctrl *pwrctrl = spm_mcdi.pwrctrl;
+
+ spm_lock_get();
+ if (is_mcdi_ready() == 0) {
+ if (is_hotplug_ready() == 1)
+ spm_clear_hotplug();
+ set_pwrctrl_pcm_flags(pwrctrl, 0);
+ spm_reset_and_init_pcm();
+ spm_kick_im_to_fetch(pcmdesc);
+ spm_set_power_control(pwrctrl);
+ spm_set_wakeup_event(pwrctrl);
+ spm_kick_pcm_to_run(pwrctrl);
+ set_mcdi_ready();
+ }
+ spm_mcdi_wfi_sel_enter(mpidr);
+ if (afflvl == MPIDR_AFFLVL1)
+ spm_mcdi_set_cputop_pwrctrl_for_cluster_off(mpidr);
+ spm_lock_release();
+}
+
+void spm_mcdi_finish_for_on_state(unsigned long mpidr, unsigned int afflvl)
+{
+ unsigned long linear_id;
+
+ linear_id = ((mpidr & MPIDR_CLUSTER_MASK) >> 6) |
+ (mpidr & MPIDR_CPU_MASK);
+
+ spm_lock_get();
+ spm_mcdi_clear_cputop_pwrctrl_for_cluster_on(mpidr);
+ spm_mcdi_wfi_sel_leave(mpidr);
+ mmio_write_32(SPM_PCM_SW_INT_CLEAR, (0x1 << linear_id));
+ spm_lock_release();
+}
diff --git a/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h b/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h
new file mode 100644
index 0000000..7f3f96e
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef SPM_MCDI_H
+#define SPM_MCDI_H
+
+void spm_mcdi_wakeup_all_cores(void);
+void spm_mcdi_prepare_for_mtcmos(void);
+void spm_mcdi_prepare_for_off_state(unsigned long mpidr, unsigned int afflvl);
+void spm_mcdi_finish_for_on_state(unsigned long mpidr, unsigned int afflvl);
+
+#endif /* SPM_MCDI_H */
diff --git a/plat/mediatek/mt8173/drivers/spm/spm_suspend.c b/plat/mediatek/mt8173/drivers/spm/spm_suspend.c
new file mode 100644
index 0000000..838455d
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm_suspend.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include <mt8173_def.h>
+#include <spm.h>
+#include <spm_suspend.h>
+
+/*
+ * System Power Manager (SPM) is a hardware module, which controls cpu or
+ * system power for different power scenarios using different firmware.
+ * This driver controls the system power in system suspend flow.
+ */
+
+#define WAKE_SRC_FOR_SUSPEND \
+ (WAKE_SRC_KP | WAKE_SRC_EINT | WAKE_SRC_MD32 | \
+ WAKE_SRC_USB_CD | WAKE_SRC_USB_PDN | WAKE_SRC_THERM | \
+ WAKE_SRC_SYSPWREQ | WAKE_SRC_ALL_MD32)
+
+#define WAKE_SRC_FOR_MD32 0
+
+#define spm_is_wakesrc_invalid(wakesrc) \
+ (!!((unsigned int)(wakesrc) & 0xc0003803))
+
+#define ARMCA15PLL_CON0 (APMIXED_BASE + 0x200)
+#define ARMCA15PLL_CON1 (APMIXED_BASE + 0x204)
+#define ARMCA15PLL_PWR_CON0 (APMIXED_BASE + 0x20c)
+#define ARMCA15PLL_PWR_ON (1U << 0)
+#define ARMCA15PLL_ISO_EN (1U << 1)
+#define ARMCA15PLL_EN (1U << 0)
+
+const unsigned int spm_flags =
+ SPM_DUALVCORE_PDN_DIS | SPM_PASR_DIS | SPM_DPD_DIS |
+ SPM_CPU_DVS_DIS | SPM_OPT | SPM_INFRA_PDN_DIS;
+
+enum wake_reason_t spm_wake_reason = WR_NONE;
+
+/**********************************************************
+ * PCM sequence for cpu suspend
+ **********************************************************/
+static const unsigned int suspend_binary_ca7[] = {
+ 0x81f58407, 0x81f68407, 0x803a0400, 0x803a8400, 0x1b80001f, 0x20000000,
+ 0x80300400, 0x80318400, 0x80328400, 0xa1d28407, 0x81f20407, 0x81009801,
+ 0xd8000244, 0x17c07c1f, 0x18c0001f, 0x10006234, 0xc0c032e0, 0x1200041f,
+ 0x80310400, 0x1b80001f, 0x2000000a, 0xa0110400, 0x18c0001f, 0x100062c8,
+ 0xe0e00010, 0xe0e00030, 0xe0e00070, 0xe0e000f0, 0x1b80001f, 0x2000001a,
+ 0xe0e00ff0, 0xe8208000, 0x10006354, 0xfffe7fff, 0xe8208000, 0x10006834,
+ 0x00000010, 0x81f00407, 0xa1dd0407, 0x81fd0407, 0xc2803800, 0x1290041f,
+ 0x8880000c, 0x2f7be75f, 0xd8200722, 0x17c07c1f, 0xd82006a9, 0x17c07c1f,
+ 0xe8208000, 0x10006814, 0x00000001, 0xc2803800, 0x1293841f, 0x1b00001f,
+ 0x7fffe7ff, 0xd0000760, 0x17c07c1f, 0x1b00001f, 0x7ffff7ff, 0xf0000000,
+ 0x17c07c1f, 0x80880001, 0xd8000842, 0x17c07c1f, 0xd00028e0, 0x1200041f,
+ 0xe8208000, 0x10006834, 0x00000000, 0x1b00001f, 0x3fffe7ff, 0x1b80001f,
+ 0x20000004, 0xd8200a0c, 0x17c07c1f, 0xe8208000, 0x10006834, 0x00000010,
+ 0xd0001280, 0x17c07c1f, 0x18c0001f, 0x10006608, 0x1910001f, 0x10006608,
+ 0x813b0404, 0xe0c00004, 0x1880001f, 0x10006320, 0xc0c03760, 0xe080000f,
+ 0xd8200c03, 0x17c07c1f, 0x1b00001f, 0x7ffff7ff, 0xd0001280, 0x17c07c1f,
+ 0xe080001f, 0xe8208000, 0x10006354, 0xffffffff, 0x18c0001f, 0x100062c8,
+ 0xe0e000f0, 0xe0e00030, 0xe0e00000, 0x81009801, 0xd80010c4, 0x17c07c1f,
+ 0x18c0001f, 0x10004094, 0x1910001f, 0x1020e374, 0xe0c00004, 0x18c0001f,
+ 0x10004098, 0x1910001f, 0x1020e378, 0xe0c00004, 0x18c0001f, 0x10011094,
+ 0x1910001f, 0x10213374, 0xe0c00004, 0x18c0001f, 0x10011098, 0x1910001f,
+ 0x10213378, 0xe0c00004, 0x1910001f, 0x10213378, 0x18c0001f, 0x10006234,
+ 0xc0c034a0, 0x17c07c1f, 0xc2803800, 0x1290841f, 0xa1d20407, 0x81f28407,
+ 0xa1d68407, 0xa0128400, 0xa0118400, 0xa0100400, 0xa01a8400, 0xa01a0400,
+ 0x19c0001f, 0x001c239f, 0x1b00001f, 0x3fffefff, 0xf0000000, 0x17c07c1f,
+ 0x808d8001, 0xd8201502, 0x17c07c1f, 0x803d8400, 0x1b80001f, 0x2000001a,
+ 0x80340400, 0x17c07c1f, 0x17c07c1f, 0x80310400, 0x81fa0407, 0x81f18407,
+ 0x81f08407, 0xa1dc0407, 0x1b80001f, 0x200000b6, 0xd0002220, 0x17c07c1f,
+ 0x1880001f, 0x20000208, 0x81011801, 0xd80016e4, 0x17c07c1f, 0xe8208000,
+ 0x1000f600, 0xd2000000, 0x1380081f, 0x18c0001f, 0x10006240, 0xe0e00016,
+ 0xe0e0001e, 0xe0e0000e, 0xe0e0000f, 0x80368400, 0x1380081f, 0x80370400,
+ 0x1380081f, 0x80360400, 0x803e0400, 0x1380081f, 0x80380400, 0x803b0400,
+ 0xa01d8400, 0x1b80001f, 0x20000034, 0x803d8400, 0x1b80001f, 0x20000152,
+ 0x803d0400, 0x1380081f, 0x18c0001f, 0x1000f5c8, 0x1910001f, 0x1000f5c8,
+ 0xa1000404, 0xe0c00004, 0x18c0001f, 0x100125c8, 0x1910001f, 0x100125c8,
+ 0xa1000404, 0xe0c00004, 0x1910001f, 0x100125c8, 0x80340400, 0x17c07c1f,
+ 0x17c07c1f, 0x80310400, 0xe8208000, 0x10000044, 0x00000100, 0x1b80001f,
+ 0x20000068, 0x1b80001f, 0x2000000a, 0x18c0001f, 0x10006240, 0xe0e0000d,
+ 0x81011801, 0xd8001f64, 0x17c07c1f, 0x18c0001f, 0x100040f4, 0x1910001f,
+ 0x100040f4, 0xa11c8404, 0xe0c00004, 0x1b80001f, 0x2000000a, 0x813c8404,
+ 0xe0c00004, 0x18c0001f, 0x100110f4, 0x1910001f, 0x100110f4, 0xa11c8404,
+ 0xe0c00004, 0x1b80001f, 0x2000000a, 0x813c8404, 0xe0c00004, 0x1b80001f,
+ 0x20000100, 0x81fa0407, 0x81f18407, 0x81f08407, 0xe8208000, 0x10006354,
+ 0xfffe7b47, 0x18c0001f, 0x65930003, 0xc0c031c0, 0x17c07c1f, 0xc2803800,
+ 0x1293041f, 0xa1d80407, 0xa1dc0407, 0x18c0001f, 0x10006608, 0x1910001f,
+ 0x10006608, 0xa11b0404, 0xe0c00004, 0xc2803800, 0x1291041f, 0x8880000c,
+ 0x2f7be75f, 0xd8202362, 0x17c07c1f, 0x1b00001f, 0x3fffe7ff, 0xd00023a0,
+ 0x17c07c1f, 0x1b00001f, 0xbfffe7ff, 0xf0000000, 0x17c07c1f, 0x1890001f,
+ 0x10006608, 0x808b0801, 0xd8202642, 0x17c07c1f, 0x1880001f, 0x10006320,
+ 0xc0c03540, 0xe080000f, 0xd80027a3, 0x17c07c1f, 0xe080001f, 0xa1da0407,
+ 0x81fc0407, 0xa0110400, 0xa0140400, 0xa01d8400, 0xd0003100, 0x17c07c1f,
+ 0x1b80001f, 0x20000fdf, 0x1890001f, 0x10006608, 0x80c98801, 0x810a8801,
+ 0x10918c1f, 0xa0939002, 0x8080080d, 0xd82028e2, 0x12007c1f, 0x1b00001f,
+ 0x3fffe7ff, 0x1b80001f, 0x20000004, 0xd800318c, 0x17c07c1f, 0x1b00001f,
+ 0xbfffe7ff, 0xd0003180, 0x17c07c1f, 0x81f80407, 0x81fc0407, 0x18c0001f,
+ 0x65930006, 0xc0c031c0, 0x17c07c1f, 0x18c0001f, 0x65930007, 0xc0c031c0,
+ 0x17c07c1f, 0x1880001f, 0x10006320, 0xc0c03540, 0xe080000f, 0xd80027a3,
+ 0x17c07c1f, 0xe080001f, 0x18c0001f, 0x65930005, 0xc0c031c0, 0x17c07c1f,
+ 0xa1da0407, 0xe8208000, 0x10000048, 0x00000100, 0x1b80001f, 0x20000068,
+ 0xa0110400, 0xa0140400, 0x18c0001f, 0x1000f5c8, 0x1910001f, 0x1000f5c8,
+ 0x81200404, 0xe0c00004, 0x18c0001f, 0x100125c8, 0x1910001f, 0x100125c8,
+ 0x81200404, 0xe0c00004, 0x1910001f, 0x100125c8, 0xa01d0400, 0xa01b0400,
+ 0xa0180400, 0x803d8400, 0xa01e0400, 0xa0160400, 0xa0170400, 0xa0168400,
+ 0x1b80001f, 0x20000104, 0x81011801, 0xd80030c4, 0x17c07c1f, 0x18c0001f,
+ 0x10006240, 0xc0c034a0, 0x17c07c1f, 0xe8208000, 0x1000f600, 0xd2000001,
+ 0xd8000848, 0x17c07c1f, 0xc2803800, 0x1291841f, 0x1b00001f, 0x7ffff7ff,
+ 0xf0000000, 0x17c07c1f, 0x1900001f, 0x10006830, 0xe1000003, 0x18c0001f,
+ 0x10006834, 0xe0e00000, 0xe0e00001, 0xf0000000, 0x17c07c1f, 0xe0f07f16,
+ 0x1380201f, 0xe0f07f1e, 0x1380201f, 0xe0f07f0e, 0x1b80001f, 0x20000104,
+ 0xe0f07f0c, 0xe0f07f0d, 0xe0f07e0d, 0xe0f07c0d, 0xe0f0780d, 0xf0000000,
+ 0xe0f0700d, 0xe0f07f0d, 0xe0f07f0f, 0xe0f07f1e, 0xf0000000, 0xe0f07f12,
+ 0x11407c1f, 0x81f08407, 0x81f18407, 0x1b80001f, 0x20000001, 0xa1d08407,
+ 0xa1d18407, 0x1392841f, 0x812ab401, 0x80ebb401, 0xa0c00c04, 0xd8203743,
+ 0x17c07c1f, 0x80c01403, 0xd8203563, 0x01400405, 0xf0000000, 0xa1d00407,
+ 0x1b80001f, 0x20000208, 0x80ea3401, 0xf0000000, 0x18c0001f, 0x10006b6c,
+ 0x1910001f, 0x10006b6c, 0xa1002804, 0xf0000000, 0xe0c00004, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f, 0x17c07c1f,
+ 0x17c07c1f, 0x17c07c1f, 0x1840001f, 0x00000001, 0xa1d48407, 0x1990001f,
+ 0x10006b08, 0x1a50001f, 0x10006610, 0x8246a401, 0xe8208000, 0x10006b6c,
+ 0x00000000, 0x1b00001f, 0x2f7be75f, 0x81469801, 0xd8004305, 0x17c07c1f,
+ 0x1b80001f, 0xd00f0000, 0x8880000c, 0x2f7be75f, 0xd8005fa2, 0x17c07c1f,
+ 0xd0004340, 0x17c07c1f, 0x1b80001f, 0x500f0000, 0xe8208000, 0x10006354,
+ 0xfffe7b47, 0xc0c06c00, 0x81401801, 0xd80048e5, 0x17c07c1f, 0x81f60407,
+ 0x18c0001f, 0x10006200, 0xc0c06060, 0x12807c1f, 0xe8208000, 0x1000625c,
+ 0x00000001, 0x1b80001f, 0x20000080, 0xc0c06060, 0x1280041f, 0x18c0001f,
+ 0x10006204, 0xc0c06400, 0x1280041f, 0x18c0001f, 0x10006208, 0xc0c06060,
+ 0x12807c1f, 0xe8208000, 0x10006244, 0x00000001, 0x1b80001f, 0x20000080,
+ 0xc0c06060, 0x1280041f, 0x18d0001f, 0x10200200, 0x18c0001f, 0x10006290,
+ 0xc0c06060, 0x1280041f, 0xe8208000, 0x10006404, 0x00003101, 0xc2803800,
+ 0x1292041f, 0x81469801, 0xd8204a45, 0x17c07c1f, 0x1b00001f, 0x2f7be75f,
+ 0x1b80001f, 0x30000004, 0x8880000c, 0x2f7be75f, 0xd8005a02, 0x17c07c1f,
+ 0xc0c06780, 0x17c07c1f, 0x18c0001f, 0x10006294, 0xe0f07fff, 0xe0e00fff,
+ 0xe0e000ff, 0x81449801, 0xd8004c85, 0x17c07c1f, 0x1a00001f, 0x10006604,
+ 0xe2200003, 0xc0c06840, 0x17c07c1f, 0xe2200005, 0xc0c06840, 0x17c07c1f,
+ 0xa1d38407, 0xa1d98407, 0x1800001f, 0x00000012, 0x1800001f, 0x00000e12,
+ 0x1800001f, 0x03800e12, 0x1800001f, 0x038e0e12, 0xe8208000, 0x10006310,
+ 0x0b1600f8, 0x1940001f, 0x00000000, 0x12407c1f, 0x1b00001f, 0xbfffe7ff,
+ 0x1b80001f, 0x90100000, 0x17c07c1f, 0xd8004fc5, 0x17c07c1f, 0x8247b001,
+ 0x1940001f, 0xffffffff, 0x80c00400, 0xd82050c3, 0xa1d58407, 0xa1dd8407,
+ 0x1b00001f, 0x3fffefff, 0xd0004ec0, 0x17c07c1f, 0x1890001f, 0x100063e8,
+ 0x88c0000c, 0x2f7be75f, 0xd80052e3, 0x17c07c1f, 0x80c40001, 0xd8005263,
+ 0x17c07c1f, 0x1b00001f, 0xbfffe7ff, 0xd00052a0, 0x17c07c1f, 0x1b00001f,
+ 0x7ffff7ff, 0xd0004ec0, 0x17c07c1f, 0x80c40001, 0xd82053e3, 0x17c07c1f,
+ 0xa1de0407, 0x1b00001f, 0x7fffe7ff, 0xd0004ec0, 0x17c07c1f, 0xe8208000,
+ 0x10006814, 0x00000000, 0x18c0001f, 0x10006b00, 0xe0e00000, 0xe0c00009,
+ 0x18c0001f, 0x10006294, 0xe0e001fe, 0xe0e003fc, 0xe0e007f8, 0xe0e00ff0,
+ 0x1b80001f, 0x20000020, 0xe0f07ff0, 0xe0f07f00, 0x81449801, 0xd80057a5,
+ 0x17c07c1f, 0x1a00001f, 0x10006604, 0xe2200002, 0xc0c06840, 0x17c07c1f,
+ 0xe2200004, 0xc0c06840, 0x17c07c1f, 0x1b80001f, 0x200016a8, 0x1800001f,
+ 0x03800e12, 0x1b80001f, 0x20000300, 0x1800001f, 0x00000e12, 0x1b80001f,
+ 0x20000300, 0x1800001f, 0x00000012, 0x1b80001f, 0x20000104, 0x10007c1f,
+ 0x81f38407, 0x81f98407, 0x81f90407, 0x81f40407, 0x1b80001f, 0x200016a8,
+ 0x81401801, 0xd8005fa5, 0x17c07c1f, 0xe8208000, 0x10006404, 0x00002101,
+ 0x18c0001f, 0x10006290, 0x1212841f, 0xc0c061e0, 0x12807c1f, 0xc0c061e0,
+ 0x1280041f, 0x18c0001f, 0x10006208, 0x1212841f, 0xc0c061e0, 0x12807c1f,
+ 0xe8208000, 0x10006244, 0x00000000, 0x1b80001f, 0x20000080, 0xc0c061e0,
+ 0x1280041f, 0xe8208000, 0x10200268, 0x000ffffe, 0x18c0001f, 0x10006204,
+ 0x1212841f, 0xc0c065a0, 0x1280041f, 0x18c0001f, 0x10006200, 0x1212841f,
+ 0xc0c061e0, 0x12807c1f, 0xe8208000, 0x1000625c, 0x00000000, 0x1b80001f,
+ 0x20000080, 0xc0c061e0, 0x1280041f, 0x19c0001f, 0x01411820, 0x1ac0001f,
+ 0x55aa55aa, 0x10007c1f, 0xf0000000, 0xd800610a, 0x17c07c1f, 0xe2e0004f,
+ 0xe2e0006f, 0xe2e0002f, 0xd82061aa, 0x17c07c1f, 0xe2e0002e, 0xe2e0003e,
+ 0xe2e00032, 0xf0000000, 0x17c07c1f, 0xd80062aa, 0x17c07c1f, 0xe2e00036,
+ 0xe2e0003e, 0x1380201f, 0xe2e0003c, 0xd82063ca, 0x17c07c1f, 0x1380201f,
+ 0xe2e0007c, 0x1b80001f, 0x20000003, 0xe2e0005c, 0xe2e0004c, 0xe2e0004d,
+ 0xf0000000, 0x17c07c1f, 0x1a50001f, 0x10006610, 0x8246a401, 0xd8206569,
+ 0x17c07c1f, 0xe2e0000d, 0xe2e0000c, 0xe2e0001c, 0xe2e0001e, 0xe2e00016,
+ 0xe2e00012, 0xf0000000, 0x17c07c1f, 0x1a50001f, 0x10006610, 0x8246a401,
+ 0xd8206749, 0x17c07c1f, 0xe2e00016, 0x1380201f, 0xe2e0001e, 0x1380201f,
+ 0xe2e0001c, 0x1380201f, 0xe2e0000c, 0xe2e0000d, 0xf0000000, 0x17c07c1f,
+ 0xa1d40407, 0x1391841f, 0xa1d90407, 0x1393041f, 0xf0000000, 0x17c07c1f,
+ 0x18d0001f, 0x10006604, 0x10cf8c1f, 0xd8206843, 0x17c07c1f, 0xf0000000,
+ 0x17c07c1f, 0xe8208000, 0x11008014, 0x00000002, 0xe8208000, 0x11008020,
+ 0x00000101, 0xe8208000, 0x11008004, 0x000000d0, 0x1a00001f, 0x11008000,
+ 0xd8006b0a, 0xe220005d, 0xd8206b2a, 0xe2200000, 0xe2200001, 0xe8208000,
+ 0x11008024, 0x00000001, 0x1b80001f, 0x20000424, 0xf0000000, 0x17c07c1f,
+ 0xa1d10407, 0x1b80001f, 0x20000020, 0xf0000000, 0x17c07c1f
+};
+
+/*
+ * PCM binary for suspend scenario
+ */
+static const struct pcm_desc suspend_pcm_ca7 = {
+ .version = "pcm_suspend_20150917_V4",
+ .base = suspend_binary_ca7,
+ .size = 869,
+ .sess = 2,
+ .replace = 0,
+ .vec0 = EVENT_VEC(11, 1, 0, 0),
+ .vec1 = EVENT_VEC(12, 1, 0, 61),
+ .vec2 = EVENT_VEC(30, 1, 0, 150),
+ .vec3 = EVENT_VEC(31, 1, 0, 287),
+};
+
+/*
+ * SPM settings for suspend scenario
+ */
+static struct pwr_ctrl spm_ctrl = {
+ .wake_src = WAKE_SRC_FOR_SUSPEND,
+ .wake_src_md32 = WAKE_SRC_FOR_MD32,
+ .r0_ctrl_en = 1,
+ .r7_ctrl_en = 1,
+ .infra_dcm_lock = 1,
+ .wfi_op = WFI_OP_AND,
+ .pcm_apsrc_req = 0,
+ .ca7top_idle_mask = 0,
+ .ca15top_idle_mask = 0,
+ .mcusys_idle_mask = 0,
+ .disp_req_mask = 0,
+ .mfg_req_mask = 0,
+ .md32_req_mask = 1,
+ .srclkenai_mask = 1,
+ .ca7_wfi0_en = 1,
+ .ca7_wfi1_en = 1,
+ .ca7_wfi2_en = 1,
+ .ca7_wfi3_en = 1,
+ .ca15_wfi0_en = 1,
+ .ca15_wfi1_en = 1,
+ .ca15_wfi2_en = 1,
+ .ca15_wfi3_en = 1,
+};
+
+/*
+ * go_to_sleep_before_wfi() - trigger SPM to enter suspend scenario
+ */
+static void go_to_sleep_before_wfi(const unsigned int flags_spm)
+{
+ struct pwr_ctrl *pwrctrl;
+
+ pwrctrl = &spm_ctrl;
+
+ set_pwrctrl_pcm_flags(pwrctrl, flags_spm);
+
+ spm_set_sysclk_settle();
+
+ INFO("sec = %u, wakesrc = 0x%x (%u)(%u)\n",
+ pwrctrl->timer_val, pwrctrl->wake_src,
+ is_cpu_pdn(pwrctrl->pcm_flags),
+ is_infra_pdn(pwrctrl->pcm_flags));
+
+ spm_reset_and_init_pcm();
+ spm_init_pcm_register();
+ spm_set_power_control(pwrctrl);
+ spm_set_wakeup_event(pwrctrl);
+ spm_kick_pcm_to_run(pwrctrl);
+ spm_init_event_vector(&suspend_pcm_ca7);
+ spm_kick_im_to_fetch(&suspend_pcm_ca7);
+}
+
+/*
+ * go_to_sleep_after_wfi() - get wakeup reason after
+ * leaving suspend scenario and clean up SPM settings
+ */
+static enum wake_reason_t go_to_sleep_after_wfi(void)
+{
+ struct wake_status wakesta;
+ static enum wake_reason_t last_wr = WR_NONE;
+
+ spm_get_wakeup_status(&wakesta);
+ spm_clean_after_wakeup();
+ last_wr = spm_output_wake_reason(&wakesta);
+
+ return last_wr;
+}
+
+static void bigcore_pll_on(void)
+{
+ mmio_setbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_PWR_ON);
+ mmio_clrbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_ISO_EN);
+ mmio_setbits_32(ARMCA15PLL_CON0, ARMCA15PLL_EN);
+}
+
+static void bigcore_pll_off(void)
+{
+ mmio_clrbits_32(ARMCA15PLL_CON0, ARMCA15PLL_EN);
+ mmio_setbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_ISO_EN);
+ mmio_clrbits_32(ARMCA15PLL_PWR_CON0, ARMCA15PLL_PWR_ON);
+}
+
+void spm_system_suspend(void)
+{
+ bigcore_pll_off();
+ spm_lock_get();
+ go_to_sleep_before_wfi(spm_flags);
+ set_suspend_ready();
+ spm_lock_release();
+}
+
+void spm_system_suspend_finish(void)
+{
+ spm_lock_get();
+ spm_wake_reason = go_to_sleep_after_wfi();
+ INFO("spm_wake_reason=%d\n", spm_wake_reason);
+ clear_all_ready();
+ spm_lock_release();
+ bigcore_pll_on();
+ /* Add 20us delay for turning on PLL*/
+ udelay(20);
+}
diff --git a/plat/mediatek/mt8173/drivers/spm/spm_suspend.h b/plat/mediatek/mt8173/drivers/spm/spm_suspend.h
new file mode 100644
index 0000000..b00faa9
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/spm/spm_suspend.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef SPM_SUSPEND_H
+#define SPM_SUSPEND_H
+
+/* cpu dormant return code */
+#define CPU_DORMANT_RESET 0
+#define CPU_DORMANT_ABORT 1
+
+void spm_system_suspend(void);
+void spm_system_suspend_finish(void);
+
+#endif /* SPM_SUSPEND_H*/
diff --git a/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c b/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c
new file mode 100644
index 0000000..174a24d
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <mt8173_def.h>
+#include <mt_cpuxgpt.h>
+
+static void write_cpuxgpt(unsigned int reg_index, unsigned int value)
+{
+ mmio_write_32((uintptr_t)&mt8173_mcucfg->xgpt_idx, reg_index);
+ mmio_write_32((uintptr_t)&mt8173_mcucfg->xgpt_ctl, value);
+}
+
+static void cpuxgpt_set_init_cnt(unsigned int countH, unsigned int countL)
+{
+ write_cpuxgpt(INDEX_CNT_H_INIT, countH);
+ /* update count when countL programmed */
+ write_cpuxgpt(INDEX_CNT_L_INIT, countL);
+}
+
+void generic_timer_backup(void)
+{
+ uint64_t cval;
+
+ cval = read_cntpct_el0();
+ cpuxgpt_set_init_cnt((uint32_t)(cval >> 32),
+ (uint32_t)(cval & 0xffffffff));
+}
diff --git a/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h b/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h
new file mode 100644
index 0000000..8c0fe83
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPUXGPT_H
+#define MT_CPUXGPT_H
+
+/* REG */
+#define INDEX_CNT_L_INIT 0x008
+#define INDEX_CNT_H_INIT 0x00C
+
+void generic_timer_backup(void);
+
+#endif /* MT_CPUXGPT_H */
diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.c b/plat/mediatek/mt8173/drivers/wdt/wdt.c
new file mode 100644
index 0000000..40f57ee
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/wdt/wdt.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt8173_def.h>
+#include <plat_sip_calls.h>
+#include <lib/psci/psci.h>
+#include <smccc_helpers.h>
+#include <wdt.h>
+
+#define WDT_BASE (RGU_BASE + 0)
+#define WDT_MODE (WDT_BASE + 0x00)
+#define WDT_LENGTH (WDT_BASE + 0x04)
+#define WDT_RESTART (WDT_BASE + 0x08)
+#define WDT_SWRST (WDT_BASE + 0x14)
+
+#define WDT_MODE_DUAL_MODE 0x40
+#define WDT_MODE_IRQ 0x8
+#define WDT_MODE_KEY 0x22000000
+#define WDT_MODE_EXTEN 0x4
+#define WDT_MODE_EN 0x1
+#define WDT_LENGTH_KEY 0x8
+#define WDT_RESTART_KEY 0x1971
+#define WDT_SWRST_KEY 0x1209
+
+
+#define WDT_MIN_TIMEOUT 1
+#define WDT_MAX_TIMEOUT 31
+
+enum smcwd_call {
+ SMCWD_INFO = 0,
+ SMCWD_SET_TIMEOUT = 1,
+ SMCWD_ENABLE = 2,
+ SMCWD_PET = 3,
+};
+
+static int wdt_enabled_before_suspend;
+
+/*
+ * We expect the WDT registers to be correctly initialized by BL2 firmware
+ * (which may be board specific), so we do not reinitialize them here.
+ */
+
+void wdt_trigger_reset(void)
+{
+ mmio_write_32(WDT_SWRST, WDT_SWRST_KEY);
+}
+
+void wdt_pet(void)
+{
+ mmio_write_32(WDT_RESTART, WDT_RESTART_KEY);
+}
+
+int wdt_set_timeout(uint32_t timeout)
+{
+ /* One tick here equals 512 32KHz ticks. 512 / 32000 * 125 / 2 = 1 */
+ uint32_t ticks = timeout * 125 / 2;
+
+ if (timeout < WDT_MIN_TIMEOUT || timeout > WDT_MAX_TIMEOUT)
+ return PSCI_E_INVALID_PARAMS;
+
+ mmio_write_32(WDT_LENGTH, ticks << 5 | WDT_LENGTH_KEY);
+
+ return PSCI_E_SUCCESS;
+}
+
+void wdt_set_enable(int enable)
+{
+ if (enable)
+ wdt_pet();
+ mmio_clrsetbits_32(WDT_MODE, WDT_MODE_EN,
+ WDT_MODE_KEY | (enable ? WDT_MODE_EN : 0));
+}
+
+void wdt_suspend(void)
+{
+ wdt_enabled_before_suspend = mmio_read_32(WDT_MODE) & WDT_MODE_EN;
+ if (wdt_enabled_before_suspend)
+ wdt_set_enable(0);
+}
+
+void wdt_resume(void)
+{
+ if (wdt_enabled_before_suspend)
+ wdt_set_enable(1);
+}
+
+uint64_t wdt_smc_handler(uint32_t x1,
+ uint32_t x2,
+ void *handle)
+{
+ int ret;
+
+ switch (x1) {
+ case SMCWD_INFO:
+ SMC_RET3(handle, PSCI_E_SUCCESS,
+ WDT_MIN_TIMEOUT, WDT_MAX_TIMEOUT);
+ case SMCWD_SET_TIMEOUT:
+ ret = wdt_set_timeout(x2);
+ SMC_RET1(handle, ret);
+ case SMCWD_ENABLE:
+ wdt_set_enable(x2 > 0);
+ SMC_RET1(handle, PSCI_E_SUCCESS);
+ case SMCWD_PET:
+ wdt_pet();
+ SMC_RET1(handle, PSCI_E_SUCCESS);
+ default:
+ ERROR("Unimplemented SMCWD call (%d)\n", x1);
+ SMC_RET1(handle, PSCI_E_NOT_SUPPORTED);
+ }
+}
diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.h b/plat/mediatek/mt8173/drivers/wdt/wdt.h
new file mode 100644
index 0000000..7262a57
--- /dev/null
+++ b/plat/mediatek/mt8173/drivers/wdt/wdt.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef WDT_H
+#define WDT_H
+
+#include "stdint.h"
+
+void wdt_pet(void);
+void wdt_resume(void);
+void wdt_set_enable(int enable);
+int wdt_set_timeout(uint32_t timeout);
+uint64_t wdt_smc_handler(uint32_t x1, uint32_t x2, void *handle);
+void wdt_suspend(void);
+void wdt_trigger_reset(void);
+
+#endif /* WDT_H */
diff --git a/plat/mediatek/mt8173/include/mcucfg.h b/plat/mediatek/mt8173/include/mcucfg.h
new file mode 100644
index 0000000..dedbc08
--- /dev/null
+++ b/plat/mediatek/mt8173/include/mcucfg.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef MCUCFG_H
+#define MCUCFG_H
+
+#include <stdint.h>
+
+#include <mt8173_def.h>
+
+struct mt8173_mcucfg_regs {
+ uint32_t mp0_ca7l_cache_config;
+ struct {
+ uint32_t mem_delsel0;
+ uint32_t mem_delsel1;
+ } mp0_cpu[4];
+ uint32_t mp0_cache_mem_delsel0;
+ uint32_t mp0_cache_mem_delsel1;
+ uint32_t mp0_axi_config;
+ uint32_t mp0_misc_config[2];
+ struct {
+ uint32_t rv_addr_lw;
+ uint32_t rv_addr_hw;
+ } mp0_rv_addr[4];
+ uint32_t mp0_ca7l_cfg_dis;
+ uint32_t mp0_ca7l_clken_ctrl;
+ uint32_t mp0_ca7l_rst_ctrl;
+ uint32_t mp0_ca7l_misc_config;
+ uint32_t mp0_ca7l_dbg_pwr_ctrl;
+ uint32_t mp0_rw_rsvd0;
+ uint32_t mp0_rw_rsvd1;
+ uint32_t mp0_ro_rsvd;
+ uint32_t reserved0_0[100];
+ uint32_t mp1_cpucfg;
+ uint32_t mp1_miscdbg;
+ uint32_t reserved0_1[13];
+ uint32_t mp1_rst_ctl;
+ uint32_t mp1_clkenm_div;
+ uint32_t reserved0_2[7];
+ uint32_t mp1_config_res;
+ uint32_t reserved0_3[13];
+ struct {
+ uint32_t rv_addr_lw;
+ uint32_t rv_addr_hw;
+ } mp1_rv_addr[2];
+ uint32_t reserved0_4[84];
+ uint32_t mp0_rst_status; /* 0x400 */
+ uint32_t mp0_dbg_ctrl;
+ uint32_t mp0_dbg_flag;
+ uint32_t mp0_ca7l_ir_mon;
+ struct {
+ uint32_t pc_lw;
+ uint32_t pc_hw;
+ uint32_t fp_arch32;
+ uint32_t sp_arch32;
+ uint32_t fp_arch64_lw;
+ uint32_t fp_arch64_hw;
+ uint32_t sp_arch64_lw;
+ uint32_t sp_arch64_hw;
+ } mp0_dbg_core[4];
+ uint32_t dfd_ctrl;
+ uint32_t dfd_cnt_l;
+ uint32_t dfd_cnt_h;
+ uint32_t misccfg_mp0_rw_rsvd;
+ uint32_t misccfg_sec_vio_status0;
+ uint32_t misccfg_sec_vio_status1;
+ uint32_t reserved1[22];
+ uint32_t misccfg_rw_rsvd; /* 0x500 */
+ uint32_t mcusys_dbg_mon_sel_a;
+ uint32_t mcusys_dbg_mon;
+ uint32_t reserved2[61];
+ uint32_t mcusys_config_a; /* 0x600 */
+ uint32_t mcusys_config1_a;
+ uint32_t mcusys_gic_peribase_a;
+ uint32_t reserved3;
+ uint32_t sec_range0_start; /* 0x610 */
+ uint32_t sec_range0_end;
+ uint32_t sec_range_enable;
+ uint32_t reserved4;
+ uint32_t int_pol_ctl[8]; /* 0x620 */
+ uint32_t aclken_div; /* 0x640 */
+ uint32_t pclken_div;
+ uint32_t l2c_sram_ctrl;
+ uint32_t armpll_jit_ctrl;
+ uint32_t cci_addrmap; /* 0x650 */
+ uint32_t cci_config;
+ uint32_t cci_periphbase;
+ uint32_t cci_nevntcntovfl;
+ uint32_t cci_clk_ctrl; /* 0x660 */
+ uint32_t cci_acel_s1_ctrl;
+ uint32_t bus_fabric_dcm_ctrl;
+ uint32_t reserved5;
+ uint32_t xgpt_ctl; /* 0x670 */
+ uint32_t xgpt_idx;
+ uint32_t ptpod2_ctl0;
+ uint32_t ptpod2_ctl1;
+ uint32_t mcusys_revid;
+ uint32_t mcusys_rw_rsvd0;
+ uint32_t mcusys_rw_rsvd1;
+};
+
+static struct mt8173_mcucfg_regs *const mt8173_mcucfg = (void *)MCUCFG_BASE;
+
+/* cpu boot mode */
+#define MP0_CPUCFG_64BIT_SHIFT 12
+#define MP1_CPUCFG_64BIT_SHIFT 28
+#define MP0_CPUCFG_64BIT (U(0xf) << MP0_CPUCFG_64BIT_SHIFT)
+#define MP1_CPUCFG_64BIT (U(0xf) << MP1_CPUCFG_64BIT_SHIFT)
+
+/* scu related */
+enum {
+ MP0_ACINACTM_SHIFT = 4,
+ MP1_ACINACTM_SHIFT = 0,
+ MP0_ACINACTM = 1 << MP0_ACINACTM_SHIFT,
+ MP1_ACINACTM = 1 << MP1_ACINACTM_SHIFT
+};
+
+enum {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16,
+
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+ MP1_AINACTS_SHIFT = 4,
+ MP1_AINACTS = 1 << MP1_AINACTS_SHIFT
+};
+
+enum {
+ MP1_SW_CG_GEN_SHIFT = 12,
+ MP1_SW_CG_GEN = 1 << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+ MP1_L2RSTDISABLE_SHIFT = 14,
+ MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT
+};
+
+/* cci clock control related */
+enum {
+ MCU_BUS_DCM_EN = 1 << 8
+};
+
+/* l2c sram control related */
+enum {
+ L2C_SRAM_DCM_EN = 1 << 0
+};
+
+/* bus fabric dcm control related */
+enum {
+ PSYS_ADB400_DCM_EN = 1 << 29,
+ GPU_ADB400_DCM_EN = 1 << 28,
+
+ EMI1_ADB400_DCM_EN = 1 << 27,
+ EMI_ADB400_DCM_EN = 1 << 26,
+ INFRA_ADB400_DCM_EN = 1 << 25,
+ L2C_ADB400_DCM_EN = 1 << 24,
+
+ MP0_ADB400_DCM_EN = 1 << 23,
+ CCI400_CK_ONLY_DCM_EN = 1 << 22,
+ L2C_IDLE_DCM_EN = 1 << 21,
+
+ CA15U_ADB_DYNAMIC_CG_EN = 1 << 19,
+ CA7L_ADB_DYNAMIC_CG_EN = 1 << 18,
+ L2C_ADB_DYNAMIC_CG_EN = 1 << 17,
+
+ EMICLK_EMI1_DYNAMIC_CG_EN = 1 << 12,
+
+ INFRACLK_PSYS_DYNAMIC_CG_EN = 1 << 11,
+ EMICLK_GPU_DYNAMIC_CG_EN = 1 << 10,
+ EMICLK_EMI_DYNAMIC_CG_EN = 1 << 8,
+
+ CCI400_SLV_RW_DCM_EN = 1 << 7,
+ CCI400_SLV_DCM_EN = 1 << 5,
+
+ ACLK_PSYS_DYNAMIC_CG_EN = 1 << 3,
+ ACLK_GPU_DYNAMIC_CG_EN = 1 << 2,
+ ACLK_EMI_DYNAMIC_CG_EN = 1 << 1,
+ ACLK_INFRA_DYNAMIC_CG_EN = 1 << 0,
+
+ /* adb400 related */
+ ADB400_GRP_DCM_EN = PSYS_ADB400_DCM_EN | GPU_ADB400_DCM_EN |
+ EMI1_ADB400_DCM_EN | EMI_ADB400_DCM_EN |
+ INFRA_ADB400_DCM_EN | L2C_ADB400_DCM_EN |
+ MP0_ADB400_DCM_EN,
+
+ /* cci400 related */
+ CCI400_GRP_DCM_EN = CCI400_CK_ONLY_DCM_EN | CCI400_SLV_RW_DCM_EN |
+ CCI400_SLV_DCM_EN,
+
+ /* adb clock related */
+ ADBCLK_GRP_DCM_EN = CA15U_ADB_DYNAMIC_CG_EN | CA7L_ADB_DYNAMIC_CG_EN |
+ L2C_ADB_DYNAMIC_CG_EN,
+
+ /* emi clock related */
+ EMICLK_GRP_DCM_EN = EMICLK_EMI1_DYNAMIC_CG_EN |
+ EMICLK_GPU_DYNAMIC_CG_EN |
+ EMICLK_EMI_DYNAMIC_CG_EN,
+
+ /* bus clock related */
+ ACLK_GRP_DCM_EN = ACLK_PSYS_DYNAMIC_CG_EN | ACLK_GPU_DYNAMIC_CG_EN |
+ ACLK_EMI_DYNAMIC_CG_EN | ACLK_INFRA_DYNAMIC_CG_EN,
+};
+
+#endif /* MCUCFG_H */
diff --git a/plat/mediatek/mt8173/include/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h
new file mode 100644
index 0000000..378b4da
--- /dev/null
+++ b/plat/mediatek/mt8173/include/mt8173_def.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT8173_DEF_H
+#define MT8173_DEF_H
+
+#if RESET_TO_BL31
+#error "MT8173 is incompatible with RESET_TO_BL31!"
+#endif
+
+#define MT8173_PRIMARY_CPU 0x0
+
+/* Register base address */
+#define IO_PHYS (0x10000000)
+#define INFRACFG_AO_BASE (IO_PHYS + 0x1000)
+#define SRAMROM_SEC_BASE (IO_PHYS + 0x1800)
+#define PERI_CON_BASE (IO_PHYS + 0x3000)
+#define GPIO_BASE (IO_PHYS + 0x5000)
+#define SPM_BASE (IO_PHYS + 0x6000)
+#define RGU_BASE (IO_PHYS + 0x7000)
+#define PMIC_WRAP_BASE (IO_PHYS + 0xD000)
+#define DEVAPC0_BASE (IO_PHYS + 0xE000)
+#define MCUCFG_BASE (IO_PHYS + 0x200000)
+#define APMIXED_BASE (IO_PHYS + 0x209000)
+#define TRNG_BASE (IO_PHYS + 0x20F000)
+#define CRYPT_BASE (IO_PHYS + 0x210000)
+#define MT_GIC_BASE (IO_PHYS + 0x220000)
+#define PLAT_MT_CCI_BASE (IO_PHYS + 0x390000)
+
+/* Aggregate of all devices in the first GB */
+#define MTK_DEV_RNG0_BASE IO_PHYS
+#define MTK_DEV_RNG0_SIZE 0x400000
+#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000)
+#define MTK_DEV_RNG1_SIZE 0x4000000
+
+/* SRAMROM related registers */
+#define SRAMROM_SEC_CTRL (SRAMROM_SEC_BASE + 0x4)
+#define SRAMROM_SEC_ADDR (SRAMROM_SEC_BASE + 0x8)
+
+/* DEVAPC0 related registers */
+#define DEVAPC0_MAS_SEC_0 (DEVAPC0_BASE + 0x500)
+#define DEVAPC0_APC_CON (DEVAPC0_BASE + 0xF00)
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define MT8173_UART0_BASE (IO_PHYS + 0x01002000)
+#define MT8173_UART1_BASE (IO_PHYS + 0x01003000)
+#define MT8173_UART2_BASE (IO_PHYS + 0x01004000)
+#define MT8173_UART3_BASE (IO_PHYS + 0x01005000)
+
+#define MT8173_BAUDRATE (115200)
+#define MT8173_UART_CLOCK (26000000)
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 13000000
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE (MT_GIC_BASE + 0x1000)
+#define BASE_GICC_BASE (MT_GIC_BASE + 0x2000)
+#define BASE_GICR_BASE 0 /* no GICR in GIC-400 */
+#define BASE_GICH_BASE (MT_GIC_BASE + 0x4000)
+#define BASE_GICV_BASE (MT_GIC_BASE + 0x6000)
+#define INT_POL_CTL0 0x10200620
+
+#define GIC_PRIVATE_SIGNALS (32)
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4
+#define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3
+
+/* FIQ platform related define */
+#define MT_IRQ_SEC_SGI_0 8
+#define MT_IRQ_SEC_SGI_1 9
+#define MT_IRQ_SEC_SGI_2 10
+#define MT_IRQ_SEC_SGI_3 11
+#define MT_IRQ_SEC_SGI_4 12
+#define MT_IRQ_SEC_SGI_5 13
+#define MT_IRQ_SEC_SGI_6 14
+#define MT_IRQ_SEC_SGI_7 15
+
+/*
+ * Macros for local power states in MTK platforms encoded by State-ID field
+ * within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define MTK_LOCAL_STATE_RUN 0
+/* Local power state for retention. Valid only for CPU power domains */
+#define MTK_LOCAL_STATE_RET 1
+/* Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains
+ */
+#define MTK_LOCAL_STATE_OFF 2
+
+#if PSCI_EXTENDED_STATE_ID
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define MTK_LOCAL_PSTATE_WIDTH 4
+#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1)
+
+/* Macros to construct the composite power state */
+
+/* Make composite power state parameter till power level 0 */
+
+#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
+#else
+#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+
+#endif /* __PSCI_EXTENDED_STATE_ID__ */
+
+/* Make composite power state parameter till power level 1 */
+#define mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \
+ mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+
+/* Make composite power state parameter till power level 2 */
+#define mtk_make_pwrstate_lvl2( \
+ lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \
+ mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type))
+
+
+#endif /* MT8173_DEF_H */
diff --git a/plat/mediatek/mt8173/include/plat_macros.S b/plat/mediatek/mt8173/include/plat_macros.S
new file mode 100644
index 0000000..ac9fb16
--- /dev/null
+++ b/plat/mediatek/mt8173/include/plat_macros.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <mt8173_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC and
+ * CCI registers whenever an unhandled exception
+ * is taken in BL3-1.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x16, BASE_GICD_BASE
+ mov_imm x17, BASE_GICC_BASE
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ .endm
diff --git a/plat/mediatek/mt8173/include/plat_private.h b/plat/mediatek/mt8173/include/plat_private.h
new file mode 100644
index 0000000..cd92d34
--- /dev/null
+++ b/plat/mediatek/mt8173/include/plat_private.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+
+void plat_cci_init(void);
+void plat_cci_enable(void);
+void plat_cci_disable(void);
+
+/* Declarations for plat_topology.c */
+int mt_setup_topology(void);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8173/include/plat_sip_calls.h b/plat/mediatek/mt8173/include/plat_sip_calls.h
new file mode 100644
index 0000000..ce9951a
--- /dev/null
+++ b/plat/mediatek/mt8173/include/plat_sip_calls.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+/*******************************************************************************
+ * Plat SiP function constants
+ ******************************************************************************/
+#define MTK_PLAT_SIP_NUM_CALLS 7
+
+#define MTK_SIP_PWR_ON_MTCMOS 0x82000402
+#define MTK_SIP_PWR_OFF_MTCMOS 0x82000403
+#define MTK_SIP_PWR_MTCMOS_SUPPORT 0x82000404
+#define MTK_SIP_SET_HDCP_KEY_NUM 0x82000405
+#define MTK_SIP_CLR_HDCP_KEY 0x82000406
+#define MTK_SIP_SET_HDCP_KEY_EX 0x82000407
+#define MTK_SIP_SMC_WATCHDOG 0x82003D06
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8173/include/platform_def.h b/plat/mediatek/mt8173/include/platform_def.h
new file mode 100644
index 0000000..d340422
--- /dev/null
+++ b/plat/mediatek/mt8173/include/platform_def.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/interrupt_props.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/utils_def.h>
+
+#include "mt8173_def.h"
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL1)
+#define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x800
+#elif defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(2)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define SOC_CHIP_ID U(0x8173)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/*
+ * MT8173 SRAM memory layout
+ * 0x100000 +-------------------+
+ * | shared mem (4KB) |
+ * 0x101000 +-------------------+
+ * | |
+ * | BL3-1 (124KB) |
+ * | |
+ * 0x120000 +-------------------+
+ * | reserved (64KB) |
+ * 0x130000 +-------------------+
+ */
+/* TF txet, ro, rw, xlat table, coherent memory ... etc.
+ * Size: release: 128KB, debug: 128KB
+ */
+#define TZRAM_BASE (0x100000)
+#if DEBUG
+#define TZRAM_SIZE (0x20000)
+#else
+#define TZRAM_SIZE (0x20000)
+#endif
+
+/* Reserved: 64KB */
+#define TZRAM2_BASE (TZRAM_BASE + TZRAM_SIZE)
+#define TZRAM2_SIZE (0x10000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+#define TZRAM2_LIMIT (TZRAM2_BASE + TZRAM2_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 4
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+
+#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
+#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(MT_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8173/include/power_tracer.h b/plat/mediatek/mt8173/include/power_tracer.h
new file mode 100644
index 0000000..195366d
--- /dev/null
+++ b/plat/mediatek/mt8173/include/power_tracer.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POWER_TRACER_H
+#define POWER_TRACER_H
+
+#define CPU_UP 0
+#define CPU_DOWN 1
+#define CPU_SUSPEND 2
+#define CLUSTER_UP 3
+#define CLUSTER_DOWN 4
+#define CLUSTER_SUSPEND 5
+
+void trace_power_flow(unsigned long mpidr, unsigned char mode);
+
+#endif /* POWER_TRACER_H */
diff --git a/plat/mediatek/mt8173/include/scu.h b/plat/mediatek/mt8173/include/scu.h
new file mode 100644
index 0000000..b1e9424
--- /dev/null
+++ b/plat/mediatek/mt8173/include/scu.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCU_H
+#define SCU_H
+
+void disable_scu(unsigned long mpidr);
+void enable_scu(unsigned long mpidr);
+
+#endif /* SCU_H */
diff --git a/plat/mediatek/mt8173/plat_mt_gic.c b/plat/mediatek/mt8173/plat_mt_gic.c
new file mode 100644
index 0000000..80b9010
--- /dev/null
+++ b/plat/mediatek/mt8173/plat_mt_gic.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <lib/utils.h>
+
+#include <mt8173_def.h>
+
+const unsigned int mt_irq_sec_array[] = {
+ MT_IRQ_SEC_SGI_0,
+ MT_IRQ_SEC_SGI_1,
+ MT_IRQ_SEC_SGI_2,
+ MT_IRQ_SEC_SGI_3,
+ MT_IRQ_SEC_SGI_4,
+ MT_IRQ_SEC_SGI_5,
+ MT_IRQ_SEC_SGI_6,
+ MT_IRQ_SEC_SGI_7
+};
+
+void plat_mt_gic_init(void)
+{
+ arm_gic_init(BASE_GICC_BASE,
+ BASE_GICD_BASE,
+ BASE_GICR_BASE,
+ mt_irq_sec_array,
+ ARRAY_SIZE(mt_irq_sec_array));
+}
diff --git a/plat/mediatek/mt8173/plat_pm.c b/plat/mediatek/mt8173/plat_pm.c
new file mode 100644
index 0000000..e72a343
--- /dev/null
+++ b/plat/mediatek/mt8173/plat_pm.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include <mcucfg.h>
+#include <mt8173_def.h>
+#include <mt_cpuxgpt.h> /* generic_timer_backup() */
+#include <plat_private.h>
+#include <power_tracer.h>
+#include <rtc.h>
+#include <scu.h>
+#include <spm_hotplug.h>
+#include <spm_mcdi.h>
+#include <spm_suspend.h>
+#include <wdt.h>
+
+#define MTK_PWR_LVL0 0
+#define MTK_PWR_LVL1 1
+#define MTK_PWR_LVL2 2
+
+/* Macros to read the MTK power domain state */
+#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0]
+#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1]
+#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ?\
+ (state)->pwr_domain_state[MTK_PWR_LVL2] : 0)
+
+#if PSCI_EXTENDED_STATE_ID
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+const unsigned int mtk_pm_idle_states[] = {
+ /* State-id - 0x001 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
+ MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x002 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
+ MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x022 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF,
+ MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
+#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1
+ /* State-id - 0x222 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF,
+ MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
+#endif
+ 0,
+};
+#endif
+
+struct core_context {
+ unsigned long timer_data[8];
+ unsigned int count;
+ unsigned int rst;
+ unsigned int abt;
+ unsigned int brk;
+};
+
+struct cluster_context {
+ struct core_context core[PLATFORM_MAX_CPUS_PER_CLUSTER];
+};
+
+/*
+ * Top level structure to hold the complete context of a multi cluster system
+ */
+struct system_context {
+ struct cluster_context cluster[PLATFORM_CLUSTER_COUNT];
+};
+
+/*
+ * Top level structure which encapsulates the context of the entire system
+ */
+static struct system_context dormant_data[1];
+
+static inline struct cluster_context *system_cluster(
+ struct system_context *system,
+ uint32_t clusterid)
+{
+ return &system->cluster[clusterid];
+}
+
+static inline struct core_context *cluster_core(struct cluster_context *cluster,
+ uint32_t cpuid)
+{
+ return &cluster->core[cpuid];
+}
+
+static struct cluster_context *get_cluster_data(unsigned long mpidr)
+{
+ uint32_t clusterid;
+
+ clusterid = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ return system_cluster(dormant_data, clusterid);
+}
+
+static struct core_context *get_core_data(unsigned long mpidr)
+{
+ struct cluster_context *cluster;
+ uint32_t cpuid;
+
+ cluster = get_cluster_data(mpidr);
+ cpuid = mpidr & MPIDR_CPU_MASK;
+
+ return cluster_core(cluster, cpuid);
+}
+
+static void mt_save_generic_timer(unsigned long *container)
+{
+ uint64_t ctl;
+ uint64_t val;
+
+ __asm__ volatile("mrs %x0, cntkctl_el1\n\t"
+ "mrs %x1, cntp_cval_el0\n\t"
+ "stp %x0, %x1, [%2, #0]"
+ : "=&r" (ctl), "=&r" (val)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("mrs %x0, cntp_tval_el0\n\t"
+ "mrs %x1, cntp_ctl_el0\n\t"
+ "stp %x0, %x1, [%2, #16]"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("mrs %x0, cntv_tval_el0\n\t"
+ "mrs %x1, cntv_ctl_el0\n\t"
+ "stp %x0, %x1, [%2, #32]"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+}
+
+static void mt_restore_generic_timer(unsigned long *container)
+{
+ uint64_t ctl;
+ uint64_t val;
+
+ __asm__ volatile("ldp %x0, %x1, [%2, #0]\n\t"
+ "msr cntkctl_el1, %x0\n\t"
+ "msr cntp_cval_el0, %x1"
+ : "=&r" (ctl), "=&r" (val)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("ldp %x0, %x1, [%2, #16]\n\t"
+ "msr cntp_tval_el0, %x0\n\t"
+ "msr cntp_ctl_el0, %x1"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+
+ __asm__ volatile("ldp %x0, %x1, [%2, #32]\n\t"
+ "msr cntv_tval_el0, %x0\n\t"
+ "msr cntv_ctl_el0, %x1"
+ : "=&r" (val), "=&r" (ctl)
+ : "r" (container)
+ : "memory");
+}
+
+static inline uint64_t read_cntpctl(void)
+{
+ uint64_t cntpctl;
+
+ __asm__ volatile("mrs %x0, cntp_ctl_el0"
+ : "=r" (cntpctl) : : "memory");
+
+ return cntpctl;
+}
+
+static inline void write_cntpctl(uint64_t cntpctl)
+{
+ __asm__ volatile("msr cntp_ctl_el0, %x0" : : "r"(cntpctl));
+}
+
+static void stop_generic_timer(void)
+{
+ /*
+ * Disable the timer and mask the irq to prevent
+ * suprious interrupts on this cpu interface. It
+ * will bite us when we come back if we don't. It
+ * will be replayed on the inbound cluster.
+ */
+ uint64_t cntpctl = read_cntpctl();
+
+ write_cntpctl(clr_cntp_ctl_enable(cntpctl));
+}
+
+static void mt_cpu_save(unsigned long mpidr)
+{
+ struct core_context *core;
+
+ core = get_core_data(mpidr);
+ mt_save_generic_timer(core->timer_data);
+
+ /* disable timer irq, and upper layer should enable it again. */
+ stop_generic_timer();
+}
+
+static void mt_cpu_restore(unsigned long mpidr)
+{
+ struct core_context *core;
+
+ core = get_core_data(mpidr);
+ mt_restore_generic_timer(core->timer_data);
+}
+
+static void mt_platform_save_context(unsigned long mpidr)
+{
+ /* mcusys_save_context: */
+ mt_cpu_save(mpidr);
+}
+
+static void mt_platform_restore_context(unsigned long mpidr)
+{
+ /* mcusys_restore_context: */
+ mt_cpu_restore(mpidr);
+}
+
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr;
+
+ scr = read_scr_el3();
+ write_scr_el3(scr | SCR_IRQ_BIT);
+ isb();
+ dsb();
+ wfi();
+ write_scr_el3(scr);
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be turned
+ * on. The level and mpidr determine the affinity instance.
+ ******************************************************************************/
+static uintptr_t secure_entrypoint;
+
+static int plat_power_domain_on(unsigned long mpidr)
+{
+ int rc = PSCI_E_SUCCESS;
+ unsigned long cpu_id;
+ unsigned long cluster_id;
+ uintptr_t rv;
+
+ cpu_id = mpidr & MPIDR_CPU_MASK;
+ cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+
+ if (cluster_id)
+ rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
+ else
+ rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
+
+ mmio_write_32(rv, secure_entrypoint);
+ INFO("mt_on[%ld:%ld], entry %x\n",
+ cluster_id, cpu_id, mmio_read_32(rv));
+
+ spm_hotplug_on(mpidr);
+ return rc;
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be turned
+ * off. The level and mpidr determine the affinity instance. The 'state' arg.
+ * allows the platform to decide whether the cluster is being turned off and
+ * take apt actions.
+ *
+ * CAUTION: This function is called with coherent stacks so that caches can be
+ * turned off, flushed and coherency disabled. There is no guarantee that caches
+ * will remain turned on across calls to this function as each affinity level is
+ * dealt with. So do not write & read global variables across calls. It will be
+ * wise to do flush a write to the global to prevent unpredictable results.
+ ******************************************************************************/
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+
+ spm_hotplug_off(mpidr);
+
+ trace_power_flow(mpidr, CPU_DOWN);
+
+ if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
+ /* Disable coherency if this cluster is to be turned off */
+ plat_cci_disable();
+
+ trace_power_flow(mpidr, CLUSTER_DOWN);
+ }
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be
+ * suspended. The level and mpidr determine the affinity instance. The 'state'
+ * arg. allows the platform to decide whether the cluster is being turned off
+ * and take apt actions.
+ *
+ * CAUTION: This function is called with coherent stacks so that caches can be
+ * turned off, flushed and coherency disabled. There is no guarantee that caches
+ * will remain turned on across calls to this function as each affinity level is
+ * dealt with. So do not write & read global variables across calls. It will be
+ * wise to do flush a write to the global to prevent unpredictable results.
+ ******************************************************************************/
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned long cluster_id;
+ unsigned long cpu_id;
+ uintptr_t rv;
+
+ cpu_id = mpidr & MPIDR_CPU_MASK;
+ cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+
+ if (cluster_id)
+ rv = (uintptr_t)&mt8173_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw;
+ else
+ rv = (uintptr_t)&mt8173_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw;
+
+ mmio_write_32(rv, secure_entrypoint);
+
+ if (MTK_SYSTEM_PWR_STATE(state) != MTK_LOCAL_STATE_OFF) {
+ spm_mcdi_prepare_for_off_state(mpidr, MTK_PWR_LVL0);
+ if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF)
+ spm_mcdi_prepare_for_off_state(mpidr, MTK_PWR_LVL1);
+ }
+
+ mt_platform_save_context(mpidr);
+
+ /* Perform the common cluster specific operations */
+ if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
+ /* Disable coherency if this cluster is to be turned off */
+ plat_cci_disable();
+ }
+
+ if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
+ wdt_suspend();
+ disable_scu(mpidr);
+ generic_timer_backup();
+ spm_system_suspend();
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+ }
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance has just been powered
+ * on after being turned off earlier. The level and mpidr determine the affinity
+ * instance. The 'state' arg. allows the platform to decide whether the cluster
+ * was turned off prior to wakeup and do what's necessary to setup it up
+ * correctly.
+ ******************************************************************************/
+void mtk_system_pwr_domain_resume(void);
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+
+ assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF);
+
+ if ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) &&
+ (state->pwr_domain_state[MTK_PWR_LVL2] == MTK_LOCAL_STATE_OFF))
+ mtk_system_pwr_domain_resume();
+
+ if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
+ plat_cci_enable();
+ trace_power_flow(mpidr, CLUSTER_UP);
+ }
+
+ if ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) &&
+ (state->pwr_domain_state[MTK_PWR_LVL2] == MTK_LOCAL_STATE_OFF))
+ return;
+
+ /* Enable the gic cpu interface */
+ gicv2_cpuif_enable();
+ gicv2_pcpu_distif_init();
+ trace_power_flow(mpidr, CPU_UP);
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance has just been powered
+ * on after having been suspended earlier. The level and mpidr determine the
+ * affinity instance.
+ ******************************************************************************/
+static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+
+ if (state->pwr_domain_state[MTK_PWR_LVL0] == MTK_LOCAL_STATE_RET)
+ return;
+
+ if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
+ /* Enable the gic cpu interface */
+ plat_arm_gic_init();
+ spm_system_suspend_finish();
+ enable_scu(mpidr);
+ wdt_resume();
+ }
+
+ /* Perform the common cluster specific operations */
+ if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) {
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ }
+
+ mt_platform_restore_context(mpidr);
+
+ if (MTK_SYSTEM_PWR_STATE(state) != MTK_LOCAL_STATE_OFF) {
+ spm_mcdi_finish_for_on_state(mpidr, MTK_PWR_LVL0);
+ if (MTK_CLUSTER_PWR_STATE(state) == MTK_LOCAL_STATE_OFF)
+ spm_mcdi_finish_for_on_state(mpidr, MTK_PWR_LVL1);
+ }
+
+ gicv2_pcpu_distif_init();
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ assert(PLAT_MAX_PWR_LVL >= 2);
+
+ for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
+}
+
+/*******************************************************************************
+ * MTK handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 plat_system_off(void)
+{
+ INFO("MTK System Off\n");
+
+ rtc_bbpu_power_down();
+
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 plat_system_reset(void)
+{
+ /* Write the System Configuration Control Register */
+ INFO("MTK System Reset\n");
+
+ wdt_trigger_reset();
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+#if !PSCI_EXTENDED_STATE_ID
+static int plat_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's possible to enter standby only on power level 0
+ * Ignore any other power level.
+ */
+ if (pwr_lvl != 0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MTK_PWR_LVL0] =
+ MTK_LOCAL_STATE_RET;
+ } else {
+ for (i = 0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ MTK_LOCAL_STATE_OFF;
+ }
+
+ /*
+ * We expect the 'state id' to be zero.
+ */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+#else
+int plat_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ int i;
+
+ assert(req_state);
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
+ */
+ for (i = 0; !!mtk_pm_idle_states[i]; i++) {
+ if (power_state == mtk_pm_idle_states[i])
+ break;
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!mtk_pm_idle_states[i])
+ return PSCI_E_INVALID_PARAMS;
+
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id &
+ MTK_LOCAL_PSTATE_MASK;
+ state_id >>= MTK_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+#endif
+
+void mtk_system_pwr_domain_resume(void)
+{
+ console_switch_state(CONSOLE_FLAG_BOOT);
+
+ /* Assert system power domain is available on the platform */
+ assert(PLAT_MAX_PWR_LVL >= MTK_PWR_LVL2);
+
+ plat_arm_gic_init();
+
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
+
+static const plat_psci_ops_t plat_plat_pm_ops = {
+ .cpu_standby = plat_cpu_standby,
+ .pwr_domain_on = plat_power_domain_on,
+ .pwr_domain_on_finish = plat_power_domain_on_finish,
+ .pwr_domain_off = plat_power_domain_off,
+ .pwr_domain_suspend = plat_power_domain_suspend,
+ .pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
+ .system_off = plat_system_off,
+ .system_reset = plat_system_reset,
+ .validate_power_state = plat_validate_power_state,
+ .get_sys_suspend_power_state = plat_get_sys_suspend_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_plat_pm_ops;
+ secure_entrypoint = sec_entrypoint;
+ return 0;
+}
+
+/*
+ * The PSCI generic code uses this API to let the platform participate in state
+ * coordination during a power management operation. It compares the platform
+ * specific local power states requested by each cpu for a given power domain
+ * and returns the coordinated target power state that the domain should
+ * enter. A platform assigns a number to a local power state. This default
+ * implementation assumes that the platform assigns these numbers in order of
+ * increasing depth of the power state i.e. for two power states X & Y, if X < Y
+ * then X represents a shallower power state than Y. As a result, the
+ * coordinated target local power state for a power domain will be the minimum
+ * of the requested local power states.
+ */
+plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
+ const plat_local_state_t *states,
+ unsigned int ncpu)
+{
+ plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
+
+ assert(ncpu);
+
+ do {
+ temp = *states++;
+ if (temp < target)
+ target = temp;
+ } while (--ncpu);
+
+ return target;
+}
diff --git a/plat/mediatek/mt8173/plat_sip_calls.c b/plat/mediatek/mt8173/plat_sip_calls.c
new file mode 100644
index 0000000..da9b91d
--- /dev/null
+++ b/plat/mediatek/mt8173/plat_sip_calls.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <crypt.h>
+#include <mtcmos.h>
+#include <mtk_sip_svc.h>
+#include <plat_sip_calls.h>
+#include <wdt.h>
+
+/* Authorized secure register list */
+enum {
+ SREG_HDMI_COLOR_EN = 0x14000904
+};
+
+static const uint32_t authorized_sreg[] = {
+ SREG_HDMI_COLOR_EN
+};
+
+#define authorized_sreg_cnt \
+ (sizeof(authorized_sreg) / sizeof(authorized_sreg[0]))
+
+uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val)
+{
+ uint64_t i;
+
+ for (i = 0; i < authorized_sreg_cnt; i++) {
+ if (authorized_sreg[i] == sreg) {
+ mmio_write_32(sreg, val);
+ return MTK_SIP_E_SUCCESS;
+ }
+ }
+
+ return MTK_SIP_E_INVALID_PARAM;
+}
+
+static uint64_t mt_sip_pwr_on_mtcmos(uint32_t val)
+{
+ uint32_t ret;
+
+ ret = mtcmos_non_cpu_ctrl(1, val);
+ if (ret)
+ return MTK_SIP_E_INVALID_PARAM;
+ else
+ return MTK_SIP_E_SUCCESS;
+}
+
+static uint64_t mt_sip_pwr_off_mtcmos(uint32_t val)
+{
+ uint32_t ret;
+
+ ret = mtcmos_non_cpu_ctrl(0, val);
+ if (ret)
+ return MTK_SIP_E_INVALID_PARAM;
+ else
+ return MTK_SIP_E_SUCCESS;
+}
+
+static uint64_t mt_sip_pwr_mtcmos_support(void)
+{
+ return MTK_SIP_E_SUCCESS;
+}
+
+uint64_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ uint64_t ret;
+
+ switch (smc_fid) {
+ case MTK_SIP_PWR_ON_MTCMOS:
+ ret = mt_sip_pwr_on_mtcmos((uint32_t)x1);
+ SMC_RET1(handle, ret);
+
+ case MTK_SIP_PWR_OFF_MTCMOS:
+ ret = mt_sip_pwr_off_mtcmos((uint32_t)x1);
+ SMC_RET1(handle, ret);
+
+ case MTK_SIP_PWR_MTCMOS_SUPPORT:
+ ret = mt_sip_pwr_mtcmos_support();
+ SMC_RET1(handle, ret);
+
+ case MTK_SIP_SET_HDCP_KEY_EX:
+ ret = crypt_set_hdcp_key_ex(x1, x2, x3);
+ SMC_RET1(handle, ret);
+
+ case MTK_SIP_SET_HDCP_KEY_NUM:
+ ret = crypt_set_hdcp_key_num((uint32_t)x1);
+ SMC_RET1(handle, ret);
+
+ case MTK_SIP_CLR_HDCP_KEY:
+ ret = crypt_clear_hdcp_key();
+ SMC_RET1(handle, ret);
+
+ case MTK_SIP_SMC_WATCHDOG:
+ return wdt_smc_handler(x1, x2, handle);
+
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ break;
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/mediatek/mt8173/plat_topology.c b/plat/mediatek/mt8173/plat_topology.c
new file mode 100644
index 0000000..23e7d2d
--- /dev/null
+++ b/plat/mediatek/mt8173/plat_topology.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <lib/psci/psci.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the MT8173 default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
+}
diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk
new file mode 100644
index 0000000..6bf1aa7
--- /dev/null
+++ b/plat/mediatek/mt8173/platform.mk
@@ -0,0 +1,75 @@
+#
+# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT}/include/ \
+ -Iinclude/plat/arm/common/aarch64 \
+ -I${MTK_PLAT_SOC}/drivers/crypt/ \
+ -I${MTK_PLAT_SOC}/drivers/mtcmos/ \
+ -I${MTK_PLAT_SOC}/drivers/pmic/ \
+ -I${MTK_PLAT_SOC}/drivers/rtc/ \
+ -I${MTK_PLAT_SOC}/drivers/spm/ \
+ -I${MTK_PLAT_SOC}/drivers/timer/ \
+ -I${MTK_PLAT_SOC}/drivers/wdt/ \
+ -I${MTK_PLAT_SOC}/include/
+
+PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ plat/arm/common/arm_gicv2.c \
+ plat/common/plat_gicv2.c \
+ plat/common/aarch64/crash_console_helpers.S
+
+BL31_SOURCES += common/desc_image_load.c \
+ drivers/arm/cci/cci.c \
+ drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/mtk_sip_svc.c \
+ ${MTK_PLAT}/drivers/pmic_wrap/pmic_wrap_init.c \
+ ${MTK_PLAT}/drivers/rtc/rtc_common.c \
+ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
+ ${MTK_PLAT_SOC}/aarch64/platform_common.c \
+ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
+ ${MTK_PLAT_SOC}/drivers/crypt/crypt.c \
+ ${MTK_PLAT_SOC}/drivers/mtcmos/mtcmos.c \
+ ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
+ ${MTK_PLAT_SOC}/drivers/spm/spm.c \
+ ${MTK_PLAT_SOC}/drivers/spm/spm_hotplug.c \
+ ${MTK_PLAT_SOC}/drivers/spm/spm_mcdi.c \
+ ${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \
+ ${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \
+ ${MTK_PLAT_SOC}/drivers/wdt/wdt.c \
+ ${MTK_PLAT_SOC}/plat_pm.c \
+ ${MTK_PLAT_SOC}/plat_sip_calls.c \
+ ${MTK_PLAT_SOC}/plat_topology.c \
+ ${MTK_PLAT_SOC}/power_tracer.c \
+ ${MTK_PLAT_SOC}/scu.c
+
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_826319 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_855873 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+$(eval $(call add_define,MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+MULTI_CONSOLE_API := 1
diff --git a/plat/mediatek/mt8173/power_tracer.c b/plat/mediatek/mt8173/power_tracer.c
new file mode 100644
index 0000000..d1fcf9f
--- /dev/null
+++ b/plat/mediatek/mt8173/power_tracer.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/debug.h>
+
+#include <power_tracer.h>
+
+#define trace_log(...) INFO("psci: " __VA_ARGS__)
+
+void trace_power_flow(unsigned long mpidr, unsigned char mode)
+{
+ switch (mode) {
+ case CPU_UP:
+ trace_log("core %lld:%lld ON\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
+ (mpidr & MPIDR_CPU_MASK));
+ break;
+ case CPU_DOWN:
+ trace_log("core %lld:%lld OFF\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
+ (mpidr & MPIDR_CPU_MASK));
+ break;
+ case CPU_SUSPEND:
+ trace_log("core %lld:%lld SUSPEND\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
+ (mpidr & MPIDR_CPU_MASK));
+ break;
+ case CLUSTER_UP:
+ trace_log("cluster %lld ON\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
+ break;
+ case CLUSTER_DOWN:
+ trace_log("cluster %lld OFF\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
+ break;
+ case CLUSTER_SUSPEND:
+ trace_log("cluster %lld SUSPEND\n",
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
+ break;
+ default:
+ trace_log("unknown power mode\n");
+ break;
+ }
+}
diff --git a/plat/mediatek/mt8173/scu.c b/plat/mediatek/mt8173/scu.c
new file mode 100644
index 0000000..2524d72
--- /dev/null
+++ b/plat/mediatek/mt8173/scu.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+
+void disable_scu(unsigned long mpidr)
+{
+ if (mpidr & MPIDR_CLUSTER_MASK)
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp1_miscdbg,
+ MP1_ACINACTM);
+ else
+ mmio_setbits_32((uintptr_t)&mt8173_mcucfg->mp0_axi_config,
+ MP0_ACINACTM);
+}
+
+void enable_scu(unsigned long mpidr)
+{
+ if (mpidr & MPIDR_CLUSTER_MASK)
+ mmio_clrbits_32((uintptr_t)&mt8173_mcucfg->mp1_miscdbg,
+ MP1_ACINACTM);
+ else
+ mmio_clrbits_32((uintptr_t)&mt8173_mcucfg->mp0_axi_config,
+ MP0_ACINACTM);
+}
diff --git a/plat/mediatek/mt8183/aarch64/plat_helpers.S b/plat/mediatek/mt8183/aarch64/plat_helpers.S
new file mode 100644
index 0000000..5c39633
--- /dev/null
+++ b/plat/mediatek/mt8183/aarch64/plat_helpers.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void);
+ *
+ * result: CorePos = CoreId + (ClusterId << 2)
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_my_core_pos
diff --git a/plat/mediatek/mt8183/aarch64/platform_common.c b/plat/mediatek/mt8183/aarch64/platform_common.c
new file mode 100644
index 0000000..31d1339
--- /dev/null
+++ b/plat/mediatek/mt8183/aarch64/platform_common.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <mcsi/mcsi.h>
+#include <platform_def.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+static const int cci_map[] = {
+ PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX
+};
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_mmap[] = {
+ /* for TF text, RO, RW */
+ MAP_REGION_FLAT(TZRAM_BASE, TZRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit,
+ uintptr_t coh_start,
+ uintptr_t coh_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_MEMORY | MT_RO | MT_SECURE);
+ mmap_add_region(coh_start, coh_start, coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ mmap_add(plat_mmap);
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+void plat_mtk_cci_init(void)
+{
+ /* Initialize CCI driver */
+ mcsi_init(PLAT_MT_CCI_BASE, ARRAY_SIZE(cci_map));
+}
+
+void plat_mtk_cci_enable(void)
+{
+ /* Enable CCI coherency for this cluster.
+ * No need for locks as no other cpu is active at the moment.
+ */
+ cci_enable_cluster_coherency(read_mpidr());
+}
+
+void plat_mtk_cci_disable(void)
+{
+ cci_disable_cluster_coherency(read_mpidr());
+}
+
+void plat_mtk_cci_init_sf(void)
+{
+ /* Init mcsi snoop filter. */
+ cci_init_sf();
+}
diff --git a/plat/mediatek/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c
new file mode 100644
index 0000000..7dac8a4
--- /dev/null
+++ b/plat/mediatek/mt8183/bl31_plat_setup.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <devapc.h>
+#include <emi_mpu.h>
+#include <plat/common/common_def.h>
+#include <drivers/console.h>
+#include <common/debug.h>
+#include <drivers/generic_delay_timer.h>
+#include <mcucfg.h>
+#include <mt_gic_v3.h>
+#include <mt_timer.h>
+#include <lib/coreboot.h>
+#include <lib/mmio.h>
+#include <mtk_mcdi.h>
+#include <mtk_plat_common.h>
+#include <mtspmc.h>
+#include <plat_debug.h>
+#include <plat_params.h>
+#include <plat_private.h>
+#include <platform_def.h>
+#include <scu.h>
+#include <spm.h>
+#include <drivers/ti/uart/uart_16550.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+static void platform_setup_cpu(void)
+{
+ mmio_write_32((uintptr_t)&mt8183_mcucfg->mp0_rw_rsvd0, 0x00000001);
+
+ /* Mcusys dcm control */
+ /* Enable pll plldiv dcm */
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->bus_pll_divider_cfg,
+ BUS_PLLDIV_DCM);
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp0_pll_divider_cfg,
+ MP0_PLLDIV_DCM);
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp2_pll_divider_cfg,
+ MP2_PLLDIV_DCM);
+ /* Enable mscib dcm */
+ mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->mscib_dcm_en,
+ MCSIB_CACTIVE_SEL_MASK, MCSIB_CACTIVE_SEL);
+ mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->mscib_dcm_en,
+ MCSIB_DCM_MASK, MCSIB_DCM);
+ /* Enable adb400 dcm */
+ mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->cci_adb400_dcm_config,
+ CCI_ADB400_DCM_MASK, CCI_ADB400_DCM);
+ /* Enable bus clock dcm */
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->cci_clk_ctrl,
+ MCU_BUS_DCM);
+ /* Enable bus fabric dcm */
+ mmio_clrsetbits_32(
+ (uintptr_t)&mt8183_mcucfg->mcusys_bus_fabric_dcm_ctrl,
+ MCUSYS_BUS_FABRIC_DCM_MASK,
+ MCUSYS_BUS_FABRIC_DCM);
+ /* Enable l2c sram dcm */
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->l2c_sram_ctrl,
+ L2C_SRAM_DCM);
+ /* Enable busmp0 sync dcm */
+ mmio_clrsetbits_32((uintptr_t)&mt8183_mcucfg->sync_dcm_config,
+ SYNC_DCM_MASK, SYNC_DCM);
+ /* Enable cntvalue dcm */
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mcu_misc_dcm_ctrl,
+ CNTVALUEB_DCM);
+ /* Enable dcm cluster stall */
+ mmio_clrsetbits_32(
+ (uintptr_t)&mt8183_mcucfg->sync_dcm_cluster_config,
+ MCUSYS_MAX_ACCESS_LATENCY_MASK,
+ MCUSYS_MAX_ACCESS_LATENCY);
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->sync_dcm_cluster_config,
+ MCU0_SYNC_DCM_STALL_WR_EN);
+ /* Enable rgu dcm */
+ mmio_setbits_32((uintptr_t)&mt8183_mcucfg->mp0_rgu_dcm_config,
+ CPUSYS_RGU_DCM_CINFIG);
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ params_early_setup(arg1);
+
+#if COREBOOT
+ if (coreboot_serial.type)
+ console_16550_register(coreboot_serial.baseaddr,
+ coreboot_serial.input_hertz,
+ coreboot_serial.baud,
+ &console);
+#else
+ console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+ NOTICE("MT8183 bl31_setup\n");
+
+ bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ devapc_init();
+
+ emi_mpu_init();
+
+ platform_setup_cpu();
+ generic_delay_timer_init();
+
+ /* Initialize the GIC driver, CPU and distributor interfaces */
+ mt_gic_driver_init();
+ mt_gic_init();
+
+ mt_systimer_init();
+
+ /* Init mcsi SF */
+ plat_mtk_cci_init_sf();
+
+#if SPMC_MODE == 1
+ spmc_init();
+#endif
+ spm_boot_init();
+ mcdi_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_mtk_cci_init();
+ plat_mtk_cci_enable();
+
+ enable_scu(read_mpidr());
+
+ plat_configure_mmu_el3(BL_CODE_BASE,
+ BL_COHERENT_RAM_END - BL_CODE_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
diff --git a/plat/mediatek/mt8183/drivers/devapc/devapc.c b/plat/mediatek/mt8183/drivers/devapc/devapc.c
new file mode 100644
index 0000000..9d76aa5
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/devapc/devapc.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <devapc.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+
+static void set_master_transaction(uint32_t master_index,
+ enum TRANSACTION transaction_type)
+{
+ uintptr_t base;
+ uint32_t master_register_index;
+ uint32_t master_set_index;
+ uint32_t set_bit;
+
+ master_register_index = master_index / (MOD_NO_IN_1_DEVAPC * 2);
+ master_set_index = master_index % (MOD_NO_IN_1_DEVAPC * 2);
+
+ base = DEVAPC_INFRA_MAS_SEC_0 + master_register_index * 4;
+
+ set_bit = 0x1 << master_set_index;
+ if (transaction_type == SECURE_TRANSACTION)
+ mmio_setbits_32(base, set_bit);
+ else
+ mmio_clrbits_32(base, set_bit);
+}
+
+static void set_master_domain(uint32_t master_index, enum MASK_DOM domain)
+{
+ uintptr_t base;
+ uint32_t domain_reg;
+ uint32_t domain_index;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+
+ domain_reg = master_index / MASTER_MOD_NO_IN_1_DEVAPC;
+ domain_index = master_index % MASTER_MOD_NO_IN_1_DEVAPC;
+ clr_bit = 0xF << (4 * domain_index);
+ set_bit = domain << (4 * domain_index);
+
+ base = DEVAPC_INFRA_MAS_DOM_0 + domain_reg * 4;
+ mmio_clrsetbits_32(base, clr_bit, set_bit);
+}
+
+static void set_master_domain_remap_infra(enum MASK_DOM domain_emi_view,
+ enum MASK_DOM domain_infra_view)
+{
+ uintptr_t base;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+
+ if (domain_emi_view < DOMAIN_10) {
+ base = DEVAPC_INFRA_DOM_RMP_0;
+ clr_bit = 0x7 << (domain_emi_view * 3);
+ set_bit = domain_infra_view << (domain_emi_view * 3);
+ mmio_clrsetbits_32(base, clr_bit, set_bit);
+ } else if (domain_emi_view > DOMAIN_10) {
+ base = DEVAPC_INFRA_DOM_RMP_1;
+ domain_emi_view = domain_emi_view - DOMAIN_11;
+ clr_bit = 0x7 << (domain_emi_view * 3 + 1);
+ set_bit = domain_infra_view << (domain_emi_view * 3 + 1);
+ mmio_clrsetbits_32(base, clr_bit, set_bit);
+ } else {
+ base = DEVAPC_INFRA_DOM_RMP_0;
+ clr_bit = 0x3 << (domain_emi_view * 3);
+ set_bit = domain_infra_view << (domain_emi_view * 3);
+ mmio_clrsetbits_32(base, clr_bit, set_bit);
+
+ base = DEVAPC_INFRA_DOM_RMP_1;
+ set_bit = (domain_infra_view & 0x4) >> 2;
+ mmio_clrsetbits_32(base, 0x1, set_bit);
+ }
+}
+
+static void set_master_domain_remap_mm(enum MASK_DOM domain_emi_view,
+ enum MASK_DOM domain_mm_view)
+{
+ uintptr_t base;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+
+ base = DEVAPC_MM_DOM_RMP_0;
+ clr_bit = 0x3 << (domain_emi_view * 2);
+ set_bit = domain_mm_view << (domain_emi_view * 2);
+
+ mmio_clrsetbits_32(base, clr_bit, set_bit);
+}
+
+static void set_module_apc(enum DAPC_SLAVE_TYPE slave_type, uint32_t module,
+ enum MASK_DOM domain_num,
+ enum APC_ATTR permission_control)
+{
+ uintptr_t base;
+ uint32_t apc_index;
+ uint32_t apc_set_index;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+
+ apc_index = module / MOD_NO_IN_1_DEVAPC;
+ apc_set_index = module % MOD_NO_IN_1_DEVAPC;
+ clr_bit = 0x3 << (apc_set_index * 2);
+ set_bit = permission_control << (apc_set_index * 2);
+
+ if (slave_type == DAPC_INFRA_SLAVE && module <= SLAVE_INFRA_MAX_INDEX)
+ base = DEVAPC_INFRA_D0_APC_0 + domain_num * 0x100 +
+ apc_index * 4;
+ else if (slave_type == DAPC_MM_SLAVE && module <= SLAVE_MM_MAX_INDEX)
+ base = DEVAPC_MM_D0_APC_0 + domain_num * 0x100 + apc_index * 4;
+ else
+ return;
+
+ mmio_clrsetbits_32(base, clr_bit, set_bit);
+}
+
+static void set_default_master_transaction(void)
+{
+ set_master_transaction(MASTER_SSPM, SECURE_TRANSACTION);
+}
+
+static void set_default_master_domain(void)
+{
+ set_master_domain(MASTER_SCP, DOMAIN_1);
+ set_master_domain_remap_infra(DOMAIN_1, DOMAIN_1);
+ set_master_domain_remap_mm(DOMAIN_1, DOMAIN_1);
+
+ set_master_domain(MASTER_SPM, DOMAIN_2);
+ set_master_domain_remap_infra(DOMAIN_2, DOMAIN_2);
+ set_master_domain_remap_mm(DOMAIN_2, DOMAIN_2);
+
+ set_master_domain(MASTER_SSPM, DOMAIN_2);
+ set_master_domain_remap_infra(DOMAIN_2, DOMAIN_2);
+ set_master_domain_remap_mm(DOMAIN_2, DOMAIN_2);
+}
+
+static void set_default_slave_permission(void)
+{
+ uint32_t module_index;
+ uint32_t infra_size;
+ uint32_t mm_size;
+
+ infra_size = sizeof(D_APC_INFRA_Devices) / sizeof(struct DEVICE_INFO);
+ mm_size = sizeof(D_APC_MM_Devices) / sizeof(struct DEVICE_INFO);
+
+ for (module_index = 0; module_index < infra_size; module_index++) {
+ if (D_APC_INFRA_Devices[module_index].d0_permission > 0) {
+ set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_0,
+ D_APC_INFRA_Devices[module_index].d0_permission);
+ }
+ if (D_APC_INFRA_Devices[module_index].d1_permission > 0) {
+ set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_1,
+ D_APC_INFRA_Devices[module_index].d1_permission);
+ }
+ if (D_APC_INFRA_Devices[module_index].d2_permission > 0) {
+ set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_2,
+ D_APC_INFRA_Devices[module_index].d2_permission);
+ }
+ }
+
+ for (module_index = 0; module_index < mm_size; module_index++) {
+ if (D_APC_MM_Devices[module_index].d0_permission > 0) {
+ set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_0,
+ D_APC_MM_Devices[module_index].d0_permission);
+ }
+ if (D_APC_MM_Devices[module_index].d1_permission > 0) {
+ set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_1,
+ D_APC_MM_Devices[module_index].d1_permission);
+ }
+ if (D_APC_MM_Devices[module_index].d2_permission > 0) {
+ set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_2,
+ D_APC_MM_Devices[module_index].d2_permission);
+ }
+ }
+}
+
+static void dump_devapc(void)
+{
+ int i;
+
+ INFO("[DEVAPC] dump DEVAPC registers:\n");
+
+ for (i = 0; i < 13; i++) {
+ INFO("[DEVAPC] (INFRA)D0_APC_%d = 0x%x, "
+ "(INFRA)D1_APC_%d = 0x%x, "
+ "(INFRA)D2_APC_%d = 0x%x\n",
+ i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + i * 4),
+ i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + 0x100 + i * 4),
+ i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + 0x200 + i * 4));
+ }
+
+ for (i = 0; i < 9; i++) {
+ INFO("[DEVAPC] (MM)D0_APC_%d = 0x%x, "
+ "(MM)D1_APC_%d = 0x%x, "
+ "(MM)D2_APC_%d = 0x%x\n",
+ i, mmio_read_32(DEVAPC_MM_D0_APC_0 + i * 4),
+ i, mmio_read_32(DEVAPC_MM_D0_APC_0 + 0x100 + i * 4),
+ i, mmio_read_32(DEVAPC_MM_D0_APC_0 + 0x200 + i * 4));
+ }
+
+ for (i = 0; i < 4; i++) {
+ INFO("[DEVAPC] MAS_DOM_%d = 0x%x\n", i,
+ mmio_read_32(DEVAPC_INFRA_MAS_DOM_0 + i * 4));
+ }
+
+ INFO("[DEVAPC] MAS_SEC_0 = 0x%x\n",
+ mmio_read_32(DEVAPC_INFRA_MAS_SEC_0));
+
+ INFO("[DEVAPC] (INFRA)MAS_DOMAIN_REMAP_0 = 0x%x, "
+ "(INFRA)MAS_DOMAIN_REMAP_1 = 0x%x\n",
+ mmio_read_32(DEVAPC_INFRA_DOM_RMP_0),
+ mmio_read_32(DEVAPC_INFRA_DOM_RMP_1));
+
+ INFO("[DEVAPC] (MM)MAS_DOMAIN_REMAP_0 = 0x%x\n",
+ mmio_read_32(DEVAPC_MM_DOM_RMP_0));
+}
+
+void devapc_init(void)
+{
+ mmio_write_32(DEVAPC_INFRA_APC_CON, 0x80000001);
+ mmio_write_32(DEVAPC_MM_APC_CON, 0x80000001);
+ mmio_write_32(DEVAPC_MD_APC_CON, 0x80000001);
+
+ set_default_master_transaction();
+ set_default_master_domain();
+ set_default_slave_permission();
+ dump_devapc();
+}
+
diff --git a/plat/mediatek/mt8183/drivers/devapc/devapc.h b/plat/mediatek/mt8183/drivers/devapc/devapc.h
new file mode 100644
index 0000000..042a8ff
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/devapc/devapc.h
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DEVAPC_H
+#define DEVAPC_H
+
+#include <stdint.h>
+
+#define DEVAPC_AO_INFRA_BASE 0x1000E000
+#define DEVAPC_AO_MM_BASE 0x1001C000
+#define DEVAPC_AO_MD_BASE 0x10019000
+
+#define DEVAPC_INFRA_D0_APC_0 (DEVAPC_AO_INFRA_BASE + 0x0000)
+#define DEVAPC_INFRA_MAS_DOM_0 (DEVAPC_AO_INFRA_BASE + 0x0A00)
+#define DEVAPC_INFRA_MAS_SEC_0 (DEVAPC_AO_INFRA_BASE + 0x0B00)
+#define DEVAPC_INFRA_DOM_RMP_0 (DEVAPC_AO_INFRA_BASE + 0x0D00)
+#define DEVAPC_INFRA_DOM_RMP_1 (DEVAPC_AO_INFRA_BASE + 0x0D04)
+#define DEVAPC_INFRA_APC_CON (DEVAPC_AO_INFRA_BASE + 0x0F00)
+
+#define DEVAPC_MD_APC_CON (DEVAPC_AO_MD_BASE + 0x0F00)
+
+#define DEVAPC_MM_D0_APC_0 (DEVAPC_AO_MM_BASE + 0x0000)
+#define DEVAPC_MM_DOM_RMP_0 (DEVAPC_AO_MM_BASE + 0x0D00)
+#define DEVAPC_MM_APC_CON (DEVAPC_AO_MM_BASE + 0x0F00)
+
+#define MOD_NO_IN_1_DEVAPC 16
+#define MASTER_MOD_NO_IN_1_DEVAPC 8
+#define SLAVE_INFRA_MAX_INDEX 195
+#define SLAVE_MM_MAX_INDEX 140
+
+enum {
+ MASTER_SCP = 0,
+ MASTER_SPM = 10,
+ MASTER_SSPM = 27
+};
+
+enum MASK_DOM {
+ DOMAIN_0 = 0,
+ DOMAIN_1,
+ DOMAIN_2,
+ DOMAIN_3,
+ DOMAIN_4,
+ DOMAIN_5,
+ DOMAIN_6,
+ DOMAIN_7,
+ DOMAIN_8,
+ DOMAIN_9,
+ DOMAIN_10,
+ DOMAIN_11
+};
+
+enum TRANSACTION {
+ NON_SECURE_TRANSACTION = 0,
+ SECURE_TRANSACTION
+};
+
+enum DAPC_SLAVE_TYPE {
+ DAPC_INFRA_SLAVE = 0,
+ DAPC_MM_SLAVE
+};
+
+enum APC_ATTR {
+ NO_SEC = 0,
+ S_RW_ONLY,
+ S_RW_NS_R,
+ FORBID,
+};
+
+struct DEVICE_INFO {
+ uint8_t d0_permission;
+ uint8_t d1_permission;
+ uint8_t d2_permission;
+};
+
+#define PERMISSION(DEV_NAME, ATTR1, ATTR2, ATTR3) \
+{(uint8_t)ATTR1, (uint8_t)ATTR2, (uint8_t)ATTR3}
+
+static const struct DEVICE_INFO D_APC_INFRA_Devices[] = {
+/* module, domain0, domain1, domain2 */
+
+/* 0 */
+PERMISSION("INFRA_AO_TOPCKGEN", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("INFRA_AO_INFRASYS_CONFIG_REGS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IO_CFG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PERICFG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_EFUSE_AO_DEBUG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_GPIO", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_SLEEP_CONTROLLER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_TOPRGU", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_APXGPT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_RESERVE", NO_SEC, FORBID, NO_SEC),
+
+/* 10 */
+PERMISSION("INFRA_AO_SEJ", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_AP_CIRQ_EINT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_APMIXEDSYS", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("INFRA_AO_PMIC_WRAP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_DEVICE_APC_AO_INFRA_PERI", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_SLEEP_CONTROLLER_MD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_KEYPAD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_TOP_MISC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_DVFS_CTRL_PROC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_MBIST_AO_REG", NO_SEC, FORBID, NO_SEC),
+
+/* 20 */
+PERMISSION("INFRA_AO_CLDMA_AO_AP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_DEVICE_MPU", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_AES_TOP_0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_SYS_TIMER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_MDEM_TEMP_SHARE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_DEVICE_APC_AO_MD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_SECURITY_AO", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_TOPCKGEN_REG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_DEVICE_APC_AO_MM", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+
+/* 30 */
+PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_SYS_CIRQ", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_MM_IOMMU", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_EFUSE_PDN_DEBUG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DEVICE_APC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DBG_TRACKER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CCIF0_AP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CCIF0_MD", NO_SEC, FORBID, NO_SEC),
+
+/* 40 */
+PERMISSION("INFRASYS_CCIF1_AP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CCIF1_MD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_MBIST", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_INFRA_PDN_REGISTER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_TRNG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DX_CC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MD_CCIF_MD1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CQ_DMA", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MD_CCIF_MD2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_SRAMROM", NO_SEC, FORBID, NO_SEC),
+
+/* 50 */
+PERMISSION("ANA_MIPI_DSI0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("ANA_MIPI_CSI0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("ANA_MIPI_CSI1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_EMI", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CLDMA_PDN", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CLDMA_PDN_MD_MISC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_MD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("BPI_BSI_SLV0", NO_SEC, FORBID, NO_SEC),
+
+/* 60 */
+PERMISSION("BPI_BSI_SLV1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("BPI_BSI_SLV2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_EMI_MPU", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DVFS_PROC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH0_TOP0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH0_TOP1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH0_TOP2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH0_TOP3", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH0_TOP4", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH1_TOP0", NO_SEC, FORBID, NO_SEC),
+
+/* 70 */
+PERMISSION("INFRASYS_DRAMC_CH1_TOP1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH1_TOP2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH1_TOP3", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DRAMC_CH1_TOP4", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_GCE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CCIF2_AP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CCIF2_MD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CCIF3_AP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_CCIF3_MD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PWRMCU Partition 1", S_RW_NS_R, FORBID, NO_SEC),
+
+/* 80 */
+PERMISSION("INFRA_AO_PWRMCU Partition 2", S_RW_NS_R, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PWRMCU Partition 3", S_RW_NS_R, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PWRMCU Partition 4", S_RW_NS_R, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PWRMCU Partition 5", S_RW_NS_R, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PWRMCU Partition 6", S_RW_NS_R, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PWRMCU Partition 7", S_RW_NS_R, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_PWRMCU Partition 8", S_RW_NS_R, FORBID, NO_SEC),
+PERMISSION("INFRA_AO_SCP", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("INFRA_AO_MCUCFG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("INFRASYS_DBUGSYS", NO_SEC, FORBID, NO_SEC),
+
+/* 90 */
+PERMISSION("PERISYS_APDMA", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_AUXADC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_UART0", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("PERISYS_UART1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_UART2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C6", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_PWM", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C2", NO_SEC, FORBID, NO_SEC),
+
+/* 100 */
+PERMISSION("PERISYS_SPI0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_PTP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_BTIF", NO_SEC, FORBID, NO_SEC),
+PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_DISP_PWM", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C3", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_SPI1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C4", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_SPI2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_SPI3", NO_SEC, FORBID, NO_SEC),
+
+/* 110 */
+PERMISSION("PERISYS_I2C1_IMM", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C2_IMM", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C5", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C5_IMM", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_SPI4", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_SPI5", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C7", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_I2C8", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_USB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_USB_2_0_SUB", NO_SEC, FORBID, NO_SEC),
+
+/* 120 */
+PERMISSION("PERISYS_AUDIO", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_MSDC0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_MSDC1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_MSDC2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_UFS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_0", NO_SEC, FORBID, NO_SEC),
+
+/* 130 */
+PERMISSION("EAST_RESERVE_1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_3", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_4", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_IO_CFG_RT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_6", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_7", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_CSI0_TOP_AO", NO_SEC, FORBID, NO_SEC),
+PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_A", NO_SEC, FORBID, NO_SEC),
+
+/* 140 */
+PERMISSION("EAST_RESERVE_B", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_C", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_D", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_E", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EAST_RESERVE_F", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_IO_CFG_RM", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_IO_CFG_RB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_EFUSE", NO_SEC, FORBID, NO_SEC),
+
+/* 150 */
+PERMISSION("SOUTH_RESERVE_5", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_6", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_7", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_8", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_9", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_A", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_B", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_C", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_D", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SOUTH_RESERVE_E", NO_SEC, FORBID, NO_SEC),
+
+/* 160 */
+PERMISSION("SOUTH_RESERVE_F", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_MSDC1_PAD_MACRO", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_3", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_4", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_MIPI_TX_CONFIG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_6", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_IO_CFG_LB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_IO_CFG_LM", NO_SEC, FORBID, NO_SEC),
+
+/* 170 */
+PERMISSION("WEST_IO_CFG_BL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_A", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_B", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_C", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_D", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_E", NO_SEC, FORBID, NO_SEC),
+PERMISSION("WEST_RESERVE_F", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("EFUSE_TOP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_IO_CFG_LT", NO_SEC, FORBID, NO_SEC),
+
+/* 180 */
+PERMISSION("NORTH_IO_CFG_TL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_USB20 PHY", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_MSDC0 PAD MACRO", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_6", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_7", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_8", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_9", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_UFS_MPHY", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_B", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_C", NO_SEC, FORBID, NO_SEC),
+
+/* 190 */
+PERMISSION("NORTH_RESERVE_D", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_E", NO_SEC, FORBID, NO_SEC),
+PERMISSION("NORTH_RESERVE_F", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_CONN", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_MD_VIOLATION", NO_SEC, FORBID, NO_SEC),
+PERMISSION("PERISYS_RESERVE", NO_SEC, FORBID, NO_SEC)
+};
+
+static const struct DEVICE_INFO D_APC_MM_Devices[] = {
+/* module, domain0, domain1, domain2 */
+
+/* 0 */
+PERMISSION("G3D_CONFIG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MFG VAD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SC0 VAD", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MFG_OTHERS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MMSYS_CONFIG", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("MDP_RDMA0", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("MDP_RDMA1", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("MDP_RSZ0", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("MDP_RSZ1", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("MDP_WROT0", NO_SEC, NO_SEC, NO_SEC),
+
+/* 10 */
+PERMISSION("MDP_WDMA", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("MDP_TDSHP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_OVL0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_OVL0_2L", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_OVL1_2L", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_RDMA0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_RDMA1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_WDMA0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_COLOR0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_CCORR0", NO_SEC, FORBID, NO_SEC),
+
+/* 20 */
+PERMISSION("DISP_AAL0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_GAMMA0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DISP_DITHER0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DSI_SPLIT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DSI0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("DPI", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MM_MUTEX", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SMI_LARB0", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SMI_LARB1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("SMI_COMMON", NO_SEC, FORBID, NO_SEC),
+
+/* 30 */
+PERMISSION("DISP_RSZ", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MDP_AAL", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("MDP_CCORR", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("DBI", NO_SEC, FORBID, NO_SEC),
+PERMISSION("MMSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_CONFIG", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("IMGSYS_SMI_LARB1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_DISP_A0", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("IMGSYS_DISP_A1", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_DISP_A2", NO_SEC, FORBID, NO_SEC),
+
+/* 40 */
+PERMISSION("IMGSYS_DISP_A3", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_DISP_A4", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_DISP_A5", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_DPE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_RSC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_WPEA", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_FDVT", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("IMGSYS_OWE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_WPEB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_MFB", NO_SEC, FORBID, NO_SEC),
+
+/* 50 */
+PERMISSION("IMGSYS_SMI_LARB2", NO_SEC, FORBID, NO_SEC),
+PERMISSION("IMGSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VENCSYS_GLOBAL_CON", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("VENCSYSSYS_SMI_LARB4", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("VENCSYS_VENC", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("VENCSYS_JPGENC", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VENCSYS_MBIST_CTRL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VENCSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VDECSYS_GLOBAL_CON", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("VDECSYS_SMI_LARB1", NO_SEC, FORBID, NO_SEC),
+
+/* 60 */
+PERMISSION("VDECSYS_FULL_TOP", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("VDECSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAMSYS_TOP", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_LARB6", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_LARB3", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_CAM_TOP", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_CAM_A", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_CAM_A", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_CAM_B", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_CAM_B", NO_SEC, NO_SEC, NO_SEC),
+
+/* 70 */
+PERMISSION("CAMSYS_CAM_C", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_CAM_C", NO_SEC, NO_SEC, NO_SEC),
+PERMISSION("CAMSYS_CAM_TOP_SET", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_A_SET", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_A_SET", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_SET", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_SET", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_SET", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_SET", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_TOP_INNER", NO_SEC, FORBID, NO_SEC),
+
+/* 80 */
+PERMISSION("CAMSYS_CAM_A_INNER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_A_INNER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_INNER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_INNER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_INNER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_INNER", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_A_EXT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_EXT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_EXT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_TOP_CLR", NO_SEC, FORBID, NO_SEC),
+
+/* 90 */
+PERMISSION("CAMSYS_CAM_A_CLR", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_A_CLR", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_CLR", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_CLR", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_CLR", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_CLR", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_A_EXT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_B_EXT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_C_EXT", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAM_RESERVE", NO_SEC, FORBID, NO_SEC),
+
+/* 100 */
+PERMISSION("CAMSYS_SENINF_A", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_SENINF_B", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_SENINF_C", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_SENINF_D", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_SENINF_E", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_SENINF_F", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_SENINF_G", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_SENINF_H", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAMSV_A", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAMSV_B", NO_SEC, FORBID, NO_SEC),
+
+/* 110 */
+PERMISSION("CAMSYS_CAMSV_C", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CAMSV_D", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_MD32 DMEM_12", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_RESEVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CCU_CTL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CCU_H2T_A", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CCU_T2H_A", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_RESERVE", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_CCU_DMA", NO_SEC, FORBID, NO_SEC),
+
+/* 120 */
+PERMISSION("CAMSYS_TSF", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_MD32_PMEM_24", NO_SEC, FORBID, NO_SEC),
+PERMISSION("CAMSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_CFG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_ADL_CTRL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREA_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREA_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREA_IMEM_256KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREA_CONTROL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREA_DEBUG", NO_SEC, FORBID, NO_SEC),
+
+/* 130 */
+PERMISSION("VPUSYS_COREB_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREB_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREB_IMEM_256KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREB_CONTROL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREB_DEBUG", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREC_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREC_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREC_IMEM_256KB", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREC_CONTROL", NO_SEC, FORBID, NO_SEC),
+PERMISSION("VPUSYS_COREC_DEBUG", NO_SEC, FORBID, NO_SEC),
+
+/* 140 */
+PERMISSION("VPUSYS_OTHERS", NO_SEC, FORBID, NO_SEC)
+};
+
+void devapc_init(void);
+
+#endif /* DEVAPC_H */
+
diff --git a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..56d2ce2
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <emi_mpu.h>
+
+int is_4GB(void)
+{
+ return 0; /* 8183 doesn't use 4GB */
+}
+
+/*
+ * emi_mpu_set_region_protection: protect a region.
+ * @start: start address of the region
+ * @end: end address of the region
+ * @region: EMI MPU region id
+ * @access_permission: EMI MPU access permission
+ * Return 0 for success, otherwise negative status code.
+ */
+int emi_mpu_set_region_protection(
+ unsigned long start, unsigned long end,
+ int region,
+ unsigned int access_permission)
+{
+ int ret = 0;
+
+ if (end <= start) {
+ ERROR("[EMI][MTEE][MPU] Invalid address!.\n");
+ return -1;
+ }
+
+ if (is_4GB()) {
+ /* 4GB mode: emi_addr = phy_addr & 0xffff */
+ start = EMI_PHY_OFFSET & 0xffff;
+ end = EMI_PHY_OFFSET & 0xffff;
+ } else {
+ /* non-4GB mode: emi_addr = phy_addr - MEM_OFFSET */
+ start = start - EMI_PHY_OFFSET;
+ end = end - EMI_PHY_OFFSET;
+ }
+
+ /*Address 64KB alignment*/
+ start = start >> 16;
+ end = end >> 16;
+
+ switch (region) {
+ case 0:
+ mmio_write_32(EMI_MPU_APC0, 0);
+ mmio_write_32(EMI_MPU_SA0, start);
+ mmio_write_32(EMI_MPU_EA0, end);
+ mmio_write_32(EMI_MPU_APC0, access_permission);
+ break;
+
+ case 1:
+ mmio_write_32(EMI_MPU_APC1, 0);
+ mmio_write_32(EMI_MPU_SA1, start);
+ mmio_write_32(EMI_MPU_EA1, end);
+ mmio_write_32(EMI_MPU_APC1, access_permission);
+ break;
+
+ case 2:
+ mmio_write_32(EMI_MPU_APC2, 0);
+ mmio_write_32(EMI_MPU_SA2, start);
+ mmio_write_32(EMI_MPU_EA2, end);
+ mmio_write_32(EMI_MPU_APC2, access_permission);
+ break;
+
+ case 3:
+ mmio_write_32(EMI_MPU_APC3, 0);
+ mmio_write_32(EMI_MPU_SA3, start);
+ mmio_write_32(EMI_MPU_EA3, end);
+ mmio_write_32(EMI_MPU_APC3, access_permission);
+ break;
+
+ case 4:
+ mmio_write_32(EMI_MPU_APC4, 0);
+ mmio_write_32(EMI_MPU_SA4, start);
+ mmio_write_32(EMI_MPU_EA4, end);
+ mmio_write_32(EMI_MPU_APC4, access_permission);
+ break;
+
+ case 5:
+ mmio_write_32(EMI_MPU_APC5, 0);
+ mmio_write_32(EMI_MPU_SA5, start);
+ mmio_write_32(EMI_MPU_EA5, end);
+ mmio_write_32(EMI_MPU_APC5, access_permission);
+ break;
+
+ case 6:
+ mmio_write_32(EMI_MPU_APC6, 0);
+ mmio_write_32(EMI_MPU_SA6, start);
+ mmio_write_32(EMI_MPU_EA6, end);
+ mmio_write_32(EMI_MPU_APC6, access_permission);
+ break;
+
+ case 7:
+ mmio_write_32(EMI_MPU_APC7, 0);
+ mmio_write_32(EMI_MPU_SA7, start);
+ mmio_write_32(EMI_MPU_EA7, end);
+ mmio_write_32(EMI_MPU_APC7, access_permission);
+ break;
+
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+void dump_emi_mpu_regions(void)
+{
+ unsigned int apc, sa, ea;
+ unsigned int apc_addr = EMI_MPU_APC0;
+ unsigned int sa_addr = EMI_MPU_SA0;
+ unsigned int ea_addr = EMI_MPU_EA0;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ apc = mmio_read_32(apc_addr + i * 4);
+ sa = mmio_read_32(sa_addr + i * 4);
+ ea = mmio_read_32(ea_addr + i * 4);
+ WARN("region %d:\n", i);
+ WARN("\tapc:0x%x, sa:0x%x, ea:0x%x\n", apc, sa, ea);
+ }
+}
+
+void emi_mpu_init(void)
+{
+ /* Set permission */
+ emi_mpu_set_region_protection(0x40000000UL, 0x4FFFFFFFUL, 0,
+ (FORBIDDEN << 3 | FORBIDDEN << 6));
+ emi_mpu_set_region_protection(0x50000000UL, 0x528FFFFFUL, 1,
+ (FORBIDDEN << 6));
+ emi_mpu_set_region_protection(0x52900000UL, 0x5FFFFFFFUL, 2,
+ (FORBIDDEN << 3 | FORBIDDEN << 6));
+ emi_mpu_set_region_protection(0x60000000UL, 0xFFFFFFFFUL, 3,
+ (FORBIDDEN << 3 | FORBIDDEN << 6));
+ emi_mpu_set_region_protection(0x100000000UL, 0x23FFFFFFFUL, 4,
+ (FORBIDDEN << 3 | FORBIDDEN << 6));
+ dump_emi_mpu_regions();
+}
+
diff --git a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..b67ea56
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __EMI_MPU_H
+#define __EMI_MPU_H
+
+#include <platform_def.h>
+
+#define EMI_MPUP (EMI_BASE + 0x01D8)
+#define EMI_MPUQ (EMI_BASE + 0x01E0)
+#define EMI_MPUR (EMI_BASE + 0x01E8)
+#define EMI_MPUS (EMI_BASE + 0x01F0)
+#define EMI_MPUT (EMI_BASE + 0x01F8)
+#define EMI_MPUY (EMI_BASE + 0x0220)
+#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x0000)
+#define EMI_MPUD0_ST (EMI_BASE + 0x0160)
+#define EMI_MPUD1_ST (EMI_BASE + 0x0164)
+#define EMI_MPUD2_ST (EMI_BASE + 0x0168)
+#define EMI_MPUD3_ST (EMI_BASE + 0x016C)
+#define EMI_MPUD0_ST2 (EMI_BASE + 0x0200)
+#define EMI_MPUD1_ST2 (EMI_BASE + 0x0204)
+#define EMI_MPUD2_ST2 (EMI_BASE + 0x0208)
+#define EMI_MPUD3_ST2 (EMI_BASE + 0x020C)
+
+#define EMI_PHY_OFFSET (0x40000000UL)
+#define EIGHT_DOMAIN
+
+#define NO_PROTECTION (0)
+#define SEC_RW (1)
+#define SEC_RW_NSEC_R (2)
+#define SEC_RW_NSEC_W (3)
+#define SEC_R_NSEC_R (4)
+#define FORBIDDEN (5)
+#define SEC_R_NSEC_RW (6)
+
+#define SECURE_OS_MPU_REGION_ID (0)
+#define ATF_MPU_REGION_ID (1)
+
+#ifdef EIGHT_DOMAIN
+#define SET_ACCESS_PERMISSON(d7, d6, d5, d4, d3, d2, d1, d0) \
+ (((d7) << 21) | ((d6) << 18) | ((d5) << 15) | ((d4) << 12) \
+ | ((d3) << 9) | ((d2) << 6) | ((d1) << 3) | (d0))
+#else
+#define SET_ACCESS_PERMISSON(d3, d2, d1, d0) \
+ (((d3) << 9) | ((d2) << 6) | ((d1) << 3) | (d0))
+#endif
+
+//#define EMI_MPU_BASE (0x1020E000U)
+
+#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
+#define EMI_MPU_SA1 (EMI_MPU_BASE + 0x104)
+#define EMI_MPU_SA2 (EMI_MPU_BASE + 0x108)
+#define EMI_MPU_SA3 (EMI_MPU_BASE + 0x10C)
+#define EMI_MPU_SA4 (EMI_MPU_BASE + 0x110)
+#define EMI_MPU_SA5 (EMI_MPU_BASE + 0x114)
+#define EMI_MPU_SA6 (EMI_MPU_BASE + 0x118)
+#define EMI_MPU_SA7 (EMI_MPU_BASE + 0x11C)
+
+#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
+#define EMI_MPU_EA1 (EMI_MPU_BASE + 0x204)
+#define EMI_MPU_EA2 (EMI_MPU_BASE + 0x208)
+#define EMI_MPU_EA3 (EMI_MPU_BASE + 0x20C)
+#define EMI_MPU_EA4 (EMI_MPU_BASE + 0x210)
+#define EMI_MPU_EA5 (EMI_MPU_BASE + 0x214)
+#define EMI_MPU_EA6 (EMI_MPU_BASE + 0x218)
+#define EMI_MPU_EA7 (EMI_MPU_BASE + 0x21C)
+
+#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC1 (EMI_MPU_BASE + 0x304)
+#define EMI_MPU_APC2 (EMI_MPU_BASE + 0x308)
+#define EMI_MPU_APC3 (EMI_MPU_BASE + 0x30C)
+#define EMI_MPU_APC4 (EMI_MPU_BASE + 0x310)
+#define EMI_MPU_APC5 (EMI_MPU_BASE + 0x314)
+#define EMI_MPU_APC6 (EMI_MPU_BASE + 0x318)
+#define EMI_MPU_APC7 (EMI_MPU_BASE + 0x31C)
+
+#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D1 (EMI_MPU_BASE + 0x804)
+#define EMI_MPU_CTRL_D2 (EMI_MPU_BASE + 0x808)
+#define EMI_MPU_CTRL_D3 (EMI_MPU_BASE + 0x80C)
+#define EMI_MPU_CTRL_D4 (EMI_MPU_BASE + 0x810)
+#define EMI_MPU_CTRL_D5 (EMI_MPU_BASE + 0x814)
+#define EMI_MPU_CTRL_D6 (EMI_MPU_BASE + 0x818)
+#define EMI_MPU_CTRL_D7 (EMI_MPU_BASE + 0x81C)
+
+#define EMI_MPU_MASK_D0 (EMI_MPU_BASE + 0x900)
+#define EMI_MPU_MASK_D1 (EMI_MPU_BASE + 0x904)
+#define EMI_MPU_MASK_D2 (EMI_MPU_BASE + 0x908)
+#define EMI_MPU_MASK_D3 (EMI_MPU_BASE + 0x90C)
+#define EMI_MPU_MASK_D4 (EMI_MPU_BASE + 0x910)
+#define EMI_MPU_MASK_D5 (EMI_MPU_BASE + 0x914)
+#define EMI_MPU_MASK_D6 (EMI_MPU_BASE + 0x918)
+#define EMI_MPU_MASK_D7 (EMI_MPU_BASE + 0x91C)
+
+int emi_mpu_set_region_protection(
+ unsigned long start, unsigned long end,
+ int region,
+ unsigned int access_permission);
+
+void dump_emi_mpu_regions(void);
+void emi_mpu_init(void);
+
+#endif /* __EMI_MPU_H */
diff --git a/plat/mediatek/mt8183/drivers/gpio/mtgpio.c b/plat/mediatek/mt8183/drivers/gpio/mtgpio.c
new file mode 100644
index 0000000..61aaeef
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/gpio/mtgpio.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <gpio/mtgpio.h>
+#include <gpio/mtgpio_cfg.h>
+#include <drivers/gpio.h>
+#include <mcucfg.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <spm.h>
+#include <stdbool.h>
+
+/******************************************************************************
+ *Macro Definition
+ ******************************************************************************/
+#define GPIO_MODE_BITS 4
+#define MAX_GPIO_MODE_PER_REG 8
+#define MAX_GPIO_REG_BITS 32
+#define DIR_BASE (GPIO_BASE + 0x000)
+#define DOUT_BASE (GPIO_BASE + 0x100)
+#define DIN_BASE (GPIO_BASE + 0x200)
+#define MODE_BASE (GPIO_BASE + 0x300)
+#define SET 0x4
+#define CLR 0x8
+#define PULLEN_ADDR_OFFSET 0x060
+#define PULLSEL_ADDR_OFFSET 0x080
+
+void mt_set_gpio_dir_chip(uint32_t pin, int dir)
+{
+ uint32_t pos, bit;
+
+ assert(pin < MAX_GPIO_PIN);
+ assert(dir < GPIO_DIR_MAX);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ if (dir == GPIO_DIR_IN)
+ mmio_write_32(DIR_BASE + 0x10 * pos + CLR, 1U << bit);
+ else
+ mmio_write_32(DIR_BASE + 0x10 * pos + SET, 1U << bit);
+}
+
+int mt_get_gpio_dir_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t reg;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ reg = mmio_read_32(DIR_BASE + 0x10 * pos);
+ return (((reg & (1U << bit)) != 0) ? GPIO_DIR_OUT : GPIO_DIR_IN);
+}
+
+void mt_set_gpio_out_chip(uint32_t pin, int output)
+{
+ uint32_t pos, bit;
+
+ assert(pin < MAX_GPIO_PIN);
+ assert(output < GPIO_OUT_MAX);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ if (output == GPIO_OUT_ZERO)
+ mmio_write_32(DOUT_BASE + 0x10 * pos + CLR, 1U << bit);
+ else
+ mmio_write_32(DOUT_BASE + 0x10 * pos + SET, 1U << bit);
+}
+
+int mt_get_gpio_out_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t reg;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ reg = mmio_read_32(DOUT_BASE + 0x10 * pos);
+ return (((reg & (1U << bit)) != 0) ? 1 : 0);
+}
+
+int mt_get_gpio_in_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t reg;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ pos = pin / MAX_GPIO_REG_BITS;
+ bit = pin % MAX_GPIO_REG_BITS;
+
+ reg = mmio_read_32(DIN_BASE + 0x10 * pos);
+ return (((reg & (1U << bit)) != 0) ? 1 : 0);
+}
+
+void mt_set_gpio_mode_chip(uint32_t pin, int mode)
+{
+ uint32_t pos, bit;
+ uint32_t data;
+ uint32_t mask;
+
+ assert(pin < MAX_GPIO_PIN);
+ assert(mode < GPIO_MODE_MAX);
+
+ mask = (1U << GPIO_MODE_BITS) - 1;
+
+ mode = mode & mask;
+ pos = pin / MAX_GPIO_MODE_PER_REG;
+ bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
+
+ data = mmio_read_32(MODE_BASE + 0x10 * pos);
+ data &= (~(mask << bit));
+ data |= (mode << bit);
+ mmio_write_32(MODE_BASE + 0x10 * pos, data);
+}
+
+int mt_get_gpio_mode_chip(uint32_t pin)
+{
+ uint32_t pos, bit;
+ uint32_t data;
+ uint32_t mask;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ mask = (1U << GPIO_MODE_BITS) - 1;
+
+ pos = pin / MAX_GPIO_MODE_PER_REG;
+ bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
+
+ data = mmio_read_32(MODE_BASE + 0x10 * pos);
+ return (data >> bit) & mask;
+}
+
+int32_t gpio_get_pull_iocfg(uint32_t pin)
+{
+ switch (pin) {
+ case 0 ... 10:
+ return IOCFG_5_BASE;
+ case 11 ... 12:
+ return IOCFG_0_BASE;
+ case 13 ... 28:
+ return IOCFG_1_BASE;
+ case 43 ... 49:
+ return IOCFG_2_BASE;
+ case 50 ... 60:
+ return IOCFG_3_BASE;
+ case 61 ... 88:
+ return IOCFG_4_BASE;
+ case 89 ... 90:
+ return IOCFG_5_BASE;
+ case 95 ... 106:
+ return IOCFG_5_BASE;
+ case 107 ... 121:
+ return IOCFG_6_BASE;
+ case 134 ... 160:
+ return IOCFG_0_BASE;
+ case 161 ... 166:
+ return IOCFG_1_BASE;
+ case 167 ... 176:
+ return IOCFG_3_BASE;
+ case 177 ... 179:
+ return IOCFG_5_BASE;
+ default:
+ return -1;
+ }
+}
+
+int32_t gpio_get_pupd_iocfg(uint32_t pin)
+{
+ const int32_t offset = 0x0c0;
+
+ switch (pin) {
+ case 29 ... 34:
+ return IOCFG_1_BASE + offset;
+ case 35 ... 42:
+ return IOCFG_2_BASE + offset;
+ case 91 ... 94:
+ return IOCFG_5_BASE + offset;
+ case 122 ... 133:
+ return IOCFG_7_BASE + offset;
+ default:
+ return -1;
+ }
+}
+
+int gpio_get_pupd_offset(uint32_t pin)
+{
+ switch (pin) {
+ case 29 ... 34:
+ return (pin - 29) * 4 % 32;
+ case 35 ... 42:
+ return (pin - 35) * 4 % 32;
+ case 91 ... 94:
+ return (pin - 91) * 4 % 32;
+ case 122 ... 129:
+ return (pin - 122) * 4 % 32;
+ case 130 ... 133:
+ return (pin - 130) * 4 % 32;
+ default:
+ return -1;
+ }
+}
+
+void mt_set_gpio_pull_enable_chip(uint32_t pin, int en)
+{
+ int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
+ int pupd_addr = gpio_get_pupd_iocfg(pin);
+ int pupd_offset = gpio_get_pupd_offset(pin);
+
+ assert(pin < MAX_GPIO_PIN);
+
+ assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
+ (pupd_offset == (int8_t)-1)));
+
+ if (en == GPIO_PULL_DISABLE) {
+ if (PULL_offset[pin].offset == (int8_t)-1)
+ mmio_clrbits_32(pupd_addr, 3U << pupd_offset);
+ else
+ mmio_clrbits_32(pullen_addr,
+ 1U << PULL_offset[pin].offset);
+ } else if (en == GPIO_PULL_ENABLE) {
+ if (PULL_offset[pin].offset == (int8_t)-1) {
+ /* For PUPD+R0+R1 Type, mt_set_gpio_pull_enable
+ * does not know
+ * which one between PU and PD shall be enabled.
+ * Use R0 to guarantee at one resistor is set when lk
+ * apply default setting
+ */
+ mmio_setbits_32(pupd_addr, 1U << pupd_offset);
+ mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
+ } else {
+ /* For PULLEN + PULLSEL Type */
+ mmio_setbits_32(pullen_addr,
+ 1U << PULL_offset[pin].offset);
+ }
+ } else if (en == GPIO_PULL_ENABLE_R0) {
+ assert(!(pupd_offset == (int8_t)-1));
+ mmio_setbits_32(pupd_addr, 1U << pupd_offset);
+ mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
+ } else if (en == GPIO_PULL_ENABLE_R1) {
+ assert(!(pupd_offset == (int8_t)-1));
+
+ mmio_clrbits_32(pupd_addr, 1U << pupd_offset);
+ mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 1));
+ } else if (en == GPIO_PULL_ENABLE_R0R1) {
+ assert(!(pupd_offset == (int8_t)-1));
+ mmio_setbits_32(pupd_addr, 3U << pupd_offset);
+ }
+}
+
+int mt_get_gpio_pull_enable_chip(uint32_t pin)
+{
+ uint32_t reg;
+
+ int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
+ int pupd_addr = gpio_get_pupd_iocfg(pin);
+ int pupd_offset = gpio_get_pupd_offset(pin);
+
+ assert(pin < MAX_GPIO_PIN);
+
+ assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
+ (pupd_offset == (int8_t)-1)));
+
+ if (PULL_offset[pin].offset == (int8_t)-1) {
+ reg = mmio_read_32(pupd_addr);
+ return ((reg & (3U << pupd_offset)) ? 1 : 0);
+ } else if (pupd_offset == (int8_t)-1) {
+ reg = mmio_read_32(pullen_addr);
+ return ((reg & (1U << PULL_offset[pin].offset)) ? 1 : 0);
+ }
+
+ return -ERINVAL;
+}
+
+void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
+{
+ int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
+ int pupd_addr = gpio_get_pupd_iocfg(pin);
+ int pupd_offset = gpio_get_pupd_offset(pin);
+
+ assert(pin < MAX_GPIO_PIN);
+
+ assert(!((PULL_offset[pin].offset == (int8_t) -1) &&
+ (pupd_offset == (int8_t)-1)));
+
+ if (sel == GPIO_PULL_NONE) {
+ /* Regard No PULL as PULL disable + pull down */
+ mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_DISABLE);
+ if (PULL_offset[pin].offset == (int8_t)-1)
+ mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
+ else
+ mmio_clrbits_32(pullsel_addr,
+ 1U << PULL_offset[pin].offset);
+ } else if (sel == GPIO_PULL_UP) {
+ mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
+ if (PULL_offset[pin].offset == (int8_t)-1)
+ mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 2));
+ else
+ mmio_setbits_32(pullsel_addr,
+ 1U << PULL_offset[pin].offset);
+ } else if (sel == GPIO_PULL_DOWN) {
+ mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
+ if (PULL_offset[pin].offset == -1)
+ mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
+ else
+ mmio_clrbits_32(pullsel_addr,
+ 1U << PULL_offset[pin].offset);
+ }
+}
+
+/* get pull-up or pull-down, regardless of resistor value */
+int mt_get_gpio_pull_select_chip(uint32_t pin)
+{
+ uint32_t reg;
+
+ int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
+ int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
+ int pupd_addr = gpio_get_pupd_iocfg(pin);
+ int pupd_offset = gpio_get_pupd_offset(pin);
+
+ assert(pin < MAX_GPIO_PIN);
+
+ assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
+ (pupd_offset == (int8_t)-1)));
+
+ if (PULL_offset[pin].offset == (int8_t)-1) {
+ reg = mmio_read_32(pupd_addr);
+ if (reg & (3U << pupd_offset)) {
+ reg = mmio_read_32(pupd_addr);
+ /* Reg value: 0 for PU, 1 for PD -->
+ * reverse return value */
+ return ((reg & (1U << (pupd_offset + 2))) ?
+ GPIO_PULL_DOWN : GPIO_PULL_UP);
+ } else {
+ return GPIO_PULL_NONE;
+ }
+ } else if (pupd_offset == (int8_t)-1) {
+ reg = mmio_read_32(pullen_addr);
+ if ((reg & (1U << PULL_offset[pin].offset))) {
+ reg = mmio_read_32(pullsel_addr);
+ return ((reg & (1U << PULL_offset[pin].offset)) ?
+ GPIO_PULL_UP : GPIO_PULL_DOWN);
+ } else {
+ return GPIO_PULL_NONE;
+ }
+ }
+
+ return -ERINVAL;
+}
+
+void mt_set_gpio_dir(int gpio, int direction)
+{
+ mt_set_gpio_dir_chip((uint32_t)gpio, direction);
+}
+
+int mt_get_gpio_dir(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_dir_chip(pin);
+}
+
+void mt_set_gpio_pull(int gpio, int pull)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ mt_set_gpio_pull_select_chip(pin, pull);
+}
+
+int mt_get_gpio_pull(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_pull_select_chip(pin);
+}
+
+void mt_set_gpio_out(int gpio, int value)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ mt_set_gpio_out_chip(pin, value);
+}
+
+int mt_get_gpio_out(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_out_chip(pin);
+}
+
+int mt_get_gpio_in(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_in_chip(pin);
+}
+
+void mt_set_gpio_mode(int gpio, int mode)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ mt_set_gpio_mode_chip(pin, mode);
+}
+
+int mt_get_gpio_mode(int gpio)
+{
+ uint32_t pin;
+
+ pin = (uint32_t)gpio;
+ return mt_get_gpio_mode_chip(pin);
+}
+
+const gpio_ops_t mtgpio_ops = {
+ .get_direction = mt_get_gpio_dir,
+ .set_direction = mt_set_gpio_dir,
+ .get_value = mt_get_gpio_in,
+ .set_value = mt_set_gpio_out,
+ .set_pull = mt_set_gpio_pull,
+ .get_pull = mt_get_gpio_pull,
+};
diff --git a/plat/mediatek/mt8183/drivers/gpio/mtgpio.h b/plat/mediatek/mt8183/drivers/gpio/mtgpio.h
new file mode 100644
index 0000000..9461c54
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/gpio/mtgpio.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <stdint.h>
+#include <plat/common/common_def.h>
+
+/* Error Code No. */
+#define RSUCCESS 0
+#define ERACCESS 1
+#define ERINVAL 2
+#define ERWRAPPER 3
+#define MAX_GPIO_PIN MT_GPIO_BASE_MAX
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+ GPIO_UNSUPPORTED = -1,
+
+ GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
+ GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
+ GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
+ GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
+ GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
+ GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
+ GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
+ GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
+ GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
+ GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
+ GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
+ GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
+ GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
+ GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
+ GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
+ GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
+ GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135,
+ GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143,
+ GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151,
+ GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159,
+ GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167,
+ GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175,
+ GPIO176, GPIO177, GPIO178, GPIO179,
+ MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+/* GPIO MODE CONTROL VALUE*/
+typedef enum {
+ GPIO_MODE_UNSUPPORTED = -1,
+ GPIO_MODE_GPIO = 0,
+ GPIO_MODE_00 = 0,
+ GPIO_MODE_01,
+ GPIO_MODE_02,
+ GPIO_MODE_03,
+ GPIO_MODE_04,
+ GPIO_MODE_05,
+ GPIO_MODE_06,
+ GPIO_MODE_07,
+
+ GPIO_MODE_MAX,
+ GPIO_MODE_DEFAULT = GPIO_MODE_00,
+} GPIO_MODE;
+
+/* GPIO DIRECTION */
+typedef enum {
+ GPIO_DIR_UNSUPPORTED = -1,
+ GPIO_DIR_OUT = 0,
+ GPIO_DIR_IN = 1,
+ GPIO_DIR_MAX,
+ GPIO_DIR_DEFAULT = GPIO_DIR_IN,
+} GPIO_DIR;
+
+/* GPIO PULL ENABLE*/
+typedef enum {
+ GPIO_PULL_EN_UNSUPPORTED = -1,
+ GPIO_PULL_DISABLE = 0,
+ GPIO_PULL_ENABLE = 1,
+ GPIO_PULL_ENABLE_R0 = 2,
+ GPIO_PULL_ENABLE_R1 = 3,
+ GPIO_PULL_ENABLE_R0R1 = 4,
+
+ GPIO_PULL_EN_MAX,
+ GPIO_PULL_EN_DEFAULT = GPIO_PULL_ENABLE,
+} GPIO_PULL_EN;
+
+/* GPIO PULL-UP/PULL-DOWN*/
+typedef enum {
+ GPIO_PULL_UNSUPPORTED = -1,
+ GPIO_PULL_NONE = 0,
+ GPIO_PULL_UP = 1,
+ GPIO_PULL_DOWN = 2,
+ GPIO_PULL_MAX,
+ GPIO_PULL_DEFAULT = GPIO_PULL_DOWN
+} GPIO_PULL;
+
+/* GPIO OUTPUT */
+typedef enum {
+ GPIO_OUT_UNSUPPORTED = -1,
+ GPIO_OUT_ZERO = 0,
+ GPIO_OUT_ONE = 1,
+
+ GPIO_OUT_MAX,
+ GPIO_OUT_DEFAULT = GPIO_OUT_ZERO,
+ GPIO_DATA_OUT_DEFAULT = GPIO_OUT_ZERO, /*compatible with DCT*/
+} GPIO_OUT;
+
+/* GPIO INPUT */
+typedef enum {
+ GPIO_IN_UNSUPPORTED = -1,
+ GPIO_IN_ZERO = 0,
+ GPIO_IN_ONE = 1,
+
+ GPIO_IN_MAX,
+} GPIO_IN;
+
+typedef struct {
+ uint32_t val;
+ uint32_t set;
+ uint32_t rst;
+ uint32_t _align1;
+} VAL_REGS;
+
+typedef struct {
+ VAL_REGS dir[6]; /*0x0000 ~ 0x005F: 96 bytes */
+ uint8_t rsv00[160]; /*0x0060 ~ 0x00FF: 160 bytes */
+ VAL_REGS dout[6]; /*0x0100 ~ 0x015F: 96 bytes */
+ uint8_t rsv01[160]; /*0x0160 ~ 0x01FF: 160 bytes */
+ VAL_REGS din[6]; /*0x0200 ~ 0x025F: 96 bytes */
+ uint8_t rsv02[160]; /*0x0260 ~ 0x02FF: 160 bytes */
+ VAL_REGS mode[23]; /*0x0300 ~ 0x046F: 368 bytes */
+} GPIO_REGS;
+
+/* GPIO Driver interface */
+/*direction*/
+void mt_set_gpio_dir(int gpio, int direction);
+int mt_get_gpio_dir(int gpio);
+
+/*pull select*/
+void mt_set_gpio_pull(int gpio, int pull);
+int mt_get_gpio_pull(int gpio);
+
+/*input/output*/
+void mt_set_gpio_out(int gpio, int value);
+int mt_get_gpio_out(int gpio);
+int mt_get_gpio_in(int gpio);
+
+/*mode control*/
+void mt_set_gpio_mode(int gpio, int mode);
+int mt_get_gpio_mode(int gpio);
+
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h b/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h
new file mode 100644
index 0000000..4e1fd2b
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_CFG_H
+#define MT_GPIO_CFG_H
+
+#include <stdint.h>
+#include <plat/common/common_def.h>
+
+#define IOCFG_0_BASE 0x11F20000
+#define IOCFG_1_BASE 0x11E80000
+#define IOCFG_2_BASE 0x11E70000
+#define IOCFG_3_BASE 0x11E90000
+#define IOCFG_4_BASE 0x11D30000
+#define IOCFG_5_BASE 0x11D20000
+#define IOCFG_6_BASE 0x11C50000
+#define IOCFG_7_BASE 0x11F30000
+
+typedef struct {
+ int8_t offset;
+} PIN_offset;
+
+PIN_offset PULL_offset[] = {
+ /* 0 */ {6},
+ /* 1 */ {7},
+ /* 2 */ {8},
+ /* 3 */ {9},
+ /* 4 */ {11},
+ /* 5 */ {12},
+ /* 6 */ {13},
+ /* 7 */ {14},
+ /* 8 */ {0},
+ /* 9 */ {26},
+ /* 10 */ {27},
+ /* 11 */ {10},
+ /* 12 */ {17},
+ /* 13 */ {6},
+ /* 14 */ {7},
+ /* 15 */ {8},
+ /* 16 */ {9},
+ /* 17 */ {10},
+ /* 18 */ {11},
+ /* 19 */ {12},
+ /* 20 */ {13},
+ /* 21 */ {14},
+ /* 22 */ {15},
+ /* 23 */ {16},
+ /* 24 */ {17},
+ /* 25 */ {18},
+ /* 26 */ {19},
+ /* 27 */ {20},
+ /* 28 */ {21},
+ /* 29 */ {-1},
+ /* 30 */ {-1},
+ /* 31 */ {-1},
+ /* 32 */ {-1},
+ /* 33 */ {-1},
+ /* 34 */ {-1},
+ /* 35 */ {-1},
+ /* 36 */ {-1},
+ /* 37 */ {-1},
+ /* 38 */ {-1},
+ /* 39 */ {-1},
+ /* 40 */ {-1},
+ /* 41 */ {-1},
+ /* 42 */ {-1},
+ /* 43 */ {8},
+ /* 44 */ {9},
+ /* 45 */ {10},
+ /* 46 */ {11},
+ /* 47 */ {12},
+ /* 48 */ {13},
+ /* 49 */ {14},
+ /* 50 */ {0},
+ /* 51 */ {1},
+ /* 52 */ {2},
+ /* 53 */ {3},
+ /* 54 */ {4},
+ /* 55 */ {5},
+ /* 56 */ {6},
+ /* 57 */ {7},
+ /* 58 */ {8},
+ /* 59 */ {9},
+ /* 60 */ {10},
+ /* 61 */ {0},
+ /* 62 */ {1},
+ /* 63 */ {2},
+ /* 64 */ {3},
+ /* 65 */ {4},
+ /* 66 */ {5},
+ /* 67 */ {6},
+ /* 68 */ {7},
+ /* 69 */ {8},
+ /* 70 */ {9},
+ /* 71 */ {10},
+ /* 72 */ {11},
+ /* 73 */ {12},
+ /* 74 */ {13},
+ /* 75 */ {14},
+ /* 76 */ {15},
+ /* 77 */ {16},
+ /* 78 */ {17},
+ /* 79 */ {18},
+ /* 80 */ {19},
+ /* 81 */ {20},
+ /* 82 */ {21},
+ /* 83 */ {22},
+ /* 84 */ {23},
+ /* 85 */ {24},
+ /* 86 */ {25},
+ /* 87 */ {26},
+ /* 88 */ {27},
+ /* 89 */ {24},
+ /* 90 */ {1},
+ /* 91 */ {-1},
+ /* 92 */ {-1},
+ /* 93 */ {-1},
+ /* 94 */ {-1},
+ /* 95 */ {15},
+ /* 96 */ {17},
+ /* 97 */ {18},
+ /* 98 */ {19},
+ /* 99 */ {20},
+ /* 100 */ {21},
+ /* 101 */ {22},
+ /* 102 */ {23},
+ /* 103 */ {28},
+ /* 104 */ {29},
+ /* 105 */ {30},
+ /* 106 */ {31},
+ /* 107 */ {0},
+ /* 108 */ {1},
+ /* 109 */ {2},
+ /* 110 */ {3},
+ /* 111 */ {4},
+ /* 112 */ {5},
+ /* 113 */ {6},
+ /* 114 */ {7},
+ /* 115 */ {8},
+ /* 116 */ {9},
+ /* 117 */ {10},
+ /* 118 */ {11},
+ /* 119 */ {12},
+ /* 120 */ {13},
+ /* 121 */ {14},
+ /* 122 */ {-1},
+ /* 123 */ {-1},
+ /* 124 */ {-1},
+ /* 125 */ {-1},
+ /* 126 */ {-1},
+ /* 127 */ {-1},
+ /* 128 */ {-1},
+ /* 129 */ {-1},
+ /* 130 */ {-1},
+ /* 131 */ {-1},
+ /* 132 */ {-1},
+ /* 133 */ {-1},
+ /* 134 */ {0},
+ /* 135 */ {1},
+ /* 136 */ {2},
+ /* 137 */ {3},
+ /* 138 */ {4},
+ /* 139 */ {5},
+ /* 140 */ {6},
+ /* 141 */ {7},
+ /* 142 */ {8},
+ /* 143 */ {9},
+ /* 144 */ {11},
+ /* 145 */ {12},
+ /* 146 */ {13},
+ /* 147 */ {14},
+ /* 148 */ {15},
+ /* 149 */ {16},
+ /* 150 */ {18},
+ /* 151 */ {19},
+ /* 152 */ {20},
+ /* 153 */ {21},
+ /* 154 */ {22},
+ /* 155 */ {23},
+ /* 156 */ {24},
+ /* 157 */ {25},
+ /* 158 */ {26},
+ /* 159 */ {27},
+ /* 160 */ {28},
+ /* 161 */ {0},
+ /* 162 */ {1},
+ /* 163 */ {2},
+ /* 164 */ {3},
+ /* 165 */ {4},
+ /* 166 */ {5},
+ /* 167 */ {11},
+ /* 168 */ {12},
+ /* 169 */ {13},
+ /* 170 */ {14},
+ /* 171 */ {15},
+ /* 172 */ {16},
+ /* 173 */ {17},
+ /* 174 */ {18},
+ /* 175 */ {19},
+ /* 176 */ {20},
+ /* 177 */ {10},
+ /* 178 */ {16},
+ /* 179 */ {25}
+};
+#endif /* MT_GPIO_CFG_H */
diff --git a/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c b/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c
new file mode 100644
index 0000000..29eebcb
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <sspm_reg.h>
+#include <mtk_mcdi.h>
+
+static inline uint32_t mcdi_mbox_read(uint32_t id)
+{
+ return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
+}
+
+static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
+{
+ mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
+}
+
+void sspm_set_bootaddr(uint32_t bootaddr)
+{
+ mcdi_mbox_write(MCDI_MBOX_BOOTADDR, bootaddr);
+}
+
+void sspm_cluster_pwr_off_notify(uint32_t cluster)
+{
+ mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 1);
+}
+
+void sspm_cluster_pwr_on_notify(uint32_t cluster)
+{
+ mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 0);
+}
+
+void sspm_standbywfi_irq_enable(uint32_t cpu_idx)
+{
+ mmio_write_32(SSPM_CFGREG_ACAO_INT_SET, STANDBYWFI_EN(cpu_idx));
+}
+
+uint32_t mcdi_avail_cpu_mask_read(void)
+{
+ return mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
+}
+
+uint32_t mcdi_avail_cpu_mask_write(uint32_t mask)
+{
+ mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, mask);
+
+ return mask;
+}
+
+uint32_t mcdi_avail_cpu_mask_set(uint32_t mask)
+{
+ uint32_t m;
+
+ m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
+ m |= mask;
+ mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
+
+ return m;
+}
+
+uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask)
+{
+ uint32_t m;
+
+ m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
+ m &= ~mask;
+ mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
+
+ return m;
+}
+
+uint32_t mcdi_cpu_cluster_pwr_stat_read(void)
+{
+ return mcdi_mbox_read(MCDI_MBOX_CPU_CLUSTER_PWR_STAT);
+}
+
+#define PAUSE_BIT 1
+#define CLUSTER_OFF_OFS 20
+#define CPU_OFF_OFS 24
+#define CLUSTER_ON_OFS 4
+#define CPU_ON_OFS 8
+
+static uint32_t target_mask(int cluster, int cpu_idx, bool on)
+{
+ uint32_t t = 0;
+
+ if (on) {
+ if (cluster >= 0)
+ t |= BIT(cluster + CLUSTER_ON_OFS);
+
+ if (cpu_idx >= 0)
+ t |= BIT(cpu_idx + CPU_ON_OFS);
+ } else {
+ if (cluster >= 0)
+ t |= BIT(cluster + CLUSTER_OFF_OFS);
+
+ if (cpu_idx >= 0)
+ t |= BIT(cpu_idx + CPU_OFF_OFS);
+ }
+
+ return t;
+}
+
+void mcdi_pause_clr(int cluster, int cpu_idx, bool on)
+{
+ uint32_t tgt = target_mask(cluster, cpu_idx, on);
+ uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
+
+ m &= ~tgt;
+ mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
+}
+
+void mcdi_pause_set(int cluster, int cpu_idx, bool on)
+{
+ uint32_t tgt = target_mask(cluster, cpu_idx, on);
+ uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
+ uint32_t tgtn = target_mask(-1, cpu_idx, !on);
+
+ /* request on and off at the same time to ensure it can be paused */
+ m |= tgt | tgtn;
+ mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
+
+ /* wait pause_ack */
+ while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
+ ;
+
+ /* clear non-requested operation */
+ m &= ~tgtn;
+ mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
+}
+
+void mcdi_pause(void)
+{
+ uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
+
+ mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
+
+ /* wait pause_ack */
+ while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
+ ;
+}
+
+void mcdi_unpause(void)
+{
+ uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
+
+ mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
+}
+
+void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on)
+{
+ uint32_t tgt = target_mask(cluster, cpu_idx, on);
+ uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
+
+ /* wait until ack */
+ while (!(ack & tgt))
+ ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
+}
+
+void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on)
+{
+ uint32_t tgt = target_mask(cluster, cpu_idx, on);
+ uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
+ uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
+ uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
+
+ if (!(cmd & tgt))
+ return;
+
+ /* wait until ack */
+ while (!(ack & tgt_cpu))
+ ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
+
+ cmd &= ~tgt;
+ mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
+}
+
+void mcdi_hotplug_set(int cluster, int cpu_idx, bool on)
+{
+ uint32_t tgt = target_mask(cluster, cpu_idx, on);
+ uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
+ uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
+ uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
+
+ if ((cmd & tgt) == tgt)
+ return;
+
+ /* wait until ack clear */
+ while (ack & tgt_cpu)
+ ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
+
+ cmd |= tgt;
+ mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
+}
+
+bool check_mcdi_ctl_stat(void)
+{
+ uint32_t clk_regs[] = {0x100010ac, 0x100010c8};
+ uint32_t clk_mask[] = {0x00028000, 0x00000018};
+ uint32_t tgt = target_mask(0, 0, true);
+ uint32_t m;
+ int i;
+
+ /* check clk status */
+ for (i = 0; i < ARRAY_SIZE(clk_regs); i++) {
+ if (mmio_read_32(clk_regs[i]) & clk_mask[i]) {
+ WARN("mcdi: clk check fail.\n");
+ return false;
+ }
+ }
+
+ /* check mcdi cmd handling */
+ m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
+ mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
+
+ i = 500;
+ while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK) && --i > 0)
+ udelay(10);
+
+ m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
+ mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
+
+ if (i == 0) {
+ WARN("mcdi: pause_action fail.\n");
+ return false;
+ }
+
+ /* check mcdi cmd handling */
+ if (mcdi_mbox_read(MCDI_MBOX_HP_CMD) ||
+ mcdi_mbox_read(MCDI_MBOX_HP_ACK)) {
+ WARN("mcdi: hp_cmd fail.\n");
+ return false;
+ }
+
+ mcdi_mbox_write(MCDI_MBOX_HP_CMD, tgt);
+
+ i = 500;
+ while ((mcdi_mbox_read(MCDI_MBOX_HP_ACK) & tgt) != tgt && --i > 0)
+ udelay(10);
+
+ mcdi_mbox_write(MCDI_MBOX_HP_CMD, 0);
+
+ if (i == 0) {
+ WARN("mcdi: hp_ack fail.\n");
+ return false;
+ }
+
+ return true;
+}
+
+void mcdi_init(void)
+{
+ mcdi_avail_cpu_mask_write(0x01); /* cpu0 default on */
+}
diff --git a/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h b/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h
new file mode 100644
index 0000000..9a40df1
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MTK_MCDI_H__
+#define __MTK_MCDI_H__
+
+#include <stdbool.h>
+
+void sspm_set_bootaddr(uint32_t bootaddr);
+void sspm_standbywfi_irq_enable(uint32_t cpu_idx);
+void sspm_cluster_pwr_off_notify(uint32_t cluster);
+void sspm_cluster_pwr_on_notify(uint32_t cluster);
+
+uint32_t mcdi_avail_cpu_mask_read(void);
+uint32_t mcdi_avail_cpu_mask_write(uint32_t mask);
+uint32_t mcdi_avail_cpu_mask_set(uint32_t mask);
+uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask);
+uint32_t mcdi_cpu_cluster_pwr_stat_read(void);
+
+void mcdi_pause(void);
+void mcdi_unpause(void);
+void mcdi_pause_set(int cluster, int cpu_idx, bool on);
+void mcdi_pause_clr(int cluster, int cpu_idx, bool on);
+void mcdi_hotplug_set(int cluster, int cpu_idx, bool on);
+void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on);
+void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on);
+
+bool check_mcdi_ctl_stat(void);
+void mcdi_init(void);
+
+#endif /* __MTK_MCDI_H__ */
diff --git a/plat/mediatek/mt8183/drivers/mcsi/mcsi.c b/plat/mediatek/mt8183/drivers/mcsi/mcsi.c
new file mode 100644
index 0000000..cbe7f0a
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/mcsi/mcsi.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <scu.h>
+#include <mcucfg.h>
+#include <drivers/delay_timer.h>
+#include <mcsi/mcsi.h>
+
+#define MAX_CLUSTERS 5
+
+static unsigned long cci_base_addr;
+static unsigned int cci_cluster_ix_to_iface[MAX_CLUSTERS];
+
+void mcsi_init(unsigned long cci_base,
+ unsigned int num_cci_masters)
+{
+ int i;
+
+ assert(cci_base);
+ assert(num_cci_masters < MAX_CLUSTERS);
+
+ cci_base_addr = cci_base;
+
+ for (i = 0; i < num_cci_masters; i++)
+ cci_cluster_ix_to_iface[i] = SLAVE_IFACE_OFFSET(i);
+}
+
+void mcsi_cache_flush(void)
+{
+ /* timeout is 10ms */
+ int timeout = 10000;
+
+ /* to make flush by SF safe, need to disable BIU DCM */
+ mmio_clrbits_32(CCI_CLK_CTRL, 1 << 8);
+ mmio_write_32(cci_base_addr + FLUSH_SF, 0x1);
+
+ for (; timeout; timeout--, udelay(1)) {
+ if ((mmio_read_32(cci_base_addr + FLUSH_SF) & 0x1) == 0x0)
+ break;
+ }
+
+ if (!timeout) {
+ INFO("SF lush timeout\n");
+ return;
+ }
+
+ /* enable BIU DCM as it was */
+ mmio_setbits_32(CCI_CLK_CTRL, 1 << 8);
+}
+
+static inline unsigned long get_slave_iface_base(unsigned long mpidr)
+{
+ /*
+ * We assume the TF topology code allocates affinity instances
+ * consecutively from zero.
+ * It is a programming error if this is called without initializing
+ * the slave interface to use for this cluster.
+ */
+ unsigned int cluster_id =
+ (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ assert(cluster_id < MAX_CLUSTERS);
+ assert(cci_cluster_ix_to_iface[cluster_id] != 0);
+
+ return cci_base_addr + cci_cluster_ix_to_iface[cluster_id];
+}
+
+void cci_enable_cluster_coherency(unsigned long mpidr)
+{
+ unsigned long slave_base;
+ unsigned int support_ability;
+ unsigned int config = 0;
+ unsigned int pending = 0;
+
+ assert(cci_base_addr);
+ slave_base = get_slave_iface_base(mpidr);
+ support_ability = mmio_read_32(slave_base);
+
+ pending = (mmio_read_32(
+ cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING;
+ while (pending) {
+ pending = (mmio_read_32(
+ cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING;
+ }
+
+ if (support_ability & SNP_SUPPORT)
+ config |= SNOOP_EN_BIT;
+ if (support_ability & DVM_SUPPORT)
+ config |= DVM_EN_BIT;
+
+ mmio_write_32(slave_base, support_ability | config);
+
+ /* Wait for the dust to settle down */
+ while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
+ ;
+}
+
+#if ERRATA_MCSIB_SW
+#pragma weak mcsib_sw_workaround_main
+#endif
+
+void cci_disable_cluster_coherency(unsigned long mpidr)
+{
+ unsigned long slave_base;
+ unsigned int config = 0;
+
+ assert(cci_base_addr);
+ slave_base = get_slave_iface_base(mpidr);
+
+ while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
+ ;
+
+ config = mmio_read_32(slave_base);
+ config &= ~(DVM_EN_BIT | SNOOP_EN_BIT);
+
+ /* Disable Snoops and DVM messages */
+ mmio_write_32(slave_base, config);
+
+#if ERRATA_MCSIB_SW
+ mcsib_sw_workaround_main();
+#endif
+
+ /* Wait for the dust to settle down */
+ while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
+ ;
+}
+
+void cci_secure_switch(unsigned int status)
+{
+ unsigned int config;
+
+ config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG);
+ if (status == NS_ACC)
+ config |= SECURE_ACC_EN;
+ else
+ config &= ~SECURE_ACC_EN;
+ mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config);
+}
+
+void cci_pmu_secure_switch(unsigned int status)
+{
+ unsigned int config;
+
+ config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG);
+ if (status == NS_ACC)
+ config |= PMU_SECURE_ACC_EN;
+ else
+ config &= ~PMU_SECURE_ACC_EN;
+ mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config);
+}
+
+void cci_init_sf(void)
+{
+ while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
+ ;
+ /* init sf1 */
+ mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF1_INIT);
+ while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF1_INIT)
+ ;
+ while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF1_INIT_DONE))
+ ;
+ /* init sf2 */
+ mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF2_INIT);
+ while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF2_INIT)
+ ;
+ while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF2_INIT_DONE))
+ ;
+}
+
+void cci_interrupt_en(void)
+{
+ mmio_setbits_32(cci_base_addr + CENTRAL_CTRL_REG, INT_EN);
+}
+
+unsigned long cci_reg_access(unsigned int op, unsigned long offset,
+ unsigned long val)
+{
+ unsigned long ret = 0;
+
+ if ((cci_base_addr == 0) || (offset > MSCI_MEMORY_SZ))
+ panic();
+
+ switch (op) {
+ case MCSI_REG_ACCESS_READ:
+ ret = mmio_read_32(cci_base_addr + offset);
+ break;
+ case MCSI_REG_ACCESS_WRITE:
+ mmio_write_32(cci_base_addr + offset, val);
+ dsb();
+ break;
+ case MCSI_REG_ACCESS_SET_BITMASK:
+ mmio_setbits_32(cci_base_addr + offset, val);
+ dsb();
+ break;
+ case MCSI_REG_ACCESS_CLEAR_BITMASK:
+ mmio_clrbits_32(cci_base_addr + offset, val);
+ dsb();
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
diff --git a/plat/mediatek/mt8183/drivers/mcsi/mcsi.h b/plat/mediatek/mt8183/drivers/mcsi/mcsi.h
new file mode 100644
index 0000000..863e7da
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/mcsi/mcsi.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCSI_H
+#define MCSI_H
+
+#define SLAVE_IFACE7_OFFSET 0x1700
+#define SLAVE_IFACE6_OFFSET 0x1600
+#define SLAVE_IFACE5_OFFSET 0x1500
+#define SLAVE_IFACE4_OFFSET 0x1400
+#define SLAVE_IFACE3_OFFSET 0x1300
+#define SLAVE_IFACE2_OFFSET 0x1200
+#define SLAVE_IFACE1_OFFSET 0x1100
+#define SLAVE_IFACE0_OFFSET 0x1000
+#define SLAVE_IFACE_OFFSET(index) (SLAVE_IFACE0_OFFSET + \
+ (0x100 * (index)))
+/* Control and ID register offsets */
+#define CENTRAL_CTRL_REG 0x0
+#define ERR_FLAG_REG 0x4
+#define SF_INIT_REG 0x10
+#define SF_CTRL_REG 0x14
+#define DCM_CTRL_REG 0x18
+#define ERR_FLAG2_REG 0x20
+#define SNP_PENDING_REG 0x28
+#define ACP_PENDING_REG 0x2c
+#define FLUSH_SF 0x500
+#define SYS_CCE_CTRL 0x2000
+#define MST1_CTRL 0x2100
+#define MTS2_CTRL 0x2200
+#define XBAR_ARAW_ARB 0x3000
+#define XBAR_R_ARB 0x3004
+
+/* Slave interface register offsets */
+#define SNOOP_CTRL_REG 0x0
+#define QOS_CTRL_REG 0x4
+#define QOS_OVERRIDE_REG 0x8
+#define QOS_TARGET_REG 0xc
+#define BD_CTRL_REG 0x40
+
+/* Snoop Control register bit definitions */
+#define DVM_SUPPORT (1U << 31)
+#define SNP_SUPPORT (1 << 30)
+#define SHAREABLE_OVWRT (1 << 2)
+#define DVM_EN_BIT (1 << 1)
+#define SNOOP_EN_BIT (1 << 0)
+#define SF2_INIT_DONE (1 << 17)
+#define SF1_INIT_DONE (1 << 16)
+#define TRIG_SF2_INIT (1 << 1)
+#define TRIG_SF1_INIT (1 << 0)
+
+/* Status register bit definitions */
+#define SNP_PENDING 31
+
+/* Status bit */
+#define NS_ACC 1
+#define S_ACC 0
+
+/* Central control register bit definitions */
+#define PMU_SECURE_ACC_EN (1 << 4)
+#define INT_EN (1 << 3)
+#define SECURE_ACC_EN (1 << 2)
+#define DVM_DIS (1 << 1)
+#define SNOOP_DIS (1 << 0)
+
+#define MSCI_MEMORY_SZ (0x10000)
+
+#define MCSI_REG_ACCESS_READ (0x0)
+#define MCSI_REG_ACCESS_WRITE (0x1)
+#define MCSI_REG_ACCESS_SET_BITMASK (0x2)
+#define MCSI_REG_ACCESS_CLEAR_BITMASK (0x3)
+
+#define NR_MAX_SLV (7)
+
+/* ICCS */
+#define CACHE_INSTR_EN (1 << 2)
+#define IDLE_CACHE (1 << 3)
+#define USE_SHARED_CACHE (1 << 4)
+#define CACHE_SHARED_PRE_EN (1 << 5)
+#define CACHE_SHARED_POST_EN (1 << 6)
+
+#define ACP_PENDING_MASK (0x1007f)
+
+#define CCI_CLK_CTRL (MCUCFG_BASE + 0x660)
+
+#ifndef __ASSEMBLER__
+
+#include <plat/common/common_def.h>
+#include <stdint.h>
+
+/* Function declarations */
+
+/*
+ * The MCSI driver must be initialized with the base address of the
+ * MCSI device in the platform memory map, and the cluster indices for
+ * the MCSI slave interfaces 3 and 4 respectively. These are the fully
+ * coherent ACE slave interfaces of MCSI.
+ * The cluster indices must either be 0 or 1, corresponding to the level 1
+ * affinity instance of the mpidr representing the cluster. A negative cluster
+ * index indicates that no cluster is present on that slave interface.
+ */
+void mcsi_init(unsigned long cci_base,
+ unsigned int num_cci_masters);
+void mcsi_cache_flush(void);
+
+void cci_enable_cluster_coherency(unsigned long mpidr);
+void cci_disable_cluster_coherency(unsigned long mpidr);
+
+void cci_secure_switch(unsigned int ns);
+void cci_init_sf(void);
+unsigned long cci_reg_access(unsigned int op, unsigned long offset, unsigned long val);
+
+#endif /* __ASSEMBLER__ */
+#endif /* MCSI_H */
diff --git a/plat/mediatek/mt8183/drivers/pmic/pmic.c b/plat/mediatek/mt8183/drivers/pmic/pmic.c
new file mode 100644
index 0000000..b0f898e
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/pmic/pmic.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <pmic_wrap_init.h>
+#include <pmic.h>
+
+void bcpu_enable(uint32_t en)
+{
+ pwrap_write(PMIC_VPROC11_OP_EN, 0x1);
+ if (en)
+ pwrap_write(PMIC_VPROC11_CON0, 1);
+ else
+ pwrap_write(PMIC_VPROC11_CON0, 0);
+}
+
+void bcpu_sram_enable(uint32_t en)
+{
+ pwrap_write(PMIC_VSRAM_PROC11_OP_EN, 0x1);
+ if (en)
+ pwrap_write(PMIC_VSRAM_PROC11_CON0, 1);
+ else
+ pwrap_write(PMIC_VSRAM_PROC11_CON0, 0);
+}
+
+void wk_pmic_enable_sdn_delay(void)
+{
+ uint32_t con;
+
+ pwrap_write(PMIC_TMA_KEY, 0x9CA7);
+ pwrap_read(PMIC_PSEQ_ELR11, &con);
+ con &= ~PMIC_RG_SDN_DLY_ENB;
+ pwrap_write(PMIC_PSEQ_ELR11, con);
+ pwrap_write(PMIC_TMA_KEY, 0);
+}
+
+void pmic_power_off(void)
+{
+ pwrap_write(PMIC_PWRHOLD, 0x0);
+}
diff --git a/plat/mediatek/mt8183/drivers/pmic/pmic.h b/plat/mediatek/mt8183/drivers/pmic/pmic.h
new file mode 100644
index 0000000..f19f9f6
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/pmic/pmic.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_H
+#define PMIC_H
+
+enum {
+ PMIC_TMA_KEY = 0x03a8,
+ PMIC_PWRHOLD = 0x0a08,
+ PMIC_PSEQ_ELR11 = 0x0a62,
+ PMIC_VPROC11_CON0 = 0x1388,
+ PMIC_VPROC11_OP_EN = 0x1390,
+ PMIC_VSRAM_PROC11_CON0 = 0x1b46,
+ PMIC_VSRAM_PROC11_OP_EN = 0x1b4e
+};
+
+enum {
+ PMIC_RG_SDN_DLY_ENB = 1U << 10
+};
+
+/* external API */
+void bcpu_enable(uint32_t en);
+void bcpu_sram_enable(uint32_t en);
+void wk_pmic_enable_sdn_delay(void);
+void pmic_power_off(void);
+
+#endif /* PMIC_H */
diff --git a/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..679c5e4
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <platform_def.h>
+#include <stdint.h>
+
+/* external API */
+int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
+int32_t pwrap_write(uint32_t adr, uint32_t wdata);
+
+static struct mt8183_pmic_wrap_regs *const mtk_pwrap =
+ (void *)PMIC_WRAP_BASE;
+
+/* timeout setting */
+enum {
+ TIMEOUT_READ = 255, /* us */
+ TIMEOUT_WAIT_IDLE = 255 /* us */
+};
+
+/* PMIC_WRAP registers */
+struct mt8183_pmic_wrap_regs {
+ uint32_t reserved[776];
+ uint32_t wacs2_cmd;
+ uint32_t wacs2_rdata;
+ uint32_t wacs2_vldclr;
+ uint32_t reserved1[4];
+};
+
+enum {
+ RDATA_WACS_RDATA_SHIFT = 0,
+ RDATA_WACS_FSM_SHIFT = 16,
+ RDATA_WACS_REQ_SHIFT = 19,
+ RDATA_SYNC_IDLE_SHIFT,
+ RDATA_INIT_DONE_SHIFT,
+ RDATA_SYS_IDLE_SHIFT,
+};
+
+enum {
+ RDATA_WACS_RDATA_MASK = 0xffff,
+ RDATA_WACS_FSM_MASK = 0x7,
+ RDATA_WACS_REQ_MASK = 0x1,
+ RDATA_SYNC_IDLE_MASK = 0x1,
+ RDATA_INIT_DONE_MASK = 0x1,
+ RDATA_SYS_IDLE_MASK = 0x1,
+};
+
+/* WACS_FSM */
+enum {
+ WACS_FSM_IDLE = 0x00,
+ WACS_FSM_REQ = 0x02,
+ WACS_FSM_WFDLE = 0x04,
+ WACS_FSM_WFVLDCLR = 0x06,
+ WACS_INIT_DONE = 0x01,
+ WACS_SYNC_IDLE = 0x01,
+ WACS_SYNC_BUSY = 0x00
+};
+
+/* error information flag */
+enum {
+ E_PWR_INVALID_ARG = 1,
+ E_PWR_INVALID_RW = 2,
+ E_PWR_INVALID_ADDR = 3,
+ E_PWR_INVALID_WDAT = 4,
+ E_PWR_INVALID_OP_MANUAL = 5,
+ E_PWR_NOT_IDLE_STATE = 6,
+ E_PWR_NOT_INIT_DONE = 7,
+ E_PWR_NOT_INIT_DONE_READ = 8,
+ E_PWR_WAIT_IDLE_TIMEOUT = 9,
+ E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
+ E_PWR_INIT_SIDLY_FAIL = 11,
+ E_PWR_RESET_TIMEOUT = 12,
+ E_PWR_TIMEOUT = 13,
+ E_PWR_INIT_RESET_SPI = 20,
+ E_PWR_INIT_SIDLY = 21,
+ E_PWR_INIT_REG_CLOCK = 22,
+ E_PWR_INIT_ENABLE_PMIC = 23,
+ E_PWR_INIT_DIO = 24,
+ E_PWR_INIT_CIPHER = 25,
+ E_PWR_INIT_WRITE_TEST = 26,
+ E_PWR_INIT_ENABLE_CRC = 27,
+ E_PWR_INIT_ENABLE_DEWRAP = 28,
+ E_PWR_INIT_ENABLE_EVENT = 29,
+ E_PWR_READ_TEST_FAIL = 30,
+ E_PWR_WRITE_TEST_FAIL = 31,
+ E_PWR_SWITCH_DIO = 32
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8183/drivers/rtc/rtc.c b/plat/mediatek/mt8183/drivers/rtc/rtc.c
new file mode 100644
index 0000000..a821c1b
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/rtc/rtc.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <rtc.h>
+
+static void RTC_Config_Interface(uint32_t addr, uint16_t data,
+ uint16_t MASK, uint16_t SHIFT)
+{
+ uint16_t pmic_reg = 0;
+
+ pmic_reg = RTC_Read(addr);
+
+ pmic_reg &= ~(MASK << SHIFT);
+ pmic_reg |= (data << SHIFT);
+
+ RTC_Write(addr, pmic_reg);
+}
+
+static void rtc_disable_2sec_reboot(void)
+{
+ uint16_t reboot;
+
+ reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
+ ~RTC_BBPU_AUTO_PDN_SEL;
+ RTC_Write(RTC_AL_SEC, reboot);
+ RTC_Write_Trigger();
+}
+
+static void rtc_xosc_write(uint16_t val, bool reload)
+{
+ uint16_t bbpu;
+
+ RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1);
+ rtc_busy_wait();
+ RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2);
+ rtc_busy_wait();
+
+ RTC_Write(RTC_OSC32CON, val);
+ rtc_busy_wait();
+
+ if (reload) {
+ bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+ RTC_Write(RTC_BBPU, bbpu);
+ RTC_Write_Trigger();
+ }
+}
+
+static void rtc_enable_k_eosc(void)
+{
+ uint16_t osc32;
+ uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */
+
+ /* Truning on eosc cali mode clock */
+ RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT);
+ RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT);
+ RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+ switch (rtc_eosc_cali_td) {
+ case 1:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ case 2:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ case 4:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ case 16:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ default:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ }
+ /* Switch the DCXO from 32k-less mode to RTC mode,
+ * otherwise, EOSC cali will fail
+ */
+ /* RTC mode will have only OFF mode and FPM */
+ RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK,
+ PMIC_RG_XO_EN32K_MAN_SHIFT);
+ RTC_Write(RTC_BBPU,
+ RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+ RTC_Write_Trigger();
+ /* Enable K EOSC mode for normal power off and then plug out battery */
+ RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
+ & (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2);
+ RTC_Write_Trigger();
+
+ osc32 = RTC_Read(RTC_OSC32CON);
+ rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true);
+ INFO("[RTC] RTC_enable_k_eosc\n");
+}
+
+void rtc_power_off_sequence(void)
+{
+ uint16_t bbpu;
+
+ rtc_disable_2sec_reboot();
+ rtc_enable_k_eosc();
+
+ /* clear alarm */
+ bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN;
+ if (Writeif_unlock()) {
+ RTC_Write(RTC_BBPU, bbpu);
+
+ RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+ RTC_Write_Trigger();
+ mdelay(1);
+
+ bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+ RTC_Write(RTC_BBPU, bbpu);
+ RTC_Write_Trigger();
+ INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n",
+ RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN),
+ RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC));
+ }
+}
diff --git a/plat/mediatek/mt8183/drivers/rtc/rtc.h b/plat/mediatek/mt8183/drivers/rtc/rtc.h
new file mode 100644
index 0000000..66686b4
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/rtc/rtc.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+/* RTC registers */
+enum {
+ RTC_BBPU = 0x0588,
+ RTC_IRQ_STA = 0x058A,
+ RTC_IRQ_EN = 0x058C,
+ RTC_CII_EN = 0x058E
+};
+
+enum {
+ RTC_AL_SEC = 0x05A0,
+ RTC_AL_MIN = 0x05A2,
+ RTC_AL_HOU = 0x05A4,
+ RTC_AL_DOM = 0x05A6,
+ RTC_AL_DOW = 0x05A8,
+ RTC_AL_MTH = 0x05AA,
+ RTC_AL_YEA = 0x05AC,
+ RTC_AL_MASK = 0x0590
+};
+
+enum {
+ RTC_OSC32CON = 0x05AE,
+ RTC_CON = 0x05C4,
+ RTC_WRTGR = 0x05C2
+};
+
+enum {
+ RTC_PDN1 = 0x05B4,
+ RTC_PDN2 = 0x05B6,
+ RTC_SPAR0 = 0x05B8,
+ RTC_SPAR1 = 0x05BA,
+ RTC_PROT = 0x05BC,
+ RTC_DIFF = 0x05BE,
+ RTC_CALI = 0x05C0
+};
+
+enum {
+ RTC_OSC32CON_UNLOCK1 = 0x1A57,
+ RTC_OSC32CON_UNLOCK2 = 0x2B68
+};
+
+enum {
+ RTC_PROT_UNLOCK1 = 0x586A,
+ RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+ RTC_BBPU_PWREN = 1U << 0,
+ RTC_BBPU_CLR = 1U << 1,
+ RTC_BBPU_INIT = 1U << 2,
+ RTC_BBPU_AUTO = 1U << 3,
+ RTC_BBPU_CLRPKY = 1U << 4,
+ RTC_BBPU_RELOAD = 1U << 5,
+ RTC_BBPU_CBUSY = 1U << 6
+};
+
+enum {
+ RTC_AL_MASK_SEC = 1U << 0,
+ RTC_AL_MASK_MIN = 1U << 1,
+ RTC_AL_MASK_HOU = 1U << 2,
+ RTC_AL_MASK_DOM = 1U << 3,
+ RTC_AL_MASK_DOW = 1U << 4,
+ RTC_AL_MASK_MTH = 1U << 5,
+ RTC_AL_MASK_YEA = 1U << 6
+};
+
+enum {
+ RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
+ RTC_BBPU_2SEC_CK_SEL = 1U << 7,
+ RTC_BBPU_2SEC_EN = 1U << 8,
+ RTC_BBPU_2SEC_MODE = 0x3 << 9,
+ RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
+ RTC_BBPU_2SEC_STAT_STA = 1U << 12
+};
+
+enum {
+ RTC_BBPU_KEY = 0x43 << 8
+};
+
+enum {
+ RTC_EMBCK_SRC_SEL = 1 << 8,
+ RTC_EMBCK_SEL_MODE = 3 << 6,
+ RTC_XOSC32_ENB = 1 << 5,
+ RTC_REG_XOSC32_ENB = 1 << 15
+};
+
+enum {
+ RTC_K_EOSC_RSV_0 = 1 << 8,
+ RTC_K_EOSC_RSV_1 = 1 << 9,
+ RTC_K_EOSC_RSV_2 = 1 << 10
+};
+
+/* PMIC TOP Register Definition */
+enum {
+ PMIC_RG_TOP_CON = 0x001E,
+ PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
+ PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
+ PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
+ PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
+ PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
+ PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
+};
+
+/* PMIC SCK Register Definition */
+enum {
+ PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x051A,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E,
+ PMIC_RG_EOSC_CALI_CON0 = 0x540
+};
+
+/* PMIC DCXO Register Definition */
+enum {
+ PMIC_RG_DCXO_CW00 = 0x0788,
+ PMIC_RG_DCXO_CW02 = 0x0790
+};
+
+enum {
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
+ PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
+ PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
+ PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
+ PMIC_RG_XO_EN32K_MAN_SHIFT = 0
+};
+
+/* external API */
+uint16_t RTC_Read(uint32_t addr);
+void RTC_Write(uint32_t addr, uint16_t data);
+int32_t rtc_busy_wait(void);
+int32_t RTC_Write_Trigger(void);
+int32_t Writeif_unlock(void);
+void rtc_power_off_sequence(void);
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/mt8183/drivers/spm/spm.c b/plat/mediatek/mt8183/drivers/spm/spm.c
new file mode 100644
index 0000000..d6d2344
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spm/spm.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <lib/bakery_lock.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <spm.h>
+#include <spm_pmic_wrap.h>
+
+DEFINE_BAKERY_LOCK(spm_lock);
+
+/* SPM_DVS_LEVEL */
+#define SPM_VMODEM_LEVEL_MASK (0xff << 16)
+#define SPM_VMODEM_LEVEL (1U << 18)
+#define SPM_VCORE_LEVEL_MASK (0xff)
+#define SPM_VCORE_LEVEL (1U << 1)
+
+/* CLK_SCP_CFG_0 */
+#define SPM_CK_OFF_CONTROL (0x3FF)
+
+/* CLK_SCP_CFG_1 */
+#define SPM_AXI_26M_SEL (0x1)
+
+/* AP_PLL_CON3 */
+#define SPM_PLL_CONTROL (0x7FAAAAF)
+
+/* AP_PLL_CON4 */
+#define SPM_PLL_OUT_OFF_CONTROL (0xFA0A)
+
+/* AP_PLL_CON6 */
+#define PLL_DLY (0x20000)
+
+const char *wakeup_src_str[32] = {
+ [0] = "R12_PCM_TIMER",
+ [1] = "R12_SSPM_WDT_EVENT_B",
+ [2] = "R12_KP_IRQ_B",
+ [3] = "R12_APWDT_EVENT_B",
+ [4] = "R12_APXGPT1_EVENT_B",
+ [5] = "R12_CONN2AP_SPM_WAKEUP_B",
+ [6] = "R12_EINT_EVENT_B",
+ [7] = "R12_CONN_WDT_IRQ_B",
+ [8] = "R12_CCIF0_EVENT_B",
+ [9] = "R12_LOWBATTERY_IRQ_B",
+ [10] = "R12_SSPM_SPM_IRQ_B",
+ [11] = "R12_SCP_SPM_IRQ_B",
+ [12] = "R12_SCP_WDT_EVENT_B",
+ [13] = "R12_PCM_WDT_WAKEUP_B",
+ [14] = "R12_USB_CDSC_B ",
+ [15] = "R12_USB_POWERDWN_B",
+ [16] = "R12_SYS_TIMER_EVENT_B",
+ [17] = "R12_EINT_EVENT_SECURE_B",
+ [18] = "R12_CCIF1_EVENT_B",
+ [19] = "R12_UART0_IRQ_B",
+ [20] = "R12_AFE_IRQ_MCU_B",
+ [21] = "R12_THERM_CTRL_EVENT_B",
+ [22] = "R12_SYS_CIRQ_IRQ_B",
+ [23] = "R12_MD2AP_PEER_EVENT_B",
+ [24] = "R12_CSYSPWREQ_B",
+ [25] = "R12_MD1_WDT_B ",
+ [26] = "R12_CLDMA_EVENT_B",
+ [27] = "R12_SEJ_WDT_GPT_B",
+ [28] = "R12_ALL_SSPM_WAKEUP_B",
+ [29] = "R12_CPU_IRQ_B",
+ [30] = "R12_CPU_WFI_AND_B"
+};
+
+const char *spm_get_firmware_version(void)
+{
+ return "DYNAMIC_SPM_FW_VERSION";
+}
+
+void spm_lock_init(void)
+{
+ bakery_lock_init(&spm_lock);
+}
+
+void spm_lock_get(void)
+{
+ bakery_lock_get(&spm_lock);
+}
+
+void spm_lock_release(void)
+{
+ bakery_lock_release(&spm_lock);
+}
+
+void spm_set_bootaddr(unsigned long bootaddr)
+{
+ /* initialize core4~7 boot entry address */
+ mmio_write_32(SW2SPM_MAILBOX_3, bootaddr);
+}
+
+void spm_set_cpu_status(int cpu)
+{
+ if (cpu >= 0 && cpu < 4) {
+ mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006204);
+ mmio_write_32(ROOT_CORE_ADDR, 0x10006208 + (cpu * 0x4));
+ } else if (cpu >= 4 && cpu < 8) {
+ mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006218);
+ mmio_write_32(ROOT_CORE_ADDR, 0x1000621c + ((cpu - 4) * 0x4));
+ } else {
+ ERROR("%s: error cpu number %d\n", __func__, cpu);
+ }
+}
+
+void spm_set_power_control(const struct pwr_ctrl *pwrctrl)
+{
+ mmio_write_32(SPM_AP_STANDBY_CON,
+ ((pwrctrl->wfi_op & 0x1) << 0) |
+ ((pwrctrl->mp0_cputop_idle_mask & 0x1) << 1) |
+ ((pwrctrl->mp1_cputop_idle_mask & 0x1) << 2) |
+ ((pwrctrl->mcusys_idle_mask & 0x1) << 4) |
+ ((pwrctrl->mm_mask_b & 0x3) << 16) |
+ ((pwrctrl->md_ddr_en_0_dbc_en & 0x1) << 18) |
+ ((pwrctrl->md_ddr_en_1_dbc_en & 0x1) << 19) |
+ ((pwrctrl->md_mask_b & 0x3) << 20) |
+ ((pwrctrl->sspm_mask_b & 0x1) << 22) |
+ ((pwrctrl->scp_mask_b & 0x1) << 23) |
+ ((pwrctrl->srcclkeni_mask_b & 0x1) << 24) |
+ ((pwrctrl->md_apsrc_1_sel & 0x1) << 25) |
+ ((pwrctrl->md_apsrc_0_sel & 0x1) << 26) |
+ ((pwrctrl->conn_ddr_en_dbc_en & 0x1) << 27) |
+ ((pwrctrl->conn_mask_b & 0x1) << 28) |
+ ((pwrctrl->conn_apsrc_sel & 0x1) << 29));
+
+ mmio_write_32(SPM_SRC_REQ,
+ ((pwrctrl->spm_apsrc_req & 0x1) << 0) |
+ ((pwrctrl->spm_f26m_req & 0x1) << 1) |
+ ((pwrctrl->spm_infra_req & 0x1) << 3) |
+ ((pwrctrl->spm_vrf18_req & 0x1) << 4) |
+ ((pwrctrl->spm_ddren_req & 0x1) << 7) |
+ ((pwrctrl->spm_rsv_src_req & 0x7) << 8) |
+ ((pwrctrl->spm_ddren_2_req & 0x1) << 11) |
+ ((pwrctrl->cpu_md_dvfs_sop_force_on & 0x1) << 16));
+
+ mmio_write_32(SPM_SRC_MASK,
+ ((pwrctrl->csyspwreq_mask & 0x1) << 0) |
+ ((pwrctrl->ccif0_md_event_mask_b & 0x1) << 1) |
+ ((pwrctrl->ccif0_ap_event_mask_b & 0x1) << 2) |
+ ((pwrctrl->ccif1_md_event_mask_b & 0x1) << 3) |
+ ((pwrctrl->ccif1_ap_event_mask_b & 0x1) << 4) |
+ ((pwrctrl->ccif2_md_event_mask_b & 0x1) << 5) |
+ ((pwrctrl->ccif2_ap_event_mask_b & 0x1) << 6) |
+ ((pwrctrl->ccif3_md_event_mask_b & 0x1) << 7) |
+ ((pwrctrl->ccif3_ap_event_mask_b & 0x1) << 8) |
+ ((pwrctrl->md_srcclkena_0_infra_mask_b & 0x1) << 9) |
+ ((pwrctrl->md_srcclkena_1_infra_mask_b & 0x1) << 10) |
+ ((pwrctrl->conn_srcclkena_infra_mask_b & 0x1) << 11) |
+ ((pwrctrl->ufs_infra_req_mask_b & 0x1) << 12) |
+ ((pwrctrl->srcclkeni_infra_mask_b & 0x1) << 13) |
+ ((pwrctrl->md_apsrc_req_0_infra_mask_b & 0x1) << 14) |
+ ((pwrctrl->md_apsrc_req_1_infra_mask_b & 0x1) << 15) |
+ ((pwrctrl->conn_apsrcreq_infra_mask_b & 0x1) << 16) |
+ ((pwrctrl->ufs_srcclkena_mask_b & 0x1) << 17) |
+ ((pwrctrl->md_vrf18_req_0_mask_b & 0x1) << 18) |
+ ((pwrctrl->md_vrf18_req_1_mask_b & 0x1) << 19) |
+ ((pwrctrl->ufs_vrf18_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->gce_vrf18_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->conn_infra_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->gce_apsrc_req_mask_b & 0x1) << 23) |
+ ((pwrctrl->disp0_apsrc_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->disp1_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->mfg_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->vdec_req_mask_b & 0x1) << 27));
+
+ mmio_write_32(SPM_SRC2_MASK,
+ ((pwrctrl->md_ddr_en_0_mask_b & 0x1) << 0) |
+ ((pwrctrl->md_ddr_en_1_mask_b & 0x1) << 1) |
+ ((pwrctrl->conn_ddr_en_mask_b & 0x1) << 2) |
+ ((pwrctrl->ddren_sspm_apsrc_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->ddren_scp_apsrc_req_mask_b & 0x1) << 4) |
+ ((pwrctrl->disp0_ddren_mask_b & 0x1) << 5) |
+ ((pwrctrl->disp1_ddren_mask_b & 0x1) << 6) |
+ ((pwrctrl->gce_ddren_mask_b & 0x1) << 7) |
+ ((pwrctrl->ddren_emi_self_refresh_ch0_mask_b & 0x1)
+ << 8) |
+ ((pwrctrl->ddren_emi_self_refresh_ch1_mask_b & 0x1)
+ << 9));
+
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK,
+ ((pwrctrl->spm_wakeup_event_mask & 0xffffffff) << 0));
+
+ mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK,
+ ((pwrctrl->spm_wakeup_event_ext_mask & 0xffffffff)
+ << 0));
+
+ mmio_write_32(SPM_SRC3_MASK,
+ ((pwrctrl->md_ddr_en_2_0_mask_b & 0x1) << 0) |
+ ((pwrctrl->md_ddr_en_2_1_mask_b & 0x1) << 1) |
+ ((pwrctrl->conn_ddr_en_2_mask_b & 0x1) << 2) |
+ ((pwrctrl->ddren2_sspm_apsrc_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->ddren2_scp_apsrc_req_mask_b & 0x1) << 4) |
+ ((pwrctrl->disp0_ddren2_mask_b & 0x1) << 5) |
+ ((pwrctrl->disp1_ddren2_mask_b & 0x1) << 6) |
+ ((pwrctrl->gce_ddren2_mask_b & 0x1) << 7) |
+ ((pwrctrl->ddren2_emi_self_refresh_ch0_mask_b & 0x1)
+ << 8) |
+ ((pwrctrl->ddren2_emi_self_refresh_ch1_mask_b & 0x1)
+ << 9));
+
+ mmio_write_32(MP0_CPU0_WFI_EN,
+ ((pwrctrl->mp0_cpu0_wfi_en & 0x1) << 0));
+ mmio_write_32(MP0_CPU1_WFI_EN,
+ ((pwrctrl->mp0_cpu1_wfi_en & 0x1) << 0));
+ mmio_write_32(MP0_CPU2_WFI_EN,
+ ((pwrctrl->mp0_cpu2_wfi_en & 0x1) << 0));
+ mmio_write_32(MP0_CPU3_WFI_EN,
+ ((pwrctrl->mp0_cpu3_wfi_en & 0x1) << 0));
+
+ mmio_write_32(MP1_CPU0_WFI_EN,
+ ((pwrctrl->mp1_cpu0_wfi_en & 0x1) << 0));
+ mmio_write_32(MP1_CPU1_WFI_EN,
+ ((pwrctrl->mp1_cpu1_wfi_en & 0x1) << 0));
+ mmio_write_32(MP1_CPU2_WFI_EN,
+ ((pwrctrl->mp1_cpu2_wfi_en & 0x1) << 0));
+ mmio_write_32(MP1_CPU3_WFI_EN,
+ ((pwrctrl->mp1_cpu3_wfi_en & 0x1) << 0));
+}
+
+void spm_disable_pcm_timer(void)
+{
+ mmio_clrsetbits_32(PCM_CON1, PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY);
+}
+
+void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
+{
+ uint32_t val, mask, isr;
+
+ val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX;
+ mmio_write_32(PCM_TIMER_VAL, val);
+ mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_TIMER_EN_LSB);
+
+ mask = pwrctrl->wake_src;
+
+ if (pwrctrl->csyspwreq_mask)
+ mask &= ~WAKE_SRC_R12_CSYSPWREQ_B;
+
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask);
+
+ isr = mmio_read_32(SPM_IRQ_MASK) & SPM_TWAM_IRQ_MASK_LSB;
+ mmio_write_32(SPM_IRQ_MASK, isr | ISRM_RET_IRQ_AUX);
+}
+
+void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl)
+{
+ mmio_write_32(SPM_SW_FLAG, pwrctrl->pcm_flags);
+ mmio_write_32(SPM_SW_RSV_2, pwrctrl->pcm_flags1);
+}
+
+void spm_set_pcm_wdt(int en)
+{
+ if (en) {
+ mmio_clrsetbits_32(PCM_CON1, PCM_WDT_WAKE_MODE_LSB,
+ SPM_REGWR_CFG_KEY);
+
+ if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX)
+ mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX);
+ mmio_write_32(PCM_WDT_VAL,
+ mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
+ mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_WDT_EN_LSB);
+ } else {
+ mmio_clrsetbits_32(PCM_CON1, PCM_WDT_EN_LSB,
+ SPM_REGWR_CFG_KEY);
+ }
+}
+
+void spm_send_cpu_wakeup_event(void)
+{
+ mmio_write_32(PCM_REG_DATA_INI, 0);
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1);
+}
+
+void spm_get_wakeup_status(struct wake_status *wakesta)
+{
+ wakesta->assert_pc = mmio_read_32(PCM_REG_DATA_INI);
+ wakesta->r12 = mmio_read_32(SPM_SW_RSV_0);
+ wakesta->r12_ext = mmio_read_32(PCM_REG12_EXT_DATA);
+ wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA);
+ wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA);
+ wakesta->wake_misc = mmio_read_32(SPM_BSI_D0_SR);
+ wakesta->timer_out = mmio_read_32(SPM_BSI_D1_SR);
+ wakesta->r13 = mmio_read_32(PCM_REG13_DATA);
+ wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA);
+ wakesta->req_sta = mmio_read_32(SRC_REQ_STA);
+ wakesta->sw_flag = mmio_read_32(SPM_SW_FLAG);
+ wakesta->sw_flag1 = mmio_read_32(SPM_SW_RSV_2);
+ wakesta->r15 = mmio_read_32(PCM_REG15_DATA);
+ wakesta->debug_flag = mmio_read_32(SPM_SW_DEBUG);
+ wakesta->debug_flag1 = mmio_read_32(WDT_LATCH_SPARE0_FIX);
+ wakesta->event_reg = mmio_read_32(SPM_BSI_D2_SR);
+ wakesta->isr = mmio_read_32(SPM_IRQ_STA);
+}
+
+void spm_clean_after_wakeup(void)
+{
+ mmio_write_32(SPM_SW_RSV_0,
+ mmio_read_32(SPM_WAKEUP_STA) |
+ mmio_read_32(SPM_SW_RSV_0));
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0);
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~0);
+ mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
+ mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM);
+ mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL);
+}
+
+void spm_output_wake_reason(struct wake_status *wakesta, const char *scenario)
+{
+ uint32_t i;
+
+ if (wakesta->assert_pc != 0) {
+ INFO("%s: PCM ASSERT AT %u, ULPOSC_CON = 0x%x\n",
+ scenario, wakesta->assert_pc, mmio_read_32(ULPOSC_CON));
+ goto spm_debug_flags;
+ }
+
+ for (i = 0; i <= 31; i++) {
+ if (wakesta->r12 & (1U << i)) {
+ INFO("%s: wake up by %s, timer_out = %u\n",
+ scenario, wakeup_src_str[i], wakesta->timer_out);
+ break;
+ }
+ }
+
+spm_debug_flags:
+ INFO("r15 = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n",
+ wakesta->r15, wakesta->r13, wakesta->debug_flag,
+ wakesta->debug_flag1);
+ INFO("sw_flag = 0x%x 0x%x, r12 = 0x%x, r12_ext = 0x%x\n",
+ wakesta->sw_flag, wakesta->sw_flag1, wakesta->r12,
+ wakesta->r12_ext);
+ INFO("idle_sta = 0x%x, req_sta = 0x%x, event_reg = 0x%x\n",
+ wakesta->idle_sta, wakesta->req_sta, wakesta->event_reg);
+ INFO("isr = 0x%x, raw_sta = 0x%x, raw_ext_sta = 0x%x\n",
+ wakesta->isr, wakesta->raw_sta, wakesta->raw_ext_sta);
+ INFO("wake_misc = 0x%x\n", wakesta->wake_misc);
+}
+
+void spm_boot_init(void)
+{
+ NOTICE("%s() start\n", __func__);
+
+ spm_lock_init();
+ mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
+
+ /* Set Vmodem / Vcore DVS init level */
+ mmio_clrsetbits_32(SPM_DVS_LEVEL,
+ SPM_VMODEM_LEVEL_MASK | SPM_VCORE_LEVEL_MASK,
+ SPM_VMODEM_LEVEL | SPM_VCORE_LEVEL);
+
+ /* switch ck_off/axi_26m control to SPM */
+ mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_OFF_CONTROL);
+ mmio_setbits_32(CLK_SCP_CFG_1, SPM_AXI_26M_SEL);
+
+ /* switch PLL/CLKSQ control to SPM */
+ mmio_clrbits_32(AP_PLL_CON3, SPM_PLL_CONTROL);
+ mmio_clrbits_32(AP_PLL_CON4, SPM_PLL_OUT_OFF_CONTROL);
+ mmio_clrbits_32(AP_PLL_CON6, PLL_DLY);
+
+ NOTICE("%s() end\n", __func__);
+}
diff --git a/plat/mediatek/mt8183/drivers/spm/spm.h b/plat/mediatek/mt8183/drivers/spm/spm.h
new file mode 100644
index 0000000..b2e83dc
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spm/spm.h
@@ -0,0 +1,2552 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPM_H
+#define SPM_H
+
+/**************************************
+ * Define and Declare
+ **************************************/
+
+#define POWERON_CONFIG_EN (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008)
+#define SPM_CLK_CON (SPM_BASE + 0x00C)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x010)
+#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014)
+#define PCM_CON0 (SPM_BASE + 0x018)
+#define PCM_CON1 (SPM_BASE + 0x01C)
+#define PCM_IM_PTR (SPM_BASE + 0x020)
+#define PCM_IM_LEN (SPM_BASE + 0x024)
+#define PCM_REG_DATA_INI (SPM_BASE + 0x028)
+#define PCM_PWR_IO_EN (SPM_BASE + 0x02C)
+#define PCM_TIMER_VAL (SPM_BASE + 0x030)
+#define PCM_WDT_VAL (SPM_BASE + 0x034)
+#define PCM_IM_HOST_RW_PTR (SPM_BASE + 0x038)
+#define PCM_IM_HOST_RW_DAT (SPM_BASE + 0x03C)
+#define PCM_EVENT_VECTOR0 (SPM_BASE + 0x040)
+#define PCM_EVENT_VECTOR1 (SPM_BASE + 0x044)
+#define PCM_EVENT_VECTOR2 (SPM_BASE + 0x048)
+#define PCM_EVENT_VECTOR3 (SPM_BASE + 0x04C)
+#define PCM_EVENT_VECTOR4 (SPM_BASE + 0x050)
+#define PCM_EVENT_VECTOR5 (SPM_BASE + 0x054)
+#define PCM_EVENT_VECTOR6 (SPM_BASE + 0x058)
+#define PCM_EVENT_VECTOR7 (SPM_BASE + 0x05C)
+#define PCM_EVENT_VECTOR8 (SPM_BASE + 0x060)
+#define PCM_EVENT_VECTOR9 (SPM_BASE + 0x064)
+#define PCM_EVENT_VECTOR10 (SPM_BASE + 0x068)
+#define PCM_EVENT_VECTOR11 (SPM_BASE + 0x06C)
+#define PCM_EVENT_VECTOR12 (SPM_BASE + 0x070)
+#define PCM_EVENT_VECTOR13 (SPM_BASE + 0x074)
+#define PCM_EVENT_VECTOR14 (SPM_BASE + 0x078)
+#define PCM_EVENT_VECTOR15 (SPM_BASE + 0x07C)
+#define PCM_EVENT_VECTOR_EN (SPM_BASE + 0x080)
+#define SPM_SRAM_RSV_CON (SPM_BASE + 0x088)
+#define SPM_SWINT (SPM_BASE + 0x08C)
+#define SPM_SWINT_SET (SPM_BASE + 0x090)
+#define SPM_SWINT_CLR (SPM_BASE + 0x094)
+#define SPM_SCP_MAILBOX (SPM_BASE + 0x098)
+#define SCP_SPM_MAILBOX (SPM_BASE + 0x09C)
+#define SPM_TWAM_CON (SPM_BASE + 0x0A0)
+#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x0A4)
+#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x0A8)
+#define SPM_SCP_IRQ (SPM_BASE + 0x0AC)
+#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x0B0)
+#define SPM_IRQ_MASK (SPM_BASE + 0x0B4)
+#define SPM_SRC_REQ (SPM_BASE + 0x0B8)
+#define SPM_SRC_MASK (SPM_BASE + 0x0BC)
+#define SPM_SRC2_MASK (SPM_BASE + 0x0C0)
+#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x0C4)
+#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0C8)
+#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x0CC)
+#define SCP_CLK_CON (SPM_BASE + 0x0D0)
+#define PCM_DEBUG_CON (SPM_BASE + 0x0D4)
+#define DDR_EN_DBC_LEN (SPM_BASE + 0x0D8)
+#define AHB_BUS_CON (SPM_BASE + 0x0DC)
+#define SPM_SRC3_MASK (SPM_BASE + 0x0E0)
+#define DDR_EN_EMI_DBC_CON (SPM_BASE + 0x0E4)
+#define SSPM_CLK_CON (SPM_BASE + 0x0E8)
+#define PCM_REG0_DATA (SPM_BASE + 0x100)
+#define PCM_REG1_DATA (SPM_BASE + 0x104)
+#define PCM_REG2_DATA (SPM_BASE + 0x108)
+#define PCM_REG3_DATA (SPM_BASE + 0x10C)
+#define PCM_REG4_DATA (SPM_BASE + 0x110)
+#define PCM_REG5_DATA (SPM_BASE + 0x114)
+#define PCM_REG6_DATA (SPM_BASE + 0x118)
+#define PCM_REG7_DATA (SPM_BASE + 0x11C)
+#define PCM_REG8_DATA (SPM_BASE + 0x120)
+#define PCM_REG9_DATA (SPM_BASE + 0x124)
+#define PCM_REG10_DATA (SPM_BASE + 0x128)
+#define PCM_REG11_DATA (SPM_BASE + 0x12C)
+#define PCM_REG12_DATA (SPM_BASE + 0x130)
+#define PCM_REG13_DATA (SPM_BASE + 0x134)
+#define PCM_REG14_DATA (SPM_BASE + 0x138)
+#define PCM_REG15_DATA (SPM_BASE + 0x13C)
+#define PCM_REG12_MASK_B_STA (SPM_BASE + 0x140)
+#define PCM_REG12_EXT_DATA (SPM_BASE + 0x144)
+#define PCM_REG12_EXT_MASK_B_STA (SPM_BASE + 0x148)
+#define PCM_EVENT_REG_STA (SPM_BASE + 0x14C)
+#define PCM_TIMER_OUT (SPM_BASE + 0x150)
+#define PCM_WDT_OUT (SPM_BASE + 0x154)
+#define SPM_IRQ_STA (SPM_BASE + 0x158)
+#define SPM_WAKEUP_STA (SPM_BASE + 0x15C)
+#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x160)
+#define SPM_WAKEUP_MISC (SPM_BASE + 0x164)
+#define BUS_PROTECT_RDY (SPM_BASE + 0x168)
+#define BUS_PROTECT2_RDY (SPM_BASE + 0x16C)
+#define SUBSYS_IDLE_STA (SPM_BASE + 0x170)
+#define CPU_IDLE_STA (SPM_BASE + 0x174)
+#define PCM_FSM_STA (SPM_BASE + 0x178)
+#define SRC_REQ_STA (SPM_BASE + 0x17C)
+#define PWR_STATUS (SPM_BASE + 0x180)
+#define PWR_STATUS_2ND (SPM_BASE + 0x184)
+#define CPU_PWR_STATUS (SPM_BASE + 0x188)
+#define CPU_PWR_STATUS_2ND (SPM_BASE + 0x18C)
+#define MISC_STA (SPM_BASE + 0x190)
+#define SPM_SRC_RDY_STA (SPM_BASE + 0x194)
+#define DRAMC_DBG_LATCH (SPM_BASE + 0x19C)
+#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1A0)
+#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1A4)
+#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1A8)
+#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1AC)
+#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1B0)
+#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1B4)
+#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1B8)
+#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1BC)
+#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1C0)
+#define SPM_DVFS_STA (SPM_BASE + 0x1C8)
+#define BUS_PROTECT3_RDY (SPM_BASE + 0x1CC)
+#define SRC_DDREN_STA (SPM_BASE + 0x1E0)
+#define MCU_PWR_CON (SPM_BASE + 0x200)
+#define MP0_CPUTOP_PWR_CON (SPM_BASE + 0x204)
+#define MP0_CPU0_PWR_CON (SPM_BASE + 0x208)
+#define MP0_CPU1_PWR_CON (SPM_BASE + 0x20C)
+#define MP0_CPU2_PWR_CON (SPM_BASE + 0x210)
+#define MP0_CPU3_PWR_CON (SPM_BASE + 0x214)
+#define MP1_CPUTOP_PWR_CON (SPM_BASE + 0x218)
+#define MP1_CPU0_PWR_CON (SPM_BASE + 0x21C)
+#define MP1_CPU1_PWR_CON (SPM_BASE + 0x220)
+#define MP1_CPU2_PWR_CON (SPM_BASE + 0x224)
+#define MP1_CPU3_PWR_CON (SPM_BASE + 0x228)
+#define MP0_CPUTOP_L2_PDN (SPM_BASE + 0x240)
+#define MP0_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x244)
+#define MP0_CPU0_L1_PDN (SPM_BASE + 0x248)
+#define MP0_CPU1_L1_PDN (SPM_BASE + 0x24C)
+#define MP0_CPU2_L1_PDN (SPM_BASE + 0x250)
+#define MP0_CPU3_L1_PDN (SPM_BASE + 0x254)
+#define MP1_CPUTOP_L2_PDN (SPM_BASE + 0x258)
+#define MP1_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x25C)
+#define MP1_CPU0_L1_PDN (SPM_BASE + 0x260)
+#define MP1_CPU1_L1_PDN (SPM_BASE + 0x264)
+#define MP1_CPU2_L1_PDN (SPM_BASE + 0x268)
+#define MP1_CPU3_L1_PDN (SPM_BASE + 0x26C)
+#define CPU_EXT_BUCK_ISO (SPM_BASE + 0x290)
+#define DUMMY1_PWR_CON (SPM_BASE + 0x2B0)
+#define BYPASS_SPMC (SPM_BASE + 0x2B4)
+#define SPMC_DORMANT_ENABLE (SPM_BASE + 0x2B8)
+#define ARMPLL_CLK_CON (SPM_BASE + 0x2BC)
+#define SPMC_IN_RET (SPM_BASE + 0x2C0)
+#define VDE_PWR_CON (SPM_BASE + 0x300)
+#define VEN_PWR_CON (SPM_BASE + 0x304)
+#define ISP_PWR_CON (SPM_BASE + 0x308)
+#define DIS_PWR_CON (SPM_BASE + 0x30C)
+#define MFG_CORE1_PWR_CON (SPM_BASE + 0x310)
+#define AUDIO_PWR_CON (SPM_BASE + 0x314)
+#define IFR_PWR_CON (SPM_BASE + 0x318)
+#define DPY_PWR_CON (SPM_BASE + 0x31C)
+#define MD1_PWR_CON (SPM_BASE + 0x320)
+#define VPU_TOP_PWR_CON (SPM_BASE + 0x324)
+#define CONN_PWR_CON (SPM_BASE + 0x32C)
+#define VPU_CORE2_PWR_CON (SPM_BASE + 0x330)
+#define MFG_ASYNC_PWR_CON (SPM_BASE + 0x334)
+#define MFG_PWR_CON (SPM_BASE + 0x338)
+#define VPU_CORE0_PWR_CON (SPM_BASE + 0x33C)
+#define VPU_CORE1_PWR_CON (SPM_BASE + 0x340)
+#define CAM_PWR_CON (SPM_BASE + 0x344)
+#define MFG_2D_PWR_CON (SPM_BASE + 0x348)
+#define MFG_CORE0_PWR_CON (SPM_BASE + 0x34C)
+#define SYSRAM_CON (SPM_BASE + 0x350)
+#define SYSROM_CON (SPM_BASE + 0x354)
+#define SSPM_SRAM_CON (SPM_BASE + 0x358)
+#define SCP_SRAM_CON (SPM_BASE + 0x35C)
+#define UFS_SRAM_CON (SPM_BASE + 0x36C)
+#define DUMMY_SRAM_CON (SPM_BASE + 0x380)
+#define MD_EXT_BUCK_ISO_CON (SPM_BASE + 0x390)
+#define MD_SRAM_ISO_CON (SPM_BASE + 0x394)
+#define MD_EXTRA_PWR_CON (SPM_BASE + 0x398)
+#define EXT_BUCK_CON (SPM_BASE + 0x3A0)
+#define MBIST_EFUSE_REPAIR_ACK_STA (SPM_BASE + 0x3D0)
+#define SPM_DVFS_CON (SPM_BASE + 0x400)
+#define SPM_MDBSI_CON (SPM_BASE + 0x404)
+#define SPM_MAS_PAUSE_MASK_B (SPM_BASE + 0x408)
+#define SPM_MAS_PAUSE2_MASK_B (SPM_BASE + 0x40C)
+#define SPM_BSI_GEN (SPM_BASE + 0x410)
+#define SPM_BSI_EN_SR (SPM_BASE + 0x414)
+#define SPM_BSI_CLK_SR (SPM_BASE + 0x418)
+#define SPM_BSI_D0_SR (SPM_BASE + 0x41C)
+#define SPM_BSI_D1_SR (SPM_BASE + 0x420)
+#define SPM_BSI_D2_SR (SPM_BASE + 0x424)
+#define SPM_AP_SEMA (SPM_BASE + 0x428)
+#define SPM_SPM_SEMA (SPM_BASE + 0x42C)
+#define AP_MDSRC_REQ (SPM_BASE + 0x430)
+#define SPM2MD_DVFS_CON (SPM_BASE + 0x438)
+#define MD2SPM_DVFS_CON (SPM_BASE + 0x43C)
+#define DRAMC_DPY_CLK_SW_CON_RSV (SPM_BASE + 0x440)
+#define DPY_LP_CON (SPM_BASE + 0x444)
+#define CPU_DVFS_REQ (SPM_BASE + 0x448)
+#define SPM_PLL_CON (SPM_BASE + 0x44C)
+#define SPM_EMI_BW_MODE (SPM_BASE + 0x450)
+#define AP2MD_PEER_WAKEUP (SPM_BASE + 0x454)
+#define ULPOSC_CON (SPM_BASE + 0x458)
+#define SPM2MM_CON (SPM_BASE + 0x45C)
+#define DRAMC_DPY_CLK_SW_CON_SEL (SPM_BASE + 0x460)
+#define DRAMC_DPY_CLK_SW_CON (SPM_BASE + 0x464)
+#define SPM_S1_MODE_CH (SPM_BASE + 0x468)
+#define EMI_SELF_REFRESH_CH_STA (SPM_BASE + 0x46C)
+#define DRAMC_DPY_CLK_SW_CON_SEL2 (SPM_BASE + 0x470)
+#define DRAMC_DPY_CLK_SW_CON2 (SPM_BASE + 0x474)
+#define DRAMC_DMYRD_CON (SPM_BASE + 0x478)
+#define SPM_DRS_CON (SPM_BASE + 0x47C)
+#define SPM_SEMA_M0 (SPM_BASE + 0x480)
+#define SPM_SEMA_M1 (SPM_BASE + 0x484)
+#define SPM_SEMA_M2 (SPM_BASE + 0x488)
+#define SPM_SEMA_M3 (SPM_BASE + 0x48C)
+#define SPM_SEMA_M4 (SPM_BASE + 0x490)
+#define SPM_SEMA_M5 (SPM_BASE + 0x494)
+#define SPM_SEMA_M6 (SPM_BASE + 0x498)
+#define SPM_SEMA_M7 (SPM_BASE + 0x49C)
+#define SPM_MAS_PAUSE_MM_MASK_B (SPM_BASE + 0x4A0)
+#define SPM_MAS_PAUSE_MCU_MASK_B (SPM_BASE + 0x4A4)
+#define SRAM_DREQ_ACK (SPM_BASE + 0x4AC)
+#define SRAM_DREQ_CON (SPM_BASE + 0x4B0)
+#define SRAM_DREQ_CON_SET (SPM_BASE + 0x4B4)
+#define SRAM_DREQ_CON_CLR (SPM_BASE + 0x4B8)
+#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x4BC)
+#define SPM_SSPM_IRQ (SPM_BASE + 0x4C0)
+#define SPM2PMCU_INT (SPM_BASE + 0x4C4)
+#define SPM2PMCU_INT_SET (SPM_BASE + 0x4C8)
+#define SPM2PMCU_INT_CLR (SPM_BASE + 0x4CC)
+#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x4D0)
+#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x4D4)
+#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x4D8)
+#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x4DC)
+#define PMCU2SPM_INT (SPM_BASE + 0x4E0)
+#define PMCU2SPM_INT_SET (SPM_BASE + 0x4E4)
+#define PMCU2SPM_INT_CLR (SPM_BASE + 0x4E8)
+#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x4EC)
+#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x4F0)
+#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x4F4)
+#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x4F8)
+#define PMCU2SPM_CFG (SPM_BASE + 0x4FC)
+#define MP0_CPU0_IRQ_MASK (SPM_BASE + 0x500)
+#define MP0_CPU1_IRQ_MASK (SPM_BASE + 0x504)
+#define MP0_CPU2_IRQ_MASK (SPM_BASE + 0x508)
+#define MP0_CPU3_IRQ_MASK (SPM_BASE + 0x50C)
+#define MP1_CPU0_IRQ_MASK (SPM_BASE + 0x510)
+#define MP1_CPU1_IRQ_MASK (SPM_BASE + 0x514)
+#define MP1_CPU2_IRQ_MASK (SPM_BASE + 0x518)
+#define MP1_CPU3_IRQ_MASK (SPM_BASE + 0x51C)
+#define MP0_CPU0_WFI_EN (SPM_BASE + 0x530)
+#define MP0_CPU1_WFI_EN (SPM_BASE + 0x534)
+#define MP0_CPU2_WFI_EN (SPM_BASE + 0x538)
+#define MP0_CPU3_WFI_EN (SPM_BASE + 0x53C)
+#define MP1_CPU0_WFI_EN (SPM_BASE + 0x540)
+#define MP1_CPU1_WFI_EN (SPM_BASE + 0x544)
+#define MP1_CPU2_WFI_EN (SPM_BASE + 0x548)
+#define MP1_CPU3_WFI_EN (SPM_BASE + 0x54C)
+#define MP0_L2CFLUSH (SPM_BASE + 0x554)
+#define MP1_L2CFLUSH (SPM_BASE + 0x558)
+#define CPU_PTPOD2_CON (SPM_BASE + 0x560)
+#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x570)
+#define ROOT_CORE_ADDR (SPM_BASE + 0x574)
+#define CPU_SPARE_CON (SPM_BASE + 0x580)
+#define CPU_SPARE_CON_SET (SPM_BASE + 0x584)
+#define CPU_SPARE_CON_CLR (SPM_BASE + 0x588)
+#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x5D0)
+#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x5D4)
+#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x5D8)
+#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x5DC)
+#define SW2SPM_INT (SPM_BASE + 0x5E0)
+#define SW2SPM_INT_SET (SPM_BASE + 0x5E4)
+#define SW2SPM_INT_CLR (SPM_BASE + 0x5E8)
+#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x5EC)
+#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x5F0)
+#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x5F4)
+#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x5F8)
+#define SW2SPM_CFG (SPM_BASE + 0x5FC)
+#define SPM_SW_FLAG (SPM_BASE + 0x600)
+#define SPM_SW_DEBUG (SPM_BASE + 0x604)
+#define SPM_SW_RSV_0 (SPM_BASE + 0x608)
+#define SPM_SW_RSV_1 (SPM_BASE + 0x60C)
+#define SPM_SW_RSV_2 (SPM_BASE + 0x610)
+#define SPM_SW_RSV_3 (SPM_BASE + 0x614)
+#define SPM_SW_RSV_4 (SPM_BASE + 0x618)
+#define SPM_SW_RSV_5 (SPM_BASE + 0x61C)
+#define SPM_RSV_CON (SPM_BASE + 0x620)
+#define SPM_RSV_STA (SPM_BASE + 0x624)
+#define SPM_RSV_CON1 (SPM_BASE + 0x628)
+#define SPM_RSV_STA1 (SPM_BASE + 0x62C)
+#define SPM_PASR_DPD_0 (SPM_BASE + 0x630)
+#define SPM_PASR_DPD_1 (SPM_BASE + 0x634)
+#define SPM_PASR_DPD_2 (SPM_BASE + 0x638)
+#define SPM_PASR_DPD_3 (SPM_BASE + 0x63C)
+#define SPM_SPARE_CON (SPM_BASE + 0x640)
+#define SPM_SPARE_CON_SET (SPM_BASE + 0x644)
+#define SPM_SPARE_CON_CLR (SPM_BASE + 0x648)
+#define SPM_SW_RSV_6 (SPM_BASE + 0x64C)
+#define SPM_SW_RSV_7 (SPM_BASE + 0x650)
+#define SPM_SW_RSV_8 (SPM_BASE + 0x654)
+#define SPM_SW_RSV_9 (SPM_BASE + 0x658)
+#define SPM_SW_RSV_10 (SPM_BASE + 0x65C)
+#define SPM_SW_RSV_18 (SPM_BASE + 0x67C)
+#define SPM_SW_RSV_19 (SPM_BASE + 0x680)
+#define DVFSRC_EVENT_MASK_CON (SPM_BASE + 0x690)
+#define DVFSRC_EVENT_FORCE_ON (SPM_BASE + 0x694)
+#define DVFSRC_EVENT_SEL (SPM_BASE + 0x698)
+#define SPM_DVFS_EVENT_STA (SPM_BASE + 0x69C)
+#define SPM_DVFS_EVENT_STA1 (SPM_BASE + 0x6A0)
+#define SPM_DVFS_LEVEL (SPM_BASE + 0x6A4)
+#define DVFS_ABORT_STA (SPM_BASE + 0x6A8)
+#define DVFS_ABORT_OTHERS_MASK (SPM_BASE + 0x6AC)
+#define SPM_DFS_LEVEL (SPM_BASE + 0x6B0)
+#define SPM_DVS_LEVEL (SPM_BASE + 0x6B4)
+#define SPM_DVFS_MISC (SPM_BASE + 0x6B8)
+#define SPARE_SRC_REQ_MASK (SPM_BASE + 0x6C0)
+#define SCP_VCORE_LEVEL (SPM_BASE + 0x6C4)
+#define SC_MM_CK_SEL_CON (SPM_BASE + 0x6C8)
+#define SPARE_ACK_STA (SPM_BASE + 0x6F0)
+#define SPARE_ACK_MASK (SPM_BASE + 0x6F4)
+#define SPM_DVFS_CON1 (SPM_BASE + 0x700)
+#define SPM_DVFS_CON1_STA (SPM_BASE + 0x704)
+#define SPM_DVFS_CMD0 (SPM_BASE + 0x710)
+#define SPM_DVFS_CMD1 (SPM_BASE + 0x714)
+#define SPM_DVFS_CMD2 (SPM_BASE + 0x718)
+#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C)
+#define SPM_DVFS_CMD4 (SPM_BASE + 0x720)
+#define SPM_DVFS_CMD5 (SPM_BASE + 0x724)
+#define SPM_DVFS_CMD6 (SPM_BASE + 0x728)
+#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C)
+#define SPM_DVFS_CMD8 (SPM_BASE + 0x730)
+#define SPM_DVFS_CMD9 (SPM_BASE + 0x734)
+#define SPM_DVFS_CMD10 (SPM_BASE + 0x738)
+#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C)
+#define SPM_DVFS_CMD12 (SPM_BASE + 0x740)
+#define SPM_DVFS_CMD13 (SPM_BASE + 0x744)
+#define SPM_DVFS_CMD14 (SPM_BASE + 0x748)
+#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C)
+#define WDT_LATCH_SPARE0_FIX (SPM_BASE + 0x780)
+#define WDT_LATCH_SPARE1_FIX (SPM_BASE + 0x784)
+#define WDT_LATCH_SPARE2_FIX (SPM_BASE + 0x788)
+#define WDT_LATCH_SPARE3_FIX (SPM_BASE + 0x78C)
+#define SPARE_ACK_IN_FIX (SPM_BASE + 0x790)
+#define DCHA_LATCH_RSV0_FIX (SPM_BASE + 0x794)
+#define DCHB_LATCH_RSV0_FIX (SPM_BASE + 0x798)
+#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800)
+#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804)
+#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808)
+#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C)
+#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810)
+#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814)
+#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818)
+#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C)
+#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820)
+#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824)
+#define WDT_LATCH_SPARE0 (SPM_BASE + 0x828)
+#define WDT_LATCH_SPARE1 (SPM_BASE + 0x82C)
+#define WDT_LATCH_SPARE2 (SPM_BASE + 0x830)
+#define WDT_LATCH_SPARE3 (SPM_BASE + 0x834)
+#define PCM_WDT_LATCH_10 (SPM_BASE + 0x838)
+#define PCM_WDT_LATCH_11 (SPM_BASE + 0x83C)
+#define DCHA_GATING_LATCH_0 (SPM_BASE + 0x840)
+#define DCHA_GATING_LATCH_1 (SPM_BASE + 0x844)
+#define DCHA_GATING_LATCH_2 (SPM_BASE + 0x848)
+#define DCHA_GATING_LATCH_3 (SPM_BASE + 0x84C)
+#define DCHA_GATING_LATCH_4 (SPM_BASE + 0x850)
+#define DCHA_GATING_LATCH_5 (SPM_BASE + 0x854)
+#define DCHA_GATING_LATCH_6 (SPM_BASE + 0x858)
+#define DCHA_GATING_LATCH_7 (SPM_BASE + 0x85C)
+#define DCHB_GATING_LATCH_0 (SPM_BASE + 0x860)
+#define DCHB_GATING_LATCH_1 (SPM_BASE + 0x864)
+#define DCHB_GATING_LATCH_2 (SPM_BASE + 0x868)
+#define DCHB_GATING_LATCH_3 (SPM_BASE + 0x86C)
+#define DCHB_GATING_LATCH_4 (SPM_BASE + 0x870)
+#define DCHB_GATING_LATCH_5 (SPM_BASE + 0x874)
+#define DCHB_GATING_LATCH_6 (SPM_BASE + 0x878)
+#define DCHB_GATING_LATCH_7 (SPM_BASE + 0x87C)
+#define DCHA_LATCH_RSV0 (SPM_BASE + 0x880)
+#define DCHB_LATCH_RSV0 (SPM_BASE + 0x884)
+#define PCM_WDT_LATCH_12 (SPM_BASE + 0x888)
+#define PCM_WDT_LATCH_13 (SPM_BASE + 0x88C)
+#define SPM_PC_TRACE_CON (SPM_BASE + 0x8C0)
+#define SPM_PC_TRACE_G0 (SPM_BASE + 0x8C4)
+#define SPM_PC_TRACE_G1 (SPM_BASE + 0x8C8)
+#define SPM_PC_TRACE_G2 (SPM_BASE + 0x8CC)
+#define SPM_PC_TRACE_G3 (SPM_BASE + 0x8D0)
+#define SPM_PC_TRACE_G4 (SPM_BASE + 0x8D4)
+#define SPM_PC_TRACE_G5 (SPM_BASE + 0x8D8)
+#define SPM_PC_TRACE_G6 (SPM_BASE + 0x8DC)
+#define SPM_PC_TRACE_G7 (SPM_BASE + 0x8E0)
+#define SPM_ACK_CHK_CON (SPM_BASE + 0x900)
+#define SPM_ACK_CHK_PC (SPM_BASE + 0x904)
+#define SPM_ACK_CHK_SEL (SPM_BASE + 0x908)
+#define SPM_ACK_CHK_TIMER (SPM_BASE + 0x90C)
+#define SPM_ACK_CHK_STA (SPM_BASE + 0x910)
+#define SPM_ACK_CHK_LATCH (SPM_BASE + 0x914)
+#define SPM_ACK_CHK_CON2 (SPM_BASE + 0x920)
+#define SPM_ACK_CHK_PC2 (SPM_BASE + 0x924)
+#define SPM_ACK_CHK_SEL2 (SPM_BASE + 0x928)
+#define SPM_ACK_CHK_TIMER2 (SPM_BASE + 0x92C)
+#define SPM_ACK_CHK_STA2 (SPM_BASE + 0x930)
+#define SPM_ACK_CHK_LATCH2 (SPM_BASE + 0x934)
+#define SPM_ACK_CHK_CON3 (SPM_BASE + 0x940)
+#define SPM_ACK_CHK_PC3 (SPM_BASE + 0x944)
+#define SPM_ACK_CHK_SEL3 (SPM_BASE + 0x948)
+#define SPM_ACK_CHK_TIMER3 (SPM_BASE + 0x94C)
+#define SPM_ACK_CHK_STA3 (SPM_BASE + 0x950)
+#define SPM_ACK_CHK_LATCH3 (SPM_BASE + 0x954)
+#define SPM_ACK_CHK_CON4 (SPM_BASE + 0x960)
+#define SPM_ACK_CHK_PC4 (SPM_BASE + 0x964)
+#define SPM_ACK_CHK_SEL4 (SPM_BASE + 0x968)
+#define SPM_ACK_CHK_TIMER4 (SPM_BASE + 0x96C)
+#define SPM_ACK_CHK_STA4 (SPM_BASE + 0x970)
+#define SPM_ACK_CHK_LATCH4 (SPM_BASE + 0x974)
+
+/* POWERON_CONFIG_EN (0x10006000+0x000) */
+#define BCLK_CG_EN_LSB (1U << 0) /* 1b */
+#define MD_BCLK_CG_EN_LSB (1U << 1) /* 1b */
+#define PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_POWER_ON_VAL0 (0x10006000+0x004) */
+#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */
+/* SPM_POWER_ON_VAL1 (0x10006000+0x008) */
+#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */
+/* SPM_CLK_CON (0x10006000+0x00C) */
+#define SYSCLK0_EN_CTRL_LSB (1U << 0) /* 2b */
+#define SYSCLK1_EN_CTRL_LSB (1U << 2) /* 2b */
+#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */
+#define SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */
+#define EXT_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */
+#define CXO32K_REMOVE_EN_MD1_LSB (1U << 9) /* 1b */
+#define CXO32K_REMOVE_EN_MD2_LSB (1U << 10) /* 1b */
+#define CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */
+#define CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */
+#define SRCLKEN0_EN_LSB (1U << 13) /* 1b */
+#define SRCLKEN1_EN_LSB (1U << 14) /* 1b */
+#define SCP_DCM_EN_LSB (1U << 15) /* 1b */
+#define SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 7b */
+#define SYSCLK1_SRC_MASK_B_LSB (1U << 23) /* 7b */
+/* SPM_CLK_SETTLE (0x10006000+0x010) */
+#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */
+/* SPM_AP_STANDBY_CON (0x10006000+0x014) */
+#define WFI_OP_LSB (1U << 0) /* 1b */
+#define MP0_CPUTOP_IDLE_MASK_LSB (1U << 1) /* 1b */
+#define MP1_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */
+#define MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */
+#define MM_MASK_B_LSB (1U << 16) /* 2b */
+#define MD_DDR_EN_0_DBC_EN_LSB (1U << 18) /* 1b */
+#define MD_DDR_EN_1_DBC_EN_LSB (1U << 19) /* 1b */
+#define MD_MASK_B_LSB (1U << 20) /* 2b */
+#define SSPM_MASK_B_LSB (1U << 22) /* 1b */
+#define SCP_MASK_B_LSB (1U << 23) /* 1b */
+#define SRCCLKENI_MASK_B_LSB (1U << 24) /* 1b */
+#define MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */
+#define MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */
+#define CONN_DDR_EN_DBC_EN_LSB (1U << 27) /* 1b */
+#define CONN_MASK_B_LSB (1U << 28) /* 1b */
+#define CONN_APSRC_SEL_LSB (1U << 29) /* 1b */
+/* PCM_CON0 (0x10006000+0x018) */
+#define PCM_KICK_L_LSB (1U << 0) /* 1b */
+#define IM_KICK_L_LSB (1U << 1) /* 1b */
+#define PCM_CK_EN_LSB (1U << 2) /* 1b */
+#define EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */
+#define IM_AUTO_PDN_EN_LSB (1U << 4) /* 1b */
+#define PCM_SW_RESET_LSB (1U << 15) /* 1b */
+#define PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* PCM_CON1 (0x10006000+0x01C) */
+#define IM_SLAVE_LSB (1U << 0) /* 1b */
+#define IM_SLEEP_LSB (1U << 1) /* 1b */
+#define MIF_APBEN_LSB (1U << 3) /* 1b */
+#define IM_PDN_LSB (1U << 4) /* 1b */
+#define PCM_TIMER_EN_LSB (1U << 5) /* 1b */
+#define IM_NONRP_EN_LSB (1U << 6) /* 1b */
+#define DIS_MIF_PROT_LSB (1U << 7) /* 1b */
+#define PCM_WDT_EN_LSB (1U << 8) /* 1b */
+#define PCM_WDT_WAKE_MODE_LSB (1U << 9) /* 1b */
+#define SPM_SRAM_SLEEP_B_LSB (1U << 10) /* 1b */
+#define SPM_SRAM_ISOINT_B_LSB (1U << 11) /* 1b */
+#define EVENT_LOCK_EN_LSB (1U << 12) /* 1b */
+#define SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */
+#define SCP_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */
+#define PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* PCM_IM_PTR (0x10006000+0x020) */
+#define PCM_IM_PTR_LSB (1U << 0) /* 32b */
+/* PCM_IM_LEN (0x10006000+0x024) */
+#define PCM_IM_LEN_LSB (1U << 0) /* 13b */
+/* PCM_REG_DATA_INI (0x10006000+0x028) */
+#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */
+/* PCM_PWR_IO_EN (0x10006000+0x02C) */
+#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */
+#define PCM_RF_SYNC_EN_LSB (1U << 16) /* 8b */
+/* PCM_TIMER_VAL (0x10006000+0x030) */
+#define PCM_TIMER_VAL_LSB (1U << 0) /* 32b */
+/* PCM_WDT_VAL (0x10006000+0x034) */
+#define PCM_WDT_VAL_LSB (1U << 0) /* 32b */
+/* PCM_IM_HOST_RW_PTR (0x10006000+0x038) */
+#define PCM_IM_HOST_RW_PTR_LSB (1U << 0) /* 12b */
+#define PCM_IM_HOST_W_EN_LSB (1U << 30) /* 1b */
+#define PCM_IM_HOST_EN_LSB (1U << 31) /* 1b */
+/* PCM_IM_HOST_RW_DAT (0x10006000+0x03C) */
+#define PCM_IM_HOST_RW_DAT_LSB (1U << 0) /* 32b */
+/* PCM_EVENT_VECTOR0 (0x10006000+0x040) */
+#define PCM_EVENT_VECTOR_0_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_0_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_0_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_0_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR1 (0x10006000+0x044) */
+#define PCM_EVENT_VECTOR_1_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_1_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_1_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_1_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR2 (0x10006000+0x048) */
+#define PCM_EVENT_VECTOR_2_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_2_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_2_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_2_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR3 (0x10006000+0x04C) */
+#define PCM_EVENT_VECTOR_3_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_3_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_3_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_3_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR4 (0x10006000+0x050) */
+#define PCM_EVENT_VECTOR_4_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_4_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_4_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_4_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR5 (0x10006000+0x054) */
+#define PCM_EVENT_VECTOR_5_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_5_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_5_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_5_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR6 (0x10006000+0x058) */
+#define PCM_EVENT_VECTOR_6_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_6_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_6_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_6_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR7 (0x10006000+0x05C) */
+#define PCM_EVENT_VECTOR_7_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_7_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_7_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_7_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR8 (0x10006000+0x060) */
+#define PCM_EVENT_VECTOR_8_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_8_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_8_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_8_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR9 (0x10006000+0x064) */
+#define PCM_EVENT_VECTOR_9_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_9_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_9_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_9_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR10 (0x10006000+0x068) */
+#define PCM_EVENT_VECTOR_10_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_10_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_10_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_10_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR11 (0x10006000+0x06C) */
+#define PCM_EVENT_VECTOR_11_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_11_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_11_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_11_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR12 (0x10006000+0x070) */
+#define PCM_EVENT_VECTOR_12_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_12_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_12_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_12_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR13 (0x10006000+0x074) */
+#define PCM_EVENT_VECTOR_13_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_13_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_13_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_13_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR14 (0x10006000+0x078) */
+#define PCM_EVENT_VECTOR_14_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_14_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_14_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_14_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR15 (0x10006000+0x07C) */
+#define PCM_EVENT_VECTOR_15_LSB (1U << 0) /* 6b */
+#define PCM_EVENT_RESUME_15_LSB (1U << 6) /* 1b */
+#define PCM_EVENT_IMMEDIA_15_LSB (1U << 7) /* 1b */
+#define PCM_EVENT_VECTPC_15_LSB (1U << 16) /* 11b */
+/* PCM_EVENT_VECTOR_EN (0x10006000+0x080) */
+#define PCM_EVENT_VECTOR_EN_LSB (1U << 0) /* 16b */
+/* SPM_SRAM_RSV_CON (0x10006000+0x088) */
+#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */
+/* SPM_SWINT (0x10006000+0x08C) */
+#define SPM_SWINT_LSB (1U << 0) /* 10b */
+/* SPM_SWINT_SET (0x10006000+0x090) */
+#define SPM_SWINT_SET_LSB (1U << 0) /* 10b */
+/* SPM_SWINT_CLR (0x10006000+0x094) */
+#define SPM_SWINT_CLR_LSB (1U << 0) /* 10b */
+/* SPM_SCP_MAILBOX (0x10006000+0x098) */
+#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */
+/* SCP_SPM_MAILBOX (0x10006000+0x09C) */
+#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CON (0x10006000+0x0A0) */
+#define TWAM_ENABLE_LSB (1U << 0) /* 1b */
+#define TWAM_SPEED_MODE_ENABLE_LSB (1U << 1) /* 1b */
+#define TWAM_SW_RST_LSB (1U << 2) /* 1b */
+#define TWAM_MON_TYPE0_LSB (1U << 4) /* 2b */
+#define TWAM_MON_TYPE1_LSB (1U << 6) /* 2b */
+#define TWAM_MON_TYPE2_LSB (1U << 8) /* 2b */
+#define TWAM_MON_TYPE3_LSB (1U << 10) /* 2b */
+#define TWAM_SIGNAL_SEL0_LSB (1U << 12) /* 5b */
+#define TWAM_SIGNAL_SEL1_LSB (1U << 17) /* 5b */
+#define TWAM_SIGNAL_SEL2_LSB (1U << 22) /* 5b */
+#define TWAM_SIGNAL_SEL3_LSB (1U << 27) /* 5b */
+/* SPM_TWAM_WINDOW_LEN (0x10006000+0x0A4) */
+#define TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_IDLE_SEL (0x10006000+0x0A8) */
+#define TWAM_IDLE_SEL_LSB (1U << 0) /* 5b */
+/* SPM_SCP_IRQ (0x10006000+0x0AC) */
+#define SPM_SCP_IRQ_LSB (1U << 0) /* 1b */
+#define SPM_SCP_IRQ_SEL_LSB (1U << 4) /* 1b */
+/* SPM_CPU_WAKEUP_EVENT (0x10006000+0x0B0) */
+#define SPM_CPU_WAKEUP_EVENT_LSB (1U << 0) /* 1b */
+/* SPM_IRQ_MASK (0x10006000+0x0B4) */
+#define SPM_TWAM_IRQ_MASK_LSB (1U << 2) /* 1b */
+#define PCM_IRQ_ROOT_MASK_LSB (1U << 3) /* 1b */
+#define SPM_IRQ_MASK_LSB (1U << 8) /* 10b */
+/* SPM_SRC_REQ (0x10006000+0x0B8) */
+#define SPM_APSRC_REQ_LSB (1U << 0) /* 1b */
+#define SPM_F26M_REQ_LSB (1U << 1) /* 1b */
+#define SPM_INFRA_REQ_LSB (1U << 3) /* 1b */
+#define SPM_VRF18_REQ_LSB (1U << 4) /* 1b */
+#define SPM_DDREN_REQ_LSB (1U << 7) /* 1b */
+#define SPM_RSV_SRC_REQ_LSB (1U << 8) /* 3b */
+#define SPM_DDREN_2_REQ_LSB (1U << 11) /* 1b */
+#define CPU_MD_DVFS_SOP_FORCE_ON_LSB (1U << 16) /* 1b */
+/* SPM_SRC_MASK (0x10006000+0x0BC) */
+#define CSYSPWREQ_MASK_LSB (1U << 0) /* 1b */
+#define CCIF0_MD_EVENT_MASK_B_LSB (1U << 1) /* 1b */
+#define CCIF0_AP_EVENT_MASK_B_LSB (1U << 2) /* 1b */
+#define CCIF1_MD_EVENT_MASK_B_LSB (1U << 3) /* 1b */
+#define CCIF1_AP_EVENT_MASK_B_LSB (1U << 4) /* 1b */
+#define CCIF2_MD_EVENT_MASK_B_LSB (1U << 5) /* 1b */
+#define CCIF2_AP_EVENT_MASK_B_LSB (1U << 6) /* 1b */
+#define CCIF3_MD_EVENT_MASK_B_LSB (1U << 7) /* 1b */
+#define CCIF3_AP_EVENT_MASK_B_LSB (1U << 8) /* 1b */
+#define MD_SRCCLKENA_0_INFRA_MASK_B_LSB (1U << 9) /* 1b */
+#define MD_SRCCLKENA_1_INFRA_MASK_B_LSB (1U << 10) /* 1b */
+#define CONN_SRCCLKENA_INFRA_MASK_B_LSB (1U << 11) /* 1b */
+#define UFS_INFRA_REQ_MASK_B_LSB (1U << 12) /* 1b */
+#define SRCCLKENI_INFRA_MASK_B_LSB (1U << 13) /* 1b */
+#define MD_APSRC_REQ_0_INFRA_MASK_B_LSB (1U << 14) /* 1b */
+#define MD_APSRC_REQ_1_INFRA_MASK_B_LSB (1U << 15) /* 1b */
+#define CONN_APSRCREQ_INFRA_MASK_B_LSB (1U << 16) /* 1b */
+#define UFS_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */
+#define MD_VRF18_REQ_0_MASK_B_LSB (1U << 18) /* 1b */
+#define MD_VRF18_REQ_1_MASK_B_LSB (1U << 19) /* 1b */
+#define UFS_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define CONN_INFRA_REQ_MASK_B_LSB (1U << 22) /* 1b */
+#define GCE_APSRC_REQ_MASK_B_LSB (1U << 23) /* 1b */
+#define DISP0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define DISP1_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define MFG_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define VDEC_REQ_MASK_B_LSB (1U << 27) /* 1b */
+/* SPM_SRC2_MASK (0x10006000+0x0C0) */
+#define MD_DDR_EN_0_MASK_B_LSB (1U << 0) /* 1b */
+#define MD_DDR_EN_1_MASK_B_LSB (1U << 1) /* 1b */
+#define CONN_DDR_EN_MASK_B_LSB (1U << 2) /* 1b */
+#define DDREN_SSPM_APSRC_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define DDREN_SCP_APSRC_REQ_MASK_B_LSB (1U << 4) /* 1b */
+#define DISP0_DDREN_MASK_B_LSB (1U << 5) /* 1b */
+#define DISP1_DDREN_MASK_B_LSB (1U << 6) /* 1b */
+#define GCE_DDREN_MASK_B_LSB (1U << 7) /* 1b */
+#define DDREN_EMI_SELF_REFRESH_CH0_MASK_B_LSB (1U << 8) /* 1b */
+#define DDREN_EMI_SELF_REFRESH_CH1_MASK_B_LSB (1U << 9) /* 1b */
+/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0C4) */
+#define SPM_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000+0x0C8) */
+#define SPM_WAKEUP_EVENT_EXT_MASK_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_EVENT_CLEAR (0x10006000+0x0CC) */
+#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */
+/* SCP_CLK_CON (0x10006000+0x0D0) */
+#define SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */
+#define SCP_SECURE_V_REQ_MASK_LSB (1U << 1) /* 1b */
+#define SCP_SLP_REQ_LSB (1U << 2) /* 1b */
+#define SCP_SLP_ACK_LSB (1U << 3) /* 1b */
+/* PCM_DEBUG_CON (0x10006000+0x0D4) */
+#define PCM_DEBUG_OUT_ENABLE_LSB (1U << 0) /* 1b */
+/* DDR_EN_DBC_LEN (0x10006000+0x0D8) */
+#define MD_DDR_EN_0_DBC_LEN_LSB (1U << 0) /* 10b */
+#define MD_DDR_EN_1_DBC_LEN_LSB (1U << 10) /* 10b */
+#define CONN_DDR_EN_DBC_LEN_LSB (1U << 20) /* 10b */
+/* AHB_BUS_CON (0x10006000+0x0DC) */
+#define AHB_HADDR_EXT_LSB (1U << 0) /* 2b */
+#define REG_AHB_LOCK_LSB (1U << 8) /* 1b */
+/* SPM_SRC3_MASK (0x10006000+0x0E0) */
+#define MD_DDR_EN_2_0_MASK_B_LSB (1U << 0) /* 1b */
+#define MD_DDR_EN_2_1_MASK_B_LSB (1U << 1) /* 1b */
+#define CONN_DDR_EN_2_MASK_B_LSB (1U << 2) /* 1b */
+#define DDREN2_SSPM_APSRC_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define DDREN2_SCP_APSRC_REQ_MASK_B_LSB (1U << 4) /* 1b */
+#define DISP0_DDREN2_MASK_B_LSB (1U << 5) /* 1b */
+#define DISP1_DDREN2_MASK_B_LSB (1U << 6) /* 1b */
+#define GCE_DDREN2_MASK_B_LSB (1U << 7) /* 1b */
+#define DDREN2_EMI_SELF_REFRESH_CH0_MASK_B_LSB (1U << 8) /* 1b */
+#define DDREN2_EMI_SELF_REFRESH_CH1_MASK_B_LSB (1U << 9) /* 1b */
+/* DDR_EN_EMI_DBC_CON (0x10006000+0x0E4) */
+#define EMI_SELF_REFRESH_CH0_DBC_LEN_LSB (1U << 0) /* 10b */
+#define EMI_SELF_REFRESH_CH0_DBC_EN_LSB (1U << 10) /* 1b */
+#define EMI_SELF_REFRESH_CH1_DBC_LEN_LSB (1U << 16) /* 10b */
+#define EMI_SELF_REFRESH_CH1_DBC_EN_LSB (1U << 26) /* 1b */
+/* SSPM_CLK_CON (0x10006000+0x0E8) */
+#define SSPM_26M_CK_SEL_LSB (1U << 0) /* 1b */
+/* PCM_REG0_DATA (0x10006000+0x100) */
+#define PCM_REG0_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG1_DATA (0x10006000+0x104) */
+#define PCM_REG1_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG2_DATA (0x10006000+0x108) */
+#define PCM_REG2_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG3_DATA (0x10006000+0x10C) */
+#define PCM_REG3_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG4_DATA (0x10006000+0x110) */
+#define PCM_REG4_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG5_DATA (0x10006000+0x114) */
+#define PCM_REG5_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG6_DATA (0x10006000+0x118) */
+#define PCM_REG6_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG7_DATA (0x10006000+0x11C) */
+#define PCM_REG7_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG8_DATA (0x10006000+0x120) */
+#define PCM_REG8_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG9_DATA (0x10006000+0x124) */
+#define PCM_REG9_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG10_DATA (0x10006000+0x128) */
+#define PCM_REG10_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG11_DATA (0x10006000+0x12C) */
+#define PCM_REG11_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG12_DATA (0x10006000+0x130) */
+#define PCM_REG12_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG13_DATA (0x10006000+0x134) */
+#define PCM_REG13_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG14_DATA (0x10006000+0x138) */
+#define PCM_REG14_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG15_DATA (0x10006000+0x13C) */
+#define PCM_REG15_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG12_MASK_B_STA (0x10006000+0x140) */
+#define PCM_REG12_MASK_B_STA_LSB (1U << 0) /* 32b */
+/* PCM_REG12_EXT_DATA (0x10006000+0x144) */
+#define PCM_REG12_EXT_DATA_LSB (1U << 0) /* 32b */
+/* PCM_REG12_EXT_MASK_B_STA (0x10006000+0x148) */
+#define PCM_REG12_EXT_MASK_B_STA_LSB (1U << 0) /* 32b */
+/* PCM_EVENT_REG_STA (0x10006000+0x14C) */
+#define PCM_EVENT_REG_STA_LSB (1U << 0) /* 32b */
+/* PCM_TIMER_OUT (0x10006000+0x150) */
+#define PCM_TIMER_OUT_LSB (1U << 0) /* 32b */
+/* PCM_WDT_OUT (0x10006000+0x154) */
+#define PCM_WDT_OUT_LSB (1U << 0) /* 32b */
+/* SPM_IRQ_STA (0x10006000+0x158) */
+#define SPM_ACK_CHK_WAKEUP_LSB (1U << 1) /* 1b */
+#define TWAM_IRQ_LSB (1U << 2) /* 1b */
+#define PCM_IRQ_LSB (1U << 3) /* 1b */
+/* #define SPM_SWINT_LSB (1U << 4) */ /* 10b */
+/* SPM_WAKEUP_STA (0x10006000+0x15C) */
+#define SPM_WAKEUP_EVENT_STA_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_EXT_STA (0x10006000+0x160) */
+#define SPM_WAKEUP_EVENT_EXT_STA_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_MISC (0x10006000+0x164) */
+#define SPM_WAKEUP_EVENT_MISC_LSB (1U << 0) /* 30b */
+#define SPM_PWRAP_IRQ_ACK_LSB (1U << 30) /* 1b */
+#define SPM_PWRAP_IRQ_LSB (1U << 31) /* 1b */
+/* BUS_PROTECT_RDY (0x10006000+0x168) */
+#define BUS_PROTECT_RDY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT2_RDY (0x10006000+0x16C) */
+#define BUS_PROTECT2_RDY_LSB (1U << 0) /* 32b */
+/* SUBSYS_IDLE_STA (0x10006000+0x170) */
+#define SUBSYS_IDLE_STA_LSB (1U << 0) /* 32b */
+/* CPU_IDLE_STA (0x10006000+0x174) */
+#define MP0_CPU0_STANDBYWFI_AFTER_SEL_LSB (1U << 0) /* 1b */
+#define MP0_CPU1_STANDBYWFI_AFTER_SEL_LSB (1U << 1) /* 1b */
+#define MP0_CPU2_STANDBYWFI_AFTER_SEL_LSB (1U << 2) /* 1b */
+#define MP0_CPU3_STANDBYWFI_AFTER_SEL_LSB (1U << 3) /* 1b */
+#define MP1_CPU0_STANDBYWFI_AFTER_SEL_LSB (1U << 4) /* 1b */
+#define MP1_CPU1_STANDBYWFI_AFTER_SEL_LSB (1U << 5) /* 1b */
+#define MP1_CPU2_STANDBYWFI_AFTER_SEL_LSB (1U << 6) /* 1b */
+#define MP1_CPU3_STANDBYWFI_AFTER_SEL_LSB (1U << 7) /* 1b */
+#define MP0_CPU0_STANDBYWFI_LSB (1U << 10) /* 1b */
+#define MP0_CPU1_STANDBYWFI_LSB (1U << 11) /* 1b */
+#define MP0_CPU2_STANDBYWFI_LSB (1U << 12) /* 1b */
+#define MP0_CPU3_STANDBYWFI_LSB (1U << 13) /* 1b */
+#define MP1_CPU0_STANDBYWFI_LSB (1U << 14) /* 1b */
+#define MP1_CPU1_STANDBYWFI_LSB (1U << 15) /* 1b */
+#define MP1_CPU2_STANDBYWFI_LSB (1U << 16) /* 1b */
+#define MP1_CPU3_STANDBYWFI_LSB (1U << 17) /* 1b */
+#define MP0_CPUTOP_IDLE_LSB (1U << 20) /* 1b */
+#define MP1_CPUTOP_IDLE_LSB (1U << 21) /* 1b */
+#define MCU_BIU_IDLE_LSB (1U << 22) /* 1b */
+#define MCUSYS_IDLE_LSB (1U << 23) /* 1b */
+/* PCM_FSM_STA (0x10006000+0x178) */
+#define EXEC_INST_OP_LSB (1U << 0) /* 4b */
+#define PC_STATE_LSB (1U << 4) /* 3b */
+#define IM_STATE_LSB (1U << 7) /* 3b */
+#define MASTER_STATE_LSB (1U << 10) /* 5b */
+#define EVENT_FSM_LSB (1U << 15) /* 3b */
+#define PCM_CLK_SEL_STA_LSB (1U << 18) /* 3b */
+#define PCM_KICK_LSB (1U << 21) /* 1b */
+#define IM_KICK_LSB (1U << 22) /* 1b */
+#define EXT_SRCCLKEN_STA_LSB (1U << 23) /* 2b */
+#define EXT_SRCVOLTEN_STA_LSB (1U << 25) /* 1b */
+/* SRC_REQ_STA (0x10006000+0x17C) */
+#define SRC_REQ_STA_LSB (1U << 0) /* 32b */
+/* PWR_STATUS (0x10006000+0x180) */
+#define PWR_STATUS_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_2ND (0x10006000+0x184) */
+#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */
+/* CPU_PWR_STATUS (0x10006000+0x188) */
+#define CPU_PWR_STATUS_LSB (1U << 0) /* 32b */
+/* CPU_PWR_STATUS_2ND (0x10006000+0x18C) */
+#define CPU_PWR_STATUS_2ND_LSB (1U << 0) /* 32b */
+/* MISC_STA (0x10006000+0x190) */
+#define MM_DVFS_HALT_AF_MASK_LSB (1U << 0) /* 5b */
+/* SPM_SRC_RDY_STA (0x10006000+0x194) */
+#define SPM_INFRA_SRC_ACK_LSB (1U << 0) /* 1b */
+#define SPM_VRF18_SRC_ACK_LSB (1U << 1) /* 1b */
+/* DRAMC_DBG_LATCH (0x10006000+0x19C) */
+#define DRAMC_DEBUG_LATCH_STATUS_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA0 (0x10006000+0x1A0) */
+#define SPM_TWAM_LAST_STA0_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA1 (0x10006000+0x1A4) */
+#define SPM_TWAM_LAST_STA1_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA2 (0x10006000+0x1A8) */
+#define SPM_TWAM_LAST_STA2_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA3 (0x10006000+0x1AC) */
+#define SPM_TWAM_LAST_STA3_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA0 (0x10006000+0x1B0) */
+#define SPM_TWAM_CURR_STA0_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA1 (0x10006000+0x1B4) */
+#define SPM_TWAM_CURR_STA1_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA2 (0x10006000+0x1B8) */
+#define SPM_TWAM_CURR_STA2_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA3 (0x10006000+0x1BC) */
+#define SPM_TWAM_CURR_STA3_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_TIMER_OUT (0x10006000+0x1C0) */
+#define SPM_TWAM_TIMER_OUT_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_STA (0x10006000+0x1C8) */
+#define MD_DVFS_ERROR_STATUS_LSB (1U << 0) /* 1b */
+/* BUS_PROTECT3_RDY (0x10006000+0x1CC) */
+#define BUS_PROTECT_MM_RDY_LSB (1U << 0) /* 16b */
+#define BUS_PROTECT_MCU_RDY_LSB (1U << 16) /* 16b */
+/* SRC_DDREN_STA (0x10006000+0x1E0) */
+#define SRC_DDREN_STA_LSB (1U << 0) /* 32b */
+/* MCU_PWR_CON (0x10006000+0x200) */
+#define MCU_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MCU_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MCU_PWR_ON_LSB (1U << 2) /* 1b */
+#define MCU_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MCU_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MCU_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MCU_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MCU_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MCU_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MCU_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MCU_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MCU_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP0_CPUTOP_PWR_CON (0x10006000+0x204) */
+#define MP0_CPUTOP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP0_CPUTOP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP0_CPUTOP_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP0_CPUTOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP0_CPUTOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP0_CPUTOP_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP0_CPUTOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP0_CPUTOP_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP0_CPUTOP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP0_CPUTOP_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP0_CPUTOP_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP0_CPUTOP_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP0_CPU0_PWR_CON (0x10006000+0x208) */
+#define MP0_CPU0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP0_CPU0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP0_CPU0_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP0_CPU0_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP0_CPU0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP0_CPU0_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP0_CPU0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP0_CPU0_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP0_CPU0_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP0_CPU0_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP0_CPU0_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP0_CPU0_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP0_CPU1_PWR_CON (0x10006000+0x20C) */
+#define MP0_CPU1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP0_CPU1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP0_CPU1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP0_CPU1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP0_CPU1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP0_CPU1_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP0_CPU1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP0_CPU1_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP0_CPU1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP0_CPU1_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP0_CPU1_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP0_CPU1_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP0_CPU2_PWR_CON (0x10006000+0x210) */
+#define MP0_CPU2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP0_CPU2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP0_CPU2_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP0_CPU2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP0_CPU2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP0_CPU2_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP0_CPU2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP0_CPU2_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP0_CPU2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP0_CPU2_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP0_CPU2_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP0_CPU2_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP0_CPU3_PWR_CON (0x10006000+0x214) */
+#define MP0_CPU3_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP0_CPU3_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP0_CPU3_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP0_CPU3_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP0_CPU3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP0_CPU3_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP0_CPU3_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP0_CPU3_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP0_CPU3_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP0_CPU3_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP0_CPU3_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP0_CPU3_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP1_CPUTOP_PWR_CON (0x10006000+0x218) */
+#define MP1_CPUTOP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP1_CPUTOP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP1_CPUTOP_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP1_CPUTOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP1_CPUTOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP1_CPUTOP_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP1_CPUTOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP1_CPUTOP_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP1_CPUTOP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP1_CPUTOP_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP1_CPUTOP_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP1_CPUTOP_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP1_CPU0_PWR_CON (0x10006000+0x21C) */
+#define MP1_CPU0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP1_CPU0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP1_CPU0_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP1_CPU0_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP1_CPU0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP1_CPU0_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP1_CPU0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP1_CPU0_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP1_CPU0_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP1_CPU0_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP1_CPU0_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP1_CPU0_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP1_CPU1_PWR_CON (0x10006000+0x220) */
+#define MP1_CPU1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP1_CPU1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP1_CPU1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP1_CPU1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP1_CPU1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP1_CPU1_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP1_CPU1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP1_CPU1_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP1_CPU1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP1_CPU1_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP1_CPU1_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP1_CPU1_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP1_CPU2_PWR_CON (0x10006000+0x224) */
+#define MP1_CPU2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP1_CPU2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP1_CPU2_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP1_CPU2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP1_CPU2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP1_CPU2_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP1_CPU2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP1_CPU2_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP1_CPU2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP1_CPU2_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP1_CPU2_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP1_CPU2_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP1_CPU3_PWR_CON (0x10006000+0x228) */
+#define MP1_CPU3_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MP1_CPU3_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MP1_CPU3_PWR_ON_LSB (1U << 2) /* 1b */
+#define MP1_CPU3_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MP1_CPU3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MP1_CPU3_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MP1_CPU3_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MP1_CPU3_SRAM_PD_SLPB_CLAMP_LSB (1U << 7) /* 1b */
+#define MP1_CPU3_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MP1_CPU3_SRAM_SLEEP_B_LSB (1U << 12) /* 1b */
+#define SC_MP1_CPU3_SRAM_PDN_ACK_LSB (1U << 24) /* 1b */
+#define SC_MP1_CPU3_SRAM_SLEEP_B_ACK_LSB (1U << 28) /* 1b */
+/* MP0_CPUTOP_L2_PDN (0x10006000+0x240) */
+#define MP0_CPUTOP_L2_SRAM_PDN_LSB (1U << 0) /* 1b */
+#define MP0_CPUTOP_L2_SRAM_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP0_CPUTOP_L2_SLEEP_B (0x10006000+0x244) */
+#define MP0_CPUTOP_L2_SRAM_SLEEP_B_LSB (1U << 0) /* 1b */
+#define MP0_CPUTOP_L2_SRAM_SLEEP_B_ACK_LSB (1U << 8) /* 1b */
+/* MP0_CPU0_L1_PDN (0x10006000+0x248) */
+#define MP0_CPU0_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP0_CPU0_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP0_CPU1_L1_PDN (0x10006000+0x24C) */
+#define MP0_CPU1_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP0_CPU1_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP0_CPU2_L1_PDN (0x10006000+0x250) */
+#define MP0_CPU2_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP0_CPU2_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP0_CPU3_L1_PDN (0x10006000+0x254) */
+#define MP0_CPU3_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP0_CPU3_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP1_CPUTOP_L2_PDN (0x10006000+0x258) */
+#define MP1_CPUTOP_L2_SRAM_PDN_LSB (1U << 0) /* 1b */
+#define MP1_CPUTOP_L2_SRAM_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP1_CPUTOP_L2_SLEEP_B (0x10006000+0x25C) */
+#define MP1_CPUTOP_L2_SRAM_SLEEP_B_LSB (1U << 0) /* 1b */
+#define MP1_CPUTOP_L2_SRAM_SLEEP_B_ACK_LSB (1U << 8) /* 1b */
+/* MP1_CPU0_L1_PDN (0x10006000+0x260) */
+#define MP1_CPU0_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP1_CPU0_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP1_CPU1_L1_PDN (0x10006000+0x264) */
+#define MP1_CPU1_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP1_CPU1_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP1_CPU2_L1_PDN (0x10006000+0x268) */
+#define MP1_CPU2_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP1_CPU2_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* MP1_CPU3_L1_PDN (0x10006000+0x26C) */
+#define MP1_CPU3_L1_PDN_LSB (1U << 0) /* 1b */
+#define MP1_CPU3_L1_PDN_ACK_LSB (1U << 8) /* 1b */
+/* CPU_EXT_BUCK_ISO (0x10006000+0x290) */
+#define MP0_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */
+#define MP1_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */
+#define MP_EXT_BUCK_ISO_LSB (1U << 2) /* 1b */
+/* DUMMY1_PWR_CON (0x10006000+0x2B0) */
+#define DUMMY1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DUMMY1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DUMMY1_PWR_ON_LSB (1U << 2) /* 1b */
+#define DUMMY1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DUMMY1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+/* BYPASS_SPMC (0x10006000+0x2B4) */
+#define BYPASS_CPU_SPMC_MODE_LSB (1U << 0) /* 1b */
+/* SPMC_DORMANT_ENABLE (0x10006000+0x2B8) */
+#define MP0_SPMC_SRAM_DORMANT_EN_LSB (1U << 0) /* 1b */
+#define MP1_SPMC_SRAM_DORMANT_EN_LSB (1U << 1) /* 1b */
+/* ARMPLL_CLK_CON (0x10006000+0x2BC) */
+#define REG_SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 3b */
+#define REG_SC_ARM_CLK_OFF_LSB (1U << 3) /* 3b */
+#define REG_SC_ARMPLLOUT_OFF_LSB (1U << 6) /* 3b */
+#define REG_SC_ARMPLL_OFF_LSB (1U << 9) /* 3b */
+#define REG_SC_ARMPLL_S_OFF_LSB (1U << 12) /* 3b */
+/* SPMC_IN_RET (0x10006000+0x2C0) */
+#define SPMC_STATUS_LSB (1U << 0) /* 8b */
+/* VDE_PWR_CON (0x10006000+0x300) */
+#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VDE_PWR_ON_LSB (1U << 2) /* 1b */
+#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VDE_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* VEN_PWR_CON (0x10006000+0x304) */
+#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VEN_PWR_ON_LSB (1U << 2) /* 1b */
+#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VEN_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* ISP_PWR_CON (0x10006000+0x308) */
+#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ISP_PWR_ON_LSB (1U << 2) /* 1b */
+#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ISP_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* DIS_PWR_CON (0x10006000+0x30C) */
+#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DIS_PWR_ON_LSB (1U << 2) /* 1b */
+#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DIS_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* MFG_CORE1_PWR_CON (0x10006000+0x310) */
+#define MFG_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG_CORE1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG_CORE1_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define MFG_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* AUDIO_PWR_CON (0x10006000+0x314) */
+#define AUD_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define AUD_PWR_ISO_LSB (1U << 1) /* 1b */
+#define AUD_PWR_ON_LSB (1U << 2) /* 1b */
+#define AUD_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define AUD_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define AUD_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define AUD_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* IFR_PWR_CON (0x10006000+0x318) */
+#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IFR_PWR_ON_LSB (1U << 2) /* 1b */
+#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IFR_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* DPY_PWR_CON (0x10006000+0x31C) */
+#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DPY_PWR_ON_LSB (1U << 2) /* 1b */
+#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DPY_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define DPY_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* MD1_PWR_CON (0x10006000+0x320) */
+#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MD1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */
+/* VPU_TOP_PWR_CON (0x10006000+0x324) */
+#define VPU_TOP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VPU_TOP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VPU_TOP_PWR_ON_LSB (1U << 2) /* 1b */
+#define VPU_TOP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VPU_TOP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VPU_TOP_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define VPU_TOP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define VPU_TOP_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define VPU_TOP_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+#define VPU_TOP_SRAM_SLPB_LSB (1U << 16) /* 4b */
+#define VPU_TOP_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */
+/* CONN_PWR_CON (0x10006000+0x32C) */
+#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CONN_PWR_ON_LSB (1U << 2) /* 1b */
+#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CONN_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define CONN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VPU_CORE2_PWR_CON (0x10006000+0x330) */
+#define VPU_CORE2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VPU_CORE2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VPU_CORE2_PWR_ON_LSB (1U << 2) /* 1b */
+#define VPU_CORE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VPU_CORE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VPU_CORE2_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define VPU_CORE2_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define VPU_CORE2_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define VPU_CORE2_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+#define VPU_CORE2_SRAM_SLPB_LSB (1U << 16) /* 4b */
+#define VPU_CORE2_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */
+/* MFG_ASYNC_PWR_CON (0x10006000+0x334) */
+#define MFG_ASYNC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG_ASYNC_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG_ASYNC_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG_ASYNC_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG_ASYNC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG_ASYNC_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define MFG_ASYNC_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* MFG_PWR_CON (0x10006000+0x338) */
+#define MFG_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define MFG_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* VPU_CORE0_PWR_CON (0x10006000+0x33C) */
+#define VPU_CORE0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VPU_CORE0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VPU_CORE0_PWR_ON_LSB (1U << 2) /* 1b */
+#define VPU_CORE0_ON_2ND_LSB (1U << 3) /* 1b */
+#define VPU_CORE0_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VPU_CORE0_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define VPU_CORE0_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define VPU_CORE0_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define VPU_CORE0_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+#define VPU_CORE0_SRAM_SLPB_LSB (1U << 16) /* 4b */
+#define VPU_CORE0_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */
+/* VPU_CORE1_PWR_CON (0x10006000+0x340) */
+#define VPU_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VPU_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VPU_CORE1_PWR_ON_LSB (1U << 2) /* 1b */
+#define VPU_CORE1_ON_2ND_LSB (1U << 3) /* 1b */
+#define VPU_CORE1_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VPU_CORE1_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define VPU_CORE1_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define VPU_CORE1_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define VPU_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+#define VPU_CORE1_SRAM_SLPB_LSB (1U << 16) /* 4b */
+#define VPU_CORE1_SRAM_SLPB_ACK_LSB (1U << 28) /* 4b */
+/* CAM_PWR_CON (0x10006000+0x344) */
+#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* MFG_2D_PWR_CON (0x10006000+0x348) */
+#define MFG_2D_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG_2D_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG_2D_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG_2D_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG_2D_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG_2D_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define MFG_2D_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* MFG_CORE0_PWR_CON (0x10006000+0x34C) */
+#define MFG_CORE0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG_CORE0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG_CORE0_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG_CORE0_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG_CORE0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG_CORE0_SRAM_PDN_LSB (1U << 8) /* 4b */
+#define MFG_CORE0_SRAM_PDN_ACK_LSB (1U << 12) /* 4b */
+/* SYSRAM_CON (0x10006000+0x350) */
+#define IFR_SRAMROM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define IFR_SRAMROM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define IFR_SRAMROM_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */
+#define IFR_SRAMROM_SRAM_PDN_LSB (1U << 16) /* 8b */
+/* SYSROM_CON (0x10006000+0x354) */
+#define IFR_SRAMROM_ROM_PDN_LSB (1U << 0) /* 6b */
+/* SSPM_SRAM_CON (0x10006000+0x358) */
+#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* SCP_SRAM_CON (0x10006000+0x35C) */
+#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* UFS_SRAM_CON (0x10006000+0x36C) */
+#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */
+#define UFS_SRAM_PDN_LSB (1U << 16) /* 5b */
+/* DUMMY_SRAM_CON (0x10006000+0x380) */
+#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */
+#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 8b */
+/* MD_EXT_BUCK_ISO_CON (0x10006000+0x390) */
+#define VMODEM_BUCK_ELS_EN_LSB (1U << 0) /* 1b */
+#define VMD_BUCK_ELS_EN_LSB (1U << 1) /* 1b */
+/* MD_SRAM_ISO_CON (0x10006000+0x394) */
+#define MD1_SRAM_ISOINT_B_LSB (1U << 0) /* 1b */
+/* MD_EXTRA_PWR_CON (0x10006000+0x398) */
+#define MD1_PWR_PROT_REQ_STA_LSB (1U << 0) /* 1b */
+#define MD2_PWR_PROT_REQ_STA_LSB (1U << 1) /* 1b */
+/* EXT_BUCK_CON (0x10006000+0x3A0) */
+#define RG_VA09_ON_LSB (1U << 0) /* 1b */
+/* MBIST_EFUSE_REPAIR_ACK_STA (0x10006000+0x3D0) */
+#define MBIST_EFUSE_REPAIR_ACK_STA_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CON (0x10006000+0x400) */
+#define SPM_DVFS_CON_LSB (1U << 0) /* 4b */
+#define SPM_DVFS_ACK_LSB (1U << 30) /* 2b */
+/* SPM_MDBSI_CON (0x10006000+0x404) */
+#define SPM_MDBSI_CON_LSB (1U << 0) /* 3b */
+/* SPM_MAS_PAUSE_MASK_B (0x10006000+0x408) */
+#define SPM_MAS_PAUSE_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_MAS_PAUSE2_MASK_B (0x10006000+0x40C) */
+#define SPM_MAS_PAUSE2_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BSI_GEN (0x10006000+0x410) */
+#define SPM_BSI_START_LSB (1U << 0) /* 1b */
+/* SPM_BSI_EN_SR (0x10006000+0x414) */
+#define SPM_BSI_EN_SR_LSB (1U << 0) /* 32b */
+/* SPM_BSI_CLK_SR (0x10006000+0x418) */
+#define SPM_BSI_CLK_SR_LSB (1U << 0) /* 32b */
+/* SPM_BSI_D0_SR (0x10006000+0x41C) */
+#define SPM_BSI_D0_SR_LSB (1U << 0) /* 32b */
+/* SPM_BSI_D1_SR (0x10006000+0x420) */
+#define SPM_BSI_D1_SR_LSB (1U << 0) /* 32b */
+/* SPM_BSI_D2_SR (0x10006000+0x424) */
+#define SPM_BSI_D2_SR_LSB (1U << 0) /* 32b */
+/* SPM_AP_SEMA (0x10006000+0x428) */
+#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */
+/* SPM_SPM_SEMA (0x10006000+0x42C) */
+#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */
+/* AP_MDSRC_REQ (0x10006000+0x430) */
+#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */
+#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */
+#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */
+#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */
+#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */
+#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */
+/* SPM2MD_DVFS_CON (0x10006000+0x438) */
+#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */
+/* MD2SPM_DVFS_CON (0x10006000+0x43C) */
+#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */
+/* DRAMC_DPY_CLK_SW_CON_RSV (0x10006000+0x440) */
+#define SPM2DRAMC_SHUFFLE_START_LSB (1U << 0) /* 1b */
+#define SPM2DRAMC_SHUFFLE_SWITCH_LSB (1U << 1) /* 1b */
+#define SPM2DPY_DIV2_SYNC_LSB (1U << 2) /* 1b */
+#define SPM2DPY_1PLL_SWITCH_LSB (1U << 3) /* 1b */
+#define SPM2DPY_TEST_CK_MUX_LSB (1U << 4) /* 1b */
+#define SPM2DPY_ASYNC_MODE_LSB (1U << 5) /* 1b */
+#define SPM2TOP_ASYNC_MODE_LSB (1U << 6) /* 1b */
+/* DPY_LP_CON (0x10006000+0x444) */
+#define SC_DDRPHY_LP_SIGNALS_LSB (1U << 0) /* 3b */
+/* CPU_DVFS_REQ (0x10006000+0x448) */
+#define CPU_DVFS_REQ_LSB (1U << 0) /* 32b */
+/* SPM_PLL_CON (0x10006000+0x44C) */
+#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */
+#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */
+#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */
+#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */
+#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */
+#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */
+#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */
+#define SC_SSPMK_CK_OFF_LSB (1U << 17) /* 1b */
+/* SPM_EMI_BW_MODE (0x10006000+0x450) */
+#define EMI_BW_MODE_LSB (1U << 0) /* 1b */
+#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */
+#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */
+#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */
+/* AP2MD_PEER_WAKEUP (0x10006000+0x454) */
+#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */
+/* ULPOSC_CON (0x10006000+0x458) */
+#define ULPOSC_EN_LSB (1U << 0) /* 1b */
+#define ULPOSC_RST_LSB (1U << 1) /* 1b */
+#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */
+#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */
+/* SPM2MM_CON (0x10006000+0x45C) */
+#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */
+#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */
+#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */
+#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */
+#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */
+#define MM2SPM_FORCE_ULTRA_ACK_LSB (1U << 16) /* 1b */
+#define MM2SPM_DBL_OSTD_ACT_ACK_LSB (1U << 17) /* 1b */
+#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */
+#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */
+#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */
+/* DRAMC_DPY_CLK_SW_CON_SEL (0x10006000+0x460) */
+#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 0) /* 2b */
+#define SW_EMI_CLK_OFF_SEL_LSB (1U << 2) /* 2b */
+#define SW_DPY_MODE_SW_SEL_LSB (1U << 4) /* 2b */
+#define SW_DMSUS_OFF_SEL_LSB (1U << 6) /* 2b */
+#define SW_MEM_CK_OFF_SEL_LSB (1U << 8) /* 2b */
+#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 10) /* 2b */
+#define SW_DPY_DLL_EN_SEL_LSB (1U << 12) /* 2b */
+#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 14) /* 2b */
+#define SW_DPY_VREF_EN_SEL_LSB (1U << 16) /* 2b */
+#define SW_PHYPLL_EN_SEL_LSB (1U << 18) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 20) /* 2b */
+#define SEPERATE_PHY_PWR_SEL_LSB (1U << 23) /* 1b */
+#define SW_DMDRAMCSHU_ACK_SEL_LSB (1U << 24) /* 2b */
+#define SW_EMI_CLK_OFF_ACK_SEL_LSB (1U << 26) /* 2b */
+#define SW_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 28) /* 2b */
+#define SW_DRAMC_DFS_STA_SEL_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_CON (0x10006000+0x464) */
+#define SW_DR_GATE_RETRY_EN_LSB (1U << 0) /* 2b */
+#define SW_EMI_CLK_OFF_LSB (1U << 2) /* 2b */
+#define SW_DPY_MODE_SW_LSB (1U << 4) /* 2b */
+#define SW_DMSUS_OFF_LSB (1U << 6) /* 2b */
+#define SW_MEM_CK_OFF_LSB (1U << 8) /* 2b */
+#define SW_DPY_2ND_DLL_EN_LSB (1U << 10) /* 2b */
+#define SW_DPY_DLL_EN_LSB (1U << 12) /* 2b */
+#define SW_DPY_DLL_CK_EN_LSB (1U << 14) /* 2b */
+#define SW_DPY_VREF_EN_LSB (1U << 16) /* 2b */
+#define SW_PHYPLL_EN_LSB (1U << 18) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_LSB (1U << 20) /* 2b */
+#define SC_DR_SHU_EN_ACK_LSB (1U << 24) /* 2b */
+#define EMI_CLK_OFF_ACK_LSB (1U << 26) /* 2b */
+#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 28) /* 2b */
+#define SC_DRAMC_DFS_STA_LSB (1U << 30) /* 2b */
+/* SPM_S1_MODE_CH (0x10006000+0x468) */
+#define SPM_S1_MODE_CH_LSB (1U << 0) /* 2b */
+#define S1_EMI_CK_SWITCH_LSB (1U << 8) /* 2b */
+/* EMI_SELF_REFRESH_CH_STA (0x10006000+0x46C) */
+#define EMI_SELF_REFRESH_CH_LSB (1U << 0) /* 2b */
+/* DRAMC_DPY_CLK_SW_CON_SEL2 (0x10006000+0x470) */
+#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 0) /* 1b */
+#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 1) /* 1b */
+#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 2) /* 1b */
+#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 3) /* 1b */
+#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 4) /* 1b */
+#define SW_DR_SHU_EN_SEL_LSB (1U << 5) /* 1b */
+#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 6) /* 1b */
+#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 8) /* 2b */
+#define SW_SHU_RESTORE_SEL_LSB (1U << 10) /* 2b */
+#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 12) /* 2b */
+#define SW_DPHY_RXDLY_TRACK_EN_SEL_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 16) /* 2b */
+/* DRAMC_DPY_CLK_SW_CON2 (0x10006000+0x474) */
+#define SW_PHYPLL_SHU_EN_LSB (1U << 0) /* 1b */
+#define SW_PHYPLL2_SHU_EN_LSB (1U << 1) /* 1b */
+#define SW_PHYPLL_MODE_SW_LSB (1U << 2) /* 1b */
+#define SW_PHYPLL2_MODE_SW_LSB (1U << 3) /* 1b */
+#define SW_DR_SHORT_QUEUE_LSB (1U << 4) /* 1b */
+#define SW_DR_SHU_EN_LSB (1U << 5) /* 1b */
+#define SW_DR_SHU_LEVEL_LSB (1U << 6) /* 2b */
+#define SW_DPY_BCLK_ENABLE_LSB (1U << 8) /* 2b */
+#define SW_SHU_RESTORE_LSB (1U << 10) /* 2b */
+#define SW_DPHY_PRECAL_UP_LSB (1U << 12) /* 2b */
+#define SW_DPHY_RXDLY_TRACK_EN_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACKING_DIS_LSB (1U << 16) /* 2b */
+/* DRAMC_DMYRD_CON (0x10006000+0x478) */
+#define DRAMC_DMYRD_EN_CH0_LSB (1U << 0) /* 1b */
+#define DRAMC_DMYRD_INTV_SEL_CH0_LSB (1U << 1) /* 1b */
+#define DRAMC_DMYRD_EN_MOD_SEL_CH0_LSB (1U << 2) /* 1b */
+#define DRAMC_DMYRD_EN_CH1_LSB (1U << 8) /* 1b */
+#define DRAMC_DMYRD_INTV_SEL_CH1_LSB (1U << 9) /* 1b */
+#define DRAMC_DMYRD_EN_MOD_SEL_CH1_LSB (1U << 10) /* 1b */
+/* SPM_DRS_CON (0x10006000+0x47C) */
+#define SPM_DRS_DIS_REQ_CH0_LSB (1U << 0) /* 1b */
+#define SPM_DRS_DIS_REQ_CH1_LSB (1U << 1) /* 1b */
+#define SPM_DRS_DIS_ACK_CH0_LSB (1U << 8) /* 1b */
+#define SPM_DRS_DIS_ACK_CH1_LSB (1U << 9) /* 1b */
+/* SPM_SEMA_M0 (0x10006000+0x480) */
+#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M1 (0x10006000+0x484) */
+#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M2 (0x10006000+0x488) */
+#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M3 (0x10006000+0x48C) */
+#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M4 (0x10006000+0x490) */
+#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M5 (0x10006000+0x494) */
+#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M6 (0x10006000+0x498) */
+#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M7 (0x10006000+0x49C) */
+#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */
+/* SPM_MAS_PAUSE_MM_MASK_B (0x10006000+0x4A0) */
+#define SPM_MAS_PAUSE_MM_MASK_B_LSB (1U << 0) /* 16b */
+/* SPM_MAS_PAUSE_MCU_MASK_B (0x10006000+0x4A4) */
+#define SPM_MAS_PAUSE_MCU_MASK_B_LSB (1U << 0) /* 16b */
+/* SRAM_DREQ_ACK (0x10006000+0x4AC) */
+#define SRAM_DREQ_ACK_LSB (1U << 0) /* 16b */
+/* SRAM_DREQ_CON (0x10006000+0x4B0) */
+#define SRAM_DREQ_CON_LSB (1U << 0) /* 16b */
+/* SRAM_DREQ_CON_SET (0x10006000+0x4B4) */
+#define SRAM_DREQ_CON_SET_LSB (1U << 0) /* 16b */
+/* SRAM_DREQ_CON_CLR (0x10006000+0x4B8) */
+#define SRAM_DREQ_CON_CLR_LSB (1U << 0) /* 16b */
+/* SPM2EMI_ENTER_ULPM (0x10006000+0x4BC) */
+#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */
+/* SPM_SSPM_IRQ (0x10006000+0x4C0) */
+#define SPM_SSPM_IRQ_LSB (1U << 0) /* 1b */
+#define SPM_SSPM_IRQ_SEL_LSB (1U << 4) /* 1b */
+/* SPM2PMCU_INT (0x10006000+0x4C4) */
+#define SPM2PMCU_INT_LSB (1U << 0) /* 4b */
+/* SPM2PMCU_INT_SET (0x10006000+0x4C8) */
+#define SPM2PMCU_INT_SET_LSB (1U << 0) /* 4b */
+/* SPM2PMCU_INT_CLR (0x10006000+0x4CC) */
+#define SPM2PMCU_INT_CLR_LSB (1U << 0) /* 4b */
+/* SPM2PMCU_MAILBOX_0 (0x10006000+0x4D0) */
+#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_1 (0x10006000+0x4D4) */
+#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_2 (0x10006000+0x4D8) */
+#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_3 (0x10006000+0x4DC) */
+#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_INT (0x10006000+0x4E0) */
+#define PMCU2SPM_INT_LSB (1U << 0) /* 4b */
+/* PMCU2SPM_INT_SET (0x10006000+0x4E4) */
+#define PMCU2SPM_INT_SET_LSB (1U << 0) /* 4b */
+/* PMCU2SPM_INT_CLR (0x10006000+0x4E8) */
+#define PMCU2SPM_INT_CLR_LSB (1U << 0) /* 4b */
+/* PMCU2SPM_MAILBOX_0 (0x10006000+0x4EC) */
+#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_1 (0x10006000+0x4F0) */
+#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_2 (0x10006000+0x4F4) */
+#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_3 (0x10006000+0x4F8) */
+#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_CFG (0x10006000+0x4FC) */
+#define PMCU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */
+#define SPM_PMCU_MAILBOX_REQ_LSB (1U << 8) /* 1b */
+/* MP0_CPU0_IRQ_MASK (0x10006000+0x500) */
+#define MP0_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU0_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU1_IRQ_MASK (0x10006000+0x504) */
+#define MP0_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU1_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU2_IRQ_MASK (0x10006000+0x508) */
+#define MP0_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU2_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU3_IRQ_MASK (0x10006000+0x50C) */
+#define MP0_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU3_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU0_IRQ_MASK (0x10006000+0x510) */
+#define MP1_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU0_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU1_IRQ_MASK (0x10006000+0x514) */
+#define MP1_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU1_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU2_IRQ_MASK (0x10006000+0x518) */
+#define MP1_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU2_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU3_IRQ_MASK (0x10006000+0x51C) */
+#define MP1_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU3_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU0_WFI_EN (0x10006000+0x530) */
+#define MP0_CPU0_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU1_WFI_EN (0x10006000+0x534) */
+#define MP0_CPU1_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU2_WFI_EN (0x10006000+0x538) */
+#define MP0_CPU2_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU3_WFI_EN (0x10006000+0x53C) */
+#define MP0_CPU3_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP1_CPU0_WFI_EN (0x10006000+0x540) */
+#define MP1_CPU0_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP1_CPU1_WFI_EN (0x10006000+0x544) */
+#define MP1_CPU1_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP1_CPU2_WFI_EN (0x10006000+0x548) */
+#define MP1_CPU2_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP1_CPU3_WFI_EN (0x10006000+0x54C) */
+#define MP1_CPU3_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_L2CFLUSH (0x10006000+0x554) */
+#define MP0_L2CFLUSH_REQ_LSB (1U << 0) /* 1b */
+#define MP0_L2CFLUSH_DONE_LSB (1U << 4) /* 1b */
+/* MP1_L2CFLUSH (0x10006000+0x558) */
+#define MP1_L2CFLUSH_REQ_LSB (1U << 0) /* 1b */
+#define MP1_L2CFLUSH_DONE_LSB (1U << 4) /* 1b */
+/* CPU_PTPOD2_CON (0x10006000+0x560) */
+#define MP0_PTPOD2_FBB_EN_LSB (1U << 0) /* 1b */
+#define MP1_PTPOD2_FBB_EN_LSB (1U << 1) /* 1b */
+#define MP0_PTPOD2_SPARK_EN_LSB (1U << 2) /* 1b */
+#define MP1_PTPOD2_SPARK_EN_LSB (1U << 3) /* 1b */
+#define MP0_PTPOD2_FBB_ACK_LSB (1U << 4) /* 1b */
+#define MP1_PTPOD2_FBB_ACK_LSB (1U << 5) /* 1b */
+/* ROOT_CPUTOP_ADDR (0x10006000+0x570) */
+#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */
+/* ROOT_CORE_ADDR (0x10006000+0x574) */
+#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */
+/* CPU_SPARE_CON (0x10006000+0x580) */
+#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */
+/* CPU_SPARE_CON_SET (0x10006000+0x584) */
+#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+/* CPU_SPARE_CON_CLR (0x10006000+0x588) */
+#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_0 (0x10006000+0x5D0) */
+#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_1 (0x10006000+0x5D4) */
+#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_2 (0x10006000+0x5D8) */
+#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_3 (0x10006000+0x5DC) */
+#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* SW2SPM_INT (0x10006000+0x5E0) */
+#define SW2SPM_INT_LSB (1U << 0) /* 4b */
+/* SW2SPM_INT_SET (0x10006000+0x5E4) */
+#define SW2SPM_INT_SET_LSB (1U << 0) /* 4b */
+/* SW2SPM_INT_CLR (0x10006000+0x5E8) */
+#define SW2SPM_INT_CLR_LSB (1U << 0) /* 4b */
+/* SW2SPM_MAILBOX_0 (0x10006000+0x5EC) */
+#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_1 (0x10006000+0x5F0) */
+#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_2 (0x10006000+0x5F4) */
+#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_3 (0x10006000+0x5F8) */
+#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* SW2SPM_CFG (0x10006000+0x5FC) */
+#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */
+#define SPM_SW_MAILBOX_REQ_LSB (1U << 8) /* 1b */
+/* SPM_SW_FLAG (0x10006000+0x600) */
+#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */
+/* SPM_SW_DEBUG (0x10006000+0x604) */
+#define SPM_SW_DEBUG_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_0 (0x10006000+0x608) */
+#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_1 (0x10006000+0x60C) */
+#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_2 (0x10006000+0x610) */
+#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_3 (0x10006000+0x614) */
+#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_4 (0x10006000+0x618) */
+#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_5 (0x10006000+0x61C) */
+#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */
+/* SPM_RSV_CON (0x10006000+0x620) */
+#define SPM_RSV_CON_LSB (1U << 0) /* 16b */
+/* SPM_RSV_STA (0x10006000+0x624) */
+#define SPM_RSV_STA_LSB (1U << 0) /* 16b */
+/* SPM_RSV_CON1 (0x10006000+0x628) */
+#define SPM_RSV_CON1_LSB (1U << 0) /* 16b */
+/* SPM_RSV_STA1 (0x10006000+0x62C) */
+#define SPM_RSV_STA1_LSB (1U << 0) /* 16b */
+/* SPM_PASR_DPD_0 (0x10006000+0x630) */
+#define SPM_PASR_DPD_0_LSB (1U << 0) /* 32b */
+/* SPM_PASR_DPD_1 (0x10006000+0x634) */
+#define SPM_PASR_DPD_1_LSB (1U << 0) /* 32b */
+/* SPM_PASR_DPD_2 (0x10006000+0x638) */
+#define SPM_PASR_DPD_2_LSB (1U << 0) /* 32b */
+/* SPM_PASR_DPD_3 (0x10006000+0x63C) */
+#define SPM_PASR_DPD_3_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON (0x10006000+0x640) */
+#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON_SET (0x10006000+0x644) */
+#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON_CLR (0x10006000+0x648) */
+#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_6 (0x10006000+0x64C) */
+#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_7 (0x10006000+0x650) */
+#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_8 (0x10006000+0x654) */
+#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_9 (0x10006000+0x658) */
+#define SPM_SW_RSV_9_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_10 (0x10006000+0x65C) */
+#define SPM_SW_RSV_10_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_18 (0x10006000+0x67C) */
+#define SPM_SW_RSV_18_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_19 (0x10006000+0x680) */
+#define SPM_SW_RSV_19_LSB (1U << 0) /* 32b */
+/* DVFSRC_EVENT_MASK_CON (0x10006000+0x690) */
+#define DVFSRC_EVENT_MASK_B_LSB (1U << 0) /* 16b */
+#define DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 16) /* 1b */
+/* DVFSRC_EVENT_FORCE_ON (0x10006000+0x694) */
+#define DVFSRC_EVENT_FORCE_ON_LSB (1U << 0) /* 16b */
+#define DVFSRC_EVENT_TRIGGER_FORCE_ON_LSB (1U << 16) /* 1b */
+/* DVFSRC_EVENT_SEL (0x10006000+0x698) */
+#define DVFSRC_EVENT_SEL_LSB (1U << 0) /* 16b */
+/* SPM_DVFS_EVENT_STA (0x10006000+0x69C) */
+#define SPM_DVFS_EVENT_STA_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_EVENT_STA1 (0x10006000+0x6A0) */
+#define SPM_DVFS_EVENT_STA1_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_LEVEL (0x10006000+0x6A4) */
+#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 16b */
+/* DVFS_ABORT_STA (0x10006000+0x6A8) */
+#define RC2SPM_EVENT_ABORT_D2T_LSB (1U << 0) /* 16b */
+#define RC2SPM_EVENT_ABORT_MASK_OR_LSB (1U << 16) /* 1b */
+/* DVFS_ABORT_OTHERS_MASK (0x10006000+0x6AC) */
+#define DVFS_ABORT_OTHERS_MASK_B_LSB (1U << 0) /* 16b */
+/* SPM_DFS_LEVEL (0x10006000+0x6B0) */
+#define SPM_DFS_LEVEL_LSB (1U << 0) /* 4b */
+/* SPM_DVS_LEVEL (0x10006000+0x6B4) */
+#define SPM_VCORE_LEVEL_LSB (1U << 0) /* 8b */
+#define SPM_VSRAM_LEVEL_LSB (1U << 8) /* 8b */
+#define SPM_VMODEM_LEVEL_LSB (1U << 16) /* 8b */
+/* SPM_DVFS_MISC (0x10006000+0x6B8) */
+#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */
+#define MSDC_DVFS_LEVEL_LSB (1U << 1) /* 4b */
+#define SDIO_READY_TO_SPM_LSB (1U << 7) /* 1b */
+#define MD2AP_CENTRAL_BUCK_GEAR_REQ_D2T_LSB (1U << 8) /* 1b */
+#define MD2AP_CENTRAL_BUCK_GEAR_RDY_D2T_LSB (1U << 9) /* 1b */
+/* SPARE_SRC_REQ_MASK (0x10006000+0x6C0) */
+#define SPARE1_DDREN_MASK_B_LSB (1U << 0) /* 1b */
+#define SPARE1_APSRC_REQ_MASK_B_LSB (1U << 1) /* 1b */
+#define SPARE1_VRF18_REQ_MASK_B_LSB (1U << 2) /* 1b */
+#define SPARE1_INFRA_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define SPARE1_SRCCLKENA_MASK_B_LSB (1U << 4) /* 1b */
+#define SPARE1_DDREN_2_MASK_B_LSB (1U << 5) /* 1b */
+#define SPARE2_DDREN_MASK_B_LSB (1U << 8) /* 1b */
+#define SPARE2_APSRC_REQ_MASK_B_LSB (1U << 9) /* 1b */
+#define SPARE2_VRF18_REQ_MASK_B_LSB (1U << 10) /* 1b */
+#define SPARE2_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */
+#define SPARE2_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */
+#define SPARE2_DDREN_2_MASK_B_LSB (1U << 13) /* 1b */
+/* SCP_VCORE_LEVEL (0x10006000+0x6C4) */
+#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 8b */
+/* SC_MM_CK_SEL_CON (0x10006000+0x6C8) */
+#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */
+#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */
+/* SPARE_ACK_STA (0x10006000+0x6F0) */
+#define SPARE_ACK_SYNC_LSB (1U << 0) /* 32b */
+/* SPARE_ACK_MASK (0x10006000+0x6F4) */
+#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CON1 (0x10006000+0x700) */
+#define SPM_DVFS_CON1_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CON1_STA (0x10006000+0x704) */
+#define SPM_DVFS_CON1_STA_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD0 (0x10006000+0x710) */
+#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD1 (0x10006000+0x714) */
+#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD2 (0x10006000+0x718) */
+#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD3 (0x10006000+0x71C) */
+#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD4 (0x10006000+0x720) */
+#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD5 (0x10006000+0x724) */
+#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD6 (0x10006000+0x728) */
+#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD7 (0x10006000+0x72C) */
+#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD8 (0x10006000+0x730) */
+#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD9 (0x10006000+0x734) */
+#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD10 (0x10006000+0x738) */
+#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD11 (0x10006000+0x73C) */
+#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD12 (0x10006000+0x740) */
+#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD13 (0x10006000+0x744) */
+#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD14 (0x10006000+0x748) */
+#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD15 (0x10006000+0x74C) */
+#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE0_FIX (0x10006000+0x780) */
+#define WDT_LATCH_SPARE0_FIX_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE1_FIX (0x10006000+0x784) */
+#define WDT_LATCH_SPARE1_FIX_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE2_FIX (0x10006000+0x788) */
+#define WDT_LATCH_SPARE2_FIX_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE3_FIX (0x10006000+0x78C) */
+#define WDT_LATCH_SPARE3_FIX_LSB (1U << 0) /* 32b */
+/* SPARE_ACK_IN_FIX (0x10006000+0x790) */
+#define SPARE_ACK_IN_FIX_LSB (1U << 0) /* 32b */
+/* DCHA_LATCH_RSV0_FIX (0x10006000+0x794) */
+#define DCHA_LATCH_RSV0_FIX_LSB (1U << 0) /* 32b */
+/* DCHB_LATCH_RSV0_FIX (0x10006000+0x798) */
+#define DCHB_LATCH_RSV0_FIX_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_0 (0x10006000+0x800) */
+#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_1 (0x10006000+0x804) */
+#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_2 (0x10006000+0x808) */
+#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_3 (0x10006000+0x80C) */
+#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_4 (0x10006000+0x810) */
+#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_5 (0x10006000+0x814) */
+#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_6 (0x10006000+0x818) */
+#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_7 (0x10006000+0x81C) */
+#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_8 (0x10006000+0x820) */
+#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_9 (0x10006000+0x824) */
+#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE0 (0x10006000+0x828) */
+#define WDT_LATCH_SPARE0_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE1 (0x10006000+0x82C) */
+#define WDT_LATCH_SPARE1_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE2 (0x10006000+0x830) */
+#define WDT_LATCH_SPARE2_LSB (1U << 0) /* 32b */
+/* WDT_LATCH_SPARE3 (0x10006000+0x834) */
+#define WDT_LATCH_SPARE3_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_10 (0x10006000+0x838) */
+#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_11 (0x10006000+0x83C) */
+#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_0 (0x10006000+0x840) */
+#define DCHA_GATING_LATCH_0_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_1 (0x10006000+0x844) */
+#define DCHA_GATING_LATCH_1_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_2 (0x10006000+0x848) */
+#define DCHA_GATING_LATCH_2_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_3 (0x10006000+0x84C) */
+#define DCHA_GATING_LATCH_3_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_4 (0x10006000+0x850) */
+#define DCHA_GATING_LATCH_4_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_5 (0x10006000+0x854) */
+#define DCHA_GATING_LATCH_5_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_6 (0x10006000+0x858) */
+#define DCHA_GATING_LATCH_6_LSB (1U << 0) /* 32b */
+/* DCHA_GATING_LATCH_7 (0x10006000+0x85C) */
+#define DCHA_GATING_LATCH_7_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_0 (0x10006000+0x860) */
+#define DCHB_GATING_LATCH_0_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_1 (0x10006000+0x864) */
+#define DCHB_GATING_LATCH_1_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_2 (0x10006000+0x868) */
+#define DCHB_GATING_LATCH_2_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_3 (0x10006000+0x86C) */
+#define DCHB_GATING_LATCH_3_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_4 (0x10006000+0x870) */
+#define DCHB_GATING_LATCH_4_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_5 (0x10006000+0x874) */
+#define DCHB_GATING_LATCH_5_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_6 (0x10006000+0x878) */
+#define DCHB_GATING_LATCH_6_LSB (1U << 0) /* 32b */
+/* DCHB_GATING_LATCH_7 (0x10006000+0x87C) */
+#define DCHB_GATING_LATCH_7_LSB (1U << 0) /* 32b */
+/* DCHA_LATCH_RSV0 (0x10006000+0x880) */
+#define DCHA_LATCH_RSV0_LSB (1U << 0) /* 32b */
+/* DCHB_LATCH_RSV0 (0x10006000+0x884) */
+#define DCHB_LATCH_RSV0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_12 (0x10006000+0x888) */
+#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_13 (0x10006000+0x88C) */
+#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */
+/* SPM_PC_TRACE_CON (0x10006000+0x8C0) */
+#define SPM_PC_TRACE_OFFSET_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE_HW_EN_LSB (1U << 16) /* 1b */
+#define SPM_PC_TRACE_SW_LSB (1U << 17) /* 1b */
+/* SPM_PC_TRACE_G0 (0x10006000+0x8C4) */
+#define SPM_PC_TRACE0_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE1_LSB (1U << 16) /* 12b */
+/* SPM_PC_TRACE_G1 (0x10006000+0x8C8) */
+#define SPM_PC_TRACE2_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE3_LSB (1U << 16) /* 12b */
+/* SPM_PC_TRACE_G2 (0x10006000+0x8CC) */
+#define SPM_PC_TRACE4_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE5_LSB (1U << 16) /* 12b */
+/* SPM_PC_TRACE_G3 (0x10006000+0x8D0) */
+#define SPM_PC_TRACE6_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE7_LSB (1U << 16) /* 12b */
+/* SPM_PC_TRACE_G4 (0x10006000+0x8D4) */
+#define SPM_PC_TRACE8_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE9_LSB (1U << 16) /* 12b */
+/* SPM_PC_TRACE_G5 (0x10006000+0x8D8) */
+#define SPM_PC_TRACE10_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE11_LSB (1U << 16) /* 12b */
+/* SPM_PC_TRACE_G6 (0x10006000+0x8DC) */
+#define SPM_PC_TRACE12_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE13_LSB (1U << 16) /* 12b */
+/* SPM_PC_TRACE_G7 (0x10006000+0x8E0) */
+#define SPM_PC_TRACE14_LSB (1U << 0) /* 12b */
+#define SPM_PC_TRACE15_LSB (1U << 16) /* 12b */
+/* SPM_ACK_CHK_CON (0x10006000+0x900) */
+#define SPM_ACK_CHK_SW_EN_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_LSB (1U << 15) /* 1b */
+#define SPM_ACK_CHK_SWINT_EN_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_PC (0x10006000+0x904) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL (0x10006000+0x908) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER (0x10006000+0x90C) */
+#define SPM_ACK_CHK_TIMER_VAL_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA (0x10006000+0x910) */
+#define SPM_ACK_CHK_STA_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_LATCH (0x10006000+0x914) */
+#define SPM_ACK_CHK_LATCH_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON2 (0x10006000+0x920) */
+#define SPM_ACK_CHK_SW_EN2_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL2_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER2_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ2_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN2_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN2_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN2_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN2_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN2_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE2_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL2_LSB (1U << 15) /* 1b */
+#define SPM_ACK_CHK_SWINT_EN2_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_PC2 (0x10006000+0x924) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL2_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL2 (0x10006000+0x928) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL2_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL2_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL2_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL2_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER2 (0x10006000+0x92C) */
+#define SPM_ACK_CHK_TIMER_VAL2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER2_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA2 (0x10006000+0x930) */
+#define SPM_ACK_CHK_STA2_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_LATCH2 (0x10006000+0x934) */
+#define SPM_ACK_CHK_LATCH2_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON3 (0x10006000+0x940) */
+#define SPM_ACK_CHK_SW_EN3_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL3_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER3_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ3_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN3_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN3_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN3_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN3_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN3_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE3_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL3_LSB (1U << 15) /* 1b */
+#define SPM_ACK_CHK_SWINT_EN3_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_PC3 (0x10006000+0x944) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL3_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL3 (0x10006000+0x948) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL3_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL3_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL3_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL3_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER3 (0x10006000+0x94C) */
+#define SPM_ACK_CHK_TIMER_VAL3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER3_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA3 (0x10006000+0x950) */
+#define SPM_ACK_CHK_STA3_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_LATCH3 (0x10006000+0x954) */
+#define SPM_ACK_CHK_LATCH3_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON4 (0x10006000+0x960) */
+#define SPM_ACK_CHK_SW_EN4_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL4_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER4_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ4_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN4_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN4_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN4_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN4_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN4_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE4_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL4_LSB (1U << 15) /* 1b */
+#define SPM_ACK_CHK_SWINT_EN4_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_PC4 (0x10006000+0x964) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL4_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL4_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL4 (0x10006000+0x968) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL4_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL4_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL4_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL4_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER4 (0x10006000+0x96C) */
+#define SPM_ACK_CHK_TIMER_VAL4_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER4_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA4 (0x10006000+0x970) */
+#define SPM_ACK_CHK_STA4_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_LATCH4 (0x10006000+0x974) */
+#define SPM_ACK_CHK_LATCH4_LSB (1U << 0) /* 32b */
+
+/* --- SPM Flag Define --- */
+#define SPM_FLAG_DIS_CPU_PDN (1U << 0)
+#define SPM_FLAG_DIS_INFRA_PDN (1U << 1)
+#define SPM_FLAG_DIS_DDRPHY_PDN (1U << 2)
+#define SPM_FLAG_DIS_VCORE_DVS (1U << 3)
+#define SPM_FLAG_DIS_VCORE_DFS (1U << 4)
+#define SPM_FLAG_DIS_COMMON_SCENARIO (1U << 5)
+#define SPM_FLAG_DIS_BUS_CLOCK_OFF (1U << 6)
+#define SPM_FLAG_DIS_ATF_ABORT (1U << 7)
+#define SPM_FLAG_KEEP_CSYSPWRUPACK_HIGH (1U << 8)
+#define SPM_FLAG_DIS_VPROC_VSRAM_DVS (1U << 9)
+#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10)
+#define SPM_FLAG_EN_MET_DEBUG_USAGE (1U << 11)
+#define SPM_FLAG_SODI_CG_MODE (1U << 12)
+#define SPM_FLAG_SODI_NO_EVENT (1U << 13)
+#define SPM_FLAG_ENABLE_SODI3 (1U << 14)
+#define SPM_FLAG_DISABLE_MMSYS_DVFS (1U << 15)
+#define SPM_FLAG_DIS_SYSRAM_SLEEP (1U << 16)
+#define SPM_FLAG_DIS_SSPM_SRAM_SLEEP (1U << 17)
+#define SPM_FLAG_DIS_VMODEM_DVS (1U << 18)
+#define SPM_FLAG_SUSPEND_OPTION (1U << 19)
+#define SPM_FLAG_DEEPIDLE_OPTION (1U << 20)
+#define SPM_FLAG_SODI_OPTION (1U << 21)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT22 (1U << 22)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT23 (1U << 23)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT24 (1U << 24)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT25 (1U << 25)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT26 (1U << 26)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT27 (1U << 27)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT28 (1U << 28)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT29 (1U << 29)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT30 (1U << 30)
+#define SPM_FLAG_SPM_FLAG_DONT_TOUCH_BIT31 (1U << 31)
+
+/* --- SPM Flag1 Define --- */
+#define SPM_FLAG1_RESERVED_BIT0 (1U << 0)
+#define SPM_FLAG1_ENABLE_CPU_DORMANT (1U << 1)
+#define SPM_FLAG1_ENABLE_CPU_SLEEP_VOLT (1U << 2)
+#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 3)
+#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 4)
+#define SPM_FLAG1_VCORE_LP_0P7V (1U << 5)
+#define SPM_FLAG1_DISABLE_MCDSR (1U << 6)
+#define SPM_FLAG1_DISABLE_NO_RESUME (1U << 7)
+#define SPM_FLAG1_BIG_BUCK_OFF_ENABLE (1U << 8)
+#define SPM_FLAG1_BIG_BUCK_ON_ENABLE (1U << 9)
+#define SPM_FLAG1_RESERVED_BIT10 (1U << 10)
+#define SPM_FLAG1_RESERVED_BIT11 (1U << 11)
+#define SPM_FLAG1_RESERVED_BIT12 (1U << 12)
+#define SPM_FLAG1_RESERVED_BIT13 (1U << 13)
+#define SPM_FLAG1_RESERVED_BIT14 (1U << 14)
+#define SPM_FLAG1_DIS_ARMPLL_OFF (1U << 15)
+#define SPM_FLAG1_DIS_AXI_BUS_TO_26M (1U << 16)
+#define SPM_FLAG1_DIS_IMP_DIS (1U << 17)
+#define SPM_FLAG1_DIS_IMP_COPY (1U << 18)
+#define SPM_FLAG1_DIS_EMI_TOGGLE_WORKAROUND (1U << 19)
+#define SPM_FLAG1_DIS_DRAM_ENTER_SREF (1U << 20)
+#define SPM_FLAG1_DIS_DRAM_DLL_OFF (1U << 21)
+#define SPM_FLAG1_DIS_PHYPLL_OFF (1U << 22)
+#define SPM_FLAG1_DIS_MPLL_OFF (1U << 23)
+#define SPM_FLAG1_DIS_SYSPLL_OFF (1U << 24)
+#define SPM_FLAG1_DIS_TOP_AXI_CLK_OFF (1U << 25)
+#define SPM_FLAG1_DIS_PCM_26M_SWITCH (1U << 26)
+#define SPM_FLAG1_DIS_CKSQ_OFF (1U << 27)
+#define SPM_FLAG1_DIS_SRCVOLTEN_OFF (1U << 28)
+#define SPM_FLAG1_DIS_CHB_CG_FREE_EN (1U << 29)
+#define SPM_FLAG1_DIS_CHA_DCM_RES (1U << 30)
+#define SPM_FLAG1_DIS_SW_MR4 (1U << 31)
+
+/* --- SPM DEBUG Define --- */
+#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0)
+#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1)
+#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2)
+#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3)
+#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4)
+#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5)
+#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6)
+#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7)
+#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8)
+#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9)
+#define SPM_DBG_DEBUG_IDX_NFC_CKBUF_ON (1U << 10)
+#define SPM_DBG_DEBUG_IDX_NFC_CKBUF_OFF (1U << 11)
+#define SPM_DBG_DEBUG_IDX_CPU_PDN (1U << 12)
+#define SPM_DBG_DEBUG_IDX_DPD (1U << 13)
+#define SPM_DBG_DEBUG_IDX_CONN_CKBUF_ON (1U << 14)
+#define SPM_DBG_DEBUG_IDX_CONN_CKBUF_OFF (1U << 15)
+#define SPM_DBG_DEBUG_IDX_VCORE_DVFS_START (1U << 16)
+#define SPM_DBG_DEBUG_IDX_DDREN2_WAKE (1U << 17)
+#define SPM_DBG_DEBUG_IDX_DDREN2_SLEEP (1U << 18)
+#define SPM_DBG_DEBUG_IDX_SSPM_WFI (1U << 19)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 20)
+#define SPM_DBG_RESERVED_BIT21 (1U << 21)
+#define SPM_DBG_RESERVED_BIT22 (1U << 22)
+#define SPM_DBG_RESERVED_BIT23 (1U << 23)
+#define SPM_DBG_RESERVED_BIT24 (1U << 24)
+#define SPM_DBG_RESERVED_BIT25 (1U << 25)
+#define SPM_DBG_RESERVED_BIT26 (1U << 26)
+#define SPM_DBG_SODI1_FLAG (1U << 27)
+#define SPM_DBG_SODI3_FLAG (1U << 28)
+#define SPM_DBG_VCORE_DVFS_FLAG (1U << 29)
+#define SPM_DBG_DEEPIDLE_FLAG (1U << 30)
+#define SPM_DBG_SUSPEND_FLAG (1U << 31)
+
+/* --- SPM DEBUG1 Define --- */
+#define SPM_DBG1_DRAM_SREF_ACK_TO (1U << 0)
+#define SPM_DBG1_PWRAP_SLEEP_ACK_TO (1U << 1)
+#define SPM_DBG1_PWRAP_SPI_ACK_TO (1U << 2)
+#define SPM_DBG1_DRAM_GATE_ERR_DDREN_WAKEUP (1U << 3)
+#define SPM_DBG1_DRAM_GATE_ERR_LEAVE_LP_SCN (1U << 4)
+#define SPM_DBG1_RESERVED_BIT5 (1U << 5)
+#define SPM_DBG1_RESERVED_BIT6 (1U << 6)
+#define SPM_DBG1_RESERVED_BIT7 (1U << 7)
+#define SPM_DBG1_RESERVED_BIT8 (1U << 8)
+#define SPM_DBG1_RESERVED_BIT9 (1U << 9)
+#define SPM_DBG1_RESERVED_BIT10 (1U << 10)
+#define SPM_DBG1_RESERVED_BIT11 (1U << 11)
+#define SPM_DBG1_RESERVED_BIT12 (1U << 12)
+#define SPM_DBG1_RESERVED_BIT13 (1U << 13)
+#define SPM_DBG1_RESERVED_BIT14 (1U << 14)
+#define SPM_DBG1_RESERVED_BIT15 (1U << 15)
+#define SPM_DBG1_RESERVED_BIT16 (1U << 16)
+#define SPM_DBG1_RESERVED_BIT17 (1U << 17)
+#define SPM_DBG1_RESERVED_BIT18 (1U << 18)
+#define SPM_DBG1_RESERVED_BIT19 (1U << 19)
+#define SPM_DBG1_RESERVED_BIT20 (1U << 20)
+#define SPM_DBG1_RESERVED_BIT21 (1U << 21)
+#define SPM_DBG1_RESERVED_BIT22 (1U << 22)
+#define SPM_DBG1_RESERVED_BIT23 (1U << 23)
+#define SPM_DBG1_RESERVED_BIT24 (1U << 24)
+#define SPM_DBG1_RESERVED_BIT25 (1U << 25)
+#define SPM_DBG1_RESERVED_BIT26 (1U << 26)
+#define SPM_DBG1_RESERVED_BIT27 (1U << 27)
+#define SPM_DBG1_RESERVED_BIT28 (1U << 28)
+#define SPM_DBG1_RESERVED_BIT29 (1U << 29)
+#define SPM_DBG1_RESERVED_BIT30 (1U << 30)
+#define SPM_DBG1_RESERVED_BIT31 (1U << 31)
+
+/* --- R0 Define --- */
+#define R0_SC_26M_CK_OFF (1U << 0)
+#define R0_BIT1 (1U << 1)
+#define R0_SC_MEM_CK_OFF (1U << 2)
+#define R0_SC_AXI_CK_OFF (1U << 3)
+#define R0_SC_DR_GATE_RETRY_EN_PCM (1U << 4)
+#define R0_SC_MD26M_CK_OFF (1U << 5)
+#define R0_SC_DPY_MODE_SW_PCM (1U << 6)
+#define R0_SC_DMSUS_OFF_PCM (1U << 7)
+#define R0_SC_DPY_2ND_DLL_EN_PCM (1U << 8)
+#define R0_BIT9 (1U << 9)
+#define R0_SC_MPLLOUT_OFF (1U << 10)
+#define R0_SC_TX_TRACKING_DIS (1U << 11)
+#define R0_SC_DPY_DLL_EN_PCM (1U << 12)
+#define R0_SC_DPY_DLL_CK_EN_PCM (1U << 13)
+#define R0_SC_DPY_VREF_EN_PCM (1U << 14)
+#define R0_SC_PHYPLL_EN_PCM (1U << 15)
+#define R0_SC_DDRPHY_FB_CK_EN_PCM (1U << 16)
+#define R0_SC_DPY_BCLK_ENABLE (1U << 17)
+#define R0_SC_MPLL_OFF (1U << 18)
+#define R0_SC_SHU_RESTORE (1U << 19)
+#define R0_SC_CKSQ0_OFF (1U << 20)
+#define R0_SC_CKSQ1_OFF (1U << 21)
+#define R0_SC_DR_SHU_EN_PCM (1U << 22)
+#define R0_SC_DPHY_PRECAL_UP (1U << 23)
+#define R0_SC_MPLL_S_OFF (1U << 24)
+#define R0_SC_DPHY_RXDLY_TRACK_EN (1U << 25)
+#define R0_SC_PHYPLL_SHU_EN_PCM (1U << 26)
+#define R0_SC_PHYPLL2_SHU_EN_PCM (1U << 27)
+#define R0_SC_PHYPLL_MODE_SW_PCM (1U << 28)
+#define R0_SC_PHYPLL2_MODE_SW_PCM (1U << 29)
+#define R0_SC_DR_SHU_LEVEL_PCM0 (1U << 30)
+#define R0_SC_DR_SHU_LEVEL_PCM1 (1U << 31)
+
+/* --- R7 Define --- */
+#define R7_PWRAP_SLEEP_REQ (1U << 0)
+#define R7_EMI_CLK_OFF_REQ (1U << 1)
+#define R7_TOP_MAS_PAU_REQ (1U << 2)
+#define R7_SPM2CKSYS_MEM_CK_MUX_UPDATE (1U << 3)
+#define R7_PCM_CK_SEL0 (1U << 4)
+#define R7_PCM_CK_SEL1 (1U << 5)
+#define R7_SPM2RC_DVS_DONE (1U << 6)
+#define R7_FREQH_PAUSE_MPLL (1U << 7)
+#define R7_SC_26M_CK_SEL (1U << 8)
+#define R7_PCM_TIMER_SET (1U << 9)
+#define R7_PCM_TIMER_CLR (1U << 10)
+#define R7_SRCVOLTEN (1U << 11)
+#define R7_CSYSPWRUPACK (1U << 12)
+#define R7_IM_SLEEP_ENABLE (1U << 13)
+#define R7_SRCCLKENO_0 (1U << 14)
+#define R7_SYSRST (1U << 15)
+#define R7_MD_APSRC_ACK (1U << 16)
+#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17)
+#define R7_SC_AXI_DCM_DIS (1U << 18)
+#define R7_FREQH_PAUSE_MAIN (1U << 19)
+#define R7_FREQH_PAUSE_MEM (1U << 20)
+#define R7_SRCCLKENO_1 (1U << 21)
+#define R7_WDT_KICK_P (1U << 22)
+#define R7_SPM2RC_EVENT_ABORT_ACK (1U << 23)
+#define R7_WAKEUP_EXT_W_SEL (1U << 24)
+#define R7_WAKEUP_EXT_R_SEL (1U << 25)
+#define R7_PMIC_IRQ_REQ_EN (1U << 26)
+#define R7_FORCE_26M_WAKE (1U << 27)
+#define R7_FORCE_APSRC_WAKE (1U << 28)
+#define R7_FORCE_INFRA_WAKE (1U << 29)
+#define R7_FORCE_VRF18_WAKE (1U << 30)
+#define R7_SC_DR_SHORT_QUEUE_PCM (1U << 31)
+
+/* --- R12 Define --- */
+#define R12_PCM_TIMER (1U << 0)
+#define R12_SSPM_WDT_EVENT_B (1U << 1)
+#define R12_KP_IRQ_B (1U << 2)
+#define R12_APWDT_EVENT_B (1U << 3)
+#define R12_APXGPT1_EVENT_B (1U << 4)
+#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5)
+#define R12_EINT_EVENT_B (1U << 6)
+#define R12_CONN_WDT_IRQ_B (1U << 7)
+#define R12_CCIF0_EVENT_B (1U << 8)
+#define R12_LOWBATTERY_IRQ_B (1U << 9)
+#define R12_SSPM_SPM_IRQ_B (1U << 10)
+#define R12_SCP_SPM_IRQ_B (1U << 11)
+#define R12_SCP_WDT_EVENT_B (1U << 12)
+#define R12_PCM_WDT_WAKEUP_B (1U << 13)
+#define R12_USB_CDSC_B (1U << 14)
+#define R12_USB_POWERDWN_B (1U << 15)
+#define R12_SYS_TIMER_EVENT_B (1U << 16)
+#define R12_EINT_EVENT_SECURE_B (1U << 17)
+#define R12_CCIF1_EVENT_B (1U << 18)
+#define R12_UART0_IRQ_B (1U << 19)
+#define R12_AFE_IRQ_MCU_B (1U << 20)
+#define R12_THERM_CTRL_EVENT_B (1U << 21)
+#define R12_SYS_CIRQ_IRQ_B (1U << 22)
+#define R12_MD2AP_PEER_EVENT_B (1U << 23)
+#define R12_CSYSPWREQ_B (1U << 24)
+#define R12_MD1_WDT_B (1U << 25)
+#define R12_CLDMA_EVENT_B (1U << 26)
+#define R12_SEJ_WDT_GPT_B (1U << 27)
+#define R12_ALL_SSPM_WAKEUP_B (1U << 28)
+#define R12_CPU_IRQ_B (1U << 29)
+#define R12_CPU_WFI_AND_B (1U << 30)
+#define R12_MCUSYS_IDLE_TO_EMI_ALL_B (1U << 31)
+
+/* --- R12ext Define --- */
+#define R12EXT_26M_WAKE (1U << 0)
+#define R12EXT_26M_SLEEP (1U << 1)
+#define R12EXT_INFRA_WAKE (1U << 2)
+#define R12EXT_INFRA_SLEEP (1U << 3)
+#define R12EXT_APSRC_WAKE (1U << 4)
+#define R12EXT_APSRC_SLEEP (1U << 5)
+#define R12EXT_VRF18_WAKE (1U << 6)
+#define R12EXT_VRF18_SLEEP (1U << 7)
+#define R12EXT_DVFS_ALL_STATE (1U << 8)
+#define R12EXT_DVFS_LEVEL_STATE0 (1U << 9)
+#define R12EXT_DVFS_LEVEL_STATE1 (1U << 10)
+#define R12EXT_DVFS_LEVEL_STATE2 (1U << 11)
+#define R12EXT_DDREN_WAKE (1U << 12)
+#define R12EXT_DDREN_SLEEP (1U << 13)
+#define R12EXT_NFC_CLK_BUF_WAKE (1U << 14)
+#define R12EXT_NFC_CLK_BUF_SLEEP (1U << 15)
+#define R12EXT_CONN_CLK_BUF_WAKE (1U << 16)
+#define R12EXT_CONN_CLK_BUF_SLEEP (1U << 17)
+#define R12EXT_MD_DVFS_ERROR_STATUS (1U << 18)
+#define R12EXT_DVFS_LEVEL_STATE3 (1U << 19)
+#define R12EXT_DVFS_LEVEL_STATE4 (1U << 20)
+#define R12EXT_DVFS_LEVEL_STATE5 (1U << 21)
+#define R12EXT_DVFS_LEVEL_STATE6 (1U << 22)
+#define R12EXT_DVFS_LEVEL_STATE7 (1U << 23)
+#define R12EXT_DVFS_LEVEL_STATE8 (1U << 24)
+#define R12EXT_DVFS_LEVEL_STATE9 (1U << 25)
+#define R12EXT_DVFS_LEVEL_STATE_G0 (1U << 26)
+#define R12EXT_DVFS_LEVEL_STATE_G1 (1U << 27)
+#define R12EXT_DVFS_LEVEL_STATE_G2 (1U << 28)
+#define R12EXT_DVFS_LEVEL_STATE_G3 (1U << 29)
+#define R12EXT_HYBRID_DDREN_SLEEP (1U << 30)
+#define R12EXT_HYBRID_DDREN_WAKE (1U << 31)
+
+/* --- R13 Define --- */
+#define R13_EXT_SRCCLKENI_0 (1U << 0)
+#define R13_EXT_SRCCLKENI_1 (1U << 1)
+#define R13_MD1_SRCCLKENA (1U << 2)
+#define R13_MD1_APSRC_REQ (1U << 3)
+#define R13_CONN_DDR_EN (1U << 4)
+#define R13_MD2_SRCCLKENA (1U << 5)
+#define R13_SSPM_SRCCLKENA (1U << 6)
+#define R13_SSPM_APSRC_REQ (1U << 7)
+#define R13_MD_STATE (1U << 8)
+#define R13_EMI_CLK_OFF_2_ACK (1U << 9)
+#define R13_MM_STATE (1U << 10)
+#define R13_SSPM_STATE (1U << 11)
+#define R13_MD_DDR_EN (1U << 12)
+#define R13_CONN_STATE (1U << 13)
+#define R13_CONN_SRCCLKENA (1U << 14)
+#define R13_CONN_APSRC_REQ (1U << 15)
+#define R13_SLEEP_EVENT_STA (1U << 16)
+#define R13_WAKE_EVENT_STA (1U << 17)
+#define R13_EMI_IDLE (1U << 18)
+#define R13_CSYSPWRUPREQ (1U << 19)
+#define R13_PWRAP_SLEEP_ACK (1U << 20)
+#define R13_EMI_CLK_OFF_ACK_ALL (1U << 21)
+#define R13_TOP_MAS_PAU_ACK (1U << 22)
+#define R13_SW_DMDRAMCSHU_ACK_ALL (1U << 23)
+#define R13_RC2SPM_EVENT_ABORT_MASK_OR (1U << 24)
+#define R13_DR_SHORT_QUEUE_ACK_ALL (1U << 25)
+#define R13_INFRA_AUX_IDLE (1U << 26)
+#define R13_DVFS_ALL_STATE (1U << 27)
+#define R13_RC2SPM_EVENT_ABORT_OR (1U << 28)
+#define R13_DRAMC_SPCMD_APSRC_REQ (1U << 29)
+#define R13_MD1_VRF18_REQ (1U << 30)
+#define R13_C2K_VRF18_REQ (1U << 31)
+
+#define is_cpu_pdn(flags) (!((flags) & SPM_FLAG_DIS_CPU_PDN))
+#define is_infra_pdn(flags) (!((flags) & SPM_FLAG_DIS_INFRA_PDN))
+#define is_ddrphy_pdn(flags) (!((flags) & SPM_FLAG_DIS_DDRPHY_PDN))
+
+#define MP0_SPMC_SRAM_DORMANT_EN (1<<0)
+#define MP1_SPMC_SRAM_DORMANT_EN (1<<1)
+#define MP2_SPMC_SRAM_DORMANT_EN (1<<2)
+
+#define EVENT_VEC(event, resume, imme, pc) \
+ (((pc) << 16) | \
+ (!!(imme) << 7) | \
+ (!!(resume) << 6) | \
+ ((event) & 0x3f))
+
+#define SPM_PROJECT_CODE 0xb16
+#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+/**************************************
+ * Config and Parameter
+ **************************************/
+#define POWER_ON_VAL1_DEF 0x00015800
+#define PCM_FSM_STA_DEF 0x00108490
+#define SPM_WAKEUP_EVENT_MASK_DEF 0xF0F92218
+#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */
+#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT)
+
+/**************************************
+ * Define and Declare
+ **************************************/
+/* PCM_PWR_IO_EN */
+#define PCM_PWRIO_EN_R0 (1U << 0)
+#define PCM_PWRIO_EN_R7 (1U << 7)
+#define PCM_RF_SYNC_R0 (1U << 16)
+#define PCM_RF_SYNC_R6 (1U << 22)
+#define PCM_RF_SYNC_R7 (1U << 23)
+
+/* SPM_SWINT */
+#define PCM_SW_INT0 (1U << 0)
+#define PCM_SW_INT1 (1U << 1)
+#define PCM_SW_INT2 (1U << 2)
+#define PCM_SW_INT3 (1U << 3)
+#define PCM_SW_INT4 (1U << 4)
+#define PCM_SW_INT5 (1U << 5)
+#define PCM_SW_INT6 (1U << 6)
+#define PCM_SW_INT7 (1U << 7)
+#define PCM_SW_INT8 (1U << 8)
+#define PCM_SW_INT9 (1U << 9)
+#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \
+ PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \
+ PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \
+ PCM_SW_INT0)
+/* SPM_IRQ_MASK */
+#define ISRM_TWAM (1U << 2)
+#define ISRM_PCM_RETURN (1U << 3)
+#define ISRM_RET_IRQ0 (1U << 8)
+#define ISRM_RET_IRQ1 (1U << 9)
+#define ISRM_RET_IRQ2 (1U << 10)
+#define ISRM_RET_IRQ3 (1U << 11)
+#define ISRM_RET_IRQ4 (1U << 12)
+#define ISRM_RET_IRQ5 (1U << 13)
+#define ISRM_RET_IRQ6 (1U << 14)
+#define ISRM_RET_IRQ7 (1U << 15)
+#define ISRM_RET_IRQ8 (1U << 16)
+#define ISRM_RET_IRQ9 (1U << 17)
+#define ISRM_RET_IRQ_AUX (ISRM_RET_IRQ9 | ISRM_RET_IRQ8 | \
+ ISRM_RET_IRQ7 | ISRM_RET_IRQ6 | \
+ ISRM_RET_IRQ5 | ISRM_RET_IRQ4 | \
+ ISRM_RET_IRQ3 | ISRM_RET_IRQ2 | \
+ ISRM_RET_IRQ1)
+#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX)
+#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM)
+
+/* SPM_IRQ_STA */
+#define ISRS_TWAM (1U << 2)
+#define ISRS_PCM_RETURN (1U << 3)
+#define ISRS_SW_INT0 (1U << 4)
+#define ISRC_TWAM ISRS_TWAM
+#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN
+#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM)
+
+/* SPM_WAKEUP_MISC */
+#define WAKE_MISC_TWAM (1U << 18)
+#define WAKE_MISC_PCM_TIMER (1U << 19)
+#define WAKE_MISC_CPU_WAKE (1U << 20)
+
+enum SPM_WAKE_SRC_LIST {
+ WAKE_SRC_R12_PCM_TIMER = (1U << 0),
+ WAKE_SRC_R12_SSPM_WDT_EVENT_B = (1U << 1),
+ WAKE_SRC_R12_KP_IRQ_B = (1U << 2),
+ WAKE_SRC_R12_APWDT_EVENT_B = (1U << 3),
+ WAKE_SRC_R12_APXGPT1_EVENT_B = (1U << 4),
+ WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B = (1U << 5),
+ WAKE_SRC_R12_EINT_EVENT_B = (1U << 6),
+ WAKE_SRC_R12_CONN_WDT_IRQ_B = (1U << 7),
+ WAKE_SRC_R12_CCIF0_EVENT_B = (1U << 8),
+ WAKE_SRC_R12_LOWBATTERY_IRQ_B = (1U << 9),
+ WAKE_SRC_R12_SSPM_SPM_IRQ_B = (1U << 10),
+ WAKE_SRC_R12_SCP_SPM_IRQ_B = (1U << 11),
+ WAKE_SRC_R12_SCP_WDT_EVENT_B = (1U << 12),
+ WAKE_SRC_R12_PCM_WDT_WAKEUP_B = (1U << 13),
+ WAKE_SRC_R12_USB_CDSC_B = (1U << 14),
+ WAKE_SRC_R12_USB_POWERDWN_B = (1U << 15),
+ WAKE_SRC_R12_SYS_TIMER_EVENT_B = (1U << 16),
+ WAKE_SRC_R12_EINT_EVENT_SECURE_B = (1U << 17),
+ WAKE_SRC_R12_CCIF1_EVENT_B = (1U << 18),
+ WAKE_SRC_R12_UART0_IRQ_B = (1U << 19),
+ WAKE_SRC_R12_AFE_IRQ_MCU_B = (1U << 20),
+ WAKE_SRC_R12_THERM_CTRL_EVENT_B = (1U << 21),
+ WAKE_SRC_R12_SYS_CIRQ_IRQ_B = (1U << 22),
+ WAKE_SRC_R12_MD2AP_PEER_EVENT_B = (1U << 23),
+ WAKE_SRC_R12_CSYSPWREQ_B = (1U << 24),
+ WAKE_SRC_R12_MD1_WDT_B = (1U << 25),
+ WAKE_SRC_R12_CLDMA_EVENT_B = (1U << 26),
+ WAKE_SRC_R12_SEJ_WDT_GPT_B = (1U << 27),
+ WAKE_SRC_R12_ALL_SSPM_WAKEUP_B = (1U << 28),
+ WAKE_SRC_R12_CPU_IRQ_B = (1U << 29),
+ WAKE_SRC_R12_CPU_WFI_AND_B = (1U << 30),
+};
+
+struct pcm_desc {
+ const char *version;
+ const uint32_t *base;
+ const uint32_t base_dma;
+ const uint32_t size;
+ const uint32_t sess;
+ const uint32_t replace;
+ const uint32_t addr_2nd;
+ const uint32_t reserved;
+
+ uint32_t vec0;
+ uint32_t vec1;
+ uint32_t vec2;
+ uint32_t vec3;
+ uint32_t vec4;
+ uint32_t vec5;
+ uint32_t vec6;
+ uint32_t vec7;
+ uint32_t vec8;
+ uint32_t vec9;
+ uint32_t vec10;
+ uint32_t vec11;
+ uint32_t vec12;
+ uint32_t vec13;
+ uint32_t vec14;
+ uint32_t vec15;
+};
+
+struct pwr_ctrl {
+ uint32_t pcm_flags;
+ uint32_t pcm_flags1;
+ uint32_t timer_val;
+ uint32_t wake_src;
+
+ /* SPM_AP_STANDBY_CON */
+ uint8_t wfi_op;
+ uint8_t mp0_cputop_idle_mask;
+ uint8_t mp1_cputop_idle_mask;
+ uint8_t mcusys_idle_mask;
+ uint8_t mm_mask_b;
+ uint8_t md_ddr_en_0_dbc_en;
+ uint8_t md_ddr_en_1_dbc_en;
+ uint8_t md_mask_b;
+ uint8_t sspm_mask_b;
+ uint8_t scp_mask_b;
+ uint8_t srcclkeni_mask_b;
+ uint8_t md_apsrc_1_sel;
+ uint8_t md_apsrc_0_sel;
+ uint8_t conn_ddr_en_dbc_en;
+ uint8_t conn_mask_b;
+ uint8_t conn_apsrc_sel;
+
+ /* SPM_SRC_REQ */
+ uint8_t spm_apsrc_req;
+ uint8_t spm_f26m_req;
+ uint8_t spm_infra_req;
+ uint8_t spm_vrf18_req;
+ uint8_t spm_ddren_req;
+ uint8_t spm_rsv_src_req;
+ uint8_t spm_ddren_2_req;
+ uint8_t cpu_md_dvfs_sop_force_on;
+
+ /* SPM_SRC_MASK */
+ uint8_t csyspwreq_mask;
+ uint8_t ccif0_md_event_mask_b;
+ uint8_t ccif0_ap_event_mask_b;
+ uint8_t ccif1_md_event_mask_b;
+ uint8_t ccif1_ap_event_mask_b;
+ uint8_t ccif2_md_event_mask_b;
+ uint8_t ccif2_ap_event_mask_b;
+ uint8_t ccif3_md_event_mask_b;
+ uint8_t ccif3_ap_event_mask_b;
+ uint8_t md_srcclkena_0_infra_mask_b;
+ uint8_t md_srcclkena_1_infra_mask_b;
+ uint8_t conn_srcclkena_infra_mask_b;
+ uint8_t ufs_infra_req_mask_b;
+ uint8_t srcclkeni_infra_mask_b;
+ uint8_t md_apsrc_req_0_infra_mask_b;
+ uint8_t md_apsrc_req_1_infra_mask_b;
+ uint8_t conn_apsrcreq_infra_mask_b;
+ uint8_t ufs_srcclkena_mask_b;
+ uint8_t md_vrf18_req_0_mask_b;
+ uint8_t md_vrf18_req_1_mask_b;
+ uint8_t ufs_vrf18_req_mask_b;
+ uint8_t gce_vrf18_req_mask_b;
+ uint8_t conn_infra_req_mask_b;
+ uint8_t gce_apsrc_req_mask_b;
+ uint8_t disp0_apsrc_req_mask_b;
+ uint8_t disp1_apsrc_req_mask_b;
+ uint8_t mfg_req_mask_b;
+ uint8_t vdec_req_mask_b;
+
+ /* SPM_SRC2_MASK */
+ uint8_t md_ddr_en_0_mask_b;
+ uint8_t md_ddr_en_1_mask_b;
+ uint8_t conn_ddr_en_mask_b;
+ uint8_t ddren_sspm_apsrc_req_mask_b;
+ uint8_t ddren_scp_apsrc_req_mask_b;
+ uint8_t disp0_ddren_mask_b;
+ uint8_t disp1_ddren_mask_b;
+ uint8_t gce_ddren_mask_b;
+ uint8_t ddren_emi_self_refresh_ch0_mask_b;
+ uint8_t ddren_emi_self_refresh_ch1_mask_b;
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ uint32_t spm_wakeup_event_mask;
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ uint32_t spm_wakeup_event_ext_mask;
+
+ /* SPM_SRC3_MASK */
+ uint8_t md_ddr_en_2_0_mask_b;
+ uint8_t md_ddr_en_2_1_mask_b;
+ uint8_t conn_ddr_en_2_mask_b;
+ uint8_t ddren2_sspm_apsrc_req_mask_b;
+ uint8_t ddren2_scp_apsrc_req_mask_b;
+ uint8_t disp0_ddren2_mask_b;
+ uint8_t disp1_ddren2_mask_b;
+ uint8_t gce_ddren2_mask_b;
+ uint8_t ddren2_emi_self_refresh_ch0_mask_b;
+ uint8_t ddren2_emi_self_refresh_ch1_mask_b;
+
+ uint8_t mp0_cpu0_wfi_en;
+ uint8_t mp0_cpu1_wfi_en;
+ uint8_t mp0_cpu2_wfi_en;
+ uint8_t mp0_cpu3_wfi_en;
+
+ uint8_t mp1_cpu0_wfi_en;
+ uint8_t mp1_cpu1_wfi_en;
+ uint8_t mp1_cpu2_wfi_en;
+ uint8_t mp1_cpu3_wfi_en;
+};
+
+struct wake_status {
+ uint32_t assert_pc;
+ uint32_t r12;
+ uint32_t r12_ext;
+ uint32_t raw_sta;
+ uint32_t raw_ext_sta;
+ uint32_t wake_misc;
+ uint32_t timer_out;
+ uint32_t r13;
+ uint32_t r15;
+ uint32_t idle_sta;
+ uint32_t req_sta;
+ uint32_t debug_flag;
+ uint32_t debug_flag1;
+ uint32_t event_reg;
+ uint32_t isr;
+ uint32_t sw_flag;
+ uint32_t sw_flag1;
+ uint32_t log_index;
+};
+
+typedef struct spm_data {
+ unsigned int cmd;
+ union {
+ struct {
+ unsigned int sys_timestamp_l;
+ unsigned int sys_timestamp_h;
+ unsigned int sys_src_clk_l;
+ unsigned int sys_src_clk_h;
+ unsigned int spm_opt;
+ } suspend;
+ struct {
+ unsigned int args1;
+ unsigned int args2;
+ unsigned int args3;
+ unsigned int args4;
+ unsigned int args5;
+ unsigned int args6;
+ unsigned int args7;
+ } args;
+ } u;
+} spm_data_t;
+
+enum {
+ SPM_SUSPEND,
+ SPM_RESUME
+};
+
+extern void spm_disable_pcm_timer(void);
+extern void spm_set_bootaddr(unsigned long bootaddr);
+extern void spm_set_cpu_status(int cpu);
+extern void spm_set_power_control(const struct pwr_ctrl *pwrctrl);
+extern void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl);
+extern void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl);
+extern void spm_send_cpu_wakeup_event(void);
+extern void spm_get_wakeup_status(struct wake_status *wakesta);
+extern void spm_clean_after_wakeup(void);
+extern void spm_output_wake_reason(struct wake_status *wakesta,
+ const char *scenario);
+extern void spm_set_pcm_wdt(int en);
+extern void spm_lock_get(void);
+extern void spm_lock_release(void);
+extern void spm_boot_init(void);
+extern const char *spm_get_firmware_version(void);
+
+#endif /* SPM_H */
diff --git a/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c b/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c
new file mode 100644
index 0000000..ce85272
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <spm.h>
+#include <spm_pmic_wrap.h>
+#include <lib/libc/string.h>
+
+#define SLEEP_REG_MD_SPM_DVFS_CMD20 (SLEEP_REG_MD_BASE + 0x010)
+#define SLEEP_REG_MD_SPM_DVFS_CMD21 (SLEEP_REG_MD_BASE + 0x014)
+#define SLEEP_REG_MD_SPM_DVFS_CMD22 (SLEEP_REG_MD_BASE + 0x018)
+#define SLEEP_REG_MD_SPM_DVFS_CMD23 (SLEEP_REG_MD_BASE + 0x01C)
+
+/* PMIC_WRAP -> PMIC MT6358 */
+#define VCORE_BASE_UV 50000
+#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625)
+#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV)
+
+#define DEFAULT_VOLT_VSRAM (100000)
+#define DEFAULT_VOLT_VCORE (100000)
+#define NR_PMIC_WRAP_CMD (NR_IDX_ALL)
+#define MAX_RETRY_COUNT (100)
+#define SPM_DATA_SHIFT (16)
+
+#define BUCK_VCORE_ELR0 0x14AA
+#define BUCK_VPROC12_CON0 0x1408
+#define BUCK_VPROC11_CON0 0x1388
+#define TOP_SPI_CON0 0x044C
+#define LDO_VSRAM_PROC12_CON0 0x1B88
+#define LDO_VSRAM_PROC11_CON0 0x1B46
+#define BUCK_VMODEM_ELR0 0x15A6
+
+struct pmic_wrap_cmd {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+};
+
+struct pmic_wrap_setting {
+ enum pmic_wrap_phase_id phase;
+ struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
+ struct {
+ struct {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+ } _[NR_PMIC_WRAP_CMD];
+ const int nr_idx;
+ } set[NR_PMIC_WRAP_PHASE];
+};
+
+static struct pmic_wrap_setting pw = {
+ .phase = NR_PMIC_WRAP_PHASE,
+ .addr = {{0, 0} },
+ .set[PMIC_WRAP_PHASE_ALLINONE] = {
+ ._[CMD_0] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(70000),},
+ ._[CMD_1] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(80000),},
+ ._[CMD_2] = {BUCK_VPROC12_CON0, 0x3,},
+ ._[CMD_3] = {BUCK_VPROC12_CON0, 0x1,},
+ ._[CMD_4] = {BUCK_VPROC11_CON0, 0x3,},
+ ._[CMD_5] = {BUCK_VPROC11_CON0, 0x1,},
+ ._[CMD_6] = {TOP_SPI_CON0, 0x1,},
+ ._[CMD_7] = {TOP_SPI_CON0, 0x0,},
+ ._[CMD_8] = {BUCK_VPROC12_CON0, 0x0,},
+ ._[CMD_9] = {BUCK_VPROC12_CON0, 0x1,},
+ ._[CMD_10] = {BUCK_VPROC11_CON0, 0x0,},
+ ._[CMD_11] = {BUCK_VPROC11_CON0, 0x1,},
+ ._[CMD_12] = {LDO_VSRAM_PROC12_CON0, 0x0,},
+ ._[CMD_13] = {LDO_VSRAM_PROC12_CON0, 0x1,},
+ ._[CMD_14] = {LDO_VSRAM_PROC11_CON0, 0x0,},
+ ._[CMD_15] = {LDO_VSRAM_PROC11_CON0, 0x1,},
+ ._[CMD_20] = {BUCK_VMODEM_ELR0, VOLT_TO_PMIC_VAL(55000),},
+ ._[CMD_21] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(60000),},
+ ._[CMD_22] = {LDO_VSRAM_PROC11_CON0, 0x3,},
+ ._[CMD_23] = {LDO_VSRAM_PROC11_CON0, 0x1,},
+ .nr_idx = NR_IDX_ALL
+ }
+};
+
+void _mt_spm_pmic_table_init(void)
+{
+ struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
+ {(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,},
+ {(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,},
+ {(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,},
+ {(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,},
+ {(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,},
+ {(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,},
+ {(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,},
+ {(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,},
+ {(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,},
+ {(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,},
+ {(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,},
+ {(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,},
+ {(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,},
+ {(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,},
+ {(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,},
+ {(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,},
+ {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,
+ (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,},
+ {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,
+ (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,},
+ {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,
+ (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,},
+ {(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,
+ (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,}
+ };
+
+ memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
+}
+
+void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
+{
+ uint32_t idx, addr, data;
+
+ if (phase >= NR_PMIC_WRAP_PHASE)
+ return;
+
+ if (pw.phase == phase)
+ return;
+
+ if (pw.addr[0].cmd_addr == 0)
+ _mt_spm_pmic_table_init();
+
+ pw.phase = phase;
+
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
+ BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
+ for (idx = 0; idx < pw.set[phase].nr_idx; idx++) {
+ addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ data = pw.set[phase]._[idx].cmd_wdata;
+ mmio_write_32(pw.addr[idx].cmd_addr, addr | data);
+ }
+}
+
+void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
+ uint32_t cmd_wdata)
+{
+ uint32_t addr;
+
+ if (phase >= NR_PMIC_WRAP_PHASE)
+ return;
+
+ if (idx >= pw.set[phase].nr_idx)
+ return;
+
+ pw.set[phase]._[idx].cmd_wdata = cmd_wdata;
+
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
+ BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
+ if (pw.phase == phase) {
+ addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata);
+ }
+}
+
+uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
+{
+ if (phase >= NR_PMIC_WRAP_PHASE)
+ return 0;
+
+ if (idx >= pw.set[phase].nr_idx)
+ return 0;
+
+ return pw.set[phase]._[idx].cmd_wdata;
+}
+
diff --git a/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h b/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h
new file mode 100644
index 0000000..194d347
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/****************************************************************
+ * Auto generated by DE, please DO NOT modify this file directly.
+ *****************************************************************/
+
+#ifndef SPM_PMIC_WRAP__H
+#define SPM_PMIC_WRAP__H
+
+enum pmic_wrap_phase_id {
+ PMIC_WRAP_PHASE_ALLINONE,
+ NR_PMIC_WRAP_PHASE
+};
+
+/* IDX mapping */
+enum {
+ CMD_0, /* 0x0 *//* PMIC_WRAP_PHASE_ALLINONE */
+ CMD_1, /* 0x1 */
+ CMD_2, /* 0x2 */
+ CMD_3, /* 0x3 */
+ CMD_4, /* 0x4 */
+ CMD_5, /* 0x5 */
+ CMD_6, /* 0x6 */
+ CMD_7, /* 0x7 */
+ CMD_8, /* 0x8 */
+ CMD_9, /* 0x9 */
+ CMD_10, /* 0xA */
+ CMD_11, /* 0xB */
+ CMD_12, /* 0xC */
+ CMD_13, /* 0xD */
+ CMD_14, /* 0xE */
+ CMD_15, /* 0xF */
+ CMD_20, /* 0x14 */
+ CMD_21, /* 0x15 */
+ CMD_22, /* 0x16 */
+ CMD_23, /* 0x17 */
+ NR_IDX_ALL
+};
+
+/* APIs */
+void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase);
+void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase,
+ uint32_t idx, uint32_t cmd_wdata);
+uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx);
+#endif /* SPM_PMIC_WRAP__H */
+
diff --git a/plat/mediatek/mt8183/drivers/spm/spm_suspend.c b/plat/mediatek/mt8183/drivers/spm/spm_suspend.c
new file mode 100644
index 0000000..b9ac19f
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spm/spm_suspend.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <mt_gic_v3.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <pmic.h>
+#include <spm.h>
+#include <uart.h>
+
+#define SPM_SYSCLK_SETTLE 99
+
+#define WAKE_SRC_FOR_SUSPEND \
+ (WAKE_SRC_R12_PCM_TIMER | \
+ WAKE_SRC_R12_SSPM_WDT_EVENT_B | \
+ WAKE_SRC_R12_KP_IRQ_B | \
+ WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B | \
+ WAKE_SRC_R12_EINT_EVENT_B | \
+ WAKE_SRC_R12_CONN_WDT_IRQ_B | \
+ WAKE_SRC_R12_CCIF0_EVENT_B | \
+ WAKE_SRC_R12_SSPM_SPM_IRQ_B | \
+ WAKE_SRC_R12_SCP_SPM_IRQ_B | \
+ WAKE_SRC_R12_SCP_WDT_EVENT_B | \
+ WAKE_SRC_R12_USB_CDSC_B | \
+ WAKE_SRC_R12_USB_POWERDWN_B | \
+ WAKE_SRC_R12_SYS_TIMER_EVENT_B | \
+ WAKE_SRC_R12_EINT_EVENT_SECURE_B | \
+ WAKE_SRC_R12_CCIF1_EVENT_B | \
+ WAKE_SRC_R12_MD2AP_PEER_EVENT_B | \
+ WAKE_SRC_R12_MD1_WDT_B | \
+ WAKE_SRC_R12_CLDMA_EVENT_B | \
+ WAKE_SRC_R12_SEJ_WDT_GPT_B)
+
+#define SLP_PCM_FLAGS \
+ (SPM_FLAG_DIS_VCORE_DVS | SPM_FLAG_DIS_VCORE_DFS | \
+ SPM_FLAG_DIS_ATF_ABORT | SPM_FLAG_DISABLE_MMSYS_DVFS | \
+ SPM_FLAG_DIS_INFRA_PDN | SPM_FLAG_SUSPEND_OPTION)
+
+#define SLP_PCM_FLAGS1 \
+ (SPM_FLAG1_DISABLE_MCDSR)
+
+static const struct pwr_ctrl suspend_ctrl = {
+ .wake_src = WAKE_SRC_FOR_SUSPEND,
+ .pcm_flags = SLP_PCM_FLAGS,
+ .pcm_flags1 = SLP_PCM_FLAGS1,
+
+ /* SPM_AP_STANDBY_CON */
+ .wfi_op = 0x1,
+ .mp0_cputop_idle_mask = 0,
+ .mp1_cputop_idle_mask = 0,
+ .mcusys_idle_mask = 0,
+ .mm_mask_b = 0,
+ .md_ddr_en_0_dbc_en = 0x1,
+ .md_ddr_en_1_dbc_en = 0,
+ .md_mask_b = 0x1,
+ .sspm_mask_b = 0x1,
+ .scp_mask_b = 0x1,
+ .srcclkeni_mask_b = 0x1,
+ .md_apsrc_1_sel = 0,
+ .md_apsrc_0_sel = 0,
+ .conn_ddr_en_dbc_en = 0x1,
+ .conn_mask_b = 0x1,
+ .conn_apsrc_sel = 0,
+
+ /* SPM_SRC_REQ */
+ .spm_apsrc_req = 0,
+ .spm_f26m_req = 0,
+ .spm_infra_req = 0,
+ .spm_vrf18_req = 0,
+ .spm_ddren_req = 0,
+ .spm_rsv_src_req = 0,
+ .spm_ddren_2_req = 0,
+ .cpu_md_dvfs_sop_force_on = 0,
+
+ /* SPM_SRC_MASK */
+ .csyspwreq_mask = 0x1,
+ .ccif0_md_event_mask_b = 0x1,
+ .ccif0_ap_event_mask_b = 0x1,
+ .ccif1_md_event_mask_b = 0x1,
+ .ccif1_ap_event_mask_b = 0x1,
+ .ccif2_md_event_mask_b = 0x1,
+ .ccif2_ap_event_mask_b = 0x1,
+ .ccif3_md_event_mask_b = 0x1,
+ .ccif3_ap_event_mask_b = 0x1,
+ .md_srcclkena_0_infra_mask_b = 0x1,
+ .md_srcclkena_1_infra_mask_b = 0,
+ .conn_srcclkena_infra_mask_b = 0,
+ .ufs_infra_req_mask_b = 0,
+ .srcclkeni_infra_mask_b = 0,
+ .md_apsrc_req_0_infra_mask_b = 0x1,
+ .md_apsrc_req_1_infra_mask_b = 0x1,
+ .conn_apsrcreq_infra_mask_b = 0x1,
+ .ufs_srcclkena_mask_b = 0,
+ .md_vrf18_req_0_mask_b = 0,
+ .md_vrf18_req_1_mask_b = 0,
+ .ufs_vrf18_req_mask_b = 0,
+ .gce_vrf18_req_mask_b = 0,
+ .conn_infra_req_mask_b = 0x1,
+ .gce_apsrc_req_mask_b = 0,
+ .disp0_apsrc_req_mask_b = 0,
+ .disp1_apsrc_req_mask_b = 0,
+ .mfg_req_mask_b = 0,
+ .vdec_req_mask_b = 0,
+
+ /* SPM_SRC2_MASK */
+ .md_ddr_en_0_mask_b = 0x1,
+ .md_ddr_en_1_mask_b = 0,
+ .conn_ddr_en_mask_b = 0x1,
+ .ddren_sspm_apsrc_req_mask_b = 0x1,
+ .ddren_scp_apsrc_req_mask_b = 0x1,
+ .disp0_ddren_mask_b = 0x1,
+ .disp1_ddren_mask_b = 0x1,
+ .gce_ddren_mask_b = 0x1,
+ .ddren_emi_self_refresh_ch0_mask_b = 0,
+ .ddren_emi_self_refresh_ch1_mask_b = 0,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ .spm_wakeup_event_mask = 0xF1782218,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ .spm_wakeup_event_ext_mask = 0xFFFFFFFF,
+
+ /* SPM_SRC3_MASK */
+ .md_ddr_en_2_0_mask_b = 0x1,
+ .md_ddr_en_2_1_mask_b = 0,
+ .conn_ddr_en_2_mask_b = 0x1,
+ .ddren2_sspm_apsrc_req_mask_b = 0x1,
+ .ddren2_scp_apsrc_req_mask_b = 0x1,
+ .disp0_ddren2_mask_b = 0,
+ .disp1_ddren2_mask_b = 0,
+ .gce_ddren2_mask_b = 0,
+ .ddren2_emi_self_refresh_ch0_mask_b = 0,
+ .ddren2_emi_self_refresh_ch1_mask_b = 0,
+
+ .mp0_cpu0_wfi_en = 0x1,
+ .mp0_cpu1_wfi_en = 0x1,
+ .mp0_cpu2_wfi_en = 0x1,
+ .mp0_cpu3_wfi_en = 0x1,
+
+ .mp1_cpu0_wfi_en = 0x1,
+ .mp1_cpu1_wfi_en = 0x1,
+ .mp1_cpu2_wfi_en = 0x1,
+ .mp1_cpu3_wfi_en = 0x1
+};
+
+static uint32_t spm_set_sysclk_settle(void)
+{
+ mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE);
+ return mmio_read_32(SPM_CLK_SETTLE);
+}
+
+void go_to_sleep_before_wfi(void)
+{
+ int cpu = MPIDR_AFFLVL0_VAL(read_mpidr());
+ uint32_t settle;
+
+ settle = spm_set_sysclk_settle();
+ spm_set_cpu_status(cpu);
+ spm_set_power_control(&suspend_ctrl);
+ spm_set_wakeup_event(&suspend_ctrl);
+ spm_set_pcm_flags(&suspend_ctrl);
+ spm_send_cpu_wakeup_event();
+ spm_set_pcm_wdt(0);
+ spm_disable_pcm_timer();
+
+ if (is_infra_pdn(suspend_ctrl.pcm_flags))
+ mt_uart_save();
+
+ if (!mt_console_uart_cg_status())
+ console_switch_state(CONSOLE_FLAG_BOOT);
+
+ INFO("cpu%d: \"%s\", wakesrc = 0x%x, pcm_con1 = 0x%x\n",
+ cpu, spm_get_firmware_version(), suspend_ctrl.wake_src,
+ mmio_read_32(PCM_CON1));
+ INFO("settle = %u, sec = %u, sw_flag = 0x%x 0x%x, src_req = 0x%x\n",
+ settle, mmio_read_32(PCM_TIMER_VAL) / 32768,
+ suspend_ctrl.pcm_flags, suspend_ctrl.pcm_flags1,
+ mmio_read_32(SPM_SRC_REQ));
+
+ if (!mt_console_uart_cg_status())
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
+
+static void go_to_sleep_after_wfi(void)
+{
+ struct wake_status spm_wakesta;
+
+ if (is_infra_pdn(suspend_ctrl.pcm_flags))
+ mt_uart_restore();
+
+ spm_set_pcm_wdt(0);
+ spm_get_wakeup_status(&spm_wakesta);
+ spm_clean_after_wakeup();
+
+ if (!mt_console_uart_cg_status())
+ console_switch_state(CONSOLE_FLAG_BOOT);
+
+ spm_output_wake_reason(&spm_wakesta, "suspend");
+
+ if (!mt_console_uart_cg_status())
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+}
+
+static void spm_enable_armpll_l(void)
+{
+ /* power on */
+ mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x1);
+
+ /* clear isolation */
+ mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x2);
+
+ /* enable pll */
+ mmio_setbits_32(ARMPLL_L_CON0, 0x1);
+
+ /* Add 20us delay for turning on PLL */
+ udelay(20);
+}
+
+static void spm_disable_armpll_l(void)
+{
+ /* disable pll */
+ mmio_clrbits_32(ARMPLL_L_CON0, 0x1);
+
+ /* isolation */
+ mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x2);
+
+ /* power off */
+ mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x1);
+}
+
+void spm_system_suspend(void)
+{
+ spm_disable_armpll_l();
+ bcpu_enable(0);
+ bcpu_sram_enable(0);
+ spm_lock_get();
+ go_to_sleep_before_wfi();
+ spm_lock_release();
+}
+
+void spm_system_suspend_finish(void)
+{
+ spm_lock_get();
+ go_to_sleep_after_wfi();
+ spm_lock_release();
+ spm_enable_armpll_l();
+ bcpu_sram_enable(1);
+ bcpu_enable(1);
+}
diff --git a/plat/mediatek/mt8183/drivers/spm/spm_suspend.h b/plat/mediatek/mt8183/drivers/spm/spm_suspend.h
new file mode 100644
index 0000000..e127c2e
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spm/spm_suspend.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SPM_SUSPEND_H__
+#define __SPM_SUSPEND_H__
+
+void spm_system_suspend(void);
+void spm_system_suspend_finish(void);
+
+#endif /* __SPM_SUSPEND_H__*/
diff --git a/plat/mediatek/mt8183/drivers/spmc/mtspmc.c b/plat/mediatek/mt8183/drivers/spmc/mtspmc.c
new file mode 100644
index 0000000..ac8e1b4
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spmc/mtspmc.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <cortex_a53.h>
+#include <cortex_a73.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+#include <mcucfg.h>
+#include <spm.h>
+#include <drivers/delay_timer.h>
+#include <mtspmc.h>
+
+#include "mtspmc_private.h"
+
+
+static void set_retention(int cluster, int tick)
+{
+ uint64_t cpuectlr;
+
+ if (cluster)
+ cpuectlr = read_a73_cpuectlr_el1();
+ else
+ cpuectlr = read_a53_cpuectlr_el1();
+
+ cpuectlr &= ~0x7ULL;
+ cpuectlr |= tick & 0x7;
+
+ if (cluster)
+ write_a73_cpuectlr_el1(cpuectlr);
+ else
+ write_a53_cpuectlr_el1(cpuectlr);
+}
+
+void spm_enable_cpu_auto_off(int cluster, int cpu)
+{
+ uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK);
+
+ set_retention(cluster, 1);
+ mmio_clrbits_32(reg, SW_NO_WAIT_Q);
+}
+
+void spm_disable_cpu_auto_off(int cluster, int cpu)
+{
+ uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK);
+
+ mmio_setbits_32(reg, SW_NO_WAIT_Q);
+ set_retention(cluster, 0);
+}
+
+void spm_set_cpu_power_off(int cluster, int cpu)
+{
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
+}
+
+void spm_enable_cluster_auto_off(int cluster)
+{
+ assert(cluster);
+
+ mmio_clrbits_32(MCUCFG_MP2_SPMC, SW_NO_WAIT_Q);
+ mmio_clrbits_32(MCUCFG_MP2_COQ, BIT(0));
+
+ mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, MP1_SPMC_SRAM_DORMANT_EN);
+
+ mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
+}
+
+void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr)
+{
+ uintptr_t reg;
+ const uintptr_t mp2_bootreg[] = {
+ MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1,
+ MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 };
+
+ if (cluster) {
+ assert(cpu >= 0 && cpu < 4);
+ reg = mp2_bootreg[cpu];
+ } else {
+ reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR);
+ }
+
+ mmio_write_32(reg, bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(int cluster, int cpu)
+{
+ uintptr_t reg;
+ const uintptr_t mp2_bootreg[] = {
+ MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1,
+ MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 };
+
+ if (cluster) {
+ assert(cpu >= 0 && cpu < 4);
+ reg = mp2_bootreg[cpu];
+ } else {
+ reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR);
+ }
+
+ return mmio_read_32(reg);
+}
+
+void mcucfg_init_archstate(int cluster, int cpu, int arm64)
+{
+ uintptr_t reg;
+ int i;
+
+ reg = per_cluster(cluster, MCUCFG_INITARCH);
+ i = cluster ? 16 : 12;
+
+ mmio_setbits_32(reg, (arm64 & 1) << (i + cpu));
+}
+
+/**
+ * Return power state of specified subsystem
+ *
+ * @mask: mask to SPM_PWR_STATUS to query the power state
+ * of one subsystem.
+ * RETURNS:
+ * 0 (the subsys was powered off)
+ * 1 (the subsys was powered on)
+ */
+int spm_get_powerstate(uint32_t mask)
+{
+ return mmio_read_32(SPM_PWR_STATUS) & mask;
+}
+
+int spm_get_cluster_powerstate(int cluster)
+{
+ uint32_t mask;
+
+ mask = cluster ? PWR_STATUS_MP1_CPUTOP : PWR_STATUS_MP0_CPUTOP;
+
+ return spm_get_powerstate(mask);
+}
+
+int spm_get_cpu_powerstate(int cluster, int cpu)
+{
+ uint32_t i;
+
+ /*
+ * a quick way to specify the mask of cpu[0-3]/cpu[4-7] in PWR_STATUS
+ * register which are the BITS[9:12](MP0_CPU0~3) and
+ * BITS[16:19](MP1_CPU0~3)
+ */
+ i = (cluster) ? 16 : 9;
+ i = 1 << (i + cpu);
+
+ return spm_get_powerstate(i);
+}
+
+int spmc_init(void)
+{
+ /* enable SPM register control */
+ mmio_write_32(SPM_POWERON_CONFIG_EN,
+ PROJECT_CODE | MD_BCLK_CG_EN | BCLK_CG_EN);
+
+#if SPMC_MODE == 1
+ INFO("SPM: enable SPMC mode\n");
+
+ /* 0: SPMC mode 1: Legacy mode */
+ mmio_write_32(SPM_BYPASS_SPMC, 0);
+
+ mmio_clrbits_32(per_cluster(0, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND);
+
+ mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+ mmio_clrbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+ mmio_clrbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+ mmio_clrbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+
+ mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+#endif
+
+ mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND);
+ mmio_setbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_RST_B);
+ mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_CLK_DIS);
+
+ mmio_clrbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+ mmio_clrbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+ mmio_clrbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+ mmio_clrbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+
+ mmio_setbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+ mmio_setbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+ mmio_setbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+ mmio_setbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+
+ return 0;
+}
+
+/**
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(int cluster, int cpu)
+{
+ INFO("spmc: power on core %d.%d\n", cluster, cpu);
+
+ /* STA_POWER_ON */
+ /* Start to turn on MP0_CPU0 */
+
+ /* Set PWR_RST_B = 1 */
+ mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+
+ /* Set PWR_ON = 1 */
+ mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
+
+ /* Wait until MP0_CPU0_PWR_STA_MASK = 1 */
+ while (!spm_get_cpu_powerstate(cluster, cpu))
+ ;
+
+ /* Finish to turn on MP0_CPU0 */
+ INFO("spmc: power on core %d.%d successfully\n", cluster, cpu);
+}
+
+/**
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(int cluster, int cpu)
+{
+ INFO("spmc: power off core %d.%d\n", cluster, cpu);
+
+ /* Start to turn off MP0_CPU0 */
+ /* Set PWR_ON_2ND = 0 */
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
+
+ /* Set PWR_ON = 0 */
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
+
+ /* Wait until MP0_CPU0_PWR_STA_MASK = 0 */
+ while (spm_get_cpu_powerstate(cluster, cpu))
+ ;
+
+ /* Set PWR_RST_B = 0 */
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
+
+ /* Finish to turn off MP0_CPU0 */
+ INFO("spmc: power off core %d.%d successfully\n", cluster, cpu);
+}
+
+/**
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(int cluster)
+{
+ uint32_t mask;
+ uint32_t pwr_rst_ctl;
+
+ INFO("spmc: power off cluster %d\n", cluster);
+
+ /* Start to turn off MP0_CPUTOP */
+ /* Set bus protect - step1 : 0 */
+ mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK :
+ MP0_CPUTOP_PROT_STEP1_0_MASK;
+ mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_SET, mask);
+
+ while ((mmio_read_32(INFRA_TOPAXI_PROTECTEN_STA1_1) & mask) != mask)
+ ;
+
+ /* Set PWR_ON_2ND = 0 */
+ mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
+ PWRCTRL_PWR_ON_2ND);
+
+ /* SPMC_DORMANT_ENABLE[0]=0 */
+ mask = (cluster) ? MP1_SPMC_SRAM_DORMANT_EN : MP0_SPMC_SRAM_DORMANT_EN;
+ mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, mask);
+
+ /* Set PWR_ON = 0" */
+ mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
+
+ /* Wait until MP0_CPUTOP_PWR_STA_MASK = 0 */
+ while (spm_get_cluster_powerstate(cluster))
+ ;
+
+ /* NOTE
+ * Following flow only for BIG core cluster. It was from
+ * application note but not covered in mtcmos_ctrl.c
+ */
+ if (cluster) {
+ pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL);
+ mmio_write_32(MCUCFG_MP2_PWR_RST_CTL,
+ (pwr_rst_ctl & ~SW_RST_B) | TOPAON_APB_MASK);
+ }
+
+ /* CPU_EXT_BUCK_ISO[0]=1 */
+ if (cluster)
+ mmio_setbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO);
+
+ /* Finish to turn off MP0_CPUTOP */
+ INFO("spmc: power off cluster %d successfully\n", cluster);
+}
+
+/**
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(int cluster)
+{
+ uint32_t mask;
+ uint32_t pwr_rst_ctl;
+
+ INFO("spmc: power on cluster %d\n", cluster);
+
+ /* Start to turn on MP1_CPUTOP */
+
+ /* NOTE
+ * Following flow only for BIG core cluster. It was from
+ * application note but not covered in mtcmos_ctrl.c
+ */
+ if (cluster) {
+ mmio_clrbits_32(MCUCFG_MP2_PWR_RST_CTL, SW_RST_B);
+
+ /* CPU_EXT_BUCK_ISO[1]=0 */
+ /* Set mp<n>_vproc_ext_off to 0 to release vproc isolation control */
+ mmio_clrbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO);
+
+ /* NOTE
+ * Following flow only for BIG core cluster. It was from
+ * application note but not covered in mtcmos_ctrl.c
+ */
+ pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL);
+ mmio_write_32(MCUCFG_MP2_PWR_RST_CTL,
+ (pwr_rst_ctl | SW_RST_B) & ~TOPAON_APB_MASK);
+ }
+
+ /* Set PWR_ON_2ND = 0 */
+ mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
+ PWRCTRL_PWR_ON_2ND);
+
+ /* Set PWR_RST_B = 1 */
+ mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
+ PWRCTRL_PWR_RST_B);
+
+ /* Set PWR_CLK_DIS = 0 */
+ mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
+ PWRCTRL_PWR_CLK_DIS);
+
+ /* Set PWR_ON = 1 */
+ mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
+
+ /* Wait until MP1_CPUTOP_PWR_STA_MASK = 1 */
+ while (!spm_get_cluster_powerstate(cluster))
+ ;
+
+ /* Release bus protect - step1 : 0 */
+ mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK :
+ MP0_CPUTOP_PROT_STEP1_0_MASK;
+ mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_CLR, mask);
+
+ /* Finish to turn on MP1_CPUTOP */
+ INFO("spmc: power on cluster %d successfully\n", cluster);
+}
diff --git a/plat/mediatek/mt8183/drivers/spmc/mtspmc.h b/plat/mediatek/mt8183/drivers/spmc/mtspmc.h
new file mode 100644
index 0000000..4cf3bcf
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spmc/mtspmc.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+/*
+ * CONFIG_SPMC_MODE: Select CPU power control mode.
+ *
+ * 0: Legacy
+ * Control power flow from SW through SPM register (MP*_PWR_CON).
+ * 1: HW
+ * Control power flow from SPMC. Most control flow and timing are handled
+ * by SPMC.
+ */
+#define SPMC_MODE 1
+
+int spmc_init(void);
+
+void spm_poweron_cpu(int cluster, int cpu);
+void spm_poweroff_cpu(int cluster, int cpu);
+
+void spm_poweroff_cluster(int cluster);
+void spm_poweron_cluster(int cluster);
+
+int spm_get_cpu_powerstate(int cluster, int cpu);
+int spm_get_cluster_powerstate(int cluster);
+int spm_get_powerstate(uint32_t mask);
+
+void spm_enable_cpu_auto_off(int cluster, int cpu);
+void spm_disable_cpu_auto_off(int cluster, int cpu);
+void spm_set_cpu_power_off(int cluster, int cpu);
+void spm_enable_cluster_auto_off(int cluster);
+
+void mcucfg_init_archstate(int cluster, int cpu, int arm64);
+void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(int cluster, int cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h
new file mode 100644
index 0000000..2228e63
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_PRIVATE_H
+#define MTSPMC_PRIVATE_H
+
+/*
+ * per_cpu/cluster helper
+ */
+struct per_cpu_reg {
+ int cluster_addr;
+ int cpu_stride;
+};
+
+#define per_cpu(cluster, cpu, reg) (reg[cluster].cluster_addr + \
+ (cpu << reg[cluster].cpu_stride))
+#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
+
+/* SPMC related registers */
+#define SPM_POWERON_CONFIG_EN (SPM_BASE + 0x000)
+/* bit-fields of SPM_POWERON_CONFIG_EN */
+#define BCLK_CG_EN (1 << 0)
+#define MD_BCLK_CG_EN (1 << 1)
+#define PROJECT_CODE (0xb16 << 16)
+
+#define SPM_PWR_STATUS (SPM_BASE + 0x180)
+#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x184)
+
+#define SPM_BYPASS_SPMC (SPM_BASE + 0x2b4)
+#define SPM_SPMC_DORMANT_ENABLE (SPM_BASE + 0x2b8)
+
+#define SPM_MP0_CPUTOP_PWR_CON (SPM_BASE + 0x204)
+#define SPM_MP0_CPU0_PWR_CON (SPM_BASE + 0x208)
+#define SPM_MP0_CPU1_PWR_CON (SPM_BASE + 0x20C)
+#define SPM_MP0_CPU2_PWR_CON (SPM_BASE + 0x210)
+#define SPM_MP0_CPU3_PWR_CON (SPM_BASE + 0x214)
+#define SPM_MP1_CPUTOP_PWR_CON (SPM_BASE + 0x218)
+#define SPM_MP1_CPU0_PWR_CON (SPM_BASE + 0x21C)
+#define SPM_MP1_CPU1_PWR_CON (SPM_BASE + 0x220)
+#define SPM_MP1_CPU2_PWR_CON (SPM_BASE + 0x224)
+#define SPM_MP1_CPU3_PWR_CON (SPM_BASE + 0x228)
+#define SPM_MP0_CPUTOP_L2_PDN (SPM_BASE + 0x240)
+#define SPM_MP0_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x244)
+#define SPM_MP0_CPU0_L1_PDN (SPM_BASE + 0x248)
+#define SPM_MP0_CPU1_L1_PDN (SPM_BASE + 0x24C)
+#define SPM_MP0_CPU2_L1_PDN (SPM_BASE + 0x250)
+#define SPM_MP0_CPU3_L1_PDN (SPM_BASE + 0x254)
+#define SPM_MP1_CPUTOP_L2_PDN (SPM_BASE + 0x258)
+#define SPM_MP1_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x25C)
+#define SPM_MP1_CPU0_L1_PDN (SPM_BASE + 0x260)
+#define SPM_MP1_CPU1_L1_PDN (SPM_BASE + 0x264)
+#define SPM_MP1_CPU2_L1_PDN (SPM_BASE + 0x268)
+#define SPM_MP1_CPU3_L1_PDN (SPM_BASE + 0x26C)
+
+#define SPM_CPU_EXT_BUCK_ISO (SPM_BASE + 0x290)
+/* bit-fields of SPM_CPU_EXT_BUCK_ISO */
+#define MP0_EXT_BUCK_ISO (1 << 0)
+#define MP1_EXT_BUCK_ISO (1 << 1)
+#define MP_EXT_BUCK_ISO (1 << 2)
+
+/* bit-fields of SPM_PWR_STATUS */
+#define PWR_STATUS_MD (1 << 0)
+#define PWR_STATUS_CONN (1 << 1)
+#define PWR_STATUS_DDRPHY (1 << 2)
+#define PWR_STATUS_DISP (1 << 3)
+#define PWR_STATUS_MFG (1 << 4)
+#define PWR_STATUS_ISP (1 << 5)
+#define PWR_STATUS_INFRA (1 << 6)
+#define PWR_STATUS_VDEC (1 << 7)
+#define PWR_STATUS_MP0_CPUTOP (1 << 8)
+#define PWR_STATUS_MP0_CPU0 (1 << 9)
+#define PWR_STATUS_MP0_CPU1 (1 << 10)
+#define PWR_STATUS_MP0_CPU2 (1 << 11)
+#define PWR_STATUS_MP0_CPU3 (1 << 12)
+#define PWR_STATUS_MCUSYS (1 << 14)
+#define PWR_STATUS_MP1_CPUTOP (1 << 15)
+#define PWR_STATUS_MP1_CPU0 (1 << 16)
+#define PWR_STATUS_MP1_CPU1 (1 << 17)
+#define PWR_STATUS_MP1_CPU2 (1 << 18)
+#define PWR_STATUS_MP1_CPU3 (1 << 19)
+#define PWR_STATUS_VEN (1 << 21)
+#define PWR_STATUS_MFG_ASYNC (1 << 23)
+#define PWR_STATUS_AUDIO (1 << 24)
+#define PWR_STATUS_C2K (1 << 28)
+#define PWR_STATUS_MD_INFRA (1 << 29)
+
+
+/* bit-fields of SPM_*_PWR_CON */
+#define PWRCTRL_PWR_RST_B (1 << 0)
+#define PWRCTRL_PWR_ISO (1 << 1)
+#define PWRCTRL_PWR_ON (1 << 2)
+#define PWRCTRL_PWR_ON_2ND (1 << 3)
+#define PWRCTRL_PWR_CLK_DIS (1 << 4)
+#define PWRCTRL_PWR_SRAM_CKISO (1 << 5)
+#define PWRCTRL_PWR_SRAM_ISOINT_B (1 << 6)
+#define PWRCTRL_PWR_SRAM_PD_SLPB_CLAMP (1 << 7)
+#define PWRCTRL_PWR_SRAM_PDN (1 << 8)
+#define PWRCTRL_PWR_SRAM_SLEEP_B (1 << 12)
+#define PWRCTRL_PWR_SRAM_PDN_ACK (1 << 24)
+#define PWRCTRL_PWR_SRAM_SLEEP_B_ACK (1 << 28)
+
+/* per_cpu registers for SPM_MP?_CPU?_PWR_CON */
+static const struct per_cpu_reg SPM_CPU_PWR[] = {
+ [0] = { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2 },
+ [1] = { .cluster_addr = SPM_MP1_CPU0_PWR_CON, .cpu_stride = 2 },
+};
+
+/* per_cluster registers for SPM_MP?_CPUTOP_PWR_CON */
+static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
+ [0] = { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON },
+ [1] = { .cluster_addr = SPM_MP1_CPUTOP_PWR_CON },
+};
+
+/* APB Module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN_1 (INFRACFG_AO_BASE + 0x250)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1 (INFRACFG_AO_BASE + 0x258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET (INFRACFG_AO_BASE + 0x2A8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR (INFRACFG_AO_BASE + 0x2AC)
+
+/* bit-fields of INFRA_TOPAXI_PROTECTEN_1_SET */
+#define MP0_CPUTOP_PROT_STEP1_0_MASK ((1 << 10)|(1 << 12)| \
+ (1 << 13)|(1 << 26))
+#define MP1_CPUTOP_PROT_STEP1_0_MASK ((1 << 11)|(1 << 14)| \
+ (1 << 15)|(1 << 27))
+
+/* bit-fields of INFRA_TOPAXI_PROTECTEN_STA1_1 */
+#define MP0_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 10)|(1 << 12)| \
+ (1 << 13)|(1 << 26))
+#define MP1_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 11)|(1 << 14)| \
+ (1 << 15)|(1 << 27))
+
+
+/*
+ * MCU configuration registers
+ */
+
+/* bit-fields of MCUCFG_MP?_AXI_CONFIG */
+#define MCUCFG_AXI_CONFIG_BROADCASTINNER (1 << 0)
+#define MCUCFG_AXI_CONFIG_BROADCASTOUTER (1 << 1)
+#define MCUCFG_AXI_CONFIG_BROADCASTCACHEMAINT (1 << 2)
+#define MCUCFG_AXI_CONFIG_SYSBARDISABLE (1 << 3)
+#define MCUCFG_AXI_CONFIG_ACINACTM (1 << 4)
+#define MCUCFG_AXI_CONFIG_AINACTS (1 << 5)
+
+
+#define MCUCFG_MP0_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[2])
+#define MCUCFG_MP0_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[3])
+#define MCUCFG_MP1_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[2])
+#define MCUCFG_MP1_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[3])
+
+#define MCUCFG_CPUSYS0_SPARKVRETCNTRL (MCUCFG_BASE + 0x1c00)
+/* bit-fields of MCUCFG_CPUSYS0_SPARKVRETCNTRL */
+#define CPU0_SPARK_VRET_CTRL (0x3f << 0)
+#define CPU1_SPARK_VRET_CTRL (0x3f << 8)
+#define CPU2_SPARK_VRET_CTRL (0x3f << 16)
+#define CPU3_SPARK_VRET_CTRL (0x3f << 24)
+
+/* SPARK control in little cores */
+#define MCUCFG_CPUSYS0_CPU0_SPMC_CTL (MCUCFG_BASE + 0x1c30)
+#define MCUCFG_CPUSYS0_CPU1_SPMC_CTL (MCUCFG_BASE + 0x1c34)
+#define MCUCFG_CPUSYS0_CPU2_SPMC_CTL (MCUCFG_BASE + 0x1c38)
+#define MCUCFG_CPUSYS0_CPU3_SPMC_CTL (MCUCFG_BASE + 0x1c3c)
+/* bit-fields of MCUCFG_CPUSYS0_CPU?_SPMC_CTL */
+#define SW_SPARK_EN (1 << 0)
+#define SW_NO_WAIT_Q (1 << 1)
+
+/* the MCUCFG which BIG cores used is at (MCUCFG_BASE + 0x2000) */
+#define MCUCFG_MP2_BASE (MCUCFG_BASE + 0x2000)
+#define MCUCFG_MP2_PWR_RST_CTL (MCUCFG_MP2_BASE + 0x8)
+/* bit-fields of MCUCFG_MP2_PWR_RST_CTL */
+#define SW_RST_B (1 << 0)
+#define TOPAON_APB_MASK (1 << 1)
+
+#define MCUCFG_MP2_CPUCFG (MCUCFG_MP2_BASE + 0x208)
+
+#define MCUCFG_MP2_RVADDR0 (MCUCFG_MP2_BASE + 0x290)
+#define MCUCFG_MP2_RVADDR1 (MCUCFG_MP2_BASE + 0x298)
+#define MCUCFG_MP2_RVADDR2 (MCUCFG_MP2_BASE + 0x2c0)
+#define MCUCFG_MP2_RVADDR3 (MCUCFG_MP2_BASE + 0x2c8)
+
+/* SPMC control */
+#define MCUCFG_MP0_SPMC (MCUCFG_BASE + 0x788)
+#define MCUCFG_MP2_SPMC (MCUCFG_MP2_BASE + 0x2a0)
+#define MCUCFG_MP2_COQ (MCUCFG_MP2_BASE + 0x2bC)
+
+/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG2 */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+ [0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG2, .cpu_stride = 3 },
+};
+
+/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG3 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+ [0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG3 },
+ [1] = { .cluster_addr = MCUCFG_MP2_CPUCFG },
+};
+
+/* SPARK control in BIG cores */
+#define MCUCFG_MP2_PTP3_CPU0_SPMC0 (MCUCFG_MP2_BASE + 0x430)
+#define MCUCFG_MP2_PTP3_CPU0_SPMC1 (MCUCFG_MP2_BASE + 0x434)
+#define MCUCFG_MP2_PTP3_CPU1_SPMC0 (MCUCFG_MP2_BASE + 0x438)
+#define MCUCFG_MP2_PTP3_CPU1_SPMC1 (MCUCFG_MP2_BASE + 0x43c)
+#define MCUCFG_MP2_PTP3_CPU2_SPMC0 (MCUCFG_MP2_BASE + 0x440)
+#define MCUCFG_MP2_PTP3_CPU2_SPMC1 (MCUCFG_MP2_BASE + 0x444)
+#define MCUCFG_MP2_PTP3_CPU3_SPMC0 (MCUCFG_MP2_BASE + 0x448)
+#define MCUCFG_MP2_PTP3_CPU3_SPMC1 (MCUCFG_MP2_BASE + 0x44c)
+/* bit-fields of MCUCFG_MP2_PTP3_CPU?_SPMC? */
+#define SW_SPARK_EN (1 << 0)
+#define SW_NO_WAIT_Q (1 << 1)
+
+#define MCUCFG_MP2_SPARK2LDO (MCUCFG_MP2_BASE + 0x700)
+/* bit-fields of MCUCFG_MP2_SPARK2LDO */
+#define SPARK_VRET_CTRL (0x3f << 0)
+#define CPU0_SPARK_LDO_AMUXSEL (0xf << 6)
+#define CPU1_SPARK_LDO_AMUXSEL (0xf << 10)
+#define CPU2_SPARK_LDO_AMUXSEL (0xf << 14)
+#define CPU3_SPARK_LDO_AMUXSEL (0xf << 18)
+
+/* per_cpu registers for SPARK */
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+ [0] = { .cluster_addr = MCUCFG_CPUSYS0_CPU0_SPMC_CTL, .cpu_stride = 2 },
+ [1] = { .cluster_addr = MCUCFG_MP2_PTP3_CPU0_SPMC0, .cpu_stride = 3 },
+};
+
+/* per_cpu registers for SPARK2LDO */
+static const struct per_cpu_reg MCUCFG_SPARK2LDO[] = {
+ [0] = { .cluster_addr = MCUCFG_CPUSYS0_SPARKVRETCNTRL },
+ [1] = { .cluster_addr = MCUCFG_MP2_SPARK2LDO },
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8183/drivers/sspm/sspm.c b/plat/mediatek/mt8183/drivers/sspm/sspm.c
new file mode 100644
index 0000000..6e76124
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/sspm/sspm.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <sspm.h>
+
+static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len)
+{
+ while (len--) {
+ mmio_write_32(dst, *src);
+ dst += sizeof(uint32_t);
+ src++;
+ }
+}
+
+static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len)
+{
+ while (len--) {
+ *dst = mmio_read_32(src);
+ dst++;
+ src += sizeof(uint32_t);
+ }
+}
+
+int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len)
+{
+ if (slot >= 32) {
+ ERROR("%s:slot = %d\n", __func__, slot);
+ return -EINVAL;
+ }
+
+ if (data)
+ memcpy_from_sspm(data,
+ MBOX3_BASE + slot * 4,
+ len);
+
+ return 0;
+}
+
+int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len)
+{
+ if (slot >= 32) {
+ ERROR("%s:slot = %d\n", __func__, slot);
+ return -EINVAL;
+ }
+
+ if (data)
+ memcpy_to_sspm(MBOX3_BASE + slot * 4,
+ data,
+ len);
+
+ return 0;
+}
+
+static int sspm_ipi_check_ack(uint32_t id)
+{
+ int ret = 0;
+
+ if (id == IPI_ID_PLATFORM) {
+ if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1)
+ ret = -EINPROGRESS;
+ } else if (id == IPI_ID_SUSPEND) {
+ if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2)
+ ret = -EINPROGRESS;
+ } else {
+ ERROR("%s: id = %d\n", __func__, id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data)
+{
+ int ret = 0;
+
+ ret = sspm_ipi_check_ack(id);
+ if (ret)
+ return ret;
+
+ if (id == IPI_ID_PLATFORM) {
+ memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
+ data,
+ PINR_SIZE_PLATFORM);
+ dsb();
+ mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1);
+ } else if (id == IPI_ID_SUSPEND) {
+ memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
+ data,
+ PINR_SIZE_SUSPEND);
+ dsb();
+ mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS,
+ 0x2);
+ }
+
+ return 0;
+}
+
+int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len)
+{
+ int ret = 0;
+
+ ret = sspm_ipi_check_ack(id);
+ if (ret == -EINPROGRESS) {
+ if (id == IPI_ID_PLATFORM) {
+ memcpy_from_sspm(data,
+ MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
+ len);
+ dsb();
+ /* clear interrupt bit*/
+ mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS,
+ 0x1);
+ ret = 0;
+ } else if (id == IPI_ID_SUSPEND) {
+ memcpy_from_sspm(data,
+ MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
+ len);
+ dsb();
+ /* clear interrupt bit*/
+ mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS,
+ 0x2);
+ ret = 0;
+ }
+ } else if (ret == 0) {
+ ret = -EBUSY;
+ }
+
+ return ret;
+}
+
+int sspm_alive_show(void)
+{
+ uint32_t ipi_data, count;
+ int ret = 0;
+
+ count = 5;
+ ipi_data = 0xdead;
+
+ if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) {
+ ERROR("sspm init send fail! ret=%d\n", ret);
+ return -1;
+ }
+
+ while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM,
+ &ipi_data,
+ sizeof(ipi_data) / sizeof(uint32_t))
+ && count) {
+ mdelay(100);
+ count--;
+ }
+
+ return (ipi_data == 1) ? 0 : -1;
+}
diff --git a/plat/mediatek/mt8183/drivers/sspm/sspm.h b/plat/mediatek/mt8183/drivers/sspm/sspm.h
new file mode 100644
index 0000000..2c2cc10
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/sspm/sspm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __SSPM_H__
+#define __SSPM_H__
+/* These should sync with sspm.bin */
+#define IPI_ID_PLATFORM 0
+#define IPI_ID_SUSPEND 6
+#define PINR_OFFSET_PLATFORM 0
+#define PINR_SIZE_PLATFORM 3
+#define PINR_OFFSET_SUSPEND 2
+#define PINR_SIZE_SUSPEND 8
+
+#define MBOX0_BASE 0x10450000
+#define MBOX1_BASE 0x10460000
+#define MBOX3_BASE 0x10480000
+#define MBOX_OUT_IRQ_OFS 0x1000
+#define MBOX_IN_IRQ_OFS 0x1004
+
+#define SHAREMBOX_OFFSET_MCDI 0
+#define SHAREMBOX_SIZE_MCDI 20
+#define SHAREMBOX_OFFSET_SUSPEND 26
+#define SHAREMBOX_SIZE_SUSPEND 6
+
+int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len);
+int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len);
+int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data);
+int sspm_ipi_recv_non_blocking(uint32_t slot, uint32_t *data, uint32_t len);
+int sspm_alive_show(void);
+#endif /* __SSPM_H__ */
diff --git a/plat/mediatek/mt8183/drivers/timer/mt_timer.c b/plat/mediatek/mt8183/drivers/timer/mt_timer.c
new file mode 100644
index 0000000..0da4815
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/timer/mt_timer.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mcucfg.h>
+#include <mt_timer.h>
+#include <platform_def.h>
+
+static void enable_systimer_compensation(void)
+{
+ unsigned int reg;
+
+ reg = mmio_read_32(CNTCR_REG);
+ reg &= ~COMP_15_EN;
+ reg |= COMP_20_EN;
+ mmio_write_32(CNTCR_REG, reg);
+
+ NOTICE("[systimer] CNTCR_REG(0x%x)\n", mmio_read_32(CNTCR_REG));
+}
+
+void mt_systimer_init(void)
+{
+ /* systimer is default on, so we only enable systimer compensation */
+ enable_systimer_compensation();
+}
diff --git a/plat/mediatek/mt8183/drivers/timer/mt_timer.h b/plat/mediatek/mt8183/drivers/timer/mt_timer.h
new file mode 100644
index 0000000..0b8edc5
--- /dev/null
+++ b/plat/mediatek/mt8183/drivers/timer/mt_timer.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_TIMER_H
+#define MT_TIMER_H
+
+
+#define SYSTIMER_BASE (0x10017000)
+#define CNTCR_REG (SYSTIMER_BASE + 0x0)
+#define CNTSR_REG (SYSTIMER_BASE + 0x4)
+
+#define COMP_15_EN (1 << 10)
+#define COMP_20_EN (1 << 11)
+
+void mt_systimer_init(void);
+
+#endif /* MT_TIMER_H */
diff --git a/plat/mediatek/mt8183/include/mcucfg.h b/plat/mediatek/mt8183/include/mcucfg.h
new file mode 100644
index 0000000..6b03818
--- /dev/null
+++ b/plat/mediatek/mt8183/include/mcucfg.h
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT8183_MCUCFG_H
+#define MT8183_MCUCFG_H
+
+#include <platform_def.h>
+#include <stdint.h>
+
+struct mt8183_mcucfg_regs {
+ uint32_t mp0_ca7l_cache_config; /* 0x0 */
+ struct {
+ uint32_t mem_delsel0;
+ uint32_t mem_delsel1;
+ } mp0_cpu[4]; /* 0x4 */
+ uint32_t mp0_cache_mem_delsel0; /* 0x24 */
+ uint32_t mp0_cache_mem_delsel1; /* 0x28 */
+ uint32_t mp0_axi_config; /* 0x2C */
+ uint32_t mp0_misc_config[10]; /* 0x30 */
+ uint32_t mp0_ca7l_cfg_dis; /* 0x58 */
+ uint32_t mp0_ca7l_clken_ctrl; /* 0x5C */
+ uint32_t mp0_ca7l_rst_ctrl; /* 0x60 */
+ uint32_t mp0_ca7l_misc_config; /* 0x64 */
+ uint32_t mp0_ca7l_dbg_pwr_ctrl; /* 0x68 */
+ uint32_t mp0_rw_rsvd0; /* 0x6C */
+ uint32_t mp0_rw_rsvd1; /* 0x70 */
+ uint32_t mp0_ro_rsvd; /* 0x74 */
+ uint32_t reserved0_0; /* 0x78 */
+ uint32_t mp0_l2_cache_parity1_rdata; /* 0x7C */
+ uint32_t mp0_l2_cache_parity2_rdata; /* 0x80 */
+ uint32_t reserved0_1; /* 0x84 */
+ uint32_t mp0_rgu_dcm_config; /* 0x88 */
+ uint32_t mp0_ca53_specific_ctrl; /* 0x8C */
+ uint32_t mp0_esr_case; /* 0x90 */
+ uint32_t mp0_esr_mask; /* 0x94 */
+ uint32_t mp0_esr_trig_en; /* 0x98 */
+ uint32_t reserved_0_2; /* 0x9C */
+ uint32_t mp0_ses_cg_en; /* 0xA0 */
+ uint32_t reserved0_3[216]; /* 0xA4 */
+ uint32_t mp_dbg_ctrl; /* 0x404 */
+ uint32_t reserved0_4[34]; /* 0x408 */
+ uint32_t mp_dfd_ctrl; /* 0x490 */
+ uint32_t dfd_cnt_l; /* 0x494 */
+ uint32_t dfd_cnt_h; /* 0x498 */
+ uint32_t misccfg_ro_rsvd; /* 0x49C */
+ uint32_t reserved0_5[24]; /* 0x4A0 */
+ uint32_t mp1_rst_status; /* 0x500 */
+ uint32_t mp1_dbg_ctrl; /* 0x504 */
+ uint32_t mp1_dbg_flag; /* 0x508 */
+ uint32_t mp1_ca7l_ir_mon; /* 0x50C */
+ uint32_t reserved0_6[32]; /* 0x510 */
+ uint32_t mcusys_dbg_mon_sel_a; /* 0x590 */
+ uint32_t mcucys_dbg_mon; /* 0x594 */
+ uint32_t misccfg_sec_voi_status0; /* 0x598 */
+ uint32_t misccfg_sec_vio_status1; /* 0x59C */
+ uint32_t reserved0_7[18]; /* 0x5A0 */
+ uint32_t gic500_int_mask; /* 0x5E8 */
+ uint32_t core_rst_en_latch; /* 0x5EC */
+ uint32_t reserved0_8[3]; /* 0x5F0 */
+ uint32_t dbg_core_ret; /* 0x5FC */
+ uint32_t mcusys_config_a; /* 0x600 */
+ uint32_t mcusys_config1_a; /* 0x604 */
+ uint32_t mcusys_gic_prebase_a; /* 0x608 */
+ uint32_t mcusys_pinmux; /* 0x60C */
+ uint32_t sec_range0_start; /* 0x610 */
+ uint32_t sec_range0_end; /* 0x614 */
+ uint32_t sec_range_enable; /* 0x618 */
+ uint32_t l2c_mm_base; /* 0x61C */
+ uint32_t reserved0_9[8]; /* 0x620 */
+ uint32_t aclken_div; /* 0x640 */
+ uint32_t pclken_div; /* 0x644 */
+ uint32_t l2c_sram_ctrl; /* 0x648 */
+ uint32_t armpll_jit_ctrl; /* 0x64C */
+ uint32_t cci_addrmap; /* 0x650 */
+ uint32_t cci_config; /* 0x654 */
+ uint32_t cci_periphbase; /* 0x658 */
+ uint32_t cci_nevntcntovfl; /* 0x65C */
+ uint32_t cci_clk_ctrl; /* 0x660 */
+ uint32_t cci_acel_s1_ctrl; /* 0x664 */
+ uint32_t mcusys_bus_fabric_dcm_ctrl; /* 0x668 */
+ uint32_t mcu_misc_dcm_ctrl; /* 0x66C */
+ uint32_t xgpt_ctl; /* 0x670 */
+ uint32_t xgpt_idx; /* 0x674 */
+ uint32_t reserved0_10[3]; /* 0x678 */
+ uint32_t mcusys_rw_rsvd0; /* 0x684 */
+ uint32_t mcusys_rw_rsvd1; /* 0x688 */
+ uint32_t reserved0_11[13]; /* 0x68C */
+ uint32_t gic_500_delsel_ctl; /* 0x6C0 */
+ uint32_t etb_delsel_ctl; /* 0x6C4 */
+ uint32_t etb_rst_ctl; /* 0x6C8 */
+ uint32_t reserved0_12[29]; /* 0x6CC */
+ uint32_t cci_adb400_dcm_config; /* 0x740 */
+ uint32_t sync_dcm_config; /* 0x744 */
+ uint32_t reserved0_13; /* 0x748 */
+ uint32_t sync_dcm_cluster_config; /* 0x74C */
+ uint32_t sw_udi; /* 0x750 */
+ uint32_t reserved0_14; /* 0x754 */
+ uint32_t gic_sync_dcm; /* 0x758 */
+ uint32_t big_dbg_pwr_ctrl; /* 0x75C */
+ uint32_t gic_cpu_periphbase; /* 0x760 */
+ uint32_t axi_cpu_config; /* 0x764 */
+ uint32_t reserved0_15[2]; /* 0x768 */
+ uint32_t mcsib_sys_ctrl1; /* 0x770 */
+ uint32_t mcsib_sys_ctrl2; /* 0x774 */
+ uint32_t mcsib_sys_ctrl3; /* 0x778 */
+ uint32_t mcsib_sys_ctrl4; /* 0x77C */
+ uint32_t mcsib_dbg_ctrl1; /* 0x780 */
+ uint32_t pwrmcu_apb2to1; /* 0x784 */
+ uint32_t mp0_spmc; /* 0x788 */
+ uint32_t reserved0_16; /* 0x78C */
+ uint32_t mp0_spmc_sram_ctl; /* 0x790 */
+ uint32_t reserved0_17; /* 0x794 */
+ uint32_t mp0_sw_rst_wait_cycle; /* 0x798 */
+ uint32_t reserved0_18; /* 0x79C */
+ uint32_t mp0_pll_divider_cfg; /* 0x7A0 */
+ uint32_t reserved0_19; /* 0x7A4 */
+ uint32_t mp2_pll_divider_cfg; /* 0x7A8 */
+ uint32_t reserved0_20[5]; /* 0x7AC */
+ uint32_t bus_pll_divider_cfg; /* 0x7C0 */
+ uint32_t reserved0_21[7]; /* 0x7C4 */
+ uint32_t clusterid_aff1; /* 0x7E0 */
+ uint32_t clusterid_aff2; /* 0x7E4 */
+ uint32_t reserved0_22[2]; /* 0x7E8 */
+ uint32_t l2_cfg_mp0; /* 0x7F0 */
+ uint32_t l2_cfg_mp1; /* 0x7F4 */
+ uint32_t reserved0_23[218]; /* 0x7F8 */
+ uint32_t mscib_dcm_en; /* 0xB60 */
+ uint32_t reserved0_24[1063]; /* 0xB64 */
+ uint32_t cpusys0_sparkvretcntrl; /* 0x1C00 */
+ uint32_t cpusys0_sparken; /* 0x1C04 */
+ uint32_t cpusys0_amuxsel; /* 0x1C08 */
+ uint32_t reserved0_25[9]; /* 0x1C0C */
+ uint32_t cpusys0_cpu0_spmc_ctl; /* 0x1C30 */
+ uint32_t cpusys0_cpu1_spmc_ctl; /* 0x1C34 */
+ uint32_t cpusys0_cpu2_spmc_ctl; /* 0x1C38 */
+ uint32_t cpusys0_cpu3_spmc_ctl; /* 0x1C3C */
+ uint32_t reserved0_26[8]; /* 0x1C40 */
+ uint32_t mp0_sync_dcm_cgavg_ctrl; /* 0x1C60 */
+ uint32_t mp0_sync_dcm_cgavg_fact; /* 0x1C64 */
+ uint32_t mp0_sync_dcm_cgavg_rfact; /* 0x1C68 */
+ uint32_t mp0_sync_dcm_cgavg; /* 0x1C6C */
+ uint32_t mp0_l2_parity_clr; /* 0x1C70 */
+ uint32_t reserved0_27[357]; /* 0x1C74 */
+ uint32_t mp2_cpucfg; /* 0x2208 */
+ uint32_t mp2_axi_config; /* 0x220C */
+ uint32_t reserved0_28[25]; /* 0x2210 */
+ uint32_t mp2_sync_dcm; /* 0x2274 */
+ uint32_t reserved0_29[10]; /* 0x2278 */
+ uint32_t ptp3_cputop_spmc0; /* 0x22A0 */
+ uint32_t ptp3_cputop_spmc1; /* 0x22A4 */
+ uint32_t reserved0_30[98]; /* 0x22A8 */
+ uint32_t ptp3_cpu0_spmc0; /* 0x2430 */
+ uint32_t ptp3_cpu0_spmc1; /* 0x2434 */
+ uint32_t ptp3_cpu1_spmc0; /* 0x2438 */
+ uint32_t ptp3_cpu1_spmc1; /* 0x243C */
+ uint32_t ptp3_cpu2_spmc0; /* 0x2440 */
+ uint32_t ptp3_cpu2_spmc1; /* 0x2444 */
+ uint32_t ptp3_cpu3_spmc0; /* 0x2448 */
+ uint32_t ptp3_cpu3_spmc1; /* 0x244C */
+ uint32_t ptp3_cpux_spmc; /* 0x2450 */
+ uint32_t reserved0_31[171]; /* 0x2454 */
+ uint32_t spark2ld0; /* 0x2700 */
+};
+
+static struct mt8183_mcucfg_regs *const mt8183_mcucfg = (void *)MCUCFG_BASE;
+
+enum {
+ SW_SPARK_EN = 1 << 0,
+ SW_NO_WAIT_FOR_Q_CHANNEL = 1 << 1,
+ SW_FSM_OVERRIDE = 1 << 2,
+ SW_LOGIC_PRE1_PDB = 1 << 3,
+ SW_LOGIC_PRE2_PDB = 1 << 4,
+ SW_LOGIC_PDB = 1 << 5,
+ SW_ISO = 1 << 6,
+ SW_SRAM_SLEEPB = 0x3f << 7,
+ SW_SRAM_ISOINTB = 1 << 13,
+ SW_CLK_DIS = 1 << 14,
+ SW_CKISO = 1 << 15,
+ SW_PD = 0x3f << 16,
+ SW_HOT_PLUG_RESET = 1 << 22,
+ SW_PWR_ON_OVERRIDE_EN = 1 << 23,
+ SW_PWR_ON = 1 << 24,
+ SW_COQ_DIS = 1 << 25,
+ LOGIC_PDBO_ALL_OFF_ACK = 1 << 26,
+ LOGIC_PDBO_ALL_ON_ACK = 1 << 27,
+ LOGIC_PRE2_PDBO_ALL_ON_ACK = 1 << 28,
+ LOGIC_PRE1_PDBO_ALL_ON_ACK = 1 << 29
+};
+
+enum {
+ CPU_SW_SPARK_EN = 1 << 0,
+ CPU_SW_NO_WAIT_FOR_Q_CHANNEL = 1 << 1,
+ CPU_SW_FSM_OVERRIDE = 1 << 2,
+ CPU_SW_LOGIC_PRE1_PDB = 1 << 3,
+ CPU_SW_LOGIC_PRE2_PDB = 1 << 4,
+ CPU_SW_LOGIC_PDB = 1 << 5,
+ CPU_SW_ISO = 1 << 6,
+ CPU_SW_SRAM_SLEEPB = 1 << 7,
+ CPU_SW_SRAM_ISOINTB = 1 << 8,
+ CPU_SW_CLK_DIS = 1 << 9,
+ CPU_SW_CKISO = 1 << 10,
+ CPU_SW_PD = 0x1f << 11,
+ CPU_SW_HOT_PLUG_RESET = 1 << 16,
+ CPU_SW_POWR_ON_OVERRIDE_EN = 1 << 17,
+ CPU_SW_PWR_ON = 1 << 18,
+ CPU_SPARK2LDO_ALLSWOFF = 1 << 19,
+ CPU_PDBO_ALL_ON_ACK = 1 << 20,
+ CPU_PRE2_PDBO_ALLON_ACK = 1 << 21,
+ CPU_PRE1_PDBO_ALLON_ACK = 1 << 22
+};
+
+enum {
+ MP2_AXI_CONFIG_ACINACTM = 1 << 0,
+ MPx_AXI_CONFIG_ACINACTM = 1 << 4,
+ MPX_CA7_MISC_CONFIG_STANDBYWFIL2 = 1 << 28
+};
+
+enum {
+ MP0_CPU0_STANDBYWFE = 1 << 20,
+ MP0_CPU1_STANDBYWFE = 1 << 21,
+ MP0_CPU2_STANDBYWFE = 1 << 22,
+ MP0_CPU3_STANDBYWFE = 1 << 23
+};
+
+enum {
+ MP1_CPU0_STANDBYWFE = 1 << 20,
+ MP1_CPU1_STANDBYWFE = 1 << 21,
+ MP1_CPU2_STANDBYWFE = 1 << 22,
+ MP1_CPU3_STANDBYWFE = 1 << 23
+};
+
+enum {
+ B_SW_HOT_PLUG_RESET = 1 << 30,
+ B_SW_PD_OFFSET = 18,
+ B_SW_PD = 0x3f << B_SW_PD_OFFSET,
+ B_SW_SRAM_SLEEPB_OFFSET = 12,
+ B_SW_SRAM_SLEEPB = 0x3f << B_SW_SRAM_SLEEPB_OFFSET
+};
+
+enum {
+ B_SW_SRAM_ISOINTB = 1 << 9,
+ B_SW_ISO = 1 << 8,
+ B_SW_LOGIC_PDB = 1 << 7,
+ B_SW_LOGIC_PRE2_PDB = 1 << 6,
+ B_SW_LOGIC_PRE1_PDB = 1 << 5,
+ B_SW_FSM_OVERRIDE = 1 << 4,
+ B_SW_PWR_ON = 1 << 3,
+ B_SW_PWR_ON_OVERRIDE_EN = 1 << 2
+};
+
+enum {
+ B_FSM_STATE_OUT_OFFSET = 6,
+ B_FSM_STATE_OUT_MASK = 0x1f << B_FSM_STATE_OUT_OFFSET,
+ B_SW_LOGIC_PDBO_ALL_OFF_ACK = 1 << 5,
+ B_SW_LOGIC_PDBO_ALL_ON_ACK = 1 << 4,
+ B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK = 1 << 3,
+ B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK = 1 << 2,
+ B_FSM_OFF = 0 << B_FSM_STATE_OUT_OFFSET,
+ B_FSM_ON = 1 << B_FSM_STATE_OUT_OFFSET,
+ B_FSM_RET = 2 << B_FSM_STATE_OUT_OFFSET
+};
+
+/* APB Module infracfg_ao */
+enum {
+ INFRA_TOPAXI_PROTECTEN_1 = INFRACFG_AO_BASE + 0x250,
+ INFRA_TOPAXI_PROTECTSTA1_1 = INFRACFG_AO_BASE + 0x258,
+ INFRA_TOPAXI_PROTECTEN_1_SET = INFRACFG_AO_BASE + 0x2A8,
+ INFRA_TOPAXI_PROTECTEN_1_CLR = INFRACFG_AO_BASE + 0x2AC
+};
+
+enum {
+ IDX_PROTECT_MP0_CACTIVE = 10,
+ IDX_PROTECT_MP1_CACTIVE = 11,
+ IDX_PROTECT_ICC0_CACTIVE = 12,
+ IDX_PROTECT_ICD0_CACTIVE = 13,
+ IDX_PROTECT_ICC1_CACTIVE = 14,
+ IDX_PROTECT_ICD1_CACTIVE = 15,
+ IDX_PROTECT_L2C0_CACTIVE = 26,
+ IDX_PROTECT_L2C1_CACTIVE = 27
+};
+
+/* cpu boot mode */
+enum {
+ MP0_CPUCFG_64BIT_SHIFT = 12,
+ MP1_CPUCFG_64BIT_SHIFT = 28,
+ MP0_CPUCFG_64BIT = 0xf << MP0_CPUCFG_64BIT_SHIFT,
+ MP1_CPUCFG_64BIT = 0xfu << MP1_CPUCFG_64BIT_SHIFT
+};
+
+/* scu related */
+enum {
+ MP0_ACINACTM_SHIFT = 4,
+ MP1_ACINACTM_SHIFT = 4,
+ MP2_ACINACTM_SHIFT = 0,
+ MP0_ACINACTM = 1 << MP0_ACINACTM_SHIFT,
+ MP1_ACINACTM = 1 << MP1_ACINACTM_SHIFT,
+ MP2_ACINACTM = 1 << MP2_ACINACTM_SHIFT
+};
+
+enum {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16,
+
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+ 0xf << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+ MP1_AINACTS_SHIFT = 4,
+ MP1_AINACTS = 1 << MP1_AINACTS_SHIFT
+};
+
+enum {
+ MP1_SW_CG_GEN_SHIFT = 12,
+ MP1_SW_CG_GEN = 1 << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+ MP1_L2RSTDISABLE_SHIFT = 14,
+ MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT
+};
+
+/* bus pll divider dcm related */
+enum {
+ BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT = 11,
+ BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
+ BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
+
+ BUS_PLLDIV_DCM = (1 << BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT) |
+ (1 << BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
+ (1 << BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT)
+};
+
+/* mp0 pll divider dcm related */
+enum {
+ MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11,
+ MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
+ MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
+ MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31,
+ MP0_PLLDIV_DCM = (1 << MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT) |
+ (1 << MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
+ (1 << MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT) |
+ (1u << MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT)
+};
+
+/* mp2 pll divider dcm related */
+enum {
+ MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11,
+ MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
+ MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
+ MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31,
+ MP2_PLLDIV_DCM = (1 << MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT) |
+ (1 << MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
+ (1 << MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT) |
+ (1u << MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT)
+};
+
+/* mcsib dcm related */
+enum {
+ MCSIB_CACTIVE_SEL_SHIFT = 0,
+ MCSIB_DCM_EN_SHIFT = 16,
+
+ MCSIB_CACTIVE_SEL_MASK = 0xffff << MCSIB_CACTIVE_SEL_SHIFT,
+ MCSIB_CACTIVE_SEL = 0xffff << MCSIB_CACTIVE_SEL_SHIFT,
+
+ MCSIB_DCM_MASK = 0xffffu << MCSIB_DCM_EN_SHIFT,
+ MCSIB_DCM = 0xffffu << MCSIB_DCM_EN_SHIFT,
+};
+
+/* cci adb400 dcm related */
+enum {
+ CCI_M0_ADB400_DCM_EN_SHIFT = 0,
+ CCI_M1_ADB400_DCM_EN_SHIFT = 1,
+ CCI_M2_ADB400_DCM_EN_SHIFT = 2,
+ CCI_S2_ADB400_DCM_EN_SHIFT = 3,
+ CCI_S3_ADB400_DCM_EN_SHIFT = 4,
+ CCI_S4_ADB400_DCM_EN_SHIFT = 5,
+ CCI_S5_ADB400_DCM_EN_SHIFT = 6,
+ ACP_S3_ADB400_DCM_EN_SHIFT = 11,
+
+ CCI_ADB400_DCM_MASK = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_M1_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_M2_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_S2_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_S4_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_S4_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_S5_ADB400_DCM_EN_SHIFT) |
+ (1 << ACP_S3_ADB400_DCM_EN_SHIFT),
+ CCI_ADB400_DCM = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_M1_ADB400_DCM_EN_SHIFT) |
+ (1 << CCI_M2_ADB400_DCM_EN_SHIFT) |
+ (0 << CCI_S2_ADB400_DCM_EN_SHIFT) |
+ (0 << CCI_S4_ADB400_DCM_EN_SHIFT) |
+ (0 << CCI_S4_ADB400_DCM_EN_SHIFT) |
+ (0 << CCI_S5_ADB400_DCM_EN_SHIFT) |
+ (1 << ACP_S3_ADB400_DCM_EN_SHIFT)
+};
+
+/* sync dcm related */
+enum {
+ CCI_SYNC_DCM_DIV_EN_SHIFT = 0,
+ CCI_SYNC_DCM_UPDATE_TOG_SHIFT = 1,
+ CCI_SYNC_DCM_DIV_SEL_SHIFT = 2,
+ MP0_SYNC_DCM_DIV_EN_SHIFT = 10,
+ MP0_SYNC_DCM_UPDATE_TOG_SHIFT = 11,
+ MP0_SYNC_DCM_DIV_SEL_SHIFT = 12,
+
+ SYNC_DCM_MASK = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) |
+ (1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) |
+ (0x7f << CCI_SYNC_DCM_DIV_SEL_SHIFT) |
+ (1 << MP0_SYNC_DCM_DIV_EN_SHIFT) |
+ (1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) |
+ (0x7f << MP0_SYNC_DCM_DIV_SEL_SHIFT),
+ SYNC_DCM = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) |
+ (1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) |
+ (0 << CCI_SYNC_DCM_DIV_SEL_SHIFT) |
+ (1 << MP0_SYNC_DCM_DIV_EN_SHIFT) |
+ (1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) |
+ (0 << MP0_SYNC_DCM_DIV_SEL_SHIFT)
+};
+
+/* mcu bus dcm related */
+enum {
+ MCU_BUS_DCM_EN_SHIFT = 8,
+ MCU_BUS_DCM = 1 << MCU_BUS_DCM_EN_SHIFT
+};
+
+/* mcusys bus fabric dcm related */
+enum {
+ ACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 0,
+ EMI2_ADB400_S_DCM_CTRL_SHIFT = 1,
+ ACLK_GPU_DYNAMIC_CG_EN_SHIFT = 2,
+ ACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 3,
+ MP0_ADB400_S_DCM_CTRL_SHIFT = 4,
+ MP0_ADB400_M_DCM_CTRL_SHIFT = 5,
+ MP1_ADB400_S_DCM_CTRL_SHIFT = 6,
+ MP1_ADB400_M_DCM_CTRL_SHIFT = 7,
+ EMICLK_EMI_DYNAMIC_CG_EN_SHIFT = 8,
+ INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 9,
+ EMICLK_GPU_DYNAMIC_CG_EN_SHIFT = 10,
+ INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 11,
+ EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT = 12,
+ EMI1_ADB400_S_DCM_CTRL_SHIFT = 16,
+ MP2_ADB400_M_DCM_CTRL_SHIFT = 17,
+ MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT = 18,
+ MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT = 19,
+ MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT = 20,
+ L2_SHARE_ADB400_DCM_CTRL_SHIFT = 21,
+ MP1_AGGRESS_DCM_CTRL_SHIFT = 22,
+ MP0_AGGRESS_DCM_CTRL_SHIFT = 23,
+ MP0_ADB400_ACP_S_DCM_CTRL_SHIFT = 24,
+ MP0_ADB400_ACP_M_DCM_CTRL_SHIFT = 25,
+ MP1_ADB400_ACP_S_DCM_CTRL_SHIFT = 26,
+ MP1_ADB400_ACP_M_DCM_CTRL_SHIFT = 27,
+ MP3_ADB400_M_DCM_CTRL_SHIFT = 28,
+ MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT = 29,
+
+ MCUSYS_BUS_FABRIC_DCM_MASK = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) |
+ (1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) |
+ (1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
+ (1 << MP0_ADB400_S_DCM_CTRL_SHIFT) |
+ (1 << MP0_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_S_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) |
+ (1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) |
+ (1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) |
+ (1 << MP2_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
+ (1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
+ (1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
+ (1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) |
+ (1 << MP1_AGGRESS_DCM_CTRL_SHIFT) |
+ (1 << MP0_AGGRESS_DCM_CTRL_SHIFT) |
+ (1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) |
+ (1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) |
+ (1 << MP3_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT),
+
+ MCUSYS_BUS_FABRIC_DCM = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) |
+ (1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) |
+ (1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
+ (0 << MP0_ADB400_S_DCM_CTRL_SHIFT) |
+ (0 << MP0_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_S_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) |
+ (1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) |
+ (1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) |
+ (1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) |
+ (0 << MP2_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
+ (1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
+ (1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
+ (1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) |
+ (1 << MP1_AGGRESS_DCM_CTRL_SHIFT) |
+ (1 << MP0_AGGRESS_DCM_CTRL_SHIFT) |
+ (1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) |
+ (1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) |
+ (1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) |
+ (1 << MP3_ADB400_M_DCM_CTRL_SHIFT) |
+ (1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT)
+};
+
+/* l2c_sram dcm related */
+enum {
+ L2C_SRAM_DCM_EN_SHIFT = 0,
+ L2C_SRAM_DCM = 1 << L2C_SRAM_DCM_EN_SHIFT
+};
+
+/* mcu misc dcm related */
+enum {
+ MP0_CNTVALUEB_DCM_EN_SHIFT = 0,
+ MP_CNTVALUEB_DCM_EN = 8,
+
+ CNTVALUEB_DCM = (1 << MP0_CNTVALUEB_DCM_EN_SHIFT) |
+ (1 << MP_CNTVALUEB_DCM_EN)
+};
+
+/* sync dcm cluster config related */
+enum {
+ MP0_SYNC_DCM_STALL_WR_EN_SHIFT = 7,
+ MCUSYS_MAX_ACCESS_LATENCY_SHIFT = 24,
+
+ MCU0_SYNC_DCM_STALL_WR_EN = 1 << MP0_SYNC_DCM_STALL_WR_EN_SHIFT,
+
+ MCUSYS_MAX_ACCESS_LATENCY_MASK = 0xf << MCUSYS_MAX_ACCESS_LATENCY_SHIFT,
+ MCUSYS_MAX_ACCESS_LATENCY = 0x5 << MCUSYS_MAX_ACCESS_LATENCY_SHIFT
+};
+
+/* cpusys rgu dcm related */
+enum {
+ CPUSYS_RGU_DCM_CONFIG_SHIFT = 0,
+
+ CPUSYS_RGU_DCM_CINFIG = 1 << CPUSYS_RGU_DCM_CONFIG_SHIFT
+};
+
+/* mp2 sync dcm related */
+enum {
+ MP2_DCM_EN_SHIFT = 0,
+
+ MP2_DCM_EN = 1 << MP2_DCM_EN_SHIFT
+};
+#endif /* MT8183_MCUCFG_H */
diff --git a/plat/mediatek/mt8183/include/mt_gic_v3.h b/plat/mediatek/mt8183/include/mt_gic_v3.h
new file mode 100644
index 0000000..b6fc29b
--- /dev/null
+++ b/plat/mediatek/mt8183/include/mt_gic_v3.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GIC_V3_H
+#define MT_GIC_V3_H
+
+#include <lib/mmio.h>
+
+#define GIC_INT_MASK (MCUCFG_BASE + 0x5e8)
+#define GIC500_ACTIVE_SEL_SHIFT 3
+#define GIC500_ACTIVE_SEL_MASK (0x7 << GIC500_ACTIVE_SEL_SHIFT)
+#define GIC500_ACTIVE_CPU_SHIFT 16
+#define GIC500_ACTIVE_CPU_MASK (0xff << GIC500_ACTIVE_CPU_SHIFT)
+
+#define NR_INT_POL_CTL 20
+
+void mt_gic_driver_init(void);
+void mt_gic_init(void);
+void mt_gic_set_pending(uint32_t irq);
+uint32_t mt_gic_get_pending(uint32_t irq);
+void mt_gic_cpuif_enable(void);
+void mt_gic_cpuif_disable(void);
+void mt_gic_rdistif_init(void);
+void mt_gic_distif_save(void);
+void mt_gic_distif_restore(void);
+void mt_gic_rdistif_save(void);
+void mt_gic_rdistif_restore(void);
+void mt_gic_sync_dcm_enable(void);
+void mt_gic_sync_dcm_disable(void);
+
+#endif /* MT_GIC_V3_H */
diff --git a/plat/mediatek/mt8183/include/plat_dcm.h b/plat/mediatek/mt8183/include/plat_dcm.h
new file mode 100644
index 0000000..afa9b63
--- /dev/null
+++ b/plat/mediatek/mt8183/include/plat_dcm.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DCM_H
+#define PLAT_DCM_H
+
+#define MP2_SYNC_DCM (MCUCFG_BASE + 0x2274)
+#define MP2_SYNC_DCM_MASK (0x1 << 0)
+#define MP2_SYNC_DCM_ON (0x1 << 0)
+#define MP2_SYNC_DCM_OFF (0x0 << 0)
+
+extern uint64_t plat_dcm_mcsi_a_addr;
+extern uint32_t plat_dcm_mcsi_a_val;
+extern int plat_dcm_initiated;
+
+extern void plat_dcm_mcsi_a_backup(void);
+extern void plat_dcm_mcsi_a_restore(void);
+extern void plat_dcm_rgu_enable(void);
+extern void plat_dcm_restore_cluster_on(unsigned long mpidr);
+extern void plat_dcm_msg_handler(uint64_t x1);
+extern unsigned long plat_dcm_get_enabled_cnt(uint64_t type);
+extern void plat_dcm_init(void);
+
+#define ALL_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE \
+ | STALL_DCM_TYPE | BIG_CORE_DCM_TYPE \
+ | GIC_SYNC_DCM_TYPE | RGU_DCM_TYPE \
+ | INFRA_DCM_TYPE \
+ | DDRPHY_DCM_TYPE | EMI_DCM_TYPE | DRAMC_DCM_TYPE \
+ | MCSI_DCM_TYPE)
+
+enum {
+ ARMCORE_DCM_TYPE = (1U << 0),
+ MCUSYS_DCM_TYPE = (1U << 1),
+ INFRA_DCM_TYPE = (1U << 2),
+ PERI_DCM_TYPE = (1U << 3),
+ EMI_DCM_TYPE = (1U << 4),
+ DRAMC_DCM_TYPE = (1U << 5),
+ DDRPHY_DCM_TYPE = (1U << 6),
+ STALL_DCM_TYPE = (1U << 7),
+ BIG_CORE_DCM_TYPE = (1U << 8),
+ GIC_SYNC_DCM_TYPE = (1U << 9),
+ LAST_CORE_DCM_TYPE = (1U << 10),
+ RGU_DCM_TYPE = (1U << 11),
+ TOPCKG_DCM_TYPE = (1U << 12),
+ LPDMA_DCM_TYPE = (1U << 13),
+ MCSI_DCM_TYPE = (1U << 14),
+ NR_DCM_TYPE = 15,
+};
+
+#endif /* PLAT_DCM_H */ \ No newline at end of file
diff --git a/plat/mediatek/mt8183/include/plat_debug.h b/plat/mediatek/mt8183/include/plat_debug.h
new file mode 100644
index 0000000..c9d73cc
--- /dev/null
+++ b/plat/mediatek/mt8183/include/plat_debug.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEBUG_H
+#define PLATFORM_DEBUG_H
+
+#define sync_writel(addr, val) \
+ do { mmio_write_32((addr), (val)); dsbsy(); } while (0)
+
+#define MCU_BIU_BASE 0x0c530000
+#define MISC1_CFG_BASE 0xb00
+#define CA15M_CFG_BASE 0x2000
+#define DFD_INTERNAL_CTL (MCU_BIU_BASE + MISC1_CFG_BASE + 0x00)
+#define CA15M_DBG_CONTROL (MCU_BIU_BASE + CA15M_CFG_BASE + 0x728)
+#define CA15M_PWR_RST_CTL (MCU_BIU_BASE + CA15M_CFG_BASE + 0x08)
+#define VPROC_EXT_CTL 0x10006290
+
+#define CFG_SF_CTRL 0x0c510014
+#define CFG_SF_INI 0x0c510010
+
+#define BIT_CA15M_L2PARITY_EN (1 << 1)
+#define BIT_CA15M_LASTPC_DIS (1 << 8)
+
+#define MCU_ALL_PWR_ON_CTRL 0x0c530b58
+#define PLAT_MTK_CIRCULAR_BUFFER_UNLOCK 0xefab4133
+#define PLAT_MTK_CIRCULAR_BUFFER_LOCK 0xefab4134
+
+extern void circular_buffer_setup(void);
+extern void l2c_parity_check_setup(void);
+extern void clear_all_on_mux(void);
+#endif /* PLATFORM_DEBUG_H */
diff --git a/plat/mediatek/mt8183/include/plat_macros.S b/plat/mediatek/mt8183/include/plat_macros.S
new file mode 100644
index 0000000..cac7769
--- /dev/null
+++ b/plat/mediatek/mt8183/include/plat_macros.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC and
+ * CCI registers whenever an unhandled exception
+ * is taken in BL31.
+ * Clobbers: x0 - x10, x26, x27, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x26, BASE_GICD_BASE
+ mov_imm x27, BASE_GICC_BASE
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x27, #GICC_HPPIR]
+ ldr w9, [x27, #GICC_AHPPIR]
+ ldr w10, [x27, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+ /* Print the GICD_ISPENDR regs */
+ add x7, x26, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x26
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (PLAT_MT_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ .endm
diff --git a/plat/mediatek/mt8183/include/plat_private.h b/plat/mediatek/mt8183/include/plat_private.h
new file mode 100644
index 0000000..0853934
--- /dev/null
+++ b/plat/mediatek/mt8183/include/plat_private.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit,
+ uintptr_t coh_start,
+ uintptr_t coh_limit);
+
+void plat_mtk_cci_init(void);
+void plat_mtk_cci_enable(void);
+void plat_mtk_cci_disable(void);
+void plat_mtk_cci_init_sf(void);
+
+/* Declarations for plat_topology.c */
+int mt_setup_topology(void);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8183/include/platform_def.h b/plat/mediatek/mt8183/include/platform_def.h
new file mode 100644
index 0000000..25ccfbc
--- /dev/null
+++ b/plat/mediatek/mt8183/include/platform_def.h
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <drivers/arm/gic_common.h>
+
+#define PLAT_PRIMARY_CPU 0x0
+
+#define IO_PHYS 0x10000000
+#define INFRACFG_AO_BASE (IO_PHYS + 0x1000)
+#define PERI_BASE (IO_PHYS + 0x3000)
+#define GPIO_BASE (IO_PHYS + 0x5000)
+#define SPM_BASE (IO_PHYS + 0x6000)
+#define SLEEP_REG_MD_BASE (IO_PHYS + 0xf000)
+#define RGU_BASE (IO_PHYS + 0x7000)
+#define I2C4_BASE_SE (IO_PHYS + 0x1008000)
+#define I2C2_BASE_SE (IO_PHYS + 0x1009000)
+#define PMIC_WRAP_BASE (IO_PHYS + 0xd000)
+#define MCUCFG_BASE 0x0c530000
+#define CFG_SF_CTRL 0x0c510014
+#define CFG_SF_INI 0x0c510010
+#define EMI_BASE (IO_PHYS + 0x219000)
+#define EMI_MPU_BASE (IO_PHYS + 0x226000)
+#define TRNG_base (IO_PHYS + 0x20f000)
+#define MT_GIC_BASE 0x0c000000
+#define PLAT_MT_CCI_BASE 0x0c500000
+#define CCI_SIZE 0x00010000
+#define EINT_BASE 0x1000b000
+#define DVFSRC_BASE (IO_PHYS + 0x12000)
+
+#define SSPM_CFGREG_BASE (IO_PHYS + 0x440000)
+#define SSPM_MBOX_3_BASE (IO_PHYS + 0x480000)
+
+#define INFRACFG_AO_BASE (IO_PHYS + 0x1000)
+
+#define TOPCKGEN_BASE (IO_PHYS + 0x0)
+#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x200)
+#define CLK_SCP_CFG_1 (TOPCKGEN_BASE + 0x204)
+
+#define APMIXEDSYS (IO_PHYS + 0xC000)
+#define AP_PLL_CON3 (APMIXEDSYS + 0xC)
+#define AP_PLL_CON4 (APMIXEDSYS + 0x10)
+#define AP_PLL_CON6 (APMIXEDSYS + 0x18)
+#define ARMPLL_LL_CON0 (APMIXEDSYS + 0x200)
+#define ARMPLL_L_CON0 (APMIXEDSYS + 0x210)
+#define ARMPLL_L_PWR_CON0 (APMIXEDSYS + 0x21c)
+#define MAINPLL_CON0 (APMIXEDSYS + 0x220)
+#define CCIPLL_CON0 (APMIXEDSYS + 0x290)
+
+#define TOP_CKMUXSEL (INFRACFG_AO_BASE + 0x0)
+
+#define armpll_mux1_sel_big_mask (0xf << 4)
+#define armpll_mux1_sel_big_ARMSPLL (0x1 << 4)
+#define armpll_mux1_sel_sml_mask (0xf << 8)
+#define armpll_mux1_sel_sml_ARMSPLL (0x1 << 8)
+
+
+/* Aggregate of all devices in the first GB */
+#define MTK_DEV_RNG0_BASE IO_PHYS
+#define MTK_DEV_RNG0_SIZE 0x490000
+#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000)
+#define MTK_DEV_RNG1_SIZE 0x4000000
+#define MTK_DEV_RNG2_BASE 0x0c000000
+#define MTK_DEV_RNG2_SIZE 0x600000
+#define MT_MCUSYS_SIZE 0x90000
+#define RAM_CONSOLE_BASE 0x11d000
+#define RAM_CONSOLE_SIZE 0x1000
+
+/*******************************************************************************
+ * MSDC
+ ******************************************************************************/
+#define MSDC0_BASE (IO_PHYS + 0x01230000)
+
+/*******************************************************************************
+ * MCUSYS related constants
+ ******************************************************************************/
+#define MT_L2_WRITE_ACCESS_RATE (MCUCFG_BASE + 0x604)
+#define MP0_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f0)
+#define MP1_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f4)
+#define EMI_WFIFO (MCUCFG_BASE + 0x0b5c)
+
+/*******************************************************************************
+ * GIC related constants
+ ******************************************************************************/
+#define MT_POLARITY_LOW 0
+#define MT_POLARITY_HIGH 1
+#define MT_EDGE_SENSITIVE 1
+#define MT_LEVEL_SENSITIVE 0
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE (IO_PHYS + 0x01002000)
+#define UART1_BASE (IO_PHYS + 0x01003000)
+
+#define UART_BAUDRATE 115200
+#define UART_CLOCK 26000000
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 13000000
+#define SYS_COUNTER_FREQ_IN_MHZ 13
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE MT_GIC_BASE
+#define BASE_GICC_BASE (MT_GIC_BASE + 0x400000)
+#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x100000)
+#define BASE_GICR_BASE (MT_GIC_BASE + 0x100000)
+#define BASE_GICH_BASE (MT_GIC_BASE + 0x4000)
+#define BASE_GICV_BASE (MT_GIC_BASE + 0x6000)
+#define INT_POL_CTL0 (MCUCFG_BASE + 0xa80)
+#define SEC_POL_CTL_EN0 (MCUCFG_BASE + 0xa00)
+#define GIC_SYNC_DCM (MCUCFG_BASE + 0x758)
+#define GIC_SYNC_DCM_MASK 0x3
+#define GIC_SYNC_DCM_ON 0x3
+#define GIC_SYNC_DCM_OFF 0x0
+#define GIC_PRIVATE_SIGNALS 32
+
+#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
+#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) ( \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+INTR_PROP_DESC(MT_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)) \
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp)
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4
+#define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3
+
+/*******************************************************************************
+ * WDT Registers
+ ******************************************************************************/
+#define MTK_WDT_BASE (IO_PHYS + 0x00007000)
+#define MTK_WDT_SIZE 0x1000
+#define MTK_WDT_MODE (MTK_WDT_BASE + 0x0000)
+#define MTK_WDT_LENGTH (MTK_WDT_BASE + 0x0004)
+#define MTK_WDT_RESTART (MTK_WDT_BASE + 0x0008)
+#define MTK_WDT_STATUS (MTK_WDT_BASE + 0x000C)
+#define MTK_WDT_INTERVAL (MTK_WDT_BASE + 0x0010)
+#define MTK_WDT_SWRST (MTK_WDT_BASE + 0x0014)
+#define MTK_WDT_SWSYSRST (MTK_WDT_BASE + 0x0018)
+#define MTK_WDT_NONRST_REG (MTK_WDT_BASE + 0x0020)
+#define MTK_WDT_NONRST_REG2 (MTK_WDT_BASE + 0x0024)
+#define MTK_WDT_REQ_MODE (MTK_WDT_BASE + 0x0030)
+#define MTK_WDT_REQ_IRQ_EN (MTK_WDT_BASE + 0x0034)
+#define MTK_WDT_EXT_REQ_CON (MTK_WDT_BASE + 0x0038)
+#define MTK_WDT_DEBUG_CTL (MTK_WDT_BASE + 0x0040)
+#define MTK_WDT_LATCH_CTL (MTK_WDT_BASE + 0x0044)
+#define MTK_WDT_DEBUG_CTL2 (MTK_WDT_BASE + 0x00A0)
+#define MTK_WDT_COUNTER (MTK_WDT_BASE + 0x0514)
+
+/* WDT_STATUS */
+#define MTK_WDT_STATUS_SPM_THERMAL_RST (1 << 0)
+#define MTK_WDT_STATUS_SPM_RST (1 << 1)
+#define MTK_WDT_STATUS_EINT_RST (1 << 2)
+#define MTK_WDT_STATUS_SYSRST_RST (1 << 3) /* from PMIC */
+#define MTK_WDT_STATUS_DVFSP_RST (1 << 4)
+#define MTK_WDT_STATUS_PMCU_RST (1 << 16)
+#define MTK_WDT_STATUS_MDDBG_RST (1 << 17)
+#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1 << 18)
+#define MTK_WDT_STATUS_DEBUG_RST (1 << 19)
+#define MTK_WDT_STATUS_SECURITY_RST (1 << 28)
+#define MTK_WDT_STATUS_IRQ_ASSERT (1 << 29)
+#define MTK_WDT_STATUS_SW_WDT_RST (1 << 30)
+#define MTK_WDT_STATUS_HW_WDT_RST (1U << 31)
+
+/* RGU other related */
+#define MTK_WDT_MODE_DUAL_MODE 0x0040
+#define MTK_WDT_MODE_IRQ 0x0008
+#define MTK_WDT_MODE_KEY 0x22000000
+#define MTK_WDT_MODE_EXTEN 0x0004
+#define MTK_WDT_SWRST_KEY 0x1209
+#define MTK_WDT_RESTART_KEY 0x1971
+
+/*******************************************************************************
+ * TRNG Registers
+ ******************************************************************************/
+#define TRNG_BASE_ADDR TRNG_base
+#define TRNG_BASE_SIZE 0x1000
+#define TRNG_CTRL (TRNG_base + 0x0000)
+#define TRNG_TIME (TRNG_base + 0x0004)
+#define TRNG_DATA (TRNG_base + 0x0008)
+#define TRNG_PDN_base 0x10001000
+#define TRNG_PDN_BASE_ADDR TRNG_PDN_BASE_ADDR
+#define TRNG_PDN_BASE_SIZE 0x1000
+#define TRNG_PDN_SET (TRNG_PDN_base + 0x0088)
+#define TRNG_PDN_CLR (TRNG_PDN_base + 0x008c)
+#define TRNG_PDN_STATUS (TRNG_PDN_base + 0x0094)
+#define TRNG_CTRL_RDY 0x80000000
+#define TRNG_CTRL_START 0x00000001
+#define TRNG_PDN_VALUE 0x200
+
+/* FIQ platform related define */
+#define MT_IRQ_SEC_SGI_0 8
+#define MT_IRQ_SEC_SGI_1 9
+#define MT_IRQ_SEC_SGI_2 10
+#define MT_IRQ_SEC_SGI_3 11
+#define MT_IRQ_SEC_SGI_4 12
+#define MT_IRQ_SEC_SGI_5 13
+#define MT_IRQ_SEC_SGI_6 14
+#define MT_IRQ_SEC_SGI_7 15
+
+#define FIQ_SMP_CALL_SGI 13
+#define WDT_IRQ_BIT_ID 174
+#define ATF_LOG_IRQ_ID 277
+
+#define ATF_AMMS_IRQ_ID 338
+#define PCCIF1_IRQ0_BIT_ID 185
+#define PCCIF1_IRQ1_BIT_ID 186
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+#define PLATFORM_CACHE_LINE_SIZE 64
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(4)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define SOC_CHIP_ID U(0x8183)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+
+#define TZRAM_BASE 0x54600000
+#define TZRAM_SIZE 0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 16
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8183/include/power_tracer.h b/plat/mediatek/mt8183/include/power_tracer.h
new file mode 100644
index 0000000..c93be64
--- /dev/null
+++ b/plat/mediatek/mt8183/include/power_tracer.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POWER_TRACER_H
+#define POWER_TRACER_H
+
+#define CPU_UP 0
+#define CPU_DOWN 1
+#define CPU_SUSPEND 2
+#define CLUSTER_UP 3
+#define CLUSTER_DOWN 4
+#define CLUSTER_SUSPEND 5
+
+void trace_power_flow(u_register_t mpidr, unsigned char mode);
+
+#endif /* POWER_TRACER_H */
+
diff --git a/plat/mediatek/mt8183/include/scu.h b/plat/mediatek/mt8183/include/scu.h
new file mode 100644
index 0000000..96b80c5
--- /dev/null
+++ b/plat/mediatek/mt8183/include/scu.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SCU_H
+#define SCU_H
+
+void disable_scu(u_register_t mpidr);
+void enable_scu(u_register_t mpidr);
+
+#endif /* SCU_H */
diff --git a/plat/mediatek/mt8183/include/sspm_reg.h b/plat/mediatek/mt8183/include/sspm_reg.h
new file mode 100644
index 0000000..3f1ac86
--- /dev/null
+++ b/plat/mediatek/mt8183/include/sspm_reg.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SSPM_REG_H__
+#define __SSPM_REG_H__
+
+#include "platform_def.h"
+
+#define SSPM_CFGREG_RSV_RW_REG0 (SSPM_CFGREG_BASE + 0x0100)
+#define SSPM_CFGREG_ACAO_INT_SET (SSPM_CFGREG_BASE + 0x00D8)
+#define SSPM_CFGREG_ACAO_INT_CLR (SSPM_CFGREG_BASE + 0x00DC)
+#define SSPM_CFGREG_ACAO_WAKEUP_EN (SSPM_CFGREG_BASE + 0x0204)
+
+#define STANDBYWFI_EN(n) (1 << (n + 8))
+#define GIC_IRQOUT_EN(n) (1 << (n + 0))
+
+#define NF_MCDI_MBOX 19
+#define MCDI_MBOX_CLUSTER_0_CAN_POWER_OFF 0
+#define MCDI_MBOX_CLUSTER_1_CAN_POWER_OFF 1
+#define MCDI_MBOX_BUCK_POWER_OFF_MASK 2
+#define MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE 3
+#define MCDI_MBOX_CLUSTER_1_ATF_ACTION_DONE 4
+#define MCDI_MBOX_BOOTADDR 5
+#define MCDI_MBOX_PAUSE_ACTION 6
+#define MCDI_MBOX_AVAIL_CPU_MASK 7
+#define MCDI_MBOX_CPU_CLUSTER_PWR_STAT 8
+#define MCDI_MBOX_ACTION_STAT 9
+#define MCDI_MBOX_CLUSTER_0_CNT 10
+#define MCDI_MBOX_CLUSTER_1_CNT 11
+#define MCDI_MBOX_CPU_ISOLATION_MASK 12
+#define MCDI_MBOX_PAUSE_ACK 13
+#define MCDI_MBOX_PENDING_ON_EVENT 14
+#define MCDI_MBOX_PROF_CMD 15
+#define MCDI_MBOX_DRCC_CALI_DONE 16
+#define MCDI_MBOX_HP_CMD 17
+#define MCDI_MBOX_HP_ACK 18
+
+#endif /* __SSPM_REG_H__ */
diff --git a/plat/mediatek/mt8183/plat_dcm.c b/plat/mediatek/mt8183/plat_dcm.c
new file mode 100644
index 0000000..8ee77f1
--- /dev/null
+++ b/plat/mediatek/mt8183/plat_dcm.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <lib/bakery_lock.h>
+#include <drivers/console.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <plat_dcm.h>
+#include <plat_private.h>
+#include <plat_dcm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <mtk_plat_common.h>
+
+#define PWR_STATUS (SPM_BASE + 0x180)
+
+uint64_t plat_dcm_mcsi_a_addr;
+uint32_t plat_dcm_mcsi_a_val;
+static int plat_dcm_init_type;
+static unsigned int dcm_big_core_cnt;
+int plat_dcm_initiated;
+
+#define PWR_STA_BIG_MP_MASK (0x1 << 15)
+
+DEFINE_BAKERY_LOCK(dcm_lock);
+
+void dcm_lock_init(void)
+{
+ bakery_lock_init(&dcm_lock);
+}
+
+void dcm_lock_get(void)
+{
+ bakery_lock_get(&dcm_lock);
+}
+
+void dcm_lock_release(void)
+{
+ bakery_lock_release(&dcm_lock);
+}
+
+void plat_dcm_mcsi_a_backup(void)
+{
+}
+
+void plat_dcm_mcsi_a_restore(void)
+{
+}
+
+void plat_dcm_rgu_enable(void)
+{
+}
+
+void plat_dcm_big_core_sync(short on)
+{
+ /* Check if Big cluster power is existed */
+ if (!(mmio_read_32(PWR_STATUS) & PWR_STA_BIG_MP_MASK))
+ return;
+
+ if (on) {
+ mmio_write_32(MP2_SYNC_DCM,
+ (mmio_read_32(MP2_SYNC_DCM) & ~MP2_SYNC_DCM_MASK)
+ | MP2_SYNC_DCM_ON);
+ dcm_big_core_cnt++;
+ } else
+ mmio_write_32(MP2_SYNC_DCM,
+ (mmio_read_32(MP2_SYNC_DCM) & ~MP2_SYNC_DCM_MASK)
+ | MP2_SYNC_DCM_OFF);
+}
+
+void plat_dcm_restore_cluster_on(unsigned long mpidr)
+{
+ unsigned long cluster_id =
+ (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
+
+ switch (cluster_id) {
+ case 0x1:
+ dcm_lock_get();
+ if (plat_dcm_init_type & BIG_CORE_DCM_TYPE)
+ plat_dcm_big_core_sync(1);
+ else
+ plat_dcm_big_core_sync(0);
+ dcm_lock_release();
+ break;
+ default:
+ break;
+ }
+}
+
+void plat_dcm_msg_handler(uint64_t x1)
+{
+ plat_dcm_init_type = x1 & ALL_DCM_TYPE;
+}
+
+unsigned long plat_dcm_get_enabled_cnt(uint64_t type)
+{
+ switch (type) {
+ case BIG_CORE_DCM_TYPE:
+ return dcm_big_core_cnt;
+ default:
+ return 0;
+ }
+}
+
+void plat_dcm_init(void)
+{
+ dcm_lock_init();
+}
diff --git a/plat/mediatek/mt8183/plat_debug.c b/plat/mediatek/mt8183/plat_debug.c
new file mode 100644
index 0000000..2f0b67d
--- /dev/null
+++ b/plat/mediatek/mt8183/plat_debug.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <plat_debug.h>
+#include <platform_def.h>
+#include <spm.h>
+
+void circular_buffer_setup(void)
+{
+ /* Clear DBG_CONTROL.lastpc_disable to enable circular buffer */
+ sync_writel(CA15M_DBG_CONTROL,
+ mmio_read_32(CA15M_DBG_CONTROL) & ~(BIT_CA15M_LASTPC_DIS));
+}
+
+void circular_buffer_unlock(void)
+{
+ unsigned int i;
+
+ /* Disable big vproc external off (set CPU_EXT_BUCK_ISO to 0x0) */
+ sync_writel(VPROC_EXT_CTL, mmio_read_32(VPROC_EXT_CTL) & ~(0x1 << 1));
+
+ /* Release vproc apb mask (set 0x0C53_2008[1] to 0x0) */
+ sync_writel(CA15M_PWR_RST_CTL, mmio_read_32(CA15M_PWR_RST_CTL) & ~(0x1 << 1));
+
+ for (i = 1; i <= 4; ++i)
+ sync_writel(MP1_CPUTOP_PWR_CON + i * 4,
+ (mmio_read_32(MP1_CPUTOP_PWR_CON + i * 4) & ~(0x4))|(0x4));
+
+ /* Set DFD.en */
+ sync_writel(DFD_INTERNAL_CTL, 0x1);
+}
+
+void circular_buffer_lock(void)
+{
+ /* Clear DFD.en */
+ sync_writel(DFD_INTERNAL_CTL, 0x0);
+}
+
+void clear_all_on_mux(void)
+{
+ sync_writel(MCU_ALL_PWR_ON_CTRL,
+ mmio_read_32(MCU_ALL_PWR_ON_CTRL) & ~(1 << 2));
+ sync_writel(MCU_ALL_PWR_ON_CTRL,
+ mmio_read_32(MCU_ALL_PWR_ON_CTRL) & ~(1 << 1));
+}
+
+void l2c_parity_check_setup(void)
+{
+ /* Enable DBG_CONTROL.l2parity_en */
+ sync_writel(CA15M_DBG_CONTROL,
+ mmio_read_32(CA15M_DBG_CONTROL) | BIT_CA15M_L2PARITY_EN);
+}
diff --git a/plat/mediatek/mt8183/plat_mt_gic.c b/plat/mediatek/mt8183/plat_mt_gic.c
new file mode 100644
index 0000000..35792b2
--- /dev/null
+++ b/plat/mediatek/mt8183/plat_mt_gic.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2019, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv3.h>
+#include <bl31/interrupt_mgmt.h>
+#include <mt_gic_v3.h>
+#include <mtk_plat_common.h>
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+#include "plat_private.h"
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <stdint.h>
+#include <stdio.h>
+
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT];
+
+/* we save and restore the GICv3 context on system suspend */
+gicv3_dist_ctx_t dist_ctx;
+
+static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
+{
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+gicv3_driver_data_t mt_gicv3_data = {
+ .gicd_base = MT_GIC_BASE,
+ .gicr_base = MT_GIC_RDIST_BASE,
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = mt_mpidr_to_core_pos,
+};
+
+struct gic_chip_data {
+ unsigned int saved_group;
+ unsigned int saved_enable;
+ unsigned int saved_conf0;
+ unsigned int saved_conf1;
+ unsigned int saved_grpmod;
+};
+
+static struct gic_chip_data gic_data;
+
+void clear_sec_pol_ctl_en(void)
+{
+ unsigned int i;
+
+ /* total 19 polarity ctrl registers */
+ for (i = 0; i <= NR_INT_POL_CTL - 1; i++) {
+ mmio_write_32((SEC_POL_CTL_EN0 + (i * 4)), 0);
+ }
+ dsb();
+}
+
+void mt_gic_driver_init(void)
+{
+ gicv3_driver_init(&mt_gicv3_data);
+}
+
+void mt_gic_set_pending(uint32_t irq)
+{
+ gicv3_set_interrupt_pending(irq, plat_my_core_pos());
+}
+
+void mt_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void mt_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void mt_gic_rdistif_init(void)
+{
+ unsigned int proc_num;
+ unsigned int index;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+ /* set all SGI/PPI as non-secure GROUP1 by default */
+ mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0);
+
+ /* setup the default PPI/SGI priorities */
+ for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U)
+ gicr_write_ipriorityr(gicr_base, index,
+ GICD_IPRIORITYR_DEF_VAL);
+}
+
+void mt_gic_distif_save(void)
+{
+ gicv3_distif_save(&dist_ctx);
+}
+
+void mt_gic_distif_restore(void)
+{
+ gicv3_distif_init_restore(&dist_ctx);
+}
+
+void mt_gic_rdistif_save(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+ gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0);
+ gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0);
+ gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0);
+ gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1);
+ gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0);
+
+ rdist_has_saved[proc_num] = 1;
+}
+
+void mt_gic_rdistif_restore(void)
+{
+ unsigned int proc_num;
+ uintptr_t gicr_base;
+
+ proc_num = plat_my_core_pos();
+ if (rdist_has_saved[proc_num] == 1) {
+ gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+ mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
+ mmio_write_32(gicr_base + GICR_ISENABLER0, gic_data.saved_enable);
+ mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
+ mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
+ mmio_write_32(gicr_base + GICR_IGRPMODR0, gic_data.saved_grpmod);
+ }
+}
+
+void mt_gic_sync_dcm_enable(void)
+{
+ mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_ON);
+}
+
+void mt_gic_sync_dcm_disable(void)
+{
+ mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_OFF);
+}
+
+void mt_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_cpuif_enable(plat_my_core_pos());
+ mt_gic_rdistif_init();
+
+ clear_sec_pol_ctl_en();
+}
diff --git a/plat/mediatek/mt8183/plat_pm.c b/plat/mediatek/mt8183/plat_pm.c
new file mode 100644
index 0000000..6094a17
--- /dev/null
+++ b/plat/mediatek/mt8183/plat_pm.c
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2019-2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* common headers */
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <errno.h>
+
+/* mediatek platform specific headers */
+#include <platform_def.h>
+#include <scu.h>
+#include <mt_gic_v3.h>
+#include <mtk_mcdi.h>
+#include <mtk_plat_common.h>
+#include <mtgpio.h>
+#include <mtspmc.h>
+#include <plat_dcm.h>
+#include <plat_debug.h>
+#include <plat_params.h>
+#include <plat_private.h>
+#include <power_tracer.h>
+#include <pmic.h>
+#include <spm.h>
+#include <spm_suspend.h>
+#include <sspm.h>
+#include <rtc.h>
+
+/* Local power state for power domains in Run state. */
+#define MTK_LOCAL_STATE_RUN 0
+/* Local power state for retention. */
+#define MTK_LOCAL_STATE_RET 1
+/* Local power state for OFF/power-down. */
+#define MTK_LOCAL_STATE_OFF 2
+
+#if PSCI_EXTENDED_STATE_ID
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define MTK_LOCAL_PSTATE_WIDTH 4
+#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1)
+
+/* Macros to construct the composite power state */
+
+/* Make composite power state parameter till power level 0 */
+
+#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
+
+#else /* !PSCI_EXTENDED_STATE_ID */
+
+#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+
+#endif /* PSCI_EXTENDED_STATE_ID */
+
+/* Make composite power state parameter till power level 1 */
+#define mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \
+ mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+
+/* Make composite power state parameter till power level 2 */
+#define mtk_make_pwrstate_lvl2( \
+ lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \
+ mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type))
+
+#define MTK_PWR_LVL0 0
+#define MTK_PWR_LVL1 1
+#define MTK_PWR_LVL2 2
+
+/* Macros to read the MTK power domain state */
+#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0]
+#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1]
+#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ? \
+ (state)->pwr_domain_state[MTK_PWR_LVL2] : 0)
+
+#if PSCI_EXTENDED_STATE_ID
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+const unsigned int mtk_pm_idle_states[] = {
+ /* State-id - 0x001 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
+ MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x002 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
+ MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x022 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF,
+ MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
+#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1
+ /* State-id - 0x222 */
+ mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF,
+ MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
+#endif
+ 0,
+};
+#endif
+
+#define CPU_IDX(cluster, cpu) ((cluster << 2) + cpu)
+#define ON true
+#define OFF false
+
+/* Pause MCDI when CPU hotplug */
+static bool HP_SSPM_PAUSE;
+/* CPU Hotplug by SSPM */
+static bool HP_SSPM_CTRL = true;
+/* Turn off cluster when CPU hotplug off */
+static bool HP_CLUSTER_OFF = true;
+/* Turn off cluster when CPU MCDI off */
+static bool MCDI_C2 = true;
+/* Enable MCDI */
+static bool MCDI_SSPM = true;
+
+static uintptr_t secure_entrypoint;
+
+static void mp1_L2_desel_config(void)
+{
+ mmio_write_64(MCUCFG_BASE + 0x2200, 0x2092c820);
+
+ dsb();
+}
+
+static bool clst_single_pwr(int cluster, int cpu)
+{
+ uint32_t cpu_mask[2] = {0x00001e00, 0x000f0000};
+ uint32_t cpu_pwr_bit[] = {9, 10, 11, 12, 16, 17, 18, 19};
+ int my_idx = (cluster << 2) + cpu;
+ uint32_t pwr_stat = mmio_read_32(0x10006180);
+
+ return !(pwr_stat & (cpu_mask[cluster] & ~BIT(cpu_pwr_bit[my_idx])));
+}
+
+static bool clst_single_on(int cluster, int cpu)
+{
+ uint32_t cpu_mask[2] = {0x0f, 0xf0};
+ int my_idx = (cluster << 2) + cpu;
+ uint32_t on_stat = mcdi_avail_cpu_mask_read();
+
+ return !(on_stat & (cpu_mask[cluster] & ~BIT(my_idx)));
+}
+
+static void plat_cpu_pwrdwn_common(void)
+{
+ /* Prevent interrupts from spuriously waking up this cpu */
+ mt_gic_rdistif_save();
+ mt_gic_cpuif_disable();
+}
+
+static void plat_cpu_pwron_common(void)
+{
+ /* Enable the gic cpu interface */
+ mt_gic_cpuif_enable();
+ mt_gic_rdistif_init();
+ mt_gic_rdistif_restore();
+}
+
+static void plat_cluster_pwrdwn_common(uint64_t mpidr, int cluster)
+{
+ if (cluster > 0)
+ mt_gic_sync_dcm_enable();
+
+ /* Disable coherency */
+ plat_mtk_cci_disable();
+ disable_scu(mpidr);
+}
+
+static void plat_cluster_pwron_common(uint64_t mpidr, int cluster)
+{
+ if (cluster > 0) {
+ l2c_parity_check_setup();
+ circular_buffer_setup();
+ mp1_L2_desel_config();
+ mt_gic_sync_dcm_disable();
+ }
+
+ /* Enable coherency */
+ enable_scu(mpidr);
+ plat_mtk_cci_enable();
+ /* Enable big core dcm */
+ plat_dcm_restore_cluster_on(mpidr);
+ /* Enable rgu dcm */
+ plat_dcm_rgu_enable();
+}
+
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr;
+
+ scr = read_scr_el3();
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+ isb();
+ dsb();
+ wfi();
+
+ write_scr_el3(scr);
+}
+
+static void mcdi_ctrl_before_hotplug_on(int cluster, int cpu)
+{
+ if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM) {
+ mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), OFF);
+ mcdi_pause_set(cluster, CPU_IDX(cluster, cpu), ON);
+ }
+}
+
+static void mcdi_ctrl_before_hotplug_off(int cluster, int cpu, bool cluster_off)
+{
+ if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM)
+ mcdi_pause_set(cluster_off ? cluster : -1,
+ CPU_IDX(cluster, cpu), OFF);
+}
+
+static void mcdi_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
+{
+ if (MCDI_SSPM) {
+ sspm_set_bootaddr(secure_entrypoint);
+
+ sspm_standbywfi_irq_enable(CPU_IDX(cluster, cpu));
+
+ if (cluster_off)
+ sspm_cluster_pwr_off_notify(cluster);
+ else
+ sspm_cluster_pwr_on_notify(cluster);
+ }
+}
+
+static void mcdi_ctrl_suspend(void)
+{
+ if (MCDI_SSPM)
+ mcdi_pause();
+}
+
+static void mcdi_ctrl_resume(void)
+{
+ if (MCDI_SSPM)
+ mcdi_unpause();
+}
+
+static void hotplug_ctrl_cluster_on(int cluster, int cpu)
+{
+ if (HP_SSPM_CTRL && MCDI_SSPM) {
+ mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), OFF);
+ mcdi_hotplug_set(cluster, -1, ON);
+ mcdi_hotplug_wait_ack(cluster, -1, ON);
+ } else {
+ /* power on cluster */
+ if (!spm_get_cluster_powerstate(cluster))
+ spm_poweron_cluster(cluster);
+ }
+}
+
+static void hotplug_ctrl_cpu_on(int cluster, int cpu)
+{
+ if (HP_SSPM_CTRL && MCDI_SSPM)
+ mcdi_hotplug_set(cluster, CPU_IDX(cluster, cpu), ON);
+ else
+ spm_poweron_cpu(cluster, cpu);
+}
+
+static void hotplug_ctrl_cpu_on_finish(int cluster, int cpu)
+{
+ spm_disable_cpu_auto_off(cluster, cpu);
+
+ if (HP_SSPM_CTRL && MCDI_SSPM)
+ mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), ON);
+ else if (HP_SSPM_PAUSE && MCDI_SSPM)
+ mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), ON);
+
+ mcdi_avail_cpu_mask_set(BIT(CPU_IDX(cluster, cpu)));
+}
+
+static void hotplug_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
+{
+ mcdi_avail_cpu_mask_clr(BIT(CPU_IDX(cluster, cpu)));
+
+ if (HP_SSPM_CTRL && MCDI_SSPM) {
+ mcdi_hotplug_set(cluster_off ? cluster : -1,
+ CPU_IDX(cluster, cpu), OFF);
+ } else {
+ spm_enable_cpu_auto_off(cluster, cpu);
+
+ if (cluster_off)
+ spm_enable_cluster_auto_off(cluster);
+
+ spm_set_cpu_power_off(cluster, cpu);
+ }
+}
+
+static int plat_mtk_power_domain_on(unsigned long mpidr)
+{
+ int cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ int clst_pwr = spm_get_cluster_powerstate(cluster);
+ unsigned int i;
+
+ mcdi_ctrl_before_hotplug_on(cluster, cpu);
+ hotplug_ctrl_cluster_on(cluster, cpu);
+
+ if (clst_pwr == 0) {
+ /* init cpu reset arch as AARCH64 of cluster */
+ for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) {
+ mcucfg_init_archstate(cluster, i, 1);
+ mcucfg_set_bootaddr(cluster, i, secure_entrypoint);
+ }
+ }
+
+ hotplug_ctrl_cpu_on(cluster, cpu);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_mtk_power_domain_off(const psci_power_state_t *state)
+{
+ uint64_t mpidr = read_mpidr();
+ int cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ const plat_local_state_t *pds = state->pwr_domain_state;
+ bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
+ bool cluster_off = (HP_CLUSTER_OFF && afflvl1 &&
+ clst_single_on(cluster, cpu));
+
+ plat_cpu_pwrdwn_common();
+
+ if (cluster_off)
+ plat_cluster_pwrdwn_common(mpidr, cluster);
+
+ mcdi_ctrl_before_hotplug_off(cluster, cpu, cluster_off);
+ hotplug_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
+}
+
+static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
+{
+ uint64_t mpidr = read_mpidr();
+ int cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ const plat_local_state_t *pds = state->pwr_domain_state;
+ bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
+
+ if (afflvl1)
+ plat_cluster_pwron_common(mpidr, cluster);
+
+ plat_cpu_pwron_common();
+
+ hotplug_ctrl_cpu_on_finish(cluster, cpu);
+}
+
+static void plat_mtk_power_domain_suspend(const psci_power_state_t *state)
+{
+ uint64_t mpidr = read_mpidr();
+ int cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ const plat_local_state_t *pds = state->pwr_domain_state;
+ bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
+ bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
+ bool cluster_off = MCDI_C2 && afflvl1 && clst_single_pwr(cluster, cpu);
+
+ plat_cpu_pwrdwn_common();
+
+ plat_dcm_mcsi_a_backup();
+
+ if (cluster_off || afflvl2)
+ plat_cluster_pwrdwn_common(mpidr, cluster);
+
+ if (afflvl2) {
+ spm_data_t spm_d = { .cmd = SPM_SUSPEND };
+ uint32_t *d = (uint32_t *)&spm_d;
+ uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
+
+ mcdi_ctrl_suspend();
+
+ spm_set_bootaddr(secure_entrypoint);
+
+ if (MCDI_SSPM)
+ sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
+
+ spm_system_suspend();
+
+ if (MCDI_SSPM)
+ while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
+ ;
+
+ mt_gic_distif_save();
+ } else {
+ mcdi_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
+ }
+}
+
+static void plat_mtk_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+ uint64_t mpidr = read_mpidr();
+ int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ const plat_local_state_t *pds = state->pwr_domain_state;
+ bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
+
+ if (afflvl2) {
+ spm_data_t spm_d = { .cmd = SPM_RESUME };
+ uint32_t *d = (uint32_t *)&spm_d;
+ uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
+
+ mt_gic_init();
+ mt_gic_distif_restore();
+ mt_gic_rdistif_restore();
+
+ mmio_write_32(EMI_WFIFO, 0xf);
+
+ if (MCDI_SSPM)
+ sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
+
+ spm_system_suspend_finish();
+
+ if (MCDI_SSPM)
+ while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
+ ;
+
+ mcdi_ctrl_resume();
+ } else {
+ plat_cpu_pwron_common();
+ }
+
+ plat_cluster_pwron_common(mpidr, cluster);
+
+ plat_dcm_mcsi_a_restore();
+}
+
+#if PSCI_EXTENDED_STATE_ID
+
+static int plat_mtk_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ int i;
+
+ assert(req_state);
+
+ if (!MCDI_SSPM)
+ return PSCI_E_INVALID_PARAMS;
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
+ */
+ for (i = 0; !!mtk_pm_idle_states[i]; i++) {
+ if (power_state == mtk_pm_idle_states[i])
+ break;
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!mtk_pm_idle_states[i])
+ return PSCI_E_INVALID_PARAMS;
+
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id &
+ MTK_LOCAL_PSTATE_MASK;
+ state_id >>= MTK_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+#else /* if !PSCI_EXTENDED_STATE_ID */
+
+static int plat_mtk_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's possible to enter standby only on power level 0
+ * Ignore any other power level.
+ */
+ if (pwr_lvl != 0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MTK_PWR_LVL0] = MTK_LOCAL_STATE_RET;
+ } else if (!MCDI_SSPM) {
+ return PSCI_E_INVALID_PARAMS;
+ } else {
+ for (i = 0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+#endif /* PSCI_EXTENDED_STATE_ID */
+
+/*******************************************************************************
+ * MTK handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 plat_mtk_system_off(void)
+{
+ INFO("MTK System Off\n");
+
+ rtc_power_off_sequence();
+ wk_pmic_enable_sdn_delay();
+ pmic_power_off();
+
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 plat_mtk_system_reset(void)
+{
+ struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+ INFO("MTK System Reset\n");
+
+ mt_set_gpio_out(gpio_reset->index, gpio_reset->polarity);
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+static void plat_mtk_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ assert(PLAT_MAX_PWR_LVL >= 2);
+
+ for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
+}
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be turned
+ * on. The level and mpidr determine the affinity instance.
+ ******************************************************************************/
+static const plat_psci_ops_t plat_plat_pm_ops = {
+ .cpu_standby = plat_cpu_standby,
+ .pwr_domain_on = plat_mtk_power_domain_on,
+ .pwr_domain_on_finish = plat_mtk_power_domain_on_finish,
+ .pwr_domain_off = plat_mtk_power_domain_off,
+ .pwr_domain_suspend = plat_mtk_power_domain_suspend,
+ .pwr_domain_suspend_finish = plat_mtk_power_domain_suspend_finish,
+ .system_off = plat_mtk_system_off,
+ .system_reset = plat_mtk_system_reset,
+ .validate_power_state = plat_mtk_validate_power_state,
+ .get_sys_suspend_power_state = plat_mtk_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ unsigned int i;
+
+ *psci_ops = &plat_plat_pm_ops;
+ secure_entrypoint = sec_entrypoint;
+
+ /* Init cpu reset arch as AARCH64 of cluster 0 */
+ for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) {
+ mcucfg_init_archstate(0, i, 1);
+ mcucfg_set_bootaddr(0, i, secure_entrypoint);
+ }
+
+ if (!check_mcdi_ctl_stat()) {
+ HP_SSPM_CTRL = false;
+ MCDI_SSPM = false;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8183/plat_topology.c b/plat/mediatek/mt8183/plat_topology.c
new file mode 100644
index 0000000..7b1dd03
--- /dev/null
+++ b/plat/mediatek/mt8183/plat_topology.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <platform_def.h>
+#include <lib/psci/psci.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* Number of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* Number of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the MT8173 default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return (cpu_id + (cluster_id * 4));
+}
diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk
new file mode 100644
index 0000000..a737d24
--- /dev/null
+++ b/plat/mediatek/mt8183/platform.mk
@@ -0,0 +1,90 @@
+#
+# Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT}/drivers/uart/ \
+ -I${MTK_PLAT}/include/ \
+ -I${MTK_PLAT_SOC}/drivers/ \
+ -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
+ -I${MTK_PLAT_SOC}/drivers/devapc/ \
+ -I${MTK_PLAT_SOC}/drivers/mcdi/ \
+ -I${MTK_PLAT_SOC}/drivers/spmc/ \
+ -I${MTK_PLAT_SOC}/drivers/gpio/ \
+ -I${MTK_PLAT_SOC}/drivers/timer/ \
+ -I${MTK_PLAT_SOC}/drivers/pmic/ \
+ -I${MTK_PLAT_SOC}/drivers/spm/ \
+ -I${MTK_PLAT_SOC}/drivers/sspm/ \
+ -I${MTK_PLAT_SOC}/drivers/rtc/ \
+ -I${MTK_PLAT_SOC}/include/
+
+PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ plat/common/plat_psci_common.c \
+ plat/common/aarch64/crash_console_helpers.S
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+BL31_SOURCES += common/desc_image_load.c \
+ drivers/arm/cci/cci.c \
+ ${GICV3_SOURCES} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/gpio/gpio.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a73.S \
+ plat/common/plat_gicv3.c \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/params_setup.c \
+ ${MTK_PLAT}/drivers/pmic_wrap/pmic_wrap_init.c \
+ ${MTK_PLAT}/drivers/rtc/rtc_common.c \
+ ${MTK_PLAT}/drivers/uart/uart.c \
+ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
+ ${MTK_PLAT_SOC}/aarch64/platform_common.c \
+ ${MTK_PLAT_SOC}/drivers/devapc/devapc.c \
+ ${MTK_PLAT_SOC}/drivers/mcsi/mcsi.c \
+ ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
+ ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mtk_mcdi.c \
+ ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
+ ${MTK_PLAT_SOC}/drivers/spm/spm.c \
+ ${MTK_PLAT_SOC}/drivers/spm/spm_pmic_wrap.c \
+ ${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \
+ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
+ ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c \
+ ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
+ ${MTK_PLAT_SOC}/plat_pm.c \
+ ${MTK_PLAT_SOC}/plat_topology.c \
+ ${MTK_PLAT_SOC}/plat_mt_gic.c \
+ ${MTK_PLAT_SOC}/plat_dcm.c \
+ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
+ ${MTK_PLAT_SOC}/plat_debug.c \
+ ${MTK_PLAT_SOC}/scu.c \
+ ${MTK_PLAT_SOC}/drivers/sspm/sspm.c
+
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_826319 := 0
+ERRATA_A53_836870 := 1
+ERRATA_A53_855873 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MULTI_CONSOLE_API := 1
+
+MACH_MT8183 := 1
+$(eval $(call add_define,MACH_MT8183))
+
+include lib/coreboot/coreboot.mk
+
diff --git a/plat/mediatek/mt8183/scu.c b/plat/mediatek/mt8183/scu.c
new file mode 100644
index 0000000..c4f1c3f
--- /dev/null
+++ b/plat/mediatek/mt8183/scu.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mcucfg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void disable_scu(u_register_t mpidr)
+{
+ uintptr_t axi_config = 0;
+ uint32_t axi_value;
+
+ switch (mpidr & MPIDR_CLUSTER_MASK) {
+ case 0x000:
+ axi_config = (uintptr_t)&mt8183_mcucfg->mp0_axi_config;
+ axi_value = MP0_ACINACTM;
+ break;
+ case 0x100:
+ axi_config = (uintptr_t)&mt8183_mcucfg->mp2_axi_config;
+ axi_value = MP2_ACINACTM;
+ break;
+ default:
+ ERROR("%s: mpidr does not exist\n", __func__);
+ panic();
+ }
+ mmio_setbits_32(axi_config, axi_value);
+}
+
+void enable_scu(u_register_t mpidr)
+{
+ uintptr_t axi_config = 0;
+ uint32_t axi_value;
+
+ switch (mpidr & MPIDR_CLUSTER_MASK) {
+ case 0x000:
+ axi_config = (uintptr_t)&mt8183_mcucfg->mp0_axi_config;
+ axi_value = MP0_ACINACTM;
+ break;
+ case 0x100:
+ axi_config = (uintptr_t)&mt8183_mcucfg->mp2_axi_config;
+ axi_value = MP2_ACINACTM;
+ break;
+ default:
+ ERROR("%s: mpidr does not exist\n", __func__);
+ panic();
+ }
+ mmio_clrbits_32(axi_config, axi_value);
+}
diff --git a/plat/mediatek/mt8186/aarch64/plat_helpers.S b/plat/mediatek/mt8186/aarch64/plat_helpers.S
new file mode 100644
index 0000000..35b293f
--- /dev/null
+++ b/plat/mediatek/mt8186/aarch64/plat_helpers.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_mediatek_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+ *
+ * With this function: CorePos = CoreID (AFF1)
+ * we do it with x0 = (x0 >> 8) & 0xff
+ * -----------------------------------------------------
+ */
+func plat_mediatek_calc_core_pos
+ mov x1, #MPIDR_AFFLVL_MASK
+ and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+ ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8186/aarch64/platform_common.c b/plat/mediatek/mt8186/aarch64/platform_common.c
new file mode 100644
index 0000000..021cab7
--- /dev/null
+++ b/plat/mediatek/mt8186/aarch64/platform_common.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_mmap[] = {
+ /* for TF text, RO, RW */
+ MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_MCDI_SRAM_BASE, MTK_MCDI_SRAM_MAP_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_RW_DATA | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_CODE | MT_SECURE);
+ mmap_add(plat_mmap);
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8186/bl31_plat_setup.c b/plat/mediatek/mt8186/bl31_plat_setup.c
new file mode 100644
index 0000000..5fc6b6e
--- /dev/null
+++ b/plat/mediatek/mt8186/bl31_plat_setup.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <emi_mpu.h>
+#include <mt_gic_v3.h>
+#include <mt_spm.h>
+#include <mt_timer.h>
+#include <mtgpio.h>
+#include <mtk_dcm.h>
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ params_early_setup(arg1);
+
+#if COREBOOT
+ if (coreboot_serial.type) {
+ console_16550_register(coreboot_serial.baseaddr,
+ coreboot_serial.input_hertz,
+ coreboot_serial.baud,
+ &console);
+ }
+#else
+ console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+ INFO("MT8186 bl31_setup\n");
+
+ bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ dcm_set_default();
+
+ /* Initialize the GIC driver, CPU and distributor interfaces */
+ mt_gic_driver_init();
+ mt_gic_init();
+
+ mt_gpio_init();
+ mt_systimer_init();
+ generic_delay_timer_init();
+ spm_boot_init();
+
+ emi_mpu_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(BL31_START,
+ BL31_END - BL31_START,
+ BL_CODE_BASE,
+ BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c
new file mode 100644
index 0000000..5dde5c5
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <mtk_dcm.h>
+#include <mtk_dcm_utils.h>
+
+static void dcm_armcore(bool mode)
+{
+ dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
+}
+
+static void dcm_mcusys(bool on)
+{
+ dcm_mp_cpusys_top_adb_dcm(on);
+ dcm_mp_cpusys_top_apb_dcm(on);
+ dcm_mp_cpusys_top_cpubiu_dcm(on);
+ dcm_mp_cpusys_top_cpubiu_dbg_cg(on);
+ dcm_mp_cpusys_top_misc_dcm(on);
+ dcm_mp_cpusys_top_mp0_qdcm(on);
+ dcm_cpccfg_reg_emi_wfifo(on);
+ dcm_mp_cpusys_top_last_cor_idle_dcm(on);
+}
+
+static void dcm_stall(bool on)
+{
+ dcm_mp_cpusys_top_core_stall_dcm(on);
+ dcm_mp_cpusys_top_fcm_stall_dcm(on);
+}
+
+static bool check_dcm_state(void)
+{
+ bool ret = true;
+
+ ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on();
+ ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
+ ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
+ ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
+
+ return ret;
+}
+
+void dcm_set_default(void)
+{
+ dcm_armcore(true);
+ dcm_mcusys(true);
+ dcm_stall(true);
+
+ INFO("%s: %d", __func__, check_dcm_state());
+}
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h
new file mode 100644
index 0000000..6abcff4
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+void dcm_set_default(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c
new file mode 100644
index 0000000..ae0e964
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mtk_dcm_utils.h>
+
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18) | \
+ (0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4) &
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_adb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16))
+
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_apb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \
+ (0x0 << 24) | \
+ (0x0 << 25))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_core_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON ((0x0 << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_OFF (BIT(0))
+
+bool dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSI_CFG2) &
+ MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dbg_cg(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2,
+ MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dbg_cg'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSI_CFG2,
+ MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DBG_CG_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSIC_DCM0) &
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11) | \
+ (0x0 << 24) | \
+ (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11) | \
+ (0x0 << 24) | \
+ (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4))
+
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK (BIT(31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON (BIT(31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0 << 31))
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3) | \
+ (0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_misc_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3))
+
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_mp0_qdcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+ }
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | BIT(2))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | BIT(2))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | (0x0 << 2))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPCCFG_REG_EMI_WFIFO) &
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK) ==
+ (unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON);
+
+ return ret;
+}
+
+void dcm_cpccfg_reg_emi_wfifo(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+ }
+}
+
diff --git a/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h
new file mode 100644
index 0000000..ba76594
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_UTILS_H
+#define MTK_DCM_UTILS_H
+
+#include <stdbool.h>
+
+#include <mtk_dcm.h>
+#include <platform_def.h>
+
+/* Base */
+#define MP_CPUSYS_TOP_BASE 0xc538000
+#define CPCCFG_REG_BASE 0xc53a800
+
+/* Register Definition */
+#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
+#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
+#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_CPUSYS_TOP_MCSI_CFG2 (MP_CPUSYS_TOP_BASE + 0x2418)
+#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
+void dcm_mp_cpusys_top_adb_dcm(bool on);
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
+void dcm_mp_cpusys_top_apb_dcm(bool on);
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_core_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dbg_cg_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dbg_cg(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
+void dcm_mp_cpusys_top_misc_dcm(bool on);
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
+void dcm_mp_cpusys_top_mp0_qdcm(bool on);
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+#endif
diff --git a/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..ade0837
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+ uint64_t cache_dump)
+{
+ mmio_write_32(MCUSYS_DFD_MAP, base_addr >> 24);
+ mmio_write_32(WDT_DEBUG_CTL, WDT_DEBUG_CTL_VAL_0);
+
+ sync_writel(DFD_INTERNAL_CTL, (BIT(0) | BIT(2)));
+
+ mmio_setbits_32(DFD_INTERNAL_CTL, BIT(13));
+ mmio_setbits_32(DFD_INTERNAL_CTL, BIT(3));
+ mmio_setbits_32(DFD_INTERNAL_CTL, (BIT(19) | BIT(20)));
+ mmio_write_32(DFD_INTERNAL_PWR_ON, (BIT(0) | BIT(1) | BIT(3)));
+ mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+ mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0);
+ mmio_write_32(DFD_INTERNAL_TEST_SO_0, DFD_INTERNAL_TEST_SO_0_VAL);
+ mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 1);
+
+ mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_VAL);
+ mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL);
+
+ sync_writel(DFD_V30_CTL, 1);
+
+ mmio_write_32(DFD_V30_BASE_ADDR, (base_addr & 0xFFF00000));
+
+ /* setup global variables for suspend and resume */
+ dfd_enabled = true;
+ dfd_base_addr = base_addr;
+ dfd_chain_length = chain_length;
+ dfd_cache_dump = cache_dump;
+
+ if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+ mmio_write_32(WDT_DEBUG_CTL, WDT_DEBUG_CTL_VAL_1);
+ sync_writel(DFD_V35_ENALBE, 1);
+ sync_writel(DFD_V35_TAP_NUMBER, DFD_V35_TAP_NUMBER_VAL);
+ sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+ sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+ if (cache_dump & DFD_PARITY_ERR_TRIGGER) {
+ sync_writel(DFD_HW_TRIGGER_MASK, DFD_HW_TRIGGER_MASK_VAL);
+ mmio_setbits_32(DFD_INTERNAL_CTL, BIT(4));
+ }
+ }
+ dsbsy();
+}
+
+void dfd_resume(void)
+{
+ if (dfd_enabled == true) {
+ dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+ }
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3)
+{
+ uint64_t ret = 0L;
+
+ switch (arg0) {
+ case PLAT_MTK_DFD_SETUP_MAGIC:
+ INFO("[%s] DFD setup call from kernel\n", __func__);
+ dfd_setup(arg1, arg2, arg3);
+ break;
+ case PLAT_MTK_DFD_READ_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+ }
+ break;
+ case PLAT_MTK_DFD_WRITE_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ sync_writel(MISC1_CFG_BASE + arg1, arg2);
+ }
+ break;
+ default:
+ ret = MTK_SIP_E_INVALID_PARAM;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..1901ec9
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \
+ dsbsy(); \
+ } while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC (0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152)
+
+#define MCU_BIU_BASE (MCUCFG_BASE)
+#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xA040)
+
+#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10)
+#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30)
+#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C)
+#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C)
+#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENALBE (MCU_BIU_BASE + 0xA0A8)
+#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xA0AC)
+#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xA0B0)
+#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xA0C0)
+#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xA0C4)
+
+#define DFD_CACHE_DUMP_ENABLE (1U)
+#define DFD_PARITY_ERR_TRIGGER (2U)
+
+#define MCUSYS_DFD_MAP (0x10001390)
+#define WDT_DEBUG_CTL (0x10007048)
+
+#define WDT_DEBUG_CTL_VAL_0 (0x950603A0)
+#define DFD_INTERNAL_TEST_SO_0_VAL (0x3B)
+#define DFD_TEST_SI_0_VAL (0x108)
+#define DFD_TEST_SI_1_VAL (0x20200000)
+
+#define WDT_DEBUG_CTL_VAL_1 (0x95063E80)
+#define DFD_V35_TAP_NUMBER_VAL (0xA)
+#define DFD_V35_TAP_EN_VAL (0x3FF)
+#define DFD_V35_SEQ0_0_VAL (0x63668820)
+#define DFD_HW_TRIGGER_MASK_VAL (0xC)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..1133c86
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <emi_mpu.h>
+
+#if ENABLE_EMI_MPU_SW_LOCK
+static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
+#endif
+
+#define EMI_MPU_START_MASK (0x00FFFFFF)
+#define EMI_MPU_END_MASK (0x00FFFFFF)
+#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
+#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
+
+static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
+ unsigned int apc)
+{
+ unsigned int dgroup;
+ unsigned int region;
+
+ region = (start >> 24) & 0xFF;
+ start &= EMI_MPU_START_MASK;
+ dgroup = (end >> 24) & 0xFF;
+ end &= EMI_MPU_END_MASK;
+
+ if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+ WARN("invalid region, domain\n");
+ return -1;
+ }
+
+#if ENABLE_EMI_MPU_SW_LOCK
+ if (region_lock_state[region] == 1) {
+ WARN("invalid region\n");
+ return -1;
+ }
+
+ if ((dgroup == 0U) && ((apc >> 31) & 0x1)) {
+ region_lock_state[region] = 1;
+ }
+
+ apc &= EMI_MPU_APC_SW_LOCK_MASK;
+#else
+ apc &= EMI_MPU_APC_HW_LOCK_MASK;
+#endif
+
+ if ((start >= DRAM_OFFSET) && (end >= start)) {
+ start -= DRAM_OFFSET;
+ end -= DRAM_OFFSET;
+ } else {
+ WARN("invalid range\n");
+ return -1;
+ }
+
+ mmio_write_32(EMI_MPU_SA(region), start);
+ mmio_write_32(EMI_MPU_EA(region), end);
+ mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+#if defined(SUB_EMI_MPU_BASE)
+ mmio_write_32(SUB_EMI_MPU_SA(region), start);
+ mmio_write_32(SUB_EMI_MPU_EA(region), end);
+ mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
+#endif
+ return 0;
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+ unsigned int start, end;
+ int i;
+
+ if (region_info->region >= EMI_MPU_REGION_NUM) {
+ WARN("invalid region\n");
+ return -1;
+ }
+
+ start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+ (region_info->region << 24);
+
+ for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+ end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
+
+ if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
+ WARN("failed to set emi mpu protection(%d, %d, %d)\n",
+ start, end, region_info->apc[i]);
+ }
+ }
+
+ return 0;
+}
+
+void emi_mpu_init(void)
+{
+ struct emi_region_info_t region_info;
+
+ /* SCP DRAM */
+ region_info.start = 0x50000000ULL;
+ region_info.end = 0x5109FFFFULL;
+ region_info.region = 2;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+ emi_mpu_set_protection(&region_info);
+
+ /* DSP protect address */
+ region_info.start = 0x60000000ULL; /* dram base addr */
+ region_info.end = 0x610FFFFFULL;
+ region_info.region = 3;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+ emi_mpu_set_protection(&region_info);
+
+ /* Forbidden All */
+ region_info.start = 0x40000000ULL; /* dram base addr */
+ region_info.end = 0x1FFFF0000ULL;
+ region_info.region = 4;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+ emi_mpu_set_protection(&region_info);
+}
diff --git a/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..415146e
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define ENABLE_EMI_MPU_SW_LOCK 1
+
+#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000)
+#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004)
+#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4))
+#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4))
+#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4))
+#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4))
+#define EMI_MPU_START (0x000)
+#define EMI_MPU_END (0x93C)
+
+#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000)
+#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004)
+#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100)
+#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200)
+#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4))
+#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4))
+#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300)
+#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800)
+#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4))
+#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900)
+#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4))
+
+#define EMI_MPU_DOMAIN_NUM (16)
+#define EMI_MPU_REGION_NUM (32)
+#define EMI_MPU_ALIGN_BITS (16)
+#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define NO_PROTECTION 0
+#define SEC_RW 1
+#define SEC_RW_NSEC_R 2
+#define SEC_RW_NSEC_W 3
+#define SEC_R_NSEC_R 4
+#define FORBIDDEN 5
+#define SEC_R_NSEC_RW 6
+
+#define LOCK 1
+#define UNLOCK 0
+
+#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = 0; \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
+ (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
+ (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
+ (((unsigned int) d1) << 3) | ((unsigned int) d0) | \
+ ((unsigned int) lock << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+ d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = \
+ (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \
+ (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \
+ (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \
+ (((unsigned int) d9) << 3) | ((unsigned int) d8); \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
+ (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
+ (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
+ (((unsigned int) d1) << 3) | ((unsigned int) d0) | \
+ ((unsigned int) lock << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+ unsigned long long start;
+ unsigned long long end;
+ unsigned int region;
+ unsigned int apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+
+#endif
diff --git a/plat/mediatek/mt8186/drivers/gpio/mtgpio.c b/plat/mediatek/mt8186/drivers/gpio/mtgpio.c
new file mode 100644
index 0000000..134476a
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/gpio/mtgpio.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+{
+ uintptr_t reg_addr = 0U;
+ struct mt_pin_info gpio_info;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ gpio_info = mt_pin_infos[pin];
+
+ switch (gpio_info.base & 0x0f) {
+ case 0:
+ reg_addr = IOCFG_LT_BASE;
+ break;
+ case 1:
+ reg_addr = IOCFG_LM_BASE;
+ break;
+ case 2:
+ reg_addr = IOCFG_LB_BASE;
+ break;
+ case 3:
+ reg_addr = IOCFG_BL_BASE;
+ break;
+ case 4:
+ reg_addr = IOCFG_RB_BASE;
+ break;
+ case 5:
+ reg_addr = IOCFG_RT_BASE;
+ break;
+ default:
+ break;
+ }
+
+ return reg_addr;
+}
diff --git a/plat/mediatek/mt8186/drivers/gpio/mtgpio.h b/plat/mediatek/mt8186/drivers/gpio/mtgpio.h
new file mode 100644
index 0000000..4430a58
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/gpio/mtgpio.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <mtgpio_common.h>
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+ GPIO_UNSUPPORTED = -1,
+ GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6,
+ GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14,
+ GPIO15, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
+ GPIO23, GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30,
+ GPIO31, GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38,
+ GPIO39, GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46,
+ GPIO47, GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54,
+ GPIO55, GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62,
+ GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70,
+ GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78,
+ GPIO79, GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86,
+ GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94,
+ GPIO95, GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102,
+ GPIO103, GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110,
+ GPIO111, GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118,
+ GPIO119, GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126,
+ GPIO127, GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134,
+ GPIO135, GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142,
+ GPIO143, GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150,
+ GPIO151, GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158,
+ GPIO159, GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166,
+ GPIO167, GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174,
+ GPIO175, GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182,
+ GPIO183, GPIO184,
+ MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+static const struct mt_pin_info mt_pin_infos[] = {
+ PIN(0, 0, 13, 0x16, 0x40),
+ PIN(1, 0, 14, 0x16, 0x40),
+ PIN(2, 0, 17, 0x16, 0x40),
+ PIN(3, 0, 18, 0x16, 0x40),
+ PIN(4, 0, 19, 0x16, 0x40),
+ PIN(5, 0, 20, 0x16, 0x40),
+ PIN(6, 0, 19, 0x24, 0x40),
+ PIN(7, 0, 20, 0x24, 0x40),
+ PIN(8, 0, 21, 0x24, 0x40),
+ PIN(9, 0, 22, 0x24, 0x40),
+ PIN(10, 0, 16, 0x24, 0x40),
+ PIN(11, 0, 17, 0x24, 0x40),
+ PIN(12, 0, 18, 0x24, 0x40),
+ PIN(13, 0, 0, 0x23, 0x60),
+ PIN(14, 0, 1, 0x23, 0x60),
+ PIN(15, 0, 15, 0x16, 0x40),
+ PIN(16, 0, 16, 0x16, 0x40),
+ PIN(17, 0, 9, 0x25, 0x70),
+ PIN(18, 0, 10, 0x25, 0x70),
+ PIN(19, 0, 3, 0x25, 0x70),
+ PIN(20, 0, 6, 0x25, 0x70),
+ PIN(21, 0, 4, 0x25, 0x70),
+ PIN(22, 0, 7, 0x25, 0x70),
+ PIN(23, 0, 5, 0x25, 0x70),
+ PIN(24, 0, 8, 0x25, 0x70),
+ PIN(25, 0, 18, 0x25, 0x70),
+ PIN(26, 0, 15, 0x25, 0x70),
+ PIN(27, 0, 17, 0x25, 0x70),
+ PIN(28, 0, 16, 0x25, 0x70),
+ PIN(29, 0, 0, 0x16, 0x40),
+ PIN(30, 0, 1, 0x16, 0x40),
+ PIN(31, 0, 2, 0x16, 0x40),
+ PIN(32, 0, 25, 0x12, 0x50),
+ PIN(33, 0, 27, 0x12, 0x50),
+ PIN(34, 0, 26, 0x12, 0x50),
+ PIN(35, 0, 28, 0x12, 0x50),
+ PIN(36, 0, 9, 0x12, 0x50),
+ PIN(37, 0, 10, 0x12, 0x50),
+ PIN(38, 0, 12, 0x12, 0x50),
+ PIN(39, 0, 11, 0x12, 0x50),
+ PIN(40, 0, 13, 0x12, 0x50),
+ PIN(41, 0, 14, 0x12, 0x50),
+ PIN(42, 0, 16, 0x12, 0x50),
+ PIN(43, 0, 15, 0x12, 0x50),
+ PIN(44, 0, 28, 0x25, 0x70),
+ PIN(45, 0, 29, 0x25, 0x70),
+ PIN(46, 0, 31, 0x25, 0x70),
+ PIN(47, 0, 30, 0x25, 0x70),
+ PIN(48, 0, 17, 0x12, 0x50),
+ PIN(49, 0, 18, 0x12, 0x50),
+ PIN(50, 0, 20, 0x12, 0x50),
+ PIN(51, 0, 19, 0x12, 0x50),
+ PIN(52, 0, 12, 0x23, 0x60),
+ PIN(53, 0, 13, 0x23, 0x60),
+ PIN(54, 0, 15, 0x23, 0x60),
+ PIN(55, 0, 14, 0x23, 0x60),
+ PIN(56, 0, 12, 0x25, 0x70),
+ PIN(57, 0, 11, 0x25, 0x70),
+ PIN(58, 0, 13, 0x25, 0x70),
+ PIN(59, 0, 14, 0x25, 0x70),
+ PIN(60, 0, 21, 0x23, 0x60),
+ PIN(61, 0, 16, 0x23, 0x60),
+ PIN(62, 0, 22, 0x23, 0x60),
+ PIN(63, 0, 17, 0x23, 0x60),
+ PIN(64, 0, 18, 0x23, 0x60),
+ PIN(65, 0, 19, 0x23, 0x60),
+ PIN(66, 0, 20, 0x23, 0x60),
+ PIN(67, 1, 10, 0x21, 0x70),
+ PIN(68, 1, 0, 0x21, 0x70),
+ PIN(69, 1, 1, 0x21, 0x70),
+ PIN(70, 1, 11, 0x21, 0x70),
+ PIN(71, 1, 2, 0x21, 0x70),
+ PIN(72, 1, 3, 0x21, 0x70),
+ PIN(73, 1, 4, 0x21, 0x70),
+ PIN(74, 1, 5, 0x21, 0x70),
+ PIN(75, 1, 6, 0x21, 0x70),
+ PIN(76, 1, 7, 0x21, 0x70),
+ PIN(77, 1, 8, 0x21, 0x70),
+ PIN(78, 1, 9, 0x21, 0x70),
+ PIN(79, 1, 0, 0x25, 0x80),
+ PIN(80, 1, 1, 0x25, 0x80),
+ PIN(81, 1, 2, 0x25, 0x80),
+ PIN(82, 1, 3, 0x25, 0x80),
+ PIN(83, 0, 3, 0x16, 0x40),
+ PIN(84, 1, 0, 0x23, 0x70),
+ PIN(85, 1, 1, 0x23, 0x70),
+ PIN(86, 1, 2, 0x23, 0x70),
+ PIN(87, 1, 3, 0x23, 0x70),
+ PIN(88, 1, 4, 0x23, 0x70),
+ PIN(89, 1, 5, 0x23, 0x70),
+ PIN(90, 0, 2, 0x23, 0x60),
+ PIN(91, 0, 23, 0x23, 0x60),
+ PIN(92, 0, 25, 0x23, 0x60),
+ PIN(93, 0, 3, 0x23, 0x60),
+ PIN(94, 0, 24, 0x23, 0x60),
+ PIN(95, 0, 26, 0x23, 0x60),
+ PIN(96, 0, 1, 0x12, 0x50),
+ PIN(97, 0, 0, 0x12, 0x50),
+ PIN(98, 0, 2, 0x12, 0x50),
+ PIN(99, 0, 14, 0x24, 0x40),
+ PIN(100, 0, 15, 0x24, 0x40),
+ PIN(101, 0, 13, 0x24, 0x40),
+ PIN(102, 0, 12, 0x24, 0x40),
+ PIN(103, 0, 0, 0x24, 0x40),
+ PIN(104, 0, 1, 0x24, 0x40),
+ PIN(105, 0, 4, 0x24, 0x40),
+ PIN(106, 0, 5, 0x24, 0x40),
+ PIN(107, 0, 6, 0x24, 0x40),
+ PIN(108, 0, 7, 0x24, 0x40),
+ PIN(109, 0, 8, 0x24, 0x40),
+ PIN(110, 0, 9, 0x24, 0x40),
+ PIN(111, 0, 10, 0x24, 0x40),
+ PIN(112, 0, 11, 0x24, 0x40),
+ PIN(113, 0, 2, 0x24, 0x40),
+ PIN(114, 0, 3, 0x24, 0x40),
+ PIN(115, 0, 4, 0x23, 0x60),
+ PIN(116, 0, 7, 0x23, 0x60),
+ PIN(117, 0, 5, 0x23, 0x60),
+ PIN(118, 0, 6, 0x23, 0x60),
+ PIN(119, 0, 22, 0x25, 0x70),
+ PIN(120, 0, 19, 0x25, 0x70),
+ PIN(121, 0, 20, 0x25, 0x70),
+ PIN(122, 0, 21, 0x25, 0x70),
+ PIN(123, 0, 23, 0x25, 0x70),
+ PIN(124, 0, 0, 0x25, 0x70),
+ PIN(125, 0, 1, 0x25, 0x70),
+ PIN(126, 0, 2, 0x25, 0x70),
+ PIN(127, 0, 8, 0x23, 0x60),
+ PIN(128, 0, 10, 0x23, 0x60),
+ PIN(129, 0, 24, 0x25, 0x70),
+ PIN(130, 0, 26, 0x25, 0x70),
+ PIN(131, 0, 25, 0x25, 0x70),
+ PIN(132, 0, 27, 0x25, 0x70),
+ PIN(133, 0, 9, 0x21, 0x60),
+ PIN(134, 0, 12, 0x21, 0x60),
+ PIN(135, 0, 21, 0x16, 0x40),
+ PIN(136, 0, 24, 0x16, 0x40),
+ PIN(137, 0, 10, 0x21, 0x60),
+ PIN(138, 0, 13, 0x21, 0x60),
+ PIN(139, 0, 7, 0x12, 0x50),
+ PIN(140, 0, 8, 0x12, 0x50),
+ PIN(141, 0, 9, 0x23, 0x60),
+ PIN(142, 0, 11, 0x23, 0x60),
+ PIN(143, 0, 22, 0x16, 0x40),
+ PIN(144, 0, 25, 0x16, 0x40),
+ PIN(145, 0, 23, 0x16, 0x40),
+ PIN(146, 0, 26, 0x16, 0x40),
+ PIN(147, 0, 23, 0x24, 0x40),
+ PIN(148, 0, 24, 0x24, 0x40),
+ PIN(149, 0, 25, 0x24, 0x40),
+ PIN(150, 0, 26, 0x24, 0x40),
+ PIN(151, 0, 27, 0x24, 0x40),
+ PIN(152, 0, 28, 0x24, 0x40),
+ PIN(153, 0, 29, 0x24, 0x40),
+ PIN(154, 0, 30, 0x24, 0x40),
+ PIN(155, 0, 31, 0x24, 0x40),
+ PIN(156, 0, 0, 0x24, 0x50),
+ PIN(157, 0, 4, 0x12, 0x50),
+ PIN(158, 0, 3, 0x12, 0x50),
+ PIN(159, 0, 6, 0x12, 0x50),
+ PIN(160, 0, 5, 0x12, 0x50),
+ PIN(161, 0, 23, 0x12, 0x50),
+ PIN(162, 0, 24, 0x12, 0x50),
+ PIN(163, 0, 11, 0x21, 0x60),
+ PIN(164, 0, 8, 0x21, 0x60),
+ PIN(165, 0, 16, 0x21, 0x60),
+ PIN(166, 0, 1, 0x21, 0x60),
+ PIN(167, 0, 7, 0x21, 0x60),
+ PIN(168, 0, 4, 0x21, 0x60),
+ PIN(169, 0, 5, 0x21, 0x60),
+ PIN(170, 0, 0, 0x21, 0x60),
+ PIN(171, 0, 6, 0x21, 0x60),
+ PIN(172, 0, 2, 0x21, 0x60),
+ PIN(173, 0, 3, 0x21, 0x60),
+ PIN(174, 0, 7, 0x16, 0x40),
+ PIN(175, 0, 8, 0x16, 0x40),
+ PIN(176, 0, 4, 0x16, 0x40),
+ PIN(177, 0, 5, 0x16, 0x40),
+ PIN(178, 0, 6, 0x16, 0x40),
+ PIN(179, 0, 9, 0x16, 0x40),
+ PIN(180, 0, 10, 0x16, 0x40),
+ PIN(181, 0, 11, 0x16, 0x40),
+ PIN(182, 0, 12, 0x16, 0x40),
+ PIN(183, 0, 21, 0x12, 0x50),
+ PIN(184, 0, 22, 0x12, 0x50),
+};
+
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c
new file mode 100644
index 0000000..8c012e7
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_lp_irqremain.h>
+#include <mt_lp_rm.h>
+#include <mt_mcdi.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
+
+static int plat_mt_lp_cpu_rc;
+
+static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
+{
+ mtk_cpc_core_on_hint_clr(cpu);
+
+ if (IS_SYSTEM_SUSPEND_STATE(state)) {
+ mtk_cpc_time_sync();
+ }
+
+ return 0;
+}
+
+static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ /* clear DBGPRCR.CORENPDRQ to allow CPU power down */
+ write_dbgprcr_el1(0ULL);
+
+ return 0;
+}
+
+static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ mtk_cpc_mcusys_off_reflect();
+
+ return 0;
+}
+
+static int pwr_mcusys_pwron_finished(unsigned int cpu,
+ const psci_power_state_t *state)
+{
+ int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
+
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id);
+ mt_lp_irqremain_release();
+
+ return 0;
+}
+
+static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
+
+ if (!IS_MCUSYS_OFF_STATE(state)) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ plat_mt_lp_cpu_rc =
+ mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL);
+
+ if (plat_mt_lp_cpu_rc < 0) {
+ goto mt_pwr_mcusysoff_reflect;
+ }
+
+ mt_lp_irqremain_aquire();
+
+ return 0;
+
+mt_pwr_mcusysoff_reflect:
+ mtk_cpc_mcusys_off_reflect();
+
+mt_pwr_mcusysoff_break:
+ plat_mt_lp_cpu_rc = -1;
+
+ return -1;
+}
+
+static const struct mt_lpm_tz plat_pm = {
+ .pwr_prompt = pwr_state_prompt,
+ .pwr_reflect = pwr_state_reflect,
+ .pwr_cpu_on = pwr_cpu_pwron,
+ .pwr_cpu_dwn = pwr_cpu_pwrdwn,
+ .pwr_cluster_on = pwr_cluster_pwron,
+ .pwr_cluster_dwn = pwr_cluster_pwrdwn,
+ .pwr_mcusys_dwn = pwr_mcusys_pwrdwn,
+ .pwr_mcusys_on = pwr_mcusys_pwron,
+ .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
+{
+ mtk_cpc_init();
+
+ if (mcdi_try_init() == 0) {
+ INFO("MCDI init done.\n");
+ }
+
+ mt_lp_irqremain_init();
+
+ return &plat_pm;
+}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h
new file mode 100644
index 0000000..83a7a53
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MT_CPU_PM_H__
+#define __MT_CPU_PM_H__
+
+#define MCUSYS_STATUS_PDN (1 << 0UL)
+#define MCUSYS_STATUS_CPUSYS_PROTECT (1 << 8UL)
+#define MCUSYS_STATUS_MCUSYS_PROTECT (1 << 9UL)
+
+/* cpu_pm function ID*/
+enum mt_cpu_pm_user_id {
+ MCUSYS_STATUS,
+ CPC_COMMAND,
+ IRQ_REMAIN_LIST_ALLOC,
+ IRQ_REMAIN_IRQ_ADD,
+ IRQ_REMAIN_IRQ_SUBMIT,
+ MBOX_INFO,
+};
+
+/* cpu_pm lp function ID */
+enum mt_cpu_pm_lp_smc_id {
+ LP_CPC_COMMAND,
+ IRQS_REMAIN_ALLOC,
+ IRQS_REMAIN_CTRL,
+ IRQS_REMAIN_IRQ,
+ IRQS_REMAIN_WAKEUP_CAT,
+ IRQS_REMAIN_WAKEUP_SRC,
+};
+
+#endif
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c
new file mode 100644
index 0000000..2b0f071
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_timer.h>
+
+struct mtk_cpc_dev {
+ int auto_off;
+ unsigned int auto_thres_tick;
+};
+
+static struct mtk_cpc_dev cpc;
+
+static int mtk_cpc_last_core_prot(uint32_t prot_req,
+ uint32_t resp_reg, uint32_t resp_ofs)
+{
+ uint32_t sta, retry;
+
+ retry = 0U;
+
+ while (retry++ < RETRY_CNT_MAX) {
+
+ mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
+
+ udelay(1U);
+
+ sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
+
+ if (sta == PROT_SUCCESS) {
+ return CPC_SUCCESS;
+ } else if (sta == PROT_GIVEUP) {
+ return CPC_ERR_FAIL;
+ }
+ }
+
+ return CPC_ERR_TIMEOUT;
+}
+
+int mtk_cpu_pm_mcusys_prot_aquire(void)
+{
+ return mtk_cpc_last_core_prot(
+ MCUSYS_PROT_SET,
+ CPC_MCUSYS_LAST_CORE_RESP,
+ MCUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_mcusys_prot_release(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
+}
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster)
+{
+ return mtk_cpc_last_core_prot(
+ CPUSYS_PROT_SET,
+ CPC_MCUSYS_MP_LAST_CORE_RESP,
+ CPUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
+}
+
+static void mtk_cpc_cluster_cnt_backup(void)
+{
+ uint32_t backup_cnt;
+ uint32_t curr_cnt;
+ uint32_t cnt_mask = GENMASK(14, 0);
+ uint32_t clr_mask = GENMASK(1, 0);
+
+ /* Single Cluster */
+ backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
+ curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
+
+ /* Get off count if dormant count is 0 */
+ if ((curr_cnt & cnt_mask) == 0U) {
+ curr_cnt = (curr_cnt >> 16) & cnt_mask;
+ } else {
+ curr_cnt = curr_cnt & cnt_mask;
+ }
+
+ mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
+ mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask);
+}
+
+static inline void mtk_cpc_mcusys_off_en(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U);
+}
+
+static inline void mtk_cpc_mcusys_off_dis(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U);
+}
+
+void mtk_cpc_mcusys_off_reflect(void)
+{
+ mtk_cpc_mcusys_off_dis();
+ mtk_cpu_pm_mcusys_prot_release();
+}
+
+int mtk_cpc_mcusys_off_prepare(void)
+{
+ if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
+ return CPC_ERR_FAIL;
+ }
+
+ mtk_cpc_cluster_cnt_backup();
+ mtk_cpc_mcusys_off_en();
+
+ return CPC_SUCCESS;
+}
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
+}
+
+void mtk_cpc_core_on_hint_clr(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+static void mtk_cpc_dump_timestamp(void)
+{
+ uint32_t id;
+
+ for (id = 0U; id < CPC_TRACE_ID_NUM; id++) {
+ mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
+
+ memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
+ (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
+ CPC_TRACE_SIZE);
+ }
+}
+
+void mtk_cpc_time_sync(void)
+{
+ uint64_t kt;
+ uint32_t systime_l, systime_h;
+
+ kt = sched_clock();
+ systime_l = mmio_read_32(CNTSYS_L_REG);
+ systime_h = mmio_read_32(CNTSYS_H_REG);
+
+ /* sync kernel timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
+ /* sync system timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
+}
+
+static void mtk_cpc_config(uint32_t cfg, uint32_t data)
+{
+ uint32_t val;
+ uint32_t reg = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ reg = CPC_MCUSYS_CPC_DBG_SETTING;
+ val = mmio_read_32(reg);
+ val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN);
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG;
+ val = mmio_read_32(reg);
+ if (data != 0U) {
+ val |= CPC_AUTO_OFF_EN;
+ cpc.auto_off = 1;
+ } else {
+ val &= ~CPC_AUTO_OFF_EN;
+ cpc.auto_off = 0;
+ }
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ reg = CPC_MCUSYS_CPC_OFF_THRES;
+ cpc.auto_thres_tick = us_to_ticks(data);
+ val = cpc.auto_thres_tick;
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR;
+ val = GENMASK(1, 0); /* clr_mask */
+ break;
+ case CPC_SMC_CONFIG_TIME_SYNC:
+ mtk_cpc_time_sync();
+ break;
+ default:
+ break;
+ }
+
+ if (reg != 0U) {
+ mmio_write_32(reg, val);
+ }
+}
+
+static uint32_t mtk_cpc_read_config(uint32_t cfg)
+{
+ uint32_t res = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ?
+ 1U : 0U;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ res = cpc.auto_off;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ res = ticks_to_us(cpc.auto_thres_tick);
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t res = 0ULL;
+
+ switch (act) {
+ case CPC_SMC_EVENT_DUMP_TRACE_DATA:
+ mtk_cpc_dump_timestamp();
+ break;
+ case CPC_SMC_EVENT_GIC_DPG_SET:
+ /* isolated_status = x2; */
+ break;
+ case CPC_SMC_EVENT_CPC_CONFIG:
+ mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2);
+ break;
+ case CPC_SMC_EVENT_READ_CONFIG:
+ res = mtk_cpc_read_config((uint32_t)arg1);
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+void mtk_cpc_init(void)
+{
+ mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING,
+ mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING)
+ | CPC_DBG_EN
+ | CPC_CALC_EN);
+
+ cpc.auto_off = 1;
+ cpc.auto_thres_tick = us_to_ticks(8000);
+
+ mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+ mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG)
+ | CPC_OFF_PRE_EN
+ | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U));
+
+ mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
+}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h
new file mode 100644
index 0000000..488b1d1
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_CPC_H
+#define MT_CPU_PM_CPC_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mcucfg.h>
+#include <platform_def.h>
+
+#define NEED_CPUSYS_PROT_WORKAROUND 1
+
+/* system sram registers */
+#define CPUIDLE_SRAM_REG(r) (0x11B000 + (r))
+
+/* db dump */
+#define CPC_TRACE_SIZE U(0x20)
+#define CPC_TRACE_ID_NUM U(10)
+#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
+
+/* buckup off count */
+#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0)
+#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */
+#define CPC_PWR_ON_SEQ_DIS BIT(1)
+#define CPC_PWR_ON_PRIORITY BIT(2)
+#define CPC_AUTO_OFF_EN BIT(5)
+#define CPC_DORMANT_WAIT_EN BIT(14)
+#define CPC_CTRL_EN BIT(16)
+#define CPC_OFF_PRE_EN BIT(29)
+
+/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */
+#define CPUSYS_PROT_SET BIT(0)
+#define MCUSYS_PROT_SET BIT(8)
+#define CPUSYS_PROT_CLR BIT(8)
+#define MCUSYS_PROT_CLR BIT(9)
+
+#define CPC_PROT_RESP_MASK U(0x3)
+#define CPUSYS_RESP_OFS U(16)
+#define MCUSYS_RESP_OFS U(30)
+
+#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+
+#define RETRY_CNT_MAX U(1000)
+
+#define PROT_RETRY U(0)
+#define PROT_SUCCESS U(1)
+#define PROT_GIVEUP U(2)
+
+/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */
+#define CPC_PROF_EN BIT(0)
+#define CPC_DBG_EN BIT(1)
+#define CPC_FREEZE BIT(2)
+#define CPC_CALC_EN BIT(3)
+
+enum {
+ CPC_SUCCESS = 0U,
+ CPC_ERR_FAIL = 1U,
+ CPC_ERR_TIMEOUT = 2U,
+ NF_CPC_ERR = 3U,
+};
+
+enum {
+ CPC_SMC_EVENT_DUMP_TRACE_DATA = 0U,
+ CPC_SMC_EVENT_GIC_DPG_SET = 1U,
+ CPC_SMC_EVENT_CPC_CONFIG = 2U,
+ CPC_SMC_EVENT_READ_CONFIG = 3U,
+ NF_CPC_SMC_EVENT = 4U,
+};
+
+enum {
+ CPC_SMC_CONFIG_PROF = 0U,
+ CPC_SMC_CONFIG_AUTO_OFF = 1U,
+ CPC_SMC_CONFIG_AUTO_OFF_THRES = 2U,
+ CPC_SMC_CONFIG_CNT_CLR = 3U,
+ CPC_SMC_CONFIG_TIME_SYNC = 4U,
+ NF_CPC_SMC_CONFIG = 5U,
+};
+
+#define us_to_ticks(us) ((us) * 13)
+#define ticks_to_us(tick) ((tick) / 13)
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster);
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster);
+
+void mtk_cpc_mcusys_off_reflect(void);
+int mtk_cpc_mcusys_off_prepare(void);
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu);
+void mtk_cpc_core_on_hint_clr(unsigned int cpu);
+void mtk_cpc_time_sync(void);
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
+void mtk_cpc_init(void);
+
+#endif /* MT_CPU_PM_CPC_H */
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c b/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c
new file mode 100644
index 0000000..b5a0284
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mt_cirq.h>
+#include <mt_lp_irqremain.h>
+#include <mt_lp_rm.h>
+#include <plat_mtk_lpm.h>
+
+#define KEYPAD_IRQ_ID U(138)
+#define KEYPAD_WAKESRC (0x4U)
+
+static struct mt_irqremain remain_irqs;
+
+int mt_lp_irqremain_submit(void)
+{
+ int ret = 0;
+
+ if (remain_irqs.count == 0) {
+ ret = -1;
+ } else {
+ set_wakeup_sources(remain_irqs.irqs, remain_irqs.count);
+ mt_lp_rm_do_update(-1, PLAT_RC_UPDATE_REMAIN_IRQS, &remain_irqs);
+ }
+
+ return ret;
+}
+
+int mt_lp_irqremain_aquire(void)
+{
+ int ret = 0;
+
+ if (remain_irqs.count == 0) {
+ ret = -1;
+ } else {
+ mt_cirq_sw_reset();
+ mt_cirq_clone_gic();
+ mt_cirq_enable();
+ }
+
+ return ret;
+}
+
+int mt_lp_irqremain_release(void)
+{
+ int ret = 0;
+
+ if (remain_irqs.count == 0) {
+ ret = -1;
+ } else {
+ mt_cirq_flush();
+ mt_cirq_disable();
+ }
+
+ return ret;
+}
+
+void mt_lp_irqremain_init(void)
+{
+ uint32_t idx;
+
+ remain_irqs.count = 0U;
+
+ /*edge keypad*/
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = KEYPAD_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0U;
+ remain_irqs.wakeupsrc[idx] = KEYPAD_WAKESRC;
+ remain_irqs.count++;
+
+ mt_lp_irqremain_submit();
+}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h b/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h
new file mode 100644
index 0000000..c313438
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_IRQREMAIN_H
+#define MT_LP_IRQREMAIN_H
+
+extern int mt_lp_irqremain_submit(void);
+extern int mt_lp_irqremain_aquire(void);
+extern int mt_lp_irqremain_release(void);
+extern void mt_lp_irqremain_init(void);
+
+#endif /* MT_LP_IRQREMAIN_H */
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c
new file mode 100644
index 0000000..0103612
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdefs.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mt_mcdi.h>
+
+/* Read/Write */
+#define APMCU_MCUPM_MBOX_AP_READY U(0)
+#define APMCU_MCUPM_MBOX_RESERVED_1 U(1)
+#define APMCU_MCUPM_MBOX_RESERVED_2 U(2)
+#define APMCU_MCUPM_MBOX_RESERVED_3 U(3)
+#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4)
+#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5)
+#define APMCU_MCUPM_MBOX_BUCK_MODE U(6)
+#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7)
+/* Read only */
+#define APMCU_MCUPM_MBOX_TASK_STA U(8)
+#define APMCU_MCUPM_MBOX_RESERVED_9 U(9)
+#define APMCU_MCUPM_MBOX_RESERVED_10 U(10)
+#define APMCU_MCUPM_MBOX_RESERVED_11 U(11)
+
+/* CPC mode - Read/Write */
+#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */
+#define MCUPM_MCUSYS_CTRL BIT(0)
+#define MCUPM_BUCK_CTRL BIT(1)
+#define MCUPM_ARMPLL_CTRL BIT(2)
+#define MCUPM_CM_CTRL BIT(3)
+#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */
+#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */
+#define MCUPM_BUCK_LP_MODE U(1)
+#define MCUPM_BUCK_OFF_MODE U(2)
+#define NF_MCUPM_BUCK_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */
+#define MCUPM_ARMPLL_ON U(0) /* default */
+#define MCUPM_ARMPLL_GATING U(1)
+#define MCUPM_ARMPLL_OFF U(2)
+#define NF_MCUPM_ARMPLL_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */
+#define MCUPM_TASK_UNINIT U(0)
+#define MCUPM_TASK_INIT U(1)
+#define MCUPM_TASK_INIT_FINISH U(2)
+#define MCUPM_TASK_WAIT U(3)
+#define MCUPM_TASK_RUN U(4)
+#define MCUPM_TASK_PAUSE U(5)
+
+#define SSPM_MBOX_3_BASE U(0x10420000)
+
+#define MCDI_NOT_INIT U(0)
+#define MCDI_INIT_1 U(1)
+#define MCDI_INIT_2 U(2)
+#define MCDI_INIT_DONE U(3)
+
+static int mcdi_init_status __section("tzfw_coherent_mem");
+
+static inline uint32_t mcdi_mbox_read(uint32_t id)
+{
+ return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
+}
+
+static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
+{
+ mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
+}
+
+static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev)
+{
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev);
+}
+
+static void mtk_set_mcupm_pll_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_ARMPLL_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode);
+ }
+}
+
+static void mtk_set_mcupm_buck_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_BUCK_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode);
+ }
+}
+
+static int mtk_mcupm_is_ready(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ return ((sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH));
+}
+
+static int mcdi_init_1(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ if (sta != MCUPM_TASK_INIT) {
+ return -1;
+ }
+
+ mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
+ mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
+
+ mtk_mcupm_pwr_ctrl_setting(
+ MCUPM_MCUSYS_CTRL |
+ MCUPM_BUCK_CTRL |
+ MCUPM_ARMPLL_CTRL);
+
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1);
+
+ return 0;
+}
+
+static int mcdi_init_2(void)
+{
+ return mtk_mcupm_is_ready() ? 0 : -1;
+}
+
+int mcdi_try_init(void)
+{
+ if (mcdi_init_status == MCDI_INIT_DONE) {
+ return 0;
+ }
+
+ if (mcdi_init_status == MCDI_NOT_INIT) {
+ mcdi_init_status = MCDI_INIT_1;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) {
+ mcdi_init_status = MCDI_INIT_2;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) {
+ mcdi_init_status = MCDI_INIT_DONE;
+ }
+
+ INFO("mcdi ready for mcusys-off-idle and system suspend\n");
+
+ return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
+}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h
new file mode 100644
index 0000000..0e6444a
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MCDI_H
+#define MT_MCDI_H
+
+int mcdi_try_init(void);
+
+#endif /* MT_MCDI_H */
diff --git a/plat/mediatek/mt8186/drivers/pmic/pmic.c b/plat/mediatek/mt8186/drivers/pmic/pmic.c
new file mode 100644
index 0000000..4f7ab13
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/pmic/pmic.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <pmic.h>
+#include <pmic_wrap_init.h>
+
+uint32_t pmic_get_hwcid(void)
+{
+ uint32_t val = 0;
+
+ pwrap_read(PMIC_RG_HWCID_ADDR, &val);
+
+ return val;
+}
+
+void pmic_power_off(void)
+{
+ pwrap_write(PMIC_PWRHOLD, 0x0);
+}
diff --git a/plat/mediatek/mt8186/drivers/pmic/pmic.h b/plat/mediatek/mt8186/drivers/pmic/pmic.h
new file mode 100644
index 0000000..91ccb19
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/pmic/pmic.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_H
+#define PMIC_H
+
+#include <stdint.h>
+
+#define PMIC_RG_HWCID_ADDR 0x8
+#define PMIC_PWRHOLD 0xa08
+
+/* external API */
+uint32_t pmic_get_hwcid(void);
+void pmic_power_off(void);
+
+#endif /* PMIC_H */
diff --git a/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..e8cbf7e
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+#include <pmic_wrap_init_common.h>
+
+static struct mt8186_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* timeout setting */
+enum {
+ TIMEOUT_RESET = 50, /* us */
+ TIMEOUT_READ = 50, /* us */
+ TIMEOUT_WAIT_IDLE = 50 /* us */
+};
+
+/* PMIC_WRAP registers */
+struct mt8186_pmic_wrap_regs {
+ uint32_t unused[776];
+ uint32_t wacs2_cmd;
+ uint32_t wacs2_rdata;
+ uint32_t wacs2_vldclr;
+};
+
+enum {
+ RDATA_WACS_RDATA_SHIFT = 0,
+ RDATA_WACS_FSM_SHIFT = 16,
+ RDATA_WACS_REQ_SHIFT = 19,
+ RDATA_SYNC_IDLE_SHIFT = 20,
+ RDATA_INIT_DONE_SHIFT = 22,
+ RDATA_SYS_IDLE_SHIFT = 23,
+};
+
+enum {
+ RDATA_WACS_RDATA_MASK = 0xffff,
+ RDATA_WACS_FSM_MASK = 0x7,
+ RDATA_WACS_REQ_MASK = 0x1,
+ RDATA_SYNC_IDLE_MASK = 0x1,
+ RDATA_INIT_DONE_MASK = 0x1,
+ RDATA_SYS_IDLE_MASK = 0x1,
+};
+
+/* WACS_FSM */
+enum {
+ WACS_FSM_IDLE = 0x00,
+ WACS_FSM_REQ = 0x02,
+ WACS_FSM_WFDLE = 0x04,
+ WACS_FSM_WFVLDCLR = 0x06,
+ WACS_INIT_DONE = 0x01,
+ WACS_SYNC_IDLE = 0x01,
+ WACS_SYNC_BUSY = 0x00
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8186/drivers/rtc/rtc.c b/plat/mediatek/mt8186/drivers/rtc/rtc.c
new file mode 100644
index 0000000..4fcf58e
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/rtc/rtc.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <rtc.h>
+
+static void RTC_Config_Interface(uint32_t addr, uint16_t data,
+ uint16_t MASK, uint16_t SHIFT)
+{
+ uint16_t pmic_reg = 0;
+
+ pmic_reg = RTC_Read(addr);
+
+ pmic_reg &= ~(MASK << SHIFT);
+ pmic_reg |= (data << SHIFT);
+
+ RTC_Write(addr, pmic_reg);
+}
+
+static void rtc_disable_2sec_reboot(void)
+{
+ uint16_t reboot;
+
+ reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
+ ~RTC_BBPU_AUTO_PDN_SEL;
+ RTC_Write(RTC_AL_SEC, reboot);
+ RTC_Write_Trigger();
+}
+
+static void rtc_xosc_write(uint16_t val, bool reload)
+{
+ uint16_t bbpu;
+
+ RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1);
+ rtc_busy_wait();
+ RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2);
+ rtc_busy_wait();
+
+ RTC_Write(RTC_OSC32CON, val);
+ rtc_busy_wait();
+
+ if (reload) {
+ bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+ RTC_Write(RTC_BBPU, bbpu);
+ RTC_Write_Trigger();
+ }
+}
+
+static void rtc_enable_k_eosc(void)
+{
+ uint16_t osc32;
+ uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */
+
+ /* Truning on eosc cali mode clock */
+ RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK,
+ PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT);
+ RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK,
+ PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT);
+ RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0,
+ PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+ PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+ switch (rtc_eosc_cali_td) {
+ case 1:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ case 2:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ case 4:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ case 16:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ default:
+ RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6,
+ PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
+ break;
+ }
+ /* Switch the DCXO from 32k-less mode to RTC mode,
+ * otherwise, EOSC cali will fail
+ */
+ /* RTC mode will have only OFF mode and FPM */
+ RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK,
+ PMIC_RG_XO_EN32K_MAN_SHIFT);
+ RTC_Write(RTC_BBPU,
+ RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+ RTC_Write_Trigger();
+ /* Enable K EOSC mode for normal power off and then plug out battery */
+ RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
+ & (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2);
+ RTC_Write_Trigger();
+
+ osc32 = RTC_Read(RTC_OSC32CON);
+ rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true);
+ INFO("[RTC] RTC_enable_k_eosc\n");
+}
+
+void rtc_power_off_sequence(void)
+{
+ uint16_t bbpu;
+
+ rtc_disable_2sec_reboot();
+ rtc_enable_k_eosc();
+
+ /* clear alarm */
+ bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN;
+ if (Writeif_unlock()) {
+ RTC_Write(RTC_BBPU, bbpu);
+
+ RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+ RTC_Write_Trigger();
+ mdelay(1);
+
+ bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+ RTC_Write(RTC_BBPU, bbpu);
+ RTC_Write_Trigger();
+ INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n",
+ RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN),
+ RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC));
+ }
+}
diff --git a/plat/mediatek/mt8186/drivers/rtc/rtc.h b/plat/mediatek/mt8186/drivers/rtc/rtc.h
new file mode 100644
index 0000000..b48dbb9
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/rtc/rtc.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#define PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK (1U)
+#define PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT (1U)
+#define PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK (1U)
+#define PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT (3U)
+#define PMIC_RG_RTC_EOSC32_CK_PDN_MASK (1U)
+#define PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT (2U)
+#define PMIC_RG_EOSC_CALI_TD_MASK (7U)
+#define PMIC_RG_EOSC_CALI_TD_SHIFT (5U)
+#define PMIC_RG_XO_EN32K_MAN_MASK (1U)
+#define PMIC_RG_XO_EN32K_MAN_SHIFT (0U)
+
+/* RTC registers */
+enum {
+ RTC_BBPU = 0x0588,
+ RTC_IRQ_STA = 0x058A,
+ RTC_IRQ_EN = 0x058C,
+ RTC_CII_EN = 0x058E
+};
+
+enum {
+ RTC_AL_SEC = 0x05A0,
+ RTC_AL_MIN = 0x05A2,
+ RTC_AL_HOU = 0x05A4,
+ RTC_AL_DOM = 0x05A6,
+ RTC_AL_DOW = 0x05A8,
+ RTC_AL_MTH = 0x05AA,
+ RTC_AL_YEA = 0x05AC,
+ RTC_AL_MASK = 0x0590
+};
+
+enum {
+ RTC_OSC32CON = 0x05AE,
+ RTC_CON = 0x05C4,
+ RTC_WRTGR = 0x05C2
+};
+
+enum {
+ RTC_PDN1 = 0x05B4,
+ RTC_PDN2 = 0x05B6,
+ RTC_SPAR0 = 0x05B8,
+ RTC_SPAR1 = 0x05BA,
+ RTC_PROT = 0x05BC,
+ RTC_DIFF = 0x05BE,
+ RTC_CALI = 0x05C0
+};
+
+enum {
+ RTC_OSC32CON_UNLOCK1 = 0x1A57,
+ RTC_OSC32CON_UNLOCK2 = 0x2B68
+};
+
+enum {
+ RTC_PROT_UNLOCK1 = 0x586A,
+ RTC_PROT_UNLOCK2 = 0x9136
+};
+
+enum {
+ RTC_BBPU_PWREN = 1U << 0,
+ RTC_BBPU_CLR = 1U << 1,
+ RTC_BBPU_INIT = 1U << 2,
+ RTC_BBPU_AUTO = 1U << 3,
+ RTC_BBPU_CLRPKY = 1U << 4,
+ RTC_BBPU_RELOAD = 1U << 5,
+ RTC_BBPU_CBUSY = 1U << 6
+};
+
+enum {
+ RTC_AL_MASK_SEC = 1U << 0,
+ RTC_AL_MASK_MIN = 1U << 1,
+ RTC_AL_MASK_HOU = 1U << 2,
+ RTC_AL_MASK_DOM = 1U << 3,
+ RTC_AL_MASK_DOW = 1U << 4,
+ RTC_AL_MASK_MTH = 1U << 5,
+ RTC_AL_MASK_YEA = 1U << 6
+};
+
+enum {
+ RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
+ RTC_BBPU_2SEC_CK_SEL = 1U << 7,
+ RTC_BBPU_2SEC_EN = 1U << 8,
+ RTC_BBPU_2SEC_MODE = 0x3 << 9,
+ RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
+ RTC_BBPU_2SEC_STAT_STA = 1U << 12
+};
+
+enum {
+ RTC_BBPU_KEY = 0x43 << 8
+};
+
+enum {
+ RTC_EMBCK_SRC_SEL = 1 << 8,
+ RTC_EMBCK_SEL_MODE = 3 << 6,
+ RTC_XOSC32_ENB = 1 << 5,
+ RTC_REG_XOSC32_ENB = 1 << 15
+};
+
+enum {
+ RTC_K_EOSC_RSV_0 = 1 << 8,
+ RTC_K_EOSC_RSV_1 = 1 << 9,
+ RTC_K_EOSC_RSV_2 = 1 << 10
+};
+
+/* PMIC TOP Register Definition */
+enum {
+ PMIC_RG_TOP_CON = 0x001E,
+ PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
+ PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
+ PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
+ PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
+ PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
+ PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
+};
+
+/* PMIC SCK Register Definition */
+enum {
+ PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x051A,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C,
+ PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E,
+ PMIC_RG_EOSC_CALI_CON0 = 0x540
+};
+
+/* PMIC DCXO Register Definition */
+enum {
+ PMIC_RG_DCXO_CW00 = 0x0788,
+ PMIC_RG_DCXO_CW02 = 0x0790
+};
+
+/* external API */
+uint16_t RTC_Read(uint32_t addr);
+void RTC_Write(uint32_t addr, uint16_t data);
+int32_t rtc_busy_wait(void);
+int32_t RTC_Write_Trigger(void);
+int32_t Writeif_unlock(void);
+void rtc_power_off_sequence(void);
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/build.mk b/plat/mediatek/mt8186/drivers/spm/build.mk
new file mode 100644
index 0000000..72a2b6b
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/build.mk
@@ -0,0 +1,78 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Enable or disable spm feature
+MT_SPM_FEATURE_SUPPORT=yes
+
+# Enable or disable cirq restore
+MT_SPM_CIRQ_FEATURE_SUPPORT=yes
+
+# sspm notifier support
+MT_SPM_SSPM_NOTIFIER_SUPPORT=yes
+
+CUR_SPM_FOLDER = ${MTK_PLAT_SOC}/drivers/spm
+
+# spm common files
+PLAT_SPM_SOURCE_FILES_COMMON += \
+ ${CUR_SPM_FOLDER}/mt_spm.c \
+ ${CUR_SPM_FOLDER}/mt_spm_internal.c \
+ ${CUR_SPM_FOLDER}/mt_spm_pmic_wrap.c \
+ ${CUR_SPM_FOLDER}/mt_spm_vcorefs.c \
+ ${CUR_SPM_FOLDER}/mt_spm_conservation.c \
+ ${CUR_SPM_FOLDER}/mt_spm_extern.c
+
+# spm platform dependcy files
+PLAT_SPM_SOURCE_FILES += \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_bus26m.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_cpu_buck_ldo.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_dram.c \
+ ${CUR_SPM_FOLDER}/mt_spm_cond.c \
+ ${CUR_SPM_FOLDER}/mt_spm_suspend.c \
+ ${CUR_SPM_FOLDER}/mt_spm_idle.c
+
+ifeq (${MT_SPM_FEATURE_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT
+
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${PLAT_SPM_SOURCE_FILES_COMMON}
+else
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \
+ ${PLAT_SPM_SOURCE_FILES_COMMON} \
+ ${PLAT_SPM_SOURCE_FILES}
+endif
+
+ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_CIRQ_UNSUPPORT
+endif
+
+ifeq (${MT_SPM_SSPM_NOTIFIER_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+else
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${CUR_SPM_FOLDER}/notifier/mt_spm_sspm_notifier.c
+endif
+
+ifeq (${MTK_VOLTAGE_BIN_VCORE}, yes)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_VOLTAGE_BIN_VCORE_SUPPORT
+endif
+
+ifeq ($(MTK_SPM_EXTENSION_CONFIG), pmic6362)
+MTK_SPM_EXTENSION_PMIC_CONTROL := 6362
+$(eval $(call add_define,MTK_SPM_EXTENSION_PMIC_CONTROL))
+endif
+
+$(info --------------------------------------)
+$(info SPM build flags: ${PLAT_SPM_DEBUG_CFLAGS})
+$(info SPM build files: ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES})
+$(info --------------------------------------)
+
+# Common makefile for platform.mk
+PLAT_INCLUDES += \
+ ${PLAT_SPM_DEBUG_CFLAGS} \
+ -I${CUR_SPM_FOLDER}/ \
+ -I${CUR_SPM_FOLDER}/constraints/ \
+ -I${CUR_SPM_FOLDER}/notifier/
+
+PLAT_BL_COMMON_SOURCES += ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES}
diff --git a/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c
new file mode 100644
index 0000000..dd2aee8
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#ifndef ATF_PLAT_CIRQ_UNSUPPORT
+#include <mt_gic_v3.h>
+#endif
+
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+
+#ifndef ATF_PLAT_CIRQ_UNSUPPORT
+#include <mt_cirq.h>
+#endif
+
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+#define CONSTRAINT_BUS26M_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
+ MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \
+ MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF)
+
+#define CONSTRAINT_BUS26M_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_ENABLE_TIA_WORKAROUND | \
+ SPM_FLAG_ENABLE_LVTS_WORKAROUND | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
+
+#define CONSTRAINT_BUS26M_PCM_FLAG1 (0U)
+#define CONSTRAINT_BUS26M_RESOURCE_REQ (0U)
+
+static unsigned int bus26m_ext_opand;
+static struct mt_irqremain *refer2remain_irq;
+static struct mt_spm_cond_tables cond_bus26m = {
+ .name = "bus26m",
+ .table_cg = {
+ 0x0385E03C, /* MTCMOS1 */
+ 0x003F0100, /* INFRA0 */
+ 0x0A040802, /* INFRA1 */
+ 0x06017E51, /* INFRA2 */
+ 0x08000000, /* INFRA3 */
+ 0x00000000, /* INFRA4 */
+ 0x00000000, /* INFRA5 */
+ 0x03720820, /* MMSYS0 */
+ 0x00000000, /* MMSYS1 */
+ 0x00000000, /* MMSYS2 */
+ 0x00015151, /* MMSYS3 */
+ },
+ .table_pll = (PLL_BIT_UNIVPLL | PLL_BIT_MFGPLL |
+ PLL_BIT_MSDCPLL | PLL_BIT_TVDPLL |
+ PLL_BIT_MMPLL),
+};
+
+static struct mt_spm_cond_tables cond_bus26m_res = {
+ .table_cg = {0U},
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_BUS26M,
+ .valid = (MT_SPM_RC_VALID_SW | MT_SPM_RC_VALID_COND_LATCH),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_bus26m_res,
+};
+
+/*
+ * Cirq will take the place of gic when gic is off.
+ * However, cirq cannot work if 26m clk is turned off when system idle/suspend.
+ * Therefore, we need to set irq pending for specific wakeup source.
+ */
+#ifdef ATF_PLAT_CIRQ_UNSUPPORT
+#define do_irqs_delivery()
+#else
+static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs,
+ unsigned int irq_index,
+ struct wake_status *wakeup)
+{
+ INFO("[SPM] r12 = 0x%08x(0x%08x), flag = 0x%08x 0x%08x 0x%08x\n",
+ wakeup->tr.comm.r12, wakeup->md32pcm_wakeup_sta,
+ wakeup->tr.comm.debug_flag, wakeup->tr.comm.b_sw_flag0,
+ wakeup->tr.comm.b_sw_flag1);
+
+ INFO("irq:%u(0x%08x) set pending\n",
+ irqs->wakeupsrc[irq_index], irqs->irqs[irq_index]);
+}
+
+static void do_irqs_delivery(void)
+{
+ unsigned int idx;
+ int res = 0;
+ struct wake_status *wakeup = NULL;
+ struct mt_irqremain *irqs = refer2remain_irq;
+
+ res = spm_conservation_get_result(&wakeup);
+
+ if ((res != 0) && (irqs == NULL)) {
+ return;
+ }
+
+ for (idx = 0; idx < irqs->count; ++idx) {
+ if (((wakeup->tr.comm.r12 & irqs->wakeupsrc[idx]) != 0U) ||
+ ((wakeup->raw_sta & irqs->wakeupsrc[idx]) != 0U)) {
+ if ((irqs->wakeupsrc_cat[idx] & MT_IRQ_REMAIN_CAT_LOG) != 0U) {
+ mt_spm_irq_remain_dump(irqs, idx, wakeup);
+ }
+
+ mt_irq_set_pending(irqs->irqs[idx]);
+ }
+ }
+}
+#endif
+
+static void spm_bus26m_conduct(struct spm_lp_scen *spm_lp, unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return ((status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid));
+}
+
+int spm_update_rc_bus26m(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ res = MT_RM_STATUS_BAD;
+ } else {
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_bus26m;
+
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ (&cond_bus26m_res) : (NULL));
+ } else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) {
+ refer2remain_irq = (struct mt_irqremain *)val;
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_bus26m(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_BUS26M_ALLOW;
+}
+
+int spm_run_rc_bus26m(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+
+#ifdef ATF_VOLTAGE_BIN_VCORE_SUPPORT
+#define SUSPEND_VB_MAGIC (0x5642)
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_SUSPEND_VCORE_VOLTAGE,
+ ((SUSPEND_VB_MAGIC << 16) |
+ spm_get_suspend_vcore_voltage_idx()));
+ }
+#endif
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, CONSTRAINT_BUS26M_ALLOW |
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U)));
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_CLR_26M_RECORD |
+ MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT |
+ bus26m_ext_opand),
+ CONSTRAINT_BUS26M_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op, spm_bus26m_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_bus26m(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ ext_op |= (bus26m_ext_opand | MT_SPM_EX_OP_SET_WDT);
+ mt_spm_suspend_resume(state_id, ext_op, NULL);
+ bus26m_ext_opand = 0U;
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL);
+ status.enter_cnt++;
+ }
+
+ do_irqs_delivery();
+ return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c
new file mode 100644
index 0000000..c47cf1f
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+#define CONSTRAINT_CPU_BUCK_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
+
+#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 (0U)
+
+#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ \
+ (MT_SPM_DRAM_S1 | \
+ MT_SPM_DRAM_S0 | \
+ MT_SPM_SYSPLL | \
+ MT_SPM_INFRA | \
+ MT_SPM_26M | \
+ MT_SPM_XO_FPM)
+
+static unsigned int cpubuckldo_status = MT_SPM_RC_VALID_SW;
+static unsigned int cpubuckldo_enter_cnt;
+
+static void spm_cpu_bcuk_ldo_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_CPU_BUCK_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return IS_MT_RM_RC_READY(cpubuckldo_status);
+}
+
+unsigned int spm_allow_rc_cpu_buck_ldo(int state_id)
+{
+ (void)state_id;
+
+ return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF;
+}
+
+int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ unsigned int ext_op = 0U;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER,
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U)));
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ MT_SPM_EX_OP_SET_WDT,
+ CONSTRAINT_CPU_BUCK_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op,
+ spm_cpu_bcuk_ldo_conduct);
+ }
+
+ cpubuckldo_enter_cnt++;
+
+ return 0;
+}
+
+int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ unsigned int ext_op = 0U;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL);
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c
new file mode 100644
index 0000000..b281734
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+#define CONSTRAINT_DRAM_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF)
+
+#define CONSTRAINT_DRAM_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
+
+#define CONSTRAINT_DRAM_PCM_FLAG1 (0U)
+
+#define CONSTRAINT_DRAM_RESOURCE_REQ \
+ (MT_SPM_SYSPLL | \
+ MT_SPM_INFRA | \
+ MT_SPM_26M)
+
+static struct mt_spm_cond_tables cond_dram = {
+ .name = "dram",
+ .table_cg = {
+ 0x0385E03C, /* MTCMOS1 */
+ 0x003F0100, /* INFRA0 */
+ 0x08040802, /* INFRA1 */
+ 0x06015641, /* INFRA2 */
+ 0x00000000, /* INFRA3 */
+ 0x00000000, /* INFRA4 */
+ 0x00000000, /* INFRA5 */
+ 0x02300020, /* MMSYS0 */
+ 0x00000000, /* MMSYS1 */
+ 0x00000000, /* MMSYS2 */
+ 0x00015111, /* MMSYS3 */
+ },
+ .table_pll = 0U,
+};
+
+static struct mt_spm_cond_tables cond_dram_res = {
+ .table_cg = {0U},
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_DRAM,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH |
+ MT_SPM_RC_VALID_XSOC_BBLPM),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_dram_res,
+};
+
+static void spm_dram_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_DRAM_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_dram(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return ((status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid));
+}
+
+int spm_update_rc_dram(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ res = MT_RM_STATUS_BAD;
+ } else {
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_dram;
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ (&cond_dram_res) : (NULL));
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_dram(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_DRAM_ALLOW;
+}
+
+int spm_run_rc_dram(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_DRAM_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | (IS_PLAT_SUSPEND_ID(state_id) ?
+ (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U)));
+#else
+ (void)allows;
+#endif
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT | MT_SPM_EX_OP_HW_S1_DETECT),
+ CONSTRAINT_DRAM_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_dram(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_DRAM_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
+#else
+ (void)allows;
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id,
+ (MT_SPM_EX_OP_SET_WDT | MT_SPM_EX_OP_HW_S1_DETECT),
+ NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL);
+ status.enter_cnt++;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h
new file mode 100644
index 0000000..dfacba9
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_RC_INTERNAL_H
+#define MT_SPM_RC_INTERNAL_H
+
+#include <stdbool.h>
+
+#define SPM_SRAM_SLEEP_DEFAULT_FLAG (SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP)
+
+#define SPM_FLAG_SRAM_SLEEP_CTRL \
+ (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_SYSRAM_SLEEP | \
+ SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_SRAM_EVENT)
+
+/* cpu buck/ldo constraint function */
+bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+unsigned int spm_allow_rc_cpu_buck_ldo(int state_id);
+int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+
+/* spm resource dram constraint function */
+bool spm_is_valid_rc_dram(unsigned int cpu, int state_id);
+int spm_update_rc_dram(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_dram(int state_id);
+int spm_run_rc_dram(unsigned int cpu, int state_id);
+int spm_reset_rc_dram(unsigned int cpu, int state_id);
+
+/* spm resource syspll constraint function */
+bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id);
+int spm_update_rc_syspll(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_syspll(int state_id);
+int spm_run_rc_syspll(unsigned int cpu, int state_id);
+int spm_reset_rc_syspll(unsigned int cpu, int state_id);
+
+/* spm resource bus26m constraint function */
+bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id);
+int spm_update_rc_bus26m(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_bus26m(int state_id);
+int spm_run_rc_bus26m(unsigned int cpu, int state_id);
+int spm_reset_rc_bus26m(unsigned int cpu, int state_id);
+
+#endif /* MT_SPM_RC_INTERNAL_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c
new file mode 100644
index 0000000..4977de1
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+#define CONSTRAINT_SYSPLL_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_VCORE_LP)
+
+#if (MTK_SPM_EXTENSION_PMIC_CONTROL == 6362)
+#define SPM_FLAG_EXTRA_PMIC_CONTROL (SPM_FLAG_ENABLE_6362_CTRL)
+#else
+#define SPM_FLAG_EXTRA_PMIC_CONTROL (SPM_FLAG_ENABLE_6315_CTRL)
+#endif
+
+#define CONSTRAINT_SYSPLL_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_USE_SRCCLKENO2 | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
+ SPM_FLAG_USE_SRCCLKENO2)
+
+#define CONSTRAINT_SYSPLL_PCM_FLAG1 (0U)
+#define CONSTRAINT_SYSPLL_RESOURCE_REQ (MT_SPM_26M)
+
+static struct mt_spm_cond_tables cond_syspll = {
+ .name = "syspll",
+ .table_cg = {
+ 0x0385E03C, /* MTCMOS1 */
+ 0x003F0100, /* INFRA0 */
+ 0x08040802, /* INFRA1 */
+ 0x06015641, /* INFRA2 */
+ 0x00000000, /* INFRA3 */
+ 0x00000000, /* INFRA4 */
+ 0x00000000, /* INFRA5 */
+ 0x03720820, /* MMSYS0 */
+ 0x00000000, /* MMSYS1 */
+ 0x00000000, /* MMSYS2 */
+ 0x00015151, /* MMSYS3 */
+ },
+ .table_pll = 0U,
+};
+
+static struct mt_spm_cond_tables cond_syspll_res = {
+ .table_cg = {0U},
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_SYSPLL,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH |
+ MT_SPM_RC_VALID_XSOC_BBLPM),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_syspll_res,
+};
+
+static void spm_syspll_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1;
+
+ *resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return ((status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid));
+}
+
+int spm_update_rc_syspll(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ res = MT_RM_STATUS_BAD;
+ } else {
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll;
+
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ (&cond_syspll_res) : (NULL));
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_syspll(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_SYSPLL_ALLOW;
+}
+
+int spm_run_rc_syspll(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | (IS_PLAT_SUSPEND_ID(state_id) ?
+ (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U)));
+#else
+ (void)allows;
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT |
+ MT_SPM_EX_OP_SET_SUSPEND_MODE),
+ CONSTRAINT_SYSPLL_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_syspll(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
+#else
+ (void)allows;
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id,
+ (MT_SPM_EX_OP_SET_SUSPEND_MODE |
+ MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT),
+ NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL);
+ status.enter_cnt++;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm.c b/plat/mediatek/mt8186/drivers/spm/mt_spm.c
new file mode 100644
index 0000000..8ad50e2
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include "mt_spm_extern.h"
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <mtk_plat_common.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+#include <sleep_def.h>
+
+#ifdef MT_SPM_USING_BAKERY_LOCK
+DEFINE_BAKERY_LOCK(spm_lock);
+#define plat_spm_lock_init() bakery_lock_init(&spm_lock)
+#else
+spinlock_t spm_lock;
+#define plat_spm_lock_init()
+#endif
+
+/* CLK_SCP_CFG_0 */
+#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x200)
+#define SPM_CK_CONTROL_EN (0x3FF)
+
+/* CLK_SCP_CFG_1 */
+#define CLK_SCP_CFG_1 (TOPCKGEN_BASE + 0x210)
+#define CLK_SCP_CFG_1_MASK (0x100C)
+#define CLK_SCP_CFG_1_SPM (0x3)
+
+#define MT_SPM_EX_OP_TIME_CHECK BIT(10)
+
+struct mt_resource_constraint plat_constraint_bus26m = {
+ .is_valid = spm_is_valid_rc_bus26m,
+ .update = spm_update_rc_bus26m,
+ .allow = spm_allow_rc_bus26m,
+ .run = spm_run_rc_bus26m,
+ .reset = spm_reset_rc_bus26m,
+};
+
+struct mt_resource_constraint plat_constraint_syspll = {
+ .is_valid = spm_is_valid_rc_syspll,
+ .update = spm_update_rc_syspll,
+ .allow = spm_allow_rc_syspll,
+ .run = spm_run_rc_syspll,
+ .reset = spm_reset_rc_syspll,
+};
+
+struct mt_resource_constraint plat_constraint_dram = {
+ .is_valid = spm_is_valid_rc_dram,
+ .update = spm_update_rc_dram,
+ .allow = spm_allow_rc_dram,
+ .run = spm_run_rc_dram,
+ .reset = spm_reset_rc_dram,
+};
+
+/* Maybe remove when the spm won't cpu power control aymore */
+struct mt_resource_constraint plat_constraint_cpu = {
+ .is_valid = spm_is_valid_rc_cpu_buck_ldo,
+ .update = NULL,
+ .allow = spm_allow_rc_cpu_buck_ldo,
+ .run = spm_run_rc_cpu_buck_ldo,
+ .reset = spm_reset_rc_cpu_buck_ldo,
+};
+
+struct mt_resource_constraint *plat_constraints[] = {
+ &plat_constraint_bus26m,
+ &plat_constraint_syspll,
+ &plat_constraint_dram,
+ &plat_constraint_cpu,
+ NULL,
+};
+
+struct mt_resource_manager plat_mt8186_rm = {
+ .update = mt_spm_cond_update,
+ .consts = plat_constraints,
+};
+
+void spm_boot_init(void)
+{
+ NOTICE("MT8186 %s\n", __func__);
+
+ /* switch ck_off/axi_26m control to SPM */
+ mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_CONTROL_EN);
+ mmio_clrsetbits_32(CLK_SCP_CFG_1, CLK_SCP_CFG_1_MASK, CLK_SCP_CFG_1_SPM);
+
+ plat_spm_lock_init();
+ mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
+ mt_lp_rm_register(&plat_mt8186_rm);
+ mt_spm_idle_generic_init();
+ mt_spm_suspend_init();
+ spm_extern_initialize();
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm.h b/plat/mediatek/mt8186/drivers/spm/mt_spm.h
new file mode 100644
index 0000000..0e21b5e
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_H
+#define MT_SPM_H
+
+#include <lib/bakery_lock.h>
+#include <lib/spinlock.h>
+#include <plat_mtk_lpm.h>
+
+/*
+ * ARM v8.2, the cache will turn off automatically when cpu
+ * power down. Therefore, there is no doubt to use the spin_lock here.
+ */
+#if !HW_ASSISTED_COHERENCY
+#define MT_SPM_USING_BAKERY_LOCK
+#endif
+
+#ifdef MT_SPM_USING_BAKERY_LOCK
+DECLARE_BAKERY_LOCK(spm_lock);
+#define plat_spm_lock() bakery_lock_get(&spm_lock)
+#define plat_spm_unlock() bakery_lock_release(&spm_lock)
+#else
+extern spinlock_t spm_lock;
+#define plat_spm_lock() spin_lock(&spm_lock)
+#define plat_spm_unlock() spin_unlock(&spm_lock)
+#endif
+
+#define MT_SPM_USING_SRCLKEN_RC
+
+/* spm extern operand definition */
+#define MT_SPM_EX_OP_CLR_26M_RECORD BIT(0)
+#define MT_SPM_EX_OP_SET_WDT BIT(1)
+#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ BIT(2)
+#define MT_SPM_EX_OP_SET_SUSPEND_MODE BIT(3)
+#define MT_SPM_EX_OP_SET_IS_ADSP BIT(4)
+#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM BIT(5)
+#define MT_SPM_EX_OP_HW_S1_DETECT BIT(6)
+#define MT_SPM_EX_OP_TRACE_LP BIT(7)
+#define MT_SPM_EX_OP_TRACE_SUSPEND BIT(8)
+#define MT_SPM_EX_OP_TRACE_TIMESTAMP_EN BIT(9)
+#define MT_SPM_EX_OP_TIME_CHECK BIT(10)
+#define MT_SPM_EX_OP_TIME_OBS BIT(11)
+
+typedef enum {
+ WR_NONE = 0,
+ WR_UART_BUSY = 1,
+ WR_ABORT = 2,
+ WR_PCM_TIMER = 3,
+ WR_WAKE_SRC = 4,
+ WR_DVFSRC = 5,
+ WR_TWAM = 6,
+ WR_PMSR = 7,
+ WR_SPM_ACK_CHK = 8,
+ WR_UNKNOWN = 9,
+} wake_reason_t;
+
+/* for suspend vol. bin settings */
+enum MT_PLAT_SUSPEND_VCORE {
+ SPM_SUSPEND_VCORE_5500 = 0,
+ SPM_SUSPEND_VCORE_5250 = 1,
+ SPM_SUSPEND_VCORE_5000 = 2,
+};
+
+extern void spm_boot_init(void);
+
+static inline void spm_lock_get(void)
+{
+ plat_spm_lock();
+}
+
+static inline void spm_lock_release(void)
+{
+ plat_spm_unlock();
+}
+
+unsigned int spm_get_suspend_vcore_voltage_idx(void);
+
+#endif /* MT_SPM_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c
new file mode 100644
index 0000000..a420e16
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+#define MT_LP_TZ_INFRA_REG(ofs) (INFRACFG_AO_BASE + ofs)
+#define MT_LP_TZ_MM_REG(ofs) (MMSYS_BASE + ofs)
+#define MT_LP_TZ_MDP_REG(ofs) (MDPSYS_BASE + ofs)
+#define MT_LP_TZ_SPM_REG(ofs) (SPM_BASE + ofs)
+#define MT_LP_TZ_TOPCK_REG(ofs) (TOPCKGEN_BASE + ofs)
+#define MT_LP_TZ_APMIXEDSYS(ofs) (APMIXEDSYS + ofs)
+
+#define SPM_PWR_STATUS MT_LP_TZ_SPM_REG(0x016C)
+#define SPM_PWR_STATUS_2ND MT_LP_TZ_SPM_REG(0x0170)
+#define INFRA_SW_CG0 MT_LP_TZ_INFRA_REG(0x0090)
+#define INFRA_SW_CG1 MT_LP_TZ_INFRA_REG(0x0094)
+#define INFRA_SW_CG2 MT_LP_TZ_INFRA_REG(0x00AC)
+#define INFRA_SW_CG3 MT_LP_TZ_INFRA_REG(0x00C8)
+#define INFRA_SW_CG4 MT_LP_TZ_INFRA_REG(0x00E8)
+#define INFRA_SW_CG5 MT_LP_TZ_INFRA_REG(0x00D8)
+#define MMSYS_CG_CON0 MT_LP_TZ_MM_REG(0x100)
+#define MMSYS_CG_CON1 MT_LP_TZ_MM_REG(0x110)
+#define MMSYS_CG_CON2 MT_LP_TZ_MM_REG(0x1A0)
+#define MMSYS_CG_CON3 MT_LP_TZ_MDP_REG(0x100)
+
+/* Check clkmux registers */
+#define CLK_CFG(id) MT_LP_TZ_TOPCK_REG(0xe0 + id * 0x10)
+#define CLK_CHECK BIT(31)
+
+enum {
+ CLKMUX_DISP = 0,
+ CLKMUX_MDP = 1,
+ CLKMUX_IMG1 = 2,
+ CLKMUX_IMG2 = 3,
+ NF_CLKMUX = 4,
+};
+
+static bool is_clkmux_pdn(unsigned int clkmux_id)
+{
+ unsigned int reg, val, idx;
+ bool ret = false;
+
+ if (clkmux_id & CLK_CHECK) {
+ clkmux_id = (clkmux_id & ~CLK_CHECK);
+ reg = clkmux_id / 4U;
+ val = mmio_read_32(CLK_CFG(reg));
+ idx = clkmux_id % 4U;
+ ret = (((val >> (idx * 8U)) & 0x80) != 0U);
+ }
+
+ return ret;
+}
+
+static struct mt_spm_cond_tables spm_cond_t;
+
+struct idle_cond_info {
+ unsigned int subsys_mask;
+ uintptr_t addr;
+ bool bit_flip;
+ unsigned int clkmux_id;
+};
+
+#define IDLE_CG(mask, addr, bitflip, clkmux) \
+ {mask, (uintptr_t)addr, bitflip, clkmux}
+
+static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = {
+ IDLE_CG(0xffffffff, SPM_PWR_STATUS, false, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG0, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG1, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG2, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG3, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG4, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG5, true, 0U),
+ IDLE_CG(0x00200000, MMSYS_CG_CON0, true, (CLK_CHECK | CLKMUX_DISP)),
+ IDLE_CG(0x00200000, MMSYS_CG_CON1, true, (CLK_CHECK | CLKMUX_DISP)),
+ IDLE_CG(0x00200000, MMSYS_CG_CON2, true, (CLK_CHECK | CLKMUX_DISP)),
+ IDLE_CG(0x00200000, MMSYS_CG_CON3, true, (CLK_CHECK | CLKMUX_MDP)),
+};
+
+/* Check pll idle condition */
+#define PLL_MFGPLL MT_LP_TZ_APMIXEDSYS(0x314)
+#define PLL_MMPLL MT_LP_TZ_APMIXEDSYS(0x254)
+#define PLL_UNIVPLL MT_LP_TZ_APMIXEDSYS(0x324)
+#define PLL_MSDCPLL MT_LP_TZ_APMIXEDSYS(0x38c)
+#define PLL_TVDPLL MT_LP_TZ_APMIXEDSYS(0x264)
+
+unsigned int mt_spm_cond_check(int state_id,
+ const struct mt_spm_cond_tables *src,
+ const struct mt_spm_cond_tables *dest,
+ struct mt_spm_cond_tables *res)
+{
+ unsigned int blocked = 0U;
+ unsigned int i;
+ bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id);
+
+ if ((src == NULL) || (dest == NULL)) {
+ blocked = SPM_COND_CHECK_FAIL;
+ } else {
+ for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
+ if (res != NULL) {
+ res->table_cg[i] = (src->table_cg[i] & dest->table_cg[i]);
+ if (is_system_suspend && ((res->table_cg[i]) != 0U)) {
+ INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n",
+ dest->name, i, idle_cg_info[i].addr,
+ res->table_cg[i]);
+ }
+
+ if ((res->table_cg[i]) != 0U) {
+ blocked |= BIT(i);
+ }
+ } else if ((src->table_cg[i] & dest->table_cg[i]) != 0U) {
+ blocked |= BIT(i);
+ break;
+ }
+ }
+
+ if (res != NULL) {
+ res->table_pll = (src->table_pll & dest->table_pll);
+
+ if (res->table_pll != 0U) {
+ blocked |= (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) |
+ SPM_COND_CHECK_BLOCKED_PLL;
+ }
+ } else if ((src->table_pll & dest->table_pll) != 0U) {
+ blocked |= SPM_COND_CHECK_BLOCKED_PLL;
+ }
+
+ if (is_system_suspend && ((blocked) != 0U)) {
+ INFO("suspend: %s total blocked = 0x%08x\n", dest->name, blocked);
+ }
+ }
+
+ return blocked;
+}
+
+#define IS_MT_SPM_PWR_OFF(mask) \
+ (((mmio_read_32(SPM_PWR_STATUS) & mask) == 0U) && \
+ ((mmio_read_32(SPM_PWR_STATUS_2ND) & mask) == 0U))
+
+int mt_spm_cond_update(struct mt_resource_constraint **con, int stateid, void *priv)
+{
+ int res;
+ uint32_t i;
+ struct mt_resource_constraint *const *rc;
+
+ /* read all cg state */
+ for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
+ spm_cond_t.table_cg[i] = 0U;
+
+ /* check mtcmos, if off set idle_value and clk to 0 disable */
+ if (IS_MT_SPM_PWR_OFF(idle_cg_info[i].subsys_mask)) {
+ continue;
+ }
+
+ /* check clkmux */
+ if (is_clkmux_pdn(idle_cg_info[i].clkmux_id)) {
+ continue;
+ }
+
+ spm_cond_t.table_cg[i] = idle_cg_info[i].bit_flip ?
+ ~mmio_read_32(idle_cg_info[i].addr) :
+ mmio_read_32(idle_cg_info[i].addr);
+ }
+
+ spm_cond_t.table_pll = 0U;
+ if ((mmio_read_32(PLL_MFGPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MFGPLL;
+ }
+
+ if ((mmio_read_32(PLL_MMPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MMPLL;
+ }
+
+ if ((mmio_read_32(PLL_UNIVPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_UNIVPLL;
+ }
+
+ if ((mmio_read_32(PLL_MSDCPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MSDCPLL;
+ }
+
+ if ((mmio_read_32(PLL_TVDPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_TVDPLL;
+ }
+
+ spm_cond_t.priv = priv;
+
+ for (rc = con; *rc != NULL; rc++) {
+ if (((*rc)->update) == NULL) {
+ continue;
+ }
+
+ res = (*rc)->update(stateid, PLAT_RC_UPDATE_CONDITION,
+ (void const *)&spm_cond_t);
+ if (res != MT_RM_STATUS_OK) {
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h
new file mode 100644
index 0000000..24c39ba
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONDIT_H
+#define MT_SPM_CONDIT_H
+
+#include <mt_lp_rm.h>
+
+enum PLAT_SPM_COND {
+ PLAT_SPM_COND_MTCMOS1 = 0,
+ PLAT_SPM_COND_CG_INFRA_0 = 1,
+ PLAT_SPM_COND_CG_INFRA_1 = 2,
+ PLAT_SPM_COND_CG_INFRA_2 = 3,
+ PLAT_SPM_COND_CG_INFRA_3 = 4,
+ PLAT_SPM_COND_CG_INFRA_4 = 5,
+ PLAT_SPM_COND_CG_INFRA_5 = 6,
+ PLAT_SPM_COND_CG_MMSYS_0 = 7,
+ PLAT_SPM_COND_CG_MMSYS_1 = 8,
+ PLAT_SPM_COND_CG_MMSYS_2 = 9,
+ PLAT_SPM_COND_CG_MMSYS_3 = 10,
+ PLAT_SPM_COND_MAX = 11,
+};
+
+#define PLL_BIT_UNIVPLL BIT(0)
+#define PLL_BIT_MFGPLL BIT(1)
+#define PLL_BIT_MSDCPLL BIT(2)
+#define PLL_BIT_TVDPLL BIT(3)
+#define PLL_BIT_MMPLL BIT(4)
+
+/*
+ * Definition about SPM_COND_CHECK_BLOCKED
+ * bit [00 ~ 15]: cg blocking index
+ * bit [16 ~ 29]: pll blocking index
+ * bit [30] : pll blocking information
+ * bit [31] : idle condition check fail
+ */
+#define SPM_COND_BLOCKED_CG_IDX U(0)
+#define SPM_COND_BLOCKED_PLL_IDX U(16)
+#define SPM_COND_CHECK_BLOCKED_PLL BIT(30)
+#define SPM_COND_CHECK_FAIL BIT(31)
+
+struct mt_spm_cond_tables {
+ char *name;
+ unsigned int table_cg[PLAT_SPM_COND_MAX];
+ unsigned int table_pll;
+ void *priv;
+};
+
+extern unsigned int mt_spm_cond_check(int state_id,
+ const struct mt_spm_cond_tables *src,
+ const struct mt_spm_cond_tables *dest,
+ struct mt_spm_cond_tables *res);
+
+extern int mt_spm_cond_update(struct mt_resource_constraint **con,
+ int stateid, void *priv);
+
+#endif /* MT_SPM_CONDIT_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c
new file mode 100644
index 0000000..a6ea977
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_vcorefs.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+#define MT_RESUMETIME_THRESHOLD_MAX (5U) /*ms*/
+#define IS_RESUME_OVERTIME(delta) (delta > MT_RESUMETIME_THRESHOLD_MAX)
+
+static struct wake_status spm_wakesta; /* record last wakesta */
+
+static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ unsigned int resource_req)
+{
+ int ret = 0;
+ struct pwr_ctrl *pwrctrl;
+ uint32_t cpu = plat_my_core_pos();
+
+ pwrctrl = spm_lp->pwrctrl;
+
+ __spm_set_cpu_status(cpu);
+ __spm_set_power_control(pwrctrl);
+ __spm_set_wakeup_event(pwrctrl);
+ __spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl);
+ __spm_set_pcm_flags(pwrctrl);
+
+ __spm_src_req_update(pwrctrl, resource_req);
+
+ if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
+ __spm_set_pcm_wdt(1);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
+ __spm_xo_soc_bblpm(1);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
+ spm_hw_s1_state_monitor_resume();
+ }
+
+ /* Disable auto resume by PCM in system suspend stage */
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ __spm_disable_pcm_timer();
+ __spm_set_pcm_wdt(0);
+ }
+
+ __spm_send_cpu_wakeup_event();
+
+ INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n",
+ cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE),
+ (mmio_read_32(PCM_TIMER_VAL) / 32768));
+ INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n",
+ pwrctrl->pcm_flags, pwrctrl->pcm_flags1,
+ mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS),
+ mmio_read_32(PWR_STATUS_2ND));
+
+ return ret;
+}
+
+static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status)
+{
+ unsigned int ext_status = 0U;
+
+ spm_wakesta.tr.comm.resumetime = 0;
+ spm_wakesta.tr.comm.times_h = spm_wakesta.tr.comm.times_l = 0;
+
+ /* system watchdog will be resumed at kernel stage */
+ if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
+ __spm_set_pcm_wdt(0);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
+ __spm_xo_soc_bblpm(0);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
+ spm_hw_s1_state_monitor_pause(&ext_status);
+ }
+
+ __spm_ext_int_wakeup_req_clr();
+
+ __spm_get_wakeup_status(&spm_wakesta, ext_status);
+
+ if (status != NULL) {
+ *status = &spm_wakesta;
+ }
+
+ __spm_clean_after_wakeup();
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ __spm_output_wake_reason(state_id, &spm_wakesta);
+ }
+
+}
+
+int spm_conservation(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp, unsigned int resource_req)
+{
+ int ret = 0;
+
+ if (spm_lp == NULL) {
+ ret = -1;
+ } else {
+ spm_lock_get();
+ go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req);
+ spm_lock_release();
+ }
+
+ return ret;
+}
+
+void spm_conservation_finish(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status)
+{
+ spm_lock_get();
+ go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
+ spm_lock_release();
+}
+
+int spm_conservation_get_result(struct wake_status **res)
+{
+ int ret = 0;
+
+ if (res == NULL) {
+ ret = -1;
+ } else {
+ *res = &spm_wakesta;
+ }
+ return ret;
+}
+
+#define GPIO_BANK (GPIO_BASE + 0x6F0)
+#define TRAP_UFS_FIRST BIT(11) /* bit 11, 0: UFS, 1: eMMC */
+
+void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl)
+{
+ if (pwrctrl != NULL) {
+ /* For ufs, emmc storage type */
+ if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) {
+ /* If eMMC is used, mask UFS req */
+ pwrctrl->reg_ufs_srcclkena_mask_b = 0;
+ pwrctrl->reg_ufs_infra_req_mask_b = 0;
+ pwrctrl->reg_ufs_apsrc_req_mask_b = 0;
+ pwrctrl->reg_ufs_vrf18_req_mask_b = 0;
+ pwrctrl->reg_ufs_ddren_req_mask_b = 0;
+ }
+ }
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h
new file mode 100644
index 0000000..e7ef346
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONSERVATION_H
+#define MT_SPM_CONSERVATION_H
+
+#include <mt_spm_internal.h>
+
+extern int spm_conservation(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ unsigned int resource_req);
+extern void spm_conservation_finish(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status);
+extern int spm_conservation_get_result(struct wake_status **res);
+extern void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl);
+
+#endif /* MT_SPM_CONSERVATION_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h
new file mode 100644
index 0000000..53be3b6
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONSTRAINT_H
+#define MT_SPM_CONSTRAINT_H
+
+#include <mt_lp_rm.h>
+
+#define MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF BIT(0)
+#define MT_RM_CONSTRAINT_ALLOW_DRAM_S0 BIT(1)
+#define MT_RM_CONSTRAINT_ALLOW_DRAM_S1 BIT(2)
+#define MT_RM_CONSTRAINT_ALLOW_VCORE_LP BIT(3)
+#define MT_RM_CONSTRAINT_ALLOW_INFRA_PDN BIT(4)
+#define MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF BIT(5)
+#define MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND BIT(6)
+#define MT_RM_CONSTRAINT_ALLOW_BBLPM BIT(7)
+#define MT_RM_CONSTRAINT_ALLOW_XO_UFS BIT(8)
+#define MT_RM_CONSTRAINT_ALLOW_GPS_STATE BIT(9)
+#define MT_RM_CONSTRAINT_ALLOW_LVTS_STATE BIT(10)
+
+#define MT_SPM_RC_INVALID (0x0)
+#define MT_SPM_RC_VALID_SW BIT(0)
+#define MT_SPM_RC_VALID_FW BIT(1)
+#define MT_SPM_RC_VALID_RESIDNECY BIT(2)
+#define MT_SPM_RC_VALID_COND_CHECK BIT(3)
+#define MT_SPM_RC_VALID_COND_LATCH BIT(4)
+#define MT_SPM_RC_VALID_UFS_H8 BIT(5)
+#define MT_SPM_RC_VALID_FLIGHTMODE BIT(6)
+#define MT_SPM_RC_VALID_XSOC_BBLPM BIT(7)
+#define MT_SPM_RC_VALID_TRACE_EVENT BIT(8)
+
+#define MT_SPM_RC_VALID (MT_SPM_RC_VALID_SW)
+
+#define IS_MT_RM_RC_READY(status) \
+ ((status & MT_SPM_RC_VALID) == MT_SPM_RC_VALID)
+
+#define MT_SPM_RC_BBLPM_MODE \
+ (MT_SPM_RC_VALID_UFS_H8 | \
+ MT_SPM_RC_VALID_FLIGHTMODE | \
+ MT_SPM_RC_VALID_XSOC_BBLPM)
+
+#define IS_MT_SPM_RC_BBLPM_MODE(st) \
+ ((st & (MT_SPM_RC_BBLPM_MODE)) == MT_SPM_RC_BBLPM_MODE)
+
+struct constraint_status {
+ uint16_t id;
+ uint16_t valid;
+ uint32_t cond_block;
+ uint32_t enter_cnt;
+ struct mt_spm_cond_tables *cond_res;
+};
+
+enum MT_SPM_RM_RC_TYPE {
+ MT_RM_CONSTRAINT_ID_BUS26M = 0U,
+ MT_RM_CONSTRAINT_ID_SYSPLL = 1U,
+ MT_RM_CONSTRAINT_ID_DRAM = 2U,
+ MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO = 3U,
+ MT_RM_CONSTRAINT_ID_ALL = 4U,
+};
+
+#endif /* MT_SPM_CONSTRAINT_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c
new file mode 100644
index 0000000..608d9f9
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) since 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define INFRA_AO_RES_CTRL_MASK (INFRACFG_AO_BASE + 0xB8)
+#define INFRA_AO_RES_CTRL_MASK_EMI_IDLE BIT(18)
+#define INFRA_AO_RES_CTRL_MASK_MPU_IDLE BIT(15)
+
+void spm_extern_initialize(void)
+{
+ unsigned int val;
+
+ val = mmio_read_32(INFRA_AO_RES_CTRL_MASK);
+
+ val |= (INFRA_AO_RES_CTRL_MASK_EMI_IDLE | INFRA_AO_RES_CTRL_MASK_MPU_IDLE);
+ mmio_write_32(INFRA_AO_RES_CTRL_MASK, val);
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h
new file mode 100644
index 0000000..5bcbaff
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) since 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_EXTERN_H
+#define MT_SPM_EXTERN_H
+
+void spm_extern_initialize(void);
+
+#endif
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c
new file mode 100644
index 0000000..04776c8
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <plat_pm.h>
+
+#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \
+ (R12_PCM_TIMER | \
+ R12_KP_IRQ_B | \
+ R12_APWDT_EVENT_B | \
+ R12_APXGPT1_EVENT_B | \
+ R12_CONN2AP_SPM_WAKEUP_B | \
+ R12_EINT_EVENT_B | \
+ R12_CONN_WDT_IRQ_B | \
+ R12_SSPM2SPM_WAKEUP_B | \
+ R12_SCP2SPM_WAKEUP_B | \
+ R12_ADSP2SPM_WAKEUP_B | \
+ R12_USBX_CDSC_B | \
+ R12_USBX_POWERDWN_B | \
+ R12_SYS_TIMER_EVENT_B | \
+ R12_EINT_EVENT_SECURE_B | \
+ R12_AFE_IRQ_MCU_B | \
+ R12_SYS_CIRQ_IRQ_B | \
+ R12_NNA_WAKEUP | \
+ R12_SEJ_EVENT_B | \
+ R12_REG_CPU_WAKEUP)
+
+#if defined(CFG_MICROTRUST_TEE_SUPPORT)
+#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__)
+#else
+#define WAKE_SRC_FOR_SUSPEND \
+ (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \
+ R12_SEJ_EVENT_B)
+#endif
+
+static struct pwr_ctrl idle_spm_pwr = {
+ .timer_val = 0x28000,
+ .wake_src = WAKE_SRC_FOR_SUSPEND,
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ .reg_wfi_op = 0,
+ .reg_wfi_type = 0,
+ .reg_mp0_cputop_idle_mask = 0,
+ .reg_mp1_cputop_idle_mask = 0,
+ .reg_mcusys_idle_mask = 0,
+ .reg_md_apsrc_1_sel = 0,
+ .reg_md_apsrc_0_sel = 0,
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC6_MASK */
+ .reg_ccif_event_infra_req_mask_b = 0,
+ .reg_ccif_event_apsrc_req_mask_b = 0,
+
+ /* SPM_SRC_REQ */
+ .reg_spm_apsrc_req = 0,
+ .reg_spm_f26m_req = 0,
+ .reg_spm_infra_req = 0,
+ .reg_spm_vrf18_req = 0,
+ .reg_spm_ddren_req = 0,
+ .reg_spm_dvfs_req = 0,
+ .reg_spm_sw_mailbox_req = 0,
+ .reg_spm_sspm_mailbox_req = 0,
+ .reg_spm_adsp_mailbox_req = 0,
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC_MASK */
+ .reg_md_0_srcclkena_mask_b = 0,
+ .reg_md_0_infra_req_mask_b = 0,
+ .reg_md_0_apsrc_req_mask_b = 0,
+ .reg_md_0_vrf18_req_mask_b = 0,
+ .reg_md_0_ddren_req_mask_b = 0,
+ .reg_md_1_srcclkena_mask_b = 0,
+ .reg_md_1_infra_req_mask_b = 0,
+ .reg_md_1_apsrc_req_mask_b = 0,
+ .reg_md_1_vrf18_req_mask_b = 0,
+ .reg_md_1_ddren_req_mask_b = 0,
+ .reg_conn_srcclkena_mask_b = 1,
+ .reg_conn_srcclkenb_mask_b = 0,
+ .reg_conn_infra_req_mask_b = 1,
+ .reg_conn_apsrc_req_mask_b = 1,
+ .reg_conn_vrf18_req_mask_b = 1,
+ .reg_conn_ddren_req_mask_b = 1,
+ .reg_conn_vfe28_mask_b = 0,
+ .reg_srcclkeni_srcclkena_mask_b = 1,
+ .reg_srcclkeni_infra_req_mask_b = 1,
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ .reg_infrasys_ddren_req_mask_b = 1,
+ .reg_sspm_srcclkena_mask_b = 1,
+ .reg_sspm_infra_req_mask_b = 1,
+ .reg_sspm_apsrc_req_mask_b = 1,
+ .reg_sspm_vrf18_req_mask_b = 1,
+ .reg_sspm_ddren_req_mask_b = 1,
+
+ /* SPM_SRC2_MASK */
+ .reg_scp_srcclkena_mask_b = 1,
+ .reg_scp_infra_req_mask_b = 1,
+ .reg_scp_apsrc_req_mask_b = 1,
+ .reg_scp_vrf18_req_mask_b = 1,
+ .reg_scp_ddren_req_mask_b = 1,
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ .reg_audio_dsp_ddren_req_mask_b = 1,
+ .reg_ufs_srcclkena_mask_b = 1,
+ .reg_ufs_infra_req_mask_b = 1,
+ .reg_ufs_apsrc_req_mask_b = 1,
+ .reg_ufs_vrf18_req_mask_b = 1,
+ .reg_ufs_ddren_req_mask_b = 1,
+ .reg_disp0_apsrc_req_mask_b = 1,
+ .reg_disp0_ddren_req_mask_b = 1,
+ .reg_disp1_apsrc_req_mask_b = 1,
+ .reg_disp1_ddren_req_mask_b = 1,
+ .reg_gce_infra_req_mask_b = 1,
+ .reg_gce_apsrc_req_mask_b = 1,
+ .reg_gce_vrf18_req_mask_b = 1,
+ .reg_gce_ddren_req_mask_b = 1,
+ .reg_apu_srcclkena_mask_b = 0,
+ .reg_apu_infra_req_mask_b = 0,
+ .reg_apu_apsrc_req_mask_b = 0,
+ .reg_apu_vrf18_req_mask_b = 0,
+ .reg_apu_ddren_req_mask_b = 0,
+ .reg_cg_check_srcclkena_mask_b = 0,
+ .reg_cg_check_apsrc_req_mask_b = 0,
+ .reg_cg_check_vrf18_req_mask_b = 0,
+ .reg_cg_check_ddren_req_mask_b = 0,
+
+ /* SPM_SRC3_MASK */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+ .reg_sw2spm_wakeup_mask_b = 0,
+ .reg_adsp2spm_wakeup_mask_b = 0,
+ .reg_sspm2spm_wakeup_mask_b = 0,
+ .reg_scp2spm_wakeup_mask_b = 0,
+ .reg_csyspwrup_ack_mask = 1,
+ .reg_spm_reserved_srcclkena_mask_b = 0,
+ .reg_spm_reserved_infra_req_mask_b = 0,
+ .reg_spm_reserved_apsrc_req_mask_b = 0,
+ .reg_spm_reserved_vrf18_req_mask_b = 0,
+ .reg_spm_reserved_ddren_req_mask_b = 0,
+ .reg_mcupm_srcclkena_mask_b = 0,
+ .reg_mcupm_infra_req_mask_b = 0,
+ .reg_mcupm_apsrc_req_mask_b = 0,
+ .reg_mcupm_vrf18_req_mask_b = 0,
+ .reg_mcupm_ddren_req_mask_b = 0,
+ .reg_msdc0_srcclkena_mask_b = 1,
+ .reg_msdc0_infra_req_mask_b = 1,
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ .reg_msdc0_ddren_req_mask_b = 1,
+ .reg_msdc1_srcclkena_mask_b = 1,
+ .reg_msdc1_infra_req_mask_b = 1,
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ .reg_msdc1_ddren_req_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ .reg_ccif_event_srcclkena_mask_b = 0,
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ .reg_bak_psri_infra_req_mask_b = 0,
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ .reg_bak_psri_ddren_req_mask_b = 0,
+ .reg_dramc_md32_infra_req_mask_b = 0,
+ .reg_dramc_md32_vrf18_req_mask_b = 0,
+ .reg_conn_srcclkenb2pwrap_mask_b = 0,
+ .reg_dramc_md32_apsrc_req_mask_b = 0,
+
+ /* SPM_SRC5_MASK */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x83,
+ .reg_mcusys_merge_ddren_req_mask_b = 0x83,
+ .reg_afe_srcclkena_mask_b = 1,
+ .reg_afe_infra_req_mask_b = 1,
+ .reg_afe_apsrc_req_mask_b = 1,
+ .reg_afe_vrf18_req_mask_b = 1,
+ .reg_afe_ddren_req_mask_b = 1,
+ .reg_msdc2_srcclkena_mask_b = 0,
+ .reg_msdc2_infra_req_mask_b = 0,
+ .reg_msdc2_apsrc_req_mask_b = 0,
+ .reg_msdc2_vrf18_req_mask_b = 0,
+ .reg_msdc2_ddren_req_mask_b = 0,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ .reg_wakeup_event_mask = 0xE1283203,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+
+ /* SPM_SRC7_MASK */
+ .reg_pcie_srcclkena_mask_b = 0,
+ .reg_pcie_infra_req_mask_b = 0,
+ .reg_pcie_apsrc_req_mask_b = 0,
+ .reg_pcie_vrf18_req_mask_b = 0,
+ .reg_pcie_ddren_req_mask_b = 0,
+ .reg_dpmaif_srcclkena_mask_b = 1,
+ .reg_dpmaif_infra_req_mask_b = 1,
+ .reg_dpmaif_apsrc_req_mask_b = 1,
+ .reg_dpmaif_vrf18_req_mask_b = 1,
+ .reg_dpmaif_ddren_req_mask_b = 1,
+
+ /* Auto-gen End */
+};
+
+struct spm_lp_scen idle_spm_lp = {
+ .pwrctrl = &idle_spm_pwr,
+};
+
+int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand,
+ spm_idle_conduct fn)
+{
+ unsigned int src_req = 0U;
+
+ if (fn != NULL) {
+ fn(&idle_spm_lp, &src_req);
+ }
+
+ return spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req);
+}
+void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status,
+ spm_idle_conduct_restore fn)
+{
+ ext_opand |= (MT_SPM_EX_OP_TIME_CHECK | MT_SPM_EX_OP_TIME_OBS);
+ spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status);
+}
+
+void mt_spm_idle_generic_init(void)
+{
+ spm_conservation_pwrctrl_init(idle_spm_lp.pwrctrl);
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h
new file mode 100644
index 0000000..7196190
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_IDLE_H
+#define MT_SPM_IDLE_H
+
+typedef void (*spm_idle_conduct)(struct spm_lp_scen *spm_lp, unsigned int *resource_req);
+
+typedef int (*spm_idle_conduct_restore)(int state_id,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status *status);
+
+int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand, spm_idle_conduct fn);
+
+void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status,
+ spm_idle_conduct_restore fn);
+
+void mt_spm_idle_generic_init(void);
+
+#endif /* MT_SPM_IDLE_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c
new file mode 100644
index 0000000..f228961
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+/* Define and Declare */
+#define ROOT_CORE_ADDR_OFFSET (0x20000000)
+#define SPM_WAKEUP_EVENT_MASK_CLEAN_MASK (0xefffffff)
+#define SPM_INIT_DONE_US (20)
+
+static unsigned int mt_spm_bblpm_cnt;
+
+const char *wakeup_src_str[32] = {
+ [0] = "R12_PCM_TIMER",
+ [1] = "R12_RESERVED_DEBUG_B",
+ [2] = "R12_KP_IRQ_B",
+ [3] = "R12_APWDT_EVENT_B",
+ [4] = "R12_APXGPT1_EVENT_B",
+ [5] = "R12_CONN2AP_SPM_WAKEUP_B",
+ [6] = "R12_EINT_EVENT_B",
+ [7] = "R12_CONN_WDT_IRQ_B",
+ [8] = "R12_CCIF0_EVENT_B",
+ [9] = "R12_LOWBATTERY_IRQ_B",
+ [10] = "R12_SC_SSPM2SPM_WAKEUP_B",
+ [11] = "R12_SC_SCP2SPM_WAKEUP_B",
+ [12] = "R12_SC_ADSP2SPM_WAKEUP_B",
+ [13] = "R12_PCM_WDT_WAKEUP_B",
+ [14] = "R12_USB_CDSC_B",
+ [15] = "R12_USB_POWERDWN_B",
+ [16] = "R12_SYS_TIMER_EVENT_B",
+ [17] = "R12_EINT_EVENT_SECURE_B",
+ [18] = "R12_CCIF1_EVENT_B",
+ [19] = "R12_UART0_IRQ_B",
+ [20] = "R12_AFE_IRQ_MCU_B",
+ [21] = "R12_THERM_CTRL_EVENT_B",
+ [22] = "R12_SYS_CIRQ_IRQ_B",
+ [23] = "R12_MD2AP_PEER_EVENT_B",
+ [24] = "R12_CSYSPWREQ_B",
+ [25] = "R12_MD1_WDT_B",
+ [26] = "R12_AP2AP_PEER_WAKEUPEVENT_B",
+ [27] = "R12_SEJ_EVENT_B",
+ [28] = "R12_SPM_CPU_WAKEUPEVENT_B",
+ [29] = "R12_APUSYS",
+ [30] = "R12_PCIE_BRIDGE_IRQ",
+ [31] = "R12_PCIE_IRQ",
+};
+
+/* Function and API */
+wake_reason_t __spm_output_wake_reason(int state_id, const struct wake_status *wakesta)
+{
+ uint32_t i, bk_vtcxo_dur, spm_26m_off_pct = 0U;
+ wake_reason_t wr = WR_UNKNOWN;
+
+ if (wakesta != NULL) {
+ if (wakesta->abort != 0U) {
+ ERROR("spmfw flow is aborted: 0x%x, timer_out = %u\n",
+ wakesta->abort, wakesta->timer_out);
+ } else {
+ for (i = 0U; i < 32U; i++) {
+ if ((wakesta->r12 & BIT(i)) != 0U) {
+ INFO("wake up by %s, timer_out = %u\n",
+ wakeup_src_str[i], wakesta->timer_out);
+ wr = WR_WAKE_SRC;
+ break;
+ }
+ }
+ }
+
+ INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n",
+ wakesta->r12, wakesta->r12_ext, wakesta->r13, wakesta->debug_flag,
+ wakesta->debug_flag1);
+ INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n",
+ wakesta->raw_sta, wakesta->md32pcm_wakeup_sta,
+ wakesta->md32pcm_event_sta, wakesta->idle_sta,
+ wakesta->cg_check_sta);
+ INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n",
+ wakesta->req_sta0, wakesta->req_sta1, wakesta->req_sta2,
+ wakesta->req_sta3, wakesta->req_sta4, wakesta->isr);
+ INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n",
+ wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2);
+ INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n",
+ wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta);
+ INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n",
+ wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1,
+ wakesta->b_sw_flag0, wakesta->b_sw_flag1, wakesta->src_req);
+ INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n",
+ wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L),
+ mmio_read_32(SYS_TIMER_VALUE_H));
+
+ if (wakesta->timer_out != 0U) {
+ bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR);
+ spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->timer_out;
+ INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct);
+ }
+ }
+
+ return wr;
+}
+
+void __spm_set_cpu_status(unsigned int cpu)
+{
+ uint32_t root_core_addr;
+
+ if (cpu < 8U) {
+ mmio_write_32(ROOT_CPUTOP_ADDR, BIT(cpu));
+
+ root_core_addr = SPM_CPU0_PWR_CON + (cpu * 0x4);
+ root_core_addr += ROOT_CORE_ADDR_OFFSET;
+ mmio_write_32(ROOT_CORE_ADDR, root_core_addr);
+
+ /* Notify SSPM that preferred cpu wakeup */
+ mmio_write_32(MCUPM_MBOX_WAKEUP_CPU, cpu);
+ } else {
+ ERROR("%s: error cpu number %d\n", __func__, cpu);
+ }
+}
+
+void __spm_src_req_update(const struct pwr_ctrl *pwrctrl,
+ unsigned int resource_usage)
+{
+ uint8_t apsrc_req = ((resource_usage & MT_SPM_DRAM_S0) != 0U) ?
+ 1 : pwrctrl->reg_spm_apsrc_req;
+ uint8_t ddr_en_req = ((resource_usage & MT_SPM_DRAM_S1) != 0U) ?
+ 1 : pwrctrl->reg_spm_ddren_req;
+ uint8_t vrf18_req = ((resource_usage & MT_SPM_SYSPLL) != 0U) ?
+ 1 : pwrctrl->reg_spm_vrf18_req;
+ uint8_t infra_req = ((resource_usage & MT_SPM_INFRA) != 0U) ?
+ 1 : pwrctrl->reg_spm_infra_req;
+ uint8_t f26m_req = ((resource_usage & (MT_SPM_26M | MT_SPM_XO_FPM)) != 0U) ?
+ 1 : pwrctrl->reg_spm_f26m_req;
+
+ /*
+ * if SPM_FLAG_SSPM_INFRA_SLEEP_MODE set,
+ * clear sspm_srclkena_mask_b and sspm_infra_mask_b
+ */
+ uint8_t reg_sspm_srcclkena_mask_b =
+ (pwrctrl->pcm_flags & SPM_FLAG_SSPM_INFRA_SLEEP_MODE)
+ ? 0U : pwrctrl->reg_sspm_srcclkena_mask_b;
+
+ uint8_t reg_sspm_infra_req_mask_b =
+ (pwrctrl->pcm_flags & SPM_FLAG_SSPM_INFRA_SLEEP_MODE)
+ ? 0 : pwrctrl->reg_sspm_infra_req_mask_b;
+
+ /* SPM_SRC_REQ */
+ mmio_write_32(SPM_SRC_REQ,
+ ((apsrc_req & 0x1) << 0) |
+ ((f26m_req & 0x1) << 1) |
+ ((infra_req & 0x1) << 3) |
+ ((vrf18_req & 0x1) << 4) |
+ ((ddr_en_req & 0x1) << 7) |
+ ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
+ ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
+ ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
+ ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
+ ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
+
+ /* SPM_SRC_MASK */
+ mmio_write_32(SPM_SRC_MASK,
+ ((pwrctrl->reg_md_0_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_md_0_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_md_0_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_md_0_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_md_0_ddren_req_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_md_1_srcclkena_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_md_1_infra_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_md_1_apsrc_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_md_1_vrf18_req_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_md_1_ddren_req_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_conn_srcclkena_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_conn_srcclkenb_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_conn_infra_req_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_conn_apsrc_req_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_conn_vrf18_req_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_conn_ddren_req_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_conn_vfe28_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_srcclkeni_srcclkena_mask_b & 0x7) << 17) |
+ ((pwrctrl->reg_srcclkeni_infra_req_mask_b & 0x7) << 20) |
+ ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_infrasys_ddren_req_mask_b & 0x1) << 26) |
+ ((reg_sspm_srcclkena_mask_b & 0x1) << 27) |
+ ((reg_sspm_infra_req_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_sspm_apsrc_req_mask_b & 0x1) << 29) |
+ ((pwrctrl->reg_sspm_vrf18_req_mask_b & 0x1) << 30) |
+ ((pwrctrl->reg_sspm_ddren_req_mask_b & 0x1) << 31));
+}
+
+void __spm_set_power_control(const struct pwr_ctrl *pwrctrl)
+{
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ mmio_write_32(SPM_AP_STANDBY_CON,
+ ((pwrctrl->reg_wfi_op & 0x1) << 0) |
+ ((pwrctrl->reg_wfi_type & 0x1) << 1) |
+ ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) |
+ ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) |
+ ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) |
+ ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) |
+ ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) |
+ ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29));
+
+ /* SPM_SRC6_MASK */
+ mmio_write_32(SPM_SRC6_MASK,
+ ((pwrctrl->reg_ccif_event_infra_req_mask_b & 0xffff) << 0) |
+ ((pwrctrl->reg_ccif_event_apsrc_req_mask_b & 0xffff) << 16));
+
+ /* SPM_SRC_REQ */
+ mmio_write_32(SPM_SRC_REQ,
+ ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) |
+ ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) |
+ ((pwrctrl->reg_spm_infra_req & 0x1) << 3) |
+ ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) |
+ ((pwrctrl->reg_spm_ddren_req & 0x1) << 7) |
+ ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
+ ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
+ ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
+ ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
+ ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
+
+ /* SPM_SRC_MASK */
+ mmio_write_32(SPM_SRC_MASK,
+ ((pwrctrl->reg_md_0_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_md_0_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_md_0_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_md_0_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_md_0_ddren_req_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_md_1_srcclkena_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_md_1_infra_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_md_1_apsrc_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_md_1_vrf18_req_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_md_1_ddren_req_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_conn_srcclkena_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_conn_srcclkenb_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_conn_infra_req_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_conn_apsrc_req_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_conn_vrf18_req_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_conn_ddren_req_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_conn_vfe28_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_srcclkeni_srcclkena_mask_b & 0x7) << 17) |
+ ((pwrctrl->reg_srcclkeni_infra_req_mask_b & 0x7) << 20) |
+ ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_infrasys_ddren_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_sspm_srcclkena_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_sspm_infra_req_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_sspm_apsrc_req_mask_b & 0x1) << 29) |
+ ((pwrctrl->reg_sspm_vrf18_req_mask_b & 0x1) << 30) |
+ ((pwrctrl->reg_sspm_ddren_req_mask_b & 0x1) << 31));
+
+ /* SPM_SRC2_MASK */
+ mmio_write_32(SPM_SRC2_MASK,
+ ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_scp_ddren_req_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_audio_dsp_ddren_req_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_ufs_ddren_req_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_disp0_apsrc_req_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_disp0_ddren_req_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_disp1_ddren_req_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_gce_infra_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_gce_apsrc_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_gce_vrf18_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_gce_ddren_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_apu_ddren_req_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_cg_check_srcclkena_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_cg_check_apsrc_req_mask_b & 0x1) << 29) |
+ ((pwrctrl->reg_cg_check_vrf18_req_mask_b & 0x1) << 30) |
+ ((pwrctrl->reg_cg_check_ddren_req_mask_b & 0x1) << 31));
+
+ /* SPM_SRC3_MASK */
+ mmio_write_32(SPM_SRC3_MASK,
+ ((pwrctrl->reg_dvfsrc_event_trigger_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_sw2spm_wakeup_mask_b & 0xf) << 1) |
+ ((pwrctrl->reg_adsp2spm_wakeup_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_sspm2spm_wakeup_mask_b & 0xf) << 6) |
+ ((pwrctrl->reg_scp2spm_wakeup_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_csyspwrup_ack_mask & 0x1) << 11) |
+ ((pwrctrl->reg_spm_reserved_srcclkena_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_spm_reserved_infra_req_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_spm_reserved_apsrc_req_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_spm_reserved_vrf18_req_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_spm_reserved_ddren_req_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_mcupm_srcclkena_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_mcupm_infra_req_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_mcupm_apsrc_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_mcupm_vrf18_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_mcupm_ddren_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_msdc0_ddren_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 29) |
+ ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 30) |
+ ((pwrctrl->reg_msdc1_ddren_req_mask_b & 0x1) << 31));
+
+ /* SPM_SRC4_MASK */
+ mmio_write_32(SPM_SRC4_MASK,
+ ((pwrctrl->reg_ccif_event_srcclkena_mask_b & 0xffff) << 0) |
+ ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_bak_psri_ddren_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_dramc_md32_infra_req_mask_b & 0x3) << 21) |
+ ((pwrctrl->reg_dramc_md32_vrf18_req_mask_b & 0x3) << 23) |
+ ((pwrctrl->reg_conn_srcclkenb2pwrap_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_dramc_md32_apsrc_req_mask_b & 0x3) << 26));
+
+ /* SPM_SRC5_MASK */
+ mmio_write_32(SPM_SRC5_MASK,
+ ((pwrctrl->reg_mcusys_merge_apsrc_req_mask_b & 0x1ff) << 0) |
+ ((pwrctrl->reg_mcusys_merge_ddren_req_mask_b & 0x1ff) << 9) |
+ ((pwrctrl->reg_afe_srcclkena_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_afe_infra_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_afe_apsrc_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_afe_vrf18_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_afe_ddren_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_msdc2_ddren_req_mask_b & 0x1) << 27));
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK,
+ ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0));
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK,
+ ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0));
+
+ /* SPM_SRC7_MASK */
+ mmio_write_32(SPM_SRC7_MASK,
+ ((pwrctrl->reg_pcie_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_pcie_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_pcie_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_pcie_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_pcie_ddren_req_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_dpmaif_srcclkena_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_dpmaif_infra_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_dpmaif_apsrc_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_dpmaif_vrf18_req_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_dpmaif_ddren_req_mask_b & 0x1) << 9));
+ /* Auto-gen End */
+}
+
+void __spm_disable_pcm_timer(void)
+{
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY);
+}
+
+
+void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
+{
+ uint32_t val, mask;
+
+ /* toggle event counter clear */
+ mmio_setbits_32(PCM_CON1,
+ SPM_REGWR_CFG_KEY | REG_SPM_EVENT_COUNTER_CLR_LSB);
+
+ /* toggle for reset SYS TIMER start point */
+ mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
+
+ if (pwrctrl->timer_val_cust == 0U) {
+ val = pwrctrl->timer_val ? (pwrctrl->timer_val) : (PCM_TIMER_MAX);
+ } else {
+ val = pwrctrl->timer_val_cust;
+ }
+
+ mmio_write_32(PCM_TIMER_VAL, val);
+ mmio_setbits_32(PCM_CON1, (SPM_REGWR_CFG_KEY | RG_PCM_TIMER_EN_LSB));
+
+ /* unmask AP wakeup source */
+ if (pwrctrl->wake_src_cust == 0U) {
+ mask = pwrctrl->wake_src;
+ } else {
+ mask = pwrctrl->wake_src_cust;
+ }
+
+ if (pwrctrl->reg_csyspwrup_ack_mask != 0U) {
+ mask &= ~R12_CSYSPWREQ_B;
+ }
+
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask);
+
+ /* unmask SPM ISR (keep TWAM setting) */
+ mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX);
+
+ /* toggle event counter clear */
+ mmio_clrsetbits_32(PCM_CON1, REG_SPM_EVENT_COUNTER_CLR_LSB,
+ SPM_REGWR_CFG_KEY);
+ /* toggle for reset SYS TIMER start point */
+ mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
+}
+
+void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl)
+{
+ /* set PCM flags and data */
+ if (pwrctrl->pcm_flags_cust_clr != 0U) {
+ pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr;
+ }
+
+ if (pwrctrl->pcm_flags_cust_set != 0U) {
+ pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set;
+ }
+
+ if (pwrctrl->pcm_flags1_cust_clr != 0U) {
+ pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr;
+ }
+
+ if (pwrctrl->pcm_flags1_cust_set != 0U) {
+ pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set;
+ }
+
+ mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags);
+
+ mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1);
+
+ mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags);
+
+ mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1);
+}
+
+void __spm_get_wakeup_status(struct wake_status *wakesta,
+ unsigned int ext_status)
+{
+ wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT);
+ wakesta->tr.comm.timer_out = mmio_read_32(SPM_BK_PCM_TIMER);
+ wakesta->tr.comm.r13 = mmio_read_32(PCM_REG13_DATA);
+ wakesta->tr.comm.req_sta0 = mmio_read_32(SRC_REQ_STA_0);
+ wakesta->tr.comm.req_sta1 = mmio_read_32(SRC_REQ_STA_1);
+ wakesta->tr.comm.req_sta2 = mmio_read_32(SRC_REQ_STA_2);
+ wakesta->tr.comm.req_sta3 = mmio_read_32(SRC_REQ_STA_3);
+ wakesta->tr.comm.req_sta4 = mmio_read_32(SRC_REQ_STA_4);
+
+ wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0);
+ wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1);
+
+ if ((ext_status & SPM_INTERNAL_STATUS_HW_S1) != 0U) {
+ wakesta->tr.comm.debug_flag |= (SPM_DBG_DEBUG_IDX_DDREN_WAKE |
+ SPM_DBG_DEBUG_IDX_DDREN_SLEEP);
+ mmio_write_32(PCM_WDT_LATCH_SPARE_0, wakesta->tr.comm.debug_flag);
+ }
+
+ wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7);
+ wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8);
+
+ /* record below spm info for debug */
+ wakesta->r12 = mmio_read_32(SPM_BK_WAKE_EVENT);
+ wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_STA);
+ wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA);
+ wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA);
+ wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA);
+ wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA);
+ wakesta->src_req = mmio_read_32(SPM_SRC_REQ);
+
+ /* backup of SPM_WAKEUP_MISC */
+ wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC);
+
+ /* get sleep time, backup of PCM_TIMER_OUT */
+ wakesta->timer_out = mmio_read_32(SPM_BK_PCM_TIMER);
+
+ /* get other SYS and co-clock status */
+ wakesta->r13 = mmio_read_32(PCM_REG13_DATA);
+ wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA);
+ wakesta->req_sta0 = mmio_read_32(SRC_REQ_STA_0);
+ wakesta->req_sta1 = mmio_read_32(SRC_REQ_STA_1);
+ wakesta->req_sta2 = mmio_read_32(SRC_REQ_STA_2);
+ wakesta->req_sta3 = mmio_read_32(SRC_REQ_STA_3);
+ wakesta->req_sta4 = mmio_read_32(SRC_REQ_STA_4);
+
+ /* get HW CG check status */
+ wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA);
+
+ /* get debug flag for PCM execution check */
+ wakesta->debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0);
+ wakesta->debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1);
+
+ /* get backup SW flag status */
+ wakesta->b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7);
+ wakesta->b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8);
+
+ wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2);
+ wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3);
+ wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4);
+ wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5);
+ wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6);
+
+ /* get ISR status */
+ wakesta->isr = mmio_read_32(SPM_IRQ_STA);
+
+ /* get SW flag status */
+ wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0);
+ wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1);
+
+ /* get CLK SETTLE */
+ wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE);
+
+ /* check abort */
+ wakesta->abort = ((wakesta->debug_flag & DEBUG_ABORT_MASK) |
+ (wakesta->debug_flag1 & DEBUG_ABORT_MASK_1));
+}
+
+void __spm_clean_after_wakeup(void)
+{
+ mmio_write_32(SPM_BK_WAKE_EVENT,
+ (mmio_read_32(SPM_WAKEUP_STA) |
+ mmio_read_32(SPM_BK_WAKE_EVENT)));
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0U);
+
+ /*
+ * clean wakeup event raw status (for edge trigger event)
+ * bit[28] for cpu wake up event
+ */
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, SPM_WAKEUP_EVENT_MASK_CLEAN_MASK);
+
+ /* clean ISR status (except TWAM) */
+ mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
+ mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM);
+ mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL);
+}
+
+void __spm_set_pcm_wdt(int en)
+{
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_EN_LSB,
+ SPM_REGWR_CFG_KEY);
+
+ if (en == 1) {
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_WAKE_LSB,
+ SPM_REGWR_CFG_KEY);
+
+ if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) {
+ mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX);
+ }
+
+ mmio_write_32(PCM_WDT_VAL,
+ mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
+ mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_WDT_EN_LSB);
+ }
+}
+
+void __spm_send_cpu_wakeup_event(void)
+{
+ /* SPM will clear SPM_CPU_WAKEUP_EVENT */
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1);
+}
+
+void __spm_ext_int_wakeup_req_clr(void)
+{
+ unsigned int reg = mmio_read_32(SPM_MD32_IRQ) & (~(0x1U << 0));
+
+ mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, mmio_read_32(ROOT_CPUTOP_ADDR));
+
+ /* Clear spm2mcupm wakeup interrupt status */
+ mmio_write_32(SPM_MD32_IRQ, reg);
+}
+
+void __spm_xo_soc_bblpm(int en)
+{
+ if (en == 1) {
+ mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG,
+ RC_SW_SRCCLKEN_FPM, RC_SW_SRCCLKEN_RC);
+ assert(mt_spm_bblpm_cnt == 0);
+ mt_spm_bblpm_cnt += 1;
+ } else {
+ mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG,
+ RC_SW_SRCCLKEN_RC, RC_SW_SRCCLKEN_FPM);
+ mt_spm_bblpm_cnt -= 1;
+ }
+}
+
+void __spm_hw_s1_state_monitor(int en, unsigned int *status)
+{
+ unsigned int reg = mmio_read_32(SPM_ACK_CHK_CON_3);
+
+ if (en == 1) {
+ reg = mmio_read_32(SPM_ACK_CHK_CON_3);
+ reg &= ~SPM_ACK_CHK_3_CON_CLR_ALL;
+ mmio_write_32(SPM_ACK_CHK_CON_3, reg);
+ reg |= SPM_ACK_CHK_3_CON_EN;
+ mmio_write_32(SPM_ACK_CHK_CON_3, reg);
+ } else {
+ if (((reg & SPM_ACK_CHK_3_CON_RESULT) != 0U) &&
+ (status != NULL)) {
+ *status |= SPM_INTERNAL_STATUS_HW_S1;
+ }
+
+ mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN,
+ SPM_ACK_CHK_3_CON_HW_MODE_TRIG |
+ SPM_ACK_CHK_3_CON_CLR_ALL);
+ }
+}
+
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h
new file mode 100644
index 0000000..8cf2062
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_INTERNAL
+#define MT_SPM_INTERNAL
+
+#include "mt_spm.h"
+
+/* Config and Parameter */
+#define POWER_ON_VAL0_DEF (0x0000F100)
+#define POWER_ON_VAL1_DEF (0x80015860)
+#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */
+#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT)
+
+/* Define and Declare */
+/* PCM_PWR_IO_EN */
+#define PCM_PWRIO_EN_R0 BIT(0)
+#define PCM_PWRIO_EN_R7 BIT(7)
+#define PCM_RF_SYNC_R0 BIT(16)
+#define PCM_RF_SYNC_R6 BIT(22)
+#define PCM_RF_SYNC_R7 BIT(23)
+
+/* SPM_SWINT */
+#define PCM_SW_INT0 BIT(0)
+#define PCM_SW_INT1 BIT(1)
+#define PCM_SW_INT2 BIT(2)
+#define PCM_SW_INT3 BIT(3)
+#define PCM_SW_INT4 BIT(4)
+#define PCM_SW_INT5 BIT(5)
+#define PCM_SW_INT6 BIT(6)
+#define PCM_SW_INT7 BIT(7)
+#define PCM_SW_INT8 BIT(8)
+#define PCM_SW_INT9 BIT(9)
+#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \
+ PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \
+ PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \
+ PCM_SW_INT0)
+
+/* SPM_AP_STANDBY_CON */
+#define WFI_OP_AND (1U)
+#define WFI_OP_OR (0U)
+
+/* SPM_IRQ_MASK */
+#define ISRM_TWAM (1U << 2)
+#define ISRM_PCM_RETURN (1U << 3)
+#define ISRM_RET_IRQ0 (1U << 8)
+#define ISRM_RET_IRQ1 (1U << 9)
+#define ISRM_RET_IRQ2 (1U << 10)
+#define ISRM_RET_IRQ3 (1U << 11)
+#define ISRM_RET_IRQ4 (1U << 12)
+#define ISRM_RET_IRQ5 (1U << 13)
+#define ISRM_RET_IRQ6 (1U << 14)
+#define ISRM_RET_IRQ7 (1U << 15)
+#define ISRM_RET_IRQ8 (1U << 16)
+#define ISRM_RET_IRQ9 (1U << 17)
+#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \
+ (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \
+ (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \
+ (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \
+ (ISRM_RET_IRQ1))
+#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX)
+#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM)
+
+/* SPM_IRQ_STA */
+#define ISRS_TWAM BIT(2)
+#define ISRS_PCM_RETURN BIT(3)
+#define ISRC_TWAM ISRS_TWAM
+#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN
+#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM)
+
+/* SPM_WAKEUP_MISC */
+#define WAKE_MISC_GIC_WAKEUP (0x3FF)
+#define WAKE_MISC_DVFSRC_IRQ DVFSRC_IRQ_LSB
+#define WAKE_MISC_REG_CPU_WAKEUP SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB
+#define WAKE_MISC_PCM_TIMER_EVENT PCM_TIMER_EVENT_LSB
+#define WAKE_MISC_PMIC_OUT_B ((1U << 19) | (1U << 20))
+#define WAKE_MISC_TWAM_IRQ_B TWAM_IRQ_B_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_0 SPM_ACK_CHK_WAKEUP_0_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_1 SPM_ACK_CHK_WAKEUP_1_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_2 SPM_ACK_CHK_WAKEUP_2_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_3 SPM_ACK_CHK_WAKEUP_3_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_ALL SPM_ACK_CHK_WAKEUP_ALL_LSB
+#define WAKE_MISC_PMIC_IRQ_ACK PMIC_IRQ_ACK_LSB
+#define WAKE_MISC_PMIC_SCP_IRQ PMIC_SCP_IRQ_LSB
+
+/* ABORT MASK for DEBUG FOORTPRINT */
+#define DEBUG_ABORT_MASK \
+ (SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC | \
+ SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN)
+
+#define DEBUG_ABORT_MASK_1 \
+ (SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT | \
+ SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT | \
+ SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT | \
+ SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT)
+
+#define MCUPM_MBOX_WAKEUP_CPU (0x0C55FD10)
+
+struct pwr_ctrl {
+ uint32_t pcm_flags;
+ uint32_t pcm_flags_cust;
+ uint32_t pcm_flags_cust_set;
+ uint32_t pcm_flags_cust_clr;
+ uint32_t pcm_flags1;
+ uint32_t pcm_flags1_cust;
+ uint32_t pcm_flags1_cust_set;
+ uint32_t pcm_flags1_cust_clr;
+ uint32_t timer_val;
+ uint32_t timer_val_cust;
+ uint32_t timer_val_ramp_en;
+ uint32_t timer_val_ramp_en_sec;
+ uint32_t wake_src;
+ uint32_t wake_src_cust;
+ uint32_t wakelock_timer_val;
+ uint8_t wdt_disable;
+
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ uint8_t reg_wfi_op;
+ uint8_t reg_wfi_type;
+ uint8_t reg_mp0_cputop_idle_mask;
+ uint8_t reg_mp1_cputop_idle_mask;
+ uint8_t reg_mcusys_idle_mask;
+ uint8_t reg_md_apsrc_1_sel;
+ uint8_t reg_md_apsrc_0_sel;
+ uint8_t reg_conn_apsrc_sel;
+
+ /* SPM_SRC6_MASK */
+ uint32_t reg_ccif_event_infra_req_mask_b;
+ uint32_t reg_ccif_event_apsrc_req_mask_b;
+
+ /* SPM_SRC_REQ */
+ uint8_t reg_spm_apsrc_req;
+ uint8_t reg_spm_f26m_req;
+ uint8_t reg_spm_infra_req;
+ uint8_t reg_spm_vrf18_req;
+ uint8_t reg_spm_ddren_req;
+ uint8_t reg_spm_dvfs_req;
+ uint8_t reg_spm_sw_mailbox_req;
+ uint8_t reg_spm_sspm_mailbox_req;
+ uint8_t reg_spm_adsp_mailbox_req;
+ uint8_t reg_spm_scp_mailbox_req;
+
+ /* SPM_SRC_MASK */
+ uint8_t reg_md_0_srcclkena_mask_b;
+ uint8_t reg_md_0_infra_req_mask_b;
+ uint8_t reg_md_0_apsrc_req_mask_b;
+ uint8_t reg_md_0_vrf18_req_mask_b;
+ uint8_t reg_md_0_ddren_req_mask_b;
+ uint8_t reg_md_1_srcclkena_mask_b;
+ uint8_t reg_md_1_infra_req_mask_b;
+ uint8_t reg_md_1_apsrc_req_mask_b;
+ uint8_t reg_md_1_vrf18_req_mask_b;
+ uint8_t reg_md_1_ddren_req_mask_b;
+ uint8_t reg_conn_srcclkena_mask_b;
+ uint8_t reg_conn_srcclkenb_mask_b;
+ uint8_t reg_conn_infra_req_mask_b;
+ uint8_t reg_conn_apsrc_req_mask_b;
+ uint8_t reg_conn_vrf18_req_mask_b;
+ uint8_t reg_conn_ddren_req_mask_b;
+ uint8_t reg_conn_vfe28_mask_b;
+ uint8_t reg_srcclkeni_srcclkena_mask_b;
+ uint8_t reg_srcclkeni_infra_req_mask_b;
+ uint8_t reg_infrasys_apsrc_req_mask_b;
+ uint8_t reg_infrasys_ddren_req_mask_b;
+ uint8_t reg_sspm_srcclkena_mask_b;
+ uint8_t reg_sspm_infra_req_mask_b;
+ uint8_t reg_sspm_apsrc_req_mask_b;
+ uint8_t reg_sspm_vrf18_req_mask_b;
+ uint8_t reg_sspm_ddren_req_mask_b;
+
+ /* SPM_SRC2_MASK */
+ uint8_t reg_scp_srcclkena_mask_b;
+ uint8_t reg_scp_infra_req_mask_b;
+ uint8_t reg_scp_apsrc_req_mask_b;
+ uint8_t reg_scp_vrf18_req_mask_b;
+ uint8_t reg_scp_ddren_req_mask_b;
+ uint8_t reg_audio_dsp_srcclkena_mask_b;
+ uint8_t reg_audio_dsp_infra_req_mask_b;
+ uint8_t reg_audio_dsp_apsrc_req_mask_b;
+ uint8_t reg_audio_dsp_vrf18_req_mask_b;
+ uint8_t reg_audio_dsp_ddren_req_mask_b;
+ uint8_t reg_ufs_srcclkena_mask_b;
+ uint8_t reg_ufs_infra_req_mask_b;
+ uint8_t reg_ufs_apsrc_req_mask_b;
+ uint8_t reg_ufs_vrf18_req_mask_b;
+ uint8_t reg_ufs_ddren_req_mask_b;
+ uint8_t reg_disp0_apsrc_req_mask_b;
+ uint8_t reg_disp0_ddren_req_mask_b;
+ uint8_t reg_disp1_apsrc_req_mask_b;
+ uint8_t reg_disp1_ddren_req_mask_b;
+ uint8_t reg_gce_infra_req_mask_b;
+ uint8_t reg_gce_apsrc_req_mask_b;
+ uint8_t reg_gce_vrf18_req_mask_b;
+ uint8_t reg_gce_ddren_req_mask_b;
+ uint8_t reg_apu_srcclkena_mask_b;
+ uint8_t reg_apu_infra_req_mask_b;
+ uint8_t reg_apu_apsrc_req_mask_b;
+ uint8_t reg_apu_vrf18_req_mask_b;
+ uint8_t reg_apu_ddren_req_mask_b;
+ uint8_t reg_cg_check_srcclkena_mask_b;
+ uint8_t reg_cg_check_apsrc_req_mask_b;
+ uint8_t reg_cg_check_vrf18_req_mask_b;
+ uint8_t reg_cg_check_ddren_req_mask_b;
+
+ /* SPM_SRC3_MASK */
+ uint8_t reg_dvfsrc_event_trigger_mask_b;
+ uint8_t reg_sw2spm_wakeup_mask_b;
+ uint8_t reg_adsp2spm_wakeup_mask_b;
+ uint8_t reg_sspm2spm_wakeup_mask_b;
+ uint8_t reg_scp2spm_wakeup_mask_b;
+ uint8_t reg_csyspwrup_ack_mask;
+ uint8_t reg_spm_reserved_srcclkena_mask_b;
+ uint8_t reg_spm_reserved_infra_req_mask_b;
+ uint8_t reg_spm_reserved_apsrc_req_mask_b;
+ uint8_t reg_spm_reserved_vrf18_req_mask_b;
+ uint8_t reg_spm_reserved_ddren_req_mask_b;
+ uint8_t reg_mcupm_srcclkena_mask_b;
+ uint8_t reg_mcupm_infra_req_mask_b;
+ uint8_t reg_mcupm_apsrc_req_mask_b;
+ uint8_t reg_mcupm_vrf18_req_mask_b;
+ uint8_t reg_mcupm_ddren_req_mask_b;
+ uint8_t reg_msdc0_srcclkena_mask_b;
+ uint8_t reg_msdc0_infra_req_mask_b;
+ uint8_t reg_msdc0_apsrc_req_mask_b;
+ uint8_t reg_msdc0_vrf18_req_mask_b;
+ uint8_t reg_msdc0_ddren_req_mask_b;
+ uint8_t reg_msdc1_srcclkena_mask_b;
+ uint8_t reg_msdc1_infra_req_mask_b;
+ uint8_t reg_msdc1_apsrc_req_mask_b;
+ uint8_t reg_msdc1_vrf18_req_mask_b;
+ uint8_t reg_msdc1_ddren_req_mask_b;
+
+ /* SPM_SRC4_MASK */
+ uint32_t reg_ccif_event_srcclkena_mask_b;
+ uint8_t reg_bak_psri_srcclkena_mask_b;
+ uint8_t reg_bak_psri_infra_req_mask_b;
+ uint8_t reg_bak_psri_apsrc_req_mask_b;
+ uint8_t reg_bak_psri_vrf18_req_mask_b;
+ uint8_t reg_bak_psri_ddren_req_mask_b;
+ uint8_t reg_dramc_md32_infra_req_mask_b;
+ uint8_t reg_dramc_md32_vrf18_req_mask_b;
+ uint8_t reg_conn_srcclkenb2pwrap_mask_b;
+ uint8_t reg_dramc_md32_apsrc_req_mask_b;
+
+ /* SPM_SRC5_MASK */
+ uint32_t reg_mcusys_merge_apsrc_req_mask_b;
+ uint32_t reg_mcusys_merge_ddren_req_mask_b;
+ uint8_t reg_afe_srcclkena_mask_b;
+ uint8_t reg_afe_infra_req_mask_b;
+ uint8_t reg_afe_apsrc_req_mask_b;
+ uint8_t reg_afe_vrf18_req_mask_b;
+ uint8_t reg_afe_ddren_req_mask_b;
+ uint8_t reg_msdc2_srcclkena_mask_b;
+ uint8_t reg_msdc2_infra_req_mask_b;
+ uint8_t reg_msdc2_apsrc_req_mask_b;
+ uint8_t reg_msdc2_vrf18_req_mask_b;
+ uint8_t reg_msdc2_ddren_req_mask_b;
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ uint32_t reg_wakeup_event_mask;
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ uint32_t reg_ext_wakeup_event_mask;
+
+ /* SPM_SRC7_MASK */
+ uint8_t reg_pcie_srcclkena_mask_b;
+ uint8_t reg_pcie_infra_req_mask_b;
+ uint8_t reg_pcie_apsrc_req_mask_b;
+ uint8_t reg_pcie_vrf18_req_mask_b;
+ uint8_t reg_pcie_ddren_req_mask_b;
+ uint8_t reg_dpmaif_srcclkena_mask_b;
+ uint8_t reg_dpmaif_infra_req_mask_b;
+ uint8_t reg_dpmaif_apsrc_req_mask_b;
+ uint8_t reg_dpmaif_vrf18_req_mask_b;
+ uint8_t reg_dpmaif_ddren_req_mask_b;
+
+ /* Auto-gen End */
+};
+
+/* code gen by spm_pwr_ctrl_atf.pl, need struct pwr_ctrl */
+enum pwr_ctrl_enum {
+ PW_PCM_FLAGS,
+ PW_PCM_FLAGS_CUST,
+ PW_PCM_FLAGS_CUST_SET,
+ PW_PCM_FLAGS_CUST_CLR,
+ PW_PCM_FLAGS1,
+ PW_PCM_FLAGS1_CUST,
+ PW_PCM_FLAGS1_CUST_SET,
+ PW_PCM_FLAGS1_CUST_CLR,
+ PW_TIMER_VAL,
+ PW_TIMER_VAL_CUST,
+ PW_TIMER_VAL_RAMP_EN,
+ PW_TIMER_VAL_RAMP_EN_SEC,
+ PW_WAKE_SRC,
+ PW_WAKE_SRC_CUST,
+ PW_WAKELOCK_TIMER_VAL,
+ PW_WDT_DISABLE,
+
+ /* SPM_AP_STANDBY_CON */
+ PW_REG_WFI_OP,
+ PW_REG_WFI_TYPE,
+ PW_REG_MP0_CPUTOP_IDLE_MASK,
+ PW_REG_MP1_CPUTOP_IDLE_MASK,
+ PW_REG_MCUSYS_IDLE_MASK,
+ PW_REG_MD_APSRC_1_SEL,
+ PW_REG_MD_APSRC_0_SEL,
+ PW_REG_CONN_APSRC_SEL,
+
+ /* SPM_SRC6_MASK */
+ PW_REG_CCIF_EVENT_INFRA_REQ_MASK_B,
+ PW_REG_CCIF_EVENT_APSRC_REQ_MASK_B,
+
+ /* SPM_WAKEUP_EVENT_SENS */
+ PW_REG_WAKEUP_EVENT_SENS,
+
+ /* SPM_SRC_REQ */
+ PW_REG_SPM_APSRC_REQ,
+ PW_REG_SPM_F26M_REQ,
+ PW_REG_SPM_INFRA_REQ,
+ PW_REG_SPM_VRF18_REQ,
+ PW_REG_SPM_DDREN_REQ,
+ PW_REG_SPM_DVFS_REQ,
+ PW_REG_SPM_SW_MAILBOX_REQ,
+ PW_REG_SPM_SSPM_MAILBOX_REQ,
+ PW_REG_SPM_ADSP_MAILBOX_REQ,
+ PW_REG_SPM_SCP_MAILBOX_REQ,
+
+ /* SPM_SRC_MASK */
+ PW_REG_MD_0_SRCCLKENA_MASK_B,
+ PW_REG_MD_0_INFRA_REQ_MASK_B,
+ PW_REG_MD_0_APSRC_REQ_MASK_B,
+ PW_REG_MD_0_VRF18_REQ_MASK_B,
+ PW_REG_MD_0_DDREN_REQ_MASK_B,
+ PW_REG_MD_1_SRCCLKENA_MASK_B,
+ PW_REG_MD_1_INFRA_REQ_MASK_B,
+ PW_REG_MD_1_APSRC_REQ_MASK_B,
+ PW_REG_MD_1_VRF18_REQ_MASK_B,
+ PW_REG_MD_1_DDREN_REQ_MASK_B,
+ PW_REG_CONN_SRCCLKENA_MASK_B,
+ PW_REG_CONN_SRCCLKENB_MASK_B,
+ PW_REG_CONN_INFRA_REQ_MASK_B,
+ PW_REG_CONN_APSRC_REQ_MASK_B,
+ PW_REG_CONN_VRF18_REQ_MASK_B,
+ PW_REG_CONN_DDREN_REQ_MASK_B,
+ PW_REG_CONN_VFE28_MASK_B,
+ PW_REG_SRCCLKENI_SRCCLKENA_MASK_B,
+ PW_REG_SRCCLKENI_INFRA_REQ_MASK_B,
+ PW_REG_INFRASYS_APSRC_REQ_MASK_B,
+ PW_REG_INFRASYS_DDREN_REQ_MASK_B,
+ PW_REG_SSPM_SRCCLKENA_MASK_B,
+ PW_REG_SSPM_INFRA_REQ_MASK_B,
+ PW_REG_SSPM_APSRC_REQ_MASK_B,
+ PW_REG_SSPM_VRF18_REQ_MASK_B,
+ PW_REG_SSPM_DDREN_REQ_MASK_B,
+
+ /* SPM_SRC2_MASK */
+ PW_REG_SCP_SRCCLKENA_MASK_B,
+ PW_REG_SCP_INFRA_REQ_MASK_B,
+ PW_REG_SCP_APSRC_REQ_MASK_B,
+ PW_REG_SCP_VRF18_REQ_MASK_B,
+ PW_REG_SCP_DDREN_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_SRCCLKENA_MASK_B,
+ PW_REG_AUDIO_DSP_INFRA_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_APSRC_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_VRF18_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_DDREN_REQ_MASK_B,
+ PW_REG_UFS_SRCCLKENA_MASK_B,
+ PW_REG_UFS_INFRA_REQ_MASK_B,
+ PW_REG_UFS_APSRC_REQ_MASK_B,
+ PW_REG_UFS_VRF18_REQ_MASK_B,
+ PW_REG_UFS_DDREN_REQ_MASK_B,
+ PW_REG_DISP0_APSRC_REQ_MASK_B,
+ PW_REG_DISP0_DDREN_REQ_MASK_B,
+ PW_REG_DISP1_APSRC_REQ_MASK_B,
+ PW_REG_DISP1_DDREN_REQ_MASK_B,
+ PW_REG_GCE_INFRA_REQ_MASK_B,
+ PW_REG_GCE_APSRC_REQ_MASK_B,
+ PW_REG_GCE_VRF18_REQ_MASK_B,
+ PW_REG_GCE_DDREN_REQ_MASK_B,
+ PW_REG_APU_SRCCLKENA_MASK_B,
+ PW_REG_APU_INFRA_REQ_MASK_B,
+ PW_REG_APU_APSRC_REQ_MASK_B,
+ PW_REG_APU_VRF18_REQ_MASK_B,
+ PW_REG_APU_DDREN_REQ_MASK_B,
+ PW_REG_CG_CHECK_SRCCLKENA_MASK_B,
+ PW_REG_CG_CHECK_APSRC_REQ_MASK_B,
+ PW_REG_CG_CHECK_VRF18_REQ_MASK_B,
+ PW_REG_CG_CHECK_DDREN_REQ_MASK_B,
+
+ /* SPM_SRC3_MASK */
+ PW_REG_DVFSRC_EVENT_TRIGGER_MASK_B,
+ PW_REG_SW2SPM_WAKEUP_MASK_B,
+ PW_REG_ADSP2SPM_WAKEUP_MASK_B,
+ PW_REG_SSPM2SPM_WAKEUP_MASK_B,
+ PW_REG_SCP2SPM_WAKEUP_MASK_B,
+ PW_REG_CSYSPWRUP_ACK_MASK,
+ PW_REG_SPM_RESERVED_SRCCLKENA_MASK_B,
+ PW_REG_SPM_RESERVED_INFRA_REQ_MASK_B,
+ PW_REG_SPM_RESERVED_APSRC_REQ_MASK_B,
+ PW_REG_SPM_RESERVED_VRF18_REQ_MASK_B,
+ PW_REG_SPM_RESERVED_DDREN_REQ_MASK_B,
+ PW_REG_MCUPM_SRCCLKENA_MASK_B,
+ PW_REG_MCUPM_INFRA_REQ_MASK_B,
+ PW_REG_MCUPM_APSRC_REQ_MASK_B,
+ PW_REG_MCUPM_VRF18_REQ_MASK_B,
+ PW_REG_MCUPM_DDREN_REQ_MASK_B,
+ PW_REG_MSDC0_SRCCLKENA_MASK_B,
+ PW_REG_MSDC0_INFRA_REQ_MASK_B,
+ PW_REG_MSDC0_APSRC_REQ_MASK_B,
+ PW_REG_MSDC0_VRF18_REQ_MASK_B,
+ PW_REG_MSDC0_DDREN_REQ_MASK_B,
+ PW_REG_MSDC1_SRCCLKENA_MASK_B,
+ PW_REG_MSDC1_INFRA_REQ_MASK_B,
+ PW_REG_MSDC1_APSRC_REQ_MASK_B,
+ PW_REG_MSDC1_VRF18_REQ_MASK_B,
+ PW_REG_MSDC1_DDREN_REQ_MASK_B,
+
+ /* SPM_SRC4_MASK */
+ PW_REG_CCIF_EVENT_SRCCLKENA_MASK_B,
+ PW_REG_BAK_PSRI_SRCCLKENA_MASK_B,
+ PW_REG_BAK_PSRI_INFRA_REQ_MASK_B,
+ PW_REG_BAK_PSRI_APSRC_REQ_MASK_B,
+ PW_REG_BAK_PSRI_VRF18_REQ_MASK_B,
+ PW_REG_BAK_PSRI_DDREN_REQ_MASK_B,
+ PW_REG_DRAMC_MD32_INFRA_REQ_MASK_B,
+ PW_REG_DRAMC_MD32_VRF18_REQ_MASK_B,
+ PW_REG_CONN_SRCCLKENB2PWRAP_MASK_B,
+ PW_REG_DRAMC_MD32_APSRC_REQ_MASK_B,
+
+ /* SPM_SRC5_MASK */
+ PW_REG_MCUSYS_MERGE_APSRC_REQ_MASK_B,
+ PW_REG_MCUSYS_MERGE_DDREN_REQ_MASK_B,
+ PW_REG_AFE_SRCCLKENA_MASK_B,
+ PW_REG_AFE_INFRA_REQ_MASK_B,
+ PW_REG_AFE_APSRC_REQ_MASK_B,
+ PW_REG_AFE_VRF18_REQ_MASK_B,
+ PW_REG_AFE_DDREN_REQ_MASK_B,
+ PW_REG_MSDC2_SRCCLKENA_MASK_B,
+ PW_REG_MSDC2_INFRA_REQ_MASK_B,
+ PW_REG_MSDC2_APSRC_REQ_MASK_B,
+ PW_REG_MSDC2_VRF18_REQ_MASK_B,
+ PW_REG_MSDC2_DDREN_REQ_MASK_B,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ PW_REG_WAKEUP_EVENT_MASK,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ PW_REG_EXT_WAKEUP_EVENT_MASK,
+
+ /* SPM_SRC7_MASK */
+ PW_REG_PCIE_SRCCLKENA_MASK_B,
+ PW_REG_PCIE_INFRA_REQ_MASK_B,
+ PW_REG_PCIE_APSRC_REQ_MASK_B,
+ PW_REG_PCIE_VRF18_REQ_MASK_B,
+ PW_REG_PCIE_DDREN_REQ_MASK_B,
+ PW_REG_DPMAIF_SRCCLKENA_MASK_B,
+ PW_REG_DPMAIF_INFRA_REQ_MASK_B,
+ PW_REG_DPMAIF_APSRC_REQ_MASK_B,
+ PW_REG_DPMAIF_VRF18_REQ_MASK_B,
+ PW_REG_DPMAIF_DDREN_REQ_MASK_B,
+
+ PW_MAX_COUNT,
+};
+
+/*
+ * ACK HW MODE SETTING
+ * 0: trigger(1)
+ * 1: trigger(0)
+ * 2: trigger(1) and target(0)
+ * 3: trigger(0) and target(1)
+ * 4: trigger(1) and target(1)
+ * 5: trigger(0) and target(0)
+ */
+#define TRIG_H_TAR_L (2U)
+#define TRIG_L_TAR_H (3U)
+#define TRIG_H_TAR_H (4U)
+#define TRIG_L_TAR_L (5U)
+
+#define SPM_INTERNAL_STATUS_HW_S1 (1U << 0)
+#define SPM_ACK_CHK_3_SEL_HW_S1 (0x00350098)
+#define SPM_ACK_CHK_3_HW_S1_CNT (1U)
+#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG (TRIG_L_TAR_H << 9u)
+#define SPM_ACK_CHK_3_CON_EN (0x110)
+#define SPM_ACK_CHK_3_CON_CLR_ALL (0x2)
+#define SPM_ACK_CHK_3_CON_RESULT (0x8000)
+
+struct wake_status_trace_comm {
+ uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */
+ uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */
+ uint32_t timer_out; /* SPM_SW_RSV_6*/
+ uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */
+ uint32_t b_sw_flag1; /* SPM_SW_RSV_7 */
+ uint32_t r12; /* SPM_SW_RSV_0 */
+ uint32_t r13; /* PCM_REG13_DATA */
+ uint32_t req_sta0; /* SRC_REQ_STA_0 */
+ uint32_t req_sta1; /* SRC_REQ_STA_1 */
+ uint32_t req_sta2; /* SRC_REQ_STA_2 */
+ uint32_t req_sta3; /* SRC_REQ_STA_3 */
+ uint32_t req_sta4; /* SRC_REQ_STA_4 */
+ uint32_t raw_sta; /* SPM_WAKEUP_STA */
+ uint32_t times_h; /* timestamp high bits */
+ uint32_t times_l; /* timestamp low bits */
+ uint32_t resumetime; /* timestamp low bits */
+};
+
+struct wake_status_trace {
+ struct wake_status_trace_comm comm;
+};
+
+struct wake_status {
+ struct wake_status_trace tr;
+ uint32_t r12; /* SPM_BK_WAKE_EVENT */
+ uint32_t r12_ext; /* SPM_WAKEUP_EXT_STA */
+ uint32_t raw_sta; /* SPM_WAKEUP_STA */
+ uint32_t raw_ext_sta; /* SPM_WAKEUP_EXT_STA */
+ uint32_t md32pcm_wakeup_sta; /* MD32CPM_WAKEUP_STA */
+ uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */
+ uint32_t wake_misc; /* SPM_BK_WAKE_MISC */
+ uint32_t timer_out; /* SPM_BK_PCM_TIMER */
+ uint32_t r13; /* PCM_REG13_DATA */
+ uint32_t idle_sta; /* SUBSYS_IDLE_STA */
+ uint32_t req_sta0; /* SRC_REQ_STA_0 */
+ uint32_t req_sta1; /* SRC_REQ_STA_1 */
+ uint32_t req_sta2; /* SRC_REQ_STA_2 */
+ uint32_t req_sta3; /* SRC_REQ_STA_3 */
+ uint32_t req_sta4; /* SRC_REQ_STA_4 */
+ uint32_t cg_check_sta; /* SPM_CG_CHECK_STA */
+ uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */
+ uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */
+ uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */
+ uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */
+ uint32_t isr; /* SPM_IRQ_STA */
+ uint32_t sw_flag0; /* SPM_SW_FLAG_0 */
+ uint32_t sw_flag1; /* SPM_SW_FLAG_1 */
+ uint32_t clk_settle; /* SPM_CLK_SETTLE */
+ uint32_t src_req; /* SPM_SRC_REQ */
+ uint32_t log_index;
+ uint32_t abort;
+ uint32_t rt_req_sta0; /* SPM_SW_RSV_2 */
+ uint32_t rt_req_sta1; /* SPM_SW_RSV_3 */
+ uint32_t rt_req_sta2; /* SPM_SW_RSV_4 */
+ uint32_t rt_req_sta3; /* SPM_SW_RSV_5 */
+ uint32_t rt_req_sta4; /* SPM_SW_RSV_6 */
+ uint32_t mcupm_req_sta;
+};
+
+struct spm_lp_scen {
+ struct pcm_desc *pcmdesc;
+ struct pwr_ctrl *pwrctrl;
+};
+
+extern struct spm_lp_scen __spm_vcorefs;
+
+extern void __spm_set_cpu_status(unsigned int cpu);
+extern void __spm_reset_and_init_pcm(const struct pcm_desc *pcmdesc);
+extern void __spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc);
+extern void __spm_init_pcm_register(void);
+extern void __spm_src_req_update(const struct pwr_ctrl *pwrctrl,
+ unsigned int resource_usage);
+extern void __spm_set_power_control(const struct pwr_ctrl *pwrctrl);
+extern void __spm_disable_pcm_timer(void);
+extern void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl);
+extern void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl);
+extern void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl);
+extern void __spm_send_cpu_wakeup_event(void);
+
+extern void __spm_get_wakeup_status(struct wake_status *wakesta,
+ unsigned int ext_status);
+extern void __spm_clean_after_wakeup(void);
+extern wake_reason_t __spm_output_wake_reason(int state_id,
+ const struct wake_status *wakesta);
+extern void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+ const struct pwr_ctrl *src_pwr_ctrl);
+extern void __spm_set_pcm_wdt(int en);
+extern uint32_t _spm_get_wake_period(int pwake_time, wake_reason_t last_wr);
+extern void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl);
+extern void __spm_ext_int_wakeup_req_clr(void);
+extern void __spm_xo_soc_bblpm(int en);
+
+static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl,
+ uint32_t flags)
+{
+ if (pwrctrl->pcm_flags_cust == 0U) {
+ pwrctrl->pcm_flags = flags;
+ } else {
+ pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust;
+ }
+}
+
+static inline void set_pwrctrl_pcm_flags1(struct pwr_ctrl *pwrctrl,
+ uint32_t flags)
+{
+ if (pwrctrl->pcm_flags1_cust == 0U) {
+ pwrctrl->pcm_flags1 = flags;
+ } else {
+ pwrctrl->pcm_flags1 = pwrctrl->pcm_flags1_cust;
+ }
+}
+
+extern void __spm_hw_s1_state_monitor(int en, unsigned int *status);
+
+static inline void spm_hw_s1_state_monitor_resume(void)
+{
+ __spm_hw_s1_state_monitor(1, NULL);
+}
+
+static inline void spm_hw_s1_state_monitor_pause(unsigned int *status)
+{
+ __spm_hw_s1_state_monitor(0, status);
+}
+
+#endif /* MT_SPM_INTERNAL_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c
new file mode 100644
index 0000000..c0000ed
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+#include <pmic.h>
+
+/* PMIC_WRAP MT6359 */
+#define NR_PMIC_WRAP_CMD (NR_IDX_ALL)
+#define SPM_DATA_SHIFT (16U)
+
+struct pmic_wrap_cmd {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+};
+
+struct pmic_wrap_setting {
+ enum pmic_wrap_phase_id phase;
+ struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
+ struct {
+ struct {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+ } _[NR_PMIC_WRAP_CMD];
+ const int nr_idx;
+ } set[NR_PMIC_WRAP_PHASE];
+};
+
+struct set_vsram {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+};
+
+/* MT6366 */
+#define VOLT_TO_PMIC_VAL_66(volt) (((volt) - 50000 + 625 - 1) / 625)
+#define BUCK_VCORE_ELR0_66 (0x14AA)
+#define TOP_SPI_CON0_66 (0x44C)
+
+static struct pmic_wrap_setting pw66 = {
+ .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */
+ .addr = { {0UL, 0UL} },
+ .set[PMIC_WRAP_PHASE_ALLINONE] = {
+ ._[CMD_0] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
+ ._[CMD_1] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
+ ._[CMD_2] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
+ ._[CMD_3] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
+ ._[CMD_4] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(80000), },
+ ._[CMD_5] = { TOP_SPI_CON0_66, 0x1, },
+ ._[CMD_6] = { TOP_SPI_CON0_66, 0x0, },
+ .nr_idx = NR_IDX_ALL,
+ },
+};
+
+/* MT6357 */
+#define VOLT_TO_PMIC_VAL_57(volt) (((volt) - 51875 + 625 - 1) / 625)
+#define BUCK_VCORE_ELR0_57 (0x152A)
+#define TOP_SPI_CON0_57 (0x448)
+
+static struct pmic_wrap_setting pw57 = {
+ .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */
+ .addr = { {0UL, 0UL} },
+ .set[PMIC_WRAP_PHASE_ALLINONE] = {
+ ._[CMD_0] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(80000), },
+ ._[CMD_1] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(75000), },
+ ._[CMD_2] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(70000), },
+ ._[CMD_3] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(65000), },
+ ._[CMD_4] = { BUCK_VCORE_ELR0_57, VOLT_TO_PMIC_VAL_57(62500), },
+ ._[CMD_5] = { TOP_SPI_CON0_57, 0x1, },
+ ._[CMD_6] = { TOP_SPI_CON0_57, 0x0, },
+ .nr_idx = NR_IDX_ALL,
+ },
+};
+
+static struct pmic_wrap_setting *pw;
+
+#define IS_PMIC_57() ((pmic_get_hwcid() >> 8) == 0x57)
+
+void _mt_spm_pmic_table_init(void)
+{
+ struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
+ { (uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0, },
+ { (uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1, },
+ { (uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2, },
+ { (uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3, },
+ { (uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4, },
+ { (uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5, },
+ { (uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6, },
+ { (uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7, },
+ { (uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8, },
+ };
+
+ if (IS_PMIC_57()) {
+ pw = &pw57;
+ } else {
+ pw = &pw66;
+ }
+
+ memcpy(pw->addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
+}
+
+void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
+{
+ uint32_t idx, addr, data;
+
+ if (phase < NR_PMIC_WRAP_PHASE) {
+ if (pw == NULL || pw->addr[0].cmd_addr == 0) {
+ _mt_spm_pmic_table_init();
+ }
+
+ if (pw->phase != phase) {
+ pw->phase = phase;
+
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
+
+ for (idx = 0; idx < pw->set[phase].nr_idx; idx++) {
+ addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ data = pw->set[phase]._[idx].cmd_wdata;
+ mmio_write_32(pw->addr[idx].cmd_addr, addr | data);
+ }
+ }
+ }
+}
+
+void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
+ uint32_t cmd_wdata)
+{
+ uint32_t addr;
+
+ if (phase >= NR_PMIC_WRAP_PHASE) {
+ return;
+ }
+
+ if (pw == NULL || idx >= pw->set[phase].nr_idx) {
+ return;
+ }
+
+ pw->set[phase]._[idx].cmd_wdata = cmd_wdata;
+
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
+ if (pw->phase == phase) {
+ addr = pw->set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ mmio_write_32(pw->addr[idx].cmd_addr, addr | cmd_wdata);
+ }
+}
+
+uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
+{
+ uint64_t ret = 0UL;
+
+ if ((phase < NR_PMIC_WRAP_PHASE) &&
+ (pw != NULL && idx < pw->set[phase].nr_idx)) {
+ ret = pw->set[phase]._[idx].cmd_wdata;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h
new file mode 100644
index 0000000..219b8d3
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/****************************************************************
+ * Auto generated by DE, please DO NOT modify this file directly.
+ *****************************************************************/
+#ifndef MT_SPM_PMIC_WRAP_H
+#define MT_SPM_PMIC_WRAP_H
+
+enum pmic_wrap_phase_id {
+ PMIC_WRAP_PHASE_ALLINONE = 0U,
+ NR_PMIC_WRAP_PHASE = 1U,
+};
+
+/* IDX mapping, PMIC_WRAP_PHASE_ALLINONE */
+enum {
+ CMD_0 = 0U, /* 0x0 */
+ CMD_1 = 1U, /* 0x1 */
+ CMD_2 = 2U, /* 0x2 */
+ CMD_3 = 3U, /* 0x3 */
+ CMD_4 = 4U, /* 0x4 */
+ CMD_5 = 5U, /* 0x5 */
+ CMD_6 = 6U, /* 0x6 */
+ CMD_7 = 7U, /* 0x7 */
+ CMD_8 = 8U, /* 0x8 */
+ NR_IDX_ALL = 9U,
+};
+
+/* APIs */
+extern void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase);
+extern void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase,
+ uint32_t idx, uint32_t cmd_wdata);
+extern uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase,
+ uint32_t idx);
+
+#endif /* MT_SPM_PMIC_WRAP_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h
new file mode 100644
index 0000000..f85ee3b
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h
@@ -0,0 +1,2957 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_REG
+#define MT_SPM_REG
+
+#include "pcm_def.h"
+#include <platform_def.h>
+#include "sleep_def.h"
+
+/* Define and Declare */
+#define POWERON_CONFIG_EN (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008)
+#define SPM_CLK_CON (SPM_BASE + 0x00C)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x010)
+#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014)
+#define PCM_CON0 (SPM_BASE + 0x018)
+#define PCM_CON1 (SPM_BASE + 0x01C)
+#define SPM_POWER_ON_VAL2 (SPM_BASE + 0x020)
+#define SPM_POWER_ON_VAL3 (SPM_BASE + 0x024)
+#define PCM_REG_DATA_INI (SPM_BASE + 0x028)
+#define PCM_PWR_IO_EN (SPM_BASE + 0x02C)
+#define PCM_TIMER_VAL (SPM_BASE + 0x030)
+#define PCM_WDT_VAL (SPM_BASE + 0x034)
+#define SPM_SW_RST_CON (SPM_BASE + 0x040)
+#define SPM_SW_RST_CON_SET (SPM_BASE + 0x044)
+#define SPM_SW_RST_CON_CLR (SPM_BASE + 0x048)
+#define SPM_SRC6_MASK (SPM_BASE + 0x04C)
+#define MD32_CLK_CON (SPM_BASE + 0x084)
+#define SPM_SRAM_RSV_CON (SPM_BASE + 0x088)
+#define SPM_SWINT (SPM_BASE + 0x08C)
+#define SPM_SWINT_SET (SPM_BASE + 0x090)
+#define SPM_SWINT_CLR (SPM_BASE + 0x094)
+#define SPM_SCP_MAILBOX (SPM_BASE + 0x098)
+#define SCP_SPM_MAILBOX (SPM_BASE + 0x09C)
+#define SPM_WAKEUP_EVENT_SENS (SPM_BASE + 0x0A0)
+#define SPM_WAKEUP_EVENT_CLEAR (SPM_BASE + 0x0A4)
+#define SPM_SCP_IRQ (SPM_BASE + 0x0AC)
+#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x0B0)
+#define SPM_IRQ_MASK (SPM_BASE + 0x0B4)
+#define SPM_SRC_REQ (SPM_BASE + 0x0B8)
+#define SPM_SRC_MASK (SPM_BASE + 0x0BC)
+#define SPM_SRC2_MASK (SPM_BASE + 0x0C0)
+#define SPM_SRC3_MASK (SPM_BASE + 0x0C4)
+#define SPM_SRC4_MASK (SPM_BASE + 0x0C8)
+#define SPM_SRC5_MASK (SPM_BASE + 0x0CC)
+#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x0D0)
+#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0D4)
+#define SPM_SRC7_MASK (SPM_BASE + 0x0D8)
+#define SCP_CLK_CON (SPM_BASE + 0x0DC)
+#define PCM_DEBUG_CON (SPM_BASE + 0x0E0)
+#define DDREN_DBC_CON (SPM_BASE + 0x0E8)
+#define SPM_RESOURCE_ACK_CON4 (SPM_BASE + 0x0EC)
+#define SPM_RESOURCE_ACK_CON0 (SPM_BASE + 0x0F0)
+#define SPM_RESOURCE_ACK_CON1 (SPM_BASE + 0x0F4)
+#define SPM_RESOURCE_ACK_CON2 (SPM_BASE + 0x0F8)
+#define SPM_RESOURCE_ACK_CON3 (SPM_BASE + 0x0FC)
+#define PCM_REG0_DATA (SPM_BASE + 0x100)
+#define PCM_REG2_DATA (SPM_BASE + 0x104)
+#define PCM_REG6_DATA (SPM_BASE + 0x108)
+#define PCM_REG7_DATA (SPM_BASE + 0x10C)
+#define PCM_REG13_DATA (SPM_BASE + 0x110)
+#define SRC_REQ_STA_0 (SPM_BASE + 0x114)
+#define SRC_REQ_STA_1 (SPM_BASE + 0x118)
+#define SRC_REQ_STA_2 (SPM_BASE + 0x11C)
+#define PCM_TIMER_OUT (SPM_BASE + 0x120)
+#define PCM_WDT_OUT (SPM_BASE + 0x124)
+#define SPM_IRQ_STA (SPM_BASE + 0x128)
+#define SRC_REQ_STA_4 (SPM_BASE + 0x12C)
+#define MD32PCM_WAKEUP_STA (SPM_BASE + 0x130)
+#define MD32PCM_EVENT_STA (SPM_BASE + 0x134)
+#define SPM_WAKEUP_STA (SPM_BASE + 0x138)
+#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x13C)
+#define SPM_WAKEUP_MISC (SPM_BASE + 0x140)
+#define MM_DVFS_HALT (SPM_BASE + 0x144)
+#define BUS_PROTECT_RDY (SPM_BASE + 0x150)
+#define BUS_PROTECT1_RDY (SPM_BASE + 0x154)
+#define BUS_PROTECT2_RDY (SPM_BASE + 0x158)
+#define BUS_PROTECT3_RDY (SPM_BASE + 0x15C)
+#define SUBSYS_IDLE_STA (SPM_BASE + 0x160)
+#define PCM_STA (SPM_BASE + 0x164)
+#define SRC_REQ_STA_3 (SPM_BASE + 0x168)
+#define PWR_STATUS (SPM_BASE + 0x16C)
+#define PWR_STATUS_2ND (SPM_BASE + 0x170)
+#define CPU_PWR_STATUS (SPM_BASE + 0x174)
+#define OTHER_PWR_STATUS (SPM_BASE + 0x178)
+#define SPM_VTCXO_EVENT_COUNT_STA (SPM_BASE + 0x17C)
+#define SPM_INFRA_EVENT_COUNT_STA (SPM_BASE + 0x180)
+#define SPM_VRF18_EVENT_COUNT_STA (SPM_BASE + 0x184)
+#define SPM_APSRC_EVENT_COUNT_STA (SPM_BASE + 0x188)
+#define SPM_DDREN_EVENT_COUNT_STA (SPM_BASE + 0x18C)
+#define MD32PCM_STA (SPM_BASE + 0x190)
+#define MD32PCM_PC (SPM_BASE + 0x194)
+#define DVFSRC_EVENT_STA (SPM_BASE + 0x1A4)
+#define BUS_PROTECT4_RDY (SPM_BASE + 0x1A8)
+#define BUS_PROTECT5_RDY (SPM_BASE + 0x1AC)
+#define BUS_PROTECT6_RDY (SPM_BASE + 0x1B0)
+#define BUS_PROTECT7_RDY (SPM_BASE + 0x1B4)
+#define BUS_PROTECT8_RDY (SPM_BASE + 0x1B8)
+#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1D0)
+#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1D4)
+#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1D8)
+#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1DC)
+#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1E0)
+#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1E4)
+#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1E8)
+#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1EC)
+#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1F0)
+#define SPM_CG_CHECK_STA (SPM_BASE + 0x1F4)
+#define SPM_DVFS_STA (SPM_BASE + 0x1F8)
+#define SPM_DVFS_OPP_STA (SPM_BASE + 0x1FC)
+#define SPM_MCUSYS_PWR_CON (SPM_BASE + 0x200)
+#define SPM_CPUTOP_PWR_CON (SPM_BASE + 0x204)
+#define SPM_CPU0_PWR_CON (SPM_BASE + 0x208)
+#define SPM_CPU1_PWR_CON (SPM_BASE + 0x20C)
+#define SPM_CPU2_PWR_CON (SPM_BASE + 0x210)
+#define SPM_CPU3_PWR_CON (SPM_BASE + 0x214)
+#define SPM_CPU4_PWR_CON (SPM_BASE + 0x218)
+#define SPM_CPU5_PWR_CON (SPM_BASE + 0x21C)
+#define SPM_CPU6_PWR_CON (SPM_BASE + 0x220)
+#define SPM_CPU7_PWR_CON (SPM_BASE + 0x224)
+#define ARMPLL_CLK_CON (SPM_BASE + 0x22C)
+#define MCUSYS_IDLE_STA (SPM_BASE + 0x230)
+#define GIC_WAKEUP_STA (SPM_BASE + 0x234)
+#define CPU_SPARE_CON (SPM_BASE + 0x238)
+#define CPU_SPARE_CON_SET (SPM_BASE + 0x23C)
+#define CPU_SPARE_CON_CLR (SPM_BASE + 0x240)
+#define ARMPLL_CLK_SEL (SPM_BASE + 0x244)
+#define EXT_INT_WAKEUP_REQ (SPM_BASE + 0x248)
+#define EXT_INT_WAKEUP_REQ_SET (SPM_BASE + 0x24C)
+#define EXT_INT_WAKEUP_REQ_CLR (SPM_BASE + 0x250)
+#define CPU_IRQ_MASK (SPM_BASE + 0x260)
+#define CPU_IRQ_MASK_SET (SPM_BASE + 0x264)
+#define CPU_IRQ_MASK_CLR (SPM_BASE + 0x268)
+#define CPU_WFI_EN (SPM_BASE + 0x280)
+#define CPU_WFI_EN_SET (SPM_BASE + 0x284)
+#define CPU_WFI_EN_CLR (SPM_BASE + 0x288)
+#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x2A0)
+#define ROOT_CORE_ADDR (SPM_BASE + 0x2A4)
+#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x2D0)
+#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x2D4)
+#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x2D8)
+#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x2DC)
+#define SW2SPM_WAKEUP (SPM_BASE + 0x2E0)
+#define SW2SPM_WAKEUP_SET (SPM_BASE + 0x2E4)
+#define SW2SPM_WAKEUP_CLR (SPM_BASE + 0x2E8)
+#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x2EC)
+#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x2F0)
+#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x2F4)
+#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x2F8)
+#define SW2SPM_CFG (SPM_BASE + 0x2FC)
+#define MD1_PWR_CON (SPM_BASE + 0x300)
+#define CONN_PWR_CON (SPM_BASE + 0x304)
+#define MFG0_PWR_CON (SPM_BASE + 0x308)
+#define MFG1_PWR_CON (SPM_BASE + 0x30C)
+#define MFG2_PWR_CON (SPM_BASE + 0x310)
+#define MFG3_PWR_CON (SPM_BASE + 0x314)
+#define MFG4_PWR_CON (SPM_BASE + 0x318)
+#define MFG5_PWR_CON (SPM_BASE + 0x31C)
+#define MFG6_PWR_CON (SPM_BASE + 0x320)
+#define IFR_PWR_CON (SPM_BASE + 0x324)
+#define IFR_SUB_PWR_CON (SPM_BASE + 0x328)
+#define DPY_PWR_CON (SPM_BASE + 0x32C)
+#define DRAMC_MD32_PWR_CON (SPM_BASE + 0x330)
+#define ISP_PWR_CON (SPM_BASE + 0x334)
+#define ISP2_PWR_CON (SPM_BASE + 0x338)
+#define IPE_PWR_CON (SPM_BASE + 0x33C)
+#define VDE_PWR_CON (SPM_BASE + 0x340)
+#define VDE2_PWR_CON (SPM_BASE + 0x344)
+#define VEN_PWR_CON (SPM_BASE + 0x348)
+#define VEN_CORE1_PWR_CON (SPM_BASE + 0x34C)
+#define MDP_PWR_CON (SPM_BASE + 0x350)
+#define DIS_PWR_CON (SPM_BASE + 0x354)
+#define AUDIO_PWR_CON (SPM_BASE + 0x358)
+#define CAM_PWR_CON (SPM_BASE + 0x35C)
+#define CAM_RAWA_PWR_CON (SPM_BASE + 0x360)
+#define CAM_RAWB_PWR_CON (SPM_BASE + 0x364)
+#define CAM_RAWC_PWR_CON (SPM_BASE + 0x368)
+#define SYSRAM_CON (SPM_BASE + 0x36C)
+#define SYSROM_CON (SPM_BASE + 0x370)
+#define SSPM_SRAM_CON (SPM_BASE + 0x374)
+#define SCP_SRAM_CON (SPM_BASE + 0x378)
+#define DPY_SHU_SRAM_CON (SPM_BASE + 0x37C)
+#define UFS_SRAM_CON (SPM_BASE + 0x380)
+#define DEVAPC_IFR_SRAM_CON (SPM_BASE + 0x384)
+#define DEVAPC_SUBIFR_SRAM_CON (SPM_BASE + 0x388)
+#define DEVAPC_ACP_SRAM_CON (SPM_BASE + 0x38C)
+#define USB_SRAM_CON (SPM_BASE + 0x390)
+#define DUMMY_SRAM_CON (SPM_BASE + 0x394)
+#define MD_EXT_BUCK_ISO_CON (SPM_BASE + 0x398)
+#define EXT_BUCK_ISO (SPM_BASE + 0x39C)
+#define DXCC_SRAM_CON (SPM_BASE + 0x3A0)
+#define MSDC_PWR_CON (SPM_BASE + 0x3A4)
+#define DEBUGTOP_SRAM_CON (SPM_BASE + 0x3A8)
+#define DP_TX_PWR_CON (SPM_BASE + 0x3AC)
+#define DPMAIF_SRAM_CON (SPM_BASE + 0x3B0)
+#define DPY_SHU2_SRAM_CON (SPM_BASE + 0x3B4)
+#define DRAMC_MCU2_SRAM_CON (SPM_BASE + 0x3B8)
+#define DRAMC_MCU_SRAM_CON (SPM_BASE + 0x3BC)
+#define MCUPM_PWR_CON (SPM_BASE + 0x3C0)
+#define DPY2_PWR_CON (SPM_BASE + 0x3C4)
+#define SPM_SRAM_CON (SPM_BASE + 0x3C8)
+#define PERI_PWR_CON (SPM_BASE + 0x3D0)
+#define NNA0_PWR_CON (SPM_BASE + 0x3D4)
+#define NNA1_PWR_CON (SPM_BASE + 0x3D8)
+#define NNA2_PWR_CON (SPM_BASE + 0x3DC)
+#define NNA_PWR_CON (SPM_BASE + 0x3E0)
+#define ADSP_PWR_CON (SPM_BASE + 0x3E4)
+#define DPY_SRAM_CON (SPM_BASE + 0x3E8)
+#define SPM_MEM_CK_SEL (SPM_BASE + 0x400)
+#define SPM_BUS_PROTECT_MASK_B (SPM_BASE + 0x404)
+#define SPM_BUS_PROTECT1_MASK_B (SPM_BASE + 0x408)
+#define SPM_BUS_PROTECT2_MASK_B (SPM_BASE + 0x40C)
+#define SPM_BUS_PROTECT3_MASK_B (SPM_BASE + 0x410)
+#define SPM_BUS_PROTECT4_MASK_B (SPM_BASE + 0x414)
+#define SPM_EMI_BW_MODE (SPM_BASE + 0x418)
+#define AP2MD_PEER_WAKEUP (SPM_BASE + 0x41C)
+#define ULPOSC_CON (SPM_BASE + 0x420)
+#define SPM2MM_CON (SPM_BASE + 0x424)
+#define SPM_BUS_PROTECT5_MASK_B (SPM_BASE + 0x428)
+#define SPM2MCUPM_CON (SPM_BASE + 0x42C)
+#define AP_MDSRC_REQ (SPM_BASE + 0x430)
+#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x434)
+#define SPM2MD_DVFS_CON (SPM_BASE + 0x438)
+#define MD2SPM_DVFS_CON (SPM_BASE + 0x43C)
+#define SPM_BUS_PROTECT6_MASK_B (SPM_BASE + 0x440)
+#define SPM_BUS_PROTECT7_MASK_B (SPM_BASE + 0x444)
+#define SPM_BUS_PROTECT8_MASK_B (SPM_BASE + 0x448)
+#define SPM_PLL_CON (SPM_BASE + 0x44C)
+#define RC_SPM_CTRL (SPM_BASE + 0x450)
+#define SPM_DRAM_MCU_SW_CON_0 (SPM_BASE + 0x454)
+#define SPM_DRAM_MCU_SW_CON_1 (SPM_BASE + 0x458)
+#define SPM_DRAM_MCU_SW_CON_2 (SPM_BASE + 0x45C)
+#define SPM_DRAM_MCU_SW_CON_3 (SPM_BASE + 0x460)
+#define SPM_DRAM_MCU_SW_CON_4 (SPM_BASE + 0x464)
+#define SPM_DRAM_MCU_STA_0 (SPM_BASE + 0x468)
+#define SPM_DRAM_MCU_STA_1 (SPM_BASE + 0x46C)
+#define SPM_DRAM_MCU_STA_2 (SPM_BASE + 0x470)
+#define SPM_DRAM_MCU_SW_SEL_0 (SPM_BASE + 0x474)
+#define RELAY_DVFS_LEVEL (SPM_BASE + 0x478)
+#define DRAMC_DPY_CLK_SW_CON_0 (SPM_BASE + 0x480)
+#define DRAMC_DPY_CLK_SW_CON_1 (SPM_BASE + 0x484)
+#define DRAMC_DPY_CLK_SW_CON_2 (SPM_BASE + 0x488)
+#define DRAMC_DPY_CLK_SW_CON_3 (SPM_BASE + 0x48C)
+#define DRAMC_DPY_CLK_SW_SEL_0 (SPM_BASE + 0x490)
+#define DRAMC_DPY_CLK_SW_SEL_1 (SPM_BASE + 0x494)
+#define DRAMC_DPY_CLK_SW_SEL_2 (SPM_BASE + 0x498)
+#define DRAMC_DPY_CLK_SW_SEL_3 (SPM_BASE + 0x49C)
+#define DRAMC_DPY_CLK_SPM_CON (SPM_BASE + 0x4A0)
+#define SPM_DVFS_LEVEL (SPM_BASE + 0x4A4)
+#define SPM_CIRQ_CON (SPM_BASE + 0x4A8)
+#define SPM_DVFS_MISC (SPM_BASE + 0x4AC)
+#define RG_MODULE_SW_CG_0_MASK_REQ_0 (SPM_BASE + 0x4B4)
+#define RG_MODULE_SW_CG_0_MASK_REQ_1 (SPM_BASE + 0x4B8)
+#define RG_MODULE_SW_CG_0_MASK_REQ_2 (SPM_BASE + 0x4BC)
+#define RG_MODULE_SW_CG_1_MASK_REQ_0 (SPM_BASE + 0x4C0)
+#define RG_MODULE_SW_CG_1_MASK_REQ_1 (SPM_BASE + 0x4C4)
+#define RG_MODULE_SW_CG_1_MASK_REQ_2 (SPM_BASE + 0x4C8)
+#define RG_MODULE_SW_CG_2_MASK_REQ_0 (SPM_BASE + 0x4CC)
+#define RG_MODULE_SW_CG_2_MASK_REQ_1 (SPM_BASE + 0x4D0)
+#define RG_MODULE_SW_CG_2_MASK_REQ_2 (SPM_BASE + 0x4D4)
+#define RG_MODULE_SW_CG_3_MASK_REQ_0 (SPM_BASE + 0x4D8)
+#define RG_MODULE_SW_CG_3_MASK_REQ_1 (SPM_BASE + 0x4DC)
+#define RG_MODULE_SW_CG_3_MASK_REQ_2 (SPM_BASE + 0x4E0)
+#define PWR_STATUS_MASK_REQ_0 (SPM_BASE + 0x4E4)
+#define PWR_STATUS_MASK_REQ_1 (SPM_BASE + 0x4E8)
+#define PWR_STATUS_MASK_REQ_2 (SPM_BASE + 0x4EC)
+#define SPM_CG_CHECK_CON (SPM_BASE + 0x4F0)
+#define SPM_SRC_RDY_STA (SPM_BASE + 0x4F4)
+#define SPM_DVS_DFS_LEVEL (SPM_BASE + 0x4F8)
+#define SPM_FORCE_DVFS (SPM_BASE + 0x4FC)
+#define RC_M00_SRCLKEN_CFG (SPM_BASE + 0x520)
+#define SPM_SW_FLAG_0 (SPM_BASE + 0x600)
+#define SPM_SW_DEBUG_0 (SPM_BASE + 0x604)
+#define SPM_SW_FLAG_1 (SPM_BASE + 0x608)
+#define SPM_SW_DEBUG_1 (SPM_BASE + 0x60C)
+#define SPM_SW_RSV_0 (SPM_BASE + 0x610)
+#define SPM_SW_RSV_1 (SPM_BASE + 0x614)
+#define SPM_SW_RSV_2 (SPM_BASE + 0x618)
+#define SPM_SW_RSV_3 (SPM_BASE + 0x61C)
+#define SPM_SW_RSV_4 (SPM_BASE + 0x620)
+#define SPM_SW_RSV_5 (SPM_BASE + 0x624)
+#define SPM_SW_RSV_6 (SPM_BASE + 0x628)
+#define SPM_SW_RSV_7 (SPM_BASE + 0x62C)
+#define SPM_SW_RSV_8 (SPM_BASE + 0x630)
+#define SPM_BK_WAKE_EVENT (SPM_BASE + 0x634)
+#define SPM_BK_VTCXO_DUR (SPM_BASE + 0x638)
+#define SPM_BK_WAKE_MISC (SPM_BASE + 0x63C)
+#define SPM_BK_PCM_TIMER (SPM_BASE + 0x640)
+#define SPM_RSV_CON_0 (SPM_BASE + 0x650)
+#define SPM_RSV_CON_1 (SPM_BASE + 0x654)
+#define SPM_RSV_STA_0 (SPM_BASE + 0x658)
+#define SPM_RSV_STA_1 (SPM_BASE + 0x65C)
+#define SPM_SPARE_CON (SPM_BASE + 0x660)
+#define SPM_SPARE_CON_SET (SPM_BASE + 0x664)
+#define SPM_SPARE_CON_CLR (SPM_BASE + 0x668)
+#define SPM_CROSS_WAKE_M00_REQ (SPM_BASE + 0x66C)
+#define SPM_CROSS_WAKE_M01_REQ (SPM_BASE + 0x670)
+#define SPM_CROSS_WAKE_M02_REQ (SPM_BASE + 0x674)
+#define SPM_CROSS_WAKE_M03_REQ (SPM_BASE + 0x678)
+#define SCP_VCORE_LEVEL (SPM_BASE + 0x67C)
+#define SC_MM_CK_SEL_CON (SPM_BASE + 0x680)
+#define SPARE_ACK_MASK (SPM_BASE + 0x684)
+#define SPM_SPARE_FUNCTION (SPM_BASE + 0x688)
+#define SPM_DV_CON_0 (SPM_BASE + 0x68C)
+#define SPM_DV_CON_1 (SPM_BASE + 0x690)
+#define SPM_DV_STA (SPM_BASE + 0x694)
+#define CONN_XOWCN_DEBUG_EN (SPM_BASE + 0x698)
+#define SPM_SEMA_M0 (SPM_BASE + 0x69C)
+#define SPM_SEMA_M1 (SPM_BASE + 0x6A0)
+#define SPM_SEMA_M2 (SPM_BASE + 0x6A4)
+#define SPM_SEMA_M3 (SPM_BASE + 0x6A8)
+#define SPM_SEMA_M4 (SPM_BASE + 0x6AC)
+#define SPM_SEMA_M5 (SPM_BASE + 0x6B0)
+#define SPM_SEMA_M6 (SPM_BASE + 0x6B4)
+#define SPM_SEMA_M7 (SPM_BASE + 0x6B8)
+#define SPM2ADSP_MAILBOX (SPM_BASE + 0x6BC)
+#define ADSP2SPM_MAILBOX (SPM_BASE + 0x6C0)
+#define SPM_ADSP_IRQ (SPM_BASE + 0x6C4)
+#define SPM_MD32_IRQ (SPM_BASE + 0x6C8)
+#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x6CC)
+#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x6D0)
+#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x6D4)
+#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x6D8)
+#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x6DC)
+#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x6E0)
+#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x6E4)
+#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x6E8)
+#define UFS_PSRI_SW (SPM_BASE + 0x6EC)
+#define UFS_PSRI_SW_SET (SPM_BASE + 0x6F0)
+#define UFS_PSRI_SW_CLR (SPM_BASE + 0x6F4)
+#define SPM_AP_SEMA (SPM_BASE + 0x6F8)
+#define SPM_SPM_SEMA (SPM_BASE + 0x6FC)
+#define SPM_DVFS_CON (SPM_BASE + 0x700)
+#define SPM_DVFS_CON_STA (SPM_BASE + 0x704)
+#define SPM_PMIC_SPMI_CON (SPM_BASE + 0x708)
+#define SPM_DVFS_CMD0 (SPM_BASE + 0x710)
+#define SPM_DVFS_CMD1 (SPM_BASE + 0x714)
+#define SPM_DVFS_CMD2 (SPM_BASE + 0x718)
+#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C)
+#define SPM_DVFS_CMD4 (SPM_BASE + 0x720)
+#define SPM_DVFS_CMD5 (SPM_BASE + 0x724)
+#define SPM_DVFS_CMD6 (SPM_BASE + 0x728)
+#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C)
+#define SPM_DVFS_CMD8 (SPM_BASE + 0x730)
+#define SPM_DVFS_CMD9 (SPM_BASE + 0x734)
+#define SPM_DVFS_CMD10 (SPM_BASE + 0x738)
+#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C)
+#define SPM_DVFS_CMD12 (SPM_BASE + 0x740)
+#define SPM_DVFS_CMD13 (SPM_BASE + 0x744)
+#define SPM_DVFS_CMD14 (SPM_BASE + 0x748)
+#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C)
+#define SPM_DVFS_CMD16 (SPM_BASE + 0x750)
+#define SPM_DVFS_CMD17 (SPM_BASE + 0x754)
+#define SPM_DVFS_CMD18 (SPM_BASE + 0x758)
+#define SPM_DVFS_CMD19 (SPM_BASE + 0x75C)
+#define SPM_DVFS_CMD20 (SPM_BASE + 0x760)
+#define SPM_DVFS_CMD21 (SPM_BASE + 0x764)
+#define SPM_DVFS_CMD22 (SPM_BASE + 0x768)
+#define SPM_DVFS_CMD23 (SPM_BASE + 0x76C)
+#define SYS_TIMER_VALUE_L (SPM_BASE + 0x770)
+#define SYS_TIMER_VALUE_H (SPM_BASE + 0x774)
+#define SYS_TIMER_START_L (SPM_BASE + 0x778)
+#define SYS_TIMER_START_H (SPM_BASE + 0x77C)
+#define SYS_TIMER_LATCH_L_00 (SPM_BASE + 0x780)
+#define SYS_TIMER_LATCH_H_00 (SPM_BASE + 0x784)
+#define SYS_TIMER_LATCH_L_01 (SPM_BASE + 0x788)
+#define SYS_TIMER_LATCH_H_01 (SPM_BASE + 0x78C)
+#define SYS_TIMER_LATCH_L_02 (SPM_BASE + 0x790)
+#define SYS_TIMER_LATCH_H_02 (SPM_BASE + 0x794)
+#define SYS_TIMER_LATCH_L_03 (SPM_BASE + 0x798)
+#define SYS_TIMER_LATCH_H_03 (SPM_BASE + 0x79C)
+#define SYS_TIMER_LATCH_L_04 (SPM_BASE + 0x7A0)
+#define SYS_TIMER_LATCH_H_04 (SPM_BASE + 0x7A4)
+#define SYS_TIMER_LATCH_L_05 (SPM_BASE + 0x7A8)
+#define SYS_TIMER_LATCH_H_05 (SPM_BASE + 0x7AC)
+#define SYS_TIMER_LATCH_L_06 (SPM_BASE + 0x7B0)
+#define SYS_TIMER_LATCH_H_06 (SPM_BASE + 0x7B4)
+#define SYS_TIMER_LATCH_L_07 (SPM_BASE + 0x7B8)
+#define SYS_TIMER_LATCH_H_07 (SPM_BASE + 0x7BC)
+#define SYS_TIMER_LATCH_L_08 (SPM_BASE + 0x7C0)
+#define SYS_TIMER_LATCH_H_08 (SPM_BASE + 0x7C4)
+#define SYS_TIMER_LATCH_L_09 (SPM_BASE + 0x7C8)
+#define SYS_TIMER_LATCH_H_09 (SPM_BASE + 0x7CC)
+#define SYS_TIMER_LATCH_L_10 (SPM_BASE + 0x7D0)
+#define SYS_TIMER_LATCH_H_10 (SPM_BASE + 0x7D4)
+#define SYS_TIMER_LATCH_L_11 (SPM_BASE + 0x7D8)
+#define SYS_TIMER_LATCH_H_11 (SPM_BASE + 0x7DC)
+#define SYS_TIMER_LATCH_L_12 (SPM_BASE + 0x7E0)
+#define SYS_TIMER_LATCH_H_12 (SPM_BASE + 0x7E4)
+#define SYS_TIMER_LATCH_L_13 (SPM_BASE + 0x7E8)
+#define SYS_TIMER_LATCH_H_13 (SPM_BASE + 0x7EC)
+#define SYS_TIMER_LATCH_L_14 (SPM_BASE + 0x7F0)
+#define SYS_TIMER_LATCH_H_14 (SPM_BASE + 0x7F4)
+#define SYS_TIMER_LATCH_L_15 (SPM_BASE + 0x7F8)
+#define SYS_TIMER_LATCH_H_15 (SPM_BASE + 0x7FC)
+#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800)
+#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804)
+#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808)
+#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C)
+#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810)
+#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814)
+#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818)
+#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C)
+#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820)
+#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824)
+#define PCM_WDT_LATCH_10 (SPM_BASE + 0x828)
+#define PCM_WDT_LATCH_11 (SPM_BASE + 0x82C)
+#define PCM_WDT_LATCH_12 (SPM_BASE + 0x830)
+#define PCM_WDT_LATCH_13 (SPM_BASE + 0x834)
+#define PCM_WDT_LATCH_14 (SPM_BASE + 0x838)
+#define PCM_WDT_LATCH_15 (SPM_BASE + 0x83C)
+#define PCM_WDT_LATCH_16 (SPM_BASE + 0x840)
+#define PCM_WDT_LATCH_17 (SPM_BASE + 0x844)
+#define PCM_WDT_LATCH_18 (SPM_BASE + 0x848)
+#define PCM_WDT_LATCH_SPARE_0 (SPM_BASE + 0x84C)
+#define PCM_WDT_LATCH_SPARE_1 (SPM_BASE + 0x850)
+#define PCM_WDT_LATCH_SPARE_2 (SPM_BASE + 0x854)
+#define PCM_WDT_LATCH_CONN_0 (SPM_BASE + 0x870)
+#define PCM_WDT_LATCH_CONN_1 (SPM_BASE + 0x874)
+#define PCM_WDT_LATCH_CONN_2 (SPM_BASE + 0x878)
+#define DRAMC_GATING_ERR_LATCH_CH0_0 (SPM_BASE + 0x8A0)
+#define DRAMC_GATING_ERR_LATCH_CH0_1 (SPM_BASE + 0x8A4)
+#define DRAMC_GATING_ERR_LATCH_CH0_2 (SPM_BASE + 0x8A8)
+#define DRAMC_GATING_ERR_LATCH_CH0_3 (SPM_BASE + 0x8AC)
+#define DRAMC_GATING_ERR_LATCH_CH0_4 (SPM_BASE + 0x8B0)
+#define DRAMC_GATING_ERR_LATCH_CH0_5 (SPM_BASE + 0x8B4)
+#define DRAMC_GATING_ERR_LATCH_CH0_6 (SPM_BASE + 0x8B8)
+#define DRAMC_GATING_ERR_LATCH_SPARE_0 (SPM_BASE + 0x8F4)
+#define SPM_ACK_CHK_CON_0 (SPM_BASE + 0x900)
+#define SPM_ACK_CHK_PC_0 (SPM_BASE + 0x904)
+#define SPM_ACK_CHK_SEL_0 (SPM_BASE + 0x908)
+#define SPM_ACK_CHK_TIMER_0 (SPM_BASE + 0x90C)
+#define SPM_ACK_CHK_STA_0 (SPM_BASE + 0x910)
+#define SPM_ACK_CHK_SWINT_0 (SPM_BASE + 0x914)
+#define SPM_ACK_CHK_CON_1 (SPM_BASE + 0x918)
+#define SPM_ACK_CHK_PC_1 (SPM_BASE + 0x91C)
+#define SPM_ACK_CHK_SEL_1 (SPM_BASE + 0x920)
+#define SPM_ACK_CHK_TIMER_1 (SPM_BASE + 0x924)
+#define SPM_ACK_CHK_STA_1 (SPM_BASE + 0x928)
+#define SPM_ACK_CHK_SWINT_1 (SPM_BASE + 0x92C)
+#define SPM_ACK_CHK_CON_2 (SPM_BASE + 0x930)
+#define SPM_ACK_CHK_PC_2 (SPM_BASE + 0x934)
+#define SPM_ACK_CHK_SEL_2 (SPM_BASE + 0x938)
+#define SPM_ACK_CHK_TIMER_2 (SPM_BASE + 0x93C)
+#define SPM_ACK_CHK_STA_2 (SPM_BASE + 0x940)
+#define SPM_ACK_CHK_SWINT_2 (SPM_BASE + 0x944)
+#define SPM_ACK_CHK_CON_3 (SPM_BASE + 0x948)
+#define SPM_ACK_CHK_PC_3 (SPM_BASE + 0x94C)
+#define SPM_ACK_CHK_SEL_3 (SPM_BASE + 0x950)
+#define SPM_ACK_CHK_TIMER_3 (SPM_BASE + 0x954)
+#define SPM_ACK_CHK_STA_3 (SPM_BASE + 0x958)
+#define SPM_ACK_CHK_SWINT_3 (SPM_BASE + 0x95C)
+#define SPM_COUNTER_0 (SPM_BASE + 0x960)
+#define SPM_COUNTER_1 (SPM_BASE + 0x964)
+#define SPM_COUNTER_2 (SPM_BASE + 0x968)
+#define SYS_TIMER_CON (SPM_BASE + 0x96C)
+#define SPM_TWAM_CON (SPM_BASE + 0x970)
+#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x974)
+#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x978)
+#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x97C)
+#define OPP0_TABLE (SPM_BASE + 0x980)
+#define OPP1_TABLE (SPM_BASE + 0x984)
+#define OPP2_TABLE (SPM_BASE + 0x988)
+#define OPP3_TABLE (SPM_BASE + 0x98C)
+#define OPP4_TABLE (SPM_BASE + 0x990)
+#define OPP5_TABLE (SPM_BASE + 0x994)
+#define OPP6_TABLE (SPM_BASE + 0x998)
+#define OPP7_TABLE (SPM_BASE + 0x99C)
+#define OPP8_TABLE (SPM_BASE + 0x9A0)
+#define OPP9_TABLE (SPM_BASE + 0x9A4)
+#define OPP10_TABLE (SPM_BASE + 0x9A8)
+#define OPP11_TABLE (SPM_BASE + 0x9AC)
+#define OPP12_TABLE (SPM_BASE + 0x9B0)
+#define OPP13_TABLE (SPM_BASE + 0x9B4)
+#define OPP14_TABLE (SPM_BASE + 0x9B8)
+#define OPP15_TABLE (SPM_BASE + 0x9BC)
+#define OPP16_TABLE (SPM_BASE + 0x9C0)
+#define OPP17_TABLE (SPM_BASE + 0x9C4)
+#define SHU0_ARRAY (SPM_BASE + 0x9C8)
+#define SHU1_ARRAY (SPM_BASE + 0x9CC)
+#define SHU2_ARRAY (SPM_BASE + 0x9D0)
+#define SHU3_ARRAY (SPM_BASE + 0x9D4)
+#define SHU4_ARRAY (SPM_BASE + 0x9D8)
+#define SHU5_ARRAY (SPM_BASE + 0x9DC)
+#define SHU6_ARRAY (SPM_BASE + 0x9E0)
+#define SHU7_ARRAY (SPM_BASE + 0x9E4)
+#define SHU8_ARRAY (SPM_BASE + 0x9E8)
+#define SHU9_ARRAY (SPM_BASE + 0x9EC)
+
+/* POWERON_CONFIG_EN (0x10006000 + 0x000) */
+#define BCLK_CG_EN_LSB (1U << 0) /* 1b */
+#define PROJECT_CODE_LSB (1U << 16) /* 16b */
+
+/* SPM_POWER_ON_VAL0 (0x10006000 + 0x004) */
+#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */
+
+/* SPM_POWER_ON_VAL1 (0x10006000 + 0x008) */
+#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */
+
+/* SPM_CLK_CON (0x10006000 + 0x00C) */
+#define REG_SRCCLKEN0_CTL_LSB (1U << 0) /* 2b */
+#define REG_SRCCLKEN1_CTL_LSB (1U << 2) /* 2b */
+#define RC_SW_SRCCLKEN_RC (1U << 3) /* 1b */
+#define RC_SW_SRCCLKEN_FPM (1U << 4) /* 1b */
+#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */
+#define REG_SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */
+#define REG_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */
+#define REG_MD1_C32RM_EN_LSB (1U << 9) /* 1b */
+#define REG_MD2_C32RM_EN_LSB (1U << 10) /* 1b */
+#define REG_CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */
+#define REG_CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */
+#define REG_SRCCLKEN0_EN_LSB (1U << 13) /* 1b */
+#define REG_SRCCLKEN1_EN_LSB (1U << 14) /* 1b */
+#define SCP_DCM_EN_LSB (1U << 15) /* 1b */
+#define REG_SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 8b */
+#define REG_SYSCLK1_SRC_MASK_B_LSB (1U << 24) /* 8b */
+
+/* SPM_CLK_SETTLE (0x10006000 + 0x010) */
+#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */
+
+/* SPM_AP_STANDBY_CON (0x10006000 + 0x014) */
+#define REG_WFI_OP_LSB (1U << 0) /* 1b */
+#define REG_WFI_TYPE_LSB (1U << 1) /* 1b */
+#define REG_MP0_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */
+#define REG_MP1_CPUTOP_IDLE_MASK_LSB (1U << 3) /* 1b */
+#define REG_MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */
+#define REG_MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */
+#define REG_MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */
+#define REG_CONN_APSRC_SEL_LSB (1U << 29) /* 1b */
+
+/* PCM_CON0 (0x10006000 + 0x018) */
+#define PCM_CK_EN_LSB (1U << 2) /* 1b */
+#define RG_EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */
+#define PCM_CK_FROM_CKSYS_LSB (1U << 4) /* 1b */
+#define PCM_SW_RESET_LSB (1U << 15) /* 1b */
+#define PCM_CON0_PROJECT_CODE_LSB (1U << 16) /* 16b */
+
+/* PCM_CON1 (0x10006000 + 0x01C) */
+#define REG_IM_SLEEP_EN_LSB (1U << 1) /* 1b */
+#define REG_SPM_SRAM_CTRL_MUX_LSB (1U << 2) /* 1b */
+#define RG_AHBMIF_APBEN_LSB (1U << 3) /* 1b */
+#define RG_PCM_TIMER_EN_LSB (1U << 5) /* 1b */
+#define REG_SPM_EVENT_COUNTER_CLR_LSB (1U << 6) /* 1b */
+#define RG_DIS_MIF_PROT_LSB (1U << 7) /* 1b */
+#define RG_PCM_WDT_EN_LSB (1U << 8) /* 1b */
+#define RG_PCM_WDT_WAKE_LSB (1U << 9) /* 1b */
+#define SPM_LEAVE_SUSPEND_MERGE_MASK_LSB (1U << 10) /* 1b */
+#define REG_SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */
+#define REG_MD32_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */
+#define RG_PCM_IRQ_MSK_LSB (1U << 15) /* 1b */
+#define PCM_CON1_PROJECT_CODE_LSB (1U << 16) /* 16b */
+
+/* SPM_POWER_ON_VAL2 (0x10006000 + 0x020) */
+#define POWER_ON_VAL2_LSB (1U << 0) /* 32b */
+
+/* SPM_POWER_ON_VAL3 (0x10006000 + 0x024) */
+#define POWER_ON_VAL3_LSB (1U << 0) /* 32b */
+
+/* PCM_REG_DATA_INI (0x10006000 + 0x028) */
+#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */
+
+/* PCM_PWR_IO_EN (0x10006000 + 0x02C) */
+#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */
+#define RG_RF_SYNC_EN_LSB (1U << 16) /* 8b */
+
+/* PCM_TIMER_VAL (0x10006000 + 0x030) */
+#define REG_PCM_TIMER_VAL_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_VAL (0x10006000 + 0x034) */
+#define RG_PCM_WDT_VAL_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RST_CON (0x10006000 + 0x040) */
+#define SPM_SW_RST_CON_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_PROJECT_CODE_LSB (1U << 16) /* 16b */
+
+/* SPM_SW_RST_CON_SET (0x10006000 + 0x044) */
+#define SPM_SW_RST_CON_SET_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_SET_PROJECT_CODE_LSB (1U << 16) /* 16b */
+
+/* SPM_SW_RST_CON_CLR (0x10006000 + 0x048) */
+#define SPM_SW_RST_CON_CLR_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_CLR_PROJECT_CODE_LSB (1U << 16) /* 16b */
+
+/* SPM_SRC6_MASK (0x10006000 + 0x04C) */
+#define REG_CCIF_EVENT_INFRA_REQ_MASK_B_LSB (1U << 0) /* 16b */
+#define REG_CCIF_EVENT_APSRC_REQ_MASK_B_LSB (1U << 16) /* 16b */
+
+/* MD32_CLK_CON (0x10006000 + 0x084) */
+#define REG_MD32_26M_CK_SEL_LSB (1U << 0) /* 1b */
+#define REG_MD32_DCM_EN_LSB (1U << 1) /* 1b */
+
+/* SPM_SRAM_RSV_CON (0x10006000 + 0x088) */
+#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */
+
+/* SPM_SWINT (0x10006000 + 0x08C) */
+#define SPM_SWINT_LSB (1U << 0) /* 32b */
+
+/* SPM_SWINT_SET (0x10006000 + 0x090) */
+#define SPM_SWINT_SET_LSB (1U << 0) /* 32b */
+
+/* SPM_SWINT_CLR (0x10006000 + 0x094) */
+#define SPM_SWINT_CLR_LSB (1U << 0) /* 32b */
+
+/* SPM_SCP_MAILBOX (0x10006000 + 0x098) */
+#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */
+
+/* SCP_SPM_MAILBOX (0x10006000 + 0x09C) */
+#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */
+
+/* SPM_WAKEUP_EVENT_SENS (0x10006000 + 0x0A0) */
+#define REG_WAKEUP_EVENT_SENS_LSB (1U << 0) /* 32b */
+
+/* SPM_WAKEUP_EVENT_CLEAR (0x10006000 + 0x0A4) */
+#define REG_WAKEUP_EVENT_CLR_LSB (1U << 0) /* 32b */
+
+/* SPM_SCP_IRQ (0x10006000 + 0x0AC) */
+#define SC_SPM2SCP_WAKEUP_LSB (1U << 0) /* 1b */
+#define SC_SCP2SPM_WAKEUP_LSB (1U << 4) /* 1b */
+
+/* SPM_CPU_WAKEUP_EVENT (0x10006000 + 0x0B0) */
+#define REG_CPU_WAKEUP_LSB (1U << 0) /* 1b */
+
+/* SPM_IRQ_MASK (0x10006000 + 0x0B4) */
+#define REG_SPM_IRQ_MASK_LSB (1U << 0) /* 32b */
+
+/* SPM_SRC_REQ (0x10006000 + 0x0B8) */
+#define REG_SPM_APSRC_REQ_LSB (1U << 0) /* 1b */
+#define REG_SPM_F26M_REQ_LSB (1U << 1) /* 1b */
+#define REG_SPM_INFRA_REQ_LSB (1U << 3) /* 1b */
+#define REG_SPM_VRF18_REQ_LSB (1U << 4) /* 1b */
+#define REG_SPM_DDREN_REQ_LSB (1U << 7) /* 1b */
+#define REG_SPM_DVFS_REQ_LSB (1U << 8) /* 1b */
+#define REG_SPM_SW_MAILBOX_REQ_LSB (1U << 9) /* 1b */
+#define REG_SPM_SSPM_MAILBOX_REQ_LSB (1U << 10) /* 1b */
+#define REG_SPM_ADSP_MAILBOX_REQ_LSB (1U << 11) /* 1b */
+#define REG_SPM_SCP_MAILBOX_REQ_LSB (1U << 12) /* 1b */
+
+/* SPM_SRC_MASK (0x10006000 + 0x0BC) */
+#define REG_MD_0_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_MD_0_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_MD_0_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_MD_0_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_MD_0_DDREN_REQ_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_MD_1_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_MD_1_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */
+#define REG_MD_1_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */
+#define REG_MD_1_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */
+#define REG_MD_1_DDREN_REQ_MASK_B_LSB (1U << 9) /* 1b */
+#define REG_CONN_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_CONN_SRCCLKENB_MASK_B_LSB (1U << 11) /* 1b */
+#define REG_CONN_INFRA_REQ_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_CONN_APSRC_REQ_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_CONN_VRF18_REQ_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_CONN_DDREN_REQ_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_CONN_VFE28_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_SRCCLKENI_SRCCLKENA_MASK_B_LSB (1U << 17) /* 3b */
+#define REG_SRCCLKENI_INFRA_REQ_MASK_B_LSB (1U << 20) /* 3b */
+#define REG_INFRASYS_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_INFRASYS_DDREN_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_SSPM_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_SSPM_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_SSPM_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_SSPM_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_SSPM_DDREN_REQ_MASK_B_LSB (1U << 31) /* 1b */
+
+/* SPM_SRC2_MASK (0x10006000 + 0x0C0) */
+#define REG_SCP_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_SCP_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_SCP_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_SCP_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_SCP_DDREN_REQ_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_AUDIO_DSP_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_AUDIO_DSP_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */
+#define REG_AUDIO_DSP_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */
+#define REG_AUDIO_DSP_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */
+#define REG_AUDIO_DSP_DDREN_REQ_MASK_B_LSB (1U << 9) /* 1b */
+#define REG_UFS_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_UFS_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */
+#define REG_UFS_APSRC_REQ_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_UFS_VRF18_REQ_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_UFS_DDREN_REQ_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_DISP0_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_DISP0_DDREN_REQ_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_DISP1_APSRC_REQ_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_DISP1_DDREN_REQ_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_GCE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_GCE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_GCE_DDREN_REQ_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_APU_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_APU_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_APU_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_APU_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_APU_DDREN_REQ_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_CG_CHECK_SRCCLKENA_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_CG_CHECK_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_CG_CHECK_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_CG_CHECK_DDREN_REQ_MASK_B_LSB (1U << 31) /* 1b */
+
+/* SPM_SRC3_MASK (0x10006000 + 0x0C4) */
+#define REG_DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_SW2SPM_WAKEUP_MASK_B_LSB (1U << 1) /* 4b */
+#define REG_ADSP2SPM_WAKEUP_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_SSPM2SPM_WAKEUP_MASK_B_LSB (1U << 6) /* 4b */
+#define REG_SCP2SPM_WAKEUP_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_CSYSPWRUP_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_SPM_RESERVED_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_SPM_RESERVED_INFRA_REQ_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_SPM_RESERVED_APSRC_REQ_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_SPM_RESERVED_VRF18_REQ_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_SPM_RESERVED_DDREN_REQ_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_MCUPM_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_MCUPM_INFRA_REQ_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_MCUPM_APSRC_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_MCUPM_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_MCUPM_DDREN_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_MSDC0_SRCCLKENA_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_MSDC0_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_MSDC0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_MSDC0_VRF18_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_MSDC0_DDREN_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_MSDC1_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_MSDC1_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_MSDC1_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_MSDC1_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_MSDC1_DDREN_REQ_MASK_B_LSB (1U << 31) /* 1b */
+
+/* SPM_SRC4_MASK (0x10006000 + 0x0C8) */
+#define REG_CCIF_EVENT_SRCCLKENA_MASK_B_LSB (1U << 0) /* 16b */
+#define REG_BAK_PSRI_SRCCLKENA_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_BAK_PSRI_INFRA_REQ_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_BAK_PSRI_APSRC_REQ_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_BAK_PSRI_VRF18_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_BAK_PSRI_DDREN_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_DRAMC_MD32_INFRA_REQ_MASK_B_LSB (1U << 21) /* 2b */
+#define REG_DRAMC_MD32_VRF18_REQ_MASK_B_LSB (1U << 23) /* 2b */
+#define REG_CONN_SRCCLKENB2PWRAP_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_DRAMC_MD32_APSRC_REQ_MASK_B_LSB (1U << 26) /* 2b */
+
+/* SPM_SRC5_MASK (0x10006000 + 0x0CC) */
+#define REG_MCUSYS_MERGE_APSRC_REQ_MASK_B_LSB (1U << 0) /* 9b */
+#define REG_MCUSYS_MERGE_DDREN_REQ_MASK_B_LSB (1U << 9) /* 9b */
+#define REG_AFE_SRCCLKENA_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_AFE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_AFE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_AFE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_AFE_DDREN_REQ_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_MSDC2_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_MSDC2_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_MSDC2_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_MSDC2_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_MSDC2_DDREN_REQ_MASK_B_LSB (1U << 27) /* 1b */
+/* SPM_WAKEUP_EVENT_MASK (0x10006000 + 0x0D0) */
+#define REG_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */
+
+/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000 + 0x0D4) */
+#define REG_EXT_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */
+
+/* SPM_SRC7_MASK (0x10006000 + 0x0D8) */
+#define REG_PCIE_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_PCIE_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_PCIE_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_PCIE_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_PCIE_DDREN_REQ_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_DPMAIF_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_DPMAIF_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */
+#define REG_DPMAIF_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */
+#define REG_DPMAIF_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */
+#define REG_DPMAIF_DDREN_REQ_MASK_B_LSB (1U << 9) /* 1b */
+
+/* SCP_CLK_CON (0x10006000 + 0x0DC) */
+#define REG_SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */
+#define REG_SCP_DCM_EN_LSB (1U << 1) /* 1b */
+#define SCP_SECURE_VREQ_MASK_LSB (1U << 2) /* 1b */
+#define SCP_SLP_REQ_LSB (1U << 3) /* 1b */
+#define SCP_SLP_ACK_LSB (1U << 4) /* 1b */
+
+/* PCM_DEBUG_CON (0x10006000 + 0x0E0) */
+#define PCM_DEBUG_OUT_ENABLE_LSB (1U << 0) /* 1b */
+
+/* DDREN_DBC_CON (0x10006000 + 0x0E8) */
+#define REG_DDREN_DBC_LEN_LSB (1U << 0) /* 10b */
+#define REG_DDREN_DBC_EN_LSB (1U << 16) /* 1b */
+
+/* SPM_RESOURCE_ACK_CON4 (0x10006000 + 0x0EC) */
+#define REG_DPMAIF_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */
+#define REG_DPMAIF_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */
+#define REG_DPMAIF_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */
+#define REG_DPMAIF_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */
+#define REG_DPMAIF_DDREN_ACK_MASK_LSB (1U << 4) /* 1b */
+
+/* SPM_RESOURCE_ACK_CON0 (0x10006000 + 0x0F0) */
+#define REG_MD_0_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */
+#define REG_MD_0_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */
+#define REG_MD_0_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */
+#define REG_MD_0_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */
+#define REG_MD_0_DDREN_ACK_MASK_LSB (1U << 4) /* 1b */
+#define REG_MD_1_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */
+#define REG_MD_1_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */
+#define REG_MD_1_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */
+#define REG_MD_1_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */
+#define REG_MD_1_DDREN_ACK_MASK_LSB (1U << 9) /* 1b */
+#define REG_CONN_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_CONN_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_CONN_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_CONN_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_CONN_DDREN_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_SSPM_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_SSPM_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_SSPM_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_SSPM_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_SSPM_DDREN_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_SCP_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_SCP_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_SCP_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_SCP_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_SCP_DDREN_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_AUDIO_DSP_SRCCLKENA_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_AUDIO_DSP_INFRA_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_AUDIO_DSP_APSRC_ACK_MASK_LSB (1U << 27) /* 1b */
+#define REG_AUDIO_DSP_VRF18_ACK_MASK_LSB (1U << 28) /* 1b */
+#define REG_AUDIO_DSP_DDREN_ACK_MASK_LSB (1U << 29) /* 1b */
+#define REG_DISP0_DDREN_ACK_MASK_LSB (1U << 30) /* 1b */
+#define REG_DISP1_APSRC_ACK_MASK_LSB (1U << 31) /* 1b */
+
+/* SPM_RESOURCE_ACK_CON1 (0x10006000 + 0x0F4) */
+#define REG_UFS_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */
+#define REG_UFS_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */
+#define REG_UFS_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */
+#define REG_UFS_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */
+#define REG_UFS_DDREN_ACK_MASK_LSB (1U << 4) /* 1b */
+#define REG_APU_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */
+#define REG_APU_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */
+#define REG_APU_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */
+#define REG_APU_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */
+#define REG_APU_DDREN_ACK_MASK_LSB (1U << 9) /* 1b */
+#define REG_MCUPM_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_MCUPM_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_MCUPM_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_MCUPM_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_MCUPM_DDREN_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_MSDC0_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_MSDC0_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_MSDC0_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_MSDC0_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_MSDC0_DDREN_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_MSDC1_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_MSDC1_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_MSDC1_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_MSDC1_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_MSDC1_DDREN_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_DISP0_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_DISP1_DDREN_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_GCE_INFRA_ACK_MASK_LSB (1U << 27) /* 1b */
+#define REG_GCE_APSRC_ACK_MASK_LSB (1U << 28) /* 1b */
+#define REG_GCE_VRF18_ACK_MASK_LSB (1U << 29) /* 1b */
+#define REG_GCE_DDREN_ACK_MASK_LSB (1U << 30) /* 1b */
+
+/* SPM_RESOURCE_ACK_CON2 (0x10006000 + 0x0F8) */
+#define SPM_SRCCLKENA_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */
+#define SPM_INFRA_ACK_WAIT_CYCLE_LSB (1U << 8) /* 8b */
+#define SPM_APSRC_ACK_WAIT_CYCLE_LSB (1U << 16) /* 8b */
+#define SPM_VRF18_ACK_WAIT_CYCLE_LSB (1U << 24) /* 8b */
+
+/* SPM_RESOURCE_ACK_CON3 (0x10006000 + 0x0FC) */
+#define SPM_DDREN_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */
+#define REG_BAK_PSRI_SRCCLKENA_ACK_MASK_LSB (1U << 8) /* 1b */
+#define REG_BAK_PSRI_INFRA_ACK_MASK_LSB (1U << 9) /* 1b */
+#define REG_BAK_PSRI_APSRC_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_BAK_PSRI_VRF18_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_BAK_PSRI_DDREN_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_AFE_SRCCLKENA_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_AFE_INFRA_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_AFE_APSRC_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_AFE_VRF18_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_AFE_DDREN_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_MSDC2_SRCCLKENA_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_MSDC2_INFRA_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_MSDC2_APSRC_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_MSDC2_VRF18_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_MSDC2_DDREN_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_PCIE_SRCCLKENA_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_PCIE_INFRA_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_PCIE_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_PCIE_VRF18_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_PCIE_DDREN_ACK_MASK_LSB (1U << 27) /* 1b */
+
+/* PCM_REG0_DATA (0x10006000 + 0x100) */
+#define PCM_REG0_RF_LSB (1U << 0) /* 32b */
+
+/* PCM_REG2_DATA (0x10006000 + 0x104) */
+#define PCM_REG2_RF_LSB (1U << 0) /* 32b */
+
+/* PCM_REG6_DATA (0x10006000 + 0x108) */
+#define PCM_REG6_RF_LSB (1U << 0) /* 32b */
+
+/* PCM_REG7_DATA (0x10006000 + 0x10C) */
+#define PCM_REG7_RF_LSB (1U << 0) /* 32b */
+
+/* PCM_REG13_DATA (0x10006000 + 0x110) */
+#define PCM_REG13_RF_LSB (1U << 0) /* 32b */
+
+/* SRC_REQ_STA_0 (0x10006000 + 0x114) */
+#define MD_0_SRCCLKENA_LSB (1U << 0) /* 1b */
+#define MD_0_INFRA_REQ_LSB (1U << 1) /* 1b */
+#define MD_0_APSRC_REQ_LSB (1U << 2) /* 1b */
+#define MD_0_VRF18_REQ_LSB (1U << 4) /* 1b */
+#define MD_0_DDREN_REQ_LSB (1U << 5) /* 1b */
+#define MD_1_SRCCLKENA_LSB (1U << 6) /* 1b */
+#define MD_1_INFRA_REQ_LSB (1U << 7) /* 1b */
+#define MD_1_APSRC_REQ_LSB (1U << 8) /* 1b */
+#define MD_1_VRF18_REQ_LSB (1U << 10) /* 1b */
+#define MD_1_DDREN_REQ_LSB (1U << 11) /* 1b */
+#define CONN_SRCCLKENA_LSB (1U << 12) /* 1b */
+#define CONN_SRCCLKENB_LSB (1U << 13) /* 1b */
+#define CONN_INFRA_REQ_LSB (1U << 14) /* 1b */
+#define CONN_APSRC_REQ_LSB (1U << 15) /* 1b */
+#define CONN_VRF18_REQ_LSB (1U << 16) /* 1b */
+#define CONN_DDREN_REQ_LSB (1U << 17) /* 1b */
+#define SRCCLKENI_LSB (1U << 18) /* 3b */
+#define SSPM_SRCCLKENA_LSB (1U << 21) /* 1b */
+#define SSPM_INFRA_REQ_LSB (1U << 22) /* 1b */
+#define SSPM_APSRC_REQ_LSB (1U << 23) /* 1b */
+#define SSPM_VRF18_REQ_LSB (1U << 24) /* 1b */
+#define SSPM_DDREN_REQ_LSB (1U << 25) /* 1b */
+#define DISP0_APSRC_REQ_LSB (1U << 26) /* 1b */
+#define DISP0_DDREN_REQ_LSB (1U << 27) /* 1b */
+#define DISP1_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define DISP1_DDREN_REQ_LSB (1U << 29) /* 1b */
+#define DVFSRC_EVENT_TRIGGER_LSB (1U << 30) /* 1b */
+
+/* SRC_REQ_STA_1 (0x10006000 + 0x118) */
+#define SCP_SRCCLKENA_LSB (1U << 0) /* 1b */
+#define SCP_INFRA_REQ_LSB (1U << 1) /* 1b */
+#define SCP_APSRC_REQ_LSB (1U << 2) /* 1b */
+#define SCP_VRF18_REQ_LSB (1U << 3) /* 1b */
+#define SCP_DDREN_REQ_LSB (1U << 4) /* 1b */
+#define AUDIO_DSP_SRCCLKENA_LSB (1U << 5) /* 1b */
+#define AUDIO_DSP_INFRA_REQ_LSB (1U << 6) /* 1b */
+#define AUDIO_DSP_APSRC_REQ_LSB (1U << 7) /* 1b */
+#define AUDIO_DSP_VRF18_REQ_LSB (1U << 8) /* 1b */
+#define AUDIO_DSP_DDREN_REQ_LSB (1U << 9) /* 1b */
+#define UFS_SRCCLKENA_LSB (1U << 10) /* 1b */
+#define UFS_INFRA_REQ_LSB (1U << 11) /* 1b */
+#define UFS_APSRC_REQ_LSB (1U << 12) /* 1b */
+#define UFS_VRF18_REQ_LSB (1U << 13) /* 1b */
+#define UFS_DDREN_REQ_LSB (1U << 14) /* 1b */
+#define GCE_INFRA_REQ_LSB (1U << 15) /* 1b */
+#define GCE_APSRC_REQ_LSB (1U << 16) /* 1b */
+#define GCE_VRF18_REQ_LSB (1U << 17) /* 1b */
+#define GCE_DDREN_REQ_LSB (1U << 18) /* 1b */
+#define INFRASYS_APSRC_REQ_LSB (1U << 19) /* 1b */
+#define INFRASYS_DDREN_REQ_LSB (1U << 20) /* 1b */
+#define MSDC0_SRCCLKENA_LSB (1U << 21) /* 1b */
+#define MSDC0_INFRA_REQ_LSB (1U << 22) /* 1b */
+#define MSDC0_APSRC_REQ_LSB (1U << 23) /* 1b */
+#define MSDC0_VRF18_REQ_LSB (1U << 24) /* 1b */
+#define MSDC0_DDREN_REQ_LSB (1U << 25) /* 1b */
+#define MSDC1_SRCCLKENA_LSB (1U << 26) /* 1b */
+#define MSDC1_INFRA_REQ_LSB (1U << 27) /* 1b */
+#define MSDC1_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define MSDC1_VRF18_REQ_LSB (1U << 29) /* 1b */
+#define MSDC1_DDREN_REQ_LSB (1U << 30) /* 1b */
+
+/* SRC_REQ_STA_2 (0x10006000 + 0x11C) */
+#define MCUSYS_MERGE_DDR_EN_LSB (1U << 0) /* 9b */
+#define EMI_SELF_REFRESH_CH_LSB (1U << 9) /* 2b */
+#define SW2SPM_WAKEUP_LSB (1U << 11) /* 4b */
+#define SC_ADSP2SPM_WAKEUP_LSB (1U << 15) /* 1b */
+#define SC_SSPM2SPM_WAKEUP_LSB (1U << 16) /* 4b */
+#define SRC_REQ_STA_2_SC_SCP2SPM_WAKEUP_LSB (1U << 20) /* 1b */
+#define SPM_RESERVED_SRCCLKENA_LSB (1U << 21) /* 1b */
+#define SPM_RESERVED_INFRA_REQ_LSB (1U << 22) /* 1b */
+#define SPM_RESERVED_APSRC_REQ_LSB (1U << 23) /* 1b */
+#define SPM_RESERVED_VRF18_REQ_LSB (1U << 24) /* 1b */
+#define SPM_RESERVED_DDREN_REQ_LSB (1U << 25) /* 1b */
+#define MCUPM_SRCCLKENA_LSB (1U << 26) /* 1b */
+#define MCUPM_INFRA_REQ_LSB (1U << 27) /* 1b */
+#define MCUPM_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define MCUPM_VRF18_REQ_LSB (1U << 29) /* 1b */
+#define MCUPM_DDREN_REQ_LSB (1U << 30) /* 1b */
+
+/* PCM_TIMER_OUT (0x10006000 + 0x120) */
+#define PCM_TIMER_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_OUT (0x10006000 + 0x124) */
+#define PCM_WDT_TIMER_VAL_OUT_LSB (1U << 0) /* 32b */
+
+/* SPM_IRQ_STA (0x10006000 + 0x128) */
+#define TWAM_IRQ_LSB (1U << 2) /* 1b */
+#define PCM_IRQ_LSB (1U << 3) /* 1b */
+
+/* SRC_REQ_STA_4 (0x10006000 + 0x12C) */
+#define APU_SRCCLKENA_LSB (1U << 0) /* 1b */
+#define APU_INFRA_REQ_LSB (1U << 1) /* 1b */
+#define APU_APSRC_REQ_LSB (1U << 2) /* 1b */
+#define APU_VRF18_REQ_LSB (1U << 3) /* 1b */
+#define APU_DDREN_REQ_LSB (1U << 4) /* 1b */
+#define BAK_PSRI_SRCCLKENA_LSB (1U << 5) /* 1b */
+#define BAK_PSRI_INFRA_REQ_LSB (1U << 6) /* 1b */
+#define BAK_PSRI_APSRC_REQ_LSB (1U << 7) /* 1b */
+#define BAK_PSRI_VRF18_REQ_LSB (1U << 8) /* 1b */
+#define BAK_PSRI_DDREN_REQ_LSB (1U << 9) /* 1b */
+#define MSDC2_SRCCLKENA_LSB (1U << 10) /* 1b */
+#define MSDC2_INFRA_REQ_LSB (1U << 11) /* 1b */
+#define MSDC2_APSRC_REQ_LSB (1U << 12) /* 1b */
+#define MSDC2_VRF18_REQ_LSB (1U << 13) /* 1b */
+#define MSDC2_DDREN_REQ_LSB (1U << 14) /* 1b */
+#define PCIE_SRCCLKENA_LSB (1U << 15) /* 1b */
+#define PCIE_INFRA_REQ_LSB (1U << 16) /* 1b */
+#define PCIE_APSRC_REQ_LSB (1U << 17) /* 1b */
+#define PCIE_VRF18_REQ_LSB (1U << 18) /* 1b */
+#define PCIE_DDREN_REQ_LSB (1U << 19) /* 1b */
+#define DPMAIF_SRCCLKENA_LSB (1U << 20) /* 1b */
+#define DPMAIF_INFRA_REQ_LSB (1U << 21) /* 1b */
+#define DPMAIF_APSRC_REQ_LSB (1U << 22) /* 1b */
+#define DPMAIF_VRF18_REQ_LSB (1U << 23) /* 1b */
+#define DPMAIF_DDREN_REQ_LSB (1U << 24) /* 1b */
+#define AFE_SRCCLKENA_LSB (1U << 25) /* 1b */
+#define AFE_INFRA_REQ_LSB (1U << 26) /* 1b */
+#define AFE_APSRC_REQ_LSB (1U << 27) /* 1b */
+#define AFE_VRF18_REQ_LSB (1U << 28) /* 1b */
+#define AFE_DDREN_REQ_LSB (1U << 29) /* 1b */
+
+/* MD32PCM_WAKEUP_STA (0x10006000 + 0x130) */
+#define MD32PCM_WAKEUP_STA_LSB (1U << 0) /* 32b */
+
+/* MD32PCM_EVENT_STA (0x10006000 + 0x134) */
+#define MD32PCM_EVENT_STA_LSB (1U << 0) /* 32b */
+
+/* SPM_WAKEUP_STA (0x10006000 + 0x138) */
+#define SPM_WAKEUP_EVENT_L_LSB (1U << 0) /* 32b */
+
+/* SPM_WAKEUP_EXT_STA (0x10006000 + 0x13C) */
+#define EXT_WAKEUP_EVENT_LSB (1U << 0) /* 32b */
+
+/* SPM_WAKEUP_MISC (0x10006000 + 0x140) */
+#define GIC_WAKEUP_LSB (1U << 0) /* 10b */
+#define DVFSRC_IRQ_LSB (1U << 16) /* 1b */
+#define SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB (1U << 17) /* 1b */
+#define PCM_TIMER_EVENT_LSB (1U << 18) /* 1b */
+#define PMIC_EINT_OUT_B_LSB (1U << 19) /* 2b */
+#define TWAM_IRQ_B_LSB (1U << 21) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_0_LSB (1U << 25) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_1_LSB (1U << 26) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_2_LSB (1U << 27) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_3_LSB (1U << 28) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_ALL_LSB (1U << 29) /* 1b */
+#define PMIC_IRQ_ACK_LSB (1U << 30) /* 1b */
+#define PMIC_SCP_IRQ_LSB (1U << 31) /* 1b */
+
+/* MM_DVFS_HALT (0x10006000 + 0x144) */
+#define MM_DVFS_HALT_LSB (1U << 0) /* 5b */
+
+/* BUS_PROTECT_RDY (0x10006000 + 0x150) */
+#define PROTECT_READY_LSB (1U << 0) /* 32b */
+
+/* BUS_PROTECT1_RDY (0x10006000 + 0x154) */
+#define PROTECT1_READY_LSB (1U << 0) /* 32b */
+
+/* BUS_PROTECT2_RDY (0x10006000 + 0x158) */
+#define PROTECT2_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT3_RDY (0x10006000 + 0x15C) */
+
+#define PROTECT3_READY_LSB (1U << 0) /* 32b */
+/* SUBSYS_IDLE_STA (0x10006000 + 0x160) */
+#define SUBSYS_IDLE_SIGNALS_LSB (1U << 0) /* 32b */
+/* PCM_STA (0x10006000 + 0x164) */
+
+#define PCM_CK_SEL_O_LSB (1U << 0) /* 4b */
+#define EXT_SRC_STA_LSB (1U << 4) /* 3b */
+
+/* SRC_REQ_STA_3 (0x10006000 + 0x168) */
+#define CCIF_EVENT_STATE_LSB (1U << 0) /* 1b */
+#define F26M_STATE_LSB (1U << 16) /* 1b */
+#define INFRA_STATE_LSB (1U << 17) /* 1b */
+#define APSRC_STATE_LSB (1U << 18) /* 1b */
+#define VRF18_STATE_LSB (1U << 19) /* 1b */
+#define DDREN_STATE_LSB (1U << 20) /* 1b */
+#define DVFS_STATE_LSB (1U << 21) /* 1b */
+#define SW_MAILBOX_STATE_LSB (1U << 22) /* 1b */
+#define SSPM_MAILBOX_STATE_LSB (1U << 23) /* 1b */
+#define ADSP_MAILBOX_STATE_LSB (1U << 24) /* 1b */
+#define SCP_MAILBOX_STATE_LSB (1U << 25) /* 1b */
+
+/* PWR_STATUS (0x10006000 + 0x16C) */
+#define PWR_STATUS_LSB (1U << 0) /* 32b */
+
+/* PWR_STATUS_2ND (0x10006000 + 0x170) */
+#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */
+
+/* CPU_PWR_STATUS (0x10006000 + 0x174) */
+#define MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 1) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 3) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 4) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 5) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 6) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 7) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 8) /* 1b */
+#define MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 9) /* 1b */
+
+/* OTHER_PWR_STATUSi (0x10006000 + 0x178) */
+#define OTHER_PWR_STATUS_LSB (1U << 0) /* 32b */
+
+/* SPM_VTCXO_EVENT_COUNT_STA (0x10006000 + 0x17C) */
+#define SPM_SRCCLKENA_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_SRCCLKENA_WAKE_COUNT_LSB (1U << 16) /* 16b */
+
+/* SPM_INFRA_EVENT_COUNT_STA (0x10006000 + 0x180) */
+#define SPM_INFRA_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_INFRA_WAKE_COUNT_LSB (1U << 16) /* 16b */
+
+/* SPM_VRF18_EVENT_COUNT_STA (0x10006000 + 0x184) */
+#define SPM_VRF18_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_VRF18_WAKE_COUNT_LSB (1U << 16) /* 16b */
+
+/* SPM_APSRC_EVENT_COUNT_STA (0x10006000 + 0x188) */
+#define SPM_APSRC_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_APSRC_WAKE_COUNT_LSB (1U << 16) /* 16b */
+
+/* SPM_DDREN_EVENT_COUNT_STA (0x10006000 + 0x18C) */
+#define SPM_DDREN_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_DDREN_WAKE_COUNT_LSB (1U << 16) /* 16b */
+
+/* MD32PCM_STA (0x10006000 + 0x190) */
+#define MD32PCM_HALT_LSB (1U << 0) /* 1b */
+#define MD32PCM_GATED_LSB (1U << 1) /* 1b */
+
+/* MD32PCM_PC (0x10006000 + 0x194) */
+#define MON_PC_LSB (1U << 0) /* 32b */
+
+/* DVFSRC_EVENT_STA (0x10006000 + 0x1A4) */
+#define DVFSRC_EVENT_LSB (1U << 0) /* 32b */
+
+/* BUS_PROTECT4_RDY (0x10006000 + 0x1A8) */
+#define PROTECT4_READY_LSB (1U << 0) /* 32b */
+
+/* BUS_PROTECT5_RDY (0x10006000 + 0x1AC) */
+#define PROTECT5_READY_LSB (1U << 0) /* 32b */
+
+/* BUS_PROTECT6_RDY (0x10006000 + 0x1B0) */
+#define PROTECT6_READY_LSB (1U << 0) /* 32b */
+
+/* BUS_PROTECT7_RDY (0x10006000 + 0x1B4) */
+#define PROTECT7_READY_LSB (1U << 0) /* 32b */
+
+/* BUS_PROTECT8_RDY (0x10006000 + 0x1B8) */
+#define PROTECT8_READY_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_LAST_STA0 (0x10006000 + 0x1D0) */
+#define LAST_IDLE_CNT_0_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_LAST_STA1 (0x10006000 + 0x1D4) */
+#define LAST_IDLE_CNT_1_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_LAST_STA2 (0x10006000 + 0x1D8) */
+#define LAST_IDLE_CNT_2_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_LAST_STA3 (0x10006000 + 0x1DC) */
+#define LAST_IDLE_CNT_3_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_CURR_STA0 (0x10006000 + 0x1E0) */
+#define CURRENT_IDLE_CNT_0_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_CURR_STA1 (0x10006000 + 0x1E4) */
+#define CURRENT_IDLE_CNT_1_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_CURR_STA2 (0x10006000 + 0x1E8) */
+#define CURRENT_IDLE_CNT_2_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_CURR_STA3 (0x10006000 + 0x1EC) */
+#define CURRENT_IDLE_CNT_3_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_TIMER_OUT (0x10006000 + 0x1F0) */
+#define TWAM_TIMER_LSB (1U << 0) /* 32b */
+
+/* SPM_CG_CHECK_STA (0x10006000 + 0x1F4) */
+#define SPM_CG_CHECK_SLEEP_REQ_0_LSB (1U << 0) /* 1b */
+#define SPM_CG_CHECK_SLEEP_REQ_1_LSB (1U << 1) /* 1b */
+#define SPM_CG_CHECK_SLEEP_REQ_2_LSB (1U << 2) /* 1b */
+
+/* SPM_DVFS_STA (0x10006000 + 0x1F8) */
+#define TARGET_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_OPP_STA (0x10006000 + 0x1FC) */
+#define TARGET_DVFS_OPP_LSB (1U << 0) /* 5b */
+#define CURRENT_DVFS_OPP_LSB (1U << 5) /* 5b */
+#define RELAY_DVFS_OPP_LSB (1U << 10) /* 5b */
+
+/* SPM_MCUSYS_PWR_CON (0x10006000 + 0x200) */
+#define MCUSYS_SPMC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MCUSYS_SPMC_PWR_ON_LSB (1U << 2) /* 1b */
+#define MCUSYS_SPMC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MCUSYS_SPMC_RESETPWRON_CONFIG_LSB (1U << 5) /* 1b */
+#define MCUSYS_SPMC_DORMANT_EN_LSB (1U << 6) /* 1b */
+#define MCUSYS_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */
+#define SPM_MCUSYS_PWR_CON_MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 31) /* 1b */
+
+/* SPM_CPUTOP_PWR_CON (0x10006000 + 0x204) */
+#define MP0_SPMC_PWR_RST_B_CPUTOP_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPUTOP_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_PWR_CLK_DIS_CPUTOP_LSB (1U << 4) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPUTOP_LSB (1U << 5) /* 1b */
+#define MP0_SPMC_DORMANT_EN_CPUTOP_LSB (1U << 6) /* 1b */
+#define MP0_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */
+#define MP0_VSRAM_EXT_OFF_LSB (1U << 8) /* 1b */
+#define SPM_CPUTOP_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 31) /* 1b */
+/* SPM_CPU0_PWR_CON (0x10006000 + 0x208) */
+#define MP0_SPMC_PWR_RST_B_CPU0_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU0_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU0_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU0_LSB (1U << 7) /* 1b */
+#define SPM_CPU0_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 31) /* 1b */
+
+/* SPM_CPU1_PWR_CON (0x10006000 + 0x20C) */
+#define MP0_SPMC_PWR_RST_B_CPU1_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU1_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU1_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU1_LSB (1U << 7) /* 1b */
+#define SPM_CPU1_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 31) /* 1b */
+
+/* SPM_CPU2_PWR_CON (0x10006000 + 0x210) */
+#define MP0_SPMC_PWR_RST_B_CPU2_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU2_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU2_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU2_LSB (1U << 7) /* 1b */
+#define SPM_CPU2_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 31) /* 1b */
+
+/* SPM_CPU3_PWR_CON (0x10006000 + 0x214) */
+#define MP0_SPMC_PWR_RST_B_CPU3_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU3_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU3_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU3_LSB (1U << 7) /* 1b */
+#define SPM_CPU3_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 31) /* 1b */
+
+/* SPM_CPU4_PWR_CON (0x10006000 + 0x218) */
+#define MP0_SPMC_PWR_RST_B_CPU4_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU4_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU4_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU4_LSB (1U << 7) /* 1b */
+#define SPM_CPU4_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 31) /* 1b */
+
+/* SPM_CPU5_PWR_CON (0x10006000 + 0x21C) */
+#define MP0_SPMC_PWR_RST_B_CPU5_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU5_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU5_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU5_LSB (1U << 7) /* 1b */
+#define SPM_CPU5_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 31) /* 1b */
+
+/* SPM_CPU6_PWR_CON (0x10006000 + 0x220) */
+#define MP0_SPMC_PWR_RST_B_CPU6_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU6_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU6_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU6_LSB (1U << 7) /* 1b */
+#define SPM_CPU6_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 31) /* 1b */
+
+/* SPM_CPU7_PWR_CON (0x10006000 + 0x224) */
+#define MP0_SPMC_PWR_RST_B_CPU7_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU7_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU7_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU7_LSB (1U << 7) /* 1b */
+#define SPM_CPU7_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 31) /* 1b */
+
+/* ARMPLL_CLK_CON (0x10006000 + 0x22C) */
+#define SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 6b */
+#define SC_ARM_CK_OFF_LSB (1U << 6) /* 6b */
+#define SC_ARMPLL_OFF_LSB (1U << 12) /* 1b */
+#define SC_ARMBPLL_OFF_LSB (1U << 13) /* 1b */
+#define SC_ARMBPLL1_OFF_LSB (1U << 14) /* 1b */
+#define SC_ARMBPLL2_OFF_LSB (1U << 15) /* 1b */
+#define SC_ARMBPLL3_OFF_LSB (1U << 16) /* 1b */
+#define SC_CCIPLL_CKOFF_LSB (1U << 17) /* 1b */
+#define SC_ARMDDS_OFF_LSB (1U << 18) /* 1b */
+#define SC_ARMBPLL_S_OFF_LSB (1U << 19) /* 1b */
+#define SC_ARMBPLL1_S_OFF_LSB (1U << 20) /* 1b */
+#define SC_ARMBPLL2_S_OFF_LSB (1U << 21) /* 1b */
+#define SC_ARMBPLL3_S_OFF_LSB (1U << 22) /* 1b */
+#define SC_CCIPLL_PWROFF_LSB (1U << 23) /* 1b */
+#define SC_ARMPLLOUT_OFF_LSB (1U << 24) /* 1b */
+#define SC_ARMBPLLOUT_OFF_LSB (1U << 25) /* 1b */
+#define SC_ARMBPLLOUT1_OFF_LSB (1U << 26) /* 1b */
+#define SC_ARMBPLLOUT2_OFF_LSB (1U << 27) /* 1b */
+#define SC_ARMBPLLOUT3_OFF_LSB (1U << 28) /* 1b */
+#define SC_CCIPLL_OUT_OFF_LSB (1U << 29) /* 1b */
+
+/* MCUSYS_IDLE_STA (0x10006000 + 0x230) */
+#define ARMBUS_IDLE_TO_26M_LSB (1U << 0) /* 1b */
+#define MP0_CLUSTER_IDLE_TO_PWR_OFF_LSB (1U << 1) /* 1b */
+#define MCUSYS_DDR_EN_0_LSB (1U << 2) /* 1b */
+#define MCUSYS_DDR_EN_1_LSB (1U << 3) /* 1b */
+#define MCUSYS_DDR_EN_2_LSB (1U << 4) /* 1b */
+#define MCUSYS_DDR_EN_3_LSB (1U << 5) /* 1b */
+#define MCUSYS_DDR_EN_4_LSB (1U << 6) /* 1b */
+#define MCUSYS_DDR_EN_5_LSB (1U << 7) /* 1b */
+#define MCUSYS_DDR_EN_6_LSB (1U << 8) /* 1b */
+#define MCUSYS_DDR_EN_7_LSB (1U << 9) /* 1b */
+#define MP0_CPU_IDLE_TO_PWR_OFF_LSB (1U << 16) /* 8b */
+#define WFI_AF_SEL_LSB (1U << 24) /* 8b */
+
+/* GIC_WAKEUP_STA (0x10006000 + 0x234) */
+#define GIC_WAKEUP_STA_GIC_WAKEUP_LSB (1U << 10) /* 10b */
+
+/* CPU_SPARE_CON (0x10006000 + 0x238) */
+#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */
+
+/* CPU_SPARE_CON_SET (0x10006000 + 0x23C) */
+#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+
+/* CPU_SPARE_CON_CLR (0x10006000 + 0x240) */
+#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+
+/* ARMPLL_CLK_SEL (0x10006000 + 0x244) */
+#define ARMPLL_CLK_SEL_LSB (1U << 0) /* 15b */
+
+/* EXT_INT_WAKEUP_REQ (0x10006000 + 0x248) */
+#define EXT_INT_WAKEUP_REQ_LSB (1U << 0) /* 10b */
+
+/* EXT_INT_WAKEUP_REQ_SET (0x10006000 + 0x24C) */
+#define EXT_INT_WAKEUP_REQ_SET_LSB (1U << 0) /* 10b */
+
+/* EXT_INT_WAKEUP_REQ_CLR (0x10006000 + 0x250) */
+#define EXT_INT_WAKEUP_REQ_CLR_LSB (1U << 0) /* 10b */
+
+/* CPU_IRQ_MASK (0x10006000 + 0x260) */
+#define CPU_IRQ_MASK_LSB (1U << 0) /* 8b */
+
+/* CPU_IRQ_MASK_SET (0x10006000 + 0x264) */
+#define CPU_IRQ_MASK_SET_LSB (1U << 0) /* 8b */
+
+/* CPU_IRQ_MASK_CLR (0x10006000 + 0x268) */
+#define CPU_IRQ_MASK_CLR_LSB (1U << 0) /* 8b */
+
+/* CPU_WFI_EN (0x10006000 + 0x280) */
+#define CPU_WFI_EN_LSB (1U << 0) /* 8b */
+
+/* CPU_WFI_EN_SET (0x10006000 + 0x284) */
+#define CPU_WFI_EN_SET_LSB (1U << 0) /* 8b */
+
+/* CPU_WFI_EN_CLR (0x10006000 + 0x288) */
+#define CPU_WFI_EN_CLR_LSB (1U << 0) /* 8b */
+
+/* ROOT_CPUTOP_ADDR (0x10006000 + 0x2A0) */
+#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */
+
+/* ROOT_CORE_ADDR (0x10006000 + 0x2A4) */
+#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */
+
+/* SPM2SW_MAILBOX_0 (0x10006000 + 0x2D0) */
+#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */
+
+/* SPM2SW_MAILBOX_1 (0x10006000 + 0x2D4) */
+#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */
+
+/* SPM2SW_MAILBOX_2 (0x10006000 + 0x2D8) */
+#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */
+
+/* SPM2SW_MAILBOX_3 (0x10006000 + 0x2DC) */
+#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */
+
+/* SW2SPM_WAKEUP (0x10006000 + 0x2E0) */
+#define SW2SPM_WAKEUP_SW2SPM_WAKEUP_LSB (1U << 0) /* 4b */
+
+/* SW2SPM_WAKEUP_SET (0x10006000 + 0x2E4) */
+#define SW2SPM_WAKEUP_SET_LSB (1U << 0) /* 4b */
+
+/* SW2SPM_WAKEUP_CLR (0x10006000 + 0x2E8) */
+#define SW2SPM_WAKEUP_CLR_LSB (1U << 0) /* 4b */
+
+/* SW2SPM_MAILBOX_0 (0x10006000 + 0x2EC) */
+#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+
+/* SW2SPM_MAILBOX_1 (0x10006000 + 0x2F0) */
+#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+
+/* SW2SPM_MAILBOX_2 (0x10006000 + 0x2F4) */
+#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+
+/* SW2SPM_MAILBOX_3 (0x10006000 + 0x2F8) */
+#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+
+/* SW2SPM_CFG (0x10006000 + 0x2FC) */
+#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */
+
+/* MD1_PWR_CON (0x10006000 + 0x300) */
+#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MD1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MD1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* CONN_PWR_CON (0x10006000 + 0x304) */
+#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CONN_PWR_ON_LSB (1U << 2) /* 1b */
+#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+
+/* MFG0_PWR_CON (0x10006000 + 0x308) */
+#define MFG0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG0_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG0_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG0_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* MFG1_PWR_CON (0x10006000 + 0x30C) */
+#define MFG1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* MFG2_PWR_CON (0x10006000 + 0x310) */
+#define MFG2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG2_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* MFG3_PWR_CON (0x10006000 + 0x314) */
+#define MFG3_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG3_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG3_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG3_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG3_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG3_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* MFG4_PWR_CON (0x10006000 + 0x318) */
+#define MFG4_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG4_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG4_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG4_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG4_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG4_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG4_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* MFG5_PWR_CON (0x10006000 + 0x31C) */
+#define MFG5_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG5_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG5_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG5_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG5_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG5_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG5_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* MFG6_PWR_CON (0x10006000 + 0x320) */
+#define MFG6_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG6_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG6_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG6_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG6_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG6_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG6_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* IFR_PWR_CON (0x10006000 + 0x324) */
+#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IFR_PWR_ON_LSB (1U << 2) /* 1b */
+#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IFR_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* IFR_SUB_PWR_CON (0x10006000 + 0x328) */
+#define IFR_SUB_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IFR_SUB_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IFR_SUB_PWR_ON_LSB (1U << 2) /* 1b */
+#define IFR_SUB_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IFR_SUB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IFR_SUB_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IFR_SUB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* DPY_PWR_CON (0x10006000 + 0x32C) */
+#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DPY_PWR_ON_LSB (1U << 2) /* 1b */
+#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+
+/* DRAMC_MD32_PWR_CON (0x10006000 + 0x330) */
+#define DRAMC_MD32_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DRAMC_MD32_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DRAMC_MD32_PWR_ON_LSB (1U << 2) /* 1b */
+#define DRAMC_MD32_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DRAMC_MD32_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DRAMC_MD32_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DRAMC_MD32_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* ISP_PWR_CON (0x10006000 + 0x334) */
+#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ISP_PWR_ON_LSB (1U << 2) /* 1b */
+#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ISP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* ISP2_PWR_CON (0x10006000 + 0x338) */
+#define ISP2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ISP2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ISP2_PWR_ON_LSB (1U << 2) /* 1b */
+#define ISP2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ISP2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ISP2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_ISP2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* IPE_PWR_CON (0x10006000 + 0x33C) */
+#define IPE_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IPE_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IPE_PWR_ON_LSB (1U << 2) /* 1b */
+#define IPE_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IPE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IPE_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IPE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* VDE_PWR_CON (0x10006000 + 0x340) */
+#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VDE_PWR_ON_LSB (1U << 2) /* 1b */
+#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VDE_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* VDE2_PWR_CON (0x10006000 + 0x344) */
+#define VDE2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VDE2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VDE2_PWR_ON_LSB (1U << 2) /* 1b */
+#define VDE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VDE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VDE2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VDE2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* VEN_PWR_CON (0x10006000 + 0x348) */
+#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VEN_PWR_ON_LSB (1U << 2) /* 1b */
+#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VEN_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* VEN_CORE1_PWR_CON (0x10006000 + 0x34C) */
+#define VEN_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VEN_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VEN_CORE1_PWR_ON_LSB (1U << 2) /* 1b */
+#define VEN_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VEN_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VEN_CORE1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VEN_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* MDP_PWR_CON (0x10006000 + 0x350) */
+#define MDP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MDP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MDP_PWR_ON_LSB (1U << 2) /* 1b */
+#define MDP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MDP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MDP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MDP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* DIS_PWR_CON (0x10006000 + 0x354) */
+#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DIS_PWR_ON_LSB (1U << 2) /* 1b */
+#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DIS_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* AUDIO_PWR_CON (0x10006000 + 0x358) */
+#define AUDIO_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define AUDIO_PWR_ISO_LSB (1U << 1) /* 1b */
+#define AUDIO_PWR_ON_LSB (1U << 2) /* 1b */
+#define AUDIO_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define AUDIO_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define AUDIO_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_AUDIO_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* CAM_PWR_CON (0x10006000 + 0x35C) */
+#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* CAM_RAWA_PWR_CON (0x10006000 + 0x360) */
+#define CAM_RAWA_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWA_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWA_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWA_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWA_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* CAM_RAWB_PWR_CON (0x10006000 + 0x364) */
+#define CAM_RAWB_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWB_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWB_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWB_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWB_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* CAM_RAWC_PWR_CON (0x10006000 + 0x368) */
+#define CAM_RAWC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWC_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWC_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWC_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWC_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* SYSRAM_CON (0x10006000 + 0x36C) */
+#define SYSRAM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SYSRAM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SYSRAM_SRAM_SLEEP_B_LSB (1U << 4) /* 4b */
+#define SYSRAM_SRAM_PDN_LSB (1U << 16) /* 4b */
+
+/* SYSROM_CON (0x10006000 + 0x370) */
+#define SYSROM_SRAM_PDN_LSB (1U << 0) /* 8b */
+
+/* SSPM_SRAM_CON (0x10006000 + 0x374) */
+#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */
+
+/* SCP_SRAM_CON (0x10006000 + 0x378) */
+#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */
+
+/* DPY_SHU_SRAM_CON (0x10006000 + 0x37C) */
+#define DPY_SHU_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPY_SHU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPY_SHU_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */
+#define DPY_SHU_SRAM_PDN_LSB (1U << 16) /* 2b */
+
+/* UFS_SRAM_CON (0x10006000 + 0x380) */
+#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */
+#define UFS_SRAM_PDN_LSB (1U << 16) /* 8b */
+
+/* DEVAPC_IFR_SRAM_CON (0x10006000 + 0x384) */
+#define DEVAPC_IFR_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_IFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_IFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */
+#define DEVAPC_IFR_SRAM_PDN_LSB (1U << 16) /* 6b */
+
+/* DEVAPC_SUBIFR_SRAM_CON (0x10006000 + 0x388) */
+#define DEVAPC_SUBIFR_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_SUBIFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_SUBIFR_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */
+#define DEVAPC_SUBIFR_SRAM_PDN_LSB (1U << 16) /* 12b */
+
+/* DEVAPC_ACP_SRAM_CON (0x10006000 + 0x38C) */
+#define DEVAPC_ACP_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_ACP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_ACP_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */
+#define DEVAPC_ACP_SRAM_PDN_LSB (1U << 16) /* 12b */
+
+/* USB_SRAM_CON (0x10006000 + 0x390) */
+#define USB_SRAM_PDN_LSB (1U << 0) /* 9b */
+
+/* DUMMY_SRAM_CONi (0x10006000 + 0x394) */
+#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */
+#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 12b */
+
+/* MD_EXT_BUCK_ISO_CON (0x10006000 + 0x398) */
+#define VMODEM_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */
+#define VMD_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */
+
+/* EXT_BUCK_ISO (0x10006000 + 0x39C) */
+#define VIMVO_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */
+#define GPU_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */
+#define ADSP_EXT_BUCK_ISO_LSB (1U << 2) /* 1b */
+#define IPU_EXT_BUCK_ISO_LSB (1U << 5) /* 3b */
+
+/* DXCC_SRAM_CON (0x10006000 + 0x3A0) */
+#define DXCC_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DXCC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DXCC_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */
+#define DXCC_SRAM_PDN_LSB (1U << 16) /* 8b */
+
+/* MSDC_PWR_CON (0x10006000 + 0x3A4) */
+#define MSDC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MSDC_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MSDC_PWR_ON_LSB (1U << 2) /* 1b */
+#define MSDC_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MSDC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MSDC_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MSDC_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MSDC_SRAM_PDN_LSB (1U << 8) /* 5b */
+#define MSDC_SRAM_SLEEP_B_LSB (1U << 13) /* 5b */
+#define SC_MSDC_SRAM_PDN_ACK_LSB (1U << 18) /* 5b */
+#define SC_MSDC_SRAM_SLEEP_B_ACK_LSB (1U << 23) /* 5b */
+
+/* DEBUGTOP_SRAM_CON (0x10006000 + 0x3A8) */
+#define DEBUGTOP_SRAM_PDN_LSB (1U << 0) /* 1b */
+
+/* DP_TX_PWR_CON (0x10006000 + 0x3AC) */
+#define DP_TX_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DP_TX_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DP_TX_PWR_ON_LSB (1U << 2) /* 1b */
+#define DP_TX_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DP_TX_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DP_TX_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DP_TX_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* DPMAIF_SRAM_CON (0x10006000 + 0x3B0) */
+#define DPMAIF_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPMAIF_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPMAIF_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DPMAIF_SRAM_PDN_LSB (1U << 16) /* 1b */
+
+/* DPY_SHU2_SRAM_CON (0x10006000 + 0x3B4) */
+#define DPY_SHU2_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPY_SHU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPY_SHU2_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */
+#define DPY_SHU2_SRAM_PDN_LSB (1U << 16) /* 12b */
+
+/* DRAMC_MCU2_SRAM_CON (0x10006000 + 0x3B8) */
+#define DRAMC_MCU2_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DRAMC_MCU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DRAMC_MCU2_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */
+#define DRAMC_MCU2_SRAM_PDN_LSB (1U << 16) /* 12b */
+
+/* DRAMC_MCU_SRAM_CON (0x10006000 + 0x3BC) */
+#define DRAMC_MCU_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DRAMC_MCU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DRAMC_MCU_SRAM_SLEEP_B_LSB (1U << 4) /* 12b */
+#define DRAMC_MCU_SRAM_PDN_LSB (1U << 16) /* 12b */
+
+/* MCUPM_PWR_CON (0x10006000 + 0x3C0) */
+#define MCUPM_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MCUPM_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MCUPM_PWR_ON_LSB (1U << 2) /* 1b */
+#define MCUPM_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MCUPM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MCUPM_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MCUPM_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MCUPM_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MCUPM_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */
+#define SC_MCUPM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+#define SC_MCUPM_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */
+#define MCUPM_WFI_LSB (1U << 14) /* 1b */
+
+/* DPY2_PWR_CON (0x10006000 + 0x3C4) */
+#define DPY2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DPY2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DPY2_PWR_ON_LSB (1U << 2) /* 1b */
+#define DPY2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DPY2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DPY2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DPY2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* SPM_SRAM_CON (0x10006000 + 0x3C8) */
+#define SPM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define REG_SPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define REG_SPM_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */
+#define SPM_SRAM_PDN_LSB (1U << 16) /* 2b */
+
+/* PERI_PWR_CON (0x10006000 + 0x3D0) */
+#define PERI_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define PERI_PWR_ISO_LSB (1U << 1) /* 1b */
+#define PERI_PWR_ON_LSB (1U << 2) /* 1b */
+#define PERI_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define PERI_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define PERI_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_PERI_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* NNA0_PWR_CON (0x10006000 + 0x3D4) */
+#define NNA0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define NNA0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define NNA0_PWR_ON_LSB (1U << 2) /* 1b */
+#define NNA0_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define NNA0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define NNA0_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_NNA0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* NNA1_PWR_CON (0x10006000 + 0x3D8) */
+#define NNA1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define NNA1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define NNA1_PWR_ON_LSB (1U << 2) /* 1b */
+#define NNA1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define NNA1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define NNA1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_NNA1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* NNA2_PWR_CON (0x10006000 + 0x3DC) */
+#define NNA2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define NNA2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define NNA2_PWR_ON_LSB (1U << 2) /* 1b */
+#define NNA2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define NNA2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define NNA2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_NNA2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* NNA_PWR_CON (0x10006000 + 0x3E0) */
+#define NNA_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define NNA_PWR_ISO_LSB (1U << 1) /* 1b */
+#define NNA_PWR_ON_LSB (1U << 2) /* 1b */
+#define NNA_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define NNA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define NNA_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_NNA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+
+/* ADSP_PWR_CON (0x10006000 + 0x3E4) */
+#define ADSP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ADSP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ADSP_PWR_ON_LSB (1U << 2) /* 1b */
+#define ADSP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ADSP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ADSP_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define ADSP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define ADSP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define ADSP_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */
+#define SC_ADSP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+#define SC_ADSP_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */
+
+/* DPY_SRAM_CON (0x10006000 + 0x3E8) */
+#define DPY_SRAM_PDN_LSB (1U << 16) /* 4b */
+#define SC_DPY_SRAM_PDN_ACK_LSB (1U << 24) /* 4b */
+
+/* SPM_MEM_CK_SEL (0x10006000 + 0x400) */
+#define SC_MEM_CK_SEL_LSB (1U << 0) /* 1b */
+#define SPM2CKSYS_MEM_CK_MUX_UPDATE_LSB (1U << 1) /* 1b */
+
+/* SPM_BUS_PROTECT_MASK_B (0x10006000 + 0X404) */
+#define SPM_BUS_PROTECT_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_BUS_PROTECT1_MASK_B (0x10006000 + 0x408) */
+#define SPM_BUS_PROTECT1_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_BUS_PROTECT2_MASK_B (0x10006000 + 0x40C) */
+#define SPM_BUS_PROTECT2_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_BUS_PROTECT3_MASK_B (0x10006000 + 0x410) */
+#define SPM_BUS_PROTECT3_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_BUS_PROTECT4_MASK_B (0x10006000 + 0x414) */
+#define SPM_BUS_PROTECT4_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_EMI_BW_MODE (0x10006000 + 0x418) */
+#define EMI_BW_MODE_LSB (1U << 0) /* 1b */
+#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */
+#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */
+#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */
+#define SPM_S1_MODE_CH_LSB (1U << 16) /* 2b */
+
+/* AP2MD_PEER_WAKEUP (0x10006000 + 0x41C) */
+#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */
+
+/* ULPOSC_CON (0x10006000 + 0x420) */
+#define ULPOSC_EN_LSB (1U << 0) /* 1b */
+#define ULPOSC_RST_LSB (1U << 1) /* 1b */
+#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */
+#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */
+
+/* SPM2MM_CON (0x10006000 + 0x424) */
+#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */
+#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */
+#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */
+#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */
+#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */
+#define MM2SPM_FORCE_ULTRA_ACK_D2T_LSB (1U << 16) /* 1b */
+#define MM2SPM_DBL_OSTD_ACT_ACK_D2T_LSB (1U << 17) /* 1b */
+#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */
+#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */
+#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */
+
+/* SPM_BUS_PROTECT5_MASK_B (0x10006000 + 0x428) */
+#define SPM_BUS_PROTECT5_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM2MCUPM_CON (0x10006000 + 0x42C) */
+#define SPM2MCUPM_SW_RST_B_LSB (1U << 0) /* 1b */
+#define SPM2MCUPM_SW_INT_LSB (1U << 1) /* 1b */
+
+/* AP_MDSRC_REQ (0x10006000 + 0x430) */
+#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */
+#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */
+#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */
+#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */
+#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */
+#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */
+
+/* SPM2EMI_ENTER_ULPM (0x10006000 + 0x434) */
+#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */
+
+/* SPM2MD_DVFS_CON (0x10006000 + 0x438) */
+#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */
+
+/* MD2SPM_DVFS_CON (0x10006000 + 0x43C) */
+#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */
+
+/* SPM_BUS_PROTECT6_MASK_B (0x10006000 + 0X440) */
+#define SPM_BUS_PROTECT6_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_BUS_PROTECT7_MASK_B (0x10006000 + 0x444) */
+#define SPM_BUS_PROTECT7_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_BUS_PROTECT8_MASK_B (0x10006000 + 0x448) */
+#define SPM_BUS_PROTECT8_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_PLL_CON (0x10006000 + 0x44C) */
+#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */
+#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */
+#define SC_SPAREPLLOUT_OFF_LSB (1U << 2) /* 2b */
+#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */
+#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */
+#define SC_SPAREPLL_OFF_LSB (1U << 6) /* 2b */
+#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */
+#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */
+#define SC_SPAREPLL_S_OFF_LSB (1U << 10) /* 2b */
+#define SC_SPARE_CK_OFF_LSB (1U << 12) /* 4b */
+#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */
+#define SC_MD32K_CK_OFF_LSB (1U << 17) /* 1b */
+#define SC_CKSQ1_OFF_LSB (1U << 18) /* 1b */
+#define SC_AXI_MEM_CK_OFF_LSB (1U << 19) /* 1b */
+#define SC_CLK_BACKUP_LSB (1U << 20) /* 12b */
+
+/* RC_SPM_CTRL (0x10006000 + 0x450) */
+#define SPM_AP_26M_RDY_LSB (1U << 0) /* 1b */
+#define SPM2RC_DMY_CTRL_LSB (1U << 2) /* 6b */
+#define RC2SPM_SRCCLKENO_0_ACK_LSB (1U << 16) /* 1b */
+
+/* SPM_DRAM_MCU_SW_CON_0 (0x10006000 + 0x454) */
+#define SW_DDR_PST_REQ_LSB (1U << 0) /* 2b */
+#define SW_DDR_PST_ABORT_REQ_LSB (1U << 2) /* 2b */
+
+/* SPM_DRAM_MCU_SW_CON_1 (0x10006000 + 0x458) */
+#define SW_DDR_PST_CH0_LSB (1U << 0) /* 32b */
+
+/* SPM_DRAM_MCU_SW_CON_2 (0x10006000 + 0x45C) */
+#define SW_DDR_PST_CH1_LSB (1U << 0) /* 32b */
+
+/* SPM_DRAM_MCU_SW_CON_3 (0x10006000 + 0x460) */
+#define SW_DDR_RESERVED_CH0_LSB (1U << 0) /* 32b */
+
+/* SPM_DRAM_MCU_SW_CON_4 (0x10006000 + 0x464) */
+#define SW_DDR_RESERVED_CH1_LSB (1U << 0) /* 32b */
+
+/* SPM_DRAM_MCU_STA_0 (0x10006000 + 0x468) */
+#define SC_DDR_PST_ACK_LSB (1U << 0) /* 2b */
+#define SC_DDR_PST_ABORT_ACK_LSB (1U << 2) /* 2b */
+
+/* SPM_DRAM_MCU_STA_1 (0x10006000 + 0x46C) */
+#define SC_DDR_CUR_PST_STA_CH0_LSB (1U << 0) /* 32b */
+
+/* SPM_DRAM_MCU_STA_2 (0x10006000 + 0x470) */
+#define SC_DDR_CUR_PST_STA_CH1_LSB (1U << 0) /* 32b */
+
+/* SPM_DRAM_MCU_SW_SEL_0 (0x10006000 + 0x474) */
+#define SW_DDR_PST_REQ_SEL_LSB (1U << 0) /* 2b */
+#define SW_DDR_PST_SEL_LSB (1U << 2) /* 2b */
+#define SW_DDR_PST_ABORT_REQ_SEL_LSB (1U << 4) /* 2b */
+#define SW_DDR_RESERVED_SEL_LSB (1U << 6) /* 2b */
+#define SW_DDR_PST_ACK_SEL_LSB (1U << 8) /* 2b */
+#define SW_DDR_PST_ABORT_ACK_SEL_LSB (1U << 10) /* 2b */
+
+/* RELAY_DVFS_LEVEL (0x10006000 + 0x478) */
+#define RELAY_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+
+/* DRAMC_DPY_CLK_SW_CON_0 (0x10006000 + 0x480) */
+#define SW_PHYPLL_EN_LSB (1U << 0) /* 2b */
+#define SW_DPY_VREF_EN_LSB (1U << 2) /* 2b */
+#define SW_DPY_DLL_CK_EN_LSB (1U << 4) /* 2b */
+#define SW_DPY_DLL_EN_LSB (1U << 6) /* 2b */
+#define SW_DPY_2ND_DLL_EN_LSB (1U << 8) /* 2b */
+#define SW_MEM_CK_OFF_LSB (1U << 10) /* 2b */
+#define SW_DMSUS_OFF_LSB (1U << 12) /* 2b */
+#define SW_DPY_MODE_SW_LSB (1U << 14) /* 2b */
+#define SW_EMI_CLK_OFF_LSB (1U << 16) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_LSB (1U << 18) /* 2b */
+#define SW_DR_GATE_RETRY_EN_LSB (1U << 20) /* 2b */
+#define SW_DPHY_PRECAL_UP_LSB (1U << 24) /* 2b */
+#define SW_DPY_BCLK_ENABLE_LSB (1U << 26) /* 2b */
+#define SW_TX_TRACKING_DIS_LSB (1U << 28) /* 2b */
+#define SW_DPHY_RXDLY_TRACKING_EN_LSB (1U << 30) /* 2b */
+
+/* DRAMC_DPY_CLK_SW_CON_1 (0x10006000 + 0x484) */
+#define SW_SHU_RESTORE_LSB (1U << 0) /* 2b */
+#define SW_DMYRD_MOD_LSB (1U << 2) /* 2b */
+#define SW_DMYRD_INTV_LSB (1U << 4) /* 2b */
+#define SW_DMYRD_EN_LSB (1U << 6) /* 2b */
+#define SW_DRS_DIS_REQ_LSB (1U << 8) /* 2b */
+#define SW_DR_SRAM_LOAD_LSB (1U << 10) /* 2b */
+#define SW_DR_SRAM_RESTORE_LSB (1U << 12) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_LATCH_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACK_RETRY_EN_LSB (1U << 16) /* 2b */
+#define SW_DPY_MIDPI_EN_LSB (1U << 18) /* 2b */
+#define SW_DPY_PI_RESETB_EN_LSB (1U << 20) /* 2b */
+#define SW_DPY_MCK8X_EN_LSB (1U << 22) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_CH0_LSB (1U << 24) /* 4b */
+#define SW_DR_SHU_LEVEL_SRAM_CH1_LSB (1U << 28) /* 4b */
+
+/* DRAMC_DPY_CLK_SW_CON_2 (0x10006000 + 0x488) */
+#define SW_DR_SHU_LEVEL_LSB (1U << 0) /* 2b */
+#define SW_DR_SHU_EN_LSB (1U << 2) /* 1b */
+#define SW_DR_SHORT_QUEUE_LSB (1U << 3) /* 1b */
+#define SW_PHYPLL_MODE_SW_LSB (1U << 4) /* 1b */
+#define SW_PHYPLL2_MODE_SW_LSB (1U << 5) /* 1b */
+#define SW_PHYPLL_SHU_EN_LSB (1U << 6) /* 1b */
+#define SW_PHYPLL2_SHU_EN_LSB (1U << 7) /* 1b */
+#define SW_DR_RESERVED_0_LSB (1U << 24) /* 2b */
+#define SW_DR_RESERVED_1_LSB (1U << 26) /* 2b */
+#define SW_DR_RESERVED_2_LSB (1U << 28) /* 2b */
+#define SW_DR_RESERVED_3_LSB (1U << 30) /* 2b */
+
+/* DRAMC_DPY_CLK_SW_CON_3 (0x10006000 + 0x48C) */
+#define SC_DR_SHU_EN_ACK_LSB (1U << 0) /* 4b */
+#define SC_EMI_CLK_OFF_ACK_LSB (1U << 4) /* 4b */
+#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 8) /* 4b */
+#define SC_DRAMC_DFS_STA_LSB (1U << 12) /* 4b */
+#define SC_DRS_DIS_ACK_LSB (1U << 16) /* 4b */
+#define SC_DR_SRAM_LOAD_ACK_LSB (1U << 20) /* 4b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_LSB (1U << 24) /* 4b */
+#define SC_DR_SRAM_RESTORE_ACK_LSB (1U << 28) /* 4b */
+
+/* DRAMC_DPY_CLK_SW_SEL_0 (0x10006000 + 0x490) */
+#define SW_PHYPLL_EN_SEL_LSB (1U << 0) /* 2b */
+#define SW_DPY_VREF_EN_SEL_LSB (1U << 2) /* 2b */
+#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 4) /* 2b */
+#define SW_DPY_DLL_EN_SEL_LSB (1U << 6) /* 2b */
+#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 8) /* 2b */
+#define SW_MEM_CK_OFF_SEL_LSB (1U << 10) /* 2b */
+#define SW_DMSUS_OFF_SEL_LSB (1U << 12) /* 2b */
+#define SW_DPY_MODE_SW_SEL_LSB (1U << 14) /* 2b */
+#define SW_EMI_CLK_OFF_SEL_LSB (1U << 16) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 18) /* 2b */
+#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 20) /* 2b */
+#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 24) /* 2b */
+#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 26) /* 2b */
+#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 28) /* 2b */
+#define SW_DPHY_RXDLY_TRACKING_EN_SEL_LSB (1U << 30) /* 2b */
+
+/* DRAMC_DPY_CLK_SW_SEL_1 (0x10006000 + 0x494) */
+#define SW_SHU_RESTORE_SEL_LSB (1U << 0) /* 2b */
+#define SW_DMYRD_MOD_SEL_LSB (1U << 2) /* 2b */
+#define SW_DMYRD_INTV_SEL_LSB (1U << 4) /* 2b */
+#define SW_DMYRD_EN_SEL_LSB (1U << 6) /* 2b */
+#define SW_DRS_DIS_REQ_SEL_LSB (1U << 8) /* 2b */
+#define SW_DR_SRAM_LOAD_SEL_LSB (1U << 10) /* 2b */
+#define SW_DR_SRAM_RESTORE_SEL_LSB (1U << 12) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_LATCH_SEL_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACK_RETRY_EN_SEL_LSB (1U << 16) /* 2b */
+#define SW_DPY_MIDPI_EN_SEL_LSB (1U << 18) /* 2b */
+#define SW_DPY_PI_RESETB_EN_SEL_LSB (1U << 20) /* 2b */
+#define SW_DPY_MCK8X_EN_SEL_LSB (1U << 22) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_SEL_LSB (1U << 24) /* 2b */
+
+/* DRAMC_DPY_CLK_SW_SEL_2 (0x10006000 + 0x498) */
+#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 0) /* 1b */
+#define SW_DR_SHU_EN_SEL_LSB (1U << 2) /* 1b */
+#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 3) /* 1b */
+#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 4) /* 1b */
+#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 5) /* 1b */
+#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 6) /* 1b */
+#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 7) /* 1b */
+#define SW_DR_RESERVED_0_SEL_LSB (1U << 24) /* 2b */
+#define SW_DR_RESERVED_1_SEL_LSB (1U << 26) /* 2b */
+#define SW_DR_RESERVED_2_SEL_LSB (1U << 28) /* 2b */
+#define SW_DR_RESERVED_3_SEL_LSB (1U << 30) /* 2b */
+
+/* DRAMC_DPY_CLK_SW_SEL_3 (0x10006000 + 0x49C) */
+#define SC_DR_SHU_EN_ACK_SEL_LSB (1U << 0) /* 4b */
+#define SC_EMI_CLK_OFF_ACK_SEL_LSB (1U << 4) /* 4b */
+#define SC_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 8) /* 4b */
+#define SC_DRAMC_DFS_STA_SEL_LSB (1U << 12) /* 4b */
+#define SC_DRS_DIS_ACK_SEL_LSB (1U << 16) /* 4b */
+#define SC_DR_SRAM_LOAD_ACK_SEL_LSB (1U << 20) /* 4b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_SEL_LSB (1U << 24) /* 4b */
+#define SC_DR_SRAM_RESTORE_ACK_SEL_LSB (1U << 28) /* 4b */
+
+/* DRAMC_DPY_CLK_SPM_CON (0x10006000 + 0x4A0) */
+#define SC_DMYRD_EN_MOD_SEL_PCM_LSB (1U << 0) /* 1b */
+#define SC_DMYRD_INTV_SEL_PCM_LSB (1U << 1) /* 1b */
+#define SC_DMYRD_EN_PCM_LSB (1U << 2) /* 1b */
+#define SC_DRS_DIS_REQ_PCM_LSB (1U << 3) /* 1b */
+#define SC_DR_SHU_LEVEL_SRAM_PCM_LSB (1U << 4) /* 4b */
+#define SC_DR_GATE_RETRY_EN_PCM_LSB (1U << 8) /* 1b */
+#define SC_DR_SHORT_QUEUE_PCM_LSB (1U << 9) /* 1b */
+#define SC_DPY_MIDPI_EN_PCM_LSB (1U << 10) /* 1b */
+#define SC_DPY_PI_RESETB_EN_PCM_LSB (1U << 11) /* 1b */
+#define SC_DPY_MCK8X_EN_PCM_LSB (1U << 12) /* 1b */
+#define SC_DR_RESERVED_0_PCM_LSB (1U << 13) /* 1b */
+#define SC_DR_RESERVED_1_PCM_LSB (1U << 14) /* 1b */
+#define SC_DR_RESERVED_2_PCM_LSB (1U << 15) /* 1b */
+#define SC_DR_RESERVED_3_PCM_LSB (1U << 16) /* 1b */
+#define SC_DMDRAMCSHU_ACK_ALL_LSB (1U << 24) /* 1b */
+#define SC_EMI_CLK_OFF_ACK_ALL_LSB (1U << 25) /* 1b */
+#define SC_DR_SHORT_QUEUE_ACK_ALL_LSB (1U << 26) /* 1b */
+#define SC_DRAMC_DFS_STA_ALL_LSB (1U << 27) /* 1b */
+#define SC_DRS_DIS_ACK_ALL_LSB (1U << 28) /* 1b */
+#define SC_DR_SRAM_LOAD_ACK_ALL_LSB (1U << 29) /* 1b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_ALL_LSB (1U << 30) /* 1b */
+#define SC_DR_SRAM_RESTORE_ACK_ALL_LSB (1U << 31) /* 1b */
+
+/* SPM_DVFS_LEVEL (0x10006000 + 0x4A4) */
+#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+
+/* SPM_CIRQ_CON (0x10006000 + 0x4A8) */
+#define CIRQ_CLK_SEL_LSB (1U << 0) /* 1b */
+
+/* SPM_DVFS_MISC (0x10006000 + 0x4AC) */
+#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */
+#define SPM2EMI_SLP_PROT_EN_LSB (1U << 1) /* 1b */
+#define SPM_DVFS_FORCE_ENABLE_LSB (1U << 2) /* 1b */
+#define FORCE_DVFS_WAKE_LSB (1U << 3) /* 1b */
+#define SPM_DVFSRC_ENABLE_LSB (1U << 4) /* 1b */
+#define SPM_DVFS_DONE_LSB (1U << 5) /* 1b */
+#define DVFSRC_IRQ_WAKEUP_EVENT_MASK_LSB (1U << 6) /* 1b */
+#define SPM2RC_EVENT_ABORT_LSB (1U << 7) /* 1b */
+#define EMI_SLP_IDLE_LSB (1U << 14) /* 1b */
+#define SDIO_READY_TO_SPM_LSB (1U << 15) /* 1b */
+
+/* RG_MODULE_SW_CG_0_MASK_REQ_0 (0x10006000 + 0x4B4) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_0_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_0_MASK_REQ_1 (0x10006000 + 0x4B8) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_1_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_0_MASK_REQ_2 (0x10006000 + 0x4BC) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_2_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_1_MASK_REQ_0 (0x10006000 + 0x4C0) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_0_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_1_MASK_REQ_1 (0x10006000 + 0x4C4) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_1_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_1_MASK_REQ_2 (0x10006000 + 0x4C8) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_2_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_2_MASK_REQ_0 (0x10006000 + 0x4CC) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_0_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_2_MASK_REQ_1 (0x10006000 + 0x4D0) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_1_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_2_MASK_REQ_2 (0x10006000 + 0x4D4) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_2_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_3_MASK_REQ_0 (0x10006000 + 0x4D8) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_0_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_3_MASK_REQ_1 (0x10006000 + 0x4DC) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_1_LSB (1U << 0) /* 32b */
+
+/* RG_MODULE_SW_CG_3_MASK_REQ_2 (0x10006000 + 0x4E0) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_2_LSB (1U << 0) /* 32b */
+
+/* PWR_STATUS_MASK_REQ_0 (0x10006000 + 0x4E4) */
+#define PWR_STATUS_MASK_REQ_0_LSB (1U << 0) /* 32b */
+
+/* PWR_STATUS_MASK_REQ_1 (0x10006000 + 0x4E8) */
+#define PWR_STATUS_MASK_REQ_1_LSB (1U << 0) /* 32b */
+
+/* PWR_STATUS_MASK_REQ_2 (0x10006000 + 0x4EC) */
+#define PWR_STATUS_MASK_REQ_2_LSB (1U << 0) /* 32b */
+
+/* SPM_CG_CHECK_CON (0x10006000 + 0x4F0) */
+#define APMIXEDSYS_BUSY_MASK_REQ_0_LSB (1U << 0) /* 5b */
+#define APMIXEDSYS_BUSY_MASK_REQ_1_LSB (1U << 8) /* 5b */
+#define APMIXEDSYS_BUSY_MASK_REQ_2_LSB (1U << 16) /* 5b */
+#define AUDIOSYS_BUSY_MASK_REQ_0_LSB (1U << 24) /* 1b */
+#define AUDIOSYS_BUSY_MASK_REQ_1_LSB (1U << 25) /* 1b */
+#define AUDIOSYS_BUSY_MASK_REQ_2_LSB (1U << 26) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_0_LSB (1U << 27) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_1_LSB (1U << 28) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_2_LSB (1U << 29) /* 1b */
+
+/* SPM_SRC_RDY_STA (0x10006000 + 0x4F4) */
+#define SPM_INFRA_INTERNAL_ACK_LSB (1U << 0) /* 1b */
+#define SPM_VRF18_INTERNAL_ACK_LSB (1U << 1) /* 1b */
+
+/* SPM_DVS_DFS_LEVEL (0x10006000 + 0x4F8) */
+#define SPM_DFS_LEVEL_LSB (1U << 0) /* 16b */
+#define SPM_DVS_LEVEL_LSB (1U << 16) /* 16b */
+
+/* SPM_FORCE_DVFS (0x10006000 + 0x4FC) */
+#define FORCE_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_FLAG_0 (0x10006000 + 0x600) */
+#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_DEBUG_0 (0x10006000 + 0x604) */
+#define SPM_SW_DEBUG_0_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_FLAG_1 (0x10006000 + 0x608) */
+#define SPM_SW_FLAG_1_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_DEBUG_1 (0x10006000 + 0x60C) */
+#define SPM_SW_DEBUG_1_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_0 (0x10006000 + 0x610) */
+#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_1 (0x10006000 + 0x614) */
+#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_2 (0x10006000 + 0x618) */
+#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_3 (0x10006000 + 0x61C) */
+#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_4 (0x10006000 + 0x620) */
+#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_5 (0x10006000 + 0x624) */
+#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_6 (0x10006000 + 0x628) */
+#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_7 (0x10006000 + 0x62C) */
+#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */
+
+/* SPM_SW_RSV_8 (0x10006000 + 0x630) */
+#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */
+
+/* SPM_BK_WAKE_EVENT (0x10006000 + 0x634) */
+#define SPM_BK_WAKE_EVENT_LSB (1U << 0) /* 32b */
+
+/* SPM_BK_VTCXO_DUR (0x10006000 + 0x638) */
+#define SPM_BK_VTCXO_DUR_LSB (1U << 0) /* 32b */
+
+/* SPM_BK_WAKE_MISC (0x10006000 + 0x63C) */
+#define SPM_BK_WAKE_MISC_LSB (1U << 0) /* 32b */
+
+/* SPM_BK_PCM_TIMER (0x10006000 + 0x640) */
+#define SPM_BK_PCM_TIMER_LSB (1U << 0) /* 32b */
+
+/* SPM_RSV_CON_0 (0x10006000 + 0x650) */
+#define SPM_RSV_CON_0_LSB (1U << 0) /* 32b */
+
+/* SPM_RSV_CON_1 (0x10006000 + 0x654) */
+#define SPM_RSV_CON_1_LSB (1U << 0) /* 32b */
+
+/* SPM_RSV_STA_0 (0x10006000 + 0x658) */
+#define SPM_RSV_STA_0_LSB (1U << 0) /* 32b */
+
+/* SPM_RSV_STA_1 (0x10006000 + 0x65C) */
+#define SPM_RSV_STA_1_LSB (1U << 0) /* 32b */
+
+/* SPM_SPARE_CON (0x10006000 + 0x660) */
+#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */
+
+/* SPM_SPARE_CON_SET (0x10006000 + 0x664) */
+#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+
+/* SPM_SPARE_CON_CLR (0x10006000 + 0x668) */
+#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+
+/* SPM_CROSS_WAKE_M00_REQ (0x10006000 + 0x66C) */
+#define SPM_CROSS_WAKE_M00_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M00_CHK_LSB (1U << 4) /* 4b */
+
+/* SPM_CROSS_WAKE_M01_REQ (0x10006000 + 0x670) */
+#define SPM_CROSS_WAKE_M01_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M01_CHK_LSB (1U << 4) /* 4b */
+
+/* SPM_CROSS_WAKE_M02_REQ (0x10006000 + 0x674) */
+#define SPM_CROSS_WAKE_M02_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M02_CHK_LSB (1U << 4) /* 4b */
+
+/* SPM_CROSS_WAKE_M03_REQ (0x10006000 + 0x678) */
+#define SPM_CROSS_WAKE_M03_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M03_CHK_LSB (1U << 4) /* 4b */
+
+/* SCP_VCORE_LEVEL (0x10006000 + 0x67C) */
+#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 16b */
+
+/* SC_MM_CK_SEL_CON (0x10006000 + 0x680) */
+#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */
+#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */
+
+/* SPARE_ACK_MASK (0x10006000 + 0x684) */
+#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */
+
+/* SPM_SPARE_FUNCTION (0x10006000 + 0x688) */
+#define SPM_SPARE_FUNCTION_LSB (1U << 0) /* 32b */
+
+/* SPM_DV_CON_0 (0x10006000 + 0x68C) */
+#define SPM_DV_CON_0_LSB (1U << 0) /* 32b */
+
+/* SPM_DV_CON_1 (0x10006000 + 0x690) */
+#define SPM_DV_CON_1_LSB (1U << 0) /* 32b */
+
+/* SPM_DV_STA (0x10006000 + 0x694) */
+#define SPM_DV_STA_LSB (1U << 0) /* 32b */
+
+/* CONN_XOWCN_DEBUG_EN (0x10006000 + 0x698) */
+#define CONN_XOWCN_DEBUG_EN_LSB (1U << 0) /* 1b */
+
+/* SPM_SEMA_M0 (0x10006000 + 0x69C) */
+#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */
+
+/* SPM_SEMA_M1 (0x10006000 + 0x6A0) */
+#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */
+
+/* SPM_SEMA_M2 (0x10006000 + 0x6A4) */
+#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */
+
+/* SPM_SEMA_M3 (0x10006000 + 0x6A8) */
+#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */
+
+/* SPM_SEMA_M4 (0x10006000 + 0x6AC) */
+#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */
+
+/* SPM_SEMA_M5 (0x10006000 + 0x6B0) */
+#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */
+
+/* SPM_SEMA_M6 (0x10006000 + 0x6B4) */
+#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */
+
+/* SPM_SEMA_M7 (0x10006000 + 0x6B8) */
+#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */
+
+/* SPM2ADSP_MAILBOXi (0x10006000 + 0x6BC) */
+#define SPM2ADSP_MAILBOX_LSB (1U << 0) /* 32b */
+
+/* ADSP2SPM_MAILBOX (0x10006000 + 0x6C0) */
+#define ADSP2SPM_MAILBOX_LSB (1U << 0) /* 32b */
+
+/* SPM_ADSP_IRQ (0x10006000 + 0x6C4) */
+#define SC_SPM2ADSP_WAKEUP_LSB (1U << 0) /* 1b */
+#define SPM_ADSP_IRQ_SC_ADSP2SPM_WAKEUP_LSB (1U << 4) /* 1b */
+
+/* SPM_MD32_IRQ (0x10006000 + 0x6C8) */
+#define SC_SPM2SSPM_WAKEUP_LSB (1U << 0) /* 4b */
+#define SPM_MD32_IRQ_SC_SSPM2SPM_WAKEUP_LSB (1U << 4) /* 4b */
+
+/* SPM2PMCU_MAILBOX_0 (0x10006000 + 0x6CC) */
+#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */
+
+/* SPM2PMCU_MAILBOX_1 (0x10006000 + 0x6D0) */
+#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */
+
+/* SPM2PMCU_MAILBOX_2 (0x10006000 + 0x6D4) */
+#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */
+
+/* SPM2PMCU_MAILBOX_3 (0x10006000 + 0x6D8) */
+#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */
+
+/* PMCU2SPM_MAILBOX_0 (0x10006000 + 0x6DC) */
+#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+
+/* PMCU2SPM_MAILBOX_1 (0x10006000 + 0x6E0) */
+#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+
+/* PMCU2SPM_MAILBOX_2 (0x10006000 + 0x6E4) */
+#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+
+/* PMCU2SPM_MAILBOX_3 (0x10006000 + 0x6E8) */
+#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+
+/* UFS_PSRI_SW (0x10006000 + 0x6EC) */
+#define UFS_PSRI_SW_LSB (1U << 0) /* 1b */
+
+/* UFS_PSRI_SW_SET (0x10006000 + 0x6F0) */
+#define UFS_PSRI_SW_SET_LSB (1U << 0) /* 1b */
+
+/* UFS_PSRI_SW_CLR (0x10006000 + 0x6F4) */
+#define UFS_PSRI_SW_CLR_LSB (1U << 0) /* 1b */
+
+/* SPM_AP_SEMA (0x10006000 + 0x6F8) */
+#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */
+
+/* SPM_SPM_SEMA (0x10006000 + 0x6FC) */
+#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */
+
+/* SPM_DVFS_CON (0x10006000 + 0x700) */
+#define SPM_DVFS_CON_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CON_STA (0x10006000 + 0x704) */
+#define SPM_DVFS_CON_STA_LSB (1U << 0) /* 32b */
+
+/* SPM_PMIC_SPMI_CON (0x10006000 + 0x708) */
+#define SPM_PMIC_SPMI_CMD_LSB (1U << 0) /* 2b */
+#define SPM_PMIC_SPMI_SLAVEID_LSB (1U << 2) /* 4b */
+#define SPM_PMIC_SPMI_PMIFID_LSB (1U << 6) /* 1b */
+#define SPM_PMIC_SPMI_DBCNT_LSB (1U << 7) /* 1b */
+
+/* SPM_DVFS_CMD0 (0x10006000 + 0x710) */
+#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD1 (0x10006000 + 0x714) */
+#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD2 (0x10006000 + 0x718) */
+#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD3 (0x10006000 + 0x71C) */
+#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD4 (0x10006000 + 0x720) */
+#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD5 (0x10006000 + 0x724) */
+#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD6 (0x10006000 + 0x728) */
+#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD7 (0x10006000 + 0x72C) */
+#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD8 (0x10006000 + 0x730) */
+#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD9 (0x10006000 + 0x734) */
+#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD10 (0x10006000 + 0x738) */
+#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD11 (0x10006000 + 0x73C) */
+#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD12 (0x10006000 + 0x740) */
+#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD13 (0x10006000 + 0x744) */
+#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD14 (0x10006000 + 0x748) */
+#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD15 (0x10006000 + 0x74C) */
+#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD16i (0x10006000 + 0x750) */
+#define SPM_DVFS_CMD16_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD17 (0x10006000 + 0x754) */
+#define SPM_DVFS_CMD17_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD18 (0x10006000 + 0x758) */
+#define SPM_DVFS_CMD18_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD19 (0x10006000 + 0x75C) */
+#define SPM_DVFS_CMD19_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD20 (0x10006000 + 0x760) */
+#define SPM_DVFS_CMD20_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD21 (0x10006000 + 0x764) */
+#define SPM_DVFS_CMD21_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD22 (0x10006000 + 0x768) */
+#define SPM_DVFS_CMD22_LSB (1U << 0) /* 32b */
+
+/* SPM_DVFS_CMD23 (0x10006000 + 0x76C) */
+#define SPM_DVFS_CMD23_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_VALUE_L (0x10006000 + 0x770) */
+#define SYS_TIMER_VALUE_L_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_VALUE_H (0x10006000 + 0x774) */
+#define SYS_TIMER_VALUE_H_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_START_L (0x10006000 + 0x778) */
+#define SYS_TIMER_START_L_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_START_H (0x10006000 + 0x77C) */
+#define SYS_TIMER_START_H_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_00 (0x10006000 + 0x780) */
+#define SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_00 (0x10006000 + 0x784) */
+#define SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_01 (0x10006000 + 0x788) */
+#define SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_01 (0x10006000 + 0x78C) */
+#define SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_02 (0x10006000 + 0x790) */
+#define SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_02 (0x10006000 + 0x794) */
+#define SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_03 (0x10006000 + 0x798) */
+#define SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_03 (0x10006000 + 0x79C) */
+#define SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_04 (0x10006000 + 0x7A0) */
+#define SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_04 (0x10006000 + 0x7A4) */
+#define SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_05 (0x10006000 + 0x7A8) */
+#define SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_05 (0x10006000 + 0x7AC) */
+#define SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_06 (0x10006000 + 0x7B0) */
+#define SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_06 (0x10006000 + 0x7B4) */
+#define SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_07 (0x10006000 + 0x7B8) */
+#define SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_07 (0x10006000 + 0x7BC) */
+#define SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_08 (0x10006000 + 0x7C0) */
+#define SYS_TIMER_LATCH_L_08_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_08 (0x10006000 + 0x7C4) */
+#define SYS_TIMER_LATCH_H_08_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_09 (0x10006000 + 0x7C8) */
+#define SYS_TIMER_LATCH_L_09_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_09 (0x10006000 + 0x7CC) */
+#define SYS_TIMER_LATCH_H_09_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_10 (0x10006000 + 0x7D0) */
+#define SYS_TIMER_LATCH_L_10_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_10 (0x10006000 + 0x7D4) */
+#define SYS_TIMER_LATCH_H_10_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_11 (0x10006000 + 0x7D8) */
+#define SYS_TIMER_LATCH_L_11_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_11 (0x10006000 + 0x7DC) */
+#define SYS_TIMER_LATCH_H_11_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_12 (0x10006000 + 0x7E0) */
+#define SYS_TIMER_LATCH_L_12_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_12 (0x10006000 + 0x7E4) */
+#define SYS_TIMER_LATCH_H_12_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_13 (0x10006000 + 0x7E8) */
+#define SYS_TIMER_LATCH_L_13_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_13 (0x10006000 + 0x7EC) */
+#define SYS_TIMER_LATCH_H_13_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_14 (0x10006000 + 0x7F0) */
+#define SYS_TIMER_LATCH_L_14_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_14 (0x10006000 + 0x7F4) */
+#define SYS_TIMER_LATCH_H_14_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_L_15 (0x10006000 + 0x7F8) */
+#define SYS_TIMER_LATCH_L_15_LSB (1U << 0) /* 32b */
+
+/* SYS_TIMER_LATCH_H_15 (0x10006000 + 0x7FC) */
+#define SYS_TIMER_LATCH_H_15_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_0 (0x10006000 + 0x800) */
+#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_1 (0x10006000 + 0x804) */
+#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_2 (0x10006000 + 0x808) */
+#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_3 (0x10006000 + 0x80C) */
+#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_4 (0x10006000 + 0x810) */
+#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_5 (0x10006000 + 0x814) */
+#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_6 (0x10006000 + 0x818) */
+#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_7 (0x10006000 + 0x81C) */
+#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_8 (0x10006000 + 0x820) */
+#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_9 (0x10006000 + 0x824) */
+#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_10 (0x10006000 + 0x828) */
+#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_11 (0x10006000 + 0x82C) */
+#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_12 (0x10006000 + 0x830) */
+#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_13 (0x10006000 + 0x834) */
+#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_14 (0x10006000 + 0x838) */
+#define PCM_WDT_LATCH_14_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_15 (0x10006000 + 0x83C) */
+#define PCM_WDT_LATCH_15_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_16 (0x10006000 + 0x840) */
+#define PCM_WDT_LATCH_16_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_17 (0x10006000 + 0x844) */
+#define PCM_WDT_LATCH_17_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_18 (0x10006000 + 0x848) */
+#define PCM_WDT_LATCH_18_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_SPARE_0 (0x10006000 + 0x84C) */
+#define PCM_WDT_LATCH_SPARE_0_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_SPARE_1 (0x10006000 + 0x850) */
+#define PCM_WDT_LATCH_SPARE_1_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_SPARE_2 (0x10006000 + 0x854) */
+#define PCM_WDT_LATCH_SPARE_2_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_CONN_0 (0x10006000 + 0x870) */
+#define PCM_WDT_LATCH_CONN_0_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_CONN_1 (0x10006000 + 0x874) */
+#define PCM_WDT_LATCH_CONN_1_LSB (1U << 0) /* 32b */
+
+/* PCM_WDT_LATCH_CONN_2 (0x10006000 + 0x878) */
+#define PCM_WDT_LATCH_CONN_2_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_CH0_0 (0x10006000 + 0x8A0) */
+#define DRAMC_GATING_ERR_LATCH_CH0_0_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_CH0_1 (0x10006000 + 0x8A4) */
+#define DRAMC_GATING_ERR_LATCH_CH0_1_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_CH0_2 (0x10006000 + 0x8A8) */
+#define DRAMC_GATING_ERR_LATCH_CH0_2_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_CH0_3 (0x10006000 + 0x8AC) */
+#define DRAMC_GATING_ERR_LATCH_CH0_3_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_CH0_4 (0x10006000 + 0x8B0) */
+#define DRAMC_GATING_ERR_LATCH_CH0_4_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_CH0_5 (0x10006000 + 0x8B4) */
+#define DRAMC_GATING_ERR_LATCH_CH0_5_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_CH0_6 (0x10006000 + 0x8B8) */
+#define DRAMC_GATING_ERR_LATCH_CH0_6_LSB (1U << 0) /* 32b */
+
+/* DRAMC_GATING_ERR_LATCH_SPARE_0 (0x10006000 + 0x8F4) */
+#define DRAMC_GATING_ERR_LATCH_SPARE_0_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_CON_0 (0x10006000 + 0x900) */
+#define SPM_ACK_CHK_SW_EN_0_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_0_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_0_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_0_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_0_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_0_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_0_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_0_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_0_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_0_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_0_LSB (1U << 15) /* 1b */
+
+/* SPM_ACK_CHK_PC_0 (0x10006000 + 0x904) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_0_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_0_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_SEL_0 (0x10006000 + 0x908) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_0_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_0_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_0_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_0_LSB (1U << 21) /* 3b */
+
+/* SPM_ACK_CHK_TIMER_0 (0x10006000 + 0x90C) */
+#define SPM_ACK_CHK_TIMER_VAL_0_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_0_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_STA_0 (0x10006000 + 0x910) */
+#define SPM_ACK_CHK_STA_0_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_SWINT_0 (0x10006000 + 0x914) */
+#define SPM_ACK_CHK_SWINT_EN_0_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_CON_1 (0x10006000 + 0x918) */
+#define SPM_ACK_CHK_SW_EN_1_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_1_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_1_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_1_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_1_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_1_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_1_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_1_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_1_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_1_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_1_LSB (1U << 15) /* 1b */
+
+/* SPM_ACK_CHK_PC_1 (0x10006000 + 0x91C) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_1_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_1_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_SEL_1 (0x10006000 + 0x920) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_1_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_1_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_1_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_1_LSB (1U << 21) /* 3b */
+
+/* SPM_ACK_CHK_TIMER_1 (0x10006000 + 0x924) */
+#define SPM_ACK_CHK_TIMER_VAL_1_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_1_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_STA_1 (0x10006000 + 0x928) */
+#define SPM_ACK_CHK_STA_1_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_SWINT_1 (0x10006000 + 0x92C) */
+#define SPM_ACK_CHK_SWINT_EN_1_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_CON_2 (0x10006000 + 0x930) */
+#define SPM_ACK_CHK_SW_EN_2_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_2_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_2_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_2_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_2_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_2_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_2_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_2_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_2_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_2_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_2_LSB (1U << 15) /* 1b */
+
+/* SPM_ACK_CHK_PC_2 (0x10006000 + 0x934) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_2_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_SEL_2 (0x10006000 + 0x938) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_2_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_2_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_2_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_2_LSB (1U << 21) /* 3b */
+
+/* SPM_ACK_CHK_TIMER_2 (0x10006000 + 0x93C) */
+#define SPM_ACK_CHK_TIMER_VAL_2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_2_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_STA_2 (0x10006000 + 0x940) */
+#define SPM_ACK_CHK_STA_2_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_SWINT_2 (0x10006000 + 0x944) */
+#define SPM_ACK_CHK_SWINT_EN_2_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_CON_3 (0x10006000 + 0x948) */
+#define SPM_ACK_CHK_SW_EN_3_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_3_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_3_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_3_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_3_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_3_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_3_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_3_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_3_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_3_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_3_LSB (1U << 15) /* 1b */
+
+/* SPM_ACK_CHK_PC_3 (0x10006000 + 0x94C) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_3_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_SEL_3 (0x10006000 + 0x950) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_3_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_3_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_3_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_3_LSB (1U << 21) /* 3b */
+
+/* SPM_ACK_CHK_TIMER_3 (0x10006000 + 0x954) */
+#define SPM_ACK_CHK_TIMER_VAL_3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_3_LSB (1U << 16) /* 16b */
+
+/* SPM_ACK_CHK_STA_3 (0x10006000 + 0x958) */
+#define SPM_ACK_CHK_STA_3_LSB (1U << 0) /* 32b */
+
+/* SPM_ACK_CHK_SWINT_3 (0x10006000 + 0x95C) */
+#define SPM_ACK_CHK_SWINT_EN_3_LSB (1U << 0) /* 32b */
+
+/* SPM_COUNTER_0 (0x10006000 + 0x960) */
+#define SPM_COUNTER_VAL_0_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_0_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_0_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_0_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_0_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_0_LSB (1U << 31) /* 1b */
+
+/* SPM_COUNTER_1 (0x10006000 + 0x964) */
+#define SPM_COUNTER_VAL_1_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_1_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_1_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_1_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_1_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_1_LSB (1U << 31) /* 1b */
+
+/* SPM_COUNTER_2 (0x10006000 + 0x968) */
+#define SPM_COUNTER_VAL_2_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_2_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_2_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_2_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_2_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_2_LSB (1U << 31) /* 1b */
+
+/* SYS_TIMER_CON (0x10006000 + 0x96C) */
+#define SYS_TIMER_START_EN_LSB (1U << 0) /* 1b */
+#define SYS_TIMER_LATCH_EN_LSB (1U << 1) /* 1b */
+#define SYS_TIMER_ID_LSB (1U << 8) /* 8b */
+#define SYS_TIMER_VALID_LSB (1U << 31) /* 1b */
+
+/* SPM_TWAM_CON (0x10006000 + 0x970) */
+#define REG_TWAM_ENABLE_LSB (1U << 0) /* 1b */
+#define REG_TWAM_SPEED_MODE_EN_LSB (1U << 1) /* 1b */
+#define REG_TWAM_SW_RST_LSB (1U << 2) /* 1b */
+#define REG_TWAM_IRQ_MASK_LSB (1U << 3) /* 1b */
+#define REG_TWAM_MON_TYPE_0_LSB (1U << 4) /* 2b */
+#define REG_TWAM_MON_TYPE_1_LSB (1U << 6) /* 2b */
+#define REG_TWAM_MON_TYPE_2_LSB (1U << 8) /* 2b */
+#define REG_TWAM_MON_TYPE_3_LSB (1U << 10) /* 2b */
+
+/* SPM_TWAM_WINDOW_LEN (0x10006000 + 0x974) */
+#define REG_TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */
+
+/* SPM_TWAM_IDLE_SEL (0x10006000 + 0x978) */
+#define REG_TWAM_SIG_SEL_0_LSB (1U << 0) /* 7b */
+#define REG_TWAM_SIG_SEL_1_LSB (1U << 8) /* 7b */
+#define REG_TWAM_SIG_SEL_2_LSB (1U << 16) /* 7b */
+#define REG_TWAM_SIG_SEL_3_LSB (1U << 24) /* 7b */
+
+/* SPM_TWAM_EVENT_CLEAR (0x10006000 + 0x97C) */
+#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */
+
+/* OPP0_TABLE (0x10006000 + 0x980) */
+#define OPP0_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP1_TABLE (0x10006000 + 0x984) */
+#define OPP1_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP2_TABLE (0x10006000 + 0x988) */
+#define OPP2_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP3_TABLE (0x10006000 + 0x98C) */
+#define OPP3_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP4_TABLE (0x10006000 + 0x990) */
+#define OPP4_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP5_TABLE (0x10006000 + 0x994) */
+#define OPP5_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP6_TABLE (0x10006000 + 0x998) */
+#define OPP6_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP7_TABLE (0x10006000 + 0x99C) */
+#define OPP7_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP8_TABLE (0x10006000 + 0x9A0) */
+#define OPP8_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP9_TABLE (0x10006000 + 0x9A4) */
+#define OPP9_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP10_TABLE (0x10006000 + 0x9A8) */
+#define OPP10_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP11_TABLE (0x10006000 + 0x9AC) */
+#define OPP11_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP12_TABLE (0x10006000 + 0x9B0) */
+#define OPP12_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP13_TABLE (0x10006000 + 0x9B4) */
+#define OPP13_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP14_TABLE (0x10006000 + 0x9B8) */
+#define OPP14_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP15_TABLE (0x10006000 + 0x9BC) */
+#define OPP15_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP16_TABLE (0x10006000 + 0x9C0) */
+#define OPP16_TABLE_LSB (1U << 0) /* 32b */
+
+/* OPP17_TABLE (0x10006000 + 0x9C4) */
+#define OPP17_TABLE_LSB (1U << 0) /* 32b */
+
+/* SHU0_ARRAY (0x10006000 + 0x9C8) */
+#define SHU0_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU1_ARRAY (0x10006000 + 0x9CC) */
+#define SHU1_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU2_ARRAY (0x10006000 + 0x9D0) */
+#define SHU2_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU3_ARRAY (0x10006000 + 0x9D4) */
+#define SHU3_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU4_ARRAY (0x10006000 + 0x9D8) */
+#define SHU4_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU5_ARRAY (0x10006000 + 0x9DC) */
+#define SHU5_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU6_ARRAY (0x10006000 + 0x9E0) */
+#define SHU6_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU7_ARRAY (0x10006000 + 0x9E4) */
+#define SHU7_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU8_ARRAY (0x10006000 + 0x9E8) */
+#define SHU8_ARRAY_LSB (1U << 0) /* 32b */
+
+/* SHU9_ARRAY (0x10006000 + 0x9EC) */
+#define SHU9_ARRAY_LSB (1U << 0) /* 32b */
+
+#define SPM_PROJECT_CODE (0xb16)
+#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16)
+
+#endif /* MT_SPM_REG */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h
new file mode 100644
index 0000000..d370daf
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_RESOURCE_REQ_H
+#define MT_SPM_RESOURCE_REQ_H
+
+/* SPM resource request internal bit */
+#define MT_SPM_BIT_XO_FPM 0U
+#define MT_SPM_BIT_26M 1U
+#define MT_SPM_BIT_INFRA 2U
+#define MT_SPM_BIT_SYSPLL 3U
+#define MT_SPM_BIT_DRAM_S0 4U
+#define MT_SPM_BIT_DRAM_S1 5U
+
+/* SPM resource request internal bit_mask */
+#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM)
+#define MT_SPM_26M BIT(MT_SPM_BIT_26M)
+#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA)
+#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL)
+#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0)
+#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1)
+
+#endif /* MT_SPM_RESOURCE_REQ_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c
new file mode 100644
index 0000000..df533a6
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <uart.h>
+
+#define SPM_SUSPEND_SLEEP_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_USE_SRCCLKENO2)
+
+#define SPM_SUSPEND_SLEEP_PCM_FLAG1 (0U)
+
+#define SPM_SUSPEND_PCM_FLAG \
+ (SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS)
+
+#define SPM_SUSPEND_PCM_FLAG1 (0U)
+
+#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \
+ (R12_PCM_TIMER | \
+ R12_KP_IRQ_B | \
+ R12_APWDT_EVENT_B | \
+ R12_CONN2AP_SPM_WAKEUP_B | \
+ R12_EINT_EVENT_B | \
+ R12_CONN_WDT_IRQ_B | \
+ R12_SSPM2SPM_WAKEUP_B | \
+ R12_SCP2SPM_WAKEUP_B | \
+ R12_ADSP2SPM_WAKEUP_B | \
+ R12_USBX_CDSC_B | \
+ R12_USBX_POWERDWN_B | \
+ R12_SYS_TIMER_EVENT_B | \
+ R12_EINT_EVENT_SECURE_B | \
+ R12_SYS_CIRQ_IRQ_B | \
+ R12_NNA_WAKEUP | \
+ R12_REG_CPU_WAKEUP)
+
+#if defined(CFG_MICROTRUST_TEE_SUPPORT)
+#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__)
+#else
+#define WAKE_SRC_FOR_SUSPEND \
+ (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \
+ R12_SEJ_EVENT_B)
+#endif
+
+static struct pwr_ctrl suspend_ctrl = {
+ .wake_src = WAKE_SRC_FOR_SUSPEND,
+
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ .reg_wfi_op = 0,
+ .reg_wfi_type = 0,
+ .reg_mp0_cputop_idle_mask = 0,
+ .reg_mp1_cputop_idle_mask = 0,
+ .reg_mcusys_idle_mask = 0,
+ .reg_md_apsrc_1_sel = 0,
+ .reg_md_apsrc_0_sel = 0,
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC6_MASK */
+ .reg_ccif_event_infra_req_mask_b = 0,
+ .reg_ccif_event_apsrc_req_mask_b = 0,
+
+ /* SPM_SRC_REQ */
+ .reg_spm_apsrc_req = 0,
+ .reg_spm_f26m_req = 0,
+ .reg_spm_infra_req = 0,
+ .reg_spm_vrf18_req = 0,
+ .reg_spm_ddren_req = 0,
+ .reg_spm_dvfs_req = 0,
+ .reg_spm_sw_mailbox_req = 0,
+ .reg_spm_sspm_mailbox_req = 0,
+ .reg_spm_adsp_mailbox_req = 0,
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC_MASK */
+ .reg_md_0_srcclkena_mask_b = 0,
+ .reg_md_0_infra_req_mask_b = 0,
+ .reg_md_0_apsrc_req_mask_b = 0,
+ .reg_md_0_vrf18_req_mask_b = 0,
+ .reg_md_0_ddren_req_mask_b = 0,
+ .reg_md_1_srcclkena_mask_b = 0,
+ .reg_md_1_infra_req_mask_b = 0,
+ .reg_md_1_apsrc_req_mask_b = 0,
+ .reg_md_1_vrf18_req_mask_b = 0,
+ .reg_md_1_ddren_req_mask_b = 0,
+ .reg_conn_srcclkena_mask_b = 1,
+ .reg_conn_srcclkenb_mask_b = 0,
+ .reg_conn_infra_req_mask_b = 1,
+ .reg_conn_apsrc_req_mask_b = 1,
+ .reg_conn_vrf18_req_mask_b = 1,
+ .reg_conn_ddren_req_mask_b = 1,
+ .reg_conn_vfe28_mask_b = 0,
+ .reg_srcclkeni_srcclkena_mask_b = 1,
+ .reg_srcclkeni_infra_req_mask_b = 1,
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ .reg_infrasys_ddren_req_mask_b = 1,
+ .reg_sspm_srcclkena_mask_b = 1,
+ .reg_sspm_infra_req_mask_b = 1,
+ .reg_sspm_apsrc_req_mask_b = 1,
+ .reg_sspm_vrf18_req_mask_b = 1,
+ .reg_sspm_ddren_req_mask_b = 1,
+
+ /* SPM_SRC2_MASK */
+ .reg_scp_srcclkena_mask_b = 1,
+ .reg_scp_infra_req_mask_b = 1,
+ .reg_scp_apsrc_req_mask_b = 1,
+ .reg_scp_vrf18_req_mask_b = 1,
+ .reg_scp_ddren_req_mask_b = 1,
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ .reg_audio_dsp_ddren_req_mask_b = 1,
+ .reg_ufs_srcclkena_mask_b = 1,
+ .reg_ufs_infra_req_mask_b = 1,
+ .reg_ufs_apsrc_req_mask_b = 1,
+ .reg_ufs_vrf18_req_mask_b = 1,
+ .reg_ufs_ddren_req_mask_b = 1,
+ .reg_disp0_apsrc_req_mask_b = 1,
+ .reg_disp0_ddren_req_mask_b = 1,
+ .reg_disp1_apsrc_req_mask_b = 1,
+ .reg_disp1_ddren_req_mask_b = 1,
+ .reg_gce_infra_req_mask_b = 1,
+ .reg_gce_apsrc_req_mask_b = 1,
+ .reg_gce_vrf18_req_mask_b = 1,
+ .reg_gce_ddren_req_mask_b = 1,
+ .reg_apu_srcclkena_mask_b = 0,
+ .reg_apu_infra_req_mask_b = 0,
+ .reg_apu_apsrc_req_mask_b = 0,
+ .reg_apu_vrf18_req_mask_b = 0,
+ .reg_apu_ddren_req_mask_b = 0,
+ .reg_cg_check_srcclkena_mask_b = 0,
+ .reg_cg_check_apsrc_req_mask_b = 0,
+ .reg_cg_check_vrf18_req_mask_b = 0,
+ .reg_cg_check_ddren_req_mask_b = 0,
+
+ /* SPM_SRC3_MASK */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+ .reg_sw2spm_wakeup_mask_b = 0,
+ .reg_adsp2spm_wakeup_mask_b = 0,
+ .reg_sspm2spm_wakeup_mask_b = 0,
+ .reg_scp2spm_wakeup_mask_b = 0,
+ .reg_csyspwrup_ack_mask = 1,
+ .reg_spm_reserved_srcclkena_mask_b = 0,
+ .reg_spm_reserved_infra_req_mask_b = 0,
+ .reg_spm_reserved_apsrc_req_mask_b = 0,
+ .reg_spm_reserved_vrf18_req_mask_b = 0,
+ .reg_spm_reserved_ddren_req_mask_b = 0,
+ .reg_mcupm_srcclkena_mask_b = 0,
+ .reg_mcupm_infra_req_mask_b = 0,
+ .reg_mcupm_apsrc_req_mask_b = 0,
+ .reg_mcupm_vrf18_req_mask_b = 0,
+ .reg_mcupm_ddren_req_mask_b = 0,
+ .reg_msdc0_srcclkena_mask_b = 1,
+ .reg_msdc0_infra_req_mask_b = 1,
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ .reg_msdc0_ddren_req_mask_b = 1,
+ .reg_msdc1_srcclkena_mask_b = 1,
+ .reg_msdc1_infra_req_mask_b = 1,
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ .reg_msdc1_ddren_req_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ .reg_ccif_event_srcclkena_mask_b = 0,
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ .reg_bak_psri_infra_req_mask_b = 0,
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ .reg_bak_psri_ddren_req_mask_b = 0,
+ .reg_dramc_md32_infra_req_mask_b = 0,
+ .reg_dramc_md32_vrf18_req_mask_b = 0,
+ .reg_conn_srcclkenb2pwrap_mask_b = 0,
+ .reg_dramc_md32_apsrc_req_mask_b = 0,
+
+ /* SPM_SRC5_MASK */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x83,
+ .reg_mcusys_merge_ddren_req_mask_b = 0x83,
+ .reg_afe_srcclkena_mask_b = 1,
+ .reg_afe_infra_req_mask_b = 1,
+ .reg_afe_apsrc_req_mask_b = 1,
+ .reg_afe_vrf18_req_mask_b = 1,
+ .reg_afe_ddren_req_mask_b = 1,
+ .reg_msdc2_srcclkena_mask_b = 0,
+ .reg_msdc2_infra_req_mask_b = 0,
+ .reg_msdc2_apsrc_req_mask_b = 0,
+ .reg_msdc2_vrf18_req_mask_b = 0,
+ .reg_msdc2_ddren_req_mask_b = 0,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ .reg_wakeup_event_mask = 0x1383213,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+
+ /* SPM_SRC7_MASK */
+ .reg_pcie_srcclkena_mask_b = 0,
+ .reg_pcie_infra_req_mask_b = 0,
+ .reg_pcie_apsrc_req_mask_b = 0,
+ .reg_pcie_vrf18_req_mask_b = 0,
+ .reg_pcie_ddren_req_mask_b = 0,
+ .reg_dpmaif_srcclkena_mask_b = 1,
+ .reg_dpmaif_infra_req_mask_b = 1,
+ .reg_dpmaif_apsrc_req_mask_b = 1,
+ .reg_dpmaif_vrf18_req_mask_b = 1,
+ .reg_dpmaif_ddren_req_mask_b = 1,
+
+ /* Auto-gen End */
+
+ /*sw flag setting */
+ .pcm_flags = SPM_SUSPEND_PCM_FLAG,
+ .pcm_flags1 = SPM_SUSPEND_PCM_FLAG1,
+};
+
+struct spm_lp_scen __spm_suspend = {
+ .pwrctrl = &suspend_ctrl,
+};
+
+int mt_spm_suspend_mode_set(int mode)
+{
+ if (mode == MT_SPM_SUSPEND_SLEEP) {
+ suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG;
+ suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1;
+ } else {
+ suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG;
+ suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1;
+ }
+
+ return 0;
+}
+
+int mt_spm_suspend_enter(int state_id, unsigned int ext_opand,
+ unsigned int resource_req)
+{
+ /* If FMAudio / ADSP is active, change to sleep suspend mode */
+ if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
+ mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP);
+ }
+
+ /* Notify MCUPM that device is going suspend flow */
+ mmio_write_32(MCUPM_MBOX_OFFSET_PDN, MCUPM_POWER_DOWN);
+
+ /* Notify UART to sleep */
+ mt_uart_save();
+
+ return spm_conservation(state_id, ext_opand,
+ &__spm_suspend, resource_req);
+}
+
+void mt_spm_suspend_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status)
+{
+ spm_conservation_finish(state_id, ext_opand, &__spm_suspend, status);
+
+ /* Notify UART to wakeup */
+ mt_uart_restore();
+
+ /* Notify MCUPM that device leave suspend */
+ mmio_write_32(MCUPM_MBOX_OFFSET_PDN, 0);
+
+ /* If FMAudio / ADSP is active, change back to suspend mode */
+ if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
+ mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN);
+ }
+}
+
+void mt_spm_suspend_init(void)
+{
+ spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl);
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h
new file mode 100644
index 0000000..f7c066a
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef MT_SPM_SUSPEDN_H
+#define MT_SPM_SUSPEDN_H
+
+#include <mt_spm_internal.h>
+
+#define MCUPM_MBOX_OFFSET_PDN (0x0C55FDA8)
+#define MCUPM_POWER_DOWN (0x4D50444E)
+
+enum MT_SPM_SUSPEND_MODE {
+ MT_SPM_SUSPEND_SYSTEM_PDN = 0U,
+ MT_SPM_SUSPEND_SLEEP = 1U,
+};
+
+extern int mt_spm_suspend_mode_set(int mode);
+extern int mt_spm_suspend_enter(int state_id, unsigned int ext_opand,
+ unsigned int reosuce_req);
+extern void mt_spm_suspend_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status);
+extern void mt_spm_suspend_init(void);
+
+#endif /* MT_SPM_SUSPEND_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c
new file mode 100644
index 0000000..fb51e69
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright(C)2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_vcorefs.h>
+#include <mtk_sip_svc.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+#include <pmic.h>
+
+#define VCORE_CT_ENABLE BIT(5)
+#define VCORE_DRM_ENABLE BIT(31)
+#define VCORE_PTPOD_SHIFT (8)
+#define VCORE_POWER_SHIFT (2)
+
+#define VCORE_MAX_OPP (3)
+#define DRAM_MAX_OPP (6)
+
+#define SW_REQ5_INIT_VAL (6U << 12)
+#define V_VMODE_SHIFT (0)
+#define VCORE_HV (105)
+#define VCORE_LV (95)
+#define PMIC_STEP_UV (6250)
+
+static int vcore_opp_0_uv = 800000;
+static int vcore_opp_1_uv = 700000;
+static int vcore_opp_2_uv = 650000;
+
+static struct pwr_ctrl vcorefs_ctrl = {
+ .wake_src = R12_REG_CPU_WAKEUP,
+
+ /* default VCORE DVFS is disabled */
+ .pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO |
+ SPM_FLAG_DISABLE_VCORE_DVS |
+ SPM_FLAG_DISABLE_VCORE_DFS),
+
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ .reg_wfi_op = 0,
+ .reg_wfi_type = 0,
+ .reg_mp0_cputop_idle_mask = 0,
+ .reg_mp1_cputop_idle_mask = 0,
+ .reg_mcusys_idle_mask = 0,
+ .reg_md_apsrc_1_sel = 0,
+ .reg_md_apsrc_0_sel = 0,
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC6_MASK */
+ .reg_ccif_event_infra_req_mask_b = 0xFFFF,
+ .reg_ccif_event_apsrc_req_mask_b = 0xFFFF,
+
+ /* SPM_SRC_REQ */
+ .reg_spm_apsrc_req = 1,
+ .reg_spm_f26m_req = 1,
+ .reg_spm_infra_req = 1,
+ .reg_spm_vrf18_req = 1,
+ .reg_spm_ddren_req = 1,
+ .reg_spm_dvfs_req = 0,
+ .reg_spm_sw_mailbox_req = 0,
+ .reg_spm_sspm_mailbox_req = 0,
+ .reg_spm_adsp_mailbox_req = 0,
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC_MASK */
+ .reg_md_0_srcclkena_mask_b = 1,
+ .reg_md_0_infra_req_mask_b = 1,
+ .reg_md_0_apsrc_req_mask_b = 1,
+ .reg_md_0_vrf18_req_mask_b = 1,
+ .reg_md_0_ddren_req_mask_b = 1,
+ .reg_md_1_srcclkena_mask_b = 0,
+ .reg_md_1_infra_req_mask_b = 0,
+ .reg_md_1_apsrc_req_mask_b = 0,
+ .reg_md_1_vrf18_req_mask_b = 0,
+ .reg_md_1_ddren_req_mask_b = 0,
+ .reg_conn_srcclkena_mask_b = 1,
+ .reg_conn_srcclkenb_mask_b = 0,
+ .reg_conn_infra_req_mask_b = 1,
+ .reg_conn_apsrc_req_mask_b = 1,
+ .reg_conn_vrf18_req_mask_b = 1,
+ .reg_conn_ddren_req_mask_b = 1,
+ .reg_conn_vfe28_mask_b = 0,
+ .reg_srcclkeni_srcclkena_mask_b = 1,
+ .reg_srcclkeni_infra_req_mask_b = 1,
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ .reg_infrasys_ddren_req_mask_b = 1,
+ .reg_sspm_srcclkena_mask_b = 1,
+ .reg_sspm_infra_req_mask_b = 1,
+ .reg_sspm_apsrc_req_mask_b = 1,
+ .reg_sspm_vrf18_req_mask_b = 1,
+ .reg_sspm_ddren_req_mask_b = 1,
+
+ /* SPM_SRC2_MASK */
+ .reg_scp_srcclkena_mask_b = 1,
+ .reg_scp_infra_req_mask_b = 1,
+ .reg_scp_apsrc_req_mask_b = 1,
+ .reg_scp_vrf18_req_mask_b = 1,
+ .reg_scp_ddren_req_mask_b = 1,
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ .reg_audio_dsp_ddren_req_mask_b = 1,
+ .reg_ufs_srcclkena_mask_b = 1,
+ .reg_ufs_infra_req_mask_b = 1,
+ .reg_ufs_apsrc_req_mask_b = 1,
+ .reg_ufs_vrf18_req_mask_b = 1,
+ .reg_ufs_ddren_req_mask_b = 1,
+ .reg_disp0_apsrc_req_mask_b = 1,
+ .reg_disp0_ddren_req_mask_b = 1,
+ .reg_disp1_apsrc_req_mask_b = 1,
+ .reg_disp1_ddren_req_mask_b = 1,
+ .reg_gce_infra_req_mask_b = 1,
+ .reg_gce_apsrc_req_mask_b = 1,
+ .reg_gce_vrf18_req_mask_b = 1,
+ .reg_gce_ddren_req_mask_b = 1,
+ .reg_apu_srcclkena_mask_b = 0,
+ .reg_apu_infra_req_mask_b = 0,
+ .reg_apu_apsrc_req_mask_b = 0,
+ .reg_apu_vrf18_req_mask_b = 0,
+ .reg_apu_ddren_req_mask_b = 0,
+ .reg_cg_check_srcclkena_mask_b = 0,
+ .reg_cg_check_apsrc_req_mask_b = 0,
+ .reg_cg_check_vrf18_req_mask_b = 0,
+ .reg_cg_check_ddren_req_mask_b = 0,
+
+ /* SPM_SRC3_MASK */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+ .reg_sw2spm_wakeup_mask_b = 0,
+ .reg_adsp2spm_wakeup_mask_b = 0,
+ .reg_sspm2spm_wakeup_mask_b = 0,
+ .reg_scp2spm_wakeup_mask_b = 0,
+ .reg_csyspwrup_ack_mask = 1,
+ .reg_spm_reserved_srcclkena_mask_b = 0,
+ .reg_spm_reserved_infra_req_mask_b = 0,
+ .reg_spm_reserved_apsrc_req_mask_b = 0,
+ .reg_spm_reserved_vrf18_req_mask_b = 0,
+ .reg_spm_reserved_ddren_req_mask_b = 0,
+ .reg_mcupm_srcclkena_mask_b = 1,
+ .reg_mcupm_infra_req_mask_b = 1,
+ .reg_mcupm_apsrc_req_mask_b = 1,
+ .reg_mcupm_vrf18_req_mask_b = 1,
+ .reg_mcupm_ddren_req_mask_b = 1,
+ .reg_msdc0_srcclkena_mask_b = 1,
+ .reg_msdc0_infra_req_mask_b = 1,
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ .reg_msdc0_ddren_req_mask_b = 1,
+ .reg_msdc1_srcclkena_mask_b = 1,
+ .reg_msdc1_infra_req_mask_b = 1,
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ .reg_msdc1_ddren_req_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ .reg_ccif_event_srcclkena_mask_b = 0x3FF,
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ .reg_bak_psri_infra_req_mask_b = 0,
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ .reg_bak_psri_ddren_req_mask_b = 0,
+ .reg_dramc_md32_infra_req_mask_b = 1,
+ .reg_dramc_md32_vrf18_req_mask_b = 0,
+ .reg_conn_srcclkenb2pwrap_mask_b = 0,
+ .reg_dramc_md32_apsrc_req_mask_b = 0,
+
+ /* SPM_SRC5_MASK */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x14,
+ .reg_mcusys_merge_ddren_req_mask_b = 0x14,
+ .reg_afe_srcclkena_mask_b = 0,
+ .reg_afe_infra_req_mask_b = 0,
+ .reg_afe_apsrc_req_mask_b = 0,
+ .reg_afe_vrf18_req_mask_b = 0,
+ .reg_afe_ddren_req_mask_b = 0,
+ .reg_msdc2_srcclkena_mask_b = 0,
+ .reg_msdc2_infra_req_mask_b = 0,
+ .reg_msdc2_apsrc_req_mask_b = 0,
+ .reg_msdc2_vrf18_req_mask_b = 0,
+ .reg_msdc2_ddren_req_mask_b = 0,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ .reg_wakeup_event_mask = 0xEFFFFFFF,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+
+ /* SPM_SRC7_MASK */
+ .reg_pcie_srcclkena_mask_b = 1,
+ .reg_pcie_infra_req_mask_b = 1,
+ .reg_pcie_apsrc_req_mask_b = 1,
+ .reg_pcie_vrf18_req_mask_b = 1,
+ .reg_pcie_ddren_req_mask_b = 1,
+ .reg_dpmaif_srcclkena_mask_b = 1,
+ .reg_dpmaif_infra_req_mask_b = 1,
+ .reg_dpmaif_apsrc_req_mask_b = 1,
+ .reg_dpmaif_vrf18_req_mask_b = 1,
+ .reg_dpmaif_ddren_req_mask_b = 1,
+
+ /* Auto-gen End */
+};
+
+struct spm_lp_scen __spm_vcorefs = {
+ .pwrctrl = &vcorefs_ctrl,
+};
+
+static struct reg_config dvfsrc_init_configs[] = {
+ {DVFSRC_HRT_REQ_UNIT, 0x0000001E},
+ {DVFSRC_DEBOUNCE_TIME, 0x00001965},
+ {DVFSRC_TIMEOUT_NEXTREQ, 0x00000015},
+ {DVFSRC_VCORE_REQUEST4, 0x22211100},
+ {DVFSRC_DDR_QOS0, 0x00000019},
+ {DVFSRC_DDR_QOS1, 0x00000026},
+ {DVFSRC_DDR_QOS2, 0x00000033},
+ {DVFSRC_DDR_QOS3, 0x0000004C},
+ {DVFSRC_DDR_QOS4, 0x00000066},
+ {DVFSRC_DDR_QOS5, 0x00000077},
+ {DVFSRC_DDR_QOS6, 0x00770077},
+ {DVFSRC_LEVEL_LABEL_0_1, 0x40225032},
+ {DVFSRC_LEVEL_LABEL_2_3, 0x20223012},
+ {DVFSRC_LEVEL_LABEL_4_5, 0x40211012},
+ {DVFSRC_LEVEL_LABEL_6_7, 0x20213011},
+ {DVFSRC_LEVEL_LABEL_8_9, 0x30101011},
+ {DVFSRC_LEVEL_LABEL_10_11, 0x10102000},
+ {DVFSRC_LEVEL_LABEL_12_13, 0x00000000},
+ {DVFSRC_LEVEL_LABEL_14_15, 0x00000000},
+ {DVFSRC_LEVEL_LABEL_16_17, 0x00000000},
+ {DVFSRC_LEVEL_LABEL_18_19, 0x00000000},
+ {DVFSRC_LEVEL_LABEL_20_21, 0x00000000},
+ {DVFSRC_LEVEL_MASK, 0x00000000},
+ {DVFSRC_MD_LATENCY_IMPROVE, 0x00000020},
+ {DVFSRC_HRT_BW_BASE, 0x00000004},
+ {DVSFRC_HRT_REQ_MD_URG, 0x000D50D5},
+ {DVFSRC_HRT_REQ_MD_BW_0, 0x00200802},
+ {DVFSRC_HRT_REQ_MD_BW_1, 0x00200802},
+ {DVFSRC_HRT_REQ_MD_BW_2, 0x00200800},
+ {DVFSRC_HRT_REQ_MD_BW_3, 0x00400802},
+ {DVFSRC_HRT_REQ_MD_BW_4, 0x00601404},
+ {DVFSRC_HRT_REQ_MD_BW_5, 0x00D02C09},
+ {DVFSRC_HRT_REQ_MD_BW_6, 0x00000012},
+ {DVFSRC_HRT_REQ_MD_BW_7, 0x00000024},
+ {DVFSRC_HRT_REQ_MD_BW_8, 0x00000000},
+ {DVFSRC_HRT_REQ_MD_BW_9, 0x00000000},
+ {DVFSRC_HRT_REQ_MD_BW_10, 0x00035400},
+ {DVFSRC_HRT1_REQ_MD_BW_0, 0x04B12C4B},
+ {DVFSRC_HRT1_REQ_MD_BW_1, 0x04B12C4B},
+ {DVFSRC_HRT1_REQ_MD_BW_2, 0x04B12C00},
+ {DVFSRC_HRT1_REQ_MD_BW_3, 0x04B12C4B},
+ {DVFSRC_HRT1_REQ_MD_BW_4, 0x04B12C4B},
+ {DVFSRC_HRT1_REQ_MD_BW_5, 0x04B12C4B},
+ {DVFSRC_HRT1_REQ_MD_BW_6, 0x0000004B},
+ {DVFSRC_HRT1_REQ_MD_BW_7, 0x0000005C},
+ {DVFSRC_HRT1_REQ_MD_BW_8, 0x00000000},
+ {DVFSRC_HRT1_REQ_MD_BW_9, 0x00000000},
+ {DVFSRC_HRT1_REQ_MD_BW_10, 0x00035400},
+ {DVFSRC_95MD_SCEN_BW0_T, 0x22222220},
+ {DVFSRC_95MD_SCEN_BW1_T, 0x22222222},
+ {DVFSRC_95MD_SCEN_BW2_T, 0x22222222},
+ {DVFSRC_95MD_SCEN_BW3_T, 0x52222222},
+ {DVFSRC_95MD_SCEN_BW4, 0x00000005},
+ {DVFSRC_RSRV_5, 0x00000001},
+#ifdef DVFSRC_1600_FLOOR
+ {DVFSRC_DDR_REQUEST, 0x00000022},
+#else
+ {DVFSRC_DDR_REQUEST, 0x00000021},
+#endif
+ {DVFSRC_DDR_REQUEST3, 0x00554300},
+ {DVFSRC_DDR_ADD_REQUEST, 0x55543210},
+#ifdef DVFSRC_1600_FLOOR
+ {DVFSRC_DDR_REQUEST5, 0x54322000},
+#else
+ {DVFSRC_DDR_REQUEST5, 0x54321000},
+#endif
+ {DVFSRC_DDR_REQUEST6, 0x53143130},
+ {DVFSRC_DDR_REQUEST7, 0x55000000},
+ {DVFSRC_DDR_REQUEST8, 0x05000000},
+ {DVFSRC_EMI_MON_DEBOUNCE_TIME, 0x4C2D0000},
+ {DVFSRC_EMI_ADD_REQUEST, 0x55543210},
+ {DVFSRC_VCORE_USER_REQ, 0x00010A29},
+ {DVFSRC_HRT_HIGH, 0x0E100960},
+ {DVFSRC_HRT_HIGH_1, 0x1AD21700},
+ {DVFSRC_HRT_HIGH_2, 0x314C2306},
+ {DVFSRC_HRT_HIGH_3, 0x314C314C},
+ {DVFSRC_HRT_LOW, 0x0E0F095F},
+ {DVFSRC_HRT_LOW_1, 0x1AD116FF},
+ {DVFSRC_HRT_LOW_2, 0x314B2305},
+ {DVFSRC_HRT_LOW_3, 0x314B314B},
+#ifdef DVFSRC_1600_FLOOR
+ {DVFSRC_HRT_REQUEST, 0x55554322},
+#else
+ {DVFSRC_HRT_REQUEST, 0x55554321},
+#endif
+ {DVFSRC_BASIC_CONTROL_3, 0x0000000E},
+ {DVFSRC_INT_EN, 0x00000002},
+ {DVFSRC_QOS_EN, 0x001e407C},
+ {DVFSRC_CURRENT_FORCE, 0x00000001},
+ {DVFSRC_BASIC_CONTROL, 0x0180004B},
+ {DVFSRC_BASIC_CONTROL, 0X0180404B},
+ {DVFSRC_BASIC_CONTROL, 0X0180014B},
+ {DVFSRC_CURRENT_FORCE, 0x00000000},
+};
+
+#define IS_PMIC_57() ((pmic_get_hwcid() >> 8) == 0x57)
+
+static inline unsigned int vcore_base_uv(void)
+{
+ static unsigned int vb;
+
+ if (vb == 0) {
+ vb = IS_PMIC_57() ? 518750 : 500000;
+ }
+
+ return vb;
+}
+
+#define _VCORE_STEP_UV (6250)
+
+#define __vcore_uv_to_pmic(uv) /* pmic >= uv */ \
+ ((((uv) - vcore_base_uv()) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV)
+
+static int devinfo_table[] = {
+ 3539, 492, 1038, 106, 231, 17, 46, 2179,
+ 4, 481, 1014, 103, 225, 17, 45, 2129,
+ 3, 516, 1087, 111, 242, 19, 49, 2282,
+ 4, 504, 1063, 108, 236, 18, 47, 2230,
+ 4, 448, 946, 96, 210, 15, 41, 1986,
+ 2, 438, 924, 93, 205, 14, 40, 1941,
+ 2, 470, 991, 101, 220, 16, 43, 2080,
+ 3, 459, 968, 98, 215, 16, 42, 2033,
+ 3, 594, 1250, 129, 279, 23, 57, 2621,
+ 6, 580, 1221, 126, 273, 22, 56, 2561,
+ 6, 622, 1309, 136, 293, 24, 60, 2745,
+ 7, 608, 1279, 132, 286, 23, 59, 2683,
+ 6, 541, 1139, 117, 254, 20, 51, 2390,
+ 5, 528, 1113, 114, 248, 19, 50, 2335,
+ 4, 566, 1193, 123, 266, 21, 54, 2503,
+ 5, 553, 1166, 120, 260, 21, 53, 2446,
+ 5, 338, 715, 70, 157, 9, 29, 1505,
+ 3153, 330, 699, 69, 153, 9, 28, 1470,
+ 3081, 354, 750, 74, 165, 10, 31, 1576,
+ 3302, 346, 732, 72, 161, 10, 30, 1540,
+ 3227, 307, 652, 63, 142, 8, 26, 1371,
+ 2875, 300, 637, 62, 139, 7, 25, 1340,
+ 2809, 322, 683, 67, 149, 8, 27, 1436,
+ 3011, 315, 667, 65, 146, 8, 26, 1404,
+ 2942, 408, 862, 86, 191, 13, 37, 1811,
+ 1, 398, 842, 84, 186, 12, 36, 1769,
+ 1, 428, 903, 91, 200, 14, 39, 1896,
+ 2, 418, 882, 89, 195, 13, 38, 1853,
+ 2, 371, 785, 78, 173, 11, 33, 1651,
+ 3458, 363, 767, 76, 169, 10, 32, 1613,
+ 3379, 389, 823, 82, 182, 12, 35, 1729,
+ 1, 380, 804, 80, 177, 11, 34, 1689,
+};
+
+static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val)
+{
+ if (cmd < NR_IDX_ALL) {
+ mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val);
+ } else {
+ INFO("cmd out of range!\n");
+ }
+}
+
+void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue)
+{
+ mmio_write_32(OPP0_TABLE, 0xFFFF0000);
+ mmio_write_32(OPP1_TABLE, 0xFFFF0100);
+ mmio_write_32(OPP2_TABLE, 0xFFFF0300);
+ mmio_write_32(OPP3_TABLE, 0xFFFF0500);
+ mmio_write_32(OPP4_TABLE, 0xFFFF0700);
+ mmio_write_32(OPP5_TABLE, 0xFFFF0202);
+ mmio_write_32(OPP6_TABLE, 0xFFFF0302);
+ mmio_write_32(OPP7_TABLE, 0xFFFF0502);
+ mmio_write_32(OPP8_TABLE, 0xFFFF0702);
+ mmio_write_32(OPP9_TABLE, 0xFFFF0403);
+ mmio_write_32(OPP10_TABLE, 0xFFFF0603);
+ mmio_write_32(OPP11_TABLE, 0xFFFF0803);
+ mmio_write_32(OPP12_TABLE, 0xFFFF0903);
+ mmio_write_32(OPP13_TABLE, 0xFFFFFFFF);
+ mmio_write_32(OPP14_TABLE, 0xFFFFFFFF);
+ mmio_write_32(OPP15_TABLE, 0xFFFFFFFF);
+ mmio_write_32(OPP16_TABLE, 0xFFFFFFFF);
+ mmio_write_32(OPP17_TABLE, 0xFFFFFFFF);
+ mmio_write_32(SHU0_ARRAY, 0xFFFFFF00);
+ mmio_write_32(SHU1_ARRAY, 0xFFFFEE01);
+ mmio_write_32(SHU2_ARRAY, 0xFF05EEFF);
+ mmio_write_32(SHU3_ARRAY, 0xFF06EE02);
+ mmio_write_32(SHU4_ARRAY, 0x0906FFFF);
+ mmio_write_32(SHU5_ARRAY, 0xFF07EE03);
+ mmio_write_32(SHU6_ARRAY, 0x0A07FFFF);
+ mmio_write_32(SHU7_ARRAY, 0xFF08EE04);
+ mmio_write_32(SHU8_ARRAY, 0x0B08FFFF);
+ mmio_write_32(SHU9_ARRAY, 0x0CFFFFFF);
+
+ mmio_clrsetbits_32(SPM_DVFS_MISC, SPM_DVFS_FORCE_ENABLE_LSB,
+ SPM_DVFSRC_ENABLE_LSB);
+
+ mmio_write_32(SPM_DVFS_LEVEL, 0x00000001);
+ mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001);
+}
+
+void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+ const struct pwr_ctrl *src_pwr_ctrl)
+{
+ uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS |
+ SPM_FLAG_DISABLE_VCORE_DFS |
+ SPM_FLAG_ENABLE_VOLTAGE_BIN;
+
+ dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) |
+ (src_pwr_ctrl->pcm_flags & dvfs_mask);
+
+ if (dest_pwr_ctrl->pcm_flags_cust > 0U) {
+ dest_pwr_ctrl->pcm_flags_cust =
+ ((dest_pwr_ctrl->pcm_flags_cust) & (~dvfs_mask)) |
+ ((src_pwr_ctrl->pcm_flags) & (dvfs_mask));
+ }
+}
+
+static void spm_go_to_vcorefs(void)
+{
+ __spm_set_power_control(__spm_vcorefs.pwrctrl);
+ __spm_set_wakeup_event(__spm_vcorefs.pwrctrl);
+ __spm_set_pcm_flags(__spm_vcorefs.pwrctrl);
+ __spm_send_cpu_wakeup_event();
+}
+
+static void dvfsrc_init(void)
+{
+ uint32_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(dvfsrc_init_configs); i++) {
+ mmio_write_32(dvfsrc_init_configs[i].offset,
+ dvfsrc_init_configs[i].val);
+ }
+}
+
+static void spm_vcorefs_vcore_setting(uint64_t flag)
+{
+ int idx, ptpod, rsv4;
+ int power = 0;
+
+ switch (flag) {
+ case 1: /*HV*/
+ vcore_opp_0_uv = 840000;
+ vcore_opp_1_uv = 725000;
+ vcore_opp_2_uv = 682500;
+ break;
+ case 2: /*LV*/
+ vcore_opp_0_uv = 760000;
+ vcore_opp_1_uv = 665000;
+ vcore_opp_2_uv = 617500;
+ break;
+ default:
+ break;
+ }
+
+ rsv4 = mmio_read_32(DVFSRC_RSRV_4);
+ ptpod = (rsv4 >> VCORE_PTPOD_SHIFT) & 0xF;
+ idx = (rsv4 >> VCORE_POWER_SHIFT) & 0xFF;
+
+ if (idx != 0) {
+ power = (int)devinfo_table[idx];
+ }
+
+ if (power > 0 && power <= 40) {
+ idx = ptpod & 0xF;
+ if (idx == 1) {
+ vcore_opp_2_uv = 700000;
+ } else if (idx > 1 && idx < 10) {
+ vcore_opp_2_uv = 675000;
+ }
+ }
+
+ spm_vcorefs_pwarp_cmd(3, __vcore_uv_to_pmic(vcore_opp_2_uv));
+ spm_vcorefs_pwarp_cmd(2, __vcore_uv_to_pmic(vcore_opp_1_uv));
+ spm_vcorefs_pwarp_cmd(0, __vcore_uv_to_pmic(vcore_opp_0_uv));
+}
+
+uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4)
+{
+ uint64_t cmd = x1;
+ uint64_t spm_flags;
+
+ switch (cmd) {
+ case VCOREFS_SMC_CMD_INIT:
+ /* vcore_dvfs init + kick */
+ mmio_write_32(DVFSRC_SW_REQ5, SW_REQ5_INIT_VAL);
+ spm_dvfsfw_init(0ULL, 0ULL);
+ spm_vcorefs_vcore_setting(x3 & 0xF);
+ spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+ if ((x2 & 0x1) > 0U) {
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+ }
+
+ if ((x2 & 0x2) > 0U) {
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+ }
+
+ if ((mmio_read_32(DVFSRC_RSRV_4) & VCORE_CT_ENABLE) > 0U) {
+ spm_flags |= SPM_FLAG_ENABLE_VOLTAGE_BIN;
+ }
+
+ set_pwrctrl_pcm_flags(__spm_vcorefs.pwrctrl, spm_flags);
+ spm_go_to_vcorefs();
+ dvfsrc_init();
+
+ *x4 = 0U;
+ mmio_write_32(DVFSRC_SW_REQ5, 0U);
+ break;
+ case VCOREFS_SMC_CMD_KICK:
+ mmio_write_32(DVFSRC_SW_REQ5, 0U);
+ break;
+ default:
+ break;
+ }
+
+ return 0ULL;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h b/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h
new file mode 100644
index 0000000..4fe1b12
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h
@@ -0,0 +1,316 @@
+/*
+ * Copyright(C)2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_VCOREFS_H
+#define MT_SPM_VCOREFS_H
+
+uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4);
+
+enum vcorefs_smc_cmd {
+ VCOREFS_SMC_CMD_0 = 0U,
+ VCOREFS_SMC_CMD_1 = 1U,
+ VCOREFS_SMC_CMD_2 = 2U,
+ VCOREFS_SMC_CMD_3 = 3U,
+ VCOREFS_SMC_CMD_4 = 4U,
+ /* check spmfw status */
+ VCOREFS_SMC_CMD_5 = 5U,
+
+ /* get spmfw type */
+ VCOREFS_SMC_CMD_6 = 6U,
+
+ /* get spm reg status */
+ VCOREFS_SMC_CMD_7 = 7U,
+
+ NUM_VCOREFS_SMC_CMD = 8U,
+};
+
+enum vcorefs_smc_cmd_new {
+ VCOREFS_SMC_CMD_INIT = 0U,
+ VCOREFS_SMC_CMD_KICK = 1U,
+ VCOREFS_SMC_CMD_OPP_TYPE = 2U,
+ VCOREFS_SMC_CMD_FW_TYPE = 3U,
+ VCOREFS_SMC_CMD_GET_UV = 4U,
+ VCOREFS_SMC_CMD_GET_FREQ = 5U,
+ VCOREFS_SMC_CMD_GET_NUM_V = 6U,
+ VCOREFS_SMC_CMD_GET_NUM_F = 7U,
+ VCOREFS_SMC_CMD_FB_ACTION = 8U,
+ /*chip specific setting */
+ VCOREFS_SMC_CMD_SET_FREQ = 16U,
+ VCOREFS_SMC_CMD_SET_EFUSE = 17U,
+ VCOREFS_SMC_CMD_GET_EFUSE = 18U,
+ VCOREFS_SMC_CMD_DVFS_HOPPING = 19U,
+ VCOREFS_SMC_CMD_DVFS_HOPPING_STATE = 20U,
+};
+
+enum dvfsrc_channel {
+ DVFSRC_CHANNEL_1 = 1U,
+ DVFSRC_CHANNEL_2 = 2U,
+ DVFSRC_CHANNEL_3 = 3U,
+ DVFSRC_CHANNEL_4 = 4U,
+ NUM_DVFSRC_CHANNEL = 5U,
+};
+
+struct reg_config {
+ uint32_t offset;
+ uint32_t val;
+};
+
+#define DVFSRC_BASIC_CONTROL (DVFSRC_BASE + 0x0)
+#define DVFSRC_SW_REQ1 (DVFSRC_BASE + 0x4)
+#define DVFSRC_SW_REQ2 (DVFSRC_BASE + 0x8)
+#define DVFSRC_SW_REQ3 (DVFSRC_BASE + 0xC)
+#define DVFSRC_SW_REQ4 (DVFSRC_BASE + 0x10)
+#define DVFSRC_SW_REQ5 (DVFSRC_BASE + 0x14)
+#define DVFSRC_SW_REQ6 (DVFSRC_BASE + 0x18)
+#define DVFSRC_SW_REQ7 (DVFSRC_BASE + 0x1C)
+#define DVFSRC_SW_REQ8 (DVFSRC_BASE + 0x20)
+#define DVFSRC_EMI_REQUEST (DVFSRC_BASE + 0x24)
+#define DVFSRC_EMI_REQUEST2 (DVFSRC_BASE + 0x28)
+#define DVFSRC_EMI_REQUEST3 (DVFSRC_BASE + 0x2C)
+#define DVFSRC_EMI_REQUEST4 (DVFSRC_BASE + 0x30)
+#define DVFSRC_EMI_REQUEST5 (DVFSRC_BASE + 0x34)
+#define DVFSRC_EMI_REQUEST6 (DVFSRC_BASE + 0x38)
+#define DVFSRC_EMI_HRT (DVFSRC_BASE + 0x3C)
+#define DVFSRC_EMI_HRT2 (DVFSRC_BASE + 0x40)
+#define DVFSRC_EMI_HRT3 (DVFSRC_BASE + 0x44)
+#define DVFSRC_EMI_QOS0 (DVFSRC_BASE + 0x48)
+#define DVFSRC_EMI_QOS1 (DVFSRC_BASE + 0x4C)
+#define DVFSRC_EMI_QOS2 (DVFSRC_BASE + 0x50)
+#define DVFSRC_EMI_MD2SPM0 (DVFSRC_BASE + 0x54)
+#define DVFSRC_EMI_MD2SPM1 (DVFSRC_BASE + 0x58)
+#define DVFSRC_EMI_MD2SPM2 (DVFSRC_BASE + 0x5C)
+#define DVFSRC_EMI_MD2SPM0_T (DVFSRC_BASE + 0x60)
+#define DVFSRC_EMI_MD2SPM1_T (DVFSRC_BASE + 0x64)
+#define DVFSRC_EMI_MD2SPM2_T (DVFSRC_BASE + 0x68)
+#define DVFSRC_VCORE_REQUEST (DVFSRC_BASE + 0x6C)
+#define DVFSRC_VCORE_REQUEST2 (DVFSRC_BASE + 0x70)
+#define DVFSRC_VCORE_REQUEST3 (DVFSRC_BASE + 0x74)
+#define DVFSRC_VCORE_REQUEST4 (DVFSRC_BASE + 0x78)
+#define DVFSRC_VCORE_HRT (DVFSRC_BASE + 0x7C)
+#define DVFSRC_VCORE_HRT2 (DVFSRC_BASE + 0x80)
+#define DVFSRC_VCORE_HRT3 (DVFSRC_BASE + 0x84)
+#define DVFSRC_VCORE_QOS0 (DVFSRC_BASE + 0x88)
+#define DVFSRC_VCORE_QOS1 (DVFSRC_BASE + 0x8C)
+#define DVFSRC_VCORE_QOS2 (DVFSRC_BASE + 0x90)
+#define DVFSRC_VCORE_MD2SPM0 (DVFSRC_BASE + 0x94)
+#define DVFSRC_VCORE_MD2SPM1 (DVFSRC_BASE + 0x98)
+#define DVFSRC_VCORE_MD2SPM2 (DVFSRC_BASE + 0x9C)
+#define DVFSRC_VCORE_MD2SPM0_T (DVFSRC_BASE + 0xA0)
+#define DVFSRC_VCORE_MD2SPM1_T (DVFSRC_BASE + 0xA4)
+#define DVFSRC_VCORE_MD2SPM2_T (DVFSRC_BASE + 0xA8)
+#define DVFSRC_MD_VSRAM_REMAP (DVFSRC_BASE + 0xBC)
+#define DVFSRC_HALT_SW_CONTROL (DVFSRC_BASE + 0xC0)
+#define DVFSRC_INT (DVFSRC_BASE + 0xC4)
+#define DVFSRC_INT_EN (DVFSRC_BASE + 0xC8)
+#define DVFSRC_INT_CLR (DVFSRC_BASE + 0xCC)
+#define DVFSRC_BW_MON_WINDOW (DVFSRC_BASE + 0xD0)
+#define DVFSRC_BW_MON_THRES_1 (DVFSRC_BASE + 0xD4)
+#define DVFSRC_BW_MON_THRES_2 (DVFSRC_BASE + 0xD8)
+#define DVFSRC_MD_TURBO (DVFSRC_BASE + 0xDC)
+#define DVFSRC_VCORE_USER_REQ (DVFSRC_BASE + 0xE4)
+#define DVFSRC_DEBOUNCE_FOUR (DVFSRC_BASE + 0xF0)
+#define DVFSRC_DEBOUNCE_RISE_FALL (DVFSRC_BASE + 0xF4)
+#define DVFSRC_TIMEOUT_NEXTREQ (DVFSRC_BASE + 0xF8)
+#define DVFSRC_LEVEL_LABEL_0_1 (DVFSRC_BASE + 0x100)
+#define DVFSRC_LEVEL_LABEL_2_3 (DVFSRC_BASE + 0x104)
+#define DVFSRC_LEVEL_LABEL_4_5 (DVFSRC_BASE + 0x108)
+#define DVFSRC_LEVEL_LABEL_6_7 (DVFSRC_BASE + 0x10C)
+#define DVFSRC_LEVEL_LABEL_8_9 (DVFSRC_BASE + 0x110)
+#define DVFSRC_LEVEL_LABEL_10_11 (DVFSRC_BASE + 0x114)
+#define DVFSRC_LEVEL_LABEL_12_13 (DVFSRC_BASE + 0x118)
+#define DVFSRC_LEVEL_LABEL_14_15 (DVFSRC_BASE + 0x11C)
+#define DVFSRC_MM_BW_0 (DVFSRC_BASE + 0x200)
+#define DVFSRC_MM_BW_1 (DVFSRC_BASE + 0x204)
+#define DVFSRC_MM_BW_2 (DVFSRC_BASE + 0x208)
+#define DVFSRC_MM_BW_3 (DVFSRC_BASE + 0x20C)
+#define DVFSRC_MM_BW_4 (DVFSRC_BASE + 0x210)
+#define DVFSRC_MM_BW_5 (DVFSRC_BASE + 0x214)
+#define DVFSRC_MM_BW_6 (DVFSRC_BASE + 0x218)
+#define DVFSRC_MM_BW_7 (DVFSRC_BASE + 0x21C)
+#define DVFSRC_MM_BW_8 (DVFSRC_BASE + 0x220)
+#define DVFSRC_MM_BW_9 (DVFSRC_BASE + 0x224)
+#define DVFSRC_MM_BW_10 (DVFSRC_BASE + 0x228)
+#define DVFSRC_MM_BW_11 (DVFSRC_BASE + 0x22C)
+#define DVFSRC_MM_BW_12 (DVFSRC_BASE + 0x230)
+#define DVFSRC_MM_BW_13 (DVFSRC_BASE + 0x234)
+#define DVFSRC_MM_BW_14 (DVFSRC_BASE + 0x238)
+#define DVFSRC_MM_BW_15 (DVFSRC_BASE + 0x23C)
+#define DVFSRC_MD_BW_0 (DVFSRC_BASE + 0x240)
+#define DVFSRC_MD_BW_1 (DVFSRC_BASE + 0x244)
+#define DVFSRC_MD_BW_2 (DVFSRC_BASE + 0x248)
+#define DVFSRC_MD_BW_3 (DVFSRC_BASE + 0x24C)
+#define DVFSRC_MD_BW_4 (DVFSRC_BASE + 0x250)
+#define DVFSRC_MD_BW_5 (DVFSRC_BASE + 0x254)
+#define DVFSRC_MD_BW_6 (DVFSRC_BASE + 0x258)
+#define DVFSRC_MD_BW_7 (DVFSRC_BASE + 0x25C)
+#define DVFSRC_SW_BW_0 (DVFSRC_BASE + 0x260)
+#define DVFSRC_SW_BW_1 (DVFSRC_BASE + 0x264)
+#define DVFSRC_SW_BW_2 (DVFSRC_BASE + 0x268)
+#define DVFSRC_SW_BW_3 (DVFSRC_BASE + 0x26C)
+#define DVFSRC_SW_BW_4 (DVFSRC_BASE + 0x270)
+#define DVFSRC_SW_BW_5 (DVFSRC_BASE + 0x274)
+#define DVFSRC_SW_BW_6 (DVFSRC_BASE + 0x278)
+#define DVFSRC_QOS_EN (DVFSRC_BASE + 0x280)
+#define DVFSRC_MD_BW_URG (DVFSRC_BASE + 0x284)
+#define DVFSRC_ISP_HRT (DVFSRC_BASE + 0x290)
+#define DVFSRC_HRT_BW_BASE (DVFSRC_BASE + 0x294)
+#define DVFSRC_SEC_SW_REQ (DVFSRC_BASE + 0x304)
+#define DVFSRC_EMI_MON_DEBOUNCE_TIME (DVFSRC_BASE + 0x308)
+#define DVFSRC_MD_LATENCY_IMPROVE (DVFSRC_BASE + 0x30C)
+#define DVFSRC_BASIC_CONTROL_3 (DVFSRC_BASE + 0x310)
+#define DVFSRC_DEBOUNCE_TIME (DVFSRC_BASE + 0x314)
+#define DVFSRC_LEVEL_MASK (DVFSRC_BASE + 0x318)
+#define DVFSRC_95MD_SCEN_EMI0 (DVFSRC_BASE + 0x500)
+#define DVFSRC_95MD_SCEN_EMI1 (DVFSRC_BASE + 0x504)
+#define DVFSRC_95MD_SCEN_EMI2 (DVFSRC_BASE + 0x508)
+#define DVFSRC_95MD_SCEN_EMI3 (DVFSRC_BASE + 0x50C)
+#define DVFSRC_95MD_SCEN_EMI0_T (DVFSRC_BASE + 0x510)
+#define DVFSRC_95MD_SCEN_EMI1_T (DVFSRC_BASE + 0x514)
+#define DVFSRC_95MD_SCEN_EMI2_T (DVFSRC_BASE + 0x518)
+#define DVFSRC_95MD_SCEN_EMI3_T (DVFSRC_BASE + 0x51C)
+#define DVFSRC_95MD_SCEN_EMI4 (DVFSRC_BASE + 0x520)
+#define DVFSRC_95MD_SCEN_BW0 (DVFSRC_BASE + 0x524)
+#define DVFSRC_95MD_SCEN_BW1 (DVFSRC_BASE + 0x528)
+#define DVFSRC_95MD_SCEN_BW2 (DVFSRC_BASE + 0x52C)
+#define DVFSRC_95MD_SCEN_BW3 (DVFSRC_BASE + 0x530)
+#define DVFSRC_95MD_SCEN_BW0_T (DVFSRC_BASE + 0x534)
+#define DVFSRC_95MD_SCEN_BW1_T (DVFSRC_BASE + 0x538)
+#define DVFSRC_95MD_SCEN_BW2_T (DVFSRC_BASE + 0x53C)
+#define DVFSRC_95MD_SCEN_BW3_T (DVFSRC_BASE + 0x540)
+#define DVFSRC_95MD_SCEN_BW4 (DVFSRC_BASE + 0x544)
+#define DVFSRC_MD_LEVEL_SW_REG (DVFSRC_BASE + 0x548)
+#define DVFSRC_RSRV_0 (DVFSRC_BASE + 0x600)
+#define DVFSRC_RSRV_1 (DVFSRC_BASE + 0x604)
+#define DVFSRC_RSRV_2 (DVFSRC_BASE + 0x608)
+#define DVFSRC_RSRV_3 (DVFSRC_BASE + 0x60C)
+#define DVFSRC_RSRV_4 (DVFSRC_BASE + 0x610)
+#define DVFSRC_RSRV_5 (DVFSRC_BASE + 0x614)
+#define DVFSRC_SPM_RESEND (DVFSRC_BASE + 0x630)
+#define DVFSRC_DEBUG_STA_0 (DVFSRC_BASE + 0x700)
+#define DVFSRC_DEBUG_STA_1 (DVFSRC_BASE + 0x704)
+#define DVFSRC_DEBUG_STA_2 (DVFSRC_BASE + 0x708)
+#define DVFSRC_DEBUG_STA_3 (DVFSRC_BASE + 0x70C)
+#define DVFSRC_DEBUG_STA_4 (DVFSRC_BASE + 0x710)
+#define DVFSRC_EMI_REQUEST7 (DVFSRC_BASE + 0x800)
+#define DVFSRC_EMI_HRT_1 (DVFSRC_BASE + 0x804)
+#define DVFSRC_EMI_HRT2_1 (DVFSRC_BASE + 0x808)
+#define DVFSRC_EMI_HRT3_1 (DVFSRC_BASE + 0x80C)
+#define DVFSRC_EMI_QOS3 (DVFSRC_BASE + 0x810)
+#define DVFSRC_EMI_QOS4 (DVFSRC_BASE + 0x814)
+#define DVFSRC_DDR_REQUEST (DVFSRC_BASE + 0xA00)
+#define DVFSRC_DDR_REQUEST2 (DVFSRC_BASE + 0xA04)
+#define DVFSRC_DDR_REQUEST3 (DVFSRC_BASE + 0xA08)
+#define DVFSRC_DDR_REQUEST4 (DVFSRC_BASE + 0xA0C)
+#define DVFSRC_DDR_REQUEST5 (DVFSRC_BASE + 0xA10)
+#define DVFSRC_DDR_REQUEST6 (DVFSRC_BASE + 0xA14)
+#define DVFSRC_DDR_REQUEST7 (DVFSRC_BASE + 0xA18)
+#define DVFSRC_DDR_HRT (DVFSRC_BASE + 0xA1C)
+#define DVFSRC_DDR_HRT2 (DVFSRC_BASE + 0xA20)
+#define DVFSRC_DDR_HRT3 (DVFSRC_BASE + 0xA24)
+#define DVFSRC_DDR_HRT_1 (DVFSRC_BASE + 0xA28)
+#define DVFSRC_DDR_HRT2_1 (DVFSRC_BASE + 0xA2C)
+#define DVFSRC_DDR_HRT3_1 (DVFSRC_BASE + 0xA30)
+#define DVFSRC_DDR_QOS0 (DVFSRC_BASE + 0xA34)
+#define DVFSRC_DDR_QOS1 (DVFSRC_BASE + 0xA38)
+#define DVFSRC_DDR_QOS2 (DVFSRC_BASE + 0xA3C)
+#define DVFSRC_DDR_QOS3 (DVFSRC_BASE + 0xA40)
+#define DVFSRC_DDR_QOS4 (DVFSRC_BASE + 0xA44)
+#define DVFSRC_DDR_MD2SPM0 (DVFSRC_BASE + 0xA48)
+#define DVFSRC_DDR_MD2SPM1 (DVFSRC_BASE + 0xA4C)
+#define DVFSRC_DDR_MD2SPM2 (DVFSRC_BASE + 0xA50)
+#define DVFSRC_DDR_MD2SPM0_T (DVFSRC_BASE + 0xA54)
+#define DVFSRC_DDR_MD2SPM1_T (DVFSRC_BASE + 0xA58)
+#define DVFSRC_DDR_MD2SPM2_T (DVFSRC_BASE + 0xA5C)
+#define DVFSRC_HRT_REQ_UNIT (DVFSRC_BASE + 0xA60)
+#define DVSFRC_HRT_REQ_MD_URG (DVFSRC_BASE + 0xA64)
+#define DVFSRC_HRT_REQ_MD_BW_0 (DVFSRC_BASE + 0xA68)
+#define DVFSRC_HRT_REQ_MD_BW_1 (DVFSRC_BASE + 0xA6C)
+#define DVFSRC_HRT_REQ_MD_BW_2 (DVFSRC_BASE + 0xA70)
+#define DVFSRC_HRT_REQ_MD_BW_3 (DVFSRC_BASE + 0xA74)
+#define DVFSRC_HRT_REQ_MD_BW_4 (DVFSRC_BASE + 0xA78)
+#define DVFSRC_HRT_REQ_MD_BW_5 (DVFSRC_BASE + 0xA7C)
+#define DVFSRC_HRT_REQ_MD_BW_6 (DVFSRC_BASE + 0xA80)
+#define DVFSRC_HRT_REQ_MD_BW_7 (DVFSRC_BASE + 0xA84)
+#define DVFSRC_HRT1_REQ_MD_BW_0 (DVFSRC_BASE + 0xA88)
+#define DVFSRC_HRT1_REQ_MD_BW_1 (DVFSRC_BASE + 0xA8C)
+#define DVFSRC_HRT1_REQ_MD_BW_2 (DVFSRC_BASE + 0xA90)
+#define DVFSRC_HRT1_REQ_MD_BW_3 (DVFSRC_BASE + 0xA94)
+#define DVFSRC_HRT1_REQ_MD_BW_4 (DVFSRC_BASE + 0xA98)
+#define DVFSRC_HRT1_REQ_MD_BW_5 (DVFSRC_BASE + 0xA9C)
+#define DVFSRC_HRT1_REQ_MD_BW_6 (DVFSRC_BASE + 0xAA0)
+#define DVFSRC_HRT1_REQ_MD_BW_7 (DVFSRC_BASE + 0xAA4)
+#define DVFSRC_HRT_REQ_MD_BW_8 (DVFSRC_BASE + 0xAA8)
+#define DVFSRC_HRT_REQ_MD_BW_9 (DVFSRC_BASE + 0xAAC)
+#define DVFSRC_HRT_REQ_MD_BW_10 (DVFSRC_BASE + 0xAB0)
+#define DVFSRC_HRT1_REQ_MD_BW_8 (DVFSRC_BASE + 0xAB4)
+#define DVFSRC_HRT1_REQ_MD_BW_9 (DVFSRC_BASE + 0xAB8)
+#define DVFSRC_HRT1_REQ_MD_BW_10 (DVFSRC_BASE + 0xABC)
+#define DVFSRC_HRT_REQ_BW_SW_REG (DVFSRC_BASE + 0xAC0)
+#define DVFSRC_HRT_REQUEST (DVFSRC_BASE + 0xAC4)
+#define DVFSRC_HRT_HIGH_2 (DVFSRC_BASE + 0xAC8)
+#define DVFSRC_HRT_HIGH_1 (DVFSRC_BASE + 0xACC)
+#define DVFSRC_HRT_HIGH (DVFSRC_BASE + 0xAD0)
+#define DVFSRC_HRT_LOW_2 (DVFSRC_BASE + 0xAD4)
+#define DVFSRC_HRT_LOW_1 (DVFSRC_BASE + 0xAD8)
+#define DVFSRC_HRT_LOW (DVFSRC_BASE + 0xADC)
+#define DVFSRC_DDR_ADD_REQUEST (DVFSRC_BASE + 0xAE0)
+#define DVFSRC_LAST (DVFSRC_BASE + 0xAE4)
+#define DVFSRC_LAST_L (DVFSRC_BASE + 0xAE8)
+#define DVFSRC_MD_SCENARIO (DVFSRC_BASE + 0xAEC)
+#define DVFSRC_RECORD_0_0 (DVFSRC_BASE + 0xAF0)
+#define DVFSRC_RECORD_0_1 (DVFSRC_BASE + 0xAF4)
+#define DVFSRC_RECORD_0_2 (DVFSRC_BASE + 0xAF8)
+#define DVFSRC_RECORD_0_3 (DVFSRC_BASE + 0xAFC)
+#define DVFSRC_RECORD_0_4 (DVFSRC_BASE + 0xB00)
+#define DVFSRC_RECORD_0_5 (DVFSRC_BASE + 0xB04)
+#define DVFSRC_RECORD_0_6 (DVFSRC_BASE + 0xB08)
+#define DVFSRC_RECORD_0_7 (DVFSRC_BASE + 0xB0C)
+#define DVFSRC_RECORD_0_L_0 (DVFSRC_BASE + 0xBF0)
+#define DVFSRC_RECORD_0_L_1 (DVFSRC_BASE + 0xBF4)
+#define DVFSRC_RECORD_0_L_2 (DVFSRC_BASE + 0xBF8)
+#define DVFSRC_RECORD_0_L_3 (DVFSRC_BASE + 0xBFC)
+#define DVFSRC_RECORD_0_L_4 (DVFSRC_BASE + 0xC00)
+#define DVFSRC_RECORD_0_L_5 (DVFSRC_BASE + 0xC04)
+#define DVFSRC_RECORD_0_L_6 (DVFSRC_BASE + 0xC08)
+#define DVFSRC_RECORD_0_L_7 (DVFSRC_BASE + 0xC0C)
+#define DVFSRC_EMI_REQUEST8 (DVFSRC_BASE + 0xCF0)
+#define DVFSRC_DDR_REQUEST8 (DVFSRC_BASE + 0xCF4)
+#define DVFSRC_EMI_HRT_2 (DVFSRC_BASE + 0xCF8)
+#define DVFSRC_EMI_HRT2_2 (DVFSRC_BASE + 0xCFC)
+#define DVFSRC_EMI_HRT3_2 (DVFSRC_BASE + 0xD00)
+#define DVFSRC_EMI_QOS5 (DVFSRC_BASE + 0xD04)
+#define DVFSRC_EMI_QOS6 (DVFSRC_BASE + 0xD08)
+#define DVFSRC_DDR_HRT_2 (DVFSRC_BASE + 0xD0C)
+#define DVFSRC_DDR_HRT2_2 (DVFSRC_BASE + 0xD10)
+#define DVFSRC_DDR_HRT3_2 (DVFSRC_BASE + 0xD14)
+#define DVFSRC_DDR_QOS5 (DVFSRC_BASE + 0xD18)
+#define DVFSRC_DDR_QOS6 (DVFSRC_BASE + 0xD1C)
+#define DVFSRC_VCORE_REQUEST5 (DVFSRC_BASE + 0xD20)
+#define DVFSRC_VCORE_HRT_1 (DVFSRC_BASE + 0xD24)
+#define DVFSRC_VCORE_HRT2_1 (DVFSRC_BASE + 0xD28)
+#define DVFSRC_VCORE_HRT3_1 (DVFSRC_BASE + 0xD2C)
+#define DVFSRC_VCORE_QOS3 (DVFSRC_BASE + 0xD30)
+#define DVFSRC_VCORE_QOS4 (DVFSRC_BASE + 0xD34)
+#define DVFSRC_HRT_HIGH_3 (DVFSRC_BASE + 0xD38)
+#define DVFSRC_HRT_LOW_3 (DVFSRC_BASE + 0xD3C)
+#define DVFSRC_BASIC_CONTROL_2 (DVFSRC_BASE + 0xD40)
+#define DVFSRC_CURRENT_LEVEL (DVFSRC_BASE + 0xD44)
+#define DVFSRC_TARGET_LEVEL (DVFSRC_BASE + 0xD48)
+#define DVFSRC_LEVEL_LABEL_16_17 (DVFSRC_BASE + 0xD4C)
+#define DVFSRC_LEVEL_LABEL_18_19 (DVFSRC_BASE + 0xD50)
+#define DVFSRC_LEVEL_LABEL_20_21 (DVFSRC_BASE + 0xD54)
+#define DVFSRC_LEVEL_LABEL_22_23 (DVFSRC_BASE + 0xD58)
+#define DVFSRC_LEVEL_LABEL_24_25 (DVFSRC_BASE + 0xD5C)
+#define DVFSRC_LEVEL_LABEL_26_27 (DVFSRC_BASE + 0xD60)
+#define DVFSRC_LEVEL_LABEL_28_29 (DVFSRC_BASE + 0xD64)
+#define DVFSRC_LEVEL_LABEL_30_31 (DVFSRC_BASE + 0xD68)
+#define DVFSRC_CURRENT_FORCE (DVFSRC_BASE + 0xD6C)
+#define DVFSRC_TARGET_FORCE (DVFSRC_BASE + 0xD70)
+#define DVFSRC_EMI_ADD_REQUEST (DVFSRC_BASE + 0xD74)
+
+#define VCORE_VB_EFUSE (0x11C105E8)
+
+#endif /* MT_SPM_VCOREFS_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h
new file mode 100644
index 0000000..89aa163
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SSPM_NOTIFIER_H
+#define MT_SPM_SSPM_NOTIFIER_H
+
+enum MT_SPM_SSPM_NOTIFY_ID {
+ MT_SPM_NOTIFY_LP_ENTER = 0U,
+ MT_SPM_NOTIFY_LP_LEAVE = 1U,
+ MT_SPM_NOTIFY_SUSPEND_VCORE_VOLTAGE = 2U,
+};
+
+int mt_spm_sspm_notify(int type, unsigned int lp_mode);
+
+static inline int mt_spm_sspm_notify_u32(int type, unsigned int lp_mode)
+{
+ return mt_spm_sspm_notify(type, lp_mode);
+}
+
+#endif /* MT_SPM_SSPM_NOTIFIER_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h
new file mode 100644
index 0000000..0b85c60
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SSPM_INTC_H
+#define MT_SPM_SSPM_INTC_H
+
+#include <mt_spm_reg.h>
+
+#define MT_SPM_SSPM_INTC_SEL_0 (0x10)
+#define MT_SPM_SSPM_INTC_SEL_1 (0x20)
+#define MT_SPM_SSPM_INTC_SEL_2 (0x40)
+#define MT_SPM_SSPM_INTC_SEL_3 (0x80)
+
+#define MT_SPM_SSPM_INTC_TRIGGER(id, sg) \
+ (((0x10 << id) | (sg << id)) & 0xff)
+
+#define MT_SPM_SSPM_INTC0_HIGH MT_SPM_SSPM_INTC_TRIGGER(0, 1)
+#define MT_SPM_SSPM_INTC0_LOW MT_SPM_SSPM_INTC_TRIGGER(0, 0)
+#define MT_SPM_SSPM_INTC1_HIGH MT_SPM_SSPM_INTC_TRIGGER(1, 1)
+#define MT_SPM_SSPM_INTC1_LOW MT_SPM_SSPM_INTC_TRIGGER(1, 0)
+#define MT_SPM_SSPM_INTC2_HIGH MT_SPM_SSPM_INTC_TRIGGER(2, 1)
+#define MT_SPM_SSPM_INTC2_LOW MT_SPM_SSPM_INTC_TRIGGER(2, 0)
+#define MT_SPM_SSPM_INTC3_HIGH MT_SPM_SSPM_INTC_TRIGGER(3, 1)
+#define MT_SPM_SSPM_INTC3_LOW MT_SPM_SSPM_INTC_TRIGGER(3, 0)
+
+/*
+ * mt8186 use cpc pbi as notify.
+ * Therefore, it won't need be notified by spm driver.
+ */
+#define DO_SPM_SSPM_LP_SUSPEND()
+#define DO_SPM_SSPM_LP_RESUME()
+
+#endif /* MT_SPM_SSPM_INTC_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c
new file mode 100644
index 0000000..20ef011
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <lib/mmio.h>
+
+#include <mt_spm_notifier.h>
+#include <mt_spm_sspm_intc.h>
+#include <sspm_reg.h>
+
+#define MT_SPM_SSPM_MBOX_OFF(x) (SSPM_MBOX_BASE + x)
+#define MT_SPM_MBOX(slot) MT_SPM_SSPM_MBOX_OFF((slot << 2UL))
+
+#define SSPM_MBOX_SPM_LP_LOOKUP1 MT_SPM_MBOX(0)
+#define SSPM_MBOX_SPM_LP_LOOKUP2 MT_SPM_MBOX(1)
+#define SSPM_MBOX_SPM_LP1 MT_SPM_MBOX(2)
+#define SSPM_MBOX_SPM_LP2 MT_SPM_MBOX(3)
+
+int mt_spm_sspm_notify(int type, unsigned int lp_mode)
+{
+ switch (type) {
+ case MT_SPM_NOTIFY_LP_ENTER:
+ mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode);
+ DO_SPM_SSPM_LP_SUSPEND();
+ break;
+ case MT_SPM_NOTIFY_LP_LEAVE:
+ mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode);
+ DO_SPM_SSPM_LP_RESUME();
+ break;
+ case MT_SPM_NOTIFY_SUSPEND_VCORE_VOLTAGE:
+ mmio_write_32(SSPM_MBOX_SPM_LP2, lp_mode);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8186/drivers/spm/pcm_def.h b/plat/mediatek/mt8186/drivers/spm/pcm_def.h
new file mode 100644
index 0000000..eb2db33
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/pcm_def.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PCM_DEF_H
+#define PCM_DEF_H
+
+/*
+ * Auto generated by DE, please DO NOT modify this file directly.
+ */
+
+/* --- R0 Define --- */
+#define R0_SC_26M_CK_OFF (1U << 0)
+#define R0_SC_TX_TRACK_RETRY_EN (1U << 1)
+#define R0_SC_MEM_CK_OFF (1U << 2)
+#define R0_SC_AXI_CK_OFF (1U << 3)
+#define R0_SC_DR_SRAM_LOAD (1U << 4)
+#define R0_SC_MD26M_CK_OFF (1U << 5)
+#define R0_SC_DPY_MODE_SW (1U << 6)
+#define R0_SC_DMSUS_OFF (1U << 7)
+#define R0_SC_DPY_2ND_DLL_EN (1U << 8)
+#define R0_SC_DR_SRAM_RESTORE (1U << 9)
+#define R0_SC_MPLLOUT_OFF (1U << 10)
+#define R0_SC_TX_TRACKING_DIS (1U << 11)
+#define R0_SC_DPY_DLL_EN (1U << 12)
+#define R0_SC_DPY_DLL_CK_EN (1U << 13)
+#define R0_SC_DPY_VREF_EN (1U << 14)
+#define R0_SC_PHYPLL_EN (1U << 15)
+#define R0_SC_DDRPHY_FB_CK_EN (1U << 16)
+#define R0_SC_DPY_BCLK_ENABLE (1U << 17)
+#define R0_SC_MPLL_OFF (1U << 18)
+#define R0_SC_SHU_RESTORE (1U << 19)
+#define R0_SC_CKSQ0_OFF (1U << 20)
+#define R0_SC_DR_SHU_LEVEL_SRAM_LATCH (1U << 21)
+#define R0_SC_DR_SHU_EN (1U << 22)
+#define R0_SC_DPHY_PRECAL_UP (1U << 23)
+#define R0_SC_MPLL_S_OFF (1U << 24)
+#define R0_SC_DPHY_RXDLY_TRACKING_EN (1U << 25)
+#define R0_SC_PHYPLL_SHU_EN (1U << 26)
+#define R0_SC_PHYPLL2_SHU_EN (1U << 27)
+#define R0_SC_PHYPLL_MODE_SW (1U << 28)
+#define R0_SC_PHYPLL2_MODE_SW (1U << 29)
+#define R0_SC_DR0_SHU_LEVEL (1U << 30)
+#define R0_SC_DR1_SHU_LEVEL (1U << 31)
+/* --- R7 Define --- */
+#define R7_PWRAP_SLEEP_REQ (1U << 0)
+#define R7_EMI_CLK_OFF_REQ_PCM (1U << 1)
+#define R7_PCM_BUS_PROTECT_REQ (1U << 2)
+#define R7_SPM_CK_UPDATE (1U << 3)
+#define R7_SPM_CK_SEL0 (1U << 4)
+#define R7_SPM_CK_SEL1 (1U << 5)
+#define R7_SPM_LEAVE_DEEPIDLE_REQ (1U << 6)
+#define R7_SC_FHC_PAUSE_MPLL (1U << 7)
+#define R7_SC_26M_CK_SEL (1U << 8)
+#define R7_PCM_TIMER_SET (1U << 9)
+#define R7_PCM_TIMER_CLR (1U << 10)
+#define R7_SPM_LEAVE_SUSPEND_REQ (1U << 11)
+#define R7_CSYSPWRUPACK (1U << 12)
+#define R7_PCM_IM_SLP_EN (1U << 13)
+#define R7_SRCCLKENO0 (1U << 14)
+#define R7_FORCE_DDR_EN_WAKE (1U << 15)
+#define R7_SPM_APSRC_INTERNAL_ACK (1U << 16)
+#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17)
+#define R7_SC_AXI_DCM_DIS (1U << 18)
+#define R7_SC_FHC_PAUSE_MEM (1U << 19)
+#define R7_SC_FHC_PAUSE_MAIN (1U << 20)
+#define R7_SRCCLKENO1 (1U << 21)
+#define R7_PCM_WDT_KICK_P (1U << 22)
+#define R7_SPM2EMI_S1_MODE_ASYNC (1U << 23)
+#define R7_SC_DDR_PST_REQ_PCM (1U << 24)
+#define R7_SC_DDR_PST_ABORT_REQ_PCM (1U << 25)
+#define R7_PMIC_IRQ_REQ_EN (1U << 26)
+#define R7_FORCE_F26M_WAKE (1U << 27)
+#define R7_FORCE_APSRC_WAKE (1U << 28)
+#define R7_FORCE_INFRA_WAKE (1U << 29)
+#define R7_FORCE_VRF18_WAKE (1U << 30)
+#define R7_SPM_DDR_EN_INTERNAL_ACK (1U << 31)
+/* --- R12 Define --- */
+#define R12_PCM_TIMER (1U << 0)
+#define R12_TWAM_IRQ_B (1U << 1)
+#define R12_KP_IRQ_B (1U << 2)
+#define R12_APWDT_EVENT_B (1U << 3)
+#define R12_APXGPT1_EVENT_B (1U << 4)
+#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5)
+#define R12_EINT_EVENT_B (1U << 6)
+#define R12_CONN_WDT_IRQ_B (1U << 7)
+#define R12_CCIF0_EVENT_B (1U << 8)
+#define R12_LOWBATTERY_IRQ_B (1U << 9)
+#define R12_SSPM2SPM_WAKEUP_B (1U << 10)
+#define R12_SCP2SPM_WAKEUP_B (1U << 11)
+#define R12_ADSP2SPM_WAKEUP_B (1U << 12)
+#define R12_PCM_WDT_WAKEUP_B (1U << 13)
+#define R12_USBX_CDSC_B (1U << 14)
+#define R12_USBX_POWERDWN_B (1U << 15)
+#define R12_SYS_TIMER_EVENT_B (1U << 16)
+#define R12_EINT_EVENT_SECURE_B (1U << 17)
+#define R12_CCIF1_EVENT_B (1U << 18)
+#define R12_UART0_IRQ_B (1U << 19)
+#define R12_AFE_IRQ_MCU_B (1U << 20)
+#define R12_THERM_CTRL_EVENT_B (1U << 21)
+#define R12_SYS_CIRQ_IRQ_B (1U << 22)
+#define R12_MD2AP_PEER_EVENT_B (1U << 23)
+#define R12_CSYSPWREQ_B (1U << 24)
+#define R12_NNA_WAKEUP (1U << 25)
+#define R12_CLDMA_EVENT_B (1U << 26)
+#define R12_SEJ_EVENT_B (1U << 27)
+#define R12_REG_CPU_WAKEUP (1U << 28)
+#define R12_CPU_IRQOUT (1U << 29)
+#define R12_CPU_WFI (1U << 30)
+#define R12_MCUSYS_IDLE (1U << 31)
+/* --- R12ext Define --- */
+#define R12EXT_26M_WAKE (1U << 0)
+#define R12EXT_26M_SLEEP (1U << 1)
+#define R12EXT_INFRA_WAKE (1U << 2)
+#define R12EXT_INFRA_SLEEP (1U << 3)
+#define R12EXT_APSRC_WAKE (1U << 4)
+#define R12EXT_APSRC_SLEEP (1U << 5)
+#define R12EXT_VRF18_WAKE (1U << 6)
+#define R12EXT_VRF18_SLEEP (1U << 7)
+#define R12EXT_DVFS_WAKE (1U << 8)
+#define R12EXT_DDREN_WAKE (1U << 9)
+#define R12EXT_DDREN_SLEEP (1U << 10)
+#define R12EXT_MCU_PM_WFI (1U << 11)
+#define R12EXT_SSPM_IDLE (1U << 12)
+#define R12EXT_CONN_SRCCLKENB (1U << 13)
+#define R12EXT_DRAMC_MD32_WFI_MERGE (1U << 14)
+#define R12EXT_SW_MAILBOX_WAKE (1U << 15)
+#define R12EXT_SSPM_MAILBOX_WAKE (1U << 16)
+#define R12EXT_ADSP_MAILBOX_WAKE (1U << 17)
+#define R12EXT_SCP_MAILBOX_WAKE (1U << 18)
+#define R12EXT_SPM_LEAVE_SUSPEND_ACK (1U << 19)
+#define R12EXT_SPM_LEAVE_DEEPIDLE_ACK (1U << 20)
+#define R12EXT_BIT21 (1U << 21)
+#define R12EXT_BIT22 (1U << 22)
+#define R12EXT_BIT23 (1U << 23)
+#define R12EXT_BIT24 (1U << 24)
+#define R12EXT_BIT25 (1U << 25)
+#define R12EXT_BIT26 (1U << 26)
+#define R12EXT_BIT27 (1U << 27)
+#define R12EXT_BIT28 (1U << 28)
+#define R12EXT_BIT29 (1U << 29)
+#define R12EXT_BIT30 (1U << 30)
+#define R12EXT_BIT31 (1U << 31)
+/* --- R13 Define --- */
+#define R13_SRCCLKENI0 (1U << 0)
+#define R13_SRCCLKENI1 (1U << 1)
+#define R13_MD_0_SRCCLKENA (1U << 2)
+#define R13_MD_0_APSRC_REQ (1U << 3)
+#define R13_CONN_DDREN (1U << 4)
+#define R13_MD_1_SRCCLKENA (1U << 5)
+#define R13_SSPM_SRCCLKENA (1U << 6)
+#define R13_SSPM_APSRC_REQ (1U << 7)
+#define R13_MD_1_STATE (1U << 8)
+#define R13_RC_SRCCLKENO_ACK (1U << 9)
+#define R13_MM_STATE (1U << 10)
+#define R13_SSPM_STATE (1U << 11)
+#define R13_MD_0_DDREN (1U << 12)
+#define R13_CONN_STATE (1U << 13)
+#define R13_CONN_SRCCLKENA (1U << 14)
+#define R13_CONN_APSRC_REQ (1U << 15)
+#define R13_SC_DDR_PST_ACK_ALL (1U << 16)
+#define R13_SC_DDR_PST_ABORT_ACK_ALL (1U << 17)
+#define R13_SCP_STATE (1U << 18)
+#define R13_CSYSPWRUPREQ (1U << 19)
+#define R13_PWRAP_SLEEP_ACK (1U << 20)
+#define R13_SC_EMI_CLK_OFF_ACK_ALL (1U << 21)
+#define R13_AUDIO_DSP_STATE (1U << 22)
+#define R13_SC_DMDRAMCSHU_ACK_ALL (1U << 23)
+#define R13_CONN_SRCCLKENB (1U << 24)
+#define R13_SC_DR_SRAM_LOAD_ACK_ALL (1U << 25)
+#define R13_SUBSYS_IDLE_SIGNALS0 (1U << 26)
+#define R13_DVFS_STATE (1U << 27)
+#define R13_SC_DR_SRAM_PLL_LOAD_ACK_ALL (1U << 28)
+#define R13_SC_DR_SRAM_RESTORE_ACK_ALL (1U << 29)
+#define R13_MD_0_VRF18_REQ (1U << 30)
+#define R13_DDR_EN_STATE (1U << 31)
+
+#endif /* PCM_DEF_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/sleep_def.h b/plat/mediatek/mt8186/drivers/spm/sleep_def.h
new file mode 100644
index 0000000..d007939
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spm/sleep_def.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SLEEP_DEF_H
+#define SLEEP_DEF_H
+
+/*
+ * Auto generated by DE, please DO NOT modify this file directly.
+ */
+
+/* --- SPM Flag Define --- */
+#define SPM_FLAG_DISABLE_CPU_PDN (1U << 0)
+#define SPM_FLAG_DISABLE_INFRA_PDN (1U << 1)
+#define SPM_FLAG_DISABLE_DDRPHY_PDN (1U << 2)
+#define SPM_FLAG_DISABLE_VCORE_DVS (1U << 3)
+#define SPM_FLAG_DISABLE_VCORE_DFS (1U << 4)
+#define SPM_FLAG_DISABLE_COMMON_SCENARIO (1U << 5)
+#define SPM_FLAG_DISABLE_BUS_CLK_OFF (1U << 6)
+#define SPM_FLAG_DISABLE_ARMPLL_OFF (1U << 7)
+#define SPM_FLAG_KEEP_CSYSPWRACK_HIGH (1U << 8)
+#define SPM_FLAG_ENABLE_LVTS_WORKAROUND (1U << 9)
+#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10)
+#define SPM_FLAG_SSPM_INFRA_SLEEP_MODE (1U << 11)
+#define SPM_FLAG_ENABLE_SPM_DBG_WDT_DUMP (1U << 12)
+#define SPM_FLAG_USE_SRCCLKENO2 (1U << 13)
+#define SPM_FLAG_RESERVED_BIT14 (1U << 14)
+#define SPM_FLAG_ENABLE_TIA_WORKAROUND (1U << 15)
+#define SPM_FLAG_DISABLE_SYSRAM_SLEEP (1U << 16)
+#define SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP (1U << 17)
+#define SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP (1U << 18)
+#define SPM_FLAG_RESERVED_BIT19 (1U << 19)
+#define SPM_FLAG_ENABLE_VOLTAGE_BIN (1U << 20)
+#define SPM_FLAG_RESERVED_BIT21 (1U << 21)
+#define SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP (1U << 22)
+#define SPM_FLAG_DISABLE_SRAM_EVENT (1U << 23)
+#define SPM_FLAG_RESERVED_BIT24 (1U << 24)
+#define SPM_FLAG_RESERVED_BIT25 (1U << 25)
+#define SPM_FLAG_RESERVED_BIT26 (1U << 26)
+#define SPM_FLAG_DDREN_STATE (1U << 27)
+#define SPM_FLAG_VTCXO_STATE (1U << 28)
+#define SPM_FLAG_INFRA_STATE (1U << 29)
+#define SPM_FLAG_VRF18_STATE (1U << 30)
+#define SPM_FLAG_APSRC_STATE (1U << 31)
+#define SPM_FLAG_SYSTEM_POWER_STATE (1U << 28)
+/* --- SPM Flag1 Define --- */
+#define SPM_FLAG1_DISABLE_AXI_BUS_TO_26M (1U << 0)
+#define SPM_FLAG1_DISABLE_SYSPLL_OFF (1U << 1)
+#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 2)
+#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 3)
+#define SPM_FLAG1_FW_SET_ULPOSC_ON (1U << 4)
+#define SPM_FLAG1_RESERVED_BIT5 (1U << 5)
+#define SPM_FLAG1_ENABLE_REKICK (1U << 6)
+#define SPM_FLAG1_RESERVED_BIT7 (1U << 7)
+#define SPM_FLAG1_RESERVED_BIT8 (1U << 8)
+#define SPM_FLAG1_RESERVED_BIT9 (1U << 9)
+#define SPM_FLAG1_DISABLE_SRCLKEN_LOW (1U << 10)
+#define SPM_FLAG1_DISABLE_SCP_CLK_SWITCH (1U << 11)
+#define SPM_FLAG1_RESERVED_BIT12 (1U << 12)
+#define SPM_FLAG1_RESERVED_BIT13 (1U << 13)
+#define SPM_FLAG1_RESERVED_BIT14 (1U << 14)
+#define SPM_FLAG1_RESERVED_BIT15 (1U << 15)
+#define SPM_FLAG1_RESERVED_BIT16 (1U << 16)
+#define SPM_FLAG1_RESERVED_BIT17 (1U << 17)
+#define SPM_FLAG1_RESERVED_BIT18 (1U << 18)
+#define SPM_FLAG1_RESERVED_BIT19 (1U << 19)
+#define SPM_FLAG1_DISABLE_DEVAPC_SRAM_SLEEP (1U << 20)
+#define SPM_FLAG1_RESERVED_BIT21 (1U << 21)
+#define SPM_FLAG1_RESERVED_BIT22 (1U << 22)
+#define SPM_FLAG1_RESERVED_BIT23 (1U << 23)
+#define SPM_FLAG1_DISABLE_SCP_VREQ_MASK_CONTROL (1U << 24)
+#define SPM_FLAG1_RESERVED_BIT25 (1U << 25)
+#define SPM_FLAG1_RESERVED_BIT26 (1U << 26)
+#define SPM_FLAG1_RESERVED_BIT27 (1U << 27)
+#define SPM_FLAG1_RESERVED_BIT28 (1U << 28)
+#define SPM_FLAG1_RESERVED_BIT29 (1U << 29)
+#define SPM_FLAG1_RESERVED_BIT30 (1U << 30)
+#define SPM_FLAG1_ENABLE_MCUPM_OFF (1U << 31)
+/* --- SPM DEBUG Define --- */
+#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0)
+#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1)
+#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2)
+#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3)
+#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4)
+#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5)
+#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6)
+#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7)
+#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8)
+#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9)
+#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC (1U << 10)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_STATE (1U << 11)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_STATE (1U << 12)
+#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN (1U << 13)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_STATE (1U << 14)
+#define SPM_DBG_DEBUG_IDX_SYSRAM_SLP (1U << 15)
+#define SPM_DBG_DEBUG_IDX_SYSRAM_ON (1U << 16)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_SLP (1U << 17)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_ON (1U << 18)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 19)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_ON (1U << 20)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_SLP (1U << 21)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_ON (1U << 22)
+#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP_ABORT (1U << 23)
+#define SPM_DBG_DEBUG_IDX_SPM_GO_WAKEUP_NOW (1U << 27)
+#define SPM_DBG_DEBUG_IDX_VTCXO_STATE (1U << 28)
+#define SPM_DBG_DEBUG_IDX_INFRA_STATE (1U << 29)
+#define SPM_DBG_DEBUG_IDX_VRR18_STATE (1U << 30)
+#define SPM_DBG_DEBUG_IDX_APSRC_STATE (1U << 31)
+/* --- SPM DEBUG1 Define --- */
+#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_LP (1U << 0)
+#define SPM_DBG1_DEBUG_IDX_VCORE_DVFS_START (1U << 1)
+#define SPM_DBG1_DEBUG_IDX_SYSPLL_OFF (1U << 2)
+#define SPM_DBG1_DEBUG_IDX_SYSPLL_ON (1U << 3)
+#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_VCORE_DVFS (1U << 4)
+#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_OFF (1U << 5)
+#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_ON (1U << 6)
+#define SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT (1U << 7)
+#define SPM_DBG1_RESERVED_BIT8 (1U << 8)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_ULPOSC (1U << 11)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_26M (1U << 12)
+#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_32K (1U << 13)
+#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_26M (1U << 14)
+#define SPM_DBG1_DEBUG_IDX_BUS_CLK_OFF (1U << 15)
+#define SPM_DBG1_DEBUG_IDX_BUS_CLK_ON (1U << 16)
+#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_LOW (1U << 17)
+#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_HIGH (1U << 18)
+#define SPM_DBG1_DEBUG_IDX_MCUPM_WAKE_IRQ (1U << 19)
+#define SPM_DBG1_DEBUG_IDX_ULPOSC_IS_OFF_BUT_SHOULD_ON (1U << 20)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT (1U << 23)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT (1U << 24)
+#define SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT (1U << 25)
+#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT (1U << 26)
+#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT (1U << 27)
+#define SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT (1U << 28)
+#define SPM_DBG1_DEBUG_IDX_SPM_TIMER_RST_DVFS (1U << 29)
+#define SPM_DBG1_DEBUG_IDX_SPM_DISABLE_DDREN_EVENT (1U << 30)
+#define MCUPM_RESTORE (1U << 31)
+
+/* Macro and Inline */
+#define is_cpu_pdn(flags) (((flags) & SPM_FLAG_DISABLE_CPU_PDN) == 0U)
+#define is_infra_pdn(flags) (((flags) & SPM_FLAG_DISABLE_INFRA_PDN) == 0U)
+#define is_ddrphy_pdn(flags) (((flags) & SPM_FLAG_DISABLE_DDRPHY_PDN) == 0U)
+
+#endif /* SLEEP_DEF_H */
diff --git a/plat/mediatek/mt8186/drivers/spmc/mtspmc.c b/plat/mediatek/mt8186/drivers/spmc/mtspmc.c
new file mode 100644
index 0000000..91ef096
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spmc/mtspmc.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <mtspmc.h>
+#include <mtspmc_private.h>
+#include <plat/common/platform.h>
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+ mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+ /* Clear cpu's cpc sw hint */
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
+{
+ assert(cluster == 0U);
+
+ mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
+{
+ assert(cluster == 0U);
+
+ return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
+}
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
+{
+ uint32_t reg;
+
+ assert(cluster == 0U);
+
+ reg = per_cluster(cluster, MCUCFG_INITARCH);
+
+ if (arm64) {
+ mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ } else {
+ mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ }
+}
+
+/*
+ * Return subsystem's power state.
+ *
+ * @mask: mask to SPM_CPU_PWR_STATUS to query the power state
+ * of one subsystem.
+ * RETURNS:
+ * 0 (the subsys was powered off)
+ * 1 (the subsys was powered on)
+ */
+bool spm_get_powerstate(uint32_t mask)
+{
+ return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask);
+}
+
+bool spm_get_cluster_powerstate(unsigned int cluster)
+{
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(MP0_CPUTOP);
+}
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
+{
+ uint32_t mask = BIT(cpu);
+
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(mask);
+}
+
+int spmc_init(void)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+
+ INFO("SPM: enable CPC mode\n");
+
+ mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
+
+ mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
+
+ mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+
+ /* Clear bootup cpu's cpc sw hint */
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+
+ return 0;
+}
+
+/*
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
+{
+ /* info CPC that CPU hotplug on */
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+
+ /* Set mp0_spmc_pwr_on_cpuX = 1 */
+ mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+
+ /* wait for power on ack */
+ while (!spm_get_cpu_powerstate(cluster, cpu))
+ ;
+
+ /* info CPC that CPU hotplug off */
+ mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+}
+
+/*
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
+{
+ /* Set mp0_spmc_pwr_on_cpuX = 0 */
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+}
+
+/*
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(unsigned int cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
+
+/*
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(unsigned int cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
diff --git a/plat/mediatek/mt8186/drivers/spmc/mtspmc.h b/plat/mediatek/mt8186/drivers/spmc/mtspmc.h
new file mode 100644
index 0000000..768599b
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spmc/mtspmc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+#include <stdint.h>
+
+int spmc_init(void);
+
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu);
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu);
+
+void spm_poweroff_cluster(unsigned int cluster);
+void spm_poweron_cluster(unsigned int cluster);
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu);
+bool spm_get_cluster_powerstate(unsigned int cluster);
+bool spm_get_powerstate(uint32_t mask);
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64);
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu);
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h
new file mode 100644
index 0000000..472b54c
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_PRIVATE_H
+#define MTSPMC_PRIVATE_H
+
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+unsigned long read_cpuectlr(void);
+void write_cpuectlr(unsigned long cpuectlr);
+
+unsigned long read_cpupwrctlr_el1(void);
+void write_cpupwrctlr_el1(unsigned long cpuectlr);
+
+/* per_cpu/cluster helper */
+struct per_cpu_reg {
+ unsigned int cluster_addr;
+ unsigned int cpu_stride;
+};
+
+#define per_cpu(cluster, cpu, reg) \
+ (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
+
+#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
+
+#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs))
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs))
+
+/* SPMC related registers */
+#define SPM_POWERON_CONFIG_EN SPM_REG(0x000)
+/* bit-fields of SPM_POWERON_CONFIG_EN */
+#define PROJECT_CODE (U(0xb16) << 16)
+#define BCLK_CG_EN BIT(0)
+
+#define SPM_PWR_STATUS SPM_REG(0x16c)
+#define SPM_PWR_STATUS_2ND SPM_REG(0x170)
+#define SPM_CPU_PWR_STATUS SPM_REG(0x174)
+
+/* bit-fields of SPM_PWR_STATUS */
+#define MD BIT(0)
+#define CONN BIT(1)
+#define DDRPHY BIT(2)
+#define DISP BIT(3)
+#define MFG BIT(4)
+#define ISP BIT(5)
+#define INFRA BIT(6)
+#define VDEC BIT(7)
+#define MP0_CPUTOP BIT(8)
+#define MP0_CPU0 BIT(9)
+#define MP0_CPU1 BIT(10)
+#define MP0_CPU2 BIT(11)
+#define MP0_CPU3 BIT(12)
+#define MCUSYS BIT(14)
+#define MP0_CPU4 BIT(15)
+#define MP0_CPU5 BIT(16)
+#define MP0_CPU6 BIT(17)
+#define MP0_CPU7 BIT(18)
+#define VEN BIT(21)
+
+/* SPMC related registers */
+#define SPM_MCUSYS_PWR_CON SPM_REG(0x200)
+#define SPM_MP0_CPUTOP_PWR_CON SPM_REG(0x204)
+#define SPM_MP0_CPU0_PWR_CON SPM_REG(0x208)
+#define SPM_MP0_CPU1_PWR_CON SPM_REG(0x20c)
+#define SPM_MP0_CPU2_PWR_CON SPM_REG(0x210)
+#define SPM_MP0_CPU3_PWR_CON SPM_REG(0x214)
+#define SPM_MP0_CPU4_PWR_CON SPM_REG(0x218)
+#define SPM_MP0_CPU5_PWR_CON SPM_REG(0x21c)
+#define SPM_MP0_CPU6_PWR_CON SPM_REG(0x220)
+#define SPM_MP0_CPU7_PWR_CON SPM_REG(0x224)
+
+/* bit-fields of SPM_*_PWR_CON */
+#define PWR_ON_ACK BIT(31)
+#define VPROC_EXT_OFF BIT(7)
+#define DORMANT_EN BIT(6)
+#define RESETPWRON_CONFIG BIT(5)
+#define PWR_CLK_DIS BIT(4)
+#define PWR_ON BIT(2)
+#define PWR_RST_B BIT(0)
+
+/* per_cpu registers for SPM_MP0_CPU_PWR_CON */
+static const struct per_cpu_reg SPM_CPU_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
+};
+
+/* per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
+static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
+};
+
+/* MCUCFG related registers */
+#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4)
+/* reset vectors */
+#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900)
+#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908)
+#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910)
+#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918)
+#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920)
+#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928)
+#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930)
+#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938)
+
+/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
+};
+
+/* per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
+};
+
+#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
+/* CPC control */
+#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
+
+/* bit-fields of CPC_FLOW_CTRL_CFG */
+#define CPC_CTRL_ENABLE BIT(16)
+#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
+
+/* bit-fields of CPC_SPMC_PWR_STATUS */
+#define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0)
+
+/* APB module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
+#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224)
+#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228)
+#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0)
+#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4)
+#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250)
+#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac)
+
+/* bit-fields of INFRA_TOPAXI_PROTECTEN */
+#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12)
+#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12))
+
+/* SPARK */
+#define VOLTAGE_04 U(0x40)
+#define VOLTAGE_05 U(0x60)
+
+#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200)
+#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334)
+#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340)
+
+/* bit-fields of CPU0_ILDO_CONTROL5 */
+#define ILDO_RET_VOSEL GENMASK(7, 0)
+
+/* bit-fields of PTP3_CPU_SPMC_SW_CFG */
+#define SW_SPARK_EN BIT(0)
+
+/* bit-fields of CPU0_ILDO_CONTROL8 */
+#define ILDO_BYPASS_B BIT(0)
+
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+ { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL5[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL8[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8186/include/mcucfg.h b/plat/mediatek/mt8186/include/mcucfg.h
new file mode 100644
index 0000000..78a01a8
--- /dev/null
+++ b/plat/mediatek/mt8186/include/mcucfg.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCUCFG_H
+#define MCUCFG_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER__ */
+
+#include <platform_def.h>
+
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+
+#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
+#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
+
+#define MP2_CPUCFG MCUCFG_REG(0x2208)
+
+#define MP2_CPU0_STANDBYWFE BIT(4)
+#define MP2_CPU1_STANDBYWFE BIT(5)
+
+#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788)
+#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C)
+#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790)
+
+#define sw_spark_en BIT(0)
+#define sw_no_wait_for_q_channel BIT(1)
+#define sw_fsm_override BIT(2)
+#define sw_logic_pre1_pdb BIT(3)
+#define sw_logic_pre2_pdb BIT(4)
+#define sw_logic_pdb BIT(5)
+#define sw_iso BIT(6)
+#define sw_sram_sleepb (U(0x3F) << 7)
+#define sw_sram_isointb BIT(13)
+#define sw_clk_dis BIT(14)
+#define sw_ckiso BIT(15)
+#define sw_pd (U(0x3F) << 16)
+#define sw_hot_plug_reset BIT(22)
+#define sw_pwr_on_override_en BIT(23)
+#define sw_pwr_on BIT(24)
+#define sw_coq_dis BIT(25)
+#define logic_pdbo_all_off_ack BIT(26)
+#define logic_pdbo_all_on_ack BIT(27)
+#define logic_pre2_pdbo_all_on_ack BIT(28)
+#define logic_pre1_pdbo_all_on_ack BIT(29)
+
+
+#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
+ (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
+
+#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30)
+#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34)
+#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38)
+#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C)
+
+#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30)
+#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34)
+#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38)
+#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C)
+
+#define cpu_sw_spark_en BIT(0)
+#define cpu_sw_no_wait_for_q_channel BIT(1)
+#define cpu_sw_fsm_override BIT(2)
+#define cpu_sw_logic_pre1_pdb BIT(3)
+#define cpu_sw_logic_pre2_pdb BIT(4)
+#define cpu_sw_logic_pdb BIT(5)
+#define cpu_sw_iso BIT(6)
+#define cpu_sw_sram_sleepb BIT(7)
+#define cpu_sw_sram_isointb BIT(8)
+#define cpu_sw_clk_dis BIT(9)
+#define cpu_sw_ckiso BIT(10)
+#define cpu_sw_pd (U(0x1F) << 11)
+#define cpu_sw_hot_plug_reset BIT(16)
+#define cpu_sw_powr_on_override_en BIT(17)
+#define cpu_sw_pwr_on BIT(18)
+#define cpu_spark2ldo_allswoff BIT(19)
+#define cpu_pdbo_all_on_ack BIT(20)
+#define cpu_pre2_pdbo_allon_ack BIT(21)
+#define cpu_pre1_pdbo_allon_ack BIT(22)
+
+/* CPC related registers */
+#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714)
+#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804)
+#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818)
+#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c)
+#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824)
+#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac)
+#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10)
+#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14)
+#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20)
+#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70)
+#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74)
+#define SPARK2LDO MCUCFG_REG(0x2700)
+/* APB module mcucfg */
+#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000)
+#define MP0_AXI_CONFIG MCUCFG_REG(0x02C)
+#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030)
+#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034)
+#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038)
+#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8))
+#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C)
+#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054)
+#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064)
+
+#define MP0_RW_RSVD0 MCUCFG_REG(0x06C)
+
+
+#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200)
+#define MP1_AXI_CONFIG MCUCFG_REG(0x22C)
+#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230)
+#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234)
+#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238)
+#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8))
+#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C)
+#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254)
+#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264)
+
+#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740)
+#define SYNC_DCM_CONFIG MCUCFG_REG(0x744)
+
+#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0)
+
+#define MP0_SPMC MCUCFG_REG(0x788)
+#define MP1_SPMC MCUCFG_REG(0x78C)
+#define MP2_AXI_CONFIG MCUCFG_REG(0x220C)
+#define MP2_AXI_CONFIG_ACINACTM BIT(0)
+#define MP2_AXI_CONFIG_AINACTS BIT(4)
+
+#define MPx_AXI_CONFIG_ACINACTM BIT(4)
+#define MPx_AXI_CONFIG_AINACTS BIT(5)
+#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
+
+#define MP0_CPU0_STANDBYWFE BIT(20)
+#define MP0_CPU1_STANDBYWFE BIT(21)
+#define MP0_CPU2_STANDBYWFE BIT(22)
+#define MP0_CPU3_STANDBYWFE BIT(23)
+
+#define MP1_CPU0_STANDBYWFE BIT(20)
+#define MP1_CPU1_STANDBYWFE BIT(21)
+#define MP1_CPU2_STANDBYWFE BIT(22)
+#define MP1_CPU3_STANDBYWFE BIT(23)
+
+#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00)
+#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04)
+#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08)
+#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00)
+#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04)
+#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08)
+
+#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008)
+#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0)
+#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4)
+
+#define MP2_COQ MCUCFG_REG(0x22BC)
+#define MP2_COQ_SW_DIS BIT(0)
+
+#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400)
+#define MP2_CA15M_MON_L MCUCFG_REG(0x2404)
+
+#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430)
+#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438)
+#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434)
+#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C)
+
+#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068)
+#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268)
+#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C)
+
+#define MP2_SW_RST_B BIT(0)
+#define MP2_TOPAON_APB_MASK BIT(1)
+
+#define B_SW_HOT_PLUG_RESET BIT(30)
+
+#define B_SW_PD_OFFSET (18U)
+#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET)
+
+#define B_SW_SRAM_SLEEPB_OFFSET (12U)
+#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
+
+#define B_SW_SRAM_ISOINTB BIT(9)
+#define B_SW_ISO BIT(8)
+#define B_SW_LOGIC_PDB BIT(7)
+#define B_SW_LOGIC_PRE2_PDB BIT(6)
+#define B_SW_LOGIC_PRE1_PDB BIT(5)
+#define B_SW_FSM_OVERRIDE BIT(4)
+#define B_SW_PWR_ON BIT(3)
+#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
+
+#define B_FSM_STATE_OUT_OFFSET (6U)
+#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET)
+#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
+#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
+#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
+#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
+
+#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
+
+#ifndef __ASSEMBLER__
+/* cpu boot mode */
+enum {
+ MP0_CPUCFG_64BIT_SHIFT = 12U,
+ MP1_CPUCFG_64BIT_SHIFT = 28U,
+ MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
+ MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
+};
+
+enum {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
+
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+ MP1_AINACTS_SHIFT = 4U,
+ MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
+};
+
+enum {
+ MP1_SW_CG_GEN_SHIFT = 12U,
+ MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+ MP1_L2RSTDISABLE_SHIFT = 14U,
+ MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
+};
+#endif /* __ASSEMBLER__ */
+
+#endif /* MCUCFG_H */
diff --git a/plat/mediatek/mt8186/include/mt_spm_resource_req.h b/plat/mediatek/mt8186/include/mt_spm_resource_req.h
new file mode 100644
index 0000000..9761e79
--- /dev/null
+++ b/plat/mediatek/mt8186/include/mt_spm_resource_req.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_RESOURCE_REQ_H
+#define MT_SPM_RESOURCE_REQ_H
+
+/* SPM resource request internal bit */
+#define MT_SPM_BIT_XO_FPM (0U)
+#define MT_SPM_BIT_26M (1U)
+#define MT_SPM_BIT_INFRA (2U)
+#define MT_SPM_BIT_SYSPLL (3U)
+#define MT_SPM_BIT_DRAM_S0 (4U)
+#define MT_SPM_BIT_DRAM_S1 (5U)
+
+/* SPM resource request internal bit_mask */
+#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM)
+#define MT_SPM_26M BIT(MT_SPM_BIT_26M)
+#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA)
+#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL)
+#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0)
+#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1)
+
+char spm_resource_req(unsigned int user, unsigned int req_mask);
+
+#define IS_PLAT_SUSPEND_ID(stateid)\
+ ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE)\
+ || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
+
+#endif /* MT_SPM_RESOURCE_REQ_H */
diff --git a/plat/mediatek/mt8186/include/plat_helpers.h b/plat/mediatek/mt8186/include/plat_helpers.h
new file mode 100644
index 0000000..ebc9fa0
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8186/include/plat_macros.S b/plat/mediatek/mt8186/include/plat_macros.S
new file mode 100644
index 0000000..39727ea
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_macros.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception
+ * is taken in BL31.
+ * Clobbers: x0 - x10, x26, x27, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /* TODO: leave implementation to GIC owner */
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8186/include/plat_mtk_lpm.h b/plat/mediatek/mt8186/include/plat_mtk_lpm.h
new file mode 100644
index 0000000..12ea9d7
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_mtk_lpm.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MTK_LPM_H
+#define PLAT_MTK_LPM_H
+
+#include <lib/psci/psci.h>
+#include <lib/utils_def.h>
+
+#define MT_IRQ_REMAIN_MAX U(32)
+#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
+
+struct mt_irqremain {
+ unsigned int count;
+ unsigned int irqs[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
+};
+
+#define PLAT_RC_STATUS_READY BIT(0)
+#define PLAT_RC_STATUS_FEATURE_EN BIT(1)
+#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31)
+
+struct mt_lpm_tz {
+ int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cluster_on)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_cluster_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+
+ int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_mcusys_on_finished)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_mcusys_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
+int plat_mt_pm_register(struct mt_lpm_tz *mt_pm);
+
+#endif /* PLAT_MTK_LPM_H */
diff --git a/plat/mediatek/mt8186/include/plat_pm.h b/plat/mediatek/mt8186/include/plat_pm.h
new file mode 100644
index 0000000..ec70e4b
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_pm.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_H
+#define PLAT_PM_H
+
+#include <lib/utils_def.h>
+
+#ifndef __ASSEMBLY__
+extern uintptr_t mtk_suspend_footprint_addr;
+extern uintptr_t mtk_suspend_timestamp_addr;
+
+#define MT_PLAT_PWR_STATE_CPU U(1)
+#define MT_PLAT_PWR_STATE_CLUSTER U(2)
+#define MT_PLAT_PWR_STATE_MCUSYS U(3)
+#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8)
+#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9)
+
+#define MTK_LOCAL_STATE_RUN U(0)
+#define MTK_LOCAL_STATE_RET U(1)
+#define MTK_LOCAL_STATE_OFF U(2)
+
+#define MTK_AFFLVL_CPU U(0)
+#define MTK_AFFLVL_CLUSTER U(1)
+#define MTK_AFFLVL_MCUSYS U(2)
+#define MTK_AFFLVL_SYSTEM U(3)
+
+void mtk_suspend_footprint_log(int idx);
+void mtk_suspend_timestamp_log(int idx);
+
+int mt_cluster_ops(int cputop_mpx, int mode, int state);
+int mt_core_ops(int cpux, int state);
+
+#define IS_CLUSTER_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
+#define IS_MCUSYS_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
+#define IS_SYSTEM_SUSPEND_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
+
+/* SMC secure magic number */
+#define SPM_LP_SMC_MAGIC (0xDAF10000)
+
+#define IS_SPM_LP_SMC(_type, _id) (_id == (SPM_LP_SMC_MAGIC | _type))
+
+enum mtk_suspend_mode {
+ MTK_MCDI_MODE = 1U,
+ MTK_IDLEDRAM_MODE = 2U,
+ MTK_IDLESYSPLL_MODE = 3U,
+ MTK_IDLEBUS26M_MODE = 4U,
+ MTK_SUSPEND_MODE = 5U,
+};
+#endif
+
+enum mt8169_idle_model {
+ IDLE_MODEL_START = 0U,
+ IDLE_MODEL_RESOURCE_HEAD = IDLE_MODEL_START,
+ IDLE_MODEL_BUS26M = IDLE_MODEL_RESOURCE_HEAD,
+ IDLE_MODEL_SYSPLL = 1U,
+ IDLE_MODEL_DRAM = 2U,
+ IDLE_MODEL_NUM = 3U,
+};
+
+#define footprint_addr(cpu) (mtk_suspend_footprint_addr + (cpu << 2))
+#define timestamp_addr(cpu, idx) (mtk_suspend_timestamp_addr + \
+ ((cpu * MTK_SUSPEND_TIMESTAMP_MAX + idx) << 3))
+
+#define MTK_SUSPEND_FOOTPRINT_ENTER_CPUIDLE (0U)
+#define MTK_SUSPEND_FOOTPRINT_BEFORE_ATF (1U)
+#define MTK_SUSPEND_FOOTPRINT_ENTER_ATF (2U)
+#define MTK_SUSPEND_FOOTPRINT_RESERVE_P1 (3U)
+#define MTK_SUSPEND_FOOTPRINT_RESERVE_P2 (4U)
+#define MTK_SUSPEND_FOOTPRINT_ENTER_SPM_SUSPEND (5U)
+#define MTK_SUSPEND_FOOTPRINT_LEAVE_SPM_SUSPEND (6U)
+#define MTK_SUSPEND_FOOTPRINT_BEFORE_WFI (7U)
+#define MTK_SUSPEND_FOOTPRINT_AFTER_WFI (8U)
+#define MTK_SUSPEND_FOOTPRINT_BEFORE_MMU (9U)
+#define MTK_SUSPEND_FOOTPRINT_AFTER_MMU (10U)
+#define MTK_SUSPEND_FOOTPRINT_ENTER_SPM_SUSPEND_FINISH (11U)
+#define MTK_SUSPEND_FOOTPRINT_LEAVE_SPM_SUSPEND_FINISH (12U)
+#define MTK_SUSPEND_FOOTPRINT_LEAVE_ATF (13U)
+#define MTK_SUSPEND_FOOTPRINT_AFTER_ATF (14U)
+#define MTK_SUSPEND_FOOTPRINT_LEAVE_CPUIDLE (15U)
+
+#define MTK_SUSPEND_TIMESTAMP_ENTER_CPUIDLE (0U)
+#define MTK_SUSPEND_TIMESTAMP_BEFORE_ATF (1U)
+#define MTK_SUSPEND_TIMESTAMP_ENTER_ATF (2U)
+#define MTK_SUSPEND_TIMESTAMP_BEFORE_L2_FLUSH (3U)
+#define MTK_SUSPEND_TIMESTAMP_AFTER_L2_FLUSH (4U)
+#define MTK_SUSPEND_TIMESTAMP_ENTER_SPM_SUSPEND (5U)
+#define MTK_SUSPEND_TIMESTAMP_LEAVE_SPM_SUSPEND (6U)
+#define MTK_SUSPEND_TIMESTAMP_GIC_P1 (7U)
+#define MTK_SUSPEND_TIMESTAMP_GIC_P2 (8U)
+#define MTK_SUSPEND_TIMESTAMP_BEFORE_WFI (9U)
+#define MTK_SUSPEND_TIMESTAMP_AFTER_WFI (10U)
+#define MTK_SUSPEND_TIMESTAMP_RESERVE_P1 (11U)
+#define MTK_SUSPEND_TIMESTAMP_RESERVE_P2 (12U)
+#define MTK_SUSPEND_TIMESTAMP_GIC_P3 (13U)
+#define MTK_SUSPEND_TIMESTAMP_GIC_P4 (14U)
+#define MTK_SUSPEND_TIMESTAMP_ENTER_SPM_SUSPEND_FINISH (15U)
+#define MTK_SUSPEND_TIMESTAMP_LEAVE_SPM_SUSPEND_FINISH (16U)
+#define MTK_SUSPEND_TIMESTAMP_LEAVE_ATF (17U)
+#define MTK_SUSPEND_TIMESTAMP_AFTER_ATF (18U)
+#define MTK_SUSPEND_TIMESTAMP_LEAVE_CPUIDLE (19U)
+#define MTK_SUSPEND_TIMESTAMP_MAX (20U)
+
+/*
+ * definition platform power state menas.
+ * PLAT_MT_SYSTEM_SUSPEND - system suspend pwr level
+ * PLAT_MT_CPU_SUSPEND_CLUSTER - cluster off pwr level
+ */
+#define PLAT_MT_SYSTEM_SUSPEND PLAT_MAX_OFF_STATE
+#define PLAT_MT_CPU_SUSPEND_CLUSTER PLAT_MAX_RET_STATE
+
+#define IS_PLAT_SYSTEM_SUSPEND(aff) (aff == PLAT_MT_SYSTEM_SUSPEND)
+#define IS_PLAT_SYSTEM_RETENTION(aff) (aff >= PLAT_MAX_RET_STATE)
+
+#define IS_PLAT_SUSPEND2IDLE_ID(stateid)\
+ (stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE)
+
+#define IS_PLAT_SUSPEND_ID(stateid) \
+ ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \
+ || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
+
+#endif /* PLAT_PM_H */
diff --git a/plat/mediatek/mt8186/include/plat_private.h b/plat/mediatek/mt8186/include/plat_private.h
new file mode 100644
index 0000000..7ef2b85
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8186/include/plat_sip_calls.h b/plat/mediatek/mt8186/include/plat_sip_calls.h
new file mode 100644
index 0000000..f5c15e3
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_sip_calls.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+/*******************************************************************************
+ * Plat SiP function constants
+ ******************************************************************************/
+#define MTK_PLAT_SIP_NUM_CALLS (6)
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8186/include/plat_uart.h b/plat/mediatek/mt8186/include/plat_uart.h
new file mode 100644
index 0000000..f0fb442
--- /dev/null
+++ b/plat/mediatek/mt8186/include/plat_uart.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_UART_H__
+#define __PLAT_UART_H__
+
+/* UART error code */
+#define UART_DONE U(0)
+#define UART_PM_ERROR U(1)
+
+/* UART HW information */
+#ifndef HW_SUPPORT_UART_PORTS
+#define HW_SUPPORT_UART_PORTS (2U) /* the UART PORTs current HW have */
+#endif
+#define MTK_UART_SEND_SLEEP_REQ (1U) /* Request uart to sleep */
+#define MTK_UART_SLEEP_ACK_IDLE (1U) /* uart in idle state */
+#define MTK_UART_WAIT_ACK_TIMES (50U)
+
+#define UART_BASE0 (0x11002000)
+#define UART_BASE1 (0x11003000)
+
+#endif /* __PLAT_UART_H__ */
diff --git a/plat/mediatek/mt8186/include/platform_def.h b/plat/mediatek/mt8186/include/platform_def.h
new file mode 100644
index 0000000..850ce2f
--- /dev/null
+++ b/plat/mediatek/mt8186/include/platform_def.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#define PLAT_PRIMARY_CPU (0x0)
+
+#define MT_GIC_BASE (0x0C000000)
+#define MCUCFG_BASE (0x0C530000)
+#define IO_PHYS (0x10000000)
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE IO_PHYS
+#define MTK_DEV_RNG0_SIZE (0x10000000)
+#define MTK_DEV_RNG2_BASE MT_GIC_BASE
+#define MTK_DEV_RNG2_SIZE (0x600000)
+#define MTK_MCDI_SRAM_BASE (0x11B000)
+#define MTK_MCDI_SRAM_MAP_SIZE (0x1000)
+
+#define TOPCKGEN_BASE (IO_PHYS + 0x00000000)
+#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
+#define SPM_BASE (IO_PHYS + 0x00006000)
+#define APMIXEDSYS (IO_PHYS + 0x0000C000)
+#define SSPM_MCDI_SHARE_SRAM (IO_PHYS + 0x00420000)
+#define SSPM_CFGREG_BASE (IO_PHYS + 0x00440000) /* SSPM view: 0x30040000 */
+#define SSPM_MBOX_BASE (IO_PHYS + 0x00480000)
+#define PERICFG_AO_BASE (IO_PHYS + 0x01003000)
+#define VPPSYS0_BASE (IO_PHYS + 0x04000000)
+#define VPPSYS1_BASE (IO_PHYS + 0x04f00000)
+#define VDOSYS0_BASE (IO_PHYS + 0x0C01A000)
+#define VDOSYS1_BASE (IO_PHYS + 0x0C100000)
+
+/*******************************************************************************
+ * GPIO related constants
+ ******************************************************************************/
+#define TOPCKGEN_BASE (IO_PHYS + 0x00000000)
+#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
+#define GPIO_BASE (IO_PHYS + 0x00005000)
+#define SPM_BASE (IO_PHYS + 0x00006000)
+#define IOCFG_LT_BASE (IO_PHYS + 0x00002000)
+#define IOCFG_LM_BASE (IO_PHYS + 0x00002200)
+#define IOCFG_LB_BASE (IO_PHYS + 0x00002400)
+#define IOCFG_BL_BASE (IO_PHYS + 0x00002600)
+#define IOCFG_RB_BASE (IO_PHYS + 0x00002A00)
+#define IOCFG_RT_BASE (IO_PHYS + 0x00002C00)
+#define APMIXEDSYS (IO_PHYS + 0x0000C000)
+#define DVFSRC_BASE (IO_PHYS + 0x00012000)
+#define MMSYS_BASE (IO_PHYS + 0x04000000)
+#define MDPSYS_BASE (IO_PHYS + 0x0B000000)
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE (IO_PHYS + 0x01002000)
+#define UART1_BASE (IO_PHYS + 0x01003000)
+
+#define UART_BAUDRATE (115200)
+
+/*******************************************************************************
+ * PWRAP related constants
+ ******************************************************************************/
+#define PMIC_WRAP_BASE (IO_PHYS + 0x0000D000)
+
+/*******************************************************************************
+ * EMI MPU related constants
+ ******************************************************************************/
+#define EMI_MPU_BASE (IO_PHYS + 0x0021B000)
+
+/*******************************************************************************
+ * MSDC related constants
+ ******************************************************************************/
+#define MSDC0_BASE (IO_PHYS + 0x01230000)
+
+/*******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE MT_GIC_BASE
+#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000)
+
+#define SYS_CIRQ_BASE (IO_PHYS + 0x204000)
+#define CIRQ_REG_NUM (11)
+#define CIRQ_IRQ_NUM (326)
+#define CIRQ_SPI_START (64)
+#define MD_WDT_IRQ_BIT_ID (107)
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS (13000000)
+#define SYS_COUNTER_FREQ_IN_MHZ (13)
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE 0x800
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLAT_MAX_PWR_LVL U(3)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(9)
+
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_MCUSYS_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(8)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8)
+
+#define SOC_CHIP_ID U(0x8186)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE (0x54600000)
+#define TZRAM_SIZE (0x00030000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES (16)
+#define MAX_MMAP_REGIONS (16)
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT (6)
+#define CACHE_WRITEBACK_GRANULE BIT(CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8186/include/sspm_reg.h b/plat/mediatek/mt8186/include/sspm_reg.h
new file mode 100644
index 0000000..40b71ac
--- /dev/null
+++ b/plat/mediatek/mt8186/include/sspm_reg.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SSPM_REG_H__
+#define __SSPM_REG_H__
+
+#include "platform_def.h"
+
+#define SSPM_CFGREG_ADDR(ofs) (SSPM_CFGREG_BASE + (ofs))
+
+#define SSPM_HW_SEM SSPM_CFGREG_ADDR(0x0048)
+#define SSPM_ACAO_INT_SET SSPM_CFGREG_ADDR(0x00D8)
+#define SSPM_ACAO_INT_CLR SSPM_CFGREG_ADDR(0x00DC)
+
+#define STANDBYWFI_EN(n) (1 << (n + 8))
+#define GIC_IRQOUT_EN(n) (1 << (n + 0))
+
+#endif /* __SSPM_REG_H__ */
diff --git a/plat/mediatek/mt8186/plat_pm.c b/plat/mediatek/mt8186/plat_pm.c
new file mode 100644
index 0000000..e125c99
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_pm.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/gpio.h>
+#include <lib/psci/psci.h>
+
+#include <mt_gic_v3.h>
+#include <mtspmc.h>
+#include <plat/common/platform.h>
+#include <plat_dfd.h>
+#include <plat_mtk_lpm.h>
+#include <plat_params.h>
+#include <plat_pm.h>
+#include <pmic.h>
+#include <rtc.h>
+
+/*
+ * Cluster state request:
+ * [0] : The CPU requires cluster power down
+ * [1] : The CPU requires cluster power on
+ */
+#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron() coordinate_cluster(1)
+#define coordinate_cluster_pwroff() coordinate_cluster(0)
+
+/* platform secure entry point */
+static uintptr_t secure_entrypoint;
+/* per-CPU power state */
+static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
+
+/* platform CPU power domain - ops */
+static const struct mt_lpm_tz *plat_mt_pm;
+
+static inline int plat_mt_pm_invoke(int (*func)(unsigned int cpu,
+ const psci_power_state_t *state),
+ int cpu, const psci_power_state_t *state)
+{
+ int ret = -1;
+
+ if (func != NULL) {
+ ret = func(cpu, state);
+ }
+ return ret;
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+static void plat_cpu_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+ assert(plat_mt_pm != NULL);
+
+ (void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_dwn, cpu, state);
+
+ if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
+ (req_pstate == 0U)) { /* hotplug off */
+ coordinate_cluster_pwroff();
+ }
+
+ /* Prevent interrupts from spuriously waking up this CPU */
+ mt_gic_rdistif_save();
+ gicv3_cpuif_disable(cpu);
+ gicv3_rdistif_off(cpu);
+}
+
+static void plat_cpu_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+ assert(plat_mt_pm != NULL);
+
+ (void)plat_mt_pm_invoke(plat_mt_pm->pwr_cpu_on, cpu, state);
+
+ coordinate_cluster_pwron();
+
+ /*
+ * If mcusys does power down before then restore
+ * all CPUs' GIC Redistributors
+ */
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ mt_gic_rdistif_restore_all();
+ } else {
+ gicv3_rdistif_on(cpu);
+ gicv3_cpuif_enable(cpu);
+ mt_gic_rdistif_init();
+ mt_gic_rdistif_restore();
+ }
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+static void plat_cluster_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+ assert(plat_mt_pm != NULL);
+
+ if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_dwn, cpu, state) != 0) {
+ coordinate_cluster_pwron();
+
+ /*
+ * TODO:
+ * Return on fail and add a 'return' here before
+ * adding any code following the if-block.
+ */
+ }
+}
+
+static void plat_cluster_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+ assert(plat_mt_pm != NULL);
+
+ if (plat_mt_pm_invoke(plat_mt_pm->pwr_cluster_on, cpu, state) != 0) {
+ /*
+ * TODO:
+ * return on fail and add a 'return' here before
+ * adding any code following the if-block.
+ */
+ }
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+static void plat_mcusys_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+ assert(plat_mt_pm != NULL);
+
+ if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_dwn, cpu, state) != 0) {
+ return; /* return on fail */
+ }
+
+ mt_gic_distif_save();
+ gic_sgi_save_all();
+}
+
+static void plat_mcusys_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+ assert(plat_mt_pm != NULL);
+
+ if (plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on, cpu, state) != 0) {
+ /* return on fail */
+ return;
+ }
+
+ mt_gic_init();
+ mt_gic_distif_restore();
+ gic_sgi_restore_all();
+
+ dfd_resume();
+
+ (void)plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on_finished, cpu, state);
+}
+
+/* plat_psci_ops implementation */
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+ uint64_t scr;
+
+ scr = read_scr_el3();
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+ isb();
+ dsb();
+ wfi();
+
+ write_scr_el3(scr);
+}
+
+static int plat_power_domain_on(u_register_t mpidr)
+{
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+ unsigned int cluster = 0U;
+
+ if (cpu >= PLATFORM_CORE_COUNT) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (!spm_get_cluster_powerstate(cluster)) {
+ spm_poweron_cluster(cluster);
+ }
+
+ /* init CPU reset arch as AARCH64 */
+ mcucfg_init_archstate(cluster, cpu, true);
+ mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+ spm_poweron_cpu(cluster, cpu);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ /* Allow IRQs to wakeup this core in IDLE flow */
+ mcucfg_enable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwron_common(cpu, state, 0U);
+ }
+
+ plat_cpu_pwron_common(cpu, state, 0U);
+}
+
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ plat_cpu_pwrdwn_common(cpu, state, 0U);
+ spm_poweroff_cpu(0U, cpu);
+
+ /* prevent unintended IRQs from waking up the hot-unplugged core */
+ mcucfg_disable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwrdwn_common(cpu, state, 0U);
+ }
+}
+
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+ assert(plat_mt_pm != NULL);
+
+ (void)plat_mt_pm_invoke(plat_mt_pm->pwr_prompt, cpu, state);
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+}
+
+static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+ assert(plat_mt_pm != NULL);
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
+
+ (void)plat_mt_pm_invoke(plat_mt_pm->pwr_reflect, cpu, state);
+}
+
+static int plat_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int cpu = plat_my_core_pos();
+
+ if (aff_lvl > PLAT_MAX_PWR_LVL) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+ } else {
+ unsigned int i;
+ unsigned int pstate_id = psci_get_pstate_id(power_state);
+ plat_local_state_t s = MTK_LOCAL_STATE_OFF;
+
+ /* Use pstate_id to be power domain state */
+ if (pstate_id > s) {
+ s = (plat_local_state_t)pstate_id;
+ }
+
+ for (i = 0U; i <= aff_lvl; i++) {
+ req_state->pwr_domain_state[i] = s;
+ }
+ }
+
+ plat_power_state[cpu] = power_state;
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int lv;
+ unsigned int cpu = plat_my_core_pos();
+
+ for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
+ req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
+ }
+
+ plat_power_state[cpu] =
+ psci_make_powerstate(
+ MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
+ PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+
+ flush_dcache_range((uintptr_t)
+ &plat_power_state[cpu],
+ sizeof(plat_power_state[cpu]));
+}
+
+/*******************************************************************************
+ * MTK handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 plat_mtk_system_reset(void)
+{
+ struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+ INFO("MTK System Reset\n");
+
+ gpio_set_value(gpio_reset->index, gpio_reset->polarity);
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 plat_mtk_system_off(void)
+{
+ INFO("MTK System Off\n");
+
+ rtc_power_off_sequence();
+ pmic_power_off();
+
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static const plat_psci_ops_t plat_psci_ops = {
+ .cpu_standby = plat_cpu_standby,
+ .pwr_domain_on = plat_power_domain_on,
+ .pwr_domain_on_finish = plat_power_domain_on_finish,
+ .pwr_domain_off = plat_power_domain_off,
+ .pwr_domain_suspend = plat_power_domain_suspend,
+ .pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
+ .validate_power_state = plat_validate_power_state,
+ .get_sys_suspend_power_state = plat_get_sys_suspend_power_state,
+ .system_off = plat_mtk_system_off,
+ .system_reset = plat_mtk_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_psci_ops;
+ secure_entrypoint = sec_entrypoint;
+
+ /*
+ * init the warm reset config for boot CPU
+ * reset arch as AARCH64
+ * reset addr as function bl31_warm_entrypoint()
+ */
+ mcucfg_init_archstate(0U, 0U, true);
+ mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
+
+ spmc_init();
+ plat_mt_pm = mt_plat_cpu_pm_init();
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8186/plat_sip_calls.c b/plat/mediatek/mt8186/plat_sip_calls.c
new file mode 100644
index 0000000..0e9c270
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_sip_calls.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <mt_msdc.h>
+#include <mt_spm_vcorefs.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+#include "plat_sip_calls.h"
+
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint64_t ret;
+
+ switch (smc_fid) {
+ case MTK_SIP_VCORE_CONTROL_AARCH32:
+ case MTK_SIP_VCORE_CONTROL_AARCH64:
+ ret = spm_vcorefs_args(x1, x2, x3, (uint64_t *)&x4);
+ SMC_RET2(handle, ret, x4);
+ break;
+ case MTK_SIP_KERNEL_DFD_AARCH32:
+ case MTK_SIP_KERNEL_DFD_AARCH64:
+ ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+ SMC_RET1(handle, ret);
+ break;
+ case MTK_SIP_KERNEL_MSDC_AARCH32:
+ case MTK_SIP_KERNEL_MSDC_AARCH64:
+ ret = msdc_smc_dispatcher(x1, x2, x3, x4);
+ SMC_RET1(handle, ret);
+ break;
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ break;
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/mediatek/mt8186/plat_topology.c b/plat/mediatek/mt8186/plat_topology.c
new file mode 100644
index 0000000..bc95c64
--- /dev/null
+++ b/plat/mediatek/mt8186/plat_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* Number of children for the root node */
+ PLATFORM_MCUSYS_COUNT,
+ /* Number of children for the mcusys node */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ if ((read_mpidr() & MPIDR_MT_MASK) != 0) {
+ /* ARMv8.2 arch */
+ if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) {
+ return -1;
+ }
+ return plat_mediatek_calc_core_pos(mpidr);
+ }
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) {
+ return -1;
+ }
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8186/platform.mk b/plat/mediatek/mt8186/platform.mk
new file mode 100644
index 0000000..68f4a1f
--- /dev/null
+++ b/plat/mediatek/mt8186/platform.mk
@@ -0,0 +1,110 @@
+#
+# Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT}/common/lpm \
+ -I${MTK_PLAT}/drivers/cirq/ \
+ -I${MTK_PLAT}/drivers/gic600/ \
+ -I${MTK_PLAT}/drivers/gpio/ \
+ -I${MTK_PLAT}/drivers/msdc/ \
+ -I${MTK_PLAT}/drivers/msdc/${PLAT} \
+ -I${MTK_PLAT}/drivers/pmic_wrap/ \
+ -I${MTK_PLAT}/drivers/timer/ \
+ -I${MTK_PLAT}/drivers/uart/ \
+ -I${MTK_PLAT}/include/ \
+ -I${MTK_PLAT_SOC}/drivers/spm/ \
+ -I${MTK_PLAT_SOC}/drivers/dcm/ \
+ -I${MTK_PLAT_SOC}/drivers/dfd/ \
+ -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
+ -I${MTK_PLAT_SOC}/drivers/gpio/ \
+ -I${MTK_PLAT_SOC}/drivers/mcdi/ \
+ -I${MTK_PLAT_SOC}/drivers/pmic/ \
+ -I${MTK_PLAT_SOC}/drivers/rtc/ \
+ -I${MTK_PLAT_SOC}/drivers/spmc/ \
+ -I${MTK_PLAT_SOC}/include/
+
+GICV3_SUPPORT_GIC600 := 1
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+
+BL31_SOURCES += common/desc_image_load.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/gpio/gpio.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/cpus/aarch64/cortex_a55.S \
+ lib/cpus/aarch64/cortex_a76.S \
+ plat/common/plat_gicv3.c \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/mtk_sip_svc.c \
+ ${MTK_PLAT}/common/params_setup.c \
+ ${MTK_PLAT}/common/lpm/mt_lp_rm.c \
+ ${MTK_PLAT}/drivers/cirq/mt_cirq.c \
+ ${MTK_PLAT}/drivers/gic600/mt_gic_v3.c \
+ ${MTK_PLAT}/drivers/gpio/mtgpio_common.c \
+ ${MTK_PLAT}/drivers/msdc/mt_msdc.c \
+ ${MTK_PLAT}/drivers/pmic_wrap/pmic_wrap_init.c \
+ ${MTK_PLAT}/drivers/rtc/rtc_common.c \
+ ${MTK_PLAT}/drivers/timer/mt_timer.c \
+ ${MTK_PLAT}/drivers/uart/uart.c \
+ ${MTK_PLAT_SOC}/aarch64/platform_common.c \
+ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
+ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
+ ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \
+ ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
+ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c \
+ ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
+ ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
+ ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
+ ${MTK_PLAT_SOC}/plat_pm.c \
+ ${MTK_PLAT_SOC}/plat_sip_calls.c \
+ ${MTK_PLAT_SOC}/plat_topology.c
+
+# Build SPM drivers
+include ${MTK_PLAT_SOC}/drivers/spm/build.mk
+
+# Configs for A76 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+ERRATA_A55_1530923 := 1
+ERRATA_A55_1221012 := 1
+
+ERRATA_A76_1257314 := 1
+ERRATA_A76_1262606 := 1
+ERRATA_A76_1262888 := 1
+ERRATA_A76_1275112 := 1
+ERRATA_A76_1286807 := 1
+ERRATA_A76_1791580 := 1
+ERRATA_A76_1165522 := 1
+ERRATA_A76_1868343 := 1
+ERRATA_A76_1946160 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8186 := 1
+$(eval $(call add_define,MACH_MT8186))
+
+include lib/coreboot/coreboot.mk
diff --git a/plat/mediatek/mt8188/include/plat_helpers.h b/plat/mediatek/mt8188/include/plat_helpers.h
new file mode 100644
index 0000000..eb78623
--- /dev/null
+++ b/plat/mediatek/mt8188/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_HELPERS_H
+#define PLAT_HELPERS_H
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* PLAT_HELPERS_H */
diff --git a/plat/mediatek/mt8188/include/plat_macros.S b/plat/mediatek/mt8188/include/plat_macros.S
new file mode 100644
index 0000000..a6e05a9
--- /dev/null
+++ b/plat/mediatek/mt8188/include/plat_macros.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception
+ * is taken in BL31.
+ * Clobbers: x0 - x10, x26, x27, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /* TODO: leave implementation to GIC owner */
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8188/include/plat_private.h b/plat/mediatek/mt8188/include/plat_private.h
new file mode 100644
index 0000000..4d4ac85
--- /dev/null
+++ b/plat/mediatek/mt8188/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8188/include/platform_def.h b/plat/mediatek/mt8188/include/platform_def.h
new file mode 100644
index 0000000..156a7e2
--- /dev/null
+++ b/plat/mediatek/mt8188/include/platform_def.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch_def.h>
+
+#define PLAT_PRIMARY_CPU (0x0)
+
+#define MT_GIC_BASE (0x0C000000)
+#define MCUCFG_BASE (0x0C530000)
+#define MCUCFG_REG_SIZE (0x10000)
+#define IO_PHYS (0x10000000)
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE (MT_GIC_BASE)
+#define MTK_DEV_RNG0_SIZE (0x600000)
+#define MTK_DEV_RNG1_BASE (IO_PHYS)
+#define MTK_DEV_RNG1_SIZE (0x10000000)
+
+/*******************************************************************************
+ * AUDIO related constants
+ ******************************************************************************/
+#define AUDIO_BASE (IO_PHYS + 0x00b10000)
+
+/*******************************************************************************
+ * SPM related constants
+ ******************************************************************************/
+#define SPM_BASE (IO_PHYS + 0x00006000)
+
+/*******************************************************************************
+ * GPIO related constants
+ ******************************************************************************/
+#define GPIO_BASE (IO_PHYS + 0x00005000)
+#define RGU_BASE (IO_PHYS + 0x00007000)
+#define DRM_BASE (IO_PHYS + 0x0000D000)
+#define IOCFG_RM_BASE (IO_PHYS + 0x01C00000)
+#define IOCFG_LT_BASE (IO_PHYS + 0x01E10000)
+#define IOCFG_LM_BASE (IO_PHYS + 0x01E20000)
+#define IOCFG_RT_BASE (IO_PHYS + 0x01EA0000)
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE (IO_PHYS + 0x01002000)
+#define UART_BAUDRATE (115200)
+
+/*******************************************************************************
+ * PMIC related constants
+ ******************************************************************************/
+#define PMIC_WRAP_BASE (IO_PHYS + 0x00024000)
+
+/*******************************************************************************
+ * Infra IOMMU related constants
+ ******************************************************************************/
+#define PERICFG_AO_BASE (IO_PHYS + 0x01003000)
+#define PERICFG_AO_REG_SIZE (0x1000)
+
+/*******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE (MT_GIC_BASE)
+#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000)
+
+/*******************************************************************************
+ * CIRQ related constants
+ ******************************************************************************/
+#define SYS_CIRQ_BASE (IO_PHYS + 0x204000)
+#define MD_WDT_IRQ_BIT_ID (141)
+#define CIRQ_IRQ_NUM (730)
+#define CIRQ_REG_NUM (23)
+#define CIRQ_SPI_START (96)
+
+/*******************************************************************************
+ * MM IOMMU & SMI related constants
+ ******************************************************************************/
+#define SMI_LARB_0_BASE (IO_PHYS + 0x0c022000)
+#define SMI_LARB_1_BASE (IO_PHYS + 0x0c023000)
+#define SMI_LARB_2_BASE (IO_PHYS + 0x0c102000)
+#define SMI_LARB_3_BASE (IO_PHYS + 0x0c103000)
+#define SMI_LARB_4_BASE (IO_PHYS + 0x04013000)
+#define SMI_LARB_5_BASE (IO_PHYS + 0x04f02000)
+#define SMI_LARB_6_BASE (IO_PHYS + 0x04f03000)
+#define SMI_LARB_7_BASE (IO_PHYS + 0x04e04000)
+#define SMI_LARB_9_BASE (IO_PHYS + 0x05001000)
+#define SMI_LARB_10_BASE (IO_PHYS + 0x05120000)
+#define SMI_LARB_11A_BASE (IO_PHYS + 0x05230000)
+#define SMI_LARB_11B_BASE (IO_PHYS + 0x05530000)
+#define SMI_LARB_11C_BASE (IO_PHYS + 0x05630000)
+#define SMI_LARB_12_BASE (IO_PHYS + 0x05340000)
+#define SMI_LARB_13_BASE (IO_PHYS + 0x06001000)
+#define SMI_LARB_14_BASE (IO_PHYS + 0x06002000)
+#define SMI_LARB_15_BASE (IO_PHYS + 0x05140000)
+#define SMI_LARB_16A_BASE (IO_PHYS + 0x06008000)
+#define SMI_LARB_16B_BASE (IO_PHYS + 0x0600a000)
+#define SMI_LARB_17A_BASE (IO_PHYS + 0x06009000)
+#define SMI_LARB_17B_BASE (IO_PHYS + 0x0600b000)
+#define SMI_LARB_19_BASE (IO_PHYS + 0x0a010000)
+#define SMI_LARB_21_BASE (IO_PHYS + 0x0802e000)
+#define SMI_LARB_23_BASE (IO_PHYS + 0x0800d000)
+#define SMI_LARB_27_BASE (IO_PHYS + 0x07201000)
+#define SMI_LARB_28_BASE (IO_PHYS + 0x00000000)
+#define SMI_LARB_REG_RNG_SIZE (0x1000)
+
+/*******************************************************************************
+ * DP related constants
+ ******************************************************************************/
+#define EDP_SEC_BASE (IO_PHYS + 0x0C504000)
+#define DP_SEC_BASE (IO_PHYS + 0x0C604000)
+#define EDP_SEC_SIZE (0x1000)
+#define DP_SEC_SIZE (0x1000)
+
+/*******************************************************************************
+ * EMI MPU related constants
+ *******************************************************************************/
+#define EMI_MPU_BASE (IO_PHYS + 0x00226000)
+#define SUB_EMI_MPU_BASE (IO_PHYS + 0x00225000)
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_HZ (13000000)
+#define SYS_COUNTER_FREQ_IN_MHZ (13)
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE (0x800)
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+#define SOC_CHIP_ID U(0x8188)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE (0x54600000)
+#define TZRAM_SIZE (0x00030000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES (16)
+#define MAX_MMAP_REGIONS (16)
+
+/*******************************************************************************
+ * CPU_EB TCM handling related constants
+ ******************************************************************************/
+#define CPU_EB_TCM_BASE (0x0C550000)
+#define CPU_EB_TCM_SIZE (0x10000)
+#define CPU_EB_MBOX3_OFFSET (0xFCE0)
+
+/*******************************************************************************
+ * CPU PM definitions
+ *******************************************************************************/
+#define PLAT_CPU_PM_B_BUCK_ISO_ID (6)
+#define PLAT_CPU_PM_ILDO_ID (6)
+#define CPU_IDLE_SRAM_BASE (0x11B000)
+#define CPU_IDLE_SRAM_SIZE (0x1000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8188/include/spm_reg.h b/plat/mediatek/mt8188/include/spm_reg.h
new file mode 100644
index 0000000..e20f1aa
--- /dev/null
+++ b/plat/mediatek/mt8188/include/spm_reg.h
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPM_REG_H
+#define SPM_REG_H
+
+#include <platform_def.h>
+
+/* Register_SPM_CFG */
+#define MD32PCM_CFG_BASE (SPM_BASE + 0xA00)
+#define POWERON_CONFIG_EN (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008)
+#define SPM_CLK_CON (SPM_BASE + 0x00C)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x010)
+#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014)
+#define PCM_CON0 (SPM_BASE + 0x018)
+#define PCM_CON1 (SPM_BASE + 0x01C)
+#define SPM_POWER_ON_VAL2 (SPM_BASE + 0x020)
+#define SPM_POWER_ON_VAL3 (SPM_BASE + 0x024)
+#define PCM_REG_DATA_INI (SPM_BASE + 0x028)
+#define PCM_PWR_IO_EN (SPM_BASE + 0x02C)
+#define PCM_TIMER_VAL (SPM_BASE + 0x030)
+#define PCM_WDT_VAL (SPM_BASE + 0x034)
+#define SPM_SW_RST_CON (SPM_BASE + 0x040)
+#define SPM_SW_RST_CON_SET (SPM_BASE + 0x044)
+#define SPM_SW_RST_CON_CLR (SPM_BASE + 0x048)
+#define SPM_ARBITER_EN (SPM_BASE + 0x050)
+#define SCPSYS_CLK_CON (SPM_BASE + 0x054)
+#define SPM_SRAM_RSV_CON (SPM_BASE + 0x058)
+#define SPM_SWINT (SPM_BASE + 0x05C)
+#define SPM_SWINT_SET (SPM_BASE + 0x060)
+#define SPM_SWINT_CLR (SPM_BASE + 0x064)
+#define SPM_SCP_MAILBOX (SPM_BASE + 0x068)
+#define SCP_SPM_MAILBOX (SPM_BASE + 0x06C)
+#define SPM_SCP_IRQ (SPM_BASE + 0x070)
+#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x074)
+#define SPM_IRQ_MASK (SPM_BASE + 0x078)
+#define SPM_SRC_REQ (SPM_BASE + 0x080)
+#define SPM_SRC_MASK (SPM_BASE + 0x084)
+#define SPM_SRC2_MASK (SPM_BASE + 0x088)
+#define SPM_SRC3_MASK (SPM_BASE + 0x090)
+#define SPM_SRC4_MASK (SPM_BASE + 0x094)
+#define SPM_WAKEUP_EVENT_MASK2 (SPM_BASE + 0x098)
+#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x09C)
+#define SPM_WAKEUP_EVENT_SENS (SPM_BASE + 0x0A0)
+#define SPM_WAKEUP_EVENT_CLEAR (SPM_BASE + 0x0A4)
+#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0A8)
+#define SCP_CLK_CON (SPM_BASE + 0x0AC)
+#define PCM_DEBUG_CON (SPM_BASE + 0x0B0)
+#define DDREN_DBC_CON (SPM_BASE + 0x0B4)
+#define SPM_RESOURCE_ACK_CON0 (SPM_BASE + 0x0B8)
+#define SPM_RESOURCE_ACK_CON1 (SPM_BASE + 0x0BC)
+#define SPM_RESOURCE_ACK_CON2 (SPM_BASE + 0x0C0)
+#define SPM_RESOURCE_ACK_CON3 (SPM_BASE + 0x0C4)
+#define SPM_RESOURCE_ACK_CON4 (SPM_BASE + 0x0C8)
+#define SPM_SRAM_CON (SPM_BASE + 0x0CC)
+#define PCM_REG0_DATA (SPM_BASE + 0x100)
+#define PCM_REG2_DATA (SPM_BASE + 0x104)
+#define PCM_REG6_DATA (SPM_BASE + 0x108)
+#define PCM_REG7_DATA (SPM_BASE + 0x10C)
+#define PCM_REG13_DATA (SPM_BASE + 0x110)
+#define SRC_REQ_STA_0 (SPM_BASE + 0x114)
+#define SRC_REQ_STA_1 (SPM_BASE + 0x118)
+#define SRC_REQ_STA_2 (SPM_BASE + 0x120)
+#define SRC_REQ_STA_3 (SPM_BASE + 0x124)
+#define SRC_REQ_STA_4 (SPM_BASE + 0x128)
+#define PCM_TIMER_OUT (SPM_BASE + 0x130)
+#define PCM_WDT_OUT (SPM_BASE + 0x134)
+#define SPM_IRQ_STA (SPM_BASE + 0x138)
+#define MD32PCM_WAKEUP_STA (SPM_BASE + 0x13C)
+#define MD32PCM_EVENT_STA (SPM_BASE + 0x140)
+#define SPM_WAKEUP_STA (SPM_BASE + 0x144)
+#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x148)
+#define SPM_WAKEUP_MISC (SPM_BASE + 0x14C)
+#define MM_DVFS_HALT (SPM_BASE + 0x150)
+#define SUBSYS_IDLE_STA (SPM_BASE + 0x164)
+#define PCM_STA (SPM_BASE + 0x168)
+#define PWR_STATUS (SPM_BASE + 0x16C)
+#define PWR_STATUS_2ND (SPM_BASE + 0x170)
+#define CPU_PWR_STATUS (SPM_BASE + 0x174)
+#define CPU_PWR_STATUS_2ND (SPM_BASE + 0x178)
+#define SPM_VTCXO_EVENT_COUNT_STA (SPM_BASE + 0x17C)
+#define SPM_INFRA_EVENT_COUNT_STA (SPM_BASE + 0x180)
+#define SPM_VRF18_EVENT_COUNT_STA (SPM_BASE + 0x184)
+#define SPM_APSRC_EVENT_COUNT_STA (SPM_BASE + 0x188)
+#define SPM_DDREN_EVENT_COUNT_STA (SPM_BASE + 0x18C)
+#define MD32PCM_STA (SPM_BASE + 0x190)
+#define MD32PCM_PC (SPM_BASE + 0x194)
+#define OTHER_PWR_STATUS (SPM_BASE + 0x198)
+#define DVFSRC_EVENT_STA (SPM_BASE + 0x19C)
+#define BUS_PROTECT_RDY (SPM_BASE + 0x1A0)
+#define BUS_PROTECT1_RDY (SPM_BASE + 0x1A4)
+#define BUS_PROTECT2_RDY (SPM_BASE + 0x1A8)
+#define BUS_PROTECT3_RDY (SPM_BASE + 0x1AC)
+#define BUS_PROTECT4_RDY (SPM_BASE + 0x1B0)
+#define BUS_PROTECT5_RDY (SPM_BASE + 0x1B4)
+#define BUS_PROTECT6_RDY (SPM_BASE + 0x1B8)
+#define BUS_PROTECT7_RDY (SPM_BASE + 0x1BC)
+#define BUS_PROTECT8_RDY (SPM_BASE + 0x1C0)
+#define BUS_PROTECT9_RDY (SPM_BASE + 0x1C4)
+#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1D0)
+#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1D4)
+#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1D8)
+#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1DC)
+#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1E0)
+#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1E4)
+#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1E8)
+#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1EC)
+#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1F0)
+#define SPM_CG_CHECK_STA (SPM_BASE + 0x1F4)
+#define SPM_DVFS_STA (SPM_BASE + 0x1F8)
+#define SPM_DVFS_OPP_STA (SPM_BASE + 0x1FC)
+#define CPUEB_PWR_CON (SPM_BASE + 0x200)
+#define SPM_MCUSYS_PWR_CON (SPM_BASE + 0x204)
+#define SPM_CPUTOP_PWR_CON (SPM_BASE + 0x208)
+#define SPM_CPU0_PWR_CON (SPM_BASE + 0x20C)
+#define SPM_CPU1_PWR_CON (SPM_BASE + 0x210)
+#define SPM_CPU2_PWR_CON (SPM_BASE + 0x214)
+#define SPM_CPU3_PWR_CON (SPM_BASE + 0x218)
+#define SPM_CPU4_PWR_CON (SPM_BASE + 0x21C)
+#define SPM_CPU5_PWR_CON (SPM_BASE + 0x220)
+#define SPM_CPU6_PWR_CON (SPM_BASE + 0x224)
+#define SPM_CPU7_PWR_CON (SPM_BASE + 0x228)
+#define ARMPLL_CLK_CON (SPM_BASE + 0x22C)
+#define MCUSYS_IDLE_STA (SPM_BASE + 0x230)
+#define GIC_WAKEUP_STA (SPM_BASE + 0x234)
+#define CPU_SPARE_CON (SPM_BASE + 0x238)
+#define CPU_SPARE_CON_SET (SPM_BASE + 0x23C)
+#define CPU_SPARE_CON_CLR (SPM_BASE + 0x240)
+#define ARMPLL_CLK_SEL (SPM_BASE + 0x244)
+#define EXT_INT_WAKEUP_REQ (SPM_BASE + 0x248)
+#define EXT_INT_WAKEUP_REQ_SET (SPM_BASE + 0x24C)
+#define EXT_INT_WAKEUP_REQ_CLR (SPM_BASE + 0x250)
+#define CPU_IRQ_MASK (SPM_BASE + 0x260)
+#define CPU_IRQ_MASK_SET (SPM_BASE + 0x264)
+#define CPU_IRQ_MASK_CLR (SPM_BASE + 0x268)
+#define CPU_WFI_EN (SPM_BASE + 0x280)
+#define CPU_WFI_EN_SET (SPM_BASE + 0x284)
+#define CPU_WFI_EN_CLR (SPM_BASE + 0x288)
+#define SYSRAM_CON (SPM_BASE + 0x290)
+#define SYSROM_CON (SPM_BASE + 0x294)
+#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x2A0)
+#define ROOT_CORE_ADDR (SPM_BASE + 0x2A4)
+#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x2D0)
+#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x2D4)
+#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x2D8)
+#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x2DC)
+#define SW2SPM_INT (SPM_BASE + 0x2E0)
+#define SW2SPM_INT_SET (SPM_BASE + 0x2E4)
+#define SW2SPM_INT_CLR (SPM_BASE + 0x2E8)
+#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x2EC)
+#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x2F0)
+#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x2F4)
+#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x2F8)
+#define SW2SPM_CFG (SPM_BASE + 0x2FC)
+#define MFG0_PWR_CON (SPM_BASE + 0x300)
+#define MFG1_PWR_CON (SPM_BASE + 0x304)
+#define MFG2_PWR_CON (SPM_BASE + 0x308)
+#define MFG3_PWR_CON (SPM_BASE + 0x30C)
+#define MFG4_PWR_CON (SPM_BASE + 0x310)
+#define MFG5_PWR_CON (SPM_BASE + 0x314)
+#define IFR_PWR_CON (SPM_BASE + 0x318)
+#define IFR_SUB_PWR_CON (SPM_BASE + 0x31C)
+#define PERI_PWR_CON (SPM_BASE + 0x320)
+#define PEXTP_MAC_TOP_P0_PWR_CON (SPM_BASE + 0x324)
+#define PEXTP_PHY_TOP_PWR_CON (SPM_BASE + 0x328)
+#define APHY_N_PWR_CON (SPM_BASE + 0x32C)
+#define APHY_S_PWR_CON (SPM_BASE + 0x330)
+#define ETHER_PWR_CON (SPM_BASE + 0x338)
+#define DPY0_PWR_CON (SPM_BASE + 0x33C)
+#define DPY1_PWR_CON (SPM_BASE + 0x340)
+#define DPM0_PWR_CON (SPM_BASE + 0x344)
+#define DPM1_PWR_CON (SPM_BASE + 0x348)
+#define AUDIO_PWR_CON (SPM_BASE + 0x34C)
+#define AUDIO_ASRC_PWR_CON (SPM_BASE + 0x350)
+#define ADSP_PWR_CON (SPM_BASE + 0x354)
+#define ADSP_INFRA_PWR_CON (SPM_BASE + 0x358)
+#define ADSP_AO_PWR_CON (SPM_BASE + 0x35C)
+#define VPPSYS0_PWR_CON (SPM_BASE + 0x360)
+#define VPPSYS1_PWR_CON (SPM_BASE + 0x364)
+#define VDOSYS0_PWR_CON (SPM_BASE + 0x368)
+#define VDOSYS1_PWR_CON (SPM_BASE + 0x36C)
+#define WPESYS_PWR_CON (SPM_BASE + 0x370)
+#define DP_TX_PWR_CON (SPM_BASE + 0x374)
+#define EDP_TX_PWR_CON (SPM_BASE + 0x378)
+#define HDMI_TX_PWR_CON (SPM_BASE + 0x37C)
+#define VDE0_PWR_CON (SPM_BASE + 0x380)
+#define VDE1_PWR_CON (SPM_BASE + 0x384)
+#define VDE2_PWR_CON (SPM_BASE + 0x388)
+#define VEN_PWR_CON (SPM_BASE + 0x38C)
+#define VEN_CORE1_PWR_CON (SPM_BASE + 0x390)
+#define CAM_MAIN_PWR_CON (SPM_BASE + 0x394)
+#define CAM_SUBA_PWR_CON (SPM_BASE + 0x398)
+#define CAM_SUBB_PWR_CON (SPM_BASE + 0x39C)
+#define CAM_VCORE_PWR_CON (SPM_BASE + 0x3A0)
+#define IMG_VCORE_PWR_CON (SPM_BASE + 0x3A4)
+#define IMG_MAIN_PWR_CON (SPM_BASE + 0x3A8)
+#define IMG_DIP_PWR_CON (SPM_BASE + 0x3AC)
+#define IMG_IPE_PWR_CON (SPM_BASE + 0x3B0)
+#define NNA0_PWR_CON (SPM_BASE + 0x3B4)
+#define NNA1_PWR_CON (SPM_BASE + 0x3B8)
+#define IPNNA_PWR_CON (SPM_BASE + 0x3C0)
+#define CSI_RX_TOP_PWR_CON (SPM_BASE + 0x3C4)
+#define SSPM_SRAM_CON (SPM_BASE + 0x3CC)
+#define SCP_SRAM_CON (SPM_BASE + 0x3D0)
+#define DEVAPC_IFR_SRAM_CON (SPM_BASE + 0x3D8)
+#define DEVAPC_SUBIFR_SRAM_CON (SPM_BASE + 0x3DC)
+#define DEVAPC_ACP_SRAM_CON (SPM_BASE + 0x3E0)
+#define USB_SRAM_CON (SPM_BASE + 0x3E4)
+#define DUMMY_SRAM_CON (SPM_BASE + 0x3E8)
+#define EXT_BUCK_ISO (SPM_BASE + 0x3EC)
+#define MSDC_SRAM_CON (SPM_BASE + 0x3F0)
+#define DEBUGTOP_SRAM_CON (SPM_BASE + 0x3F4)
+#define DPMAIF_SRAM_CON (SPM_BASE + 0x3F8)
+#define GCPU_SRAM_CON (SPM_BASE + 0x3FC)
+#define SPM_MEM_CK_SEL (SPM_BASE + 0x400)
+#define SPM_BUS_PROTECT_MASK_B (SPM_BASE + 0x404)
+#define SPM_BUS_PROTECT1_MASK_B (SPM_BASE + 0x408)
+#define SPM_BUS_PROTECT2_MASK_B (SPM_BASE + 0x40C)
+#define SPM_BUS_PROTECT3_MASK_B (SPM_BASE + 0x410)
+#define SPM_BUS_PROTECT4_MASK_B (SPM_BASE + 0x414)
+#define SPM_BUS_PROTECT5_MASK_B (SPM_BASE + 0x418)
+#define SPM_BUS_PROTECT6_MASK_B (SPM_BASE + 0x41C)
+#define SPM_BUS_PROTECT7_MASK_B (SPM_BASE + 0x420)
+#define SPM_BUS_PROTECT8_MASK_B (SPM_BASE + 0x424)
+#define SPM_BUS_PROTECT9_MASK_B (SPM_BASE + 0x428)
+#define SPM_EMI_BW_MODE (SPM_BASE + 0x42C)
+#define SPM2MM_CON (SPM_BASE + 0x434)
+#define SPM2CPUEB_CON (SPM_BASE + 0x438)
+#define AP_MDSRC_REQ (SPM_BASE + 0x43C)
+#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x440)
+#define SPM_PLL_CON (SPM_BASE + 0x444)
+#define RC_SPM_CTRL (SPM_BASE + 0x448)
+#define SPM_DRAM_MCU_SW_CON_0 (SPM_BASE + 0x44C)
+#define SPM_DRAM_MCU_SW_CON_1 (SPM_BASE + 0x450)
+#define SPM_DRAM_MCU_SW_CON_2 (SPM_BASE + 0x454)
+#define SPM_DRAM_MCU_SW_CON_3 (SPM_BASE + 0x458)
+#define SPM_DRAM_MCU_SW_CON_4 (SPM_BASE + 0x45C)
+#define SPM_DRAM_MCU_STA_0 (SPM_BASE + 0x460)
+#define SPM_DRAM_MCU_STA_1 (SPM_BASE + 0x464)
+#define SPM_DRAM_MCU_STA_2 (SPM_BASE + 0x468)
+#define SPM_DRAM_MCU_SW_SEL_0 (SPM_BASE + 0x46C)
+#define RELAY_DVFS_LEVEL (SPM_BASE + 0x470)
+#define DRAMC_DPY_CLK_SW_CON_0 (SPM_BASE + 0x474)
+#define DRAMC_DPY_CLK_SW_CON_1 (SPM_BASE + 0x478)
+#define DRAMC_DPY_CLK_SW_CON_2 (SPM_BASE + 0x47C)
+#define DRAMC_DPY_CLK_SW_CON_3 (SPM_BASE + 0x480)
+#define DRAMC_DPY_CLK_SW_SEL_0 (SPM_BASE + 0x484)
+#define DRAMC_DPY_CLK_SW_SEL_1 (SPM_BASE + 0x488)
+#define DRAMC_DPY_CLK_SW_SEL_2 (SPM_BASE + 0x48C)
+#define DRAMC_DPY_CLK_SW_SEL_3 (SPM_BASE + 0x490)
+#define DRAMC_DPY_CLK_SPM_CON (SPM_BASE + 0x494)
+#define SPM_DVFS_LEVEL (SPM_BASE + 0x498)
+#define SPM_CIRQ_CON (SPM_BASE + 0x49C)
+#define SPM_DVFS_MISC (SPM_BASE + 0x4A0)
+#define RG_MODULE_SW_CG_0_MASK_REQ_0 (SPM_BASE + 0x4A4)
+#define RG_MODULE_SW_CG_0_MASK_REQ_1 (SPM_BASE + 0x4A8)
+#define RG_MODULE_SW_CG_0_MASK_REQ_2 (SPM_BASE + 0x4AC)
+#define RG_MODULE_SW_CG_1_MASK_REQ_0 (SPM_BASE + 0x4B0)
+#define RG_MODULE_SW_CG_1_MASK_REQ_1 (SPM_BASE + 0x4B4)
+#define RG_MODULE_SW_CG_1_MASK_REQ_2 (SPM_BASE + 0x4B8)
+#define RG_MODULE_SW_CG_2_MASK_REQ_0 (SPM_BASE + 0x4BC)
+#define RG_MODULE_SW_CG_2_MASK_REQ_1 (SPM_BASE + 0x4C0)
+#define RG_MODULE_SW_CG_2_MASK_REQ_2 (SPM_BASE + 0x4C4)
+#define RG_MODULE_SW_CG_3_MASK_REQ_0 (SPM_BASE + 0x4C8)
+#define RG_MODULE_SW_CG_3_MASK_REQ_1 (SPM_BASE + 0x4CC)
+#define RG_MODULE_SW_CG_3_MASK_REQ_2 (SPM_BASE + 0x4D0)
+#define PWR_STATUS_MASK_REQ_0 (SPM_BASE + 0x4D4)
+#define PWR_STATUS_MASK_REQ_1 (SPM_BASE + 0x4D8)
+#define PWR_STATUS_MASK_REQ_2 (SPM_BASE + 0x4DC)
+#define SPM_CG_CHECK_CON (SPM_BASE + 0x4E0)
+#define SPM_SRC_RDY_STA (SPM_BASE + 0x4E4)
+#define SPM_DVS_DFS_LEVEL (SPM_BASE + 0x4E8)
+#define SPM_FORCE_DVFS (SPM_BASE + 0x4EC)
+#define DRAMC_MCU_SRAM_CON (SPM_BASE + 0x4F0)
+#define DRAMC_MCU2_SRAM_CON (SPM_BASE + 0x4F4)
+#define DPY_SHU_SRAM_CON (SPM_BASE + 0x4F8)
+#define DPY_SHU2_SRAM_CON (SPM_BASE + 0x4FC)
+#define SPM_DPM_P2P_STA (SPM_BASE + 0x514)
+#define SPM_DPM_P2P_CON (SPM_BASE + 0x518)
+#define SPM_SW_FLAG_0 (SPM_BASE + 0x600)
+#define SPM_SW_DEBUG_0 (SPM_BASE + 0x604)
+#define SPM_SW_FLAG_1 (SPM_BASE + 0x608)
+#define SPM_SW_DEBUG_1 (SPM_BASE + 0x60C)
+#define SPM_SW_RSV_0 (SPM_BASE + 0x610)
+#define SPM_SW_RSV_1 (SPM_BASE + 0x614)
+#define SPM_SW_RSV_2 (SPM_BASE + 0x618)
+#define SPM_SW_RSV_3 (SPM_BASE + 0x61C)
+#define SPM_SW_RSV_4 (SPM_BASE + 0x620)
+#define SPM_SW_RSV_5 (SPM_BASE + 0x624)
+#define SPM_SW_RSV_6 (SPM_BASE + 0x628)
+#define SPM_SW_RSV_7 (SPM_BASE + 0x62C)
+#define SPM_SW_RSV_8 (SPM_BASE + 0x630)
+#define SPM_BK_WAKE_EVENT (SPM_BASE + 0x634)
+#define SPM_BK_VTCXO_DUR (SPM_BASE + 0x638)
+#define SPM_BK_WAKE_MISC (SPM_BASE + 0x63C)
+#define SPM_BK_PCM_TIMER (SPM_BASE + 0x640)
+#define ULPOSC_CON (SPM_BASE + 0x644)
+#define SPM_RSV_CON_0 (SPM_BASE + 0x650)
+#define SPM_RSV_CON_1 (SPM_BASE + 0x654)
+#define SPM_RSV_STA_0 (SPM_BASE + 0x658)
+#define SPM_RSV_STA_1 (SPM_BASE + 0x65C)
+#define SPM_SPARE_CON (SPM_BASE + 0x660)
+#define SPM_SPARE_CON_SET (SPM_BASE + 0x664)
+#define SPM_SPARE_CON_CLR (SPM_BASE + 0x668)
+#define SPM_CROSS_WAKE_M00_REQ (SPM_BASE + 0x66C)
+#define SPM_CROSS_WAKE_M01_REQ (SPM_BASE + 0x670)
+#define SPM_CROSS_WAKE_M02_REQ (SPM_BASE + 0x674)
+#define SPM_CROSS_WAKE_M03_REQ (SPM_BASE + 0x678)
+#define SCP_VCORE_LEVEL (SPM_BASE + 0x67C)
+#define SC_MM_CK_SEL_CON (SPM_BASE + 0x680)
+#define SPARE_ACK_MASK (SPM_BASE + 0x684)
+#define SPM_DV_CON_0 (SPM_BASE + 0x68C)
+#define SPM_DV_CON_1 (SPM_BASE + 0x690)
+#define SPM_DV_STA (SPM_BASE + 0x694)
+#define CONN_XOWCN_DEBUG_EN (SPM_BASE + 0x698)
+#define SPM_SEMA_M0 (SPM_BASE + 0x69C)
+#define SPM_SEMA_M1 (SPM_BASE + 0x6A0)
+#define SPM_SEMA_M2 (SPM_BASE + 0x6A4)
+#define SPM_SEMA_M3 (SPM_BASE + 0x6A8)
+#define SPM_SEMA_M4 (SPM_BASE + 0x6AC)
+#define SPM_SEMA_M5 (SPM_BASE + 0x6B0)
+#define SPM_SEMA_M6 (SPM_BASE + 0x6B4)
+#define SPM_SEMA_M7 (SPM_BASE + 0x6B8)
+#define SPM2ADSP_MAILBOX (SPM_BASE + 0x6BC)
+#define ADSP2SPM_MAILBOX (SPM_BASE + 0x6C0)
+#define SPM_ADSP_IRQ (SPM_BASE + 0x6C4)
+#define SPM_MD32_IRQ (SPM_BASE + 0x6C8)
+#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x6CC)
+#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x6D0)
+#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x6D4)
+#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x6D8)
+#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x6DC)
+#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x6E0)
+#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x6E4)
+#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x6E8)
+#define SPM_AP_SEMA (SPM_BASE + 0x6F8)
+#define SPM_SPM_SEMA (SPM_BASE + 0x6FC)
+#define SPM_DVFS_CON (SPM_BASE + 0x700)
+#define SPM_DVFS_CON_STA (SPM_BASE + 0x704)
+#define SPM_PMIC_SPMI_CON (SPM_BASE + 0x708)
+#define SPM_DVFS_CMD0 (SPM_BASE + 0x710)
+#define SPM_DVFS_CMD1 (SPM_BASE + 0x714)
+#define SPM_DVFS_CMD2 (SPM_BASE + 0x718)
+#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C)
+#define SPM_DVFS_CMD4 (SPM_BASE + 0x720)
+#define SPM_DVFS_CMD5 (SPM_BASE + 0x724)
+#define SPM_DVFS_CMD6 (SPM_BASE + 0x728)
+#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C)
+#define SPM_DVFS_CMD8 (SPM_BASE + 0x730)
+#define SPM_DVFS_CMD9 (SPM_BASE + 0x734)
+#define SPM_DVFS_CMD10 (SPM_BASE + 0x738)
+#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C)
+#define SPM_DVFS_CMD12 (SPM_BASE + 0x740)
+#define SPM_DVFS_CMD13 (SPM_BASE + 0x744)
+#define SPM_DVFS_CMD14 (SPM_BASE + 0x748)
+#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C)
+#define SPM_DVFS_CMD16 (SPM_BASE + 0x750)
+#define SPM_DVFS_CMD17 (SPM_BASE + 0x754)
+#define SPM_DVFS_CMD18 (SPM_BASE + 0x758)
+#define SPM_DVFS_CMD19 (SPM_BASE + 0x75C)
+#define SPM_DVFS_CMD20 (SPM_BASE + 0x760)
+#define SPM_DVFS_CMD21 (SPM_BASE + 0x764)
+#define SPM_DVFS_CMD22 (SPM_BASE + 0x768)
+#define SPM_DVFS_CMD23 (SPM_BASE + 0x76C)
+#define SYS_TIMER_VALUE_L (SPM_BASE + 0x770)
+#define SYS_TIMER_VALUE_H (SPM_BASE + 0x774)
+#define SYS_TIMER_START_L (SPM_BASE + 0x778)
+#define SYS_TIMER_START_H (SPM_BASE + 0x77C)
+#define SYS_TIMER_LATCH_L_00 (SPM_BASE + 0x780)
+#define SYS_TIMER_LATCH_H_00 (SPM_BASE + 0x784)
+#define SYS_TIMER_LATCH_L_01 (SPM_BASE + 0x788)
+#define SYS_TIMER_LATCH_H_01 (SPM_BASE + 0x78C)
+#define SYS_TIMER_LATCH_L_02 (SPM_BASE + 0x790)
+#define SYS_TIMER_LATCH_H_02 (SPM_BASE + 0x794)
+#define SYS_TIMER_LATCH_L_03 (SPM_BASE + 0x798)
+#define SYS_TIMER_LATCH_H_03 (SPM_BASE + 0x79C)
+#define SYS_TIMER_LATCH_L_04 (SPM_BASE + 0x7A0)
+#define SYS_TIMER_LATCH_H_04 (SPM_BASE + 0x7A4)
+#define SYS_TIMER_LATCH_L_05 (SPM_BASE + 0x7A8)
+#define SYS_TIMER_LATCH_H_05 (SPM_BASE + 0x7AC)
+#define SYS_TIMER_LATCH_L_06 (SPM_BASE + 0x7B0)
+#define SYS_TIMER_LATCH_H_06 (SPM_BASE + 0x7B4)
+#define SYS_TIMER_LATCH_L_07 (SPM_BASE + 0x7B8)
+#define SYS_TIMER_LATCH_H_07 (SPM_BASE + 0x7BC)
+#define SYS_TIMER_LATCH_L_08 (SPM_BASE + 0x7C0)
+#define SYS_TIMER_LATCH_H_08 (SPM_BASE + 0x7C4)
+#define SYS_TIMER_LATCH_L_09 (SPM_BASE + 0x7C8)
+#define SYS_TIMER_LATCH_H_09 (SPM_BASE + 0x7CC)
+#define SYS_TIMER_LATCH_L_10 (SPM_BASE + 0x7D0)
+#define SYS_TIMER_LATCH_H_10 (SPM_BASE + 0x7D4)
+#define SYS_TIMER_LATCH_L_11 (SPM_BASE + 0x7D8)
+#define SYS_TIMER_LATCH_H_11 (SPM_BASE + 0x7DC)
+#define SYS_TIMER_LATCH_L_12 (SPM_BASE + 0x7E0)
+#define SYS_TIMER_LATCH_H_12 (SPM_BASE + 0x7E4)
+#define SYS_TIMER_LATCH_L_13 (SPM_BASE + 0x7E8)
+#define SYS_TIMER_LATCH_H_13 (SPM_BASE + 0x7EC)
+#define SYS_TIMER_LATCH_L_14 (SPM_BASE + 0x7F0)
+#define SYS_TIMER_LATCH_H_14 (SPM_BASE + 0x7F4)
+#define SYS_TIMER_LATCH_L_15 (SPM_BASE + 0x7F8)
+#define SYS_TIMER_LATCH_H_15 (SPM_BASE + 0x7FC)
+#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800)
+#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804)
+#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808)
+#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C)
+#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810)
+#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814)
+#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818)
+#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C)
+#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820)
+#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824)
+#define PCM_WDT_LATCH_10 (SPM_BASE + 0x828)
+#define PCM_WDT_LATCH_11 (SPM_BASE + 0x82C)
+#define PCM_WDT_LATCH_12 (SPM_BASE + 0x830)
+#define PCM_WDT_LATCH_13 (SPM_BASE + 0x834)
+#define PCM_WDT_LATCH_14 (SPM_BASE + 0x838)
+#define PCM_WDT_LATCH_15 (SPM_BASE + 0x83C)
+#define PCM_WDT_LATCH_16 (SPM_BASE + 0x840)
+#define PCM_WDT_LATCH_17 (SPM_BASE + 0x844)
+#define PCM_WDT_LATCH_18 (SPM_BASE + 0x848)
+#define PCM_WDT_LATCH_SPARE_0 (SPM_BASE + 0x84C)
+#define PCM_WDT_LATCH_SPARE_1 (SPM_BASE + 0x850)
+#define PCM_WDT_LATCH_SPARE_2 (SPM_BASE + 0x854)
+#define DRAMC_GATING_ERR_LATCH_CH0_0 (SPM_BASE + 0x8A0)
+#define DRAMC_GATING_ERR_LATCH_CH0_1 (SPM_BASE + 0x8A4)
+#define DRAMC_GATING_ERR_LATCH_CH0_2 (SPM_BASE + 0x8A8)
+#define DRAMC_GATING_ERR_LATCH_CH0_3 (SPM_BASE + 0x8AC)
+#define DRAMC_GATING_ERR_LATCH_CH0_4 (SPM_BASE + 0x8B0)
+#define DRAMC_GATING_ERR_LATCH_CH0_5 (SPM_BASE + 0x8B4)
+#define DRAMC_GATING_ERR_LATCH_SPARE_0 (SPM_BASE + 0x8F4)
+#define SPM_ACK_CHK_CON_0 (SPM_BASE + 0x900)
+#define SPM_ACK_CHK_PC_0 (SPM_BASE + 0x904)
+#define SPM_ACK_CHK_SEL_0 (SPM_BASE + 0x908)
+#define SPM_ACK_CHK_TIMER_0 (SPM_BASE + 0x90C)
+#define SPM_ACK_CHK_STA_0 (SPM_BASE + 0x910)
+#define SPM_ACK_CHK_SWINT_0 (SPM_BASE + 0x914)
+#define SPM_ACK_CHK_CON_1 (SPM_BASE + 0x920)
+#define SPM_ACK_CHK_PC_1 (SPM_BASE + 0x924)
+#define SPM_ACK_CHK_SEL_1 (SPM_BASE + 0x928)
+#define SPM_ACK_CHK_TIMER_1 (SPM_BASE + 0x92C)
+#define SPM_ACK_CHK_STA_1 (SPM_BASE + 0x930)
+#define SPM_ACK_CHK_SWINT_1 (SPM_BASE + 0x934)
+#define SPM_ACK_CHK_CON_2 (SPM_BASE + 0x940)
+#define SPM_ACK_CHK_PC_2 (SPM_BASE + 0x944)
+#define SPM_ACK_CHK_SEL_2 (SPM_BASE + 0x948)
+#define SPM_ACK_CHK_TIMER_2 (SPM_BASE + 0x94C)
+#define SPM_ACK_CHK_STA_2 (SPM_BASE + 0x950)
+#define SPM_ACK_CHK_SWINT_2 (SPM_BASE + 0x954)
+#define SPM_ACK_CHK_CON_3 (SPM_BASE + 0x960)
+#define SPM_ACK_CHK_PC_3 (SPM_BASE + 0x964)
+#define SPM_ACK_CHK_SEL_3 (SPM_BASE + 0x968)
+#define SPM_ACK_CHK_TIMER_3 (SPM_BASE + 0x96C)
+#define SPM_ACK_CHK_STA_3 (SPM_BASE + 0x970)
+#define SPM_ACK_CHK_SWINT_3 (SPM_BASE + 0x974)
+#define SPM_COUNTER_0 (SPM_BASE + 0x978)
+#define SPM_COUNTER_1 (SPM_BASE + 0x97C)
+#define SPM_COUNTER_2 (SPM_BASE + 0x980)
+#define SYS_TIMER_CON (SPM_BASE + 0x98C)
+#define SPM_TWAM_CON (SPM_BASE + 0x990)
+#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x994)
+#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x998)
+#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x99C)
+#define PMSR_LAST_DAT (SPM_BASE + 0xF00)
+#define PMSR_LAST_CNT (SPM_BASE + 0xF04)
+#define PMSR_LAST_ACK (SPM_BASE + 0xF08)
+#define SPM_PMSR_SEL_CON0 (SPM_BASE + 0xF10)
+#define SPM_PMSR_SEL_CON1 (SPM_BASE + 0xF14)
+#define SPM_PMSR_SEL_CON2 (SPM_BASE + 0xF18)
+#define SPM_PMSR_SEL_CON3 (SPM_BASE + 0xF1C)
+#define SPM_PMSR_SEL_CON4 (SPM_BASE + 0xF20)
+#define SPM_PMSR_SEL_CON5 (SPM_BASE + 0xF24)
+#define SPM_PMSR_SEL_CON6 (SPM_BASE + 0xF28)
+#define SPM_PMSR_SEL_CON7 (SPM_BASE + 0xF2C)
+#define SPM_PMSR_SEL_CON8 (SPM_BASE + 0xF30)
+#define SPM_PMSR_SEL_CON9 (SPM_BASE + 0xF34)
+#define SPM_PMSR_SEL_CON10 (SPM_BASE + 0xF3C)
+#define SPM_PMSR_SEL_CON11 (SPM_BASE + 0xF40)
+#define SPM_PMSR_TIEMR_STA0 (SPM_BASE + 0xFB8)
+#define SPM_PMSR_TIEMR_STA1 (SPM_BASE + 0xFBC)
+#define SPM_PMSR_TIEMR_STA2 (SPM_BASE + 0xFC0)
+#define SPM_PMSR_GENERAL_CON0 (SPM_BASE + 0xFC4)
+#define SPM_PMSR_GENERAL_CON1 (SPM_BASE + 0xFC8)
+#define SPM_PMSR_GENERAL_CON2 (SPM_BASE + 0xFCC)
+#define SPM_PMSR_GENERAL_CON3 (SPM_BASE + 0xFD0)
+#define SPM_PMSR_GENERAL_CON4 (SPM_BASE + 0xFD4)
+#define SPM_PMSR_GENERAL_CON5 (SPM_BASE + 0xFD8)
+#define SPM_PMSR_SW_RESET (SPM_BASE + 0xFDC)
+#define SPM_PMSR_MON_CON0 (SPM_BASE + 0xFE0)
+#define SPM_PMSR_MON_CON1 (SPM_BASE + 0xFE4)
+#define SPM_PMSR_MON_CON2 (SPM_BASE + 0xFE8)
+#define SPM_PMSR_LEN_CON0 (SPM_BASE + 0xFEC)
+#define SPM_PMSR_LEN_CON1 (SPM_BASE + 0xFF0)
+#define SPM_PMSR_LEN_CON2 (SPM_BASE + 0xFF4)
+
+#endif /* SPM_REG_H */
diff --git a/plat/mediatek/mt8188/plat_config.mk b/plat/mediatek/mt8188/plat_config.mk
new file mode 100644
index 0000000..137318e
--- /dev/null
+++ b/plat/mediatek/mt8188/plat_config.mk
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Separate text code and read only data
+SEPARATE_CODE_AND_RODATA := 1
+# ARMv8.2 and above need enable HW assist coherence
+HW_ASSISTED_COHERENCY := 1
+# No need coherency memory because of HW assistency
+USE_COHERENT_MEM := 0
+# GIC600
+GICV3_SUPPORT_GIC600 := 1
+#
+# MTK options
+#
+PLAT_EXTRA_RODATA_INCLUDES := 1
+USE_PMIC_WRAP_INIT_V2 := 1
+USE_RTC_MT6359P := 1
+
+# Configs for A78 and A55
+CTX_INCLUDE_AARCH32_REGS := 0
+ERRATA_A55_1530923 := 1
+ERRATA_A55_1221012 := 1
+ERRATA_A78_1688305 := 1
+ERRATA_A78_1941498 := 1
+ERRATA_A78_1951500 := 1
+ERRATA_A78_1821534 := 1
+ERRATA_A78_2132060 := 1
+ERRATA_A78_2242635 := 1
+ERRATA_A78_2376745 := 1
+ERRATA_A78_2395406 := 1
+
+CONFIG_ARCH_ARM_V8_2 := y
+CONFIG_MTK_MCUSYS := y
+MCUSYS_VERSION := v1
+CONFIG_MTK_PM_SUPPORT := y
+CONFIG_MTK_PM_ARCH := 8_2
+CONFIG_MTK_CPU_PM_SUPPORT := y
+CONFIG_MTK_CPU_PM_ARCH := 3_2
+CONFIG_MTK_SMP_EN := y
+CONFIG_MTK_CPU_SUSPEND_EN := y
+CPU_PM_TINYSYS_SUPPORT := y
+MTK_PUBEVENT_ENABLE := y
+
+MACH_MT8188 := 1
+$(eval $(call add_define,MACH_MT8188))
diff --git a/plat/mediatek/mt8188/plat_mmap.c b/plat/mediatek/mt8188/plat_mmap.c
new file mode 100644
index 0000000..a611d22
--- /dev/null
+++ b/plat/mediatek/mt8188/plat_mmap.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <mtk_mmap_pool.h>
+#include <platform_def.h>
+
+static const mmap_region_t plat_mmap[] = {
+ MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CPU_IDLE_SRAM_BASE, CPU_IDLE_SRAM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+DECLARE_MTK_MMAP_REGIONS(plat_mmap);
diff --git a/plat/mediatek/mt8188/platform.mk b/plat/mediatek/mt8188/platform.mk
new file mode 100644
index 0000000..b6a17aa
--- /dev/null
+++ b/plat/mediatek/mt8188/platform.mk
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+MTK_SOC := ${PLAT}
+
+include plat/mediatek/build_helpers/mtk_build_helpers.mk
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common \
+ -I${MTK_PLAT}/include \
+ -I${MTK_PLAT}/include/${ARCH_VERSION} \
+ -I${MTK_PLAT} \
+ -I${MTK_PLAT_SOC}/include \
+ -Idrivers/arm/gic \
+
+MODULES-y += $(MTK_PLAT)/common
+MODULES-y += $(MTK_PLAT)/common/lpm
+MODULES-y += $(MTK_PLAT)/lib/mtk_init
+MODULES-y += $(MTK_PLAT)/lib/pm
+MODULES-y += $(MTK_PLAT)/lib/system_reset
+MODULES-y += $(MTK_PLAT)/drivers/audio
+MODULES-y += $(MTK_PLAT)/drivers/cirq
+MODULES-y += $(MTK_PLAT)/drivers/cpu_pm
+MODULES-y += $(MTK_PLAT)/drivers/dcm
+MODULES-y += $(MTK_PLAT)/drivers/dfd
+MODULES-y += $(MTK_PLAT)/drivers/dp
+MODULES-y += $(MTK_PLAT)/drivers/emi_mpu
+MODULES-y += $(MTK_PLAT)/drivers/gic600
+MODULES-y += $(MTK_PLAT)/drivers/gpio
+MODULES-y += $(MTK_PLAT)/drivers/iommu
+MODULES-y += $(MTK_PLAT)/drivers/mcusys
+MODULES-y += $(MTK_PLAT)/drivers/pmic
+MODULES-y += $(MTK_PLAT)/drivers/pmic_wrap
+MODULES-y += $(MTK_PLAT)/drivers/ptp3
+MODULES-y += $(MTK_PLAT)/drivers/rtc
+MODULES-y += $(MTK_PLAT)/drivers/timer
+MODULES-y += $(MTK_PLAT)/helpers
+MODULES-y += $(MTK_PLAT)/topology
+
+PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/bl_aux_params/bl_aux_params.c
+
+BL31_SOURCES += drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/aarch64/cortex_a55.S \
+ lib/cpus/aarch64/cortex_a78.S \
+ ${GICV3_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/params_setup.c \
+ $(MTK_PLAT)/$(MTK_SOC)/plat_mmap.c
+
+include plat/mediatek/build_helpers/mtk_build_helpers_epilogue.mk
+
+include lib/coreboot/coreboot.mk
diff --git a/plat/mediatek/mt8192/aarch64/plat_helpers.S b/plat/mediatek/mt8192/aarch64/plat_helpers.S
new file mode 100644
index 0000000..99274de
--- /dev/null
+++ b/plat/mediatek/mt8192/aarch64/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_mediatek_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+ *
+ * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and
+ * AFF0 is thread id. There is only one cluster in ARMv8.2
+ * and one thread in current implementation.
+ *
+ * With this function: CorePos = CoreID (AFF1)
+ * we do it with x0 = (x0 >> 8) & 0xff
+ * -----------------------------------------------------
+ */
+func plat_mediatek_calc_core_pos
+ mov x1, #MPIDR_AFFLVL_MASK
+ and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+ ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8192/aarch64/platform_common.c b/plat/mediatek/mt8192/aarch64/platform_common.c
new file mode 100644
index 0000000..fc98871
--- /dev/null
+++ b/plat/mediatek/mt8192/aarch64/platform_common.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Project Includes */
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+/* Platform Includes */
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_mmap[] = {
+ /* for TF text, RO, RW */
+ MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_MCDI_SRAM_BASE, MTK_MCDI_SRAM_MAP_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_SCTRL_REVISER_BASE, APUSYS_SCTRL_REVISER_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_APU_S_S_4_BASE, APUSYS_APU_S_S_4_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_APC_AO_WRAPPER_BASE, APUSYS_APC_AO_WRAPPER_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_NOC_DAPC_AO_BASE, APUSYS_NOC_DAPC_AO_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_RW_DATA | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_CODE | MT_SECURE);
+ mmap_add(plat_mmap);
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c
new file mode 100644
index 0000000..c3cb9a5
--- /dev/null
+++ b/plat/mediatek/mt8192/bl31_plat_setup.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <devapc/devapc.h>
+#include <emi_mpu/emi_mpu.h>
+#include <gpio/mtgpio.h>
+#include <mt_gic_v3.h>
+#include <mt_spm.h>
+#include <mt_timer.h>
+#include <mtk_dcm.h>
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ params_early_setup(arg1);
+
+#if COREBOOT
+ if (coreboot_serial.type) {
+ console_16550_register(coreboot_serial.baseaddr,
+ coreboot_serial.input_hertz,
+ coreboot_serial.baud,
+ &console);
+ }
+#else
+ console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+ NOTICE("MT8192 bl31_setup\n");
+
+ bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ /* Set dcm on */
+ if (!dcm_set_default()) {
+ ERROR("Failed to set default dcm on!!\n");
+ }
+
+ /* MPU Init */
+ emi_mpu_init();
+
+ /* DAPC Init */
+ devapc_init();
+
+ /* Initialize the GIC driver, CPU and distributor interfaces */
+ mt_gic_driver_init();
+ mt_gic_init();
+
+ mt_gpio_init();
+ mt_systimer_init();
+ generic_delay_timer_init();
+ spm_boot_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(BL31_START,
+ BL31_END - BL31_START,
+ BL_CODE_BASE,
+ BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c
new file mode 100644
index 0000000..782aa5f
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <mtk_apusys.h>
+#include <plat/common/platform.h>
+
+uint64_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+ uint32_t *ret1)
+{
+ uint32_t request_ops;
+
+ request_ops = (uint32_t)x1;
+ INFO("[APUSYS] ops=0x%x\n", request_ops);
+
+ switch (request_ops) {
+ case MTK_SIP_APU_START_MCU:
+ /* setup addr[33:32] in reviser */
+ mmio_write_32(REVISER_SECUREFW_CTXT, 0U);
+ mmio_write_32(REVISER_USDRFW_CTXT, 0U);
+
+ /* setup secure sideband */
+ mmio_write_32(AO_SEC_FW,
+ (SEC_FW_NON_SECURE << SEC_FW_SHIFT_NS) |
+ (0U << SEC_FW_DOMAIN_SHIFT));
+
+ /* setup boot address */
+ mmio_write_32(AO_MD32_BOOT_CTRL, 0U);
+
+ /* setup pre-define region */
+ mmio_write_32(AO_MD32_PRE_DEFINE,
+ (PRE_DEFINE_CACHE_TCM << PRE_DEFINE_SHIFT_0G) |
+ (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_1G) |
+ (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_2G) |
+ (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_3G));
+
+ /* release runstall */
+ mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_RUN);
+
+ INFO("[APUSYS] reviser_ctxt=%x,%x\n",
+ mmio_read_32(REVISER_SECUREFW_CTXT),
+ mmio_read_32(REVISER_USDRFW_CTXT));
+ INFO("[APUSYS]fw=0x%08x,boot=0x%08x,def=0x%08x,sys=0x%08x\n",
+ mmio_read_32(AO_SEC_FW),
+ mmio_read_32(AO_MD32_BOOT_CTRL),
+ mmio_read_32(AO_MD32_PRE_DEFINE),
+ mmio_read_32(AO_MD32_SYS_CTRL));
+ break;
+ case MTK_SIP_APU_STOP_MCU:
+ /* hold runstall */
+ mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_STALL);
+
+ INFO("[APUSYS] md32_boot_ctrl=0x%08x,runstall=0x%08x\n",
+ mmio_read_32(AO_MD32_BOOT_CTRL),
+ mmio_read_32(AO_MD32_SYS_CTRL));
+ break;
+ default:
+ ERROR("%s, unknown request_ops = %x\n", __func__, request_ops);
+ break;
+ }
+
+ return 0UL;
+}
diff --git a/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h
new file mode 100644
index 0000000..95fac4a
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MTK_APUSYS_H__
+#define __MTK_APUSYS_H__
+
+#include <stdint.h>
+
+/* setup the SMC command ops */
+#define MTK_SIP_APU_START_MCU 0x00U
+#define MTK_SIP_APU_STOP_MCU 0x01U
+
+/* AO Register */
+#define AO_MD32_PRE_DEFINE (APUSYS_APU_S_S_4_BASE + 0x00)
+#define AO_MD32_BOOT_CTRL (APUSYS_APU_S_S_4_BASE + 0x04)
+#define AO_MD32_SYS_CTRL (APUSYS_APU_S_S_4_BASE + 0x08)
+#define AO_SEC_FW (APUSYS_APU_S_S_4_BASE + 0x10)
+
+#define PRE_DEFINE_CACHE_TCM 0x3U
+#define PRE_DEFINE_CACHE 0x2U
+#define PRE_DEFINE_SHIFT_0G 0U
+#define PRE_DEFINE_SHIFT_1G 2U
+#define PRE_DEFINE_SHIFT_2G 4U
+#define PRE_DEFINE_SHIFT_3G 6U
+
+#define SEC_FW_NON_SECURE 1U
+#define SEC_FW_SHIFT_NS 4U
+#define SEC_FW_DOMAIN_SHIFT 0U
+
+#define SYS_CTRL_RUN 0U
+#define SYS_CTRL_STALL 1U
+
+/* Reviser Register */
+#define REVISER_SECUREFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x300)
+#define REVISER_USDRFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x304)
+
+uint64_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+ uint32_t *ret1);
+#endif /* __MTK_APUSYS_H__ */
diff --git a/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c
new file mode 100644
index 0000000..245d512
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c
@@ -0,0 +1,571 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <mtk_apusys_apc.h>
+#include <mtk_apusys_apc_def.h>
+#include <mtk_plat_common.h>
+#include <platform_def.h>
+
+static const struct APC_DOM_16 APUSYS_NOC_DAPC_AO[] = {
+/* 0~3 */
+APUSYS_APC_AO_ATTR("slv07-0",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+APUSYS_APC_AO_ATTR("slv07-1",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+APUSYS_APC_AO_ATTR("slv07-2",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+APUSYS_APC_AO_ATTR("slv07-3",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+
+/* 16~18 */
+APUSYS_APC_AO_ATTR("slv01-0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("slv01-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("slv01-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 19~21 */
+APUSYS_APC_AO_ATTR("slv00-0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("slv00-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("slv00-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 22~26 */
+APUSYS_APC_AO_ATTR("slv02-0",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+APUSYS_APC_AO_ATTR("slv02-1",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+APUSYS_APC_AO_ATTR("slv02-2",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+APUSYS_APC_AO_ATTR("slv02-3",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+APUSYS_APC_AO_ATTR("slv02-4",
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION,
+ NO_PROTECTION, NO_PROTECTION, NO_PROTECTION, NO_PROTECTION),
+};
+
+static int32_t set_slave_noc_dapc(uint32_t slave,
+ enum APUSYS_APC_DOMAIN_ID domain_id,
+ enum APUSYS_APC_PERM_TYPE perm)
+{
+ uint32_t apc_register_index;
+ uint32_t apc_set_index;
+ uintptr_t base;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+ int32_t ret;
+
+ if (perm >= PERM_NUM) {
+ ERROR("[NOC_DAPC] perm type:0x%x is not supported!\n", perm);
+ ret = APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED;
+ goto exit;
+ }
+
+ apc_register_index = slave / APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM;
+ apc_set_index = slave % APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM;
+
+ clr_bit = 0xFFFFFFFF ^ (0x3U << (apc_set_index * 2));
+ set_bit = perm << (apc_set_index * 2);
+
+ if ((slave < APUSYS_NOC_DAPC_AO_SLAVE_NUM) &&
+ (domain_id < APUSYS_NOC_DAPC_AO_DOM_NUM)) {
+ base = APUSYS_NOC_DAPC_AO_BASE +
+ (domain_id * 0x40) + (apc_register_index * 4);
+ apuapc_writel(apuapc_readl(base) & clr_bit, base);
+ apuapc_writel(apuapc_readl(base) | set_bit, base);
+ ret = APUSYS_APC_OK;
+ } else {
+ ERROR("[NOC_DAPC] %s: %s, %s:0x%x, %s:0x%x\n",
+ __func__, "out of boundary",
+ "slave", slave,
+ "domain_id", domain_id);
+ ret = APUSYS_APC_ERR_OUT_OF_BOUNDARY;
+ }
+
+exit:
+ return ret;
+}
+
+static void dump_apusys_noc_dapc(void)
+{
+ uint32_t reg_num;
+ uint32_t d, i;
+
+ reg_num = APUSYS_NOC_DAPC_AO_SLAVE_NUM /
+ APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM;
+ for (d = 0U; d < APUSYS_NOC_DAPC_AO_DOM_NUM; d++) {
+ for (i = 0U; i <= reg_num; i++) {
+ INFO("[NOCDAPC] D%d_APC_%d: 0x%x\n", d, i,
+ apuapc_readl(APUSYS_NOC_DAPC_AO_BASE +
+ (d * 0x40) + (i * 4)));
+ }
+ }
+
+ INFO("[NOCDAPC] APC_CON: 0x%x\n", apuapc_readl(APUSYS_NOC_DAPC_CON));
+}
+
+static const struct APC_DOM_16 APUSYS_AO_Devices[] = {
+
+/* 0 */
+APUSYS_APC_AO_ATTR("apusys_ao-0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apusys_ao-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apusys_ao-2",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apusys_ao-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apusys_ao-4",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apusys_ao-5",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("md32_apb_s-0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("md32_apb_s-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("md32_apb_s-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("md32_debug_apb",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+APUSYS_APC_AO_ATTR("apu_conn_config",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_sctrl_reviser",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_sema_stimer",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_emi_config",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_adl",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_edma_lite0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_edma_lite1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_edma0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_edma0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_dapc_ao",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+APUSYS_APC_AO_ATTR("apu_dapc",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("infra_bcrm",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apb_dbg_ctl",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("noc_dapc",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_noc_bcrm",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_noc_config",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("vpu_core0_config-0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("vpu_core0_config-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("vpu_core1_config-0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("vpu_core1_config-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 30 */
+APUSYS_APC_AO_ATTR("mdla0_apb-0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("mdla0_apb-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("mdla0_apb-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("mdla0_apb-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_iommu0_r0",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_iommu0_r1",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_iommu0_r2",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_iommu0_r3",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_iommu0_r4",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("apu_rsi2_config",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 40 */
+APUSYS_APC_AO_ATTR("apu_ssc2_config",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("vp6_core0_debug_apb",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+APUSYS_APC_AO_ATTR("vp6_core1_debug_apb",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+};
+
+static int32_t set_slave_apc(uint32_t slave,
+ enum APUSYS_APC_DOMAIN_ID domain_id,
+ enum APUSYS_APC_PERM_TYPE perm)
+{
+ uint32_t apc_register_index;
+ uint32_t apc_set_index;
+ uintptr_t base;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+ int32_t ret;
+
+ if (perm >= PERM_NUM) {
+ ERROR("[APUAPC] perm type:0x%x is not supported!\n", perm);
+ ret = APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED;
+ goto exit;
+ }
+
+ apc_register_index = slave / APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM;
+ apc_set_index = slave % APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM;
+
+ clr_bit = 0xFFFFFFFF ^ (0x3U << (apc_set_index * 2));
+ set_bit = perm << (apc_set_index * 2);
+
+ if ((slave < APUSYS_APC_SYS0_AO_SLAVE_NUM) &&
+ (domain_id < APUSYS_APC_SYS0_AO_DOM_NUM)) {
+ base = APUSYS_APC_AO_BASE +
+ (domain_id * 0x40) + (apc_register_index * 4);
+ apuapc_writel(apuapc_readl(base) & clr_bit, base);
+ apuapc_writel(apuapc_readl(base) | set_bit, base);
+ ret = APUSYS_APC_OK;
+ } else {
+ ERROR("[APUAPC] %s: %s, %s:0x%x, %s:0x%x\n",
+ __func__, "out of boundary",
+ "slave", slave,
+ "domain_id", domain_id);
+ ret = APUSYS_APC_ERR_OUT_OF_BOUNDARY;
+ }
+
+exit:
+ return ret;
+}
+
+static void dump_apusys_ao_apc(void)
+{
+ uint32_t reg_num;
+ uint32_t d, i;
+
+ reg_num = APUSYS_APC_SYS0_AO_SLAVE_NUM /
+ APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM;
+ for (d = 0U; d < APUSYS_APC_SYS0_AO_DOM_NUM; d++) {
+ for (i = 0U; i <= reg_num; i++) {
+ INFO("[APUAPC] D%d_APC_%d: 0x%x\n", d, i,
+ apuapc_readl(APUSYS_APC_AO_BASE +
+ (d * 0x40) + (i * 4)));
+ }
+ }
+ INFO("[APUAPC] APC_CON: 0x%x\n", apuapc_readl(APUSYS_APC_CON));
+}
+
+static int32_t set_apusys_noc_dapc(void)
+{
+ int32_t ret = 0;
+ uint32_t i;
+ uint32_t index;
+
+ for (i = 0U; i < ARRAY_SIZE(APUSYS_NOC_DAPC_AO); i++) {
+ if (i < APUSYS_NOC_DAPC_GAP_BOUNDARY) {
+ index = i;
+ } else {
+ index = i + APUSYS_NOC_DAPC_JUMP_GAP;
+ }
+ ret += set_slave_noc_dapc(index, DOMAIN_0,
+ APUSYS_NOC_DAPC_AO[i].d0_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_1,
+ APUSYS_NOC_DAPC_AO[i].d1_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_2,
+ APUSYS_NOC_DAPC_AO[i].d2_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_3,
+ APUSYS_NOC_DAPC_AO[i].d3_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_4,
+ APUSYS_NOC_DAPC_AO[i].d4_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_5,
+ APUSYS_NOC_DAPC_AO[i].d5_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_6,
+ APUSYS_NOC_DAPC_AO[i].d6_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_7,
+ APUSYS_NOC_DAPC_AO[i].d7_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_8,
+ APUSYS_NOC_DAPC_AO[i].d8_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_9,
+ APUSYS_NOC_DAPC_AO[i].d9_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_10,
+ APUSYS_NOC_DAPC_AO[i].d10_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_11,
+ APUSYS_NOC_DAPC_AO[i].d11_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_12,
+ APUSYS_NOC_DAPC_AO[i].d12_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_13,
+ APUSYS_NOC_DAPC_AO[i].d13_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_14,
+ APUSYS_NOC_DAPC_AO[i].d14_permission);
+ ret += set_slave_noc_dapc(index, DOMAIN_15,
+ APUSYS_NOC_DAPC_AO[i].d15_permission);
+ }
+
+ return ret;
+}
+
+static int32_t set_apusys_ao_apc(void)
+{
+ int32_t ret = 0;
+ uint32_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(APUSYS_AO_Devices); i++) {
+ ret += set_slave_apc(i, DOMAIN_0,
+ APUSYS_AO_Devices[i].d0_permission);
+ ret += set_slave_apc(i, DOMAIN_1,
+ APUSYS_AO_Devices[i].d1_permission);
+ ret += set_slave_apc(i, DOMAIN_2,
+ APUSYS_AO_Devices[i].d2_permission);
+ ret += set_slave_apc(i, DOMAIN_3,
+ APUSYS_AO_Devices[i].d3_permission);
+ ret += set_slave_apc(i, DOMAIN_4,
+ APUSYS_AO_Devices[i].d4_permission);
+ ret += set_slave_apc(i, DOMAIN_5,
+ APUSYS_AO_Devices[i].d5_permission);
+ ret += set_slave_apc(i, DOMAIN_6,
+ APUSYS_AO_Devices[i].d6_permission);
+ ret += set_slave_apc(i, DOMAIN_7,
+ APUSYS_AO_Devices[i].d7_permission);
+ ret += set_slave_apc(i, DOMAIN_8,
+ APUSYS_AO_Devices[i].d8_permission);
+ ret += set_slave_apc(i, DOMAIN_9,
+ APUSYS_AO_Devices[i].d9_permission);
+ ret += set_slave_apc(i, DOMAIN_10,
+ APUSYS_AO_Devices[i].d10_permission);
+ ret += set_slave_apc(i, DOMAIN_11,
+ APUSYS_AO_Devices[i].d11_permission);
+ ret += set_slave_apc(i, DOMAIN_12,
+ APUSYS_AO_Devices[i].d12_permission);
+ ret += set_slave_apc(i, DOMAIN_13,
+ APUSYS_AO_Devices[i].d13_permission);
+ ret += set_slave_apc(i, DOMAIN_14,
+ APUSYS_AO_Devices[i].d14_permission);
+ ret += set_slave_apc(i, DOMAIN_15,
+ APUSYS_AO_Devices[i].d15_permission);
+ }
+
+ return ret;
+}
+
+static void set_apusys_apc_lock(void)
+{
+ uint32_t set_bit = 1U << APUSYS_APC_SYS0_LOCK_BIT_APU_SCTRL_REVISER;
+
+ /* Lock apu_sctrl_reviser */
+ set_bit = set_bit | (1U << APUSYS_APC_SYS0_LOCK_BIT_APUSYS_AO_5);
+ apuapc_writel(set_bit, APUSYS_SYS0_APC_LOCK_0);
+}
+
+void set_apusys_apc(void)
+{
+ int32_t ret = 0;
+
+ /* Check violation status */
+ INFO("[APUAPC] vio %d\n", apuapc_readl(APUSYS_APC_CON) & 0x80000000);
+
+ /* Initial Permission */
+ ret = set_apusys_ao_apc();
+ INFO("[APUAPC] %s - %s!\n", "set_apusys_ao_apc",
+ ret ? "FAILED" : "SUCCESS");
+
+ /* Lock */
+ set_apusys_apc_lock();
+
+ /* Initial NoC Permission */
+ ret = set_apusys_noc_dapc();
+ INFO("[APUAPC] %s - %s!\n", "set_apusys_noc_dapc",
+ ret ? "FAILED" : "SUCCESS");
+
+ /* Dump Permission */
+ dump_apusys_ao_apc();
+ dump_apusys_noc_dapc();
+
+ INFO("[APUAPC] %s done\n", __func__);
+}
diff --git a/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h
new file mode 100644
index 0000000..ff7a9fa
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MTK_APUSYS_APC_H__
+#define __MTK_APUSYS_APC_H__
+
+void set_apusys_apc(void);
+
+#endif /* __MTK_APUSYS_APC_H__ */
diff --git a/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h
new file mode 100644
index 0000000..b392d6a
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MTK_APUSYS_APC_DEF_H__
+#define __MTK_APUSYS_APC_DEF_H__
+
+#include <lib/mmio.h>
+
+enum APUSYS_APC_ERR_STATUS {
+ APUSYS_APC_OK = 0x0,
+
+ APUSYS_APC_ERR_GENERIC = 0x1000,
+ APUSYS_APC_ERR_INVALID_CMD = 0x1001,
+ APUSYS_APC_ERR_SLAVE_TYPE_NOT_SUPPORTED = 0x1002,
+ APUSYS_APC_ERR_SLAVE_IDX_NOT_SUPPORTED = 0x1003,
+ APUSYS_APC_ERR_DOMAIN_NOT_SUPPORTED = 0x1004,
+ APUSYS_APC_ERR_PERMISSION_NOT_SUPPORTED = 0x1005,
+ APUSYS_APC_ERR_OUT_OF_BOUNDARY = 0x1006,
+ APUSYS_APC_ERR_REQ_TYPE_NOT_SUPPORTED = 0x1007,
+};
+
+enum APUSYS_APC_PERM_TYPE {
+ NO_PROTECTION = 0U,
+ SEC_RW_ONLY = 1U,
+ SEC_RW_NS_R = 2U,
+ FORBIDDEN = 3U,
+ PERM_NUM = 4U,
+};
+
+enum APUSYS_APC_DOMAIN_ID {
+ DOMAIN_0 = 0U,
+ DOMAIN_1 = 1U,
+ DOMAIN_2 = 2U,
+ DOMAIN_3 = 3U,
+ DOMAIN_4 = 4U,
+ DOMAIN_5 = 5U,
+ DOMAIN_6 = 6U,
+ DOMAIN_7 = 7U,
+ DOMAIN_8 = 8U,
+ DOMAIN_9 = 9U,
+ DOMAIN_10 = 10U,
+ DOMAIN_11 = 11U,
+ DOMAIN_12 = 12U,
+ DOMAIN_13 = 13U,
+ DOMAIN_14 = 14U,
+ DOMAIN_15 = 15U,
+};
+
+struct APC_DOM_16 {
+ unsigned char d0_permission;
+ unsigned char d1_permission;
+ unsigned char d2_permission;
+ unsigned char d3_permission;
+ unsigned char d4_permission;
+ unsigned char d5_permission;
+ unsigned char d6_permission;
+ unsigned char d7_permission;
+ unsigned char d8_permission;
+ unsigned char d9_permission;
+ unsigned char d10_permission;
+ unsigned char d11_permission;
+ unsigned char d12_permission;
+ unsigned char d13_permission;
+ unsigned char d14_permission;
+ unsigned char d15_permission;
+};
+
+#define APUSYS_APC_AO_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \
+ PERM_ATTR2, PERM_ATTR3, PERM_ATTR4, PERM_ATTR5, \
+ PERM_ATTR6, PERM_ATTR7, PERM_ATTR8, PERM_ATTR9, \
+ PERM_ATTR10, PERM_ATTR11, PERM_ATTR12, PERM_ATTR13, \
+ PERM_ATTR14, PERM_ATTR15) \
+ {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \
+ (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3, \
+ (unsigned char)PERM_ATTR4, (unsigned char)PERM_ATTR5, \
+ (unsigned char)PERM_ATTR6, (unsigned char)PERM_ATTR7, \
+ (unsigned char)PERM_ATTR8, (unsigned char)PERM_ATTR9, \
+ (unsigned char)PERM_ATTR10, (unsigned char)PERM_ATTR11, \
+ (unsigned char)PERM_ATTR12, (unsigned char)PERM_ATTR13, \
+ (unsigned char)PERM_ATTR14, (unsigned char)PERM_ATTR15}
+
+#define apuapc_writel(VAL, REG) mmio_write_32((uintptr_t)REG, VAL)
+#define apuapc_readl(REG) mmio_read_32((uintptr_t)REG)
+
+/* APUSYS APC AO Registers */
+#define APUSYS_APC_AO_BASE APUSYS_APC_AO_WRAPPER_BASE
+#define APUSYS_APC_CON (APUSYS_APC_AO_BASE + 0x00F00)
+#define APUSYS_SYS0_APC_LOCK_0 (APUSYS_APC_AO_BASE + 0x00700)
+
+/* APUSYS NOC_DPAC_AO Registers */
+#define APUSYS_NOC_DAPC_CON (APUSYS_NOC_DAPC_AO_BASE + 0x00F00)
+
+#define APUSYS_NOC_DAPC_GAP_BOUNDARY 4U
+#define APUSYS_NOC_DAPC_JUMP_GAP 12U
+
+#define APUSYS_APC_SYS0_AO_SLAVE_NUM_IN_1_DOM 16U
+#define APUSYS_APC_SYS0_AO_DOM_NUM 16U
+#define APUSYS_APC_SYS0_AO_SLAVE_NUM 59U
+
+#define APUSYS_APC_SYS0_LOCK_BIT_APU_SCTRL_REVISER 11U
+#define APUSYS_APC_SYS0_LOCK_BIT_APUSYS_AO_5 5U
+
+#define APUSYS_NOC_DAPC_AO_SLAVE_NUM_IN_1_DOM 16U
+#define APUSYS_NOC_DAPC_AO_DOM_NUM 16U
+#define APUSYS_NOC_DAPC_AO_SLAVE_NUM 27U
+
+#endif /* __MTK_APUSYS_APC_DEF_H__ */
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c
new file mode 100644
index 0000000..dd8bf4e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mtk_dcm.h>
+#include <mtk_dcm_utils.h>
+
+static void dcm_armcore(bool mode)
+{
+ dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
+}
+
+static void dcm_mcusys(bool on)
+{
+ dcm_mp_cpusys_top_adb_dcm(on);
+ dcm_mp_cpusys_top_apb_dcm(on);
+ dcm_mp_cpusys_top_cpubiu_dcm(on);
+ dcm_mp_cpusys_top_misc_dcm(on);
+ dcm_mp_cpusys_top_mp0_qdcm(on);
+ dcm_cpccfg_reg_emi_wfifo(on);
+ dcm_mp_cpusys_top_last_cor_idle_dcm(on);
+}
+
+static void dcm_stall(bool on)
+{
+ dcm_mp_cpusys_top_core_stall_dcm(on);
+ dcm_mp_cpusys_top_fcm_stall_dcm(on);
+}
+
+static bool check_dcm_state(void)
+{
+ bool ret = true;
+
+ ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
+ ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
+ ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
+
+ return ret;
+}
+
+bool dcm_set_default(void)
+{
+ dcm_armcore(true);
+ dcm_mcusys(true);
+ dcm_stall(true);
+
+ return check_dcm_state();
+}
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h
new file mode 100644
index 0000000..ee98d0e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+bool dcm_set_default(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c
new file mode 100644
index 0000000..15a700c
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mtk_dcm_utils.h>
+
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | \
+ (0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18) | \
+ (0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | \
+ (0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_ADB_DCM_CFG0) &
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MP_ADB_DCM_CFG4) &
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_adb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16))
+
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ ret &= ((mmio_read_32(MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_apb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_core_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MCSI_DCM0) &
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MCSI_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MCSI_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG0) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG1) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG2) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG2,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_2_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG2,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_2_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG3) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG3,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_3_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG3,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_3_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON (BIT(11))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF ((0x0 << 11))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPU_PLLDIV_CFG4) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG4,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_4_dcm'" */
+ mmio_clrsetbits_32(CPU_PLLDIV_CFG4,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_4_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4))
+
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0U << 31))
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | \
+ (0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_misc_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3))
+
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ ret &= ((mmio_read_32(MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_mp0_qdcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+ mmio_clrsetbits_32(MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF);
+ }
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(EMI_WFIFO) &
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK) ==
+ (unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON);
+
+ return ret;
+}
+
+void dcm_cpccfg_reg_emi_wfifo(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+ }
+}
+
diff --git a/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h
new file mode 100644
index 0000000..1cf7834
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_UTILS_H
+#define MTK_DCM_UTILS_H
+
+#include <stdbool.h>
+
+#include <mtk_dcm.h>
+#include <platform_def.h>
+
+/* Base */
+#define MP_CPUSYS_TOP_BASE (MCUCFG_BASE + 0x8000)
+#define CPCCFG_REG_BASE (MCUCFG_BASE + 0xA800)
+
+/* Register Definition */
+#define CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
+#define CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
+#define CPU_PLLDIV_CFG2 (MP_CPUSYS_TOP_BASE + 0x22a8)
+#define CPU_PLLDIV_CFG3 (MP_CPUSYS_TOP_BASE + 0x22ac)
+#define CPU_PLLDIV_CFG4 (MP_CPUSYS_TOP_BASE + 0x22b0)
+#define BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MCSI_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500)
+#define MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
+#define MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
+#define EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
+#define MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
+
+/* MP_CPUSYS_TOP */
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
+void dcm_mp_cpusys_top_adb_dcm(bool on);
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
+void dcm_mp_cpusys_top_apb_dcm(bool on);
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_core_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_2_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_2_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_3_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_3_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_4_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_4_dcm(bool on);
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
+void dcm_mp_cpusys_top_misc_dcm(bool on);
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
+void dcm_mp_cpusys_top_mp0_qdcm(bool on);
+/* CPCCFG_REG */
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+
+#endif
diff --git a/plat/mediatek/mt8192/drivers/devapc/devapc.c b/plat/mediatek/mt8192/drivers/devapc/devapc.c
new file mode 100644
index 0000000..b11f272
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/devapc/devapc.c
@@ -0,0 +1,2847 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+
+#include <devapc.h>
+#include <mtk_apusys_apc.h>
+
+/* Infra_ao */
+static const struct APC_INFRA_PERI_DOM_16 INFRA_AO_SYS0_Devices[] = {
+
+/* 0 */
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-4",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-5",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-6",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-7",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MFG_S_S-8",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("APU_S_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-4",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("APU_S_S-5",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-1",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-2",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-3",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("MCUSYS_CFGREG_APB_S-4",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+DAPC_INFRA_AO_SYS0_ATTR("L3C_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("L3C_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS0_ATTR("PCIE_AXI_S",
+ NO_PROTECTION, NO_PROTECTION, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+static const struct APC_INFRA_PERI_DOM_4 INFRA_AO_SYS1_Devices[] = {
+
+/* 0 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-4",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-5",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-6",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-7",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-8",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-9",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-10",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-11",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-12",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-13",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-14",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-15",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-16",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-17",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-18",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-19",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-20",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-21",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-22",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-23",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-24",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-25",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-26",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-27",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-28",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-29",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 30 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-30",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-31",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-32",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-33",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-34",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-35",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-36",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-37",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-38",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-39",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 40 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-100",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-101",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-102",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-103",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-104",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-105",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-106",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-107",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-108",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-109",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 50 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-110",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-111",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-112",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-113",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-114",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-115",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-116",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-117",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-118",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-119",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 60 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-120",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-121",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-122",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-123",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-124",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-125",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-126",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-127",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-128",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-129",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 70 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-130",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-131",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-132",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-133",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-134",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-135",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-136",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-137",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-138",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-139",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 80 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-140",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-141",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-142",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-143",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-200",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-201",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-202",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-203",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-204",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-205",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 90 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-206",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-207",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-300",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-301",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-302",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-303",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-304",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-305",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-306",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-307",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 100 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-400",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-401",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-402",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-403",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-404",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-405",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-406",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-407",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-408",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-409",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 110 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-410",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-411",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-412",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-413",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-414",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-415",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-416",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-417",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-418",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-419",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 120 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-420",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-421",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-422",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-423",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-424",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-425",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-426",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-427",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-428",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-429",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 130 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-430",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-431",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-432",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-433",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-434",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-435",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-436",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-437",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-438",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-439",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 140 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-440",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-441",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-442",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-443",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-444",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-445",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-446",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-447",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-448",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-449",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 150 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-450",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-451",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-452",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-453",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-454",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-455",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-456",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-457",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-458",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-459",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 160 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-460",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-461",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-462",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-463",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-464",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-465",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-466",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-467",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-468",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-469",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 170 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-470",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-471",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-472",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-473",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-474",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-475",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-476",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-477",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-478",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-479",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 180 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-480",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-481",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-482",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-483",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-484",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-485",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-486",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-487",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-488",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-489",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 190 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-490",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-491",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-492",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-493",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-494",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-495",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-496",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-497",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-498",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-499",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 200 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-500",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-501",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-502",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-503",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-504",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-505",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-506",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-507",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-508",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-509",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 210 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-510",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-511",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-512",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-513",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-514",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-515",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-516",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-517",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-518",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-519",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 220 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-520",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-521",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-522",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-523",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-524",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-525",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-526",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-527",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-528",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-529",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 230 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-530",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-531",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-532",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-533",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-534",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-535",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-536",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-537",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-538",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-539",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 240 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-540",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-541",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-542",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-543",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-544",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-545",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-546",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-547",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-548",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-549",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 250 */
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-550",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-551",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-552",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-553",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-554",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS1_ATTR("MM_S_S-555",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+static const struct APC_INFRA_PERI_DOM_4 INFRA_AO_SYS2_Devices[] = {
+
+/* 0 */
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-556",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-557",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-558",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-559",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-560",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-561",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-562",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-563",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-564",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-565",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-566",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-567",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-568",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-569",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-570",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-571",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-572",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-573",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-574",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-575",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-576",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-577",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-578",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-579",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-580",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-581",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-582",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-583",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-584",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-585",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 30 */
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-586",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-587",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-588",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-589",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-590",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-591",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-592",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-593",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-594",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-595",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 40 */
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-600",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-601",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-602",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-603",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-604",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-605",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-606",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-607",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-608",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-609",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 50 */
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-610",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-611",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-700",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-701",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-702",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-703",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-704",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-705",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-706",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-707",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 60 */
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-708",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-709",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-710",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-711",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-712",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-713",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-714",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-715",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-716",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_INFRA_AO_SYS2_ATTR("MM_S_S-717",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+/* Peri_ao */
+static const struct APC_INFRA_PERI_DOM_16 PERI_AO_SYS0_Devices[] = {
+
+/* 0 */
+DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SPM_APB_S-4",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("APMIXEDSYS_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, NO_PROTECTION,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("APMIXEDSYS_APB_S-1",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("TOPCKGEN_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, NO_PROTECTION,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("INFRACFG_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("INFRACFG_AO_MEM_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+DAPC_PERI_AO_SYS0_ATTR("PERICFG_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("GPIO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("TOPRGU_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("RESERVED_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_INFRA_AO_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("BCRM_INFRA_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEBUG_CTRL_INFRA_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_PERI_AO_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("BCRM_PERI_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEBUG_CTRL_PERI_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+DAPC_PERI_AO_SYS0_ATTR("AP_CIRQ_EINT_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PMIC_WRAP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_AO_MM_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("KP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("TOP_MISC_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DVFSRC_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("MBIST_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DPMAIF_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEVICE_MPU_AO_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SYS_TIMER_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 30 */
+DAPC_PERI_AO_SYS0_ATTR("MODEM_TEMP_SHARE_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEVICE_APC_AO_MD_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PMIF1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PMICSPI_MST_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("TIA_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("TOPCKGEN_INFRA_CFG_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRM_DEBUG_TOP_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 40 */
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-3",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-4",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-5",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-6",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-7",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-8",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-9",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PWR_MD32_S-10",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("AUDIO_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("AUDIO_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 50 */
+DAPC_PERI_AO_SYS0_ATTR("SSUSB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SSUSB_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SSUSB_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("UFS_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("UFS_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("UFS_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("UFS_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEBUGSYS_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S0_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S0_APB_S-1",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 60 */
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_MD32_S1_APB_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("NOR_AXI_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("PCIE_AHB_S",
+ NO_PROTECTION, NO_PROTECTION, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP0_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP3_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP4_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP5_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 70 */
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH0_TOP6_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP0_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP3_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP4_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP5_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH1_TOP6_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP0_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 80 */
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP3_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP4_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP5_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH2_TOP6_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP0_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP3_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP4_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 90 */
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP5_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DRAMC_CH3_TOP6_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("CCIF2_AP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("CCIF2_MD_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("CCIF3_AP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("CCIF3_MD_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("CCIF4_AP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("CCIF4_MD_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("INFRA_BUS_TRACE_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("CCIF5_AP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 100 */
+DAPC_PERI_AO_SYS0_ATTR("CCIF5_MD_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SSC_INFRA_APB0_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SSC_INFRA_APB1_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("SSC_INFRA_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS0_ATTR("DEVICE_MPU_ACP_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+static const struct APC_INFRA_PERI_DOM_8 PERI_AO_SYS1_Devices[] = {
+
+/* 0 */
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-4",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-5",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-6",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-7",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-8",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-9",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-10",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-11",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-12",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-13",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-14",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-15",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-16",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-17",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-18",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-19",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-20",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-21",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("TINSYS_S-22",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-4",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-5",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-6",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 30 */
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-7",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-8",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-9",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-10",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-11",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-12",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-13",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-14",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-15",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-16",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 40 */
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-17",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-18",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-19",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-20",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-21",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-22",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-23",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-24",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-25",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-26",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 50 */
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-27",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-28",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-29",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-30",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-31",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-32",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-33",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-34",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-35",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-36",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 60 */
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-37",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-38",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-39",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-40",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-41",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO_SYS1_ATTR("MD_AP_S-42",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+static const struct APC_INFRA_PERI_DOM_4 PERI_AO_SYS2_Devices[] = {
+
+/* 0 */
+DAPC_PERI_AO_SYS2_ATTR("CONN_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+/* Peri_ao2 */
+static const struct APC_INFRA_PERI_DOM_16 PERI_AO2_SYS0_Devices[] = {
+
+/* 0 */
+DAPC_PERI_AO2_SYS0_ATTR("EFUSE_DEBUG_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("APXGPT_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("SEJ_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("AES_TOP0_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("SECURITY_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_PERI_AO2_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BCRM_PERI_AO2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEBUG_CTRL_PERI_AO2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("SPMI_MST_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEBUG_CTRL_FMEM_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+DAPC_PERI_AO2_SYS0_ATTR("BCRM_FMEM_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_FMEM_AO_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("PWM_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("GCE_APB_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S-1",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S-2",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+DAPC_PERI_AO2_SYS0_ATTR("DPMAIF_PDN_APB_S-3",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB0_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB1_S",
+ NO_PROTECTION, FORBIDDEN, SEC_RW_NS_R, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB3_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB4_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB5_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB6_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB7_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB8_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 30 */
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB9_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB10_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB11_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB12_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB13_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB14_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_APB15_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB0_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB1_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 40 */
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB3_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB4_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB5_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB6_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_WEST_APB7_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB0_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB1_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB3_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB4_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 50 */
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB5_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB6_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB7_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB8_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB9_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB10_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB11_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB12_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB13_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB14_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 60 */
+DAPC_PERI_AO2_SYS0_ATTR("BND_NORTH_APB15_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB0_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB1_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB3_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB4_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB5_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB6_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB7_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB8_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 70 */
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB9_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB10_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB11_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB12_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB13_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB14_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_SOUTH_APB15_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB0_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB1_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 80 */
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB3_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB4_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB5_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB6_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BND_EAST_NORTH_APB7_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("SYS_CIRQ_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("EFUSE_DEBUG_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_INFRA_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEBUG_TRACKER_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("CCIF0_AP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 90 */
+DAPC_PERI_AO2_SYS0_ATTR("CCIF0_MD_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("CCIF1_AP_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("CCIF1_MD_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("MBIST_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("INFRACFG_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("TRNG_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DX_CC_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("CQ_DMA_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("SRAMROM_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("INFRACFG_MEM_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 100 */
+DAPC_PERI_AO2_SYS0_ATTR("RESERVED_DVFS_PROC_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("SYS_CIRQ1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("SYS_CIRQ2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEBUG_TRACKER_APB1_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("EMI_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("EMI_MPU_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEVICE_MPU_PDN_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("APDMA_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEBUG_TRACKER_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BCRM_INFRA_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 110 */
+DAPC_PERI_AO2_SYS0_ATTR("BCRM_PERI_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BCRM_PERI_PDN2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_PERI_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("DEVICE_APC_PERI_PDN2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_AO2_SYS0_ATTR("BCRM_FMEM_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+/* Peri_par_ao */
+static const struct APC_INFRA_PERI_DOM_16 PERI_PAR_AO_SYS0_Devices[] = {
+
+/* 0 */
+DAPC_PERI_PAR_AO_SYS0_ATTR("AUXADC_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("UART0_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("UART1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("UART2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB4_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI0_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("PTP_THERM_CTRL_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("BTIF_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("DISP_PWM_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI1_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 10 */
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI2_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI3_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB0_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB1_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI4_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI5_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB2_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("IIC_P2P_REMAP_APB3_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI6_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("SPI7_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+/* 20 */
+DAPC_PERI_PAR_AO_SYS0_ATTR("BCRM_PERI_PAR_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("DEVICE_APC_PERI_PAR_PDN_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("PTP_THERM_CTRL2_APB_S",
+ NO_PROTECTION, FORBIDDEN, NO_PROTECTION, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("NOR_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("DEVICE_APC_PERI_PAR_AO_APB_S",
+ SEC_RW_ONLY, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("DEBUG_CTRL_PERI_PAR_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+DAPC_PERI_PAR_AO_SYS0_ATTR("BCRM_PERI_PAR_AO_APB_S",
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN),
+
+};
+
+static void set_module_apc(enum DEVAPC_SLAVE_TYPE slave_type,
+ uint32_t module, enum DOMAIN_ID domain_id,
+ enum DEVAPC_PERM_TYPE perm)
+{
+ uint32_t apc_register_index;
+ uint32_t apc_set_index;
+ uintptr_t base = 0, reg;
+ uint32_t clr_bit;
+ uint32_t set_bit;
+
+ apc_register_index = module / MOD_NO_IN_1_DEVAPC;
+ apc_set_index = module % MOD_NO_IN_1_DEVAPC;
+
+ clr_bit = (0x3U << (apc_set_index * 2));
+ set_bit = (uint32_t)perm << (apc_set_index * 2);
+
+ /* infra_ao */
+ if ((slave_type == SLAVE_TYPE_INFRA_AO_SYS0) &&
+ (module < SLAVE_NUM_INFRA_AO_SYS0) &&
+ (domain_id < (uint32_t)DOM_NUM_INFRA_AO_SYS0)) {
+ base = DEVAPC_INFRA_AO_SYS0_D0_APC_0;
+
+ } else if ((slave_type == SLAVE_TYPE_INFRA_AO_SYS1) &&
+ (module < SLAVE_NUM_INFRA_AO_SYS1) &&
+ (domain_id < (uint32_t)DOM_NUM_INFRA_AO_SYS1)) {
+ base = DEVAPC_INFRA_AO_SYS1_D0_APC_0;
+
+ } else if ((slave_type == SLAVE_TYPE_INFRA_AO_SYS2) &&
+ (module < SLAVE_NUM_INFRA_AO_SYS2) &&
+ (domain_id < (uint32_t)DOM_NUM_INFRA_AO_SYS2)) {
+ base = DEVAPC_INFRA_AO_SYS2_D0_APC_0;
+ /* peri_ao */
+ } else if ((slave_type == SLAVE_TYPE_PERI_AO_SYS0) &&
+ (module < SLAVE_NUM_PERI_AO_SYS0) &&
+ (domain_id < (uint32_t)DOM_NUM_PERI_AO_SYS0)) {
+ base = DEVAPC_PERI_AO_SYS0_D0_APC_0;
+
+ } else if ((slave_type == SLAVE_TYPE_PERI_AO_SYS1) &&
+ (module < SLAVE_NUM_PERI_AO_SYS1) &&
+ (domain_id <= (uint32_t)DOM_NUM_PERI_AO_SYS1)) {
+ base = DEVAPC_PERI_AO_SYS1_D0_APC_0;
+
+ } else if ((slave_type == SLAVE_TYPE_PERI_AO_SYS2) &&
+ (module < SLAVE_NUM_PERI_AO_SYS2) &&
+ (domain_id < (uint32_t)DOM_NUM_PERI_AO_SYS2)) {
+ base = DEVAPC_PERI_AO_SYS2_D0_APC_0;
+ /* peri_ao2 */
+ } else if ((slave_type == SLAVE_TYPE_PERI_AO2_SYS0) &&
+ (module < SLAVE_NUM_PERI_AO2_SYS0) &&
+ (domain_id < (uint32_t)DOM_NUM_PERI_AO2_SYS0)) {
+ base = DEVAPC_PERI_AO2_SYS0_D0_APC_0;
+
+ /* peri_par_ao */
+ } else if ((slave_type == SLAVE_TYPE_PERI_PAR_AO_SYS0) &&
+ (module < SLAVE_NUM_PERI_PAR_AO_SYS0) &&
+ (domain_id < (uint32_t)DOM_NUM_PERI_PAR_AO_SYS0)) {
+ base = DEVAPC_PERI_PAR_AO_SYS0_D0_APC_0;
+
+ } else {
+ ERROR("[DEVAPC] %s: %s, %s:0x%x, %s:0x%x, %s:0x%x\n",
+ __func__, "out of boundary",
+ "slave_type", slave_type,
+ "module", module,
+ "domain_id", domain_id);
+ }
+
+ if (base != 0U) {
+ reg = base + domain_id * 0x40 + apc_register_index * 4;
+ mmio_clrsetbits_32(reg, clr_bit, set_bit);
+ }
+}
+
+static void dump_infra_ao_apc(void)
+{
+ int reg_num;
+ int d, i;
+
+ reg_num = (SLAVE_NUM_INFRA_AO_SYS0 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_INFRA_AO_SYS0; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (INFRA_AO_SYS0)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_INFRA_AO_SYS0_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+
+ reg_num = (SLAVE_NUM_INFRA_AO_SYS1 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_INFRA_AO_SYS1; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (INFRA_AO_SYS1)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_INFRA_AO_SYS1_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+
+ reg_num = (SLAVE_NUM_INFRA_AO_SYS2 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_INFRA_AO_SYS2; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (INFRA_AO_SYS2)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_INFRA_AO_SYS2_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+
+ INFO("[DEVAPC] (INFRA_AO)MAS_SEC_0: 0x%x\n",
+ devapc_readl(DEVAPC_INFRA_AO_MAS_SEC_0));
+}
+
+static void dump_peri_ao_apc(void)
+{
+ int reg_num;
+ int d, i;
+
+ reg_num = (SLAVE_NUM_PERI_AO_SYS0 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_PERI_AO_SYS0; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (PERI_AO_SYS0)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_PERI_AO_SYS0_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+
+ reg_num = (SLAVE_NUM_PERI_AO_SYS1 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_PERI_AO_SYS1; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (PERI_AO_SYS1)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_PERI_AO_SYS1_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+
+ reg_num = (SLAVE_NUM_PERI_AO_SYS2 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_PERI_AO_SYS2; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (PERI_AO_SYS2)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_PERI_AO_SYS2_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+
+ INFO("[DEVAPC] (PERI_AO)MAS_SEC_0: 0x%x\n",
+ devapc_readl(DEVAPC_PERI_AO_MAS_SEC_0));
+}
+
+static void dump_peri_ao2_apc(void)
+{
+ int reg_num;
+ int d, i;
+
+ reg_num = (SLAVE_NUM_PERI_AO2_SYS0 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_PERI_AO2_SYS0; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (PERI_AO2_SYS0)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_PERI_AO2_SYS0_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+}
+
+static void dump_peri_par_ao_apc(void)
+{
+ int reg_num;
+ int d, i;
+
+ reg_num = (SLAVE_NUM_PERI_PAR_AO_SYS0 - 1) / MOD_NO_IN_1_DEVAPC;
+ for (d = 0; d < DOM_NUM_PERI_PAR_AO_SYS0; d++) {
+ for (i = 0; i <= reg_num; i++) {
+ INFO("[DEVAPC] (PERI_PAR_AO_SYS0)D%d_APC_%d: 0x%x\n",
+ d, i, devapc_readl(
+ DEVAPC_PERI_PAR_AO_SYS0_D0_APC_0 +
+ d * 0x40 + i * 4)
+ );
+ }
+ }
+
+ INFO("[DEVAPC] (PERI_PAR_AO)MAS_SEC_0: 0x%x\n",
+ devapc_readl(DEVAPC_PERI_PAR_AO_MAS_SEC_0));
+}
+
+static void set_infra_ao_apc(void)
+{
+ uint32_t infra_ao_size;
+ uint32_t i;
+
+ infra_ao_size = ARRAY_SIZE(INFRA_AO_SYS0_Devices);
+
+ for (i = 0; i < infra_ao_size; i++) {
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_0,
+ INFRA_AO_SYS0_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_1,
+ INFRA_AO_SYS0_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_2,
+ INFRA_AO_SYS0_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_3,
+ INFRA_AO_SYS0_Devices[i].d3_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_4,
+ INFRA_AO_SYS0_Devices[i].d4_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_5,
+ INFRA_AO_SYS0_Devices[i].d5_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_6,
+ INFRA_AO_SYS0_Devices[i].d6_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_7,
+ INFRA_AO_SYS0_Devices[i].d7_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_8,
+ INFRA_AO_SYS0_Devices[i].d8_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_9,
+ INFRA_AO_SYS0_Devices[i].d9_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_10,
+ INFRA_AO_SYS0_Devices[i].d10_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_11,
+ INFRA_AO_SYS0_Devices[i].d11_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_12,
+ INFRA_AO_SYS0_Devices[i].d12_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_13,
+ INFRA_AO_SYS0_Devices[i].d13_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_14,
+ INFRA_AO_SYS0_Devices[i].d14_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS0, i, DOMAIN_15,
+ INFRA_AO_SYS0_Devices[i].d15_permission);
+ }
+
+ infra_ao_size = ARRAY_SIZE(INFRA_AO_SYS1_Devices);
+
+ for (i = 0; i < infra_ao_size; i++) {
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_0,
+ INFRA_AO_SYS1_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_1,
+ INFRA_AO_SYS1_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_2,
+ INFRA_AO_SYS1_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS1, i, DOMAIN_3,
+ INFRA_AO_SYS1_Devices[i].d3_permission);
+ }
+
+ infra_ao_size = ARRAY_SIZE(INFRA_AO_SYS2_Devices);
+
+ for (i = 0; i < infra_ao_size; i++) {
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_0,
+ INFRA_AO_SYS2_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_1,
+ INFRA_AO_SYS2_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_2,
+ INFRA_AO_SYS2_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_INFRA_AO_SYS2, i, DOMAIN_3,
+ INFRA_AO_SYS2_Devices[i].d3_permission);
+ }
+}
+
+static void set_peri_ao_apc(void)
+{
+ uint32_t peri_ao_size;
+ uint32_t i;
+
+ peri_ao_size = ARRAY_SIZE(PERI_AO_SYS0_Devices);
+
+ for (i = 0; i < peri_ao_size; i++) {
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_0,
+ PERI_AO_SYS0_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_1,
+ PERI_AO_SYS0_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_2,
+ PERI_AO_SYS0_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_3,
+ PERI_AO_SYS0_Devices[i].d3_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_4,
+ PERI_AO_SYS0_Devices[i].d4_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_5,
+ PERI_AO_SYS0_Devices[i].d5_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_6,
+ PERI_AO_SYS0_Devices[i].d6_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_7,
+ PERI_AO_SYS0_Devices[i].d7_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_8,
+ PERI_AO_SYS0_Devices[i].d8_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_9,
+ PERI_AO_SYS0_Devices[i].d9_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_10,
+ PERI_AO_SYS0_Devices[i].d10_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_11,
+ PERI_AO_SYS0_Devices[i].d11_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_12,
+ PERI_AO_SYS0_Devices[i].d12_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_13,
+ PERI_AO_SYS0_Devices[i].d13_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_14,
+ PERI_AO_SYS0_Devices[i].d14_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, i, DOMAIN_15,
+ PERI_AO_SYS0_Devices[i].d15_permission);
+ }
+
+ peri_ao_size = ARRAY_SIZE(PERI_AO_SYS1_Devices);
+
+ for (i = 0; i < peri_ao_size; i++) {
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_0,
+ PERI_AO_SYS1_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_1,
+ PERI_AO_SYS1_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_2,
+ PERI_AO_SYS1_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_3,
+ PERI_AO_SYS1_Devices[i].d3_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_4,
+ PERI_AO_SYS1_Devices[i].d4_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_5,
+ PERI_AO_SYS1_Devices[i].d5_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_6,
+ PERI_AO_SYS1_Devices[i].d6_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS1, i, DOMAIN_7,
+ PERI_AO_SYS1_Devices[i].d7_permission);
+ }
+
+ peri_ao_size = ARRAY_SIZE(PERI_AO_SYS2_Devices);
+
+ for (i = 0; i < peri_ao_size; i++) {
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_0,
+ PERI_AO_SYS2_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_1,
+ PERI_AO_SYS2_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_2,
+ PERI_AO_SYS2_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS2, i, DOMAIN_3,
+ PERI_AO_SYS2_Devices[i].d3_permission);
+ }
+}
+
+static void set_peri_ao2_apc(void)
+{
+ uint32_t peri_ao2_size;
+ uint32_t i;
+
+ peri_ao2_size = ARRAY_SIZE(PERI_AO2_SYS0_Devices);
+
+ for (i = 0; i < peri_ao2_size; i++) {
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_0,
+ PERI_AO2_SYS0_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_1,
+ PERI_AO2_SYS0_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_2,
+ PERI_AO2_SYS0_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_3,
+ PERI_AO2_SYS0_Devices[i].d3_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_4,
+ PERI_AO2_SYS0_Devices[i].d4_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_5,
+ PERI_AO2_SYS0_Devices[i].d5_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_6,
+ PERI_AO2_SYS0_Devices[i].d6_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_7,
+ PERI_AO2_SYS0_Devices[i].d7_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_8,
+ PERI_AO2_SYS0_Devices[i].d8_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_9,
+ PERI_AO2_SYS0_Devices[i].d9_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_10,
+ PERI_AO2_SYS0_Devices[i].d10_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_11,
+ PERI_AO2_SYS0_Devices[i].d11_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_12,
+ PERI_AO2_SYS0_Devices[i].d12_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_13,
+ PERI_AO2_SYS0_Devices[i].d13_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_14,
+ PERI_AO2_SYS0_Devices[i].d14_permission);
+ set_module_apc(SLAVE_TYPE_PERI_AO2_SYS0, i, DOMAIN_15,
+ PERI_AO2_SYS0_Devices[i].d15_permission);
+ }
+}
+
+static void set_peri_par_ao_apc(void)
+{
+ uint32_t peri_par_ao_size;
+ uint32_t i;
+
+ peri_par_ao_size = ARRAY_SIZE(PERI_PAR_AO_SYS0_Devices);
+
+ for (i = 0; i < peri_par_ao_size; i++) {
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_0,
+ PERI_PAR_AO_SYS0_Devices[i].d0_permission); /* APMCU */
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_1,
+ PERI_PAR_AO_SYS0_Devices[i].d1_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_2,
+ PERI_PAR_AO_SYS0_Devices[i].d2_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_3,
+ PERI_PAR_AO_SYS0_Devices[i].d3_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_4,
+ PERI_PAR_AO_SYS0_Devices[i].d4_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_5,
+ PERI_PAR_AO_SYS0_Devices[i].d5_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_6,
+ PERI_PAR_AO_SYS0_Devices[i].d6_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_7,
+ PERI_PAR_AO_SYS0_Devices[i].d7_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_8,
+ PERI_PAR_AO_SYS0_Devices[i].d8_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_9,
+ PERI_PAR_AO_SYS0_Devices[i].d9_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_10,
+ PERI_PAR_AO_SYS0_Devices[i].d10_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_11,
+ PERI_PAR_AO_SYS0_Devices[i].d11_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_12,
+ PERI_PAR_AO_SYS0_Devices[i].d12_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_13,
+ PERI_PAR_AO_SYS0_Devices[i].d13_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_14,
+ PERI_PAR_AO_SYS0_Devices[i].d14_permission);
+ set_module_apc(SLAVE_TYPE_PERI_PAR_AO_SYS0, i, DOMAIN_15,
+ PERI_PAR_AO_SYS0_Devices[i].d15_permission);
+ }
+}
+
+static void set_extra_apc(void)
+{
+#ifdef MTK_DEBUGSYS_LOCK
+ /* Block debugsys to avoid privilege escalation (user load only) */
+ set_module_apc(SLAVE_TYPE_PERI_AO_SYS0, DEVAPC_DEBUGSYS_INDEX,
+ DOMAIN_0, SEC_RW_NS_R);
+#endif
+}
+
+void devapc_init(void)
+{
+ /* Initial Permission */
+ set_infra_ao_apc();
+ set_peri_ao_apc();
+ set_peri_ao2_apc();
+ set_peri_par_ao_apc();
+
+ /* Extra Permission */
+ set_extra_apc();
+
+ /* Dump Permission */
+ dump_infra_ao_apc();
+ dump_peri_ao_apc();
+ dump_peri_ao2_apc();
+ dump_peri_par_ao_apc();
+
+ /* Setup APUSYS Permission */
+ set_apusys_apc();
+
+ INFO("[DEVAPC] %s done\n", __func__);
+}
diff --git a/plat/mediatek/mt8192/drivers/devapc/devapc.h b/plat/mediatek/mt8192/drivers/devapc/devapc.h
new file mode 100644
index 0000000..9033a0f
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/devapc/devapc.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DEVAPC_H
+#define DEVAPC_H
+
+#include <stdint.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * FUNCTION DEFINITION
+ ******************************************************************************/
+void devapc_init(void);
+
+/******************************************************************************
+ * STRUCTURE DEFINITION
+ ******************************************************************************/
+enum DEVAPC_PERM_TYPE {
+ NO_PROTECTION = 0,
+ SEC_RW_ONLY,
+ SEC_RW_NS_R,
+ FORBIDDEN,
+ PERM_NUM,
+};
+
+enum DOMAIN_ID {
+ DOMAIN_0 = 0,
+ DOMAIN_1,
+ DOMAIN_2,
+ DOMAIN_3,
+ DOMAIN_4,
+ DOMAIN_5,
+ DOMAIN_6,
+ DOMAIN_7,
+ DOMAIN_8,
+ DOMAIN_9,
+ DOMAIN_10,
+ DOMAIN_11,
+ DOMAIN_12,
+ DOMAIN_13,
+ DOMAIN_14,
+ DOMAIN_15,
+};
+
+/* Slave Type */
+enum DEVAPC_SLAVE_TYPE_SIMPLE {
+ SLAVE_TYPE_INFRA = 0,
+ SLAVE_TYPE_PERI,
+ SLAVE_TYPE_PERI2,
+ SLAVE_TYPE_PERI_PAR,
+};
+
+enum DEVAPC_SYS_INDEX {
+ DEVAPC_SYS0 = 0,
+ DEVAPC_SYS1,
+ DEVAPC_SYS2,
+};
+
+enum DEVAPC_SLAVE_TYPE {
+ SLAVE_TYPE_INFRA_AO_SYS0 = 0,
+ SLAVE_TYPE_INFRA_AO_SYS1,
+ SLAVE_TYPE_INFRA_AO_SYS2,
+ SLAVE_TYPE_PERI_AO_SYS0,
+ SLAVE_TYPE_PERI_AO_SYS1,
+ SLAVE_TYPE_PERI_AO_SYS2,
+ SLAVE_TYPE_PERI_AO2_SYS0,
+ SLAVE_TYPE_PERI_PAR_AO_SYS0,
+};
+
+/* Slave Num */
+enum DEVAPC_SLAVE_NUM {
+ SLAVE_NUM_INFRA_AO_SYS0 = 23,
+ SLAVE_NUM_INFRA_AO_SYS1 = 256,
+ SLAVE_NUM_INFRA_AO_SYS2 = 70,
+ SLAVE_NUM_PERI_AO_SYS0 = 105,
+ SLAVE_NUM_PERI_AO_SYS1 = 66,
+ SLAVE_NUM_PERI_AO_SYS2 = 1,
+ SLAVE_NUM_PERI_AO2_SYS0 = 115,
+ SLAVE_NUM_PERI_PAR_AO_SYS0 = 27,
+};
+
+enum DEVAPC_SYS_DOM_NUM {
+ DOM_NUM_INFRA_AO_SYS0 = 16,
+ DOM_NUM_INFRA_AO_SYS1 = 4,
+ DOM_NUM_INFRA_AO_SYS2 = 4,
+ DOM_NUM_PERI_AO_SYS0 = 16,
+ DOM_NUM_PERI_AO_SYS1 = 8,
+ DOM_NUM_PERI_AO_SYS2 = 4,
+ DOM_NUM_PERI_AO2_SYS0 = 16,
+ DOM_NUM_PERI_PAR_AO_SYS0 = 16,
+};
+
+enum DEVAPC_CFG_INDEX {
+ DEVAPC_DEBUGSYS_INDEX = 57,
+};
+
+struct APC_INFRA_PERI_DOM_16 {
+ unsigned char d0_permission;
+ unsigned char d1_permission;
+ unsigned char d2_permission;
+ unsigned char d3_permission;
+ unsigned char d4_permission;
+ unsigned char d5_permission;
+ unsigned char d6_permission;
+ unsigned char d7_permission;
+ unsigned char d8_permission;
+ unsigned char d9_permission;
+ unsigned char d10_permission;
+ unsigned char d11_permission;
+ unsigned char d12_permission;
+ unsigned char d13_permission;
+ unsigned char d14_permission;
+ unsigned char d15_permission;
+};
+
+struct APC_INFRA_PERI_DOM_8 {
+ unsigned char d0_permission;
+ unsigned char d1_permission;
+ unsigned char d2_permission;
+ unsigned char d3_permission;
+ unsigned char d4_permission;
+ unsigned char d5_permission;
+ unsigned char d6_permission;
+ unsigned char d7_permission;
+};
+
+struct APC_INFRA_PERI_DOM_4 {
+ unsigned char d0_permission;
+ unsigned char d1_permission;
+ unsigned char d2_permission;
+ unsigned char d3_permission;
+};
+
+#define DAPC_INFRA_AO_SYS0_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \
+ PERM_ATTR2, PERM_ATTR3, PERM_ATTR4, PERM_ATTR5, \
+ PERM_ATTR6, PERM_ATTR7, PERM_ATTR8, PERM_ATTR9, \
+ PERM_ATTR10, PERM_ATTR11, PERM_ATTR12, PERM_ATTR13, \
+ PERM_ATTR14, PERM_ATTR15) \
+ {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \
+ (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3, \
+ (unsigned char)PERM_ATTR4, (unsigned char)PERM_ATTR5, \
+ (unsigned char)PERM_ATTR6, (unsigned char)PERM_ATTR7, \
+ (unsigned char)PERM_ATTR8, (unsigned char)PERM_ATTR9, \
+ (unsigned char)PERM_ATTR10, (unsigned char)PERM_ATTR11, \
+ (unsigned char)PERM_ATTR12, (unsigned char)PERM_ATTR13, \
+ (unsigned char)PERM_ATTR14, (unsigned char)PERM_ATTR15}
+
+#define DAPC_INFRA_AO_SYS1_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \
+ PERM_ATTR2, PERM_ATTR3) \
+ {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \
+ (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3}
+
+#define DAPC_PERI_AO_SYS1_ATTR(DEV_NAME, PERM_ATTR0, PERM_ATTR1, \
+ PERM_ATTR2, PERM_ATTR3, PERM_ATTR4, PERM_ATTR5, \
+ PERM_ATTR6, PERM_ATTR7) \
+ {(unsigned char)PERM_ATTR0, (unsigned char)PERM_ATTR1, \
+ (unsigned char)PERM_ATTR2, (unsigned char)PERM_ATTR3, \
+ (unsigned char)PERM_ATTR4, (unsigned char)PERM_ATTR5, \
+ (unsigned char)PERM_ATTR6, (unsigned char)PERM_ATTR7}
+
+#define DAPC_INFRA_AO_SYS2_ATTR(...) DAPC_INFRA_AO_SYS1_ATTR(__VA_ARGS__)
+#define DAPC_PERI_AO_SYS0_ATTR(...) DAPC_INFRA_AO_SYS0_ATTR(__VA_ARGS__)
+#define DAPC_PERI_AO_SYS2_ATTR(...) DAPC_INFRA_AO_SYS1_ATTR(__VA_ARGS__)
+#define DAPC_PERI_AO2_SYS0_ATTR(...) DAPC_INFRA_AO_SYS0_ATTR(__VA_ARGS__)
+#define DAPC_PERI_PAR_AO_SYS0_ATTR(...) DAPC_INFRA_AO_SYS0_ATTR(__VA_ARGS__)
+
+/******************************************************************************
+ * UTILITY DEFINITION
+ ******************************************************************************/
+#define devapc_writel(VAL, REG) mmio_write_32((uintptr_t)REG, VAL)
+#define devapc_readl(REG) mmio_read_32((uintptr_t)REG)
+
+/******************************************************************************/
+/* Device APC AO for INFRA AO */
+#define DEVAPC_INFRA_AO_SYS0_D0_APC_0 (DEVAPC_INFRA_AO_BASE + 0x0000)
+#define DEVAPC_INFRA_AO_SYS1_D0_APC_0 (DEVAPC_INFRA_AO_BASE + 0x1000)
+#define DEVAPC_INFRA_AO_SYS2_D0_APC_0 (DEVAPC_INFRA_AO_BASE + 0x2000)
+
+#define DEVAPC_INFRA_AO_MAS_SEC_0 (DEVAPC_INFRA_AO_BASE + 0x0A00)
+
+/******************************************************************************/
+/* Device APC AO for PERI AO */
+#define DEVAPC_PERI_AO_SYS0_D0_APC_0 (DEVAPC_PERI_AO_BASE + 0x0000)
+#define DEVAPC_PERI_AO_SYS1_D0_APC_0 (DEVAPC_PERI_AO_BASE + 0x1000)
+#define DEVAPC_PERI_AO_SYS2_D0_APC_0 (DEVAPC_PERI_AO_BASE + 0x2000)
+
+#define DEVAPC_PERI_AO_MAS_SEC_0 (DEVAPC_PERI_AO_BASE + 0x0A00)
+
+/******************************************************************************/
+/* Device APC AO for PERI AO2 */
+#define DEVAPC_PERI_AO2_SYS0_D0_APC_0 (DEVAPC_PERI_AO2_BASE + 0x0000)
+
+/******************************************************************************/
+/* Device APC AO for PERI PAR AO */
+#define DEVAPC_PERI_PAR_AO_SYS0_D0_APC_0 (DEVAPC_PERI_PAR_AO_BASE + 0x0000)
+
+#define DEVAPC_PERI_PAR_AO_MAS_SEC_0 (DEVAPC_PERI_PAR_AO_BASE + 0x0A00)
+
+/******************************************************************************/
+
+
+/******************************************************************************
+ * Variable DEFINITION
+ ******************************************************************************/
+#define MOD_NO_IN_1_DEVAPC 16
+
+#endif /* DEVAPC_H */
+
diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..69c395e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+ uint64_t cache_dump)
+{
+ /* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */
+ /* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */
+ sync_writel(DFD_INTERNAL_CTL, 0x5);
+
+ /* bit[13]: xreset_b_update_disable */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13);
+
+ /*
+ * bit[10:3]: DFD trigger selection mask
+ * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger)
+ * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger)
+ * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger)
+ * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger)
+ * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger)
+ */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 3);
+
+ /* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
+
+ /*
+ * bit[0]: rg_rw_dfd_auto_power_on = 1
+ * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us)
+ * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us)
+ */
+ mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
+
+ /* longest scan chain length */
+ mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+
+ /* bit[1:0]: rg_rw_dfd_shift_clock_ratio */
+ mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
+
+ /* rg_dfd_test_so_over_64 */
+ mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
+
+ /* DFD3.0 */
+ mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_DIS_VAL);
+ mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL);
+ mmio_write_32(DFD_TEST_SI_2, DFD_TEST_SI_2_VAL);
+ mmio_write_32(DFD_TEST_SI_3, DFD_TEST_SI_3_VAL);
+
+ /* for iLDO feature */
+ sync_writel(DFD_POWER_CTL, 0xF9);
+
+ /* set base address */
+ mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
+
+ /*
+ * disable sleep protect of DFD
+ * 10001220[8]: protect_en_reg[8]
+ * 10001a3c[2]: infra_mcu_pwr_ctl_mask[2]
+ */
+ mmio_clrbits_32(DFD_O_PROTECT_EN_REG, 1 << 8);
+ mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 1 << 2);
+
+ /* clean DFD trigger status */
+ sync_writel(DFD_CLEAN_STATUS, 0x1);
+ sync_writel(DFD_CLEAN_STATUS, 0x0);
+
+ /* DFD-3.0 */
+ sync_writel(DFD_V30_CTL, 0x1);
+
+ /* setup global variables for suspend and resume */
+ dfd_enabled = true;
+ dfd_base_addr = base_addr;
+ dfd_chain_length = chain_length;
+ dfd_cache_dump = cache_dump;
+
+ if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+ /* DFD3.5 */
+ mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_EN_VAL);
+ sync_writel(DFD_V35_ENALBE, 0x1);
+ sync_writel(DFD_V35_TAP_NUMBER, 0xB);
+ sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+ sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+ if (cache_dump & DFD_PARITY_ERR_TRIGGER) {
+ sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
+ }
+ }
+ dsbsy();
+}
+
+void dfd_resume(void)
+{
+ if (dfd_enabled == true) {
+ dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+ }
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3)
+{
+ uint64_t ret = 0L;
+
+ switch (arg0) {
+ case PLAT_MTK_DFD_SETUP_MAGIC:
+ dfd_setup(arg1, arg2, arg3);
+ break;
+ case PLAT_MTK_DFD_READ_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+ }
+ break;
+ case PLAT_MTK_DFD_WRITE_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ sync_writel(MISC1_CFG_BASE + arg1, arg2);
+ }
+ break;
+ default:
+ ret = MTK_SIP_E_INVALID_PARAM;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..7f0f4b5
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \
+ dsbsy(); \
+ } while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC (0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152)
+
+#define MCU_BIU_BASE (MCUCFG_BASE)
+#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040)
+#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10)
+#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C)
+#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20)
+#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24)
+#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30)
+#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34)
+#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C)
+#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50)
+#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C)
+#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60)
+#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8)
+#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC)
+#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENALBE (MCU_BIU_BASE + 0xE0A8)
+#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC)
+#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0)
+#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4)
+#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0)
+#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4)
+
+#define DFD_O_PROTECT_EN_REG (0x10001220)
+#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C)
+#define DFD_O_SET_BASEADDR_REG (0x10043034)
+
+#define DFD_CACHE_DUMP_ENABLE 1U
+#define DFD_PARITY_ERR_TRIGGER 2U
+
+#define DFD_TEST_SI_0_CACHE_DIS_VAL (0x1E000202)
+#define DFD_TEST_SI_0_CACHE_EN_VAL (0x1E000002)
+#define DFD_TEST_SI_1_VAL (0x20408100)
+#define DFD_TEST_SI_2_VAL (0x10101000)
+#define DFD_TEST_SI_3_VAL (0x00000010)
+#define DFD_V35_TAP_EN_VAL (0x43FF)
+#define DFD_V35_SEQ0_0_VAL (0x63668820)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..26bed29
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <emi_mpu.h>
+#include <lib/mmio.h>
+
+/*
+ * emi_mpu_set_region_protection: protect a region.
+ * @start: start address of the region
+ * @end: end address of the region
+ * @access_permission: EMI MPU access permission
+ * Return 0 for success, otherwise negative status code.
+ */
+static int _emi_mpu_set_protection(
+ unsigned long start, unsigned long end,
+ unsigned int apc)
+{
+ unsigned int dgroup;
+ unsigned int region;
+
+ region = (start >> 24) & 0xFF;
+ start &= 0x00FFFFFF;
+ dgroup = (end >> 24) & 0xFF;
+ end &= 0x00FFFFFF;
+
+ if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+ WARN("Region:%u or dgroup:%u is wrong!\n", region, dgroup);
+ return -1;
+ }
+
+ apc &= 0x80FFFFFF;
+
+ if ((start >= DRAM_OFFSET) && (end >= start)) {
+ start -= DRAM_OFFSET;
+ end -= DRAM_OFFSET;
+ } else {
+ WARN("start:0x%lx or end:0x%lx address is wrong!\n",
+ start, end);
+ return -2;
+ }
+
+ mmio_write_32(EMI_MPU_SA(region), start);
+ mmio_write_32(EMI_MPU_EA(region), end);
+ mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+ return 0;
+}
+
+void dump_emi_mpu_regions(void)
+{
+ unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea;
+
+ int region, i;
+
+ /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
+ for (region = 0; region < 8; ++region) {
+ for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i)
+ apc[i] = mmio_read_32(EMI_MPU_APC(region, i));
+ sa = mmio_read_32(EMI_MPU_SA(region));
+ ea = mmio_read_32(EMI_MPU_EA(region));
+
+ WARN("region %d:\n", region);
+ WARN("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
+ sa, ea, apc[0], apc[1]);
+ }
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+ unsigned long start, end;
+ int i;
+
+ if (region_info->region >= EMI_MPU_REGION_NUM)
+ return -1;
+
+ start = (unsigned long)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+ (region_info->region << 24);
+
+ for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+ end = (unsigned long)(region_info->end >> EMI_MPU_ALIGN_BITS) |
+ (i << 24);
+ _emi_mpu_set_protection(start, end, region_info->apc[i]);
+ }
+
+ return 0;
+}
+
+void emi_mpu_init(void)
+{
+ struct emi_region_info_t region_info;
+
+ /* reserve region 0 for future use */
+
+ /* PCI-e protect address(64MB) */
+ region_info.start = 0xC0000000ULL;
+ region_info.end = 0xC3FF0000ULL;
+ region_info.region = 1;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, NO_PROT, NO_PROT);
+ emi_mpu_set_protection(&region_info);
+
+ /* SCP protect address */
+ region_info.start = 0x50000000ULL;
+ region_info.end = 0x513F0000ULL;
+ region_info.region = 2;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ NO_PROT, FORBIDDEN, FORBIDDEN, NO_PROT);
+ emi_mpu_set_protection(&region_info);
+
+ /* DSP protect address */
+ region_info.start = 0x40000000ULL; /* dram base addr */
+ region_info.end = 0x1FFFF0000ULL;
+ region_info.region = 3;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROT);
+ emi_mpu_set_protection(&region_info);
+
+ /* Forbidden All */
+ region_info.start = 0x40000000ULL; /* dram base addr */
+ region_info.end = 0x1FFFF0000ULL;
+ region_info.region = 4;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROT);
+ emi_mpu_set_protection(&region_info);
+
+ dump_emi_mpu_regions();
+}
+
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..0b15431
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define EMI_MPUP (EMI_BASE + 0x01D8)
+#define EMI_MPUQ (EMI_BASE + 0x01E0)
+#define EMI_MPUR (EMI_BASE + 0x01E8)
+#define EMI_MPUS (EMI_BASE + 0x01F0)
+#define EMI_MPUT (EMI_BASE + 0x01F8)
+#define EMI_MPUY (EMI_BASE + 0x0220)
+#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x0000)
+#define EMI_MPUD0_ST (EMI_BASE + 0x0160)
+#define EMI_MPUD1_ST (EMI_BASE + 0x0164)
+#define EMI_MPUD2_ST (EMI_BASE + 0x0168)
+#define EMI_MPUD3_ST (EMI_BASE + 0x016C)
+#define EMI_MPUD0_ST2 (EMI_BASE + 0x0200)
+#define EMI_MPUD1_ST2 (EMI_BASE + 0x0204)
+#define EMI_MPUD2_ST2 (EMI_BASE + 0x0208)
+#define EMI_MPUD3_ST2 (EMI_BASE + 0x020C)
+
+#define EMI_PHY_OFFSET (0x40000000UL)
+
+#define NO_PROT (0)
+#define SEC_RW (1)
+#define SEC_RW_NSEC_R (2)
+#define SEC_RW_NSEC_W (3)
+#define SEC_R_NSEC_R (4)
+#define FORBIDDEN (5)
+#define SEC_R_NSEC_RW (6)
+
+#define SECURE_OS_MPU_REGION_ID (0)
+#define ATF_MPU_REGION_ID (1)
+
+#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region) * 4)
+#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region) * 4)
+
+#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region) * 4 + \
+ (dgroup) * 0x100)
+
+#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + domain * 4)
+#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + domain * 4)
+
+#define EMI_MPU_DOMAIN_NUM 16
+#define EMI_MPU_REGION_NUM 32
+#define EMI_MPU_ALIGN_BITS 16
+#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[0] = 0; \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \
+ | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \
+ | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \
+ | (((unsigned int) d1) << 3) | ((unsigned int) d0) \
+ | (((unsigned int) lock) << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+ d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = \
+ (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) \
+ | (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) \
+ | (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) \
+ | (((unsigned int) d9) << 3) | ((unsigned int) d8); \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) \
+ | (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) \
+ | (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) \
+ | (((unsigned int) d1) << 3) | ((unsigned int) d0) \
+ | (((unsigned int) lock) << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+ unsigned long long start;
+ unsigned long long end;
+ unsigned int region;
+ unsigned long apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+int emi_mpu_set_protection(struct emi_region_info_t *region_info);
+void dump_emi_mpu_regions(void);
+
+#endif /* __EMI_MPU_H */
diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.c b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c
new file mode 100644
index 0000000..c78332d
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+{
+ uintptr_t reg_addr = 0U;
+ struct mt_pin_info gpio_info;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ gpio_info = mt_pin_infos[pin];
+
+ switch (gpio_info.base & 0x0f) {
+ case 0:
+ reg_addr = IOCFG_RM_BASE;
+ break;
+ case 1:
+ reg_addr = IOCFG_BM_BASE;
+ break;
+ case 2:
+ reg_addr = IOCFG_BL_BASE;
+ break;
+ case 3:
+ reg_addr = IOCFG_BR_BASE;
+ break;
+ case 4:
+ reg_addr = IOCFG_LM_BASE;
+ break;
+ case 5:
+ reg_addr = IOCFG_LB_BASE;
+ break;
+ case 6:
+ reg_addr = IOCFG_RT_BASE;
+ break;
+ case 7:
+ reg_addr = IOCFG_LT_BASE;
+ break;
+ case 8:
+ reg_addr = IOCFG_TL_BASE;
+ break;
+ default:
+ break;
+ }
+
+ return reg_addr;
+}
diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.h b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h
new file mode 100644
index 0000000..d3aa24d
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <mtgpio_common.h>
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+ GPIO_UNSUPPORTED = -1,
+
+ GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
+ GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
+ GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
+ GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
+ GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
+ GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
+ GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
+ GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
+ GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
+ GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
+ GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
+ GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
+ GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
+ GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
+ GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
+ GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
+ GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135,
+ GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143,
+ GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151,
+ GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159,
+ GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167,
+ GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175,
+ GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182, GPIO183,
+ GPIO184, GPIO185, GPIO186, GPIO187, GPIO188, GPIO189, GPIO190, GPIO191,
+ GPIO192, GPIO193, GPIO194, GPIO195, GPIO196, GPIO197, GPIO198, GPIO199,
+ GPIO200, GPIO201, GPIO202, GPIO203, GPIO204, GPIO205, GPIO206, GPIO207,
+ GPIO208, GPIO209, GPIO210, GPIO211, GPIO212, GPIO213, GPIO214, GPIO215,
+ GPIO216, GPIO217, GPIO218, GPIO219,
+ MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+static const struct mt_pin_info mt_pin_infos[] = {
+ PIN(0, 0, 9, 0x23, 0xb0),
+ PIN(1, 0, 10, 0x23, 0xb0),
+ PIN(2, 0, 11, 0x23, 0xb0),
+ PIN(3, 0, 12, 0x23, 0xb0),
+ PIN(4, 0, 13, 0x23, 0xb0),
+ PIN(5, 0, 14, 0x23, 0xb0),
+ PIN(6, 0, 15, 0x23, 0xb0),
+ PIN(7, 0, 16, 0x23, 0xb0),
+ PIN(8, 0, 17, 0x23, 0xb0),
+ PIN(9, 0, 18, 0x23, 0xb0),
+ PIN(10, 1, 0, 0x15, 0x20),
+ PIN(11, 1, 1, 0x15, 0x20),
+ PIN(12, 1, 2, 0x15, 0x20),
+ PIN(13, 1, 3, 0x15, 0x20),
+ PIN(14, 1, 4, 0x15, 0x20),
+ PIN(15, 1, 5, 0x15, 0x20),
+ PIN(16, 0, 2, 0x17, 0x50),
+ PIN(17, 0, 3, 0x17, 0x50),
+ PIN(18, 0, 21, 0x36, 0xa0),
+ PIN(19, 0, 22, 0x36, 0xa0),
+ PIN(20, 0, 23, 0x36, 0xa0),
+ PIN(21, 0, 24, 0x36, 0xa0),
+ PIN(22, 0, 3, 0x21, 0x90),
+ PIN(23, 0, 4, 0x21, 0x90),
+ PIN(24, 0, 5, 0x21, 0x90),
+ PIN(25, 0, 6, 0x21, 0x90),
+ PIN(26, 0, 5, 0x22, 0x80),
+ PIN(27, 0, 6, 0x22, 0x80),
+ PIN(28, 0, 7, 0x22, 0x80),
+ PIN(29, 0, 8, 0x22, 0x80),
+ PIN(30, 0, 9, 0x22, 0x80),
+ PIN(31, 0, 27, 0x22, 0x70),
+ PIN(32, 0, 24, 0x22, 0x70),
+ PIN(33, 0, 26, 0x22, 0x70),
+ PIN(34, 0, 23, 0x22, 0x70),
+ PIN(35, 0, 25, 0x22, 0x70),
+ PIN(36, 0, 20, 0x21, 0x90),
+ PIN(37, 0, 21, 0x21, 0x90),
+ PIN(38, 0, 22, 0x21, 0x90),
+ PIN(39, 0, 23, 0x21, 0x90),
+ PIN(40, 0, 0, 0x17, 0x50),
+ PIN(41, 0, 1, 0x17, 0x50),
+ PIN(42, 0, 4, 0x17, 0x50),
+ PIN(43, 0, 25, 0x36, 0xa0),
+ PIN(44, 0, 26, 0x36, 0xa0),
+ PIN(45, 1, 9, 0x20, 0x60),
+ PIN(46, 1, 11, 0x20, 0x60),
+ PIN(47, 1, 10, 0x20, 0x60),
+ PIN(48, 1, 7, 0x20, 0x60),
+ PIN(49, 1, 8, 0x20, 0x60),
+ PIN(50, 1, 6, 0x20, 0x60),
+ PIN(51, 1, 0, 0x20, 0x60),
+ PIN(52, 1, 1, 0x20, 0x60),
+ PIN(53, 1, 5, 0x20, 0x60),
+ PIN(54, 1, 2, 0x20, 0x60),
+ PIN(55, 1, 4, 0x20, 0x60),
+ PIN(56, 1, 3, 0x20, 0x60),
+ PIN(57, 0, 1, 0x22, 0x80),
+ PIN(58, 0, 2, 0x22, 0x80),
+ PIN(59, 0, 3, 0x22, 0x80),
+ PIN(60, 0, 4, 0x22, 0x80),
+ PIN(61, 0, 28, 0x22, 0x70),
+ PIN(62, 0, 22, 0x22, 0x70),
+ PIN(63, 0, 0, 0x22, 0x70),
+ PIN(64, 0, 1, 0x22, 0x70),
+ PIN(65, 0, 12, 0x22, 0x70),
+ PIN(66, 0, 15, 0x22, 0x70),
+ PIN(67, 0, 16, 0x22, 0x70),
+ PIN(68, 0, 17, 0x22, 0x70),
+ PIN(69, 0, 18, 0x22, 0x70),
+ PIN(70, 0, 19, 0x22, 0x70),
+ PIN(71, 0, 20, 0x22, 0x70),
+ PIN(72, 0, 21, 0x22, 0x70),
+ PIN(73, 0, 2, 0x22, 0x70),
+ PIN(74, 0, 3, 0x22, 0x70),
+ PIN(75, 0, 4, 0x22, 0x70),
+ PIN(76, 0, 5, 0x22, 0x70),
+ PIN(77, 0, 6, 0x22, 0x70),
+ PIN(78, 0, 7, 0x22, 0x70),
+ PIN(79, 0, 8, 0x22, 0x70),
+ PIN(80, 0, 9, 0x22, 0x70),
+ PIN(81, 0, 10, 0x22, 0x70),
+ PIN(82, 0, 11, 0x22, 0x70),
+ PIN(83, 0, 13, 0x22, 0x70),
+ PIN(84, 0, 14, 0x22, 0x70),
+ PIN(85, 0, 31, 0x22, 0x70),
+ PIN(86, 0, 0, 0x22, 0x80),
+ PIN(87, 0, 29, 0x22, 0x70),
+ PIN(88, 0, 30, 0x22, 0x70),
+ PIN(89, 0, 24, 0x21, 0x90),
+ PIN(90, 0, 25, 0x21, 0x90),
+ PIN(91, 0, 0, 0x21, 0x90),
+ PIN(92, 0, 2, 0x21, 0xa0),
+ PIN(93, 0, 4, 0x21, 0xa0),
+ PIN(94, 0, 3, 0x21, 0xa0),
+ PIN(95, 0, 5, 0x21, 0xa0),
+ PIN(96, 0, 31, 0x21, 0x90),
+ PIN(97, 0, 26, 0x21, 0x90),
+ PIN(98, 0, 0, 0x21, 0xa0),
+ PIN(99, 0, 27, 0x21, 0x90),
+ PIN(100, 0, 28, 0x21, 0x90),
+ PIN(101, 0, 29, 0x21, 0x90),
+ PIN(102, 0, 30, 0x21, 0x90),
+ PIN(103, 0, 18, 0x21, 0x90),
+ PIN(104, 0, 17, 0x21, 0x90),
+ PIN(105, 0, 19, 0x21, 0x90),
+ PIN(106, 0, 16, 0x21, 0x90),
+ PIN(107, 0, 1, 0x21, 0x90),
+ PIN(108, 0, 2, 0x21, 0x90),
+ PIN(109, 0, 10, 0x21, 0x90),
+ PIN(110, 0, 7, 0x21, 0x90),
+ PIN(111, 0, 9, 0x21, 0x90),
+ PIN(112, 0, 11, 0x21, 0x90),
+ PIN(113, 0, 8, 0x21, 0x90),
+ PIN(114, 0, 14, 0x21, 0x90),
+ PIN(115, 0, 13, 0x21, 0x90),
+ PIN(116, 0, 15, 0x21, 0x90),
+ PIN(117, 0, 12, 0x21, 0x90),
+ PIN(118, 0, 23, 0x23, 0xb0),
+ PIN(119, 0, 29, 0x23, 0xb0),
+ PIN(120, 0, 28, 0x23, 0xb0),
+ PIN(121, 0, 2, 0x23, 0xc0),
+ PIN(122, 0, 27, 0x23, 0xb0),
+ PIN(123, 0, 1, 0x23, 0xc0),
+ PIN(124, 0, 26, 0x23, 0xb0),
+ PIN(125, 0, 0, 0x23, 0xc0),
+ PIN(126, 0, 19, 0x23, 0xb0),
+ PIN(127, 0, 20, 0x23, 0xb0),
+ PIN(128, 0, 21, 0x23, 0xb0),
+ PIN(129, 0, 22, 0x23, 0xb0),
+ PIN(130, 0, 6, 0x23, 0xb0),
+ PIN(131, 0, 7, 0x23, 0xb0),
+ PIN(132, 0, 8, 0x23, 0xb0),
+ PIN(133, 0, 3, 0x23, 0xb0),
+ PIN(134, 0, 4, 0x23, 0xb0),
+ PIN(135, 0, 5, 0x23, 0xb0),
+ PIN(136, 0, 0, 0x23, 0xb0),
+ PIN(137, 0, 1, 0x23, 0xb0),
+ PIN(138, 0, 2, 0x23, 0xb0),
+ PIN(139, 0, 25, 0x23, 0xb0),
+ PIN(140, 0, 31, 0x23, 0xb0),
+ PIN(141, 0, 24, 0x23, 0xb0),
+ PIN(142, 0, 30, 0x23, 0xb0),
+ PIN(143, 0, 6, 0x20, 0x70),
+ PIN(144, 0, 7, 0x20, 0x70),
+ PIN(145, 0, 8, 0x20, 0x70),
+ PIN(146, 0, 3, 0x20, 0x70),
+ PIN(147, 0, 4, 0x20, 0x70),
+ PIN(148, 0, 5, 0x20, 0x70),
+ PIN(149, 0, 0, 0x20, 0x70),
+ PIN(150, 0, 1, 0x20, 0x70),
+ PIN(151, 0, 2, 0x20, 0x70),
+ PIN(152, 1, 3, 0x36, 0x90),
+ PIN(153, 1, 2, 0x36, 0x90),
+ PIN(154, 1, 0, 0x36, 0x906),
+ PIN(155, 1, 1, 0x36, 0x90),
+ PIN(156, 0, 29, 0x36, 0xa0),
+ PIN(157, 0, 30, 0x36, 0xa0),
+ PIN(158, 0, 31, 0x36, 0xa0),
+ PIN(159, 0, 0, 0x36, 0xb0),
+ PIN(160, 0, 27, 0x36, 0xa04),
+ PIN(161, 0, 28, 0x36, 0xa0),
+ PIN(162, 0, 0, 0x36, 0xa0),
+ PIN(163, 0, 1, 0x36, 0xa0),
+ PIN(164, 0, 2, 0x36, 0xa0),
+ PIN(165, 0, 3, 0x36, 0xa0),
+ PIN(166, 0, 4, 0x36, 0xa0),
+ PIN(167, 0, 5, 0x36, 0xa0),
+ PIN(168, 0, 6, 0x36, 0xa0),
+ PIN(169, 0, 7, 0x36, 0xa0),
+ PIN(170, 0, 8, 0x36, 0xa0),
+ PIN(171, 0, 9, 0x36, 0xa0),
+ PIN(172, 0, 13, 0x36, 0xa0),
+ PIN(173, 0, 14, 0x36, 0xa0),
+ PIN(174, 0, 12, 0x36, 0xa0),
+ PIN(175, 0, 15, 0x36, 0xa0),
+ PIN(176, 0, 10, 0x36, 0xa0),
+ PIN(177, 0, 11, 0x36, 0xa0),
+ PIN(178, 0, 16, 0x36, 0xa0),
+ PIN(179, 0, 17, 0x36, 0xa0),
+ PIN(180, 0, 18, 0x36, 0xa0),
+ PIN(181, 0, 19, 0x36, 0xa0),
+ PIN(182, 0, 20, 0x36, 0xa0),
+ PIN(183, 1, 1, 0x18, 0x30),
+ PIN(184, 1, 2, 0x18, 0x30),
+ PIN(185, 1, 4, 0x18, 0x30),
+ PIN(186, 1, 6, 0x18, 0x30),
+ PIN(187, 1, 8, 0x18, 0x30),
+ PIN(188, 1, 3, 0x18, 0x30),
+ PIN(189, 1, 7, 0x18, 0x30),
+ PIN(190, 1, 9, 0x18, 0x30),
+ PIN(191, 1, 10, 0x18, 0x30),
+ PIN(192, 1, 0, 0x18, 0x30),
+ PIN(193, 1, 5, 0x18, 0x30),
+ PIN(194, 1, 11, 0x18, 0x30),
+ PIN(195, 0, 16, 0x14, 0x50),
+ PIN(196, 0, 6, 0x14, 0x50),
+ PIN(197, 0, 8, 0x14, 0x50),
+ PIN(198, 0, 7, 0x14, 0x50),
+ PIN(199, 0, 3, 0x14, 0x50),
+ PIN(200, 0, 6, 0x17, 0x50),
+ PIN(201, 0, 8, 0x17, 0x50),
+ PIN(202, 0, 15, 0x14, 0x50),
+ PIN(203, 0, 17, 0x14, 0x50),
+ PIN(204, 0, 5, 0x17, 0x50),
+ PIN(205, 0, 7, 0x17, 0x50),
+ PIN(206, 0, 18, 0x14, 0x50),
+ PIN(207, 0, 19, 0x14, 0x50),
+ PIN(208, 0, 20, 0x14, 0x50),
+ PIN(209, 0, 12, 0x14, 0x50),
+ PIN(210, 0, 11, 0x14, 0x50),
+ PIN(211, 0, 13, 0x14, 0x50),
+ PIN(212, 0, 10, 0x14, 0x50),
+ PIN(213, 0, 14, 0x14, 0x50),
+ PIN(214, 0, 0, 0x14, 0x50),
+ PIN(215, 0, 9, 0x14, 0x50),
+ PIN(216, 0, 4, 0x14, 0x50),
+ PIN(217, 0, 5, 0x14, 0x50),
+ PIN(218, 0, 1, 0x14, 0x50),
+ PIN(219, 0, 2, 0x14, 0x50),
+};
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
new file mode 100644
index 0000000..b483c36
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_lp_irqremain.h>
+#include <mt_lp_rm.h>
+#include <mt_mcdi.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
+
+static int plat_mt_lp_cpu_rc;
+
+static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
+{
+ mtk_cpc_core_on_hint_clr(cpu);
+
+ if (IS_SYSTEM_SUSPEND_STATE(state)) {
+ mtk_cpc_time_sync();
+ }
+
+ return 0;
+}
+
+static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ /* clear DBGPRCR.CORENPDRQ to allow CPU power down */
+ write_dbgprcr_el1(0ULL);
+
+ return 0;
+}
+
+static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ mtk_cpc_mcusys_off_reflect();
+
+ return 0;
+}
+
+static int pwr_mcusys_pwron_finished(unsigned int cpu,
+ const psci_power_state_t *state)
+{
+ int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
+
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id);
+ mt_lp_irqremain_release();
+
+ return 0;
+}
+
+static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
+
+ if (!IS_MCUSYS_OFF_STATE(state)) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (mcdi_try_init() != 0) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ plat_mt_lp_cpu_rc =
+ mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL);
+
+ if (plat_mt_lp_cpu_rc < 0) {
+ goto mt_pwr_mcusysoff_reflect;
+ }
+
+ mt_lp_irqremain_aquire();
+
+ return 0;
+
+mt_pwr_mcusysoff_reflect:
+ mtk_cpc_mcusys_off_reflect();
+
+mt_pwr_mcusysoff_break:
+ plat_mt_lp_cpu_rc = -1;
+
+ return -1;
+}
+
+static const struct mt_lpm_tz plat_pm = {
+ .pwr_prompt = pwr_state_prompt,
+ .pwr_reflect = pwr_state_reflect,
+ .pwr_cpu_on = pwr_cpu_pwron,
+ .pwr_cpu_dwn = pwr_cpu_pwrdwn,
+ .pwr_cluster_on = pwr_cluster_pwron,
+ .pwr_cluster_dwn = pwr_cluster_pwrdwn,
+ .pwr_mcusys_dwn = pwr_mcusys_pwrdwn,
+ .pwr_mcusys_on = pwr_mcusys_pwron,
+ .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
+{
+ mtk_cpc_init();
+
+ if (mcdi_try_init() == 0) {
+ INFO("MCDI init done.\n");
+ }
+
+ mt_lp_irqremain_init();
+
+ return &plat_pm;
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c
new file mode 100644
index 0000000..f8c51a1
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_timer.h>
+
+struct mtk_cpc_dev {
+ int auto_off;
+ unsigned int auto_thres_tick;
+};
+
+static struct mtk_cpc_dev cpc;
+
+static int mtk_cpc_last_core_prot(uint32_t prot_req,
+ uint32_t resp_reg, uint32_t resp_ofs)
+{
+ uint32_t sta, retry;
+
+ retry = 0U;
+
+ while (retry++ < RETRY_CNT_MAX) {
+
+ mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
+
+ udelay(1U);
+
+ sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
+
+ if (sta == PROT_SUCCESS) {
+ return CPC_SUCCESS;
+ } else if (sta == PROT_GIVEUP) {
+ return CPC_ERR_FAIL;
+ }
+ }
+
+ return CPC_ERR_TIMEOUT;
+}
+
+int mtk_cpu_pm_mcusys_prot_aquire(void)
+{
+ return mtk_cpc_last_core_prot(
+ MCUSYS_PROT_SET,
+ CPC_MCUSYS_LAST_CORE_RESP,
+ MCUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_mcusys_prot_release(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
+}
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster)
+{
+ return mtk_cpc_last_core_prot(
+ CPUSYS_PROT_SET,
+ CPC_MCUSYS_MP_LAST_CORE_RESP,
+ CPUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
+}
+
+static void mtk_cpc_cluster_cnt_backup(void)
+{
+ uint32_t backup_cnt;
+ uint32_t curr_cnt;
+ uint32_t cnt_mask = GENMASK(14, 0);
+ uint32_t clr_mask = GENMASK(1, 0);
+
+ /* Single Cluster */
+ backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
+ curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
+
+ /* Get off count if dormant count is 0 */
+ if ((curr_cnt & cnt_mask) == 0U) {
+ curr_cnt = (curr_cnt >> 16) & cnt_mask;
+ } else {
+ curr_cnt = curr_cnt & cnt_mask;
+ }
+
+ mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
+ mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask);
+}
+
+static inline void mtk_cpc_mcusys_off_en(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U);
+}
+
+static inline void mtk_cpc_mcusys_off_dis(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U);
+}
+
+void mtk_cpc_mcusys_off_reflect(void)
+{
+ mtk_cpc_mcusys_off_dis();
+ mtk_cpu_pm_mcusys_prot_release();
+}
+
+int mtk_cpc_mcusys_off_prepare(void)
+{
+ if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
+ return CPC_ERR_FAIL;
+ }
+
+ mtk_cpc_cluster_cnt_backup();
+ mtk_cpc_mcusys_off_en();
+
+ return CPC_SUCCESS;
+}
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
+}
+
+void mtk_cpc_core_on_hint_clr(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+static void mtk_cpc_dump_timestamp(void)
+{
+ uint32_t id;
+
+ for (id = 0U; id < CPC_TRACE_ID_NUM; id++) {
+ mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
+
+ memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
+ (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
+ CPC_TRACE_SIZE);
+ }
+}
+
+void mtk_cpc_time_sync(void)
+{
+ uint64_t kt;
+ uint32_t systime_l, systime_h;
+
+ kt = sched_clock();
+ systime_l = mmio_read_32(CNTSYS_L_REG);
+ systime_h = mmio_read_32(CNTSYS_H_REG);
+
+ /* sync kernel timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
+ /* sync system timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
+}
+
+static void mtk_cpc_config(uint32_t cfg, uint32_t data)
+{
+ uint32_t val;
+ uint32_t reg = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ reg = CPC_MCUSYS_CPC_DBG_SETTING;
+ val = mmio_read_32(reg);
+ val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN);
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG;
+ val = mmio_read_32(reg);
+ if (data != 0U) {
+ val |= CPC_AUTO_OFF_EN;
+ cpc.auto_off = 1;
+ } else {
+ val &= ~CPC_AUTO_OFF_EN;
+ cpc.auto_off = 0;
+ }
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ reg = CPC_MCUSYS_CPC_OFF_THRES;
+ cpc.auto_thres_tick = us_to_ticks(data);
+ val = cpc.auto_thres_tick;
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR;
+ val = GENMASK(1, 0); /* clr_mask */
+ break;
+ case CPC_SMC_CONFIG_TIME_SYNC:
+ mtk_cpc_time_sync();
+ break;
+ default:
+ break;
+ }
+
+ if (reg != 0U) {
+ mmio_write_32(reg, val);
+ }
+}
+
+static uint32_t mtk_cpc_read_config(uint32_t cfg)
+{
+ uint32_t res = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ?
+ 1U : 0U;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ res = cpc.auto_off;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ res = ticks_to_us(cpc.auto_thres_tick);
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t res = 0ULL;
+
+ switch (act) {
+ case CPC_SMC_EVENT_DUMP_TRACE_DATA:
+ mtk_cpc_dump_timestamp();
+ break;
+ case CPC_SMC_EVENT_GIC_DPG_SET:
+ /* isolated_status = x2; */
+ break;
+ case CPC_SMC_EVENT_CPC_CONFIG:
+ mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2);
+ break;
+ case CPC_SMC_EVENT_READ_CONFIG:
+ res = mtk_cpc_read_config((uint32_t)arg1);
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+void mtk_cpc_init(void)
+{
+ mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING,
+ mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING)
+ | CPC_DBG_EN
+ | CPC_CALC_EN);
+
+ cpc.auto_off = 1;
+ cpc.auto_thres_tick = us_to_ticks(8000);
+
+ mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+ mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG)
+ | CPC_OFF_PRE_EN
+ | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U));
+
+ mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h
new file mode 100644
index 0000000..19dd6a2
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_CPC_H
+#define MT_CPU_PM_CPC_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mcucfg.h>
+#include <platform_def.h>
+
+#define NEED_CPUSYS_PROT_WORKAROUND 1
+
+/* system sram registers */
+#define CPUIDLE_SRAM_REG(r) (uint32_t)(MTK_MCDI_SRAM_BASE + (r))
+
+/* db dump */
+#define CPC_TRACE_SIZE U(0x20)
+#define CPC_TRACE_ID_NUM U(10)
+#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
+
+/* buckup off count */
+#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0)
+#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */
+#define CPC_PWR_ON_SEQ_DIS BIT(1)
+#define CPC_PWR_ON_PRIORITY BIT(2)
+#define CPC_AUTO_OFF_EN BIT(5)
+#define CPC_DORMANT_WAIT_EN BIT(14)
+#define CPC_CTRL_EN BIT(16)
+#define CPC_OFF_PRE_EN BIT(29)
+
+/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */
+#define CPUSYS_PROT_SET BIT(0)
+#define MCUSYS_PROT_SET BIT(8)
+#define CPUSYS_PROT_CLR BIT(8)
+#define MCUSYS_PROT_CLR BIT(9)
+
+#define CPC_PROT_RESP_MASK U(0x3)
+#define CPUSYS_RESP_OFS U(16)
+#define MCUSYS_RESP_OFS U(30)
+
+#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+
+#define RETRY_CNT_MAX U(1000)
+
+#define PROT_RETRY U(0)
+#define PROT_SUCCESS U(1)
+#define PROT_GIVEUP U(2)
+
+/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */
+#define CPC_PROF_EN BIT(0)
+#define CPC_DBG_EN BIT(1)
+#define CPC_FREEZE BIT(2)
+#define CPC_CALC_EN BIT(3)
+
+enum {
+ CPC_SUCCESS = 0,
+
+ CPC_ERR_FAIL,
+ CPC_ERR_TIMEOUT,
+
+ NF_CPC_ERR
+};
+
+enum {
+ CPC_SMC_EVENT_DUMP_TRACE_DATA,
+ CPC_SMC_EVENT_GIC_DPG_SET,
+ CPC_SMC_EVENT_CPC_CONFIG,
+ CPC_SMC_EVENT_READ_CONFIG,
+
+ NF_CPC_SMC_EVENT
+};
+
+enum {
+ CPC_SMC_CONFIG_PROF,
+ CPC_SMC_CONFIG_AUTO_OFF,
+ CPC_SMC_CONFIG_AUTO_OFF_THRES,
+ CPC_SMC_CONFIG_CNT_CLR,
+ CPC_SMC_CONFIG_TIME_SYNC,
+
+ NF_CPC_SMC_CONFIG
+};
+
+#define us_to_ticks(us) ((us) * 13)
+#define ticks_to_us(tick) ((tick) / 13)
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster);
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster);
+
+void mtk_cpc_mcusys_off_reflect(void);
+int mtk_cpc_mcusys_off_prepare(void);
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu);
+void mtk_cpc_core_on_hint_clr(unsigned int cpu);
+void mtk_cpc_time_sync(void);
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
+void mtk_cpc_init(void);
+
+#endif /* MT_CPU_PM_CPC_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c
new file mode 100644
index 0000000..872f4d0
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mt_cirq.h>
+#include <mt_lp_irqremain.h>
+#include <mt_lp_rm.h>
+#include <plat_mtk_lpm.h>
+
+#define EDMA0_IRQ_ID U(448)
+#define MDLA_IRQ_ID U(446)
+#define MALI4_IRQ_ID U(399)
+#define MALI3_IRQ_ID U(398)
+#define MALI2_IRQ_ID U(397)
+#define MALI1_IRQ_ID U(396)
+#define MALI0_IRQ_ID U(395)
+#define VPU_CORE1_IRQ_ID U(453)
+#define VPU_CORE0_IRQ_ID U(452)
+#define MD_WDT_IRQ_ID U(110)
+#define KEYPAD_IRQ_ID U(106)
+
+#define MD_WDT_WAKESRC 0x2000000
+#define KEYPAD_WAKESRC 0x4
+
+static struct mt_irqremain remain_irqs;
+
+int mt_lp_irqremain_submit(void)
+{
+ if (remain_irqs.count == 0) {
+ return -1;
+ }
+
+ set_wakeup_sources(remain_irqs.irqs, remain_irqs.count);
+ mt_lp_rm_do_update(-1, PLAT_RC_UPDATE_REMAIN_IRQS, &remain_irqs);
+
+ return 0;
+}
+
+int mt_lp_irqremain_aquire(void)
+{
+ if (remain_irqs.count == 0) {
+ return -1;
+ }
+
+ mt_cirq_sw_reset();
+ mt_cirq_clone_gic();
+ mt_cirq_enable();
+
+ return 0;
+}
+
+int mt_lp_irqremain_release(void)
+{
+ if (remain_irqs.count == 0) {
+ return -1;
+ }
+
+ mt_cirq_flush();
+ mt_cirq_disable();
+
+ return 0;
+}
+
+void mt_lp_irqremain_init(void)
+{
+ uint32_t idx;
+
+ remain_irqs.count = 0;
+
+ /* level edma0 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = EDMA0_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level mdla */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = MDLA_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level mali4 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = MALI4_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level mali3 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = MALI3_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level mali2 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = MALI2_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level mali1 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = MALI1_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level mali0 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = MALI0_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level vpu core1 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = VPU_CORE1_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* level vpu core0 */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = VPU_CORE0_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = 0;
+ remain_irqs.count++;
+
+ /* edge mdwdt */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = MD_WDT_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = MD_WDT_WAKESRC;
+ remain_irqs.count++;
+
+ /* edge keypad */
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = KEYPAD_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = KEYPAD_WAKESRC;
+ remain_irqs.count++;
+
+ mt_lp_irqremain_submit();
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h
new file mode 100644
index 0000000..cbed967
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_IRQREMAIN_H
+#define MT_LP_IRQREMAIN_H
+
+extern int mt_lp_irqremain_submit(void);
+extern int mt_lp_irqremain_aquire(void);
+extern int mt_lp_irqremain_release(void);
+extern void mt_lp_irqremain_init(void);
+#endif /* MT_LP_IRQREMAIN_H */
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c
new file mode 100644
index 0000000..1635b67
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdefs.h>
+#include <common/debug.h>
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mt_mcdi.h>
+
+/* Read/Write */
+#define APMCU_MCUPM_MBOX_AP_READY U(0)
+#define APMCU_MCUPM_MBOX_RESERVED_1 U(1)
+#define APMCU_MCUPM_MBOX_RESERVED_2 U(2)
+#define APMCU_MCUPM_MBOX_RESERVED_3 U(3)
+#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4)
+#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5)
+#define APMCU_MCUPM_MBOX_BUCK_MODE U(6)
+#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7)
+/* Read only */
+#define APMCU_MCUPM_MBOX_TASK_STA U(8)
+#define APMCU_MCUPM_MBOX_RESERVED_9 U(9)
+#define APMCU_MCUPM_MBOX_RESERVED_10 U(10)
+#define APMCU_MCUPM_MBOX_RESERVED_11 U(11)
+
+/* CPC mode - Read/Write */
+#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */
+#define MCUPM_MCUSYS_CTRL BIT(0)
+#define MCUPM_BUCK_CTRL BIT(1)
+#define MCUPM_ARMPLL_CTRL BIT(2)
+#define MCUPM_CM_CTRL BIT(3)
+#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */
+#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */
+#define MCUPM_BUCK_LP_MODE U(1)
+#define MCUPM_BUCK_OFF_MODE U(2)
+#define NF_MCUPM_BUCK_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */
+#define MCUPM_ARMPLL_ON U(0) /* default */
+#define MCUPM_ARMPLL_GATING U(1)
+#define MCUPM_ARMPLL_OFF U(2)
+#define NF_MCUPM_ARMPLL_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */
+#define MCUPM_TASK_UNINIT U(0)
+#define MCUPM_TASK_INIT U(1)
+#define MCUPM_TASK_INIT_FINISH U(2)
+#define MCUPM_TASK_WAIT U(3)
+#define MCUPM_TASK_RUN U(4)
+#define MCUPM_TASK_PAUSE U(5)
+
+#define SSPM_MBOX_3_BASE U(0x0c55fce0)
+
+#define MCDI_NOT_INIT 0
+#define MCDI_INIT_1 1
+#define MCDI_INIT_2 2
+#define MCDI_INIT_DONE 3
+
+static int mcdi_init_status __section("tzfw_coherent_mem");
+
+static inline uint32_t mcdi_mbox_read(uint32_t id)
+{
+ return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
+}
+
+static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
+{
+ mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
+}
+
+static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev)
+{
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev);
+}
+
+static void mtk_set_mcupm_pll_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_ARMPLL_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode);
+ }
+}
+
+static void mtk_set_mcupm_buck_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_BUCK_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode);
+ }
+}
+
+static int mtk_mcupm_is_ready(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH);
+}
+
+static int mcdi_init_1(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ if (sta != MCUPM_TASK_INIT) {
+ return -1;
+ }
+
+ mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
+ mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
+
+ mtk_mcupm_pwr_ctrl_setting(
+ MCUPM_MCUSYS_CTRL |
+ MCUPM_BUCK_CTRL |
+ MCUPM_ARMPLL_CTRL);
+
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1);
+
+ return 0;
+}
+
+static int mcdi_init_2(void)
+{
+ return mtk_mcupm_is_ready() ? 0 : -1;
+}
+
+int mcdi_try_init(void)
+{
+ if (mcdi_init_status == MCDI_INIT_DONE) {
+ return 0;
+ }
+
+ if (mcdi_init_status == MCDI_NOT_INIT) {
+ mcdi_init_status = MCDI_INIT_1;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) {
+ mcdi_init_status = MCDI_INIT_2;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) {
+ mcdi_init_status = MCDI_INIT_DONE;
+ }
+
+ INFO("mcdi ready for mcusys-off-idle and system suspend\n");
+
+ return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
+}
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h
new file mode 100644
index 0000000..f3545aa
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MCDI_H
+#define MT_MCDI_H
+
+int mcdi_try_init(void);
+
+#endif /* MT_MCDI_H */
diff --git a/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..b9ab586
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+#include <pmic_wrap_init_common.h>
+
+static struct mt8192_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* PMIC_WRAP registers */
+struct mt8192_pmic_wrap_regs {
+ uint32_t init_done;
+ uint32_t reserved[799];
+ uint32_t wacs2_cmd;
+ uint32_t wacs2_wdata;
+ uint32_t reserved1[3];
+ uint32_t wacs2_rdata;
+ uint32_t reserved2[3];
+ uint32_t wacs2_vldclr;
+ uint32_t wacs2_sta;
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h
new file mode 100644
index 0000000..92c71bc
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_PTP3_H
+#define MTK_PTP3_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+/************************************************
+ * BIT Operation and REG r/w
+ ************************************************/
+#define ptp3_read(addr) mmio_read_32((uintptr_t)addr)
+#define ptp3_write(addr, val) mmio_write_32((uintptr_t)addr, val)
+
+/************************************************
+ * CPU info
+ ************************************************/
+#define NR_PTP3_CFG1_CPU U(8)
+#define PTP3_CFG1_CPU_START_ID U(0)
+#define PTP3_CFG1_MASK 0x00100000
+
+#define NR_PTP3_CFG2_CPU U(4)
+#define PTP3_CFG2_CPU_START_ID U(4)
+
+#define NR_PTP3_CFG3_CPU U(4)
+#define PTP3_CFG3_CPU_START_ID U(4)
+
+/************************************************
+ * config enum
+ ************************************************/
+enum PTP3_CFG {
+ PTP3_CFG_ADDR,
+ PTP3_CFG_VALUE,
+ NR_PTP3_CFG,
+};
+
+/************************************
+ * prototype
+ ************************************/
+/* init trigger for ptp3 feature */
+extern void ptp3_init(unsigned int core);
+extern void ptp3_deinit(unsigned int core);
+
+#endif /* MTK_PTP3_H */
diff --git a/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
new file mode 100644
index 0000000..f1d8493
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved. \
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "mtk_ptp3_common.h"
+
+/************************************************
+ * Central control: turn on sysPi protection
+ ************************************************/
+static unsigned int ptp3_cfg1[NR_PTP3_CFG1_CPU][NR_PTP3_CFG] = {
+ {0x0C530610, 0x110842},
+ {0x0C530E10, 0x110842},
+ {0x0C531610, 0x110842},
+ {0x0C531E10, 0x110842},
+ {0x0C532610, 0x110842},
+ {0x0C532E10, 0x110842},
+ {0x0C533610, 0x110842},
+ {0x0C533E10, 0x110842}
+};
+static unsigned int ptp3_cfg2[NR_PTP3_CFG2_CPU][NR_PTP3_CFG] = {
+ {0x0C53B830, 0x68000},
+ {0x0C53BA30, 0x68000},
+ {0x0C53BC30, 0x68000},
+ {0x0C53BE30, 0x68000}
+};
+static unsigned int ptp3_cfg3[NR_PTP3_CFG3_CPU][NR_PTP3_CFG] = {
+ {0x0C532480, 0x7C607C6},
+ {0x0C532C80, 0x7C607C6},
+ {0x0C533480, 0x7C607C6},
+ {0x0C533C80, 0x7C607C6}
+};
+
+/************************************************
+ * API
+ ************************************************/
+void ptp3_init(unsigned int core)
+{
+ unsigned int _core;
+
+ /* Apply ptp3_cfg1 for core 0 to 7 */
+ if (core < NR_PTP3_CFG1_CPU) {
+ /* update ptp3_cfg1 */
+ ptp3_write(
+ ptp3_cfg1[core][PTP3_CFG_ADDR],
+ ptp3_cfg1[core][PTP3_CFG_VALUE]);
+ }
+
+ /* Apply ptp3_cfg2 for core 4 to 7 */
+ if (core >= PTP3_CFG2_CPU_START_ID) {
+ _core = core - PTP3_CFG2_CPU_START_ID;
+
+ if (_core < NR_PTP3_CFG2_CPU) {
+ /* update ptp3_cfg2 */
+ ptp3_write(
+ ptp3_cfg2[_core][PTP3_CFG_ADDR],
+ ptp3_cfg2[_core][PTP3_CFG_VALUE]);
+ }
+ }
+
+ /* Apply ptp3_cfg3 for core 4 to 7 */
+ if (core >= PTP3_CFG3_CPU_START_ID) {
+ _core = core - PTP3_CFG3_CPU_START_ID;
+
+ if (_core < NR_PTP3_CFG3_CPU) {
+ /* update ptp3_cfg3 */
+ ptp3_write(
+ ptp3_cfg3[_core][PTP3_CFG_ADDR],
+ ptp3_cfg3[_core][PTP3_CFG_VALUE]);
+ }
+ }
+}
+
+void ptp3_deinit(unsigned int core)
+{
+ if (core < NR_PTP3_CFG1_CPU) {
+ /* update ptp3_cfg1 */
+ ptp3_write(
+ ptp3_cfg1[core][PTP3_CFG_ADDR],
+ ptp3_cfg1[core][PTP3_CFG_VALUE] &
+ ~PTP3_CFG1_MASK);
+ }
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/build.mk b/plat/mediatek/mt8192/drivers/spm/build.mk
new file mode 100644
index 0000000..4153603
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/build.mk
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2020, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Enable or disable spm feature
+MT_SPM_FEATURE_SUPPORT = yes
+
+# Enable or disable cirq restore
+MT_SPM_CIRQ_FEATURE_SUPPORT = yes
+
+# sspm notifier support
+MT_SPM_SSPM_NOTIFIER_SUPPORT = yes
+
+CUR_SPM_FOLDER = ${MTK_PLAT_SOC}/drivers/spm
+
+# spm common files
+PLAT_SPM_SOURCE_FILES_COMMON += \
+ ${CUR_SPM_FOLDER}/mt_spm.c \
+ ${CUR_SPM_FOLDER}/mt_spm_conservation.c \
+ ${CUR_SPM_FOLDER}/mt_spm_internal.c \
+ ${CUR_SPM_FOLDER}/mt_spm_pmic_wrap.c \
+ ${CUR_SPM_FOLDER}/mt_spm_vcorefs.c
+
+# spm platform dependcy files
+PLAT_SPM_SOURCE_FILES += \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_bus26m.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_cpu_buck_ldo.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_dram.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c \
+ ${CUR_SPM_FOLDER}/mt_spm_cond.c \
+ ${CUR_SPM_FOLDER}/mt_spm_suspend.c \
+ ${CUR_SPM_FOLDER}/mt_spm_idle.c
+
+ifeq (${MT_SPM_FEATURE_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${PLAT_SPM_SOURCE_FILES_COMMON}
+else
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \
+ ${PLAT_SPM_SOURCE_FILES_COMMON} \
+ ${PLAT_SPM_SOURCE_FILES}
+endif
+
+ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_CIRQ_UNSUPPORT
+endif
+
+ifeq (${MT_SPM_SSPM_NOTIFIER_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+else
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \
+ ${CUR_SPM_FOLDER}/notifier/mt_spm_sspm_notifier.c
+endif
+
+$(info --------------------------------------)
+$(info SPM build flags: ${PLAT_SPM_DEBUG_CFLAGS})
+$(info SPM build files: ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES})
+$(info --------------------------------------)
+
+# Common makefile for platform.mk
+PLAT_INCLUDES += \
+ ${PLAT_SPM_DEBUG_CFLAGS} \
+ -I${CUR_SPM_FOLDER}/ \
+ -I${CUR_SPM_FOLDER}/constraints/ \
+ -I${CUR_SPM_FOLDER}/notifier/
+
+PLAT_BL_COMMON_SOURCES += ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES}
diff --git a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c
new file mode 100644
index 0000000..18c43b1
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <plat_mtk_lpm.h>
+
+#ifndef ATF_PLAT_CIRQ_UNSUPPORT
+#include <mt_cirq.h>
+#include <mt_gic_v3.h>
+#endif
+
+#define CONSTRAINT_BUS26M_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
+ MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \
+ MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF)
+
+#define CONSTRAINT_BUS26M_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_ENABLE_TIA_WORKAROUND | \
+ SPM_FLAG_ENABLE_LVTS_WORKAROUND | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
+
+#define CONSTRAINT_BUS26M_PCM_FLAG1 \
+ (SPM_FLAG1_DISABLE_MD26M_CK_OFF)
+
+#define CONSTRAINT_BUS26M_RESOURCE_REQ 0U
+
+static unsigned int bus26m_ext_opand;
+static struct mt_irqremain *refer2remain_irq;
+static struct mt_spm_cond_tables cond_bus26m = {
+ .name = "bus26m",
+ .table_cg = {
+ 0x07CBF1FC, /* MTCMOS1 */
+ 0x0A0D8856, /* INFRA0 */
+ 0x03AF9A00, /* INFRA1 */
+ 0x86000650, /* INFRA2 */
+ 0xC800C000, /* INFRA3 */
+ 0x00000000, /* INFRA4 */
+ 0x4000007C, /* INFRA5 */
+ 0x280E0800, /* MMSYS0 */
+ 0x00000001, /* MMSYS1 */
+ 0x00000000, /* MMSYS2 */
+ },
+ .table_pll = (PLL_BIT_UNIVPLL | PLL_BIT_MFGPLL |
+ PLL_BIT_MSDCPLL | PLL_BIT_TVDPLL |
+ PLL_BIT_MMPLL),
+};
+
+static struct mt_spm_cond_tables cond_bus26m_res = {
+ .table_cg = { 0U },
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_BUS26M,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_bus26m_res,
+};
+
+/*
+ * Cirq will take the place of gic when gic is off.
+ * However, cirq cannot work if 26m clk is turned off when system idle/suspend.
+ * Therefore, we need to set irq pending for specific wakeup source.
+ */
+#ifdef ATF_PLAT_CIRQ_UNSUPPORT
+#define do_irqs_delivery()
+#else
+static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs,
+ unsigned int irq_index,
+ struct wake_status *wakeup)
+{
+ INFO("[SPM] r12 = 0x%08x(0x%08x), flag = 0x%08x 0x%08x 0x%08x\n",
+ wakeup->tr.comm.r12, wakeup->md32pcm_wakeup_sta,
+ wakeup->tr.comm.debug_flag, wakeup->tr.comm.b_sw_flag0,
+ wakeup->tr.comm.b_sw_flag1);
+
+ INFO("irq:%u(0x%08x) set pending\n",
+ irqs->wakeupsrc[irq_index], irqs->irqs[irq_index]);
+}
+
+static void do_irqs_delivery(void)
+{
+ unsigned int idx;
+ int res = 0;
+ struct wake_status *wakeup = NULL;
+ struct mt_irqremain *irqs = refer2remain_irq;
+
+ res = spm_conservation_get_result(&wakeup);
+
+ if ((res != 0) && (irqs == NULL)) {
+ return;
+ }
+
+ for (idx = 0U; idx < irqs->count; ++idx) {
+ if (((wakeup->tr.comm.r12 & irqs->wakeupsrc[idx]) != 0U) ||
+ ((wakeup->raw_sta & irqs->wakeupsrc[idx]) != 0U)) {
+ if ((irqs->wakeupsrc_cat[idx] &
+ MT_IRQ_REMAIN_CAT_LOG) != 0U) {
+ mt_spm_irq_remain_dump(irqs, idx, wakeup);
+ }
+
+ mt_irq_set_pending(irqs->irqs[idx]);
+ }
+ }
+}
+#endif
+
+static void spm_bus26m_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
+}
+
+int spm_update_rc_bus26m(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_bus26m;
+
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ &cond_bus26m_res : NULL);
+ } else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) {
+ refer2remain_irq = (struct mt_irqremain *)val;
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_bus26m(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_BUS26M_ALLOW;
+}
+
+int spm_run_rc_bus26m(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, CONSTRAINT_BUS26M_ALLOW |
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT |
+ bus26m_ext_opand),
+ CONSTRAINT_BUS26M_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, MT_SPM_EX_OP_HW_S1_DETECT,
+ spm_bus26m_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_bus26m(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ ext_op |= (bus26m_ext_opand | MT_SPM_EX_OP_SET_WDT);
+ mt_spm_suspend_resume(state_id, ext_op, NULL);
+ bus26m_ext_opand = 0U;
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL);
+ status.enter_cnt++;
+ }
+
+ do_irqs_delivery();
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c
new file mode 100644
index 0000000..9618f3b
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+
+#define CONSTRAINT_CPU_BUCK_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
+
+#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 0U
+
+#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ \
+ (MT_SPM_DRAM_S1 | \
+ MT_SPM_DRAM_S0 | \
+ MT_SPM_SYSPLL | \
+ MT_SPM_INFRA | \
+ MT_SPM_26M | \
+ MT_SPM_XO_FPM)
+
+
+static unsigned int cpubuckldo_status = MT_SPM_RC_VALID_SW;
+static unsigned int cpubuckldo_enter_cnt;
+
+static void spm_cpu_bcuk_ldo_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_CPU_BUCK_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return IS_MT_RM_RC_READY(cpubuckldo_status);
+}
+
+unsigned int spm_allow_rc_cpu_buck_ldo(int state_id)
+{
+ (void)state_id;
+
+ return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF;
+}
+
+int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER,
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ MT_SPM_EX_OP_SET_WDT,
+ CONSTRAINT_CPU_BUCK_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, 0U,
+ spm_cpu_bcuk_ldo_conduct);
+ }
+
+ cpubuckldo_enter_cnt++;
+
+ return 0;
+}
+
+int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, 0U, NULL);
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c
new file mode 100644
index 0000000..34293c4
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <plat_mtk_lpm.h>
+
+#define CONSTRAINT_DRAM_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF)
+
+#define CONSTRAINT_DRAM_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
+
+#define CONSTRAINT_DRAM_PCM_FLAG1 0U
+
+#define CONSTRAINT_DRAM_RESOURCE_REQ \
+ (MT_SPM_SYSPLL | \
+ MT_SPM_INFRA | \
+ MT_SPM_26M)
+
+static struct mt_spm_cond_tables cond_dram = {
+ .name = "dram",
+ .table_cg = {
+ 0x078BF1FC, /* MTCMOS1 */
+ 0x080D8856, /* INFRA0 */
+ 0x03AF9A00, /* INFRA1 */
+ 0x86000640, /* INFRA2 */
+ 0xC800C000, /* INFRA3 */
+ 0x00000000, /* INFRA4 */
+ 0x00000000, /* INFRA5 */
+ 0x200C0000, /* MMSYS0 */
+ 0x00000000, /* MMSYS1 */
+ 0x00000000, /* MMSYS2 */
+ },
+ .table_pll = 0U,
+};
+
+static struct mt_spm_cond_tables cond_dram_res = {
+ .table_cg = { 0U },
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_DRAM,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH |
+ MT_SPM_RC_VALID_XSOC_BBLPM),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_dram_res,
+};
+
+static void spm_dram_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_DRAM_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_dram(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
+}
+
+int spm_update_rc_dram(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_dram;
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ &cond_dram_res : NULL);
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_dram(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_DRAM_ALLOW;
+}
+
+int spm_run_rc_dram(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_DRAM_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows |
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#else
+ (void)allows;
+#endif
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT),
+ CONSTRAINT_DRAM_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_dram(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_DRAM_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
+#else
+ (void)allows;
+#endif
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT),
+ NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL);
+ status.enter_cnt++;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h
new file mode 100644
index 0000000..aeb778a
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_RC_INTERNAL_H
+#define MT_SPM_RC_INTERNAL_H
+
+#include <stdbool.h>
+
+#define SPM_FLAG_SRAM_SLEEP_CTRL \
+ (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_SYSRAM_SLEEP | \
+ SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_SRAM_EVENT)
+
+/* cpu buck/ldo constraint function */
+bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+unsigned int spm_allow_rc_cpu_buck_ldo(int state_id);
+int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+
+/* spm resource dram constraint function */
+bool spm_is_valid_rc_dram(unsigned int cpu, int state_id);
+int spm_update_rc_dram(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_dram(int state_id);
+int spm_run_rc_dram(unsigned int cpu, int state_id);
+int spm_reset_rc_dram(unsigned int cpu, int state_id);
+
+/* spm resource syspll constraint function */
+bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id);
+int spm_update_rc_syspll(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_syspll(int state_id);
+int spm_run_rc_syspll(unsigned int cpu, int state_id);
+int spm_reset_rc_syspll(unsigned int cpu, int state_id);
+
+/* spm resource bus26m constraint function */
+bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id);
+int spm_update_rc_bus26m(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_bus26m(int state_id);
+int spm_run_rc_bus26m(unsigned int cpu, int state_id);
+int spm_reset_rc_bus26m(unsigned int cpu, int state_id);
+#endif /* MT_SPM_RC_INTERNAL_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c
new file mode 100644
index 0000000..8d76d63
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <plat_mtk_lpm.h>
+
+#define CONSTRAINT_SYSPLL_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_VCORE_LP)
+
+#define CONSTRAINT_SYSPLL_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
+ SPM_FLAG_ENABLE_6315_CTRL | \
+ SPM_FLAG_USE_SRCCLKENO2)
+
+#define CONSTRAINT_SYSPLL_PCM_FLAG1 0U
+#define CONSTRAINT_SYSPLL_RESOURCE_REQ \
+ (MT_SPM_26M)
+
+static struct mt_spm_cond_tables cond_syspll = {
+ .name = "syspll",
+ .table_cg = {
+ 0x078BF1FC, /* MTCMOS1 */
+ 0x080D8856, /* INFRA0 */
+ 0x03AF9A00, /* INFRA1 */
+ 0x86000640, /* INFRA2 */
+ 0xC800C000, /* INFRA3 */
+ 0x00000000, /* INFRA4 */
+ 0x0000007C, /* INFRA5 */
+ 0x280E0800, /* MMSYS0 */
+ 0x00000001, /* MMSYS1 */
+ 0x00000000, /* MMSYS2 */
+ },
+ .table_pll = 0U,
+};
+
+static struct mt_spm_cond_tables cond_syspll_res = {
+ .table_cg = { 0U },
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_SYSPLL,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH |
+ MT_SPM_RC_VALID_XSOC_BBLPM),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_syspll_res,
+};
+
+static void spm_syspll_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
+}
+
+int spm_update_rc_syspll(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll;
+
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ &cond_syspll_res : NULL);
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_syspll(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_SYSPLL_ALLOW;
+}
+
+int spm_run_rc_syspll(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows |
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#else
+ (void)allows;
+#endif
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT |
+ MT_SPM_EX_OP_SET_SUSPEND_MODE),
+ CONSTRAINT_SYSPLL_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_syspll(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
+#else
+ (void)allows;
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id,
+ (MT_SPM_EX_OP_SET_SUSPEND_MODE |
+ MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT),
+ NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL);
+ status.enter_cnt++;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm.c b/plat/mediatek/mt8192/drivers/spm/mt_spm.c
new file mode 100644
index 0000000..f4505b6
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <mtk_plat_common.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+#include <sleep_def.h>
+
+#ifdef MT_SPM_USING_BAKERY_LOCK
+DEFINE_BAKERY_LOCK(spm_lock);
+#define plat_spm_lock_init() bakery_lock_init(&spm_lock)
+#else
+spinlock_t spm_lock;
+#define plat_spm_lock_init()
+#endif
+
+/* CLK_SCP_CFG_0 */
+#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x200)
+#define SPM_CK_CONTROL_EN 0x3FF
+
+/* CLK_SCP_CFG_1 */
+#define CLK_SCP_CFG_1 (TOPCKGEN_BASE + 0x210)
+#define CLK_SCP_CFG_1_MASK 0x100C
+#define CLK_SCP_CFG_1_SPM 0x3
+
+struct mt_resource_constraint plat_constraint_bus26m = {
+ .is_valid = spm_is_valid_rc_bus26m,
+ .update = spm_update_rc_bus26m,
+ .allow = spm_allow_rc_bus26m,
+ .run = spm_run_rc_bus26m,
+ .reset = spm_reset_rc_bus26m,
+};
+
+struct mt_resource_constraint plat_constraint_syspll = {
+ .is_valid = spm_is_valid_rc_syspll,
+ .update = spm_update_rc_syspll,
+ .allow = spm_allow_rc_syspll,
+ .run = spm_run_rc_syspll,
+ .reset = spm_reset_rc_syspll,
+};
+
+struct mt_resource_constraint plat_constraint_dram = {
+ .is_valid = spm_is_valid_rc_dram,
+ .update = spm_update_rc_dram,
+ .allow = spm_allow_rc_dram,
+ .run = spm_run_rc_dram,
+ .reset = spm_reset_rc_dram,
+};
+
+struct mt_resource_constraint plat_constraint_cpu = {
+ .is_valid = spm_is_valid_rc_cpu_buck_ldo,
+ .update = NULL,
+ .allow = spm_allow_rc_cpu_buck_ldo,
+ .run = spm_run_rc_cpu_buck_ldo,
+ .reset = spm_reset_rc_cpu_buck_ldo,
+};
+
+struct mt_resource_constraint *plat_constraints[] = {
+ &plat_constraint_bus26m,
+ &plat_constraint_syspll,
+ &plat_constraint_dram,
+ &plat_constraint_cpu,
+ NULL,
+};
+
+struct mt_resource_manager plat_mt8192_rm = {
+ .update = mt_spm_cond_update,
+ .consts = plat_constraints,
+};
+
+void spm_boot_init(void)
+{
+ /* switch ck_off/axi_26m control to SPM */
+ mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_CONTROL_EN);
+ mmio_clrsetbits_32(CLK_SCP_CFG_1, CLK_SCP_CFG_1_MASK,
+ CLK_SCP_CFG_1_SPM);
+
+ plat_spm_lock_init();
+ mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
+ mt_lp_rm_register(&plat_mt8192_rm);
+ mt_spm_idle_generic_init();
+ mt_spm_suspend_init();
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm.h b/plat/mediatek/mt8192/drivers/spm/mt_spm.h
new file mode 100644
index 0000000..b147fe2
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_H
+#define MT_SPM_H
+
+#include <lib/bakery_lock.h>
+#include <lib/spinlock.h>
+
+#include <plat_mtk_lpm.h>
+
+/*
+ * ARM v8.2, the cache will turn off automatically when cpu
+ * power down. So, there is no doubt to use the spin_lock here
+ */
+#if !HW_ASSISTED_COHERENCY
+#define MT_SPM_USING_BAKERY_LOCK
+#endif
+
+#ifdef MT_SPM_USING_BAKERY_LOCK
+DECLARE_BAKERY_LOCK(spm_lock);
+#define plat_spm_lock() bakery_lock_get(&spm_lock)
+#define plat_spm_unlock() bakery_lock_release(&spm_lock)
+#else
+extern spinlock_t spm_lock;
+#define plat_spm_lock() spin_lock(&spm_lock)
+#define plat_spm_unlock() spin_unlock(&spm_lock)
+#endif
+
+#define MT_SPM_USING_SRCLKEN_RC
+
+/* spm extern operand definition */
+#define MT_SPM_EX_OP_CLR_26M_RECORD (1U << 0)
+#define MT_SPM_EX_OP_SET_WDT (1U << 1)
+#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ (1U << 2)
+#define MT_SPM_EX_OP_SET_SUSPEND_MODE (1U << 3)
+#define MT_SPM_EX_OP_SET_IS_ADSP (1U << 4)
+#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM (1U << 5)
+#define MT_SPM_EX_OP_HW_S1_DETECT (1U << 6)
+
+typedef enum {
+ WR_NONE = 0,
+ WR_UART_BUSY = 1,
+ WR_ABORT = 2,
+ WR_PCM_TIMER = 3,
+ WR_WAKE_SRC = 4,
+ WR_DVFSRC = 5,
+ WR_TWAM = 6,
+ WR_PMSR = 7,
+ WR_SPM_ACK_CHK = 8,
+ WR_UNKNOWN = 9,
+} wake_reason_t;
+
+static inline void spm_lock_get(void)
+{
+ plat_spm_lock();
+}
+
+static inline void spm_lock_release(void)
+{
+ plat_spm_unlock();
+}
+
+extern void spm_boot_init(void);
+#endif /* MT_SPM_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c
new file mode 100644
index 0000000..2d67fdf
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+#define MT_LP_TZ_INFRA_REG(ofs) (INFRACFG_AO_BASE + ofs)
+#define MT_LP_TZ_MM_REG(ofs) (MMSYS_BASE + ofs)
+#define MT_LP_TZ_SPM_REG(ofs) (SPM_BASE + ofs)
+#define MT_LP_TZ_TOPCK_REG(ofs) (TOPCKGEN_BASE + ofs)
+#define MT_LP_TZ_APMIXEDSYS(ofs) (APMIXEDSYS + ofs)
+
+#define SPM_PWR_STATUS MT_LP_TZ_SPM_REG(0x016C)
+#define SPM_PWR_STATUS_2ND MT_LP_TZ_SPM_REG(0x0170)
+#define INFRA_SW_CG0 MT_LP_TZ_INFRA_REG(0x0094)
+#define INFRA_SW_CG1 MT_LP_TZ_INFRA_REG(0x0090)
+#define INFRA_SW_CG2 MT_LP_TZ_INFRA_REG(0x00AC)
+#define INFRA_SW_CG3 MT_LP_TZ_INFRA_REG(0x00C8)
+#define INFRA_SW_CG4 MT_LP_TZ_INFRA_REG(0x00D8)
+#define INFRA_SW_CG5 MT_LP_TZ_INFRA_REG(0x00E8)
+#define MMSYS_CG_CON0 MT_LP_TZ_MM_REG(0x100)
+#define MMSYS_CG_CON1 MT_LP_TZ_MM_REG(0x110)
+#define MMSYS_CG_CON2 MT_LP_TZ_MM_REG(0x1A0)
+
+/***********************************************************
+ * Check clkmux registers
+ ***********************************************************/
+#define CLK_CFG(id) MT_LP_TZ_TOPCK_REG(0x20 + id * 0x10)
+#define PDN_CHECK BIT(7)
+#define CLK_CHECK BIT(31)
+
+enum {
+ CLKMUX_DISP = 0,
+ CLKMUX_MDP = 1,
+ CLKMUX_IMG1 = 2,
+ CLKMUX_IMG2 = 3,
+ NF_CLKMUX,
+};
+
+static bool is_clkmux_pdn(unsigned int clkmux_id)
+{
+ unsigned int reg, val, idx;
+
+ if ((clkmux_id & CLK_CHECK) != 0U) {
+ clkmux_id = (clkmux_id & ~CLK_CHECK);
+ reg = clkmux_id / 4U;
+ val = mmio_read_32(CLK_CFG(reg));
+ idx = clkmux_id % 4U;
+ val = (val >> (idx * 8U)) & PDN_CHECK;
+ return (val != 0U);
+ }
+
+ return false;
+}
+
+static struct mt_spm_cond_tables spm_cond_t;
+
+struct idle_cond_info {
+ unsigned int subsys_mask;
+ uintptr_t addr;
+ bool bBitflip;
+ unsigned int clkmux_id;
+};
+
+#define IDLE_CG(mask, addr, bitflip, clkmux) \
+ {mask, (uintptr_t)addr, bitflip, clkmux}
+
+static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = {
+ IDLE_CG(0xffffffff, SPM_PWR_STATUS, false, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG0, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG1, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG2, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG3, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG4, true, 0U),
+ IDLE_CG(0x00000200, INFRA_SW_CG5, true, 0U),
+ IDLE_CG(0x00100000, MMSYS_CG_CON0, true, (CLK_CHECK | CLKMUX_DISP)),
+ IDLE_CG(0x00100000, MMSYS_CG_CON1, true, (CLK_CHECK | CLKMUX_DISP)),
+ IDLE_CG(0x00100000, MMSYS_CG_CON2, true, (CLK_CHECK | CLKMUX_DISP)),
+};
+
+/***********************************************************
+ * Check pll idle condition
+ ***********************************************************/
+#define PLL_MFGPLL MT_LP_TZ_APMIXEDSYS(0x268)
+#define PLL_MMPLL MT_LP_TZ_APMIXEDSYS(0x360)
+#define PLL_UNIVPLL MT_LP_TZ_APMIXEDSYS(0x308)
+#define PLL_MSDCPLL MT_LP_TZ_APMIXEDSYS(0x350)
+#define PLL_TVDPLL MT_LP_TZ_APMIXEDSYS(0x380)
+
+unsigned int mt_spm_cond_check(int state_id,
+ const struct mt_spm_cond_tables *src,
+ const struct mt_spm_cond_tables *dest,
+ struct mt_spm_cond_tables *res)
+{
+ unsigned int blocked = 0U, i;
+ bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id);
+
+ if ((src == NULL) || (dest == NULL)) {
+ return SPM_COND_CHECK_FAIL;
+ }
+
+ for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
+ if (res != NULL) {
+ res->table_cg[i] =
+ (src->table_cg[i] & dest->table_cg[i]);
+
+ if (is_system_suspend && (res->table_cg[i] != 0U)) {
+ INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n",
+ dest->name, i, idle_cg_info[i].addr,
+ res->table_cg[i]);
+ }
+
+ if (res->table_cg[i] != 0U) {
+ blocked |= (1U << i);
+ }
+ } else if ((src->table_cg[i] & dest->table_cg[i]) != 0U) {
+ blocked |= (1U << i);
+ break;
+ }
+ }
+
+ if (res != NULL) {
+ res->table_pll = (src->table_pll & dest->table_pll);
+
+ if (res->table_pll != 0U) {
+ blocked |=
+ (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) |
+ SPM_COND_CHECK_BLOCKED_PLL;
+ }
+ } else if ((src->table_pll & dest->table_pll) != 0U) {
+ blocked |= SPM_COND_CHECK_BLOCKED_PLL;
+ }
+
+ if (is_system_suspend && (blocked != 0U)) {
+ INFO("suspend: %s total blocked = 0x%08x\n",
+ dest->name, blocked);
+ }
+
+ return blocked;
+}
+
+#define IS_MT_SPM_PWR_OFF(mask) \
+ (((mmio_read_32(SPM_PWR_STATUS) & mask) == 0U) && \
+ ((mmio_read_32(SPM_PWR_STATUS_2ND) & mask) == 0U))
+
+int mt_spm_cond_update(struct mt_resource_constraint **con,
+ int stateid, void *priv)
+{
+ int res;
+ uint32_t i;
+ struct mt_resource_constraint *const *rc;
+
+ /* read all cg state */
+ for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
+ spm_cond_t.table_cg[i] = 0U;
+
+ /* check mtcmos, if off set idle_value and clk to 0 disable */
+ if (IS_MT_SPM_PWR_OFF(idle_cg_info[i].subsys_mask)) {
+ continue;
+ }
+
+ /* check clkmux */
+ if (is_clkmux_pdn(idle_cg_info[i].clkmux_id)) {
+ continue;
+ }
+
+ spm_cond_t.table_cg[i] = idle_cg_info[i].bBitflip ?
+ ~mmio_read_32(idle_cg_info[i].addr) :
+ mmio_read_32(idle_cg_info[i].addr);
+ }
+
+ spm_cond_t.table_pll = 0U;
+ if ((mmio_read_32(PLL_MFGPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MFGPLL;
+ }
+
+ if ((mmio_read_32(PLL_MMPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MMPLL;
+ }
+
+ if ((mmio_read_32(PLL_UNIVPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_UNIVPLL;
+ }
+
+ if ((mmio_read_32(PLL_MSDCPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MSDCPLL;
+ }
+
+ if ((mmio_read_32(PLL_TVDPLL) & 0x1) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_TVDPLL;
+ }
+
+ spm_cond_t.priv = priv;
+ for (rc = con; *rc != NULL; rc++) {
+ if (((*rc)->update) == NULL) {
+ continue;
+ }
+
+ res = (*rc)->update(stateid, PLAT_RC_UPDATE_CONDITION,
+ (void const *)&spm_cond_t);
+ if (res != MT_RM_STATUS_OK) {
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h
new file mode 100644
index 0000000..91ebdd9
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONDIT_H
+#define MT_SPM_CONDIT_H
+
+#include <mt_lp_rm.h>
+
+enum PLAT_SPM_COND {
+ PLAT_SPM_COND_MTCMOS1 = 0,
+ PLAT_SPM_COND_CG_INFRA_0,
+ PLAT_SPM_COND_CG_INFRA_1,
+ PLAT_SPM_COND_CG_INFRA_2,
+ PLAT_SPM_COND_CG_INFRA_3,
+ PLAT_SPM_COND_CG_INFRA_4,
+ PLAT_SPM_COND_CG_INFRA_5,
+ PLAT_SPM_COND_CG_MMSYS_0,
+ PLAT_SPM_COND_CG_MMSYS_1,
+ PLAT_SPM_COND_CG_MMSYS_2,
+ PLAT_SPM_COND_MAX,
+};
+
+#define PLL_BIT_UNIVPLL BIT(0)
+#define PLL_BIT_MFGPLL BIT(1)
+#define PLL_BIT_MSDCPLL BIT(2)
+#define PLL_BIT_TVDPLL BIT(3)
+#define PLL_BIT_MMPLL BIT(4)
+
+/* Definition about SPM_COND_CHECK_BLOCKED
+ * bit [00 ~ 15]: cg blocking index
+ * bit [16 ~ 29]: pll blocking index
+ * bit [30] : pll blocking information
+ * bit [31] : idle condition check fail
+ */
+#define SPM_COND_BLOCKED_CG_IDX U(0)
+#define SPM_COND_BLOCKED_PLL_IDX U(16)
+#define SPM_COND_CHECK_BLOCKED_PLL BIT(30)
+#define SPM_COND_CHECK_FAIL BIT(31)
+
+struct mt_spm_cond_tables {
+ char *name;
+ unsigned int table_cg[PLAT_SPM_COND_MAX];
+ unsigned int table_pll;
+ void *priv;
+};
+
+extern unsigned int mt_spm_cond_check(int state_id,
+ const struct mt_spm_cond_tables *src,
+ const struct mt_spm_cond_tables *dest,
+ struct mt_spm_cond_tables *res);
+extern int mt_spm_cond_update(struct mt_resource_constraint **con,
+ int stateid, void *priv);
+#endif /* MT_SPM_CONDIT_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c
new file mode 100644
index 0000000..f9e6654
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_vcorefs.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+struct wake_status spm_wakesta; /* record last wakesta */
+
+static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ unsigned int resource_req)
+{
+ int ret = 0;
+ struct pwr_ctrl *pwrctrl;
+ uint32_t cpu = plat_my_core_pos();
+
+ pwrctrl = spm_lp->pwrctrl;
+
+ __spm_set_cpu_status(cpu);
+ __spm_set_power_control(pwrctrl);
+ __spm_set_wakeup_event(pwrctrl);
+ __spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl);
+ __spm_set_pcm_flags(pwrctrl);
+ __spm_src_req_update(pwrctrl, resource_req);
+
+ if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
+ __spm_set_pcm_wdt(1);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
+ __spm_xo_soc_bblpm(1);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
+ spm_hw_s1_state_monitor_resume();
+ }
+
+ /* Disable auto resume by PCM in system suspend stage */
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ __spm_disable_pcm_timer();
+ __spm_set_pcm_wdt(0);
+ }
+
+ __spm_send_cpu_wakeup_event();
+
+ INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n",
+ cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE),
+ mmio_read_32(PCM_TIMER_VAL) / 32768);
+ INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n",
+ pwrctrl->pcm_flags, pwrctrl->pcm_flags1,
+ mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS),
+ mmio_read_32(PWR_STATUS_2ND));
+
+ return ret;
+}
+
+static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status)
+{
+ unsigned int ext_status = 0U;
+
+ /* system watchdog will be resumed at kernel stage */
+ if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
+ __spm_set_pcm_wdt(0);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
+ __spm_xo_soc_bblpm(0);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
+ spm_hw_s1_state_monitor_pause(&ext_status);
+ }
+
+ __spm_ext_int_wakeup_req_clr();
+ __spm_get_wakeup_status(&spm_wakesta, ext_status);
+
+ if (status != NULL) {
+ *status = &spm_wakesta;
+ }
+
+ __spm_clean_after_wakeup();
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ __spm_output_wake_reason(state_id, &spm_wakesta);
+ }
+}
+
+int spm_conservation(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp, unsigned int resource_req)
+{
+ if (spm_lp == NULL) {
+ return -1;
+ }
+
+ spm_lock_get();
+ go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req);
+ spm_lock_release();
+
+ return 0;
+}
+
+void spm_conservation_finish(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status)
+{
+ spm_lock_get();
+ go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
+ spm_lock_release();
+}
+
+int spm_conservation_get_result(struct wake_status **res)
+{
+ if (res == NULL) {
+ return -1;
+ }
+
+ *res = &spm_wakesta;
+
+ return 0;
+}
+
+#define GPIO_BANK (GPIO_BASE + 0x6F0)
+#define TRAP_UFS_FIRST BIT(11) /* bit 11, 0: UFS, 1: eMMC */
+
+void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl)
+{
+ if (pwrctrl == NULL) {
+ return;
+ }
+
+ /* For ufs, emmc storage type */
+ if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) {
+ /* If eMMC is used, mask UFS req */
+ pwrctrl->reg_ufs_srcclkena_mask_b = 0;
+ pwrctrl->reg_ufs_infra_req_mask_b = 0;
+ pwrctrl->reg_ufs_apsrc_req_mask_b = 0;
+ pwrctrl->reg_ufs_vrf18_req_mask_b = 0;
+ pwrctrl->reg_ufs_ddr_en_mask_b = 0;
+ }
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h
new file mode 100644
index 0000000..c5e97db
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONSERVATION_H
+#define MT_SPM_CONSERVATION_H
+
+#include <mt_spm_internal.h>
+
+extern int spm_conservation(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ unsigned int resource_req);
+extern void spm_conservation_finish(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status);
+extern int spm_conservation_get_result(struct wake_status **res);
+extern void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl);
+#endif /* MT_SPM_CONSERVATION_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h
new file mode 100644
index 0000000..a3409f7
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONSTRAINT_H
+#define MT_SPM_CONSTRAINT_H
+
+#include <mt_lp_rm.h>
+
+#define MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF (1U << 0)
+#define MT_RM_CONSTRAINT_ALLOW_DRAM_S0 (1U << 1)
+#define MT_RM_CONSTRAINT_ALLOW_DRAM_S1 (1U << 2)
+#define MT_RM_CONSTRAINT_ALLOW_VCORE_LP (1U << 3)
+#define MT_RM_CONSTRAINT_ALLOW_INFRA_PDN (1U << 4)
+#define MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF (1U << 5)
+#define MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND (1U << 6)
+#define MT_RM_CONSTRAINT_ALLOW_BBLPM (1U << 7)
+#define MT_RM_CONSTRAINT_ALLOW_XO_UFS (1U << 8)
+#define MT_RM_CONSTRAINT_ALLOW_GPS_STATE (1U << 9)
+#define MT_RM_CONSTRAINT_ALLOW_LVTS_STATE (1U << 10)
+
+#define MT_SPM_RC_INVALID 0x0
+#define MT_SPM_RC_VALID_SW (1U << 0)
+#define MT_SPM_RC_VALID_FW (1U << 1)
+#define MT_SPM_RC_VALID_RESIDNECY (1U << 2)
+#define MT_SPM_RC_VALID_COND_CHECK (1U << 3)
+#define MT_SPM_RC_VALID_COND_LATCH (1U << 4)
+#define MT_SPM_RC_VALID_UFS_H8 (1U << 5)
+#define MT_SPM_RC_VALID_FLIGHTMODE (1U << 6)
+#define MT_SPM_RC_VALID_XSOC_BBLPM (1U << 7)
+#define MT_SPM_RC_VALID_TRACE_EVENT (1U << 8)
+
+#define MT_SPM_RC_VALID (MT_SPM_RC_VALID_SW)
+
+#define IS_MT_RM_RC_READY(status) \
+ ((status & MT_SPM_RC_VALID) == MT_SPM_RC_VALID)
+
+#define MT_SPM_RC_BBLPM_MODE \
+ (MT_SPM_RC_VALID_UFS_H8 | \
+ MT_SPM_RC_VALID_FLIGHTMODE | \
+ MT_SPM_RC_VALID_XSOC_BBLPM)
+
+#define IS_MT_SPM_RC_BBLPM_MODE(st) \
+ ((st & (MT_SPM_RC_BBLPM_MODE)) == MT_SPM_RC_BBLPM_MODE)
+
+struct constraint_status {
+ uint16_t id;
+ uint16_t valid;
+ uint32_t cond_block;
+ uint32_t enter_cnt;
+ struct mt_spm_cond_tables *cond_res;
+};
+
+enum MT_SPM_RM_RC_TYPE {
+ MT_RM_CONSTRAINT_ID_BUS26M,
+ MT_RM_CONSTRAINT_ID_SYSPLL,
+ MT_RM_CONSTRAINT_ID_DRAM,
+ MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO,
+ MT_RM_CONSTRAINT_ID_ALL,
+};
+#endif /* MT_SPM_CONSTRAINT_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c
new file mode 100644
index 0000000..3540ec2
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <plat_pm.h>
+
+#define __WAKE_SRC_FOR_IDLE_COMMON__ \
+ (R12_PCM_TIMER | \
+ R12_KP_IRQ_B | \
+ R12_APWDT_EVENT_B | \
+ R12_APXGPT1_EVENT_B | \
+ R12_CONN2AP_SPM_WAKEUP_B | \
+ R12_EINT_EVENT_B | \
+ R12_CONN_WDT_IRQ_B | \
+ R12_CCIF0_EVENT_B | \
+ R12_SSPM2SPM_WAKEUP_B | \
+ R12_SCP2SPM_WAKEUP_B | \
+ R12_ADSP2SPM_WAKEUP_B | \
+ R12_USBX_CDSC_B | \
+ R12_USBX_POWERDWN_B | \
+ R12_SYS_TIMER_EVENT_B | \
+ R12_EINT_EVENT_SECURE_B | \
+ R12_CCIF1_EVENT_B | \
+ R12_AFE_IRQ_MCU_B | \
+ R12_SYS_CIRQ_IRQ_B | \
+ R12_MD2AP_PEER_EVENT_B | \
+ R12_MD1_WDT_B | \
+ R12_CLDMA_EVENT_B | \
+ R12_REG_CPU_WAKEUP | \
+ R12_APUSYS_WAKE_HOST_B | \
+ R12_PCIE_BRIDGE_IRQ | \
+ R12_PCIE_IRQ)
+
+#if defined(CFG_MICROTRUST_TEE_SUPPORT)
+#define WAKE_SRC_FOR_IDLE (__WAKE_SRC_FOR_IDLE_COMMON__)
+#else
+#define WAKE_SRC_FOR_IDLE \
+ (__WAKE_SRC_FOR_IDLE_COMMON__ | \
+ R12_SEJ_EVENT_B)
+#endif
+
+static struct pwr_ctrl idle_spm_pwr = {
+ .timer_val = 0x28000,
+ .wake_src = WAKE_SRC_FOR_IDLE,
+
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ .reg_wfi_op = 0,
+ .reg_wfi_type = 0,
+ .reg_mp0_cputop_idle_mask = 0,
+ .reg_mp1_cputop_idle_mask = 0,
+ .reg_mcusys_idle_mask = 0,
+ .reg_md_apsrc_1_sel = 0,
+ .reg_md_apsrc_0_sel = 0,
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC6_MASK */
+ .reg_dpmaif_srcclkena_mask_b = 1,
+ .reg_dpmaif_infra_req_mask_b = 1,
+ .reg_dpmaif_apsrc_req_mask_b = 1,
+ .reg_dpmaif_vrf18_req_mask_b = 1,
+ .reg_dpmaif_ddr_en_mask_b = 1,
+
+ /* SPM_SRC_REQ */
+ .reg_spm_apsrc_req = 1,
+ .reg_spm_f26m_req = 1,
+ .reg_spm_infra_req = 1,
+ .reg_spm_vrf18_req = 1,
+ .reg_spm_ddr_en_req = 1,
+ .reg_spm_dvfs_req = 0,
+ .reg_spm_sw_mailbox_req = 0,
+ .reg_spm_sspm_mailbox_req = 0,
+ .reg_spm_adsp_mailbox_req = 0,
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC_MASK */
+ .reg_md_srcclkena_0_mask_b = 1,
+ .reg_md_srcclkena2infra_req_0_mask_b = 0,
+ .reg_md_apsrc2infra_req_0_mask_b = 1,
+ .reg_md_apsrc_req_0_mask_b = 1,
+ .reg_md_vrf18_req_0_mask_b = 1,
+ .reg_md_ddr_en_0_mask_b = 1,
+ .reg_md_srcclkena_1_mask_b = 0,
+ .reg_md_srcclkena2infra_req_1_mask_b = 0,
+ .reg_md_apsrc2infra_req_1_mask_b = 0,
+ .reg_md_apsrc_req_1_mask_b = 0,
+ .reg_md_vrf18_req_1_mask_b = 0,
+ .reg_md_ddr_en_1_mask_b = 0,
+ .reg_conn_srcclkena_mask_b = 1,
+ .reg_conn_srcclkenb_mask_b = 0,
+ .reg_conn_infra_req_mask_b = 1,
+ .reg_conn_apsrc_req_mask_b = 1,
+ .reg_conn_vrf18_req_mask_b = 1,
+ .reg_conn_ddr_en_mask_b = 1,
+ .reg_conn_vfe28_mask_b = 0,
+ .reg_srcclkeni0_srcclkena_mask_b = 1,
+ .reg_srcclkeni0_infra_req_mask_b = 1,
+ .reg_srcclkeni1_srcclkena_mask_b = 0,
+ .reg_srcclkeni1_infra_req_mask_b = 0,
+ .reg_srcclkeni2_srcclkena_mask_b = 0,
+ .reg_srcclkeni2_infra_req_mask_b = 0,
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ .reg_infrasys_ddr_en_mask_b = 1,
+ .reg_md32_srcclkena_mask_b = 1,
+ .reg_md32_infra_req_mask_b = 1,
+ .reg_md32_apsrc_req_mask_b = 1,
+ .reg_md32_vrf18_req_mask_b = 1,
+ .reg_md32_ddr_en_mask_b = 1,
+
+ /* SPM_SRC2_MASK */
+ .reg_scp_srcclkena_mask_b = 1,
+ .reg_scp_infra_req_mask_b = 1,
+ .reg_scp_apsrc_req_mask_b = 1,
+ .reg_scp_vrf18_req_mask_b = 1,
+ .reg_scp_ddr_en_mask_b = 1,
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ .reg_audio_dsp_ddr_en_mask_b = 1,
+ .reg_ufs_srcclkena_mask_b = 1,
+ .reg_ufs_infra_req_mask_b = 1,
+ .reg_ufs_apsrc_req_mask_b = 1,
+ .reg_ufs_vrf18_req_mask_b = 1,
+ .reg_ufs_ddr_en_mask_b = 1,
+ .reg_disp0_apsrc_req_mask_b = 1,
+ .reg_disp0_ddr_en_mask_b = 1,
+ .reg_disp1_apsrc_req_mask_b = 1,
+ .reg_disp1_ddr_en_mask_b = 1,
+ .reg_gce_infra_req_mask_b = 1,
+ .reg_gce_apsrc_req_mask_b = 1,
+ .reg_gce_vrf18_req_mask_b = 1,
+ .reg_gce_ddr_en_mask_b = 1,
+ .reg_apu_srcclkena_mask_b = 1,
+ .reg_apu_infra_req_mask_b = 1,
+ .reg_apu_apsrc_req_mask_b = 1,
+ .reg_apu_vrf18_req_mask_b = 1,
+ .reg_apu_ddr_en_mask_b = 1,
+ .reg_cg_check_srcclkena_mask_b = 0,
+ .reg_cg_check_apsrc_req_mask_b = 0,
+ .reg_cg_check_vrf18_req_mask_b = 0,
+ .reg_cg_check_ddr_en_mask_b = 0,
+
+ /* SPM_SRC3_MASK */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+ .reg_sw2spm_int0_mask_b = 0,
+ .reg_sw2spm_int1_mask_b = 0,
+ .reg_sw2spm_int2_mask_b = 0,
+ .reg_sw2spm_int3_mask_b = 0,
+ .reg_sc_adsp2spm_wakeup_mask_b = 0,
+ .reg_sc_sspm2spm_wakeup_mask_b = 0,
+ .reg_sc_scp2spm_wakeup_mask_b = 0,
+ .reg_csyspwrreq_mask = 1,
+ .reg_spm_srcclkena_reserved_mask_b = 0,
+ .reg_spm_infra_req_reserved_mask_b = 0,
+ .reg_spm_apsrc_req_reserved_mask_b = 0,
+ .reg_spm_vrf18_req_reserved_mask_b = 0,
+ .reg_spm_ddr_en_reserved_mask_b = 0,
+ .reg_mcupm_srcclkena_mask_b = 1,
+ .reg_mcupm_infra_req_mask_b = 1,
+ .reg_mcupm_apsrc_req_mask_b = 1,
+ .reg_mcupm_vrf18_req_mask_b = 1,
+ .reg_mcupm_ddr_en_mask_b = 1,
+ .reg_msdc0_srcclkena_mask_b = 1,
+ .reg_msdc0_infra_req_mask_b = 1,
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ .reg_msdc0_ddr_en_mask_b = 1,
+ .reg_msdc1_srcclkena_mask_b = 1,
+ .reg_msdc1_infra_req_mask_b = 1,
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ .reg_msdc1_ddr_en_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ .ccif_event_mask_b = 0xFFF,
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ .reg_bak_psri_infra_req_mask_b = 0,
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ .reg_bak_psri_ddr_en_mask_b = 0,
+ .reg_dramc0_md32_infra_req_mask_b = 1,
+ .reg_dramc0_md32_vrf18_req_mask_b = 0,
+ .reg_dramc1_md32_infra_req_mask_b = 1,
+ .reg_dramc1_md32_vrf18_req_mask_b = 0,
+ .reg_conn_srcclkenb2pwrap_mask_b = 0,
+ .reg_dramc0_md32_wakeup_mask = 1,
+ .reg_dramc1_md32_wakeup_mask = 1,
+
+ /* SPM_SRC5_MASK */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x11,
+ .reg_mcusys_merge_ddr_en_mask_b = 0x11,
+ .reg_msdc2_srcclkena_mask_b = 1,
+ .reg_msdc2_infra_req_mask_b = 1,
+ .reg_msdc2_apsrc_req_mask_b = 1,
+ .reg_msdc2_vrf18_req_mask_b = 1,
+ .reg_msdc2_ddr_en_mask_b = 1,
+ .reg_pcie_srcclkena_mask_b = 1,
+ .reg_pcie_infra_req_mask_b = 1,
+ .reg_pcie_apsrc_req_mask_b = 1,
+ .reg_pcie_vrf18_req_mask_b = 1,
+ .reg_pcie_ddr_en_mask_b = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ .reg_wakeup_event_mask = 0x01282202,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+
+ /* Auto-gen End */
+};
+
+struct spm_lp_scen idle_spm_lp = {
+ .pwrctrl = &idle_spm_pwr,
+};
+
+int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand,
+ spm_idle_conduct fn)
+{
+ unsigned int src_req = 0;
+
+ if (fn != NULL) {
+ fn(&idle_spm_lp, &src_req);
+ }
+
+ return spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req);
+}
+void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status)
+{
+ spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status);
+}
+
+void mt_spm_idle_generic_init(void)
+{
+ spm_conservation_pwrctrl_init(idle_spm_lp.pwrctrl);
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h
new file mode 100644
index 0000000..3d42cf1
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_IDLE_H
+#define MT_SPM_IDLE_H
+
+typedef void (*spm_idle_conduct)(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req);
+int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand,
+ spm_idle_conduct fn);
+void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status);
+void mt_spm_idle_generic_init(void);
+#endif /* MT_SPM_IDLE_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c
new file mode 100644
index 0000000..40be027
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <platform_def.h>
+#include <plat_pm.h>
+
+/**************************************
+ * Define and Declare
+ **************************************/
+#define ROOT_CORE_ADDR_OFFSET 0x20000000
+#define SPM_WAKEUP_EVENT_MASK_CLEAN_MASK 0xefffffff
+#define SPM_INIT_DONE_US 20
+
+static unsigned int mt_spm_bblpm_cnt;
+
+const char *wakeup_src_str[32] = {
+ [0] = "R12_PCM_TIMER",
+ [1] = "R12_RESERVED_DEBUG_B",
+ [2] = "R12_KP_IRQ_B",
+ [3] = "R12_APWDT_EVENT_B",
+ [4] = "R12_APXGPT1_EVENT_B",
+ [5] = "R12_CONN2AP_SPM_WAKEUP_B",
+ [6] = "R12_EINT_EVENT_B",
+ [7] = "R12_CONN_WDT_IRQ_B",
+ [8] = "R12_CCIF0_EVENT_B",
+ [9] = "R12_LOWBATTERY_IRQ_B",
+ [10] = "R12_SC_SSPM2SPM_WAKEUP_B",
+ [11] = "R12_SC_SCP2SPM_WAKEUP_B",
+ [12] = "R12_SC_ADSP2SPM_WAKEUP_B",
+ [13] = "R12_PCM_WDT_WAKEUP_B",
+ [14] = "R12_USB_CDSC_B",
+ [15] = "R12_USB_POWERDWN_B",
+ [16] = "R12_SYS_TIMER_EVENT_B",
+ [17] = "R12_EINT_EVENT_SECURE_B",
+ [18] = "R12_CCIF1_EVENT_B",
+ [19] = "R12_UART0_IRQ_B",
+ [20] = "R12_AFE_IRQ_MCU_B",
+ [21] = "R12_THERM_CTRL_EVENT_B",
+ [22] = "R12_SYS_CIRQ_IRQ_B",
+ [23] = "R12_MD2AP_PEER_EVENT_B",
+ [24] = "R12_CSYSPWREQ_B",
+ [25] = "R12_MD1_WDT_B",
+ [26] = "R12_AP2AP_PEER_WAKEUPEVENT_B",
+ [27] = "R12_SEJ_EVENT_B",
+ [28] = "R12_SPM_CPU_WAKEUPEVENT_B",
+ [29] = "R12_APUSYS",
+ [30] = "R12_PCIE_BRIDGE_IRQ",
+ [31] = "R12_PCIE_IRQ",
+};
+
+/**************************************
+ * Function and API
+ **************************************/
+
+wake_reason_t __spm_output_wake_reason(int state_id,
+ const struct wake_status *wakesta)
+{
+ uint32_t i, bk_vtcxo_dur, spm_26m_off_pct = 0U;
+ wake_reason_t wr = WR_UNKNOWN;
+
+ if (wakesta == NULL) {
+ return WR_UNKNOWN;
+ }
+
+ if (wakesta->abort != 0U) {
+ ERROR("spmfw flow is aborted: 0x%x, timer_out = %u\n",
+ wakesta->abort, wakesta->timer_out);
+ } else {
+ for (i = 0U; i < 32U; i++) {
+ if ((wakesta->r12 & (1U << i)) != 0U) {
+ INFO("wake up by %s, timer_out = %u\n",
+ wakeup_src_str[i], wakesta->timer_out);
+ wr = WR_WAKE_SRC;
+ break;
+ }
+ }
+ }
+
+ INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n",
+ wakesta->r12, wakesta->r12_ext, wakesta->r13, wakesta->debug_flag,
+ wakesta->debug_flag1);
+ INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n",
+ wakesta->raw_sta, wakesta->md32pcm_wakeup_sta,
+ wakesta->md32pcm_event_sta, wakesta->idle_sta,
+ wakesta->cg_check_sta);
+ INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n",
+ wakesta->req_sta0, wakesta->req_sta1, wakesta->req_sta2,
+ wakesta->req_sta3, wakesta->req_sta4, wakesta->isr);
+ INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n",
+ wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2);
+ INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n",
+ wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta);
+ INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n",
+ wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1,
+ wakesta->b_sw_flag0, wakesta->b_sw_flag1, wakesta->src_req);
+ INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n",
+ wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L),
+ mmio_read_32(SYS_TIMER_VALUE_H));
+
+ if (wakesta->timer_out != 0U) {
+ bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR);
+ spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->timer_out;
+ INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct);
+ }
+
+ return wr;
+}
+
+void __spm_set_cpu_status(unsigned int cpu)
+{
+ uint32_t root_core_addr;
+
+ if (cpu < 8U) {
+ mmio_write_32(ROOT_CPUTOP_ADDR, (1U << cpu));
+ root_core_addr = SPM_CPU0_PWR_CON + (cpu * 0x4);
+ root_core_addr += ROOT_CORE_ADDR_OFFSET;
+ mmio_write_32(ROOT_CORE_ADDR, root_core_addr);
+ /* Notify MCUPM that preferred cpu wakeup */
+ mmio_write_32(MCUPM_MBOX_WAKEUP_CPU, cpu);
+ } else {
+ ERROR("%s: error cpu number %d\n", __func__, cpu);
+ }
+}
+
+void __spm_src_req_update(const struct pwr_ctrl *pwrctrl,
+ unsigned int resource_usage)
+{
+ uint8_t apsrc_req = ((resource_usage & MT_SPM_DRAM_S0) != 0U) ?
+ 1 : pwrctrl->reg_spm_apsrc_req;
+ uint8_t ddr_en_req = ((resource_usage & MT_SPM_DRAM_S1) != 0U) ?
+ 1 : pwrctrl->reg_spm_ddr_en_req;
+ uint8_t vrf18_req = ((resource_usage & MT_SPM_SYSPLL) != 0U) ?
+ 1 : pwrctrl->reg_spm_vrf18_req;
+ uint8_t infra_req = ((resource_usage & MT_SPM_INFRA) != 0U) ?
+ 1 : pwrctrl->reg_spm_infra_req;
+ uint8_t f26m_req = ((resource_usage &
+ (MT_SPM_26M | MT_SPM_XO_FPM)) != 0U) ?
+ 1 : pwrctrl->reg_spm_f26m_req;
+
+ mmio_write_32(SPM_SRC_REQ,
+ ((apsrc_req & 0x1) << 0) |
+ ((f26m_req & 0x1) << 1) |
+ ((infra_req & 0x1) << 3) |
+ ((vrf18_req & 0x1) << 4) |
+ ((ddr_en_req & 0x1) << 7) |
+ ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
+ ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
+ ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
+ ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
+ ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
+}
+
+void __spm_set_power_control(const struct pwr_ctrl *pwrctrl)
+{
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ mmio_write_32(SPM_AP_STANDBY_CON,
+ ((pwrctrl->reg_wfi_op & 0x1) << 0) |
+ ((pwrctrl->reg_wfi_type & 0x1) << 1) |
+ ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) |
+ ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) |
+ ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) |
+ ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) |
+ ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) |
+ ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29));
+
+ /* SPM_SRC6_MASK */
+ mmio_write_32(SPM_SRC6_MASK,
+ ((pwrctrl->reg_dpmaif_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_dpmaif_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_dpmaif_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_dpmaif_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_dpmaif_ddr_en_mask_b & 0x1) << 4));
+
+ /* SPM_SRC_REQ */
+ mmio_write_32(SPM_SRC_REQ,
+ ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) |
+ ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) |
+ ((pwrctrl->reg_spm_infra_req & 0x1) << 3) |
+ ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) |
+ ((pwrctrl->reg_spm_ddr_en_req & 0x1) << 7) |
+ ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
+ ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
+ ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
+ ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
+ ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
+
+ /* SPM_SRC_MASK */
+ mmio_write_32(SPM_SRC_MASK,
+ ((pwrctrl->reg_md_srcclkena_0_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_md_srcclkena2infra_req_0_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_md_apsrc2infra_req_0_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_md_apsrc_req_0_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_md_vrf18_req_0_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_md_ddr_en_0_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_md_srcclkena_1_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_md_srcclkena2infra_req_1_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_md_apsrc2infra_req_1_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_md_apsrc_req_1_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_md_vrf18_req_1_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_md_ddr_en_1_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_conn_srcclkena_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_conn_srcclkenb_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_conn_infra_req_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_conn_apsrc_req_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_conn_vrf18_req_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_conn_ddr_en_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_conn_vfe28_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_srcclkeni0_srcclkena_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_srcclkeni0_infra_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_srcclkeni1_srcclkena_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_srcclkeni1_infra_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_srcclkeni2_srcclkena_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_srcclkeni2_infra_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_infrasys_ddr_en_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_md32_srcclkena_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_md32_infra_req_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_md32_apsrc_req_mask_b & 0x1) << 29) |
+ ((pwrctrl->reg_md32_vrf18_req_mask_b & 0x1) << 30) |
+ ((pwrctrl->reg_md32_ddr_en_mask_b & 0x1) << 31));
+
+ /* SPM_SRC2_MASK */
+ mmio_write_32(SPM_SRC2_MASK,
+ ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_scp_ddr_en_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_audio_dsp_ddr_en_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_ufs_ddr_en_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_disp0_apsrc_req_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_disp1_ddr_en_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_gce_infra_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_gce_apsrc_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_gce_vrf18_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_gce_ddr_en_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_apu_ddr_en_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_cg_check_srcclkena_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_cg_check_apsrc_req_mask_b & 0x1) << 29) |
+ ((pwrctrl->reg_cg_check_vrf18_req_mask_b & 0x1) << 30) |
+ ((pwrctrl->reg_cg_check_ddr_en_mask_b & 0x1) << 31));
+
+ /* SPM_SRC3_MASK */
+ mmio_write_32(SPM_SRC3_MASK,
+ ((pwrctrl->reg_dvfsrc_event_trigger_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_sw2spm_int0_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_sw2spm_int1_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_sw2spm_int2_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_sw2spm_int3_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_sc_adsp2spm_wakeup_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_sc_sspm2spm_wakeup_mask_b & 0xf) << 6) |
+ ((pwrctrl->reg_sc_scp2spm_wakeup_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_csyspwrreq_mask & 0x1) << 11) |
+ ((pwrctrl->reg_spm_srcclkena_reserved_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_spm_infra_req_reserved_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_spm_apsrc_req_reserved_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_spm_vrf18_req_reserved_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_spm_ddr_en_reserved_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_mcupm_srcclkena_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_mcupm_infra_req_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_mcupm_apsrc_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_mcupm_vrf18_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_mcupm_ddr_en_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_msdc0_ddr_en_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 29) |
+ ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 30) |
+ ((pwrctrl->reg_msdc1_ddr_en_mask_b & 0x1) << 31));
+
+ /* SPM_SRC4_MASK */
+ mmio_write_32(SPM_SRC4_MASK,
+ ((pwrctrl->ccif_event_mask_b & 0xffff) << 0) |
+ ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_bak_psri_ddr_en_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_dramc0_md32_infra_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_dramc0_md32_vrf18_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_dramc1_md32_infra_req_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_dramc1_md32_vrf18_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_conn_srcclkenb2pwrap_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_dramc0_md32_wakeup_mask & 0x1) << 26) |
+ ((pwrctrl->reg_dramc1_md32_wakeup_mask & 0x1) << 27));
+
+ /* SPM_SRC5_MASK */
+ mmio_write_32(SPM_SRC5_MASK,
+ ((pwrctrl->reg_mcusys_merge_apsrc_req_mask_b & 0x1ff) << 0) |
+ ((pwrctrl->reg_mcusys_merge_ddr_en_mask_b & 0x1ff) << 9) |
+ ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_msdc2_ddr_en_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_pcie_srcclkena_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_pcie_infra_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_pcie_apsrc_req_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_pcie_vrf18_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_pcie_ddr_en_mask_b & 0x1) << 27));
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK,
+ ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0));
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK,
+ ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0));
+
+ /* Auto-gen End */
+}
+
+void __spm_disable_pcm_timer(void)
+{
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY);
+}
+
+void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
+{
+ uint32_t val, mask;
+
+ /* toggle event counter clear */
+ mmio_setbits_32(PCM_CON1,
+ SPM_REGWR_CFG_KEY | SPM_EVENT_COUNTER_CLR_LSB);
+
+ /* toggle for reset SYS TIMER start point */
+ mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
+
+ if (pwrctrl->timer_val_cust == 0U) {
+ val = pwrctrl->timer_val;
+ } else {
+ val = pwrctrl->timer_val_cust;
+ }
+
+ mmio_write_32(PCM_TIMER_VAL, val);
+ mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_TIMER_EN_LSB);
+
+ /* unmask AP wakeup source */
+ if (pwrctrl->wake_src_cust == 0U) {
+ mask = pwrctrl->wake_src;
+ } else {
+ mask = pwrctrl->wake_src_cust;
+ }
+
+ if (pwrctrl->reg_csyspwrreq_mask != 0U) {
+ mask &= ~R12_CSYSPWREQ_B;
+ }
+
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask);
+
+ /* unmask SPM ISR (keep TWAM setting) */
+ mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX);
+
+ /* toggle event counter clear */
+ mmio_clrsetbits_32(PCM_CON1, SPM_EVENT_COUNTER_CLR_LSB,
+ SPM_REGWR_CFG_KEY);
+ /* toggle for reset SYS TIMER start point */
+ mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
+}
+
+void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl)
+{
+ /* set PCM flags and data */
+ if (pwrctrl->pcm_flags_cust_clr != 0U) {
+ pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr;
+ }
+
+ if (pwrctrl->pcm_flags_cust_set != 0U) {
+ pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set;
+ }
+
+ if (pwrctrl->pcm_flags1_cust_clr != 0U) {
+ pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr;
+ }
+
+ if (pwrctrl->pcm_flags1_cust_set != 0U) {
+ pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set;
+ }
+
+ mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags);
+ mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1);
+ mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags);
+ mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1);
+}
+
+void __spm_get_wakeup_status(struct wake_status *wakesta,
+ unsigned int ext_status)
+{
+ wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT);
+ wakesta->tr.comm.timer_out = mmio_read_32(SPM_BK_PCM_TIMER);
+ wakesta->tr.comm.r13 = mmio_read_32(PCM_REG13_DATA);
+ wakesta->tr.comm.req_sta0 = mmio_read_32(SRC_REQ_STA_0);
+ wakesta->tr.comm.req_sta1 = mmio_read_32(SRC_REQ_STA_1);
+ wakesta->tr.comm.req_sta2 = mmio_read_32(SRC_REQ_STA_2);
+ wakesta->tr.comm.req_sta3 = mmio_read_32(SRC_REQ_STA_3);
+ wakesta->tr.comm.req_sta4 = mmio_read_32(SRC_REQ_STA_4);
+ wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0);
+ wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1);
+
+ if ((ext_status & SPM_INTERNAL_STATUS_HW_S1) != 0U) {
+ wakesta->tr.comm.debug_flag |= (SPM_DBG_DEBUG_IDX_DDREN_WAKE |
+ SPM_DBG_DEBUG_IDX_DDREN_SLEEP);
+ mmio_write_32(PCM_WDT_LATCH_SPARE_0,
+ wakesta->tr.comm.debug_flag);
+ }
+
+ wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7);
+ wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8);
+
+ /* record below spm info for debug */
+ wakesta->r12 = mmio_read_32(SPM_BK_WAKE_EVENT);
+ wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_STA);
+ wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA);
+ wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA);
+ wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA);
+ wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA);
+ wakesta->src_req = mmio_read_32(SPM_SRC_REQ);
+
+ /* backup of SPM_WAKEUP_MISC */
+ wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC);
+
+ /* get sleep time, backup of PCM_TIMER_OUT */
+ wakesta->timer_out = mmio_read_32(SPM_BK_PCM_TIMER);
+
+ /* get other SYS and co-clock status */
+ wakesta->r13 = mmio_read_32(PCM_REG13_DATA);
+ wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA);
+ wakesta->req_sta0 = mmio_read_32(SRC_REQ_STA_0);
+ wakesta->req_sta1 = mmio_read_32(SRC_REQ_STA_1);
+ wakesta->req_sta2 = mmio_read_32(SRC_REQ_STA_2);
+ wakesta->req_sta3 = mmio_read_32(SRC_REQ_STA_3);
+ wakesta->req_sta4 = mmio_read_32(SRC_REQ_STA_4);
+
+ /* get HW CG check status */
+ wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA);
+
+ /* get debug flag for PCM execution check */
+ wakesta->debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0);
+ wakesta->debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1);
+
+ /* get backup SW flag status */
+ wakesta->b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7);
+ wakesta->b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8);
+
+ wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2);
+ wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3);
+ wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4);
+ wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5);
+ wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6);
+
+ /* get ISR status */
+ wakesta->isr = mmio_read_32(SPM_IRQ_STA);
+
+ /* get SW flag status */
+ wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0);
+ wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1);
+
+ /* get CLK SETTLE */
+ wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE);
+
+ /* check abort */
+ wakesta->abort = (wakesta->debug_flag & DEBUG_ABORT_MASK) |
+ (wakesta->debug_flag1 & DEBUG_ABORT_MASK_1);
+}
+
+void __spm_clean_after_wakeup(void)
+{
+ mmio_write_32(SPM_BK_WAKE_EVENT,
+ mmio_read_32(SPM_WAKEUP_STA) |
+ mmio_read_32(SPM_BK_WAKE_EVENT));
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0);
+
+ /*
+ * clean wakeup event raw status (for edge trigger event)
+ * bit[28] for cpu wake up event
+ */
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, SPM_WAKEUP_EVENT_MASK_CLEAN_MASK);
+
+ /* clean ISR status (except TWAM) */
+ mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
+ mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM);
+ mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL);
+}
+
+void __spm_set_pcm_wdt(int en)
+{
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_EN_LSB,
+ SPM_REGWR_CFG_KEY);
+
+ if (en == 1) {
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_WAKE_LSB,
+ SPM_REGWR_CFG_KEY);
+
+ if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) {
+ mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX);
+ }
+
+ mmio_write_32(PCM_WDT_VAL,
+ mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
+ mmio_setbits_32(PCM_CON1,
+ SPM_REGWR_CFG_KEY | RG_PCM_WDT_EN_LSB);
+ }
+}
+
+void __spm_send_cpu_wakeup_event(void)
+{
+ /* SPM will clear SPM_CPU_WAKEUP_EVENT */
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1);
+}
+
+void __spm_ext_int_wakeup_req_clr(void)
+{
+ mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, mmio_read_32(ROOT_CPUTOP_ADDR));
+
+ /* Clear spm2mcupm wakeup interrupt status */
+ mmio_write_32(SPM2MCUPM_CON, 0);
+}
+
+void __spm_xo_soc_bblpm(int en)
+{
+ if (en == 1) {
+ mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG,
+ RC_SW_SRCLKEN_FPM, RC_SW_SRCLKEN_RC);
+ assert(mt_spm_bblpm_cnt == 0);
+ mt_spm_bblpm_cnt += 1;
+ } else {
+ mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG,
+ RC_SW_SRCLKEN_RC, RC_SW_SRCLKEN_FPM);
+ mt_spm_bblpm_cnt -= 1;
+ }
+}
+
+void __spm_hw_s1_state_monitor(int en, unsigned int *status)
+{
+ unsigned int reg;
+
+ reg = mmio_read_32(SPM_ACK_CHK_CON_3);
+
+ if (en == 1) {
+ reg &= ~SPM_ACK_CHK_3_CON_CLR_ALL;
+ mmio_write_32(SPM_ACK_CHK_CON_3, reg);
+ reg |= SPM_ACK_CHK_3_CON_EN;
+ mmio_write_32(SPM_ACK_CHK_CON_3, reg);
+ } else {
+ if (((reg & SPM_ACK_CHK_3_CON_RESULT) != 0U) &&
+ (status != NULL)) {
+ *status |= SPM_INTERNAL_STATUS_HW_S1;
+ }
+
+ mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN,
+ SPM_ACK_CHK_3_CON_HW_MODE_TRIG |
+ SPM_ACK_CHK_3_CON_CLR_ALL);
+ }
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h
new file mode 100644
index 0000000..1d0f783
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h
@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_INTERNAL_H
+#define MT_SPM_INTERNAL_H
+
+#include "mt_spm.h"
+
+/**************************************
+ * Config and Parameter
+ **************************************/
+#define POWER_ON_VAL0_DEF 0x0000F100
+#define POWER_ON_VAL1_DEF 0x80015860
+#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */
+#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT)
+
+/**************************************
+ * Define and Declare
+ **************************************/
+/* PCM_PWR_IO_EN */
+#define PCM_PWRIO_EN_R0 (1U << 0)
+#define PCM_PWRIO_EN_R7 (1U << 7)
+#define PCM_RF_SYNC_R0 (1U << 16)
+#define PCM_RF_SYNC_R6 (1U << 22)
+#define PCM_RF_SYNC_R7 (1U << 23)
+
+/* SPM_SWINT */
+#define PCM_SW_INT0 (1U << 0)
+#define PCM_SW_INT1 (1U << 1)
+#define PCM_SW_INT2 (1U << 2)
+#define PCM_SW_INT3 (1U << 3)
+#define PCM_SW_INT4 (1U << 4)
+#define PCM_SW_INT5 (1U << 5)
+#define PCM_SW_INT6 (1U << 6)
+#define PCM_SW_INT7 (1U << 7)
+#define PCM_SW_INT8 (1U << 8)
+#define PCM_SW_INT9 (1U << 9)
+#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \
+ PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \
+ PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \
+ PCM_SW_INT0)
+
+/* SPM_AP_STANDBY_CON */
+#define WFI_OP_AND 1
+#define WFI_OP_OR 0
+
+/* SPM_IRQ_MASK */
+#define ISRM_TWAM (1U << 2)
+#define ISRM_PCM_RETURN (1U << 3)
+#define ISRM_RET_IRQ0 (1U << 8)
+#define ISRM_RET_IRQ1 (1U << 9)
+#define ISRM_RET_IRQ2 (1U << 10)
+#define ISRM_RET_IRQ3 (1U << 11)
+#define ISRM_RET_IRQ4 (1U << 12)
+#define ISRM_RET_IRQ5 (1U << 13)
+#define ISRM_RET_IRQ6 (1U << 14)
+#define ISRM_RET_IRQ7 (1U << 15)
+#define ISRM_RET_IRQ8 (1U << 16)
+#define ISRM_RET_IRQ9 (1U << 17)
+#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \
+ (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \
+ (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \
+ (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \
+ (ISRM_RET_IRQ1))
+#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX)
+#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM)
+
+/* SPM_IRQ_STA */
+#define ISRS_TWAM (1U << 2)
+#define ISRS_PCM_RETURN (1U << 3)
+#define ISRC_TWAM ISRS_TWAM
+#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN
+#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM)
+
+/* SPM_WAKEUP_MISC */
+#define WAKE_MISC_GIC_WAKEUP 0x3FF
+#define WAKE_MISC_DVFSRC_IRQ DVFSRC_IRQ_LSB
+#define WAKE_MISC_REG_CPU_WAKEUP SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB
+#define WAKE_MISC_PCM_TIMER_EVENT PCM_TIMER_EVENT_LSB
+#define WAKE_MISC_PMIC_OUT_B ((1U << 19) | (1U << 20))
+#define WAKE_MISC_TWAM_IRQ_B TWAM_IRQ_B_LSB
+#define WAKE_MISC_PMSR_IRQ_B_SET0 PMSR_IRQ_B_SET0_LSB
+#define WAKE_MISC_PMSR_IRQ_B_SET1 PMSR_IRQ_B_SET1_LSB
+#define WAKE_MISC_PMSR_IRQ_B_SET2 PMSR_IRQ_B_SET2_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_0 SPM_ACK_CHK_WAKEUP_0_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_1 SPM_ACK_CHK_WAKEUP_1_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_2 SPM_ACK_CHK_WAKEUP_2_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_3 SPM_ACK_CHK_WAKEUP_3_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_ALL SPM_ACK_CHK_WAKEUP_ALL_LSB
+#define WAKE_MISC_PMIC_IRQ_ACK PMIC_IRQ_ACK_LSB
+#define WAKE_MISC_PMIC_SCP_IRQ PMIC_SCP_IRQ_LSB
+
+/* ABORT MASK for DEBUG FOORTPRINT */
+#define DEBUG_ABORT_MASK \
+ (SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC | \
+ SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN)
+
+#define DEBUG_ABORT_MASK_1 \
+ (SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT | \
+ SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT | \
+ SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT | \
+ SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT)
+
+#define MCUPM_MBOX_WAKEUP_CPU 0x0C55FD10
+
+struct pwr_ctrl {
+ uint32_t pcm_flags;
+ uint32_t pcm_flags_cust;
+ uint32_t pcm_flags_cust_set;
+ uint32_t pcm_flags_cust_clr;
+ uint32_t pcm_flags1;
+ uint32_t pcm_flags1_cust;
+ uint32_t pcm_flags1_cust_set;
+ uint32_t pcm_flags1_cust_clr;
+ uint32_t timer_val;
+ uint32_t timer_val_cust;
+ uint32_t timer_val_ramp_en;
+ uint32_t timer_val_ramp_en_sec;
+ uint32_t wake_src;
+ uint32_t wake_src_cust;
+ uint32_t wakelock_timer_val;
+ uint8_t wdt_disable;
+
+ /* Auto-gen Start */
+
+ /* SPM_CLK_CON */
+ uint8_t reg_srcclken0_ctl;
+ uint8_t reg_srcclken1_ctl;
+ uint8_t reg_spm_lock_infra_dcm;
+ uint8_t reg_srcclken_mask;
+ uint8_t reg_md1_c32rm_en;
+ uint8_t reg_md2_c32rm_en;
+ uint8_t reg_clksq0_sel_ctrl;
+ uint8_t reg_clksq1_sel_ctrl;
+ uint8_t reg_srcclken0_en;
+ uint8_t reg_srcclken1_en;
+ uint32_t reg_sysclk0_src_mask_b;
+ uint32_t reg_sysclk1_src_mask_b;
+
+ /* SPM_AP_STANDBY_CON */
+ uint8_t reg_wfi_op;
+ uint8_t reg_wfi_type;
+ uint8_t reg_mp0_cputop_idle_mask;
+ uint8_t reg_mp1_cputop_idle_mask;
+ uint8_t reg_mcusys_idle_mask;
+ uint8_t reg_md_apsrc_1_sel;
+ uint8_t reg_md_apsrc_0_sel;
+ uint8_t reg_conn_apsrc_sel;
+
+ /* SPM_SRC6_MASK */
+ uint8_t reg_dpmaif_srcclkena_mask_b;
+ uint8_t reg_dpmaif_infra_req_mask_b;
+ uint8_t reg_dpmaif_apsrc_req_mask_b;
+ uint8_t reg_dpmaif_vrf18_req_mask_b;
+ uint8_t reg_dpmaif_ddr_en_mask_b;
+ /* SPM_SRC_REQ */
+ uint8_t reg_spm_apsrc_req;
+ uint8_t reg_spm_f26m_req;
+ uint8_t reg_spm_infra_req;
+ uint8_t reg_spm_vrf18_req;
+ uint8_t reg_spm_ddr_en_req;
+ uint8_t reg_spm_dvfs_req;
+ uint8_t reg_spm_sw_mailbox_req;
+ uint8_t reg_spm_sspm_mailbox_req;
+ uint8_t reg_spm_adsp_mailbox_req;
+ uint8_t reg_spm_scp_mailbox_req;
+
+ /* SPM_SRC_MASK */
+ uint8_t reg_md_srcclkena_0_mask_b;
+ uint8_t reg_md_srcclkena2infra_req_0_mask_b;
+ uint8_t reg_md_apsrc2infra_req_0_mask_b;
+ uint8_t reg_md_apsrc_req_0_mask_b;
+ uint8_t reg_md_vrf18_req_0_mask_b;
+ uint8_t reg_md_ddr_en_0_mask_b;
+ uint8_t reg_md_srcclkena_1_mask_b;
+ uint8_t reg_md_srcclkena2infra_req_1_mask_b;
+ uint8_t reg_md_apsrc2infra_req_1_mask_b;
+ uint8_t reg_md_apsrc_req_1_mask_b;
+ uint8_t reg_md_vrf18_req_1_mask_b;
+ uint8_t reg_md_ddr_en_1_mask_b;
+ uint8_t reg_conn_srcclkena_mask_b;
+ uint8_t reg_conn_srcclkenb_mask_b;
+ uint8_t reg_conn_infra_req_mask_b;
+ uint8_t reg_conn_apsrc_req_mask_b;
+ uint8_t reg_conn_vrf18_req_mask_b;
+ uint8_t reg_conn_ddr_en_mask_b;
+ uint8_t reg_conn_vfe28_mask_b;
+ uint8_t reg_srcclkeni0_srcclkena_mask_b;
+ uint8_t reg_srcclkeni0_infra_req_mask_b;
+ uint8_t reg_srcclkeni1_srcclkena_mask_b;
+ uint8_t reg_srcclkeni1_infra_req_mask_b;
+ uint8_t reg_srcclkeni2_srcclkena_mask_b;
+ uint8_t reg_srcclkeni2_infra_req_mask_b;
+ uint8_t reg_infrasys_apsrc_req_mask_b;
+ uint8_t reg_infrasys_ddr_en_mask_b;
+ uint8_t reg_md32_srcclkena_mask_b;
+ uint8_t reg_md32_infra_req_mask_b;
+ uint8_t reg_md32_apsrc_req_mask_b;
+ uint8_t reg_md32_vrf18_req_mask_b;
+ uint8_t reg_md32_ddr_en_mask_b;
+
+ /* SPM_SRC2_MASK */
+ uint8_t reg_scp_srcclkena_mask_b;
+ uint8_t reg_scp_infra_req_mask_b;
+ uint8_t reg_scp_apsrc_req_mask_b;
+ uint8_t reg_scp_vrf18_req_mask_b;
+ uint8_t reg_scp_ddr_en_mask_b;
+ uint8_t reg_audio_dsp_srcclkena_mask_b;
+ uint8_t reg_audio_dsp_infra_req_mask_b;
+ uint8_t reg_audio_dsp_apsrc_req_mask_b;
+ uint8_t reg_audio_dsp_vrf18_req_mask_b;
+ uint8_t reg_audio_dsp_ddr_en_mask_b;
+ uint8_t reg_ufs_srcclkena_mask_b;
+ uint8_t reg_ufs_infra_req_mask_b;
+ uint8_t reg_ufs_apsrc_req_mask_b;
+ uint8_t reg_ufs_vrf18_req_mask_b;
+ uint8_t reg_ufs_ddr_en_mask_b;
+ uint8_t reg_disp0_apsrc_req_mask_b;
+ uint8_t reg_disp0_ddr_en_mask_b;
+ uint8_t reg_disp1_apsrc_req_mask_b;
+ uint8_t reg_disp1_ddr_en_mask_b;
+ uint8_t reg_gce_infra_req_mask_b;
+ uint8_t reg_gce_apsrc_req_mask_b;
+ uint8_t reg_gce_vrf18_req_mask_b;
+ uint8_t reg_gce_ddr_en_mask_b;
+ uint8_t reg_apu_srcclkena_mask_b;
+ uint8_t reg_apu_infra_req_mask_b;
+ uint8_t reg_apu_apsrc_req_mask_b;
+ uint8_t reg_apu_vrf18_req_mask_b;
+ uint8_t reg_apu_ddr_en_mask_b;
+ uint8_t reg_cg_check_srcclkena_mask_b;
+ uint8_t reg_cg_check_apsrc_req_mask_b;
+ uint8_t reg_cg_check_vrf18_req_mask_b;
+ uint8_t reg_cg_check_ddr_en_mask_b;
+
+ /* SPM_SRC3_MASK */
+ uint8_t reg_dvfsrc_event_trigger_mask_b;
+ uint8_t reg_sw2spm_int0_mask_b;
+ uint8_t reg_sw2spm_int1_mask_b;
+ uint8_t reg_sw2spm_int2_mask_b;
+ uint8_t reg_sw2spm_int3_mask_b;
+ uint8_t reg_sc_adsp2spm_wakeup_mask_b;
+ uint8_t reg_sc_sspm2spm_wakeup_mask_b;
+ uint8_t reg_sc_scp2spm_wakeup_mask_b;
+ uint8_t reg_csyspwrreq_mask;
+ uint8_t reg_spm_srcclkena_reserved_mask_b;
+ uint8_t reg_spm_infra_req_reserved_mask_b;
+ uint8_t reg_spm_apsrc_req_reserved_mask_b;
+ uint8_t reg_spm_vrf18_req_reserved_mask_b;
+ uint8_t reg_spm_ddr_en_reserved_mask_b;
+ uint8_t reg_mcupm_srcclkena_mask_b;
+ uint8_t reg_mcupm_infra_req_mask_b;
+ uint8_t reg_mcupm_apsrc_req_mask_b;
+ uint8_t reg_mcupm_vrf18_req_mask_b;
+ uint8_t reg_mcupm_ddr_en_mask_b;
+ uint8_t reg_msdc0_srcclkena_mask_b;
+ uint8_t reg_msdc0_infra_req_mask_b;
+ uint8_t reg_msdc0_apsrc_req_mask_b;
+ uint8_t reg_msdc0_vrf18_req_mask_b;
+ uint8_t reg_msdc0_ddr_en_mask_b;
+ uint8_t reg_msdc1_srcclkena_mask_b;
+ uint8_t reg_msdc1_infra_req_mask_b;
+ uint8_t reg_msdc1_apsrc_req_mask_b;
+ uint8_t reg_msdc1_vrf18_req_mask_b;
+ uint8_t reg_msdc1_ddr_en_mask_b;
+
+ /* SPM_SRC4_MASK */
+ uint32_t ccif_event_mask_b;
+ uint8_t reg_bak_psri_srcclkena_mask_b;
+ uint8_t reg_bak_psri_infra_req_mask_b;
+ uint8_t reg_bak_psri_apsrc_req_mask_b;
+ uint8_t reg_bak_psri_vrf18_req_mask_b;
+ uint8_t reg_bak_psri_ddr_en_mask_b;
+ uint8_t reg_dramc0_md32_infra_req_mask_b;
+ uint8_t reg_dramc0_md32_vrf18_req_mask_b;
+ uint8_t reg_dramc1_md32_infra_req_mask_b;
+ uint8_t reg_dramc1_md32_vrf18_req_mask_b;
+ uint8_t reg_conn_srcclkenb2pwrap_mask_b;
+ uint8_t reg_dramc0_md32_wakeup_mask;
+ uint8_t reg_dramc1_md32_wakeup_mask;
+
+ /* SPM_SRC5_MASK */
+ uint32_t reg_mcusys_merge_apsrc_req_mask_b;
+ uint32_t reg_mcusys_merge_ddr_en_mask_b;
+ uint8_t reg_msdc2_srcclkena_mask_b;
+ uint8_t reg_msdc2_infra_req_mask_b;
+ uint8_t reg_msdc2_apsrc_req_mask_b;
+ uint8_t reg_msdc2_vrf18_req_mask_b;
+ uint8_t reg_msdc2_ddr_en_mask_b;
+ uint8_t reg_pcie_srcclkena_mask_b;
+ uint8_t reg_pcie_infra_req_mask_b;
+ uint8_t reg_pcie_apsrc_req_mask_b;
+ uint8_t reg_pcie_vrf18_req_mask_b;
+ uint8_t reg_pcie_ddr_en_mask_b;
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ uint32_t reg_wakeup_event_mask;
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ uint32_t reg_ext_wakeup_event_mask;
+
+ /* Auto-gen End */
+};
+
+/* code gen by spm_pwr_ctrl_atf.pl, need struct pwr_ctrl */
+enum pwr_ctrl_enum {
+ PW_PCM_FLAGS,
+ PW_PCM_FLAGS_CUST,
+ PW_PCM_FLAGS_CUST_SET,
+ PW_PCM_FLAGS_CUST_CLR,
+ PW_PCM_FLAGS1,
+ PW_PCM_FLAGS1_CUST,
+ PW_PCM_FLAGS1_CUST_SET,
+ PW_PCM_FLAGS1_CUST_CLR,
+ PW_TIMER_VAL,
+ PW_TIMER_VAL_CUST,
+ PW_TIMER_VAL_RAMP_EN,
+ PW_TIMER_VAL_RAMP_EN_SEC,
+ PW_WAKE_SRC,
+ PW_WAKE_SRC_CUST,
+ PW_WAKELOCK_TIMER_VAL,
+ PW_WDT_DISABLE,
+
+ /* SPM_CLK_CON */
+ PW_REG_SRCCLKEN0_CTL,
+ PW_REG_SRCCLKEN1_CTL,
+ PW_REG_SPM_LOCK_INFRA_DCM,
+ PW_REG_SRCCLKEN_MASK,
+ PW_REG_MD1_C32RM_EN,
+ PW_REG_MD2_C32RM_EN,
+ PW_REG_CLKSQ0_SEL_CTRL,
+ PW_REG_CLKSQ1_SEL_CTRL,
+ PW_REG_SRCCLKEN0_EN,
+ PW_REG_SRCCLKEN1_EN,
+ PW_REG_SYSCLK0_SRC_MASK_B,
+ PW_REG_SYSCLK1_SRC_MASK_B,
+
+ /* SPM_AP_STANDBY_CON */
+ PW_REG_WFI_OP,
+ PW_REG_WFI_TYPE,
+ PW_REG_MP0_CPUTOP_IDLE_MASK,
+ PW_REG_MP1_CPUTOP_IDLE_MASK,
+ PW_REG_MCUSYS_IDLE_MASK,
+ PW_REG_MD_APSRC_1_SEL,
+ PW_REG_MD_APSRC_0_SEL,
+ PW_REG_CONN_APSRC_SEL,
+
+ /* SPM_SRC6_MASK */
+ PW_REG_DPMAIF_SRCCLKENA_MASK_B,
+ PW_REG_DPMAIF_INFRA_REQ_MASK_B,
+ PW_REG_DPMAIF_APSRC_REQ_MASK_B,
+ PW_REG_DPMAIF_VRF18_REQ_MASK_B,
+ PW_REG_DPMAIF_DDR_EN_MASK_B,
+
+ /* SPM_SRC_REQ */
+ PW_REG_SPM_APSRC_REQ,
+ PW_REG_SPM_F26M_REQ,
+ PW_REG_SPM_INFRA_REQ,
+ PW_REG_SPM_VRF18_REQ,
+ PW_REG_SPM_DDR_EN_REQ,
+ PW_REG_SPM_DVFS_REQ,
+ PW_REG_SPM_SW_MAILBOX_REQ,
+ PW_REG_SPM_SSPM_MAILBOX_REQ,
+ PW_REG_SPM_ADSP_MAILBOX_REQ,
+ PW_REG_SPM_SCP_MAILBOX_REQ,
+
+ /* SPM_SRC_MASK */
+ PW_REG_MD_SRCCLKENA_0_MASK_B,
+ PW_REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B,
+ PW_REG_MD_APSRC2INFRA_REQ_0_MASK_B,
+ PW_REG_MD_APSRC_REQ_0_MASK_B,
+ PW_REG_MD_VRF18_REQ_0_MASK_B,
+ PW_REG_MD_DDR_EN_0_MASK_B,
+ PW_REG_MD_SRCCLKENA_1_MASK_B,
+ PW_REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B,
+ PW_REG_MD_APSRC2INFRA_REQ_1_MASK_B,
+ PW_REG_MD_APSRC_REQ_1_MASK_B,
+ PW_REG_MD_VRF18_REQ_1_MASK_B,
+ PW_REG_MD_DDR_EN_1_MASK_B,
+ PW_REG_CONN_SRCCLKENA_MASK_B,
+ PW_REG_CONN_SRCCLKENB_MASK_B,
+ PW_REG_CONN_INFRA_REQ_MASK_B,
+ PW_REG_CONN_APSRC_REQ_MASK_B,
+ PW_REG_CONN_VRF18_REQ_MASK_B,
+ PW_REG_CONN_DDR_EN_MASK_B,
+ PW_REG_CONN_VFE28_MASK_B,
+ PW_REG_SRCCLKENI0_SRCCLKENA_MASK_B,
+ PW_REG_SRCCLKENI0_INFRA_REQ_MASK_B,
+ PW_REG_SRCCLKENI1_SRCCLKENA_MASK_B,
+ PW_REG_SRCCLKENI1_INFRA_REQ_MASK_B,
+ PW_REG_SRCCLKENI2_SRCCLKENA_MASK_B,
+ PW_REG_SRCCLKENI2_INFRA_REQ_MASK_B,
+ PW_REG_INFRASYS_APSRC_REQ_MASK_B,
+ PW_REG_INFRASYS_DDR_EN_MASK_B,
+ PW_REG_MD32_SRCCLKENA_MASK_B,
+ PW_REG_MD32_INFRA_REQ_MASK_B,
+ PW_REG_MD32_APSRC_REQ_MASK_B,
+ PW_REG_MD32_VRF18_REQ_MASK_B,
+ PW_REG_MD32_DDR_EN_MASK_B,
+
+ /* SPM_SRC2_MASK */
+ PW_REG_SCP_SRCCLKENA_MASK_B,
+ PW_REG_SCP_INFRA_REQ_MASK_B,
+ PW_REG_SCP_APSRC_REQ_MASK_B,
+ PW_REG_SCP_VRF18_REQ_MASK_B,
+ PW_REG_SCP_DDR_EN_MASK_B,
+ PW_REG_AUDIO_DSP_SRCCLKENA_MASK_B,
+ PW_REG_AUDIO_DSP_INFRA_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_APSRC_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_VRF18_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_DDR_EN_MASK_B,
+ PW_REG_UFS_SRCCLKENA_MASK_B,
+ PW_REG_UFS_INFRA_REQ_MASK_B,
+ PW_REG_UFS_APSRC_REQ_MASK_B,
+ PW_REG_UFS_VRF18_REQ_MASK_B,
+ PW_REG_UFS_DDR_EN_MASK_B,
+ PW_REG_DISP0_APSRC_REQ_MASK_B,
+ PW_REG_DISP0_DDR_EN_MASK_B,
+ PW_REG_DISP1_APSRC_REQ_MASK_B,
+ PW_REG_DISP1_DDR_EN_MASK_B,
+ PW_REG_GCE_INFRA_REQ_MASK_B,
+ PW_REG_GCE_APSRC_REQ_MASK_B,
+ PW_REG_GCE_VRF18_REQ_MASK_B,
+ PW_REG_GCE_DDR_EN_MASK_B,
+ PW_REG_APU_SRCCLKENA_MASK_B,
+ PW_REG_APU_INFRA_REQ_MASK_B,
+ PW_REG_APU_APSRC_REQ_MASK_B,
+ PW_REG_APU_VRF18_REQ_MASK_B,
+ PW_REG_APU_DDR_EN_MASK_B,
+ PW_REG_CG_CHECK_SRCCLKENA_MASK_B,
+ PW_REG_CG_CHECK_APSRC_REQ_MASK_B,
+ PW_REG_CG_CHECK_VRF18_REQ_MASK_B,
+ PW_REG_CG_CHECK_DDR_EN_MASK_B,
+
+ /* SPM_SRC3_MASK */
+ PW_REG_DVFSRC_EVENT_TRIGGER_MASK_B,
+ PW_REG_SW2SPM_INT0_MASK_B,
+ PW_REG_SW2SPM_INT1_MASK_B,
+ PW_REG_SW2SPM_INT2_MASK_B,
+ PW_REG_SW2SPM_INT3_MASK_B,
+ PW_REG_SC_ADSP2SPM_WAKEUP_MASK_B,
+ PW_REG_SC_SSPM2SPM_WAKEUP_MASK_B,
+ PW_REG_SC_SCP2SPM_WAKEUP_MASK_B,
+ PW_REG_CSYSPWRREQ_MASK,
+ PW_REG_SPM_SRCCLKENA_RESERVED_MASK_B,
+ PW_REG_SPM_INFRA_REQ_RESERVED_MASK_B,
+ PW_REG_SPM_APSRC_REQ_RESERVED_MASK_B,
+ PW_REG_SPM_VRF18_REQ_RESERVED_MASK_B,
+ PW_REG_SPM_DDR_EN_RESERVED_MASK_B,
+ PW_REG_MCUPM_SRCCLKENA_MASK_B,
+ PW_REG_MCUPM_INFRA_REQ_MASK_B,
+ PW_REG_MCUPM_APSRC_REQ_MASK_B,
+ PW_REG_MCUPM_VRF18_REQ_MASK_B,
+ PW_REG_MCUPM_DDR_EN_MASK_B,
+ PW_REG_MSDC0_SRCCLKENA_MASK_B,
+ PW_REG_MSDC0_INFRA_REQ_MASK_B,
+ PW_REG_MSDC0_APSRC_REQ_MASK_B,
+ PW_REG_MSDC0_VRF18_REQ_MASK_B,
+ PW_REG_MSDC0_DDR_EN_MASK_B,
+ PW_REG_MSDC1_SRCCLKENA_MASK_B,
+ PW_REG_MSDC1_INFRA_REQ_MASK_B,
+ PW_REG_MSDC1_APSRC_REQ_MASK_B,
+ PW_REG_MSDC1_VRF18_REQ_MASK_B,
+ PW_REG_MSDC1_DDR_EN_MASK_B,
+
+ /* SPM_SRC4_MASK */
+ PW_CCIF_EVENT_MASK_B,
+ PW_REG_BAK_PSRI_SRCCLKENA_MASK_B,
+ PW_REG_BAK_PSRI_INFRA_REQ_MASK_B,
+ PW_REG_BAK_PSRI_APSRC_REQ_MASK_B,
+ PW_REG_BAK_PSRI_VRF18_REQ_MASK_B,
+ PW_REG_BAK_PSRI_DDR_EN_MASK_B,
+ PW_REG_DRAMC0_MD32_INFRA_REQ_MASK_B,
+ PW_REG_DRAMC0_MD32_VRF18_REQ_MASK_B,
+ PW_REG_DRAMC1_MD32_INFRA_REQ_MASK_B,
+ PW_REG_DRAMC1_MD32_VRF18_REQ_MASK_B,
+ PW_REG_CONN_SRCCLKENB2PWRAP_MASK_B,
+ PW_REG_DRAMC0_MD32_WAKEUP_MASK,
+ PW_REG_DRAMC1_MD32_WAKEUP_MASK,
+
+ /* SPM_SRC5_MASK */
+ PW_REG_MCUSYS_MERGE_APSRC_REQ_MASK_B,
+ PW_REG_MCUSYS_MERGE_DDR_EN_MASK_B,
+ PW_REG_MSDC2_SRCCLKENA_MASK_B,
+ PW_REG_MSDC2_INFRA_REQ_MASK_B,
+ PW_REG_MSDC2_APSRC_REQ_MASK_B,
+ PW_REG_MSDC2_VRF18_REQ_MASK_B,
+ PW_REG_MSDC2_DDR_EN_MASK_B,
+ PW_REG_PCIE_SRCCLKENA_MASK_B,
+ PW_REG_PCIE_INFRA_REQ_MASK_B,
+ PW_REG_PCIE_APSRC_REQ_MASK_B,
+ PW_REG_PCIE_VRF18_REQ_MASK_B,
+ PW_REG_PCIE_DDR_EN_MASK_B,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ PW_REG_WAKEUP_EVENT_MASK,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ PW_REG_EXT_WAKEUP_EVENT_MASK,
+
+ PW_MAX_COUNT,
+};
+
+#define SPM_INTERNAL_STATUS_HW_S1 (1U << 0)
+#define SPM_ACK_CHK_3_SEL_HW_S1 0x00350098
+#define SPM_ACK_CHK_3_HW_S1_CNT 1
+#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG 0x800
+#define SPM_ACK_CHK_3_CON_EN 0x110
+#define SPM_ACK_CHK_3_CON_CLR_ALL 0x2
+#define SPM_ACK_CHK_3_CON_RESULT 0x8000
+
+struct wake_status_trace_comm {
+ uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */
+ uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */
+ uint32_t timer_out; /* SPM_SW_RSV_6*/
+ uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */
+ uint32_t b_sw_flag1; /* SPM_SW_RSV_7 */
+ uint32_t r12; /* SPM_SW_RSV_0 */
+ uint32_t r13; /* PCM_REG13_DATA */
+ uint32_t req_sta0; /* SRC_REQ_STA_0 */
+ uint32_t req_sta1; /* SRC_REQ_STA_1 */
+ uint32_t req_sta2; /* SRC_REQ_STA_2 */
+ uint32_t req_sta3; /* SRC_REQ_STA_3 */
+ uint32_t req_sta4; /* SRC_REQ_STA_4 */
+};
+
+struct wake_status_trace {
+ struct wake_status_trace_comm comm;
+};
+
+struct wake_status {
+ struct wake_status_trace tr;
+ uint32_t r12; /* SPM_BK_WAKE_EVENT */
+ uint32_t r12_ext; /* SPM_WAKEUP_EXT_STA */
+ uint32_t raw_sta; /* SPM_WAKEUP_STA */
+ uint32_t raw_ext_sta; /* SPM_WAKEUP_EXT_STA */
+ uint32_t md32pcm_wakeup_sta; /* MD32CPM_WAKEUP_STA */
+ uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */
+ uint32_t wake_misc; /* SPM_BK_WAKE_MISC */
+ uint32_t timer_out; /* SPM_BK_PCM_TIMER */
+ uint32_t r13; /* PCM_REG13_DATA */
+ uint32_t idle_sta; /* SUBSYS_IDLE_STA */
+ uint32_t req_sta0; /* SRC_REQ_STA_0 */
+ uint32_t req_sta1; /* SRC_REQ_STA_1 */
+ uint32_t req_sta2; /* SRC_REQ_STA_2 */
+ uint32_t req_sta3; /* SRC_REQ_STA_3 */
+ uint32_t req_sta4; /* SRC_REQ_STA_4 */
+ uint32_t cg_check_sta; /* SPM_CG_CHECK_STA */
+ uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */
+ uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */
+ uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */
+ uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */
+ uint32_t isr; /* SPM_IRQ_STA */
+ uint32_t sw_flag0; /* SPM_SW_FLAG_0 */
+ uint32_t sw_flag1; /* SPM_SW_FLAG_1 */
+ uint32_t clk_settle; /* SPM_CLK_SETTLE */
+ uint32_t src_req; /* SPM_SRC_REQ */
+ uint32_t log_index;
+ uint32_t abort;
+ uint32_t rt_req_sta0; /* SPM_SW_RSV_2 */
+ uint32_t rt_req_sta1; /* SPM_SW_RSV_3 */
+ uint32_t rt_req_sta2; /* SPM_SW_RSV_4 */
+ uint32_t rt_req_sta3; /* SPM_SW_RSV_5 */
+ uint32_t rt_req_sta4; /* SPM_SW_RSV_6 */
+ uint32_t mcupm_req_sta;
+};
+
+struct spm_lp_scen {
+ struct pcm_desc *pcmdesc;
+ struct pwr_ctrl *pwrctrl;
+};
+
+extern struct spm_lp_scen __spm_vcorefs;
+extern void __spm_set_cpu_status(unsigned int cpu);
+extern void __spm_reset_and_init_pcm(const struct pcm_desc *pcmdesc);
+extern void __spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc);
+extern void __spm_init_pcm_register(void);
+extern void __spm_src_req_update(const struct pwr_ctrl *pwrctrl,
+ unsigned int resource_usage);
+extern void __spm_set_power_control(const struct pwr_ctrl *pwrctrl);
+extern void __spm_disable_pcm_timer(void);
+extern void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl);
+extern void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl);
+extern void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl);
+extern void __spm_send_cpu_wakeup_event(void);
+extern void __spm_get_wakeup_status(struct wake_status *wakesta,
+ unsigned int ext_status);
+extern void __spm_clean_after_wakeup(void);
+extern wake_reason_t
+__spm_output_wake_reason(int state_id, const struct wake_status *wakesta);
+extern void
+__spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+ const struct pwr_ctrl *src_pwr_ctrl);
+extern void __spm_set_pcm_wdt(int en);
+extern uint32_t _spm_get_wake_period(int pwake_time, wake_reason_t last_wr);
+extern void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl);
+extern void __spm_ext_int_wakeup_req_clr(void);
+extern void __spm_xo_soc_bblpm(int en);
+
+static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl,
+ uint32_t flags)
+{
+ if (pwrctrl->pcm_flags_cust == 0U) {
+ pwrctrl->pcm_flags = flags;
+ } else {
+ pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust;
+ }
+}
+
+static inline void set_pwrctrl_pcm_flags1(struct pwr_ctrl *pwrctrl,
+ uint32_t flags)
+{
+ if (pwrctrl->pcm_flags1_cust == 0U) {
+ pwrctrl->pcm_flags1 = flags;
+ } else {
+ pwrctrl->pcm_flags1 = pwrctrl->pcm_flags1_cust;
+ }
+}
+
+extern void __spm_hw_s1_state_monitor(int en, unsigned int *status);
+
+static inline void spm_hw_s1_state_monitor_resume(void)
+{
+ __spm_hw_s1_state_monitor(1, NULL);
+}
+
+static inline void spm_hw_s1_state_monitor_pause(unsigned int *status)
+{
+ __spm_hw_s1_state_monitor(0, status);
+}
+#endif /* MT_SPM_INTERNAL_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c
new file mode 100644
index 0000000..4e5f6a0
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+/* PMIC_WRAP MT6359 */
+#define VCORE_BASE_UV 40000
+#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625)
+#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV)
+
+#define NR_PMIC_WRAP_CMD (NR_IDX_ALL)
+#define SPM_DATA_SHIFT 16
+
+#define BUCK_VGPU11_ELR0 0x15B4
+#define TOP_SPI_CON0 0x0456
+#define BUCK_TOP_CON1 0x1443
+#define TOP_CON 0x0013
+#define TOP_DIG_WPK 0x03a9
+#define TOP_CON_LOCK 0x03a8
+#define TOP_CLK_CON0 0x0134
+
+struct pmic_wrap_cmd {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+};
+
+struct pmic_wrap_setting {
+ enum pmic_wrap_phase_id phase;
+ struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
+ struct {
+ struct {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+ } _[NR_PMIC_WRAP_CMD];
+ const int nr_idx;
+ } set[NR_PMIC_WRAP_PHASE];
+};
+
+static struct pmic_wrap_setting pw = {
+ .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */
+ .addr = { {0UL, 0UL} },
+ .set[PMIC_WRAP_PHASE_ALLINONE] = {
+ ._[CMD_0] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(72500),},
+ ._[CMD_1] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(65000),},
+ ._[CMD_2] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(60000),},
+ ._[CMD_3] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(57500),},
+ ._[CMD_4] = {TOP_SPI_CON0, 0x1,},
+ ._[CMD_5] = {TOP_SPI_CON0, 0x0,},
+ ._[CMD_6] = {BUCK_TOP_CON1, 0x0,},
+ ._[CMD_7] = {BUCK_TOP_CON1, 0xf,},
+ ._[CMD_8] = {TOP_CON, 0x3,},
+ ._[CMD_9] = {TOP_CON, 0x0,},
+ ._[CMD_10] = {TOP_DIG_WPK, 0x63,},
+ ._[CMD_11] = {TOP_CON_LOCK, 0x15,},
+ ._[CMD_12] = {TOP_DIG_WPK, 0x0,},
+ ._[CMD_13] = {TOP_CON_LOCK, 0x0,},
+ ._[CMD_14] = {TOP_CLK_CON0, 0x40,},
+ ._[CMD_15] = {TOP_CLK_CON0, 0x0,},
+ .nr_idx = NR_IDX_ALL,
+ },
+};
+
+void _mt_spm_pmic_table_init(void)
+{
+ struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
+ {(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,},
+ {(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,},
+ {(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,},
+ {(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,},
+ {(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,},
+ {(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,},
+ {(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,},
+ {(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,},
+ {(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,},
+ {(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,},
+ {(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,},
+ {(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,},
+ {(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,},
+ {(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,},
+ {(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,},
+ {(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,},
+ };
+
+ memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
+}
+
+void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
+{
+ uint32_t idx, addr, data;
+
+ if (phase >= NR_PMIC_WRAP_PHASE) {
+ return;
+ }
+
+ if (pw.phase == phase) {
+ return;
+ }
+
+ if (pw.addr[0].cmd_addr == 0UL) {
+ _mt_spm_pmic_table_init();
+ }
+
+ pw.phase = phase;
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
+
+ for (idx = 0U; idx < pw.set[phase].nr_idx; idx++) {
+ addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ data = pw.set[phase]._[idx].cmd_wdata;
+ mmio_write_32(pw.addr[idx].cmd_addr, addr | data);
+ }
+}
+
+void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
+ uint32_t cmd_wdata)
+{
+ uint32_t addr;
+
+ if (phase >= NR_PMIC_WRAP_PHASE) {
+ return;
+ }
+
+ if (idx >= pw.set[phase].nr_idx) {
+ return;
+ }
+
+ pw.set[phase]._[idx].cmd_wdata = cmd_wdata;
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
+
+ if (pw.phase == phase) {
+ addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata);
+ }
+}
+
+uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
+{
+ if (phase >= NR_PMIC_WRAP_PHASE) {
+ return 0UL;
+ }
+
+ if (idx >= pw.set[phase].nr_idx) {
+ return 0UL;
+ }
+
+ return pw.set[phase]._[idx].cmd_wdata;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h
new file mode 100644
index 0000000..6e20916
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/****************************************************************
+ * Auto generated by DE, please DO NOT modify this file directly.
+ *****************************************************************/
+#ifndef MT_SPM_PMIC_WRAP_H
+#define MT_SPM_PMIC_WRAP_H
+
+enum pmic_wrap_phase_id {
+ PMIC_WRAP_PHASE_ALLINONE,
+ NR_PMIC_WRAP_PHASE,
+};
+
+/* IDX mapping, PMIC_WRAP_PHASE_ALLINONE */
+enum {
+ CMD_0, /* 0x0 */
+ CMD_1, /* 0x1 */
+ CMD_2, /* 0x2 */
+ CMD_3, /* 0x3 */
+ CMD_4, /* 0x4 */
+ CMD_5, /* 0x5 */
+ CMD_6, /* 0x6 */
+ CMD_7, /* 0x7 */
+ CMD_8, /* 0x8 */
+ CMD_9, /* 0x9 */
+ CMD_10, /* 0xA */
+ CMD_11, /* 0xB */
+ CMD_12, /* 0xC */
+ CMD_13, /* 0xD */
+ CMD_14, /* 0xE */
+ CMD_15, /* 0xF */
+ NR_IDX_ALL,
+};
+
+/* APIs */
+extern void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase);
+extern void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase,
+ uint32_t idx, uint32_t cmd_wdata);
+extern uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase,
+ uint32_t idx);
+#endif /* MT_SPM_PMIC_WRAP_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h
new file mode 100644
index 0000000..fba011d
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h
@@ -0,0 +1,2919 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/****************************************************************
+ * Auto generated by DE, please DO NOT modify this file directly.
+ *****************************************************************/
+#ifndef MT_SPM_REG
+#define MT_SPM_REG
+
+#include "pcm_def.h"
+#include <platform_def.h>
+#include "sleep_def.h"
+
+/**************************************
+ * Define and Declare
+ **************************************/
+#define POWERON_CONFIG_EN (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008)
+#define SPM_CLK_CON (SPM_BASE + 0x00C)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x010)
+#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014)
+#define PCM_CON0 (SPM_BASE + 0x018)
+#define PCM_CON1 (SPM_BASE + 0x01C)
+#define SPM_POWER_ON_VAL2 (SPM_BASE + 0x020)
+#define SPM_POWER_ON_VAL3 (SPM_BASE + 0x024)
+#define PCM_REG_DATA_INI (SPM_BASE + 0x028)
+#define PCM_PWR_IO_EN (SPM_BASE + 0x02C)
+#define PCM_TIMER_VAL (SPM_BASE + 0x030)
+#define PCM_WDT_VAL (SPM_BASE + 0x034)
+#define SPM_SRC6_MASK (SPM_BASE + 0x038)
+#define SPM_SW_RST_CON (SPM_BASE + 0x040)
+#define SPM_SW_RST_CON_SET (SPM_BASE + 0x044)
+#define SPM_SW_RST_CON_CLR (SPM_BASE + 0x048)
+#define VS1_PSR_MASK_B (SPM_BASE + 0x04C)
+#define VS2_PSR_MASK_B (SPM_BASE + 0x050)
+#define MD32_CLK_CON (SPM_BASE + 0x084)
+#define SPM_SRAM_RSV_CON (SPM_BASE + 0x088)
+#define SPM_SWINT (SPM_BASE + 0x08C)
+#define SPM_SWINT_SET (SPM_BASE + 0x090)
+#define SPM_SWINT_CLR (SPM_BASE + 0x094)
+#define SPM_SCP_MAILBOX (SPM_BASE + 0x098)
+#define SCP_SPM_MAILBOX (SPM_BASE + 0x09C)
+#define SPM_TWAM_CON (SPM_BASE + 0x0A0)
+#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x0A4)
+#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x0A8)
+#define SPM_SCP_IRQ (SPM_BASE + 0x0AC)
+#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x0B0)
+#define SPM_IRQ_MASK (SPM_BASE + 0x0B4)
+#define SPM_SRC_REQ (SPM_BASE + 0x0B8)
+#define SPM_SRC_MASK (SPM_BASE + 0x0BC)
+#define SPM_SRC2_MASK (SPM_BASE + 0x0C0)
+#define SPM_SRC3_MASK (SPM_BASE + 0x0C4)
+#define SPM_SRC4_MASK (SPM_BASE + 0x0C8)
+#define SPM_SRC5_MASK (SPM_BASE + 0x0CC)
+#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x0D0)
+#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0D4)
+#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x0D8)
+#define SCP_CLK_CON (SPM_BASE + 0x0DC)
+#define PCM_DEBUG_CON (SPM_BASE + 0x0E0)
+#define AHB_BUS_CON (SPM_BASE + 0x0E4)
+#define DDR_EN_DBC_CON0 (SPM_BASE + 0x0E8)
+#define DDR_EN_DBC_CON1 (SPM_BASE + 0x0EC)
+#define SPM_RESOURCE_ACK_CON0 (SPM_BASE + 0x0F0)
+#define SPM_RESOURCE_ACK_CON1 (SPM_BASE + 0x0F4)
+#define SPM_RESOURCE_ACK_CON2 (SPM_BASE + 0x0F8)
+#define SPM_RESOURCE_ACK_CON3 (SPM_BASE + 0x0FC)
+#define PCM_REG0_DATA (SPM_BASE + 0x100)
+#define PCM_REG2_DATA (SPM_BASE + 0x104)
+#define PCM_REG6_DATA (SPM_BASE + 0x108)
+#define PCM_REG7_DATA (SPM_BASE + 0x10C)
+#define PCM_REG13_DATA (SPM_BASE + 0x110)
+#define SRC_REQ_STA_0 (SPM_BASE + 0x114)
+#define SRC_REQ_STA_1 (SPM_BASE + 0x118)
+#define SRC_REQ_STA_2 (SPM_BASE + 0x11C)
+#define PCM_TIMER_OUT (SPM_BASE + 0x120)
+#define PCM_WDT_OUT (SPM_BASE + 0x124)
+#define SPM_IRQ_STA (SPM_BASE + 0x128)
+#define SRC_REQ_STA_4 (SPM_BASE + 0x12C)
+#define MD32PCM_WAKEUP_STA (SPM_BASE + 0x130)
+#define MD32PCM_EVENT_STA (SPM_BASE + 0x134)
+#define SPM_WAKEUP_STA (SPM_BASE + 0x138)
+#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x13C)
+#define SPM_WAKEUP_MISC (SPM_BASE + 0x140)
+#define MM_DVFS_HALT (SPM_BASE + 0x144)
+#define BUS_PROTECT_RDY (SPM_BASE + 0x150)
+#define BUS_PROTECT1_RDY (SPM_BASE + 0x154)
+#define BUS_PROTECT2_RDY (SPM_BASE + 0x158)
+#define BUS_PROTECT3_RDY (SPM_BASE + 0x15C)
+#define SUBSYS_IDLE_STA (SPM_BASE + 0x160)
+#define PCM_STA (SPM_BASE + 0x164)
+#define SRC_REQ_STA_3 (SPM_BASE + 0x168)
+#define PWR_STATUS (SPM_BASE + 0x16C)
+#define PWR_STATUS_2ND (SPM_BASE + 0x170)
+#define CPU_PWR_STATUS (SPM_BASE + 0x174)
+#define OTHER_PWR_STATUS (SPM_BASE + 0x178)
+#define SPM_VTCXO_EVENT_COUNT_STA (SPM_BASE + 0x17C)
+#define SPM_INFRA_EVENT_COUNT_STA (SPM_BASE + 0x180)
+#define SPM_VRF18_EVENT_COUNT_STA (SPM_BASE + 0x184)
+#define SPM_APSRC_EVENT_COUNT_STA (SPM_BASE + 0x188)
+#define SPM_DDREN_EVENT_COUNT_STA (SPM_BASE + 0x18C)
+#define MD32PCM_STA (SPM_BASE + 0x190)
+#define MD32PCM_PC (SPM_BASE + 0x194)
+#define DVFSRC_EVENT_STA (SPM_BASE + 0x1A4)
+#define BUS_PROTECT4_RDY (SPM_BASE + 0x1A8)
+#define BUS_PROTECT5_RDY (SPM_BASE + 0x1AC)
+#define BUS_PROTECT6_RDY (SPM_BASE + 0x1B0)
+#define BUS_PROTECT7_RDY (SPM_BASE + 0x1B4)
+#define BUS_PROTECT8_RDY (SPM_BASE + 0x1B8)
+#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1D0)
+#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1D4)
+#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1D8)
+#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1DC)
+#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1E0)
+#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1E4)
+#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1E8)
+#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1EC)
+#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1F0)
+#define SPM_CG_CHECK_STA (SPM_BASE + 0x1F4)
+#define SPM_DVFS_STA (SPM_BASE + 0x1F8)
+#define SPM_DVFS_OPP_STA (SPM_BASE + 0x1FC)
+#define SPM_MCUSYS_PWR_CON (SPM_BASE + 0x200)
+#define SPM_CPUTOP_PWR_CON (SPM_BASE + 0x204)
+#define SPM_CPU0_PWR_CON (SPM_BASE + 0x208)
+#define SPM_CPU1_PWR_CON (SPM_BASE + 0x20C)
+#define SPM_CPU2_PWR_CON (SPM_BASE + 0x210)
+#define SPM_CPU3_PWR_CON (SPM_BASE + 0x214)
+#define SPM_CPU4_PWR_CON (SPM_BASE + 0x218)
+#define SPM_CPU5_PWR_CON (SPM_BASE + 0x21C)
+#define SPM_CPU6_PWR_CON (SPM_BASE + 0x220)
+#define SPM_CPU7_PWR_CON (SPM_BASE + 0x224)
+#define ARMPLL_CLK_CON (SPM_BASE + 0x22C)
+#define MCUSYS_IDLE_STA (SPM_BASE + 0x230)
+#define GIC_WAKEUP_STA (SPM_BASE + 0x234)
+#define CPU_SPARE_CON (SPM_BASE + 0x238)
+#define CPU_SPARE_CON_SET (SPM_BASE + 0x23C)
+#define CPU_SPARE_CON_CLR (SPM_BASE + 0x240)
+#define ARMPLL_CLK_SEL (SPM_BASE + 0x244)
+#define EXT_INT_WAKEUP_REQ (SPM_BASE + 0x248)
+#define EXT_INT_WAKEUP_REQ_SET (SPM_BASE + 0x24C)
+#define EXT_INT_WAKEUP_REQ_CLR (SPM_BASE + 0x250)
+#define MP0_CPU0_IRQ_MASK (SPM_BASE + 0x260)
+#define MP0_CPU1_IRQ_MASK (SPM_BASE + 0x264)
+#define MP0_CPU2_IRQ_MASK (SPM_BASE + 0x268)
+#define MP0_CPU3_IRQ_MASK (SPM_BASE + 0x26C)
+#define MP1_CPU0_IRQ_MASK (SPM_BASE + 0x270)
+#define MP1_CPU1_IRQ_MASK (SPM_BASE + 0x274)
+#define MP1_CPU2_IRQ_MASK (SPM_BASE + 0x278)
+#define MP1_CPU3_IRQ_MASK (SPM_BASE + 0x27C)
+#define MP0_CPU0_WFI_EN (SPM_BASE + 0x280)
+#define MP0_CPU1_WFI_EN (SPM_BASE + 0x284)
+#define MP0_CPU2_WFI_EN (SPM_BASE + 0x288)
+#define MP0_CPU3_WFI_EN (SPM_BASE + 0x28C)
+#define MP0_CPU4_WFI_EN (SPM_BASE + 0x290)
+#define MP0_CPU5_WFI_EN (SPM_BASE + 0x294)
+#define MP0_CPU6_WFI_EN (SPM_BASE + 0x298)
+#define MP0_CPU7_WFI_EN (SPM_BASE + 0x29C)
+#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x2A0)
+#define ROOT_CORE_ADDR (SPM_BASE + 0x2A4)
+#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x2D0)
+#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x2D4)
+#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x2D8)
+#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x2DC)
+#define SW2SPM_INT (SPM_BASE + 0x2E0)
+#define SW2SPM_INT_SET (SPM_BASE + 0x2E4)
+#define SW2SPM_INT_CLR (SPM_BASE + 0x2E8)
+#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x2EC)
+#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x2F0)
+#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x2F4)
+#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x2F8)
+#define SW2SPM_CFG (SPM_BASE + 0x2FC)
+#define MD1_PWR_CON (SPM_BASE + 0x300)
+#define CONN_PWR_CON (SPM_BASE + 0x304)
+#define MFG0_PWR_CON (SPM_BASE + 0x308)
+#define MFG1_PWR_CON (SPM_BASE + 0x30C)
+#define MFG2_PWR_CON (SPM_BASE + 0x310)
+#define MFG3_PWR_CON (SPM_BASE + 0x314)
+#define MFG4_PWR_CON (SPM_BASE + 0x318)
+#define MFG5_PWR_CON (SPM_BASE + 0x31C)
+#define MFG6_PWR_CON (SPM_BASE + 0x320)
+#define IFR_PWR_CON (SPM_BASE + 0x324)
+#define IFR_SUB_PWR_CON (SPM_BASE + 0x328)
+#define DPY_PWR_CON (SPM_BASE + 0x32C)
+#define ISP_PWR_CON (SPM_BASE + 0x330)
+#define ISP2_PWR_CON (SPM_BASE + 0x334)
+#define IPE_PWR_CON (SPM_BASE + 0x338)
+#define VDE_PWR_CON (SPM_BASE + 0x33C)
+#define VDE2_PWR_CON (SPM_BASE + 0x340)
+#define VEN_PWR_CON (SPM_BASE + 0x344)
+#define VEN_CORE1_PWR_CON (SPM_BASE + 0x348)
+#define MDP_PWR_CON (SPM_BASE + 0x34C)
+#define DIS_PWR_CON (SPM_BASE + 0x350)
+#define AUDIO_PWR_CON (SPM_BASE + 0x354)
+#define ADSP_PWR_CON (SPM_BASE + 0x358)
+#define CAM_PWR_CON (SPM_BASE + 0x35C)
+#define CAM_RAWA_PWR_CON (SPM_BASE + 0x360)
+#define CAM_RAWB_PWR_CON (SPM_BASE + 0x364)
+#define CAM_RAWC_PWR_CON (SPM_BASE + 0x368)
+#define SYSRAM_CON (SPM_BASE + 0x36C)
+#define SYSROM_CON (SPM_BASE + 0x370)
+#define SSPM_SRAM_CON (SPM_BASE + 0x374)
+#define SCP_SRAM_CON (SPM_BASE + 0x378)
+#define DPY_SHU_SRAM_CON (SPM_BASE + 0x37C)
+#define UFS_SRAM_CON (SPM_BASE + 0x380)
+#define DEVAPC_IFR_SRAM_CON (SPM_BASE + 0x384)
+#define DEVAPC_SUBIFR_SRAM_CON (SPM_BASE + 0x388)
+#define DEVAPC_ACP_SRAM_CON (SPM_BASE + 0x38C)
+#define USB_SRAM_CON (SPM_BASE + 0x390)
+#define DUMMY_SRAM_CON (SPM_BASE + 0x394)
+#define MD_EXT_BUCK_ISO_CON (SPM_BASE + 0x398)
+#define EXT_BUCK_ISO (SPM_BASE + 0x39C)
+#define DXCC_SRAM_CON (SPM_BASE + 0x3A0)
+#define MSDC_SRAM_CON (SPM_BASE + 0x3A4)
+#define DEBUGTOP_SRAM_CON (SPM_BASE + 0x3A8)
+#define DP_TX_PWR_CON (SPM_BASE + 0x3AC)
+#define DPMAIF_SRAM_CON (SPM_BASE + 0x3B0)
+#define DPY_SHU2_SRAM_CON (SPM_BASE + 0x3B4)
+#define DRAMC_MCU2_SRAM_CON (SPM_BASE + 0x3B8)
+#define DRAMC_MCU_SRAM_CON (SPM_BASE + 0x3BC)
+#define MCUPM_SRAM_CON (SPM_BASE + 0x3C0)
+#define DPY2_PWR_CON (SPM_BASE + 0x3C4)
+#define PERI_PWR_CON (SPM_BASE + 0x3C8)
+#define SPM_MEM_CK_SEL (SPM_BASE + 0x400)
+#define SPM_BUS_PROTECT_MASK_B (SPM_BASE + 0x404)
+#define SPM_BUS_PROTECT1_MASK_B (SPM_BASE + 0x408)
+#define SPM_BUS_PROTECT2_MASK_B (SPM_BASE + 0x40C)
+#define SPM_BUS_PROTECT3_MASK_B (SPM_BASE + 0x410)
+#define SPM_BUS_PROTECT4_MASK_B (SPM_BASE + 0x414)
+#define SPM_EMI_BW_MODE (SPM_BASE + 0x418)
+#define AP2MD_PEER_WAKEUP (SPM_BASE + 0x41C)
+#define ULPOSC_CON (SPM_BASE + 0x420)
+#define SPM2MM_CON (SPM_BASE + 0x424)
+#define SPM_BUS_PROTECT5_MASK_B (SPM_BASE + 0x428)
+#define SPM2MCUPM_CON (SPM_BASE + 0x42C)
+#define AP_MDSRC_REQ (SPM_BASE + 0x430)
+#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x434)
+#define SPM2MD_DVFS_CON (SPM_BASE + 0x438)
+#define MD2SPM_DVFS_CON (SPM_BASE + 0x43C)
+#define SPM_BUS_PROTECT6_MASK_B (SPM_BASE + 0x440)
+#define SPM_BUS_PROTECT7_MASK_B (SPM_BASE + 0x444)
+#define SPM_BUS_PROTECT8_MASK_B (SPM_BASE + 0x448)
+#define SPM_PLL_CON (SPM_BASE + 0x44C)
+#define CPU_DVFS_REQ (SPM_BASE + 0x450)
+#define SPM_DRAM_MCU_SW_CON_0 (SPM_BASE + 0x454)
+#define SPM_DRAM_MCU_SW_CON_1 (SPM_BASE + 0x458)
+#define SPM_DRAM_MCU_SW_CON_2 (SPM_BASE + 0x45C)
+#define SPM_DRAM_MCU_SW_CON_3 (SPM_BASE + 0x460)
+#define SPM_DRAM_MCU_SW_CON_4 (SPM_BASE + 0x464)
+#define SPM_DRAM_MCU_STA_0 (SPM_BASE + 0x468)
+#define SPM_DRAM_MCU_STA_1 (SPM_BASE + 0x46C)
+#define SPM_DRAM_MCU_STA_2 (SPM_BASE + 0x470)
+#define SPM_DRAM_MCU_SW_SEL_0 (SPM_BASE + 0x474)
+#define RELAY_DVFS_LEVEL (SPM_BASE + 0x478)
+#define DRAMC_DPY_CLK_SW_CON_0 (SPM_BASE + 0x480)
+#define DRAMC_DPY_CLK_SW_CON_1 (SPM_BASE + 0x484)
+#define DRAMC_DPY_CLK_SW_CON_2 (SPM_BASE + 0x488)
+#define DRAMC_DPY_CLK_SW_CON_3 (SPM_BASE + 0x48C)
+#define DRAMC_DPY_CLK_SW_SEL_0 (SPM_BASE + 0x490)
+#define DRAMC_DPY_CLK_SW_SEL_1 (SPM_BASE + 0x494)
+#define DRAMC_DPY_CLK_SW_SEL_2 (SPM_BASE + 0x498)
+#define DRAMC_DPY_CLK_SW_SEL_3 (SPM_BASE + 0x49C)
+#define DRAMC_DPY_CLK_SPM_CON (SPM_BASE + 0x4A0)
+#define SPM_DVFS_LEVEL (SPM_BASE + 0x4A4)
+#define SPM_CIRQ_CON (SPM_BASE + 0x4A8)
+#define SPM_DVFS_MISC (SPM_BASE + 0x4AC)
+#define SPM_VS1_VS2_RC_CON (SPM_BASE + 0x4B0)
+#define RG_MODULE_SW_CG_0_MASK_REQ_0 (SPM_BASE + 0x4B4)
+#define RG_MODULE_SW_CG_0_MASK_REQ_1 (SPM_BASE + 0x4B8)
+#define RG_MODULE_SW_CG_0_MASK_REQ_2 (SPM_BASE + 0x4BC)
+#define RG_MODULE_SW_CG_1_MASK_REQ_0 (SPM_BASE + 0x4C0)
+#define RG_MODULE_SW_CG_1_MASK_REQ_1 (SPM_BASE + 0x4C4)
+#define RG_MODULE_SW_CG_1_MASK_REQ_2 (SPM_BASE + 0x4C8)
+#define RG_MODULE_SW_CG_2_MASK_REQ_0 (SPM_BASE + 0x4CC)
+#define RG_MODULE_SW_CG_2_MASK_REQ_1 (SPM_BASE + 0x4D0)
+#define RG_MODULE_SW_CG_2_MASK_REQ_2 (SPM_BASE + 0x4D4)
+#define RG_MODULE_SW_CG_3_MASK_REQ_0 (SPM_BASE + 0x4D8)
+#define RG_MODULE_SW_CG_3_MASK_REQ_1 (SPM_BASE + 0x4DC)
+#define RG_MODULE_SW_CG_3_MASK_REQ_2 (SPM_BASE + 0x4E0)
+#define PWR_STATUS_MASK_REQ_0 (SPM_BASE + 0x4E4)
+#define PWR_STATUS_MASK_REQ_1 (SPM_BASE + 0x4E8)
+#define PWR_STATUS_MASK_REQ_2 (SPM_BASE + 0x4EC)
+#define SPM_CG_CHECK_CON (SPM_BASE + 0x4F0)
+#define SPM_SRC_RDY_STA (SPM_BASE + 0x4F4)
+#define SPM_DVS_DFS_LEVEL (SPM_BASE + 0x4F8)
+#define SPM_FORCE_DVFS (SPM_BASE + 0x4FC)
+#define SRCLKEN_RC_CFG (SPM_BASE + 0x500)
+#define RC_CENTRAL_CFG1 (SPM_BASE + 0x504)
+#define RC_CENTRAL_CFG2 (SPM_BASE + 0x508)
+#define RC_CMD_ARB_CFG (SPM_BASE + 0x50C)
+#define RC_PMIC_RCEN_ADDR (SPM_BASE + 0x510)
+#define RC_PMIC_RCEN_SET_CLR_ADDR (SPM_BASE + 0x514)
+#define RC_DCXO_FPM_CFG (SPM_BASE + 0x518)
+#define RC_CENTRAL_CFG3 (SPM_BASE + 0x51C)
+#define RC_M00_SRCLKEN_CFG (SPM_BASE + 0x520)
+#define RC_M01_SRCLKEN_CFG (SPM_BASE + 0x524)
+#define RC_M02_SRCLKEN_CFG (SPM_BASE + 0x528)
+#define RC_M03_SRCLKEN_CFG (SPM_BASE + 0x52C)
+#define RC_M04_SRCLKEN_CFG (SPM_BASE + 0x530)
+#define RC_M05_SRCLKEN_CFG (SPM_BASE + 0x534)
+#define RC_M06_SRCLKEN_CFG (SPM_BASE + 0x538)
+#define RC_M07_SRCLKEN_CFG (SPM_BASE + 0x53C)
+#define RC_M08_SRCLKEN_CFG (SPM_BASE + 0x540)
+#define RC_M09_SRCLKEN_CFG (SPM_BASE + 0x544)
+#define RC_M10_SRCLKEN_CFG (SPM_BASE + 0x548)
+#define RC_M11_SRCLKEN_CFG (SPM_BASE + 0x54C)
+#define RC_M12_SRCLKEN_CFG (SPM_BASE + 0x550)
+#define RC_SRCLKEN_SW_CON_CFG (SPM_BASE + 0x554)
+#define RC_CENTRAL_CFG4 (SPM_BASE + 0x558)
+#define RC_PROTOCOL_CHK_CFG (SPM_BASE + 0x560)
+#define RC_DEBUG_CFG (SPM_BASE + 0x564)
+#define RC_MISC_0 (SPM_BASE + 0x5B4)
+#define RC_SPM_CTRL (SPM_BASE + 0x5B8)
+#define SUBSYS_INTF_CFG (SPM_BASE + 0x5BC)
+#define PCM_WDT_LATCH_25 (SPM_BASE + 0x5C0)
+#define PCM_WDT_LATCH_26 (SPM_BASE + 0x5C4)
+#define PCM_WDT_LATCH_27 (SPM_BASE + 0x5C8)
+#define PCM_WDT_LATCH_28 (SPM_BASE + 0x5CC)
+#define PCM_WDT_LATCH_29 (SPM_BASE + 0x5D0)
+#define PCM_WDT_LATCH_30 (SPM_BASE + 0x5D4)
+#define PCM_WDT_LATCH_31 (SPM_BASE + 0x5D8)
+#define PCM_WDT_LATCH_32 (SPM_BASE + 0x5DC)
+#define PCM_WDT_LATCH_33 (SPM_BASE + 0x5E0)
+#define PCM_WDT_LATCH_34 (SPM_BASE + 0x5E4)
+#define PCM_WDT_LATCH_35 (SPM_BASE + 0x5EC)
+#define PCM_WDT_LATCH_36 (SPM_BASE + 0x5F0)
+#define PCM_WDT_LATCH_37 (SPM_BASE + 0x5F4)
+#define PCM_WDT_LATCH_38 (SPM_BASE + 0x5F8)
+#define PCM_WDT_LATCH_39 (SPM_BASE + 0x5FC)
+#define SPM_SW_FLAG_0 (SPM_BASE + 0x600)
+#define SPM_SW_DEBUG_0 (SPM_BASE + 0x604)
+#define SPM_SW_FLAG_1 (SPM_BASE + 0x608)
+#define SPM_SW_DEBUG_1 (SPM_BASE + 0x60C)
+#define SPM_SW_RSV_0 (SPM_BASE + 0x610)
+#define SPM_SW_RSV_1 (SPM_BASE + 0x614)
+#define SPM_SW_RSV_2 (SPM_BASE + 0x618)
+#define SPM_SW_RSV_3 (SPM_BASE + 0x61C)
+#define SPM_SW_RSV_4 (SPM_BASE + 0x620)
+#define SPM_SW_RSV_5 (SPM_BASE + 0x624)
+#define SPM_SW_RSV_6 (SPM_BASE + 0x628)
+#define SPM_SW_RSV_7 (SPM_BASE + 0x62C)
+#define SPM_SW_RSV_8 (SPM_BASE + 0x630)
+#define SPM_BK_WAKE_EVENT (SPM_BASE + 0x634)
+#define SPM_BK_VTCXO_DUR (SPM_BASE + 0x638)
+#define SPM_BK_WAKE_MISC (SPM_BASE + 0x63C)
+#define SPM_BK_PCM_TIMER (SPM_BASE + 0x640)
+#define SPM_RSV_CON_0 (SPM_BASE + 0x650)
+#define SPM_RSV_CON_1 (SPM_BASE + 0x654)
+#define SPM_RSV_STA_0 (SPM_BASE + 0x658)
+#define SPM_RSV_STA_1 (SPM_BASE + 0x65C)
+#define SPM_SPARE_CON (SPM_BASE + 0x660)
+#define SPM_SPARE_CON_SET (SPM_BASE + 0x664)
+#define SPM_SPARE_CON_CLR (SPM_BASE + 0x668)
+#define SPM_CROSS_WAKE_M00_REQ (SPM_BASE + 0x66C)
+#define SPM_CROSS_WAKE_M01_REQ (SPM_BASE + 0x670)
+#define SPM_CROSS_WAKE_M02_REQ (SPM_BASE + 0x674)
+#define SPM_CROSS_WAKE_M03_REQ (SPM_BASE + 0x678)
+#define SCP_VCORE_LEVEL (SPM_BASE + 0x67C)
+#define SC_MM_CK_SEL_CON (SPM_BASE + 0x680)
+#define SPARE_ACK_MASK (SPM_BASE + 0x684)
+#define SPM_CROSS_WAKE_M04_REQ (SPM_BASE + 0x688)
+#define SPM_DV_CON_0 (SPM_BASE + 0x68C)
+#define SPM_DV_CON_1 (SPM_BASE + 0x690)
+#define SPM_DV_STA (SPM_BASE + 0x694)
+#define CONN_XOWCN_DEBUG_EN (SPM_BASE + 0x698)
+#define SPM_SEMA_M0 (SPM_BASE + 0x69C)
+#define SPM_SEMA_M1 (SPM_BASE + 0x6A0)
+#define SPM_SEMA_M2 (SPM_BASE + 0x6A4)
+#define SPM_SEMA_M3 (SPM_BASE + 0x6A8)
+#define SPM_SEMA_M4 (SPM_BASE + 0x6AC)
+#define SPM_SEMA_M5 (SPM_BASE + 0x6B0)
+#define SPM_SEMA_M6 (SPM_BASE + 0x6B4)
+#define SPM_SEMA_M7 (SPM_BASE + 0x6B8)
+#define SPM2ADSP_MAILBOX (SPM_BASE + 0x6BC)
+#define ADSP2SPM_MAILBOX (SPM_BASE + 0x6C0)
+#define SPM_ADSP_IRQ (SPM_BASE + 0x6C4)
+#define SPM_MD32_IRQ (SPM_BASE + 0x6C8)
+#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x6CC)
+#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x6D0)
+#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x6D4)
+#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x6D8)
+#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x6DC)
+#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x6E0)
+#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x6E4)
+#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x6E8)
+#define UFS_PSRI_SW (SPM_BASE + 0x6EC)
+#define UFS_PSRI_SW_SET (SPM_BASE + 0x6F0)
+#define UFS_PSRI_SW_CLR (SPM_BASE + 0x6F4)
+#define SPM_AP_SEMA (SPM_BASE + 0x6F8)
+#define SPM_SPM_SEMA (SPM_BASE + 0x6FC)
+#define SPM_DVFS_CON (SPM_BASE + 0x700)
+#define SPM_DVFS_CON_STA (SPM_BASE + 0x704)
+#define SPM_PMIC_SPMI_CON (SPM_BASE + 0x708)
+#define SPM_DVFS_CMD0 (SPM_BASE + 0x710)
+#define SPM_DVFS_CMD1 (SPM_BASE + 0x714)
+#define SPM_DVFS_CMD2 (SPM_BASE + 0x718)
+#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C)
+#define SPM_DVFS_CMD4 (SPM_BASE + 0x720)
+#define SPM_DVFS_CMD5 (SPM_BASE + 0x724)
+#define SPM_DVFS_CMD6 (SPM_BASE + 0x728)
+#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C)
+#define SPM_DVFS_CMD8 (SPM_BASE + 0x730)
+#define SPM_DVFS_CMD9 (SPM_BASE + 0x734)
+#define SPM_DVFS_CMD10 (SPM_BASE + 0x738)
+#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C)
+#define SPM_DVFS_CMD12 (SPM_BASE + 0x740)
+#define SPM_DVFS_CMD13 (SPM_BASE + 0x744)
+#define SPM_DVFS_CMD14 (SPM_BASE + 0x748)
+#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C)
+#define SPM_DVFS_CMD16 (SPM_BASE + 0x750)
+#define SPM_DVFS_CMD17 (SPM_BASE + 0x754)
+#define SPM_DVFS_CMD18 (SPM_BASE + 0x758)
+#define SPM_DVFS_CMD19 (SPM_BASE + 0x75C)
+#define SPM_DVFS_CMD20 (SPM_BASE + 0x760)
+#define SPM_DVFS_CMD21 (SPM_BASE + 0x764)
+#define SPM_DVFS_CMD22 (SPM_BASE + 0x768)
+#define SPM_DVFS_CMD23 (SPM_BASE + 0x76C)
+#define SYS_TIMER_VALUE_L (SPM_BASE + 0x770)
+#define SYS_TIMER_VALUE_H (SPM_BASE + 0x774)
+#define SYS_TIMER_START_L (SPM_BASE + 0x778)
+#define SYS_TIMER_START_H (SPM_BASE + 0x77C)
+#define SYS_TIMER_LATCH_L_00 (SPM_BASE + 0x780)
+#define SYS_TIMER_LATCH_H_00 (SPM_BASE + 0x784)
+#define SYS_TIMER_LATCH_L_01 (SPM_BASE + 0x788)
+#define SYS_TIMER_LATCH_H_01 (SPM_BASE + 0x78C)
+#define SYS_TIMER_LATCH_L_02 (SPM_BASE + 0x790)
+#define SYS_TIMER_LATCH_H_02 (SPM_BASE + 0x794)
+#define SYS_TIMER_LATCH_L_03 (SPM_BASE + 0x798)
+#define SYS_TIMER_LATCH_H_03 (SPM_BASE + 0x79C)
+#define SYS_TIMER_LATCH_L_04 (SPM_BASE + 0x7A0)
+#define SYS_TIMER_LATCH_H_04 (SPM_BASE + 0x7A4)
+#define SYS_TIMER_LATCH_L_05 (SPM_BASE + 0x7A8)
+#define SYS_TIMER_LATCH_H_05 (SPM_BASE + 0x7AC)
+#define SYS_TIMER_LATCH_L_06 (SPM_BASE + 0x7B0)
+#define SYS_TIMER_LATCH_H_06 (SPM_BASE + 0x7B4)
+#define SYS_TIMER_LATCH_L_07 (SPM_BASE + 0x7B8)
+#define SYS_TIMER_LATCH_H_07 (SPM_BASE + 0x7BC)
+#define SYS_TIMER_LATCH_L_08 (SPM_BASE + 0x7C0)
+#define SYS_TIMER_LATCH_H_08 (SPM_BASE + 0x7C4)
+#define SYS_TIMER_LATCH_L_09 (SPM_BASE + 0x7C8)
+#define SYS_TIMER_LATCH_H_09 (SPM_BASE + 0x7CC)
+#define SYS_TIMER_LATCH_L_10 (SPM_BASE + 0x7D0)
+#define SYS_TIMER_LATCH_H_10 (SPM_BASE + 0x7D4)
+#define SYS_TIMER_LATCH_L_11 (SPM_BASE + 0x7D8)
+#define SYS_TIMER_LATCH_H_11 (SPM_BASE + 0x7DC)
+#define SYS_TIMER_LATCH_L_12 (SPM_BASE + 0x7E0)
+#define SYS_TIMER_LATCH_H_12 (SPM_BASE + 0x7E4)
+#define SYS_TIMER_LATCH_L_13 (SPM_BASE + 0x7E8)
+#define SYS_TIMER_LATCH_H_13 (SPM_BASE + 0x7EC)
+#define SYS_TIMER_LATCH_L_14 (SPM_BASE + 0x7F0)
+#define SYS_TIMER_LATCH_H_14 (SPM_BASE + 0x7F4)
+#define SYS_TIMER_LATCH_L_15 (SPM_BASE + 0x7F8)
+#define SYS_TIMER_LATCH_H_15 (SPM_BASE + 0x7FC)
+#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800)
+#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804)
+#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808)
+#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C)
+#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810)
+#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814)
+#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818)
+#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C)
+#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820)
+#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824)
+#define PCM_WDT_LATCH_10 (SPM_BASE + 0x828)
+#define PCM_WDT_LATCH_11 (SPM_BASE + 0x82C)
+#define PCM_WDT_LATCH_12 (SPM_BASE + 0x830)
+#define PCM_WDT_LATCH_13 (SPM_BASE + 0x834)
+#define PCM_WDT_LATCH_14 (SPM_BASE + 0x838)
+#define PCM_WDT_LATCH_15 (SPM_BASE + 0x83C)
+#define PCM_WDT_LATCH_16 (SPM_BASE + 0x840)
+#define PCM_WDT_LATCH_17 (SPM_BASE + 0x844)
+#define PCM_WDT_LATCH_18 (SPM_BASE + 0x848)
+#define PCM_WDT_LATCH_SPARE_0 (SPM_BASE + 0x84C)
+#define PCM_WDT_LATCH_SPARE_1 (SPM_BASE + 0x850)
+#define PCM_WDT_LATCH_SPARE_2 (SPM_BASE + 0x854)
+#define PCM_WDT_LATCH_CONN_0 (SPM_BASE + 0x870)
+#define PCM_WDT_LATCH_CONN_1 (SPM_BASE + 0x874)
+#define PCM_WDT_LATCH_CONN_2 (SPM_BASE + 0x878)
+#define DRAMC_GATING_ERR_LATCH_CH0_0 (SPM_BASE + 0x8A0)
+#define DRAMC_GATING_ERR_LATCH_CH0_1 (SPM_BASE + 0x8A4)
+#define DRAMC_GATING_ERR_LATCH_CH0_2 (SPM_BASE + 0x8A8)
+#define DRAMC_GATING_ERR_LATCH_CH0_3 (SPM_BASE + 0x8AC)
+#define DRAMC_GATING_ERR_LATCH_CH0_4 (SPM_BASE + 0x8B0)
+#define DRAMC_GATING_ERR_LATCH_CH0_5 (SPM_BASE + 0x8B4)
+#define DRAMC_GATING_ERR_LATCH_CH0_6 (SPM_BASE + 0x8B8)
+#define DRAMC_GATING_ERR_LATCH_SPARE_0 (SPM_BASE + 0x8F4)
+#define SPM_ACK_CHK_CON_0 (SPM_BASE + 0x900)
+#define SPM_ACK_CHK_PC_0 (SPM_BASE + 0x904)
+#define SPM_ACK_CHK_SEL_0 (SPM_BASE + 0x908)
+#define SPM_ACK_CHK_TIMER_0 (SPM_BASE + 0x90C)
+#define SPM_ACK_CHK_STA_0 (SPM_BASE + 0x910)
+#define SPM_ACK_CHK_SWINT_0 (SPM_BASE + 0x914)
+#define SPM_ACK_CHK_CON_1 (SPM_BASE + 0x920)
+#define SPM_ACK_CHK_PC_1 (SPM_BASE + 0x924)
+#define SPM_ACK_CHK_SEL_1 (SPM_BASE + 0x928)
+#define SPM_ACK_CHK_TIMER_1 (SPM_BASE + 0x92C)
+#define SPM_ACK_CHK_STA_1 (SPM_BASE + 0x930)
+#define SPM_ACK_CHK_SWINT_1 (SPM_BASE + 0x934)
+#define SPM_ACK_CHK_CON_2 (SPM_BASE + 0x940)
+#define SPM_ACK_CHK_PC_2 (SPM_BASE + 0x944)
+#define SPM_ACK_CHK_SEL_2 (SPM_BASE + 0x948)
+#define SPM_ACK_CHK_TIMER_2 (SPM_BASE + 0x94C)
+#define SPM_ACK_CHK_STA_2 (SPM_BASE + 0x950)
+#define SPM_ACK_CHK_SWINT_2 (SPM_BASE + 0x954)
+#define SPM_ACK_CHK_CON_3 (SPM_BASE + 0x960)
+#define SPM_ACK_CHK_PC_3 (SPM_BASE + 0x964)
+#define SPM_ACK_CHK_SEL_3 (SPM_BASE + 0x968)
+#define SPM_ACK_CHK_TIMER_3 (SPM_BASE + 0x96C)
+#define SPM_ACK_CHK_STA_3 (SPM_BASE + 0x970)
+#define SPM_ACK_CHK_SWINT_3 (SPM_BASE + 0x974)
+#define SPM_COUNTER_0 (SPM_BASE + 0x978)
+#define SPM_COUNTER_1 (SPM_BASE + 0x97C)
+#define SPM_COUNTER_2 (SPM_BASE + 0x980)
+#define SYS_TIMER_CON (SPM_BASE + 0x98C)
+#define RC_FSM_STA_0 (SPM_BASE + 0xE00)
+#define RC_CMD_STA_0 (SPM_BASE + 0xE04)
+#define RC_CMD_STA_1 (SPM_BASE + 0xE08)
+#define RC_SPI_STA_0 (SPM_BASE + 0xE0C)
+#define RC_PI_PO_STA_0 (SPM_BASE + 0xE10)
+#define RC_M00_REQ_STA_0 (SPM_BASE + 0xE14)
+#define RC_M01_REQ_STA_0 (SPM_BASE + 0xE1C)
+#define RC_M02_REQ_STA_0 (SPM_BASE + 0xE20)
+#define RC_M03_REQ_STA_0 (SPM_BASE + 0xE24)
+#define RC_M04_REQ_STA_0 (SPM_BASE + 0xE28)
+#define RC_M05_REQ_STA_0 (SPM_BASE + 0xE2C)
+#define RC_M06_REQ_STA_0 (SPM_BASE + 0xE30)
+#define RC_M07_REQ_STA_0 (SPM_BASE + 0xE34)
+#define RC_M08_REQ_STA_0 (SPM_BASE + 0xE38)
+#define RC_M09_REQ_STA_0 (SPM_BASE + 0xE3C)
+#define RC_M10_REQ_STA_0 (SPM_BASE + 0xE40)
+#define RC_M11_REQ_STA_0 (SPM_BASE + 0xE44)
+#define RC_M12_REQ_STA_0 (SPM_BASE + 0xE48)
+#define RC_DEBUG_STA_0 (SPM_BASE + 0xE4C)
+#define RC_DEBUG_TRACE_0_LSB (SPM_BASE + 0xE50)
+#define RC_DEBUG_TRACE_0_MSB (SPM_BASE + 0xE54)
+#define RC_DEBUG_TRACE_1_LSB (SPM_BASE + 0xE5C)
+#define RC_DEBUG_TRACE_1_MSB (SPM_BASE + 0xE60)
+#define RC_DEBUG_TRACE_2_LSB (SPM_BASE + 0xE64)
+#define RC_DEBUG_TRACE_2_MSB (SPM_BASE + 0xE6C)
+#define RC_DEBUG_TRACE_3_LSB (SPM_BASE + 0xE70)
+#define RC_DEBUG_TRACE_3_MSB (SPM_BASE + 0xE74)
+#define RC_DEBUG_TRACE_4_LSB (SPM_BASE + 0xE78)
+#define RC_DEBUG_TRACE_4_MSB (SPM_BASE + 0xE7C)
+#define RC_DEBUG_TRACE_5_LSB (SPM_BASE + 0xE80)
+#define RC_DEBUG_TRACE_5_MSB (SPM_BASE + 0xE84)
+#define RC_DEBUG_TRACE_6_LSB (SPM_BASE + 0xE88)
+#define RC_DEBUG_TRACE_6_MSB (SPM_BASE + 0xE8C)
+#define RC_DEBUG_TRACE_7_LSB (SPM_BASE + 0xE90)
+#define RC_DEBUG_TRACE_7_MSB (SPM_BASE + 0xE94)
+#define RC_SYS_TIMER_LATCH_0_LSB (SPM_BASE + 0xE98)
+#define RC_SYS_TIMER_LATCH_0_MSB (SPM_BASE + 0xE9C)
+#define RC_SYS_TIMER_LATCH_1_LSB (SPM_BASE + 0xEA0)
+#define RC_SYS_TIMER_LATCH_1_MSB (SPM_BASE + 0xEA4)
+#define RC_SYS_TIMER_LATCH_2_LSB (SPM_BASE + 0xEA8)
+#define RC_SYS_TIMER_LATCH_2_MSB (SPM_BASE + 0xEAC)
+#define RC_SYS_TIMER_LATCH_3_LSB (SPM_BASE + 0xEB0)
+#define RC_SYS_TIMER_LATCH_3_MSB (SPM_BASE + 0xEB4)
+#define RC_SYS_TIMER_LATCH_4_LSB (SPM_BASE + 0xEB8)
+#define RC_SYS_TIMER_LATCH_4_MSB (SPM_BASE + 0xEBC)
+#define RC_SYS_TIMER_LATCH_5_LSB (SPM_BASE + 0xEC0)
+#define RC_SYS_TIMER_LATCH_5_MSB (SPM_BASE + 0xEC4)
+#define RC_SYS_TIMER_LATCH_6_LSB (SPM_BASE + 0xEC8)
+#define RC_SYS_TIMER_LATCH_6_MSB (SPM_BASE + 0xECC)
+#define RC_SYS_TIMER_LATCH_7_LSB (SPM_BASE + 0xED0)
+#define RC_SYS_TIMER_LATCH_7_MSB (SPM_BASE + 0xED4)
+#define PCM_WDT_LATCH_19 (SPM_BASE + 0xED8)
+#define PCM_WDT_LATCH_20 (SPM_BASE + 0xEDC)
+#define PCM_WDT_LATCH_21 (SPM_BASE + 0xEE0)
+#define PCM_WDT_LATCH_22 (SPM_BASE + 0xEE4)
+#define PCM_WDT_LATCH_23 (SPM_BASE + 0xEE8)
+#define PCM_WDT_LATCH_24 (SPM_BASE + 0xEEC)
+#define PMSR_LAST_DAT (SPM_BASE + 0xF00)
+#define PMSR_LAST_CNT (SPM_BASE + 0xF04)
+#define PMSR_LAST_ACK (SPM_BASE + 0xF08)
+#define SPM_PMSR_SEL_CON0 (SPM_BASE + 0xF10)
+#define SPM_PMSR_SEL_CON1 (SPM_BASE + 0xF14)
+#define SPM_PMSR_SEL_CON2 (SPM_BASE + 0xF18)
+#define SPM_PMSR_SEL_CON3 (SPM_BASE + 0xF1C)
+#define SPM_PMSR_SEL_CON4 (SPM_BASE + 0xF20)
+#define SPM_PMSR_SEL_CON5 (SPM_BASE + 0xF24)
+#define SPM_PMSR_SEL_CON6 (SPM_BASE + 0xF28)
+#define SPM_PMSR_SEL_CON7 (SPM_BASE + 0xF2C)
+#define SPM_PMSR_SEL_CON8 (SPM_BASE + 0xF30)
+#define SPM_PMSR_SEL_CON9 (SPM_BASE + 0xF34)
+#define SPM_PMSR_SEL_CON10 (SPM_BASE + 0xF3C)
+#define SPM_PMSR_SEL_CON11 (SPM_BASE + 0xF40)
+#define SPM_PMSR_TIEMR_STA0 (SPM_BASE + 0xFB8)
+#define SPM_PMSR_TIEMR_STA1 (SPM_BASE + 0xFBC)
+#define SPM_PMSR_TIEMR_STA2 (SPM_BASE + 0xFC0)
+#define SPM_PMSR_GENERAL_CON0 (SPM_BASE + 0xFC4)
+#define SPM_PMSR_GENERAL_CON1 (SPM_BASE + 0xFC8)
+#define SPM_PMSR_GENERAL_CON2 (SPM_BASE + 0xFCC)
+#define SPM_PMSR_GENERAL_CON3 (SPM_BASE + 0xFD0)
+#define SPM_PMSR_GENERAL_CON4 (SPM_BASE + 0xFD4)
+#define SPM_PMSR_GENERAL_CON5 (SPM_BASE + 0xFD8)
+#define SPM_PMSR_SW_RESET (SPM_BASE + 0xFDC)
+#define SPM_PMSR_MON_CON0 (SPM_BASE + 0xFE0)
+#define SPM_PMSR_MON_CON1 (SPM_BASE + 0xFE4)
+#define SPM_PMSR_MON_CON2 (SPM_BASE + 0xFE8)
+#define SPM_PMSR_LEN_CON0 (SPM_BASE + 0xFEC)
+#define SPM_PMSR_LEN_CON1 (SPM_BASE + 0xFF0)
+#define SPM_PMSR_LEN_CON2 (SPM_BASE + 0xFF4)
+
+/* POWERON_CONFIG_EN (0x10006000+0x000) */
+#define BCLK_CG_EN_LSB (1U << 0) /* 1b */
+#define PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_POWER_ON_VAL0 (0x10006000+0x004) */
+#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */
+/* SPM_POWER_ON_VAL1 (0x10006000+0x008) */
+#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */
+/* SPM_CLK_CON (0x10006000+0x00C) */
+#define REG_SRCCLKEN0_CTL_LSB (1U << 0) /* 2b */
+#define REG_SRCCLKEN1_CTL_LSB (1U << 2) /* 2b */
+#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */
+#define REG_SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */
+#define REG_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */
+#define REG_MD1_C32RM_EN_LSB (1U << 9) /* 1b */
+#define REG_MD2_C32RM_EN_LSB (1U << 10) /* 1b */
+#define REG_CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */
+#define REG_CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */
+#define REG_SRCCLKEN0_EN_LSB (1U << 13) /* 1b */
+#define REG_SRCCLKEN1_EN_LSB (1U << 14) /* 1b */
+#define SCP_DCM_EN_LSB (1U << 15) /* 1b */
+#define REG_SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 8b */
+#define REG_SYSCLK1_SRC_MASK_B_LSB (1U << 24) /* 8b */
+/* SPM_CLK_SETTLE (0x10006000+0x010) */
+#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */
+/* SPM_AP_STANDBY_CON (0x10006000+0x014) */
+#define REG_WFI_OP_LSB (1U << 0) /* 1b */
+#define REG_WFI_TYPE_LSB (1U << 1) /* 1b */
+#define REG_MP0_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */
+#define REG_MP1_CPUTOP_IDLE_MASK_LSB (1U << 3) /* 1b */
+#define REG_MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */
+#define REG_MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */
+#define REG_MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */
+#define REG_CONN_APSRC_SEL_LSB (1U << 29) /* 1b */
+/* PCM_CON0 (0x10006000+0x018) */
+#define PCM_CK_EN_LSB (1U << 2) /* 1b */
+#define RG_EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */
+#define PCM_CK_FROM_CKSYS_LSB (1U << 4) /* 1b */
+#define PCM_SW_RESET_LSB (1U << 15) /* 1b */
+#define PCM_CON0_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* PCM_CON1 (0x10006000+0x01C) */
+#define RG_IM_SLAVE_LSB (1U << 0) /* 1b */
+#define RG_IM_SLEEP_LSB (1U << 1) /* 1b */
+#define REG_SPM_SRAM_CTRL_MUX_LSB (1U << 2) /* 1b */
+#define RG_AHBMIF_APBEN_LSB (1U << 3) /* 1b */
+#define RG_IM_PDN_LSB (1U << 4) /* 1b */
+#define RG_PCM_TIMER_EN_LSB (1U << 5) /* 1b */
+#define SPM_EVENT_COUNTER_CLR_LSB (1U << 6) /* 1b */
+#define RG_DIS_MIF_PROT_LSB (1U << 7) /* 1b */
+#define RG_PCM_WDT_EN_LSB (1U << 8) /* 1b */
+#define RG_PCM_WDT_WAKE_LSB (1U << 9) /* 1b */
+#define REG_SPM_SRAM_SLEEP_B_LSB (1U << 10) /* 1b */
+#define REG_SPM_SRAM_ISOINT_B_LSB (1U << 11) /* 1b */
+#define REG_EVENT_LOCK_EN_LSB (1U << 12) /* 1b */
+#define REG_SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */
+#define REG_MD32_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */
+#define RG_PCM_IRQ_MSK_LSB (1U << 15) /* 1b */
+#define PCM_CON1_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_POWER_ON_VAL2 (0x10006000+0x020) */
+#define POWER_ON_VAL2_LSB (1U << 0) /* 32b */
+/* SPM_POWER_ON_VAL3 (0x10006000+0x024) */
+#define POWER_ON_VAL3_LSB (1U << 0) /* 32b */
+/* PCM_REG_DATA_INI (0x10006000+0x028) */
+#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */
+/* PCM_PWR_IO_EN (0x10006000+0x02C) */
+#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */
+#define RG_RF_SYNC_EN_LSB (1U << 16) /* 8b */
+/* PCM_TIMER_VAL (0x10006000+0x030) */
+#define REG_PCM_TIMER_VAL_LSB (1U << 0) /* 32b */
+/* PCM_WDT_VAL (0x10006000+0x034) */
+#define RG_PCM_WDT_VAL_LSB (1U << 0) /* 32b */
+/* SPM_SRC6_MASK (0x10006000+0x038) */
+#define REG_DPMAIF_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_DPMAIF_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_DPMAIF_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_DPMAIF_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_DPMAIF_DDR_EN_MASK_B_LSB (1U << 4) /* 1b */
+/* SPM_SW_RST_CON (0x10006000+0x040) */
+#define SPM_SW_RST_CON_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_SW_RST_CON_SET (0x10006000+0x044) */
+#define SPM_SW_RST_CON_SET_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_SET_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_SW_RST_CON_CLR (0x10006000+0x048) */
+#define SPM_SW_RST_CON_CLR_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_CLR_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* VS1_PSR_MASK_B (0x10006000+0x04C) */
+#define VS1_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */
+#define VS1_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */
+/* VS2_PSR_MASK_B (0x10006000+0x050) */
+#define VS2_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */
+#define VS2_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */
+#define VS2_OPP2_PSR_MASK_B_LSB (1U << 16) /* 8b */
+/* MD32_CLK_CON (0x10006000+0x084) */
+#define REG_MD32_26M_CK_SEL_LSB (1U << 0) /* 1b */
+#define REG_MD32_DCM_EN_LSB (1U << 1) /* 1b */
+/* SPM_SRAM_RSV_CON (0x10006000+0x088) */
+#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */
+/* SPM_SWINT (0x10006000+0x08C) */
+#define SPM_SWINT_LSB (1U << 0) /* 32b */
+/* SPM_SWINT_SET (0x10006000+0x090) */
+#define SPM_SWINT_SET_LSB (1U << 0) /* 32b */
+/* SPM_SWINT_CLR (0x10006000+0x094) */
+#define SPM_SWINT_CLR_LSB (1U << 0) /* 32b */
+/* SPM_SCP_MAILBOX (0x10006000+0x098) */
+#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */
+/* SCP_SPM_MAILBOX (0x10006000+0x09C) */
+#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CON (0x10006000+0x0A0) */
+#define REG_TWAM_ENABLE_LSB (1U << 0) /* 1b */
+#define REG_TWAM_SPEED_MODE_EN_LSB (1U << 1) /* 1b */
+#define REG_TWAM_SW_RST_LSB (1U << 2) /* 1b */
+#define REG_TWAM_IRQ_MASK_LSB (1U << 3) /* 1b */
+#define REG_TWAM_MON_TYPE_0_LSB (1U << 4) /* 2b */
+#define REG_TWAM_MON_TYPE_1_LSB (1U << 6) /* 2b */
+#define REG_TWAM_MON_TYPE_2_LSB (1U << 8) /* 2b */
+#define REG_TWAM_MON_TYPE_3_LSB (1U << 10) /* 2b */
+/* SPM_TWAM_WINDOW_LEN (0x10006000+0x0A4) */
+#define REG_TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_IDLE_SEL (0x10006000+0x0A8) */
+#define REG_TWAM_SIG_SEL_0_LSB (1U << 0) /* 7b */
+#define REG_TWAM_SIG_SEL_1_LSB (1U << 8) /* 7b */
+#define REG_TWAM_SIG_SEL_2_LSB (1U << 16) /* 7b */
+#define REG_TWAM_SIG_SEL_3_LSB (1U << 24) /* 7b */
+/* SPM_SCP_IRQ (0x10006000+0x0AC) */
+#define SC_SPM2SCP_WAKEUP_LSB (1U << 0) /* 1b */
+#define SC_SCP2SPM_WAKEUP_LSB (1U << 4) /* 1b */
+/* SPM_CPU_WAKEUP_EVENT (0x10006000+0x0B0) */
+#define REG_CPU_WAKEUP_LSB (1U << 0) /* 1b */
+/* SPM_IRQ_MASK (0x10006000+0x0B4) */
+#define REG_SPM_IRQ_MASK_LSB (1U << 0) /* 32b */
+/* SPM_SRC_REQ (0x10006000+0x0B8) */
+#define REG_SPM_APSRC_REQ_LSB (1U << 0) /* 1b */
+#define REG_SPM_F26M_REQ_LSB (1U << 1) /* 1b */
+#define REG_SPM_INFRA_REQ_LSB (1U << 3) /* 1b */
+#define REG_SPM_VRF18_REQ_LSB (1U << 4) /* 1b */
+#define REG_SPM_DDR_EN_REQ_LSB (1U << 7) /* 1b */
+#define REG_SPM_DVFS_REQ_LSB (1U << 8) /* 1b */
+#define REG_SPM_SW_MAILBOX_REQ_LSB (1U << 9) /* 1b */
+#define REG_SPM_SSPM_MAILBOX_REQ_LSB (1U << 10) /* 1b */
+#define REG_SPM_ADSP_MAILBOX_REQ_LSB (1U << 11) /* 1b */
+#define REG_SPM_SCP_MAILBOX_REQ_LSB (1U << 12) /* 1b */
+/* SPM_SRC_MASK (0x10006000+0x0BC) */
+#define REG_MD_SRCCLKENA_0_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_MD_APSRC2INFRA_REQ_0_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_MD_APSRC_REQ_0_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_MD_VRF18_REQ_0_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_MD_DDR_EN_0_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_MD_SRCCLKENA_1_MASK_B_LSB (1U << 6) /* 1b */
+#define REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B_LSB (1U << 7) /* 1b */
+#define REG_MD_APSRC2INFRA_REQ_1_MASK_B_LSB (1U << 8) /* 1b */
+#define REG_MD_APSRC_REQ_1_MASK_B_LSB (1U << 9) /* 1b */
+#define REG_MD_VRF18_REQ_1_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_MD_DDR_EN_1_MASK_B_LSB (1U << 11) /* 1b */
+#define REG_CONN_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_CONN_SRCCLKENB_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_CONN_INFRA_REQ_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_CONN_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_CONN_VRF18_REQ_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_CONN_DDR_EN_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_CONN_VFE28_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_SRCCLKENI0_SRCCLKENA_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_SRCCLKENI0_INFRA_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_SRCCLKENI1_SRCCLKENA_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_SRCCLKENI1_INFRA_REQ_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_SRCCLKENI2_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_SRCCLKENI2_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_INFRASYS_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_INFRASYS_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_MD32_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_MD32_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_MD32_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_MD32_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_MD32_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */
+/* SPM_SRC2_MASK (0x10006000+0x0C0) */
+#define REG_SCP_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_SCP_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_SCP_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_SCP_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_SCP_DDR_EN_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_AUDIO_DSP_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_AUDIO_DSP_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */
+#define REG_AUDIO_DSP_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */
+#define REG_AUDIO_DSP_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */
+#define REG_AUDIO_DSP_DDR_EN_MASK_B_LSB (1U << 9) /* 1b */
+#define REG_UFS_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_UFS_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */
+#define REG_UFS_APSRC_REQ_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_UFS_VRF18_REQ_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_UFS_DDR_EN_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_DISP0_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_DISP0_DDR_EN_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_DISP1_APSRC_REQ_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_DISP1_DDR_EN_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_GCE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_GCE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_GCE_DDR_EN_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_APU_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_APU_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_APU_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_APU_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_APU_DDR_EN_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_CG_CHECK_SRCCLKENA_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_CG_CHECK_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_CG_CHECK_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_CG_CHECK_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */
+/* SPM_SRC3_MASK (0x10006000+0x0C4) */
+#define REG_DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_SW2SPM_INT0_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_SW2SPM_INT1_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_SW2SPM_INT2_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_SW2SPM_INT3_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_SC_ADSP2SPM_WAKEUP_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_SC_SSPM2SPM_WAKEUP_MASK_B_LSB (1U << 6) /* 4b */
+#define REG_SC_SCP2SPM_WAKEUP_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_CSYSPWRREQ_MASK_LSB (1U << 11) /* 1b */
+#define REG_SPM_SRCCLKENA_RESERVED_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_SPM_INFRA_REQ_RESERVED_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_SPM_APSRC_REQ_RESERVED_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_SPM_VRF18_REQ_RESERVED_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_SPM_DDR_EN_RESERVED_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_MCUPM_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_MCUPM_INFRA_REQ_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_MCUPM_APSRC_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_MCUPM_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_MCUPM_DDR_EN_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_MSDC0_SRCCLKENA_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_MSDC0_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_MSDC0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_MSDC0_VRF18_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_MSDC0_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_MSDC1_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_MSDC1_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_MSDC1_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_MSDC1_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_MSDC1_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */
+/* SPM_SRC4_MASK (0x10006000+0x0C8) */
+#define CCIF_EVENT_MASK_B_LSB (1U << 0) /* 16b */
+#define REG_BAK_PSRI_SRCCLKENA_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_BAK_PSRI_INFRA_REQ_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_BAK_PSRI_APSRC_REQ_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_BAK_PSRI_VRF18_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_BAK_PSRI_DDR_EN_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_DRAMC0_MD32_INFRA_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_DRAMC0_MD32_VRF18_REQ_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_DRAMC1_MD32_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_DRAMC1_MD32_VRF18_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_CONN_SRCCLKENB2PWRAP_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_DRAMC0_MD32_WAKEUP_MASK_LSB (1U << 26) /* 1b */
+#define REG_DRAMC1_MD32_WAKEUP_MASK_LSB (1U << 27) /* 1b */
+/* SPM_SRC5_MASK (0x10006000+0x0CC) */
+#define REG_MCUSYS_MERGE_APSRC_REQ_MASK_B_LSB (1U << 0) /* 9b */
+#define REG_MCUSYS_MERGE_DDR_EN_MASK_B_LSB (1U << 9) /* 9b */
+#define REG_MSDC2_SRCCLKENA_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_MSDC2_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_MSDC2_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_MSDC2_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_MSDC2_DDR_EN_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_PCIE_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_PCIE_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_PCIE_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_PCIE_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_PCIE_DDR_EN_MASK_B_LSB (1U << 27) /* 1b */
+/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0D0) */
+#define REG_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000+0x0D4) */
+#define REG_EXT_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_EVENT_CLEAR (0x10006000+0x0D8) */
+#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */
+/* SCP_CLK_CON (0x10006000+0x0DC) */
+#define REG_SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */
+#define REG_SCP_DCM_EN_LSB (1U << 1) /* 1b */
+#define SCP_SECURE_V_REQ_MASK_LSB (1U << 2) /* 1b */
+#define SCP_SLP_REQ_LSB (1U << 3) /* 1b */
+#define SCP_SLP_ACK_LSB (1U << 4) /* 1b */
+/* PCM_DEBUG_CON (0x10006000+0x0E0) */
+#define PCM_DEBUG_OUT_ENABLE_LSB (1U << 0) /* 1b */
+/* AHB_BUS_CON (0x10006000+0x0E4) */
+#define AHB_HADDR_EXT_LSB (1U << 0) /* 2b */
+#define REG_AHB_LOCK_LSB (1U << 8) /* 1b */
+/* DDR_EN_DBC_CON0 (0x10006000+0x0E8) */
+#define REG_ALL_DDR_EN_DBC_LEN_LSB (1U << 0) /* 10b */
+#define REG_MD_DDR_EN_0_DBC_LEN_LSB (1U << 10) /* 10b */
+#define REG_HW_S1_DBC_LEN_LSB (1U << 20) /* 10b */
+/* DDR_EN_DBC_CON1 (0x10006000+0x0EC) */
+#define REG_ALL_DDR_EN_DBC_EN_LSB (1U << 0) /* 1b */
+#define REG_MD_DDR_EN_0_DBC_EN_LSB (1U << 1) /* 1b */
+#define REG_HW_S1_DBC_EN_LSB (1U << 2) /* 1b */
+/* SPM_RESOURCE_ACK_CON0 (0x10006000+0x0F0) */
+#define REG_MD_SRCCLKENA_ACK_0_MASK_LSB (1U << 0) /* 1b */
+#define REG_MD_INFRA_ACK_0_MASK_LSB (1U << 1) /* 1b */
+#define REG_MD_APSRC_ACK_0_MASK_LSB (1U << 2) /* 1b */
+#define REG_MD_VRF18_ACK_0_MASK_LSB (1U << 3) /* 1b */
+#define REG_MD_DDR_EN_ACK_0_MASK_LSB (1U << 4) /* 1b */
+#define REG_MD_SRCCLKENA_ACK_1_MASK_LSB (1U << 5) /* 1b */
+#define REG_MD_INFRA_ACK_1_MASK_LSB (1U << 6) /* 1b */
+#define REG_MD_APSRC_ACK_1_MASK_LSB (1U << 7) /* 1b */
+#define REG_MD_VRF18_ACK_1_MASK_LSB (1U << 8) /* 1b */
+#define REG_MD_DDR_EN_ACK_1_MASK_LSB (1U << 9) /* 1b */
+#define REG_CONN_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_CONN_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_CONN_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_CONN_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_CONN_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_MD32_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_MD32_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_MD32_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_MD32_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_MD32_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_SCP_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_SCP_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_SCP_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_SCP_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_SCP_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_AUDIO_DSP_SRCCLKENA_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_AUDIO_DSP_INFRA_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_AUDIO_DSP_APSRC_ACK_MASK_LSB (1U << 27) /* 1b */
+#define REG_AUDIO_DSP_VRF18_ACK_MASK_LSB (1U << 28) /* 1b */
+#define REG_AUDIO_DSP_DDR_EN_ACK_MASK_LSB (1U << 29) /* 1b */
+#define REG_DISP0_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */
+#define REG_DISP1_APSRC_ACK_MASK_LSB (1U << 31) /* 1b */
+/* SPM_RESOURCE_ACK_CON1 (0x10006000+0x0F4) */
+#define REG_UFS_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */
+#define REG_UFS_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */
+#define REG_UFS_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */
+#define REG_UFS_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */
+#define REG_UFS_DDR_EN_ACK_MASK_LSB (1U << 4) /* 1b */
+#define REG_APU_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */
+#define REG_APU_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */
+#define REG_APU_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */
+#define REG_APU_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */
+#define REG_APU_DDR_EN_ACK_MASK_LSB (1U << 9) /* 1b */
+#define REG_MCUPM_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_MCUPM_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_MCUPM_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_MCUPM_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_MCUPM_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_MSDC0_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_MSDC0_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_MSDC0_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_MSDC0_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_MSDC0_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_MSDC1_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_MSDC1_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_MSDC1_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_MSDC1_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_MSDC1_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_DISP0_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_DISP1_DDR_EN_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_GCE_INFRA_ACK_MASK_LSB (1U << 27) /* 1b */
+#define REG_GCE_APSRC_ACK_MASK_LSB (1U << 28) /* 1b */
+#define REG_GCE_VRF18_ACK_MASK_LSB (1U << 29) /* 1b */
+#define REG_GCE_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */
+/* SPM_RESOURCE_ACK_CON2 (0x10006000+0x0F8) */
+#define SPM_F26M_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */
+#define SPM_INFRA_ACK_WAIT_CYCLE_LSB (1U << 8) /* 8b */
+#define SPM_APSRC_ACK_WAIT_CYCLE_LSB (1U << 16) /* 8b */
+#define SPM_VRF18_ACK_WAIT_CYCLE_LSB (1U << 24) /* 8b */
+/* SPM_RESOURCE_ACK_CON3 (0x10006000+0x0FC) */
+#define SPM_DDR_EN_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */
+#define REG_BAK_PSRI_SRCCLKENA_ACK_MASK_LSB (1U << 8) /* 1b */
+#define REG_BAK_PSRI_INFRA_ACK_MASK_LSB (1U << 9) /* 1b */
+#define REG_BAK_PSRI_APSRC_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_BAK_PSRI_VRF18_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_BAK_PSRI_DDR_EN_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_MSDC2_SRCCLKENA_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_MSDC2_INFRA_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_MSDC2_APSRC_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_MSDC2_VRF18_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_MSDC2_DDR_EN_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_PCIE_SRCCLKENA_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_PCIE_INFRA_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_PCIE_APSRC_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_PCIE_VRF18_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_PCIE_DDR_EN_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_DPMAIF_SRCCLKENA_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_DPMAIF_INFRA_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_DPMAIF_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_DPMAIF_VRF18_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_DPMAIF_DDR_EN_ACK_MASK_LSB (1U << 27) /* 1b */
+/* PCM_REG0_DATA (0x10006000+0x100) */
+#define PCM_REG0_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG2_DATA (0x10006000+0x104) */
+#define PCM_REG2_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG6_DATA (0x10006000+0x108) */
+#define PCM_REG6_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG7_DATA (0x10006000+0x10C) */
+#define PCM_REG7_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG13_DATA (0x10006000+0x110) */
+#define PCM_REG13_RF_LSB (1U << 0) /* 32b */
+/* SRC_REQ_STA_0 (0x10006000+0x114) */
+#define MD_SRCCLKENA_0_LSB (1U << 0) /* 1b */
+#define MD_SRCCLKENA2INFRA_REQ_0_LSB (1U << 1) /* 1b */
+#define MD_APSRC2INFRA_REQ_0_LSB (1U << 2) /* 1b */
+#define MD_APSRC_REQ_0_LSB (1U << 3) /* 1b */
+#define MD_VRF18_REQ_0_LSB (1U << 4) /* 1b */
+#define MD_DDR_EN_0_LSB (1U << 5) /* 1b */
+#define MD_SRCCLKENA_1_LSB (1U << 6) /* 1b */
+#define MD_SRCCLKENA2INFRA_REQ_1_LSB (1U << 7) /* 1b */
+#define MD_APSRC2INFRA_REQ_1_LSB (1U << 8) /* 1b */
+#define MD_APSRC_REQ_1_LSB (1U << 9) /* 1b */
+#define MD_VRF18_REQ_1_LSB (1U << 10) /* 1b */
+#define MD_DDR_EN_1_LSB (1U << 11) /* 1b */
+#define CONN_SRCCLKENA_LSB (1U << 12) /* 1b */
+#define CONN_SRCCLKENB_LSB (1U << 13) /* 1b */
+#define CONN_INFRA_REQ_LSB (1U << 14) /* 1b */
+#define CONN_APSRC_REQ_LSB (1U << 15) /* 1b */
+#define CONN_VRF18_REQ_LSB (1U << 16) /* 1b */
+#define CONN_DDR_EN_LSB (1U << 17) /* 1b */
+#define SRCCLKENI_LSB (1U << 18) /* 3b */
+#define MD32_SRCCLKENA_LSB (1U << 21) /* 1b */
+#define MD32_INFRA_REQ_LSB (1U << 22) /* 1b */
+#define MD32_APSRC_REQ_LSB (1U << 23) /* 1b */
+#define MD32_VRF18_REQ_LSB (1U << 24) /* 1b */
+#define MD32_DDR_EN_LSB (1U << 25) /* 1b */
+#define DISP0_APSRC_REQ_LSB (1U << 26) /* 1b */
+#define DISP0_DDR_EN_LSB (1U << 27) /* 1b */
+#define DISP1_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define DISP1_DDR_EN_LSB (1U << 29) /* 1b */
+#define DVFSRC_EVENT_TRIGGER_LSB (1U << 30) /* 1b */
+/* SRC_REQ_STA_1 (0x10006000+0x118) */
+#define SCP_SRCCLKENA_LSB (1U << 0) /* 1b */
+#define SCP_INFRA_REQ_LSB (1U << 1) /* 1b */
+#define SCP_APSRC_REQ_LSB (1U << 2) /* 1b */
+#define SCP_VRF18_REQ_LSB (1U << 3) /* 1b */
+#define SCP_DDR_EN_LSB (1U << 4) /* 1b */
+#define AUDIO_DSP_SRCCLKENA_LSB (1U << 5) /* 1b */
+#define AUDIO_DSP_INFRA_REQ_LSB (1U << 6) /* 1b */
+#define AUDIO_DSP_APSRC_REQ_LSB (1U << 7) /* 1b */
+#define AUDIO_DSP_VRF18_REQ_LSB (1U << 8) /* 1b */
+#define AUDIO_DSP_DDR_EN_LSB (1U << 9) /* 1b */
+#define UFS_SRCCLKENA_LSB (1U << 10) /* 1b */
+#define UFS_INFRA_REQ_LSB (1U << 11) /* 1b */
+#define UFS_APSRC_REQ_LSB (1U << 12) /* 1b */
+#define UFS_VRF18_REQ_LSB (1U << 13) /* 1b */
+#define UFS_DDR_EN_LSB (1U << 14) /* 1b */
+#define GCE_INFRA_REQ_LSB (1U << 15) /* 1b */
+#define GCE_APSRC_REQ_LSB (1U << 16) /* 1b */
+#define GCE_VRF18_REQ_LSB (1U << 17) /* 1b */
+#define GCE_DDR_EN_LSB (1U << 18) /* 1b */
+#define INFRASYS_APSRC_REQ_LSB (1U << 19) /* 1b */
+#define INFRASYS_DDR_EN_LSB (1U << 20) /* 1b */
+#define MSDC0_SRCCLKENA_LSB (1U << 21) /* 1b */
+#define MSDC0_INFRA_REQ_LSB (1U << 22) /* 1b */
+#define MSDC0_APSRC_REQ_LSB (1U << 23) /* 1b */
+#define MSDC0_VRF18_REQ_LSB (1U << 24) /* 1b */
+#define MSDC0_DDR_EN_LSB (1U << 25) /* 1b */
+#define MSDC1_SRCCLKENA_LSB (1U << 26) /* 1b */
+#define MSDC1_INFRA_REQ_LSB (1U << 27) /* 1b */
+#define MSDC1_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define MSDC1_VRF18_REQ_LSB (1U << 29) /* 1b */
+#define MSDC1_DDR_EN_LSB (1U << 30) /* 1b */
+/* SRC_REQ_STA_2 (0x10006000+0x11C) */
+#define MCUSYS_MERGE_DDR_EN_LSB (1U << 0) /* 9b */
+#define EMI_SELF_REFRESH_CH_LSB (1U << 9) /* 2b */
+#define SW2SPM_INT_LSB (1U << 11) /* 4b */
+#define SC_ADSP2SPM_WAKEUP_LSB (1U << 15) /* 1b */
+#define SC_SSPM2SPM_WAKEUP_LSB (1U << 16) /* 4b */
+#define SRC_REQ_STA_2_SC_SCP2SPM_WAKEUP_LSB (1U << 20) /* 1b */
+#define SPM_SRCCLKENA_RESERVED_LSB (1U << 21) /* 1b */
+#define SPM_INFRA_REQ_RESERVED_LSB (1U << 22) /* 1b */
+#define SPM_APSRC_REQ_RESERVED_LSB (1U << 23) /* 1b */
+#define SPM_VRF18_REQ_RESERVED_LSB (1U << 24) /* 1b */
+#define SPM_DDR_EN_RESERVED_LSB (1U << 25) /* 1b */
+#define MCUPM_SRCCLKENA_LSB (1U << 26) /* 1b */
+#define MCUPM_INFRA_REQ_LSB (1U << 27) /* 1b */
+#define MCUPM_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define MCUPM_VRF18_REQ_LSB (1U << 29) /* 1b */
+#define MCUPM_DDR_EN_LSB (1U << 30) /* 1b */
+/* PCM_TIMER_OUT (0x10006000+0x120) */
+#define PCM_TIMER_LSB (1U << 0) /* 32b */
+/* PCM_WDT_OUT (0x10006000+0x124) */
+#define PCM_WDT_TIMER_VAL_OUT_LSB (1U << 0) /* 32b */
+/* SPM_IRQ_STA (0x10006000+0x128) */
+#define TWAM_IRQ_LSB (1U << 2) /* 1b */
+#define PCM_IRQ_LSB (1U << 3) /* 1b */
+/* SRC_REQ_STA_4 (0x10006000+0x12C) */
+#define APU_SRCCLKENA_LSB (1U << 0) /* 1b */
+#define APU_INFRA_REQ_LSB (1U << 1) /* 1b */
+#define APU_APSRC_REQ_LSB (1U << 2) /* 1b */
+#define APU_VRF18_REQ_LSB (1U << 3) /* 1b */
+#define APU_DDR_EN_LSB (1U << 4) /* 1b */
+#define BAK_PSRI_SRCCLKENA_LSB (1U << 5) /* 1b */
+#define BAK_PSRI_INFRA_REQ_LSB (1U << 6) /* 1b */
+#define BAK_PSRI_APSRC_REQ_LSB (1U << 7) /* 1b */
+#define BAK_PSRI_VRF18_REQ_LSB (1U << 8) /* 1b */
+#define BAK_PSRI_DDR_EN_LSB (1U << 9) /* 1b */
+#define MSDC2_SRCCLKENA_LSB (1U << 10) /* 1b */
+#define MSDC2_INFRA_REQ_LSB (1U << 11) /* 1b */
+#define MSDC2_APSRC_REQ_LSB (1U << 12) /* 1b */
+#define MSDC2_VRF18_REQ_LSB (1U << 13) /* 1b */
+#define MSDC2_DDR_EN_LSB (1U << 14) /* 1b */
+#define PCIE_SRCCLKENA_LSB (1U << 15) /* 1b */
+#define PCIE_INFRA_REQ_LSB (1U << 16) /* 1b */
+#define PCIE_APSRC_REQ_LSB (1U << 17) /* 1b */
+#define PCIE_VRF18_REQ_LSB (1U << 18) /* 1b */
+#define PCIE_DDR_EN_LSB (1U << 19) /* 1b */
+#define DPMAIF_SRCCLKENA_LSB (1U << 20) /* 1b */
+#define DPMAIF_INFRA_REQ_LSB (1U << 21) /* 1b */
+#define DPMAIF_APSRC_REQ_LSB (1U << 22) /* 1b */
+#define DPMAIF_VRF18_REQ_LSB (1U << 23) /* 1b */
+#define DPMAIF_DDR_EN_LSB (1U << 24) /* 1b */
+/* MD32PCM_WAKEUP_STA (0x10006000+0x130) */
+#define MD32PCM_WAKEUP_STA_LSB (1U << 0) /* 32b */
+/* MD32PCM_EVENT_STA (0x10006000+0x134) */
+#define MD32PCM_EVENT_STA_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_STA (0x10006000+0x138) */
+#define F32K_WAKEUP_EVENT_L_LSB (1U << 0) /* 16b */
+#define ASYN_WAKEUP_EVENT_L_LSB (1U << 16) /* 16b */
+/* SPM_WAKEUP_EXT_STA (0x10006000+0x13C) */
+#define EXT_WAKEUP_EVENT_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_MISC (0x10006000+0x140) */
+#define GIC_WAKEUP_LSB (1U << 0) /* 10b */
+#define DVFSRC_IRQ_LSB (1U << 16) /* 1b */
+#define SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB (1U << 17) /* 1b */
+#define PCM_TIMER_EVENT_LSB (1U << 18) /* 1b */
+#define PMIC_EINT_OUT_B_LSB (1U << 19) /* 2b */
+#define TWAM_IRQ_B_LSB (1U << 21) /* 1b */
+#define PMSR_IRQ_B_SET0_LSB (1U << 22) /* 1b */
+#define PMSR_IRQ_B_SET1_LSB (1U << 23) /* 1b */
+#define PMSR_IRQ_B_SET2_LSB (1U << 24) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_0_LSB (1U << 25) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_1_LSB (1U << 26) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_2_LSB (1U << 27) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_3_LSB (1U << 28) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_ALL_LSB (1U << 29) /* 1b */
+#define PMIC_IRQ_ACK_LSB (1U << 30) /* 1b */
+#define PMIC_SCP_IRQ_LSB (1U << 31) /* 1b */
+/* MM_DVFS_HALT (0x10006000+0x144) */
+#define MM_DVFS_HALT_LSB (1U << 0) /* 5b */
+/* BUS_PROTECT_RDY (0x10006000+0x150) */
+#define PROTECT_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT1_RDY (0x10006000+0x154) */
+#define PROTECT1_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT2_RDY (0x10006000+0x158) */
+#define PROTECT2_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT3_RDY (0x10006000+0x15C) */
+#define PROTECT3_READY_LSB (1U << 0) /* 32b */
+/* SUBSYS_IDLE_STA (0x10006000+0x160) */
+#define SUBSYS_IDLE_SIGNALS_LSB (1U << 0) /* 32b */
+/* PCM_STA (0x10006000+0x164) */
+#define PCM_CK_SEL_O_LSB (1U << 0) /* 4b */
+#define EXT_SRC_STA_LSB (1U << 4) /* 3b */
+/* SRC_REQ_STA_3 (0x10006000+0x168) */
+#define CCIF_EVENT_RAW_STATUS_LSB (1U << 0) /* 16b */
+#define F26M_STATE_LSB (1U << 16) /* 1b */
+#define INFRA_STATE_LSB (1U << 17) /* 1b */
+#define APSRC_STATE_LSB (1U << 18) /* 1b */
+#define VRF18_STATE_LSB (1U << 19) /* 1b */
+#define DDR_EN_STATE_LSB (1U << 20) /* 1b */
+#define DVFS_STATE_LSB (1U << 21) /* 1b */
+#define SW_MAILBOX_STATE_LSB (1U << 22) /* 1b */
+#define SSPM_MAILBOX_STATE_LSB (1U << 23) /* 1b */
+#define ADSP_MAILBOX_STATE_LSB (1U << 24) /* 1b */
+#define SCP_MAILBOX_STATE_LSB (1U << 25) /* 1b */
+/* PWR_STATUS (0x10006000+0x16C) */
+#define PWR_STATUS_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_2ND (0x10006000+0x170) */
+#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */
+/* CPU_PWR_STATUS (0x10006000+0x174) */
+#define MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 1) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 3) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 4) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 5) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 6) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 7) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 8) /* 1b */
+#define MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 9) /* 1b */
+/* OTHER_PWR_STATUS (0x10006000+0x178) */
+#define OTHER_PWR_STATUS_LSB (1U << 0) /* 32b */
+/* SPM_VTCXO_EVENT_COUNT_STA (0x10006000+0x17C) */
+#define SPM_VTCXO_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_VTCXO_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_INFRA_EVENT_COUNT_STA (0x10006000+0x180) */
+#define SPM_INFRA_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_INFRA_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_VRF18_EVENT_COUNT_STA (0x10006000+0x184) */
+#define SPM_VRF18_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_VRF18_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_APSRC_EVENT_COUNT_STA (0x10006000+0x188) */
+#define SPM_APSRC_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_APSRC_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_DDREN_EVENT_COUNT_STA (0x10006000+0x18C) */
+#define SPM_DDREN_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_DDREN_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* MD32PCM_STA (0x10006000+0x190) */
+#define MD32PCM_HALT_LSB (1U << 0) /* 1b */
+#define MD32PCM_GATED_LSB (1U << 1) /* 1b */
+/* MD32PCM_PC (0x10006000+0x194) */
+#define MON_PC_LSB (1U << 0) /* 32b */
+/* DVFSRC_EVENT_STA (0x10006000+0x1A4) */
+#define DVFSRC_EVENT_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT4_RDY (0x10006000+0x1A8) */
+#define PROTECT4_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT5_RDY (0x10006000+0x1AC) */
+#define PROTECT5_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT6_RDY (0x10006000+0x1B0) */
+#define PROTECT6_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT7_RDY (0x10006000+0x1B4) */
+#define PROTECT7_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT8_RDY (0x10006000+0x1B8) */
+#define PROTECT8_READY_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA0 (0x10006000+0x1D0) */
+#define LAST_IDLE_CNT_0_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA1 (0x10006000+0x1D4) */
+#define LAST_IDLE_CNT_1_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA2 (0x10006000+0x1D8) */
+#define LAST_IDLE_CNT_2_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA3 (0x10006000+0x1DC) */
+#define LAST_IDLE_CNT_3_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA0 (0x10006000+0x1E0) */
+#define CURRENT_IDLE_CNT_0_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA1 (0x10006000+0x1E4) */
+#define CURRENT_IDLE_CNT_1_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA2 (0x10006000+0x1E8) */
+#define CURRENT_IDLE_CNT_2_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA3 (0x10006000+0x1EC) */
+#define CURRENT_IDLE_CNT_3_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_TIMER_OUT (0x10006000+0x1F0) */
+#define TWAM_TIMER_LSB (1U << 0) /* 32b */
+/* SPM_CG_CHECK_STA (0x10006000+0x1F4) */
+#define SPM_CG_CHECK_SLEEP_REQ_0_LSB (1U << 0) /* 1b */
+#define SPM_CG_CHECK_SLEEP_REQ_1_LSB (1U << 1) /* 1b */
+#define SPM_CG_CHECK_SLEEP_REQ_2_LSB (1U << 2) /* 1b */
+/* SPM_DVFS_STA (0x10006000+0x1F8) */
+#define TARGET_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_OPP_STA (0x10006000+0x1FC) */
+#define TARGET_DVFS_OPP_LSB (1U << 0) /* 5b */
+#define CURRENT_DVFS_OPP_LSB (1U << 5) /* 5b */
+#define RELAY_DVFS_OPP_LSB (1U << 10) /* 5b */
+/* SPM_MCUSYS_PWR_CON (0x10006000+0x200) */
+#define MCUSYS_SPMC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MCUSYS_SPMC_PWR_ON_LSB (1U << 2) /* 1b */
+#define MCUSYS_SPMC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MCUSYS_SPMC_RESETPWRON_CONFIG_LSB (1U << 5) /* 1b */
+#define MCUSYS_SPMC_DORMANT_EN_LSB (1U << 6) /* 1b */
+#define MCUSYS_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */
+#define SPM_MCUSYS_PWR_CON_MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 31) /* 1b */
+/* SPM_CPUTOP_PWR_CON (0x10006000+0x204) */
+#define MP0_SPMC_PWR_RST_B_CPUTOP_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPUTOP_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_PWR_CLK_DIS_CPUTOP_LSB (1U << 4) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPUTOP_LSB (1U << 5) /* 1b */
+#define MP0_SPMC_DORMANT_EN_CPUTOP_LSB (1U << 6) /* 1b */
+#define MP0_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */
+#define MP0_VSRAM_EXT_OFF_LSB (1U << 8) /* 1b */
+#define SPM_CPUTOP_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 31) /* 1b */
+/* SPM_CPU0_PWR_CON (0x10006000+0x208) */
+#define MP0_SPMC_PWR_RST_B_CPU0_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU0_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU0_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU0_LSB (1U << 7) /* 1b */
+#define SPM_CPU0_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 31) /* 1b */
+/* SPM_CPU1_PWR_CON (0x10006000+0x20C) */
+#define MP0_SPMC_PWR_RST_B_CPU1_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU1_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU1_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU1_LSB (1U << 7) /* 1b */
+#define SPM_CPU1_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 31) /* 1b */
+/* SPM_CPU2_PWR_CON (0x10006000+0x210) */
+#define MP0_SPMC_PWR_RST_B_CPU2_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU2_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU2_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU2_LSB (1U << 7) /* 1b */
+#define SPM_CPU2_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 31) /* 1b */
+/* SPM_CPU3_PWR_CON (0x10006000+0x214) */
+#define MP0_SPMC_PWR_RST_B_CPU3_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU3_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU3_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU3_LSB (1U << 7) /* 1b */
+#define SPM_CPU3_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 31) /* 1b */
+/* SPM_CPU4_PWR_CON (0x10006000+0x218) */
+#define MP0_SPMC_PWR_RST_B_CPU4_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU4_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU4_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU4_LSB (1U << 7) /* 1b */
+#define SPM_CPU4_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 31) /* 1b */
+/* SPM_CPU5_PWR_CON (0x10006000+0x21C) */
+#define MP0_SPMC_PWR_RST_B_CPU5_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU5_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU5_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU5_LSB (1U << 7) /* 1b */
+#define SPM_CPU5_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 31) /* 1b */
+/* SPM_CPU6_PWR_CON (0x10006000+0x220) */
+#define MP0_SPMC_PWR_RST_B_CPU6_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU6_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU6_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU6_LSB (1U << 7) /* 1b */
+#define SPM_CPU6_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 31) /* 1b */
+/* SPM_CPU7_PWR_CON (0x10006000+0x224) */
+#define MP0_SPMC_PWR_RST_B_CPU7_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU7_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU7_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU7_LSB (1U << 7) /* 1b */
+#define SPM_CPU7_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 31) /* 1b */
+/* ARMPLL_CLK_CON (0x10006000+0x22C) */
+#define SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 6b */
+#define SC_ARM_CK_OFF_LSB (1U << 6) /* 6b */
+#define SC_ARMPLL_OFF_LSB (1U << 12) /* 1b */
+#define SC_ARMBPLL_OFF_LSB (1U << 13) /* 1b */
+#define SC_ARMBPLL1_OFF_LSB (1U << 14) /* 1b */
+#define SC_ARMBPLL2_OFF_LSB (1U << 15) /* 1b */
+#define SC_ARMBPLL3_OFF_LSB (1U << 16) /* 1b */
+#define SC_CCIPLL_CKOFF_LSB (1U << 17) /* 1b */
+#define SC_ARMDDS_OFF_LSB (1U << 18) /* 1b */
+#define SC_ARMBPLL_S_OFF_LSB (1U << 19) /* 1b */
+#define SC_ARMBPLL1_S_OFF_LSB (1U << 20) /* 1b */
+#define SC_ARMBPLL2_S_OFF_LSB (1U << 21) /* 1b */
+#define SC_ARMBPLL3_S_OFF_LSB (1U << 22) /* 1b */
+#define SC_CCIPLL_PWROFF_LSB (1U << 23) /* 1b */
+#define SC_ARMPLLOUT_OFF_LSB (1U << 24) /* 1b */
+#define SC_ARMBPLLOUT_OFF_LSB (1U << 25) /* 1b */
+#define SC_ARMBPLLOUT1_OFF_LSB (1U << 26) /* 1b */
+#define SC_ARMBPLLOUT2_OFF_LSB (1U << 27) /* 1b */
+#define SC_ARMBPLLOUT3_OFF_LSB (1U << 28) /* 1b */
+#define SC_CCIPLL_OUT_OFF_LSB (1U << 29) /* 1b */
+/* MCUSYS_IDLE_STA (0x10006000+0x230) */
+#define ARMBUS_IDLE_TO_26M_LSB (1U << 0) /* 1b */
+#define MP0_CLUSTER_IDLE_TO_PWR_OFF_LSB (1U << 1) /* 1b */
+#define MCUSYS_DDR_EN_0_LSB (1U << 2) /* 1b */
+#define MCUSYS_DDR_EN_1_LSB (1U << 3) /* 1b */
+#define MCUSYS_DDR_EN_2_LSB (1U << 4) /* 1b */
+#define MCUSYS_DDR_EN_3_LSB (1U << 5) /* 1b */
+#define MCUSYS_DDR_EN_4_LSB (1U << 6) /* 1b */
+#define MCUSYS_DDR_EN_5_LSB (1U << 7) /* 1b */
+#define MCUSYS_DDR_EN_6_LSB (1U << 8) /* 1b */
+#define MCUSYS_DDR_EN_7_LSB (1U << 9) /* 1b */
+#define MP0_CPU_IDLE_TO_PWR_OFF_LSB (1U << 16) /* 8b */
+#define WFI_AF_SEL_LSB (1U << 24) /* 8b */
+/* GIC_WAKEUP_STA (0x10006000+0x234) */
+#define GIC_WAKEUP_STA_GIC_WAKEUP_LSB (1U << 10) /* 10b */
+/* CPU_SPARE_CON (0x10006000+0x238) */
+#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */
+/* CPU_SPARE_CON_SET (0x10006000+0x23C) */
+#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+/* CPU_SPARE_CON_CLR (0x10006000+0x240) */
+#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+/* ARMPLL_CLK_SEL (0x10006000+0x244) */
+#define ARMPLL_CLK_SEL_LSB (1U << 0) /* 15b */
+/* EXT_INT_WAKEUP_REQ (0x10006000+0x248) */
+#define EXT_INT_WAKEUP_REQ_LSB (1U << 0) /* 10b */
+/* EXT_INT_WAKEUP_REQ_SET (0x10006000+0x24C) */
+#define EXT_INT_WAKEUP_REQ_SET_LSB (1U << 0) /* 10b */
+/* EXT_INT_WAKEUP_REQ_CLR (0x10006000+0x250) */
+#define EXT_INT_WAKEUP_REQ_CLR_LSB (1U << 0) /* 10b */
+/* MP0_CPU0_IRQ_MASK (0x10006000+0x260) */
+#define MP0_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU0_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU1_IRQ_MASK (0x10006000+0x264) */
+#define MP0_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU1_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU2_IRQ_MASK (0x10006000+0x268) */
+#define MP0_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU2_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU3_IRQ_MASK (0x10006000+0x26C) */
+#define MP0_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU3_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU0_IRQ_MASK (0x10006000+0x270) */
+#define MP1_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU0_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU1_IRQ_MASK (0x10006000+0x274) */
+#define MP1_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU1_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU2_IRQ_MASK (0x10006000+0x278) */
+#define MP1_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU2_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU3_IRQ_MASK (0x10006000+0x27C) */
+#define MP1_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU3_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU0_WFI_EN (0x10006000+0x280) */
+#define MP0_CPU0_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU1_WFI_EN (0x10006000+0x284) */
+#define MP0_CPU1_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU2_WFI_EN (0x10006000+0x288) */
+#define MP0_CPU2_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU3_WFI_EN (0x10006000+0x28C) */
+#define MP0_CPU3_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU4_WFI_EN (0x10006000+0x290) */
+#define MP0_CPU4_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU5_WFI_EN (0x10006000+0x294) */
+#define MP0_CPU5_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU6_WFI_EN (0x10006000+0x298) */
+#define MP0_CPU6_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU7_WFI_EN (0x10006000+0x29C) */
+#define MP0_CPU7_WFI_EN_LSB (1U << 0) /* 1b */
+/* ROOT_CPUTOP_ADDR (0x10006000+0x2A0) */
+#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */
+/* ROOT_CORE_ADDR (0x10006000+0x2A4) */
+#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_0 (0x10006000+0x2D0) */
+#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_1 (0x10006000+0x2D4) */
+#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_2 (0x10006000+0x2D8) */
+#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_3 (0x10006000+0x2DC) */
+#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* SW2SPM_INT (0x10006000+0x2E0) */
+#define SW2SPM_INT_SW2SPM_INT_LSB (1U << 0) /* 4b */
+/* SW2SPM_INT_SET (0x10006000+0x2E4) */
+#define SW2SPM_INT_SET_LSB (1U << 0) /* 4b */
+/* SW2SPM_INT_CLR (0x10006000+0x2E8) */
+#define SW2SPM_INT_CLR_LSB (1U << 0) /* 4b */
+/* SW2SPM_MAILBOX_0 (0x10006000+0x2EC) */
+#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_1 (0x10006000+0x2F0) */
+#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_2 (0x10006000+0x2F4) */
+#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_3 (0x10006000+0x2F8) */
+#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* SW2SPM_CFG (0x10006000+0x2FC) */
+#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */
+/* MD1_PWR_CON (0x10006000+0x300) */
+#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MD1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MD1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CONN_PWR_CON (0x10006000+0x304) */
+#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CONN_PWR_ON_LSB (1U << 2) /* 1b */
+#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+/* MFG0_PWR_CON (0x10006000+0x308) */
+#define MFG0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG0_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG0_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG0_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG1_PWR_CON (0x10006000+0x30C) */
+#define MFG1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG2_PWR_CON (0x10006000+0x310) */
+#define MFG2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG2_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG3_PWR_CON (0x10006000+0x314) */
+#define MFG3_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG3_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG3_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG3_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG3_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG3_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG4_PWR_CON (0x10006000+0x318) */
+#define MFG4_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG4_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG4_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG4_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG4_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG4_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG4_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG5_PWR_CON (0x10006000+0x31C) */
+#define MFG5_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG5_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG5_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG5_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG5_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG5_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG5_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG6_PWR_CON (0x10006000+0x320) */
+#define MFG6_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG6_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG6_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG6_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG6_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG6_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG6_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* IFR_PWR_CON (0x10006000+0x324) */
+#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IFR_PWR_ON_LSB (1U << 2) /* 1b */
+#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IFR_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* IFR_SUB_PWR_CON (0x10006000+0x328) */
+#define IFR_SUB_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IFR_SUB_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IFR_SUB_PWR_ON_LSB (1U << 2) /* 1b */
+#define IFR_SUB_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IFR_SUB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IFR_SUB_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IFR_SUB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* DPY_PWR_CON (0x10006000+0x32C) */
+#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DPY_PWR_ON_LSB (1U << 2) /* 1b */
+#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DPY_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DPY_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* ISP_PWR_CON (0x10006000+0x330) */
+#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ISP_PWR_ON_LSB (1U << 2) /* 1b */
+#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ISP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* ISP2_PWR_CON (0x10006000+0x334) */
+#define ISP2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ISP2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ISP2_PWR_ON_LSB (1U << 2) /* 1b */
+#define ISP2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ISP2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ISP2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_ISP2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* IPE_PWR_CON (0x10006000+0x338) */
+#define IPE_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IPE_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IPE_PWR_ON_LSB (1U << 2) /* 1b */
+#define IPE_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IPE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IPE_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IPE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VDE_PWR_CON (0x10006000+0x33C) */
+#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VDE_PWR_ON_LSB (1U << 2) /* 1b */
+#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VDE_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VDE2_PWR_CON (0x10006000+0x340) */
+#define VDE2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VDE2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VDE2_PWR_ON_LSB (1U << 2) /* 1b */
+#define VDE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VDE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VDE2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VDE2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VEN_PWR_CON (0x10006000+0x344) */
+#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VEN_PWR_ON_LSB (1U << 2) /* 1b */
+#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VEN_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VEN_CORE1_PWR_CON (0x10006000+0x348) */
+#define VEN_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VEN_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VEN_CORE1_PWR_ON_LSB (1U << 2) /* 1b */
+#define VEN_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VEN_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VEN_CORE1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VEN_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MDP_PWR_CON (0x10006000+0x34C) */
+#define MDP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MDP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MDP_PWR_ON_LSB (1U << 2) /* 1b */
+#define MDP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MDP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MDP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MDP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* DIS_PWR_CON (0x10006000+0x350) */
+#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DIS_PWR_ON_LSB (1U << 2) /* 1b */
+#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DIS_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* AUDIO_PWR_CON (0x10006000+0x354) */
+#define AUDIO_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define AUDIO_PWR_ISO_LSB (1U << 1) /* 1b */
+#define AUDIO_PWR_ON_LSB (1U << 2) /* 1b */
+#define AUDIO_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define AUDIO_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define AUDIO_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_AUDIO_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* ADSP_PWR_CON (0x10006000+0x358) */
+#define ADSP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ADSP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ADSP_PWR_ON_LSB (1U << 2) /* 1b */
+#define ADSP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ADSP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ADSP_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define ADSP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define ADSP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define ADSP_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */
+#define SC_ADSP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+#define SC_ADSP_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */
+/* CAM_PWR_CON (0x10006000+0x35C) */
+#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CAM_RAWA_PWR_CON (0x10006000+0x360) */
+#define CAM_RAWA_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWA_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWA_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWA_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWA_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CAM_RAWB_PWR_CON (0x10006000+0x364) */
+#define CAM_RAWB_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWB_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWB_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWB_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWB_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CAM_RAWC_PWR_CON (0x10006000+0x368) */
+#define CAM_RAWC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWC_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWC_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWC_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWC_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* SYSRAM_CON (0x10006000+0x36C) */
+#define SYSRAM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SYSRAM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SYSRAM_SRAM_SLEEP_B_LSB (1U << 4) /* 4b */
+#define SYSRAM_SRAM_PDN_LSB (1U << 16) /* 4b */
+/* SYSROM_CON (0x10006000+0x370) */
+#define SYSROM_SRAM_PDN_LSB (1U << 0) /* 6b */
+/* SSPM_SRAM_CON (0x10006000+0x374) */
+#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* SCP_SRAM_CON (0x10006000+0x378) */
+#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* DPY_SHU_SRAM_CON (0x10006000+0x37C) */
+#define DPY_SHU_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPY_SHU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPY_SHU_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */
+#define DPY_SHU_SRAM_PDN_LSB (1U << 16) /* 2b */
+/* UFS_SRAM_CON (0x10006000+0x380) */
+#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */
+#define UFS_SRAM_PDN_LSB (1U << 16) /* 5b */
+/* DEVAPC_IFR_SRAM_CON (0x10006000+0x384) */
+#define DEVAPC_IFR_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_IFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_IFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */
+#define DEVAPC_IFR_SRAM_PDN_LSB (1U << 16) /* 6b */
+/* DEVAPC_SUBIFR_SRAM_CON (0x10006000+0x388) */
+#define DEVAPC_SUBIFR_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_SUBIFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_SUBIFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */
+#define DEVAPC_SUBIFR_SRAM_PDN_LSB (1U << 16) /* 6b */
+/* DEVAPC_ACP_SRAM_CON (0x10006000+0x38C) */
+#define DEVAPC_ACP_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_ACP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_ACP_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */
+#define DEVAPC_ACP_SRAM_PDN_LSB (1U << 16) /* 6b */
+/* USB_SRAM_CON (0x10006000+0x390) */
+#define USB_SRAM_PDN_LSB (1U << 0) /* 7b */
+/* DUMMY_SRAM_CON (0x10006000+0x394) */
+#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */
+#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 8b */
+/* MD_EXT_BUCK_ISO_CON (0x10006000+0x398) */
+#define VMODEM_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */
+#define VMD_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */
+/* EXT_BUCK_ISO (0x10006000+0x39C) */
+#define VIMVO_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */
+#define GPU_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */
+#define ADSP_EXT_BUCK_ISO_LSB (1U << 2) /* 1b */
+#define IPU_EXT_BUCK_ISO_LSB (1U << 5) /* 3b */
+/* DXCC_SRAM_CON (0x10006000+0x3A0) */
+#define DXCC_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DXCC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DXCC_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DXCC_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* MSDC_SRAM_CON (0x10006000+0x3A4) */
+#define MSDC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MSDC_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MSDC_PWR_ON_LSB (1U << 2) /* 1b */
+#define MSDC_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MSDC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MSDC_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MSDC_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MSDC_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MSDC_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */
+#define SC_MSDC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+#define SC_MSDC_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */
+/* DEBUGTOP_SRAM_CON (0x10006000+0x3A8) */
+#define DEBUGTOP_SRAM_PDN_LSB (1U << 0) /* 1b */
+/* DP_TX_PWR_CON (0x10006000+0x3AC) */
+#define DP_TX_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DP_TX_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DP_TX_PWR_ON_LSB (1U << 2) /* 1b */
+#define DP_TX_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DP_TX_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DP_TX_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DP_TX_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* DPMAIF_SRAM_CON (0x10006000+0x3B0) */
+#define DPMAIF_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPMAIF_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPMAIF_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DPMAIF_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* DPY_SHU2_SRAM_CON (0x10006000+0x3B4) */
+#define DPY_SHU2_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPY_SHU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPY_SHU2_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */
+#define DPY_SHU2_SRAM_PDN_LSB (1U << 16) /* 2b */
+/* DRAMC_MCU2_SRAM_CON (0x10006000+0x3B8) */
+#define DRAMC_MCU2_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DRAMC_MCU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DRAMC_MCU2_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DRAMC_MCU2_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* DRAMC_MCU_SRAM_CON (0x10006000+0x3BC) */
+#define DRAMC_MCU_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DRAMC_MCU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DRAMC_MCU_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DRAMC_MCU_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* MCUPM_SRAM_CON (0x10006000+0x3C0) */
+#define MCUPM_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MCUPM_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MCUPM_PWR_ON_LSB (1U << 2) /* 1b */
+#define MCUPM_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MCUPM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MCUPM_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define MCUPM_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define MCUPM_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define MCUPM_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */
+#define SC_MCUPM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+#define SC_MCUPM_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */
+/* DPY2_PWR_CON (0x10006000+0x3C4) */
+#define DPY2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DPY2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DPY2_PWR_ON_LSB (1U << 2) /* 1b */
+#define DPY2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DPY2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DPY2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DPY2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* PERI_PWR_CON (0x10006000+0x3C8) */
+#define PERI_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define PERI_PWR_ISO_LSB (1U << 1) /* 1b */
+#define PERI_PWR_ON_LSB (1U << 2) /* 1b */
+#define PERI_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define PERI_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define PERI_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_PERI_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* SPM_MEM_CK_SEL (0x10006000+0x400) */
+#define SC_MEM_CK_SEL_LSB (1U << 0) /* 1b */
+#define SPM2CKSYS_MEM_CK_MUX_UPDATE_LSB (1U << 1) /* 1b */
+/* SPM_BUS_PROTECT_MASK_B (0x10006000+0X404) */
+#define SPM_BUS_PROTECT_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT1_MASK_B (0x10006000+0x408) */
+#define SPM_BUS_PROTECT1_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT2_MASK_B (0x10006000+0x40C) */
+#define SPM_BUS_PROTECT2_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT3_MASK_B (0x10006000+0x410) */
+#define SPM_BUS_PROTECT3_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT4_MASK_B (0x10006000+0x414) */
+#define SPM_BUS_PROTECT4_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_EMI_BW_MODE (0x10006000+0x418) */
+#define EMI_BW_MODE_LSB (1U << 0) /* 1b */
+#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */
+#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */
+#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */
+/* AP2MD_PEER_WAKEUP (0x10006000+0x41C) */
+#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */
+/* ULPOSC_CON (0x10006000+0x420) */
+#define ULPOSC_EN_LSB (1U << 0) /* 1b */
+#define ULPOSC_RST_LSB (1U << 1) /* 1b */
+#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */
+#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */
+/* SPM2MM_CON (0x10006000+0x424) */
+#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */
+#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */
+#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */
+#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */
+#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */
+#define MM2SPM_FORCE_ULTRA_ACK_D2T_LSB (1U << 16) /* 1b */
+#define MM2SPM_DBL_OSTD_ACT_ACK_D2T_LSB (1U << 17) /* 1b */
+#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */
+#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */
+#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */
+/* SPM_BUS_PROTECT5_MASK_B (0x10006000+0x428) */
+#define SPM_BUS_PROTECT5_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM2MCUPM_CON (0x10006000+0x42C) */
+#define SPM2MCUPM_SW_RST_B_LSB (1U << 0) /* 1b */
+#define SPM2MCUPM_SW_INT_LSB (1U << 1) /* 1b */
+/* AP_MDSRC_REQ (0x10006000+0x430) */
+#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */
+#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */
+#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */
+#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */
+#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */
+#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */
+/* SPM2EMI_ENTER_ULPM (0x10006000+0x434) */
+#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */
+/* SPM2MD_DVFS_CON (0x10006000+0x438) */
+#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */
+/* MD2SPM_DVFS_CON (0x10006000+0x43C) */
+#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT6_MASK_B (0x10006000+0X440) */
+#define SPM_BUS_PROTECT6_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT7_MASK_B (0x10006000+0x444) */
+#define SPM_BUS_PROTECT7_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT8_MASK_B (0x10006000+0x448) */
+#define SPM_BUS_PROTECT8_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PLL_CON (0x10006000+0x44C) */
+#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */
+#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */
+#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */
+#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */
+#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */
+#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */
+#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */
+#define SC_MD32K_CK_OFF_LSB (1U << 17) /* 1b */
+#define SC_CKSQ1_OFF_LSB (1U << 18) /* 1b */
+#define SC_AXI_MEM_CK_OFF_LSB (1U << 19) /* 1b */
+/* CPU_DVFS_REQ (0x10006000+0x450) */
+#define CPU_DVFS_REQ_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_0 (0x10006000+0x454) */
+#define SW_DDR_PST_REQ_LSB (1U << 0) /* 2b */
+#define SW_DDR_PST_ABORT_REQ_LSB (1U << 2) /* 2b */
+/* SPM_DRAM_MCU_SW_CON_1 (0x10006000+0x458) */
+#define SW_DDR_PST_CH0_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_2 (0x10006000+0x45C) */
+#define SW_DDR_PST_CH1_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_3 (0x10006000+0x460) */
+#define SW_DDR_RESERVED_CH0_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_4 (0x10006000+0x464) */
+#define SW_DDR_RESERVED_CH1_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_STA_0 (0x10006000+0x468) */
+#define SC_DDR_PST_ACK_LSB (1U << 0) /* 2b */
+#define SC_DDR_PST_ABORT_ACK_LSB (1U << 2) /* 2b */
+/* SPM_DRAM_MCU_STA_1 (0x10006000+0x46C) */
+#define SC_DDR_CUR_PST_STA_CH0_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_STA_2 (0x10006000+0x470) */
+#define SC_DDR_CUR_PST_STA_CH1_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_SEL_0 (0x10006000+0x474) */
+#define SW_DDR_PST_REQ_SEL_LSB (1U << 0) /* 2b */
+#define SW_DDR_PST_SEL_LSB (1U << 2) /* 2b */
+#define SW_DDR_PST_ABORT_REQ_SEL_LSB (1U << 4) /* 2b */
+#define SW_DDR_RESERVED_SEL_LSB (1U << 6) /* 2b */
+#define SW_DDR_PST_ACK_SEL_LSB (1U << 8) /* 2b */
+#define SW_DDR_PST_ABORT_ACK_SEL_LSB (1U << 10) /* 2b */
+/* RELAY_DVFS_LEVEL (0x10006000+0x478) */
+#define RELAY_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* DRAMC_DPY_CLK_SW_CON_0 (0x10006000+0x480) */
+#define SW_PHYPLL_EN_LSB (1U << 0) /* 2b */
+#define SW_DPY_VREF_EN_LSB (1U << 2) /* 2b */
+#define SW_DPY_DLL_CK_EN_LSB (1U << 4) /* 2b */
+#define SW_DPY_DLL_EN_LSB (1U << 6) /* 2b */
+#define SW_DPY_2ND_DLL_EN_LSB (1U << 8) /* 2b */
+#define SW_MEM_CK_OFF_LSB (1U << 10) /* 2b */
+#define SW_DMSUS_OFF_LSB (1U << 12) /* 2b */
+#define SW_DPY_MODE_SW_LSB (1U << 14) /* 2b */
+#define SW_EMI_CLK_OFF_LSB (1U << 16) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_LSB (1U << 18) /* 2b */
+#define SW_DR_GATE_RETRY_EN_LSB (1U << 20) /* 2b */
+#define SW_DPHY_PRECAL_UP_LSB (1U << 24) /* 2b */
+#define SW_DPY_BCLK_ENABLE_LSB (1U << 26) /* 2b */
+#define SW_TX_TRACKING_DIS_LSB (1U << 28) /* 2b */
+#define SW_DPHY_RXDLY_TRACKING_EN_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_CON_1 (0x10006000+0x484) */
+#define SW_SHU_RESTORE_LSB (1U << 0) /* 2b */
+#define SW_DMYRD_MOD_LSB (1U << 2) /* 2b */
+#define SW_DMYRD_INTV_LSB (1U << 4) /* 2b */
+#define SW_DMYRD_EN_LSB (1U << 6) /* 2b */
+#define SW_DRS_DIS_REQ_LSB (1U << 8) /* 2b */
+#define SW_DR_SRAM_LOAD_LSB (1U << 10) /* 2b */
+#define SW_DR_SRAM_RESTORE_LSB (1U << 12) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_LATCH_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACK_RETRY_EN_LSB (1U << 16) /* 2b */
+#define SW_DPY_MIDPI_EN_LSB (1U << 18) /* 2b */
+#define SW_DPY_PI_RESETB_EN_LSB (1U << 20) /* 2b */
+#define SW_DPY_MCK8X_EN_LSB (1U << 22) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_CH0_LSB (1U << 24) /* 4b */
+#define SW_DR_SHU_LEVEL_SRAM_CH1_LSB (1U << 28) /* 4b */
+/* DRAMC_DPY_CLK_SW_CON_2 (0x10006000+0x488) */
+#define SW_DR_SHU_LEVEL_LSB (1U << 0) /* 2b */
+#define SW_DR_SHU_EN_LSB (1U << 2) /* 1b */
+#define SW_DR_SHORT_QUEUE_LSB (1U << 3) /* 1b */
+#define SW_PHYPLL_MODE_SW_LSB (1U << 4) /* 1b */
+#define SW_PHYPLL2_MODE_SW_LSB (1U << 5) /* 1b */
+#define SW_PHYPLL_SHU_EN_LSB (1U << 6) /* 1b */
+#define SW_PHYPLL2_SHU_EN_LSB (1U << 7) /* 1b */
+#define SW_DR_RESERVED_0_LSB (1U << 24) /* 2b */
+#define SW_DR_RESERVED_1_LSB (1U << 26) /* 2b */
+#define SW_DR_RESERVED_2_LSB (1U << 28) /* 2b */
+#define SW_DR_RESERVED_3_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_CON_3 (0x10006000+0x48C) */
+#define SC_DR_SHU_EN_ACK_LSB (1U << 0) /* 4b */
+#define SC_EMI_CLK_OFF_ACK_LSB (1U << 4) /* 4b */
+#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 8) /* 4b */
+#define SC_DRAMC_DFS_STA_LSB (1U << 12) /* 4b */
+#define SC_DRS_DIS_ACK_LSB (1U << 16) /* 4b */
+#define SC_DR_SRAM_LOAD_ACK_LSB (1U << 20) /* 4b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_LSB (1U << 24) /* 4b */
+#define SC_DR_SRAM_RESTORE_ACK_LSB (1U << 28) /* 4b */
+/* DRAMC_DPY_CLK_SW_SEL_0 (0x10006000+0x490) */
+#define SW_PHYPLL_EN_SEL_LSB (1U << 0) /* 2b */
+#define SW_DPY_VREF_EN_SEL_LSB (1U << 2) /* 2b */
+#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 4) /* 2b */
+#define SW_DPY_DLL_EN_SEL_LSB (1U << 6) /* 2b */
+#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 8) /* 2b */
+#define SW_MEM_CK_OFF_SEL_LSB (1U << 10) /* 2b */
+#define SW_DMSUS_OFF_SEL_LSB (1U << 12) /* 2b */
+#define SW_DPY_MODE_SW_SEL_LSB (1U << 14) /* 2b */
+#define SW_EMI_CLK_OFF_SEL_LSB (1U << 16) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 18) /* 2b */
+#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 20) /* 2b */
+#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 24) /* 2b */
+#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 26) /* 2b */
+#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 28) /* 2b */
+#define SW_DPHY_RXDLY_TRACKING_EN_SEL_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_SEL_1 (0x10006000+0x494) */
+#define SW_SHU_RESTORE_SEL_LSB (1U << 0) /* 2b */
+#define SW_DMYRD_MOD_SEL_LSB (1U << 2) /* 2b */
+#define SW_DMYRD_INTV_SEL_LSB (1U << 4) /* 2b */
+#define SW_DMYRD_EN_SEL_LSB (1U << 6) /* 2b */
+#define SW_DRS_DIS_REQ_SEL_LSB (1U << 8) /* 2b */
+#define SW_DR_SRAM_LOAD_SEL_LSB (1U << 10) /* 2b */
+#define SW_DR_SRAM_RESTORE_SEL_LSB (1U << 12) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_LATCH_SEL_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACK_RETRY_EN_SEL_LSB (1U << 16) /* 2b */
+#define SW_DPY_MIDPI_EN_SEL_LSB (1U << 18) /* 2b */
+#define SW_DPY_PI_RESETB_EN_SEL_LSB (1U << 20) /* 2b */
+#define SW_DPY_MCK8X_EN_SEL_LSB (1U << 22) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_SEL_LSB (1U << 24) /* 2b */
+/* DRAMC_DPY_CLK_SW_SEL_2 (0x10006000+0x498) */
+#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 0) /* 1b */
+#define SW_DR_SHU_EN_SEL_LSB (1U << 2) /* 1b */
+#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 3) /* 1b */
+#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 4) /* 1b */
+#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 5) /* 1b */
+#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 6) /* 1b */
+#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 7) /* 1b */
+#define SW_DR_RESERVED_0_SEL_LSB (1U << 24) /* 2b */
+#define SW_DR_RESERVED_1_SEL_LSB (1U << 26) /* 2b */
+#define SW_DR_RESERVED_2_SEL_LSB (1U << 28) /* 2b */
+#define SW_DR_RESERVED_3_SEL_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_SEL_3 (0x10006000+0x49C) */
+#define SC_DR_SHU_EN_ACK_SEL_LSB (1U << 0) /* 4b */
+#define SC_EMI_CLK_OFF_ACK_SEL_LSB (1U << 4) /* 4b */
+#define SC_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 8) /* 4b */
+#define SC_DRAMC_DFS_STA_SEL_LSB (1U << 12) /* 4b */
+#define SC_DRS_DIS_ACK_SEL_LSB (1U << 16) /* 4b */
+#define SC_DR_SRAM_LOAD_ACK_SEL_LSB (1U << 20) /* 4b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_SEL_LSB (1U << 24) /* 4b */
+#define SC_DR_SRAM_RESTORE_ACK_SEL_LSB (1U << 28) /* 4b */
+/* DRAMC_DPY_CLK_SPM_CON (0x10006000+0x4A0) */
+#define SC_DMYRD_EN_MOD_SEL_PCM_LSB (1U << 0) /* 1b */
+#define SC_DMYRD_INTV_SEL_PCM_LSB (1U << 1) /* 1b */
+#define SC_DMYRD_EN_PCM_LSB (1U << 2) /* 1b */
+#define SC_DRS_DIS_REQ_PCM_LSB (1U << 3) /* 1b */
+#define SC_DR_SHU_LEVEL_SRAM_PCM_LSB (1U << 4) /* 4b */
+#define SC_DR_GATE_RETRY_EN_PCM_LSB (1U << 8) /* 1b */
+#define SC_DR_SHORT_QUEUE_PCM_LSB (1U << 9) /* 1b */
+#define SC_DPY_MIDPI_EN_PCM_LSB (1U << 10) /* 1b */
+#define SC_DPY_PI_RESETB_EN_PCM_LSB (1U << 11) /* 1b */
+#define SC_DPY_MCK8X_EN_PCM_LSB (1U << 12) /* 1b */
+#define SC_DR_RESERVED_0_PCM_LSB (1U << 13) /* 1b */
+#define SC_DR_RESERVED_1_PCM_LSB (1U << 14) /* 1b */
+#define SC_DR_RESERVED_2_PCM_LSB (1U << 15) /* 1b */
+#define SC_DR_RESERVED_3_PCM_LSB (1U << 16) /* 1b */
+#define SC_DMDRAMCSHU_ACK_ALL_LSB (1U << 24) /* 1b */
+#define SC_EMI_CLK_OFF_ACK_ALL_LSB (1U << 25) /* 1b */
+#define SC_DR_SHORT_QUEUE_ACK_ALL_LSB (1U << 26) /* 1b */
+#define SC_DRAMC_DFS_STA_ALL_LSB (1U << 27) /* 1b */
+#define SC_DRS_DIS_ACK_ALL_LSB (1U << 28) /* 1b */
+#define SC_DR_SRAM_LOAD_ACK_ALL_LSB (1U << 29) /* 1b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_ALL_LSB (1U << 30) /* 1b */
+#define SC_DR_SRAM_RESTORE_ACK_ALL_LSB (1U << 31) /* 1b */
+/* SPM_DVFS_LEVEL (0x10006000+0x4A4) */
+#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* SPM_CIRQ_CON (0x10006000+0x4A8) */
+#define CIRQ_CLK_SEL_LSB (1U << 0) /* 1b */
+/* SPM_DVFS_MISC (0x10006000+0x4AC) */
+#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */
+#define SPM2EMI_SLP_PROT_EN_LSB (1U << 1) /* 1b */
+#define SPM_DVFS_FORCE_ENABLE_LSB (1U << 2) /* 1b */
+#define FORCE_DVFS_WAKE_LSB (1U << 3) /* 1b */
+#define SPM_DVFSRC_ENABLE_LSB (1U << 4) /* 1b */
+#define SPM_DVFS_DONE_LSB (1U << 5) /* 1b */
+#define DVFSRC_IRQ_WAKEUP_EVENT_MASK_LSB (1U << 6) /* 1b */
+#define SPM2RC_EVENT_ABORT_LSB (1U << 7) /* 1b */
+#define EMI_SLP_IDLE_LSB (1U << 14) /* 1b */
+#define SDIO_READY_TO_SPM_LSB (1U << 15) /* 1b */
+/* SPM_VS1_VS2_RC_CON (0x10006000+0x4B0) */
+#define VS1_INIT_LEVEL_LSB (1U << 0) /* 2b */
+#define VS1_INIT_LSB (1U << 2) /* 1b */
+#define VS1_CURR_LEVEL_LSB (1U << 3) /* 2b */
+#define VS1_NEXT_LEVEL_LSB (1U << 5) /* 2b */
+#define VS1_VOTE_LEVEL_LSB (1U << 7) /* 2b */
+#define VS1_TRIGGER_LSB (1U << 9) /* 1b */
+#define VS2_INIT_LEVEL_LSB (1U << 10) /* 3b */
+#define VS2_INIT_LSB (1U << 13) /* 1b */
+#define VS2_CURR_LEVEL_LSB (1U << 14) /* 3b */
+#define VS2_NEXT_LEVEL_LSB (1U << 17) /* 3b */
+#define VS2_VOTE_LEVEL_LSB (1U << 20) /* 3b */
+#define VS2_TRIGGER_LSB (1U << 23) /* 1b */
+#define VS1_FORCE_LSB (1U << 24) /* 1b */
+#define VS2_FORCE_LSB (1U << 25) /* 1b */
+#define VS1_VOTE_LEVEL_FORCE_LSB (1U << 26) /* 2b */
+#define VS2_VOTE_LEVEL_FORCE_LSB (1U << 28) /* 3b */
+/* RG_MODULE_SW_CG_0_MASK_REQ_0 (0x10006000+0x4B4) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_0_MASK_REQ_1 (0x10006000+0x4B8) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_0_MASK_REQ_2 (0x10006000+0x4BC) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_1_MASK_REQ_0 (0x10006000+0x4C0) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_1_MASK_REQ_1 (0x10006000+0x4C4) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_1_MASK_REQ_2 (0x10006000+0x4C8) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_2_MASK_REQ_0 (0x10006000+0x4CC) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_2_MASK_REQ_1 (0x10006000+0x4D0) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_2_MASK_REQ_2 (0x10006000+0x4D4) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_3_MASK_REQ_0 (0x10006000+0x4D8) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_3_MASK_REQ_1 (0x10006000+0x4DC) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_3_MASK_REQ_2 (0x10006000+0x4E0) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_MASK_REQ_0 (0x10006000+0x4E4) */
+#define PWR_STATUS_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_MASK_REQ_1 (0x10006000+0x4E8) */
+#define PWR_STATUS_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_MASK_REQ_2 (0x10006000+0x4EC) */
+#define PWR_STATUS_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* SPM_CG_CHECK_CON (0x10006000+0x4F0) */
+#define APMIXEDSYS_BUSY_MASK_REQ_0_LSB (1U << 0) /* 5b */
+#define APMIXEDSYS_BUSY_MASK_REQ_1_LSB (1U << 8) /* 5b */
+#define APMIXEDSYS_BUSY_MASK_REQ_2_LSB (1U << 16) /* 5b */
+#define AUDIOSYS_BUSY_MASK_REQ_0_LSB (1U << 24) /* 1b */
+#define AUDIOSYS_BUSY_MASK_REQ_1_LSB (1U << 25) /* 1b */
+#define AUDIOSYS_BUSY_MASK_REQ_2_LSB (1U << 26) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_0_LSB (1U << 27) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_1_LSB (1U << 28) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_2_LSB (1U << 29) /* 1b */
+/* SPM_SRC_RDY_STA (0x10006000+0x4F4) */
+#define SPM_INFRA_INTERNAL_ACK_LSB (1U << 0) /* 1b */
+#define SPM_VRF18_INTERNAL_ACK_LSB (1U << 1) /* 1b */
+/* SPM_DVS_DFS_LEVEL (0x10006000+0x4F8) */
+#define SPM_DFS_LEVEL_LSB (1U << 0) /* 16b */
+#define SPM_DVS_LEVEL_LSB (1U << 16) /* 16b */
+/* SPM_FORCE_DVFS (0x10006000+0x4FC) */
+#define FORCE_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* SRCLKEN_RC_CFG (0x10006000+0x500) */
+#define SRCLKEN_RC_CFG_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG1 (0x10006000+0x504) */
+#define RC_CENTRAL_CFG1_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG2 (0x10006000+0x508) */
+#define RC_CENTRAL_CFG2_LSB (1U << 0) /* 32b */
+/* RC_CMD_ARB_CFG (0x10006000+0x50C) */
+#define RC_CMD_ARB_CFG_LSB (1U << 0) /* 32b */
+/* RC_PMIC_RCEN_ADDR (0x10006000+0x510) */
+#define RC_PMIC_RCEN_ADDR_LSB (1U << 0) /* 16b */
+#define RC_PMIC_RCEN_RESERVE_LSB (1U << 16) /* 16b */
+/* RC_PMIC_RCEN_SET_CLR_ADDR (0x10006000+0x514) */
+#define RC_PMIC_RCEN_SET_ADDR_LSB (1U << 0) /* 16b */
+#define RC_PMIC_RCEN_CLR_ADDR_LSB (1U << 16) /* 16b */
+/* RC_DCXO_FPM_CFG (0x10006000+0x518) */
+#define RC_DCXO_FPM_CFG_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG3 (0x10006000+0x51C) */
+#define RC_CENTRAL_CFG3_LSB (1U << 0) /* 32b */
+/* RC_M00_SRCLKEN_CFG (0x10006000+0x520) */
+#define RC_M00_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+#define RC_SW_SRCLKEN_RC (1U << 3) /* 1b */
+#define RC_SW_SRCLKEN_FPM (1U << 4) /* 1b */
+/* RC_M01_SRCLKEN_CFG (0x10006000+0x524) */
+#define RC_M01_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M02_SRCLKEN_CFG (0x10006000+0x528) */
+#define RC_M02_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M03_SRCLKEN_CFG (0x10006000+0x52C) */
+#define RC_M03_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M04_SRCLKEN_CFG (0x10006000+0x530) */
+#define RC_M04_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M05_SRCLKEN_CFG (0x10006000+0x534) */
+#define RC_M05_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M06_SRCLKEN_CFG (0x10006000+0x538) */
+#define RC_M06_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M07_SRCLKEN_CFG (0x10006000+0x53C) */
+#define RC_M07_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M08_SRCLKEN_CFG (0x10006000+0x540) */
+#define RC_M08_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M09_SRCLKEN_CFG (0x10006000+0x544) */
+#define RC_M09_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M10_SRCLKEN_CFG (0x10006000+0x548) */
+#define RC_M10_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M11_SRCLKEN_CFG (0x10006000+0x54C) */
+#define RC_M11_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M12_SRCLKEN_CFG (0x10006000+0x550) */
+#define RC_M12_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_SRCLKEN_SW_CON_CFG (0x10006000+0x554) */
+#define RC_SRCLKEN_SW_CON_CFG_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG4 (0x10006000+0x558) */
+#define RC_CENTRAL_CFG4_LSB (1U << 0) /* 32b */
+/* RC_PROTOCOL_CHK_CFG (0x10006000+0x560) */
+#define RC_PROTOCOL_CHK_CFG_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_CFG (0x10006000+0x564) */
+#define RC_DEBUG_CFG_LSB (1U << 0) /* 32b */
+/* RC_MISC_0 (0x10006000+0x5B4) */
+#define SRCCLKENO_LSB (1U << 0) /* 2b */
+#define PCM_SRCCLKENO_LSB (1U << 3) /* 2b */
+#define RC_VREQ_LSB (1U << 5) /* 1b */
+#define RC_SPM_SRCCLKENO_0_ACK_LSB (1U << 6) /* 1b */
+/* RC_SPM_CTRL (0x10006000+0x5B8) */
+#define SPM_AP_26M_RDY_LSB (1U << 0) /* 1b */
+#define KEEP_RC_SPI_ACTIVE_LSB (1U << 1) /* 1b */
+#define SPM2RC_DMY_CTRL_LSB (1U << 2) /* 6b */
+/* SUBSYS_INTF_CFG (0x10006000+0x5BC) */
+#define SRCLKEN_FPM_MASK_B_LSB (1U << 0) /* 13b */
+#define SRCLKEN_BBLPM_MASK_B_LSB (1U << 16) /* 13b */
+/* PCM_WDT_LATCH_25 (0x10006000+0x5C0) */
+#define PCM_WDT_LATCH_25_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_26 (0x10006000+0x5C4) */
+#define PCM_WDT_LATCH_26_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_27 (0x10006000+0x5C8) */
+#define PCM_WDT_LATCH_27_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_28 (0x10006000+0x5CC) */
+#define PCM_WDT_LATCH_28_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_29 (0x10006000+0x5D0) */
+#define PCM_WDT_LATCH_29_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_30 (0x10006000+0x5D4) */
+#define PCM_WDT_LATCH_30_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_31 (0x10006000+0x5D8) */
+#define PCM_WDT_LATCH_31_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_32 (0x10006000+0x5DC) */
+#define PCM_WDT_LATCH_32_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_33 (0x10006000+0x5E0) */
+#define PCM_WDT_LATCH_33_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_34 (0x10006000+0x5E4) */
+#define PCM_WDT_LATCH_34_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_35 (0x10006000+0x5EC) */
+#define PCM_WDT_LATCH_35_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_36 (0x10006000+0x5F0) */
+#define PCM_WDT_LATCH_36_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_37 (0x10006000+0x5F4) */
+#define PCM_WDT_LATCH_37_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_38 (0x10006000+0x5F8) */
+#define PCM_WDT_LATCH_38_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_39 (0x10006000+0x5FC) */
+#define PCM_WDT_LATCH_39_LSB (1U << 0) /* 32b */
+/* SPM_SW_FLAG_0 (0x10006000+0x600) */
+#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */
+/* SPM_SW_DEBUG_0 (0x10006000+0x604) */
+#define SPM_SW_DEBUG_0_LSB (1U << 0) /* 32b */
+/* SPM_SW_FLAG_1 (0x10006000+0x608) */
+#define SPM_SW_FLAG_1_LSB (1U << 0) /* 32b */
+/* SPM_SW_DEBUG_1 (0x10006000+0x60C) */
+#define SPM_SW_DEBUG_1_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_0 (0x10006000+0x610) */
+#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_1 (0x10006000+0x614) */
+#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_2 (0x10006000+0x618) */
+#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_3 (0x10006000+0x61C) */
+#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_4 (0x10006000+0x620) */
+#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_5 (0x10006000+0x624) */
+#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_6 (0x10006000+0x628) */
+#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_7 (0x10006000+0x62C) */
+#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_8 (0x10006000+0x630) */
+#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */
+/* SPM_BK_WAKE_EVENT (0x10006000+0x634) */
+#define SPM_BK_WAKE_EVENT_LSB (1U << 0) /* 32b */
+/* SPM_BK_VTCXO_DUR (0x10006000+0x638) */
+#define SPM_BK_VTCXO_DUR_LSB (1U << 0) /* 32b */
+/* SPM_BK_WAKE_MISC (0x10006000+0x63C) */
+#define SPM_BK_WAKE_MISC_LSB (1U << 0) /* 32b */
+/* SPM_BK_PCM_TIMER (0x10006000+0x640) */
+#define SPM_BK_PCM_TIMER_LSB (1U << 0) /* 32b */
+/* SPM_RSV_CON_0 (0x10006000+0x650) */
+#define SPM_RSV_CON_0_LSB (1U << 0) /* 32b */
+/* SPM_RSV_CON_1 (0x10006000+0x654) */
+#define SPM_RSV_CON_1_LSB (1U << 0) /* 32b */
+/* SPM_RSV_STA_0 (0x10006000+0x658) */
+#define SPM_RSV_STA_0_LSB (1U << 0) /* 32b */
+/* SPM_RSV_STA_1 (0x10006000+0x65C) */
+#define SPM_RSV_STA_1_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON (0x10006000+0x660) */
+#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON_SET (0x10006000+0x664) */
+#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON_CLR (0x10006000+0x668) */
+#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+/* SPM_CROSS_WAKE_M00_REQ (0x10006000+0x66C) */
+#define SPM_CROSS_WAKE_M00_REQ_LSB (1U << 0) /* 5b */
+#define SPM_CROSS_WAKE_M00_CHK_LSB (1U << 8) /* 5b */
+/* SPM_CROSS_WAKE_M01_REQ (0x10006000+0x670) */
+#define SPM_CROSS_WAKE_M01_REQ_LSB (1U << 0) /* 5b */
+#define SPM_CROSS_WAKE_M01_CHK_LSB (1U << 8) /* 5b */
+/* SPM_CROSS_WAKE_M02_REQ (0x10006000+0x674) */
+#define SPM_CROSS_WAKE_M02_REQ_LSB (1U << 0) /* 5b */
+#define SPM_CROSS_WAKE_M02_CHK_LSB (1U << 8) /* 5b */
+/* SPM_CROSS_WAKE_M03_REQ (0x10006000+0x678) */
+#define SPM_CROSS_WAKE_M03_REQ_LSB (1U << 0) /* 5b */
+#define SPM_CROSS_WAKE_M03_CHK_LSB (1U << 8) /* 5b */
+/* SCP_VCORE_LEVEL (0x10006000+0x67C) */
+#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 16b */
+/* SC_MM_CK_SEL_CON (0x10006000+0x680) */
+#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */
+#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */
+/* SPARE_ACK_MASK (0x10006000+0x684) */
+#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_CROSS_WAKE_M04_REQ (0x10006000+0x688) */
+#define SPM_CROSS_WAKE_M04_REQ_LSB (1U << 0) /* 5b */
+#define SPM_CROSS_WAKE_M04_CHK_LSB (1U << 8) /* 5b */
+/* SPM_DV_CON_0 (0x10006000+0x68C) */
+#define SPM_DV_CON_0_LSB (1U << 0) /* 32b */
+/* SPM_DV_CON_1 (0x10006000+0x690) */
+#define SPM_DV_CON_1_LSB (1U << 0) /* 32b */
+/* SPM_DV_STA (0x10006000+0x694) */
+#define SPM_DV_STA_LSB (1U << 0) /* 32b */
+/* CONN_XOWCN_DEBUG_EN (0x10006000+0x698) */
+#define CONN_XOWCN_DEBUG_EN_LSB (1U << 0) /* 1b */
+/* SPM_SEMA_M0 (0x10006000+0x69C) */
+#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M1 (0x10006000+0x6A0) */
+#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M2 (0x10006000+0x6A4) */
+#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M3 (0x10006000+0x6A8) */
+#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M4 (0x10006000+0x6AC) */
+#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M5 (0x10006000+0x6B0) */
+#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M6 (0x10006000+0x6B4) */
+#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M7 (0x10006000+0x6B8) */
+#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */
+/* SPM2ADSP_MAILBOX (0x10006000+0x6BC) */
+#define SPM2ADSP_MAILBOX_LSB (1U << 0) /* 32b */
+/* ADSP2SPM_MAILBOX (0x10006000+0x6C0) */
+#define ADSP2SPM_MAILBOX_LSB (1U << 0) /* 32b */
+/* SPM_ADSP_IRQ (0x10006000+0x6C4) */
+#define SC_SPM2ADSP_WAKEUP_LSB (1U << 0) /* 1b */
+#define SPM_ADSP_IRQ_SC_ADSP2SPM_WAKEUP_LSB (1U << 4) /* 1b */
+/* SPM_MD32_IRQ (0x10006000+0x6C8) */
+#define SC_SPM2SSPM_WAKEUP_LSB (1U << 0) /* 4b */
+#define SPM_MD32_IRQ_SC_SSPM2SPM_WAKEUP_LSB (1U << 4) /* 4b */
+/* SPM2PMCU_MAILBOX_0 (0x10006000+0x6CC) */
+#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_1 (0x10006000+0x6D0) */
+#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_2 (0x10006000+0x6D4) */
+#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_3 (0x10006000+0x6D8) */
+#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_0 (0x10006000+0x6DC) */
+#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_1 (0x10006000+0x6E0) */
+#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_2 (0x10006000+0x6E4) */
+#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_3 (0x10006000+0x6E8) */
+#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* UFS_PSRI_SW (0x10006000+0x6EC) */
+#define UFS_PSRI_SW_LSB (1U << 0) /* 1b */
+/* UFS_PSRI_SW_SET (0x10006000+0x6F0) */
+#define UFS_PSRI_SW_SET_LSB (1U << 0) /* 1b */
+/* UFS_PSRI_SW_CLR (0x10006000+0x6F4) */
+#define UFS_PSRI_SW_CLR_LSB (1U << 0) /* 1b */
+/* SPM_AP_SEMA (0x10006000+0x6F8) */
+#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */
+/* SPM_SPM_SEMA (0x10006000+0x6FC) */
+#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */
+/* SPM_DVFS_CON (0x10006000+0x700) */
+#define SPM_DVFS_CON_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CON_STA (0x10006000+0x704) */
+#define SPM_DVFS_CON_STA_LSB (1U << 0) /* 32b */
+/* SPM_PMIC_SPMI_CON (0x10006000+0x708) */
+#define SPM_PMIC_SPMI_CMD_LSB (1U << 0) /* 2b */
+#define SPM_PMIC_SPMI_SLAVEID_LSB (1U << 2) /* 4b */
+#define SPM_PMIC_SPMI_PMIFID_LSB (1U << 6) /* 1b */
+#define SPM_PMIC_SPMI_DBCNT_LSB (1U << 7) /* 1b */
+/* SPM_DVFS_CMD0 (0x10006000+0x710) */
+#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD1 (0x10006000+0x714) */
+#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD2 (0x10006000+0x718) */
+#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD3 (0x10006000+0x71C) */
+#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD4 (0x10006000+0x720) */
+#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD5 (0x10006000+0x724) */
+#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD6 (0x10006000+0x728) */
+#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD7 (0x10006000+0x72C) */
+#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD8 (0x10006000+0x730) */
+#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD9 (0x10006000+0x734) */
+#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD10 (0x10006000+0x738) */
+#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD11 (0x10006000+0x73C) */
+#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD12 (0x10006000+0x740) */
+#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD13 (0x10006000+0x744) */
+#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD14 (0x10006000+0x748) */
+#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD15 (0x10006000+0x74C) */
+#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD16 (0x10006000+0x750) */
+#define SPM_DVFS_CMD16_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD17 (0x10006000+0x754) */
+#define SPM_DVFS_CMD17_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD18 (0x10006000+0x758) */
+#define SPM_DVFS_CMD18_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD19 (0x10006000+0x75C) */
+#define SPM_DVFS_CMD19_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD20 (0x10006000+0x760) */
+#define SPM_DVFS_CMD20_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD21 (0x10006000+0x764) */
+#define SPM_DVFS_CMD21_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD22 (0x10006000+0x768) */
+#define SPM_DVFS_CMD22_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD23 (0x10006000+0x76C) */
+#define SPM_DVFS_CMD23_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_VALUE_L (0x10006000+0x770) */
+#define SYS_TIMER_VALUE_L_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_VALUE_H (0x10006000+0x774) */
+#define SYS_TIMER_VALUE_H_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_START_L (0x10006000+0x778) */
+#define SYS_TIMER_START_L_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_START_H (0x10006000+0x77C) */
+#define SYS_TIMER_START_H_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_00 (0x10006000+0x780) */
+#define SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_00 (0x10006000+0x784) */
+#define SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_01 (0x10006000+0x788) */
+#define SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_01 (0x10006000+0x78C) */
+#define SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_02 (0x10006000+0x790) */
+#define SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_02 (0x10006000+0x794) */
+#define SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_03 (0x10006000+0x798) */
+#define SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_03 (0x10006000+0x79C) */
+#define SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_04 (0x10006000+0x7A0) */
+#define SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_04 (0x10006000+0x7A4) */
+#define SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_05 (0x10006000+0x7A8) */
+#define SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_05 (0x10006000+0x7AC) */
+#define SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_06 (0x10006000+0x7B0) */
+#define SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_06 (0x10006000+0x7B4) */
+#define SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_07 (0x10006000+0x7B8) */
+#define SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_07 (0x10006000+0x7BC) */
+#define SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_08 (0x10006000+0x7C0) */
+#define SYS_TIMER_LATCH_L_08_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_08 (0x10006000+0x7C4) */
+#define SYS_TIMER_LATCH_H_08_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_09 (0x10006000+0x7C8) */
+#define SYS_TIMER_LATCH_L_09_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_09 (0x10006000+0x7CC) */
+#define SYS_TIMER_LATCH_H_09_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_10 (0x10006000+0x7D0) */
+#define SYS_TIMER_LATCH_L_10_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_10 (0x10006000+0x7D4) */
+#define SYS_TIMER_LATCH_H_10_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_11 (0x10006000+0x7D8) */
+#define SYS_TIMER_LATCH_L_11_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_11 (0x10006000+0x7DC) */
+#define SYS_TIMER_LATCH_H_11_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_12 (0x10006000+0x7E0) */
+#define SYS_TIMER_LATCH_L_12_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_12 (0x10006000+0x7E4) */
+#define SYS_TIMER_LATCH_H_12_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_13 (0x10006000+0x7E8) */
+#define SYS_TIMER_LATCH_L_13_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_13 (0x10006000+0x7EC) */
+#define SYS_TIMER_LATCH_H_13_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_14 (0x10006000+0x7F0) */
+#define SYS_TIMER_LATCH_L_14_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_14 (0x10006000+0x7F4) */
+#define SYS_TIMER_LATCH_H_14_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_15 (0x10006000+0x7F8) */
+#define SYS_TIMER_LATCH_L_15_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_15 (0x10006000+0x7FC) */
+#define SYS_TIMER_LATCH_H_15_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_0 (0x10006000+0x800) */
+#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_1 (0x10006000+0x804) */
+#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_2 (0x10006000+0x808) */
+#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_3 (0x10006000+0x80C) */
+#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_4 (0x10006000+0x810) */
+#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_5 (0x10006000+0x814) */
+#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_6 (0x10006000+0x818) */
+#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_7 (0x10006000+0x81C) */
+#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_8 (0x10006000+0x820) */
+#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_9 (0x10006000+0x824) */
+#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_10 (0x10006000+0x828) */
+#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_11 (0x10006000+0x82C) */
+#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_12 (0x10006000+0x830) */
+#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_13 (0x10006000+0x834) */
+#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_14 (0x10006000+0x838) */
+#define PCM_WDT_LATCH_14_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_15 (0x10006000+0x83C) */
+#define PCM_WDT_LATCH_15_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_16 (0x10006000+0x840) */
+#define PCM_WDT_LATCH_16_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_17 (0x10006000+0x844) */
+#define PCM_WDT_LATCH_17_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_18 (0x10006000+0x848) */
+#define PCM_WDT_LATCH_18_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_SPARE_0 (0x10006000+0x84C) */
+#define PCM_WDT_LATCH_SPARE_0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_SPARE_1 (0x10006000+0x850) */
+#define PCM_WDT_LATCH_SPARE_1_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_SPARE_2 (0x10006000+0x854) */
+#define PCM_WDT_LATCH_SPARE_2_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_CONN_0 (0x10006000+0x870) */
+#define PCM_WDT_LATCH_CONN_0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_CONN_1 (0x10006000+0x874) */
+#define PCM_WDT_LATCH_CONN_1_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_CONN_2 (0x10006000+0x878) */
+#define PCM_WDT_LATCH_CONN_2_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_0 (0x10006000+0x8A0) */
+#define DRAMC_GATING_ERR_LATCH_CH0_0_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_1 (0x10006000+0x8A4) */
+#define DRAMC_GATING_ERR_LATCH_CH0_1_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_2 (0x10006000+0x8A8) */
+#define DRAMC_GATING_ERR_LATCH_CH0_2_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_3 (0x10006000+0x8AC) */
+#define DRAMC_GATING_ERR_LATCH_CH0_3_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_4 (0x10006000+0x8B0) */
+#define DRAMC_GATING_ERR_LATCH_CH0_4_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_5 (0x10006000+0x8B4) */
+#define DRAMC_GATING_ERR_LATCH_CH0_5_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_6 (0x10006000+0x8B8) */
+#define DRAMC_GATING_ERR_LATCH_CH0_6_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_SPARE_0 (0x10006000+0x8F4) */
+#define DRAMC_GATING_ERR_LATCH_SPARE_0_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_0 (0x10006000+0x900) */
+#define SPM_ACK_CHK_SW_EN_0_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_0_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_0_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_0_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_0_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_0_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_0_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_0_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_0_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_0_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_0_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_0 (0x10006000+0x904) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_0_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_0_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_0 (0x10006000+0x908) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_0_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_0_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_0_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_0_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_0 (0x10006000+0x90C) */
+#define SPM_ACK_CHK_TIMER_VAL_0_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_0_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_0 (0x10006000+0x910) */
+#define SPM_ACK_CHK_STA_0_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_0 (0x10006000+0x914) */
+#define SPM_ACK_CHK_SWINT_EN_0_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_1 (0x10006000+0x920) */
+#define SPM_ACK_CHK_SW_EN_1_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_1_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_1_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_1_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_1_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_1_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_1_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_1_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_1_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_1_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_1_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_1 (0x10006000+0x924) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_1_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_1_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_1 (0x10006000+0x928) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_1_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_1_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_1_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_1_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_1 (0x10006000+0x92C) */
+#define SPM_ACK_CHK_TIMER_VAL_1_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_1_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_1 (0x10006000+0x930) */
+#define SPM_ACK_CHK_STA_1_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_1 (0x10006000+0x934) */
+#define SPM_ACK_CHK_SWINT_EN_1_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_2 (0x10006000+0x940) */
+#define SPM_ACK_CHK_SW_EN_2_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_2_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_2_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_2_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_2_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_2_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_2_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_2_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_2_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_2_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_2_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_2 (0x10006000+0x944) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_2_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_2 (0x10006000+0x948) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_2_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_2_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_2_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_2_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_2 (0x10006000+0x94C) */
+#define SPM_ACK_CHK_TIMER_VAL_2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_2_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_2 (0x10006000+0x950) */
+#define SPM_ACK_CHK_STA_2_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_2 (0x10006000+0x954) */
+#define SPM_ACK_CHK_SWINT_EN_2_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_3 (0x10006000+0x960) */
+#define SPM_ACK_CHK_SW_EN_3_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_3_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_3_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_3_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_3_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_3_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_3_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_3_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_3_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_3_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_3_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_3 (0x10006000+0x964) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_3_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_3 (0x10006000+0x968) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_3_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_3_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_3_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_3_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_3 (0x10006000+0x96C) */
+#define SPM_ACK_CHK_TIMER_VAL_3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_3_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_3 (0x10006000+0x970) */
+#define SPM_ACK_CHK_STA_3_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_3 (0x10006000+0x974) */
+#define SPM_ACK_CHK_SWINT_EN_3_LSB (1U << 0) /* 32b */
+/* SPM_COUNTER_0 (0x10006000+0x978) */
+#define SPM_COUNTER_VAL_0_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_0_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_0_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_0_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_0_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_0_LSB (1U << 31) /* 1b */
+/* SPM_COUNTER_1 (0x10006000+0x97C) */
+#define SPM_COUNTER_VAL_1_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_1_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_1_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_1_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_1_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_1_LSB (1U << 31) /* 1b */
+/* SPM_COUNTER_2 (0x10006000+0x980) */
+#define SPM_COUNTER_VAL_2_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_2_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_2_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_2_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_2_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_2_LSB (1U << 31) /* 1b */
+/* SYS_TIMER_CON (0x10006000+0x98C) */
+#define SYS_TIMER_START_EN_LSB (1U << 0) /* 1b */
+#define SYS_TIMER_LATCH_EN_LSB (1U << 1) /* 1b */
+#define SYS_TIMER_ID_LSB (1U << 8) /* 8b */
+#define SYS_TIMER_VALID_LSB (1U << 31) /* 1b */
+/* RC_FSM_STA_0 (0x10006000+0xE00) */
+#define RC_FSM_STA_0_LSB (1U << 0) /* 32b */
+/* RC_CMD_STA_0 (0x10006000+0xE04) */
+#define RC_CMD_STA_0_LSB (1U << 0) /* 32b */
+/* RC_CMD_STA_1 (0x10006000+0xE08) */
+#define RC_CMD_STA_1_LSB (1U << 0) /* 32b */
+/* RC_SPI_STA_0 (0x10006000+0xE0C) */
+#define RC_SPI_STA_0_LSB (1U << 0) /* 32b */
+/* RC_PI_PO_STA_0 (0x10006000+0xE10) */
+#define RC_PI_PO_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M00_REQ_STA_0 (0x10006000+0xE14) */
+#define RC_M00_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M01_REQ_STA_0 (0x10006000+0xE1C) */
+#define RC_M01_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M02_REQ_STA_0 (0x10006000+0xE20) */
+#define RC_M02_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M03_REQ_STA_0 (0x10006000+0xE24) */
+#define RC_M03_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M04_REQ_STA_0 (0x10006000+0xE28) */
+#define RC_M04_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M05_REQ_STA_0 (0x10006000+0xE2C) */
+#define RC_M05_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M06_REQ_STA_0 (0x10006000+0xE30) */
+#define RC_M06_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M07_REQ_STA_0 (0x10006000+0xE34) */
+#define RC_M07_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M08_REQ_STA_0 (0x10006000+0xE38) */
+#define RC_M08_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M09_REQ_STA_0 (0x10006000+0xE3C) */
+#define RC_M09_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M10_REQ_STA_0 (0x10006000+0xE40) */
+#define RC_M10_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M11_REQ_STA_0 (0x10006000+0xE44) */
+#define RC_M11_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M12_REQ_STA_0 (0x10006000+0xE48) */
+#define RC_M12_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_STA_0 (0x10006000+0xE4C) */
+#define RC_DEBUG_STA_0_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_0_LSB (0x10006000+0xE50) */
+#define RO_PMRC_TRACE_00_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_0_MSB (0x10006000+0xE54) */
+#define RO_PMRC_TRACE_00_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_1_LSB (0x10006000+0xE5C) */
+#define RO_PMRC_TRACE_01_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_1_MSB (0x10006000+0xE60) */
+#define RO_PMRC_TRACE_01_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_2_LSB (0x10006000+0xE64) */
+#define RO_PMRC_TRACE_02_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_2_MSB (0x10006000+0xE6C) */
+#define RO_PMRC_TRACE_02_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_3_LSB (0x10006000+0xE70) */
+#define RO_PMRC_TRACE_03_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_3_MSB (0x10006000+0xE74) */
+#define RO_PMRC_TRACE_03_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_4_LSB (0x10006000+0xE78) */
+#define RO_PMRC_TRACE_04_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_4_MSB (0x10006000+0xE7C) */
+#define RO_PMRC_TRACE_04_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_5_LSB (0x10006000+0xE80) */
+#define RO_PMRC_TRACE_05_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_5_MSB (0x10006000+0xE84) */
+#define RO_PMRC_TRACE_05_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_6_LSB (0x10006000+0xE88) */
+#define RO_PMRC_TRACE_06_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_6_MSB (0x10006000+0xE8C) */
+#define RO_PMRC_TRACE_06_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_7_LSB (0x10006000+0xE90) */
+#define RO_PMRC_TRACE_07_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_7_MSB (0x10006000+0xE94) */
+#define RO_PMRC_TRACE_07_MSB_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_0_LSB (0x10006000+0xE98) */
+#define RC_SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_0_MSB (0x10006000+0xE9C) */
+#define RC_SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_1_LSB (0x10006000+0xEA0) */
+#define RC_SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_1_MSB (0x10006000+0xEA4) */
+#define RC_SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_2_LSB (0x10006000+0xEA8) */
+#define RC_SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_2_MSB (0x10006000+0xEAC) */
+#define RC_SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_3_LSB (0x10006000+0xEB0) */
+#define RC_SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_3_MSB (0x10006000+0xEB4) */
+#define RC_SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_4_LSB (0x10006000+0xEB8) */
+#define RC_SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_4_MSB (0x10006000+0xEBC) */
+#define RC_SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_5_LSB (0x10006000+0xEC0) */
+#define RC_SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_5_MSB (0x10006000+0xEC4) */
+#define RC_SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_6_LSB (0x10006000+0xEC8) */
+#define RC_SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_6_MSB (0x10006000+0xECC) */
+#define RC_SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_7_LSB (0x10006000+0xED0) */
+#define RC_SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_7_MSB (0x10006000+0xED4) */
+#define RC_SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_19 (0x10006000+0xED8) */
+#define PCM_WDT_LATCH_19_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_20 (0x10006000+0xEDC) */
+#define PCM_WDT_LATCH_20_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_21 (0x10006000+0xEE0) */
+#define PCM_WDT_LATCH_21_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_22 (0x10006000+0xEE4) */
+#define PCM_WDT_LATCH_22_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_23 (0x10006000+0xEE8) */
+#define PCM_WDT_LATCH_23_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_24 (0x10006000+0xEEC) */
+#define PCM_WDT_LATCH_24_LSB (1U << 0) /* 32b */
+/* PMSR_LAST_DAT (0x10006000+0xF00) */
+#define PMSR_LAST_DAT_LSB (1U << 0) /* 32b */
+/* PMSR_LAST_CNT (0x10006000+0xF04) */
+#define PMSR_LAST_CMD_LSB (1U << 0) /* 30b */
+#define PMSR_LAST_REQ_LSB (1U << 30) /* 1b */
+/* PMSR_LAST_ACK (0x10006000+0xF08) */
+#define PMSR_LAST_ACK_LSB (1U << 0) /* 1b */
+/* SPM_PMSR_SEL_CON0 (0x10006000+0xF10) */
+#define REG_PMSR_SIG_SEL_0_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_1_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_2_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_3_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON1 (0x10006000+0xF14) */
+#define REG_PMSR_SIG_SEL_4_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_5_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_6_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_7_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON2 (0x10006000+0xF18) */
+#define REG_PMSR_SIG_SEL_8_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_9_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_10_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_11_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON3 (0x10006000+0xF1C) */
+#define REG_PMSR_SIG_SEL_12_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_13_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_14_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_15_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON4 (0x10006000+0xF20) */
+#define REG_PMSR_SIG_SEL_16_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_17_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_18_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_19_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON5 (0x10006000+0xF24) */
+#define REG_PMSR_SIG_SEL_20_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_21_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_22_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_23_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON6 (0x10006000+0xF28) */
+#define REG_PMSR_SIG_SEL_24_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_25_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_26_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_27_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON7 (0x10006000+0xF2C) */
+#define REG_PMSR_SIG_SEL_28_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_29_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_30_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_31_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON8 (0x10006000+0xF30) */
+#define REG_PMSR_SIG_SEL_32_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_33_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_34_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_35_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON9 (0x10006000+0xF34) */
+#define REG_PMSR_SIG_SEL_36_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_37_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_38_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_39_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON10 (0x10006000+0xF3C) */
+#define REG_PMSR_SIG_SEL_40_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_41_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_42_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_43_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON11 (0x10006000+0xF40) */
+#define REG_PMSR_SIG_SEL_44_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_45_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_46_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_47_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_TIEMR_STA0 (0x10006000+0xFB8) */
+#define PMSR_TIMER_SET0_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_TIEMR_STA1 (0x10006000+0xFBC) */
+#define PMSR_TIMER_SET1_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_TIEMR_STA2 (0x10006000+0xFC0) */
+#define PMSR_TIMER_SET2_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON0 (0x10006000+0xFC4) */
+#define PMSR_ENABLE_SET0_LSB (1U << 0) /* 1b */
+#define PMSR_ENABLE_SET1_LSB (1U << 1) /* 1b */
+#define PMSR_ENABLE_SET2_LSB (1U << 2) /* 1b */
+#define PMSR_IRQ_CLR_SET0_LSB (1U << 3) /* 1b */
+#define PMSR_IRQ_CLR_SET1_LSB (1U << 4) /* 1b */
+#define PMSR_IRQ_CLR_SET2_LSB (1U << 5) /* 1b */
+#define PMSR_SPEED_MODE_EN_SET0_LSB (1U << 6) /* 1b */
+#define PMSR_SPEED_MODE_EN_SET1_LSB (1U << 7) /* 1b */
+#define PMSR_SPEED_MODE_EN_SET2_LSB (1U << 8) /* 1b */
+#define PMSR_EVENT_CLR_SET0_LSB (1U << 9) /* 1b */
+#define PMSR_EVENT_CLR_SET1_LSB (1U << 10) /* 1b */
+#define PMSR_EVENT_CLR_SET2_LSB (1U << 11) /* 1b */
+#define REG_PMSR_IRQ_MASK_SET0_LSB (1U << 12) /* 1b */
+#define REG_PMSR_IRQ_MASK_SET1_LSB (1U << 13) /* 1b */
+#define REG_PMSR_IRQ_MASK_SET2_LSB (1U << 14) /* 1b */
+#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET0_LSB (1U << 15) /* 1b */
+#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET1_LSB (1U << 16) /* 1b */
+#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET2_LSB (1U << 17) /* 1b */
+#define PMSR_GEN_SW_RST_EN_LSB (1U << 18) /* 1b */
+#define PMSR_MODULE_ENABLE_LSB (1U << 19) /* 1b */
+#define PMSR_MODE_LSB (1U << 20) /* 2b */
+#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET0_LSB (1U << 29) /* 1b */
+#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET1_LSB (1U << 30) /* 1b */
+#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET2_LSB (1U << 31) /* 1b */
+/* SPM_PMSR_GENERAL_CON1 (0x10006000+0xFC8) */
+#define PMSR_COUNTER_THRES_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON2 (0x10006000+0xFCC) */
+#define PMSR_DEBUG_IN_0_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON3 (0x10006000+0xFD0) */
+#define PMSR_DEBUG_IN_1_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON4 (0x10006000+0xFD4) */
+#define PMSR_DEBUG_IN_2_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON5 (0x10006000+0xFD8) */
+#define PMSR_DEBUG_IN_3_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_SW_RESET (0x10006000+0xFDC) */
+#define PMSR_SW_RST_EN_SET0_LSB (1U << 0) /* 1b */
+#define PMSR_SW_RST_EN_SET1_LSB (1U << 1) /* 1b */
+#define PMSR_SW_RST_EN_SET2_LSB (1U << 2) /* 1b */
+/* SPM_PMSR_MON_CON0 (0x10006000+0xFE0) */
+#define REG_PMSR_MON_TYPE_0_LSB (1U << 0) /* 2b */
+#define REG_PMSR_MON_TYPE_1_LSB (1U << 2) /* 2b */
+#define REG_PMSR_MON_TYPE_2_LSB (1U << 4) /* 2b */
+#define REG_PMSR_MON_TYPE_3_LSB (1U << 6) /* 2b */
+#define REG_PMSR_MON_TYPE_4_LSB (1U << 8) /* 2b */
+#define REG_PMSR_MON_TYPE_5_LSB (1U << 10) /* 2b */
+#define REG_PMSR_MON_TYPE_6_LSB (1U << 12) /* 2b */
+#define REG_PMSR_MON_TYPE_7_LSB (1U << 14) /* 2b */
+#define REG_PMSR_MON_TYPE_8_LSB (1U << 16) /* 2b */
+#define REG_PMSR_MON_TYPE_9_LSB (1U << 18) /* 2b */
+#define REG_PMSR_MON_TYPE_10_LSB (1U << 20) /* 2b */
+#define REG_PMSR_MON_TYPE_11_LSB (1U << 22) /* 2b */
+#define REG_PMSR_MON_TYPE_12_LSB (1U << 24) /* 2b */
+#define REG_PMSR_MON_TYPE_13_LSB (1U << 26) /* 2b */
+#define REG_PMSR_MON_TYPE_14_LSB (1U << 28) /* 2b */
+#define REG_PMSR_MON_TYPE_15_LSB (1U << 30) /* 2b */
+/* SPM_PMSR_MON_CON1 (0x10006000+0xFE4) */
+#define REG_PMSR_MON_TYPE_16_LSB (1U << 0) /* 2b */
+#define REG_PMSR_MON_TYPE_17_LSB (1U << 2) /* 2b */
+#define REG_PMSR_MON_TYPE_18_LSB (1U << 4) /* 2b */
+#define REG_PMSR_MON_TYPE_19_LSB (1U << 6) /* 2b */
+#define REG_PMSR_MON_TYPE_20_LSB (1U << 8) /* 2b */
+#define REG_PMSR_MON_TYPE_21_LSB (1U << 10) /* 2b */
+#define REG_PMSR_MON_TYPE_22_LSB (1U << 12) /* 2b */
+#define REG_PMSR_MON_TYPE_23_LSB (1U << 14) /* 2b */
+#define REG_PMSR_MON_TYPE_24_LSB (1U << 16) /* 2b */
+#define REG_PMSR_MON_TYPE_25_LSB (1U << 18) /* 2b */
+#define REG_PMSR_MON_TYPE_26_LSB (1U << 20) /* 2b */
+#define REG_PMSR_MON_TYPE_27_LSB (1U << 22) /* 2b */
+#define REG_PMSR_MON_TYPE_28_LSB (1U << 24) /* 2b */
+#define REG_PMSR_MON_TYPE_29_LSB (1U << 26) /* 2b */
+#define REG_PMSR_MON_TYPE_30_LSB (1U << 28) /* 2b */
+#define REG_PMSR_MON_TYPE_31_LSB (1U << 30) /* 2b */
+/* SPM_PMSR_MON_CON2 (0x10006000+0xFE8) */
+#define REG_PMSR_MON_TYPE_32_LSB (1U << 0) /* 2b */
+#define REG_PMSR_MON_TYPE_33_LSB (1U << 2) /* 2b */
+#define REG_PMSR_MON_TYPE_34_LSB (1U << 4) /* 2b */
+#define REG_PMSR_MON_TYPE_35_LSB (1U << 6) /* 2b */
+#define REG_PMSR_MON_TYPE_36_LSB (1U << 8) /* 2b */
+#define REG_PMSR_MON_TYPE_37_LSB (1U << 10) /* 2b */
+#define REG_PMSR_MON_TYPE_38_LSB (1U << 12) /* 2b */
+#define REG_PMSR_MON_TYPE_39_LSB (1U << 14) /* 2b */
+#define REG_PMSR_MON_TYPE_40_LSB (1U << 16) /* 2b */
+#define REG_PMSR_MON_TYPE_41_LSB (1U << 18) /* 2b */
+#define REG_PMSR_MON_TYPE_42_LSB (1U << 20) /* 2b */
+#define REG_PMSR_MON_TYPE_43_LSB (1U << 22) /* 2b */
+#define REG_PMSR_MON_TYPE_44_LSB (1U << 24) /* 2b */
+#define REG_PMSR_MON_TYPE_45_LSB (1U << 26) /* 2b */
+#define REG_PMSR_MON_TYPE_46_LSB (1U << 28) /* 2b */
+#define REG_PMSR_MON_TYPE_47_LSB (1U << 30) /* 2b */
+/* SPM_PMSR_LEN_CON0 (0x10006000+0xFEC) */
+#define REG_PMSR_WINDOW_LEN_SET0_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_LEN_CON1 (0x10006000+0xFF0) */
+#define REG_PMSR_WINDOW_LEN_SET1_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_LEN_CON2 (0x10006000+0xFF4) */
+#define REG_PMSR_WINDOW_LEN_SET2_LSB (1U << 0) /* 32b */
+
+#define SPM_PROJECT_CODE 0xb16
+#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16)
+#endif /* MT_SPM_REG */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h
new file mode 100644
index 0000000..30194eb
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_RESOURCE_REQ_H
+#define MT_SPM_RESOURCE_REQ_H
+
+/* SPM resource request internal bit */
+#define MT_SPM_BIT_XO_FPM 0
+#define MT_SPM_BIT_26M 1
+#define MT_SPM_BIT_INFRA 2
+#define MT_SPM_BIT_SYSPLL 3
+#define MT_SPM_BIT_DRAM_S0 4
+#define MT_SPM_BIT_DRAM_S1 5
+
+/* SPM resource request internal bit_mask */
+#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM)
+#define MT_SPM_26M BIT(MT_SPM_BIT_26M)
+#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA)
+#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL)
+#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0)
+#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1)
+#endif /* MT_SPM_RESOURCE_REQ_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c
new file mode 100644
index 0000000..3eb73d4
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <uart.h>
+
+#define SPM_SUSPEND_SLEEP_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
+ SPM_FLAG_USE_SRCCLKENO2 | \
+ SPM_FLAG_ENABLE_MD_MUMTAS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL)
+
+#define SPM_SUSPEND_SLEEP_PCM_FLAG1 \
+ (SPM_FLAG1_DISABLE_MD26M_CK_OFF)
+
+#define SPM_SUSPEND_PCM_FLAG \
+ (SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_ENABLE_TIA_WORKAROUND | \
+ SPM_FLAG_ENABLE_MD_MUMTAS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL)
+
+#define SPM_SUSPEND_PCM_FLAG1 \
+ (SPM_FLAG1_DISABLE_MD26M_CK_OFF)
+
+#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \
+ (R12_PCM_TIMER | \
+ R12_KP_IRQ_B | \
+ R12_APWDT_EVENT_B | \
+ R12_APXGPT1_EVENT_B | \
+ R12_CONN2AP_SPM_WAKEUP_B | \
+ R12_EINT_EVENT_B | \
+ R12_CONN_WDT_IRQ_B | \
+ R12_CCIF0_EVENT_B | \
+ R12_SSPM2SPM_WAKEUP_B | \
+ R12_SCP2SPM_WAKEUP_B | \
+ R12_ADSP2SPM_WAKEUP_B | \
+ R12_USBX_CDSC_B | \
+ R12_USBX_POWERDWN_B | \
+ R12_SYS_TIMER_EVENT_B | \
+ R12_EINT_EVENT_SECURE_B | \
+ R12_CCIF1_EVENT_B | \
+ R12_SYS_CIRQ_IRQ_B | \
+ R12_MD2AP_PEER_EVENT_B | \
+ R12_MD1_WDT_B | \
+ R12_CLDMA_EVENT_B | \
+ R12_REG_CPU_WAKEUP | \
+ R12_APUSYS_WAKE_HOST_B | \
+ R12_PCIE_BRIDGE_IRQ | \
+ R12_PCIE_IRQ)
+
+#if defined(CFG_MICROTRUST_TEE_SUPPORT)
+#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__)
+#else
+#define WAKE_SRC_FOR_SUSPEND \
+ (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \
+ R12_SEJ_EVENT_B)
+#endif
+
+static struct pwr_ctrl suspend_ctrl = {
+ .wake_src = WAKE_SRC_FOR_SUSPEND,
+ .pcm_flags = SPM_SUSPEND_PCM_FLAG | SPM_FLAG_DISABLE_INFRA_PDN,
+ .pcm_flags1 = SPM_SUSPEND_PCM_FLAG1,
+
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ .reg_wfi_op = 0,
+ .reg_wfi_type = 0,
+ .reg_mp0_cputop_idle_mask = 0,
+ .reg_mp1_cputop_idle_mask = 0,
+ .reg_mcusys_idle_mask = 0,
+ .reg_md_apsrc_1_sel = 0,
+ .reg_md_apsrc_0_sel = 0,
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC6_MASK */
+ .reg_dpmaif_srcclkena_mask_b = 1,
+ .reg_dpmaif_infra_req_mask_b = 1,
+ .reg_dpmaif_apsrc_req_mask_b = 1,
+ .reg_dpmaif_vrf18_req_mask_b = 1,
+ .reg_dpmaif_ddr_en_mask_b = 1,
+
+ /* SPM_SRC_REQ */
+ .reg_spm_apsrc_req = 0,
+ .reg_spm_f26m_req = 0,
+ .reg_spm_infra_req = 0,
+ .reg_spm_vrf18_req = 0,
+ .reg_spm_ddr_en_req = 0,
+ .reg_spm_dvfs_req = 0,
+ .reg_spm_sw_mailbox_req = 0,
+ .reg_spm_sspm_mailbox_req = 0,
+ .reg_spm_adsp_mailbox_req = 0,
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC_MASK */
+ .reg_md_srcclkena_0_mask_b = 1,
+ .reg_md_srcclkena2infra_req_0_mask_b = 0,
+ .reg_md_apsrc2infra_req_0_mask_b = 1,
+ .reg_md_apsrc_req_0_mask_b = 1,
+ .reg_md_vrf18_req_0_mask_b = 1,
+ .reg_md_ddr_en_0_mask_b = 1,
+ .reg_md_srcclkena_1_mask_b = 0,
+ .reg_md_srcclkena2infra_req_1_mask_b = 0,
+ .reg_md_apsrc2infra_req_1_mask_b = 0,
+ .reg_md_apsrc_req_1_mask_b = 0,
+ .reg_md_vrf18_req_1_mask_b = 0,
+ .reg_md_ddr_en_1_mask_b = 0,
+ .reg_conn_srcclkena_mask_b = 1,
+ .reg_conn_srcclkenb_mask_b = 0,
+ .reg_conn_infra_req_mask_b = 1,
+ .reg_conn_apsrc_req_mask_b = 1,
+ .reg_conn_vrf18_req_mask_b = 1,
+ .reg_conn_ddr_en_mask_b = 1,
+ .reg_conn_vfe28_mask_b = 0,
+ .reg_srcclkeni0_srcclkena_mask_b = 1,
+ .reg_srcclkeni0_infra_req_mask_b = 1,
+ .reg_srcclkeni1_srcclkena_mask_b = 0,
+ .reg_srcclkeni1_infra_req_mask_b = 0,
+ .reg_srcclkeni2_srcclkena_mask_b = 0,
+ .reg_srcclkeni2_infra_req_mask_b = 0,
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ .reg_infrasys_ddr_en_mask_b = 1,
+ .reg_md32_srcclkena_mask_b = 1,
+ .reg_md32_infra_req_mask_b = 1,
+ .reg_md32_apsrc_req_mask_b = 1,
+ .reg_md32_vrf18_req_mask_b = 1,
+ .reg_md32_ddr_en_mask_b = 1,
+
+ /* SPM_SRC2_MASK */
+ .reg_scp_srcclkena_mask_b = 1,
+ .reg_scp_infra_req_mask_b = 1,
+ .reg_scp_apsrc_req_mask_b = 1,
+ .reg_scp_vrf18_req_mask_b = 1,
+ .reg_scp_ddr_en_mask_b = 1,
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ .reg_audio_dsp_ddr_en_mask_b = 1,
+ .reg_ufs_srcclkena_mask_b = 1,
+ .reg_ufs_infra_req_mask_b = 1,
+ .reg_ufs_apsrc_req_mask_b = 1,
+ .reg_ufs_vrf18_req_mask_b = 1,
+ .reg_ufs_ddr_en_mask_b = 1,
+ .reg_disp0_apsrc_req_mask_b = 1,
+ .reg_disp0_ddr_en_mask_b = 1,
+ .reg_disp1_apsrc_req_mask_b = 1,
+ .reg_disp1_ddr_en_mask_b = 1,
+ .reg_gce_infra_req_mask_b = 1,
+ .reg_gce_apsrc_req_mask_b = 1,
+ .reg_gce_vrf18_req_mask_b = 1,
+ .reg_gce_ddr_en_mask_b = 1,
+ .reg_apu_srcclkena_mask_b = 1,
+ .reg_apu_infra_req_mask_b = 1,
+ .reg_apu_apsrc_req_mask_b = 1,
+ .reg_apu_vrf18_req_mask_b = 1,
+ .reg_apu_ddr_en_mask_b = 1,
+ .reg_cg_check_srcclkena_mask_b = 0,
+ .reg_cg_check_apsrc_req_mask_b = 0,
+ .reg_cg_check_vrf18_req_mask_b = 0,
+ .reg_cg_check_ddr_en_mask_b = 0,
+
+ /* SPM_SRC3_MASK */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+ .reg_sw2spm_int0_mask_b = 0,
+ .reg_sw2spm_int1_mask_b = 0,
+ .reg_sw2spm_int2_mask_b = 0,
+ .reg_sw2spm_int3_mask_b = 0,
+ .reg_sc_adsp2spm_wakeup_mask_b = 0,
+ .reg_sc_sspm2spm_wakeup_mask_b = 0,
+ .reg_sc_scp2spm_wakeup_mask_b = 0,
+ .reg_csyspwrreq_mask = 1,
+ .reg_spm_srcclkena_reserved_mask_b = 0,
+ .reg_spm_infra_req_reserved_mask_b = 0,
+ .reg_spm_apsrc_req_reserved_mask_b = 0,
+ .reg_spm_vrf18_req_reserved_mask_b = 0,
+ .reg_spm_ddr_en_reserved_mask_b = 0,
+ .reg_mcupm_srcclkena_mask_b = 1,
+ .reg_mcupm_infra_req_mask_b = 1,
+ .reg_mcupm_apsrc_req_mask_b = 1,
+ .reg_mcupm_vrf18_req_mask_b = 1,
+ .reg_mcupm_ddr_en_mask_b = 1,
+ .reg_msdc0_srcclkena_mask_b = 1,
+ .reg_msdc0_infra_req_mask_b = 1,
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ .reg_msdc0_ddr_en_mask_b = 1,
+ .reg_msdc1_srcclkena_mask_b = 1,
+ .reg_msdc1_infra_req_mask_b = 1,
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ .reg_msdc1_ddr_en_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ .ccif_event_mask_b = 0xFFF,
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ .reg_bak_psri_infra_req_mask_b = 0,
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ .reg_bak_psri_ddr_en_mask_b = 0,
+ .reg_dramc0_md32_infra_req_mask_b = 1,
+ .reg_dramc0_md32_vrf18_req_mask_b = 0,
+ .reg_dramc1_md32_infra_req_mask_b = 1,
+ .reg_dramc1_md32_vrf18_req_mask_b = 0,
+ .reg_conn_srcclkenb2pwrap_mask_b = 0,
+ .reg_dramc0_md32_wakeup_mask = 1,
+ .reg_dramc1_md32_wakeup_mask = 1,
+
+ /* SPM_SRC5_MASK */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x11,
+ .reg_mcusys_merge_ddr_en_mask_b = 0x11,
+ .reg_msdc2_srcclkena_mask_b = 1,
+ .reg_msdc2_infra_req_mask_b = 1,
+ .reg_msdc2_apsrc_req_mask_b = 1,
+ .reg_msdc2_vrf18_req_mask_b = 1,
+ .reg_msdc2_ddr_en_mask_b = 1,
+ .reg_pcie_srcclkena_mask_b = 1,
+ .reg_pcie_infra_req_mask_b = 1,
+ .reg_pcie_apsrc_req_mask_b = 1,
+ .reg_pcie_vrf18_req_mask_b = 1,
+ .reg_pcie_ddr_en_mask_b = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ .reg_wakeup_event_mask = 0x01382202,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+
+ /* Auto-gen End */
+};
+
+struct spm_lp_scen __spm_suspend = {
+ .pwrctrl = &suspend_ctrl,
+};
+
+int mt_spm_suspend_mode_set(int mode)
+{
+ if (mode == MT_SPM_SUSPEND_SLEEP) {
+ suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG;
+ suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1;
+ } else {
+ suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG;
+ suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1;
+ }
+
+ return 0;
+}
+
+int mt_spm_suspend_enter(int state_id, unsigned int ext_opand,
+ unsigned int resource_req)
+{
+ /* If FMAudio / ADSP is active, change to sleep suspend mode */
+ if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
+ mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP);
+ }
+
+ /* Notify MCUPM that device is going suspend flow */
+ mmio_write_32(MCUPM_MBOX_OFFSET_PDN, MCUPM_POWER_DOWN);
+
+ /* Notify UART to sleep */
+ mt_uart_save();
+
+ return spm_conservation(state_id, ext_opand,
+ &__spm_suspend, resource_req);
+}
+
+void mt_spm_suspend_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status)
+{
+ spm_conservation_finish(state_id, ext_opand, &__spm_suspend, status);
+
+ /* Notify UART to wakeup */
+ mt_uart_restore();
+
+ /* Notify MCUPM that device leave suspend */
+ mmio_write_32(MCUPM_MBOX_OFFSET_PDN, 0);
+
+ /* If FMAudio / ADSP is active, change back to suspend mode */
+ if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
+ mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN);
+ }
+}
+
+void mt_spm_suspend_init(void)
+{
+ spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl);
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h
new file mode 100644
index 0000000..08bbad2
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SUSPEND_H
+#define MT_SPM_SUSPEND_H
+
+#include <mt_spm_internal.h>
+
+#define MCUPM_MBOX_OFFSET_PDN 0x0C55FDA8
+#define MCUPM_POWER_DOWN 0x4D50444E
+
+enum MT_SPM_SUSPEND_MODE {
+ MT_SPM_SUSPEND_SYSTEM_PDN,
+ MT_SPM_SUSPEND_SLEEP,
+};
+
+extern int mt_spm_suspend_mode_set(int mode);
+extern int mt_spm_suspend_enter(int state_id, unsigned int ext_opand,
+ unsigned int reosuce_req);
+extern void mt_spm_suspend_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status);
+extern void mt_spm_suspend_init(void);
+#endif /* MT_SPM_SUSPEND_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c
new file mode 100644
index 0000000..f74ea80
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright(C)2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <lib/utils_def.h>
+
+#include <mtk_sip_svc.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+#include "mt_spm.h"
+#include "mt_spm_internal.h"
+#include "mt_spm_reg.h"
+#include "mt_spm_vcorefs.h"
+#include "mt_spm_pmic_wrap.h"
+
+#define VCORE_CT_ENABLE (1U << 5)
+#define SW_REQ5_INIT_VAL (6U << 12)
+#define V_VMODE_SHIFT 0
+#define VCORE_HV 105
+#define VCORE_LV 95
+#define PMIC_STEP_UV 6250
+
+static const struct reg_config dvfsrc_init_configs[] = {
+ /* Setup opp table */
+ { DVFSRC_LEVEL_LABEL_0_1, 0x50436053 },
+ { DVFSRC_LEVEL_LABEL_2_3, 0x40335042 },
+ { DVFSRC_LEVEL_LABEL_4_5, 0x40314032 },
+ { DVFSRC_LEVEL_LABEL_6_7, 0x30223023 },
+ { DVFSRC_LEVEL_LABEL_8_9, 0x20133021 },
+ { DVFSRC_LEVEL_LABEL_10_11, 0x20112012 },
+ { DVFSRC_LEVEL_LABEL_12_13, 0x10032010 },
+ { DVFSRC_LEVEL_LABEL_14_15, 0x10011002 },
+ { DVFSRC_LEVEL_LABEL_16_17, 0x00131000 },
+ { DVFSRC_LEVEL_LABEL_18_19, 0x00110012 },
+ { DVFSRC_LEVEL_LABEL_20_21, 0x00000010 },
+
+ /* Setup hw emi qos policy */
+ { DVFSRC_DDR_REQUEST, 0x00004321 },
+ { DVFSRC_DDR_REQUEST3, 0x00000065 },
+
+ /* Setup up for PCIe */
+ { DVFSRC_PCIE_VCORE_REQ, 0x0A298001 },
+
+ /* Setup up HRT QOS policy */
+ { DVFSRC_HRT_BW_BASE, 0x00000004 },
+ { DVFSRC_HRT_REQ_UNIT, 0x0000001E },
+ { DVFSRC_HRT_HIGH_3, 0x18A618A6 },
+ { DVFSRC_HRT_HIGH_2, 0x18A61183 },
+ { DVFSRC_HRT_HIGH_1, 0x0D690B80 },
+ { DVFSRC_HRT_HIGH, 0x070804B0 },
+ { DVFSRC_HRT_LOW_3, 0x18A518A5 },
+ { DVFSRC_HRT_LOW_2, 0x18A51182 },
+ { DVFSRC_HRT_LOW_1, 0x0D680B7F },
+ { DVFSRC_HRT_LOW, 0x070704AF },
+ { DVFSRC_HRT_REQUEST, 0x66654321 },
+ /* Setup up SRT QOS policy */
+ { DVFSRC_QOS_EN, 0x0011007C },
+ { DVFSRC_DDR_QOS0, 0x00000019 },
+ { DVFSRC_DDR_QOS1, 0x00000026 },
+ { DVFSRC_DDR_QOS2, 0x00000033 },
+ { DVFSRC_DDR_QOS3, 0x0000003B },
+ { DVFSRC_DDR_QOS4, 0x0000004C },
+ { DVFSRC_DDR_QOS5, 0x00000066 },
+ { DVFSRC_DDR_QOS6, 0x00000066 },
+ { DVFSRC_DDR_REQUEST5, 0x54321000 },
+ { DVFSRC_DDR_REQUEST7, 0x66000000 },
+ /* Setup up hifi request policy */
+ { DVFSRC_DDR_REQUEST6, 0x66543210 },
+ /* Setup up hw request vcore policy */
+ { DVFSRC_VCORE_USER_REQ, 0x00010A29 },
+
+ /* Setup misc*/
+ { DVFSRC_TIMEOUT_NEXTREQ, 0x00000015 },
+ { DVFSRC_RSRV_5, 0x00000001 },
+ { DVFSRC_INT_EN, 0x00000002 },
+ /* Init opp and enable dvfsrc*/
+ { DVFSRC_CURRENT_FORCE, 0x00000001 },
+ { DVFSRC_BASIC_CONTROL, 0x0298444B },
+ { DVFSRC_BASIC_CONTROL, 0x0298054B },
+ { DVFSRC_CURRENT_FORCE, 0x00000000 },
+};
+
+static struct pwr_ctrl vcorefs_ctrl = {
+ .wake_src = R12_REG_CPU_WAKEUP,
+
+ /* default VCORE DVFS is disabled */
+ .pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO |
+ SPM_FLAG_DISABLE_VCORE_DVS |
+ SPM_FLAG_DISABLE_VCORE_DFS),
+
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ .reg_wfi_op = 0,
+ .reg_wfi_type = 0,
+ .reg_mp0_cputop_idle_mask = 0,
+ .reg_mp1_cputop_idle_mask = 0,
+ .reg_mcusys_idle_mask = 0,
+ .reg_md_apsrc_1_sel = 0,
+ .reg_md_apsrc_0_sel = 0,
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC_REQ */
+ .reg_spm_apsrc_req = 0,
+ .reg_spm_f26m_req = 0,
+ .reg_spm_infra_req = 0,
+ .reg_spm_vrf18_req = 0,
+ .reg_spm_ddr_en_req = 1,
+ .reg_spm_dvfs_req = 0,
+ .reg_spm_sw_mailbox_req = 0,
+ .reg_spm_sspm_mailbox_req = 0,
+ .reg_spm_adsp_mailbox_req = 0,
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC6_MASK */
+ .reg_dpmaif_srcclkena_mask_b = 1,
+ .reg_dpmaif_infra_req_mask_b = 1,
+ .reg_dpmaif_apsrc_req_mask_b = 1,
+ .reg_dpmaif_vrf18_req_mask_b = 1,
+ .reg_dpmaif_ddr_en_mask_b = 1,
+
+ /* SPM_SRC_MASK */
+ .reg_md_srcclkena_0_mask_b = 1,
+ .reg_md_srcclkena2infra_req_0_mask_b = 0,
+ .reg_md_apsrc2infra_req_0_mask_b = 1,
+ .reg_md_apsrc_req_0_mask_b = 1,
+ .reg_md_vrf18_req_0_mask_b = 1,
+ .reg_md_ddr_en_0_mask_b = 1,
+ .reg_md_srcclkena_1_mask_b = 0,
+ .reg_md_srcclkena2infra_req_1_mask_b = 0,
+ .reg_md_apsrc2infra_req_1_mask_b = 0,
+ .reg_md_apsrc_req_1_mask_b = 0,
+ .reg_md_vrf18_req_1_mask_b = 0,
+ .reg_md_ddr_en_1_mask_b = 0,
+ .reg_conn_srcclkena_mask_b = 1,
+ .reg_conn_srcclkenb_mask_b = 0,
+ .reg_conn_infra_req_mask_b = 1,
+ .reg_conn_apsrc_req_mask_b = 1,
+ .reg_conn_vrf18_req_mask_b = 1,
+ .reg_conn_ddr_en_mask_b = 1,
+ .reg_conn_vfe28_mask_b = 0,
+ .reg_srcclkeni0_srcclkena_mask_b = 1,
+ .reg_srcclkeni0_infra_req_mask_b = 1,
+ .reg_srcclkeni1_srcclkena_mask_b = 0,
+ .reg_srcclkeni1_infra_req_mask_b = 0,
+ .reg_srcclkeni2_srcclkena_mask_b = 0,
+ .reg_srcclkeni2_infra_req_mask_b = 0,
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ .reg_infrasys_ddr_en_mask_b = 1,
+ .reg_md32_srcclkena_mask_b = 1,
+ .reg_md32_infra_req_mask_b = 1,
+ .reg_md32_apsrc_req_mask_b = 1,
+ .reg_md32_vrf18_req_mask_b = 1,
+ .reg_md32_ddr_en_mask_b = 1,
+
+ /* SPM_SRC2_MASK */
+ .reg_scp_srcclkena_mask_b = 1,
+ .reg_scp_infra_req_mask_b = 1,
+ .reg_scp_apsrc_req_mask_b = 1,
+ .reg_scp_vrf18_req_mask_b = 1,
+ .reg_scp_ddr_en_mask_b = 1,
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ .reg_audio_dsp_ddr_en_mask_b = 1,
+ .reg_ufs_srcclkena_mask_b = 1,
+ .reg_ufs_infra_req_mask_b = 1,
+ .reg_ufs_apsrc_req_mask_b = 1,
+ .reg_ufs_vrf18_req_mask_b = 1,
+ .reg_ufs_ddr_en_mask_b = 1,
+ .reg_disp0_apsrc_req_mask_b = 1,
+ .reg_disp0_ddr_en_mask_b = 1,
+ .reg_disp1_apsrc_req_mask_b = 1,
+ .reg_disp1_ddr_en_mask_b = 1,
+ .reg_gce_infra_req_mask_b = 1,
+ .reg_gce_apsrc_req_mask_b = 1,
+ .reg_gce_vrf18_req_mask_b = 1,
+ .reg_gce_ddr_en_mask_b = 1,
+ .reg_apu_srcclkena_mask_b = 1,
+ .reg_apu_infra_req_mask_b = 1,
+ .reg_apu_apsrc_req_mask_b = 1,
+ .reg_apu_vrf18_req_mask_b = 1,
+ .reg_apu_ddr_en_mask_b = 1,
+ .reg_cg_check_srcclkena_mask_b = 0,
+ .reg_cg_check_apsrc_req_mask_b = 0,
+ .reg_cg_check_vrf18_req_mask_b = 0,
+ .reg_cg_check_ddr_en_mask_b = 0,
+
+ /* SPM_SRC3_MASK */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+ .reg_sw2spm_int0_mask_b = 0,
+ .reg_sw2spm_int1_mask_b = 0,
+ .reg_sw2spm_int2_mask_b = 0,
+ .reg_sw2spm_int3_mask_b = 0,
+ .reg_sc_adsp2spm_wakeup_mask_b = 0,
+ .reg_sc_sspm2spm_wakeup_mask_b = 0,
+ .reg_sc_scp2spm_wakeup_mask_b = 0,
+ .reg_csyspwrreq_mask = 1,
+ .reg_spm_srcclkena_reserved_mask_b = 0,
+ .reg_spm_infra_req_reserved_mask_b = 0,
+ .reg_spm_apsrc_req_reserved_mask_b = 0,
+ .reg_spm_vrf18_req_reserved_mask_b = 0,
+ .reg_spm_ddr_en_reserved_mask_b = 0,
+ .reg_mcupm_srcclkena_mask_b = 1,
+ .reg_mcupm_infra_req_mask_b = 1,
+ .reg_mcupm_apsrc_req_mask_b = 1,
+ .reg_mcupm_vrf18_req_mask_b = 1,
+ .reg_mcupm_ddr_en_mask_b = 1,
+ .reg_msdc0_srcclkena_mask_b = 1,
+ .reg_msdc0_infra_req_mask_b = 1,
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ .reg_msdc0_ddr_en_mask_b = 1,
+ .reg_msdc1_srcclkena_mask_b = 1,
+ .reg_msdc1_infra_req_mask_b = 1,
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ .reg_msdc1_ddr_en_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ .ccif_event_mask_b = 0xFFF,
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ .reg_bak_psri_infra_req_mask_b = 0,
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ .reg_bak_psri_ddr_en_mask_b = 0,
+ .reg_dramc0_md32_infra_req_mask_b = 1,
+ .reg_dramc0_md32_vrf18_req_mask_b = 0,
+ .reg_dramc1_md32_infra_req_mask_b = 1,
+ .reg_dramc1_md32_vrf18_req_mask_b = 0,
+ .reg_conn_srcclkenb2pwrap_mask_b = 0,
+ .reg_dramc0_md32_wakeup_mask = 1,
+ .reg_dramc1_md32_wakeup_mask = 1,
+
+ /* SPM_SRC5_MASK */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x11,
+ .reg_mcusys_merge_ddr_en_mask_b = 0x11,
+ .reg_msdc2_srcclkena_mask_b = 1,
+ .reg_msdc2_infra_req_mask_b = 1,
+ .reg_msdc2_apsrc_req_mask_b = 1,
+ .reg_msdc2_vrf18_req_mask_b = 1,
+ .reg_msdc2_ddr_en_mask_b = 1,
+ .reg_pcie_srcclkena_mask_b = 1,
+ .reg_pcie_infra_req_mask_b = 1,
+ .reg_pcie_apsrc_req_mask_b = 1,
+ .reg_pcie_vrf18_req_mask_b = 1,
+ .reg_pcie_ddr_en_mask_b = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ .reg_wakeup_event_mask = 0xEFFFFFFF,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+
+ /* Auto-gen End */
+};
+
+struct spm_lp_scen __spm_vcorefs = {
+ .pwrctrl = &vcorefs_ctrl,
+};
+
+static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val)
+{
+ if (cmd < NR_IDX_ALL) {
+ mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val);
+ } else {
+ INFO("cmd out of range!\n");
+ }
+}
+
+void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue)
+{
+ mmio_clrsetbits_32(SPM_DVFS_MISC, SPM_DVFS_FORCE_ENABLE_LSB,
+ SPM_DVFSRC_ENABLE_LSB);
+
+ mmio_write_32(SPM_DVFS_LEVEL, 0x00000001);
+ mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001);
+}
+
+void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+ const struct pwr_ctrl *src_pwr_ctrl)
+{
+ uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS |
+ SPM_FLAG_DISABLE_VCORE_DFS |
+ SPM_FLAG_ENABLE_VOLTAGE_BIN;
+
+ dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) |
+ (src_pwr_ctrl->pcm_flags & dvfs_mask);
+
+ if (dest_pwr_ctrl->pcm_flags_cust > 0U) {
+ dest_pwr_ctrl->pcm_flags_cust =
+ (dest_pwr_ctrl->pcm_flags_cust & (~dvfs_mask)) |
+ (src_pwr_ctrl->pcm_flags & dvfs_mask);
+ }
+}
+
+static void spm_go_to_vcorefs(void)
+{
+ __spm_set_power_control(__spm_vcorefs.pwrctrl);
+ __spm_set_wakeup_event(__spm_vcorefs.pwrctrl);
+ __spm_set_pcm_flags(__spm_vcorefs.pwrctrl);
+ __spm_send_cpu_wakeup_event();
+}
+
+static void dvfsrc_init(void)
+{
+ uint32_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(dvfsrc_init_configs); i++) {
+ mmio_write_32(dvfsrc_init_configs[i].offset,
+ dvfsrc_init_configs[i].val);
+ }
+}
+
+static uint32_t spm_vcorefs_get_efuse_data(void)
+{
+ return mmio_read_32(VCORE_VB_EFUSE);
+}
+
+static uint32_t is_rising_need(void)
+{
+ return ((spm_vcorefs_get_efuse_data() & 0xF) == 11U) ? 1U : 0U;
+}
+
+static void spm_vcorefs_vcore_setting(uint64_t flag)
+{
+ uint32_t dvfs_v_mode, dvfsrc_rsrv, i;
+ uint32_t opp_uv[] = {725000U, 650000U, 600000U, 575000U};
+
+ dvfsrc_rsrv = mmio_read_32(DVFSRC_RSRV_4);
+
+ dvfs_v_mode = (dvfsrc_rsrv >> V_VMODE_SHIFT) & 0x3;
+
+ if (is_rising_need() != 0U) {
+ opp_uv[2] = 625000U;
+ opp_uv[3] = 600000U;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(opp_uv); i++) {
+ if (dvfs_v_mode == 3U) {
+ /* LV */
+ opp_uv[i] = round_down((opp_uv[i] * VCORE_LV) / 100U,
+ PMIC_STEP_UV);
+ } else if (dvfs_v_mode == 1U) {
+ /* HV */
+ opp_uv[i] = round_up((opp_uv[i] * VCORE_HV) / 100U,
+ PMIC_STEP_UV);
+ }
+ spm_vcorefs_pwarp_cmd(i, __vcore_uv_to_pmic(opp_uv[i]));
+ }
+}
+
+uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4)
+{
+ uint64_t cmd = x1;
+ uint64_t spm_flags;
+
+ switch (cmd) {
+ case VCOREFS_SMC_CMD_INIT:
+ /* vcore_dvfs init + kick */
+ mmio_write_32(DVFSRC_SW_REQ5, SW_REQ5_INIT_VAL);
+ spm_dvfsfw_init(0ULL, 0ULL);
+ spm_vcorefs_vcore_setting(x3 & 0xF);
+ spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+ if ((x2 & 0x1) > 0U) {
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+ }
+
+ if ((x2 & 0x2) > 0U) {
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+ }
+
+ if ((mmio_read_32(DVFSRC_RSRV_4) & VCORE_CT_ENABLE) > 0U) {
+ spm_flags |= SPM_FLAG_ENABLE_VOLTAGE_BIN;
+ }
+
+ set_pwrctrl_pcm_flags(__spm_vcorefs.pwrctrl, spm_flags);
+ spm_go_to_vcorefs();
+ dvfsrc_init();
+
+ *x4 = 0U;
+ mmio_write_32(DVFSRC_SW_REQ5, 0U);
+ break;
+ case VCOREFS_SMC_CMD_KICK:
+ mmio_write_32(DVFSRC_SW_REQ5, 0U);
+ break;
+ default:
+ break;
+ }
+
+ return 0ULL;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h
new file mode 100644
index 0000000..f4e0c48
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright(C)2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_VCOREFS_H
+#define MT_SPM_VCOREFS_H
+
+uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t *x4);
+
+enum vcorefs_smc_cmd {
+ VCOREFS_SMC_CMD_0,
+ VCOREFS_SMC_CMD_1,
+ VCOREFS_SMC_CMD_2,
+ VCOREFS_SMC_CMD_3,
+ VCOREFS_SMC_CMD_4,
+ /* check spmfw status */
+ VCOREFS_SMC_CMD_5,
+
+ /* get spmfw type */
+ VCOREFS_SMC_CMD_6,
+
+ /* get spm reg status */
+ VCOREFS_SMC_CMD_7,
+
+ NUM_VCOREFS_SMC_CMD,
+};
+
+enum vcorefs_smc_cmd_new {
+ VCOREFS_SMC_CMD_INIT = 0,
+ VCOREFS_SMC_CMD_KICK = 1,
+};
+
+#define _VCORE_BASE_UV 400000
+#define _VCORE_STEP_UV 6250
+
+/* PMIC */
+#define __vcore_pmic_to_uv(pmic) \
+ (((pmic) * _VCORE_STEP_UV) + _VCORE_BASE_UV)
+
+#define __vcore_uv_to_pmic(uv) /* pmic >= uv */ \
+ ((((uv) - _VCORE_BASE_UV) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV)
+
+struct reg_config {
+ uint32_t offset;
+ uint32_t val;
+};
+
+#define DVFSRC_BASIC_CONTROL (DVFSRC_BASE + 0x0)
+#define DVFSRC_SW_REQ5 (DVFSRC_BASE + 0x14)
+#define DVFSRC_INT_EN (DVFSRC_BASE + 0xC8)
+#define DVFSRC_MD_TURBO (DVFSRC_BASE + 0xDC)
+#define DVFSRC_PCIE_VCORE_REQ (DVFSRC_BASE + 0xE0)
+#define DVFSRC_VCORE_USER_REQ (DVFSRC_BASE + 0xE4)
+#define DVFSRC_TIMEOUT_NEXTREQ (DVFSRC_BASE + 0xF8)
+#define DVFSRC_LEVEL_LABEL_0_1 (DVFSRC_BASE + 0x100)
+#define DVFSRC_LEVEL_LABEL_2_3 (DVFSRC_BASE + 0x104)
+#define DVFSRC_LEVEL_LABEL_4_5 (DVFSRC_BASE + 0x108)
+#define DVFSRC_LEVEL_LABEL_6_7 (DVFSRC_BASE + 0x10C)
+#define DVFSRC_LEVEL_LABEL_8_9 (DVFSRC_BASE + 0x110)
+#define DVFSRC_LEVEL_LABEL_10_11 (DVFSRC_BASE + 0x114)
+#define DVFSRC_LEVEL_LABEL_12_13 (DVFSRC_BASE + 0x118)
+#define DVFSRC_LEVEL_LABEL_14_15 (DVFSRC_BASE + 0x11C)
+#define DVFSRC_QOS_EN (DVFSRC_BASE + 0x280)
+#define DVFSRC_HRT_BW_BASE (DVFSRC_BASE + 0x294)
+#define DVFSRC_RSRV_4 (DVFSRC_BASE + 0x610)
+#define DVFSRC_RSRV_5 (DVFSRC_BASE + 0x614)
+#define DVFSRC_DDR_REQUEST (DVFSRC_BASE + 0xA00)
+#define DVFSRC_DDR_REQUEST2 (DVFSRC_BASE + 0xA04)
+#define DVFSRC_DDR_REQUEST3 (DVFSRC_BASE + 0xA08)
+#define DVFSRC_DDR_REQUEST4 (DVFSRC_BASE + 0xA0C)
+#define DVFSRC_DDR_REQUEST5 (DVFSRC_BASE + 0xA10)
+#define DVFSRC_DDR_REQUEST6 (DVFSRC_BASE + 0xA14)
+#define DVFSRC_DDR_REQUEST7 (DVFSRC_BASE + 0xA18)
+#define DVFSRC_DDR_QOS0 (DVFSRC_BASE + 0xA34)
+#define DVFSRC_DDR_QOS1 (DVFSRC_BASE + 0xA38)
+#define DVFSRC_DDR_QOS2 (DVFSRC_BASE + 0xA3C)
+#define DVFSRC_DDR_QOS3 (DVFSRC_BASE + 0xA40)
+#define DVFSRC_DDR_QOS4 (DVFSRC_BASE + 0xA44)
+#define DVFSRC_HRT_REQ_UNIT (DVFSRC_BASE + 0xA60)
+#define DVFSRC_HRT_REQUEST (DVFSRC_BASE + 0xAC4)
+#define DVFSRC_HRT_HIGH_2 (DVFSRC_BASE + 0xAC8)
+#define DVFSRC_HRT_HIGH_1 (DVFSRC_BASE + 0xACC)
+#define DVFSRC_HRT_HIGH (DVFSRC_BASE + 0xAD0)
+#define DVFSRC_HRT_LOW_2 (DVFSRC_BASE + 0xAD4)
+#define DVFSRC_HRT_LOW_1 (DVFSRC_BASE + 0xAD8)
+#define DVFSRC_HRT_LOW (DVFSRC_BASE + 0xADC)
+#define DVFSRC_DDR_ADD_REQUEST (DVFSRC_BASE + 0xAE0)
+#define DVFSRC_LAST (DVFSRC_BASE + 0xAE4)
+#define DVFSRC_LAST_L (DVFSRC_BASE + 0xAE8)
+#define DVFSRC_MD_SCENARIO (DVFSRC_BASE + 0xAEC)
+#define DVFSRC_RECORD_0_0 (DVFSRC_BASE + 0xAF0)
+#define DVFSRC_RECORD_0_1 (DVFSRC_BASE + 0xAF4)
+#define DVFSRC_RECORD_0_2 (DVFSRC_BASE + 0xAF8)
+#define DVFSRC_RECORD_0_3 (DVFSRC_BASE + 0xAFC)
+#define DVFSRC_RECORD_0_4 (DVFSRC_BASE + 0xB00)
+#define DVFSRC_RECORD_0_5 (DVFSRC_BASE + 0xB04)
+#define DVFSRC_RECORD_0_6 (DVFSRC_BASE + 0xB08)
+#define DVFSRC_RECORD_0_7 (DVFSRC_BASE + 0xB0C)
+#define DVFSRC_RECORD_0_L_0 (DVFSRC_BASE + 0xBF0)
+#define DVFSRC_RECORD_0_L_1 (DVFSRC_BASE + 0xBF4)
+#define DVFSRC_RECORD_0_L_2 (DVFSRC_BASE + 0xBF8)
+#define DVFSRC_RECORD_0_L_3 (DVFSRC_BASE + 0xBFC)
+#define DVFSRC_RECORD_0_L_4 (DVFSRC_BASE + 0xC00)
+#define DVFSRC_RECORD_0_L_5 (DVFSRC_BASE + 0xC04)
+#define DVFSRC_RECORD_0_L_6 (DVFSRC_BASE + 0xC08)
+#define DVFSRC_RECORD_0_L_7 (DVFSRC_BASE + 0xC0C)
+#define DVFSRC_EMI_REQUEST8 (DVFSRC_BASE + 0xCF0)
+#define DVFSRC_DDR_REQUEST8 (DVFSRC_BASE + 0xCF4)
+#define DVFSRC_EMI_HRT_2 (DVFSRC_BASE + 0xCF8)
+#define DVFSRC_EMI_HRT2_2 (DVFSRC_BASE + 0xCFC)
+#define DVFSRC_EMI_HRT3_2 (DVFSRC_BASE + 0xD00)
+#define DVFSRC_EMI_QOS5 (DVFSRC_BASE + 0xD04)
+#define DVFSRC_EMI_QOS6 (DVFSRC_BASE + 0xD08)
+#define DVFSRC_DDR_HRT_2 (DVFSRC_BASE + 0xD0C)
+#define DVFSRC_DDR_HRT2_2 (DVFSRC_BASE + 0xD10)
+#define DVFSRC_DDR_HRT3_2 (DVFSRC_BASE + 0xD14)
+#define DVFSRC_DDR_QOS5 (DVFSRC_BASE + 0xD18)
+#define DVFSRC_DDR_QOS6 (DVFSRC_BASE + 0xD1C)
+#define DVFSRC_HRT_HIGH_3 (DVFSRC_BASE + 0xD38)
+#define DVFSRC_HRT_LOW_3 (DVFSRC_BASE + 0xD3C)
+#define DVFSRC_LEVEL_LABEL_16_17 (DVFSRC_BASE + 0xD4C)
+#define DVFSRC_LEVEL_LABEL_18_19 (DVFSRC_BASE + 0xD50)
+#define DVFSRC_LEVEL_LABEL_20_21 (DVFSRC_BASE + 0xD54)
+#define DVFSRC_LEVEL_LABEL_22_23 (DVFSRC_BASE + 0xD58)
+#define DVFSRC_LEVEL_LABEL_24_25 (DVFSRC_BASE + 0xD5C)
+#define DVFSRC_LEVEL_LABEL_26_27 (DVFSRC_BASE + 0xD60)
+#define DVFSRC_LEVEL_LABEL_28_29 (DVFSRC_BASE + 0xD64)
+#define DVFSRC_LEVEL_LABEL_30_31 (DVFSRC_BASE + 0xD68)
+#define DVFSRC_CURRENT_FORCE (DVFSRC_BASE + 0xD6C)
+
+#define VCORE_VB_EFUSE (0x11C105E8)
+
+#endif /* MT_SPM_VCOREFS_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h b/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h
new file mode 100644
index 0000000..66be7ee
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SSPM_NOTIFIER_H
+#define MT_SPM_SSPM_NOTIFIER_H
+
+enum MT_SPM_SSPM_NOTIFY_ID {
+ MT_SPM_NOTIFY_LP_ENTER,
+ MT_SPM_NOTIFY_LP_LEAVE,
+};
+
+int mt_spm_sspm_notify(int type, unsigned int lp_mode);
+
+static inline int mt_spm_sspm_notify_u32(int type, unsigned int lp_mode)
+{
+ return mt_spm_sspm_notify(type, lp_mode);
+}
+#endif /* MT_SPM_SSPM_NOTIFIER_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h b/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h
new file mode 100644
index 0000000..452ae90
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SSPM_INTC_H
+#define MT_SPM_SSPM_INTC_H
+
+#include <mt_spm_reg.h>
+
+#define MT_SPM_SSPM_INTC_SEL_0 0x10
+#define MT_SPM_SSPM_INTC_SEL_1 0x20
+#define MT_SPM_SSPM_INTC_SEL_2 0x40
+#define MT_SPM_SSPM_INTC_SEL_3 0x80
+
+#define MT_SPM_SSPM_INTC_TRIGGER(id, sg) \
+ (((0x10 << id) | (sg << id)) & 0xff)
+
+#define MT_SPM_SSPM_INTC0_HIGH MT_SPM_SSPM_INTC_TRIGGER(0, 1)
+#define MT_SPM_SSPM_INTC0_LOW MT_SPM_SSPM_INTC_TRIGGER(0, 0)
+#define MT_SPM_SSPM_INTC1_HIGH MT_SPM_SSPM_INTC_TRIGGER(1, 1)
+#define MT_SPM_SSPM_INTC1_LOW MT_SPM_SSPM_INTC_TRIGGER(1, 0)
+#define MT_SPM_SSPM_INTC2_HIGH MT_SPM_SSPM_INTC_TRIGGER(2, 1)
+#define MT_SPM_SSPM_INTC2_LOW MT_SPM_SSPM_INTC_TRIGGER(2, 0)
+#define MT_SPM_SSPM_INTC3_HIGH MT_SPM_SSPM_INTC_TRIGGER(3, 1)
+#define MT_SPM_SSPM_INTC3_LOW MT_SPM_SSPM_INTC_TRIGGER(3, 0)
+
+#define DO_SPM_SSPM_LP_SUSPEND() \
+ mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_HIGH)
+#define DO_SPM_SSPM_LP_RESUME() \
+ mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_LOW)
+#endif /* MT_SPM_SSPM_INTC_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c b/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c
new file mode 100644
index 0000000..e0ba037
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <lib/mmio.h>
+
+#include <mt_spm_notifier.h>
+#include <mt_spm_sspm_intc.h>
+
+#define MT_SPM_SSPM_MBOX_OFF(x) (SSPM_MBOX_BASE + x)
+#define MT_SPM_MBOX(slot) MT_SPM_SSPM_MBOX_OFF((slot << 2UL))
+
+#define SSPM_MBOX_SPM_LP_LOOKUP1 MT_SPM_MBOX(0)
+#define SSPM_MBOX_SPM_LP_LOOKUP2 MT_SPM_MBOX(1)
+#define SSPM_MBOX_SPM_LP1 MT_SPM_MBOX(2)
+#define SSPM_MBOX_SPM_LP2 MT_SPM_MBOX(3)
+
+#define MCUPM_MBOX_OFFSET_LP 0x0C55FDA4
+#define MCUPM_MBOX_ENTER_LP 0x454e0000
+#define MCUPM_MBOX_LEAVE_LP 0x4c450000
+#define MCUPM_MBOX_SLEEP_MASK 0x0000FFFF
+
+int mt_spm_sspm_notify(int type, unsigned int lp_mode)
+{
+ switch (type) {
+ case MT_SPM_NOTIFY_LP_ENTER:
+ mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode);
+ mmio_write_32(MCUPM_MBOX_OFFSET_LP, MCUPM_MBOX_ENTER_LP |
+ (lp_mode & MCUPM_MBOX_SLEEP_MASK));
+ DO_SPM_SSPM_LP_SUSPEND();
+ break;
+ case MT_SPM_NOTIFY_LP_LEAVE:
+ mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode);
+ mmio_write_32(MCUPM_MBOX_OFFSET_LP, MCUPM_MBOX_LEAVE_LP |
+ (lp_mode & MCUPM_MBOX_SLEEP_MASK));
+ DO_SPM_SSPM_LP_RESUME();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/drivers/spm/pcm_def.h b/plat/mediatek/mt8192/drivers/spm/pcm_def.h
new file mode 100644
index 0000000..ab46b86
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/pcm_def.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PCM_DEF_H
+#define PCM_DEF_H
+
+/*
+ * Auto generated by DE, please DO NOT modify this file directly.
+ */
+
+/* --- R0 Define --- */
+#define R0_SC_26M_CK_OFF (1U << 0)
+#define R0_SC_TX_TRACK_RETRY_EN (1U << 1)
+#define R0_SC_MEM_CK_OFF (1U << 2)
+#define R0_SC_AXI_CK_OFF (1U << 3)
+#define R0_SC_DR_SRAM_LOAD (1U << 4)
+#define R0_SC_MD26M_CK_OFF (1U << 5)
+#define R0_SC_DPY_MODE_SW (1U << 6)
+#define R0_SC_DMSUS_OFF (1U << 7)
+#define R0_SC_DPY_2ND_DLL_EN (1U << 8)
+#define R0_SC_DR_SRAM_RESTORE (1U << 9)
+#define R0_SC_MPLLOUT_OFF (1U << 10)
+#define R0_SC_TX_TRACKING_DIS (1U << 11)
+#define R0_SC_DPY_DLL_EN (1U << 12)
+#define R0_SC_DPY_DLL_CK_EN (1U << 13)
+#define R0_SC_DPY_VREF_EN (1U << 14)
+#define R0_SC_PHYPLL_EN (1U << 15)
+#define R0_SC_DDRPHY_FB_CK_EN (1U << 16)
+#define R0_SC_DPY_BCLK_ENABLE (1U << 17)
+#define R0_SC_MPLL_OFF (1U << 18)
+#define R0_SC_SHU_RESTORE (1U << 19)
+#define R0_SC_CKSQ0_OFF (1U << 20)
+#define R0_SC_DR_SHU_LEVEL_SRAM_LATCH (1U << 21)
+#define R0_SC_DR_SHU_EN (1U << 22)
+#define R0_SC_DPHY_PRECAL_UP (1U << 23)
+#define R0_SC_MPLL_S_OFF (1U << 24)
+#define R0_SC_DPHY_RXDLY_TRACKING_EN (1U << 25)
+#define R0_SC_PHYPLL_SHU_EN (1U << 26)
+#define R0_SC_PHYPLL2_SHU_EN (1U << 27)
+#define R0_SC_PHYPLL_MODE_SW (1U << 28)
+#define R0_SC_PHYPLL2_MODE_SW (1U << 29)
+#define R0_SC_DR_SHU_LEVEL0 (1U << 30)
+#define R0_SC_DR_SHU_LEVEL1 (1U << 31)
+/* --- R7 Define --- */
+#define R7_PWRAP_SLEEP_REQ (1U << 0)
+#define R7_EMI_CLK_OFF_REQ (1U << 1)
+#define R7_PCM_BUS_PROTECT_REQ (1U << 2)
+#define R7_SPM_CK_UPDATE (1U << 3)
+#define R7_SPM_CK_SEL0 (1U << 4)
+#define R7_SPM_CK_SEL1 (1U << 5)
+#define R7_SPM_LEAVE_DEEPIDLE_REQ (1U << 6)
+#define R7_SC_FHC_PAUSE_MPLL (1U << 7)
+#define R7_SC_26M_CK_SEL (1U << 8)
+#define R7_PCM_TIMER_SET (1U << 9)
+#define R7_PCM_TIMER_CLR (1U << 10)
+#define R7_SPM_LEAVE_SUSPEND_REQ (1U << 11)
+#define R7_CSYSPWRUPACK (1U << 12)
+#define R7_PCM_IM_SLP_EN (1U << 13)
+#define R7_SRCCLKENO0 (1U << 14)
+#define R7_FORCE_DDR_EN_WAKE (1U << 15)
+#define R7_SPM_APSRC_INTERNAL_ACK (1U << 16)
+#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17)
+#define R7_SC_AXI_DCM_DIS (1U << 18)
+#define R7_SC_FHC_PAUSE_MEM (1U << 19)
+#define R7_SC_FHC_PAUSE_MAIN (1U << 20)
+#define R7_SRCCLKENO1 (1U << 21)
+#define R7_PCM_WDT_KICK_P (1U << 22)
+#define R7_SPM2EMI_S1_MODE_ASYNC (1U << 23)
+#define R7_SC_DDR_PST_REQ_PCM (1U << 24)
+#define R7_SC_DDR_PST_ABORT_REQ_PCM (1U << 25)
+#define R7_PMIC_IRQ_REQ_EN (1U << 26)
+#define R7_FORCE_F26M_WAKE (1U << 27)
+#define R7_FORCE_APSRC_WAKE (1U << 28)
+#define R7_FORCE_INFRA_WAKE (1U << 29)
+#define R7_FORCE_VRF18_WAKE (1U << 30)
+#define R7_SPM_DDR_EN_INTERNAL_ACK (1U << 31)
+/* --- R12 Define --- */
+#define R12_PCM_TIMER (1U << 0)
+#define R12_TWAM_IRQ_B (1U << 1)
+#define R12_KP_IRQ_B (1U << 2)
+#define R12_APWDT_EVENT_B (1U << 3)
+#define R12_APXGPT1_EVENT_B (1U << 4)
+#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5)
+#define R12_EINT_EVENT_B (1U << 6)
+#define R12_CONN_WDT_IRQ_B (1U << 7)
+#define R12_CCIF0_EVENT_B (1U << 8)
+#define R12_LOWBATTERY_IRQ_B (1U << 9)
+#define R12_SSPM2SPM_WAKEUP_B (1U << 10)
+#define R12_SCP2SPM_WAKEUP_B (1U << 11)
+#define R12_ADSP2SPM_WAKEUP_B (1U << 12)
+#define R12_PCM_WDT_WAKEUP_B (1U << 13)
+#define R12_USBX_CDSC_B (1U << 14)
+#define R12_USBX_POWERDWN_B (1U << 15)
+#define R12_SYS_TIMER_EVENT_B (1U << 16)
+#define R12_EINT_EVENT_SECURE_B (1U << 17)
+#define R12_CCIF1_EVENT_B (1U << 18)
+#define R12_UART0_IRQ_B (1U << 19)
+#define R12_AFE_IRQ_MCU_B (1U << 20)
+#define R12_THERM_CTRL_EVENT_B (1U << 21)
+#define R12_SYS_CIRQ_IRQ_B (1U << 22)
+#define R12_MD2AP_PEER_EVENT_B (1U << 23)
+#define R12_CSYSPWREQ_B (1U << 24)
+#define R12_MD1_WDT_B (1U << 25)
+#define R12_CLDMA_EVENT_B (1U << 26)
+#define R12_SEJ_EVENT_B (1U << 27)
+#define R12_REG_CPU_WAKEUP (1U << 28)
+#define R12_APUSYS_WAKE_HOST_B (1U << 29)
+#define R12_PCIE_BRIDGE_IRQ (1U << 30)
+#define R12_PCIE_IRQ (1U << 31)
+/* --- R12ext Define --- */
+#define R12EXT_26M_WAKE (1U << 0)
+#define R12EXT_26M_SLEEP (1U << 1)
+#define R12EXT_INFRA_WAKE (1U << 2)
+#define R12EXT_INFRA_SLEEP (1U << 3)
+#define R12EXT_APSRC_WAKE (1U << 4)
+#define R12EXT_APSRC_SLEEP (1U << 5)
+#define R12EXT_VRF18_WAKE (1U << 6)
+#define R12EXT_VRF18_SLEEP (1U << 7)
+#define R12EXT_DVFS_WAKE (1U << 8)
+#define R12EXT_DDREN_WAKE (1U << 9)
+#define R12EXT_DDREN_SLEEP (1U << 10)
+#define R12EXT_MCU_PM_WFI (1U << 11)
+#define R12EXT_SSPM_IDLE (1U << 12)
+#define R12EXT_CONN_SRCCLKENB (1U << 13)
+#define R12EXT_DRAMC_SSPM_WFI_MERGE (1U << 14)
+#define R12EXT_SW_MAILBOX_WAKE (1U << 15)
+#define R12EXT_SSPM_MAILBOX_WAKE (1U << 16)
+#define R12EXT_ADSP_MAILBOX_WAKE (1U << 17)
+#define R12EXT_SCP_MAILBOX_WAKE (1U << 18)
+#define R12EXT_SPM_LEAVE_SUSPEND_ACK (1U << 19)
+#define R12EXT_SPM_LEAVE_DEEPIDLE_ACK (1U << 20)
+#define R12EXT_VS1_TRIGGER (1U << 21)
+#define R12EXT_VS2_TRIGGER (1U << 22)
+#define R12EXT_COROSS_REQ_APU (1U << 23)
+#define R12EXT_CROSS_REQ_L3 (1U << 24)
+#define R12EXT_DDR_PST_ACK (1U << 25)
+#define R12EXT_BIT26 (1U << 26)
+#define R12EXT_BIT27 (1U << 27)
+#define R12EXT_BIT28 (1U << 28)
+#define R12EXT_BIT29 (1U << 29)
+#define R12EXT_BIT30 (1U << 30)
+#define R12EXT_BIT31 (1U << 31)
+/* --- R13 Define --- */
+#define R13_SRCCLKENI0 (1U << 0)
+#define R13_SRCCLKENI1 (1U << 1)
+#define R13_MD_SRCCLKENA_0 (1U << 2)
+#define R13_MD_APSRC_REQ_0 (1U << 3)
+#define R13_CONN_DDR_EN (1U << 4)
+#define R13_MD_SRCCLKENA_1 (1U << 5)
+#define R13_SSPM_SRCCLKENA (1U << 6)
+#define R13_SSPM_APSRC_REQ (1U << 7)
+#define R13_MD1_STATE (1U << 8)
+#define R13_BIT9 (1U << 9)
+#define R13_MM_STATE (1U << 10)
+#define R13_SSPM_STATE (1U << 11)
+#define R13_MD_DDR_EN_0 (1U << 12)
+#define R13_CONN_STATE (1U << 13)
+#define R13_CONN_SRCCLKENA (1U << 14)
+#define R13_CONN_APSRC_REQ (1U << 15)
+#define R13_SC_DDR_PST_ACK_ALL (1U << 16)
+#define R13_SC_DDR_PST_ABORT_ACK_ALL (1U << 17)
+#define R13_SCP_STATE (1U << 18)
+#define R13_CSYSPWRUPREQ (1U << 19)
+#define R13_PWRAP_SLEEP_ACK (1U << 20)
+#define R13_SC_EMI_CLK_OFF_ACK_ALL (1U << 21)
+#define R13_AUDIO_DSP_STATE (1U << 22)
+#define R13_SC_DMDRAMCSHU_ACK_ALL (1U << 23)
+#define R13_CONN_SRCCLKENB (1U << 24)
+#define R13_SC_DR_SRAM_LOAD_ACK_ALL (1U << 25)
+#define R13_SUBSYS_IDLE_SIGNALS0 (1U << 26)
+#define R13_DVFS_STATE (1U << 27)
+#define R13_SC_DR_SRAM_PLL_LOAD_ACK_ALL (1U << 28)
+#define R13_SC_DR_SRAM_RESTORE_ACK_ALL (1U << 29)
+#define R13_MD_VRF18_REQ_0 (1U << 30)
+#define R13_DDR_EN_STATE (1U << 31)
+#endif /* PCM_DEF_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/sleep_def.h b/plat/mediatek/mt8192/drivers/spm/sleep_def.h
new file mode 100644
index 0000000..6c5cbed
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spm/sleep_def.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SLEEP_DEF_H
+#define SLEEP_DEF_H
+
+/*
+ * Auto generated by DE, please DO NOT modify this file directly.
+ */
+
+/* --- SPM Flag Define --- */
+#define SPM_FLAG_DISABLE_CPU_PDN (1U << 0)
+#define SPM_FLAG_DISABLE_INFRA_PDN (1U << 1)
+#define SPM_FLAG_DISABLE_DDRPHY_PDN (1U << 2)
+#define SPM_FLAG_DISABLE_VCORE_DVS (1U << 3)
+#define SPM_FLAG_DISABLE_VCORE_DFS (1U << 4)
+#define SPM_FLAG_DISABLE_COMMON_SCENARIO (1U << 5)
+#define SPM_FLAG_DISABLE_BUS_CLK_OFF (1U << 6)
+#define SPM_FLAG_DISABLE_ARMPLL_OFF (1U << 7)
+#define SPM_FLAG_KEEP_CSYSPWRACK_HIGH (1U << 8)
+#define SPM_FLAG_ENABLE_LVTS_WORKAROUND (1U << 9)
+#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10)
+#define SPM_FLAG_RESERVED_BIT11 (1U << 11)
+#define SPM_FLAG_ENABLE_SPM_DBG_WDT_DUMP (1U << 12)
+#define SPM_FLAG_USE_SRCCLKENO2 (1U << 13)
+#define SPM_FLAG_ENABLE_6315_CTRL (1U << 14)
+#define SPM_FLAG_ENABLE_TIA_WORKAROUND (1U << 15)
+#define SPM_FLAG_DISABLE_SYSRAM_SLEEP (1U << 16)
+#define SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP (1U << 17)
+#define SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP (1U << 18)
+#define SPM_FLAG_ENABLE_MD_MUMTAS (1U << 19)
+#define SPM_FLAG_ENABLE_VOLTAGE_BIN (1U << 20)
+#define SPM_FLAG_RESERVED_BIT21 (1U << 21)
+#define SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP (1U << 22)
+#define SPM_FLAG_DISABLE_SRAM_EVENT (1U << 23)
+#define SPM_FLAG_RESERVED_BIT24 (1U << 24)
+#define SPM_FLAG_RESERVED_BIT25 (1U << 25)
+#define SPM_FLAG_RESERVED_BIT26 (1U << 26)
+#define SPM_FLAG_VTCXO_STATE (1U << 27)
+#define SPM_FLAG_INFRA_STATE (1U << 28)
+#define SPM_FLAG_APSRC_STATE (1U << 29)
+#define SPM_FLAG_VRF18_STATE (1U << 30)
+#define SPM_FLAG_DDREN_STATE (1U << 31)
+/* --- SPM Flag1 Define --- */
+#define SPM_FLAG1_DISABLE_AXI_BUS_TO_26M (1U << 0)
+#define SPM_FLAG1_DISABLE_SYSPLL_OFF (1U << 1)
+#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 2)
+#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 3)
+#define SPM_FLAG1_FW_SET_ULPOSC_ON (1U << 4)
+#define SPM_FLAG1_RESERVED_BIT5 (1U << 5)
+#define SPM_FLAG1_ENABLE_REKICK (1U << 6)
+#define SPM_FLAG1_DISABLE_MD26M_CK_OFF (1U << 7)
+#define SPM_FLAG1_RESERVED_BIT8 (1U << 8)
+#define SPM_FLAG1_RESERVED_BIT9 (1U << 9)
+#define SPM_FLAG1_DISABLE_SRCLKEN_LOW (1U << 10)
+#define SPM_FLAG1_DISABLE_SCP_CLK_SWITCH (1U << 11)
+#define SPM_FLAG1_RESERVED_BIT12 (1U << 12)
+#define SPM_FLAG1_RESERVED_BIT13 (1U << 13)
+#define SPM_FLAG1_RESERVED_BIT14 (1U << 14)
+#define SPM_FLAG1_RESERVED_BIT15 (1U << 15)
+#define SPM_FLAG1_RESERVED_BIT16 (1U << 16)
+#define SPM_FLAG1_RESERVED_BIT17 (1U << 17)
+#define SPM_FLAG1_RESERVED_BIT18 (1U << 18)
+#define SPM_FLAG1_RESERVED_BIT19 (1U << 19)
+#define SPM_FLAG1_DISABLE_DEVAPC_SRAM_SLEEP (1U << 20)
+#define SPM_FLAG1_RESERVED_BIT21 (1U << 21)
+#define SPM_FLAG1_ENABLE_VS1_VOTER (1U << 22)
+#define SPM_FLAG1_ENABLE_VS2_VOTER (1U << 23)
+#define SPM_FLAG1_DISABLE_SCP_VREQ_MASK_CONTROL (1U << 24)
+#define SPM_FLAG1_RESERVED_BIT25 (1U << 25)
+#define SPM_FLAG1_RESERVED_BIT26 (1U << 26)
+#define SPM_FLAG1_RESERVED_BIT27 (1U << 27)
+#define SPM_FLAG1_RESERVED_BIT28 (1U << 28)
+#define SPM_FLAG1_RESERVED_BIT29 (1U << 29)
+#define SPM_FLAG1_RESERVED_BIT30 (1U << 30)
+#define SPM_FLAG1_DISABLE_CPUEB_OFF (1U << 31)
+/* --- SPM DEBUG Define --- */
+#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0)
+#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1)
+#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2)
+#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3)
+#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4)
+#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5)
+#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6)
+#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7)
+#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8)
+#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9)
+#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC (1U << 10)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_STATE (1U << 11)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_STATE (1U << 12)
+#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN (1U << 13)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_STATE (1U << 14)
+#define SPM_DBG_DEBUG_IDX_SYSRAM_SLP (1U << 15)
+#define SPM_DBG_DEBUG_IDX_SYSRAM_ON (1U << 16)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_SLP (1U << 17)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_ON (1U << 18)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 19)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_ON (1U << 20)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_SLP (1U << 21)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_ON (1U << 22)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P575V (1U << 23)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P600V (1U << 24)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P650V (1U << 25)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P725V (1U << 26)
+#define SPM_DBG_DEBUG_IDX_SPM_GO_WAKEUP_NOW (1U << 27)
+#define SPM_DBG_DEBUG_IDX_VTCXO_STATE (1U << 28)
+#define SPM_DBG_DEBUG_IDX_INFRA_STATE (1U << 29)
+#define SPM_DBG_DEBUG_IDX_VRR18_STATE (1U << 30)
+#define SPM_DBG_DEBUG_IDX_APSRC_STATE (1U << 31)
+/* --- SPM DEBUG1 Define --- */
+#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_LP (1U << 0)
+#define SPM_DBG1_DEBUG_IDX_VCORE_DVFS_START (1U << 1)
+#define SPM_DBG1_DEBUG_IDX_SYSPLL_OFF (1U << 2)
+#define SPM_DBG1_DEBUG_IDX_SYSPLL_ON (1U << 3)
+#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_VCORE_DVFS (1U << 4)
+#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_OFF (1U << 5)
+#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_ON (1U << 6)
+#define SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT (1U << 7)
+#define SPM_DBG1_RESERVED_BIT8 (1U << 8)
+#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_OFF (1U << 9)
+#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_ON (1U << 10)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_ULPOSC (1U << 11)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_26M (1U << 12)
+#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_32K (1U << 13)
+#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_26M (1U << 14)
+#define SPM_DBG1_DEBUG_IDX_BUS_CLK_OFF (1U << 15)
+#define SPM_DBG1_DEBUG_IDX_BUS_CLK_ON (1U << 16)
+#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_LOW (1U << 17)
+#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_HIGH (1U << 18)
+#define SPM_DBG1_RESERVED_BIT19 (1U << 19)
+#define SPM_DBG1_DEBUG_IDX_ULPOSC_IS_OFF_BUT_SHOULD_ON (1U << 20)
+#define SPM_DBG1_DEBUG_IDX_6315_LOW (1U << 21)
+#define SPM_DBG1_DEBUG_IDX_6315_HIGH (1U << 22)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT (1U << 23)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT (1U << 24)
+#define SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT (1U << 25)
+#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT (1U << 26)
+#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT (1U << 27)
+#define SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT (1U << 28)
+#define SPM_DBG1_RESERVED_BIT29 (1U << 29)
+#define SPM_DBG1_RESERVED_BIT30 (1U << 30)
+#define SPM_DBG1_DEBUG_DISABLE_CPUEB_OFF (1U << 31)
+
+ /* Macro and Inline */
+#define is_cpu_pdn(flags) (((flags) & SPM_FLAG_DISABLE_CPU_PDN) == 0U)
+#define is_infra_pdn(flags) (((flags) & SPM_FLAG_DISABLE_INFRA_PDN) == 0U)
+#define is_ddrphy_pdn(flags) (((flags) & SPM_FLAG_DISABLE_DDRPHY_PDN) == 0U)
+#endif /* SLEEP_DEF_H */
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc.c b/plat/mediatek/mt8192/drivers/spmc/mtspmc.c
new file mode 100644
index 0000000..7ccebd6
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <mtspmc.h>
+#include <mtspmc_private.h>
+
+
+void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu)
+{
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu)
+{
+ mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr)
+{
+ assert(cluster == 0U);
+
+ mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu)
+{
+ assert(cluster == 0U);
+
+ return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
+}
+
+void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64)
+{
+ uint32_t reg;
+
+ assert(cluster == 0U);
+
+ reg = per_cluster(cluster, MCUCFG_INITARCH);
+
+ if (arm64) {
+ mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ } else {
+ mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ }
+}
+
+/**
+ * Return subsystem's power state.
+ *
+ * @mask: mask to SPM_CPU_PWR_STATUS to query the power state
+ * of one subsystem.
+ * RETURNS:
+ * 0 (the subsys was powered off)
+ * 1 (the subsys was powered on)
+ */
+bool spm_get_powerstate(uint32_t mask)
+{
+ return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask) != 0U;
+}
+
+bool spm_get_cluster_powerstate(uint32_t cluster)
+{
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(MP0_CPUTOP);
+}
+
+bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu)
+{
+ uint32_t mask = BIT(cpu);
+
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(mask);
+}
+
+int spmc_init(void)
+{
+ INFO("SPM: enable CPC mode\n");
+
+ mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
+
+ mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(1));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(2));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(3));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(4));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(5));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(6));
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(7));
+
+ mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+
+ return 0;
+}
+
+/**
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(uint32_t cluster, uint32_t cpu)
+{
+ /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
+ if (cpu >= 4U) {
+ mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
+ }
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+ mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+
+ while (!spm_get_cpu_powerstate(cluster, cpu)) {
+ }
+
+ mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
+
+ /* Enable Big CPU Last PC */
+ if (cpu >= 4U) {
+ mmio_clrbits_32(LAST_PC_REG(cpu), BIT(3));
+ }
+}
+
+/**
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu)
+{
+ /* Set mp0_spmc_pwr_on_cpuX = 0 */
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+}
+
+/**
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(uint32_t cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
+
+/**
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(uint32_t cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc.h b/plat/mediatek/mt8192/drivers/spmc/mtspmc.h
new file mode 100644
index 0000000..7ed2e62
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+#include <stdint.h>
+
+int spmc_init(void);
+
+void spm_poweron_cpu(uint32_t cluster, uint32_t cpu);
+void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu);
+
+void spm_poweroff_cluster(uint32_t cluster);
+void spm_poweron_cluster(uint32_t cluster);
+
+bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu);
+bool spm_get_cluster_powerstate(uint32_t cluster);
+bool spm_get_powerstate(uint32_t mask);
+
+void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64);
+void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu);
+
+void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu);
+void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h
new file mode 100644
index 0000000..ad78295
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_PRIVATE_H
+#define MTSPMC_PRIVATE_H
+
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+unsigned long read_cpuectlr(void);
+void write_cpuectlr(unsigned long cpuectlr);
+
+unsigned long read_cpupwrctlr_el1(void);
+void write_cpupwrctlr_el1(unsigned long cpuectlr);
+
+/*
+ * per_cpu/cluster helper
+ */
+struct per_cpu_reg {
+ unsigned int cluster_addr;
+ unsigned int cpu_stride;
+};
+
+#define per_cpu(cluster, cpu, reg) \
+ (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
+
+#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
+
+#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs))
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs))
+
+/* === SPMC related registers */
+#define SPM_POWERON_CONFIG_EN SPM_REG(0x000)
+/* bit-fields of SPM_POWERON_CONFIG_EN */
+#define PROJECT_CODE (U(0xb16) << 16)
+#define BCLK_CG_EN BIT(0)
+
+#define SPM_PWR_STATUS SPM_REG(0x16c)
+#define SPM_PWR_STATUS_2ND SPM_REG(0x170)
+#define SPM_CPU_PWR_STATUS SPM_REG(0x174)
+
+/* bit-fields of SPM_PWR_STATUS */
+#define MD BIT(0)
+#define CONN BIT(1)
+#define DDRPHY BIT(2)
+#define DISP BIT(3)
+#define MFG BIT(4)
+#define ISP BIT(5)
+#define INFRA BIT(6)
+#define VDEC BIT(7)
+#define MP0_CPUTOP BIT(8)
+#define MP0_CPU0 BIT(9)
+#define MP0_CPU1 BIT(10)
+#define MP0_CPU2 BIT(11)
+#define MP0_CPU3 BIT(12)
+#define MCUSYS BIT(14)
+#define MP0_CPU4 BIT(15)
+#define MP0_CPU5 BIT(16)
+#define MP0_CPU6 BIT(17)
+#define MP0_CPU7 BIT(18)
+#define VEN BIT(21)
+
+/* === SPMC related registers */
+#define SPM_MCUSYS_PWR_CON MCUCFG_REG(0xd200)
+#define SPM_MP0_CPUTOP_PWR_CON MCUCFG_REG(0xd204)
+#define SPM_MP0_CPU0_PWR_CON MCUCFG_REG(0xd208)
+#define SPM_MP0_CPU1_PWR_CON MCUCFG_REG(0xd20c)
+#define SPM_MP0_CPU2_PWR_CON MCUCFG_REG(0xd210)
+#define SPM_MP0_CPU3_PWR_CON MCUCFG_REG(0xd214)
+#define SPM_MP0_CPU4_PWR_CON MCUCFG_REG(0xd218)
+#define SPM_MP0_CPU5_PWR_CON MCUCFG_REG(0xd21c)
+#define SPM_MP0_CPU6_PWR_CON MCUCFG_REG(0xd220)
+#define SPM_MP0_CPU7_PWR_CON MCUCFG_REG(0xd224)
+
+/* bit fields of SPM_*_PWR_CON */
+#define PWR_ON_ACK BIT(31)
+#define VPROC_EXT_OFF BIT(7)
+#define DORMANT_EN BIT(6)
+#define RESETPWRON_CONFIG BIT(5)
+#define PWR_CLK_DIS BIT(4)
+#define PWR_ON BIT(2)
+#define PWR_RST_B BIT(0)
+
+/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */
+static const struct per_cpu_reg SPM_CPU_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
+};
+
+/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
+static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
+};
+
+/* === MCUCFG related registers */
+/* aa64naa32 */
+#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4)
+/* reset vectors */
+#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900)
+#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908)
+#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910)
+#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918)
+#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920)
+#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928)
+#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930)
+#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938)
+
+/* MCUSYS DREQ BIG VPROC ISO control */
+#define DREQ20_BIG_VPROC_ISO MCUCFG_REG(0xad8c)
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
+};
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
+};
+
+#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
+#define LAST_PC_REG(cpu) (MCUCFG_REG(0x308) + (cpu * 0x800))
+
+/* === CPC control */
+#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
+
+/* bit fields of CPC_FLOW_CTRL_CFG */
+#define CPC_CTRL_ENABLE BIT(16)
+#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
+
+/* bit fields of CPC_SPMC_PWR_STATUS */
+#define CORE_SPMC_PWR_ON_ACK GENMASK(15, 0)
+
+/* === APB Module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
+#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224)
+#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228)
+#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0)
+#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4)
+#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250)
+#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac)
+
+/* bit fields of INFRA_TOPAXI_PROTECTEN */
+#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12)
+#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12))
+
+/* === SPARK */
+#define VOLTAGE_04 U(0x40)
+#define VOLTAGE_05 U(0x60)
+
+#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200)
+#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334)
+#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340)
+
+/* bit fields of CPU0_ILDO_CONTROL5 */
+#define ILDO_RET_VOSEL GENMASK(7, 0)
+
+/* bit fields of PTP3_CPU_SPMC_SW_CFG */
+#define SW_SPARK_EN BIT(0)
+
+/* bit fields of CPU0_ILDO_CONTROL8 */
+#define ILDO_BYPASS_B BIT(0)
+
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+ { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL5[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL8[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8192/include/mcucfg.h b/plat/mediatek/mt8192/include/mcucfg.h
new file mode 100644
index 0000000..046cf73
--- /dev/null
+++ b/plat/mediatek/mt8192/include/mcucfg.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCUCFG_H
+#define MCUCFG_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER__ */
+
+#include <platform_def.h>
+
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+
+#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
+#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
+
+#define MP2_CPUCFG MCUCFG_REG(0x2208)
+
+#define MP2_CPU0_STANDBYWFE BIT(4)
+#define MP2_CPU1_STANDBYWFE BIT(5)
+
+#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788)
+#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C)
+#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790)
+
+#define sw_spark_en BIT(0)
+#define sw_no_wait_for_q_channel BIT(1)
+#define sw_fsm_override BIT(2)
+#define sw_logic_pre1_pdb BIT(3)
+#define sw_logic_pre2_pdb BIT(4)
+#define sw_logic_pdb BIT(5)
+#define sw_iso BIT(6)
+#define sw_sram_sleepb (U(0x3F) << 7)
+#define sw_sram_isointb BIT(13)
+#define sw_clk_dis BIT(14)
+#define sw_ckiso BIT(15)
+#define sw_pd (U(0x3F) << 16)
+#define sw_hot_plug_reset BIT(22)
+#define sw_pwr_on_override_en BIT(23)
+#define sw_pwr_on BIT(24)
+#define sw_coq_dis BIT(25)
+#define logic_pdbo_all_off_ack BIT(26)
+#define logic_pdbo_all_on_ack BIT(27)
+#define logic_pre2_pdbo_all_on_ack BIT(28)
+#define logic_pre1_pdbo_all_on_ack BIT(29)
+
+
+#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
+ (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
+
+#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30)
+#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34)
+#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38)
+#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C)
+
+#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30)
+#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34)
+#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38)
+#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C)
+
+#define cpu_sw_spark_en BIT(0)
+#define cpu_sw_no_wait_for_q_channel BIT(1)
+#define cpu_sw_fsm_override BIT(2)
+#define cpu_sw_logic_pre1_pdb BIT(3)
+#define cpu_sw_logic_pre2_pdb BIT(4)
+#define cpu_sw_logic_pdb BIT(5)
+#define cpu_sw_iso BIT(6)
+#define cpu_sw_sram_sleepb BIT(7)
+#define cpu_sw_sram_isointb BIT(8)
+#define cpu_sw_clk_dis BIT(9)
+#define cpu_sw_ckiso BIT(10)
+#define cpu_sw_pd (U(0x1F) << 11)
+#define cpu_sw_hot_plug_reset BIT(16)
+#define cpu_sw_powr_on_override_en BIT(17)
+#define cpu_sw_pwr_on BIT(18)
+#define cpu_spark2ldo_allswoff BIT(19)
+#define cpu_pdbo_all_on_ack BIT(20)
+#define cpu_pre2_pdbo_allon_ack BIT(21)
+#define cpu_pre1_pdbo_allon_ack BIT(22)
+
+/* CPC related registers */
+#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714)
+#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804)
+#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818)
+#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c)
+#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824)
+#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac)
+#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10)
+#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14)
+#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20)
+#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70)
+#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74)
+
+#define SPARK2LDO MCUCFG_REG(0x2700)
+/* APB Module mcucfg */
+#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000)
+#define MP0_AXI_CONFIG MCUCFG_REG(0x02C)
+#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030)
+#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034)
+#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038)
+#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8))
+#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C)
+#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054)
+#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064)
+
+#define MP0_RW_RSVD0 MCUCFG_REG(0x06C)
+
+
+#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200)
+#define MP1_AXI_CONFIG MCUCFG_REG(0x22C)
+#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230)
+#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234)
+#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238)
+#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8))
+#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C)
+#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254)
+#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264)
+
+#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740)
+#define SYNC_DCM_CONFIG MCUCFG_REG(0x744)
+
+#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0)
+
+#define MP0_SPMC MCUCFG_REG(0x788)
+#define MP1_SPMC MCUCFG_REG(0x78C)
+#define MP2_AXI_CONFIG MCUCFG_REG(0x220C)
+#define MP2_AXI_CONFIG_ACINACTM BIT(0)
+#define MP2_AXI_CONFIG_AINACTS BIT(4)
+
+#define MPx_AXI_CONFIG_ACINACTM BIT(4)
+#define MPx_AXI_CONFIG_AINACTS BIT(5)
+
+#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
+
+#define MP0_CPU0_STANDBYWFE BIT(20)
+#define MP0_CPU1_STANDBYWFE BIT(21)
+#define MP0_CPU2_STANDBYWFE BIT(22)
+#define MP0_CPU3_STANDBYWFE BIT(23)
+
+#define MP1_CPU0_STANDBYWFE BIT(20)
+#define MP1_CPU1_STANDBYWFE BIT(21)
+#define MP1_CPU2_STANDBYWFE BIT(22)
+#define MP1_CPU3_STANDBYWFE BIT(23)
+
+#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00)
+#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04)
+#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08)
+#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00)
+#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04)
+#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08)
+
+#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008)
+#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0)
+#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4)
+
+#define MP2_COQ MCUCFG_REG(0x22BC)
+#define MP2_COQ_SW_DIS BIT(0)
+
+#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400)
+#define MP2_CA15M_MON_L MCUCFG_REG(0x2404)
+
+#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430)
+#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438)
+#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434)
+#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C)
+
+#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068)
+#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268)
+#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C)
+
+#define MP2_SW_RST_B BIT(0)
+#define MP2_TOPAON_APB_MASK BIT(1)
+
+#define B_SW_HOT_PLUG_RESET BIT(30)
+
+#define B_SW_PD_OFFSET 18U
+#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET)
+
+#define B_SW_SRAM_SLEEPB_OFFSET 12U
+#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
+
+#define B_SW_SRAM_ISOINTB BIT(9)
+#define B_SW_ISO BIT(8)
+#define B_SW_LOGIC_PDB BIT(7)
+#define B_SW_LOGIC_PRE2_PDB BIT(6)
+#define B_SW_LOGIC_PRE1_PDB BIT(5)
+#define B_SW_FSM_OVERRIDE BIT(4)
+#define B_SW_PWR_ON BIT(3)
+#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
+
+#define B_FSM_STATE_OUT_OFFSET (6U)
+#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET)
+#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
+#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
+#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
+#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
+
+#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
+
+#ifndef __ASSEMBLER__
+/* cpu boot mode */
+enum {
+ MP0_CPUCFG_64BIT_SHIFT = 12U,
+ MP1_CPUCFG_64BIT_SHIFT = 28U,
+ MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
+ MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
+};
+
+enum {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
+
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+ MP1_AINACTS_SHIFT = 4U,
+ MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
+};
+
+enum {
+ MP1_SW_CG_GEN_SHIFT = 12U,
+ MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+ MP1_L2RSTDISABLE_SHIFT = 14U,
+ MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
+};
+#endif /* __ASSEMBLER__ */
+
+#endif /* MCUCFG_H */
diff --git a/plat/mediatek/mt8192/include/plat_helpers.h b/plat/mediatek/mt8192/include/plat_helpers.h
new file mode 100644
index 0000000..9b550ee
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8192/include/plat_macros.S b/plat/mediatek/mt8192/include/plat_macros.S
new file mode 100644
index 0000000..7d17e36
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_macros.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception
+ * is taken in BL31.
+ * Clobbers: x0 - x10, x26, x27, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /* To-do: GIC owner */
+ /* To-do: CCI owner */
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8192/include/plat_mtk_lpm.h b/plat/mediatek/mt8192/include/plat_mtk_lpm.h
new file mode 100644
index 0000000..deaac97
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_mtk_lpm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MTK_LPM_H
+#define PLAT_MTK_LPM_H
+
+#include <lib/psci/psci.h>
+#include <lib/utils_def.h>
+
+#define MT_IRQ_REMAIN_MAX U(32)
+#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
+
+struct mt_irqremain {
+ unsigned int count;
+ unsigned int irqs[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
+};
+
+#define PLAT_RC_STATUS_READY BIT(0)
+#define PLAT_RC_STATUS_FEATURE_EN BIT(1)
+#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31)
+
+struct mt_lpm_tz {
+ int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cluster_on)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_cluster_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+
+ int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_mcusys_on_finished)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_mcusys_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
+
+#endif /* PLAT_MTK_LPM_H */
diff --git a/plat/mediatek/mt8192/include/plat_pm.h b/plat/mediatek/mt8192/include/plat_pm.h
new file mode 100644
index 0000000..a2881ce
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_pm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_H
+#define PLAT_PM_H
+
+#include <lib/utils_def.h>
+
+#define MT_PLAT_PWR_STATE_CPU U(1)
+#define MT_PLAT_PWR_STATE_CLUSTER U(2)
+#define MT_PLAT_PWR_STATE_MCUSYS U(3)
+#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8)
+#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9)
+
+#define MTK_LOCAL_STATE_RUN U(0)
+#define MTK_LOCAL_STATE_RET U(1)
+#define MTK_LOCAL_STATE_OFF U(2)
+
+#define MTK_AFFLVL_CPU U(0)
+#define MTK_AFFLVL_CLUSTER U(1)
+#define MTK_AFFLVL_MCUSYS U(2)
+#define MTK_AFFLVL_SYSTEM U(3)
+
+#define IS_CLUSTER_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
+#define IS_MCUSYS_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
+#define IS_SYSTEM_SUSPEND_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
+
+#define IS_PLAT_SUSPEND_ID(stateid)\
+ ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \
+ || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
+
+#endif /* PLAT_PM_H */
diff --git a/plat/mediatek/mt8192/include/plat_private.h b/plat/mediatek/mt8192/include/plat_private.h
new file mode 100644
index 0000000..42ca415
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8192/include/plat_sip_calls.h b/plat/mediatek/mt8192/include/plat_sip_calls.h
new file mode 100644
index 0000000..fdc7bea
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_sip_calls.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+/*******************************************************************************
+ * Plat SiP function constants
+ ******************************************************************************/
+#define MTK_PLAT_SIP_NUM_CALLS (4)
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8192/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h
new file mode 100644
index 0000000..ec377b5
--- /dev/null
+++ b/plat/mediatek/mt8192/include/platform_def.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+
+#define PLAT_PRIMARY_CPU 0x0
+
+#define MT_GIC_BASE 0x0c000000
+#define PLAT_MT_CCI_BASE 0x0c500000
+#define MCUCFG_BASE 0x0c530000
+
+#define IO_PHYS 0x10000000
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE IO_PHYS
+#define MTK_DEV_RNG0_SIZE 0x10000000
+#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x10000000)
+#define MTK_DEV_RNG1_SIZE 0x10000000
+#define MTK_DEV_RNG2_BASE 0x0c000000
+#define MTK_DEV_RNG2_SIZE 0x600000
+#define MTK_MCDI_SRAM_BASE 0x11B000
+#define MTK_MCDI_SRAM_MAP_SIZE 0x1000
+
+#define APUSYS_BASE 0x19000000
+#define APUSYS_SCTRL_REVISER_BASE 0x19021000
+#define APUSYS_SCTRL_REVISER_SIZE 0x1000
+#define APUSYS_APU_S_S_4_BASE 0x190F2000
+#define APUSYS_APU_S_S_4_SIZE 0x1000
+#define APUSYS_APC_AO_WRAPPER_BASE 0x190F8000
+#define APUSYS_APC_AO_WRAPPER_SIZE 0x1000
+#define APUSYS_NOC_DAPC_AO_BASE 0x190FC000
+#define APUSYS_NOC_DAPC_AO_SIZE 0x1000
+
+#define TOPCKGEN_BASE (IO_PHYS + 0x00000000)
+#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
+#define GPIO_BASE (IO_PHYS + 0x00005000)
+#define SPM_BASE (IO_PHYS + 0x00006000)
+#define APMIXEDSYS (IO_PHYS + 0x0000C000)
+#define DVFSRC_BASE (IO_PHYS + 0x00012000)
+#define PMIC_WRAP_BASE (IO_PHYS + 0x00026000)
+#define DEVAPC_INFRA_AO_BASE (IO_PHYS + 0x00030000)
+#define DEVAPC_PERI_AO_BASE (IO_PHYS + 0x00034000)
+#define DEVAPC_PERI_AO2_BASE (IO_PHYS + 0x00038000)
+#define DEVAPC_PERI_PAR_AO_BASE (IO_PHYS + 0x0003C000)
+#define EMI_BASE (IO_PHYS + 0x00219000)
+#define EMI_MPU_BASE (IO_PHYS + 0x00226000)
+#define SSPM_MBOX_BASE (IO_PHYS + 0x00480000)
+#define IOCFG_RM_BASE (IO_PHYS + 0x01C20000)
+#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000)
+#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000)
+#define IOCFG_BR_BASE (IO_PHYS + 0x01D40000)
+#define IOCFG_LM_BASE (IO_PHYS + 0x01E20000)
+#define IOCFG_LB_BASE (IO_PHYS + 0x01E70000)
+#define IOCFG_RT_BASE (IO_PHYS + 0x01EA0000)
+#define IOCFG_LT_BASE (IO_PHYS + 0x01F20000)
+#define IOCFG_TL_BASE (IO_PHYS + 0x01F30000)
+#define MMSYS_BASE (IO_PHYS + 0x04000000)
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE (IO_PHYS + 0x01002000)
+#define UART1_BASE (IO_PHYS + 0x01003000)
+
+#define UART_BAUDRATE 115200
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 13000000
+#define SYS_COUNTER_FREQ_IN_MHZ 13
+
+/*******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE MT_GIC_BASE
+#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000)
+
+#define SYS_CIRQ_BASE (IO_PHYS + 0x204000)
+#define CIRQ_REG_NUM 14
+#define CIRQ_IRQ_NUM 439
+#define CIRQ_SPI_START 64
+#define MD_WDT_IRQ_BIT_ID 110
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE 0x800
+
+#define PLAT_MAX_PWR_LVL U(3)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(9)
+
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_MCUSYS_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(8)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8)
+
+#define SOC_CHIP_ID U(0x8192)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE 0x54600000
+#define TZRAM_SIZE 0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 16
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8192/include/rtc.h b/plat/mediatek/mt8192/include/rtc.h
new file mode 100644
index 0000000..a9c7bc8
--- /dev/null
+++ b/plat/mediatek/mt8192/include/rtc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#include <rtc_mt6359p.h>
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c
new file mode 100644
index 0000000..018e418
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_pm.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* common headers */
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/gpio.h>
+#include <lib/psci/psci.h>
+
+/* platform specific headers */
+#include <mt_gic_v3.h>
+#include <mtk_ptp3_common.h>
+#include <mtspmc.h>
+#include <plat/common/platform.h>
+#include <plat_dfd.h>
+#include <plat_mtk_lpm.h>
+#include <plat_params.h>
+#include <plat_pm.h>
+#include <pmic.h>
+#include <rtc.h>
+
+/*
+ * Cluster state request:
+ * [0] : The CPU requires cluster power down
+ * [1] : The CPU requires cluster power on
+ */
+#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron() coordinate_cluster(1)
+#define coordinate_cluster_pwroff() coordinate_cluster(0)
+
+/* platform secure entry point */
+static uintptr_t secure_entrypoint;
+/* per-CPU power state */
+static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
+
+/* platform CPU power domain - ops */
+static const struct mt_lpm_tz *plat_mt_pm;
+
+#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \
+ int ret = -1; \
+ if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+ ret = plat_mt_pm->_name(_cpu, _state); \
+ } \
+ ret; })
+
+#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \
+ if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+ (void) plat_mt_pm->_name(_cpu, _state); \
+ } \
+ })
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cpu_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state);
+
+ if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
+ (req_pstate == 0U)) { /* hotplug off */
+ coordinate_cluster_pwroff();
+ }
+
+ /* Prevent interrupts from spuriously waking up this CPU */
+ mt_gic_rdistif_save();
+ gicv3_cpuif_disable(cpu);
+ gicv3_rdistif_off(cpu);
+ /* PTP3 config */
+ ptp3_deinit(cpu);
+}
+
+static void plat_cpu_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state);
+
+ coordinate_cluster_pwron();
+
+ /*
+ * If mcusys does power down before then restore
+ * all CPUs' GIC Redistributors
+ */
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ mt_gic_rdistif_restore_all();
+ } else {
+ gicv3_rdistif_on(cpu);
+ gicv3_cpuif_enable(cpu);
+ mt_gic_rdistif_init();
+ mt_gic_rdistif_restore();
+ }
+
+ /* PTP3 config */
+ ptp3_init(cpu);
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cluster_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) {
+ coordinate_cluster_pwron();
+
+ /* TODO: return on fail.
+ * Add a 'return' here before adding any code following
+ * the if-block.
+ */
+ }
+}
+
+static void plat_cluster_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) {
+ /* TODO: return on fail.
+ * Add a 'return' here before adding any code following
+ * the if-block.
+ */
+ }
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_mcusys_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) {
+ return; /* return on fail */
+ }
+
+ mt_gic_distif_save();
+ gic_sgi_save_all();
+}
+
+static void plat_mcusys_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) {
+ return; /* return on fail */
+ }
+
+ mt_gic_init();
+ mt_gic_distif_restore();
+ gic_sgi_restore_all();
+
+ dfd_resume();
+
+ plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
+}
+
+/*
+ * plat_psci_ops implementation
+ */
+
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+ uint64_t scr;
+
+ scr = read_scr_el3();
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+ isb();
+ dsb();
+ wfi();
+
+ write_scr_el3(scr);
+}
+
+static int plat_power_domain_on(u_register_t mpidr)
+{
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+ unsigned int cluster = 0U;
+
+ if (cpu >= PLATFORM_CORE_COUNT) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (!spm_get_cluster_powerstate(cluster)) {
+ spm_poweron_cluster(cluster);
+ }
+
+ /* init CPU reset arch as AARCH64 */
+ mcucfg_init_archstate(cluster, cpu, true);
+ mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+ spm_poweron_cpu(cluster, cpu);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ /* Allow IRQs to wakeup this core in IDLE flow */
+ mcucfg_enable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwron_common(cpu, state, 0U);
+ }
+
+ plat_cpu_pwron_common(cpu, state, 0U);
+}
+
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ plat_cpu_pwrdwn_common(cpu, state, 0U);
+ spm_poweroff_cpu(0U, cpu);
+
+ /* prevent unintended IRQs from waking up the hot-unplugged core */
+ mcucfg_disable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwrdwn_common(cpu, state, 0U);
+ }
+}
+
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state);
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+}
+
+static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
+
+ plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state);
+}
+
+static int plat_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int cpu = plat_my_core_pos();
+
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+ } else {
+ unsigned int i;
+ unsigned int pstate_id = psci_get_pstate_id(power_state);
+ plat_local_state_t s = MTK_LOCAL_STATE_OFF;
+
+ /* Use pstate_id to be power domain state */
+ if (pstate_id > s) {
+ s = (plat_local_state_t)pstate_id;
+ }
+
+ for (i = 0U; i <= aff_lvl; i++) {
+ req_state->pwr_domain_state[i] = s;
+ }
+ }
+
+ plat_power_state[cpu] = power_state;
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int lv;
+ unsigned int cpu = plat_my_core_pos();
+
+ for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
+ req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
+ }
+
+ plat_power_state[cpu] =
+ psci_make_powerstate(
+ MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
+ PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+
+ flush_dcache_range((uintptr_t)
+ &plat_power_state[cpu],
+ sizeof(plat_power_state[cpu]));
+}
+
+static void __dead2 plat_mtk_system_off(void)
+{
+ INFO("MTK System Off\n");
+
+ rtc_power_off_sequence();
+ pmic_power_off();
+
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 plat_mtk_system_reset(void)
+{
+ struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+ INFO("MTK System Reset\n");
+
+ gpio_set_value(gpio_reset->index, gpio_reset->polarity);
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+static const plat_psci_ops_t plat_psci_ops = {
+ .system_reset = plat_mtk_system_reset,
+ .cpu_standby = plat_cpu_standby,
+ .pwr_domain_on = plat_power_domain_on,
+ .pwr_domain_on_finish = plat_power_domain_on_finish,
+ .pwr_domain_off = plat_power_domain_off,
+ .pwr_domain_suspend = plat_power_domain_suspend,
+ .pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
+ .system_off = plat_mtk_system_off,
+ .validate_power_state = plat_validate_power_state,
+ .get_sys_suspend_power_state = plat_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_psci_ops;
+ secure_entrypoint = sec_entrypoint;
+
+ /*
+ * init the warm reset config for boot CPU
+ * reset arch as AARCH64
+ * reset addr as function bl31_warm_entrypoint()
+ */
+ mcucfg_init_archstate(0U, 0U, true);
+ mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
+
+ spmc_init();
+ plat_mt_pm = mt_plat_cpu_pm_init();
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8192/plat_sip_calls.c b/plat/mediatek/mt8192/plat_sip_calls.c
new file mode 100644
index 0000000..0fffed5
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_sip_calls.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <mtk_apusys.h>
+#include <mtk_sip_svc.h>
+#include <mt_spm_vcorefs.h>
+#include <plat_dfd.h>
+#include "plat_sip_calls.h"
+
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint64_t ret;
+ uint32_t rnd_val0 = 0U;
+
+ switch (smc_fid) {
+ case MTK_SIP_VCORE_CONTROL_AARCH32:
+ case MTK_SIP_VCORE_CONTROL_AARCH64:
+ ret = spm_vcorefs_args(x1, x2, x3, (uint64_t *)&x4);
+ SMC_RET2(handle, ret, x4);
+ break;
+ case MTK_SIP_APUSYS_CONTROL_AARCH32:
+ case MTK_SIP_APUSYS_CONTROL_AARCH64:
+ ret = apusys_kernel_ctrl(x1, x2, x3, x4, &rnd_val0);
+ SMC_RET2(handle, ret, rnd_val0);
+ break;
+ case MTK_SIP_KERNEL_DFD_AARCH32:
+ case MTK_SIP_KERNEL_DFD_AARCH64:
+ ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+ SMC_RET1(handle, ret);
+ break;
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ break;
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/mediatek/mt8192/plat_topology.c b/plat/mediatek/mt8192/plat_topology.c
new file mode 100644
index 0000000..8c1231a
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_topology.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Project Includes */
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+/* Platform Includes */
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* Number of children for the root node */
+ PLATFORM_MCUSYS_COUNT,
+ /* Number of children for the mcusys node */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the MT8192 default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ if (read_mpidr() & MPIDR_MT_MASK) {
+ /* ARMv8.2 arch */
+ if (mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) {
+ return -1;
+ }
+ return plat_mediatek_calc_core_pos(mpidr);
+ }
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
+ return -1;
+ }
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
new file mode 100644
index 0000000..a19fc45
--- /dev/null
+++ b/plat/mediatek/mt8192/platform.mk
@@ -0,0 +1,103 @@
+#
+# Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT}/common/lpm/ \
+ -I${MTK_PLAT}/drivers/cirq/ \
+ -I${MTK_PLAT}/drivers/gic600/ \
+ -I${MTK_PLAT}/drivers/gpio/ \
+ -I${MTK_PLAT}/drivers/pmic/ \
+ -I${MTK_PLAT}/drivers/pmic_wrap/ \
+ -I${MTK_PLAT}/drivers/rtc/ \
+ -I${MTK_PLAT}/drivers/timer/ \
+ -I${MTK_PLAT}/drivers/uart/ \
+ -I${MTK_PLAT}/include/ \
+ -I${MTK_PLAT_SOC}/include/ \
+ -I${MTK_PLAT_SOC}/drivers/ \
+ -I${MTK_PLAT_SOC}/drivers/apusys/ \
+ -I${MTK_PLAT_SOC}/drivers/dcm \
+ -I${MTK_PLAT_SOC}/drivers/devapc \
+ -I${MTK_PLAT_SOC}/drivers/dfd \
+ -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
+ -I${MTK_PLAT_SOC}/drivers/gpio/ \
+ -I${MTK_PLAT_SOC}/drivers/mcdi/ \
+ -I${MTK_PLAT_SOC}/drivers/pmic/ \
+ -I${MTK_PLAT_SOC}/drivers/ptp3/ \
+ -I${MTK_PLAT_SOC}/drivers/spmc/
+
+GICV3_SUPPORT_GIC600 := 1
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+BL31_SOURCES += common/desc_image_load.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ drivers/gpio/gpio.c \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/cpus/aarch64/cortex_a55.S \
+ lib/cpus/aarch64/cortex_a76.S \
+ plat/common/plat_gicv3.c \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/mtk_sip_svc.c \
+ ${MTK_PLAT}/common/params_setup.c \
+ ${MTK_PLAT}/common/lpm/mt_lp_rm.c \
+ ${MTK_PLAT}/drivers/cirq/mt_cirq.c \
+ ${MTK_PLAT}/drivers/gic600/mt_gic_v3.c \
+ ${MTK_PLAT}/drivers/gpio/mtgpio_common.c \
+ ${MTK_PLAT}/drivers/pmic/pmic.c \
+ ${MTK_PLAT}/drivers/pmic_wrap/pmic_wrap_init_v2.c \
+ ${MTK_PLAT}/drivers/rtc/rtc_common.c \
+ ${MTK_PLAT}/drivers/rtc/rtc_mt6359p.c \
+ ${MTK_PLAT}/drivers/timer/mt_timer.c \
+ ${MTK_PLAT}/drivers/uart/uart.c \
+ ${MTK_PLAT_SOC}/aarch64/platform_common.c \
+ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
+ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
+ ${MTK_PLAT_SOC}/plat_pm.c \
+ ${MTK_PLAT_SOC}/plat_topology.c \
+ ${MTK_PLAT_SOC}/plat_sip_calls.c \
+ ${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys.c \
+ ${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys_apc.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
+ ${MTK_PLAT_SOC}/drivers/devapc/devapc.c \
+ ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \
+ ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
+ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \
+ ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c \
+ ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c
+
+# Build SPM drivers
+include ${MTK_PLAT_SOC}/drivers/spm/build.mk
+
+# Configs for A76 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8192 := 1
+$(eval $(call add_define,MACH_MT8192))
+
+include lib/coreboot/coreboot.mk
+
diff --git a/plat/mediatek/mt8195/aarch64/plat_helpers.S b/plat/mediatek/mt8195/aarch64/plat_helpers.S
new file mode 100644
index 0000000..a973f4d
--- /dev/null
+++ b/plat/mediatek/mt8195/aarch64/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_mediatek_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+ *
+ * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and
+ * AFF0 is thread id. There is only one cluster in ARMv8.2
+ * and one thread in current implementation.
+ *
+ * With this function: CorePos = CoreID (AFF1)
+ * we do it with x0 = (x0 >> 8) & 0xff
+ * -----------------------------------------------------
+ */
+func plat_mediatek_calc_core_pos
+ mov x1, #MPIDR_AFFLVL_MASK
+ and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+ ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8195/aarch64/platform_common.c b/plat/mediatek/mt8195/aarch64/platform_common.c
new file mode 100644
index 0000000..1f5c5fa
--- /dev/null
+++ b/plat/mediatek/mt8195/aarch64/platform_common.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_mmap[] = {
+ /* for TF text, RO, RW */
+ MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MTK_MCDI_SRAM_BASE, MTK_MCDI_SRAM_MAP_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DP_SEC_BASE, DP_SEC_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(EDP_SEC_BASE, EDP_SEC_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_SCTRL_REVISER_BASE, APUSYS_SCTRL_REVISER_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_APU_S_S_4_BASE, APUSYS_APU_S_S_4_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_APU_PLL_BASE, APUSYS_APU_PLL_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(APUSYS_APU_ACC_BASE, APUSYS_APU_ACC_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_RW_DATA | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_CODE | MT_SECURE);
+ mmap_add(plat_mmap);
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8195/bl31_plat_setup.c b/plat/mediatek/mt8195/bl31_plat_setup.c
new file mode 100644
index 0000000..dff6670
--- /dev/null
+++ b/plat/mediatek/mt8195/bl31_plat_setup.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <emi_mpu.h>
+#include <mt_gic_v3.h>
+#include <mt_spm.h>
+#include <mt_timer.h>
+#include <mtk_dcm.h>
+#include <mtgpio.h>
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ params_early_setup(arg1);
+
+#if COREBOOT
+ if (coreboot_serial.type) {
+ console_16550_register(coreboot_serial.baseaddr,
+ coreboot_serial.input_hertz,
+ coreboot_serial.baud,
+ &console);
+ }
+#else
+ console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+ NOTICE("MT8195 bl31_setup\n");
+
+ bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ /* Set dcm on */
+ if (!dcm_set_default()) {
+ ERROR("Failed to set default dcm on!!\n");
+ }
+
+ /* Initialize EMI MPU */
+ emi_mpu_init();
+
+ /* Initialize the GIC driver, CPU and distributor interfaces */
+ mt_gic_driver_init();
+ mt_gic_init();
+
+ mt_gpio_init();
+ mt_systimer_init();
+ generic_delay_timer_init();
+ spm_boot_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_configure_mmu_el3(BL31_START,
+ BL31_END - BL31_START,
+ BL_CODE_BASE,
+ BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupll.c b/plat/mediatek/mt8195/drivers/apusys/apupll.c
new file mode 100644
index 0000000..0eb8d4a
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupll.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/spinlock.h>
+
+#include <apupwr_clkctl.h>
+#include <apupwr_clkctl_def.h>
+#include <mtk_plat_common.h>
+#include <platform_def.h>
+
+uint32_t mixed_con0_addr[APUPLL_MAX] = {
+ APU_PLL4H_PLL1_CON0,
+ APU_PLL4H_PLL2_CON0,
+ APU_PLL4H_PLL3_CON0,
+ APU_PLL4H_PLL4_CON0,
+};
+
+uint32_t mixed_con1_addr[APUPLL_MAX] = {
+ APU_PLL4H_PLL1_CON1,
+ APU_PLL4H_PLL2_CON1,
+ APU_PLL4H_PLL3_CON1,
+ APU_PLL4H_PLL4_CON1,
+};
+
+uint32_t mixed_con3_addr[APUPLL_MAX] = {
+ APU_PLL4H_PLL1_CON3,
+ APU_PLL4H_PLL2_CON3,
+ APU_PLL4H_PLL3_CON3,
+ APU_PLL4H_PLL4_CON3,
+};
+
+uint32_t fhctl_dds_addr[APUPLL_MAX] = {
+ APU_PLL4H_FHCTL0_DDS,
+ APU_PLL4H_FHCTL1_DDS,
+ APU_PLL4H_FHCTL2_DDS,
+ APU_PLL4H_FHCTL3_DDS,
+};
+
+uint32_t fhctl_dvfs_addr[APUPLL_MAX] = {
+ APU_PLL4H_FHCTL0_DVFS,
+ APU_PLL4H_FHCTL1_DVFS,
+ APU_PLL4H_FHCTL2_DVFS,
+ APU_PLL4H_FHCTL3_DVFS,
+};
+
+uint32_t fhctl_mon_addr[APUPLL_MAX] = {
+ APU_PLL4H_FHCTL0_MON,
+ APU_PLL4H_FHCTL1_MON,
+ APU_PLL4H_FHCTL2_MON,
+ APU_PLL4H_FHCTL3_MON,
+};
+
+uint32_t fhctl_cfg_addr[APUPLL_MAX] = {
+ APU_PLL4H_FHCTL0_CFG,
+ APU_PLL4H_FHCTL1_CFG,
+ APU_PLL4H_FHCTL2_CFG,
+ APU_PLL4H_FHCTL3_CFG,
+};
+
+static spinlock_t apupll_lock;
+static spinlock_t npupll_lock;
+static spinlock_t apupll_1_lock;
+static spinlock_t apupll_2_lock;
+static uint32_t pll_cnt[APUPLL_MAX];
+/**
+ * vd2pllidx() - voltage domain to pll idx.
+ * @domain: the voltage domain for getting pll index.
+ *
+ * Caller will get correspond pll index by different voltage domain.
+ * pll_idx[0] --> APUPLL (MDLA0/1)
+ * pll_idx[1] --> NPUPLL (VPU0/1)
+ * pll_idx[2] --> APUPLL1(CONN)
+ * pll_idx[3] --> APUPLL2(IOMMU)
+ * The longer description may have multiple paragraphs.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 ~ 3 - return the corresponding pll index
+ * * -EEXIST - cannot find pll idex of the specific voltage domain
+ *
+ */
+static int32_t vd2pllidx(enum dvfs_voltage_domain domain)
+{
+ int32_t ret;
+
+ switch (domain) {
+ case V_VPU0:
+ case V_VPU1:
+ ret = NPUPLL;
+ break;
+ case V_MDLA0:
+ case V_MDLA1:
+ ret = APUPLL;
+ break;
+ case V_TOP_IOMMU:
+ ret = APUPLL2;
+ break;
+ case V_APU_CONN:
+ ret = APUPLL1;
+ break;
+ default:
+ ERROR("%s wrong voltage domain: %d\n", __func__, domain);
+ ret = -EEXIST; /* non-exist */
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * pllidx2name() - return names of specific pll index.
+ * @pll_idx: input for specific pll index.
+ *
+ * Given pll index, this function will return name of it.
+ *
+ * Context: Any context.
+ * Return: Names of pll_idx, if found, otherwise will return "NULL"
+ */
+static const char *pllidx2name(int32_t pll_idx)
+{
+ static const char *const names[] = {
+ [APUPLL] = "PLL4H_PLL1",
+ [NPUPLL] = "PLL4H_PLL2",
+ [APUPLL1] = "PLL4H_PLL3",
+ [APUPLL2] = "PLL4H_PLL4",
+ [APUPLL_MAX] = "NULL",
+ };
+
+ if (pll_idx >= APUPLL_MAX) {
+ pll_idx = APUPLL_MAX;
+ }
+
+ return names[pll_idx];
+}
+
+/**
+ * _fhctl_mon_done() - poll whether fhctl HW mode is done.
+ * @pll_idx: input for specific pll index.
+ * @tar_dds: target dds for fhctl_mon to be.
+ *
+ * Given pll index, this function will continue to poll whether fhctl_mon
+ * has reached the expected value within 80us.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - OK for fhctl_mon == tar_dds
+ * * -ETIMEDOUT - fhctl_mon not reach tar_dds
+ */
+static int32_t _fhctl_mon_done(uint32_t pll_idx, unsigned long tar_dds)
+{
+ unsigned long mon_dds;
+ uint64_t timeout = timeout_init_us(PLL_READY_TIME_20US);
+ int32_t ret = 0;
+
+ tar_dds &= DDS_MASK;
+ do {
+ mon_dds = apupwr_readl(fhctl_mon_addr[pll_idx]) & DDS_MASK;
+ if (mon_dds == tar_dds) {
+ break;
+ }
+
+ if (timeout_elapsed(timeout)) {
+ ERROR("%s monitor DDS 0x%08lx != expect 0x%08lx\n",
+ pllidx2name(pll_idx), mon_dds, tar_dds);
+ ret = -ETIMEDOUT;
+ break;
+ }
+ } while (mon_dds != tar_dds);
+
+ return ret;
+}
+
+/**
+ * _pll_get_postdiv_reg() - return current post dividor of pll_idx
+ * @pll_idx: input for specific pll index.
+ *
+ * Given pll index, this function will return its current post dividor.
+ *
+ * Context: Any context.
+ * Return: post dividor of current pll_idx.
+ *
+ */
+static uint32_t _pll_get_postdiv_reg(uint32_t pll_idx)
+{
+ int32_t pll_postdiv_reg = 0;
+ uint32_t val;
+
+ val = apupwr_readl(mixed_con1_addr[pll_idx]);
+ pll_postdiv_reg = (val >> POSDIV_SHIFT) & POSDIV_MASK;
+ return pll_postdiv_reg;
+}
+
+/**
+ * _set_postdiv_reg() - set pll_idx's post dividor.
+ * @pll_idx: Which PLL to enable/disable
+ * @post_div: the register value of post dividor to be wrtten.
+ *
+ * Below are lists of post dividor register value and its meaning:
+ * [31] APUPLL_SDM_PCW_CHG
+ * [26:24] APUPLL_POSDIV
+ * [21:0] APUPLL_SDM_PCW (8bit integer + 14bit fraction)
+ * expected freq range ----- divider-------post divider in reg:
+ * >1500M (1500/ 1) -> 1 -> 0(2 to the zero power)
+ * > 750M (1500/ 2) -> 2 -> 1(2 to the 1st power)
+ * > 375M (1500/ 4) -> 4 -> 2(2 to the 2nd power)
+ * > 187.5M (1500/ 8) -> 8 -> 3(2 to the 3rd power)
+ * > 93.75M (1500/16) -> 16 -> 4(2 to the 4th power)
+ *
+ * Context: Any context.
+ */
+static void _set_postdiv_reg(uint32_t pll_idx, uint32_t post_div)
+{
+ apupwr_clrbits(POSDIV_MASK << POSDIV_SHIFT, mixed_con1_addr[pll_idx]);
+ apupwr_setbits((post_div & POSDIV_MASK) << POSDIV_SHIFT,
+ mixed_con1_addr[pll_idx]);
+}
+
+/**
+ * _cal_pll_data() - input freq, calculate correspond post dividor and dds.
+ * @pd: address of output post dividor.
+ * @dds: address of output dds.
+ * @freq: input frequency.
+ *
+ * Given freq, this function will calculate correspond post dividor and dds.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - done for calculating post dividor and dds.
+ */
+static int32_t _cal_pll_data(uint32_t *pd, uint32_t *dds, uint32_t freq)
+{
+ uint32_t vco, postdiv_val = 1, postdiv_reg = 0;
+ uint32_t pcw_val;
+
+ vco = freq;
+ postdiv_val = 1;
+ postdiv_reg = 0;
+ while (vco <= FREQ_VCO_MIN) {
+ postdiv_val = postdiv_val << 1;
+ postdiv_reg = postdiv_reg + 1;
+ vco = vco << 1;
+ }
+
+ pcw_val = vco * (1 << PCW_FRACTIONAL_SHIFT);
+ pcw_val = pcw_val / FREQ_FIN;
+
+ if (postdiv_reg == 0) { /* Fvco * 2 with post_divider = 2 */
+ pcw_val = pcw_val * 2;
+ postdiv_val = postdiv_val << 1;
+ postdiv_reg = postdiv_reg + 1;
+ } /* Post divider is 1 is not available */
+ *pd = postdiv_reg;
+ *dds = pcw_val | RG_PLL_SDM_PCW_CHG;
+
+ return 0;
+}
+
+/**
+ * _pll_en() - enable/disable RG_PLL_EN of CON1 for pll[pll_idx]
+ * @pll_idx: Which PLL to enable/disable
+ * @on: 1 -> enable, 0 -> disable.
+ *
+ * This funciton will only change RG_PLL_EN of CON1 for pll[pll_idx].
+ *
+ * Context: Any context.
+ */
+static void _pll_en(uint32_t pll_idx, bool on)
+{
+ if (on) {
+ apupwr_setbits(RG_PLL_EN, mixed_con0_addr[pll_idx]);
+ } else {
+ apupwr_clrbits(RG_PLL_EN, mixed_con0_addr[pll_idx]);
+ }
+}
+
+/**
+ * _pll_pwr() - enable/disable PLL_SDM_PWR_ON of CON3 for pll[pll_idx]
+ * @pll_idx: Which PLL to enable/disable
+ * @on: 1 -> enable, 0 -> disable.
+ *
+ * This funciton will only change PLL_SDM_PWR_ON of CON3 for pll[pll_idx].
+ *
+ * Context: Any context.
+ */
+static void _pll_pwr(uint32_t pll_idx, bool on)
+{
+ if (on) {
+ apupwr_setbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]);
+ } else {
+ apupwr_clrbits(DA_PLL_SDM_PWR_ON, mixed_con3_addr[pll_idx]);
+ }
+}
+
+/**
+ * _pll_iso() - enable/disable PLL_SDM_ISO_EN of CON3 for pll[pll_idx]
+ * @pll_idx: Which PLL to enable/disable
+ * @enable: 1 -> turn on isolation, 0 -> turn off isolation.
+ *
+ * This funciton will turn on/off pll isolation by
+ * changing PLL_SDM_PWR_ON of CON3 for pll[pll_idx].
+ *
+ * Context: Any context.
+ */
+static void _pll_iso(uint32_t pll_idx, bool enable)
+{
+ if (enable) {
+ apupwr_setbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]);
+ } else {
+ apupwr_clrbits(DA_PLL_SDM_ISO_EN, mixed_con3_addr[pll_idx]);
+ }
+}
+
+/**
+ * _pll_switch() - entry point to turn whole PLL on/off
+ * @pll_idx: Which PLL to enable/disable
+ * @on: 1 -> enable, 0 -> disable.
+ * @fhctl_en: enable or disable fhctl function
+ *
+ * This is the entry poing for controlling pll and fhctl funciton on/off.
+ * Caller can chose only enable pll instead of fhctl function.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - done for enable pll or fhctl as well.
+ */
+static int32_t _pll_switch(uint32_t pll_idx, bool on, bool fhctl_en)
+{
+ int32_t ret = 0;
+
+ if (pll_idx >= APUPLL_MAX) {
+ ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (on) {
+ _pll_pwr(pll_idx, true);
+ udelay(PLL_CMD_READY_TIME_1US);
+ _pll_iso(pll_idx, false);
+ udelay(PLL_CMD_READY_TIME_1US);
+ _pll_en(pll_idx, true);
+ udelay(PLL_READY_TIME_20US);
+ } else {
+ _pll_en(pll_idx, false);
+ _pll_iso(pll_idx, true);
+ _pll_pwr(pll_idx, false);
+ }
+
+err:
+ return ret;
+}
+
+/**
+ * apu_pll_enable() - API for smc function to enable/disable pll
+ * @pll_idx: Which pll to enable/disable.
+ * @enable: 1 -> enable, 0 -> disable.
+ * @fhctl_en: enable or disable fhctl function
+ *
+ * pll_idx[0] --> APUPLL (MDLA0/1)
+ * pll_idx[1] --> NPUPLL (VPU0/1)
+ * pll_idx[2] --> APUPLL1(CONN)
+ * pll_idx[3] --> APUPLL2(IOMMU)
+ * The differences between _pll_switch are:
+ * 1. Atomic update pll reference cnt to protect double enable pll &
+ * close pll during user is not zero.
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - done for enable pll or fhctl as well.
+ */
+int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en)
+{
+ int32_t ret = 0;
+
+ if (pll_idx >= APUPLL_MAX) {
+ ERROR("%s wrong pll_idx: %d\n", __func__, pll_idx);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (enable) {
+ switch (pll_idx) {
+ case APUPLL:
+ spin_lock(&apupll_lock);
+ if (pll_cnt[APUPLL] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ pll_cnt[APUPLL]++;
+ spin_unlock(&apupll_lock);
+ break;
+ case NPUPLL:
+ spin_lock(&npupll_lock);
+ if (pll_cnt[NPUPLL] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ pll_cnt[NPUPLL]++;
+ spin_unlock(&npupll_lock);
+ break;
+ case APUPLL1:
+ spin_lock(&apupll_1_lock);
+ if (pll_cnt[APUPLL1] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ pll_cnt[APUPLL1]++;
+ spin_unlock(&apupll_1_lock);
+ break;
+ case APUPLL2:
+ spin_lock(&apupll_2_lock);
+ if (pll_cnt[APUPLL2] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ pll_cnt[APUPLL2]++;
+ spin_unlock(&apupll_2_lock);
+ break;
+ default:
+ ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx);
+ ret = -EINVAL;
+ break;
+ }
+ } else {
+ switch (pll_idx) {
+ case APUPLL:
+ spin_lock(&apupll_lock);
+ if (pll_cnt[APUPLL]) {
+ pll_cnt[APUPLL]--;
+ }
+ if (pll_cnt[APUPLL] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ spin_unlock(&apupll_lock);
+ break;
+ case NPUPLL:
+ spin_lock(&npupll_lock);
+ if (pll_cnt[NPUPLL]) {
+ pll_cnt[NPUPLL]--;
+ }
+ if (pll_cnt[NPUPLL] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ spin_unlock(&npupll_lock);
+ break;
+ case APUPLL1:
+ spin_lock(&apupll_1_lock);
+ if (pll_cnt[APUPLL1]) {
+ pll_cnt[APUPLL1]--;
+ }
+ if (pll_cnt[APUPLL1] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ spin_unlock(&apupll_1_lock);
+ break;
+ case APUPLL2:
+ spin_lock(&apupll_2_lock);
+ if (pll_cnt[APUPLL2]) {
+ pll_cnt[APUPLL2]--;
+ }
+ if (pll_cnt[APUPLL2] == 0) {
+ _pll_switch(pll_idx, enable, fhctl_en);
+ }
+ spin_unlock(&apupll_2_lock);
+ break;
+ default:
+ ERROR("%s invalid pll_idx: %d\n", __func__, pll_idx);
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+err:
+ return ret;
+}
+
+/**
+ * anpu_pll_set_rate() - API for smc function to set rate of voltage domain.
+ * @domain: Which pll of correspond voltage domain to change rate.
+ * @mode: which mode to use when set_rate
+ * @freq: which frequency to set.
+ *
+ * For V_VPU0/1, it will only allow 1 of them to modify NPUPLL
+ * such that there will be no race condition happen.
+ *
+ * For V_MDLA0/1, it will only allow 1 of them to modify APUPLL1
+ * such that there will be no race condition happen.
+ *
+ * There are 3 kinds of modes to set pll's rate.
+ * 1. pure sw mode: (CON0_PCW)
+ * fhctl function is off and change rate by programming CON1_PCW.
+ * 2. fhctl sw mode: (FHCTL_SW)
+ * fhctl function is on and change rate by programming fhctl_dds.
+ * (post dividor is still need to program CON1_PCW)
+ * 3. fhctl hw mode: (FHCTL_HW)
+ * fhctl function is on and change rate by programming fhctl_dvfs.
+ * (post dividor is still need to program CON1_PCW)
+ *
+ * Context: Any context.
+ * Return:
+ * * 0 - done for set rate of voltage domain.
+ */
+int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain,
+ enum pll_set_rate_mode mode, int32_t freq)
+{
+ uint32_t pd, old_pd, dds;
+ int32_t pll_idx, ret = 0;
+
+ pll_idx = vd2pllidx(domain);
+ if (pll_idx < 0) {
+ ret = pll_idx;
+ goto err;
+ }
+
+ _cal_pll_data(&pd, &dds, freq / 1000);
+
+ INFO("%s %s new post_div=%d, target dds=0x%08x(%dMhz) mode = %d\n",
+ __func__, pllidx2name(pll_idx), pd, dds, freq / 1000, mode);
+
+ /* spin_lock for NPULL, since vpu0/1 share npupll */
+ if (domain == V_VPU0 || domain == V_VPU1) {
+ spin_lock(&npupll_lock);
+ }
+
+ /* spin_lock for APUPLL, since mdla0/1 shate apupll */
+ if (domain == V_MDLA0 || domain == V_MDLA1) {
+ spin_lock(&apupll_lock);
+ }
+
+ switch (mode) {
+ case CON0_PCW:
+ pd = RG_PLL_SDM_PCW_CHG |
+ (pd & POSDIV_MASK) << POSDIV_SHIFT | dds;
+ apupwr_writel(pd, mixed_con1_addr[pll_idx]);
+ udelay(PLL_READY_TIME_20US);
+ break;
+ case FHCTL_SW:
+ /* pll con0 disable */
+ _pll_en(pll_idx, false);
+ apupwr_writel(dds, fhctl_dds_addr[pll_idx]);
+ _set_postdiv_reg(pll_idx, pd);
+ apupwr_setbits(PLL_TGL_ORG, fhctl_dds_addr[pll_idx]);
+ udelay(PLL_CMD_READY_TIME_1US);
+ /* pll con0 enable */
+ _pll_en(pll_idx, true);
+ udelay(PLL_READY_TIME_20US);
+ break;
+ case FHCTL_HW:
+ old_pd = _pll_get_postdiv_reg(pll_idx);
+ if (pd > old_pd) {
+ _set_postdiv_reg(pll_idx, pd);
+ apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]);
+ } else {
+ apupwr_writel(dds, fhctl_dvfs_addr[pll_idx]);
+ _set_postdiv_reg(pll_idx, pd);
+ }
+ ret = _fhctl_mon_done(pll_idx, dds);
+ break;
+ default:
+ ERROR("%s input wrong mode: %d\n", __func__, mode);
+ ret = -EINVAL;
+ break;
+ }
+
+ /* spin_lock for NPULL, since vpu0/1 share npupll */
+ if (domain == V_VPU0 || domain == V_VPU1) {
+ spin_unlock(&npupll_lock);
+ }
+
+ /* spin_lock for APUPLL, since mdla0/1 share apupll */
+ if (domain == V_MDLA0 || domain == V_MDLA1) {
+ spin_unlock(&apupll_lock);
+ }
+
+err:
+ return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c
new file mode 100644
index 0000000..465054d
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <apupwr_clkctl.h>
+#include <apupwr_clkctl_def.h>
+#include <mtk_plat_common.h>
+#include <platform_def.h>
+
+/* 8195 use PCW mode to change freq directly */
+enum pll_set_rate_mode PLL_MODE = CON0_PCW;
+
+char *buck_domain_str[APUSYS_BUCK_DOMAIN_NUM] = {
+ "V_VPU0",
+ "V_VPU1",
+ "V_MDLA0",
+ "V_MDLA1",
+ "V_APU_CONN",
+ "V_TOP_IOMMU",
+ "V_VCORE",
+};
+
+uint32_t aacc_set[APUSYS_BUCK_DOMAIN_NUM] = {
+ APU_ACC_CONFG_SET1, APU_ACC_CONFG_SET2,
+ APU_ACC_CONFG_SET4, APU_ACC_CONFG_SET5,
+ APU_ACC_CONFG_SET0, APU_ACC_CONFG_SET7
+};
+
+uint32_t aacc_clr[APUSYS_BUCK_DOMAIN_NUM] = {
+ APU_ACC_CONFG_CLR1, APU_ACC_CONFG_CLR2,
+ APU_ACC_CONFG_CLR4, APU_ACC_CONFG_CLR5,
+ APU_ACC_CONFG_CLR0, APU_ACC_CONFG_CLR7
+};
+
+struct reg_seq {
+ uint32_t address;
+ uint32_t val;
+};
+
+static const struct reg_seq init_acc_cfg[] = {
+ { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU) },
+ { APU_ACC_CONFG_CLR0, BIT(BIT_CGEN_SOC) },
+ { APU_ACC_CONFG_SET0, BIT(BIT_SEL_APU_DIV2) },
+ { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU) },
+ { APU_ACC_CONFG_CLR7, BIT(BIT_CGEN_SOC) },
+ { APU_ACC_CONFG_SET7, BIT(BIT_SEL_APU_DIV2) },
+ { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU) },
+ { APU_ACC_CONFG_CLR1, BIT(BIT_CGEN_SOC) },
+ { APU_ACC_CONFG_SET1, BIT(BIT_SEL_APU_DIV2) },
+ { APU_ACC_CONFG_SET2, BIT(BIT_INVEN_OUT) },
+ { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU) },
+ { APU_ACC_CONFG_CLR2, BIT(BIT_CGEN_SOC) },
+ { APU_ACC_CONFG_SET2, BIT(BIT_SEL_APU_DIV2) },
+ { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU) },
+ { APU_ACC_CONFG_CLR4, BIT(BIT_CGEN_SOC) },
+ { APU_ACC_CONFG_SET4, BIT(BIT_SEL_APU_DIV2) },
+ { APU_ACC_CONFG_SET5, BIT(BIT_INVEN_OUT) },
+ { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU) },
+ { APU_ACC_CONFG_CLR5, BIT(BIT_CGEN_SOC) },
+ { APU_ACC_CONFG_SET5, BIT(BIT_SEL_APU_DIV2) },
+};
+
+int32_t apupwr_smc_acc_init_all(void)
+{
+ int32_t i;
+
+ for (i = 0; i < ARRAY_SIZE(init_acc_cfg); i++) {
+ apupwr_writel(init_acc_cfg[i].val,
+ init_acc_cfg[i].address);
+ }
+
+ /* Deault ACC will raise APU_DIV_2 */
+ apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
+ true, V_APU_CONN);
+
+ apupwr_smc_pll_set_rate(BUCK_VCONN_DOMAIN_DEFAULT_FREQ,
+ true, V_TOP_IOMMU);
+
+ apupwr_smc_pll_set_rate(BUCK_VVPU_DOMAIN_DEFAULT_FREQ,
+ true, V_VPU0);
+
+ apupwr_smc_pll_set_rate(BUCK_VMDLA_DOMAIN_DEFAULT_FREQ,
+ true, V_MDLA0);
+
+ return 0;
+}
+
+void apupwr_smc_acc_top(bool enable)
+{
+ if (enable) {
+ apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_APU_CONN]);
+ apupwr_writel(BIT(BIT_CGEN_APU), aacc_set[V_TOP_IOMMU]);
+ } else {
+ apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_APU_CONN]);
+ apupwr_writel(BIT(BIT_CGEN_APU), aacc_clr[V_TOP_IOMMU]);
+ }
+}
+
+/*
+ * acc_clk_set_parent:ACC MUX select
+ * 0. freq parameters here, only ACC clksrc is valid
+ * 1. Switch between APUPLL <=> Parking (F26M, PARK)
+ * 2. Turn on/off CG_F26M, CG_PARK, CG_SOC, but no CG_APU
+ * 3. Clear APU Div2 while Parking
+ * 4. Only use clksrc of APUPLL while ACC CG_APU is on
+ */
+int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain)
+{
+ uint32_t acc_set = 0;
+ uint32_t acc_clr = 0;
+ int32_t ret = 0;
+
+ if (freq > DVFS_FREQ_ACC_APUPLL) {
+ ERROR("%s wrong clksrc: %d\n", __func__, freq);
+ ret = -EIO;
+ goto err;
+ }
+
+ switch (domain) {
+ case V_VPU1:
+ case V_VPU0:
+ case V_MDLA1:
+ case V_MDLA0:
+ case V_APU_CONN:
+ case V_TOP_IOMMU:
+ acc_set = aacc_set[domain];
+ acc_clr = aacc_clr[domain];
+ break;
+ default:
+ ret = -EIO;
+ break;
+ }
+
+ /* Select park source */
+ switch (freq) {
+ case DVFS_FREQ_ACC_PARKING:
+ /* Select park source */
+ apupwr_writel(BIT(BIT_SEL_PARK), acc_set);
+ apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
+ /* Enable park cg */
+ apupwr_writel(BIT(BIT_CGEN_PARK), acc_set);
+ apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_SOC), acc_clr);
+ /* Select park path */
+ apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
+ /* clear apu div 2 */
+ apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
+ break;
+
+ case DVFS_FREQ_ACC_APUPLL:
+ /* Select park path */
+ apupwr_writel(BIT(BIT_SEL_APU), acc_set);
+ /* Clear park cg */
+ apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_F26M) |
+ BIT(BIT_CGEN_SOC), acc_clr);
+ break;
+
+ case DVFS_FREQ_ACC_SOC:
+ /* Select park source */
+ apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
+ apupwr_writel(BIT(BIT_SEL_F26M), acc_clr);
+ /* Enable park cg */
+ apupwr_writel(BIT(BIT_CGEN_SOC), acc_set);
+ apupwr_writel(BIT(BIT_CGEN_F26M) | BIT(BIT_CGEN_PARK), acc_clr);
+ /* Select park path */
+ apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
+ /* clear apu div 2 */
+ apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
+ break;
+
+ case DVFS_FREQ_ACC_26M:
+ case DVFS_FREQ_NOT_SUPPORT:
+ default:
+ /* Select park source */
+ apupwr_writel(BIT(BIT_SEL_F26M), acc_set);
+ apupwr_writel(BIT(BIT_SEL_PARK), acc_clr);
+ /* Enable park cg */
+ apupwr_writel(BIT(BIT_CGEN_F26M), acc_set);
+ apupwr_writel(BIT(BIT_CGEN_PARK) | BIT(BIT_CGEN_SOC), acc_clr);
+ /* Select park path */
+ apupwr_writel(BIT(BIT_SEL_APU), acc_clr);
+ /* clear apu div 2 */
+ apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_clr);
+ ERROR("[APUPWR] %s wrong ACC clksrc : %d, force assign 26M\n",
+ __func__, freq);
+ break;
+ }
+
+err:
+ return ret;
+}
+
+int32_t apupwr_smc_pll_set_rate(uint32_t freq, bool div2, uint32_t domain)
+{
+ int32_t ret = 0;
+ uint32_t acc_set0 = 0, acc_set1 = 0;
+
+ if (freq > DVFS_FREQ_MAX) {
+ ERROR("%s wrong freq: %d\n", __func__, freq);
+ ret = -EIO;
+ goto err;
+ }
+
+ /*
+ * Switch to Parking src
+ * 1. Need to switch out all ACCs sharing the same apupll
+ */
+ switch (domain) {
+ case V_MDLA0:
+ case V_MDLA1:
+ acc_set0 = APU_ACC_CONFG_SET4;
+ acc_set1 = APU_ACC_CONFG_SET5;
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+ V_MDLA0);
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+ V_MDLA1);
+ break;
+ case V_VPU0:
+ case V_VPU1:
+ acc_set0 = APU_ACC_CONFG_SET1;
+ acc_set1 = APU_ACC_CONFG_SET2;
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+ V_VPU0);
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+ V_VPU1);
+ break;
+ case V_APU_CONN:
+ acc_set0 = APU_ACC_CONFG_SET0;
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+ V_APU_CONN);
+ break;
+ case V_TOP_IOMMU:
+ acc_set0 = APU_ACC_CONFG_SET7;
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_PARKING,
+ V_TOP_IOMMU);
+ break;
+ default:
+ ERROR("[APUPWR] %s %d invalid domain (%d)\n",
+ __func__, __LINE__, domain);
+ ret = -EIO;
+ goto err;
+ }
+
+ anpu_pll_set_rate(domain, PLL_MODE, (div2) ? (freq * 2) : freq);
+
+ if (div2) {
+ apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set0);
+ if (acc_set1) {
+ apupwr_writel(BIT(BIT_SEL_APU_DIV2), acc_set1);
+ }
+ }
+
+ /*
+ * Switch back to APUPLL
+ * Only switch back to APUPLL while CG_APU on
+ * And clksrc is not APUPLL
+ */
+ switch (domain) {
+ case V_VPU0:
+ case V_VPU1:
+ if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
+ !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+ V_VPU0);
+ }
+ if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
+ !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+ V_VPU1);
+ }
+ break;
+ case V_MDLA0:
+ case V_MDLA1:
+ if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
+ !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+ V_MDLA0);
+ }
+ if ((apupwr_readl(acc_set1) & BIT(BIT_CGEN_APU)) &&
+ !(apupwr_readl(acc_set1) & BIT(BIT_SEL_APU))) {
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+ V_MDLA1);
+ }
+ break;
+ case V_APU_CONN:
+ case V_TOP_IOMMU:
+ if ((apupwr_readl(acc_set0) & BIT(BIT_CGEN_APU)) &&
+ !(apupwr_readl(acc_set0) & BIT(BIT_SEL_APU))) {
+ ret = apupwr_smc_acc_set_parent(DVFS_FREQ_ACC_APUPLL,
+ domain);
+ }
+ break;
+ default:
+ ERROR("[APUPWR] %s %d invalid domain (%d)\n",
+ __func__, __LINE__, domain);
+ ret = -EIO;
+ break;
+ }
+ INFO("[%s][%d] set domain %d to freq %d\n",
+ __func__, __LINE__, domain, (div2) ? (freq * 2) : freq);
+
+err:
+ return ret;
+}
+
+int32_t apupwr_smc_bulk_pll(bool enable)
+{
+ int32_t ret = 0;
+ int32_t pll_idx;
+
+ if (enable) {
+ for (pll_idx = APUPLL; pll_idx < APUPLL_MAX; pll_idx++) {
+ ret = apu_pll_enable(pll_idx, enable, false);
+ if (ret != 0) {
+ goto err;
+ }
+ }
+ } else {
+ for (pll_idx = APUPLL2; pll_idx >= APUPLL; pll_idx--) {
+ ret = apu_pll_enable(pll_idx, enable, false);
+ if (ret != 0) {
+ goto err;
+ }
+ }
+ }
+
+err:
+ return ret;
+}
+
+void apupwr_smc_bus_prot_cg_on(void)
+{
+ apupwr_clrbits(AO_MD32_MNOC_MASK, APU_CSR_DUMMY_0);
+}
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h
new file mode 100644
index 0000000..3b27c1b
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUPWR_CLKCTL_H
+#define APUPWR_CLKCTL_H
+
+#include <arch_helpers.h>
+#include <apupwr_clkctl_def.h>
+
+int32_t apupwr_smc_acc_init_all(void);
+void apupwr_smc_acc_top(bool enable);
+int32_t apupwr_smc_acc_set_parent(uint32_t freq, uint32_t domain);
+int32_t apupwr_smc_pll_set_rate(uint32_t pll, bool div2, uint32_t domain);
+int32_t apupwr_smc_bulk_pll(bool enable);
+void apupwr_smc_bus_prot_cg_on(void);
+
+int32_t apu_pll_enable(int32_t pll_idx, bool enable, bool fhctl_en);
+int32_t anpu_pll_set_rate(enum dvfs_voltage_domain domain,
+ enum pll_set_rate_mode mode, int32_t freq);
+#endif /* APUPWR_CLKCTL_H */
diff --git a/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h
new file mode 100644
index 0000000..6663ad9
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef APUPWR_CLKCTL_DEF_H
+#define APUPWR_CLKCTL_DEF_H
+
+#include <lib/mmio.h>
+
+enum dvfs_voltage_domain {
+ V_VPU0 = 0,
+ V_VPU1 = 1,
+ V_MDLA0 = 2,
+ V_MDLA1 = 3,
+ V_APU_CONN = 4,
+ V_TOP_IOMMU = 5,
+ V_VCORE = 6,
+ APUSYS_BUCK_DOMAIN_NUM = 7,
+};
+
+enum dvfs_freq {
+ DVFS_FREQ_NOT_SUPPORT = 0,
+ DVFS_FREQ_ACC_26M = 1,
+ DVFS_FREQ_ACC_PARKING = 2,
+ DVFS_FREQ_ACC_SOC = 3,
+ DVFS_FREQ_ACC_APUPLL = 4,
+ DVFS_FREQ_00_026000_F = 26000,
+ DVFS_FREQ_00_208000_F = 208000,
+ DVFS_FREQ_00_238000_F = 238000,
+ DVFS_FREQ_00_273000_F = 273000,
+ DVFS_FREQ_00_312000_F = 312000,
+ DVFS_FREQ_00_358000_F = 358000,
+ DVFS_FREQ_00_385000_F = 385000,
+ DVFS_FREQ_00_499200_F = 499200,
+ DVFS_FREQ_00_500000_F = 500000,
+ DVFS_FREQ_00_525000_F = 525000,
+ DVFS_FREQ_00_546000_F = 546000,
+ DVFS_FREQ_00_594000_F = 594000,
+ DVFS_FREQ_00_624000_F = 624000,
+ DVFS_FREQ_00_688000_F = 688000,
+ DVFS_FREQ_00_687500_F = 687500,
+ DVFS_FREQ_00_728000_F = 728000,
+ DVFS_FREQ_00_800000_F = 800000,
+ DVFS_FREQ_00_832000_F = 832000,
+ DVFS_FREQ_00_960000_F = 960000,
+ DVFS_FREQ_00_1100000_F = 1100000,
+};
+#define DVFS_FREQ_MAX (DVFS_FREQ_00_1100000_F)
+
+enum pll_set_rate_mode {
+ CON0_PCW = 0,
+ FHCTL_SW = 1,
+ FHCTL_HW = 2,
+ PLL_SET_RATE_MODE_MAX = 3,
+};
+
+enum apupll {
+ APUPLL = 0,
+ NPUPLL = 1,
+ APUPLL1 = 2,
+ APUPLL2 = 3,
+ APUPLL_MAX = 4,
+};
+
+#define BUCK_VVPU_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_273000_F)
+#define BUCK_VMDLA_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_312000_F)
+#define BUCK_VCONN_DOMAIN_DEFAULT_FREQ (DVFS_FREQ_00_208000_F)
+
+#define apupwr_writel(VAL, REG) mmio_write_32((uintptr_t)REG, VAL)
+#define apupwr_writel_relax(VAL, REG) mmio_write_32_relax((uintptr_t)REG, VAL)
+#define apupwr_readl(REG) mmio_read_32((uintptr_t)REG)
+#define apupwr_clrbits(VAL, REG) mmio_clrbits_32((uintptr_t)REG, VAL)
+#define apupwr_setbits(VAL, REG) mmio_setbits_32((uintptr_t)REG, VAL)
+#define apupwr_clrsetbits(CLR_VAL, SET_VAL, REG) \
+ mmio_clrsetbits_32((uintptr_t)REG, CLR_VAL, SET_VAL)
+
+/* PLL and related register */
+#define APU_PLL_BASE (APUSYS_APU_PLL_BASE)
+#define APU_PLL4H_PLL1_CON0 (APU_PLL_BASE + 0x008)
+#define APU_PLL4H_PLL1_CON1 (APU_PLL_BASE + 0x00C)
+#define APU_PLL4H_PLL1_CON3 (APU_PLL_BASE + 0x014)
+
+#define APU_PLL4H_PLL2_CON0 (APU_PLL_BASE + 0x018)
+#define APU_PLL4H_PLL2_CON1 (APU_PLL_BASE + 0x01C)
+#define APU_PLL4H_PLL2_CON3 (APU_PLL_BASE + 0x024)
+
+#define APU_PLL4H_PLL3_CON0 (APU_PLL_BASE + 0x028)
+#define APU_PLL4H_PLL3_CON1 (APU_PLL_BASE + 0x02C)
+#define APU_PLL4H_PLL3_CON3 (APU_PLL_BASE + 0x034)
+
+#define APU_PLL4H_PLL4_CON0 (APU_PLL_BASE + 0x038)
+#define APU_PLL4H_PLL4_CON1 (APU_PLL_BASE + 0x03C)
+#define APU_PLL4H_PLL4_CON3 (APU_PLL_BASE + 0x044)
+
+#define APU_PLL4H_FHCTL_HP_EN (APU_PLL_BASE + 0x0E00)
+#define APU_PLL4H_FHCTL_UNITSLOPE_EN (APU_PLL_BASE + 0x0E04)
+#define APU_PLL4H_FHCTL_CLK_CON (APU_PLL_BASE + 0x0E08)
+#define APU_PLL4H_FHCTL_RST_CON (APU_PLL_BASE + 0x0E0C)
+#define APU_PLL4H_FHCTL_SLOPE0 (APU_PLL_BASE + 0x0E10)
+#define APU_PLL4H_FHCTL_SLOPE1 (APU_PLL_BASE + 0x0E14)
+#define APU_PLL4H_FHCTL_DSSC_CFG (APU_PLL_BASE + 0x0E18)
+#define APU_PLL4H_FHCTL_DSSC0_CON (APU_PLL_BASE + 0x0E1C)
+#define APU_PLL4H_FHCTL_DSSC1_CON (APU_PLL_BASE + 0x0E20)
+#define APU_PLL4H_FHCTL_DSSC2_CON (APU_PLL_BASE + 0x0E24)
+#define APU_PLL4H_FHCTL_DSSC3_CON (APU_PLL_BASE + 0x0E28)
+#define APU_PLL4H_FHCTL_DSSC4_CON (APU_PLL_BASE + 0x0E2C)
+#define APU_PLL4H_FHCTL_DSSC5_CON (APU_PLL_BASE + 0x0E30)
+#define APU_PLL4H_FHCTL_DSSC6_CON (APU_PLL_BASE + 0x0E34)
+#define APU_PLL4H_FHCTL_DSSC7_CON (APU_PLL_BASE + 0x0E38)
+#define APU_PLL4H_FHCTL0_CFG (APU_PLL_BASE + 0x0E3C)
+#define APU_PLL4H_FHCTL0_UPDNLMT (APU_PLL_BASE + 0x0E40)
+#define APU_PLL4H_FHCTL0_DDS (APU_PLL_BASE + 0x0E44)
+#define APU_PLL4H_FHCTL0_DVFS (APU_PLL_BASE + 0x0E48)
+#define APU_PLL4H_FHCTL0_MON (APU_PLL_BASE + 0x0E4C)
+#define APU_PLL4H_FHCTL1_CFG (APU_PLL_BASE + 0x0E50)
+#define APU_PLL4H_FHCTL1_UPDNLMT (APU_PLL_BASE + 0x0E54)
+#define APU_PLL4H_FHCTL1_DDS (APU_PLL_BASE + 0x0E58)
+#define APU_PLL4H_FHCTL1_DVFS (APU_PLL_BASE + 0x0E5C)
+#define APU_PLL4H_FHCTL1_MON (APU_PLL_BASE + 0x0E60)
+#define APU_PLL4H_FHCTL2_CFG (APU_PLL_BASE + 0x0E64)
+#define APU_PLL4H_FHCTL2_UPDNLMT (APU_PLL_BASE + 0x0E68)
+#define APU_PLL4H_FHCTL2_DDS (APU_PLL_BASE + 0x0E6C)
+#define APU_PLL4H_FHCTL2_DVFS (APU_PLL_BASE + 0x0E70)
+#define APU_PLL4H_FHCTL2_MON (APU_PLL_BASE + 0x0E74)
+#define APU_PLL4H_FHCTL3_CFG (APU_PLL_BASE + 0x0E78)
+#define APU_PLL4H_FHCTL3_UPDNLMT (APU_PLL_BASE + 0x0E7C)
+#define APU_PLL4H_FHCTL3_DDS (APU_PLL_BASE + 0x0E80)
+#define APU_PLL4H_FHCTL3_DVFS (APU_PLL_BASE + 0x0E84)
+#define APU_PLL4H_FHCTL3_MON (APU_PLL_BASE + 0x0E88)
+
+/* PLL4H_PLLx_CON0 */
+#define RG_PLL_EN BIT(0)
+
+/* PLL4H_PLLx_CON1 */
+#define RG_PLL_SDM_PCW_CHG BIT(31)
+#define POSDIV_SHIFT (24U)
+#define POSDIV_MASK (0x7)
+
+/* PLL4H_PLLx_CON3 */
+#define DA_PLL_SDM_PWR_ON BIT(0)
+#define DA_PLL_SDM_ISO_EN BIT(1)
+
+/* FHCTLx_DDS */
+#define DDS_MASK GENMASK_32(21, 0)
+#define PCW_FRACTIONAL_SHIFT 14U
+#define PLL_TGL_ORG BIT(31)
+
+#define PLL_READY_TIME_20US (20U)
+#define PLL_CMD_READY_TIME_1US (1U)
+
+#define FREQ_VCO_MIN (1500U) /* 1500MHz*/
+#define FREQ_FIN (26U) /* 26M*/
+
+/* ACC and related register */
+#define APU_ACC_BASE (APUSYS_APU_ACC_BASE)
+#define APU_ACC_CONFG_SET0 (APU_ACC_BASE + 0x000)
+#define APU_ACC_CONFG_SET1 (APU_ACC_BASE + 0x004)
+#define APU_ACC_CONFG_SET2 (APU_ACC_BASE + 0x008)
+#define APU_ACC_CONFG_SET4 (APU_ACC_BASE + 0x010)
+#define APU_ACC_CONFG_SET5 (APU_ACC_BASE + 0x014)
+#define APU_ACC_CONFG_SET7 (APU_ACC_BASE + 0x01C)
+
+#define APU_ACC_CONFG_CLR0 (APU_ACC_BASE + 0x040)
+#define APU_ACC_CONFG_CLR1 (APU_ACC_BASE + 0x044)
+#define APU_ACC_CONFG_CLR2 (APU_ACC_BASE + 0x048)
+#define APU_ACC_CONFG_CLR4 (APU_ACC_BASE + 0x050)
+#define APU_ACC_CONFG_CLR5 (APU_ACC_BASE + 0x054)
+#define APU_ACC_CONFG_CLR7 (APU_ACC_BASE + 0x05C)
+
+#define APU_ACC_FM_CONFG_SET (APU_ACC_BASE + 0x0C0)
+#define APU_ACC_FM_CONFG_CLR (APU_ACC_BASE + 0x0C4)
+#define APU_ACC_FM_SEL (APU_ACC_BASE + 0x0C8)
+#define APU_ACC_FM_CNT (APU_ACC_BASE + 0x0CC)
+
+/* APU AO control */
+#define APU_AO_CTRL_BASE (APUSYS_APU_S_S_4_BASE)
+#define APU_CSR_DUMMY_0 (APU_AO_CTRL_BASE + 0x24)
+
+#define AO_MD32_MNOC_MASK (BIT(1) | BIT(0))
+
+#define BIT_CGEN_F26M (0)
+#define BIT_CGEN_PARK (1)
+#define BIT_CGEN_SOC (2)
+#define BIT_CGEN_APU (3)
+#define BIT_CGEN_OUT (4)
+#define BIT_SEL_PARK (8)
+#define BIT_SEL_F26M (9)
+#define BIT_SEL_APU_DIV2 (10)
+#define BIT_SEL_APU (11)
+#define BIT_SEL_PARK_SRC_OUT (12)
+#define BIT_INVEN_OUT (15)
+
+#endif /* APUPWR_CLKCTL_DEF_H*/
diff --git a/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c
new file mode 100644
index 0000000..3ed26a1
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+
+#include <apupwr_clkctl.h>
+#include <mtk_apusys.h>
+#include <plat/common/platform.h>
+
+int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+ uint32_t *ret1)
+{
+ int32_t ret = 0L;
+ uint32_t request_ops;
+
+ request_ops = (uint32_t)x1;
+
+ switch (request_ops) {
+ case MTK_SIP_APU_START_MCU:
+ /* setup addr[33:32] in reviser */
+ mmio_write_32(REVISER_SECUREFW_CTXT, 0U);
+ mmio_write_32(REVISER_USDRFW_CTXT, 0U);
+
+ /* setup secure sideband */
+ mmio_write_32(AO_SEC_FW,
+ (SEC_FW_NON_SECURE << SEC_FW_SHIFT_NS) |
+ (0U << SEC_FW_DOMAIN_SHIFT));
+
+ /* setup boot address */
+ mmio_write_32(AO_MD32_BOOT_CTRL, 0U);
+
+ /* setup pre-define region */
+ mmio_write_32(AO_MD32_PRE_DEFINE,
+ (PRE_DEFINE_CACHE_TCM << PRE_DEFINE_SHIFT_0G) |
+ (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_1G) |
+ (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_2G) |
+ (PRE_DEFINE_CACHE << PRE_DEFINE_SHIFT_3G));
+
+ /* release runstall */
+ mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_RUN);
+
+ INFO("[APUSYS] rev(0x%08x,0x%08x)\n",
+ mmio_read_32(REVISER_SECUREFW_CTXT),
+ mmio_read_32(REVISER_USDRFW_CTXT));
+ INFO("[APUSYS] ao(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x)\n",
+ mmio_read_32(AO_SEC_FW),
+ mmio_read_32(AO_SEC_USR_FW),
+ mmio_read_32(AO_MD32_BOOT_CTRL),
+ mmio_read_32(AO_MD32_PRE_DEFINE),
+ mmio_read_32(AO_MD32_SYS_CTRL));
+ break;
+ case MTK_SIP_APU_STOP_MCU:
+ /* hold runstall */
+ mmio_write_32(AO_MD32_SYS_CTRL, SYS_CTRL_STALL);
+
+ INFO("[APUSYS] md32_boot_ctrl=0x%08x,runstall=0x%08x\n",
+ mmio_read_32(AO_MD32_BOOT_CTRL),
+ mmio_read_32(AO_MD32_SYS_CTRL));
+ break;
+ case MTK_SIP_APUPWR_BUS_PROT_CG_ON:
+ apupwr_smc_bus_prot_cg_on();
+ break;
+ case MTK_SIP_APUPWR_BULK_PLL:
+ ret = apupwr_smc_bulk_pll((bool)x2);
+ break;
+ case MTK_SIP_APUPWR_ACC_INIT_ALL:
+ ret = apupwr_smc_acc_init_all();
+ break;
+ case MTK_SIP_APUPWR_ACC_TOP:
+ apupwr_smc_acc_top((bool)x2);
+ break;
+ default:
+ ERROR("%s, unknown request_ops=0x%x\n", __func__, request_ops);
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h
new file mode 100644
index 0000000..639abd3
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_APUSYS_H
+#define MTK_APUSYS_H
+
+#include <stdint.h>
+
+/* setup the SMC command ops */
+#define MTK_SIP_APU_START_MCU (0x00U)
+#define MTK_SIP_APU_STOP_MCU (0x01U)
+#define MTK_SIP_APUPWR_BUS_PROT_CG_ON (0x02U)
+#define MTK_SIP_APUPWR_BULK_PLL (0x03U)
+#define MTK_SIP_APUPWR_ACC_INIT_ALL (0x04U)
+#define MTK_SIP_APUPWR_ACC_TOP (0x05U)
+
+/* AO Register */
+#define AO_MD32_PRE_DEFINE (APUSYS_APU_S_S_4_BASE + 0x00)
+#define AO_MD32_BOOT_CTRL (APUSYS_APU_S_S_4_BASE + 0x04)
+#define AO_MD32_SYS_CTRL (APUSYS_APU_S_S_4_BASE + 0x08)
+#define AO_SEC_FW (APUSYS_APU_S_S_4_BASE + 0x10)
+#define AO_SEC_USR_FW (APUSYS_APU_S_S_4_BASE + 0x14)
+
+#define PRE_DEFINE_CACHE_TCM (0x3U)
+#define PRE_DEFINE_CACHE (0x2U)
+#define PRE_DEFINE_SHIFT_0G (0U)
+#define PRE_DEFINE_SHIFT_1G (2U)
+#define PRE_DEFINE_SHIFT_2G (4U)
+#define PRE_DEFINE_SHIFT_3G (6U)
+
+#define SEC_FW_NON_SECURE (1U)
+#define SEC_FW_SHIFT_NS (4U)
+#define SEC_FW_DOMAIN_SHIFT (0U)
+
+#define SEC_USR_FW_NON_SECURE (1U)
+#define SEC_USR_FW_SHIFT_NS (4U)
+#define SEC_USR_FW_DOMAIN_SHIFT (0U)
+
+#define SYS_CTRL_RUN (0U)
+#define SYS_CTRL_STALL (1U)
+
+/* Reviser Register */
+#define REVISER_SECUREFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x100)
+#define REVISER_USDRFW_CTXT (APUSYS_SCTRL_REVISER_BASE + 0x104)
+
+int32_t apusys_kernel_ctrl(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+ uint32_t *ret1);
+#endif /* MTK_APUSYS_H */
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c
new file mode 100644
index 0000000..aed0833
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mtk_dcm.h>
+#include <mtk_dcm_utils.h>
+
+static void dcm_armcore(bool mode)
+{
+ dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
+ dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
+}
+
+static void dcm_mcusys(bool on)
+{
+ dcm_mp_cpusys_top_adb_dcm(on);
+ dcm_mp_cpusys_top_apb_dcm(on);
+ dcm_mp_cpusys_top_cpubiu_dcm(on);
+ dcm_mp_cpusys_top_misc_dcm(on);
+ dcm_mp_cpusys_top_mp0_qdcm(on);
+ dcm_cpccfg_reg_emi_wfifo(on);
+ dcm_mp_cpusys_top_last_cor_idle_dcm(on);
+}
+
+static void dcm_stall(bool on)
+{
+ dcm_mp_cpusys_top_core_stall_dcm(on);
+ dcm_mp_cpusys_top_fcm_stall_dcm(on);
+}
+
+static bool check_dcm_state(void)
+{
+ bool ret = true;
+
+ ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
+ ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
+ ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
+
+ ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
+ ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
+
+ return ret;
+}
+
+bool dcm_set_default(void)
+{
+ dcm_armcore(true);
+ dcm_mcusys(true);
+ dcm_stall(true);
+
+ return check_dcm_state();
+}
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h
new file mode 100644
index 0000000..cb65b85
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+bool dcm_set_default(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c
new file mode 100644
index 0000000..a1a3720
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mtk_dcm_utils.h>
+
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18) | \
+ BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | \
+ BIT(16) | \
+ BIT(17) | \
+ BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | \
+ (0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18) | \
+ (0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | \
+ (0x0 << 16) | \
+ (0x0 << 17) | \
+ (0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0) &
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4) &
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_adb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_ADB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16))
+
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_apb_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+ MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | \
+ BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \
+ (0x0 << 24) | \
+ (0x0 << 25))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_core_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSIC_DCM0) &
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 24) | \
+ (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(24) | \
+ BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 24) | \
+ (0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1) &
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4))
+
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0U << 31))
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | \
+ BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | \
+ (0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_misc_dcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+ MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
+ }
+}
+
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3))
+
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK) ==
+ (unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+
+ return ret;
+}
+
+void dcm_mp_cpusys_top_mp0_qdcm(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+ mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+ MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF);
+ }
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | \
+ BIT(1) | \
+ BIT(2) | \
+ BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | \
+ (0x0 << 1) | \
+ (0x0 << 2) | \
+ (0x0 << 3))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+ bool ret = true;
+
+ ret &= ((mmio_read_32(CPCCFG_REG_EMI_WFIFO) &
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK) ==
+ (unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON);
+
+ return ret;
+}
+
+void dcm_cpccfg_reg_emi_wfifo(bool on)
+{
+ if (on) {
+ /* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_ON);
+ } else {
+ /* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
+ mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+ CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+ CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+ }
+}
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h
new file mode 100644
index 0000000..e5743af
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_UTILS_H
+#define MTK_DCM_UTILS_H
+
+#include <stdbool.h>
+
+#include <mtk_dcm.h>
+#include <platform_def.h>
+
+/* Base */
+#define MP_CPUSYS_TOP_BASE (MCUCFG_BASE + 0x8000)
+#define CPCCFG_REG_BASE (MCUCFG_BASE + 0xA800)
+
+/* Register Definition */
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
+#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
+#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
+#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
+
+/* MP_CPUSYS_TOP */
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
+void dcm_mp_cpusys_top_adb_dcm(bool on);
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
+void dcm_mp_cpusys_top_apb_dcm(bool on);
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_core_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
+void dcm_mp_cpusys_top_misc_dcm(bool on);
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
+void dcm_mp_cpusys_top_mp0_qdcm(bool on);
+/* CPCCFG_REG */
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+
+#endif
diff --git a/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..c083318
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+ uint64_t cache_dump)
+{
+ mmio_write_32(MTK_WDT_LATCH_CTL2, MTK_WDT_LATCH_CTL2_VAL);
+ mmio_write_32(MTK_WDT_INTERVAL, MTK_WDT_INTERVAL_VAL);
+ mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_VAL);
+ mmio_write_32(MTK_DRM_LATCH_CTL1, MTK_DRM_LATCH_CTL1_VAL);
+
+ /* Bit[2] = 0 (default=1), disable dfd apb bus protect_en */
+ mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 0x1 << 2);
+
+ /* Bit[0] : enable?mcusys_vproc?external_off?dfd?trigger -> 1 */
+ mmio_setbits_32(DFD_V50_GROUP_0_63_DIFF, 0x1);
+
+ /* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */
+ /* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */
+ sync_writel(DFD_INTERNAL_CTL, 0x5);
+
+ /* bit[13]: xreset_b_update_disable */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13);
+
+ /*
+ * bit[10:3]: DFD trigger selection mask
+ * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger)
+ * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger)
+ * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger)
+ * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger)
+ * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger)
+ */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1F << 3);
+
+ /*
+ * bit[9] : rg_rw_dfd_trigger_sel[6] = 1(cpu_eb_sw_dfd_trigger)
+ * bit[10] : rg_rw_dfd_trigger_sel[7] = 1(cpu_eb_wdt_dfd_trigger)
+ */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 9);
+
+ /* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
+
+ /*
+ * bit[0]: rg_rw_dfd_auto_power_on = 1
+ * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us)
+ * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us)
+ */
+ mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
+
+ /* longest scan chain length */
+ mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+
+ /* bit[1:0]: rg_rw_dfd_shift_clock_ratio */
+ mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
+
+ /* rg_dfd_test_so_over_64 */
+ mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
+
+ /* DFD3.0 */
+ mmio_write_32(DFD_TEST_SI_0, 0x0);
+ mmio_write_32(DFD_TEST_SI_1, 0x0);
+ mmio_write_32(DFD_TEST_SI_2, 0x0);
+ mmio_write_32(DFD_TEST_SI_3, 0x0);
+
+ /* for iLDO feature */
+ sync_writel(DFD_POWER_CTL, 0xF9);
+
+ /* read offset */
+ sync_writel(DFD_READ_ADDR, DFD_READ_ADDR_VAL);
+
+ /* for DFD-3.0 setup */
+ sync_writel(DFD_V30_CTL, 0xD);
+
+ /* set base address */
+ mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
+ mmio_write_32(DFD_O_REG_0, 0);
+
+ /* setup global variables for suspend and resume */
+ dfd_enabled = true;
+ dfd_base_addr = base_addr;
+ dfd_chain_length = chain_length;
+ dfd_cache_dump = cache_dump;
+
+ if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+ mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_CACHE_VAL);
+ sync_writel(DFD_V35_ENABLE, 0x1);
+ sync_writel(DFD_V35_TAP_NUMBER, 0xB);
+ sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+ sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+ /* Cache dump only mode */
+ sync_writel(DFD_V35_CTL, 0x1);
+ mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 0xF);
+ mmio_write_32(DFD_CHAIN_LENGTH0, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH1, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH2, DFD_CHAIN_LENGTH_VAL);
+ mmio_write_32(DFD_CHAIN_LENGTH3, DFD_CHAIN_LENGTH_VAL);
+
+ if ((cache_dump & DFD_PARITY_ERR_TRIGGER) != 0UL) {
+ sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
+ mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
+ }
+ }
+ dsbsy();
+}
+
+void dfd_resume(void)
+{
+ if (dfd_enabled == true) {
+ dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+ }
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3)
+{
+ uint64_t ret = 0L;
+
+ switch (arg0) {
+ case PLAT_MTK_DFD_SETUP_MAGIC:
+ INFO("[%s] DFD setup call from kernel\n", __func__);
+ dfd_setup(arg1, arg2, arg3);
+ break;
+ case PLAT_MTK_DFD_READ_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+ }
+ break;
+ case PLAT_MTK_DFD_WRITE_MAGIC:
+ /* only allow to access DFD register base + 0x200 */
+ if (arg1 <= 0x200) {
+ sync_writel(MISC1_CFG_BASE + arg1, arg2);
+ }
+ break;
+ default:
+ ret = MTK_SIP_E_INVALID_PARAM;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..2a7e979
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \
+ dsbsy(); \
+ } while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC (0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152)
+
+#define MTK_DRM_LATCH_CTL1 (DRM_BASE + 0x40)
+#define MTK_DRM_LATCH_CTL2 (DRM_BASE + 0x44)
+
+#define MTK_WDT_BASE (RGU_BASE)
+#define MTK_WDT_INTERVAL (MTK_WDT_BASE + 0x10)
+#define MTK_WDT_LATCH_CTL2 (MTK_WDT_BASE + 0x48)
+
+#define MCU_BIU_BASE (MCUCFG_BASE)
+#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040)
+#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10)
+#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C)
+#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20)
+#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24)
+#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30)
+#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34)
+#define DFD_INTERNAL_SW_NS_TRIGGER (MISC1_CFG_BASE + 0x3c)
+#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C)
+#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50)
+#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C)
+#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60)
+#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8)
+#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC)
+#define DFD_READ_ADDR (MISC1_CFG_BASE + 0x1E8)
+#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENABLE (MCU_BIU_BASE + 0xE0A8)
+#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC)
+#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0)
+#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4)
+#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0)
+#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4)
+#define DFD_V50_GROUP_0_63_DIFF (MCU_BIU_BASE + 0xE2AC)
+
+#define DFD_O_PROTECT_EN_REG (0x10001220)
+#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C)
+#define DFD_O_SET_BASEADDR_REG (0x10043000)
+#define DFD_O_REG_0 (0x10001390)
+
+#define DFD_CACHE_DUMP_ENABLE 1U
+#define DFD_PARITY_ERR_TRIGGER 2U
+
+#define DFD_V35_TAP_EN_VAL (0x43FF)
+#define DFD_V35_SEQ0_0_VAL (0x63668820)
+#define DFD_READ_ADDR_VAL (0x40000008)
+#define DFD_CHAIN_LENGTH_VAL (0xFFFFFFFF)
+
+#define MTK_WDT_LATCH_CTL2_VAL (0x9507FFFF)
+#define MTK_WDT_INTERVAL_VAL (0x6600000A)
+#define MTK_DRM_LATCH_CTL2_VAL (0x950600C8)
+#define MTK_DRM_LATCH_CTL2_CACHE_VAL (0x95065DC0)
+
+#define MTK_DRM_LATCH_CTL1_VAL (0x95000013)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+ uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..794e21e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <emi_mpu.h>
+
+#if ENABLE_EMI_MPU_SW_LOCK
+static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
+#endif
+
+#define EMI_MPU_START_MASK (0x00FFFFFF)
+#define EMI_MPU_END_MASK (0x00FFFFFF)
+#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
+#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
+
+static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
+ unsigned int apc)
+{
+ unsigned int dgroup;
+ unsigned int region;
+
+ region = (start >> 24) & 0xFF;
+ start &= EMI_MPU_START_MASK;
+ dgroup = (end >> 24) & 0xFF;
+ end &= EMI_MPU_END_MASK;
+
+ if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+ WARN("invalid region, domain\n");
+ return -1;
+ }
+
+#if ENABLE_EMI_MPU_SW_LOCK
+ if (region_lock_state[region] == 1) {
+ WARN("invalid region\n");
+ return -1;
+ }
+
+ if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
+ region_lock_state[region] = 1;
+ }
+
+ apc &= EMI_MPU_APC_SW_LOCK_MASK;
+#else
+ apc &= EMI_MPU_APC_HW_LOCK_MASK;
+#endif
+
+ if ((start >= DRAM_OFFSET) && (end >= start)) {
+ start -= DRAM_OFFSET;
+ end -= DRAM_OFFSET;
+ } else {
+ WARN("invalid range\n");
+ return -1;
+ }
+
+ mmio_write_32(EMI_MPU_SA(region), start);
+ mmio_write_32(EMI_MPU_EA(region), end);
+ mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+#if defined(SUB_EMI_MPU_BASE)
+ mmio_write_32(SUB_EMI_MPU_SA(region), start);
+ mmio_write_32(SUB_EMI_MPU_EA(region), end);
+ mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
+#endif
+ return 1;
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+ unsigned int start, end;
+ int i;
+
+ if (region_info->region >= EMI_MPU_REGION_NUM) {
+ WARN("invalid region\n");
+ return -1;
+ }
+
+ start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+ (region_info->region << 24);
+
+ for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+ end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) |
+ (i << 24);
+ _emi_mpu_set_protection(start, end, region_info->apc[i]);
+ }
+
+ return 0;
+}
+
+void dump_emi_mpu_regions(void)
+{
+ unsigned long apc[EMI_MPU_DGROUP_NUM], sa, ea;
+
+ int region, i;
+
+ /* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
+ for (region = 0; region < 8; ++region) {
+ for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i)
+ apc[i] = mmio_read_32(EMI_MPU_APC(region, i));
+ sa = mmio_read_32(EMI_MPU_SA(region));
+ ea = mmio_read_32(EMI_MPU_EA(region));
+
+ INFO("region %d:\n", region);
+ INFO("\tsa:0x%lx, ea:0x%lx, apc0: 0x%lx apc1: 0x%lx\n",
+ sa, ea, apc[0], apc[1]);
+ }
+}
+
+void emi_mpu_init(void)
+{
+ struct emi_region_info_t region_info;
+
+ /* SCP DRAM */
+ region_info.start = 0x50000000ULL;
+ region_info.end = 0x51400000ULL;
+ region_info.region = 2;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ NO_PROTECTION, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+ emi_mpu_set_protection(&region_info);
+
+ /* DSP protect address */
+ region_info.start = 0x60000000ULL; /* dram base addr */
+ region_info.end = 0x610FFFFFULL;
+ region_info.region = 3;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+ emi_mpu_set_protection(&region_info);
+
+ /* Forbidden All */
+ region_info.start = 0x40000000ULL; /* dram base addr */
+ region_info.end = 0x1FFFF0000ULL;
+ region_info.region = 4;
+ SET_ACCESS_PERMISSION(region_info.apc, 1,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
+ FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROTECTION);
+ emi_mpu_set_protection(&region_info);
+
+ dump_emi_mpu_regions();
+}
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..415146e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define ENABLE_EMI_MPU_SW_LOCK 1
+
+#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000)
+#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004)
+#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4))
+#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4))
+#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4))
+#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4))
+#define EMI_MPU_START (0x000)
+#define EMI_MPU_END (0x93C)
+
+#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000)
+#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004)
+#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100)
+#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200)
+#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4))
+#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4))
+#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300)
+#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800)
+#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4))
+#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900)
+#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4))
+
+#define EMI_MPU_DOMAIN_NUM (16)
+#define EMI_MPU_REGION_NUM (32)
+#define EMI_MPU_ALIGN_BITS (16)
+#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define NO_PROTECTION 0
+#define SEC_RW 1
+#define SEC_RW_NSEC_R 2
+#define SEC_RW_NSEC_W 3
+#define SEC_R_NSEC_R 4
+#define FORBIDDEN 5
+#define SEC_R_NSEC_RW 6
+
+#define LOCK 1
+#define UNLOCK 0
+
+#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = 0; \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
+ (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
+ (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
+ (((unsigned int) d1) << 3) | ((unsigned int) d0) | \
+ ((unsigned int) lock << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+ d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+ apc_ary[1] = \
+ (((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \
+ (((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \
+ (((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \
+ (((unsigned int) d9) << 3) | ((unsigned int) d8); \
+ apc_ary[0] = \
+ (((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
+ (((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
+ (((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
+ (((unsigned int) d1) << 3) | ((unsigned int) d0) | \
+ ((unsigned int) lock << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+ unsigned long long start;
+ unsigned long long end;
+ unsigned int region;
+ unsigned int apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+
+#endif
diff --git a/plat/mediatek/mt8195/drivers/gpio/mtgpio.c b/plat/mediatek/mt8195/drivers/gpio/mtgpio.c
new file mode 100644
index 0000000..daab84c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/gpio/mtgpio.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mtgpio.h>
+#include <platform_def.h>
+
+uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
+{
+ uintptr_t reg_addr = 0U;
+ struct mt_pin_info gpio_info;
+
+ assert(pin < MAX_GPIO_PIN);
+
+ gpio_info = mt_pin_infos[pin];
+
+ switch (gpio_info.base & 0x0f) {
+ case 0:
+ reg_addr = IOCFG_BM_BASE;
+ break;
+ case 1:
+ reg_addr = IOCFG_BL_BASE;
+ break;
+ case 2:
+ reg_addr = IOCFG_BR_BASE;
+ break;
+ case 3:
+ reg_addr = IOCFG_LM_BASE;
+ break;
+ case 4:
+ reg_addr = IOCFG_RB_BASE;
+ break;
+ case 5:
+ reg_addr = IOCFG_TL_BASE;
+ break;
+ default:
+ break;
+ }
+
+ return reg_addr;
+}
diff --git a/plat/mediatek/mt8195/drivers/gpio/mtgpio.h b/plat/mediatek/mt8195/drivers/gpio/mtgpio.h
new file mode 100644
index 0000000..88b4706
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/gpio/mtgpio.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_GPIO_H
+#define MT_GPIO_H
+
+#include <mtgpio_common.h>
+
+/* Enumeration for GPIO pin */
+typedef enum GPIO_PIN {
+ GPIO_UNSUPPORTED = -1,
+
+ GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
+ GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
+ GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
+ GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
+ GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
+ GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
+ GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
+ GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
+ GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
+ GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
+ GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
+ GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
+ GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
+ GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
+ GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
+ GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
+ GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135,
+ GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143,
+ MT_GPIO_BASE_MAX
+} GPIO_PIN;
+
+static const struct mt_pin_info mt_pin_infos[] = {
+ PIN(0, 1, 0, 0x23, 0x60),
+ PIN(1, 1, 1, 0x23, 0x60),
+ PIN(2, 1, 2, 0x23, 0x60),
+ PIN(3, 1, 3, 0x23, 0x60),
+ PIN(4, 1, 4, 0x23, 0x60),
+ PIN(5, 1, 5, 0x23, 0x60),
+ PIN(6, 0, 6, 0x23, 0x70),
+ PIN(7, 0, 7, 0x23, 0x70),
+ PIN(8, 0, 13, 0x23, 0x70),
+ PIN(9, 0, 8, 0x23, 0x70),
+ PIN(10, 0, 14, 0x23, 0x70),
+ PIN(11, 0, 9, 0x23, 0x70),
+ PIN(12, 0, 15, 0x23, 0x70),
+ PIN(13, 0, 10, 0x23, 0x70),
+ PIN(14, 0, 16, 0x23, 0x70),
+ PIN(15, 0, 11, 0x23, 0x70),
+ PIN(16, 0, 17, 0x23, 0x70),
+ PIN(17, 0, 12, 0x23, 0x70),
+ PIN(18, 0, 5, 0x10, 0x60),
+ PIN(19, 0, 12, 0x10, 0x60),
+ PIN(20, 0, 11, 0x10, 0x60),
+ PIN(21, 0, 10, 0x10, 0x60),
+ PIN(22, 0, 0, 0x10, 0x60),
+ PIN(23, 0, 1, 0x10, 0x60),
+ PIN(24, 0, 2, 0x10, 0x60),
+ PIN(25, 0, 4, 0x10, 0x60),
+ PIN(26, 0, 3, 0x10, 0x60),
+ PIN(27, 0, 6, 0x10, 0x60),
+ PIN(28, 0, 7, 0x10, 0x60),
+ PIN(29, 0, 8, 0x10, 0x60),
+ PIN(30, 0, 9, 0x10, 0x60),
+ PIN(31, 0, 13, 0x21, 0xa0),
+ PIN(32, 0, 12, 0x21, 0xa0),
+ PIN(33, 0, 11, 0x21, 0xa0),
+ PIN(34, 0, 14, 0x21, 0xa0),
+ PIN(35, 0, 15, 0x21, 0xa0),
+ PIN(36, 0, 3, 0x21, 0xb0),
+ PIN(37, 0, 6, 0x21, 0xb0),
+ PIN(38, 0, 4, 0x21, 0xb0),
+ PIN(39, 0, 5, 0x21, 0xb0),
+ PIN(40, 0, 8, 0x21, 0xb0),
+ PIN(41, 0, 7, 0x21, 0xb0),
+ PIN(42, 0, 10, 0x21, 0xb0),
+ PIN(43, 0, 9, 0x21, 0xb0),
+ PIN(44, 0, 20, 0x21, 0xb0),
+ PIN(45, 0, 21, 0x21, 0xb0),
+ PIN(46, 0, 18, 0x21, 0xa0),
+ PIN(47, 0, 16, 0x21, 0xa0),
+ PIN(48, 0, 19, 0x21, 0xa0),
+ PIN(49, 0, 17, 0x21, 0xa0),
+ PIN(50, 0, 25, 0x21, 0xa0),
+ PIN(51, 0, 20, 0x21, 0xa0),
+ PIN(52, 0, 26, 0x21, 0xa0),
+ PIN(53, 0, 21, 0x21, 0xa0),
+ PIN(54, 0, 22, 0x21, 0xa0),
+ PIN(55, 0, 23, 0x21, 0xa0),
+ PIN(56, 0, 24, 0x21, 0xa0),
+ PIN(57, 0, 29, 0x21, 0xa0),
+ PIN(58, 0, 27, 0x21, 0xa0),
+ PIN(59, 0, 30, 0x21, 0xa0),
+ PIN(60, 0, 28, 0x21, 0xa0),
+ PIN(61, 0, 8, 0x21, 0xa0),
+ PIN(62, 0, 7, 0x21, 0xa0),
+ PIN(63, 0, 10, 0x21, 0xa0),
+ PIN(64, 0, 9, 0x21, 0xa0),
+ PIN(65, 0, 1, 0x21, 0xb0),
+ PIN(66, 0, 31, 0x21, 0xa0),
+ PIN(67, 0, 0, 0x21, 0xb0),
+ PIN(68, 0, 2, 0x21, 0xb0),
+ PIN(69, 0, 0, 0x21, 0xa0),
+ PIN(70, 0, 6, 0x21, 0xa0),
+ PIN(71, 0, 4, 0x21, 0xa0),
+ PIN(72, 0, 5, 0x21, 0xa0),
+ PIN(73, 0, 1, 0x21, 0xa0),
+ PIN(74, 0, 2, 0x21, 0xa0),
+ PIN(75, 0, 3, 0x21, 0xa0),
+ PIN(76, 0, 11, 0x21, 0xb0),
+ PIN(77, 1, 1, 0x22, 0x60),
+ PIN(78, 1, 2, 0x22, 0x60),
+ PIN(79, 1, 9, 0x22, 0x60),
+ PIN(80, 1, 10, 0x22, 0x60),
+ PIN(81, 1, 11, 0x22, 0x60),
+ PIN(82, 1, 12, 0x22, 0x60),
+ PIN(83, 1, 13, 0x22, 0x60),
+ PIN(84, 1, 14, 0x22, 0x60),
+ PIN(85, 1, 15, 0x22, 0x60),
+ PIN(86, 1, 16, 0x22, 0x60),
+ PIN(87, 1, 3, 0x22, 0x60),
+ PIN(88, 1, 4, 0x22, 0x60),
+ PIN(89, 1, 5, 0x22, 0x60),
+ PIN(90, 1, 6, 0x22, 0x60),
+ PIN(91, 1, 7, 0x22, 0x60),
+ PIN(92, 1, 8, 0x22, 0x60),
+ PIN(93, 1, 18, 0x22, 0x60),
+ PIN(94, 1, 19, 0x22, 0x60),
+ PIN(95, 1, 17, 0x22, 0x60),
+ PIN(96, 1, 0, 0x22, 0x60),
+ PIN(97, 0, 20, 0x22, 0x70),
+ PIN(98, 0, 28, 0x22, 0x70),
+ PIN(99, 0, 27, 0x22, 0x70),
+ PIN(100, 0, 30, 0x22, 0x70),
+ PIN(101, 0, 29, 0x22, 0x70),
+ PIN(102, 0, 0, 0x22, 0x70),
+ PIN(103, 0, 31, 0x22, 0x70),
+ PIN(104, 1, 25, 0x22, 0x60),
+ PIN(105, 1, 26, 0x22, 0x60),
+ PIN(106, 1, 23, 0x22, 0x60),
+ PIN(107, 1, 24, 0x22, 0x60),
+ PIN(108, 0, 22, 0x22, 0x70),
+ PIN(109, 0, 21, 0x22, 0x70),
+ PIN(110, 1, 1, 0x14, 0x20),
+ PIN(111, 1, 0, 0x14, 0x20),
+ PIN(112, 1, 2, 0x14, 0x20),
+ PIN(113, 1, 3, 0x14, 0x20),
+ PIN(114, 1, 4, 0x14, 0x20),
+ PIN(115, 1, 5, 0x14, 0x20),
+ PIN(116, 1, 9, 0x25, 0x50),
+ PIN(117, 1, 8, 0x25, 0x50),
+ PIN(118, 1, 7, 0x25, 0x50),
+ PIN(119, 1, 6, 0x25, 0x50),
+ PIN(120, 1, 11, 0x25, 0x50),
+ PIN(121, 1, 1, 0x25, 0x50),
+ PIN(122, 1, 0, 0x25, 0x50),
+ PIN(123, 1, 5, 0x25, 0x50),
+ PIN(124, 1, 4, 0x25, 0x50),
+ PIN(125, 1, 3, 0x25, 0x50),
+ PIN(126, 1, 2, 0x25, 0x50),
+ PIN(127, 1, 10, 0x25, 0x50),
+ PIN(128, 0, 3, 0x22, 0x70),
+ PIN(129, 0, 1, 0x22, 0x70),
+ PIN(130, 0, 4, 0x22, 0x70),
+ PIN(131, 0, 2, 0x22, 0x70),
+ PIN(132, 0, 13, 0x25, 0x60),
+ PIN(133, 0, 12, 0x25, 0x60),
+ PIN(134, 0, 15, 0x25, 0x60),
+ PIN(135, 0, 14, 0x25, 0x60),
+ PIN(136, 0, 13, 0x21, 0xb0),
+ PIN(137, 0, 12, 0x21, 0xb0),
+ PIN(138, 0, 15, 0x21, 0xb0),
+ PIN(139, 0, 14, 0x21, 0xb0),
+ PIN(140, 0, 17, 0x21, 0xb0),
+ PIN(141, 0, 16, 0x21, 0xb0),
+ PIN(142, 0, 19, 0x21, 0xb0),
+ PIN(143, 0, 18, 0x21, 0xb0),
+};
+#endif /* MT_GPIO_H */
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c
new file mode 100644
index 0000000..5a80d95
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+#include <lib/spinlock.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_lp_irqremain.h>
+#include <mt_lp_rm.h>
+#include <mt_mcdi.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+
+DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
+
+static int plat_mt_lp_cpu_rc;
+
+static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state)
+{
+ mtk_cpc_core_on_hint_clr(cpu);
+
+ if (IS_SYSTEM_SUSPEND_STATE(state)) {
+ mtk_cpc_time_sync();
+ }
+
+ return 0;
+}
+
+static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ /* clear DBGPRCR.CORENPDRQ to allow CPU power down */
+ write_dbgprcr_el1(0ULL);
+
+ return 0;
+}
+
+static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ return 0;
+}
+
+static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state)
+{
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ mtk_cpc_mcusys_off_reflect();
+
+ return 0;
+}
+
+static int pwr_mcusys_pwron_finished(unsigned int cpu,
+ const psci_power_state_t *state)
+{
+ int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
+
+ if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) {
+ return -1;
+ }
+
+ mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id);
+ mt_lp_irqremain_release();
+
+ return 0;
+}
+
+static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state)
+{
+ int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS];
+
+ if (!IS_MCUSYS_OFF_STATE(state)) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (mcdi_try_init() != 0) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
+ goto mt_pwr_mcusysoff_break;
+ }
+
+ plat_mt_lp_cpu_rc =
+ mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL);
+
+ if (plat_mt_lp_cpu_rc < 0) {
+ goto mt_pwr_mcusysoff_reflect;
+ }
+
+ mt_lp_irqremain_aquire();
+
+ return 0;
+
+mt_pwr_mcusysoff_reflect:
+ mtk_cpc_mcusys_off_reflect();
+
+mt_pwr_mcusysoff_break:
+
+ plat_mt_lp_cpu_rc = -1;
+
+ return -1;
+}
+
+static const struct mt_lpm_tz plat_pm = {
+ .pwr_prompt = pwr_state_prompt,
+ .pwr_reflect = pwr_state_reflect,
+ .pwr_cpu_on = pwr_cpu_pwron,
+ .pwr_cpu_dwn = pwr_cpu_pwrdwn,
+ .pwr_cluster_on = pwr_cluster_pwron,
+ .pwr_cluster_dwn = pwr_cluster_pwrdwn,
+ .pwr_mcusys_dwn = pwr_mcusys_pwrdwn,
+ .pwr_mcusys_on = pwr_mcusys_pwron,
+ .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void)
+{
+ mtk_cpc_init();
+
+ if (mcdi_try_init() == 0) {
+ INFO("MCDI init done.\n");
+ }
+
+ mt_lp_irqremain_init();
+
+ return &plat_pm;
+}
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c
new file mode 100644
index 0000000..f8c51a1
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <drivers/delay_timer.h>
+
+#include <mt_cpu_pm_cpc.h>
+#include <mt_timer.h>
+
+struct mtk_cpc_dev {
+ int auto_off;
+ unsigned int auto_thres_tick;
+};
+
+static struct mtk_cpc_dev cpc;
+
+static int mtk_cpc_last_core_prot(uint32_t prot_req,
+ uint32_t resp_reg, uint32_t resp_ofs)
+{
+ uint32_t sta, retry;
+
+ retry = 0U;
+
+ while (retry++ < RETRY_CNT_MAX) {
+
+ mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
+
+ udelay(1U);
+
+ sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
+
+ if (sta == PROT_SUCCESS) {
+ return CPC_SUCCESS;
+ } else if (sta == PROT_GIVEUP) {
+ return CPC_ERR_FAIL;
+ }
+ }
+
+ return CPC_ERR_TIMEOUT;
+}
+
+int mtk_cpu_pm_mcusys_prot_aquire(void)
+{
+ return mtk_cpc_last_core_prot(
+ MCUSYS_PROT_SET,
+ CPC_MCUSYS_LAST_CORE_RESP,
+ MCUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_mcusys_prot_release(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
+}
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster)
+{
+ return mtk_cpc_last_core_prot(
+ CPUSYS_PROT_SET,
+ CPC_MCUSYS_MP_LAST_CORE_RESP,
+ CPUSYS_RESP_OFS);
+}
+
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
+}
+
+static void mtk_cpc_cluster_cnt_backup(void)
+{
+ uint32_t backup_cnt;
+ uint32_t curr_cnt;
+ uint32_t cnt_mask = GENMASK(14, 0);
+ uint32_t clr_mask = GENMASK(1, 0);
+
+ /* Single Cluster */
+ backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
+ curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
+
+ /* Get off count if dormant count is 0 */
+ if ((curr_cnt & cnt_mask) == 0U) {
+ curr_cnt = (curr_cnt >> 16) & cnt_mask;
+ } else {
+ curr_cnt = curr_cnt & cnt_mask;
+ }
+
+ mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
+ mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask);
+}
+
+static inline void mtk_cpc_mcusys_off_en(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U);
+}
+
+static inline void mtk_cpc_mcusys_off_dis(void)
+{
+ mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U);
+}
+
+void mtk_cpc_mcusys_off_reflect(void)
+{
+ mtk_cpc_mcusys_off_dis();
+ mtk_cpu_pm_mcusys_prot_release();
+}
+
+int mtk_cpc_mcusys_off_prepare(void)
+{
+ if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
+ return CPC_ERR_FAIL;
+ }
+
+ mtk_cpc_cluster_cnt_backup();
+ mtk_cpc_mcusys_off_en();
+
+ return CPC_SUCCESS;
+}
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
+}
+
+void mtk_cpc_core_on_hint_clr(unsigned int cpu)
+{
+ mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
+}
+
+static void mtk_cpc_dump_timestamp(void)
+{
+ uint32_t id;
+
+ for (id = 0U; id < CPC_TRACE_ID_NUM; id++) {
+ mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
+
+ memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
+ (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
+ CPC_TRACE_SIZE);
+ }
+}
+
+void mtk_cpc_time_sync(void)
+{
+ uint64_t kt;
+ uint32_t systime_l, systime_h;
+
+ kt = sched_clock();
+ systime_l = mmio_read_32(CNTSYS_L_REG);
+ systime_h = mmio_read_32(CNTSYS_H_REG);
+
+ /* sync kernel timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
+ mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
+ /* sync system timer to cpc */
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
+ mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
+}
+
+static void mtk_cpc_config(uint32_t cfg, uint32_t data)
+{
+ uint32_t val;
+ uint32_t reg = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ reg = CPC_MCUSYS_CPC_DBG_SETTING;
+ val = mmio_read_32(reg);
+ val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN);
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG;
+ val = mmio_read_32(reg);
+ if (data != 0U) {
+ val |= CPC_AUTO_OFF_EN;
+ cpc.auto_off = 1;
+ } else {
+ val &= ~CPC_AUTO_OFF_EN;
+ cpc.auto_off = 0;
+ }
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ reg = CPC_MCUSYS_CPC_OFF_THRES;
+ cpc.auto_thres_tick = us_to_ticks(data);
+ val = cpc.auto_thres_tick;
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR;
+ val = GENMASK(1, 0); /* clr_mask */
+ break;
+ case CPC_SMC_CONFIG_TIME_SYNC:
+ mtk_cpc_time_sync();
+ break;
+ default:
+ break;
+ }
+
+ if (reg != 0U) {
+ mmio_write_32(reg, val);
+ }
+}
+
+static uint32_t mtk_cpc_read_config(uint32_t cfg)
+{
+ uint32_t res = 0U;
+
+ switch (cfg) {
+ case CPC_SMC_CONFIG_PROF:
+ res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ?
+ 1U : 0U;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF:
+ res = cpc.auto_off;
+ break;
+ case CPC_SMC_CONFIG_AUTO_OFF_THRES:
+ res = ticks_to_us(cpc.auto_thres_tick);
+ break;
+ case CPC_SMC_CONFIG_CNT_CLR:
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
+{
+ uint64_t res = 0ULL;
+
+ switch (act) {
+ case CPC_SMC_EVENT_DUMP_TRACE_DATA:
+ mtk_cpc_dump_timestamp();
+ break;
+ case CPC_SMC_EVENT_GIC_DPG_SET:
+ /* isolated_status = x2; */
+ break;
+ case CPC_SMC_EVENT_CPC_CONFIG:
+ mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2);
+ break;
+ case CPC_SMC_EVENT_READ_CONFIG:
+ res = mtk_cpc_read_config((uint32_t)arg1);
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+void mtk_cpc_init(void)
+{
+ mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING,
+ mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING)
+ | CPC_DBG_EN
+ | CPC_CALC_EN);
+
+ cpc.auto_off = 1;
+ cpc.auto_thres_tick = us_to_ticks(8000);
+
+ mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
+ mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG)
+ | CPC_OFF_PRE_EN
+ | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U));
+
+ mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
+}
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h
new file mode 100644
index 0000000..19dd6a2
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_CPU_PM_CPC_H
+#define MT_CPU_PM_CPC_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mcucfg.h>
+#include <platform_def.h>
+
+#define NEED_CPUSYS_PROT_WORKAROUND 1
+
+/* system sram registers */
+#define CPUIDLE_SRAM_REG(r) (uint32_t)(MTK_MCDI_SRAM_BASE + (r))
+
+/* db dump */
+#define CPC_TRACE_SIZE U(0x20)
+#define CPC_TRACE_ID_NUM U(10)
+#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
+
+/* buckup off count */
+#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0)
+#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4)
+
+/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */
+#define CPC_PWR_ON_SEQ_DIS BIT(1)
+#define CPC_PWR_ON_PRIORITY BIT(2)
+#define CPC_AUTO_OFF_EN BIT(5)
+#define CPC_DORMANT_WAIT_EN BIT(14)
+#define CPC_CTRL_EN BIT(16)
+#define CPC_OFF_PRE_EN BIT(29)
+
+/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */
+#define CPUSYS_PROT_SET BIT(0)
+#define MCUSYS_PROT_SET BIT(8)
+#define CPUSYS_PROT_CLR BIT(8)
+#define MCUSYS_PROT_CLR BIT(9)
+
+#define CPC_PROT_RESP_MASK U(0x3)
+#define CPUSYS_RESP_OFS U(16)
+#define MCUSYS_RESP_OFS U(30)
+
+#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK)
+
+#define RETRY_CNT_MAX U(1000)
+
+#define PROT_RETRY U(0)
+#define PROT_SUCCESS U(1)
+#define PROT_GIVEUP U(2)
+
+/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */
+#define CPC_PROF_EN BIT(0)
+#define CPC_DBG_EN BIT(1)
+#define CPC_FREEZE BIT(2)
+#define CPC_CALC_EN BIT(3)
+
+enum {
+ CPC_SUCCESS = 0,
+
+ CPC_ERR_FAIL,
+ CPC_ERR_TIMEOUT,
+
+ NF_CPC_ERR
+};
+
+enum {
+ CPC_SMC_EVENT_DUMP_TRACE_DATA,
+ CPC_SMC_EVENT_GIC_DPG_SET,
+ CPC_SMC_EVENT_CPC_CONFIG,
+ CPC_SMC_EVENT_READ_CONFIG,
+
+ NF_CPC_SMC_EVENT
+};
+
+enum {
+ CPC_SMC_CONFIG_PROF,
+ CPC_SMC_CONFIG_AUTO_OFF,
+ CPC_SMC_CONFIG_AUTO_OFF_THRES,
+ CPC_SMC_CONFIG_CNT_CLR,
+ CPC_SMC_CONFIG_TIME_SYNC,
+
+ NF_CPC_SMC_CONFIG
+};
+
+#define us_to_ticks(us) ((us) * 13)
+#define ticks_to_us(tick) ((tick) / 13)
+
+int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster);
+void mtk_cpu_pm_cluster_prot_release(unsigned int cluster);
+
+void mtk_cpc_mcusys_off_reflect(void);
+int mtk_cpc_mcusys_off_prepare(void);
+
+void mtk_cpc_core_on_hint_set(unsigned int cpu);
+void mtk_cpc_core_on_hint_clr(unsigned int cpu);
+void mtk_cpc_time_sync(void);
+
+uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
+void mtk_cpc_init(void);
+
+#endif /* MT_CPU_PM_CPC_H */
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c b/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c
new file mode 100644
index 0000000..f415cb8
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mt_cirq.h>
+#include <mt_lp_irqremain.h>
+#include <mt_lp_rm.h>
+#include <plat_mtk_lpm.h>
+
+#define KEYPAD_IRQ_ID U(138)
+
+#define KEYPAD_WAKESRC 0x4
+
+static struct mt_irqremain remain_irqs;
+
+int mt_lp_irqremain_submit(void)
+{
+ if (remain_irqs.count == 0) {
+ return -1;
+ }
+
+ set_wakeup_sources(remain_irqs.irqs, remain_irqs.count);
+ mt_lp_rm_do_update(-1, PLAT_RC_UPDATE_REMAIN_IRQS, &remain_irqs);
+
+ return 0;
+}
+
+int mt_lp_irqremain_aquire(void)
+{
+ if (remain_irqs.count == 0) {
+ return -1;
+ }
+
+ mt_cirq_sw_reset();
+ mt_cirq_clone_gic();
+ mt_cirq_enable();
+
+ return 0;
+}
+
+int mt_lp_irqremain_release(void)
+{
+ if (remain_irqs.count == 0) {
+ return -1;
+ }
+
+ mt_cirq_flush();
+ mt_cirq_disable();
+
+ return 0;
+}
+
+void mt_lp_irqremain_init(void)
+{
+ uint32_t idx;
+
+ remain_irqs.count = 0;
+
+ /*edge keypad*/
+ idx = remain_irqs.count;
+ remain_irqs.irqs[idx] = KEYPAD_IRQ_ID;
+ remain_irqs.wakeupsrc_cat[idx] = 0;
+ remain_irqs.wakeupsrc[idx] = KEYPAD_WAKESRC;
+ remain_irqs.count++;
+
+ mt_lp_irqremain_submit();
+}
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h b/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h
new file mode 100644
index 0000000..b86e17e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_LP_IRQREMAIN_H
+#define MT_LP_IRQREMAIN_H
+
+extern int mt_lp_irqremain_submit(void);
+extern int mt_lp_irqremain_aquire(void);
+extern int mt_lp_irqremain_release(void);
+extern void mt_lp_irqremain_init(void);
+#endif /* MT_LP_IRQREMAIN_H */
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c
new file mode 100644
index 0000000..c14e83b
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cdefs.h>
+#include <common/debug.h>
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mt_mcdi.h>
+
+/* Read/Write */
+#define APMCU_MCUPM_MBOX_AP_READY U(0)
+#define APMCU_MCUPM_MBOX_RESERVED_1 U(1)
+#define APMCU_MCUPM_MBOX_RESERVED_2 U(2)
+#define APMCU_MCUPM_MBOX_RESERVED_3 U(3)
+#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4)
+#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5)
+#define APMCU_MCUPM_MBOX_BUCK_MODE U(6)
+#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7)
+/* Read only */
+#define APMCU_MCUPM_MBOX_TASK_STA U(8)
+#define APMCU_MCUPM_MBOX_RESERVED_9 U(9)
+#define APMCU_MCUPM_MBOX_RESERVED_10 U(10)
+#define APMCU_MCUPM_MBOX_RESERVED_11 U(11)
+
+/* CPC mode - Read/Write */
+#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */
+#define MCUPM_MCUSYS_CTRL BIT(0)
+#define MCUPM_BUCK_CTRL BIT(1)
+#define MCUPM_ARMPLL_CTRL BIT(2)
+#define MCUPM_CM_CTRL BIT(3)
+#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */
+#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */
+#define MCUPM_BUCK_LP_MODE U(1)
+#define MCUPM_BUCK_OFF_MODE U(2)
+#define NF_MCUPM_BUCK_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */
+#define MCUPM_ARMPLL_ON U(0) /* default */
+#define MCUPM_ARMPLL_GATING U(1)
+#define MCUPM_ARMPLL_OFF U(2)
+#define NF_MCUPM_ARMPLL_MODE U(3)
+
+/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */
+#define MCUPM_TASK_UNINIT U(0)
+#define MCUPM_TASK_INIT U(1)
+#define MCUPM_TASK_INIT_FINISH U(2)
+#define MCUPM_TASK_WAIT U(3)
+#define MCUPM_TASK_RUN U(4)
+#define MCUPM_TASK_PAUSE U(5)
+
+#define SSPM_MBOX_3_BASE U(0x0c55fce0)
+
+#define MCDI_NOT_INIT 0
+#define MCDI_INIT_1 1
+#define MCDI_INIT_2 2
+#define MCDI_INIT_DONE 3
+
+static int mcdi_init_status __section("tzfw_coherent_mem");
+
+static inline uint32_t mcdi_mbox_read(uint32_t id)
+{
+ return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
+}
+
+static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
+{
+ mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
+}
+
+static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev)
+{
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev);
+}
+
+static void mtk_set_mcupm_pll_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_ARMPLL_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode);
+ }
+}
+
+static void mtk_set_mcupm_buck_mode(uint32_t mode)
+{
+ if (mode < NF_MCUPM_BUCK_MODE) {
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode);
+ }
+}
+
+static int mtk_mcupm_is_ready(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH);
+}
+
+static int mcdi_init_1(void)
+{
+ unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA);
+
+ if (sta != MCUPM_TASK_INIT) {
+ return -1;
+ }
+
+ mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
+ mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
+
+ mtk_mcupm_pwr_ctrl_setting(
+ MCUPM_MCUSYS_CTRL |
+ MCUPM_BUCK_CTRL |
+ MCUPM_ARMPLL_CTRL);
+
+ mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1);
+
+ return 0;
+}
+
+static int mcdi_init_2(void)
+{
+ return mtk_mcupm_is_ready() ? 0 : -1;
+}
+
+int mcdi_try_init(void)
+{
+ if (mcdi_init_status == MCDI_INIT_DONE) {
+ return 0;
+ }
+
+ if (mcdi_init_status == MCDI_NOT_INIT) {
+ mcdi_init_status = MCDI_INIT_1;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) {
+ mcdi_init_status = MCDI_INIT_2;
+ }
+
+ if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) {
+ mcdi_init_status = MCDI_INIT_DONE;
+ }
+
+ INFO("mcdi ready for mcusys-off-idle and system suspend\n");
+
+ return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status;
+}
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h
new file mode 100644
index 0000000..f3545aa
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_MCDI_H
+#define MT_MCDI_H
+
+int mcdi_try_init(void);
+
+#endif /* MT_MCDI_H */
diff --git a/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h
new file mode 100644
index 0000000..9e6e74c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMIC_WRAP_INIT_H
+#define PMIC_WRAP_INIT_H
+
+#include <stdint.h>
+
+#include "platform_def.h"
+#include <pmic_wrap_init_common.h>
+
+static struct mt8195_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
+
+/* PMIC_WRAP registers */
+struct mt8195_pmic_wrap_regs {
+ uint32_t init_done;
+ uint32_t reserved[543];
+ uint32_t wacs2_cmd;
+ uint32_t wacs2_wdata;
+ uint32_t reserved1[3];
+ uint32_t wacs2_rdata;
+ uint32_t reserved2[3];
+ uint32_t wacs2_vldclr;
+ uint32_t wacs2_sta;
+};
+
+#endif /* PMIC_WRAP_INIT_H */
diff --git a/plat/mediatek/mt8195/drivers/ptp3/ptp3_plat.h b/plat/mediatek/mt8195/drivers/ptp3/ptp3_plat.h
new file mode 100644
index 0000000..7d5391c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/ptp3/ptp3_plat.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PTP3_PLAT_H
+#define PTP3_PLAT_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <ptp3_common.h>
+
+/* CPU info */
+#define NR_PTP3_CFG_CPU U(8)
+#define PTP3_CFG_CPU_START_ID_L U(0)
+#define PTP3_CFG_CPU_START_ID_B U(4)
+#define PTP3_CFG_CPU_END_ID U(7)
+
+#define NR_PTP3_CFG1_DATA U(2)
+#define PTP3_CFG1_MASK 0x3000
+
+#define NR_PTP3_CFG2_DATA U(5)
+
+#define PTP3_CFG3_MASK1 0x1180
+#define PTP3_CFG3_MASK2 0x35C0
+#define PTP3_CFG3_MASK3 0x3DC0
+
+/* Central control */
+static unsigned int ptp3_cfg1[NR_PTP3_CFG1_DATA][NR_PTP3_CFG] = {
+ {0x0C53A2A0, 0x1000},
+ {0x0C53A2A4, 0x1000}
+};
+
+static unsigned int ptp3_cfg2[NR_PTP3_CFG2_DATA][NR_PTP3_CFG] = {
+ {0x0C530404, 0x3A1000},
+ {0x0C530428, 0x13E0408},
+ {0x0C530434, 0xB22800},
+ {0x0C53043C, 0x750},
+ {0x0C530440, 0x0222c4cc}
+};
+
+static unsigned int ptp3_cfg3[NR_PTP3_CFG] = {0x0C530400, 0x2D80};
+static unsigned int ptp3_cfg3_ext[NR_PTP3_CFG] = {0x0C530400, 0xC00};
+
+#endif /* PTP3_PLAT_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/build.mk b/plat/mediatek/mt8195/drivers/spm/build.mk
new file mode 100644
index 0000000..28b2d07
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/build.mk
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2021, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Enable or disable spm feature
+MT_SPM_FEATURE_SUPPORT = yes
+
+# Enable or disable cirq restore
+MT_SPM_CIRQ_FEATURE_SUPPORT = yes
+
+# sspm notifier support
+MT_SPM_SSPM_NOTIFIER_SUPPORT = yes
+
+CUR_SPM_FOLDER = ${MTK_PLAT_SOC}/drivers/spm
+
+# spm common files
+PLAT_SPM_SOURCE_FILES_COMMON += \
+ ${CUR_SPM_FOLDER}/mt_spm.c \
+ ${CUR_SPM_FOLDER}/mt_spm_conservation.c \
+ ${CUR_SPM_FOLDER}/mt_spm_internal.c \
+ ${CUR_SPM_FOLDER}/mt_spm_pmic_wrap.c
+
+# spm platform dependcy files
+PLAT_SPM_SOURCE_FILES += \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_bus26m.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_cpu_buck_ldo.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_dram.c \
+ ${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c \
+ ${CUR_SPM_FOLDER}/mt_spm_cond.c \
+ ${CUR_SPM_FOLDER}/mt_spm_suspend.c \
+ ${CUR_SPM_FOLDER}/mt_spm_idle.c \
+ ${CUR_SPM_FOLDER}/mt_spm_vcorefs.c
+
+ifeq (${MT_SPM_FEATURE_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += ${PLAT_SPM_SOURCE_FILES_COMMON}
+else
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \
+ ${PLAT_SPM_SOURCE_FILES_COMMON} \
+ ${PLAT_SPM_SOURCE_FILES}
+endif
+
+ifeq (${MT_SPM_CIRQ_FEATURE_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_CIRQ_UNSUPPORT
+endif
+
+ifeq (${MT_SPM_SSPM_NOTIFIER_SUPPORT}, no)
+PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+else
+BL31_MT_LPM_PLAT_SPM_SOURCE_FILES += \
+ ${CUR_SPM_FOLDER}/notifier/mt_spm_sspm_notifier.c
+endif
+
+$(info --------------------------------------)
+$(info SPM build flags: ${PLAT_SPM_DEBUG_CFLAGS})
+$(info SPM build files: ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES})
+$(info --------------------------------------)
+
+# Common makefile for platform.mk
+PLAT_INCLUDES += \
+ ${PLAT_SPM_DEBUG_CFLAGS} \
+ -I${CUR_SPM_FOLDER}/ \
+ -I${CUR_SPM_FOLDER}/constraints/ \
+ -I${CUR_SPM_FOLDER}/notifier/
+
+PLAT_BL_COMMON_SOURCES += ${BL31_MT_LPM_PLAT_SPM_SOURCE_FILES}
diff --git a/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c
new file mode 100644
index 0000000..87278d7
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <plat_mtk_lpm.h>
+
+#ifndef ATF_PLAT_CIRQ_UNSUPPORT
+#include <mt_cirq.h>
+#include <mt_gic_v3.h>
+#endif
+
+#define CONSTRAINT_BUS26M_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
+ MT_RM_CONSTRAINT_ALLOW_LVTS_STATE | \
+ MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF)
+
+#define CONSTRAINT_BUS26M_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_ENABLE_TIA_WORKAROUND | \
+ SPM_FLAG_ENABLE_LVTS_WORKAROUND | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP)
+
+#define CONSTRAINT_BUS26M_PCM_FLAG1 0U
+
+#define CONSTRAINT_BUS26M_RESOURCE_REQ 0U
+
+static unsigned int bus26m_ext_opand;
+static struct mt_irqremain *refer2remain_irq;
+static struct mt_spm_cond_tables cond_bus26m = {
+ .name = "bus26m",
+ .table_cg = {
+ 0xFFFFD408, /* MTCMOS1 */
+ 0x2284C802, /* INFRA0 */
+ 0x27AF8000, /* INFRA1 */
+ 0x86040650, /* INFRA2 */
+ 0x30038020, /* INFRA3 */
+ 0x80000000, /* INFRA4 */
+ 0x00080ABB, /* PERI0 */
+ 0x00004000, /* VPPSYS0_0 */
+ 0x08803000, /* VPPSYS0_1 */
+ 0x00000000, /* VPPSYS0_2 */
+ 0x80005555, /* VPPSYS1_0 */
+ 0x00009008, /* VPPSYS1_1 */
+ 0x60060000, /* VDOSYS0_0 */
+ 0x00000000, /* VDOSYS0_1 */
+ 0x201E01F8, /* VDOSYS1_0 */
+ 0x00800000, /* VDOSYS1_1 */
+ 0x00000000, /* VDOSYS1_2 */
+ 0x00000080, /* I2C */
+ },
+ .table_pll = (PLL_BIT_UNIVPLL |
+ PLL_BIT_MFGPLL |
+ PLL_BIT_MSDCPLL |
+ PLL_BIT_TVDPLL |
+ PLL_BIT_MMPLL),
+};
+
+static struct mt_spm_cond_tables cond_bus26m_res = {
+ .table_cg = { 0U },
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_BUS26M,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_bus26m_res,
+};
+
+/*
+ * Cirq will take the place of gic when gic is off.
+ * However, cirq cannot work if 26m clk is turned off when system idle/suspend.
+ * Therefore, we need to set irq pending for specific wakeup source.
+ */
+#ifdef ATF_PLAT_CIRQ_UNSUPPORT
+#define do_irqs_delivery()
+#else
+static void mt_spm_irq_remain_dump(struct mt_irqremain *irqs,
+ unsigned int irq_index,
+ struct wake_status *wakeup)
+{
+ INFO("[SPM] r12 = 0x%08x(0x%08x), flag = 0x%08x 0x%08x 0x%08x\n",
+ wakeup->tr.comm.r12, wakeup->md32pcm_wakeup_sta,
+ wakeup->tr.comm.debug_flag, wakeup->tr.comm.b_sw_flag0,
+ wakeup->tr.comm.b_sw_flag1);
+
+ INFO("irq:%u(0x%08x) set pending\n",
+ irqs->wakeupsrc[irq_index], irqs->irqs[irq_index]);
+}
+
+static void do_irqs_delivery(void)
+{
+ unsigned int idx;
+ int res = 0;
+ struct wake_status *wakeup = NULL;
+ struct mt_irqremain *irqs = refer2remain_irq;
+
+ res = spm_conservation_get_result(&wakeup);
+
+ if ((res != 0) && (irqs == NULL)) {
+ return;
+ }
+
+ for (idx = 0U; idx < irqs->count; ++idx) {
+ if (((wakeup->tr.comm.r12 & irqs->wakeupsrc[idx]) != 0U) ||
+ ((wakeup->raw_sta & irqs->wakeupsrc[idx]) != 0U)) {
+ if ((irqs->wakeupsrc_cat[idx] &
+ MT_IRQ_REMAIN_CAT_LOG) != 0U) {
+ mt_spm_irq_remain_dump(irqs, idx, wakeup);
+ }
+
+ mt_irq_set_pending(irqs->irqs[idx]);
+ }
+ }
+}
+#endif
+
+static void spm_bus26m_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_BUS26M_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
+}
+
+int spm_update_rc_bus26m(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_bus26m;
+
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ &cond_bus26m_res : NULL);
+ } else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) {
+ refer2remain_irq = (struct mt_irqremain *)val;
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_bus26m(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_BUS26M_ALLOW;
+}
+
+int spm_run_rc_bus26m(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, CONSTRAINT_BUS26M_ALLOW |
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT |
+ MT_SPM_EX_OP_SET_SUSPEND_MODE |
+ bus26m_ext_opand),
+ CONSTRAINT_BUS26M_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, MT_SPM_EX_OP_HW_S1_DETECT,
+ spm_bus26m_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_bus26m(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ ext_op |= (bus26m_ext_opand | MT_SPM_EX_OP_SET_WDT);
+ mt_spm_suspend_resume(state_id, ext_op, NULL);
+ bus26m_ext_opand = 0U;
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL);
+ status.enter_cnt++;
+ }
+
+ do_irqs_delivery();
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c
new file mode 100644
index 0000000..cf71350
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+
+#define CONSTRAINT_CPU_BUCK_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP |\
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
+
+#define CONSTRAINT_CPU_BUCK_PCM_FLAG1 0U
+
+#define CONSTRAINT_CPU_BUCK_RESOURCE_REQ \
+ (MT_SPM_DRAM_S1 | \
+ MT_SPM_DRAM_S0 | \
+ MT_SPM_SYSPLL | \
+ MT_SPM_INFRA | \
+ MT_SPM_26M | \
+ MT_SPM_XO_FPM)
+
+
+static unsigned int cpubuckldo_status = MT_SPM_RC_VALID_SW;
+static unsigned int cpubuckldo_enter_cnt;
+
+static void spm_cpu_bcuk_ldo_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_CPU_BUCK_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return IS_MT_RM_RC_READY(cpubuckldo_status);
+}
+
+unsigned int spm_allow_rc_cpu_buck_ldo(int state_id)
+{
+ (void)state_id;
+
+ return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF;
+}
+
+int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER,
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ MT_SPM_EX_OP_SET_SUSPEND_MODE |
+ MT_SPM_EX_OP_SET_WDT,
+ CONSTRAINT_CPU_BUCK_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, 0U,
+ spm_cpu_bcuk_ldo_conduct);
+ }
+
+ cpubuckldo_enter_cnt++;
+
+ return 0;
+}
+
+int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U);
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, 0U, NULL);
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c
new file mode 100644
index 0000000..bd24ddd
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <plat_mtk_lpm.h>
+
+#define CONSTRAINT_DRAM_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF)
+
+#define CONSTRAINT_DRAM_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP)
+
+#define CONSTRAINT_DRAM_PCM_FLAG1 0U
+
+#define CONSTRAINT_DRAM_RESOURCE_REQ \
+ (MT_SPM_SYSPLL | \
+ MT_SPM_INFRA | \
+ MT_SPM_26M)
+
+static struct mt_spm_cond_tables cond_dram = {
+ .name = "dram",
+ .table_cg = {
+ 0xFFFDD008, /* MTCMOS1 */
+ 0x20040802, /* INFRA0 */
+ 0x27AF8000, /* INFRA1 */
+ 0x86040640, /* INFRA2 */
+ 0x00000000, /* INFRA3 */
+ 0x80000000, /* INFRA4 */
+ 0x00000000, /* PERI0 */
+ 0x00004000, /* VPPSYS0_0 */
+ 0x08803000, /* VPPSYS0_1 */
+ 0x00000000, /* VPPSYS0_2 */
+ 0x80005555, /* VPPSYS1_0 */
+ 0x00009008, /* VPPSYS1_1 */
+ 0x60060000, /* VDOSYS0_0 */
+ 0x00000000, /* VDOSYS0_1 */
+ 0x201E01F8, /* VDOSYS1_0 */
+ 0x00800000, /* VDOSYS1_1 */
+ 0x00000000, /* VDOSYS1_2 */
+ 0x00000080, /* I2C */
+ },
+ .table_pll = 0U,
+};
+
+static struct mt_spm_cond_tables cond_dram_res = {
+ .table_cg = { 0U },
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_DRAM,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH |
+ MT_SPM_RC_VALID_XSOC_BBLPM),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_dram_res,
+};
+
+static void spm_dram_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_DRAM_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_DRAM_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_dram(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
+}
+
+int spm_update_rc_dram(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_dram;
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ &cond_dram_res : NULL);
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_dram(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_DRAM_ALLOW;
+}
+
+int spm_run_rc_dram(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_DRAM_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows |
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#else
+ (void)allows;
+#endif
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_SET_SUSPEND_MODE |
+ MT_SPM_EX_OP_HW_S1_DETECT),
+ CONSTRAINT_DRAM_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op, spm_dram_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_dram(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_DRAM_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
+#else
+ (void)allows;
+#endif
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT),
+ NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL);
+ status.enter_cnt++;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h
new file mode 100644
index 0000000..9e74ace
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_RC_INTERNAL_H
+#define MT_SPM_RC_INTERNAL_H
+
+#include <stdbool.h>
+
+#define SPM_FLAG_SRAM_SLEEP_CTRL \
+ (SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
+ SPM_FLAG_DISABLE_SYSRAM_SLEEP)
+
+/* cpu buck/ldo constraint function */
+bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+unsigned int spm_allow_rc_cpu_buck_ldo(int state_id);
+int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id);
+
+/* spm resource dram constraint function */
+bool spm_is_valid_rc_dram(unsigned int cpu, int state_id);
+int spm_update_rc_dram(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_dram(int state_id);
+int spm_run_rc_dram(unsigned int cpu, int state_id);
+int spm_reset_rc_dram(unsigned int cpu, int state_id);
+
+/* spm resource syspll constraint function */
+bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id);
+int spm_update_rc_syspll(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_syspll(int state_id);
+int spm_run_rc_syspll(unsigned int cpu, int state_id);
+int spm_reset_rc_syspll(unsigned int cpu, int state_id);
+
+/* spm resource bus26m constraint function */
+bool spm_is_valid_rc_bus26m(unsigned int cpu, int state_id);
+int spm_update_rc_bus26m(int state_id, int type, const void *val);
+unsigned int spm_allow_rc_bus26m(int state_id);
+int spm_run_rc_bus26m(unsigned int cpu, int state_id);
+int spm_reset_rc_bus26m(unsigned int cpu, int state_id);
+#endif /* MT_SPM_RC_INTERNAL_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c
new file mode 100644
index 0000000..662f85e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_notifier.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <plat_mtk_lpm.h>
+
+#define CONSTRAINT_SYSPLL_ALLOW \
+ (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
+ MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
+ MT_RM_CONSTRAINT_ALLOW_VCORE_LP)
+
+#define CONSTRAINT_SYSPLL_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_SRAM_SLEEP_CTRL | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
+ SPM_FLAG_ENABLE_6315_CTRL | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP |\
+ SPM_FLAG_USE_SRCCLKENO2)
+
+#define CONSTRAINT_SYSPLL_PCM_FLAG1 0U
+#define CONSTRAINT_SYSPLL_RESOURCE_REQ (MT_SPM_26M)
+
+static struct mt_spm_cond_tables cond_syspll = {
+ .name = "syspll",
+ .table_cg = {
+ 0xFFFFD008, /* MTCMOS1 */
+ 0x20844802, /* INFRA0 */
+ 0x27AF8000, /* INFRA1 */
+ 0x86040640, /* INFRA2 */
+ 0x30038020, /* INFRA3 */
+ 0x80000000, /* INFRA4 */
+ 0x00080A8B, /* PERI0 */
+ 0x00004000, /* VPPSYS0_0 */
+ 0x08803000, /* VPPSYS0_1 */
+ 0x00000000, /* VPPSYS0_2 */
+ 0x80005555, /* VPPSYS1_0 */
+ 0x00009008, /* VPPSYS1_1 */
+ 0x60060000, /* VDOSYS0_0 */
+ 0x00000000, /* VDOSYS0_1 */
+ 0x201E01F8, /* VDOSYS1_0 */
+ 0x00800000, /* VDOSYS1_1 */
+ 0x00000000, /* VDOSYS1_2 */
+ 0x00000080, /* I2C */
+ },
+ .table_pll = 0U,
+};
+
+static struct mt_spm_cond_tables cond_syspll_res = {
+ .table_cg = { 0U },
+ .table_pll = 0U,
+};
+
+static struct constraint_status status = {
+ .id = MT_RM_CONSTRAINT_ID_SYSPLL,
+ .valid = (MT_SPM_RC_VALID_SW |
+ MT_SPM_RC_VALID_COND_LATCH |
+ MT_SPM_RC_VALID_XSOC_BBLPM),
+ .cond_block = 0U,
+ .enter_cnt = 0U,
+ .cond_res = &cond_syspll_res,
+};
+
+static void spm_syspll_conduct(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req)
+{
+ spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG;
+ spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1;
+ *resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ;
+}
+
+bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id)
+{
+ (void)cpu;
+ (void)state_id;
+
+ return (status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid);
+}
+
+int spm_update_rc_syspll(int state_id, int type, const void *val)
+{
+ const struct mt_spm_cond_tables *tlb;
+ const struct mt_spm_cond_tables *tlb_check;
+ int res = MT_RM_STATUS_OK;
+
+ if (val == NULL) {
+ return MT_RM_STATUS_BAD;
+ }
+
+ if (type == PLAT_RC_UPDATE_CONDITION) {
+ tlb = (const struct mt_spm_cond_tables *)val;
+ tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll;
+
+ status.cond_block =
+ mt_spm_cond_check(state_id, tlb, tlb_check,
+ ((status.valid &
+ MT_SPM_RC_VALID_COND_LATCH) != 0U) ?
+ &cond_syspll_res : NULL);
+ } else {
+ res = MT_RM_STATUS_BAD;
+ }
+
+ return res;
+}
+
+unsigned int spm_allow_rc_syspll(int state_id)
+{
+ (void)state_id;
+
+ return CONSTRAINT_SYSPLL_ALLOW;
+}
+
+int spm_run_rc_syspll(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows |
+ (IS_PLAT_SUSPEND_ID(state_id) ?
+ MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : 0U));
+#else
+ (void)allows;
+#endif
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_enter(state_id,
+ (MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT |
+ MT_SPM_EX_OP_SET_SUSPEND_MODE),
+ CONSTRAINT_SYSPLL_RESOURCE_REQ);
+ } else {
+ mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct);
+ }
+
+ return 0;
+}
+
+int spm_reset_rc_syspll(unsigned int cpu, int state_id)
+{
+ unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
+ unsigned int allows = CONSTRAINT_SYSPLL_ALLOW;
+
+ (void)cpu;
+
+ if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) {
+#ifdef MT_SPM_USING_SRCLKEN_RC
+ ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM;
+#else
+ allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM;
+#endif
+ }
+
+#ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT
+ mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows);
+#else
+ (void)allows;
+#endif
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ mt_spm_suspend_resume(state_id,
+ (MT_SPM_EX_OP_SET_SUSPEND_MODE |
+ MT_SPM_EX_OP_SET_WDT |
+ MT_SPM_EX_OP_HW_S1_DETECT),
+ NULL);
+ } else {
+ mt_spm_idle_generic_resume(state_id, ext_op, NULL);
+ status.enter_cnt++;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm.c b/plat/mediatek/mt8195/drivers/spm/mt_spm.c
new file mode 100644
index 0000000..f708bf5
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <mt_lp_rm.h>
+#include <mt_spm.h>
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <mtk_plat_common.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+#include <sleep_def.h>
+
+#ifdef MT_SPM_USING_BAKERY_LOCK
+DEFINE_BAKERY_LOCK(spm_lock);
+#define plat_spm_lock_init() bakery_lock_init(&spm_lock)
+#else
+spinlock_t spm_lock;
+#define plat_spm_lock_init()
+#endif
+
+/* CLK_SCP_CFG_0 */
+#define CLK_SCP_CFG_0 (TOPCKGEN_BASE + 0x264)
+#define SPM_CK_CONTROL_EN 0x7FF
+
+struct mt_resource_constraint plat_constraint_bus26m = {
+ .is_valid = spm_is_valid_rc_bus26m,
+ .update = spm_update_rc_bus26m,
+ .allow = spm_allow_rc_bus26m,
+ .run = spm_run_rc_bus26m,
+ .reset = spm_reset_rc_bus26m,
+};
+
+struct mt_resource_constraint plat_constraint_syspll = {
+ .is_valid = spm_is_valid_rc_syspll,
+ .update = spm_update_rc_syspll,
+ .allow = spm_allow_rc_syspll,
+ .run = spm_run_rc_syspll,
+ .reset = spm_reset_rc_syspll,
+};
+
+struct mt_resource_constraint plat_constraint_dram = {
+ .is_valid = spm_is_valid_rc_dram,
+ .update = spm_update_rc_dram,
+ .allow = spm_allow_rc_dram,
+ .run = spm_run_rc_dram,
+ .reset = spm_reset_rc_dram,
+};
+
+struct mt_resource_constraint plat_constraint_cpu = {
+ .is_valid = spm_is_valid_rc_cpu_buck_ldo,
+ .update = NULL,
+ .allow = spm_allow_rc_cpu_buck_ldo,
+ .run = spm_run_rc_cpu_buck_ldo,
+ .reset = spm_reset_rc_cpu_buck_ldo,
+};
+
+struct mt_resource_constraint *plat_constraints[] = {
+ &plat_constraint_bus26m,
+ &plat_constraint_syspll,
+ &plat_constraint_dram,
+ &plat_constraint_cpu,
+ NULL,
+};
+
+struct mt_resource_manager plat_mt8195_rm = {
+ .update = mt_spm_cond_update,
+ .consts = plat_constraints,
+};
+
+void spm_boot_init(void)
+{
+ NOTICE("MT8195 %s\n", __func__);
+ /* switch ck_off/axi_26m control to SPM */
+ mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_CONTROL_EN);
+
+ plat_spm_lock_init();
+ mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
+ mt_lp_rm_register(&plat_mt8195_rm);
+ mt_spm_idle_generic_init();
+ mt_spm_suspend_init();
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm.h b/plat/mediatek/mt8195/drivers/spm/mt_spm.h
new file mode 100644
index 0000000..bc57b61
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_H
+#define MT_SPM_H
+
+#include <lib/bakery_lock.h>
+#include <lib/spinlock.h>
+
+#include <plat_mtk_lpm.h>
+
+/*
+ * ARM v8.2, the cache will turn off automatically when cpu
+ * power down. So, there is no doubt to use the spin_lock here
+ */
+#if !HW_ASSISTED_COHERENCY
+#define MT_SPM_USING_BAKERY_LOCK
+#endif
+
+#ifdef MT_SPM_USING_BAKERY_LOCK
+DECLARE_BAKERY_LOCK(spm_lock);
+#define plat_spm_lock() bakery_lock_get(&spm_lock)
+#define plat_spm_unlock() bakery_lock_release(&spm_lock)
+#else
+extern spinlock_t spm_lock;
+#define plat_spm_lock() spin_lock(&spm_lock)
+#define plat_spm_unlock() spin_unlock(&spm_lock)
+#endif
+
+#define MT_SPM_USING_SRCLKEN_RC
+
+/* spm extern operand definition */
+#define MT_SPM_EX_OP_CLR_26M_RECORD (1U << 0)
+#define MT_SPM_EX_OP_SET_WDT (1U << 1)
+#define MT_SPM_EX_OP_NON_GENERIC_RESOURCE_REQ (1U << 2)
+#define MT_SPM_EX_OP_SET_SUSPEND_MODE (1U << 3)
+#define MT_SPM_EX_OP_SET_IS_ADSP (1U << 4)
+#define MT_SPM_EX_OP_SRCLKEN_RC_BBLPM (1U << 5)
+#define MT_SPM_EX_OP_HW_S1_DETECT (1U << 6)
+
+typedef enum {
+ WR_NONE = 0,
+ WR_UART_BUSY = 1,
+ WR_ABORT = 2,
+ WR_PCM_TIMER = 3,
+ WR_WAKE_SRC = 4,
+ WR_DVFSRC = 5,
+ WR_TWAM = 6,
+ WR_PMSR = 7,
+ WR_SPM_ACK_CHK = 8,
+ WR_UNKNOWN = 9,
+} wake_reason_t;
+
+static inline void spm_lock_get(void)
+{
+ plat_spm_lock();
+}
+
+static inline void spm_lock_release(void)
+{
+ plat_spm_unlock();
+}
+
+extern void spm_boot_init(void);
+#endif /* MT_SPM_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c
new file mode 100644
index 0000000..c80faf5
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm_cond.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_constraint.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+#define MT_LP_TZ_INFRA_REG(ofs) (INFRACFG_AO_BASE + ofs)
+#define MT_LP_TZ_SPM_REG(ofs) (SPM_BASE + ofs)
+#define MT_LP_TZ_TOPCK_REG(ofs) (TOPCKGEN_BASE + ofs)
+#define MT_LP_TZ_APMIXEDSYS(ofs) (APMIXEDSYS + ofs)
+#define MT_LP_TZ_VPPSYS0_REG(ofs) (VPPSYS0_BASE + ofs)
+#define MT_LP_TZ_VPPSYS1_REG(ofs) (VPPSYS1_BASE + ofs)
+#define MT_LP_TZ_VDOSYS0_REG(ofs) (VDOSYS0_BASE + ofs)
+#define MT_LP_TZ_VDOSYS1_REG(ofs) (VDOSYS1_BASE + ofs)
+#define MT_LP_TZ_PERI_AO_REG(ofs) (PERICFG_AO_BASE + ofs)
+
+#define SPM_PWR_STATUS MT_LP_TZ_SPM_REG(0x016C)
+#define SPM_PWR_STATUS_2ND MT_LP_TZ_SPM_REG(0x0170)
+#define INFRA_SW_CG0 MT_LP_TZ_INFRA_REG(0x0094)
+#define INFRA_SW_CG1 MT_LP_TZ_INFRA_REG(0x0090)
+#define INFRA_SW_CG2 MT_LP_TZ_INFRA_REG(0x00AC)
+#define INFRA_SW_CG3 MT_LP_TZ_INFRA_REG(0x00C8)
+#define INFRA_SW_CG4 MT_LP_TZ_INFRA_REG(0x00E8)
+#define TOP_SW_I2C_CG MT_LP_TZ_TOPCK_REG(0x00BC)
+#define PERI_SW_CG0 MT_LP_TZ_PERI_AO_REG(0x0018)
+#define VPPSYS0_SW_CG0 MT_LP_TZ_VPPSYS0_REG(0x0020)
+#define VPPSYS0_SW_CG1 MT_LP_TZ_VPPSYS0_REG(0x002C)
+#define VPPSYS0_SW_CG2 MT_LP_TZ_VPPSYS0_REG(0x0038)
+#define VPPSYS1_SW_CG0 MT_LP_TZ_VPPSYS1_REG(0x0100)
+#define VPPSYS1_SW_CG1 MT_LP_TZ_VPPSYS1_REG(0x0110)
+#define VDOSYS0_SW_CG0 MT_LP_TZ_VDOSYS0_REG(0x0100)
+#define VDOSYS0_SW_CG1 MT_LP_TZ_VDOSYS0_REG(0x0110)
+#define VDOSYS1_SW_CG0 MT_LP_TZ_VDOSYS1_REG(0x0100)
+#define VDOSYS1_SW_CG1 MT_LP_TZ_VDOSYS1_REG(0x0120)
+#define VDOSYS1_SW_CG2 MT_LP_TZ_VDOSYS1_REG(0x0130)
+
+/***********************************************************
+ * Check clkmux registers
+ ***********************************************************/
+#define CLK_CFG(id) MT_LP_TZ_TOPCK_REG(0x98 + id * 0x10)
+#define PDN_CHECK BIT(7)
+#define CLK_CHECK BIT(31)
+
+enum {
+ CLKMUX_DISP = 0,
+ NF_CLKMUX,
+};
+
+static bool is_clkmux_pdn(unsigned int clkmux_id)
+{
+ unsigned int reg, val, idx;
+
+ if ((clkmux_id & CLK_CHECK) != 0U) {
+ clkmux_id = (clkmux_id & ~CLK_CHECK);
+ reg = clkmux_id / 4U;
+ val = mmio_read_32(CLK_CFG(reg));
+ idx = clkmux_id % 4U;
+ val = (val >> (idx * 8U)) & PDN_CHECK;
+ return (val != 0U);
+ }
+
+ return false;
+}
+
+static struct mt_spm_cond_tables spm_cond_t;
+
+struct idle_cond_info {
+ unsigned int subsys_mask;
+ uintptr_t addr;
+ bool bBitflip;
+ unsigned int clkmux_id;
+};
+
+#define IDLE_CG(mask, addr, bitflip, clkmux) \
+ {mask, (uintptr_t)addr, bitflip, clkmux}
+
+static struct idle_cond_info idle_cg_info[PLAT_SPM_COND_MAX] = {
+ IDLE_CG(0xffffffff, SPM_PWR_STATUS, false, 0U),
+ IDLE_CG(0xffffffff, INFRA_SW_CG0, true, 0U),
+ IDLE_CG(0xffffffff, INFRA_SW_CG1, true, 0U),
+ IDLE_CG(0xffffffff, INFRA_SW_CG2, true, 0U),
+ IDLE_CG(0xffffffff, INFRA_SW_CG3, true, 0U),
+ IDLE_CG(0xffffffff, INFRA_SW_CG4, true, 0U),
+ IDLE_CG(0xffffffff, PERI_SW_CG0, true, 0U),
+ IDLE_CG(0x00000800, VPPSYS0_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00000800, VPPSYS0_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00000800, VPPSYS0_SW_CG2, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00001000, VPPSYS1_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00001000, VPPSYS1_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00002000, VDOSYS0_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00002000, VDOSYS0_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00004000, VDOSYS1_SW_CG0, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00004000, VDOSYS1_SW_CG1, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00004000, VDOSYS1_SW_CG2, true, (CLK_CHECK|CLKMUX_DISP)),
+ IDLE_CG(0x00000080, TOP_SW_I2C_CG, true, (CLK_CHECK|CLKMUX_DISP)),
+};
+
+/***********************************************************
+ * Check pll idle condition
+ ***********************************************************/
+#define PLL_MFGPLL MT_LP_TZ_APMIXEDSYS(0x340)
+#define PLL_MMPLL MT_LP_TZ_APMIXEDSYS(0x0E0)
+#define PLL_UNIVPLL MT_LP_TZ_APMIXEDSYS(0x1F0)
+#define PLL_MSDCPLL MT_LP_TZ_APMIXEDSYS(0x710)
+#define PLL_TVDPLL MT_LP_TZ_APMIXEDSYS(0x380)
+
+unsigned int mt_spm_cond_check(int state_id,
+ const struct mt_spm_cond_tables *src,
+ const struct mt_spm_cond_tables *dest,
+ struct mt_spm_cond_tables *res)
+{
+ unsigned int blocked = 0U, i;
+ bool is_system_suspend = IS_PLAT_SUSPEND_ID(state_id);
+
+ if ((src == NULL) || (dest == NULL)) {
+ return SPM_COND_CHECK_FAIL;
+ }
+
+ for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
+ if (res != NULL) {
+ res->table_cg[i] =
+ (src->table_cg[i] & dest->table_cg[i]);
+
+ if (is_system_suspend && (res->table_cg[i] != 0U)) {
+ INFO("suspend: %s block[%u](0x%lx) = 0x%08x\n",
+ dest->name, i, idle_cg_info[i].addr,
+ res->table_cg[i]);
+ }
+
+ if (res->table_cg[i] != 0U) {
+ blocked |= (1U << i);
+ }
+ } else if ((src->table_cg[i] & dest->table_cg[i]) != 0U) {
+ blocked |= (1U << i);
+ break;
+ }
+ }
+
+ if (res != NULL) {
+ res->table_pll = (src->table_pll & dest->table_pll);
+
+ if (res->table_pll != 0U) {
+ blocked |=
+ (res->table_pll << SPM_COND_BLOCKED_PLL_IDX) |
+ SPM_COND_CHECK_BLOCKED_PLL;
+ }
+ } else if ((src->table_pll & dest->table_pll) != 0U) {
+ blocked |= SPM_COND_CHECK_BLOCKED_PLL;
+ }
+
+ if (is_system_suspend && (blocked != 0U)) {
+ INFO("suspend: %s blocked=0x%08x\n", dest->name, blocked);
+ }
+
+ return blocked;
+}
+
+#define IS_MT_SPM_PWR_OFF(mask) \
+ (((mmio_read_32(SPM_PWR_STATUS) & mask) == 0U) && \
+ ((mmio_read_32(SPM_PWR_STATUS_2ND) & mask) == 0U))
+
+int mt_spm_cond_update(struct mt_resource_constraint **con,
+ int stateid, void *priv)
+{
+ int res;
+ uint32_t i;
+ struct mt_resource_constraint *const *rc;
+
+ /* read all cg state */
+ for (i = 0U; i < PLAT_SPM_COND_MAX; i++) {
+ spm_cond_t.table_cg[i] = 0U;
+
+ /* check mtcmos, if off set idle_value and clk to 0 disable */
+ if (IS_MT_SPM_PWR_OFF(idle_cg_info[i].subsys_mask)) {
+ continue;
+ }
+
+ /* check clkmux */
+ if (is_clkmux_pdn(idle_cg_info[i].clkmux_id)) {
+ continue;
+ }
+
+ spm_cond_t.table_cg[i] = idle_cg_info[i].bBitflip ?
+ ~mmio_read_32(idle_cg_info[i].addr) :
+ mmio_read_32(idle_cg_info[i].addr);
+ }
+
+ spm_cond_t.table_pll = 0U;
+ if ((mmio_read_32(PLL_MFGPLL) & 0x200) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MFGPLL;
+ }
+
+ if ((mmio_read_32(PLL_MMPLL) & 0x200) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MMPLL;
+ }
+
+ if ((mmio_read_32(PLL_UNIVPLL) & 0x200) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_UNIVPLL;
+ }
+
+ if ((mmio_read_32(PLL_MSDCPLL) & 0x200) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_MSDCPLL;
+ }
+
+ if ((mmio_read_32(PLL_TVDPLL) & 0x200) != 0U) {
+ spm_cond_t.table_pll |= PLL_BIT_TVDPLL;
+ }
+
+ spm_cond_t.priv = priv;
+ for (rc = con; *rc != NULL; rc++) {
+ if (((*rc)->update) == NULL) {
+ continue;
+ }
+
+ res = (*rc)->update(stateid, PLAT_RC_UPDATE_CONDITION,
+ (void const *)&spm_cond_t);
+ if (res != MT_RM_STATUS_OK) {
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h
new file mode 100644
index 0000000..e471b55
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONDIT_H
+#define MT_SPM_CONDIT_H
+
+#include <mt_lp_rm.h>
+
+enum PLAT_SPM_COND {
+ PLAT_SPM_COND_MTCMOS1 = 0,
+ PLAT_SPM_COND_CG_INFRA_0,
+ PLAT_SPM_COND_CG_INFRA_1,
+ PLAT_SPM_COND_CG_INFRA_2,
+ PLAT_SPM_COND_CG_INFRA_3,
+ PLAT_SPM_COND_CG_INFRA_4,
+ PLAT_SPM_COND_CG_PERI_SW_0,
+ PLAT_SPM_COND_CG_VPPSYS0_SW_CG_0,
+ PLAT_SPM_COND_CG_VPPSYS0_SW_CG_1,
+ PLAT_SPM_COND_CG_VPPSYS0_SW_CG_2,
+ PLAT_SPM_COND_CG_VPPSYS1_SW_CG_0,
+ PLAT_SPM_COND_CG_VPPSYS1_SW_CG_1,
+ PLAT_SPM_COND_CG_VDOSYS0_SW_CG_0,
+ PLAT_SPM_COND_CG_VDOSYS0_SW_CG_1,
+ PLAT_SPM_COND_CG_VDOSYS1_SW_CG_0,
+ PLAT_SPM_COND_CG_VDOSYS1_SW_CG_1,
+ PLAT_SPM_COND_CG_VDOSYS1_SW_CG_2,
+ PLAT_SPM_COND_CG_I2C_SW_CG,
+ PLAT_SPM_COND_MAX,
+};
+
+enum PLAT_SPM_COND_PLL {
+ PLAT_SPM_COND_PLL_UNIVPLL = 0,
+ PLAT_SPM_COND_PLL_MFGPLL,
+ PLAT_SPM_COND_PLL_MSDCPLL,
+ PLAT_SPM_COND_PLL_TVDPLL,
+ PLAT_SPM_COND_PLL_MMPLL,
+ PLAT_SPM_COND_PLL_MAX,
+};
+
+#define PLL_BIT_MFGPLL BIT(PLAT_SPM_COND_PLL_MFGPLL)
+#define PLL_BIT_MMPLL BIT(PLAT_SPM_COND_PLL_MMPLL)
+#define PLL_BIT_UNIVPLL BIT(PLAT_SPM_COND_PLL_UNIVPLL)
+#define PLL_BIT_MSDCPLL BIT(PLAT_SPM_COND_PLL_MSDCPLL)
+#define PLL_BIT_TVDPLL BIT(PLAT_SPM_COND_PLL_TVDPLL)
+
+/* Definition about SPM_COND_CHECK_BLOCKED
+ * bit [00 ~ 17]: cg blocking index
+ * bit [18 ~ 29]: pll blocking index
+ * bit [30] : pll blocking information
+ * bit [31] : idle condition check fail
+ */
+#define SPM_COND_BLOCKED_CG_IDX U(0)
+#define SPM_COND_BLOCKED_PLL_IDX U(18)
+#define SPM_COND_CHECK_BLOCKED_PLL BIT(30)
+#define SPM_COND_CHECK_FAIL BIT(31)
+
+struct mt_spm_cond_tables {
+ char *name;
+ unsigned int table_cg[PLAT_SPM_COND_MAX];
+ unsigned int table_pll;
+ void *priv;
+};
+
+extern unsigned int mt_spm_cond_check(int state_id,
+ const struct mt_spm_cond_tables *src,
+ const struct mt_spm_cond_tables *dest,
+ struct mt_spm_cond_tables *res);
+extern int mt_spm_cond_update(struct mt_resource_constraint **con,
+ int stateid, void *priv);
+#endif /* MT_SPM_CONDIT_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c
new file mode 100644
index 0000000..7f33408
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_reg.h>
+#include <plat_mtk_lpm.h>
+#include <plat_pm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+struct wake_status spm_wakesta; /* record last wakesta */
+
+static int go_to_spm_before_wfi(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ unsigned int resource_req)
+{
+ int ret = 0;
+ struct pwr_ctrl *pwrctrl;
+ uint32_t cpu = plat_my_core_pos();
+
+ pwrctrl = spm_lp->pwrctrl;
+
+ __spm_set_cpu_status(cpu);
+ __spm_set_power_control(pwrctrl);
+ __spm_set_wakeup_event(pwrctrl);
+ __spm_set_pcm_flags(pwrctrl);
+ __spm_src_req_update(pwrctrl, resource_req);
+
+ if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
+ __spm_set_pcm_wdt(1);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
+ __spm_xo_soc_bblpm(1);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
+ spm_hw_s1_state_monitor_resume();
+ }
+
+ /* Disable auto resume by PCM in system suspend stage */
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ __spm_disable_pcm_timer();
+ __spm_set_pcm_wdt(0);
+ }
+
+ __spm_send_cpu_wakeup_event();
+
+ INFO("cpu%d: wakesrc = 0x%x, settle = 0x%x, sec = %u\n",
+ cpu, pwrctrl->wake_src, mmio_read_32(SPM_CLK_SETTLE),
+ mmio_read_32(PCM_TIMER_VAL) / 32768);
+ INFO("sw_flag = 0x%x 0x%x, req = 0x%x, pwr = 0x%x 0x%x\n",
+ pwrctrl->pcm_flags, pwrctrl->pcm_flags1,
+ mmio_read_32(SPM_SRC_REQ), mmio_read_32(PWR_STATUS),
+ mmio_read_32(PWR_STATUS_2ND));
+ INFO("cpu_pwr = 0x%x 0x%x\n", mmio_read_32(CPU_PWR_STATUS),
+ mmio_read_32(CPU_PWR_STATUS_2ND));
+
+ return ret;
+}
+
+static void go_to_spm_after_wfi(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status)
+{
+ unsigned int ext_status = 0U;
+
+ /* system watchdog will be resumed at kernel stage */
+ if ((ext_opand & MT_SPM_EX_OP_SET_WDT) != 0U) {
+ __spm_set_pcm_wdt(0);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_SRCLKEN_RC_BBLPM) != 0U) {
+ __spm_xo_soc_bblpm(0);
+ }
+
+ if ((ext_opand & MT_SPM_EX_OP_HW_S1_DETECT) != 0U) {
+ spm_hw_s1_state_monitor_pause(&ext_status);
+ }
+
+ __spm_ext_int_wakeup_req_clr();
+ __spm_get_wakeup_status(&spm_wakesta, ext_status);
+
+ if (status != NULL) {
+ *status = &spm_wakesta;
+ }
+
+ __spm_clean_after_wakeup();
+
+ if (IS_PLAT_SUSPEND_ID(state_id)) {
+ __spm_output_wake_reason(state_id, &spm_wakesta);
+ }
+}
+
+int spm_conservation(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp, unsigned int resource_req)
+{
+ if (spm_lp == NULL) {
+ return -1;
+ }
+
+ spm_lock_get();
+ go_to_spm_before_wfi(state_id, ext_opand, spm_lp, resource_req);
+ spm_lock_release();
+
+ return 0;
+}
+
+void spm_conservation_finish(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status)
+{
+ spm_lock_get();
+ go_to_spm_after_wfi(state_id, ext_opand, spm_lp, status);
+ spm_lock_release();
+}
+
+int spm_conservation_get_result(struct wake_status **res)
+{
+ if (res == NULL) {
+ return -1;
+ }
+
+ *res = &spm_wakesta;
+
+ return 0;
+}
+
+#define GPIO_BANK (GPIO_BASE + 0x6F0)
+#define TRAP_UFS_FIRST BIT(11) /* bit 11, 0: UFS, 1: eMMC */
+
+void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl)
+{
+ if (pwrctrl == NULL) {
+ return;
+ }
+
+ /* For ufs, emmc storage type */
+ if ((mmio_read_32(GPIO_BANK) & TRAP_UFS_FIRST) != 0U) {
+ /* If eMMC is used, mask UFS req */
+ pwrctrl->reg_ufs_srcclkena_mask_b = 0;
+ pwrctrl->reg_ufs_infra_req_mask_b = 0;
+ pwrctrl->reg_ufs_apsrc_req_mask_b = 0;
+ pwrctrl->reg_ufs_vrf18_req_mask_b = 0;
+ pwrctrl->reg_ufs_ddr_en_mask_b = 0;
+ }
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h
new file mode 100644
index 0000000..aa627e7
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONSERVATION_H
+#define MT_SPM_CONSERVATION_H
+
+#include <mt_spm_internal.h>
+
+extern int spm_conservation(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ unsigned int resource_req);
+extern void spm_conservation_finish(int state_id, unsigned int ext_opand,
+ struct spm_lp_scen *spm_lp,
+ struct wake_status **status);
+extern int spm_conservation_get_result(struct wake_status **res);
+extern void spm_conservation_pwrctrl_init(struct pwr_ctrl *pwrctrl);
+#endif /* MT_SPM_CONSERVATION_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h
new file mode 100644
index 0000000..944c227
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_CONSTRAINT_H
+#define MT_SPM_CONSTRAINT_H
+
+#include <mt_lp_rm.h>
+
+#define MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF (1U << 0)
+#define MT_RM_CONSTRAINT_ALLOW_DRAM_S0 (1U << 1)
+#define MT_RM_CONSTRAINT_ALLOW_DRAM_S1 (1U << 2)
+#define MT_RM_CONSTRAINT_ALLOW_VCORE_LP (1U << 3)
+#define MT_RM_CONSTRAINT_ALLOW_INFRA_PDN (1U << 4)
+#define MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF (1U << 5)
+#define MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND (1U << 6)
+#define MT_RM_CONSTRAINT_ALLOW_BBLPM (1U << 7)
+#define MT_RM_CONSTRAINT_ALLOW_XO_UFS (1U << 8)
+#define MT_RM_CONSTRAINT_ALLOW_GPS_STATE (1U << 9)
+#define MT_RM_CONSTRAINT_ALLOW_LVTS_STATE (1U << 10)
+
+#define MT_SPM_RC_INVALID 0x0
+#define MT_SPM_RC_VALID_SW (1U << 0)
+#define MT_SPM_RC_VALID_FW (1U << 1)
+#define MT_SPM_RC_VALID_RESIDNECY (1U << 2)
+#define MT_SPM_RC_VALID_COND_CHECK (1U << 3)
+#define MT_SPM_RC_VALID_COND_LATCH (1U << 4)
+#define MT_SPM_RC_VALID_UFS_H8 (1U << 5)
+#define MT_SPM_RC_VALID_FLIGHTMODE (1U << 6)
+#define MT_SPM_RC_VALID_XSOC_BBLPM (1U << 7)
+#define MT_SPM_RC_VALID_TRACE_EVENT (1U << 8)
+
+#define MT_SPM_RC_VALID (MT_SPM_RC_VALID_SW)
+
+#define IS_MT_RM_RC_READY(status) \
+ ((status & MT_SPM_RC_VALID) == MT_SPM_RC_VALID)
+
+#define MT_SPM_RC_BBLPM_MODE \
+ (MT_SPM_RC_VALID_UFS_H8 | \
+ MT_SPM_RC_VALID_FLIGHTMODE | \
+ MT_SPM_RC_VALID_XSOC_BBLPM)
+
+#define IS_MT_SPM_RC_BBLPM_MODE(st) \
+ ((st & (MT_SPM_RC_BBLPM_MODE)) == MT_SPM_RC_BBLPM_MODE)
+
+struct constraint_status {
+ uint16_t id;
+ uint16_t valid;
+ uint32_t cond_block;
+ uint32_t enter_cnt;
+ struct mt_spm_cond_tables *cond_res;
+};
+
+enum MT_SPM_RM_RC_TYPE {
+ MT_RM_CONSTRAINT_ID_BUS26M,
+ MT_RM_CONSTRAINT_ID_SYSPLL,
+ MT_RM_CONSTRAINT_ID_DRAM,
+ MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO,
+ MT_RM_CONSTRAINT_ID_ALL,
+};
+#endif /* MT_SPM_CONSTRAINT_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c
new file mode 100644
index 0000000..4bafe95
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_idle.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <plat_pm.h>
+
+#define __WAKE_SRC_FOR_IDLE_COMMON__ \
+ (R12_PCM_TIMER | \
+ R12_KP_IRQ_B | \
+ R12_APWDT_EVENT_B | \
+ R12_APXGPT1_EVENT_B | \
+ R12_CONN2AP_SPM_WAKEUP_B | \
+ R12_EINT_EVENT_B | \
+ R12_CONN_WDT_IRQ_B | \
+ R12_CCIF0_EVENT_B | \
+ R12_SSPM2SPM_WAKEUP_B | \
+ R12_SCP2SPM_WAKEUP_B | \
+ R12_ADSP2SPM_WAKEUP_B | \
+ R12_USBX_CDSC_B | \
+ R12_USBX_POWERDWN_B | \
+ R12_SYS_TIMER_EVENT_B | \
+ R12_EINT_EVENT_SECURE_B | \
+ R12_AFE_IRQ_MCU_B | \
+ R12_SYS_CIRQ_IRQ_B | \
+ R12_MD2AP_PEER_EVENT_B | \
+ R12_MD1_WDT_B | \
+ R12_CLDMA_EVENT_B | \
+ R12_REG_CPU_WAKEUP | \
+ R12_APUSYS_WAKE_HOST_B)
+
+#if defined(CFG_MICROTRUST_TEE_SUPPORT)
+#define WAKE_SRC_FOR_IDLE (__WAKE_SRC_FOR_IDLE_COMMON__)
+#else
+#define WAKE_SRC_FOR_IDLE \
+ (__WAKE_SRC_FOR_IDLE_COMMON__ | \
+ R12_SEJ_EVENT_B)
+#endif
+
+static struct pwr_ctrl idle_spm_pwr = {
+ .wake_src = WAKE_SRC_FOR_IDLE,
+
+ /* SPM_AP_STANDBY_CON */
+ /* [0] */
+ .reg_wfi_op = 0,
+ /* [1] */
+ .reg_wfi_type = 0,
+ /* [2] */
+ .reg_mp0_cputop_idle_mask = 0,
+ /* [3] */
+ .reg_mp1_cputop_idle_mask = 0,
+ /* [4] */
+ .reg_mcusys_idle_mask = 0,
+ /* [25] */
+ .reg_md_apsrc_1_sel = 0,
+ /* [26] */
+ .reg_md_apsrc_0_sel = 0,
+ /* [29] */
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC_REQ */
+ /* [0] */
+ .reg_spm_apsrc_req = 0,
+ /* [1] */
+ .reg_spm_f26m_req = 1,
+ /* [3] */
+ .reg_spm_infra_req = 1,
+ /* [4] */
+ .reg_spm_vrf18_req = 0,
+ /* [7] FIXME: default disable HW Auto S1 */
+ .reg_spm_ddr_en_req = 1,
+ /* [8] */
+ .reg_spm_dvfs_req = 0,
+ /* [9] */
+ .reg_spm_sw_mailbox_req = 0,
+ /* [10] */
+ .reg_spm_sspm_mailbox_req = 0,
+ /* [11] */
+ .reg_spm_adsp_mailbox_req = 0,
+ /* [12] */
+ .reg_spm_scp_mailbox_req = 0,
+
+
+ /* SPM_SRC_MASK */
+ /* [0] */
+ .reg_sspm_srcclkena_0_mask_b = 1,
+ /* [1] */
+ .reg_sspm_infra_req_0_mask_b = 1,
+ /* [2] */
+ .reg_sspm_apsrc_req_0_mask_b = 1,
+ /* [3] */
+ .reg_sspm_vrf18_req_0_mask_b = 1,
+ /* [4] */
+ .reg_sspm_ddr_en_0_mask_b = 1,
+ /* [5] */
+ .reg_scp_srcclkena_mask_b = 1,
+ /* [6] */
+ .reg_scp_infra_req_mask_b = 1,
+ /* [7] */
+ .reg_scp_apsrc_req_mask_b = 1,
+ /* [8] */
+ .reg_scp_vrf18_req_mask_b = 1,
+ /* [9] */
+ .reg_scp_ddr_en_mask_b = 1,
+ /* [10] */
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ /* [11] */
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ /* [12] */
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ /* [13] */
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ /* [14] */
+ .reg_audio_dsp_ddr_en_mask_b = 1,
+ /* [15] */
+ .reg_apu_srcclkena_mask_b = 1,
+ /* [16] */
+ .reg_apu_infra_req_mask_b = 1,
+ /* [17] */
+ .reg_apu_apsrc_req_mask_b = 1,
+ /* [18] */
+ .reg_apu_vrf18_req_mask_b = 1,
+ /* [19] */
+ .reg_apu_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_cpueb_srcclkena_mask_b = 1,
+ /* [21] */
+ .reg_cpueb_infra_req_mask_b = 1,
+ /* [22] */
+ .reg_cpueb_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_cpueb_vrf18_req_mask_b = 1,
+ /* [24] */
+ .reg_cpueb_ddr_en_mask_b = 1,
+ /* [25] */
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ /* [26] */
+ .reg_bak_psri_infra_req_mask_b = 0,
+ /* [27] */
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ /* [28] */
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ /* [29] */
+ .reg_bak_psri_ddr_en_mask_b = 0,
+
+ /* SPM_SRC2_MASK */
+ /* [0] */
+ .reg_msdc0_srcclkena_mask_b = 1,
+ /* [1] */
+ .reg_msdc0_infra_req_mask_b = 1,
+ /* [2] */
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ /* [3] */
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ /* [4] */
+ .reg_msdc0_ddr_en_mask_b = 1,
+ /* [5] */
+ .reg_msdc1_srcclkena_mask_b = 1,
+ /* [6] */
+ .reg_msdc1_infra_req_mask_b = 1,
+ /* [7] */
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ /* [8] */
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ /* [9] */
+ .reg_msdc1_ddr_en_mask_b = 1,
+ /* [10] */
+ .reg_msdc2_srcclkena_mask_b = 1,
+ /* [11] */
+ .reg_msdc2_infra_req_mask_b = 1,
+ /* [12] */
+ .reg_msdc2_apsrc_req_mask_b = 1,
+ /* [13] */
+ .reg_msdc2_vrf18_req_mask_b = 1,
+ /* [14] */
+ .reg_msdc2_ddr_en_mask_b = 1,
+ /* [15] */
+ .reg_ufs_srcclkena_mask_b = 1,
+ /* [16] */
+ .reg_ufs_infra_req_mask_b = 1,
+ /* [17] */
+ .reg_ufs_apsrc_req_mask_b = 1,
+ /* [18] */
+ .reg_ufs_vrf18_req_mask_b = 1,
+ /* [19] */
+ .reg_ufs_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_usb_srcclkena_mask_b = 1,
+ /* [21] */
+ .reg_usb_infra_req_mask_b = 1,
+ /* [22] */
+ .reg_usb_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_usb_vrf18_req_mask_b = 1,
+ /* [24] */
+ .reg_usb_ddr_en_mask_b = 1,
+ /* [25] */
+ .reg_pextp_p0_srcclkena_mask_b = 1,
+ /* [26] */
+ .reg_pextp_p0_infra_req_mask_b = 1,
+ /* [27] */
+ .reg_pextp_p0_apsrc_req_mask_b = 1,
+ /* [28] */
+ .reg_pextp_p0_vrf18_req_mask_b = 1,
+ /* [29] */
+ .reg_pextp_p0_ddr_en_mask_b = 1,
+
+ /* SPM_SRC3_MASK */
+ /* [0] */
+ .reg_pextp_p1_srcclkena_mask_b = 1,
+ /* [1] */
+ .reg_pextp_p1_infra_req_mask_b = 1,
+ /* [2] */
+ .reg_pextp_p1_apsrc_req_mask_b = 1,
+ /* [3] */
+ .reg_pextp_p1_vrf18_req_mask_b = 1,
+ /* [4] */
+ .reg_pextp_p1_ddr_en_mask_b = 1,
+ /* [5] */
+ .reg_gce0_infra_req_mask_b = 1,
+ /* [6] */
+ .reg_gce0_apsrc_req_mask_b = 1,
+ /* [7] */
+ .reg_gce0_vrf18_req_mask_b = 1,
+ /* [8] */
+ .reg_gce0_ddr_en_mask_b = 1,
+ /* [9] */
+ .reg_gce1_infra_req_mask_b = 1,
+ /* [10] */
+ .reg_gce1_apsrc_req_mask_b = 1,
+ /* [11] */
+ .reg_gce1_vrf18_req_mask_b = 1,
+ /* [12] */
+ .reg_gce1_ddr_en_mask_b = 1,
+ /* [13] */
+ .reg_spm_srcclkena_reserved_mask_b = 1,
+ /* [14] */
+ .reg_spm_infra_req_reserved_mask_b = 1,
+ /* [15] */
+ .reg_spm_apsrc_req_reserved_mask_b = 1,
+ /* [16] */
+ .reg_spm_vrf18_req_reserved_mask_b = 1,
+ /* [17] */
+ .reg_spm_ddr_en_reserved_mask_b = 1,
+ /* [18] */
+ .reg_disp0_apsrc_req_mask_b = 1,
+ /* [19] */
+ .reg_disp0_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_disp1_apsrc_req_mask_b = 1,
+ /* [21] */
+ .reg_disp1_ddr_en_mask_b = 1,
+ /* [22] */
+ .reg_disp2_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_disp2_ddr_en_mask_b = 1,
+ /* [24] */
+ .reg_disp3_apsrc_req_mask_b = 1,
+ /* [25] */
+ .reg_disp3_ddr_en_mask_b = 1,
+ /* [26] */
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ /* [27] */
+ .reg_infrasys_ddr_en_mask_b = 1,
+
+ /* [28] */
+ .reg_cg_check_srcclkena_mask_b = 1,
+ /* [29] */
+ .reg_cg_check_apsrc_req_mask_b = 1,
+ /* [30] */
+ .reg_cg_check_vrf18_req_mask_b = 1,
+ /* [31] */
+ .reg_cg_check_ddr_en_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ /* [8:0] */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x17,
+ /* [17:9] */
+ .reg_mcusys_merge_ddr_en_mask_b = 0x17,
+ /* [19:18] */
+ .reg_dramc_md32_infra_req_mask_b = 0,
+ /* [21:20] */
+ .reg_dramc_md32_vrf18_req_mask_b = 0,
+ /* [23:22] */
+ .reg_dramc_md32_ddr_en_mask_b = 0,
+ /* [24] */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK2 */
+ /* [3:0] */
+ .reg_sc_sw2spm_wakeup_mask_b = 0,
+ /* [4] */
+ .reg_sc_adsp2spm_wakeup_mask_b = 0,
+ /* [8:5] */
+ .reg_sc_sspm2spm_wakeup_mask_b = 0,
+ /* [9] */
+ .reg_sc_scp2spm_wakeup_mask_b = 0,
+ /* [10] */
+ .reg_csyspwrup_ack_mask = 0,
+ /* [11] */
+ .reg_csyspwrup_req_mask = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ /* [31:0] */
+ .reg_wakeup_event_mask = 0xC1282203,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ /* [31:0] */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+};
+
+struct spm_lp_scen idle_spm_lp = {
+ .pwrctrl = &idle_spm_pwr,
+};
+
+int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand,
+ spm_idle_conduct fn)
+{
+ unsigned int src_req = 0;
+
+ if (fn != NULL) {
+ fn(&idle_spm_lp, &src_req);
+ }
+
+ return spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req);
+}
+void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status)
+{
+ spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status);
+}
+
+void mt_spm_idle_generic_init(void)
+{
+ spm_conservation_pwrctrl_init(idle_spm_lp.pwrctrl);
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h
new file mode 100644
index 0000000..7f6fb0c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_IDLE_H
+#define MT_SPM_IDLE_H
+
+typedef void (*spm_idle_conduct)(struct spm_lp_scen *spm_lp,
+ unsigned int *resource_req);
+int mt_spm_idle_generic_enter(int state_id, unsigned int ext_opand,
+ spm_idle_conduct fn);
+void mt_spm_idle_generic_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status);
+void mt_spm_idle_generic_init(void);
+#endif /* MT_SPM_IDLE_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c
new file mode 100644
index 0000000..2647d9f
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <assert.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <platform_def.h>
+#include <plat_pm.h>
+
+/**************************************
+ * Define and Declare
+ **************************************/
+#define ROOT_CORE_ADDR_OFFSET 0x20000000
+#define SPM_WAKEUP_EVENT_MASK_CLEAN_MASK 0xefffffff
+#define SPM_INIT_DONE_US 20
+#define SPM_WAKEUP_REASON_MISSING 0xdeaddead
+
+static unsigned int mt_spm_bblpm_cnt;
+
+const char *wakeup_src_str[32] = {
+ [0] = "PCM_TIMER",
+ [1] = "RESERVED_DEBUG_B",
+ [2] = "KEYPAD",
+ [3] = "APWDT",
+ [4] = "APXGPT",
+ [5] = "MSDC",
+ [6] = "EINT",
+ [7] = "IRRX",
+ [8] = "ETHERNET_QOS",
+ [9] = "RESERVE0",
+ [10] = "SSPM",
+ [11] = "SCP",
+ [12] = "ADSP",
+ [13] = "SPM_WDT",
+ [14] = "USB_U2",
+ [15] = "USB_TOP",
+ [16] = "SYS_TIMER",
+ [17] = "EINT_SECURE",
+ [18] = "HDMI",
+ [19] = "RESERVE1",
+ [20] = "AFE",
+ [21] = "THERMAL",
+ [22] = "SYS_CIRQ",
+ [23] = "NNA2INFRA",
+ [24] = "CSYSPWREQ",
+ [25] = "RESERVE2",
+ [26] = "PCIE",
+ [27] = "SEJ",
+ [28] = "SPM_CPU_WAKEUPEVENT",
+ [29] = "APUSYS",
+ [30] = "RESERVE3",
+ [31] = "RESERVE4",
+};
+
+/**************************************
+ * Function and API
+ **************************************/
+
+wake_reason_t __spm_output_wake_reason(int state_id,
+ const struct wake_status *wakesta)
+{
+ uint32_t i, bk_vtcxo_dur, spm_26m_off_pct = 0U;
+ char *spm_26m_sta = NULL;
+ wake_reason_t wr = WR_UNKNOWN;
+
+ if (wakesta == NULL) {
+ return WR_UNKNOWN;
+ }
+
+ spm_26m_sta = ((wakesta->debug_flag & SPM_DBG_DEBUG_IDX_26M_SLEEP) == 0U) ? "on" : "off";
+
+ if (wakesta->abort != 0U) {
+ ERROR("spmfw flow is aborted: 0x%x, timer_out = %u, 26M(%s)\n",
+ wakesta->abort, wakesta->timer_out, spm_26m_sta);
+ } else if (wakesta->r12 == SPM_WAKEUP_REASON_MISSING) {
+ WARN("cannot find wake up reason, timer_out = %u, 26M(%s)\n",
+ wakesta->timer_out, spm_26m_sta);
+ } else {
+ for (i = 0U; i < 32U; i++) {
+ if ((wakesta->r12 & (1U << i)) != 0U) {
+ INFO("wake up by %s, timer_out = %u, 26M(%s)\n",
+ wakeup_src_str[i], wakesta->timer_out, spm_26m_sta);
+ wr = WR_WAKE_SRC;
+ break;
+ }
+ }
+ }
+
+ INFO("r12 = 0x%x, r12_ext = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n",
+ wakesta->r12, wakesta->r12_ext, wakesta->r13, wakesta->debug_flag,
+ wakesta->debug_flag1);
+ INFO("raw_sta = 0x%x 0x%x 0x%x, idle_sta = 0x%x, cg_check_sta = 0x%x\n",
+ wakesta->raw_sta, wakesta->md32pcm_wakeup_sta,
+ wakesta->md32pcm_event_sta, wakesta->idle_sta,
+ wakesta->cg_check_sta);
+ INFO("req_sta = 0x%x 0x%x 0x%x 0x%x 0x%x, isr = 0x%x\n",
+ wakesta->req_sta0, wakesta->req_sta1, wakesta->req_sta2,
+ wakesta->req_sta3, wakesta->req_sta4, wakesta->isr);
+ INFO("rt_req_sta0 = 0x%x, rt_req_sta1 = 0x%x, rt_req_sta2 = 0x%x\n",
+ wakesta->rt_req_sta0, wakesta->rt_req_sta1, wakesta->rt_req_sta2);
+ INFO("rt_req_sta3 = 0x%x, dram_sw_con_3 = 0x%x, raw_ext_sta = 0x%x\n",
+ wakesta->rt_req_sta3, wakesta->rt_req_sta4, wakesta->raw_ext_sta);
+ INFO("wake_misc = 0x%x, pcm_flag = 0x%x 0x%x 0x%x 0x%x, req = 0x%x\n",
+ wakesta->wake_misc, wakesta->sw_flag0, wakesta->sw_flag1,
+ wakesta->b_sw_flag0, wakesta->b_sw_flag1, wakesta->src_req);
+ INFO("clk_settle = 0x%x, wlk_cntcv_l = 0x%x, wlk_cntcv_h = 0x%x\n",
+ wakesta->clk_settle, mmio_read_32(SYS_TIMER_VALUE_L),
+ mmio_read_32(SYS_TIMER_VALUE_H));
+
+ if (wakesta->timer_out != 0U) {
+ bk_vtcxo_dur = mmio_read_32(SPM_BK_VTCXO_DUR);
+ spm_26m_off_pct = (100 * bk_vtcxo_dur) / wakesta->timer_out;
+ INFO("spm_26m_off_pct = %u\n", spm_26m_off_pct);
+ }
+
+ return wr;
+}
+
+void __spm_set_cpu_status(unsigned int cpu)
+{
+ uint32_t root_core_addr;
+
+ if (cpu < 8U) {
+ mmio_write_32(ROOT_CPUTOP_ADDR, (1U << cpu));
+ root_core_addr = SPM_CPU0_PWR_CON + (cpu * 0x4);
+ root_core_addr += ROOT_CORE_ADDR_OFFSET;
+ mmio_write_32(ROOT_CORE_ADDR, root_core_addr);
+ /* Notify MCUPM that preferred cpu wakeup */
+ mmio_write_32(MCUPM_MBOX_WAKEUP_CPU, cpu);
+ } else {
+ ERROR("%s: error cpu number %d\n", __func__, cpu);
+ }
+}
+
+void __spm_src_req_update(const struct pwr_ctrl *pwrctrl,
+ unsigned int resource_usage)
+{
+ uint8_t apsrc_req = ((resource_usage & MT_SPM_DRAM_S0) != 0U) ?
+ 1 : pwrctrl->reg_spm_apsrc_req;
+ uint8_t ddr_en_req = ((resource_usage & MT_SPM_DRAM_S1) != 0U) ?
+ 1 : pwrctrl->reg_spm_ddr_en_req;
+ uint8_t vrf18_req = ((resource_usage & MT_SPM_SYSPLL) != 0U) ?
+ 1 : pwrctrl->reg_spm_vrf18_req;
+ uint8_t infra_req = ((resource_usage & MT_SPM_INFRA) != 0U) ?
+ 1 : pwrctrl->reg_spm_infra_req;
+ uint8_t f26m_req = ((resource_usage &
+ (MT_SPM_26M | MT_SPM_XO_FPM)) != 0U) ?
+ 1 : pwrctrl->reg_spm_f26m_req;
+
+ mmio_write_32(SPM_SRC_REQ,
+ ((apsrc_req & 0x1) << 0) |
+ ((f26m_req & 0x1) << 1) |
+ ((infra_req & 0x1) << 3) |
+ ((vrf18_req & 0x1) << 4) |
+ ((ddr_en_req & 0x1) << 7) |
+ ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
+ ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
+ ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
+ ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
+ ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
+}
+
+void __spm_set_power_control(const struct pwr_ctrl *pwrctrl)
+{
+ /* Auto-gen Start */
+
+ /* SPM_AP_STANDBY_CON */
+ mmio_write_32(SPM_AP_STANDBY_CON,
+ ((pwrctrl->reg_wfi_op & 0x1) << 0) |
+ ((pwrctrl->reg_wfi_type & 0x1) << 1) |
+ ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) |
+ ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) |
+ ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) |
+ ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) |
+ ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) |
+ ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29));
+
+ /* SPM_SRC_REQ */
+ mmio_write_32(SPM_SRC_REQ,
+ ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) |
+ ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) |
+ ((pwrctrl->reg_spm_infra_req & 0x1) << 3) |
+ ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) |
+ ((pwrctrl->reg_spm_ddr_en_req & 0x1) << 7) |
+ ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
+ ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
+ ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
+ ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
+ ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
+
+ /* SPM_SRC_MASK */
+ mmio_write_32(SPM_SRC_MASK,
+ ((pwrctrl->reg_sspm_srcclkena_0_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_sspm_infra_req_0_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_sspm_apsrc_req_0_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_sspm_vrf18_req_0_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_sspm_ddr_en_0_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_scp_ddr_en_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_audio_dsp_ddr_en_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_apu_ddr_en_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_cpueb_srcclkena_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_cpueb_infra_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_cpueb_apsrc_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_cpueb_vrf18_req_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_cpueb_ddr_en_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_bak_psri_ddr_en_mask_b & 0x1) << 29));
+
+ /* SPM_SRC2_MASK */
+ mmio_write_32(SPM_SRC2_MASK,
+ ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_msdc0_ddr_en_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_msdc1_ddr_en_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_msdc2_ddr_en_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_ufs_ddr_en_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_usb_srcclkena_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_usb_infra_req_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_usb_apsrc_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_usb_vrf18_req_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_usb_ddr_en_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_pextp_p0_srcclkena_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_pextp_p0_infra_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_pextp_p0_apsrc_req_mask_b & 0x1) << 27) |
+ ((pwrctrl->reg_pextp_p0_vrf18_req_mask_b & 0x1) << 28) |
+ ((pwrctrl->reg_pextp_p0_ddr_en_mask_b & 0x1) << 29));
+
+ /* SPM_SRC3_MASK */
+ mmio_write_32(SPM_SRC3_MASK,
+ ((pwrctrl->reg_pextp_p1_srcclkena_mask_b & 0x1) << 0) |
+ ((pwrctrl->reg_pextp_p1_infra_req_mask_b & 0x1) << 1) |
+ ((pwrctrl->reg_pextp_p1_apsrc_req_mask_b & 0x1) << 2) |
+ ((pwrctrl->reg_pextp_p1_vrf18_req_mask_b & 0x1) << 3) |
+ ((pwrctrl->reg_pextp_p1_ddr_en_mask_b & 0x1) << 4) |
+ ((pwrctrl->reg_gce0_infra_req_mask_b & 0x1) << 5) |
+ ((pwrctrl->reg_gce0_apsrc_req_mask_b & 0x1) << 6) |
+ ((pwrctrl->reg_gce0_vrf18_req_mask_b & 0x1) << 7) |
+ ((pwrctrl->reg_gce0_ddr_en_mask_b & 0x1) << 8) |
+ ((pwrctrl->reg_gce1_infra_req_mask_b & 0x1) << 9) |
+ ((pwrctrl->reg_gce1_apsrc_req_mask_b & 0x1) << 10) |
+ ((pwrctrl->reg_gce1_vrf18_req_mask_b & 0x1) << 11) |
+ ((pwrctrl->reg_gce1_ddr_en_mask_b & 0x1) << 12) |
+ ((pwrctrl->reg_spm_srcclkena_reserved_mask_b & 0x1) << 13) |
+ ((pwrctrl->reg_spm_infra_req_reserved_mask_b & 0x1) << 14) |
+ ((pwrctrl->reg_spm_apsrc_req_reserved_mask_b & 0x1) << 15) |
+ ((pwrctrl->reg_spm_vrf18_req_reserved_mask_b & 0x1) << 16) |
+ ((pwrctrl->reg_spm_ddr_en_reserved_mask_b & 0x1) << 17) |
+ ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 18) |
+ ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 19) |
+ ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 20) |
+ ((pwrctrl->reg_disp1_ddr_en_mask_b & 0x1) << 21) |
+ ((pwrctrl->reg_disp2_apsrc_req_mask_b & 0x1) << 22) |
+ ((pwrctrl->reg_disp2_ddr_en_mask_b & 0x1) << 23) |
+ ((pwrctrl->reg_disp3_apsrc_req_mask_b & 0x1) << 24) |
+ ((pwrctrl->reg_disp3_ddr_en_mask_b & 0x1) << 25) |
+ ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 26) |
+ ((pwrctrl->reg_infrasys_ddr_en_mask_b & 0x1) << 27));
+
+ /* Mask MCUSYS request since SOC HW would check it */
+ mmio_write_32(SPM_SRC4_MASK, 0x1fc0000);
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK,
+ ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0));
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK,
+ ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0));
+
+ /* Auto-gen End */
+}
+
+void __spm_disable_pcm_timer(void)
+{
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY);
+}
+
+void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
+{
+ uint32_t val, mask;
+
+ /* toggle event counter clear */
+ mmio_setbits_32(PCM_CON1,
+ SPM_REGWR_CFG_KEY | SPM_EVENT_COUNTER_CLR_LSB);
+
+ /* toggle for reset SYS TIMER start point */
+ mmio_setbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
+
+ if (pwrctrl->timer_val_cust == 0U) {
+ val = pwrctrl->timer_val;
+ } else {
+ val = pwrctrl->timer_val_cust;
+ }
+
+ mmio_write_32(PCM_TIMER_VAL, val);
+ mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | RG_PCM_TIMER_EN_LSB);
+
+ /* unmask AP wakeup source */
+ if (pwrctrl->wake_src_cust == 0U) {
+ mask = pwrctrl->wake_src;
+ } else {
+ mask = pwrctrl->wake_src_cust;
+ }
+
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask);
+
+ /* unmask SPM ISR (keep TWAM setting) */
+ mmio_setbits_32(SPM_IRQ_MASK, ISRM_RET_IRQ_AUX);
+
+ /* toggle event counter clear */
+ mmio_clrsetbits_32(PCM_CON1, SPM_EVENT_COUNTER_CLR_LSB,
+ SPM_REGWR_CFG_KEY);
+ /* toggle for reset SYS TIMER start point */
+ mmio_clrbits_32(SYS_TIMER_CON, SYS_TIMER_START_EN_LSB);
+}
+
+void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl)
+{
+ /* set PCM flags and data */
+ if (pwrctrl->pcm_flags_cust_clr != 0U) {
+ pwrctrl->pcm_flags &= ~pwrctrl->pcm_flags_cust_clr;
+ }
+
+ if (pwrctrl->pcm_flags_cust_set != 0U) {
+ pwrctrl->pcm_flags |= pwrctrl->pcm_flags_cust_set;
+ }
+
+ if (pwrctrl->pcm_flags1_cust_clr != 0U) {
+ pwrctrl->pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr;
+ }
+
+ if (pwrctrl->pcm_flags1_cust_set != 0U) {
+ pwrctrl->pcm_flags1 |= pwrctrl->pcm_flags1_cust_set;
+ }
+
+ mmio_write_32(SPM_SW_FLAG_0, pwrctrl->pcm_flags);
+ mmio_write_32(SPM_SW_FLAG_1, pwrctrl->pcm_flags1);
+ mmio_write_32(SPM_SW_RSV_7, pwrctrl->pcm_flags);
+ mmio_write_32(SPM_SW_RSV_8, pwrctrl->pcm_flags1);
+}
+
+void __spm_get_wakeup_status(struct wake_status *wakesta,
+ unsigned int ext_status)
+{
+ wakesta->tr.comm.r12 = mmio_read_32(SPM_BK_WAKE_EVENT);
+ wakesta->tr.comm.timer_out = mmio_read_32(SPM_BK_PCM_TIMER);
+ wakesta->tr.comm.r13 = mmio_read_32(PCM_REG13_DATA);
+ wakesta->tr.comm.req_sta0 = mmio_read_32(SRC_REQ_STA_0);
+ wakesta->tr.comm.req_sta1 = mmio_read_32(SRC_REQ_STA_1);
+ wakesta->tr.comm.req_sta2 = mmio_read_32(SRC_REQ_STA_2);
+ wakesta->tr.comm.req_sta3 = mmio_read_32(SRC_REQ_STA_3);
+ wakesta->tr.comm.req_sta4 = mmio_read_32(SRC_REQ_STA_4);
+ wakesta->tr.comm.debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0);
+ wakesta->tr.comm.debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1);
+
+ if ((ext_status & SPM_INTERNAL_STATUS_HW_S1) != 0U) {
+ wakesta->tr.comm.debug_flag |= (SPM_DBG_DEBUG_IDX_DDREN_WAKE |
+ SPM_DBG_DEBUG_IDX_DDREN_SLEEP);
+ mmio_write_32(PCM_WDT_LATCH_SPARE_0,
+ wakesta->tr.comm.debug_flag);
+ }
+
+ wakesta->tr.comm.b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7);
+ wakesta->tr.comm.b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8);
+
+ /* record below spm info for debug */
+ wakesta->r12 = mmio_read_32(SPM_BK_WAKE_EVENT);
+ wakesta->r12_ext = mmio_read_32(SPM_WAKEUP_STA);
+ wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA);
+ wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA);
+ wakesta->md32pcm_wakeup_sta = mmio_read_32(MD32PCM_WAKEUP_STA);
+ wakesta->md32pcm_event_sta = mmio_read_32(MD32PCM_EVENT_STA);
+ wakesta->src_req = mmio_read_32(SPM_SRC_REQ);
+
+ /* backup of SPM_WAKEUP_MISC */
+ wakesta->wake_misc = mmio_read_32(SPM_BK_WAKE_MISC);
+
+ /* get sleep time, backup of PCM_TIMER_OUT */
+ wakesta->timer_out = mmio_read_32(SPM_BK_PCM_TIMER);
+
+ /* get other SYS and co-clock status */
+ wakesta->r13 = mmio_read_32(PCM_REG13_DATA);
+ wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA);
+ wakesta->req_sta0 = mmio_read_32(SRC_REQ_STA_0);
+ wakesta->req_sta1 = mmio_read_32(SRC_REQ_STA_1);
+ wakesta->req_sta2 = mmio_read_32(SRC_REQ_STA_2);
+ wakesta->req_sta3 = mmio_read_32(SRC_REQ_STA_3);
+ wakesta->req_sta4 = mmio_read_32(SRC_REQ_STA_4);
+
+ /* get HW CG check status */
+ wakesta->cg_check_sta = mmio_read_32(SPM_CG_CHECK_STA);
+
+ /* get debug flag for PCM execution check */
+ wakesta->debug_flag = mmio_read_32(PCM_WDT_LATCH_SPARE_0);
+ wakesta->debug_flag1 = mmio_read_32(PCM_WDT_LATCH_SPARE_1);
+
+ /* get backup SW flag status */
+ wakesta->b_sw_flag0 = mmio_read_32(SPM_SW_RSV_7);
+ wakesta->b_sw_flag1 = mmio_read_32(SPM_SW_RSV_8);
+
+ wakesta->rt_req_sta0 = mmio_read_32(SPM_SW_RSV_2);
+ wakesta->rt_req_sta1 = mmio_read_32(SPM_SW_RSV_3);
+ wakesta->rt_req_sta2 = mmio_read_32(SPM_SW_RSV_4);
+ wakesta->rt_req_sta3 = mmio_read_32(SPM_SW_RSV_5);
+ wakesta->rt_req_sta4 = mmio_read_32(SPM_SW_RSV_6);
+
+ /* get ISR status */
+ wakesta->isr = mmio_read_32(SPM_IRQ_STA);
+
+ /* get SW flag status */
+ wakesta->sw_flag0 = mmio_read_32(SPM_SW_FLAG_0);
+ wakesta->sw_flag1 = mmio_read_32(SPM_SW_FLAG_1);
+
+ /* get CLK SETTLE */
+ wakesta->clk_settle = mmio_read_32(SPM_CLK_SETTLE);
+
+ /* check abort */
+ wakesta->abort = (wakesta->debug_flag & DEBUG_ABORT_MASK) |
+ (wakesta->debug_flag1 & DEBUG_ABORT_MASK_1);
+}
+
+void __spm_clean_after_wakeup(void)
+{
+ mmio_write_32(SPM_BK_WAKE_EVENT,
+ mmio_read_32(SPM_WAKEUP_STA) |
+ mmio_read_32(SPM_BK_WAKE_EVENT));
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0);
+
+ /*
+ * clean wakeup event raw status (for edge trigger event)
+ * bit[28] for cpu wake up event
+ */
+ mmio_write_32(SPM_WAKEUP_EVENT_MASK, SPM_WAKEUP_EVENT_MASK_CLEAN_MASK);
+
+ /* clean ISR status (except TWAM) */
+ mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
+ mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM);
+ mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL);
+}
+
+void __spm_set_pcm_wdt(int en)
+{
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_EN_LSB,
+ SPM_REGWR_CFG_KEY);
+
+ if (en == 1) {
+ mmio_clrsetbits_32(PCM_CON1, RG_PCM_WDT_WAKE_LSB,
+ SPM_REGWR_CFG_KEY);
+
+ if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX) {
+ mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX);
+ }
+
+ mmio_write_32(PCM_WDT_VAL,
+ mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
+ mmio_setbits_32(PCM_CON1,
+ SPM_REGWR_CFG_KEY | RG_PCM_WDT_EN_LSB);
+ }
+}
+
+void __spm_send_cpu_wakeup_event(void)
+{
+ /* SPM will clear SPM_CPU_WAKEUP_EVENT */
+ mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1);
+}
+
+void __spm_ext_int_wakeup_req_clr(void)
+{
+ mmio_write_32(EXT_INT_WAKEUP_REQ_CLR, mmio_read_32(ROOT_CPUTOP_ADDR));
+
+ /* Clear spm2mcupm wakeup interrupt status */
+ mmio_write_32(SPM2CPUEB_CON, 0);
+}
+
+void __spm_xo_soc_bblpm(int en)
+{
+ if (en == 1) {
+ mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG,
+ RC_SW_SRCLKEN_FPM, RC_SW_SRCLKEN_RC);
+ assert(mt_spm_bblpm_cnt == 0);
+ mt_spm_bblpm_cnt += 1;
+ } else {
+ mmio_clrsetbits_32(RC_M00_SRCLKEN_CFG,
+ RC_SW_SRCLKEN_RC, RC_SW_SRCLKEN_FPM);
+ mt_spm_bblpm_cnt -= 1;
+ }
+}
+
+void __spm_hw_s1_state_monitor(int en, unsigned int *status)
+{
+ unsigned int reg;
+
+ reg = mmio_read_32(SPM_ACK_CHK_CON_3);
+
+ if (en == 1) {
+ reg &= ~SPM_ACK_CHK_3_CON_CLR_ALL;
+ mmio_write_32(SPM_ACK_CHK_CON_3, reg);
+ reg |= SPM_ACK_CHK_3_CON_EN;
+ mmio_write_32(SPM_ACK_CHK_CON_3, reg);
+ } else {
+ if (((reg & SPM_ACK_CHK_3_CON_RESULT) != 0U) &&
+ (status != NULL)) {
+ *status |= SPM_INTERNAL_STATUS_HW_S1;
+ }
+
+ mmio_clrsetbits_32(SPM_ACK_CHK_CON_3, SPM_ACK_CHK_3_CON_EN,
+ SPM_ACK_CHK_3_CON_HW_MODE_TRIG |
+ SPM_ACK_CHK_3_CON_CLR_ALL);
+ }
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h
new file mode 100644
index 0000000..5ac7c91
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_INTERNAL_H
+#define MT_SPM_INTERNAL_H
+
+#include "mt_spm.h"
+
+/**************************************
+ * Config and Parameter
+ **************************************/
+#define POWER_ON_VAL0_DEF 0x0000F100
+#define POWER_ON_VAL1_DEF 0x80015860
+#define PCM_WDT_TIMEOUT (30 * 32768) /* 30s */
+#define PCM_TIMER_MAX (0xffffffff - PCM_WDT_TIMEOUT)
+
+/**************************************
+ * Define and Declare
+ **************************************/
+/* PCM_PWR_IO_EN */
+#define PCM_PWRIO_EN_R0 (1U << 0)
+#define PCM_PWRIO_EN_R7 (1U << 7)
+#define PCM_RF_SYNC_R0 (1U << 16)
+#define PCM_RF_SYNC_R6 (1U << 22)
+#define PCM_RF_SYNC_R7 (1U << 23)
+
+/* SPM_SWINT */
+#define PCM_SW_INT0 (1U << 0)
+#define PCM_SW_INT1 (1U << 1)
+#define PCM_SW_INT2 (1U << 2)
+#define PCM_SW_INT3 (1U << 3)
+#define PCM_SW_INT4 (1U << 4)
+#define PCM_SW_INT5 (1U << 5)
+#define PCM_SW_INT6 (1U << 6)
+#define PCM_SW_INT7 (1U << 7)
+#define PCM_SW_INT8 (1U << 8)
+#define PCM_SW_INT9 (1U << 9)
+#define PCM_SW_INT_ALL (PCM_SW_INT9 | PCM_SW_INT8 | PCM_SW_INT7 | \
+ PCM_SW_INT6 | PCM_SW_INT5 | PCM_SW_INT4 | \
+ PCM_SW_INT3 | PCM_SW_INT2 | PCM_SW_INT1 | \
+ PCM_SW_INT0)
+
+/* SPM_AP_STANDBY_CON */
+#define WFI_OP_AND 1
+#define WFI_OP_OR 0
+
+/* SPM_IRQ_MASK */
+#define ISRM_TWAM (1U << 2)
+#define ISRM_PCM_RETURN (1U << 3)
+#define ISRM_RET_IRQ0 (1U << 8)
+#define ISRM_RET_IRQ1 (1U << 9)
+#define ISRM_RET_IRQ2 (1U << 10)
+#define ISRM_RET_IRQ3 (1U << 11)
+#define ISRM_RET_IRQ4 (1U << 12)
+#define ISRM_RET_IRQ5 (1U << 13)
+#define ISRM_RET_IRQ6 (1U << 14)
+#define ISRM_RET_IRQ7 (1U << 15)
+#define ISRM_RET_IRQ8 (1U << 16)
+#define ISRM_RET_IRQ9 (1U << 17)
+#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \
+ (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \
+ (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \
+ (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \
+ (ISRM_RET_IRQ1))
+#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX)
+#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM)
+
+/* SPM_IRQ_STA */
+#define ISRS_TWAM (1U << 2)
+#define ISRS_PCM_RETURN (1U << 3)
+#define ISRC_TWAM ISRS_TWAM
+#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN
+#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM)
+
+/* SPM_WAKEUP_MISC */
+#define WAKE_MISC_GIC_WAKEUP 0x3FF
+#define WAKE_MISC_DVFSRC_IRQ DVFSRC_IRQ_LSB
+#define WAKE_MISC_REG_CPU_WAKEUP SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB
+#define WAKE_MISC_PCM_TIMER_EVENT PCM_TIMER_EVENT_LSB
+#define WAKE_MISC_PMIC_OUT_B ((1U << 19) | (1U << 20))
+#define WAKE_MISC_TWAM_IRQ_B TWAM_IRQ_B_LSB
+#define WAKE_MISC_PMSR_IRQ_B_SET0 PMSR_IRQ_B_SET0_LSB
+#define WAKE_MISC_PMSR_IRQ_B_SET1 PMSR_IRQ_B_SET1_LSB
+#define WAKE_MISC_PMSR_IRQ_B_SET2 PMSR_IRQ_B_SET2_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_0 SPM_ACK_CHK_WAKEUP_0_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_1 SPM_ACK_CHK_WAKEUP_1_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_2 SPM_ACK_CHK_WAKEUP_2_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_3 SPM_ACK_CHK_WAKEUP_3_LSB
+#define WAKE_MISC_SPM_ACK_CHK_WAKEUP_ALL SPM_ACK_CHK_WAKEUP_ALL_LSB
+#define WAKE_MISC_PMIC_IRQ_ACK PMIC_IRQ_ACK_LSB
+#define WAKE_MISC_PMIC_SCP_IRQ PMIC_SCP_IRQ_LSB
+
+/* ABORT MASK for DEBUG FOORTPRINT */
+#define DEBUG_ABORT_MASK \
+ (SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC | \
+ SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN)
+
+#define DEBUG_ABORT_MASK_1 \
+ (SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT | \
+ SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT | \
+ SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT | \
+ SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT | \
+ SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT)
+
+#define MCUPM_MBOX_WAKEUP_CPU 0x0C55FD10
+
+struct pwr_ctrl {
+ uint32_t pcm_flags;
+ uint32_t pcm_flags_cust;
+ uint32_t pcm_flags_cust_set;
+ uint32_t pcm_flags_cust_clr;
+ uint32_t pcm_flags1;
+ uint32_t pcm_flags1_cust;
+ uint32_t pcm_flags1_cust_set;
+ uint32_t pcm_flags1_cust_clr;
+ uint32_t timer_val;
+ uint32_t timer_val_cust;
+ uint32_t timer_val_ramp_en;
+ uint32_t timer_val_ramp_en_sec;
+ uint32_t wake_src;
+ uint32_t wake_src_cust;
+ uint8_t wdt_disable;
+
+ /* SPM_AP_STANDBY_CON */
+ uint8_t reg_wfi_op;
+ uint8_t reg_wfi_type;
+ uint8_t reg_mp0_cputop_idle_mask;
+ uint8_t reg_mp1_cputop_idle_mask;
+ uint8_t reg_mcusys_idle_mask;
+ uint8_t reg_md_apsrc_1_sel;
+ uint8_t reg_md_apsrc_0_sel;
+ uint8_t reg_conn_apsrc_sel;
+
+ /* SPM_SRC_REQ */
+ uint8_t reg_spm_apsrc_req;
+ uint8_t reg_spm_f26m_req;
+ uint8_t reg_spm_infra_req;
+ uint8_t reg_spm_vrf18_req;
+ uint8_t reg_spm_ddr_en_req;
+ uint8_t reg_spm_dvfs_req;
+ uint8_t reg_spm_sw_mailbox_req;
+ uint8_t reg_spm_sspm_mailbox_req;
+ uint8_t reg_spm_adsp_mailbox_req;
+ uint8_t reg_spm_scp_mailbox_req;
+
+ /* SPM_SRC_MASK */
+ uint8_t reg_sspm_srcclkena_0_mask_b;
+ uint8_t reg_sspm_infra_req_0_mask_b;
+ uint8_t reg_sspm_apsrc_req_0_mask_b;
+ uint8_t reg_sspm_vrf18_req_0_mask_b;
+ uint8_t reg_sspm_ddr_en_0_mask_b;
+ uint8_t reg_scp_srcclkena_mask_b;
+ uint8_t reg_scp_infra_req_mask_b;
+ uint8_t reg_scp_apsrc_req_mask_b;
+ uint8_t reg_scp_vrf18_req_mask_b;
+ uint8_t reg_scp_ddr_en_mask_b;
+ uint8_t reg_audio_dsp_srcclkena_mask_b;
+ uint8_t reg_audio_dsp_infra_req_mask_b;
+ uint8_t reg_audio_dsp_apsrc_req_mask_b;
+ uint8_t reg_audio_dsp_vrf18_req_mask_b;
+ uint8_t reg_audio_dsp_ddr_en_mask_b;
+ uint8_t reg_apu_srcclkena_mask_b;
+ uint8_t reg_apu_infra_req_mask_b;
+ uint8_t reg_apu_apsrc_req_mask_b;
+ uint8_t reg_apu_vrf18_req_mask_b;
+ uint8_t reg_apu_ddr_en_mask_b;
+ uint8_t reg_cpueb_srcclkena_mask_b;
+ uint8_t reg_cpueb_infra_req_mask_b;
+ uint8_t reg_cpueb_apsrc_req_mask_b;
+ uint8_t reg_cpueb_vrf18_req_mask_b;
+ uint8_t reg_cpueb_ddr_en_mask_b;
+ uint8_t reg_bak_psri_srcclkena_mask_b;
+ uint8_t reg_bak_psri_infra_req_mask_b;
+ uint8_t reg_bak_psri_apsrc_req_mask_b;
+ uint8_t reg_bak_psri_vrf18_req_mask_b;
+ uint8_t reg_bak_psri_ddr_en_mask_b;
+
+ /* SPM_SRC2_MASK */
+ uint8_t reg_msdc0_srcclkena_mask_b;
+ uint8_t reg_msdc0_infra_req_mask_b;
+ uint8_t reg_msdc0_apsrc_req_mask_b;
+ uint8_t reg_msdc0_vrf18_req_mask_b;
+ uint8_t reg_msdc0_ddr_en_mask_b;
+ uint8_t reg_msdc1_srcclkena_mask_b;
+ uint8_t reg_msdc1_infra_req_mask_b;
+ uint8_t reg_msdc1_apsrc_req_mask_b;
+ uint8_t reg_msdc1_vrf18_req_mask_b;
+ uint8_t reg_msdc1_ddr_en_mask_b;
+ uint8_t reg_msdc2_srcclkena_mask_b;
+ uint8_t reg_msdc2_infra_req_mask_b;
+ uint8_t reg_msdc2_apsrc_req_mask_b;
+ uint8_t reg_msdc2_vrf18_req_mask_b;
+ uint8_t reg_msdc2_ddr_en_mask_b;
+ uint8_t reg_ufs_srcclkena_mask_b;
+ uint8_t reg_ufs_infra_req_mask_b;
+ uint8_t reg_ufs_apsrc_req_mask_b;
+ uint8_t reg_ufs_vrf18_req_mask_b;
+ uint8_t reg_ufs_ddr_en_mask_b;
+ uint8_t reg_usb_srcclkena_mask_b;
+ uint8_t reg_usb_infra_req_mask_b;
+ uint8_t reg_usb_apsrc_req_mask_b;
+ uint8_t reg_usb_vrf18_req_mask_b;
+ uint8_t reg_usb_ddr_en_mask_b;
+ uint8_t reg_pextp_p0_srcclkena_mask_b;
+ uint8_t reg_pextp_p0_infra_req_mask_b;
+ uint8_t reg_pextp_p0_apsrc_req_mask_b;
+ uint8_t reg_pextp_p0_vrf18_req_mask_b;
+ uint8_t reg_pextp_p0_ddr_en_mask_b;
+
+ /* SPM_SRC3_MASK */
+ uint8_t reg_pextp_p1_srcclkena_mask_b;
+ uint8_t reg_pextp_p1_infra_req_mask_b;
+ uint8_t reg_pextp_p1_apsrc_req_mask_b;
+ uint8_t reg_pextp_p1_vrf18_req_mask_b;
+ uint8_t reg_pextp_p1_ddr_en_mask_b;
+ uint8_t reg_gce0_infra_req_mask_b;
+ uint8_t reg_gce0_apsrc_req_mask_b;
+ uint8_t reg_gce0_vrf18_req_mask_b;
+ uint8_t reg_gce0_ddr_en_mask_b;
+ uint8_t reg_gce1_infra_req_mask_b;
+ uint8_t reg_gce1_apsrc_req_mask_b;
+ uint8_t reg_gce1_vrf18_req_mask_b;
+ uint8_t reg_gce1_ddr_en_mask_b;
+ uint8_t reg_spm_srcclkena_reserved_mask_b;
+ uint8_t reg_spm_infra_req_reserved_mask_b;
+ uint8_t reg_spm_apsrc_req_reserved_mask_b;
+ uint8_t reg_spm_vrf18_req_reserved_mask_b;
+ uint8_t reg_spm_ddr_en_reserved_mask_b;
+ uint8_t reg_disp0_apsrc_req_mask_b;
+ uint8_t reg_disp0_ddr_en_mask_b;
+ uint8_t reg_disp1_apsrc_req_mask_b;
+ uint8_t reg_disp1_ddr_en_mask_b;
+ uint8_t reg_disp2_apsrc_req_mask_b;
+ uint8_t reg_disp2_ddr_en_mask_b;
+ uint8_t reg_disp3_apsrc_req_mask_b;
+ uint8_t reg_disp3_ddr_en_mask_b;
+ uint8_t reg_infrasys_apsrc_req_mask_b;
+ uint8_t reg_infrasys_ddr_en_mask_b;
+ uint8_t reg_cg_check_srcclkena_mask_b;
+ uint8_t reg_cg_check_apsrc_req_mask_b;
+ uint8_t reg_cg_check_vrf18_req_mask_b;
+ uint8_t reg_cg_check_ddr_en_mask_b;
+
+ /* SPM_SRC4_MASK */
+ uint32_t reg_mcusys_merge_apsrc_req_mask_b;
+ uint32_t reg_mcusys_merge_ddr_en_mask_b;
+ uint8_t reg_dramc_md32_infra_req_mask_b;
+ uint8_t reg_dramc_md32_vrf18_req_mask_b;
+ uint8_t reg_dramc_md32_ddr_en_mask_b;
+ uint8_t reg_dvfsrc_event_trigger_mask_b;
+
+ /* SPM_WAKEUP_EVENT_MASK2 */
+ uint8_t reg_sc_sw2spm_wakeup_mask_b;
+ uint8_t reg_sc_adsp2spm_wakeup_mask_b;
+ uint8_t reg_sc_sspm2spm_wakeup_mask_b;
+ uint8_t reg_sc_scp2spm_wakeup_mask_b;
+ uint8_t reg_csyspwrup_ack_mask;
+ uint8_t reg_csyspwrup_req_mask;
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ uint32_t reg_wakeup_event_mask;
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ uint32_t reg_ext_wakeup_event_mask;
+};
+
+/* code gen by spm_pwr_ctrl_atf.pl, need struct pwr_ctrl */
+enum pwr_ctrl_enum {
+ PW_PCM_FLAGS,
+ PW_PCM_FLAGS_CUST,
+ PW_PCM_FLAGS_CUST_SET,
+ PW_PCM_FLAGS_CUST_CLR,
+ PW_PCM_FLAGS1,
+ PW_PCM_FLAGS1_CUST,
+ PW_PCM_FLAGS1_CUST_SET,
+ PW_PCM_FLAGS1_CUST_CLR,
+ PW_TIMER_VAL,
+ PW_TIMER_VAL_CUST,
+ PW_TIMER_VAL_RAMP_EN,
+ PW_TIMER_VAL_RAMP_EN_SEC,
+ PW_WAKE_SRC,
+ PW_WAKE_SRC_CUST,
+ PW_WAKELOCK_TIMER_VAL,
+ PW_WDT_DISABLE,
+
+ /* SPM_CLK_CON */
+ PW_REG_SRCCLKEN0_CTL,
+ PW_REG_SRCCLKEN1_CTL,
+ PW_REG_SPM_LOCK_INFRA_DCM,
+ PW_REG_SRCCLKEN_MASK,
+ PW_REG_MD1_C32RM_EN,
+ PW_REG_MD2_C32RM_EN,
+ PW_REG_CLKSQ0_SEL_CTRL,
+ PW_REG_CLKSQ1_SEL_CTRL,
+ PW_REG_SRCCLKEN0_EN,
+ PW_REG_SRCCLKEN1_EN,
+ PW_REG_SYSCLK0_SRC_MASK_B,
+ PW_REG_SYSCLK1_SRC_MASK_B,
+
+ /* SPM_AP_STANDBY_CON */
+ PW_REG_WFI_OP,
+ PW_REG_WFI_TYPE,
+ PW_REG_MP0_CPUTOP_IDLE_MASK,
+ PW_REG_MP1_CPUTOP_IDLE_MASK,
+ PW_REG_MCUSYS_IDLE_MASK,
+ PW_REG_MD_APSRC_1_SEL,
+ PW_REG_MD_APSRC_0_SEL,
+ PW_REG_CONN_APSRC_SEL,
+
+ /* SPM_SRC_REQ */
+ PW_REG_SPM_APSRC_REQ,
+ PW_REG_SPM_F26M_REQ,
+ PW_REG_SPM_INFRA_REQ,
+ PW_REG_SPM_VRF18_REQ,
+ PW_REG_SPM_DDR_EN_REQ,
+ PW_REG_SPM_DVFS_REQ,
+ PW_REG_SPM_SW_MAILBOX_REQ,
+ PW_REG_SPM_SSPM_MAILBOX_REQ,
+ PW_REG_SPM_ADSP_MAILBOX_REQ,
+ PW_REG_SPM_SCP_MAILBOX_REQ,
+
+ /* SPM_SRC_MASK */
+ PW_REG_MD_SRCCLKENA_0_MASK_B,
+ PW_REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B,
+ PW_REG_MD_APSRC2INFRA_REQ_0_MASK_B,
+ PW_REG_MD_APSRC_REQ_0_MASK_B,
+ PW_REG_MD_VRF18_REQ_0_MASK_B,
+ PW_REG_MD_DDR_EN_0_MASK_B,
+ PW_REG_MD_SRCCLKENA_1_MASK_B,
+ PW_REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B,
+ PW_REG_MD_APSRC2INFRA_REQ_1_MASK_B,
+ PW_REG_MD_APSRC_REQ_1_MASK_B,
+ PW_REG_MD_VRF18_REQ_1_MASK_B,
+ PW_REG_MD_DDR_EN_1_MASK_B,
+ PW_REG_CONN_SRCCLKENA_MASK_B,
+ PW_REG_CONN_SRCCLKENB_MASK_B,
+ PW_REG_CONN_INFRA_REQ_MASK_B,
+ PW_REG_CONN_APSRC_REQ_MASK_B,
+ PW_REG_CONN_VRF18_REQ_MASK_B,
+ PW_REG_CONN_DDR_EN_MASK_B,
+ PW_REG_CONN_VFE28_MASK_B,
+ PW_REG_SRCCLKENI0_SRCCLKENA_MASK_B,
+ PW_REG_SRCCLKENI0_INFRA_REQ_MASK_B,
+ PW_REG_SRCCLKENI1_SRCCLKENA_MASK_B,
+ PW_REG_SRCCLKENI1_INFRA_REQ_MASK_B,
+ PW_REG_SRCCLKENI2_SRCCLKENA_MASK_B,
+ PW_REG_SRCCLKENI2_INFRA_REQ_MASK_B,
+ PW_REG_INFRASYS_APSRC_REQ_MASK_B,
+ PW_REG_INFRASYS_DDR_EN_MASK_B,
+ PW_REG_MD32_SRCCLKENA_MASK_B,
+ PW_REG_MD32_INFRA_REQ_MASK_B,
+ PW_REG_MD32_APSRC_REQ_MASK_B,
+ PW_REG_MD32_VRF18_REQ_MASK_B,
+ PW_REG_MD32_DDR_EN_MASK_B,
+
+ /* SPM_SRC2_MASK */
+ PW_REG_SCP_SRCCLKENA_MASK_B,
+ PW_REG_SCP_INFRA_REQ_MASK_B,
+ PW_REG_SCP_APSRC_REQ_MASK_B,
+ PW_REG_SCP_VRF18_REQ_MASK_B,
+ PW_REG_SCP_DDR_EN_MASK_B,
+ PW_REG_AUDIO_DSP_SRCCLKENA_MASK_B,
+ PW_REG_AUDIO_DSP_INFRA_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_APSRC_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_VRF18_REQ_MASK_B,
+ PW_REG_AUDIO_DSP_DDR_EN_MASK_B,
+ PW_REG_UFS_SRCCLKENA_MASK_B,
+ PW_REG_UFS_INFRA_REQ_MASK_B,
+ PW_REG_UFS_APSRC_REQ_MASK_B,
+ PW_REG_UFS_VRF18_REQ_MASK_B,
+ PW_REG_UFS_DDR_EN_MASK_B,
+ PW_REG_DISP0_APSRC_REQ_MASK_B,
+ PW_REG_DISP0_DDR_EN_MASK_B,
+ PW_REG_DISP1_APSRC_REQ_MASK_B,
+ PW_REG_DISP1_DDR_EN_MASK_B,
+ PW_REG_GCE_INFRA_REQ_MASK_B,
+ PW_REG_GCE_APSRC_REQ_MASK_B,
+ PW_REG_GCE_VRF18_REQ_MASK_B,
+ PW_REG_GCE_DDR_EN_MASK_B,
+ PW_REG_APU_SRCCLKENA_MASK_B,
+ PW_REG_APU_INFRA_REQ_MASK_B,
+ PW_REG_APU_APSRC_REQ_MASK_B,
+ PW_REG_APU_VRF18_REQ_MASK_B,
+ PW_REG_APU_DDR_EN_MASK_B,
+ PW_REG_CG_CHECK_SRCCLKENA_MASK_B,
+ PW_REG_CG_CHECK_APSRC_REQ_MASK_B,
+ PW_REG_CG_CHECK_VRF18_REQ_MASK_B,
+ PW_REG_CG_CHECK_DDR_EN_MASK_B,
+
+ /* SPM_SRC3_MASK */
+ PW_REG_DVFSRC_EVENT_TRIGGER_MASK_B,
+ PW_REG_SW2SPM_INT0_MASK_B,
+ PW_REG_SW2SPM_INT1_MASK_B,
+ PW_REG_SW2SPM_INT2_MASK_B,
+ PW_REG_SW2SPM_INT3_MASK_B,
+ PW_REG_SC_ADSP2SPM_WAKEUP_MASK_B,
+ PW_REG_SC_SSPM2SPM_WAKEUP_MASK_B,
+ PW_REG_SC_SCP2SPM_WAKEUP_MASK_B,
+ PW_REG_CSYSPWRREQ_MASK,
+ PW_REG_SPM_SRCCLKENA_RESERVED_MASK_B,
+ PW_REG_SPM_INFRA_REQ_RESERVED_MASK_B,
+ PW_REG_SPM_APSRC_REQ_RESERVED_MASK_B,
+ PW_REG_SPM_VRF18_REQ_RESERVED_MASK_B,
+ PW_REG_SPM_DDR_EN_RESERVED_MASK_B,
+ PW_REG_MCUPM_SRCCLKENA_MASK_B,
+ PW_REG_MCUPM_INFRA_REQ_MASK_B,
+ PW_REG_MCUPM_APSRC_REQ_MASK_B,
+ PW_REG_MCUPM_VRF18_REQ_MASK_B,
+ PW_REG_MCUPM_DDR_EN_MASK_B,
+ PW_REG_MSDC0_SRCCLKENA_MASK_B,
+ PW_REG_MSDC0_INFRA_REQ_MASK_B,
+ PW_REG_MSDC0_APSRC_REQ_MASK_B,
+ PW_REG_MSDC0_VRF18_REQ_MASK_B,
+ PW_REG_MSDC0_DDR_EN_MASK_B,
+ PW_REG_MSDC1_SRCCLKENA_MASK_B,
+ PW_REG_MSDC1_INFRA_REQ_MASK_B,
+ PW_REG_MSDC1_APSRC_REQ_MASK_B,
+ PW_REG_MSDC1_VRF18_REQ_MASK_B,
+ PW_REG_MSDC1_DDR_EN_MASK_B,
+
+ /* SPM_SRC4_MASK */
+ PW_CCIF_EVENT_MASK_B,
+ PW_REG_BAK_PSRI_SRCCLKENA_MASK_B,
+ PW_REG_BAK_PSRI_INFRA_REQ_MASK_B,
+ PW_REG_BAK_PSRI_APSRC_REQ_MASK_B,
+ PW_REG_BAK_PSRI_VRF18_REQ_MASK_B,
+ PW_REG_BAK_PSRI_DDR_EN_MASK_B,
+ PW_REG_DRAMC0_MD32_INFRA_REQ_MASK_B,
+ PW_REG_DRAMC0_MD32_VRF18_REQ_MASK_B,
+ PW_REG_DRAMC1_MD32_INFRA_REQ_MASK_B,
+ PW_REG_DRAMC1_MD32_VRF18_REQ_MASK_B,
+ PW_REG_CONN_SRCCLKENB2PWRAP_MASK_B,
+ PW_REG_DRAMC0_MD32_WAKEUP_MASK,
+ PW_REG_DRAMC1_MD32_WAKEUP_MASK,
+
+ /* SPM_SRC5_MASK */
+ PW_REG_MCUSYS_MERGE_APSRC_REQ_MASK_B,
+ PW_REG_MCUSYS_MERGE_DDR_EN_MASK_B,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ PW_REG_WAKEUP_EVENT_MASK,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ PW_REG_EXT_WAKEUP_EVENT_MASK,
+
+ PW_MAX_COUNT,
+};
+
+#define SPM_INTERNAL_STATUS_HW_S1 (1U << 0)
+#define SPM_ACK_CHK_3_SEL_HW_S1 0x00350098
+#define SPM_ACK_CHK_3_HW_S1_CNT 1
+#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG 0x800
+#define SPM_ACK_CHK_3_CON_EN 0x110
+#define SPM_ACK_CHK_3_CON_CLR_ALL 0x2
+#define SPM_ACK_CHK_3_CON_RESULT 0x8000
+
+struct wake_status_trace_comm {
+ uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */
+ uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */
+ uint32_t timer_out; /* SPM_BK_PCM_TIMER */
+ uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */
+ uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */
+ uint32_t r12; /* SPM_SW_RSV_0 */
+ uint32_t r13; /* PCM_REG13_DATA */
+ uint32_t req_sta0; /* SRC_REQ_STA_0 */
+ uint32_t req_sta1; /* SRC_REQ_STA_1 */
+ uint32_t req_sta2; /* SRC_REQ_STA_2 */
+ uint32_t req_sta3; /* SRC_REQ_STA_3 */
+ uint32_t req_sta4; /* SRC_REQ_STA_4 */
+ uint32_t raw_sta; /* SPM_WAKEUP_STA */
+ uint32_t times_h; /* timestamp high bits */
+ uint32_t times_l; /* timestamp low bits */
+ uint32_t resumetime; /* timestamp low bits */
+};
+
+struct wake_status_trace {
+ struct wake_status_trace_comm comm;
+};
+
+struct wake_status {
+ struct wake_status_trace tr;
+ uint32_t r12; /* SPM_BK_WAKE_EVENT */
+ uint32_t r12_ext; /* SPM_WAKEUP_STA */
+ uint32_t raw_sta; /* SPM_WAKEUP_STA */
+ uint32_t raw_ext_sta; /* SPM_WAKEUP_EXT_STA */
+ uint32_t md32pcm_wakeup_sta; /* MD32PCM_WAKEUP_STA */
+ uint32_t md32pcm_event_sta; /* MD32PCM_EVENT_STA */
+ uint32_t src_req; /* SPM_SRC_REQ */
+ uint32_t wake_misc; /* SPM_BK_WAKE_MISC */
+ uint32_t timer_out; /* SPM_BK_PCM_TIMER */
+ uint32_t r13; /* PCM_REG13_DATA */
+ uint32_t idle_sta; /* SUBSYS_IDLE_STA */
+ uint32_t req_sta0; /* SRC_REQ_STA_0 */
+ uint32_t req_sta1; /* SRC_REQ_STA_1 */
+ uint32_t req_sta2; /* SRC_REQ_STA_2 */
+ uint32_t req_sta3; /* SRC_REQ_STA_3 */
+ uint32_t req_sta4; /* SRC_REQ_STA_4 */
+ uint32_t cg_check_sta; /* SPM_CG_CHECK_STA */
+ uint32_t debug_flag; /* PCM_WDT_LATCH_SPARE_0 */
+ uint32_t debug_flag1; /* PCM_WDT_LATCH_SPARE_1 */
+ uint32_t b_sw_flag0; /* SPM_SW_RSV_7 */
+ uint32_t b_sw_flag1; /* SPM_SW_RSV_8 */
+ uint32_t rt_req_sta0; /* SPM_SW_RSV_2 */
+ uint32_t rt_req_sta1; /* SPM_SW_RSV_3 */
+ uint32_t rt_req_sta2; /* SPM_SW_RSV_4 */
+ uint32_t rt_req_sta3; /* SPM_SW_RSV_5 */
+ uint32_t rt_req_sta4; /* SPM_SW_RSV_6 */
+ uint32_t isr; /* SPM_IRQ_STA */
+ uint32_t sw_flag0; /* SPM_SW_FLAG_0 */
+ uint32_t sw_flag1; /* SPM_SW_FLAG_1 */
+ uint32_t clk_settle; /* SPM_CLK_SETTLE */
+ uint32_t abort;
+};
+
+struct spm_lp_scen {
+ struct pcm_desc *pcmdesc;
+ struct pwr_ctrl *pwrctrl;
+};
+
+extern struct spm_lp_scen __spm_vcorefs;
+extern void __spm_set_cpu_status(unsigned int cpu);
+extern void __spm_reset_and_init_pcm(const struct pcm_desc *pcmdesc);
+extern void __spm_kick_im_to_fetch(const struct pcm_desc *pcmdesc);
+extern void __spm_init_pcm_register(void);
+extern void __spm_src_req_update(const struct pwr_ctrl *pwrctrl,
+ unsigned int resource_usage);
+extern void __spm_set_power_control(const struct pwr_ctrl *pwrctrl);
+extern void __spm_disable_pcm_timer(void);
+extern void __spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl);
+extern void __spm_kick_pcm_to_run(struct pwr_ctrl *pwrctrl);
+extern void __spm_set_pcm_flags(struct pwr_ctrl *pwrctrl);
+extern void __spm_send_cpu_wakeup_event(void);
+extern void __spm_get_wakeup_status(struct wake_status *wakesta,
+ unsigned int ext_status);
+extern void __spm_clean_after_wakeup(void);
+extern wake_reason_t
+__spm_output_wake_reason(int state_id, const struct wake_status *wakesta);
+extern void
+__spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+ const struct pwr_ctrl *src_pwr_ctrl);
+extern void __spm_set_pcm_wdt(int en);
+extern uint32_t _spm_get_wake_period(int pwake_time, wake_reason_t last_wr);
+extern void __spm_set_fw_resume_option(struct pwr_ctrl *pwrctrl);
+extern void __spm_ext_int_wakeup_req_clr(void);
+extern void __spm_xo_soc_bblpm(int en);
+
+static inline void set_pwrctrl_pcm_flags(struct pwr_ctrl *pwrctrl,
+ uint32_t flags)
+{
+ if (pwrctrl->pcm_flags_cust == 0U) {
+ pwrctrl->pcm_flags = flags;
+ } else {
+ pwrctrl->pcm_flags = pwrctrl->pcm_flags_cust;
+ }
+}
+
+static inline void set_pwrctrl_pcm_flags1(struct pwr_ctrl *pwrctrl,
+ uint32_t flags)
+{
+ if (pwrctrl->pcm_flags1_cust == 0U) {
+ pwrctrl->pcm_flags1 = flags;
+ } else {
+ pwrctrl->pcm_flags1 = pwrctrl->pcm_flags1_cust;
+ }
+}
+
+extern void __spm_hw_s1_state_monitor(int en, unsigned int *status);
+
+static inline void spm_hw_s1_state_monitor_resume(void)
+{
+ __spm_hw_s1_state_monitor(1, NULL);
+}
+
+static inline void spm_hw_s1_state_monitor_pause(unsigned int *status)
+{
+ __spm_hw_s1_state_monitor(0, status);
+}
+#endif /* MT_SPM_INTERNAL_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c
new file mode 100644
index 0000000..9da644c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <plat_pm.h>
+#include <platform_def.h>
+
+/* PMIC_WRAP MT6359 */
+#define VCORE_BASE_UV 40000
+#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625)
+#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV)
+
+#define NR_PMIC_WRAP_CMD (NR_IDX_ALL)
+#define SPM_DATA_SHIFT 16
+
+#define BUCK_VGPU11_ELR0 0x15B4
+#define TOP_SPI_CON0 0x0456
+#define BUCK_TOP_CON1 0x1443
+#define TOP_CON 0x0013
+#define TOP_DIG_WPK 0x03a9
+#define TOP_CON_LOCK 0x03a8
+#define TOP_CLK_CON0 0x0134
+
+struct pmic_wrap_cmd {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+};
+
+struct pmic_wrap_setting {
+ enum pmic_wrap_phase_id phase;
+ struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
+ struct {
+ struct {
+ unsigned long cmd_addr;
+ unsigned long cmd_wdata;
+ } _[NR_PMIC_WRAP_CMD];
+ const int nr_idx;
+ } set[NR_PMIC_WRAP_PHASE];
+};
+
+static struct pmic_wrap_setting pw = {
+ .phase = NR_PMIC_WRAP_PHASE, /* invalid setting for init */
+ .addr = { {0UL, 0UL} },
+ .set[PMIC_WRAP_PHASE_ALLINONE] = {
+ ._[CMD_0] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(75000),},
+ ._[CMD_1] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(65000),},
+ ._[CMD_2] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(60000),},
+ ._[CMD_3] = {BUCK_VGPU11_ELR0, VOLT_TO_PMIC_VAL(55000),},
+ ._[CMD_4] = {TOP_SPI_CON0, 0x1,},
+ ._[CMD_5] = {TOP_SPI_CON0, 0x0,},
+ ._[CMD_6] = {BUCK_TOP_CON1, 0x0,},
+ ._[CMD_7] = {BUCK_TOP_CON1, 0xf,},
+ ._[CMD_8] = {TOP_CON, 0x3,},
+ ._[CMD_9] = {TOP_CON, 0x0,},
+ ._[CMD_10] = {TOP_DIG_WPK, 0x63,},
+ ._[CMD_11] = {TOP_CON_LOCK, 0x15,},
+ ._[CMD_12] = {TOP_DIG_WPK, 0x0,},
+ ._[CMD_13] = {TOP_CON_LOCK, 0x0,},
+ ._[CMD_14] = {TOP_CLK_CON0, 0x40,},
+ ._[CMD_15] = {TOP_CLK_CON0, 0x0,},
+ .nr_idx = NR_IDX_ALL,
+ },
+};
+
+void _mt_spm_pmic_table_init(void)
+{
+ struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
+ {(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,},
+ {(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,},
+ {(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,},
+ {(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,},
+ {(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,},
+ {(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,},
+ {(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,},
+ {(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,},
+ {(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,},
+ {(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,},
+ {(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,},
+ {(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,},
+ {(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,},
+ {(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,},
+ {(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,},
+ {(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,},
+ };
+
+ memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
+}
+
+void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
+{
+ uint32_t idx, addr, data;
+
+ if (phase >= NR_PMIC_WRAP_PHASE) {
+ return;
+ }
+
+ if (pw.phase == phase) {
+ return;
+ }
+
+ if (pw.addr[0].cmd_addr == 0UL) {
+ _mt_spm_pmic_table_init();
+ }
+
+ pw.phase = phase;
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
+
+ for (idx = 0U; idx < pw.set[phase].nr_idx; idx++) {
+ addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ data = pw.set[phase]._[idx].cmd_wdata;
+ mmio_write_32(pw.addr[idx].cmd_addr, addr | data);
+ }
+}
+
+void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
+ uint32_t cmd_wdata)
+{
+ uint32_t addr;
+
+ if (phase >= NR_PMIC_WRAP_PHASE) {
+ return;
+ }
+
+ if (idx >= pw.set[phase].nr_idx) {
+ return;
+ }
+
+ pw.set[phase]._[idx].cmd_wdata = cmd_wdata;
+ mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB);
+
+ if (pw.phase == phase) {
+ addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
+ mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata);
+ }
+}
+
+uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
+{
+ if (phase >= NR_PMIC_WRAP_PHASE) {
+ return 0UL;
+ }
+
+ if (idx >= pw.set[phase].nr_idx) {
+ return 0UL;
+ }
+
+ return pw.set[phase]._[idx].cmd_wdata;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h
new file mode 100644
index 0000000..53fdda2
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/****************************************************************
+ * Auto generated by DE, please DO NOT modify this file directly.
+ *****************************************************************/
+#ifndef MT_SPM_PMIC_WRAP_H
+#define MT_SPM_PMIC_WRAP_H
+
+enum pmic_wrap_phase_id {
+ PMIC_WRAP_PHASE_ALLINONE,
+ NR_PMIC_WRAP_PHASE,
+};
+
+/* IDX mapping, PMIC_WRAP_PHASE_ALLINONE */
+enum {
+ CMD_0, /* 0x0 */
+ CMD_1, /* 0x1 */
+ CMD_2, /* 0x2 */
+ CMD_3, /* 0x3 */
+ CMD_4, /* 0x4 */
+ CMD_5, /* 0x5 */
+ CMD_6, /* 0x6 */
+ CMD_7, /* 0x7 */
+ CMD_8, /* 0x8 */
+ CMD_9, /* 0x9 */
+ CMD_10, /* 0xA */
+ CMD_11, /* 0xB */
+ CMD_12, /* 0xC */
+ CMD_13, /* 0xD */
+ CMD_14, /* 0xE */
+ CMD_15, /* 0xF */
+ NR_IDX_ALL,
+};
+
+/* APIs */
+extern void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase);
+extern void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase,
+ uint32_t idx, uint32_t cmd_wdata);
+extern uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase,
+ uint32_t idx);
+#endif /* MT_SPM_PMIC_WRAP_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h
new file mode 100644
index 0000000..d8b9b29
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h
@@ -0,0 +1,2859 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/****************************************************************
+ * Auto generated by DE, please DO NOT modify this file directly.
+ *****************************************************************/
+
+#ifndef MT_SPM_REG
+#define MT_SPM_REG
+
+#include "sleep_def.h"
+#include <platform_def.h>
+#include "pcm_def.h"
+
+/**************************************
+ * Define and Declare
+ **************************************/
+
+/*******Register_SPM_CFG*************************************************/
+#define POWERON_CONFIG_EN (SPM_BASE + 0x000)
+#define SPM_POWER_ON_VAL0 (SPM_BASE + 0x004)
+#define SPM_POWER_ON_VAL1 (SPM_BASE + 0x008)
+#define SPM_CLK_CON (SPM_BASE + 0x00C)
+#define SPM_CLK_SETTLE (SPM_BASE + 0x010)
+#define SPM_AP_STANDBY_CON (SPM_BASE + 0x014)
+#define PCM_CON0 (SPM_BASE + 0x018)
+#define PCM_CON1 (SPM_BASE + 0x01C)
+#define SPM_POWER_ON_VAL2 (SPM_BASE + 0x020)
+#define SPM_POWER_ON_VAL3 (SPM_BASE + 0x024)
+#define PCM_REG_DATA_INI (SPM_BASE + 0x028)
+#define PCM_PWR_IO_EN (SPM_BASE + 0x02C)
+#define PCM_TIMER_VAL (SPM_BASE + 0x030)
+#define PCM_WDT_VAL (SPM_BASE + 0x034)
+#define SPM_SW_RST_CON (SPM_BASE + 0x040)
+#define SPM_SW_RST_CON_SET (SPM_BASE + 0x044)
+#define SPM_SW_RST_CON_CLR (SPM_BASE + 0x048)
+#define VS1_PSR_MASK_B (SPM_BASE + 0x04C)
+#define SPM_ARBITER_EN (SPM_BASE + 0x050)
+#define SCPSYS_CLK_CON (SPM_BASE + 0x054)
+#define SPM_SRAM_RSV_CON (SPM_BASE + 0x058)
+#define SPM_SWINT (SPM_BASE + 0x05C)
+#define SPM_SWINT_SET (SPM_BASE + 0x060)
+#define SPM_SWINT_CLR (SPM_BASE + 0x064)
+#define SPM_SCP_MAILBOX (SPM_BASE + 0x068)
+#define SCP_SPM_MAILBOX (SPM_BASE + 0x06C)
+#define SPM_SCP_IRQ (SPM_BASE + 0x070)
+#define SPM_CPU_WAKEUP_EVENT (SPM_BASE + 0x074)
+#define SPM_IRQ_MASK (SPM_BASE + 0x078)
+#define SPM_SRC_REQ (SPM_BASE + 0x080)
+#define SPM_SRC_MASK (SPM_BASE + 0x084)
+#define SPM_SRC2_MASK (SPM_BASE + 0x088)
+#define SPM_SRC3_MASK (SPM_BASE + 0x090)
+#define SPM_SRC4_MASK (SPM_BASE + 0x094)
+#define SPM_WAKEUP_EVENT_MASK2 (SPM_BASE + 0x098)
+#define SPM_WAKEUP_EVENT_MASK (SPM_BASE + 0x09C)
+#define SPM_WAKEUP_EVENT_SENS (SPM_BASE + 0x0A0)
+#define SPM_WAKEUP_EVENT_CLEAR (SPM_BASE + 0x0A4)
+#define SPM_WAKEUP_EVENT_EXT_MASK (SPM_BASE + 0x0A8)
+#define SCP_CLK_CON (SPM_BASE + 0x0AC)
+#define PCM_DEBUG_CON (SPM_BASE + 0x0B0)
+#define DDREN_DBC_CON (SPM_BASE + 0x0B4)
+#define SPM_RESOURCE_ACK_CON0 (SPM_BASE + 0x0B8)
+#define SPM_RESOURCE_ACK_CON1 (SPM_BASE + 0x0BC)
+#define SPM_RESOURCE_ACK_CON2 (SPM_BASE + 0x0C0)
+#define SPM_RESOURCE_ACK_CON3 (SPM_BASE + 0x0C4)
+#define SPM_RESOURCE_ACK_CON4 (SPM_BASE + 0x0C8)
+#define SPM_SRAM_CON (SPM_BASE + 0x0CC)
+/*******Register_SPM_STA*************************************************/
+#define PCM_REG0_DATA (SPM_BASE + 0x100)
+#define PCM_REG2_DATA (SPM_BASE + 0x104)
+#define PCM_REG6_DATA (SPM_BASE + 0x108)
+#define PCM_REG7_DATA (SPM_BASE + 0x10C)
+#define PCM_REG13_DATA (SPM_BASE + 0x110)
+#define SRC_REQ_STA_0 (SPM_BASE + 0x114)
+#define SRC_REQ_STA_1 (SPM_BASE + 0x118)
+#define SRC_REQ_STA_2 (SPM_BASE + 0x120)
+#define SRC_REQ_STA_3 (SPM_BASE + 0x124)
+#define SRC_REQ_STA_4 (SPM_BASE + 0x128)
+#define PCM_TIMER_OUT (SPM_BASE + 0x130)
+#define PCM_WDT_OUT (SPM_BASE + 0x134)
+#define SPM_IRQ_STA (SPM_BASE + 0x138)
+#define MD32PCM_WAKEUP_STA (SPM_BASE + 0x13C)
+#define MD32PCM_EVENT_STA (SPM_BASE + 0x140)
+#define SPM_WAKEUP_STA (SPM_BASE + 0x144)
+#define SPM_WAKEUP_EXT_STA (SPM_BASE + 0x148)
+#define SPM_WAKEUP_MISC (SPM_BASE + 0x14C)
+#define MM_DVFS_HALT (SPM_BASE + 0x150)
+#define SUBSYS_IDLE_STA (SPM_BASE + 0x164)
+#define PCM_STA (SPM_BASE + 0x168)
+#define PWR_STATUS (SPM_BASE + 0x16C)
+#define PWR_STATUS_2ND (SPM_BASE + 0x170)
+#define CPU_PWR_STATUS (SPM_BASE + 0x174)
+#define CPU_PWR_STATUS_2ND (SPM_BASE + 0x178)
+#define SPM_VTCXO_EVENT_COUNT_STA (SPM_BASE + 0x17C)
+#define SPM_INFRA_EVENT_COUNT_STA (SPM_BASE + 0x180)
+#define SPM_VRF18_EVENT_COUNT_STA (SPM_BASE + 0x184)
+#define SPM_APSRC_EVENT_COUNT_STA (SPM_BASE + 0x188)
+#define SPM_DDREN_EVENT_COUNT_STA (SPM_BASE + 0x18C)
+#define MD32PCM_STA (SPM_BASE + 0x190)
+#define MD32PCM_PC (SPM_BASE + 0x194)
+#define OTHER_PWR_STATUS (SPM_BASE + 0x198)
+#define DVFSRC_EVENT_STA (SPM_BASE + 0x19C)
+#define BUS_PROTECT_RDY (SPM_BASE + 0x1A0)
+#define BUS_PROTECT1_RDY (SPM_BASE + 0x1A4)
+#define BUS_PROTECT2_RDY (SPM_BASE + 0x1A8)
+#define BUS_PROTECT3_RDY (SPM_BASE + 0x1AC)
+#define BUS_PROTECT4_RDY (SPM_BASE + 0x1B0)
+#define BUS_PROTECT5_RDY (SPM_BASE + 0x1B4)
+#define BUS_PROTECT6_RDY (SPM_BASE + 0x1B8)
+#define BUS_PROTECT7_RDY (SPM_BASE + 0x1BC)
+#define BUS_PROTECT8_RDY (SPM_BASE + 0x1C0)
+#define BUS_PROTECT9_RDY (SPM_BASE + 0x1C4)
+#define SPM_TWAM_LAST_STA0 (SPM_BASE + 0x1D0)
+#define SPM_TWAM_LAST_STA1 (SPM_BASE + 0x1D4)
+#define SPM_TWAM_LAST_STA2 (SPM_BASE + 0x1D8)
+#define SPM_TWAM_LAST_STA3 (SPM_BASE + 0x1DC)
+#define SPM_TWAM_CURR_STA0 (SPM_BASE + 0x1E0)
+#define SPM_TWAM_CURR_STA1 (SPM_BASE + 0x1E4)
+#define SPM_TWAM_CURR_STA2 (SPM_BASE + 0x1E8)
+#define SPM_TWAM_CURR_STA3 (SPM_BASE + 0x1EC)
+#define SPM_TWAM_TIMER_OUT (SPM_BASE + 0x1F0)
+#define SPM_CG_CHECK_STA (SPM_BASE + 0x1F4)
+#define SPM_DVFS_STA (SPM_BASE + 0x1F8)
+#define SPM_DVFS_OPP_STA (SPM_BASE + 0x1FC)
+/*******Register_CPU_MT*************************************************/
+#define CPUEB_PWR_CON (SPM_BASE + 0x200)
+#define SPM_MCUSYS_PWR_CON (SPM_BASE + 0x204)
+#define SPM_CPUTOP_PWR_CON (SPM_BASE + 0x208)
+#define SPM_CPU0_PWR_CON (SPM_BASE + 0x20C)
+#define SPM_CPU1_PWR_CON (SPM_BASE + 0x210)
+#define SPM_CPU2_PWR_CON (SPM_BASE + 0x214)
+#define SPM_CPU3_PWR_CON (SPM_BASE + 0x218)
+#define SPM_CPU4_PWR_CON (SPM_BASE + 0x21C)
+#define SPM_CPU5_PWR_CON (SPM_BASE + 0x220)
+#define SPM_CPU6_PWR_CON (SPM_BASE + 0x224)
+#define SPM_CPU7_PWR_CON (SPM_BASE + 0x228)
+#define ARMPLL_CLK_CON (SPM_BASE + 0x22C)
+#define MCUSYS_IDLE_STA (SPM_BASE + 0x230)
+#define GIC_WAKEUP_STA (SPM_BASE + 0x234)
+#define CPU_SPARE_CON (SPM_BASE + 0x238)
+#define CPU_SPARE_CON_SET (SPM_BASE + 0x23C)
+#define CPU_SPARE_CON_CLR (SPM_BASE + 0x240)
+#define ARMPLL_CLK_SEL (SPM_BASE + 0x244)
+#define EXT_INT_WAKEUP_REQ (SPM_BASE + 0x248)
+#define EXT_INT_WAKEUP_REQ_SET (SPM_BASE + 0x24C)
+#define EXT_INT_WAKEUP_REQ_CLR (SPM_BASE + 0x250)
+#define CPU0_IRQ_MASK (SPM_BASE + 0x260)
+#define CPU_IRQ_MASK_SET (SPM_BASE + 0x264)
+#define CPU_IRQ_MASK_CLR (SPM_BASE + 0x268)
+#define CPU_WFI_EN (SPM_BASE + 0x280)
+#define CPU_WFI_EN_SET (SPM_BASE + 0x284)
+#define CPU_WFI_EN_CLR (SPM_BASE + 0x288)
+#define SYSRAM_CON (SPM_BASE + 0x290)
+#define SYSROM_CON (SPM_BASE + 0x294)
+#define ROOT_CPUTOP_ADDR (SPM_BASE + 0x2A0)
+#define ROOT_CORE_ADDR (SPM_BASE + 0x2A4)
+#define SPM2SW_MAILBOX_0 (SPM_BASE + 0x2D0)
+#define SPM2SW_MAILBOX_1 (SPM_BASE + 0x2D4)
+#define SPM2SW_MAILBOX_2 (SPM_BASE + 0x2D8)
+#define SPM2SW_MAILBOX_3 (SPM_BASE + 0x2DC)
+#define SW2SPM_INT (SPM_BASE + 0x2E0)
+#define SW2SPM_INT_SET (SPM_BASE + 0x2E4)
+#define SW2SPM_INT_CLR (SPM_BASE + 0x2E8)
+#define SW2SPM_MAILBOX_0 (SPM_BASE + 0x2EC)
+#define SW2SPM_MAILBOX_1 (SPM_BASE + 0x2F0)
+#define SW2SPM_MAILBOX_2 (SPM_BASE + 0x2F4)
+#define SW2SPM_MAILBOX_3 (SPM_BASE + 0x2F8)
+#define SW2SPM_CFG (SPM_BASE + 0x2FC)
+/*******Register_NONCPU_MT*************************************************/
+#define MFG0_PWR_CON (SPM_BASE + 0x300)
+#define MFG1_PWR_CON (SPM_BASE + 0x304)
+#define MFG2_PWR_CON (SPM_BASE + 0x308)
+#define MFG3_PWR_CON (SPM_BASE + 0x30C)
+#define MFG4_PWR_CON (SPM_BASE + 0x310)
+#define MFG5_PWR_CON (SPM_BASE + 0x314)
+#define MFG6_PWR_CON (SPM_BASE + 0x318)
+#define IFR_PWR_CON (SPM_BASE + 0x31C)
+#define IFR_SUB_PWR_CON (SPM_BASE + 0x320)
+#define PERI_PWR_CON (SPM_BASE + 0x324)
+#define PEXTP_MAC_TOP_P0_PWR_CON (SPM_BASE + 0x328)
+#define PEXTP_MAC_TOP_P1_PWR_CON (SPM_BASE + 0x32C)
+#define PCIE_PHY_PWR_CON (SPM_BASE + 0x330)
+#define SSUSB_PCIE_PHY_PWR_CON (SPM_BASE + 0x334)
+#define SSUSB_TOP_P1_PWR_CON (SPM_BASE + 0x338)
+#define SSUSB_TOP_P2_PWR_CON (SPM_BASE + 0x33C)
+#define SSUSB_TOP_P3_PWR_CON (SPM_BASE + 0x340)
+#define ETHER_PWR_CON (SPM_BASE + 0x344)
+#define DPY0_PWR_CON (SPM_BASE + 0x348)
+#define DPY1_PWR_CON (SPM_BASE + 0x34C)
+#define DPM0_PWR_CON (SPM_BASE + 0x350)
+#define DPM1_PWR_CON (SPM_BASE + 0x354)
+#define AUDIO_PWR_CON (SPM_BASE + 0x358)
+#define AUDIO_ASRC_PWR_CON (SPM_BASE + 0x35C)
+#define ADSP_PWR_CON (SPM_BASE + 0x360)
+#define VPPSYS0_PWR_CON (SPM_BASE + 0x364)
+#define VPPSYS1_PWR_CON (SPM_BASE + 0x368)
+#define VDOSYS0_PWR_CON (SPM_BASE + 0x36C)
+#define VDOSYS1_PWR_CON (SPM_BASE + 0x370)
+#define WPESYS_PWR_CON (SPM_BASE + 0x374)
+#define DP_TX_PWR_CON (SPM_BASE + 0x378)
+#define EDP_TX_PWR_CON (SPM_BASE + 0x37C)
+#define HDMI_TX_PWR_CON (SPM_BASE + 0x380)
+#define HDMI_RX_PWR_CON (SPM_BASE + 0x384)
+#define VDE0_PWR_CON (SPM_BASE + 0x388)
+#define VDE1_PWR_CON (SPM_BASE + 0x38C)
+#define VDE2_PWR_CON (SPM_BASE + 0x390)
+#define VEN_PWR_CON (SPM_BASE + 0x394)
+#define VEN_CORE1_PWR_CON (SPM_BASE + 0x398)
+#define CAM_PWR_CON (SPM_BASE + 0x39C)
+#define CAM_RAWA_PWR_CON (SPM_BASE + 0x3A0)
+#define CAM_RAWB_PWR_CON (SPM_BASE + 0x3A4)
+#define CAM_RAWC_PWR_CON (SPM_BASE + 0x3A8)
+#define IMG_M_PWR_CON (SPM_BASE + 0x3AC)
+#define IMG_D_PWR_CON (SPM_BASE + 0x3B0)
+#define IPE_PWR_CON (SPM_BASE + 0x3B4)
+#define NNA0_PWR_CON (SPM_BASE + 0x3B8)
+#define NNA1_PWR_CON (SPM_BASE + 0x3BC)
+#define IPNNA_PWR_CON (SPM_BASE + 0x3C0)
+#define CSI_RX_TOP_PWR_CON (SPM_BASE + 0x3C4)
+#define SSPM_SRAM_CON (SPM_BASE + 0x3C4)
+#define SCP_SRAM_CON (SPM_BASE + 0x3D0)
+#define UFS_SRAM_CON (SPM_BASE + 0x3D4)
+#define DEVAPC_IFR_SRAM_CON (SPM_BASE + 0x3D8)
+#define DEVAPC_SUBIFR_SRAM_CON (SPM_BASE + 0x3DC)
+#define DEVAPC_ACP_SRAM_CON (SPM_BASE + 0x3E0)
+#define USB_SRAM_CON (SPM_BASE + 0x3E4)
+#define DUMMY_SRAM_CO (SPM_BASE + 0x3E8)
+#define EXT_BUCK_ISO (SPM_BASE + 0x3EC)
+#define MSDC_SRAM_CON (SPM_BASE + 0x3F0)
+#define DEBUGTOP_SRAM (SPM_BASE + 0x3F4)
+#define DPMAIF_SRAM_C (SPM_BASE + 0x3F8)
+#define GCPU_SRAM_CON (SPM_BASE + 0x3FC)
+/*******Register_DIRC_IF*************************************************/
+#define SPM_MEM_CK_SEL (SPM_BASE + 0x400)
+#define SPM_BUS_PROTECT_MASK_B (SPM_BASE + 0x404)
+#define SPM_BUS_PROTECT1_MASK_B (SPM_BASE + 0x408)
+#define SPM_BUS_PROTECT2_MASK_B (SPM_BASE + 0x40C)
+#define SPM_BUS_PROTECT3_MASK_B (SPM_BASE + 0x410)
+#define SPM_BUS_PROTECT4_MASK_B (SPM_BASE + 0x414)
+#define SPM_BUS_PROTECT5_MASK_B (SPM_BASE + 0x418)
+#define SPM_BUS_PROTECT6_MASK_B (SPM_BASE + 0x41C)
+#define SPM_BUS_PROTECT7_MASK_B (SPM_BASE + 0x420)
+#define SPM_BUS_PROTECT8_MASK_B (SPM_BASE + 0x424)
+#define SPM_BUS_PROTECT9_MASK_B (SPM_BASE + 0x428)
+#define SPM_EMI_BW_MODE (SPM_BASE + 0x42C)
+#define SPM2MM_CON (SPM_BASE + 0x434)
+#define SPM2CPUEB_CON (SPM_BASE + 0x438)
+#define AP_MDSRC_REQ (SPM_BASE + 0x43C)
+#define SPM2EMI_ENTER_ULPM (SPM_BASE + 0x440)
+#define SPM_PLL_CON (SPM_BASE + 0x444)
+#define RC_SPM_CTRL (SPM_BASE + 0x448)
+#define SPM_DRAM_MCU_SW_CON_0 (SPM_BASE + 0x44C)
+#define SPM_DRAM_MCU_SW_CON_1 (SPM_BASE + 0x450)
+#define SPM_DRAM_MCU_SW_CON_2 (SPM_BASE + 0x454)
+#define SPM_DRAM_MCU_SW_CON_3 (SPM_BASE + 0x458)
+#define SPM_DRAM_MCU_SW_CON_4 (SPM_BASE + 0x45C)
+#define SPM_DRAM_MCU_STA_0 (SPM_BASE + 0x460)
+#define SPM_DRAM_MCU_STA_1 (SPM_BASE + 0x464)
+#define SPM_DRAM_MCU_STA_2 (SPM_BASE + 0x468)
+#define SPM_DRAM_MCU_SW_SEL_0 (SPM_BASE + 0x46C)
+#define RELAY_DVFS_LEVEL (SPM_BASE + 0x470)
+#define DRAMC_DPY_CLK_SW_CON_0 (SPM_BASE + 0x474)
+#define DRAMC_DPY_CLK_SW_CON_1 (SPM_BASE + 0x478)
+#define DRAMC_DPY_CLK_SW_CON_2 (SPM_BASE + 0x47C)
+#define DRAMC_DPY_CLK_SW_CON_3 (SPM_BASE + 0x480)
+#define DRAMC_DPY_CLK_SW_SEL_0 (SPM_BASE + 0x484)
+#define DRAMC_DPY_CLK_SW_SEL_1 (SPM_BASE + 0x488)
+#define DRAMC_DPY_CLK_SW_SEL_2 (SPM_BASE + 0x48C)
+#define DRAMC_DPY_CLK_SW_SEL_3 (SPM_BASE + 0x490)
+#define DRAMC_DPY_CLK_SPM_CON (SPM_BASE + 0x494)
+#define SPM_DVFS_LEVEL (SPM_BASE + 0x498)
+#define SPM_CIRQ_CON (SPM_BASE + 0x49C)
+#define SPM_DVFS_MISC (SPM_BASE + 0x4A0)
+#define RG_MODULE_SW_CG_0_MASK_REQ_0 (SPM_BASE + 0x4A4)
+#define RG_MODULE_SW_CG_0_MASK_REQ_1 (SPM_BASE + 0x4A8)
+#define RG_MODULE_SW_CG_0_MASK_REQ_2 (SPM_BASE + 0x4AC)
+#define RG_MODULE_SW_CG_1_MASK_REQ_0 (SPM_BASE + 0x4B0)
+#define RG_MODULE_SW_CG_1_MASK_REQ_1 (SPM_BASE + 0x4B4)
+#define RG_MODULE_SW_CG_1_MASK_REQ_2 (SPM_BASE + 0x4B8)
+#define RG_MODULE_SW_CG_2_MASK_REQ_0 (SPM_BASE + 0x4BC)
+#define RG_MODULE_SW_CG_2_MASK_REQ_1 (SPM_BASE + 0x4C0)
+#define RG_MODULE_SW_CG_2_MASK_REQ_2 (SPM_BASE + 0x4C4)
+#define RG_MODULE_SW_CG_3_MASK_REQ_0 (SPM_BASE + 0x4C8)
+#define RG_MODULE_SW_CG_3_MASK_REQ_1 (SPM_BASE + 0x4CC)
+#define RG_MODULE_SW_CG_3_MASK_REQ_2 (SPM_BASE + 0x4D0)
+#define PWR_STATUS_MASK_REQ_0 (SPM_BASE + 0x4D4)
+#define PWR_STATUS_MASK_REQ_1 (SPM_BASE + 0x4D8)
+#define PWR_STATUS_MASK_REQ_2 (SPM_BASE + 0x4DC)
+#define SPM_CG_CHECK_CON (SPM_BASE + 0x4E0)
+#define SPM_SRC_RDY_STA (SPM_BASE + 0x4E4)
+#define SPM_DVS_DFS_LEVEL (SPM_BASE + 0x4E8)
+#define SPM_FORCE_DVFS (SPM_BASE + 0x4EC)
+#define DRAMC_MCU_SRAM_CON (SPM_BASE + 0x4F0)
+#define DRAMC_MCU2_SRAM_CON (SPM_BASE + 0x4F4)
+#define DPY_SHU_SRAM_CON (SPM_BASE + 0x4F8)
+#define DPY_SHU2_SRAM_CON (SPM_BASE + 0x4FC)
+/*******The Others*************************************************/
+#define SRCLKEN_RC_CFG (SPM_BASE + 0x500)
+#define RC_CENTRAL_CFG1 (SPM_BASE + 0x504)
+#define RC_CENTRAL_CFG2 (SPM_BASE + 0x508)
+#define RC_CMD_ARB_CFG (SPM_BASE + 0x50C)
+#define RC_PMIC_RCEN_ADDR (SPM_BASE + 0x510)
+#define RC_PMIC_RCEN_SET_CLR_ADDR (SPM_BASE + 0x514)
+#define RC_DCXO_FPM_CFG (SPM_BASE + 0x518)
+#define RC_CENTRAL_CFG3 (SPM_BASE + 0x51C)
+#define RC_M00_SRCLKEN_CFG (SPM_BASE + 0x520)
+#define RC_M01_SRCLKEN_CFG (SPM_BASE + 0x524)
+#define RC_M02_SRCLKEN_CFG (SPM_BASE + 0x528)
+#define RC_M03_SRCLKEN_CFG (SPM_BASE + 0x52C)
+#define RC_M04_SRCLKEN_CFG (SPM_BASE + 0x530)
+#define RC_M05_SRCLKEN_CFG (SPM_BASE + 0x534)
+#define RC_M06_SRCLKEN_CFG (SPM_BASE + 0x538)
+#define RC_M07_SRCLKEN_CFG (SPM_BASE + 0x53C)
+#define RC_M08_SRCLKEN_CFG (SPM_BASE + 0x540)
+#define RC_M09_SRCLKEN_CFG (SPM_BASE + 0x544)
+#define RC_M10_SRCLKEN_CFG (SPM_BASE + 0x548)
+#define RC_M11_SRCLKEN_CFG (SPM_BASE + 0x54C)
+#define RC_M12_SRCLKEN_CFG (SPM_BASE + 0x550)
+#define RC_SRCLKEN_SW_CON_CFG (SPM_BASE + 0x554)
+#define RC_CENTRAL_CFG4 (SPM_BASE + 0x558)
+#define RC_PROTOCOL_CHK_CFG (SPM_BASE + 0x560)
+#define RC_DEBUG_CFG (SPM_BASE + 0x564)
+#define RC_MISC_0 (SPM_BASE + 0x5B4)
+
+#define SUBSYS_INTF_CFG (SPM_BASE + 0x5BC)
+#define PCM_WDT_LATCH_25 (SPM_BASE + 0x5C0)
+#define PCM_WDT_LATCH_26 (SPM_BASE + 0x5C4)
+#define PCM_WDT_LATCH_27 (SPM_BASE + 0x5C8)
+#define PCM_WDT_LATCH_28 (SPM_BASE + 0x5CC)
+#define PCM_WDT_LATCH_29 (SPM_BASE + 0x5D0)
+#define PCM_WDT_LATCH_30 (SPM_BASE + 0x5D4)
+#define PCM_WDT_LATCH_31 (SPM_BASE + 0x5D8)
+#define PCM_WDT_LATCH_32 (SPM_BASE + 0x5DC)
+#define PCM_WDT_LATCH_33 (SPM_BASE + 0x5E0)
+#define PCM_WDT_LATCH_34 (SPM_BASE + 0x5E4)
+#define PCM_WDT_LATCH_35 (SPM_BASE + 0x5EC)
+#define PCM_WDT_LATCH_36 (SPM_BASE + 0x5F0)
+#define PCM_WDT_LATCH_37 (SPM_BASE + 0x5F4)
+#define PCM_WDT_LATCH_38 (SPM_BASE + 0x5F8)
+#define PCM_WDT_LATCH_39 (SPM_BASE + 0x5FC)
+/*******Register_RSV*************************************************/
+#define SPM_SW_FLAG_0 (SPM_BASE + 0x600)
+#define SPM_SW_DEBUG_0 (SPM_BASE + 0x604)
+#define SPM_SW_FLAG_1 (SPM_BASE + 0x608)
+#define SPM_SW_DEBUG_1 (SPM_BASE + 0x60C)
+#define SPM_SW_RSV_0 (SPM_BASE + 0x610)
+#define SPM_SW_RSV_1 (SPM_BASE + 0x614)
+#define SPM_SW_RSV_2 (SPM_BASE + 0x618)
+#define SPM_SW_RSV_3 (SPM_BASE + 0x61C)
+#define SPM_SW_RSV_4 (SPM_BASE + 0x620)
+#define SPM_SW_RSV_5 (SPM_BASE + 0x624)
+#define SPM_SW_RSV_6 (SPM_BASE + 0x628)
+#define SPM_SW_RSV_7 (SPM_BASE + 0x62C)
+#define SPM_SW_RSV_8 (SPM_BASE + 0x630)
+#define SPM_BK_WAKE_EVENT (SPM_BASE + 0x634)
+#define SPM_BK_VTCXO_DUR (SPM_BASE + 0x638)
+#define SPM_BK_WAKE_MISC (SPM_BASE + 0x63C)
+#define SPM_BK_PCM_TIMER (SPM_BASE + 0x640)
+#define ULPOSC_CON (SPM_BASE + 0x644)
+#define SPM_RSV_CON_0 (SPM_BASE + 0x650)
+#define SPM_RSV_CON_1 (SPM_BASE + 0x654)
+#define SPM_RSV_STA_0 (SPM_BASE + 0x658)
+#define SPM_RSV_STA_1 (SPM_BASE + 0x65C)
+#define SPM_SPARE_CON (SPM_BASE + 0x660)
+#define SPM_SPARE_CON_SET (SPM_BASE + 0x664)
+#define SPM_SPARE_CON_CLR (SPM_BASE + 0x668)
+#define SPM_CROSS_WAKE_M00_REQ (SPM_BASE + 0x66C)
+#define SPM_CROSS_WAKE_M01_REQ (SPM_BASE + 0x670)
+#define SPM_CROSS_WAKE_M02_REQ (SPM_BASE + 0x674)
+#define SPM_CROSS_WAKE_M03_REQ (SPM_BASE + 0x678)
+#define SCP_VCORE_LEVEL (SPM_BASE + 0x67C)
+#define SC_MM_CK_SEL_CON (SPM_BASE + 0x680)
+#define SPARE_ACK_MASK (SPM_BASE + 0x684)
+#define SPM_DV_CON_0 (SPM_BASE + 0x68C)
+#define SPM_DV_CON_1 (SPM_BASE + 0x690)
+#define SPM_DV_STA (SPM_BASE + 0x694)
+#define CONN_XOWCN_DEBUG_EN (SPM_BASE + 0x698)
+#define SPM_SEMA_M0 (SPM_BASE + 0x69C)
+#define SPM_SEMA_M1 (SPM_BASE + 0x6A0)
+#define SPM_SEMA_M2 (SPM_BASE + 0x6A4)
+#define SPM_SEMA_M3 (SPM_BASE + 0x6A8)
+#define SPM_SEMA_M4 (SPM_BASE + 0x6AC)
+#define SPM_SEMA_M5 (SPM_BASE + 0x6B0)
+#define SPM_SEMA_M6 (SPM_BASE + 0x6B4)
+#define SPM_SEMA_M7 (SPM_BASE + 0x6B8)
+#define SPM2ADSP_MAILBOX (SPM_BASE + 0x6BC)
+#define ADSP2SPM_MAILBOX (SPM_BASE + 0x6C0)
+#define SPM_ADSP_IRQ (SPM_BASE + 0x6C4)
+#define SPM_MD32_IRQ (SPM_BASE + 0x6C8)
+#define SPM2PMCU_MAILBOX_0 (SPM_BASE + 0x6CC)
+#define SPM2PMCU_MAILBOX_1 (SPM_BASE + 0x6D0)
+#define SPM2PMCU_MAILBOX_2 (SPM_BASE + 0x6D4)
+#define SPM2PMCU_MAILBOX_3 (SPM_BASE + 0x6D8)
+#define PMCU2SPM_MAILBOX_0 (SPM_BASE + 0x6DC)
+#define PMCU2SPM_MAILBOX_1 (SPM_BASE + 0x6E0)
+#define PMCU2SPM_MAILBOX_2 (SPM_BASE + 0x6E4)
+#define PMCU2SPM_MAILBOX_3 (SPM_BASE + 0x6E8)
+#define UFS_PSRI_SW (SPM_BASE + 0x6EC)
+#define UFS_PSRI_SW_SET (SPM_BASE + 0x6F0)
+#define UFS_PSRI_SW_CLR (SPM_BASE + 0x6F4)
+#define SPM_AP_SEMA (SPM_BASE + 0x6F8)
+#define SPM_SPM_SEMA (SPM_BASE + 0x6FC)
+/*******Register_DVFS_TAB*************************************************/
+#define SPM_DVFS_CON (SPM_BASE + 0x700)
+#define SPM_DVFS_CON_STA (SPM_BASE + 0x704)
+#define SPM_PMIC_SPMI_CON (SPM_BASE + 0x708)
+#define SPM_DVFS_CMD0 (SPM_BASE + 0x710)
+#define SPM_DVFS_CMD1 (SPM_BASE + 0x714)
+#define SPM_DVFS_CMD2 (SPM_BASE + 0x718)
+#define SPM_DVFS_CMD3 (SPM_BASE + 0x71C)
+#define SPM_DVFS_CMD4 (SPM_BASE + 0x720)
+#define SPM_DVFS_CMD5 (SPM_BASE + 0x724)
+#define SPM_DVFS_CMD6 (SPM_BASE + 0x728)
+#define SPM_DVFS_CMD7 (SPM_BASE + 0x72C)
+#define SPM_DVFS_CMD8 (SPM_BASE + 0x730)
+#define SPM_DVFS_CMD9 (SPM_BASE + 0x734)
+#define SPM_DVFS_CMD10 (SPM_BASE + 0x738)
+#define SPM_DVFS_CMD11 (SPM_BASE + 0x73C)
+#define SPM_DVFS_CMD12 (SPM_BASE + 0x740)
+#define SPM_DVFS_CMD13 (SPM_BASE + 0x744)
+#define SPM_DVFS_CMD14 (SPM_BASE + 0x748)
+#define SPM_DVFS_CMD15 (SPM_BASE + 0x74C)
+#define SPM_DVFS_CMD16 (SPM_BASE + 0x750)
+#define SPM_DVFS_CMD17 (SPM_BASE + 0x754)
+#define SPM_DVFS_CMD18 (SPM_BASE + 0x758)
+#define SPM_DVFS_CMD19 (SPM_BASE + 0x75C)
+#define SPM_DVFS_CMD20 (SPM_BASE + 0x760)
+#define SPM_DVFS_CMD21 (SPM_BASE + 0x764)
+#define SPM_DVFS_CMD22 (SPM_BASE + 0x768)
+#define SPM_DVFS_CMD23 (SPM_BASE + 0x76C)
+#define SYS_TIMER_VALUE_L (SPM_BASE + 0x770)
+#define SYS_TIMER_VALUE_H (SPM_BASE + 0x774)
+#define SYS_TIMER_START_L (SPM_BASE + 0x778)
+#define SYS_TIMER_START_H (SPM_BASE + 0x77C)
+#define SYS_TIMER_LATCH_L_00 (SPM_BASE + 0x780)
+#define SYS_TIMER_LATCH_H_00 (SPM_BASE + 0x784)
+#define SYS_TIMER_LATCH_L_01 (SPM_BASE + 0x788)
+#define SYS_TIMER_LATCH_H_01 (SPM_BASE + 0x78C)
+#define SYS_TIMER_LATCH_L_02 (SPM_BASE + 0x790)
+#define SYS_TIMER_LATCH_H_02 (SPM_BASE + 0x794)
+#define SYS_TIMER_LATCH_L_03 (SPM_BASE + 0x798)
+#define SYS_TIMER_LATCH_H_03 (SPM_BASE + 0x79C)
+#define SYS_TIMER_LATCH_L_04 (SPM_BASE + 0x7A0)
+#define SYS_TIMER_LATCH_H_04 (SPM_BASE + 0x7A4)
+#define SYS_TIMER_LATCH_L_05 (SPM_BASE + 0x7A8)
+#define SYS_TIMER_LATCH_H_05 (SPM_BASE + 0x7AC)
+#define SYS_TIMER_LATCH_L_06 (SPM_BASE + 0x7B0)
+#define SYS_TIMER_LATCH_H_06 (SPM_BASE + 0x7B4)
+#define SYS_TIMER_LATCH_L_07 (SPM_BASE + 0x7B8)
+#define SYS_TIMER_LATCH_H_07 (SPM_BASE + 0x7BC)
+#define SYS_TIMER_LATCH_L_08 (SPM_BASE + 0x7C0)
+#define SYS_TIMER_LATCH_H_08 (SPM_BASE + 0x7C4)
+#define SYS_TIMER_LATCH_L_09 (SPM_BASE + 0x7C8)
+#define SYS_TIMER_LATCH_H_09 (SPM_BASE + 0x7CC)
+#define SYS_TIMER_LATCH_L_10 (SPM_BASE + 0x7D0)
+#define SYS_TIMER_LATCH_H_10 (SPM_BASE + 0x7D4)
+#define SYS_TIMER_LATCH_L_11 (SPM_BASE + 0x7D8)
+#define SYS_TIMER_LATCH_H_11 (SPM_BASE + 0x7DC)
+#define SYS_TIMER_LATCH_L_12 (SPM_BASE + 0x7E0)
+#define SYS_TIMER_LATCH_H_12 (SPM_BASE + 0x7E4)
+#define SYS_TIMER_LATCH_L_13 (SPM_BASE + 0x7E8)
+#define SYS_TIMER_LATCH_H_13 (SPM_BASE + 0x7EC)
+#define SYS_TIMER_LATCH_L_14 (SPM_BASE + 0x7F0)
+#define SYS_TIMER_LATCH_H_14 (SPM_BASE + 0x7F4)
+#define SYS_TIMER_LATCH_L_15 (SPM_BASE + 0x7F8)
+#define SYS_TIMER_LATCH_H_15 (SPM_BASE + 0x7FC)
+/*******Register_LAT_STA*************************************************/
+#define PCM_WDT_LATCH_0 (SPM_BASE + 0x800)
+#define PCM_WDT_LATCH_1 (SPM_BASE + 0x804)
+#define PCM_WDT_LATCH_2 (SPM_BASE + 0x808)
+#define PCM_WDT_LATCH_3 (SPM_BASE + 0x80C)
+#define PCM_WDT_LATCH_4 (SPM_BASE + 0x810)
+#define PCM_WDT_LATCH_5 (SPM_BASE + 0x814)
+#define PCM_WDT_LATCH_6 (SPM_BASE + 0x818)
+#define PCM_WDT_LATCH_7 (SPM_BASE + 0x81C)
+#define PCM_WDT_LATCH_8 (SPM_BASE + 0x820)
+#define PCM_WDT_LATCH_9 (SPM_BASE + 0x824)
+#define PCM_WDT_LATCH_10 (SPM_BASE + 0x828)
+#define PCM_WDT_LATCH_11 (SPM_BASE + 0x82C)
+#define PCM_WDT_LATCH_12 (SPM_BASE + 0x830)
+#define PCM_WDT_LATCH_13 (SPM_BASE + 0x834)
+#define PCM_WDT_LATCH_14 (SPM_BASE + 0x838)
+#define PCM_WDT_LATCH_15 (SPM_BASE + 0x83C)
+#define PCM_WDT_LATCH_16 (SPM_BASE + 0x840)
+#define PCM_WDT_LATCH_17 (SPM_BASE + 0x844)
+#define PCM_WDT_LATCH_18 (SPM_BASE + 0x848)
+#define PCM_WDT_LATCH_SPARE_0 (SPM_BASE + 0x84C)
+#define PCM_WDT_LATCH_SPARE_1 (SPM_BASE + 0x850)
+#define PCM_WDT_LATCH_SPARE_2 (SPM_BASE + 0x854)
+#define PCM_WDT_LATCH_CONN_0 (SPM_BASE + 0x870)
+#define PCM_WDT_LATCH_CONN_1 (SPM_BASE + 0x874)
+#define PCM_WDT_LATCH_CONN_2 (SPM_BASE + 0x878)
+#define DRAMC_GATING_ERR_LATCH_CH0_0 (SPM_BASE + 0x8A0)
+#define DRAMC_GATING_ERR_LATCH_CH0_1 (SPM_BASE + 0x8A4)
+#define DRAMC_GATING_ERR_LATCH_CH0_2 (SPM_BASE + 0x8A8)
+#define DRAMC_GATING_ERR_LATCH_CH0_3 (SPM_BASE + 0x8AC)
+#define DRAMC_GATING_ERR_LATCH_CH0_4 (SPM_BASE + 0x8B0)
+#define DRAMC_GATING_ERR_LATCH_CH0_5 (SPM_BASE + 0x8B4)
+#define DRAMC_GATING_ERR_LATCH_CH0_6 (SPM_BASE + 0x8B8)
+#define DRAMC_GATING_ERR_LATCH_SPARE_0 (SPM_BASE + 0x8F4)
+/*******Register_SPM_ACK_CHK*************************************************/
+#define SPM_ACK_CHK_CON_0 (SPM_BASE + 0x900)
+#define SPM_ACK_CHK_PC_0 (SPM_BASE + 0x904)
+#define SPM_ACK_CHK_SEL_0 (SPM_BASE + 0x908)
+#define SPM_ACK_CHK_TIMER_0 (SPM_BASE + 0x90C)
+#define SPM_ACK_CHK_STA_0 (SPM_BASE + 0x910)
+#define SPM_ACK_CHK_SWINT_0 (SPM_BASE + 0x914)
+#define SPM_ACK_CHK_CON_1 (SPM_BASE + 0x920)
+#define SPM_ACK_CHK_PC_1 (SPM_BASE + 0x924)
+#define SPM_ACK_CHK_SEL_1 (SPM_BASE + 0x928)
+#define SPM_ACK_CHK_TIMER_1 (SPM_BASE + 0x92C)
+#define SPM_ACK_CHK_STA_1 (SPM_BASE + 0x930)
+#define SPM_ACK_CHK_SWINT_1 (SPM_BASE + 0x934)
+#define SPM_ACK_CHK_CON_2 (SPM_BASE + 0x940)
+#define SPM_ACK_CHK_PC_2 (SPM_BASE + 0x944)
+#define SPM_ACK_CHK_SEL_2 (SPM_BASE + 0x948)
+#define SPM_ACK_CHK_TIMER_2 (SPM_BASE + 0x94C)
+#define SPM_ACK_CHK_STA_2 (SPM_BASE + 0x950)
+#define SPM_ACK_CHK_SWINT_2 (SPM_BASE + 0x954)
+#define SPM_ACK_CHK_CON_3 (SPM_BASE + 0x960)
+#define SPM_ACK_CHK_PC_3 (SPM_BASE + 0x964)
+#define SPM_ACK_CHK_SEL_3 (SPM_BASE + 0x968)
+#define SPM_ACK_CHK_TIMER_3 (SPM_BASE + 0x96C)
+#define SPM_ACK_CHK_STA_3 (SPM_BASE + 0x970)
+#define SPM_ACK_CHK_SWINT_3 (SPM_BASE + 0x974)
+#define SPM_COUNTER_0 (SPM_BASE + 0x978)
+#define SPM_COUNTER_1 (SPM_BASE + 0x97C)
+#define SPM_COUNTER_2 (SPM_BASE + 0x980)
+#define SYS_TIMER_CON (SPM_BASE + 0x98C)
+#define SPM_TWAM_CON (SPM_BASE + 0x990)
+#define SPM_TWAM_WINDOW_LEN (SPM_BASE + 0x994)
+#define SPM_TWAM_IDLE_SEL (SPM_BASE + 0x998)
+#define SPM_TWAM_EVENT_CLEAR (SPM_BASE + 0x99C)
+/*******The OTHERS*************************************************/
+#define RC_FSM_STA_0 (SPM_BASE + 0xE00)
+#define RC_CMD_STA_0 (SPM_BASE + 0xE04)
+#define RC_CMD_STA_1 (SPM_BASE + 0xE08)
+#define RC_SPI_STA_0 (SPM_BASE + 0xE0C)
+#define RC_PI_PO_STA_0 (SPM_BASE + 0xE10)
+#define RC_M00_REQ_STA_0 (SPM_BASE + 0xE14)
+#define RC_M01_REQ_STA_0 (SPM_BASE + 0xE1C)
+#define RC_M02_REQ_STA_0 (SPM_BASE + 0xE20)
+#define RC_M03_REQ_STA_0 (SPM_BASE + 0xE24)
+#define RC_M04_REQ_STA_0 (SPM_BASE + 0xE28)
+#define RC_M05_REQ_STA_0 (SPM_BASE + 0xE2C)
+#define RC_M06_REQ_STA_0 (SPM_BASE + 0xE30)
+#define RC_M07_REQ_STA_0 (SPM_BASE + 0xE34)
+#define RC_M08_REQ_STA_0 (SPM_BASE + 0xE38)
+#define RC_M09_REQ_STA_0 (SPM_BASE + 0xE3C)
+#define RC_M10_REQ_STA_0 (SPM_BASE + 0xE40)
+#define RC_M11_REQ_STA_0 (SPM_BASE + 0xE44)
+#define RC_M12_REQ_STA_0 (SPM_BASE + 0xE48)
+#define RC_DEBUG_STA_0 (SPM_BASE + 0xE4C)
+#define RC_DEBUG_TRACE_0_LSB (SPM_BASE + 0xE50)
+#define RC_DEBUG_TRACE_0_MSB (SPM_BASE + 0xE54)
+#define RC_DEBUG_TRACE_1_LSB (SPM_BASE + 0xE5C)
+#define RC_DEBUG_TRACE_1_MSB (SPM_BASE + 0xE60)
+#define RC_DEBUG_TRACE_2_LSB (SPM_BASE + 0xE64)
+#define RC_DEBUG_TRACE_2_MSB (SPM_BASE + 0xE6C)
+#define RC_DEBUG_TRACE_3_LSB (SPM_BASE + 0xE70)
+#define RC_DEBUG_TRACE_3_MSB (SPM_BASE + 0xE74)
+#define RC_DEBUG_TRACE_4_LSB (SPM_BASE + 0xE78)
+#define RC_DEBUG_TRACE_4_MSB (SPM_BASE + 0xE7C)
+#define RC_DEBUG_TRACE_5_LSB (SPM_BASE + 0xE80)
+#define RC_DEBUG_TRACE_5_MSB (SPM_BASE + 0xE84)
+#define RC_DEBUG_TRACE_6_LSB (SPM_BASE + 0xE88)
+#define RC_DEBUG_TRACE_6_MSB (SPM_BASE + 0xE8C)
+#define RC_DEBUG_TRACE_7_LSB (SPM_BASE + 0xE90)
+#define RC_DEBUG_TRACE_7_MSB (SPM_BASE + 0xE94)
+#define RC_SYS_TIMER_LATCH_0_LSB (SPM_BASE + 0xE98)
+#define RC_SYS_TIMER_LATCH_0_MSB (SPM_BASE + 0xE9C)
+#define RC_SYS_TIMER_LATCH_1_LSB (SPM_BASE + 0xEA0)
+#define RC_SYS_TIMER_LATCH_1_MSB (SPM_BASE + 0xEA4)
+#define RC_SYS_TIMER_LATCH_2_LSB (SPM_BASE + 0xEA8)
+#define RC_SYS_TIMER_LATCH_2_MSB (SPM_BASE + 0xEAC)
+#define RC_SYS_TIMER_LATCH_3_LSB (SPM_BASE + 0xEB0)
+#define RC_SYS_TIMER_LATCH_3_MSB (SPM_BASE + 0xEB4)
+#define RC_SYS_TIMER_LATCH_4_LSB (SPM_BASE + 0xEB8)
+#define RC_SYS_TIMER_LATCH_4_MSB (SPM_BASE + 0xEBC)
+#define RC_SYS_TIMER_LATCH_5_LSB (SPM_BASE + 0xEC0)
+#define RC_SYS_TIMER_LATCH_5_MSB (SPM_BASE + 0xEC4)
+#define RC_SYS_TIMER_LATCH_6_LSB (SPM_BASE + 0xEC8)
+#define RC_SYS_TIMER_LATCH_6_MSB (SPM_BASE + 0xECC)
+#define RC_SYS_TIMER_LATCH_7_LSB (SPM_BASE + 0xED0)
+#define RC_SYS_TIMER_LATCH_7_MSB (SPM_BASE + 0xED4)
+#define PCM_WDT_LATCH_19 (SPM_BASE + 0xED8)
+#define PCM_WDT_LATCH_20 (SPM_BASE + 0xEDC)
+#define PCM_WDT_LATCH_21 (SPM_BASE + 0xEE0)
+#define PCM_WDT_LATCH_22 (SPM_BASE + 0xEE4)
+#define PCM_WDT_LATCH_23 (SPM_BASE + 0xEE8)
+#define PCM_WDT_LATCH_24 (SPM_BASE + 0xEEC)
+/*******Register_PMSR*************************************************/
+#define PMSR_LAST_DAT (SPM_BASE + 0xF00)
+#define PMSR_LAST_CNT (SPM_BASE + 0xF04)
+#define PMSR_LAST_ACK (SPM_BASE + 0xF08)
+#define SPM_PMSR_SEL_CON0 (SPM_BASE + 0xF10)
+#define SPM_PMSR_SEL_CON1 (SPM_BASE + 0xF14)
+#define SPM_PMSR_SEL_CON2 (SPM_BASE + 0xF18)
+#define SPM_PMSR_SEL_CON3 (SPM_BASE + 0xF1C)
+#define SPM_PMSR_SEL_CON4 (SPM_BASE + 0xF20)
+#define SPM_PMSR_SEL_CON5 (SPM_BASE + 0xF24)
+#define SPM_PMSR_SEL_CON6 (SPM_BASE + 0xF28)
+#define SPM_PMSR_SEL_CON7 (SPM_BASE + 0xF2C)
+#define SPM_PMSR_SEL_CON8 (SPM_BASE + 0xF30)
+#define SPM_PMSR_SEL_CON9 (SPM_BASE + 0xF34)
+#define SPM_PMSR_SEL_CON10 (SPM_BASE + 0xF3C)
+#define SPM_PMSR_SEL_CON11 (SPM_BASE + 0xF40)
+#define SPM_PMSR_TIEMR_STA0 (SPM_BASE + 0xFB8)
+#define SPM_PMSR_TIEMR_STA1 (SPM_BASE + 0xFBC)
+#define SPM_PMSR_TIEMR_STA2 (SPM_BASE + 0xFC0)
+#define SPM_PMSR_GENERAL_CON0 (SPM_BASE + 0xFC4)
+#define SPM_PMSR_GENERAL_CON1 (SPM_BASE + 0xFC8)
+#define SPM_PMSR_GENERAL_CON2 (SPM_BASE + 0xFCC)
+#define SPM_PMSR_GENERAL_CON3 (SPM_BASE + 0xFD0)
+#define SPM_PMSR_GENERAL_CON4 (SPM_BASE + 0xFD4)
+#define SPM_PMSR_GENERAL_CON5 (SPM_BASE + 0xFD8)
+#define SPM_PMSR_SW_RESET (SPM_BASE + 0xFDC)
+#define SPM_PMSR_MON_CON0 (SPM_BASE + 0xFE0)
+#define SPM_PMSR_MON_CON1 (SPM_BASE + 0xFE4)
+#define SPM_PMSR_MON_CON2 (SPM_BASE + 0xFE8)
+#define SPM_PMSR_LEN_CON0 (SPM_BASE + 0xFEC)
+#define SPM_PMSR_LEN_CON1 (SPM_BASE + 0xFF0)
+#define SPM_PMSR_LEN_CON2 (SPM_BASE + 0xFF4)
+/*******Register End*************************************************/
+
+/* POWERON_CONFIG_EN (0x10006000+0x000) */
+#define BCLK_CG_EN_LSB (1U << 0) /* 1b */
+#define PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_POWER_ON_VAL0 (0x10006000+0x004) */
+#define POWER_ON_VAL0_LSB (1U << 0) /* 32b */
+/* SPM_POWER_ON_VAL1 (0x10006000+0x008) */
+#define POWER_ON_VAL1_LSB (1U << 0) /* 32b */
+/* SPM_CLK_CON (0x10006000+0x00C) */
+#define REG_SRCCLKEN0_CTL_LSB (1U << 0) /* 2b */
+#define REG_SRCCLKEN1_CTL_LSB (1U << 2) /* 2b */
+#define SYS_SETTLE_SEL_LSB (1U << 4) /* 1b */
+#define REG_SPM_LOCK_INFRA_DCM_LSB (1U << 5) /* 1b */
+#define REG_SRCCLKEN_MASK_LSB (1U << 6) /* 3b */
+#define REG_MD1_C32RM_EN_LSB (1U << 9) /* 1b */
+#define REG_MD2_C32RM_EN_LSB (1U << 10) /* 1b */
+#define REG_CLKSQ0_SEL_CTRL_LSB (1U << 11) /* 1b */
+#define REG_CLKSQ1_SEL_CTRL_LSB (1U << 12) /* 1b */
+#define REG_SRCCLKEN0_EN_LSB (1U << 13) /* 1b */
+#define REG_SRCCLKEN1_EN_LSB (1U << 14) /* 1b */
+#define SCP_DCM_EN_LSB (1U << 15) /* 1b */
+#define REG_SYSCLK0_SRC_MASK_B_LSB (1U << 16) /* 8b */
+#define REG_SYSCLK1_SRC_MASK_B_LSB (1U << 24) /* 8b */
+/* SPM_CLK_SETTLE (0x10006000+0x010) */
+#define SYSCLK_SETTLE_LSB (1U << 0) /* 28b */
+/* SPM_AP_STANDBY_CON (0x10006000+0x014) */
+#define REG_WFI_OP_LSB (1U << 0) /* 1b */
+#define REG_WFI_TYPE_LSB (1U << 1) /* 1b */
+#define REG_MP0_CPUTOP_IDLE_MASK_LSB (1U << 2) /* 1b */
+#define REG_MP1_CPUTOP_IDLE_MASK_LSB (1U << 3) /* 1b */
+#define REG_MCUSYS_IDLE_MASK_LSB (1U << 4) /* 1b */
+#define REG_MD_APSRC_1_SEL_LSB (1U << 25) /* 1b */
+#define REG_MD_APSRC_0_SEL_LSB (1U << 26) /* 1b */
+#define REG_CONN_APSRC_SEL_LSB (1U << 29) /* 1b */
+/* PCM_CON0 (0x10006000+0x018) */
+#define PCM_CK_EN_LSB (1U << 2) /* 1b */
+#define RG_EN_IM_SLEEP_DVS_LSB (1U << 3) /* 1b */
+#define PCM_CK_FROM_CKSYS_LSB (1U << 4) /* 1b */
+#define PCM_SW_RESET_LSB (1U << 15) /* 1b */
+#define PCM_CON0_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* PCM_CON1 (0x10006000+0x01C) */
+#define RG_IM_SLAVE_LSB (1U << 0) /* 1b */
+#define RG_IM_SLEEP_LSB (1U << 1) /* 1b */
+#define REG_SPM_SRAM_CTRL_MUX_LSB (1U << 2) /* 1b */
+#define RG_AHBMIF_APBEN_LSB (1U << 3) /* 1b */
+#define RG_IM_PDN_LSB (1U << 4) /* 1b */
+#define RG_PCM_TIMER_EN_LSB (1U << 5) /* 1b */
+#define SPM_EVENT_COUNTER_CLR_LSB (1U << 6) /* 1b */
+#define RG_DIS_MIF_PROT_LSB (1U << 7) /* 1b */
+#define RG_PCM_WDT_EN_LSB (1U << 8) /* 1b */
+#define RG_PCM_WDT_WAKE_LSB (1U << 9) /* 1b */
+#define REG_SPM_SRAM_SLEEP_B_LSB (1U << 10) /* 1b */
+#define REG_SPM_SRAM_ISOINT_B_LSB (1U << 11) /* 1b */
+#define REG_EVENT_LOCK_EN_LSB (1U << 12) /* 1b */
+#define REG_SRCCLKEN_FAST_RESP_LSB (1U << 13) /* 1b */
+#define REG_MD32_APB_INTERNAL_EN_LSB (1U << 14) /* 1b */
+#define RG_PCM_IRQ_MSK_LSB (1U << 15) /* 1b */
+#define PCM_CON1_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_POWER_ON_VAL2 (0x10006000+0x020) */
+#define POWER_ON_VAL2_LSB (1U << 0) /* 32b */
+/* SPM_POWER_ON_VAL3 (0x10006000+0x024) */
+#define POWER_ON_VAL3_LSB (1U << 0) /* 32b */
+/* PCM_REG_DATA_INI (0x10006000+0x028) */
+#define PCM_REG_DATA_INI_LSB (1U << 0) /* 32b */
+/* PCM_PWR_IO_EN (0x10006000+0x02C) */
+#define PCM_PWR_IO_EN_LSB (1U << 0) /* 8b */
+#define RG_RF_SYNC_EN_LSB (1U << 16) /* 8b */
+/* PCM_TIMER_VAL (0x10006000+0x030) */
+#define REG_PCM_TIMER_VAL_LSB (1U << 0) /* 32b */
+/* PCM_WDT_VAL (0x10006000+0x034) */
+#define RG_PCM_WDT_VAL_LSB (1U << 0) /* 32b */
+/* SPM_SW_RST_CON (0x10006000+0x040) */
+#define SPM_SW_RST_CON_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_SW_RST_CON_SET (0x10006000+0x044) */
+#define SPM_SW_RST_CON_SET_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_SET_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* SPM_SW_RST_CON_CLR (0x10006000+0x048) */
+#define SPM_SW_RST_CON_CLR_LSB (1U << 0) /* 16b */
+#define SPM_SW_RST_CON_CLR_PROJECT_CODE_LSB (1U << 16) /* 16b */
+/* VS1_PSR_MASK_B (0x10006000+0x04C) */
+#define VS1_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */
+#define VS1_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */
+/* VS2_PSR_MASK_B (0x10006000+0x050) */
+#define VS2_OPP0_PSR_MASK_B_LSB (1U << 0) /* 8b */
+#define VS2_OPP1_PSR_MASK_B_LSB (1U << 8) /* 8b */
+#define VS2_OPP2_PSR_MASK_B_LSB (1U << 16) /* 8b */
+/* MD32_CLK_CON (0x10006000+0x084) */
+#define REG_MD32_26M_CK_SEL_LSB (1U << 0) /* 1b */
+#define REG_MD32_DCM_EN_LSB (1U << 1) /* 1b */
+/* SPM_SRAM_RSV_CON (0x10006000+0x088) */
+#define SPM_SRAM_SLEEP_B_ECO_EN_LSB (1U << 0) /* 1b */
+/* SPM_SWINT (0x10006000+0x08C) */
+#define SPM_SWINT_LSB (1U << 0) /* 32b */
+/* SPM_SWINT_SET (0x10006000+0x090) */
+#define SPM_SWINT_SET_LSB (1U << 0) /* 32b */
+/* SPM_SWINT_CLR (0x10006000+0x094) */
+#define SPM_SWINT_CLR_LSB (1U << 0) /* 32b */
+/* SPM_SCP_MAILBOX (0x10006000+0x098) */
+#define SPM_SCP_MAILBOX_LSB (1U << 0) /* 32b */
+/* SCP_SPM_MAILBOX (0x10006000+0x09C) */
+#define SCP_SPM_MAILBOX_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CON (0x10006000+0x0A0) */
+#define REG_TWAM_ENABLE_LSB (1U << 0) /* 1b */
+#define REG_TWAM_SPEED_MODE_EN_LSB (1U << 1) /* 1b */
+#define REG_TWAM_SW_RST_LSB (1U << 2) /* 1b */
+#define REG_TWAM_IRQ_MASK_LSB (1U << 3) /* 1b */
+#define REG_TWAM_MON_TYPE_0_LSB (1U << 4) /* 2b */
+#define REG_TWAM_MON_TYPE_1_LSB (1U << 6) /* 2b */
+#define REG_TWAM_MON_TYPE_2_LSB (1U << 8) /* 2b */
+#define REG_TWAM_MON_TYPE_3_LSB (1U << 10) /* 2b */
+/* SPM_TWAM_WINDOW_LEN (0x10006000+0x0A4) */
+#define REG_TWAM_WINDOW_LEN_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_IDLE_SEL (0x10006000+0x0A8) */
+#define REG_TWAM_SIG_SEL_0_LSB (1U << 0) /* 7b */
+#define REG_TWAM_SIG_SEL_1_LSB (1U << 8) /* 7b */
+#define REG_TWAM_SIG_SEL_2_LSB (1U << 16) /* 7b */
+#define REG_TWAM_SIG_SEL_3_LSB (1U << 24) /* 7b */
+/* SPM_SCP_IRQ (0x10006000+0x0AC) */
+#define SC_SPM2SCP_WAKEUP_LSB (1U << 0) /* 1b */
+#define SC_SCP2SPM_WAKEUP_LSB (1U << 4) /* 1b */
+/* SPM_CPU_WAKEUP_EVENT (0x10006000+0x0B0) */
+#define REG_CPU_WAKEUP_LSB (1U << 0) /* 1b */
+/* SPM_IRQ_MASK (0x10006000+0x0B4) */
+#define REG_SPM_IRQ_MASK_LSB (1U << 0) /* 32b */
+/* DDR_EN_DBC (0x10006000+0x0B4) */
+#define REG_ALL_DDR_EN_DBC_EN_LSB (1U << 16) /* 1b */
+/* SPM_SRC_REQ (0x10006000+0x0B8) */
+#define REG_SPM_APSRC_REQ_LSB (1U << 0) /* 1b */
+#define REG_SPM_F26M_REQ_LSB (1U << 1) /* 1b */
+#define REG_SPM_INFRA_REQ_LSB (1U << 3) /* 1b */
+#define REG_SPM_VRF18_REQ_LSB (1U << 4) /* 1b */
+#define REG_SPM_DDR_EN_REQ_LSB (1U << 7) /* 1b */
+#define REG_SPM_DVFS_REQ_LSB (1U << 8) /* 1b */
+#define REG_SPM_SW_MAILBOX_REQ_LSB (1U << 9) /* 1b */
+#define REG_SPM_SSPM_MAILBOX_REQ_LSB (1U << 10) /* 1b */
+#define REG_SPM_ADSP_MAILBOX_REQ_LSB (1U << 11) /* 1b */
+#define REG_SPM_SCP_MAILBOX_REQ_LSB (1U << 12) /* 1b */
+/* SPM_SRC_MASK (0x10006000+0x0BC) */
+#define REG_MD_SRCCLKENA_0_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_MD_SRCCLKENA2INFRA_REQ_0_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_MD_APSRC2INFRA_REQ_0_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_MD_APSRC_REQ_0_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_MD_VRF18_REQ_0_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_MD_DDR_EN_0_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_MD_SRCCLKENA_1_MASK_B_LSB (1U << 6) /* 1b */
+#define REG_MD_SRCCLKENA2INFRA_REQ_1_MASK_B_LSB (1U << 7) /* 1b */
+#define REG_MD_APSRC2INFRA_REQ_1_MASK_B_LSB (1U << 8) /* 1b */
+#define REG_MD_APSRC_REQ_1_MASK_B_LSB (1U << 9) /* 1b */
+#define REG_MD_VRF18_REQ_1_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_MD_DDR_EN_1_MASK_B_LSB (1U << 11) /* 1b */
+#define REG_CONN_SRCCLKENA_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_CONN_SRCCLKENB_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_CONN_INFRA_REQ_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_CONN_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_CONN_VRF18_REQ_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_CONN_DDR_EN_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_CONN_VFE28_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_SRCCLKENI0_SRCCLKENA_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_SRCCLKENI0_INFRA_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_SRCCLKENI1_SRCCLKENA_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_SRCCLKENI1_INFRA_REQ_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_SRCCLKENI2_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_SRCCLKENI2_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_INFRASYS_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_INFRASYS_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_MD32_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_MD32_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_MD32_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_MD32_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_MD32_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */
+/* SPM_SRC2_MASK (0x10006000+0x0C0) */
+#define REG_SCP_SRCCLKENA_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_SCP_INFRA_REQ_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_SCP_APSRC_REQ_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_SCP_VRF18_REQ_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_SCP_DDR_EN_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_AUDIO_DSP_SRCCLKENA_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_AUDIO_DSP_INFRA_REQ_MASK_B_LSB (1U << 6) /* 1b */
+#define REG_AUDIO_DSP_APSRC_REQ_MASK_B_LSB (1U << 7) /* 1b */
+#define REG_AUDIO_DSP_VRF18_REQ_MASK_B_LSB (1U << 8) /* 1b */
+#define REG_AUDIO_DSP_DDR_EN_MASK_B_LSB (1U << 9) /* 1b */
+#define REG_UFS_SRCCLKENA_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_UFS_INFRA_REQ_MASK_B_LSB (1U << 11) /* 1b */
+#define REG_UFS_APSRC_REQ_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_UFS_VRF18_REQ_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_UFS_DDR_EN_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_DISP0_APSRC_REQ_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_DISP0_DDR_EN_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_DISP1_APSRC_REQ_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_DISP1_DDR_EN_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_GCE_INFRA_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_GCE_APSRC_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_GCE_VRF18_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_GCE_DDR_EN_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_APU_SRCCLKENA_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_APU_INFRA_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_APU_APSRC_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_APU_VRF18_REQ_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_APU_DDR_EN_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_CG_CHECK_SRCCLKENA_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_CG_CHECK_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_CG_CHECK_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_CG_CHECK_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */
+/* SPM_SRC3_MASK (0x10006000+0x0C4) */
+#define REG_DVFSRC_EVENT_TRIGGER_MASK_B_LSB (1U << 0) /* 1b */
+#define REG_SW2SPM_INT0_MASK_B_LSB (1U << 1) /* 1b */
+#define REG_SW2SPM_INT1_MASK_B_LSB (1U << 2) /* 1b */
+#define REG_SW2SPM_INT2_MASK_B_LSB (1U << 3) /* 1b */
+#define REG_SW2SPM_INT3_MASK_B_LSB (1U << 4) /* 1b */
+#define REG_SC_ADSP2SPM_WAKEUP_MASK_B_LSB (1U << 5) /* 1b */
+#define REG_SC_SSPM2SPM_WAKEUP_MASK_B_LSB (1U << 6) /* 4b */
+#define REG_SC_SCP2SPM_WAKEUP_MASK_B_LSB (1U << 10) /* 1b */
+#define REG_CSYSPWRREQ_MASK_LSB (1U << 11) /* 1b */
+#define REG_SPM_SRCCLKENA_RESERVED_MASK_B_LSB (1U << 12) /* 1b */
+#define REG_SPM_INFRA_REQ_RESERVED_MASK_B_LSB (1U << 13) /* 1b */
+#define REG_SPM_APSRC_REQ_RESERVED_MASK_B_LSB (1U << 14) /* 1b */
+#define REG_SPM_VRF18_REQ_RESERVED_MASK_B_LSB (1U << 15) /* 1b */
+#define REG_SPM_DDR_EN_RESERVED_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_MCUPM_SRCCLKENA_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_MCUPM_INFRA_REQ_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_MCUPM_APSRC_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_MCUPM_VRF18_REQ_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_MCUPM_DDR_EN_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_MSDC0_SRCCLKENA_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_MSDC0_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_MSDC0_APSRC_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_MSDC0_VRF18_REQ_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_MSDC0_DDR_EN_MASK_B_LSB (1U << 26) /* 1b */
+#define REG_MSDC1_SRCCLKENA_MASK_B_LSB (1U << 27) /* 1b */
+#define REG_MSDC1_INFRA_REQ_MASK_B_LSB (1U << 28) /* 1b */
+#define REG_MSDC1_APSRC_REQ_MASK_B_LSB (1U << 29) /* 1b */
+#define REG_MSDC1_VRF18_REQ_MASK_B_LSB (1U << 30) /* 1b */
+#define REG_MSDC1_DDR_EN_MASK_B_LSB (1U << 31) /* 1b */
+/* SPM_SRC4_MASK (0x10006000+0x0C8) */
+#define CCIF_EVENT_MASK_B_LSB (1U << 0) /* 16b */
+#define REG_BAK_PSRI_SRCCLKENA_MASK_B_LSB (1U << 16) /* 1b */
+#define REG_BAK_PSRI_INFRA_REQ_MASK_B_LSB (1U << 17) /* 1b */
+#define REG_BAK_PSRI_APSRC_REQ_MASK_B_LSB (1U << 18) /* 1b */
+#define REG_BAK_PSRI_VRF18_REQ_MASK_B_LSB (1U << 19) /* 1b */
+#define REG_BAK_PSRI_DDR_EN_MASK_B_LSB (1U << 20) /* 1b */
+#define REG_DRAMC0_MD32_INFRA_REQ_MASK_B_LSB (1U << 21) /* 1b */
+#define REG_DRAMC0_MD32_VRF18_REQ_MASK_B_LSB (1U << 22) /* 1b */
+#define REG_DRAMC1_MD32_INFRA_REQ_MASK_B_LSB (1U << 23) /* 1b */
+#define REG_DRAMC1_MD32_VRF18_REQ_MASK_B_LSB (1U << 24) /* 1b */
+#define REG_CONN_SRCCLKENB2PWRAP_MASK_B_LSB (1U << 25) /* 1b */
+#define REG_DRAMC0_MD32_WAKEUP_MASK_LSB (1U << 26) /* 1b */
+#define REG_DRAMC1_MD32_WAKEUP_MASK_LSB (1U << 27) /* 1b */
+/* SPM_SRC5_MASK (0x10006000+0x0CC) */
+#define REG_MCUSYS_MERGE_APSRC_REQ_MASK_B_LSB (1U << 0) /* 9b */
+#define REG_MCUSYS_MERGE_DDR_EN_MASK_B_LSB (1U << 9) /* 9b */
+/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0D0) */
+#define REG_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_EVENT_EXT_MASK (0x10006000+0x0D4) */
+#define REG_EXT_WAKEUP_EVENT_MASK_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_EVENT_CLEAR (0x10006000+0x0D8) */
+#define SPM_TWAM_EVENT_CLEAR_LSB (1U << 0) /* 1b */
+/* SCP_CLK_CON (0x10006000+0x0DC) */
+#define REG_SCP_26M_CK_SEL_LSB (1U << 0) /* 1b */
+#define REG_SCP_DCM_EN_LSB (1U << 1) /* 1b */
+#define SCP_SECURE_V_REQ_MASK_LSB (1U << 2) /* 1b */
+#define SCP_SLP_REQ_LSB (1U << 3) /* 1b */
+#define SCP_SLP_ACK_LSB (1U << 4) /* 1b */
+/* SPM_RESOURCE_ACK_CON0 (0x10006000+0x0F0) */
+#define REG_MD_SRCCLKENA_ACK_0_MASK_LSB (1U << 0) /* 1b */
+#define REG_MD_INFRA_ACK_0_MASK_LSB (1U << 1) /* 1b */
+#define REG_MD_APSRC_ACK_0_MASK_LSB (1U << 2) /* 1b */
+#define REG_MD_VRF18_ACK_0_MASK_LSB (1U << 3) /* 1b */
+#define REG_MD_DDR_EN_ACK_0_MASK_LSB (1U << 4) /* 1b */
+#define REG_MD_SRCCLKENA_ACK_1_MASK_LSB (1U << 5) /* 1b */
+#define REG_MD_INFRA_ACK_1_MASK_LSB (1U << 6) /* 1b */
+#define REG_MD_APSRC_ACK_1_MASK_LSB (1U << 7) /* 1b */
+#define REG_MD_VRF18_ACK_1_MASK_LSB (1U << 8) /* 1b */
+#define REG_MD_DDR_EN_ACK_1_MASK_LSB (1U << 9) /* 1b */
+#define REG_CONN_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_CONN_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_CONN_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_CONN_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_CONN_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_MD32_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_MD32_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_MD32_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_MD32_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_MD32_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_SCP_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_SCP_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_SCP_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_SCP_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_SCP_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_AUDIO_DSP_SRCCLKENA_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_AUDIO_DSP_INFRA_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_AUDIO_DSP_APSRC_ACK_MASK_LSB (1U << 27) /* 1b */
+#define REG_AUDIO_DSP_VRF18_ACK_MASK_LSB (1U << 28) /* 1b */
+#define REG_AUDIO_DSP_DDR_EN_ACK_MASK_LSB (1U << 29) /* 1b */
+#define REG_DISP0_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */
+#define REG_DISP1_APSRC_ACK_MASK_LSB (1U << 31) /* 1b */
+/* SPM_RESOURCE_ACK_CON1 (0x10006000+0x0F4) */
+#define REG_UFS_SRCCLKENA_ACK_MASK_LSB (1U << 0) /* 1b */
+#define REG_UFS_INFRA_ACK_MASK_LSB (1U << 1) /* 1b */
+#define REG_UFS_APSRC_ACK_MASK_LSB (1U << 2) /* 1b */
+#define REG_UFS_VRF18_ACK_MASK_LSB (1U << 3) /* 1b */
+#define REG_UFS_DDR_EN_ACK_MASK_LSB (1U << 4) /* 1b */
+#define REG_APU_SRCCLKENA_ACK_MASK_LSB (1U << 5) /* 1b */
+#define REG_APU_INFRA_ACK_MASK_LSB (1U << 6) /* 1b */
+#define REG_APU_APSRC_ACK_MASK_LSB (1U << 7) /* 1b */
+#define REG_APU_VRF18_ACK_MASK_LSB (1U << 8) /* 1b */
+#define REG_APU_DDR_EN_ACK_MASK_LSB (1U << 9) /* 1b */
+#define REG_MCUPM_SRCCLKENA_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_MCUPM_INFRA_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_MCUPM_APSRC_ACK_MASK_LSB (1U << 12) /* 1b */
+#define REG_MCUPM_VRF18_ACK_MASK_LSB (1U << 13) /* 1b */
+#define REG_MCUPM_DDR_EN_ACK_MASK_LSB (1U << 14) /* 1b */
+#define REG_MSDC0_SRCCLKENA_ACK_MASK_LSB (1U << 15) /* 1b */
+#define REG_MSDC0_INFRA_ACK_MASK_LSB (1U << 16) /* 1b */
+#define REG_MSDC0_APSRC_ACK_MASK_LSB (1U << 17) /* 1b */
+#define REG_MSDC0_VRF18_ACK_MASK_LSB (1U << 18) /* 1b */
+#define REG_MSDC0_DDR_EN_ACK_MASK_LSB (1U << 19) /* 1b */
+#define REG_MSDC1_SRCCLKENA_ACK_MASK_LSB (1U << 20) /* 1b */
+#define REG_MSDC1_INFRA_ACK_MASK_LSB (1U << 21) /* 1b */
+#define REG_MSDC1_APSRC_ACK_MASK_LSB (1U << 22) /* 1b */
+#define REG_MSDC1_VRF18_ACK_MASK_LSB (1U << 23) /* 1b */
+#define REG_MSDC1_DDR_EN_ACK_MASK_LSB (1U << 24) /* 1b */
+#define REG_DISP0_APSRC_ACK_MASK_LSB (1U << 25) /* 1b */
+#define REG_DISP1_DDR_EN_ACK_MASK_LSB (1U << 26) /* 1b */
+#define REG_GCE_INFRA_ACK_MASK_LSB (1U << 27) /* 1b */
+#define REG_GCE_APSRC_ACK_MASK_LSB (1U << 28) /* 1b */
+#define REG_GCE_VRF18_ACK_MASK_LSB (1U << 29) /* 1b */
+#define REG_GCE_DDR_EN_ACK_MASK_LSB (1U << 30) /* 1b */
+/* SPM_RESOURCE_ACK_CON2 (0x10006000+0x0F8) */
+#define SPM_F26M_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */
+#define SPM_INFRA_ACK_WAIT_CYCLE_LSB (1U << 8) /* 8b */
+#define SPM_APSRC_ACK_WAIT_CYCLE_LSB (1U << 16) /* 8b */
+#define SPM_VRF18_ACK_WAIT_CYCLE_LSB (1U << 24) /* 8b */
+/* SPM_RESOURCE_ACK_CON3 (0x10006000+0x0FC) */
+#define SPM_DDR_EN_ACK_WAIT_CYCLE_LSB (1U << 0) /* 8b */
+#define REG_BAK_PSRI_SRCCLKENA_ACK_MASK_LSB (1U << 8) /* 1b */
+#define REG_BAK_PSRI_INFRA_ACK_MASK_LSB (1U << 9) /* 1b */
+#define REG_BAK_PSRI_APSRC_ACK_MASK_LSB (1U << 10) /* 1b */
+#define REG_BAK_PSRI_VRF18_ACK_MASK_LSB (1U << 11) /* 1b */
+#define REG_BAK_PSRI_DDR_EN_ACK_MASK_LSB (1U << 12) /* 1b */
+/* PCM_REG0_DATA (0x10006000+0x100) */
+#define PCM_REG0_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG2_DATA (0x10006000+0x104) */
+#define PCM_REG2_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG6_DATA (0x10006000+0x108) */
+#define PCM_REG6_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG7_DATA (0x10006000+0x10C) */
+#define PCM_REG7_RF_LSB (1U << 0) /* 32b */
+/* PCM_REG13_DATA (0x10006000+0x110) */
+#define PCM_REG13_RF_LSB (1U << 0) /* 32b */
+/* SRC_REQ_STA_0 (0x10006000+0x114) */
+#define MD_SRCCLKENA_0_LSB (1U << 0) /* 1b */
+#define MD_SRCCLKENA2INFRA_REQ_0_LSB (1U << 1) /* 1b */
+#define MD_APSRC2INFRA_REQ_0_LSB (1U << 2) /* 1b */
+#define MD_APSRC_REQ_0_LSB (1U << 3) /* 1b */
+#define MD_VRF18_REQ_0_LSB (1U << 4) /* 1b */
+#define MD_DDR_EN_0_LSB (1U << 5) /* 1b */
+#define MD_SRCCLKENA_1_LSB (1U << 6) /* 1b */
+#define MD_SRCCLKENA2INFRA_REQ_1_LSB (1U << 7) /* 1b */
+#define MD_APSRC2INFRA_REQ_1_LSB (1U << 8) /* 1b */
+#define MD_APSRC_REQ_1_LSB (1U << 9) /* 1b */
+#define MD_VRF18_REQ_1_LSB (1U << 10) /* 1b */
+#define MD_DDR_EN_1_LSB (1U << 11) /* 1b */
+#define CONN_SRCCLKENA_LSB (1U << 12) /* 1b */
+#define CONN_SRCCLKENB_LSB (1U << 13) /* 1b */
+#define CONN_INFRA_REQ_LSB (1U << 14) /* 1b */
+#define CONN_APSRC_REQ_LSB (1U << 15) /* 1b */
+#define CONN_VRF18_REQ_LSB (1U << 16) /* 1b */
+#define CONN_DDR_EN_LSB (1U << 17) /* 1b */
+#define SRCCLKENI_LSB (1U << 18) /* 3b */
+#define MD32_SRCCLKENA_LSB (1U << 21) /* 1b */
+#define MD32_INFRA_REQ_LSB (1U << 22) /* 1b */
+#define MD32_APSRC_REQ_LSB (1U << 23) /* 1b */
+#define MD32_VRF18_REQ_LSB (1U << 24) /* 1b */
+#define MD32_DDR_EN_LSB (1U << 25) /* 1b */
+#define DISP0_APSRC_REQ_LSB (1U << 26) /* 1b */
+#define DISP0_DDR_EN_LSB (1U << 27) /* 1b */
+#define DISP1_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define DISP1_DDR_EN_LSB (1U << 29) /* 1b */
+#define DVFSRC_EVENT_TRIGGER_LSB (1U << 30) /* 1b */
+/* SRC_REQ_STA_1 (0x10006000+0x118) */
+#define SCP_SRCCLKENA_LSB (1U << 0) /* 1b */
+#define SCP_INFRA_REQ_LSB (1U << 1) /* 1b */
+#define SCP_APSRC_REQ_LSB (1U << 2) /* 1b */
+#define SCP_VRF18_REQ_LSB (1U << 3) /* 1b */
+#define SCP_DDR_EN_LSB (1U << 4) /* 1b */
+#define AUDIO_DSP_SRCCLKENA_LSB (1U << 5) /* 1b */
+#define AUDIO_DSP_INFRA_REQ_LSB (1U << 6) /* 1b */
+#define AUDIO_DSP_APSRC_REQ_LSB (1U << 7) /* 1b */
+#define AUDIO_DSP_VRF18_REQ_LSB (1U << 8) /* 1b */
+#define AUDIO_DSP_DDR_EN_LSB (1U << 9) /* 1b */
+#define UFS_SRCCLKENA_LSB (1U << 10) /* 1b */
+#define UFS_INFRA_REQ_LSB (1U << 11) /* 1b */
+#define UFS_APSRC_REQ_LSB (1U << 12) /* 1b */
+#define UFS_VRF18_REQ_LSB (1U << 13) /* 1b */
+#define UFS_DDR_EN_LSB (1U << 14) /* 1b */
+#define GCE_INFRA_REQ_LSB (1U << 15) /* 1b */
+#define GCE_APSRC_REQ_LSB (1U << 16) /* 1b */
+#define GCE_VRF18_REQ_LSB (1U << 17) /* 1b */
+#define GCE_DDR_EN_LSB (1U << 18) /* 1b */
+#define INFRASYS_APSRC_REQ_LSB (1U << 19) /* 1b */
+#define INFRASYS_DDR_EN_LSB (1U << 20) /* 1b */
+#define MSDC0_SRCCLKENA_LSB (1U << 21) /* 1b */
+#define MSDC0_INFRA_REQ_LSB (1U << 22) /* 1b */
+#define MSDC0_APSRC_REQ_LSB (1U << 23) /* 1b */
+#define MSDC0_VRF18_REQ_LSB (1U << 24) /* 1b */
+#define MSDC0_DDR_EN_LSB (1U << 25) /* 1b */
+#define MSDC1_SRCCLKENA_LSB (1U << 26) /* 1b */
+#define MSDC1_INFRA_REQ_LSB (1U << 27) /* 1b */
+#define MSDC1_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define MSDC1_VRF18_REQ_LSB (1U << 29) /* 1b */
+#define MSDC1_DDR_EN_LSB (1U << 30) /* 1b */
+/* SRC_REQ_STA_2 (0x10006000+0x11C) */
+#define MCUSYS_MERGE_DDR_EN_LSB (1U << 0) /* 9b */
+#define EMI_SELF_REFRESH_CH_LSB (1U << 9) /* 2b */
+#define SW2SPM_INT_LSB (1U << 11) /* 4b */
+#define SC_ADSP2SPM_WAKEUP_LSB (1U << 15) /* 1b */
+#define SC_SSPM2SPM_WAKEUP_LSB (1U << 16) /* 4b */
+#define SRC_REQ_STA_2_SC_SCP2SPM_WAKEUP_LSB (1U << 20) /* 1b */
+#define SPM_SRCCLKENA_RESERVED_LSB (1U << 21) /* 1b */
+#define SPM_INFRA_REQ_RESERVED_LSB (1U << 22) /* 1b */
+#define SPM_APSRC_REQ_RESERVED_LSB (1U << 23) /* 1b */
+#define SPM_VRF18_REQ_RESERVED_LSB (1U << 24) /* 1b */
+#define SPM_DDR_EN_RESERVED_LSB (1U << 25) /* 1b */
+#define MCUPM_SRCCLKENA_LSB (1U << 26) /* 1b */
+#define MCUPM_INFRA_REQ_LSB (1U << 27) /* 1b */
+#define MCUPM_APSRC_REQ_LSB (1U << 28) /* 1b */
+#define MCUPM_VRF18_REQ_LSB (1U << 29) /* 1b */
+#define MCUPM_DDR_EN_LSB (1U << 30) /* 1b */
+/* PCM_TIMER_OUT (0x10006000+0x120) */
+#define PCM_TIMER_LSB (1U << 0) /* 32b */
+/* PCM_WDT_OUT (0x10006000+0x124) */
+#define PCM_WDT_TIMER_VAL_OUT_LSB (1U << 0) /* 32b */
+/* SPM_IRQ_STA (0x10006000+0x128) */
+#define TWAM_IRQ_LSB (1U << 2) /* 1b */
+#define PCM_IRQ_LSB (1U << 3) /* 1b */
+/* SRC_REQ_STA_4 (0x10006000+0x12C) */
+#define APU_SRCCLKENA_LSB (1U << 0) /* 1b */
+#define APU_INFRA_REQ_LSB (1U << 1) /* 1b */
+#define APU_APSRC_REQ_LSB (1U << 2) /* 1b */
+#define APU_VRF18_REQ_LSB (1U << 3) /* 1b */
+#define APU_DDR_EN_LSB (1U << 4) /* 1b */
+#define BAK_PSRI_SRCCLKENA_LSB (1U << 5) /* 1b */
+#define BAK_PSRI_INFRA_REQ_LSB (1U << 6) /* 1b */
+#define BAK_PSRI_APSRC_REQ_LSB (1U << 7) /* 1b */
+#define BAK_PSRI_VRF18_REQ_LSB (1U << 8) /* 1b */
+#define BAK_PSRI_DDR_EN_LSB (1U << 9) /* 1b */
+/* MD32PCM_WAKEUP_STA (0x10006000+0x130) */
+#define MD32PCM_WAKEUP_STA_LSB (1U << 0) /* 32b */
+/* MD32PCM_EVENT_STA (0x10006000+0x134) */
+#define MD32PCM_EVENT_STA_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_STA (0x10006000+0x138) */
+#define F32K_WAKEUP_EVENT_L_LSB (1U << 0) /* 16b */
+#define ASYN_WAKEUP_EVENT_L_LSB (1U << 16) /* 16b */
+/* SPM_WAKEUP_EXT_STA (0x10006000+0x13C) */
+#define EXT_WAKEUP_EVENT_LSB (1U << 0) /* 32b */
+/* SPM_WAKEUP_MISC (0x10006000+0x140) */
+#define GIC_WAKEUP_LSB (1U << 0) /* 10b */
+#define DVFSRC_IRQ_LSB (1U << 16) /* 1b */
+#define SPM_WAKEUP_MISC_REG_CPU_WAKEUP_LSB (1U << 17) /* 1b */
+#define PCM_TIMER_EVENT_LSB (1U << 18) /* 1b */
+#define PMIC_EINT_OUT_B_LSB (1U << 19) /* 2b */
+#define TWAM_IRQ_B_LSB (1U << 21) /* 1b */
+#define PMSR_IRQ_B_SET0_LSB (1U << 22) /* 1b */
+#define PMSR_IRQ_B_SET1_LSB (1U << 23) /* 1b */
+#define PMSR_IRQ_B_SET2_LSB (1U << 24) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_0_LSB (1U << 25) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_1_LSB (1U << 26) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_2_LSB (1U << 27) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_3_LSB (1U << 28) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_ALL_LSB (1U << 29) /* 1b */
+#define PMIC_IRQ_ACK_LSB (1U << 30) /* 1b */
+#define PMIC_SCP_IRQ_LSB (1U << 31) /* 1b */
+/* MM_DVFS_HALT (0x10006000+0x144) */
+#define MM_DVFS_HALT_LSB (1U << 0) /* 5b */
+/* BUS_PROTECT_RDY (0x10006000+0x150) */
+#define PROTECT_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT1_RDY (0x10006000+0x154) */
+#define PROTECT1_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT2_RDY (0x10006000+0x158) */
+#define PROTECT2_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT3_RDY (0x10006000+0x15C) */
+#define PROTECT3_READY_LSB (1U << 0) /* 32b */
+/* SUBSYS_IDLE_STA (0x10006000+0x160) */
+#define SUBSYS_IDLE_SIGNALS_LSB (1U << 0) /* 32b */
+/* PCM_STA (0x10006000+0x164) */
+#define PCM_CK_SEL_O_LSB (1U << 0) /* 4b */
+#define EXT_SRC_STA_LSB (1U << 4) /* 3b */
+/* SRC_REQ_STA_3 (0x10006000+0x168) */
+#define CCIF_EVENT_RAW_STATUS_LSB (1U << 0) /* 16b */
+#define F26M_STATE_LSB (1U << 16) /* 1b */
+#define INFRA_STATE_LSB (1U << 17) /* 1b */
+#define APSRC_STATE_LSB (1U << 18) /* 1b */
+#define VRF18_STATE_LSB (1U << 19) /* 1b */
+#define DDR_EN_STATE_LSB (1U << 20) /* 1b */
+#define DVFS_STATE_LSB (1U << 21) /* 1b */
+#define SW_MAILBOX_STATE_LSB (1U << 22) /* 1b */
+#define SSPM_MAILBOX_STATE_LSB (1U << 23) /* 1b */
+#define ADSP_MAILBOX_STATE_LSB (1U << 24) /* 1b */
+#define SCP_MAILBOX_STATE_LSB (1U << 25) /* 1b */
+/* PWR_STATUS (0x10006000+0x16C) */
+#define PWR_STATUS_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_2ND (0x10006000+0x170) */
+#define PWR_STATUS_2ND_LSB (1U << 0) /* 32b */
+/* CPU_PWR_STATUS (0x10006000+0x174) */
+#define MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 1) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 3) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 4) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 5) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 6) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 7) /* 1b */
+#define MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 8) /* 1b */
+#define MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 9) /* 1b */
+/* OTHER_PWR_STATUS (0x10006000+0x178) */
+#define OTHER_PWR_STATUS_LSB (1U << 0) /* 32b */
+/* SPM_VTCXO_EVENT_COUNT_STA (0x10006000+0x17C) */
+#define SPM_VTCXO_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_VTCXO_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_INFRA_EVENT_COUNT_STA (0x10006000+0x180) */
+#define SPM_INFRA_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_INFRA_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_VRF18_EVENT_COUNT_STA (0x10006000+0x184) */
+#define SPM_VRF18_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_VRF18_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_APSRC_EVENT_COUNT_STA (0x10006000+0x188) */
+#define SPM_APSRC_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_APSRC_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* SPM_DDREN_EVENT_COUNT_STA (0x10006000+0x18C) */
+#define SPM_DDREN_SLEEP_COUNT_LSB (1U << 0) /* 16b */
+#define SPM_DDREN_WAKE_COUNT_LSB (1U << 16) /* 16b */
+/* MD32PCM_STA (0x10006000+0x190) */
+#define MD32PCM_HALT_LSB (1U << 0) /* 1b */
+#define MD32PCM_GATED_LSB (1U << 1) /* 1b */
+/* MD32PCM_PC (0x10006000+0x194) */
+#define MON_PC_LSB (1U << 0) /* 32b */
+/* DVFSRC_EVENT_STA (0x10006000+0x1A4) */
+#define DVFSRC_EVENT_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT4_RDY (0x10006000+0x1A8) */
+#define PROTECT4_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT5_RDY (0x10006000+0x1AC) */
+#define PROTECT5_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT6_RDY (0x10006000+0x1B0) */
+#define PROTECT6_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT7_RDY (0x10006000+0x1B4) */
+#define PROTECT7_READY_LSB (1U << 0) /* 32b */
+/* BUS_PROTECT8_RDY (0x10006000+0x1B8) */
+#define PROTECT8_READY_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA0 (0x10006000+0x1D0) */
+#define LAST_IDLE_CNT_0_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA1 (0x10006000+0x1D4) */
+#define LAST_IDLE_CNT_1_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA2 (0x10006000+0x1D8) */
+#define LAST_IDLE_CNT_2_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_LAST_STA3 (0x10006000+0x1DC) */
+#define LAST_IDLE_CNT_3_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA0 (0x10006000+0x1E0) */
+#define CURRENT_IDLE_CNT_0_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA1 (0x10006000+0x1E4) */
+#define CURRENT_IDLE_CNT_1_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA2 (0x10006000+0x1E8) */
+#define CURRENT_IDLE_CNT_2_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_CURR_STA3 (0x10006000+0x1EC) */
+#define CURRENT_IDLE_CNT_3_LSB (1U << 0) /* 32b */
+/* SPM_TWAM_TIMER_OUT (0x10006000+0x1F0) */
+#define TWAM_TIMER_LSB (1U << 0) /* 32b */
+/* SPM_CG_CHECK_STA (0x10006000+0x1F4) */
+#define SPM_CG_CHECK_SLEEP_REQ_0_LSB (1U << 0) /* 1b */
+#define SPM_CG_CHECK_SLEEP_REQ_1_LSB (1U << 1) /* 1b */
+#define SPM_CG_CHECK_SLEEP_REQ_2_LSB (1U << 2) /* 1b */
+/* SPM_DVFS_STA (0x10006000+0x1F8) */
+#define TARGET_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_OPP_STA (0x10006000+0x1FC) */
+#define TARGET_DVFS_OPP_LSB (1U << 0) /* 5b */
+#define CURRENT_DVFS_OPP_LSB (1U << 5) /* 5b */
+#define RELAY_DVFS_OPP_LSB (1U << 10) /* 5b */
+/* SPM_MCUSYS_PWR_CON (0x10006000+0x200) */
+#define MCUSYS_SPMC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MCUSYS_SPMC_PWR_ON_LSB (1U << 2) /* 1b */
+#define MCUSYS_SPMC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MCUSYS_SPMC_RESETPWRON_CONFIG_LSB (1U << 5) /* 1b */
+#define MCUSYS_SPMC_DORMANT_EN_LSB (1U << 6) /* 1b */
+#define MCUSYS_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */
+#define SPM_MCUSYS_PWR_CON_MCUSYS_SPMC_PWR_ON_ACK_LSB (1U << 31) /* 1b */
+/* SPM_CPUTOP_PWR_CON (0x10006000+0x204) */
+#define MP0_SPMC_PWR_RST_B_CPUTOP_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPUTOP_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_PWR_CLK_DIS_CPUTOP_LSB (1U << 4) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPUTOP_LSB (1U << 5) /* 1b */
+#define MP0_SPMC_DORMANT_EN_CPUTOP_LSB (1U << 6) /* 1b */
+#define MP0_VPROC_EXT_OFF_LSB (1U << 7) /* 1b */
+#define MP0_VSRAM_EXT_OFF_LSB (1U << 8) /* 1b */
+#define SPM_CPUTOP_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPUTOP_LSB (1U << 31) /* 1b */
+/* SPM_CPU0_PWR_CON (0x10006000+0x208) */
+#define MP0_SPMC_PWR_RST_B_CPU0_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU0_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU0_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU0_LSB (1U << 7) /* 1b */
+#define SPM_CPU0_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU0_LSB (1U << 31) /* 1b */
+/* SPM_CPU1_PWR_CON (0x10006000+0x20C) */
+#define MP0_SPMC_PWR_RST_B_CPU1_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU1_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU1_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU1_LSB (1U << 7) /* 1b */
+#define SPM_CPU1_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU1_LSB (1U << 31) /* 1b */
+/* SPM_CPU2_PWR_CON (0x10006000+0x210) */
+#define MP0_SPMC_PWR_RST_B_CPU2_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU2_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU2_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU2_LSB (1U << 7) /* 1b */
+#define SPM_CPU2_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU2_LSB (1U << 31) /* 1b */
+/* SPM_CPU3_PWR_CON (0x10006000+0x214) */
+#define MP0_SPMC_PWR_RST_B_CPU3_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU3_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU3_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU3_LSB (1U << 7) /* 1b */
+#define SPM_CPU3_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU3_LSB (1U << 31) /* 1b */
+/* SPM_CPU4_PWR_CON (0x10006000+0x218) */
+#define MP0_SPMC_PWR_RST_B_CPU4_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU4_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU4_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU4_LSB (1U << 7) /* 1b */
+#define SPM_CPU4_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU4_LSB (1U << 31) /* 1b */
+/* SPM_CPU5_PWR_CON (0x10006000+0x21C) */
+#define MP0_SPMC_PWR_RST_B_CPU5_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU5_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU5_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU5_LSB (1U << 7) /* 1b */
+#define SPM_CPU5_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU5_LSB (1U << 31) /* 1b */
+/* SPM_CPU6_PWR_CON (0x10006000+0x220) */
+#define MP0_SPMC_PWR_RST_B_CPU6_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU6_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU6_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU6_LSB (1U << 7) /* 1b */
+#define SPM_CPU6_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU6_LSB (1U << 31) /* 1b */
+/* SPM_CPU7_PWR_CON (0x10006000+0x224) */
+#define MP0_SPMC_PWR_RST_B_CPU7_LSB (1U << 0) /* 1b */
+#define MP0_SPMC_PWR_ON_CPU7_LSB (1U << 2) /* 1b */
+#define MP0_SPMC_RESETPWRON_CONFIG_CPU7_LSB (1U << 5) /* 1b */
+#define MP0_VPROC_EXT_OFF_CPU7_LSB (1U << 7) /* 1b */
+#define SPM_CPU7_PWR_CON_MP0_SPMC_PWR_ON_ACK_CPU7_LSB (1U << 31) /* 1b */
+/* ARMPLL_CLK_CON (0x10006000+0x22C) */
+#define SC_ARM_FHC_PAUSE_LSB (1U << 0) /* 6b */
+#define SC_ARM_CK_OFF_LSB (1U << 6) /* 6b */
+#define SC_ARMPLL_OFF_LSB (1U << 12) /* 1b */
+#define SC_ARMBPLL_OFF_LSB (1U << 13) /* 1b */
+#define SC_ARMBPLL1_OFF_LSB (1U << 14) /* 1b */
+#define SC_ARMBPLL2_OFF_LSB (1U << 15) /* 1b */
+#define SC_ARMBPLL3_OFF_LSB (1U << 16) /* 1b */
+#define SC_CCIPLL_CKOFF_LSB (1U << 17) /* 1b */
+#define SC_ARMDDS_OFF_LSB (1U << 18) /* 1b */
+#define SC_ARMBPLL_S_OFF_LSB (1U << 19) /* 1b */
+#define SC_ARMBPLL1_S_OFF_LSB (1U << 20) /* 1b */
+#define SC_ARMBPLL2_S_OFF_LSB (1U << 21) /* 1b */
+#define SC_ARMBPLL3_S_OFF_LSB (1U << 22) /* 1b */
+#define SC_CCIPLL_PWROFF_LSB (1U << 23) /* 1b */
+#define SC_ARMPLLOUT_OFF_LSB (1U << 24) /* 1b */
+#define SC_ARMBPLLOUT_OFF_LSB (1U << 25) /* 1b */
+#define SC_ARMBPLLOUT1_OFF_LSB (1U << 26) /* 1b */
+#define SC_ARMBPLLOUT2_OFF_LSB (1U << 27) /* 1b */
+#define SC_ARMBPLLOUT3_OFF_LSB (1U << 28) /* 1b */
+#define SC_CCIPLL_OUT_OFF_LSB (1U << 29) /* 1b */
+/* MCUSYS_IDLE_STA (0x10006000+0x230) */
+#define ARMBUS_IDLE_TO_26M_LSB (1U << 0) /* 1b */
+#define MP0_CLUSTER_IDLE_TO_PWR_OFF_LSB (1U << 1) /* 1b */
+#define MCUSYS_DDR_EN_0_LSB (1U << 2) /* 1b */
+#define MCUSYS_DDR_EN_1_LSB (1U << 3) /* 1b */
+#define MCUSYS_DDR_EN_2_LSB (1U << 4) /* 1b */
+#define MCUSYS_DDR_EN_3_LSB (1U << 5) /* 1b */
+#define MCUSYS_DDR_EN_4_LSB (1U << 6) /* 1b */
+#define MCUSYS_DDR_EN_5_LSB (1U << 7) /* 1b */
+#define MCUSYS_DDR_EN_6_LSB (1U << 8) /* 1b */
+#define MCUSYS_DDR_EN_7_LSB (1U << 9) /* 1b */
+#define MP0_CPU_IDLE_TO_PWR_OFF_LSB (1U << 16) /* 8b */
+#define WFI_AF_SEL_LSB (1U << 24) /* 8b */
+/* GIC_WAKEUP_STA (0x10006000+0x234) */
+#define GIC_WAKEUP_STA_GIC_WAKEUP_LSB (1U << 10) /* 10b */
+/* CPU_SPARE_CON (0x10006000+0x238) */
+#define CPU_SPARE_CON_LSB (1U << 0) /* 32b */
+/* CPU_SPARE_CON_SET (0x10006000+0x23C) */
+#define CPU_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+/* CPU_SPARE_CON_CLR (0x10006000+0x240) */
+#define CPU_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+/* ARMPLL_CLK_SEL (0x10006000+0x244) */
+#define ARMPLL_CLK_SEL_LSB (1U << 0) /* 15b */
+/* EXT_INT_WAKEUP_REQ (0x10006000+0x248) */
+#define EXT_INT_WAKEUP_REQ_LSB (1U << 0) /* 10b */
+/* EXT_INT_WAKEUP_REQ_SET (0x10006000+0x24C) */
+#define EXT_INT_WAKEUP_REQ_SET_LSB (1U << 0) /* 10b */
+/* EXT_INT_WAKEUP_REQ_CLR (0x10006000+0x250) */
+#define EXT_INT_WAKEUP_REQ_CLR_LSB (1U << 0) /* 10b */
+/* MP0_CPU0_IRQ_MASK (0x10006000+0x260) */
+#define MP0_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU0_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU1_IRQ_MASK (0x10006000+0x264) */
+#define MP0_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU1_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU2_IRQ_MASK (0x10006000+0x268) */
+#define MP0_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU2_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU3_IRQ_MASK (0x10006000+0x26C) */
+#define MP0_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP0_CPU3_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU0_IRQ_MASK (0x10006000+0x270) */
+#define MP1_CPU0_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU0_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU1_IRQ_MASK (0x10006000+0x274) */
+#define MP1_CPU1_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU1_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU2_IRQ_MASK (0x10006000+0x278) */
+#define MP1_CPU2_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU2_AUX_LSB (1U << 8) /* 11b */
+/* MP1_CPU3_IRQ_MASK (0x10006000+0x27C) */
+#define MP1_CPU3_IRQ_MASK_LSB (1U << 0) /* 1b */
+#define MP1_CPU3_AUX_LSB (1U << 8) /* 11b */
+/* MP0_CPU0_WFI_EN (0x10006000+0x280) */
+#define MP0_CPU0_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU1_WFI_EN (0x10006000+0x284) */
+#define MP0_CPU1_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU2_WFI_EN (0x10006000+0x288) */
+#define MP0_CPU2_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU3_WFI_EN (0x10006000+0x28C) */
+#define MP0_CPU3_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU4_WFI_EN (0x10006000+0x290) */
+#define MP0_CPU4_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU5_WFI_EN (0x10006000+0x294) */
+#define MP0_CPU5_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU6_WFI_EN (0x10006000+0x298) */
+#define MP0_CPU6_WFI_EN_LSB (1U << 0) /* 1b */
+/* MP0_CPU7_WFI_EN (0x10006000+0x29C) */
+#define MP0_CPU7_WFI_EN_LSB (1U << 0) /* 1b */
+/* ROOT_CPUTOP_ADDR (0x10006000+0x2A0) */
+#define ROOT_CPUTOP_ADDR_LSB (1U << 0) /* 32b */
+/* ROOT_CORE_ADDR (0x10006000+0x2A4) */
+#define ROOT_CORE_ADDR_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_0 (0x10006000+0x2D0) */
+#define SPM2SW_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_1 (0x10006000+0x2D4) */
+#define SPM2SW_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_2 (0x10006000+0x2D8) */
+#define SPM2SW_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SPM2SW_MAILBOX_3 (0x10006000+0x2DC) */
+#define SPM2SW_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* SW2SPM_INT (0x10006000+0x2E0) */
+#define SW2SPM_INT_SW2SPM_INT_LSB (1U << 0) /* 4b */
+/* SW2SPM_INT_SET (0x10006000+0x2E4) */
+#define SW2SPM_INT_SET_LSB (1U << 0) /* 4b */
+/* SW2SPM_INT_CLR (0x10006000+0x2E8) */
+#define SW2SPM_INT_CLR_LSB (1U << 0) /* 4b */
+/* SW2SPM_MAILBOX_0 (0x10006000+0x2EC) */
+#define SW2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_1 (0x10006000+0x2F0) */
+#define SW2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_2 (0x10006000+0x2F4) */
+#define SW2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SW2SPM_MAILBOX_3 (0x10006000+0x2F8) */
+#define SW2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* SW2SPM_CFG (0x10006000+0x2FC) */
+#define SWU2SPM_INT_MASK_B_LSB (1U << 0) /* 4b */
+/* MD1_PWR_CON (0x10006000+0x300) */
+#define MD1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MD1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MD1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MD1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MD1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MD1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MD1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CONN_PWR_CON (0x10006000+0x304) */
+#define CONN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CONN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CONN_PWR_ON_LSB (1U << 2) /* 1b */
+#define CONN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CONN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+/* MFG0_PWR_CON (0x10006000+0x308) */
+#define MFG0_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG0_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG0_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG0_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG0_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG0_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG0_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG1_PWR_CON (0x10006000+0x30C) */
+#define MFG1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG1_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG2_PWR_CON (0x10006000+0x310) */
+#define MFG2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG2_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG3_PWR_CON (0x10006000+0x314) */
+#define MFG3_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG3_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG3_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG3_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG3_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG3_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG3_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG4_PWR_CON (0x10006000+0x318) */
+#define MFG4_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG4_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG4_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG4_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG4_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG4_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG4_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG5_PWR_CON (0x10006000+0x31C) */
+#define MFG5_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG5_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG5_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG5_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG5_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG5_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG5_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MFG6_PWR_CON (0x10006000+0x320) */
+#define MFG6_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MFG6_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MFG6_PWR_ON_LSB (1U << 2) /* 1b */
+#define MFG6_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MFG6_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MFG6_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MFG6_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* IFR_PWR_CON (0x10006000+0x324) */
+#define IFR_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IFR_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IFR_PWR_ON_LSB (1U << 2) /* 1b */
+#define IFR_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IFR_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IFR_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IFR_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* IFR_SUB_PWR_CON (0x10006000+0x328) */
+#define IFR_SUB_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IFR_SUB_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IFR_SUB_PWR_ON_LSB (1U << 2) /* 1b */
+#define IFR_SUB_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IFR_SUB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IFR_SUB_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IFR_SUB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* DPY_PWR_CON (0x10006000+0x32C) */
+#define DPY_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DPY_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DPY_PWR_ON_LSB (1U << 2) /* 1b */
+#define DPY_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DPY_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DPY_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DPY_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* ISP_PWR_CON (0x10006000+0x330) */
+#define ISP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ISP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ISP_PWR_ON_LSB (1U << 2) /* 1b */
+#define ISP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ISP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ISP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_ISP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* ISP2_PWR_CON (0x10006000+0x334) */
+#define ISP2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ISP2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ISP2_PWR_ON_LSB (1U << 2) /* 1b */
+#define ISP2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ISP2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ISP2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_ISP2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* IPE_PWR_CON (0x10006000+0x338) */
+#define IPE_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define IPE_PWR_ISO_LSB (1U << 1) /* 1b */
+#define IPE_PWR_ON_LSB (1U << 2) /* 1b */
+#define IPE_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define IPE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define IPE_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_IPE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VDE_PWR_CON (0x10006000+0x33C) */
+#define VDE_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VDE_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VDE_PWR_ON_LSB (1U << 2) /* 1b */
+#define VDE_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VDE_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VDE_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VDE_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VDE2_PWR_CON (0x10006000+0x340) */
+#define VDE2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VDE2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VDE2_PWR_ON_LSB (1U << 2) /* 1b */
+#define VDE2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VDE2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VDE2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VDE2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VEN_PWR_CON (0x10006000+0x344) */
+#define VEN_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VEN_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VEN_PWR_ON_LSB (1U << 2) /* 1b */
+#define VEN_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VEN_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VEN_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VEN_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* VEN_CORE1_PWR_CON (0x10006000+0x348) */
+#define VEN_CORE1_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define VEN_CORE1_PWR_ISO_LSB (1U << 1) /* 1b */
+#define VEN_CORE1_PWR_ON_LSB (1U << 2) /* 1b */
+#define VEN_CORE1_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define VEN_CORE1_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define VEN_CORE1_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_VEN_CORE1_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* MDP_PWR_CON (0x10006000+0x34C) */
+#define MDP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define MDP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define MDP_PWR_ON_LSB (1U << 2) /* 1b */
+#define MDP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define MDP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define MDP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_MDP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* DIS_PWR_CON (0x10006000+0x350) */
+#define DIS_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DIS_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DIS_PWR_ON_LSB (1U << 2) /* 1b */
+#define DIS_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DIS_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DIS_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DIS_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* AUDIO_PWR_CON (0x10006000+0x354) */
+#define AUDIO_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define AUDIO_PWR_ISO_LSB (1U << 1) /* 1b */
+#define AUDIO_PWR_ON_LSB (1U << 2) /* 1b */
+#define AUDIO_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define AUDIO_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define AUDIO_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_AUDIO_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* ADSP_PWR_CON (0x10006000+0x358) */
+#define ADSP_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define ADSP_PWR_ISO_LSB (1U << 1) /* 1b */
+#define ADSP_PWR_ON_LSB (1U << 2) /* 1b */
+#define ADSP_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define ADSP_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define ADSP_SRAM_CKISO_LSB (1U << 5) /* 1b */
+#define ADSP_SRAM_ISOINT_B_LSB (1U << 6) /* 1b */
+#define ADSP_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define ADSP_SRAM_SLEEP_B_LSB (1U << 9) /* 1b */
+#define SC_ADSP_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+#define SC_ADSP_SRAM_SLEEP_B_ACK_LSB (1U << 13) /* 1b */
+/* CAM_PWR_CON (0x10006000+0x35C) */
+#define CAM_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CAM_RAWA_PWR_CON (0x10006000+0x360) */
+#define CAM_RAWA_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWA_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWA_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWA_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWA_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWA_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWA_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CAM_RAWB_PWR_CON (0x10006000+0x364) */
+#define CAM_RAWB_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWB_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWB_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWB_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWB_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWB_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWB_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* CAM_RAWC_PWR_CON (0x10006000+0x368) */
+#define CAM_RAWC_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define CAM_RAWC_PWR_ISO_LSB (1U << 1) /* 1b */
+#define CAM_RAWC_PWR_ON_LSB (1U << 2) /* 1b */
+#define CAM_RAWC_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define CAM_RAWC_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define CAM_RAWC_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_CAM_RAWC_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* SYSRAM_CON (0x10006000+0x36C) */
+#define SYSRAM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SYSRAM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SYSRAM_SRAM_SLEEP_B_LSB (1U << 4) /* 4b */
+#define SYSRAM_SRAM_PDN_LSB (1U << 16) /* 4b */
+/* SYSROM_CON (0x10006000+0x370) */
+#define SYSROM_SRAM_PDN_LSB (1U << 0) /* 6b */
+/* SSPM_SRAM_CON (0x10006000+0x374) */
+#define SSPM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SSPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SSPM_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SSPM_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* SCP_SRAM_CON (0x10006000+0x378) */
+#define SCP_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define SCP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define SCP_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define SCP_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* DPY_SHU_SRAM_CON (0x10006000+0x37C) */
+#define DPY_SHU_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPY_SHU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPY_SHU_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */
+#define DPY_SHU_SRAM_PDN_LSB (1U << 16) /* 2b */
+/* UFS_SRAM_CON (0x10006000+0x380) */
+#define UFS_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define UFS_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define UFS_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */
+#define UFS_SRAM_PDN_LSB (1U << 16) /* 5b */
+/* DEVAPC_IFR_SRAM_CON (0x10006000+0x384) */
+#define DEVAPC_IFR_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_IFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_IFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */
+#define DEVAPC_IFR_SRAM_PDN_LSB (1U << 16) /* 6b */
+/* DEVAPC_SUBIFR_SRAM_CON (0x10006000+0x388) */
+#define DEVAPC_SUBIFR_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_SUBIFR_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_SUBIFR_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */
+#define DEVAPC_SUBIFR_SRAM_PDN_LSB (1U << 16) /* 6b */
+/* DEVAPC_ACP_SRAM_CON (0x10006000+0x38C) */
+#define DEVAPC_ACP_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DEVAPC_ACP_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DEVAPC_ACP_SRAM_SLEEP_B_LSB (1U << 4) /* 6b */
+#define DEVAPC_ACP_SRAM_PDN_LSB (1U << 16) /* 6b */
+/* USB_SRAM_CON (0x10006000+0x390) */
+#define USB_SRAM_PDN_LSB (1U << 0) /* 7b */
+/* DUMMY_SRAM_CON (0x10006000+0x394) */
+#define DUMMY_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DUMMY_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DUMMY_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */
+#define DUMMY_SRAM_PDN_LSB (1U << 16) /* 8b */
+/* MD_EXT_BUCK_ISO_CON (0x10006000+0x398) */
+#define VMODEM_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */
+#define VMD_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */
+/* EXT_BUCK_ISO (0x10006000+0x39C) */
+#define VIMVO_EXT_BUCK_ISO_LSB (1U << 0) /* 1b */
+#define GPU_EXT_BUCK_ISO_LSB (1U << 1) /* 1b */
+#define IPU_EXT_BUCK_ISO_LSB (1U << 5) /* 3b */
+/* DXCC_SRAM_CON (0x10006000+0x3A0) */
+#define DXCC_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DXCC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DXCC_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DXCC_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* MSDC_SRAM_CON (0x10006000+0x3A4) */
+#define MSDC_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define MSDC_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define MSDC_SRAM_SLEEP_B_LSB (1U << 4) /* 5b */
+#define MSDC_SRAM_PDN_LSB (1U << 16) /* 5b */
+/* DEBUGTOP_SRAM_CON (0x10006000+0x3A8) */
+#define DEBUGTOP_SRAM_PDN_LSB (1U << 0) /* 1b */
+/* DP_TX_PWR_CON (0x10006000+0x3AC) */
+#define DP_TX_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DP_TX_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DP_TX_PWR_ON_LSB (1U << 2) /* 1b */
+#define DP_TX_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DP_TX_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DP_TX_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DP_TX_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* DPMAIF_SRAM_CON (0x10006000+0x3B0) */
+#define DPMAIF_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPMAIF_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPMAIF_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DPMAIF_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* DPY_SHU2_SRAM_CON (0x10006000+0x3B4) */
+#define DPY_SHU2_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DPY_SHU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DPY_SHU2_SRAM_SLEEP_B_LSB (1U << 4) /* 2b */
+#define DPY_SHU2_SRAM_PDN_LSB (1U << 16) /* 2b */
+/* DRAMC_MCU2_SRAM_CON (0x10006000+0x3B8) */
+#define DRAMC_MCU2_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DRAMC_MCU2_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DRAMC_MCU2_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DRAMC_MCU2_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* DRAMC_MCU_SRAM_CON (0x10006000+0x3BC) */
+#define DRAMC_MCU_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define DRAMC_MCU_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define DRAMC_MCU_SRAM_SLEEP_B_LSB (1U << 4) /* 1b */
+#define DRAMC_MCU_SRAM_PDN_LSB (1U << 16) /* 1b */
+/* MCUPM_SRAM_CON (0x10006000+0x3C0) */
+#define MCUPM_SRAM_CKISO_LSB (1U << 0) /* 1b */
+#define MCUPM_SRAM_ISOINT_B_LSB (1U << 1) /* 1b */
+#define MCUPM_SRAM_SLEEP_B_LSB (1U << 4) /* 8b */
+#define MCUPM_SRAM_PDN_LSB (1U << 16) /* 8b */
+/* DPY2_PWR_CON (0x10006000+0x3C4) */
+#define DPY2_PWR_RST_B_LSB (1U << 0) /* 1b */
+#define DPY2_PWR_ISO_LSB (1U << 1) /* 1b */
+#define DPY2_PWR_ON_LSB (1U << 2) /* 1b */
+#define DPY2_PWR_ON_2ND_LSB (1U << 3) /* 1b */
+#define DPY2_PWR_CLK_DIS_LSB (1U << 4) /* 1b */
+#define DPY2_SRAM_PDN_LSB (1U << 8) /* 1b */
+#define SC_DPY2_SRAM_PDN_ACK_LSB (1U << 12) /* 1b */
+/* SPM_MEM_CK_SEL (0x10006000+0x400) */
+#define SC_MEM_CK_SEL_LSB (1U << 0) /* 1b */
+#define SPM2CKSYS_MEM_CK_MUX_UPDATE_LSB (1U << 1) /* 1b */
+/* SPM_BUS_PROTECT_MASK_B (0x10006000+0X404) */
+#define SPM_BUS_PROTECT_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT1_MASK_B (0x10006000+0x408) */
+#define SPM_BUS_PROTECT1_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT2_MASK_B (0x10006000+0x40C) */
+#define SPM_BUS_PROTECT2_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT3_MASK_B (0x10006000+0x410) */
+#define SPM_BUS_PROTECT3_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT4_MASK_B (0x10006000+0x414) */
+#define SPM_BUS_PROTECT4_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_EMI_BW_MODE (0x10006000+0x418) */
+#define EMI_BW_MODE_LSB (1U << 0) /* 1b */
+#define EMI_BOOST_MODE_LSB (1U << 1) /* 1b */
+#define EMI_BW_MODE_2_LSB (1U << 2) /* 1b */
+#define EMI_BOOST_MODE_2_LSB (1U << 3) /* 1b */
+/* AP2MD_PEER_WAKEUP (0x10006000+0x41C) */
+#define AP2MD_PEER_WAKEUP_LSB (1U << 0) /* 1b */
+/* ULPOSC_CON (0x10006000+0x420) */
+#define ULPOSC_EN_LSB (1U << 0) /* 1b */
+#define ULPOSC_RST_LSB (1U << 1) /* 1b */
+#define ULPOSC_CG_EN_LSB (1U << 2) /* 1b */
+#define ULPOSC_CLK_SEL_LSB (1U << 3) /* 1b */
+/* SPM2MM_CON (0x10006000+0x424) */
+#define SPM2MM_FORCE_ULTRA_LSB (1U << 0) /* 1b */
+#define SPM2MM_DBL_OSTD_ACT_LSB (1U << 1) /* 1b */
+#define SPM2MM_ULTRAREQ_LSB (1U << 2) /* 1b */
+#define SPM2MD_ULTRAREQ_LSB (1U << 3) /* 1b */
+#define SPM2ISP_ULTRAREQ_LSB (1U << 4) /* 1b */
+#define MM2SPM_FORCE_ULTRA_ACK_D2T_LSB (1U << 16) /* 1b */
+#define MM2SPM_DBL_OSTD_ACT_ACK_D2T_LSB (1U << 17) /* 1b */
+#define SPM2ISP_ULTRAACK_D2T_LSB (1U << 18) /* 1b */
+#define SPM2MM_ULTRAACK_D2T_LSB (1U << 19) /* 1b */
+#define SPM2MD_ULTRAACK_D2T_LSB (1U << 20) /* 1b */
+/* SPM_BUS_PROTECT5_MASK_B (0x10006000+0x428) */
+#define SPM_BUS_PROTECT5_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM2MCUPM_CON (0x10006000+0x42C) */
+#define SPM2MCUPM_SW_RST_B_LSB (1U << 0) /* 1b */
+#define SPM2MCUPM_SW_INT_LSB (1U << 1) /* 1b */
+/* AP_MDSRC_REQ (0x10006000+0x430) */
+#define AP_MDSMSRC_REQ_LSB (1U << 0) /* 1b */
+#define AP_L1SMSRC_REQ_LSB (1U << 1) /* 1b */
+#define AP_MD2SRC_REQ_LSB (1U << 2) /* 1b */
+#define AP_MDSMSRC_ACK_LSB (1U << 4) /* 1b */
+#define AP_L1SMSRC_ACK_LSB (1U << 5) /* 1b */
+#define AP_MD2SRC_ACK_LSB (1U << 6) /* 1b */
+/* SPM2EMI_ENTER_ULPM (0x10006000+0x434) */
+#define SPM2EMI_ENTER_ULPM_LSB (1U << 0) /* 1b */
+/* SPM2MD_DVFS_CON (0x10006000+0x438) */
+#define SPM2MD_DVFS_CON_LSB (1U << 0) /* 32b */
+/* MD2SPM_DVFS_CON (0x10006000+0x43C) */
+#define MD2SPM_DVFS_CON_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT6_MASK_B (0x10006000+0X440) */
+#define SPM_BUS_PROTECT6_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT7_MASK_B (0x10006000+0x444) */
+#define SPM_BUS_PROTECT7_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_BUS_PROTECT8_MASK_B (0x10006000+0x448) */
+#define SPM_BUS_PROTECT8_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PLL_CON (0x10006000+0x44C) */
+#define SC_MAINPLLOUT_OFF_LSB (1U << 0) /* 1b */
+#define SC_UNIPLLOUT_OFF_LSB (1U << 1) /* 1b */
+#define SC_MAINPLL_OFF_LSB (1U << 4) /* 1b */
+#define SC_UNIPLL_OFF_LSB (1U << 5) /* 1b */
+#define SC_MAINPLL_S_OFF_LSB (1U << 8) /* 1b */
+#define SC_UNIPLL_S_OFF_LSB (1U << 9) /* 1b */
+#define SC_SMI_CK_OFF_LSB (1U << 16) /* 1b */
+#define SC_MD32K_CK_OFF_LSB (1U << 17) /* 1b */
+#define SC_CKSQ1_OFF_LSB (1U << 18) /* 1b */
+#define SC_AXI_MEM_CK_OFF_LSB (1U << 19) /* 1b */
+/* CPU_DVFS_REQ (0x10006000+0x450) */
+#define CPU_DVFS_REQ_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_0 (0x10006000+0x454) */
+#define SW_DDR_PST_REQ_LSB (1U << 0) /* 2b */
+#define SW_DDR_PST_ABORT_REQ_LSB (1U << 2) /* 2b */
+/* SPM_DRAM_MCU_SW_CON_1 (0x10006000+0x458) */
+#define SW_DDR_PST_CH0_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_2 (0x10006000+0x45C) */
+#define SW_DDR_PST_CH1_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_3 (0x10006000+0x460) */
+#define SW_DDR_RESERVED_CH0_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_CON_4 (0x10006000+0x464) */
+#define SW_DDR_RESERVED_CH1_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_STA_0 (0x10006000+0x468) */
+#define SC_DDR_PST_ACK_LSB (1U << 0) /* 2b */
+#define SC_DDR_PST_ABORT_ACK_LSB (1U << 2) /* 2b */
+/* SPM_DRAM_MCU_STA_1 (0x10006000+0x46C) */
+#define SC_DDR_CUR_PST_STA_CH0_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_STA_2 (0x10006000+0x470) */
+#define SC_DDR_CUR_PST_STA_CH1_LSB (1U << 0) /* 32b */
+/* SPM_DRAM_MCU_SW_SEL_0 (0x10006000+0x474) */
+#define SW_DDR_PST_REQ_SEL_LSB (1U << 0) /* 2b */
+#define SW_DDR_PST_SEL_LSB (1U << 2) /* 2b */
+#define SW_DDR_PST_ABORT_REQ_SEL_LSB (1U << 4) /* 2b */
+#define SW_DDR_RESERVED_SEL_LSB (1U << 6) /* 2b */
+#define SW_DDR_PST_ACK_SEL_LSB (1U << 8) /* 2b */
+#define SW_DDR_PST_ABORT_ACK_SEL_LSB (1U << 10) /* 2b */
+/* RELAY_DVFS_LEVEL (0x10006000+0x478) */
+#define RELAY_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* DRAMC_DPY_CLK_SW_CON_0 (0x10006000+0x480) */
+#define SW_PHYPLL_EN_LSB (1U << 0) /* 2b */
+#define SW_DPY_VREF_EN_LSB (1U << 2) /* 2b */
+#define SW_DPY_DLL_CK_EN_LSB (1U << 4) /* 2b */
+#define SW_DPY_DLL_EN_LSB (1U << 6) /* 2b */
+#define SW_DPY_2ND_DLL_EN_LSB (1U << 8) /* 2b */
+#define SW_MEM_CK_OFF_LSB (1U << 10) /* 2b */
+#define SW_DMSUS_OFF_LSB (1U << 12) /* 2b */
+#define SW_DPY_MODE_SW_LSB (1U << 14) /* 2b */
+#define SW_EMI_CLK_OFF_LSB (1U << 16) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_LSB (1U << 18) /* 2b */
+#define SW_DR_GATE_RETRY_EN_LSB (1U << 20) /* 2b */
+#define SW_DPHY_PRECAL_UP_LSB (1U << 24) /* 2b */
+#define SW_DPY_BCLK_ENABLE_LSB (1U << 26) /* 2b */
+#define SW_TX_TRACKING_DIS_LSB (1U << 28) /* 2b */
+#define SW_DPHY_RXDLY_TRACKING_EN_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_CON_1 (0x10006000+0x484) */
+#define SW_SHU_RESTORE_LSB (1U << 0) /* 2b */
+#define SW_DMYRD_MOD_LSB (1U << 2) /* 2b */
+#define SW_DMYRD_INTV_LSB (1U << 4) /* 2b */
+#define SW_DMYRD_EN_LSB (1U << 6) /* 2b */
+#define SW_DRS_DIS_REQ_LSB (1U << 8) /* 2b */
+#define SW_DR_SRAM_LOAD_LSB (1U << 10) /* 2b */
+#define SW_DR_SRAM_RESTORE_LSB (1U << 12) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_LATCH_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACK_RETRY_EN_LSB (1U << 16) /* 2b */
+#define SW_DPY_MIDPI_EN_LSB (1U << 18) /* 2b */
+#define SW_DPY_PI_RESETB_EN_LSB (1U << 20) /* 2b */
+#define SW_DPY_MCK8X_EN_LSB (1U << 22) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_CH0_LSB (1U << 24) /* 4b */
+#define SW_DR_SHU_LEVEL_SRAM_CH1_LSB (1U << 28) /* 4b */
+/* DRAMC_DPY_CLK_SW_CON_2 (0x10006000+0x488) */
+#define SW_DR_SHU_LEVEL_LSB (1U << 0) /* 2b */
+#define SW_DR_SHU_EN_LSB (1U << 2) /* 1b */
+#define SW_DR_SHORT_QUEUE_LSB (1U << 3) /* 1b */
+#define SW_PHYPLL_MODE_SW_LSB (1U << 4) /* 1b */
+#define SW_PHYPLL2_MODE_SW_LSB (1U << 5) /* 1b */
+#define SW_PHYPLL_SHU_EN_LSB (1U << 6) /* 1b */
+#define SW_PHYPLL2_SHU_EN_LSB (1U << 7) /* 1b */
+#define SW_DR_RESERVED_0_LSB (1U << 24) /* 2b */
+#define SW_DR_RESERVED_1_LSB (1U << 26) /* 2b */
+#define SW_DR_RESERVED_2_LSB (1U << 28) /* 2b */
+#define SW_DR_RESERVED_3_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_CON_3 (0x10006000+0x48C) */
+#define SC_DR_SHU_EN_ACK_LSB (1U << 0) /* 4b */
+#define SC_EMI_CLK_OFF_ACK_LSB (1U << 4) /* 4b */
+#define SC_DR_SHORT_QUEUE_ACK_LSB (1U << 8) /* 4b */
+#define SC_DRAMC_DFS_STA_LSB (1U << 12) /* 4b */
+#define SC_DRS_DIS_ACK_LSB (1U << 16) /* 4b */
+#define SC_DR_SRAM_LOAD_ACK_LSB (1U << 20) /* 4b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_LSB (1U << 24) /* 4b */
+#define SC_DR_SRAM_RESTORE_ACK_LSB (1U << 28) /* 4b */
+/* DRAMC_DPY_CLK_SW_SEL_0 (0x10006000+0x490) */
+#define SW_PHYPLL_EN_SEL_LSB (1U << 0) /* 2b */
+#define SW_DPY_VREF_EN_SEL_LSB (1U << 2) /* 2b */
+#define SW_DPY_DLL_CK_EN_SEL_LSB (1U << 4) /* 2b */
+#define SW_DPY_DLL_EN_SEL_LSB (1U << 6) /* 2b */
+#define SW_DPY_2ND_DLL_EN_SEL_LSB (1U << 8) /* 2b */
+#define SW_MEM_CK_OFF_SEL_LSB (1U << 10) /* 2b */
+#define SW_DMSUS_OFF_SEL_LSB (1U << 12) /* 2b */
+#define SW_DPY_MODE_SW_SEL_LSB (1U << 14) /* 2b */
+#define SW_EMI_CLK_OFF_SEL_LSB (1U << 16) /* 2b */
+#define SW_DDRPHY_FB_CK_EN_SEL_LSB (1U << 18) /* 2b */
+#define SW_DR_GATE_RETRY_EN_SEL_LSB (1U << 20) /* 2b */
+#define SW_DPHY_PRECAL_UP_SEL_LSB (1U << 24) /* 2b */
+#define SW_DPY_BCLK_ENABLE_SEL_LSB (1U << 26) /* 2b */
+#define SW_TX_TRACKING_DIS_SEL_LSB (1U << 28) /* 2b */
+#define SW_DPHY_RXDLY_TRACKING_EN_SEL_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_SEL_1 (0x10006000+0x494) */
+#define SW_SHU_RESTORE_SEL_LSB (1U << 0) /* 2b */
+#define SW_DMYRD_MOD_SEL_LSB (1U << 2) /* 2b */
+#define SW_DMYRD_INTV_SEL_LSB (1U << 4) /* 2b */
+#define SW_DMYRD_EN_SEL_LSB (1U << 6) /* 2b */
+#define SW_DRS_DIS_REQ_SEL_LSB (1U << 8) /* 2b */
+#define SW_DR_SRAM_LOAD_SEL_LSB (1U << 10) /* 2b */
+#define SW_DR_SRAM_RESTORE_SEL_LSB (1U << 12) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_LATCH_SEL_LSB (1U << 14) /* 2b */
+#define SW_TX_TRACK_RETRY_EN_SEL_LSB (1U << 16) /* 2b */
+#define SW_DPY_MIDPI_EN_SEL_LSB (1U << 18) /* 2b */
+#define SW_DPY_PI_RESETB_EN_SEL_LSB (1U << 20) /* 2b */
+#define SW_DPY_MCK8X_EN_SEL_LSB (1U << 22) /* 2b */
+#define SW_DR_SHU_LEVEL_SRAM_SEL_LSB (1U << 24) /* 2b */
+/* DRAMC_DPY_CLK_SW_SEL_2 (0x10006000+0x498) */
+#define SW_DR_SHU_LEVEL_SEL_LSB (1U << 0) /* 1b */
+#define SW_DR_SHU_EN_SEL_LSB (1U << 2) /* 1b */
+#define SW_DR_SHORT_QUEUE_SEL_LSB (1U << 3) /* 1b */
+#define SW_PHYPLL_MODE_SW_SEL_LSB (1U << 4) /* 1b */
+#define SW_PHYPLL2_MODE_SW_SEL_LSB (1U << 5) /* 1b */
+#define SW_PHYPLL_SHU_EN_SEL_LSB (1U << 6) /* 1b */
+#define SW_PHYPLL2_SHU_EN_SEL_LSB (1U << 7) /* 1b */
+#define SW_DR_RESERVED_0_SEL_LSB (1U << 24) /* 2b */
+#define SW_DR_RESERVED_1_SEL_LSB (1U << 26) /* 2b */
+#define SW_DR_RESERVED_2_SEL_LSB (1U << 28) /* 2b */
+#define SW_DR_RESERVED_3_SEL_LSB (1U << 30) /* 2b */
+/* DRAMC_DPY_CLK_SW_SEL_3 (0x10006000+0x49C) */
+#define SC_DR_SHU_EN_ACK_SEL_LSB (1U << 0) /* 4b */
+#define SC_EMI_CLK_OFF_ACK_SEL_LSB (1U << 4) /* 4b */
+#define SC_DR_SHORT_QUEUE_ACK_SEL_LSB (1U << 8) /* 4b */
+#define SC_DRAMC_DFS_STA_SEL_LSB (1U << 12) /* 4b */
+#define SC_DRS_DIS_ACK_SEL_LSB (1U << 16) /* 4b */
+#define SC_DR_SRAM_LOAD_ACK_SEL_LSB (1U << 20) /* 4b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_SEL_LSB (1U << 24) /* 4b */
+#define SC_DR_SRAM_RESTORE_ACK_SEL_LSB (1U << 28) /* 4b */
+/* DRAMC_DPY_CLK_SPM_CON (0x10006000+0x4A0) */
+#define SC_DMYRD_EN_MOD_SEL_PCM_LSB (1U << 0) /* 1b */
+#define SC_DMYRD_INTV_SEL_PCM_LSB (1U << 1) /* 1b */
+#define SC_DMYRD_EN_PCM_LSB (1U << 2) /* 1b */
+#define SC_DRS_DIS_REQ_PCM_LSB (1U << 3) /* 1b */
+#define SC_DR_SHU_LEVEL_SRAM_PCM_LSB (1U << 4) /* 4b */
+#define SC_DR_GATE_RETRY_EN_PCM_LSB (1U << 8) /* 1b */
+#define SC_DR_SHORT_QUEUE_PCM_LSB (1U << 9) /* 1b */
+#define SC_DPY_MIDPI_EN_PCM_LSB (1U << 10) /* 1b */
+#define SC_DPY_PI_RESETB_EN_PCM_LSB (1U << 11) /* 1b */
+#define SC_DPY_MCK8X_EN_PCM_LSB (1U << 12) /* 1b */
+#define SC_DR_RESERVED_0_PCM_LSB (1U << 13) /* 1b */
+#define SC_DR_RESERVED_1_PCM_LSB (1U << 14) /* 1b */
+#define SC_DR_RESERVED_2_PCM_LSB (1U << 15) /* 1b */
+#define SC_DR_RESERVED_3_PCM_LSB (1U << 16) /* 1b */
+#define SC_DMDRAMCSHU_ACK_ALL_LSB (1U << 24) /* 1b */
+#define SC_EMI_CLK_OFF_ACK_ALL_LSB (1U << 25) /* 1b */
+#define SC_DR_SHORT_QUEUE_ACK_ALL_LSB (1U << 26) /* 1b */
+#define SC_DRAMC_DFS_STA_ALL_LSB (1U << 27) /* 1b */
+#define SC_DRS_DIS_ACK_ALL_LSB (1U << 28) /* 1b */
+#define SC_DR_SRAM_LOAD_ACK_ALL_LSB (1U << 29) /* 1b */
+#define SC_DR_SRAM_PLL_LOAD_ACK_ALL_LSB (1U << 30) /* 1b */
+#define SC_DR_SRAM_RESTORE_ACK_ALL_LSB (1U << 31) /* 1b */
+/* SPM_DVFS_LEVEL (0x10006000+0x4A4) */
+#define SPM_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* SPM_CIRQ_CON (0x10006000+0x4A8) */
+#define CIRQ_CLK_SEL_LSB (1U << 0) /* 1b */
+/* SPM_DVFS_MISC (0x10006000+0x4AC) */
+#define MSDC_DVFS_REQUEST_LSB (1U << 0) /* 1b */
+#define SPM2EMI_SLP_PROT_EN_LSB (1U << 1) /* 1b */
+#define SPM_DVFS_FORCE_ENABLE_LSB (1U << 2) /* 1b */
+#define FORCE_DVFS_WAKE_LSB (1U << 3) /* 1b */
+#define SPM_DVFSRC_ENABLE_LSB (1U << 4) /* 1b */
+#define SPM_DVFS_DONE_LSB (1U << 5) /* 1b */
+#define DVFSRC_IRQ_WAKEUP_EVENT_MASK_LSB (1U << 6) /* 1b */
+#define SPM2RC_EVENT_ABORT_LSB (1U << 7) /* 1b */
+#define EMI_SLP_IDLE_LSB (1U << 14) /* 1b */
+#define SDIO_READY_TO_SPM_LSB (1U << 15) /* 1b */
+/* SPM_VS1_VS2_RC_CON (0x10006000+0x4B0) */
+#define VS1_INIT_LEVEL_LSB (1U << 0) /* 2b */
+#define VS1_INIT_LSB (1U << 2) /* 1b */
+#define VS1_CURR_LEVEL_LSB (1U << 3) /* 2b */
+#define VS1_NEXT_LEVEL_LSB (1U << 5) /* 2b */
+#define VS1_VOTE_LEVEL_LSB (1U << 7) /* 2b */
+#define VS1_TRIGGER_LSB (1U << 9) /* 1b */
+#define VS2_INIT_LEVEL_LSB (1U << 10) /* 3b */
+#define VS2_INIT_LSB (1U << 13) /* 1b */
+#define VS2_CURR_LEVEL_LSB (1U << 14) /* 3b */
+#define VS2_NEXT_LEVEL_LSB (1U << 17) /* 3b */
+#define VS2_VOTE_LEVEL_LSB (1U << 20) /* 3b */
+#define VS2_TRIGGER_LSB (1U << 23) /* 1b */
+#define VS1_FORCE_LSB (1U << 24) /* 1b */
+#define VS2_FORCE_LSB (1U << 25) /* 1b */
+#define VS1_VOTE_LEVEL_FORCE_LSB (1U << 26) /* 2b */
+#define VS2_VOTE_LEVEL_FORCE_LSB (1U << 28) /* 3b */
+/* RG_MODULE_SW_CG_0_MASK_REQ_0 (0x10006000+0x4B4) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_0_MASK_REQ_1 (0x10006000+0x4B8) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_0_MASK_REQ_2 (0x10006000+0x4BC) */
+#define RG_MODULE_SW_CG_0_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_1_MASK_REQ_0 (0x10006000+0x4C0) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_1_MASK_REQ_1 (0x10006000+0x4C4) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_1_MASK_REQ_2 (0x10006000+0x4C8) */
+#define RG_MODULE_SW_CG_1_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_2_MASK_REQ_0 (0x10006000+0x4CC) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_2_MASK_REQ_1 (0x10006000+0x4D0) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_2_MASK_REQ_2 (0x10006000+0x4D4) */
+#define RG_MODULE_SW_CG_2_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_3_MASK_REQ_0 (0x10006000+0x4D8) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_3_MASK_REQ_1 (0x10006000+0x4DC) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* RG_MODULE_SW_CG_3_MASK_REQ_2 (0x10006000+0x4E0) */
+#define RG_MODULE_SW_CG_3_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_MASK_REQ_0 (0x10006000+0x4E4) */
+#define PWR_STATUS_MASK_REQ_0_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_MASK_REQ_1 (0x10006000+0x4E8) */
+#define PWR_STATUS_MASK_REQ_1_LSB (1U << 0) /* 32b */
+/* PWR_STATUS_MASK_REQ_2 (0x10006000+0x4EC) */
+#define PWR_STATUS_MASK_REQ_2_LSB (1U << 0) /* 32b */
+/* SPM_CG_CHECK_CON (0x10006000+0x4F0) */
+#define APMIXEDSYS_BUSY_MASK_REQ_0_LSB (1U << 0) /* 5b */
+#define APMIXEDSYS_BUSY_MASK_REQ_1_LSB (1U << 8) /* 5b */
+#define APMIXEDSYS_BUSY_MASK_REQ_2_LSB (1U << 16) /* 5b */
+#define AUDIOSYS_BUSY_MASK_REQ_0_LSB (1U << 24) /* 1b */
+#define AUDIOSYS_BUSY_MASK_REQ_1_LSB (1U << 25) /* 1b */
+#define AUDIOSYS_BUSY_MASK_REQ_2_LSB (1U << 26) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_0_LSB (1U << 27) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_1_LSB (1U << 28) /* 1b */
+#define SSUSB_BUSY_MASK_REQ_2_LSB (1U << 29) /* 1b */
+/* SPM_SRC_RDY_STA (0x10006000+0x4F4) */
+#define SPM_INFRA_INTERNAL_ACK_LSB (1U << 0) /* 1b */
+#define SPM_VRF18_INTERNAL_ACK_LSB (1U << 1) /* 1b */
+/* SPM_DVS_DFS_LEVEL (0x10006000+0x4F8) */
+#define SPM_DFS_LEVEL_LSB (1U << 0) /* 16b */
+#define SPM_DVS_LEVEL_LSB (1U << 16) /* 16b */
+/* SPM_FORCE_DVFS (0x10006000+0x4FC) */
+#define FORCE_DVFS_LEVEL_LSB (1U << 0) /* 32b */
+/* SRCLKEN_RC_CFG (0x10006000+0x500) */
+#define SRCLKEN_RC_CFG_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG1 (0x10006000+0x504) */
+#define RC_CENTRAL_CFG1_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG2 (0x10006000+0x508) */
+#define RC_CENTRAL_CFG2_LSB (1U << 0) /* 32b */
+/* RC_CMD_ARB_CFG (0x10006000+0x50C) */
+#define RC_CMD_ARB_CFG_LSB (1U << 0) /* 32b */
+/* RC_PMIC_RCEN_ADDR (0x10006000+0x510) */
+#define RC_PMIC_RCEN_ADDR_LSB (1U << 0) /* 16b */
+#define RC_PMIC_RCEN_RESERVE_LSB (1U << 16) /* 16b */
+/* RC_PMIC_RCEN_SET_CLR_ADDR (0x10006000+0x514) */
+#define RC_PMIC_RCEN_SET_ADDR_LSB (1U << 0) /* 16b */
+#define RC_PMIC_RCEN_CLR_ADDR_LSB (1U << 16) /* 16b */
+/* RC_DCXO_FPM_CFG (0x10006000+0x518) */
+#define RC_DCXO_FPM_CFG_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG3 (0x10006000+0x51C) */
+#define RC_CENTRAL_CFG3_LSB (1U << 0) /* 32b */
+/* RC_M00_SRCLKEN_CFG (0x10006000+0x520) */
+#define RC_M00_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+#define RC_SW_SRCLKEN_RC (1U << 3) /* 1b */
+#define RC_SW_SRCLKEN_FPM (1U << 4) /* 1b */
+/* RC_M01_SRCLKEN_CFG (0x10006000+0x524) */
+#define RC_M01_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M02_SRCLKEN_CFG (0x10006000+0x528) */
+#define RC_M02_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M03_SRCLKEN_CFG (0x10006000+0x52C) */
+#define RC_M03_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M04_SRCLKEN_CFG (0x10006000+0x530) */
+#define RC_M04_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M05_SRCLKEN_CFG (0x10006000+0x534) */
+#define RC_M05_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M06_SRCLKEN_CFG (0x10006000+0x538) */
+#define RC_M06_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M07_SRCLKEN_CFG (0x10006000+0x53C) */
+#define RC_M07_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M08_SRCLKEN_CFG (0x10006000+0x540) */
+#define RC_M08_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M09_SRCLKEN_CFG (0x10006000+0x544) */
+#define RC_M09_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M10_SRCLKEN_CFG (0x10006000+0x548) */
+#define RC_M10_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M11_SRCLKEN_CFG (0x10006000+0x54C) */
+#define RC_M11_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_M12_SRCLKEN_CFG (0x10006000+0x550) */
+#define RC_M12_SRCLKEN_CFG_LSB (1U << 0) /* 32b */
+/* RC_SRCLKEN_SW_CON_CFG (0x10006000+0x554) */
+#define RC_SRCLKEN_SW_CON_CFG_LSB (1U << 0) /* 32b */
+/* RC_CENTRAL_CFG4 (0x10006000+0x558) */
+#define RC_CENTRAL_CFG4_LSB (1U << 0) /* 32b */
+/* RC_PROTOCOL_CHK_CFG (0x10006000+0x560) */
+#define RC_PROTOCOL_CHK_CFG_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_CFG (0x10006000+0x564) */
+#define RC_DEBUG_CFG_LSB (1U << 0) /* 32b */
+/* RC_MISC_0 (0x10006000+0x5B4) */
+#define SRCCLKENO_LSB (1U << 0) /* 2b */
+#define PCM_SRCCLKENO_LSB (1U << 3) /* 2b */
+#define RC_VREQ_LSB (1U << 5) /* 1b */
+#define RC_SPM_SRCCLKENO_0_ACK_LSB (1U << 6) /* 1b */
+/* RC_SPM_CTRL (0x10006000+0x448) */
+#define SPM_AP_26M_RDY_LSB (1U << 0) /* 1b */
+#define KEEP_RC_SPI_ACTIVE_LSB (1U << 1) /* 1b */
+#define SPM2RC_DMY_CTRL_LSB (1U << 2) /* 6b */
+/* SUBSYS_INTF_CFG (0x10006000+0x5BC) */
+#define SRCLKEN_FPM_MASK_B_LSB (1U << 0) /* 13b */
+#define SRCLKEN_BBLPM_MASK_B_LSB (1U << 16) /* 13b */
+/* PCM_WDT_LATCH_25 (0x10006000+0x5C0) */
+#define PCM_WDT_LATCH_25_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_26 (0x10006000+0x5C4) */
+#define PCM_WDT_LATCH_26_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_27 (0x10006000+0x5C8) */
+#define PCM_WDT_LATCH_27_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_28 (0x10006000+0x5CC) */
+#define PCM_WDT_LATCH_28_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_29 (0x10006000+0x5D0) */
+#define PCM_WDT_LATCH_29_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_30 (0x10006000+0x5D4) */
+#define PCM_WDT_LATCH_30_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_31 (0x10006000+0x5D8) */
+#define PCM_WDT_LATCH_31_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_32 (0x10006000+0x5DC) */
+#define PCM_WDT_LATCH_32_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_33 (0x10006000+0x5E0) */
+#define PCM_WDT_LATCH_33_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_34 (0x10006000+0x5E4) */
+#define PCM_WDT_LATCH_34_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_35 (0x10006000+0x5EC) */
+#define PCM_WDT_LATCH_35_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_36 (0x10006000+0x5F0) */
+#define PCM_WDT_LATCH_36_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_37 (0x10006000+0x5F4) */
+#define PCM_WDT_LATCH_37_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_38 (0x10006000+0x5F8) */
+#define PCM_WDT_LATCH_38_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_39 (0x10006000+0x5FC) */
+#define PCM_WDT_LATCH_39_LSB (1U << 0) /* 32b */
+/* SPM_SW_FLAG_0 (0x10006000+0x600) */
+#define SPM_SW_FLAG_LSB (1U << 0) /* 32b */
+/* SPM_SW_DEBUG_0 (0x10006000+0x604) */
+#define SPM_SW_DEBUG_0_LSB (1U << 0) /* 32b */
+/* SPM_SW_FLAG_1 (0x10006000+0x608) */
+#define SPM_SW_FLAG_1_LSB (1U << 0) /* 32b */
+/* SPM_SW_DEBUG_1 (0x10006000+0x60C) */
+#define SPM_SW_DEBUG_1_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_0 (0x10006000+0x610) */
+#define SPM_SW_RSV_0_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_1 (0x10006000+0x614) */
+#define SPM_SW_RSV_1_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_2 (0x10006000+0x618) */
+#define SPM_SW_RSV_2_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_3 (0x10006000+0x61C) */
+#define SPM_SW_RSV_3_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_4 (0x10006000+0x620) */
+#define SPM_SW_RSV_4_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_5 (0x10006000+0x624) */
+#define SPM_SW_RSV_5_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_6 (0x10006000+0x628) */
+#define SPM_SW_RSV_6_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_7 (0x10006000+0x62C) */
+#define SPM_SW_RSV_7_LSB (1U << 0) /* 32b */
+/* SPM_SW_RSV_8 (0x10006000+0x630) */
+#define SPM_SW_RSV_8_LSB (1U << 0) /* 32b */
+/* SPM_BK_WAKE_EVENT (0x10006000+0x634) */
+#define SPM_BK_WAKE_EVENT_LSB (1U << 0) /* 32b */
+/* SPM_BK_VTCXO_DUR (0x10006000+0x638) */
+#define SPM_BK_VTCXO_DUR_LSB (1U << 0) /* 32b */
+/* SPM_BK_WAKE_MISC (0x10006000+0x63C) */
+#define SPM_BK_WAKE_MISC_LSB (1U << 0) /* 32b */
+/* SPM_BK_PCM_TIMER (0x10006000+0x640) */
+#define SPM_BK_PCM_TIMER_LSB (1U << 0) /* 32b */
+/* SPM_RSV_CON_0 (0x10006000+0x650) */
+#define SPM_RSV_CON_0_LSB (1U << 0) /* 32b */
+/* SPM_RSV_CON_1 (0x10006000+0x654) */
+#define SPM_RSV_CON_1_LSB (1U << 0) /* 32b */
+/* SPM_RSV_STA_0 (0x10006000+0x658) */
+#define SPM_RSV_STA_0_LSB (1U << 0) /* 32b */
+/* SPM_RSV_STA_1 (0x10006000+0x65C) */
+#define SPM_RSV_STA_1_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON (0x10006000+0x660) */
+#define SPM_SPARE_CON_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON_SET (0x10006000+0x664) */
+#define SPM_SPARE_CON_SET_LSB (1U << 0) /* 32b */
+/* SPM_SPARE_CON_CLR (0x10006000+0x668) */
+#define SPM_SPARE_CON_CLR_LSB (1U << 0) /* 32b */
+/* SPM_CROSS_WAKE_M00_REQ (0x10006000+0x66C) */
+#define SPM_CROSS_WAKE_M00_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M00_CHK_LSB (1U << 4) /* 4b */
+/* SPM_CROSS_WAKE_M01_REQ (0x10006000+0x670) */
+#define SPM_CROSS_WAKE_M01_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M01_CHK_LSB (1U << 4) /* 4b */
+/* SPM_CROSS_WAKE_M02_REQ (0x10006000+0x674) */
+#define SPM_CROSS_WAKE_M02_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M02_CHK_LSB (1U << 4) /* 4b */
+/* SPM_CROSS_WAKE_M03_REQ (0x10006000+0x678) */
+#define SPM_CROSS_WAKE_M03_REQ_LSB (1U << 0) /* 4b */
+#define SPM_CROSS_WAKE_M03_CHK_LSB (1U << 4) /* 4b */
+/* SCP_VCORE_LEVEL (0x10006000+0x67C) */
+#define SCP_VCORE_LEVEL_LSB (1U << 0) /* 16b */
+/* SC_MM_CK_SEL_CON (0x10006000+0x680) */
+#define SC_MM_CK_SEL_LSB (1U << 0) /* 4b */
+#define SC_MM_CK_SEL_EN_LSB (1U << 4) /* 1b */
+/* SPARE_ACK_MASK (0x10006000+0x684) */
+#define SPARE_ACK_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_DV_CON_0 (0x10006000+0x68C) */
+#define SPM_DV_CON_0_LSB (1U << 0) /* 32b */
+/* SPM_DV_CON_1 (0x10006000+0x690) */
+#define SPM_DV_CON_1_LSB (1U << 0) /* 32b */
+/* SPM_DV_STA (0x10006000+0x694) */
+#define SPM_DV_STA_LSB (1U << 0) /* 32b */
+/* CONN_XOWCN_DEBUG_EN (0x10006000+0x698) */
+#define CONN_XOWCN_DEBUG_EN_LSB (1U << 0) /* 1b */
+/* SPM_SEMA_M0 (0x10006000+0x69C) */
+#define SPM_SEMA_M0_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M1 (0x10006000+0x6A0) */
+#define SPM_SEMA_M1_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M2 (0x10006000+0x6A4) */
+#define SPM_SEMA_M2_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M3 (0x10006000+0x6A8) */
+#define SPM_SEMA_M3_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M4 (0x10006000+0x6AC) */
+#define SPM_SEMA_M4_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M5 (0x10006000+0x6B0) */
+#define SPM_SEMA_M5_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M6 (0x10006000+0x6B4) */
+#define SPM_SEMA_M6_LSB (1U << 0) /* 8b */
+/* SPM_SEMA_M7 (0x10006000+0x6B8) */
+#define SPM_SEMA_M7_LSB (1U << 0) /* 8b */
+/* SPM2ADSP_MAILBOX (0x10006000+0x6BC) */
+#define SPM2ADSP_MAILBOX_LSB (1U << 0) /* 32b */
+/* ADSP2SPM_MAILBOX (0x10006000+0x6C0) */
+#define ADSP2SPM_MAILBOX_LSB (1U << 0) /* 32b */
+/* SPM_ADSP_IRQ (0x10006000+0x6C4) */
+#define SC_SPM2ADSP_WAKEUP_LSB (1U << 0) /* 1b */
+#define SPM_ADSP_IRQ_SC_ADSP2SPM_WAKEUP_LSB (1U << 4) /* 1b */
+/* SPM_MD32_IRQ (0x10006000+0x6C8) */
+#define SC_SPM2SSPM_WAKEUP_LSB (1U << 0) /* 4b */
+#define SPM_MD32_IRQ_SC_SSPM2SPM_WAKEUP_LSB (1U << 4) /* 4b */
+/* SPM2PMCU_MAILBOX_0 (0x10006000+0x6CC) */
+#define SPM2PMCU_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_1 (0x10006000+0x6D0) */
+#define SPM2PMCU_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_2 (0x10006000+0x6D4) */
+#define SPM2PMCU_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* SPM2PMCU_MAILBOX_3 (0x10006000+0x6D8) */
+#define SPM2PMCU_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_0 (0x10006000+0x6DC) */
+#define PMCU2SPM_MAILBOX_0_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_1 (0x10006000+0x6E0) */
+#define PMCU2SPM_MAILBOX_1_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_2 (0x10006000+0x6E4) */
+#define PMCU2SPM_MAILBOX_2_LSB (1U << 0) /* 32b */
+/* PMCU2SPM_MAILBOX_3 (0x10006000+0x6E8) */
+#define PMCU2SPM_MAILBOX_3_LSB (1U << 0) /* 32b */
+/* UFS_PSRI_SW (0x10006000+0x6EC) */
+#define UFS_PSRI_SW_LSB (1U << 0) /* 1b */
+/* UFS_PSRI_SW_SET (0x10006000+0x6F0) */
+#define UFS_PSRI_SW_SET_LSB (1U << 0) /* 1b */
+/* UFS_PSRI_SW_CLR (0x10006000+0x6F4) */
+#define UFS_PSRI_SW_CLR_LSB (1U << 0) /* 1b */
+/* SPM_AP_SEMA (0x10006000+0x6F8) */
+#define SPM_AP_SEMA_LSB (1U << 0) /* 1b */
+/* SPM_SPM_SEMA (0x10006000+0x6FC) */
+#define SPM_SPM_SEMA_LSB (1U << 0) /* 1b */
+/* SPM_DVFS_CON (0x10006000+0x700) */
+#define SPM_DVFS_CON_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CON_STA (0x10006000+0x704) */
+#define SPM_DVFS_CON_STA_LSB (1U << 0) /* 32b */
+/* SPM_PMIC_SPMI_CON (0x10006000+0x708) */
+#define SPM_PMIC_SPMI_CMD_LSB (1U << 0) /* 2b */
+#define SPM_PMIC_SPMI_SLAVEID_LSB (1U << 2) /* 4b */
+#define SPM_PMIC_SPMI_PMIFID_LSB (1U << 6) /* 1b */
+#define SPM_PMIC_SPMI_DBCNT_LSB (1U << 7) /* 1b */
+/* SPM_DVFS_CMD0 (0x10006000+0x710) */
+#define SPM_DVFS_CMD0_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD1 (0x10006000+0x714) */
+#define SPM_DVFS_CMD1_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD2 (0x10006000+0x718) */
+#define SPM_DVFS_CMD2_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD3 (0x10006000+0x71C) */
+#define SPM_DVFS_CMD3_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD4 (0x10006000+0x720) */
+#define SPM_DVFS_CMD4_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD5 (0x10006000+0x724) */
+#define SPM_DVFS_CMD5_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD6 (0x10006000+0x728) */
+#define SPM_DVFS_CMD6_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD7 (0x10006000+0x72C) */
+#define SPM_DVFS_CMD7_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD8 (0x10006000+0x730) */
+#define SPM_DVFS_CMD8_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD9 (0x10006000+0x734) */
+#define SPM_DVFS_CMD9_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD10 (0x10006000+0x738) */
+#define SPM_DVFS_CMD10_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD11 (0x10006000+0x73C) */
+#define SPM_DVFS_CMD11_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD12 (0x10006000+0x740) */
+#define SPM_DVFS_CMD12_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD13 (0x10006000+0x744) */
+#define SPM_DVFS_CMD13_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD14 (0x10006000+0x748) */
+#define SPM_DVFS_CMD14_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD15 (0x10006000+0x74C) */
+#define SPM_DVFS_CMD15_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD16 (0x10006000+0x750) */
+#define SPM_DVFS_CMD16_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD17 (0x10006000+0x754) */
+#define SPM_DVFS_CMD17_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD18 (0x10006000+0x758) */
+#define SPM_DVFS_CMD18_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD19 (0x10006000+0x75C) */
+#define SPM_DVFS_CMD19_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD20 (0x10006000+0x760) */
+#define SPM_DVFS_CMD20_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD21 (0x10006000+0x764) */
+#define SPM_DVFS_CMD21_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD22 (0x10006000+0x768) */
+#define SPM_DVFS_CMD22_LSB (1U << 0) /* 32b */
+/* SPM_DVFS_CMD23 (0x10006000+0x76C) */
+#define SPM_DVFS_CMD23_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_VALUE_L (0x10006000+0x770) */
+#define SYS_TIMER_VALUE_L_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_VALUE_H (0x10006000+0x774) */
+#define SYS_TIMER_VALUE_H_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_START_L (0x10006000+0x778) */
+#define SYS_TIMER_START_L_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_START_H (0x10006000+0x77C) */
+#define SYS_TIMER_START_H_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_00 (0x10006000+0x780) */
+#define SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_00 (0x10006000+0x784) */
+#define SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_01 (0x10006000+0x788) */
+#define SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_01 (0x10006000+0x78C) */
+#define SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_02 (0x10006000+0x790) */
+#define SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_02 (0x10006000+0x794) */
+#define SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_03 (0x10006000+0x798) */
+#define SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_03 (0x10006000+0x79C) */
+#define SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_04 (0x10006000+0x7A0) */
+#define SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_04 (0x10006000+0x7A4) */
+#define SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_05 (0x10006000+0x7A8) */
+#define SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_05 (0x10006000+0x7AC) */
+#define SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_06 (0x10006000+0x7B0) */
+#define SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_06 (0x10006000+0x7B4) */
+#define SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_07 (0x10006000+0x7B8) */
+#define SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_07 (0x10006000+0x7BC) */
+#define SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_08 (0x10006000+0x7C0) */
+#define SYS_TIMER_LATCH_L_08_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_08 (0x10006000+0x7C4) */
+#define SYS_TIMER_LATCH_H_08_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_09 (0x10006000+0x7C8) */
+#define SYS_TIMER_LATCH_L_09_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_09 (0x10006000+0x7CC) */
+#define SYS_TIMER_LATCH_H_09_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_10 (0x10006000+0x7D0) */
+#define SYS_TIMER_LATCH_L_10_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_10 (0x10006000+0x7D4) */
+#define SYS_TIMER_LATCH_H_10_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_11 (0x10006000+0x7D8) */
+#define SYS_TIMER_LATCH_L_11_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_11 (0x10006000+0x7DC) */
+#define SYS_TIMER_LATCH_H_11_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_12 (0x10006000+0x7E0) */
+#define SYS_TIMER_LATCH_L_12_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_12 (0x10006000+0x7E4) */
+#define SYS_TIMER_LATCH_H_12_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_13 (0x10006000+0x7E8) */
+#define SYS_TIMER_LATCH_L_13_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_13 (0x10006000+0x7EC) */
+#define SYS_TIMER_LATCH_H_13_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_14 (0x10006000+0x7F0) */
+#define SYS_TIMER_LATCH_L_14_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_14 (0x10006000+0x7F4) */
+#define SYS_TIMER_LATCH_H_14_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_L_15 (0x10006000+0x7F8) */
+#define SYS_TIMER_LATCH_L_15_LSB (1U << 0) /* 32b */
+/* SYS_TIMER_LATCH_H_15 (0x10006000+0x7FC) */
+#define SYS_TIMER_LATCH_H_15_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_0 (0x10006000+0x800) */
+#define PCM_WDT_LATCH_0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_1 (0x10006000+0x804) */
+#define PCM_WDT_LATCH_1_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_2 (0x10006000+0x808) */
+#define PCM_WDT_LATCH_2_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_3 (0x10006000+0x80C) */
+#define PCM_WDT_LATCH_3_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_4 (0x10006000+0x810) */
+#define PCM_WDT_LATCH_4_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_5 (0x10006000+0x814) */
+#define PCM_WDT_LATCH_5_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_6 (0x10006000+0x818) */
+#define PCM_WDT_LATCH_6_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_7 (0x10006000+0x81C) */
+#define PCM_WDT_LATCH_7_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_8 (0x10006000+0x820) */
+#define PCM_WDT_LATCH_8_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_9 (0x10006000+0x824) */
+#define PCM_WDT_LATCH_9_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_10 (0x10006000+0x828) */
+#define PCM_WDT_LATCH_10_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_11 (0x10006000+0x82C) */
+#define PCM_WDT_LATCH_11_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_12 (0x10006000+0x830) */
+#define PCM_WDT_LATCH_12_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_13 (0x10006000+0x834) */
+#define PCM_WDT_LATCH_13_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_14 (0x10006000+0x838) */
+#define PCM_WDT_LATCH_14_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_15 (0x10006000+0x83C) */
+#define PCM_WDT_LATCH_15_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_16 (0x10006000+0x840) */
+#define PCM_WDT_LATCH_16_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_17 (0x10006000+0x844) */
+#define PCM_WDT_LATCH_17_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_18 (0x10006000+0x848) */
+#define PCM_WDT_LATCH_18_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_SPARE_0 (0x10006000+0x84C) */
+#define PCM_WDT_LATCH_SPARE_0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_SPARE_1 (0x10006000+0x850) */
+#define PCM_WDT_LATCH_SPARE_1_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_SPARE_2 (0x10006000+0x854) */
+#define PCM_WDT_LATCH_SPARE_2_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_CONN_0 (0x10006000+0x870) */
+#define PCM_WDT_LATCH_CONN_0_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_CONN_1 (0x10006000+0x874) */
+#define PCM_WDT_LATCH_CONN_1_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_CONN_2 (0x10006000+0x878) */
+#define PCM_WDT_LATCH_CONN_2_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_0 (0x10006000+0x8A0) */
+#define DRAMC_GATING_ERR_LATCH_CH0_0_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_1 (0x10006000+0x8A4) */
+#define DRAMC_GATING_ERR_LATCH_CH0_1_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_2 (0x10006000+0x8A8) */
+#define DRAMC_GATING_ERR_LATCH_CH0_2_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_3 (0x10006000+0x8AC) */
+#define DRAMC_GATING_ERR_LATCH_CH0_3_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_4 (0x10006000+0x8B0) */
+#define DRAMC_GATING_ERR_LATCH_CH0_4_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_5 (0x10006000+0x8B4) */
+#define DRAMC_GATING_ERR_LATCH_CH0_5_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_CH0_6 (0x10006000+0x8B8) */
+#define DRAMC_GATING_ERR_LATCH_CH0_6_LSB (1U << 0) /* 32b */
+/* DRAMC_GATING_ERR_LATCH_SPARE_0 (0x10006000+0x8F4) */
+#define DRAMC_GATING_ERR_LATCH_SPARE_0_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_0 (0x10006000+0x900) */
+#define SPM_ACK_CHK_SW_EN_0_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_0_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_0_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_0_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_0_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_0_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_0_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_0_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_0_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_0_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_0_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_0 (0x10006000+0x904) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_0_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_0_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_0 (0x10006000+0x908) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_0_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_0_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_0_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_0_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_0 (0x10006000+0x90C) */
+#define SPM_ACK_CHK_TIMER_VAL_0_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_0_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_0 (0x10006000+0x910) */
+#define SPM_ACK_CHK_STA_0_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_0 (0x10006000+0x914) */
+#define SPM_ACK_CHK_SWINT_EN_0_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_1 (0x10006000+0x920) */
+#define SPM_ACK_CHK_SW_EN_1_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_1_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_1_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_1_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_1_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_1_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_1_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_1_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_1_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_1_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_1_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_1 (0x10006000+0x924) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_1_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_1_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_1 (0x10006000+0x928) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_1_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_1_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_1_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_1_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_1 (0x10006000+0x92C) */
+#define SPM_ACK_CHK_TIMER_VAL_1_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_1_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_1 (0x10006000+0x930) */
+#define SPM_ACK_CHK_STA_1_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_1 (0x10006000+0x934) */
+#define SPM_ACK_CHK_SWINT_EN_1_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_2 (0x10006000+0x940) */
+#define SPM_ACK_CHK_SW_EN_2_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_2_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_2_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_2_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_2_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_2_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_2_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_2_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_2_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_2_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_2_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_2 (0x10006000+0x944) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_2_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_2 (0x10006000+0x948) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_2_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_2_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_2_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_2_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_2 (0x10006000+0x94C) */
+#define SPM_ACK_CHK_TIMER_VAL_2_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_2_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_2 (0x10006000+0x950) */
+#define SPM_ACK_CHK_STA_2_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_2 (0x10006000+0x954) */
+#define SPM_ACK_CHK_SWINT_EN_2_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_CON_3 (0x10006000+0x960) */
+#define SPM_ACK_CHK_SW_EN_3_LSB (1U << 0) /* 1b */
+#define SPM_ACK_CHK_CLR_ALL_3_LSB (1U << 1) /* 1b */
+#define SPM_ACK_CHK_CLR_TIMER_3_LSB (1U << 2) /* 1b */
+#define SPM_ACK_CHK_CLR_IRQ_3_LSB (1U << 3) /* 1b */
+#define SPM_ACK_CHK_STA_EN_3_LSB (1U << 4) /* 1b */
+#define SPM_ACK_CHK_WAKEUP_EN_3_LSB (1U << 5) /* 1b */
+#define SPM_ACK_CHK_WDT_EN_3_LSB (1U << 6) /* 1b */
+#define SPM_ACK_CHK_LOCK_PC_TRACE_EN_3_LSB (1U << 7) /* 1b */
+#define SPM_ACK_CHK_HW_EN_3_LSB (1U << 8) /* 1b */
+#define SPM_ACK_CHK_HW_MODE_3_LSB (1U << 9) /* 3b */
+#define SPM_ACK_CHK_FAIL_3_LSB (1U << 15) /* 1b */
+/* SPM_ACK_CHK_PC_3 (0x10006000+0x964) */
+#define SPM_ACK_CHK_HW_TRIG_PC_VAL_3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_HW_TARG_PC_VAL_3_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_SEL_3 (0x10006000+0x968) */
+#define SPM_ACK_CHK_HW_TRIG_SIGNAL_SEL_3_LSB (1U << 0) /* 5b */
+#define SPM_ACK_CHK_HW_TRIG_GROUP_SEL_3_LSB (1U << 5) /* 3b */
+#define SPM_ACK_CHK_HW_TARG_SIGNAL_SEL_3_LSB (1U << 16) /* 5b */
+#define SPM_ACK_CHK_HW_TARG_GROUP_SEL_3_LSB (1U << 21) /* 3b */
+/* SPM_ACK_CHK_TIMER_3 (0x10006000+0x96C) */
+#define SPM_ACK_CHK_TIMER_VAL_3_LSB (1U << 0) /* 16b */
+#define SPM_ACK_CHK_TIMER_3_LSB (1U << 16) /* 16b */
+/* SPM_ACK_CHK_STA_3 (0x10006000+0x970) */
+#define SPM_ACK_CHK_STA_3_LSB (1U << 0) /* 32b */
+/* SPM_ACK_CHK_SWINT_3 (0x10006000+0x974) */
+#define SPM_ACK_CHK_SWINT_EN_3_LSB (1U << 0) /* 32b */
+/* SPM_COUNTER_0 (0x10006000+0x978) */
+#define SPM_COUNTER_VAL_0_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_0_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_0_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_0_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_0_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_0_LSB (1U << 31) /* 1b */
+/* SPM_COUNTER_1 (0x10006000+0x97C) */
+#define SPM_COUNTER_VAL_1_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_1_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_1_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_1_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_1_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_1_LSB (1U << 31) /* 1b */
+/* SPM_COUNTER_2 (0x10006000+0x980) */
+#define SPM_COUNTER_VAL_2_LSB (1U << 0) /* 14b */
+#define SPM_COUNTER_OUT_2_LSB (1U << 14) /* 14b */
+#define SPM_COUNTER_EN_2_LSB (1U << 28) /* 1b */
+#define SPM_COUNTER_CLR_2_LSB (1U << 29) /* 1b */
+#define SPM_COUNTER_TIMEOUT_2_LSB (1U << 30) /* 1b */
+#define SPM_COUNTER_WAKEUP_EN_2_LSB (1U << 31) /* 1b */
+/* SYS_TIMER_CON (0x10006000+0x98C) */
+#define SYS_TIMER_START_EN_LSB (1U << 0) /* 1b */
+#define SYS_TIMER_LATCH_EN_LSB (1U << 1) /* 1b */
+#define SYS_TIMER_ID_LSB (1U << 8) /* 8b */
+#define SYS_TIMER_VALID_LSB (1U << 31) /* 1b */
+/* RC_FSM_STA_0 (0x10006000+0xE00) */
+#define RC_FSM_STA_0_LSB (1U << 0) /* 32b */
+/* RC_CMD_STA_0 (0x10006000+0xE04) */
+#define RC_CMD_STA_0_LSB (1U << 0) /* 32b */
+/* RC_CMD_STA_1 (0x10006000+0xE08) */
+#define RC_CMD_STA_1_LSB (1U << 0) /* 32b */
+/* RC_SPI_STA_0 (0x10006000+0xE0C) */
+#define RC_SPI_STA_0_LSB (1U << 0) /* 32b */
+/* RC_PI_PO_STA_0 (0x10006000+0xE10) */
+#define RC_PI_PO_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M00_REQ_STA_0 (0x10006000+0xE14) */
+#define RC_M00_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M01_REQ_STA_0 (0x10006000+0xE1C) */
+#define RC_M01_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M02_REQ_STA_0 (0x10006000+0xE20) */
+#define RC_M02_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M03_REQ_STA_0 (0x10006000+0xE24) */
+#define RC_M03_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M04_REQ_STA_0 (0x10006000+0xE28) */
+#define RC_M04_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M05_REQ_STA_0 (0x10006000+0xE2C) */
+#define RC_M05_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M06_REQ_STA_0 (0x10006000+0xE30) */
+#define RC_M06_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M07_REQ_STA_0 (0x10006000+0xE34) */
+#define RC_M07_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M08_REQ_STA_0 (0x10006000+0xE38) */
+#define RC_M08_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M09_REQ_STA_0 (0x10006000+0xE3C) */
+#define RC_M09_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M10_REQ_STA_0 (0x10006000+0xE40) */
+#define RC_M10_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M11_REQ_STA_0 (0x10006000+0xE44) */
+#define RC_M11_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_M12_REQ_STA_0 (0x10006000+0xE48) */
+#define RC_M12_REQ_STA_0_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_STA_0 (0x10006000+0xE4C) */
+#define RC_DEBUG_STA_0_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_0_LSB (0x10006000+0xE50) */
+#define RO_PMRC_TRACE_00_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_0_MSB (0x10006000+0xE54) */
+#define RO_PMRC_TRACE_00_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_1_LSB (0x10006000+0xE5C) */
+#define RO_PMRC_TRACE_01_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_1_MSB (0x10006000+0xE60) */
+#define RO_PMRC_TRACE_01_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_2_LSB (0x10006000+0xE64) */
+#define RO_PMRC_TRACE_02_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_2_MSB (0x10006000+0xE6C) */
+#define RO_PMRC_TRACE_02_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_3_LSB (0x10006000+0xE70) */
+#define RO_PMRC_TRACE_03_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_3_MSB (0x10006000+0xE74) */
+#define RO_PMRC_TRACE_03_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_4_LSB (0x10006000+0xE78) */
+#define RO_PMRC_TRACE_04_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_4_MSB (0x10006000+0xE7C) */
+#define RO_PMRC_TRACE_04_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_5_LSB (0x10006000+0xE80) */
+#define RO_PMRC_TRACE_05_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_5_MSB (0x10006000+0xE84) */
+#define RO_PMRC_TRACE_05_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_6_LSB (0x10006000+0xE88) */
+#define RO_PMRC_TRACE_06_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_6_MSB (0x10006000+0xE8C) */
+#define RO_PMRC_TRACE_06_MSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_7_LSB (0x10006000+0xE90) */
+#define RO_PMRC_TRACE_07_LSB_LSB (1U << 0) /* 32b */
+/* RC_DEBUG_TRACE_7_MSB (0x10006000+0xE94) */
+#define RO_PMRC_TRACE_07_MSB_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_0_LSB (0x10006000+0xE98) */
+#define RC_SYS_TIMER_LATCH_L_00_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_0_MSB (0x10006000+0xE9C) */
+#define RC_SYS_TIMER_LATCH_H_00_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_1_LSB (0x10006000+0xEA0) */
+#define RC_SYS_TIMER_LATCH_L_01_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_1_MSB (0x10006000+0xEA4) */
+#define RC_SYS_TIMER_LATCH_H_01_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_2_LSB (0x10006000+0xEA8) */
+#define RC_SYS_TIMER_LATCH_L_02_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_2_MSB (0x10006000+0xEAC) */
+#define RC_SYS_TIMER_LATCH_H_02_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_3_LSB (0x10006000+0xEB0) */
+#define RC_SYS_TIMER_LATCH_L_03_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_3_MSB (0x10006000+0xEB4) */
+#define RC_SYS_TIMER_LATCH_H_03_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_4_LSB (0x10006000+0xEB8) */
+#define RC_SYS_TIMER_LATCH_L_04_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_4_MSB (0x10006000+0xEBC) */
+#define RC_SYS_TIMER_LATCH_H_04_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_5_LSB (0x10006000+0xEC0) */
+#define RC_SYS_TIMER_LATCH_L_05_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_5_MSB (0x10006000+0xEC4) */
+#define RC_SYS_TIMER_LATCH_H_05_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_6_LSB (0x10006000+0xEC8) */
+#define RC_SYS_TIMER_LATCH_L_06_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_6_MSB (0x10006000+0xECC) */
+#define RC_SYS_TIMER_LATCH_H_06_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_7_LSB (0x10006000+0xED0) */
+#define RC_SYS_TIMER_LATCH_L_07_LSB (1U << 0) /* 32b */
+/* RC_SYS_TIMER_LATCH_7_MSB (0x10006000+0xED4) */
+#define RC_SYS_TIMER_LATCH_H_07_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_19 (0x10006000+0xED8) */
+#define PCM_WDT_LATCH_19_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_20 (0x10006000+0xEDC) */
+#define PCM_WDT_LATCH_20_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_21 (0x10006000+0xEE0) */
+#define PCM_WDT_LATCH_21_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_22 (0x10006000+0xEE4) */
+#define PCM_WDT_LATCH_22_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_23 (0x10006000+0xEE8) */
+#define PCM_WDT_LATCH_23_LSB (1U << 0) /* 32b */
+/* PCM_WDT_LATCH_24 (0x10006000+0xEEC) */
+#define PCM_WDT_LATCH_24_LSB (1U << 0) /* 32b */
+/* PMSR_LAST_DAT (0x10006000+0xF00) */
+#define PMSR_LAST_DAT_LSB (1U << 0) /* 32b */
+/* PMSR_LAST_CNT (0x10006000+0xF04) */
+#define PMSR_LAST_CMD_LSB (1U << 0) /* 30b */
+#define PMSR_LAST_REQ_LSB (1U << 30) /* 1b */
+/* PMSR_LAST_ACK (0x10006000+0xF08) */
+#define PMSR_LAST_ACK_LSB (1U << 0) /* 1b */
+/* SPM_PMSR_SEL_CON0 (0x10006000+0xF10) */
+#define REG_PMSR_SIG_SEL_0_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_1_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_2_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_3_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON1 (0x10006000+0xF14) */
+#define REG_PMSR_SIG_SEL_4_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_5_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_6_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_7_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON2 (0x10006000+0xF18) */
+#define REG_PMSR_SIG_SEL_8_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_9_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_10_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_11_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON3 (0x10006000+0xF1C) */
+#define REG_PMSR_SIG_SEL_12_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_13_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_14_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_15_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON4 (0x10006000+0xF20) */
+#define REG_PMSR_SIG_SEL_16_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_17_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_18_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_19_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON5 (0x10006000+0xF24) */
+#define REG_PMSR_SIG_SEL_20_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_21_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_22_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_23_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON6 (0x10006000+0xF28) */
+#define REG_PMSR_SIG_SEL_24_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_25_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_26_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_27_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON7 (0x10006000+0xF2C) */
+#define REG_PMSR_SIG_SEL_28_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_29_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_30_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_31_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON8 (0x10006000+0xF30) */
+#define REG_PMSR_SIG_SEL_32_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_33_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_34_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_35_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON9 (0x10006000+0xF34) */
+#define REG_PMSR_SIG_SEL_36_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_37_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_38_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_39_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON10 (0x10006000+0xF3C) */
+#define REG_PMSR_SIG_SEL_40_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_41_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_42_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_43_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_SEL_CON11 (0x10006000+0xF40) */
+#define REG_PMSR_SIG_SEL_44_LSB (1U << 0) /* 8b */
+#define REG_PMSR_SIG_SEL_45_LSB (1U << 8) /* 8b */
+#define REG_PMSR_SIG_SEL_46_LSB (1U << 16) /* 8b */
+#define REG_PMSR_SIG_SEL_47_LSB (1U << 24) /* 8b */
+/* SPM_PMSR_TIEMR_STA0 (0x10006000+0xFB8) */
+#define PMSR_TIMER_SET0_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_TIEMR_STA1 (0x10006000+0xFBC) */
+#define PMSR_TIMER_SET1_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_TIEMR_STA2 (0x10006000+0xFC0) */
+#define PMSR_TIMER_SET2_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON0 (0x10006000+0xFC4) */
+#define PMSR_ENABLE_SET0_LSB (1U << 0) /* 1b */
+#define PMSR_ENABLE_SET1_LSB (1U << 1) /* 1b */
+#define PMSR_ENABLE_SET2_LSB (1U << 2) /* 1b */
+#define PMSR_IRQ_CLR_SET0_LSB (1U << 3) /* 1b */
+#define PMSR_IRQ_CLR_SET1_LSB (1U << 4) /* 1b */
+#define PMSR_IRQ_CLR_SET2_LSB (1U << 5) /* 1b */
+#define PMSR_SPEED_MODE_EN_SET0_LSB (1U << 6) /* 1b */
+#define PMSR_SPEED_MODE_EN_SET1_LSB (1U << 7) /* 1b */
+#define PMSR_SPEED_MODE_EN_SET2_LSB (1U << 8) /* 1b */
+#define PMSR_EVENT_CLR_SET0_LSB (1U << 9) /* 1b */
+#define PMSR_EVENT_CLR_SET1_LSB (1U << 10) /* 1b */
+#define PMSR_EVENT_CLR_SET2_LSB (1U << 11) /* 1b */
+#define REG_PMSR_IRQ_MASK_SET0_LSB (1U << 12) /* 1b */
+#define REG_PMSR_IRQ_MASK_SET1_LSB (1U << 13) /* 1b */
+#define REG_PMSR_IRQ_MASK_SET2_LSB (1U << 14) /* 1b */
+#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET0_LSB (1U << 15) /* 1b */
+#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET1_LSB (1U << 16) /* 1b */
+#define REG_PMSR_IRQ_WAKEUP_EVENT_MASK_SET2_LSB (1U << 17) /* 1b */
+#define PMSR_GEN_SW_RST_EN_LSB (1U << 18) /* 1b */
+#define PMSR_MODULE_ENABLE_LSB (1U << 19) /* 1b */
+#define PMSR_MODE_LSB (1U << 20) /* 2b */
+#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET0_LSB (1U << 29) /* 1b */
+#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET1_LSB (1U << 30) /* 1b */
+#define SPM_PMSR_GENERAL_CON0_PMSR_IRQ_B_SET2_LSB (1U << 31) /* 1b */
+/* SPM_PMSR_GENERAL_CON1 (0x10006000+0xFC8) */
+#define PMSR_COUNTER_THRES_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON2 (0x10006000+0xFCC) */
+#define PMSR_DEBUG_IN_0_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON3 (0x10006000+0xFD0) */
+#define PMSR_DEBUG_IN_1_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON4 (0x10006000+0xFD4) */
+#define PMSR_DEBUG_IN_2_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_GENERAL_CON5 (0x10006000+0xFD8) */
+#define PMSR_DEBUG_IN_3_MASK_B_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_SW_RESET (0x10006000+0xFDC) */
+#define PMSR_SW_RST_EN_SET0_LSB (1U << 0) /* 1b */
+#define PMSR_SW_RST_EN_SET1_LSB (1U << 1) /* 1b */
+#define PMSR_SW_RST_EN_SET2_LSB (1U << 2) /* 1b */
+/* SPM_PMSR_MON_CON0 (0x10006000+0xFE0) */
+#define REG_PMSR_MON_TYPE_0_LSB (1U << 0) /* 2b */
+#define REG_PMSR_MON_TYPE_1_LSB (1U << 2) /* 2b */
+#define REG_PMSR_MON_TYPE_2_LSB (1U << 4) /* 2b */
+#define REG_PMSR_MON_TYPE_3_LSB (1U << 6) /* 2b */
+#define REG_PMSR_MON_TYPE_4_LSB (1U << 8) /* 2b */
+#define REG_PMSR_MON_TYPE_5_LSB (1U << 10) /* 2b */
+#define REG_PMSR_MON_TYPE_6_LSB (1U << 12) /* 2b */
+#define REG_PMSR_MON_TYPE_7_LSB (1U << 14) /* 2b */
+#define REG_PMSR_MON_TYPE_8_LSB (1U << 16) /* 2b */
+#define REG_PMSR_MON_TYPE_9_LSB (1U << 18) /* 2b */
+#define REG_PMSR_MON_TYPE_10_LSB (1U << 20) /* 2b */
+#define REG_PMSR_MON_TYPE_11_LSB (1U << 22) /* 2b */
+#define REG_PMSR_MON_TYPE_12_LSB (1U << 24) /* 2b */
+#define REG_PMSR_MON_TYPE_13_LSB (1U << 26) /* 2b */
+#define REG_PMSR_MON_TYPE_14_LSB (1U << 28) /* 2b */
+#define REG_PMSR_MON_TYPE_15_LSB (1U << 30) /* 2b */
+/* SPM_PMSR_MON_CON1 (0x10006000+0xFE4) */
+#define REG_PMSR_MON_TYPE_16_LSB (1U << 0) /* 2b */
+#define REG_PMSR_MON_TYPE_17_LSB (1U << 2) /* 2b */
+#define REG_PMSR_MON_TYPE_18_LSB (1U << 4) /* 2b */
+#define REG_PMSR_MON_TYPE_19_LSB (1U << 6) /* 2b */
+#define REG_PMSR_MON_TYPE_20_LSB (1U << 8) /* 2b */
+#define REG_PMSR_MON_TYPE_21_LSB (1U << 10) /* 2b */
+#define REG_PMSR_MON_TYPE_22_LSB (1U << 12) /* 2b */
+#define REG_PMSR_MON_TYPE_23_LSB (1U << 14) /* 2b */
+#define REG_PMSR_MON_TYPE_24_LSB (1U << 16) /* 2b */
+#define REG_PMSR_MON_TYPE_25_LSB (1U << 18) /* 2b */
+#define REG_PMSR_MON_TYPE_26_LSB (1U << 20) /* 2b */
+#define REG_PMSR_MON_TYPE_27_LSB (1U << 22) /* 2b */
+#define REG_PMSR_MON_TYPE_28_LSB (1U << 24) /* 2b */
+#define REG_PMSR_MON_TYPE_29_LSB (1U << 26) /* 2b */
+#define REG_PMSR_MON_TYPE_30_LSB (1U << 28) /* 2b */
+#define REG_PMSR_MON_TYPE_31_LSB (1U << 30) /* 2b */
+/* SPM_PMSR_MON_CON2 (0x10006000+0xFE8) */
+#define REG_PMSR_MON_TYPE_32_LSB (1U << 0) /* 2b */
+#define REG_PMSR_MON_TYPE_33_LSB (1U << 2) /* 2b */
+#define REG_PMSR_MON_TYPE_34_LSB (1U << 4) /* 2b */
+#define REG_PMSR_MON_TYPE_35_LSB (1U << 6) /* 2b */
+#define REG_PMSR_MON_TYPE_36_LSB (1U << 8) /* 2b */
+#define REG_PMSR_MON_TYPE_37_LSB (1U << 10) /* 2b */
+#define REG_PMSR_MON_TYPE_38_LSB (1U << 12) /* 2b */
+#define REG_PMSR_MON_TYPE_39_LSB (1U << 14) /* 2b */
+#define REG_PMSR_MON_TYPE_40_LSB (1U << 16) /* 2b */
+#define REG_PMSR_MON_TYPE_41_LSB (1U << 18) /* 2b */
+#define REG_PMSR_MON_TYPE_42_LSB (1U << 20) /* 2b */
+#define REG_PMSR_MON_TYPE_43_LSB (1U << 22) /* 2b */
+#define REG_PMSR_MON_TYPE_44_LSB (1U << 24) /* 2b */
+#define REG_PMSR_MON_TYPE_45_LSB (1U << 26) /* 2b */
+#define REG_PMSR_MON_TYPE_46_LSB (1U << 28) /* 2b */
+#define REG_PMSR_MON_TYPE_47_LSB (1U << 30) /* 2b */
+/* SPM_PMSR_LEN_CON0 (0x10006000+0xFEC) */
+#define REG_PMSR_WINDOW_LEN_SET0_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_LEN_CON1 (0x10006000+0xFF0) */
+#define REG_PMSR_WINDOW_LEN_SET1_LSB (1U << 0) /* 32b */
+/* SPM_PMSR_LEN_CON2 (0x10006000+0xFF4) */
+#define REG_PMSR_WINDOW_LEN_SET2_LSB (1U << 0) /* 32b */
+
+#define SPM_PROJECT_CODE 0xb16
+#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16)
+#endif
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h
new file mode 100644
index 0000000..26250ba
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_RESOURCE_REQ_H
+#define MT_SPM_RESOURCE_REQ_H
+
+/* SPM resource request internal bit */
+#define MT_SPM_BIT_XO_FPM 0
+#define MT_SPM_BIT_26M 1
+#define MT_SPM_BIT_INFRA 2
+#define MT_SPM_BIT_SYSPLL 3
+#define MT_SPM_BIT_DRAM_S0 4
+#define MT_SPM_BIT_DRAM_S1 5
+
+/* SPM resource request internal bit_mask */
+#define MT_SPM_XO_FPM BIT(MT_SPM_BIT_XO_FPM)
+#define MT_SPM_26M BIT(MT_SPM_BIT_26M)
+#define MT_SPM_INFRA BIT(MT_SPM_BIT_INFRA)
+#define MT_SPM_SYSPLL BIT(MT_SPM_BIT_SYSPLL)
+#define MT_SPM_DRAM_S0 BIT(MT_SPM_BIT_DRAM_S0)
+#define MT_SPM_DRAM_S1 BIT(MT_SPM_BIT_DRAM_S1)
+#endif /* MT_SPM_RESOURCE_REQ_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c
new file mode 100644
index 0000000..d018953
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_conservation.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_rc_internal.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_resource_req.h>
+#include <mt_spm_suspend.h>
+#include <plat_pm.h>
+#include <uart.h>
+
+#define SPM_SUSPEND_SLEEP_PCM_FLAG \
+ (SPM_FLAG_DISABLE_INFRA_PDN | \
+ SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
+ SPM_FLAG_SRAM_SLEEP_CTRL)
+
+#define SPM_SUSPEND_SLEEP_PCM_FLAG1 0
+
+#define SPM_SUSPEND_PCM_FLAG \
+ (SPM_FLAG_DISABLE_VCORE_DVS | \
+ SPM_FLAG_DISABLE_VCORE_DFS | \
+ SPM_FLAG_ENABLE_TIA_WORKAROUND | \
+ SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
+ SPM_FLAG_SRAM_SLEEP_CTRL)
+
+#define SPM_SUSPEND_PCM_FLAG1 0
+
+/* Suspend spm power control */
+#define __WAKE_SRC_FOR_SUSPEND_COMMON__ \
+ (R12_PCM_TIMER | \
+ R12_KP_IRQ_B | \
+ R12_APWDT_EVENT_B | \
+ R12_CONN2AP_SPM_WAKEUP_B | \
+ R12_EINT_EVENT_B | \
+ R12_CONN_WDT_IRQ_B | \
+ R12_CCIF0_EVENT_B | \
+ R12_SSPM2SPM_WAKEUP_B | \
+ R12_SCP2SPM_WAKEUP_B | \
+ R12_USBX_CDSC_B | \
+ R12_USBX_POWERDWN_B | \
+ R12_SYS_TIMER_EVENT_B | \
+ R12_EINT_EVENT_SECURE_B | \
+ R12_SYS_CIRQ_IRQ_B | \
+ R12_MD2AP_PEER_EVENT_B | \
+ R12_MD1_WDT_B | \
+ R12_CLDMA_EVENT_B | \
+ R12_REG_CPU_WAKEUP | \
+ R12_APUSYS_WAKE_HOST_B)
+
+#if defined(CFG_MICROTRUST_TEE_SUPPORT)
+#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__)
+#else
+#define WAKE_SRC_FOR_SUSPEND \
+ (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \
+ R12_SEJ_EVENT_B)
+#endif
+
+static struct pwr_ctrl suspend_ctrl = {
+ .wake_src = WAKE_SRC_FOR_SUSPEND,
+
+ /* SPM_AP_STANDBY_CON */
+ /* [0] */
+ .reg_wfi_op = 0,
+ /* [1] */
+ .reg_wfi_type = 0,
+ /* [2] */
+ .reg_mp0_cputop_idle_mask = 0,
+ /* [3] */
+ .reg_mp1_cputop_idle_mask = 0,
+ /* [4] */
+ .reg_mcusys_idle_mask = 0,
+ /* [25] */
+ .reg_md_apsrc_1_sel = 0,
+ /* [26] */
+ .reg_md_apsrc_0_sel = 0,
+ /* [29] */
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC_REQ */
+ /* [0] */
+ .reg_spm_apsrc_req = 0,
+ /* [1] */
+ .reg_spm_f26m_req = 0,
+ /* [3] */
+ .reg_spm_infra_req = 0,
+ /* [4] */
+ .reg_spm_vrf18_req = 0,
+ /* [7] FIXME: default disable HW Auto S1*/
+ .reg_spm_ddr_en_req = 1,
+ /* [8] */
+ .reg_spm_dvfs_req = 0,
+ /* [9] */
+ .reg_spm_sw_mailbox_req = 0,
+ /* [10] */
+ .reg_spm_sspm_mailbox_req = 0,
+ /* [11] */
+ .reg_spm_adsp_mailbox_req = 0,
+ /* [12] */
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC_MASK */
+ /* [0] */
+ .reg_sspm_srcclkena_0_mask_b = 1,
+ /* [1] */
+ .reg_sspm_infra_req_0_mask_b = 1,
+ /* [2] */
+ .reg_sspm_apsrc_req_0_mask_b = 1,
+ /* [3] */
+ .reg_sspm_vrf18_req_0_mask_b = 1,
+ /* [4] */
+ .reg_sspm_ddr_en_0_mask_b = 1,
+ /* [5] */
+ .reg_scp_srcclkena_mask_b = 1,
+ /* [6] */
+ .reg_scp_infra_req_mask_b = 1,
+ /* [7] */
+ .reg_scp_apsrc_req_mask_b = 1,
+ /* [8] */
+ .reg_scp_vrf18_req_mask_b = 1,
+ /* [9] */
+ .reg_scp_ddr_en_mask_b = 1,
+ /* [10] */
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ /* [11] */
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ /* [12] */
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ /* [13] */
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ /* [14] */
+ .reg_audio_dsp_ddr_en_mask_b = 1,
+ /* [15] */
+ .reg_apu_srcclkena_mask_b = 1,
+ /* [16] */
+ .reg_apu_infra_req_mask_b = 1,
+ /* [17] */
+ .reg_apu_apsrc_req_mask_b = 1,
+ /* [18] */
+ .reg_apu_vrf18_req_mask_b = 1,
+ /* [19] */
+ .reg_apu_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_cpueb_srcclkena_mask_b = 1,
+ /* [21] */
+ .reg_cpueb_infra_req_mask_b = 1,
+ /* [22] */
+ .reg_cpueb_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_cpueb_vrf18_req_mask_b = 1,
+ /* [24] */
+ .reg_cpueb_ddr_en_mask_b = 1,
+ /* [25] */
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ /* [26] */
+ .reg_bak_psri_infra_req_mask_b = 0,
+ /* [27] */
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ /* [28] */
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ /* [29] */
+ .reg_bak_psri_ddr_en_mask_b = 0,
+
+ /* SPM_SRC2_MASK */
+ /* [0] */
+ .reg_msdc0_srcclkena_mask_b = 1,
+ /* [1] */
+ .reg_msdc0_infra_req_mask_b = 1,
+ /* [2] */
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ /* [3] */
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ /* [4] */
+ .reg_msdc0_ddr_en_mask_b = 1,
+ /* [5] */
+ .reg_msdc1_srcclkena_mask_b = 1,
+ /* [6] */
+ .reg_msdc1_infra_req_mask_b = 1,
+ /* [7] */
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ /* [8] */
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ /* [9] */
+ .reg_msdc1_ddr_en_mask_b = 1,
+ /* [10] */
+ .reg_msdc2_srcclkena_mask_b = 1,
+ /* [11] */
+ .reg_msdc2_infra_req_mask_b = 1,
+ /* [12] */
+ .reg_msdc2_apsrc_req_mask_b = 1,
+ /* [13] */
+ .reg_msdc2_vrf18_req_mask_b = 1,
+ /* [14] */
+ .reg_msdc2_ddr_en_mask_b = 1,
+ /* [15] */
+ .reg_ufs_srcclkena_mask_b = 0,
+ /* [16] */
+ .reg_ufs_infra_req_mask_b = 0,
+ /* [17] */
+ .reg_ufs_apsrc_req_mask_b = 0,
+ /* [18] */
+ .reg_ufs_vrf18_req_mask_b = 0,
+ /* [19] */
+ .reg_ufs_ddr_en_mask_b = 0,
+ /* [20] */
+ .reg_usb_srcclkena_mask_b = 1,
+ /* [21] */
+ .reg_usb_infra_req_mask_b = 1,
+ /* [22] */
+ .reg_usb_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_usb_vrf18_req_mask_b = 1,
+ /* [24] */
+ .reg_usb_ddr_en_mask_b = 1,
+ /* [25] */
+ .reg_pextp_p0_srcclkena_mask_b = 1,
+ /* [26] */
+ .reg_pextp_p0_infra_req_mask_b = 1,
+ /* [27] */
+ .reg_pextp_p0_apsrc_req_mask_b = 1,
+ /* [28] */
+ .reg_pextp_p0_vrf18_req_mask_b = 1,
+ /* [29] */
+ .reg_pextp_p0_ddr_en_mask_b = 1,
+
+ /* SPM_SRC3_MASK */
+ /* [0] */
+ .reg_pextp_p1_srcclkena_mask_b = 1,
+ /* [1] */
+ .reg_pextp_p1_infra_req_mask_b = 1,
+ /* [2] */
+ .reg_pextp_p1_apsrc_req_mask_b = 1,
+ /* [3] */
+ .reg_pextp_p1_vrf18_req_mask_b = 1,
+ /* [4] */
+ .reg_pextp_p1_ddr_en_mask_b = 1,
+ /* [5] */
+ .reg_gce0_infra_req_mask_b = 1,
+ /* [6] */
+ .reg_gce0_apsrc_req_mask_b = 1,
+ /* [7] */
+ .reg_gce0_vrf18_req_mask_b = 1,
+ /* [8] */
+ .reg_gce0_ddr_en_mask_b = 1,
+ /* [9] */
+ .reg_gce1_infra_req_mask_b = 1,
+ /* [10] */
+ .reg_gce1_apsrc_req_mask_b = 1,
+ /* [11] */
+ .reg_gce1_vrf18_req_mask_b = 1,
+ /* [12] */
+ .reg_gce1_ddr_en_mask_b = 1,
+ /* [13] */
+ .reg_spm_srcclkena_reserved_mask_b = 1,
+ /* [14] */
+ .reg_spm_infra_req_reserved_mask_b = 1,
+ /* [15] */
+ .reg_spm_apsrc_req_reserved_mask_b = 1,
+ /* [16] */
+ .reg_spm_vrf18_req_reserved_mask_b = 1,
+ /* [17] */
+ .reg_spm_ddr_en_reserved_mask_b = 1,
+ /* [18] */
+ .reg_disp0_apsrc_req_mask_b = 1,
+ /* [19] */
+ .reg_disp0_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_disp1_apsrc_req_mask_b = 1,
+ /* [21] */
+ .reg_disp1_ddr_en_mask_b = 1,
+ /* [22] */
+ .reg_disp2_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_disp2_ddr_en_mask_b = 1,
+ /* [24] */
+ .reg_disp3_apsrc_req_mask_b = 1,
+ /* [25] */
+ .reg_disp3_ddr_en_mask_b = 1,
+ /* [26] */
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ /* [27] */
+ .reg_infrasys_ddr_en_mask_b = 1,
+
+ /* [28] */
+ .reg_cg_check_srcclkena_mask_b = 1,
+ /* [29] */
+ .reg_cg_check_apsrc_req_mask_b = 1,
+ /* [30] */
+ .reg_cg_check_vrf18_req_mask_b = 1,
+ /* [31] */
+ .reg_cg_check_ddr_en_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ /* [8:0] */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x17,
+ /* [17:9] */
+ .reg_mcusys_merge_ddr_en_mask_b = 0x17,
+ /* [19:18] */
+ .reg_dramc_md32_infra_req_mask_b = 0,
+ /* [21:20] */
+ .reg_dramc_md32_vrf18_req_mask_b = 0,
+ /* [23:22] */
+ .reg_dramc_md32_ddr_en_mask_b = 0,
+ /* [24] */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK2 */
+ /* [3:0] */
+ .reg_sc_sw2spm_wakeup_mask_b = 0,
+ /* [4] */
+ .reg_sc_adsp2spm_wakeup_mask_b = 0,
+ /* [8:5] */
+ .reg_sc_sspm2spm_wakeup_mask_b = 0,
+ /* [9] */
+ .reg_sc_scp2spm_wakeup_mask_b = 0,
+ /* [10] */
+ .reg_csyspwrup_ack_mask = 0,
+ /* [11] */
+ .reg_csyspwrup_req_mask = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ /* [31:0] */
+ .reg_wakeup_event_mask = 0xC1382213,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ /* [31:0] */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+};
+
+struct spm_lp_scen __spm_suspend = {
+ .pwrctrl = &suspend_ctrl,
+};
+
+int mt_spm_suspend_mode_set(int mode)
+{
+ if (mode == MT_SPM_SUSPEND_SLEEP) {
+ suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG;
+ suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1;
+ } else {
+ suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG;
+ suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1;
+ }
+
+ return 0;
+}
+
+int mt_spm_suspend_enter(int state_id, unsigned int ext_opand,
+ unsigned int resource_req)
+{
+ /* If FMAudio / ADSP is active, change to sleep suspend mode */
+ if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
+ mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP);
+ }
+
+ /* Notify MCUPM that device is going suspend flow */
+ mmio_write_32(MCUPM_MBOX_OFFSET_PDN, MCUPM_POWER_DOWN);
+
+ /* Notify UART to sleep */
+ mt_uart_save();
+
+ return spm_conservation(state_id, ext_opand,
+ &__spm_suspend, resource_req);
+}
+
+void mt_spm_suspend_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status)
+{
+ spm_conservation_finish(state_id, ext_opand, &__spm_suspend, status);
+
+ /* Notify UART to wakeup */
+ mt_uart_restore();
+
+ /* Notify MCUPM that device leave suspend */
+ mmio_write_32(MCUPM_MBOX_OFFSET_PDN, 0);
+
+ /* If FMAudio / ADSP is active, change back to suspend mode */
+ if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
+ mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN);
+ }
+}
+
+void mt_spm_suspend_init(void)
+{
+ spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl);
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h
new file mode 100644
index 0000000..69c5230
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SUSPEND_H
+#define MT_SPM_SUSPEND_H
+
+#include <mt_spm_internal.h>
+
+#define MCUPM_MBOX_OFFSET_PDN 0x1031FF88
+#define MCUPM_POWER_DOWN 0x4D50444E
+
+enum MT_SPM_SUSPEND_MODE {
+ MT_SPM_SUSPEND_SYSTEM_PDN,
+ MT_SPM_SUSPEND_SLEEP,
+};
+
+extern int mt_spm_suspend_mode_set(int mode);
+extern int mt_spm_suspend_enter(int state_id, unsigned int ext_opand,
+ unsigned int reosuce_req);
+extern void mt_spm_suspend_resume(int state_id, unsigned int ext_opand,
+ struct wake_status **status);
+extern void mt_spm_suspend_init(void);
+#endif /* MT_SPM_SUSPEND_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c
new file mode 100644
index 0000000..6a85b5c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stddef.h>
+#include <string.h>
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_vcorefs.h>
+#include <mtk_plat_common.h>
+#include <mtk_sip_svc.h>
+#include <platform_def.h>
+
+#define VCORE_MAX_OPP 4
+#define DRAM_MAX_OPP 7
+
+static bool spm_dvfs_init_done;
+static bool dvfs_enable_done;
+static int vcore_opp_0_uv = 750000;
+static int vcore_opp_1_uv = 650000;
+static int vcore_opp_2_uv = 600000;
+static int vcore_opp_3_uv = 550000;
+
+static struct reg_config dvfsrc_init_configs[] = {
+ { DVFSRC_HRT_REQ_UNIT, 0x0000001E },
+ { DVFSRC_DEBOUNCE_TIME, 0x19651965 },
+ { DVFSRC_TIMEOUT_NEXTREQ, 0x00000015 },
+ { DVFSRC_LEVEL_MASK, 0x000EE000 },
+ { DVFSRC_DDR_QOS0, 0x00000019 },
+ { DVFSRC_DDR_QOS1, 0x00000026 },
+ { DVFSRC_DDR_QOS2, 0x00000033 },
+ { DVFSRC_DDR_QOS3, 0x0000003B },
+ { DVFSRC_DDR_QOS4, 0x0000004C },
+ { DVFSRC_DDR_QOS5, 0x00000066 },
+ { DVFSRC_DDR_QOS6, 0x00660066 },
+ { DVFSRC_LEVEL_LABEL_0_1, 0x50436053 },
+ { DVFSRC_LEVEL_LABEL_2_3, 0x40335042 },
+ { DVFSRC_LEVEL_LABEL_4_5, 0x40314032 },
+ { DVFSRC_LEVEL_LABEL_6_7, 0x30223023 },
+ { DVFSRC_LEVEL_LABEL_8_9, 0x20133021 },
+ { DVFSRC_LEVEL_LABEL_10_11, 0x20112012 },
+ { DVFSRC_LEVEL_LABEL_12_13, 0x10032010 },
+ { DVFSRC_LEVEL_LABEL_14_15, 0x10011002 },
+ { DVFSRC_LEVEL_LABEL_16_17, 0x00131000 },
+ { DVFSRC_LEVEL_LABEL_18_19, 0x00110012 },
+ { DVFSRC_LEVEL_LABEL_20_21, 0x00000010 },
+ { DVFSRC_MD_LATENCY_IMPROVE, 0x00000040 },
+ { DVFSRC_DDR_REQUEST, 0x00004321 },
+ { DVFSRC_DDR_REQUEST3, 0x00000065 },
+ { DVFSRC_DDR_ADD_REQUEST, 0x66543210 },
+ { DVFSRC_HRT_REQUEST, 0x66654321 },
+ { DVFSRC_DDR_REQUEST5, 0x54321000 },
+ { DVFSRC_DDR_REQUEST7, 0x66000000 },
+ { DVFSRC_VCORE_USER_REQ, 0x00010A29 },
+ { DVFSRC_HRT_HIGH_3, 0x18A618A6 },
+ { DVFSRC_HRT_HIGH_2, 0x18A61183 },
+ { DVFSRC_HRT_HIGH_1, 0x0D690B80 },
+ { DVFSRC_HRT_HIGH, 0x070804B0 },
+ { DVFSRC_HRT_LOW_3, 0x18A518A5 },
+ { DVFSRC_HRT_LOW_2, 0x18A51182 },
+ { DVFSRC_HRT_LOW_1, 0x0D680B7F },
+ { DVFSRC_HRT_LOW, 0x070704AF },
+ { DVFSRC_BASIC_CONTROL_3, 0x00000006 },
+ { DVFSRC_INT_EN, 0x00000002 },
+ { DVFSRC_QOS_EN, 0x0000407C },
+ { DVFSRC_HRT_BW_BASE, 0x00000004 },
+ { DVFSRC_PCIE_VCORE_REQ, 0x65908101 },
+ { DVFSRC_CURRENT_FORCE, 0x00000001 },
+ { DVFSRC_BASIC_CONTROL, 0x6698444B },
+ { DVFSRC_BASIC_CONTROL, 0x6698054B },
+ { DVFSRC_CURRENT_FORCE, 0x00000000 },
+};
+
+static struct pwr_ctrl vcorefs_ctrl = {
+ .wake_src = R12_REG_CPU_WAKEUP,
+
+ /* default VCORE DVFS is disabled */
+ .pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO |
+ SPM_FLAG_DISABLE_VCORE_DVS | SPM_FLAG_DISABLE_VCORE_DFS),
+
+ /* SPM_AP_STANDBY_CON */
+ /* [0] */
+ .reg_wfi_op = 0,
+ /* [1] */
+ .reg_wfi_type = 0,
+ /* [2] */
+ .reg_mp0_cputop_idle_mask = 0,
+ /* [3] */
+ .reg_mp1_cputop_idle_mask = 0,
+ /* [4] */
+ .reg_mcusys_idle_mask = 0,
+ /* [25] */
+ .reg_md_apsrc_1_sel = 0,
+ /* [26] */
+ .reg_md_apsrc_0_sel = 0,
+ /* [29] */
+ .reg_conn_apsrc_sel = 0,
+
+ /* SPM_SRC_REQ */
+ /* [0] */
+ .reg_spm_apsrc_req = 0,
+ /* [1] */
+ .reg_spm_f26m_req = 0,
+ /* [3] */
+ .reg_spm_infra_req = 0,
+ /* [4] */
+ .reg_spm_vrf18_req = 0,
+ /* [7] FIXME: default disable HW Auto S1*/
+ .reg_spm_ddr_en_req = 1,
+ /* [8] */
+ .reg_spm_dvfs_req = 0,
+ /* [9] */
+ .reg_spm_sw_mailbox_req = 0,
+ /* [10] */
+ .reg_spm_sspm_mailbox_req = 0,
+ /* [11] */
+ .reg_spm_adsp_mailbox_req = 0,
+ /* [12] */
+ .reg_spm_scp_mailbox_req = 0,
+
+ /* SPM_SRC_MASK */
+ /* [0] */
+ .reg_sspm_srcclkena_0_mask_b = 1,
+ /* [1] */
+ .reg_sspm_infra_req_0_mask_b = 1,
+ /* [2] */
+ .reg_sspm_apsrc_req_0_mask_b = 1,
+ /* [3] */
+ .reg_sspm_vrf18_req_0_mask_b = 1,
+ /* [4] */
+ .reg_sspm_ddr_en_0_mask_b = 1,
+ /* [5] */
+ .reg_scp_srcclkena_mask_b = 1,
+ /* [6] */
+ .reg_scp_infra_req_mask_b = 1,
+ /* [7] */
+ .reg_scp_apsrc_req_mask_b = 1,
+ /* [8] */
+ .reg_scp_vrf18_req_mask_b = 1,
+ /* [9] */
+ .reg_scp_ddr_en_mask_b = 1,
+ /* [10] */
+ .reg_audio_dsp_srcclkena_mask_b = 1,
+ /* [11] */
+ .reg_audio_dsp_infra_req_mask_b = 1,
+ /* [12] */
+ .reg_audio_dsp_apsrc_req_mask_b = 1,
+ /* [13] */
+ .reg_audio_dsp_vrf18_req_mask_b = 1,
+ /* [14] */
+ .reg_audio_dsp_ddr_en_mask_b = 1,
+ /* [15] */
+ .reg_apu_srcclkena_mask_b = 1,
+ /* [16] */
+ .reg_apu_infra_req_mask_b = 1,
+ /* [17] */
+ .reg_apu_apsrc_req_mask_b = 1,
+ /* [18] */
+ .reg_apu_vrf18_req_mask_b = 1,
+ /* [19] */
+ .reg_apu_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_cpueb_srcclkena_mask_b = 1,
+ /* [21] */
+ .reg_cpueb_infra_req_mask_b = 1,
+ /* [22] */
+ .reg_cpueb_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_cpueb_vrf18_req_mask_b = 1,
+ /* [24] */
+ .reg_cpueb_ddr_en_mask_b = 1,
+ /* [25] */
+ .reg_bak_psri_srcclkena_mask_b = 0,
+ /* [26] */
+ .reg_bak_psri_infra_req_mask_b = 0,
+ /* [27] */
+ .reg_bak_psri_apsrc_req_mask_b = 0,
+ /* [28] */
+ .reg_bak_psri_vrf18_req_mask_b = 0,
+ /* [29] */
+ .reg_bak_psri_ddr_en_mask_b = 0,
+
+ /* SPM_SRC2_MASK */
+ /* [0] */
+ .reg_msdc0_srcclkena_mask_b = 1,
+ /* [1] */
+ .reg_msdc0_infra_req_mask_b = 1,
+ /* [2] */
+ .reg_msdc0_apsrc_req_mask_b = 1,
+ /* [3] */
+ .reg_msdc0_vrf18_req_mask_b = 1,
+ /* [4] */
+ .reg_msdc0_ddr_en_mask_b = 1,
+ /* [5] */
+ .reg_msdc1_srcclkena_mask_b = 1,
+ /* [6] */
+ .reg_msdc1_infra_req_mask_b = 1,
+ /* [7] */
+ .reg_msdc1_apsrc_req_mask_b = 1,
+ /* [8] */
+ .reg_msdc1_vrf18_req_mask_b = 1,
+ /* [9] */
+ .reg_msdc1_ddr_en_mask_b = 1,
+ /* [10] */
+ .reg_msdc2_srcclkena_mask_b = 1,
+ /* [11] */
+ .reg_msdc2_infra_req_mask_b = 1,
+ /* [12] */
+ .reg_msdc2_apsrc_req_mask_b = 1,
+ /* [13] */
+ .reg_msdc2_vrf18_req_mask_b = 1,
+ /* [14] */
+ .reg_msdc2_ddr_en_mask_b = 1,
+ /* [15] */
+ .reg_ufs_srcclkena_mask_b = 1,
+ /* [16] */
+ .reg_ufs_infra_req_mask_b = 1,
+ /* [17] */
+ .reg_ufs_apsrc_req_mask_b = 1,
+ /* [18] */
+ .reg_ufs_vrf18_req_mask_b = 1,
+ /* [19] */
+ .reg_ufs_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_usb_srcclkena_mask_b = 1,
+ /* [21] */
+ .reg_usb_infra_req_mask_b = 1,
+ /* [22] */
+ .reg_usb_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_usb_vrf18_req_mask_b = 1,
+ /* [24] */
+ .reg_usb_ddr_en_mask_b = 1,
+ /* [25] */
+ .reg_pextp_p0_srcclkena_mask_b = 1,
+ /* [26] */
+ .reg_pextp_p0_infra_req_mask_b = 1,
+ /* [27] */
+ .reg_pextp_p0_apsrc_req_mask_b = 1,
+ /* [28] */
+ .reg_pextp_p0_vrf18_req_mask_b = 1,
+ /* [29] */
+ .reg_pextp_p0_ddr_en_mask_b = 1,
+
+ /* SPM_SRC3_MASK */
+ /* [0] */
+ .reg_pextp_p1_srcclkena_mask_b = 1,
+ /* [1] */
+ .reg_pextp_p1_infra_req_mask_b = 1,
+ /* [2] */
+ .reg_pextp_p1_apsrc_req_mask_b = 1,
+ /* [3] */
+ .reg_pextp_p1_vrf18_req_mask_b = 1,
+ /* [4] */
+ .reg_pextp_p1_ddr_en_mask_b = 1,
+ /* [5] */
+ .reg_gce0_infra_req_mask_b = 1,
+ /* [6] */
+ .reg_gce0_apsrc_req_mask_b = 1,
+ /* [7] */
+ .reg_gce0_vrf18_req_mask_b = 1,
+ /* [8] */
+ .reg_gce0_ddr_en_mask_b = 1,
+ /* [9] */
+ .reg_gce1_infra_req_mask_b = 1,
+ /* [10] */
+ .reg_gce1_apsrc_req_mask_b = 1,
+ /* [11] */
+ .reg_gce1_vrf18_req_mask_b = 1,
+ /* [12] */
+ .reg_gce1_ddr_en_mask_b = 1,
+ /* [13] */
+ .reg_spm_srcclkena_reserved_mask_b = 1,
+ /* [14] */
+ .reg_spm_infra_req_reserved_mask_b = 1,
+ /* [15] */
+ .reg_spm_apsrc_req_reserved_mask_b = 1,
+ /* [16] */
+ .reg_spm_vrf18_req_reserved_mask_b = 1,
+ /* [17] */
+ .reg_spm_ddr_en_reserved_mask_b = 1,
+ /* [18] */
+ .reg_disp0_apsrc_req_mask_b = 1,
+ /* [19] */
+ .reg_disp0_ddr_en_mask_b = 1,
+ /* [20] */
+ .reg_disp1_apsrc_req_mask_b = 1,
+ /* [21] */
+ .reg_disp1_ddr_en_mask_b = 1,
+ /* [22] */
+ .reg_disp2_apsrc_req_mask_b = 1,
+ /* [23] */
+ .reg_disp2_ddr_en_mask_b = 1,
+ /* [24] */
+ .reg_disp3_apsrc_req_mask_b = 1,
+ /* [25] */
+ .reg_disp3_ddr_en_mask_b = 1,
+ /* [26] */
+ .reg_infrasys_apsrc_req_mask_b = 0,
+ /* [27] */
+ .reg_infrasys_ddr_en_mask_b = 1,
+
+ /* [28] */
+ .reg_cg_check_srcclkena_mask_b = 1,
+ /* [29] */
+ .reg_cg_check_apsrc_req_mask_b = 1,
+ /* [30] */
+ .reg_cg_check_vrf18_req_mask_b = 1,
+ /* [31] */
+ .reg_cg_check_ddr_en_mask_b = 1,
+
+ /* SPM_SRC4_MASK */
+ /* [8:0] */
+ .reg_mcusys_merge_apsrc_req_mask_b = 0x11,
+ /* [17:9] */
+ .reg_mcusys_merge_ddr_en_mask_b = 0x11,
+ /* [19:18] */
+ .reg_dramc_md32_infra_req_mask_b = 0,
+ /* [21:20] */
+ .reg_dramc_md32_vrf18_req_mask_b = 0,
+ /* [23:22] */
+ .reg_dramc_md32_ddr_en_mask_b = 0,
+ /* [24] */
+ .reg_dvfsrc_event_trigger_mask_b = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK2 */
+ /* [3:0] */
+ .reg_sc_sw2spm_wakeup_mask_b = 0,
+ /* [4] */
+ .reg_sc_adsp2spm_wakeup_mask_b = 0,
+ /* [8:5] */
+ .reg_sc_sspm2spm_wakeup_mask_b = 0,
+ /* [9] */
+ .reg_sc_scp2spm_wakeup_mask_b = 0,
+ /* [10] */
+ .reg_csyspwrup_ack_mask = 0,
+ /* [11] */
+ .reg_csyspwrup_req_mask = 1,
+
+ /* SPM_WAKEUP_EVENT_MASK */
+ /* [31:0] */
+ .reg_wakeup_event_mask = 0xEFFFFFFF,
+
+ /* SPM_WAKEUP_EVENT_EXT_MASK */
+ /* [31:0] */
+ .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+};
+
+struct spm_lp_scen __spm_vcorefs = {
+ .pwrctrl = &vcorefs_ctrl,
+};
+
+static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val)
+{
+ if (cmd < NR_IDX_ALL) {
+ mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val);
+ } else {
+ INFO("cmd out of range!\n");
+ }
+}
+
+void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue)
+{
+ if (spm_dvfs_init_done == false) {
+ mmio_write_32(SPM_DVFS_MISC, (mmio_read_32(SPM_DVFS_MISC) &
+ ~(SPM_DVFS_FORCE_ENABLE_LSB)) | (SPM_DVFSRC_ENABLE_LSB));
+
+ mmio_write_32(SPM_DVFS_LEVEL, 0x00000001);
+ mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001);
+
+ spm_dvfs_init_done = true;
+ }
+}
+
+void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+ const struct pwr_ctrl *src_pwr_ctrl)
+{
+ uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS |
+ SPM_FLAG_DISABLE_VCORE_DFS |
+ SPM_FLAG_ENABLE_VOLTAGE_BIN;
+
+ dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) |
+ (src_pwr_ctrl->pcm_flags & dvfs_mask);
+
+ if (dest_pwr_ctrl->pcm_flags_cust) {
+ dest_pwr_ctrl->pcm_flags_cust = (dest_pwr_ctrl->pcm_flags_cust & (~dvfs_mask)) |
+ (src_pwr_ctrl->pcm_flags & dvfs_mask);
+ }
+}
+
+void spm_go_to_vcorefs(uint64_t spm_flags)
+{
+ __spm_set_power_control(__spm_vcorefs.pwrctrl);
+ __spm_set_wakeup_event(__spm_vcorefs.pwrctrl);
+ __spm_set_pcm_flags(__spm_vcorefs.pwrctrl);
+ __spm_send_cpu_wakeup_event();
+}
+
+uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3)
+{
+ uint64_t ret = 0U;
+ uint64_t cmd = x1;
+ uint64_t spm_flags;
+
+ switch (cmd) {
+ case VCOREFS_SMC_CMD_0:
+ spm_dvfsfw_init(x2, x3);
+ break;
+ case VCOREFS_SMC_CMD_1:
+ spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+ if (x2 & SPM_FLAG_DISABLE_VCORE_DVS)
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+ if (x2 & SPM_FLAG_DISABLE_VCORE_DFS)
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+ spm_go_to_vcorefs(spm_flags);
+ break;
+ case VCOREFS_SMC_CMD_3:
+ spm_vcorefs_pwarp_cmd(x2, x3);
+ break;
+ case VCOREFS_SMC_CMD_2:
+ case VCOREFS_SMC_CMD_4:
+ case VCOREFS_SMC_CMD_5:
+ case VCOREFS_SMC_CMD_7:
+ default:
+ break;
+ }
+ return ret;
+}
+
+static void dvfsrc_init(void)
+{
+ int i;
+ int count = ARRAY_SIZE(dvfsrc_init_configs);
+
+ if (dvfs_enable_done == false) {
+ for (i = 0; i < count; i++) {
+ mmio_write_32(dvfsrc_init_configs[i].offset,
+ dvfsrc_init_configs[i].val);
+ }
+
+ mmio_write_32(DVFSRC_QOS_EN, 0x0011007C);
+
+ dvfs_enable_done = true;
+ }
+}
+
+static void spm_vcorefs_vcore_setting(uint64_t flag)
+{
+ spm_vcorefs_pwarp_cmd(3, __vcore_uv_to_pmic(vcore_opp_3_uv));
+ spm_vcorefs_pwarp_cmd(2, __vcore_uv_to_pmic(vcore_opp_2_uv));
+ spm_vcorefs_pwarp_cmd(1, __vcore_uv_to_pmic(vcore_opp_1_uv));
+ spm_vcorefs_pwarp_cmd(0, __vcore_uv_to_pmic(vcore_opp_0_uv));
+}
+
+int spm_vcorefs_get_vcore(unsigned int gear)
+{
+ int ret_val;
+
+ switch (gear) {
+ case 3:
+ ret_val = vcore_opp_0_uv;
+ break;
+ case 2:
+ ret_val = vcore_opp_1_uv;
+ break;
+ case 1:
+ ret_val = vcore_opp_2_uv;
+ break;
+ case 0:
+ default:
+ ret_val = vcore_opp_3_uv;
+ break;
+ }
+ return ret_val;
+}
+
+uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3, u_register_t *x4)
+{
+ uint64_t ret = 0U;
+ uint64_t cmd = x1;
+ uint64_t spm_flags;
+
+ switch (cmd) {
+ case VCOREFS_SMC_CMD_INIT:
+ /* vcore_dvfs init + kick */
+ spm_dvfsfw_init(0, 0);
+ spm_vcorefs_vcore_setting(x3 & 0xF);
+ spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+ if (x2 & 0x1) {
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+ }
+ if (x2 & 0x2) {
+ spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+ }
+ spm_go_to_vcorefs(spm_flags);
+ dvfsrc_init();
+ *x4 = 0U;
+ break;
+ case VCOREFS_SMC_CMD_OPP_TYPE:
+ /* get dram type */
+ *x4 = 0U;
+ break;
+ case VCOREFS_SMC_CMD_FW_TYPE:
+ *x4 = 0U;
+ break;
+ case VCOREFS_SMC_CMD_GET_UV:
+ *x4 = spm_vcorefs_get_vcore(x2);
+ break;
+ case VCOREFS_SMC_CMD_GET_NUM_V:
+ *x4 = VCORE_MAX_OPP;
+ break;
+ case VCOREFS_SMC_CMD_GET_NUM_F:
+ *x4 = DRAM_MAX_OPP;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h
new file mode 100644
index 0000000..b08fcce
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __MT_SPM_VCOREFS__H__
+#define __MT_SPM_VCOREFS__H__
+
+int spm_vcorefs_get_vcore(unsigned int gear);
+uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3,
+ u_register_t *x4);
+
+enum vcorefs_smc_cmd {
+ VCOREFS_SMC_CMD_0 = 0,
+ VCOREFS_SMC_CMD_1,
+ VCOREFS_SMC_CMD_2,
+ VCOREFS_SMC_CMD_3,
+ VCOREFS_SMC_CMD_4,
+ /* check spmfw status */
+ VCOREFS_SMC_CMD_5,
+
+ /* get spmfw type */
+ VCOREFS_SMC_CMD_6,
+
+ /* get spm reg status */
+ VCOREFS_SMC_CMD_7,
+
+ NUM_VCOREFS_SMC_CMD,
+};
+
+enum vcorefs_smc_cmd_new {
+ VCOREFS_SMC_CMD_INIT = 0,
+ VCOREFS_SMC_CMD_KICK = 1,
+ VCOREFS_SMC_CMD_OPP_TYPE = 2,
+ VCOREFS_SMC_CMD_FW_TYPE = 3,
+ VCOREFS_SMC_CMD_GET_UV = 4,
+ VCOREFS_SMC_CMD_GET_FREQ = 5,
+ VCOREFS_SMC_CMD_GET_NUM_V = 6,
+ VCOREFS_SMC_CMD_GET_NUM_F = 7,
+ VCOREFS_SMC_CMD_FB_ACTION = 8,
+ /*chip specific setting */
+ VCOREFS_SMC_CMD_SET_FREQ = 16,
+ VCOREFS_SMC_CMD_SET_EFUSE = 17,
+ VCOREFS_SMC_CMD_GET_EFUSE = 18,
+ VCOREFS_SMC_CMD_DVFS_HOPPING = 19,
+ VCOREFS_SMC_CMD_DVFS_HOPPING_STATE = 20,
+};
+
+enum dvfsrc_channel {
+ DVFSRC_CHANNEL_1 = 1,
+ DVFSRC_CHANNEL_2,
+ DVFSRC_CHANNEL_3,
+ DVFSRC_CHANNEL_4,
+ NUM_DVFSRC_CHANNEL,
+};
+
+#define _VCORE_BASE_UV 400000
+#define _VCORE_STEP_UV 6250
+
+/* PMIC */
+#define __vcore_pmic_to_uv(pmic) \
+ (((pmic) * _VCORE_STEP_UV) + _VCORE_BASE_UV)
+
+#define __vcore_uv_to_pmic(uv) /* pmic >= uv */ \
+ ((((uv) - _VCORE_BASE_UV) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV)
+
+struct reg_config {
+ uint32_t offset;
+ uint32_t val;
+};
+
+#define DVFSRC_BASIC_CONTROL (DVFSRC_BASE + 0x0)
+#define DVFSRC_SW_REQ1 (DVFSRC_BASE + 0x4)
+#define DVFSRC_SW_REQ2 (DVFSRC_BASE + 0x8)
+#define DVFSRC_SW_REQ3 (DVFSRC_BASE + 0xC)
+#define DVFSRC_SW_REQ4 (DVFSRC_BASE + 0x10)
+#define DVFSRC_SW_REQ5 (DVFSRC_BASE + 0x14)
+#define DVFSRC_SW_REQ6 (DVFSRC_BASE + 0x18)
+#define DVFSRC_SW_REQ7 (DVFSRC_BASE + 0x1C)
+#define DVFSRC_SW_REQ8 (DVFSRC_BASE + 0x20)
+#define DVFSRC_EMI_REQUEST (DVFSRC_BASE + 0x24)
+#define DVFSRC_EMI_REQUEST2 (DVFSRC_BASE + 0x28)
+#define DVFSRC_EMI_REQUEST3 (DVFSRC_BASE + 0x2C)
+#define DVFSRC_EMI_REQUEST4 (DVFSRC_BASE + 0x30)
+#define DVFSRC_EMI_REQUEST5 (DVFSRC_BASE + 0x34)
+#define DVFSRC_EMI_REQUEST6 (DVFSRC_BASE + 0x38)
+#define DVFSRC_EMI_HRT (DVFSRC_BASE + 0x3C)
+#define DVFSRC_EMI_HRT2 (DVFSRC_BASE + 0x40)
+#define DVFSRC_EMI_HRT3 (DVFSRC_BASE + 0x44)
+#define DVFSRC_EMI_QOS0 (DVFSRC_BASE + 0x48)
+#define DVFSRC_EMI_QOS1 (DVFSRC_BASE + 0x4C)
+#define DVFSRC_EMI_QOS2 (DVFSRC_BASE + 0x50)
+#define DVFSRC_EMI_MD2SPM0 (DVFSRC_BASE + 0x54)
+#define DVFSRC_EMI_MD2SPM1 (DVFSRC_BASE + 0x58)
+#define DVFSRC_EMI_MD2SPM2 (DVFSRC_BASE + 0x5C)
+#define DVFSRC_EMI_MD2SPM0_T (DVFSRC_BASE + 0x60)
+#define DVFSRC_EMI_MD2SPM1_T (DVFSRC_BASE + 0x64)
+#define DVFSRC_EMI_MD2SPM2_T (DVFSRC_BASE + 0x68)
+#define DVFSRC_VCORE_REQUEST (DVFSRC_BASE + 0x6C)
+#define DVFSRC_VCORE_REQUEST2 (DVFSRC_BASE + 0x70)
+#define DVFSRC_VCORE_REQUEST3 (DVFSRC_BASE + 0x74)
+#define DVFSRC_VCORE_REQUEST4 (DVFSRC_BASE + 0x78)
+#define DVFSRC_VCORE_HRT (DVFSRC_BASE + 0x7C)
+#define DVFSRC_VCORE_HRT2 (DVFSRC_BASE + 0x80)
+#define DVFSRC_VCORE_HRT3 (DVFSRC_BASE + 0x84)
+#define DVFSRC_VCORE_QOS0 (DVFSRC_BASE + 0x88)
+#define DVFSRC_VCORE_QOS1 (DVFSRC_BASE + 0x8C)
+#define DVFSRC_VCORE_QOS2 (DVFSRC_BASE + 0x90)
+#define DVFSRC_VCORE_MD2SPM0 (DVFSRC_BASE + 0x94)
+#define DVFSRC_VCORE_MD2SPM1 (DVFSRC_BASE + 0x98)
+#define DVFSRC_VCORE_MD2SPM2 (DVFSRC_BASE + 0x9C)
+#define DVFSRC_VCORE_MD2SPM0_T (DVFSRC_BASE + 0xA0)
+#define DVFSRC_VCORE_MD2SPM1_T (DVFSRC_BASE + 0xA4)
+#define DVFSRC_VCORE_MD2SPM2_T (DVFSRC_BASE + 0xA8)
+#define DVFSRC_MD_VSRAM_REMAP (DVFSRC_BASE + 0xBC)
+#define DVFSRC_HALT_SW_CONTROL (DVFSRC_BASE + 0xC0)
+#define DVFSRC_INT (DVFSRC_BASE + 0xC4)
+#define DVFSRC_INT_EN (DVFSRC_BASE + 0xC8)
+#define DVFSRC_INT_CLR (DVFSRC_BASE + 0xCC)
+#define DVFSRC_BW_MON_WINDOW (DVFSRC_BASE + 0xD0)
+#define DVFSRC_BW_MON_THRES_1 (DVFSRC_BASE + 0xD4)
+#define DVFSRC_BW_MON_THRES_2 (DVFSRC_BASE + 0xD8)
+#define DVFSRC_MD_TURBO (DVFSRC_BASE + 0xDC)
+#define DVFSRC_PCIE_VCORE_REQ (DVFSRC_BASE + 0xE0)
+#define DVFSRC_VCORE_USER_REQ (DVFSRC_BASE + 0xE4)
+#define DVFSRC_DEBOUNCE_FOUR (DVFSRC_BASE + 0xF0)
+#define DVFSRC_DEBOUNCE_RISE_FALL (DVFSRC_BASE + 0xF4)
+#define DVFSRC_TIMEOUT_NEXTREQ (DVFSRC_BASE + 0xF8)
+#define DVFSRC_LEVEL_LABEL_0_1 (DVFSRC_BASE + 0x100)
+#define DVFSRC_LEVEL_LABEL_2_3 (DVFSRC_BASE + 0x104)
+#define DVFSRC_LEVEL_LABEL_4_5 (DVFSRC_BASE + 0x108)
+#define DVFSRC_LEVEL_LABEL_6_7 (DVFSRC_BASE + 0x10C)
+#define DVFSRC_LEVEL_LABEL_8_9 (DVFSRC_BASE + 0x110)
+#define DVFSRC_LEVEL_LABEL_10_11 (DVFSRC_BASE + 0x114)
+#define DVFSRC_LEVEL_LABEL_12_13 (DVFSRC_BASE + 0x118)
+#define DVFSRC_LEVEL_LABEL_14_15 (DVFSRC_BASE + 0x11C)
+#define DVFSRC_MM_BW_0 (DVFSRC_BASE + 0x200)
+#define DVFSRC_MM_BW_1 (DVFSRC_BASE + 0x204)
+#define DVFSRC_MM_BW_2 (DVFSRC_BASE + 0x208)
+#define DVFSRC_MM_BW_3 (DVFSRC_BASE + 0x20C)
+#define DVFSRC_MM_BW_4 (DVFSRC_BASE + 0x210)
+#define DVFSRC_MM_BW_5 (DVFSRC_BASE + 0x214)
+#define DVFSRC_MM_BW_6 (DVFSRC_BASE + 0x218)
+#define DVFSRC_MM_BW_7 (DVFSRC_BASE + 0x21C)
+#define DVFSRC_MM_BW_8 (DVFSRC_BASE + 0x220)
+#define DVFSRC_MM_BW_9 (DVFSRC_BASE + 0x224)
+#define DVFSRC_MM_BW_10 (DVFSRC_BASE + 0x228)
+#define DVFSRC_MM_BW_11 (DVFSRC_BASE + 0x22C)
+#define DVFSRC_MM_BW_12 (DVFSRC_BASE + 0x230)
+#define DVFSRC_MM_BW_13 (DVFSRC_BASE + 0x234)
+#define DVFSRC_MM_BW_14 (DVFSRC_BASE + 0x238)
+#define DVFSRC_MM_BW_15 (DVFSRC_BASE + 0x23C)
+#define DVFSRC_MD_BW_0 (DVFSRC_BASE + 0x240)
+#define DVFSRC_MD_BW_1 (DVFSRC_BASE + 0x244)
+#define DVFSRC_MD_BW_2 (DVFSRC_BASE + 0x248)
+#define DVFSRC_MD_BW_3 (DVFSRC_BASE + 0x24C)
+#define DVFSRC_MD_BW_4 (DVFSRC_BASE + 0x250)
+#define DVFSRC_MD_BW_5 (DVFSRC_BASE + 0x254)
+#define DVFSRC_MD_BW_6 (DVFSRC_BASE + 0x258)
+#define DVFSRC_MD_BW_7 (DVFSRC_BASE + 0x25C)
+#define DVFSRC_SW_BW_0 (DVFSRC_BASE + 0x260)
+#define DVFSRC_SW_BW_1 (DVFSRC_BASE + 0x264)
+#define DVFSRC_SW_BW_2 (DVFSRC_BASE + 0x268)
+#define DVFSRC_SW_BW_3 (DVFSRC_BASE + 0x26C)
+#define DVFSRC_SW_BW_4 (DVFSRC_BASE + 0x270)
+#define DVFSRC_SW_BW_5 (DVFSRC_BASE + 0x274)
+#define DVFSRC_SW_BW_6 (DVFSRC_BASE + 0x278)
+#define DVFSRC_QOS_EN (DVFSRC_BASE + 0x280)
+#define DVFSRC_MD_BW_URG (DVFSRC_BASE + 0x284)
+#define DVFSRC_ISP_HRT (DVFSRC_BASE + 0x290)
+#define DVFSRC_HRT_BW_BASE (DVFSRC_BASE + 0x294)
+#define DVFSRC_SEC_SW_REQ (DVFSRC_BASE + 0x304)
+#define DVFSRC_EMI_MON_DEBOUNCE_TIME (DVFSRC_BASE + 0x308)
+#define DVFSRC_MD_LATENCY_IMPROVE (DVFSRC_BASE + 0x30C)
+#define DVFSRC_BASIC_CONTROL_3 (DVFSRC_BASE + 0x310)
+#define DVFSRC_DEBOUNCE_TIME (DVFSRC_BASE + 0x314)
+#define DVFSRC_LEVEL_MASK (DVFSRC_BASE + 0x318)
+#define DVFSRC_DEFAULT_OPP (DVFSRC_BASE + 0x31C)
+#define DVFSRC_95MD_SCEN_EMI0 (DVFSRC_BASE + 0x500)
+#define DVFSRC_95MD_SCEN_EMI1 (DVFSRC_BASE + 0x504)
+#define DVFSRC_95MD_SCEN_EMI2 (DVFSRC_BASE + 0x508)
+#define DVFSRC_95MD_SCEN_EMI3 (DVFSRC_BASE + 0x50C)
+#define DVFSRC_95MD_SCEN_EMI0_T (DVFSRC_BASE + 0x510)
+#define DVFSRC_95MD_SCEN_EMI1_T (DVFSRC_BASE + 0x514)
+#define DVFSRC_95MD_SCEN_EMI2_T (DVFSRC_BASE + 0x518)
+#define DVFSRC_95MD_SCEN_EMI3_T (DVFSRC_BASE + 0x51C)
+#define DVFSRC_95MD_SCEN_EMI4 (DVFSRC_BASE + 0x520)
+#define DVFSRC_95MD_SCEN_BW0 (DVFSRC_BASE + 0x524)
+#define DVFSRC_95MD_SCEN_BW1 (DVFSRC_BASE + 0x528)
+#define DVFSRC_95MD_SCEN_BW2 (DVFSRC_BASE + 0x52C)
+#define DVFSRC_95MD_SCEN_BW3 (DVFSRC_BASE + 0x530)
+#define DVFSRC_95MD_SCEN_BW0_T (DVFSRC_BASE + 0x534)
+#define DVFSRC_95MD_SCEN_BW1_T (DVFSRC_BASE + 0x538)
+#define DVFSRC_95MD_SCEN_BW2_T (DVFSRC_BASE + 0x53C)
+#define DVFSRC_95MD_SCEN_BW3_T (DVFSRC_BASE + 0x540)
+#define DVFSRC_95MD_SCEN_BW4 (DVFSRC_BASE + 0x544)
+#define DVFSRC_MD_LEVEL_SW_REG (DVFSRC_BASE + 0x548)
+#define DVFSRC_RSRV_0 (DVFSRC_BASE + 0x600)
+#define DVFSRC_RSRV_1 (DVFSRC_BASE + 0x604)
+#define DVFSRC_RSRV_2 (DVFSRC_BASE + 0x608)
+#define DVFSRC_RSRV_3 (DVFSRC_BASE + 0x60C)
+#define DVFSRC_RSRV_4 (DVFSRC_BASE + 0x610)
+#define DVFSRC_RSRV_5 (DVFSRC_BASE + 0x614)
+#define DVFSRC_SPM_RESEND (DVFSRC_BASE + 0x630)
+#define DVFSRC_DEBUG_STA_0 (DVFSRC_BASE + 0x700)
+#define DVFSRC_DEBUG_STA_1 (DVFSRC_BASE + 0x704)
+#define DVFSRC_DEBUG_STA_2 (DVFSRC_BASE + 0x708)
+#define DVFSRC_DEBUG_STA_3 (DVFSRC_BASE + 0x70C)
+#define DVFSRC_DEBUG_STA_4 (DVFSRC_BASE + 0x710)
+#define DVFSRC_DEBUG_STA_5 (DVFSRC_BASE + 0x714)
+#define DVFSRC_EMI_REQUEST7 (DVFSRC_BASE + 0x800)
+#define DVFSRC_EMI_HRT_1 (DVFSRC_BASE + 0x804)
+#define DVFSRC_EMI_HRT2_1 (DVFSRC_BASE + 0x808)
+#define DVFSRC_EMI_HRT3_1 (DVFSRC_BASE + 0x80C)
+#define DVFSRC_EMI_QOS3 (DVFSRC_BASE + 0x810)
+#define DVFSRC_EMI_QOS4 (DVFSRC_BASE + 0x814)
+#define DVFSRC_DDR_REQUEST (DVFSRC_BASE + 0xA00)
+#define DVFSRC_DDR_REQUEST2 (DVFSRC_BASE + 0xA04)
+#define DVFSRC_DDR_REQUEST3 (DVFSRC_BASE + 0xA08)
+#define DVFSRC_DDR_REQUEST4 (DVFSRC_BASE + 0xA0C)
+#define DVFSRC_DDR_REQUEST5 (DVFSRC_BASE + 0xA10)
+#define DVFSRC_DDR_REQUEST6 (DVFSRC_BASE + 0xA14)
+#define DVFSRC_DDR_REQUEST7 (DVFSRC_BASE + 0xA18)
+#define DVFSRC_DDR_HRT (DVFSRC_BASE + 0xA1C)
+#define DVFSRC_DDR_HRT2 (DVFSRC_BASE + 0xA20)
+#define DVFSRC_DDR_HRT3 (DVFSRC_BASE + 0xA24)
+#define DVFSRC_DDR_HRT_1 (DVFSRC_BASE + 0xA28)
+#define DVFSRC_DDR_HRT2_1 (DVFSRC_BASE + 0xA2C)
+#define DVFSRC_DDR_HRT3_1 (DVFSRC_BASE + 0xA30)
+#define DVFSRC_DDR_QOS0 (DVFSRC_BASE + 0xA34)
+#define DVFSRC_DDR_QOS1 (DVFSRC_BASE + 0xA38)
+#define DVFSRC_DDR_QOS2 (DVFSRC_BASE + 0xA3C)
+#define DVFSRC_DDR_QOS3 (DVFSRC_BASE + 0xA40)
+#define DVFSRC_DDR_QOS4 (DVFSRC_BASE + 0xA44)
+#define DVFSRC_DDR_MD2SPM0 (DVFSRC_BASE + 0xA48)
+#define DVFSRC_DDR_MD2SPM1 (DVFSRC_BASE + 0xA4C)
+#define DVFSRC_DDR_MD2SPM2 (DVFSRC_BASE + 0xA50)
+#define DVFSRC_DDR_MD2SPM0_T (DVFSRC_BASE + 0xA54)
+#define DVFSRC_DDR_MD2SPM1_T (DVFSRC_BASE + 0xA58)
+#define DVFSRC_DDR_MD2SPM2_T (DVFSRC_BASE + 0xA5C)
+#define DVFSRC_HRT_REQ_UNIT (DVFSRC_BASE + 0xA60)
+#define DVSFRC_HRT_REQ_MD_URG (DVFSRC_BASE + 0xA64)
+#define DVFSRC_HRT_REQ_MD_BW_0 (DVFSRC_BASE + 0xA68)
+#define DVFSRC_HRT_REQ_MD_BW_1 (DVFSRC_BASE + 0xA6C)
+#define DVFSRC_HRT_REQ_MD_BW_2 (DVFSRC_BASE + 0xA70)
+#define DVFSRC_HRT_REQ_MD_BW_3 (DVFSRC_BASE + 0xA74)
+#define DVFSRC_HRT_REQ_MD_BW_4 (DVFSRC_BASE + 0xA78)
+#define DVFSRC_HRT_REQ_MD_BW_5 (DVFSRC_BASE + 0xA7C)
+#define DVFSRC_HRT_REQ_MD_BW_6 (DVFSRC_BASE + 0xA80)
+#define DVFSRC_HRT_REQ_MD_BW_7 (DVFSRC_BASE + 0xA84)
+#define DVFSRC_HRT1_REQ_MD_BW_0 (DVFSRC_BASE + 0xA88)
+#define DVFSRC_HRT1_REQ_MD_BW_1 (DVFSRC_BASE + 0xA8C)
+#define DVFSRC_HRT1_REQ_MD_BW_2 (DVFSRC_BASE + 0xA90)
+#define DVFSRC_HRT1_REQ_MD_BW_3 (DVFSRC_BASE + 0xA94)
+#define DVFSRC_HRT1_REQ_MD_BW_4 (DVFSRC_BASE + 0xA98)
+#define DVFSRC_HRT1_REQ_MD_BW_5 (DVFSRC_BASE + 0xA9C)
+#define DVFSRC_HRT1_REQ_MD_BW_6 (DVFSRC_BASE + 0xAA0)
+#define DVFSRC_HRT1_REQ_MD_BW_7 (DVFSRC_BASE + 0xAA4)
+#define DVFSRC_HRT_REQ_MD_BW_8 (DVFSRC_BASE + 0xAA8)
+#define DVFSRC_HRT_REQ_MD_BW_9 (DVFSRC_BASE + 0xAAC)
+#define DVFSRC_HRT_REQ_MD_BW_10 (DVFSRC_BASE + 0xAB0)
+#define DVFSRC_HRT1_REQ_MD_BW_8 (DVFSRC_BASE + 0xAB4)
+#define DVFSRC_HRT1_REQ_MD_BW_9 (DVFSRC_BASE + 0xAB8)
+#define DVFSRC_HRT1_REQ_MD_BW_10 (DVFSRC_BASE + 0xABC)
+#define DVFSRC_HRT_REQ_BW_SW_REG (DVFSRC_BASE + 0xAC0)
+#define DVFSRC_HRT_REQUEST (DVFSRC_BASE + 0xAC4)
+#define DVFSRC_HRT_HIGH_2 (DVFSRC_BASE + 0xAC8)
+#define DVFSRC_HRT_HIGH_1 (DVFSRC_BASE + 0xACC)
+#define DVFSRC_HRT_HIGH (DVFSRC_BASE + 0xAD0)
+#define DVFSRC_HRT_LOW_2 (DVFSRC_BASE + 0xAD4)
+#define DVFSRC_HRT_LOW_1 (DVFSRC_BASE + 0xAD8)
+#define DVFSRC_HRT_LOW (DVFSRC_BASE + 0xADC)
+#define DVFSRC_DDR_ADD_REQUEST (DVFSRC_BASE + 0xAE0)
+#define DVFSRC_LAST (DVFSRC_BASE + 0xAE4)
+#define DVFSRC_LAST_L (DVFSRC_BASE + 0xAE8)
+#define DVFSRC_MD_SCENARIO (DVFSRC_BASE + 0xAEC)
+#define DVFSRC_RECORD_0_0 (DVFSRC_BASE + 0xAF0)
+#define DVFSRC_RECORD_0_1 (DVFSRC_BASE + 0xAF4)
+#define DVFSRC_RECORD_0_2 (DVFSRC_BASE + 0xAF8)
+#define DVFSRC_RECORD_0_3 (DVFSRC_BASE + 0xAFC)
+#define DVFSRC_RECORD_0_4 (DVFSRC_BASE + 0xB00)
+#define DVFSRC_RECORD_0_5 (DVFSRC_BASE + 0xB04)
+#define DVFSRC_RECORD_0_6 (DVFSRC_BASE + 0xB08)
+#define DVFSRC_RECORD_0_7 (DVFSRC_BASE + 0xB0C)
+#define DVFSRC_RECORD_0_L_0 (DVFSRC_BASE + 0xBF0)
+#define DVFSRC_RECORD_0_L_1 (DVFSRC_BASE + 0xBF4)
+#define DVFSRC_RECORD_0_L_2 (DVFSRC_BASE + 0xBF8)
+#define DVFSRC_RECORD_0_L_3 (DVFSRC_BASE + 0xBFC)
+#define DVFSRC_RECORD_0_L_4 (DVFSRC_BASE + 0xC00)
+#define DVFSRC_RECORD_0_L_5 (DVFSRC_BASE + 0xC04)
+#define DVFSRC_RECORD_0_L_6 (DVFSRC_BASE + 0xC08)
+#define DVFSRC_RECORD_0_L_7 (DVFSRC_BASE + 0xC0C)
+#define DVFSRC_EMI_REQUEST8 (DVFSRC_BASE + 0xCF0)
+#define DVFSRC_DDR_REQUEST8 (DVFSRC_BASE + 0xCF4)
+#define DVFSRC_EMI_HRT_2 (DVFSRC_BASE + 0xCF8)
+#define DVFSRC_EMI_HRT2_2 (DVFSRC_BASE + 0xCFC)
+#define DVFSRC_EMI_HRT3_2 (DVFSRC_BASE + 0xD00)
+#define DVFSRC_EMI_QOS5 (DVFSRC_BASE + 0xD04)
+#define DVFSRC_EMI_QOS6 (DVFSRC_BASE + 0xD08)
+#define DVFSRC_DDR_HRT_2 (DVFSRC_BASE + 0xD0C)
+#define DVFSRC_DDR_HRT2_2 (DVFSRC_BASE + 0xD10)
+#define DVFSRC_DDR_HRT3_2 (DVFSRC_BASE + 0xD14)
+#define DVFSRC_DDR_QOS5 (DVFSRC_BASE + 0xD18)
+#define DVFSRC_DDR_QOS6 (DVFSRC_BASE + 0xD1C)
+#define DVFSRC_VCORE_REQUEST5 (DVFSRC_BASE + 0xD20)
+#define DVFSRC_VCORE_HRT_1 (DVFSRC_BASE + 0xD24)
+#define DVFSRC_VCORE_HRT2_1 (DVFSRC_BASE + 0xD28)
+#define DVFSRC_VCORE_HRT3_1 (DVFSRC_BASE + 0xD2C)
+#define DVFSRC_VCORE_QOS3 (DVFSRC_BASE + 0xD30)
+#define DVFSRC_VCORE_QOS4 (DVFSRC_BASE + 0xD34)
+#define DVFSRC_HRT_HIGH_3 (DVFSRC_BASE + 0xD38)
+#define DVFSRC_HRT_LOW_3 (DVFSRC_BASE + 0xD3C)
+#define DVFSRC_BASIC_CONTROL_2 (DVFSRC_BASE + 0xD40)
+#define DVFSRC_CURRENT_LEVEL (DVFSRC_BASE + 0xD44)
+#define DVFSRC_TARGET_LEVEL (DVFSRC_BASE + 0xD48)
+#define DVFSRC_LEVEL_LABEL_16_17 (DVFSRC_BASE + 0xD4C)
+#define DVFSRC_LEVEL_LABEL_18_19 (DVFSRC_BASE + 0xD50)
+#define DVFSRC_LEVEL_LABEL_20_21 (DVFSRC_BASE + 0xD54)
+#define DVFSRC_LEVEL_LABEL_22_23 (DVFSRC_BASE + 0xD58)
+#define DVFSRC_LEVEL_LABEL_24_25 (DVFSRC_BASE + 0xD5C)
+#define DVFSRC_LEVEL_LABEL_26_27 (DVFSRC_BASE + 0xD60)
+#define DVFSRC_LEVEL_LABEL_28_29 (DVFSRC_BASE + 0xD64)
+#define DVFSRC_LEVEL_LABEL_30_31 (DVFSRC_BASE + 0xD68)
+#define DVFSRC_CURRENT_FORCE (DVFSRC_BASE + 0xD6C)
+#define DVFSRC_TARGET_FORCE (DVFSRC_BASE + 0xD70)
+#define DVFSRC_EMI_ADD_REQUEST (DVFSRC_BASE + 0xD74)
+
+#endif /* __MT_SPM_VCOREFS__H__ */
diff --git a/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h b/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h
new file mode 100644
index 0000000..ee3738d
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SSPM_NOTIFIER_H
+#define MT_SPM_SSPM_NOTIFIER_H
+
+enum MT_SPM_SSPM_NOTIFY_ID {
+ MT_SPM_NOTIFY_LP_ENTER,
+ MT_SPM_NOTIFY_LP_LEAVE,
+};
+
+int mt_spm_sspm_notify(int type, unsigned int lp_mode);
+
+static inline int mt_spm_sspm_notify_u32(int type, unsigned int lp_mode)
+{
+ return mt_spm_sspm_notify(type, lp_mode);
+}
+#endif /* MT_SPM_SSPM_NOTIFIER_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h b/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h
new file mode 100644
index 0000000..6847e77
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MT_SPM_SSPM_INTC_H
+#define MT_SPM_SSPM_INTC_H
+
+#include <mt_spm_reg.h>
+
+#define MT_SPM_SSPM_INTC_SEL_0 0x10
+#define MT_SPM_SSPM_INTC_SEL_1 0x20
+#define MT_SPM_SSPM_INTC_SEL_2 0x40
+#define MT_SPM_SSPM_INTC_SEL_3 0x80
+
+#define MT_SPM_SSPM_INTC_TRIGGER(id, sg) \
+ (((0x10 << id) | (sg << id)) & 0xff)
+
+#define MT_SPM_SSPM_INTC0_HIGH MT_SPM_SSPM_INTC_TRIGGER(0, 1)
+#define MT_SPM_SSPM_INTC0_LOW MT_SPM_SSPM_INTC_TRIGGER(0, 0)
+#define MT_SPM_SSPM_INTC1_HIGH MT_SPM_SSPM_INTC_TRIGGER(1, 1)
+#define MT_SPM_SSPM_INTC1_LOW MT_SPM_SSPM_INTC_TRIGGER(1, 0)
+#define MT_SPM_SSPM_INTC2_HIGH MT_SPM_SSPM_INTC_TRIGGER(2, 1)
+#define MT_SPM_SSPM_INTC2_LOW MT_SPM_SSPM_INTC_TRIGGER(2, 0)
+#define MT_SPM_SSPM_INTC3_HIGH MT_SPM_SSPM_INTC_TRIGGER(3, 1)
+#define MT_SPM_SSPM_INTC3_LOW MT_SPM_SSPM_INTC_TRIGGER(3, 0)
+
+#define DO_SPM_SSPM_LP_SUSPEND() \
+ mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_HIGH)
+#define DO_SPM_SSPM_LP_RESUME() \
+ mmio_write_32(SPM_MD32_IRQ, MT_SPM_SSPM_INTC0_LOW)
+#endif /* MT_SPM_SSPM_INTC_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c b/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c
new file mode 100644
index 0000000..a755a38
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <lib/mmio.h>
+
+#include <mt_spm_notifier.h>
+#include <mt_spm_sspm_intc.h>
+
+#define MT_SPM_SSPM_MBOX_OFF(x) (SSPM_MBOX_BASE + x)
+#define MT_SPM_MBOX(slot) MT_SPM_SSPM_MBOX_OFF((slot << 2UL))
+
+#define SSPM_MBOX_SPM_LP_LOOKUP1 MT_SPM_MBOX(0)
+#define SSPM_MBOX_SPM_LP_LOOKUP2 MT_SPM_MBOX(1)
+#define SSPM_MBOX_SPM_LP1 MT_SPM_MBOX(2)
+#define SSPM_MBOX_SPM_LP2 MT_SPM_MBOX(3)
+
+int mt_spm_sspm_notify(int type, unsigned int lp_mode)
+{
+ switch (type) {
+ case MT_SPM_NOTIFY_LP_ENTER:
+ mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode);
+ DO_SPM_SSPM_LP_SUSPEND();
+ break;
+ case MT_SPM_NOTIFY_LP_LEAVE:
+ mmio_write_32(SSPM_MBOX_SPM_LP1, lp_mode);
+ DO_SPM_SSPM_LP_RESUME();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/pcm_def.h b/plat/mediatek/mt8195/drivers/spm/pcm_def.h
new file mode 100644
index 0000000..fa77b95
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/pcm_def.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PCM_DEF_H
+#define PCM_DEF_H
+
+/*
+ * Auto generated by DE, please DO NOT modify this file directly.
+ */
+
+/* --- R0 Define --- */
+#define R0_SC_26M_CK_OFF (1U << 0)
+#define R0_SC_TX_TRACK_RETRY_EN (1U << 1)
+#define R0_SC_MEM_CK_OFF (1U << 2)
+#define R0_SC_AXI_CK_OFF (1U << 3)
+#define R0_SC_DR_SRAM_LOAD (1U << 4)
+#define R0_SC_MD26M_CK_OFF (1U << 5)
+#define R0_SC_DPY_MODE_SW (1U << 6)
+#define R0_SC_DMSUS_OFF (1U << 7)
+#define R0_SC_DPY_2ND_DLL_EN (1U << 8)
+#define R0_SC_DR_SRAM_RESTORE (1U << 9)
+#define R0_SC_MPLLOUT_OFF (1U << 10)
+#define R0_SC_TX_TRACKING_DIS (1U << 11)
+#define R0_SC_DPY_DLL_EN (1U << 12)
+#define R0_SC_DPY_DLL_CK_EN (1U << 13)
+#define R0_SC_DPY_VREF_EN (1U << 14)
+#define R0_SC_PHYPLL_EN (1U << 15)
+#define R0_SC_DDRPHY_FB_CK_EN (1U << 16)
+#define R0_SC_DPY_BCLK_ENABLE (1U << 17)
+#define R0_SC_MPLL_OFF (1U << 18)
+#define R0_SC_SHU_RESTORE (1U << 19)
+#define R0_SC_CKSQ0_OFF (1U << 20)
+#define R0_SC_DR_SHU_LEVEL_SRAM_LATCH (1U << 21)
+#define R0_SC_DR_SHU_EN (1U << 22)
+#define R0_SC_DPHY_PRECAL_UP (1U << 23)
+#define R0_SC_MPLL_S_OFF (1U << 24)
+#define R0_SC_DPHY_RXDLY_TRACKING_EN (1U << 25)
+#define R0_SC_PHYPLL_SHU_EN (1U << 26)
+#define R0_SC_PHYPLL2_SHU_EN (1U << 27)
+#define R0_SC_PHYPLL_MODE_SW (1U << 28)
+#define R0_SC_PHYPLL2_MODE_SW (1U << 29)
+#define R0_SC_DR_SHU_LEVEL0 (1U << 30)
+#define R0_SC_DR_SHU_LEVEL1 (1U << 31)
+/* --- R7 Define --- */
+#define R7_PWRAP_SLEEP_REQ (1U << 0)
+#define R7_EMI_CLK_OFF_REQ (1U << 1)
+#define R7_PCM_BUS_PROTECT_REQ (1U << 2)
+#define R7_SPM_CK_UPDATE (1U << 3)
+#define R7_SPM_CK_SEL0 (1U << 4)
+#define R7_SPM_CK_SEL1 (1U << 5)
+#define R7_SPM_LEAVE_DEEPIDLE_REQ (1U << 6)
+#define R7_SC_FHC_PAUSE_MPLL (1U << 7)
+#define R7_SC_26M_CK_SEL (1U << 8)
+#define R7_PCM_TIMER_SET (1U << 9)
+#define R7_PCM_TIMER_CLR (1U << 10)
+#define R7_SPM_LEAVE_SUSPEND_REQ (1U << 11)
+#define R7_CSYSPWRUPACK (1U << 12)
+#define R7_PCM_IM_SLP_EN (1U << 13)
+#define R7_SRCCLKENO0 (1U << 14)
+#define R7_FORCE_DDR_EN_WAKE (1U << 15)
+#define R7_SPM_APSRC_INTERNAL_ACK (1U << 16)
+#define R7_CPU_SYS_TIMER_CLK_SEL (1U << 17)
+#define R7_SC_AXI_DCM_DIS (1U << 18)
+#define R7_SC_FHC_PAUSE_MEM (1U << 19)
+#define R7_SC_FHC_PAUSE_MAIN (1U << 20)
+#define R7_SRCCLKENO1 (1U << 21)
+#define R7_PCM_WDT_KICK_P (1U << 22)
+#define R7_SPM2EMI_S1_MODE_ASYNC (1U << 23)
+#define R7_SC_DDR_PST_REQ_PCM (1U << 24)
+#define R7_SC_DDR_PST_ABORT_REQ_PCM (1U << 25)
+#define R7_PMIC_IRQ_REQ_EN (1U << 26)
+#define R7_FORCE_F26M_WAKE (1U << 27)
+#define R7_FORCE_APSRC_WAKE (1U << 28)
+#define R7_FORCE_INFRA_WAKE (1U << 29)
+#define R7_FORCE_VRF18_WAKE (1U << 30)
+#define R7_SPM_DDR_EN_INTERNAL_ACK (1U << 31)
+/* --- R12 Define --- */
+#define R12_PCM_TIMER (1U << 0)
+#define R12_TWAM_IRQ_B (1U << 1)
+#define R12_KP_IRQ_B (1U << 2)
+#define R12_APWDT_EVENT_B (1U << 3)
+#define R12_APXGPT1_EVENT_B (1U << 4)
+#define R12_CONN2AP_SPM_WAKEUP_B (1U << 5)
+#define R12_EINT_EVENT_B (1U << 6)
+#define R12_CONN_WDT_IRQ_B (1U << 7)
+#define R12_CCIF0_EVENT_B (1U << 8)
+#define R12_LOWBATTERY_IRQ_B (1U << 9)
+#define R12_SSPM2SPM_WAKEUP_B (1U << 10)
+#define R12_SCP2SPM_WAKEUP_B (1U << 11)
+#define R12_ADSP2SPM_WAKEUP_B (1U << 12)
+#define R12_PCM_WDT_WAKEUP_B (1U << 13)
+#define R12_USBX_CDSC_B (1U << 14)
+#define R12_USBX_POWERDWN_B (1U << 15)
+#define R12_SYS_TIMER_EVENT_B (1U << 16)
+#define R12_EINT_EVENT_SECURE_B (1U << 17)
+#define R12_CCIF1_EVENT_B (1U << 18)
+#define R12_UART0_IRQ_B (1U << 19)
+#define R12_AFE_IRQ_MCU_B (1U << 20)
+#define R12_THERM_CTRL_EVENT_B (1U << 21)
+#define R12_SYS_CIRQ_IRQ_B (1U << 22)
+#define R12_MD2AP_PEER_EVENT_B (1U << 23)
+#define R12_CSYSPWREQ_B (1U << 24)
+#define R12_MD1_WDT_B (1U << 25)
+#define R12_CLDMA_EVENT_B (1U << 26)
+#define R12_SEJ_EVENT_B (1U << 27)
+#define R12_REG_CPU_WAKEUP (1U << 28)
+#define R12_APUSYS_WAKE_HOST_B (1U << 29)
+#define R12_NOT_USED1 (1U << 30)
+#define R12_NOT_USED2 (1U << 31)
+/* --- R12ext Define --- */
+#define R12EXT_26M_WAKE (1U << 0)
+#define R12EXT_26M_SLEEP (1U << 1)
+#define R12EXT_INFRA_WAKE (1U << 2)
+#define R12EXT_INFRA_SLEEP (1U << 3)
+#define R12EXT_APSRC_WAKE (1U << 4)
+#define R12EXT_APSRC_SLEEP (1U << 5)
+#define R12EXT_VRF18_WAKE (1U << 6)
+#define R12EXT_VRF18_SLEEP (1U << 7)
+#define R12EXT_DVFS_WAKE (1U << 8)
+#define R12EXT_DDREN_WAKE (1U << 9)
+#define R12EXT_DDREN_SLEEP (1U << 10)
+#define R12EXT_MCU_PM_WFI (1U << 11)
+#define R12EXT_SSPM_IDLE (1U << 12)
+#define R12EXT_CONN_SRCCLKENB (1U << 13)
+#define R12EXT_DRAMC_SSPM_WFI_MERGE (1U << 14)
+#define R12EXT_SW_MAILBOX_WAKE (1U << 15)
+#define R12EXT_SSPM_MAILBOX_WAKE (1U << 16)
+#define R12EXT_ADSP_MAILBOX_WAKE (1U << 17)
+#define R12EXT_SCP_MAILBOX_WAKE (1U << 18)
+#define R12EXT_SPM_LEAVE_SUSPEND_ACK (1U << 19)
+#define R12EXT_SPM_LEAVE_DEEPIDLE_ACK (1U << 20)
+#define R12EXT_VS1_TRIGGER (1U << 21)
+#define R12EXT_VS2_TRIGGER (1U << 22)
+#define R12EXT_COROSS_REQ_APU (1U << 23)
+#define R12EXT_CROSS_REQ_L3 (1U << 24)
+#define R12EXT_DDR_PST_ACK (1U << 25)
+#define R12EXT_BIT26 (1U << 26)
+#define R12EXT_BIT27 (1U << 27)
+#define R12EXT_BIT28 (1U << 28)
+#define R12EXT_BIT29 (1U << 29)
+#define R12EXT_BIT30 (1U << 30)
+#define R12EXT_BIT31 (1U << 31)
+/* --- R13 Define --- */
+#define R13_SRCCLKENI0 (1U << 0)
+#define R13_SRCCLKENI1 (1U << 1)
+#define R13_MD_SRCCLKENA_0 (1U << 2)
+#define R13_MD_APSRC_REQ_0 (1U << 3)
+#define R13_CONN_DDR_EN (1U << 4)
+#define R13_MD_SRCCLKENA_1 (1U << 5)
+#define R13_SSPM_SRCCLKENA (1U << 6)
+#define R13_SSPM_APSRC_REQ (1U << 7)
+#define R13_MD1_STATE (1U << 8)
+#define R13_BIT9 (1U << 9)
+#define R13_MM_STATE (1U << 10)
+#define R13_SSPM_STATE (1U << 11)
+#define R13_MD_DDR_EN_0 (1U << 12)
+#define R13_CONN_STATE (1U << 13)
+#define R13_CONN_SRCCLKENA (1U << 14)
+#define R13_CONN_APSRC_REQ (1U << 15)
+#define R13_SC_DDR_PST_ACK_ALL (1U << 16)
+#define R13_SC_DDR_PST_ABORT_ACK_ALL (1U << 17)
+#define R13_SCP_STATE (1U << 18)
+#define R13_CSYSPWRUPREQ (1U << 19)
+#define R13_PWRAP_SLEEP_ACK (1U << 20)
+#define R13_SC_EMI_CLK_OFF_ACK_ALL (1U << 21)
+#define R13_AUDIO_DSP_STATE (1U << 22)
+#define R13_SC_DMDRAMCSHU_ACK_ALL (1U << 23)
+#define R13_CONN_SRCCLKENB (1U << 24)
+#define R13_SC_DR_SRAM_LOAD_ACK_ALL (1U << 25)
+#define R13_SUBSYS_IDLE_SIGNALS0 (1U << 26)
+#define R13_DVFS_STATE (1U << 27)
+#define R13_SC_DR_SRAM_PLL_LOAD_ACK_ALL (1U << 28)
+#define R13_SC_DR_SRAM_RESTORE_ACK_ALL (1U << 29)
+#define R13_MD_VRF18_REQ_0 (1U << 30)
+#define R13_DDR_EN_STATE (1U << 31)
+#endif /* PCM_DEF_H */
diff --git a/plat/mediatek/mt8195/drivers/spm/sleep_def.h b/plat/mediatek/mt8195/drivers/spm/sleep_def.h
new file mode 100644
index 0000000..2639b7e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/sleep_def.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SLEEP_DEF_H
+#define SLEEP_DEF_H
+
+/*
+ * Auto generated by DE, please DO NOT modify this file directly.
+ */
+
+/* --- SPM Flag Define --- */
+#define SPM_FLAG_DISABLE_CPU_PDN (1U << 0)
+#define SPM_FLAG_DISABLE_INFRA_PDN (1U << 1)
+#define SPM_FLAG_DISABLE_DDRPHY_PDN (1U << 2)
+#define SPM_FLAG_DISABLE_VCORE_DVS (1U << 3)
+#define SPM_FLAG_DISABLE_VCORE_DFS (1U << 4)
+#define SPM_FLAG_DISABLE_COMMON_SCENARIO (1U << 5)
+#define SPM_FLAG_DISABLE_BUS_CLK_OFF (1U << 6)
+#define SPM_FLAG_DISABLE_ARMPLL_OFF (1U << 7)
+#define SPM_FLAG_KEEP_CSYSPWRACK_HIGH (1U << 8)
+#define SPM_FLAG_ENABLE_LVTS_WORKAROUND (1U << 9)
+#define SPM_FLAG_RUN_COMMON_SCENARIO (1U << 10)
+#define SPM_FLAG_RESERVED_BIT11 (1U << 11)
+#define SPM_FLAG_ENABLE_SPM_DBG_WDT_DUMP (1U << 12)
+#define SPM_FLAG_USE_SRCCLKENO2 (1U << 13)
+#define SPM_FLAG_ENABLE_6315_CTRL (1U << 14)
+#define SPM_FLAG_ENABLE_TIA_WORKAROUND (1U << 15)
+#define SPM_FLAG_DISABLE_SYSRAM_SLEEP (1U << 16)
+#define SPM_FLAG_DISABLE_SSPM_SRAM_SLEEP (1U << 17)
+#define SPM_FLAG_DISABLE_MCUPM_SRAM_SLEEP (1U << 18)
+#define SPM_FLAG_DISABLE_DRAMC_ISSUE_CMD (1U << 19)
+#define SPM_FLAG_ENABLE_VOLTAGE_BIN (1U << 20)
+#define SPM_FLAG_RESERVED_BIT21 (1U << 21)
+#define SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP (1U << 22)
+#define SPM_FLAG_DISABLE_DRAMC_MD32_BACKUP (1U << 23)
+#define SPM_FLAG_RESERVED_BIT24 (1U << 24)
+#define SPM_FLAG_RESERVED_BIT25 (1U << 25)
+#define SPM_FLAG_RESERVED_BIT26 (1U << 26)
+#define SPM_FLAG_VTCXO_STATE (1U << 27)
+#define SPM_FLAG_INFRA_STATE (1U << 28)
+#define SPM_FLAG_APSRC_STATE (1U << 29)
+#define SPM_FLAG_VRF18_STATE (1U << 30)
+#define SPM_FLAG_DDREN_STATE (1U << 31)
+/* --- SPM Flag1 Define --- */
+#define SPM_FLAG1_DISABLE_AXI_BUS_TO_26M (1U << 0)
+#define SPM_FLAG1_DISABLE_SYSPLL_OFF (1U << 1)
+#define SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH (1U << 2)
+#define SPM_FLAG1_DISABLE_ULPOSC_OFF (1U << 3)
+#define SPM_FLAG1_FW_SET_ULPOSC_ON (1U << 4)
+#define SPM_FLAG1_RESERVED_BIT5 (1U << 5)
+#define SPM_FLAG1_ENABLE_REKICK (1U << 6)
+#define SPM_FLAG1_RESERVED_BIT7 (1U << 7)
+#define SPM_FLAG1_RESERVED_BIT8 (1U << 8)
+#define SPM_FLAG1_RESERVED_BIT9 (1U << 9)
+#define SPM_FLAG1_DISABLE_SRCLKEN_LOW (1U << 10)
+#define SPM_FLAG1_DISABLE_SCP_CLK_SWITCH (1U << 11)
+#define SPM_FLAG1_RESERVED_BIT12 (1U << 12)
+#define SPM_FLAG1_RESERVED_BIT13 (1U << 13)
+#define SPM_FLAG1_RESERVED_BIT14 (1U << 14)
+#define SPM_FLAG1_RESERVED_BIT15 (1U << 15)
+#define SPM_FLAG1_RESERVED_BIT16 (1U << 16)
+#define SPM_FLAG1_RESERVED_BIT17 (1U << 17)
+#define SPM_FLAG1_RESERVED_BIT18 (1U << 18)
+#define SPM_FLAG1_RESERVED_BIT19 (1U << 19)
+#define SPM_FLAG1_DISABLE_DEVAPC_SRAM_SLEEP (1U << 20)
+#define SPM_FLAG1_RESERVED_BIT21 (1U << 21)
+#define SPM_FLAG1_ENABLE_VS1_VOTER (1U << 22)
+#define SPM_FLAG1_ENABLE_VS2_VOTER (1U << 23)
+#define SPM_FLAG1_DISABLE_SCP_VREQ_MASK_CONTROL (1U << 24)
+#define SPM_FLAG1_RESERVED_BIT25 (1U << 25)
+#define SPM_FLAG1_RESERVED_BIT26 (1U << 26)
+#define SPM_FLAG1_RESERVED_BIT27 (1U << 27)
+#define SPM_FLAG1_RESERVED_BIT28 (1U << 28)
+#define SPM_FLAG1_RESERVED_BIT29 (1U << 29)
+#define SPM_FLAG1_RESERVED_BIT30 (1U << 30)
+#define SPM_FLAG1_RESERVED_BIT31 (1U << 31)
+/* --- SPM DEBUG Define --- */
+#define SPM_DBG_DEBUG_IDX_26M_WAKE (1U << 0)
+#define SPM_DBG_DEBUG_IDX_26M_SLEEP (1U << 1)
+#define SPM_DBG_DEBUG_IDX_INFRA_WAKE (1U << 2)
+#define SPM_DBG_DEBUG_IDX_INFRA_SLEEP (1U << 3)
+#define SPM_DBG_DEBUG_IDX_APSRC_WAKE (1U << 4)
+#define SPM_DBG_DEBUG_IDX_APSRC_SLEEP (1U << 5)
+#define SPM_DBG_DEBUG_IDX_VRF18_WAKE (1U << 6)
+#define SPM_DBG_DEBUG_IDX_VRF18_SLEEP (1U << 7)
+#define SPM_DBG_DEBUG_IDX_DDREN_WAKE (1U << 8)
+#define SPM_DBG_DEBUG_IDX_DDREN_SLEEP (1U << 9)
+#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_APSRC (1U << 10)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_STATE (1U << 11)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_STATE (1U << 12)
+#define SPM_DBG_DEBUG_IDX_DRAM_SREF_ABORT_IN_DDREN (1U << 13)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_STATE (1U << 14)
+#define SPM_DBG_DEBUG_IDX_SYSRAM_SLP (1U << 15)
+#define SPM_DBG_DEBUG_IDX_SYSRAM_ON (1U << 16)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_SLP (1U << 17)
+#define SPM_DBG_DEBUG_IDX_MCUPM_SRAM_ON (1U << 18)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_SLP (1U << 19)
+#define SPM_DBG_DEBUG_IDX_SSPM_SRAM_ON (1U << 20)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_SLP (1U << 21)
+#define SPM_DBG_DEBUG_IDX_DRAMC_MCU_SRAM_ON (1U << 22)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P575V (1U << 23)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P600V (1U << 24)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P650V (1U << 25)
+#define SPM_DBG_DEBUG_IDX_SCP_VCORE_0P725V (1U << 26)
+#define SPM_DBG_DEBUG_IDX_SPM_GO_WAKEUP_NOW (1U << 27)
+#define SPM_DBG_DEBUG_IDX_VTCXO_STATE (1U << 28)
+#define SPM_DBG_DEBUG_IDX_INFRA_STATE (1U << 29)
+#define SPM_DBG_DEBUG_IDX_VRR18_STATE (1U << 30)
+#define SPM_DBG_DEBUG_IDX_APSRC_STATE (1U << 31)
+/* --- SPM DEBUG1 Define --- */
+#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_LP (1U << 0)
+#define SPM_DBG1_DEBUG_IDX_VCORE_DVFS_START (1U << 1)
+#define SPM_DBG1_DEBUG_IDX_SYSPLL_OFF (1U << 2)
+#define SPM_DBG1_DEBUG_IDX_SYSPLL_ON (1U << 3)
+#define SPM_DBG1_DEBUG_IDX_CURRENT_IS_VCORE_DVFS (1U << 4)
+#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_OFF (1U << 5)
+#define SPM_DBG1_DEBUG_IDX_INFRA_MTCMOS_ON (1U << 6)
+#define SPM_DBG1_DEBUG_IDX_VRCXO_SLEEP_ABORT (1U << 7)
+#define SPM_DBG1_RESERVED_BIT8 (1U << 8)
+#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_OFF (1U << 9)
+#define SPM_DBG1_DEBUG_IDX_INFRA_SUB_MTCMOS_ON (1U << 10)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_ULPOSC (1U << 11)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_CLK_TO_26M (1U << 12)
+#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_32K (1U << 13)
+#define SPM_DBG1_DEBUG_IDX_SCP_CLK_TO_26M (1U << 14)
+#define SPM_DBG1_DEBUG_IDX_BUS_CLK_OFF (1U << 15)
+#define SPM_DBG1_DEBUG_IDX_BUS_CLK_ON (1U << 16)
+#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_LOW (1U << 17)
+#define SPM_DBG1_DEBUG_IDX_SRCLKEN2_HIGH (1U << 18)
+#define SPM_DBG1_RESERVED_BIT19 (1U << 19)
+#define SPM_DBG1_DEBUG_IDX_ULPOSC_IS_OFF_BUT_SHOULD_ON (1U << 20)
+#define SPM_DBG1_DEBUG_IDX_6315_LOW (1U << 21)
+#define SPM_DBG1_DEBUG_IDX_6315_HIGH (1U << 22)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_LOW_ABORT (1U << 23)
+#define SPM_DBG1_DEBUG_IDX_PWRAP_SLEEP_ACK_HIGH_ABORT (1U << 24)
+#define SPM_DBG1_DEBUG_IDX_EMI_SLP_IDLE_ABORT (1U << 25)
+#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_LOW_ABORT (1U << 26)
+#define SPM_DBG1_DEBUG_IDX_SCP_SLP_ACK_HIGH_ABORT (1U << 27)
+#define SPM_DBG1_DEBUG_IDX_SPM_DVFS_CMD_RDY_ABORT (1U << 28)
+#define SPM_DBG1_RESERVED_BIT29 (1U << 29)
+#define SPM_DBG1_RESERVED_BIT30 (1U << 30)
+#define SPM_DBG1_RESERVED_BIT31 (1U << 31)
+
+ /* Macro and Inline */
+#define is_cpu_pdn(flags) (((flags) & SPM_FLAG_DISABLE_CPU_PDN) == 0U)
+#define is_infra_pdn(flags) (((flags) & SPM_FLAG_DISABLE_INFRA_PDN) == 0U)
+#define is_ddrphy_pdn(flags) (((flags) & SPM_FLAG_DISABLE_DDRPHY_PDN) == 0U)
+#endif /* SLEEP_DEF_H */
diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc.c b/plat/mediatek/mt8195/drivers/spmc/mtspmc.c
new file mode 100644
index 0000000..9b332a0
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <mcucfg.h>
+#include <mtspmc.h>
+#include <mtspmc_private.h>
+
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
+{
+ mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
+}
+
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
+{
+ assert(cluster == 0U);
+
+ mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
+}
+
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
+{
+ assert(cluster == 0U);
+
+ return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
+}
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
+{
+ uint32_t reg;
+
+ assert(cluster == 0U);
+
+ reg = per_cluster(cluster, MCUCFG_INITARCH);
+
+ if (arm64) {
+ mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ } else {
+ mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
+ }
+}
+
+/**
+ * Return subsystem's power state.
+ *
+ * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state
+ * of one subsystem.
+ * RETURNS:
+ * 0 (the subsys was powered off)
+ * 1 (the subsys was powered on)
+ */
+bool spm_get_powerstate(uint32_t mask)
+{
+ return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U;
+}
+
+bool spm_get_cluster_powerstate(unsigned int cluster)
+{
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(BIT(14));
+}
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
+{
+ uint32_t mask = BIT(cpu);
+
+ assert(cluster == 0U);
+
+ return spm_get_powerstate(mask);
+}
+
+int spmc_init(void)
+{
+ INFO("SPM: enable CPC mode\n");
+
+ mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
+
+ mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
+ mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
+
+ mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
+ mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
+
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
+ mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN);
+
+ return 0;
+}
+
+/**
+ * Power on a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered on
+ * @cpu: the CPU ID of the CPU which to be powered on
+ */
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
+{
+ uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR);
+
+ /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */
+ if (cpu >= 4U) {
+ mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U);
+ }
+
+ mmio_setbits_32(cpu_pwr_con, PWR_ON);
+
+ while (!spm_get_cpu_powerstate(cluster, cpu)) {
+ mmio_clrbits_32(cpu_pwr_con, PWR_ON);
+ mmio_setbits_32(cpu_pwr_con, PWR_ON);
+ }
+}
+
+/**
+ * Power off a core with specified cluster and core index
+ *
+ * @cluster: the cluster ID of the CPU which to be powered off
+ * @cpu: the CPU ID of the CPU which to be powered off
+ */
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
+{
+ /* Set mp0_spmc_pwr_on_cpuX = 0 */
+ mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
+}
+
+/**
+ * Power off a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered off
+ */
+void spm_poweroff_cluster(unsigned int cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
+
+/**
+ * Power on a cluster with specified index
+ *
+ * @cluster: the cluster index which to be powered on
+ */
+void spm_poweron_cluster(unsigned int cluster)
+{
+ /* No need to power on/off cluster on single cluster platform */
+ assert(false);
+}
diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc.h b/plat/mediatek/mt8195/drivers/spmc/mtspmc.h
new file mode 100644
index 0000000..34e93d0
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_H
+#define MTSPMC_H
+
+#include <stdint.h>
+
+int spmc_init(void);
+
+void spm_poweron_cpu(unsigned int cluster, unsigned int cpu);
+void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu);
+
+void spm_poweroff_cluster(unsigned int cluster);
+void spm_poweron_cluster(unsigned int cluster);
+
+bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu);
+bool spm_get_cluster_powerstate(unsigned int cluster);
+bool spm_get_powerstate(uint32_t mask);
+
+void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64);
+void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr);
+uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu);
+
+void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu);
+
+#endif /* MTSPMC_H */
diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h
new file mode 100644
index 0000000..bf4092e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTSPMC_PRIVATE_H
+#define MTSPMC_PRIVATE_H
+
+#include <lib/utils_def.h>
+#include <platform_def.h>
+
+unsigned long read_cpuectlr(void);
+void write_cpuectlr(unsigned long cpuectlr);
+
+unsigned long read_cpupwrctlr_el1(void);
+void write_cpupwrctlr_el1(unsigned long cpuectlr);
+
+/*
+ * per_cpu/cluster helper
+ */
+struct per_cpu_reg {
+ unsigned int cluster_addr;
+ unsigned int cpu_stride;
+};
+
+#define per_cpu(cluster, cpu, reg) \
+ (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride))
+
+#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
+
+#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs))
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs))
+
+/* === SPMC related registers */
+#define SPM_POWERON_CONFIG_EN SPM_REG(0x000)
+/* bit-fields of SPM_POWERON_CONFIG_EN */
+#define PROJECT_CODE (U(0xb16) << 16)
+#define BCLK_CG_EN BIT(0)
+
+#define SPM_PWR_STATUS SPM_REG(0x16c)
+#define SPM_PWR_STATUS_2ND SPM_REG(0x170)
+#define SPM_CPU_PWR_STATUS SPM_REG(0x174)
+
+/* bit-fields of SPM_PWR_STATUS */
+#define MD BIT(0)
+#define CONN BIT(1)
+#define DDRPHY BIT(2)
+#define DISP BIT(3)
+#define MFG BIT(4)
+#define ISP BIT(5)
+#define INFRA BIT(6)
+#define VDEC BIT(7)
+#define MP0_CPUTOP BIT(8)
+#define MP0_CPU0 BIT(9)
+#define MP0_CPU1 BIT(10)
+#define MP0_CPU2 BIT(11)
+#define MP0_CPU3 BIT(12)
+#define MCUSYS BIT(14)
+#define MP0_CPU4 BIT(15)
+#define MP0_CPU5 BIT(16)
+#define MP0_CPU6 BIT(17)
+#define MP0_CPU7 BIT(18)
+#define VEN BIT(21)
+
+/* === SPMC related registers */
+#define SPM_MCUSYS_PWR_CON MCUCFG_REG(0xd200)
+#define SPM_MP0_CPUTOP_PWR_CON MCUCFG_REG(0xd204)
+#define SPM_MP0_CPU0_PWR_CON MCUCFG_REG(0xd208)
+#define SPM_MP0_CPU1_PWR_CON MCUCFG_REG(0xd20c)
+#define SPM_MP0_CPU2_PWR_CON MCUCFG_REG(0xd210)
+#define SPM_MP0_CPU3_PWR_CON MCUCFG_REG(0xd214)
+#define SPM_MP0_CPU4_PWR_CON MCUCFG_REG(0xd218)
+#define SPM_MP0_CPU5_PWR_CON MCUCFG_REG(0xd21c)
+#define SPM_MP0_CPU6_PWR_CON MCUCFG_REG(0xd220)
+#define SPM_MP0_CPU7_PWR_CON MCUCFG_REG(0xd224)
+
+/* bit fields of SPM_*_PWR_CON */
+#define PWR_ON_ACK BIT(31)
+#define VPROC_EXT_OFF BIT(7)
+#define DORMANT_EN BIT(6)
+#define RESETPWRON_CONFIG BIT(5)
+#define PWR_CLK_DIS BIT(4)
+#define PWR_ON BIT(2)
+#define PWR_RST_B BIT(0)
+
+/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */
+static const struct per_cpu_reg SPM_CPU_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
+};
+
+/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
+static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
+ { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
+};
+
+/* === MCUCFG related registers */
+/* aa64naa32 */
+#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4)
+/* reset vectors */
+#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900)
+#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908)
+#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910)
+#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918)
+#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920)
+#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928)
+#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930)
+#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938)
+
+/* MCUSYS DREQ BIG VPROC ISO control */
+#define DREQ20_BIG_VPROC_ISO MCUCFG_REG(0xad8c)
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */
+static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
+};
+
+/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
+static const struct per_cpu_reg MCUCFG_INITARCH[] = {
+ { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
+};
+
+#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
+/* === CPC control */
+#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
+
+/* bit fields of CPC_FLOW_CTRL_CFG */
+#define CPC_CTRL_ENABLE BIT(16)
+#define SSPM_CORE_PWR_ON_EN BIT(7) /* for cpu-hotplug */
+#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
+#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
+
+/* bit fields of CPC_SPMC_PWR_STATUS */
+#define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0)
+
+/* === APB Module infracfg_ao */
+#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
+#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224)
+#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228)
+#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0)
+#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4)
+#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250)
+#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254)
+#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258)
+#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8)
+#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac)
+
+/* bit fields of INFRA_TOPAXI_PROTECTEN */
+#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12)
+#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12))
+
+/* === SPARK */
+#define VOLTAGE_04 U(0x40)
+#define VOLTAGE_05 U(0x60)
+
+#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200)
+#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334)
+#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340)
+
+/* bit fields of CPU0_ILDO_CONTROL5 */
+#define ILDO_RET_VOSEL GENMASK(7, 0)
+
+/* bit fields of PTP3_CPU_SPMC_SW_CFG */
+#define SW_SPARK_EN BIT(0)
+
+/* bit fields of CPU0_ILDO_CONTROL8 */
+#define ILDO_BYPASS_B BIT(0)
+
+static const struct per_cpu_reg MCUCFG_SPARK[] = {
+ { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL5[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
+};
+
+static const struct per_cpu_reg ILDO_CONTROL8[] = {
+ { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
+};
+
+#endif /* MTSPMC_PRIVATE_H */
diff --git a/plat/mediatek/mt8195/include/mcucfg.h b/plat/mediatek/mt8195/include/mcucfg.h
new file mode 100644
index 0000000..046cf73
--- /dev/null
+++ b/plat/mediatek/mt8195/include/mcucfg.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCUCFG_H
+#define MCUCFG_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#endif /* __ASSEMBLER__ */
+
+#include <platform_def.h>
+
+#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
+
+#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
+#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
+
+#define MP2_CPUCFG MCUCFG_REG(0x2208)
+
+#define MP2_CPU0_STANDBYWFE BIT(4)
+#define MP2_CPU1_STANDBYWFE BIT(5)
+
+#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788)
+#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C)
+#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790)
+
+#define sw_spark_en BIT(0)
+#define sw_no_wait_for_q_channel BIT(1)
+#define sw_fsm_override BIT(2)
+#define sw_logic_pre1_pdb BIT(3)
+#define sw_logic_pre2_pdb BIT(4)
+#define sw_logic_pdb BIT(5)
+#define sw_iso BIT(6)
+#define sw_sram_sleepb (U(0x3F) << 7)
+#define sw_sram_isointb BIT(13)
+#define sw_clk_dis BIT(14)
+#define sw_ckiso BIT(15)
+#define sw_pd (U(0x3F) << 16)
+#define sw_hot_plug_reset BIT(22)
+#define sw_pwr_on_override_en BIT(23)
+#define sw_pwr_on BIT(24)
+#define sw_coq_dis BIT(25)
+#define logic_pdbo_all_off_ack BIT(26)
+#define logic_pdbo_all_on_ack BIT(27)
+#define logic_pre2_pdbo_all_on_ack BIT(28)
+#define logic_pre1_pdbo_all_on_ack BIT(29)
+
+
+#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
+ (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
+
+#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30)
+#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34)
+#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38)
+#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C)
+
+#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30)
+#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34)
+#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38)
+#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C)
+
+#define cpu_sw_spark_en BIT(0)
+#define cpu_sw_no_wait_for_q_channel BIT(1)
+#define cpu_sw_fsm_override BIT(2)
+#define cpu_sw_logic_pre1_pdb BIT(3)
+#define cpu_sw_logic_pre2_pdb BIT(4)
+#define cpu_sw_logic_pdb BIT(5)
+#define cpu_sw_iso BIT(6)
+#define cpu_sw_sram_sleepb BIT(7)
+#define cpu_sw_sram_isointb BIT(8)
+#define cpu_sw_clk_dis BIT(9)
+#define cpu_sw_ckiso BIT(10)
+#define cpu_sw_pd (U(0x1F) << 11)
+#define cpu_sw_hot_plug_reset BIT(16)
+#define cpu_sw_powr_on_override_en BIT(17)
+#define cpu_sw_pwr_on BIT(18)
+#define cpu_spark2ldo_allswoff BIT(19)
+#define cpu_pdbo_all_on_ack BIT(20)
+#define cpu_pre2_pdbo_allon_ack BIT(21)
+#define cpu_pre1_pdbo_allon_ack BIT(22)
+
+/* CPC related registers */
+#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714)
+#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804)
+#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
+#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818)
+#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c)
+#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824)
+#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8)
+#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac)
+#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04)
+#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c)
+#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10)
+#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14)
+#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20)
+#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70)
+#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74)
+
+#define SPARK2LDO MCUCFG_REG(0x2700)
+/* APB Module mcucfg */
+#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000)
+#define MP0_AXI_CONFIG MCUCFG_REG(0x02C)
+#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030)
+#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034)
+#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038)
+#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8))
+#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C)
+#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054)
+#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064)
+
+#define MP0_RW_RSVD0 MCUCFG_REG(0x06C)
+
+
+#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200)
+#define MP1_AXI_CONFIG MCUCFG_REG(0x22C)
+#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230)
+#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234)
+#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238)
+#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8))
+#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C)
+#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254)
+#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264)
+
+#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740)
+#define SYNC_DCM_CONFIG MCUCFG_REG(0x744)
+
+#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0)
+
+#define MP0_SPMC MCUCFG_REG(0x788)
+#define MP1_SPMC MCUCFG_REG(0x78C)
+#define MP2_AXI_CONFIG MCUCFG_REG(0x220C)
+#define MP2_AXI_CONFIG_ACINACTM BIT(0)
+#define MP2_AXI_CONFIG_AINACTS BIT(4)
+
+#define MPx_AXI_CONFIG_ACINACTM BIT(4)
+#define MPx_AXI_CONFIG_AINACTS BIT(5)
+
+#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
+
+#define MP0_CPU0_STANDBYWFE BIT(20)
+#define MP0_CPU1_STANDBYWFE BIT(21)
+#define MP0_CPU2_STANDBYWFE BIT(22)
+#define MP0_CPU3_STANDBYWFE BIT(23)
+
+#define MP1_CPU0_STANDBYWFE BIT(20)
+#define MP1_CPU1_STANDBYWFE BIT(21)
+#define MP1_CPU2_STANDBYWFE BIT(22)
+#define MP1_CPU3_STANDBYWFE BIT(23)
+
+#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00)
+#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04)
+#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08)
+#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00)
+#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04)
+#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08)
+
+#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008)
+#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0)
+#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4)
+
+#define MP2_COQ MCUCFG_REG(0x22BC)
+#define MP2_COQ_SW_DIS BIT(0)
+
+#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400)
+#define MP2_CA15M_MON_L MCUCFG_REG(0x2404)
+
+#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430)
+#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438)
+#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434)
+#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C)
+
+#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068)
+#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268)
+#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C)
+
+#define MP2_SW_RST_B BIT(0)
+#define MP2_TOPAON_APB_MASK BIT(1)
+
+#define B_SW_HOT_PLUG_RESET BIT(30)
+
+#define B_SW_PD_OFFSET 18U
+#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET)
+
+#define B_SW_SRAM_SLEEPB_OFFSET 12U
+#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
+
+#define B_SW_SRAM_ISOINTB BIT(9)
+#define B_SW_ISO BIT(8)
+#define B_SW_LOGIC_PDB BIT(7)
+#define B_SW_LOGIC_PRE2_PDB BIT(6)
+#define B_SW_LOGIC_PRE1_PDB BIT(5)
+#define B_SW_FSM_OVERRIDE BIT(4)
+#define B_SW_PWR_ON BIT(3)
+#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
+
+#define B_FSM_STATE_OUT_OFFSET (6U)
+#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET)
+#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
+#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
+#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
+#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
+
+#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
+#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
+
+#ifndef __ASSEMBLER__
+/* cpu boot mode */
+enum {
+ MP0_CPUCFG_64BIT_SHIFT = 12U,
+ MP1_CPUCFG_64BIT_SHIFT = 28U,
+ MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
+ MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
+};
+
+enum {
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
+
+ MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
+ MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
+ U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
+};
+
+enum {
+ MP1_AINACTS_SHIFT = 4U,
+ MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
+};
+
+enum {
+ MP1_SW_CG_GEN_SHIFT = 12U,
+ MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
+};
+
+enum {
+ MP1_L2RSTDISABLE_SHIFT = 14U,
+ MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
+};
+#endif /* __ASSEMBLER__ */
+
+#endif /* MCUCFG_H */
diff --git a/plat/mediatek/mt8195/include/plat_helpers.h b/plat/mediatek/mt8195/include/plat_helpers.h
new file mode 100644
index 0000000..ebc9fa0
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8195/include/plat_macros.S b/plat/mediatek/mt8195/include/plat_macros.S
new file mode 100644
index 0000000..39727ea
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_macros.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception
+ * is taken in BL31.
+ * Clobbers: x0 - x10, x26, x27, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /* TODO: leave implementation to GIC owner */
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8195/include/plat_mtk_lpm.h b/plat/mediatek/mt8195/include/plat_mtk_lpm.h
new file mode 100644
index 0000000..347f358
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_mtk_lpm.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MTK_LPM_H
+#define PLAT_MTK_LPM_H
+
+#include <lib/psci/psci.h>
+#include <lib/utils_def.h>
+
+#define MT_IRQ_REMAIN_MAX U(32)
+#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
+
+struct mt_irqremain {
+ unsigned int count;
+ unsigned int irqs[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
+ unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
+};
+
+#define PLAT_RC_STATUS_READY BIT(0)
+#define PLAT_RC_STATUS_FEATURE_EN BIT(1)
+#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31)
+
+struct mt_lpm_tz {
+ int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
+
+ int (*pwr_cluster_on)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_cluster_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+
+ int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
+ int (*pwr_mcusys_on_finished)(unsigned int cpu,
+ const psci_power_state_t *state);
+ int (*pwr_mcusys_dwn)(unsigned int cpu,
+ const psci_power_state_t *state);
+};
+
+const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
+
+#endif /* PLAT_MTK_LPM_H */
diff --git a/plat/mediatek/mt8195/include/plat_pm.h b/plat/mediatek/mt8195/include/plat_pm.h
new file mode 100644
index 0000000..a2881ce
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_pm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_H
+#define PLAT_PM_H
+
+#include <lib/utils_def.h>
+
+#define MT_PLAT_PWR_STATE_CPU U(1)
+#define MT_PLAT_PWR_STATE_CLUSTER U(2)
+#define MT_PLAT_PWR_STATE_MCUSYS U(3)
+#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8)
+#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9)
+
+#define MTK_LOCAL_STATE_RUN U(0)
+#define MTK_LOCAL_STATE_RET U(1)
+#define MTK_LOCAL_STATE_OFF U(2)
+
+#define MTK_AFFLVL_CPU U(0)
+#define MTK_AFFLVL_CLUSTER U(1)
+#define MTK_AFFLVL_MCUSYS U(2)
+#define MTK_AFFLVL_SYSTEM U(3)
+
+#define IS_CLUSTER_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
+#define IS_MCUSYS_OFF_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
+#define IS_SYSTEM_SUSPEND_STATE(s) \
+ is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
+
+#define IS_PLAT_SUSPEND_ID(stateid)\
+ ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \
+ || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
+
+#endif /* PLAT_PM_H */
diff --git a/plat/mediatek/mt8195/include/plat_private.h b/plat/mediatek/mt8195/include/plat_private.h
new file mode 100644
index 0000000..7ef2b85
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+ uintptr_t total_size,
+ uintptr_t ro_start,
+ uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8195/include/plat_sip_calls.h b/plat/mediatek/mt8195/include/plat_sip_calls.h
new file mode 100644
index 0000000..7d1f9fc
--- /dev/null
+++ b/plat/mediatek/mt8195/include/plat_sip_calls.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+/*******************************************************************************
+ * Plat SiP function constants
+ ******************************************************************************/
+#define MTK_PLAT_SIP_NUM_CALLS (8)
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8195/include/platform_def.h b/plat/mediatek/mt8195/include/platform_def.h
new file mode 100644
index 0000000..2a2f559
--- /dev/null
+++ b/plat/mediatek/mt8195/include/platform_def.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#define PLAT_PRIMARY_CPU 0x0
+
+#define MT_GIC_BASE (0x0C000000)
+#define MCUCFG_BASE (0x0C530000)
+#define IO_PHYS (0x10000000)
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE IO_PHYS
+#define MTK_DEV_RNG0_SIZE 0x10000000
+#define MTK_DEV_RNG2_BASE MT_GIC_BASE
+#define MTK_DEV_RNG2_SIZE 0x600000
+#define MTK_MCDI_SRAM_BASE 0x11B000
+#define MTK_MCDI_SRAM_MAP_SIZE 0x1000
+
+#define APUSYS_BASE 0x19000000
+#define APUSYS_SCTRL_REVISER_BASE 0x19021000
+#define APUSYS_SCTRL_REVISER_SIZE 0x1000
+#define APUSYS_APU_S_S_4_BASE 0x190F2000
+#define APUSYS_APU_S_S_4_SIZE 0x1000
+#define APUSYS_APU_PLL_BASE 0x190F3000
+#define APUSYS_APU_PLL_SIZE 0x1000
+#define APUSYS_APU_ACC_BASE 0x190F4000
+#define APUSYS_APU_ACC_SIZE 0x1000
+
+#define TOPCKGEN_BASE (IO_PHYS + 0x00000000)
+#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
+#define SPM_BASE (IO_PHYS + 0x00006000)
+#define RGU_BASE (IO_PHYS + 0x00007000)
+#define APMIXEDSYS (IO_PHYS + 0x0000C000)
+#define DRM_BASE (IO_PHYS + 0x0000D000)
+#define SSPM_MBOX_BASE (IO_PHYS + 0x00480000)
+#define PERICFG_AO_BASE (IO_PHYS + 0x01003000)
+#define VPPSYS0_BASE (IO_PHYS + 0x04000000)
+#define VPPSYS1_BASE (IO_PHYS + 0x04f00000)
+#define VDOSYS0_BASE (IO_PHYS + 0x0C01A000)
+#define VDOSYS1_BASE (IO_PHYS + 0x0C100000)
+#define DVFSRC_BASE (IO_PHYS + 0x00012000)
+
+/*******************************************************************************
+ * DP/eDP related constants
+ ******************************************************************************/
+#define EDP_SEC_BASE (IO_PHYS + 0x0C504000)
+#define DP_SEC_BASE (IO_PHYS + 0x0C604000)
+#define EDP_SEC_SIZE 0x1000
+#define DP_SEC_SIZE 0x1000
+
+/*******************************************************************************
+ * GPIO related constants
+ ******************************************************************************/
+#define GPIO_BASE (IO_PHYS + 0x00005000)
+#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000)
+#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000)
+#define IOCFG_BR_BASE (IO_PHYS + 0x01D40000)
+#define IOCFG_LM_BASE (IO_PHYS + 0x01E20000)
+#define IOCFG_RB_BASE (IO_PHYS + 0x01EB0000)
+#define IOCFG_TL_BASE (IO_PHYS + 0x01F40000)
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE (IO_PHYS + 0x01001100)
+#define UART1_BASE (IO_PHYS + 0x01001200)
+
+#define UART_BAUDRATE 115200
+
+/*******************************************************************************
+ * PMIC related constants
+ ******************************************************************************/
+#define PMIC_WRAP_BASE (IO_PHYS + 0x00024000)
+
+/*******************************************************************************
+ * EMI MPU related constants
+ ******************************************************************************/
+#define EMI_MPU_BASE (IO_PHYS + 0x00226000)
+#define SUB_EMI_MPU_BASE (IO_PHYS + 0x00225000)
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 13000000
+#define SYS_COUNTER_FREQ_IN_MHZ 13
+
+/*******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+/* Base MTK_platform compatible GIC memory map */
+#define BASE_GICD_BASE MT_GIC_BASE
+#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000)
+
+#define SYS_CIRQ_BASE (IO_PHYS + 0x204000)
+#define CIRQ_REG_NUM 23
+#define CIRQ_IRQ_NUM 730
+#define CIRQ_SPI_START 96
+#define MD_WDT_IRQ_BIT_ID 141
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE 0x800
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLAT_MAX_PWR_LVL U(3)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(9)
+
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_MCUSYS_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(8)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8)
+
+#define SOC_CHIP_ID U(0x8195)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE 0x54600000
+#define TZRAM_SIZE 0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL3-1 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 16
+#define MAX_MMAP_REGIONS 16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8195/include/rtc.h b/plat/mediatek/mt8195/include/rtc.h
new file mode 100644
index 0000000..a9c7bc8
--- /dev/null
+++ b/plat/mediatek/mt8195/include/rtc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#include <rtc_mt6359p.h>
+
+#endif /* RTC_H */
diff --git a/plat/mediatek/mt8195/plat_pm.c b/plat/mediatek/mt8195/plat_pm.c
new file mode 100644
index 0000000..bd8a3fa
--- /dev/null
+++ b/plat/mediatek/mt8195/plat_pm.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* common headers */
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/gpio.h>
+#include <lib/psci/psci.h>
+
+/* platform specific headers */
+#include <plat/common/platform.h>
+#include <mt_gic_v3.h>
+#include <mtspmc.h>
+#include <plat_dfd.h>
+#include <plat_mtk_lpm.h>
+#include <plat_params.h>
+#include <plat_pm.h>
+#include <pmic.h>
+#include <ptp3_common.h>
+#include <rtc.h>
+
+/*
+ * Cluster state request:
+ * [0] : The CPU requires cluster power down
+ * [1] : The CPU requires cluster power on
+ */
+#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
+#define coordinate_cluster_pwron() coordinate_cluster(1)
+#define coordinate_cluster_pwroff() coordinate_cluster(0)
+
+/* platform secure entry point */
+static uintptr_t secure_entrypoint;
+/* per-CPU power state */
+static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
+
+/* platform CPU power domain - ops */
+static const struct mt_lpm_tz *plat_mt_pm;
+
+#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \
+ int ret = -1; \
+ if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+ ret = plat_mt_pm->_name(_cpu, _state); \
+ } \
+ ret; })
+
+#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \
+ if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
+ (void) plat_mt_pm->_name(_cpu, _state); \
+ } \
+ })
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cpu_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state);
+
+ if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
+ (req_pstate == 0U)) { /* hotplug off */
+ coordinate_cluster_pwroff();
+ }
+
+ /* Prevent interrupts from spuriously waking up this CPU */
+ mt_gic_rdistif_save();
+ gicv3_cpuif_disable(cpu);
+ gicv3_rdistif_off(cpu);
+}
+
+static void plat_cpu_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state);
+
+ coordinate_cluster_pwron();
+
+ /* PTP3 config */
+ ptp3_core_init(cpu);
+
+ /*
+ * If mcusys does power down before then restore
+ * all CPUs' GIC Redistributors
+ */
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ mt_gic_rdistif_restore_all();
+ } else {
+ gicv3_rdistif_on(cpu);
+ gicv3_cpuif_enable(cpu);
+ mt_gic_rdistif_init();
+ mt_gic_rdistif_restore();
+ }
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_cluster_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) {
+ coordinate_cluster_pwron();
+
+ /* TODO: return on fail.
+ * Add a 'return' here before adding any code following
+ * the if-block.
+ */
+ }
+}
+
+static void plat_cluster_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) {
+ /* TODO: return on fail.
+ * Add a 'return' here before adding any code following
+ * the if-block.
+ */
+ }
+}
+
+/*
+ * Common MTK_platform operations to power on/off a
+ * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
+ */
+
+static void plat_mcusys_pwrdwn_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) {
+ return; /* return on fail */
+ }
+
+ mt_gic_distif_save();
+ gic_sgi_save_all();
+}
+
+static void plat_mcusys_pwron_common(unsigned int cpu,
+ const psci_power_state_t *state, unsigned int req_pstate)
+{
+ assert(cpu == plat_my_core_pos());
+
+ if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) {
+ return; /* return on fail */
+ }
+
+ mt_gic_init();
+ mt_gic_distif_restore();
+ gic_sgi_restore_all();
+
+ dfd_resume();
+
+ plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
+}
+
+/*
+ * plat_psci_ops implementation
+ */
+
+static void plat_cpu_standby(plat_local_state_t cpu_state)
+{
+ uint64_t scr;
+
+ scr = read_scr_el3();
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+
+ isb();
+ dsb();
+ wfi();
+
+ write_scr_el3(scr);
+}
+
+static int plat_power_domain_on(u_register_t mpidr)
+{
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+ unsigned int cluster = 0U;
+
+ if (cpu >= PLATFORM_CORE_COUNT) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (!spm_get_cluster_powerstate(cluster)) {
+ spm_poweron_cluster(cluster);
+ }
+
+ /* init CPU reset arch as AARCH64 */
+ mcucfg_init_archstate(cluster, cpu, true);
+ mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
+ spm_poweron_cpu(cluster, cpu);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_power_domain_on_finish(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ /* Allow IRQs to wakeup this core in IDLE flow */
+ mcucfg_enable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwron_common(cpu, state, 0U);
+ }
+
+ plat_cpu_pwron_common(cpu, state, 0U);
+}
+
+static void plat_power_domain_off(const psci_power_state_t *state)
+{
+ unsigned long mpidr = read_mpidr_el1();
+ unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ plat_cpu_pwrdwn_common(cpu, state, 0U);
+ spm_poweroff_cpu(0U, cpu);
+
+ /* prevent unintended IRQs from waking up the hot-unplugged core */
+ mcucfg_disable_gic_wakeup(0U, cpu);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ plat_cluster_pwrdwn_common(cpu, state, 0U);
+ }
+}
+
+static void plat_power_domain_suspend(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state);
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
+ }
+}
+
+static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
+{
+ unsigned int cpu = plat_my_core_pos();
+
+ assert(cpu < PLATFORM_CORE_COUNT);
+
+ if (IS_MCUSYS_OFF_STATE(state)) {
+ /* Perform the common mcusys specific operations */
+ plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ if (IS_CLUSTER_OFF_STATE(state)) {
+ /* Perform the common cluster specific operations */
+ plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
+ }
+
+ /* Perform the common CPU specific operations */
+ plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
+
+ plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state);
+}
+
+static int plat_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int cpu = plat_my_core_pos();
+
+ if (aff_lvl > PLAT_MAX_PWR_LVL) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
+ } else {
+ unsigned int i;
+ unsigned int pstate_id = psci_get_pstate_id(power_state);
+ plat_local_state_t s = MTK_LOCAL_STATE_OFF;
+
+ /* Use pstate_id to be power domain state */
+ if (pstate_id > s) {
+ s = (plat_local_state_t)pstate_id;
+ }
+
+ for (i = 0U; i <= aff_lvl; i++) {
+ req_state->pwr_domain_state[i] = s;
+ }
+ }
+
+ plat_power_state[cpu] = power_state;
+ return PSCI_E_SUCCESS;
+}
+
+static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int lv;
+ unsigned int cpu = plat_my_core_pos();
+
+ for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
+ req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
+ }
+
+ plat_power_state[cpu] =
+ psci_make_powerstate(
+ MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
+ PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
+
+ flush_dcache_range((uintptr_t)
+ &plat_power_state[cpu],
+ sizeof(plat_power_state[cpu]));
+}
+
+/*******************************************************************************
+ * MTK handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 plat_mtk_system_reset(void)
+{
+ struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
+
+ INFO("MTK System Reset\n");
+
+ gpio_set_value(gpio_reset->index, gpio_reset->polarity);
+
+ wfi();
+ ERROR("MTK System Reset: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 plat_mtk_system_off(void)
+{
+ INFO("MTK System Off\n");
+
+ rtc_power_off_sequence();
+ pmic_power_off();
+
+ wfi();
+ ERROR("MTK System Off: operation not handled.\n");
+ panic();
+}
+
+static const plat_psci_ops_t plat_psci_ops = {
+ .system_reset = plat_mtk_system_reset,
+ .system_off = plat_mtk_system_off,
+ .cpu_standby = plat_cpu_standby,
+ .pwr_domain_on = plat_power_domain_on,
+ .pwr_domain_on_finish = plat_power_domain_on_finish,
+ .pwr_domain_off = plat_power_domain_off,
+ .pwr_domain_suspend = plat_power_domain_suspend,
+ .pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
+ .validate_power_state = plat_validate_power_state,
+ .get_sys_suspend_power_state = plat_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_psci_ops;
+ secure_entrypoint = sec_entrypoint;
+
+ /*
+ * init the warm reset config for boot CPU
+ * reset arch as AARCH64
+ * reset addr as function bl31_warm_entrypoint()
+ */
+ mcucfg_init_archstate(0U, 0U, true);
+ mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
+
+ spmc_init();
+ plat_mt_pm = mt_plat_cpu_pm_init();
+
+ return 0;
+}
diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c
new file mode 100644
index 0000000..1cdd622
--- /dev/null
+++ b/plat/mediatek/mt8195/plat_sip_calls.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <mt_dp.h>
+#include <mt_spm.h>
+#include <mt_spm_vcorefs.h>
+#include <mtk_apusys.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+#include "plat_sip_calls.h"
+
+uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ int32_t ret;
+ uint32_t ret_val;
+
+ switch (smc_fid) {
+ case MTK_SIP_DP_CONTROL_AARCH32:
+ case MTK_SIP_DP_CONTROL_AARCH64:
+ ret = dp_secure_handler(x1, x2, &ret_val);
+ SMC_RET2(handle, ret, ret_val);
+ break;
+ case MTK_SIP_VCORE_CONTROL_AARCH32:
+ case MTK_SIP_VCORE_CONTROL_AARCH64:
+ ret = spm_vcorefs_v2_args(x1, x2, x3, &x4);
+ SMC_RET2(handle, ret, x4);
+ break;
+ case MTK_SIP_KERNEL_DFD_AARCH32:
+ case MTK_SIP_KERNEL_DFD_AARCH64:
+ ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+ SMC_RET1(handle, ret);
+ break;
+ case MTK_SIP_APUSYS_CONTROL_AARCH32:
+ case MTK_SIP_APUSYS_CONTROL_AARCH64:
+ ret = apusys_kernel_ctrl(x1, x2, x3, x4, &ret_val);
+ SMC_RET2(handle, ret, ret_val);
+ break;
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ break;
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/mediatek/mt8195/plat_topology.c b/plat/mediatek/mt8195/plat_topology.c
new file mode 100644
index 0000000..bc95c64
--- /dev/null
+++ b/plat/mediatek/mt8195/plat_topology.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* Number of children for the root node */
+ PLATFORM_MCUSYS_COUNT,
+ /* Number of children for the mcusys node */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ if ((read_mpidr() & MPIDR_MT_MASK) != 0) {
+ /* ARMv8.2 arch */
+ if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) {
+ return -1;
+ }
+ return plat_mediatek_calc_core_pos(mpidr);
+ }
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) {
+ return -1;
+ }
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk
new file mode 100644
index 0000000..07d39cb
--- /dev/null
+++ b/plat/mediatek/mt8195/platform.mk
@@ -0,0 +1,113 @@
+#
+# Copyright (c) 2021-2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT := plat/mediatek
+MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
+ -I${MTK_PLAT}/common/lpm/ \
+ -I${MTK_PLAT}/drivers/cirq/ \
+ -I${MTK_PLAT}/drivers/dp/ \
+ -I${MTK_PLAT}/drivers/gic600/ \
+ -I${MTK_PLAT}/drivers/gpio/ \
+ -I${MTK_PLAT}/drivers/pmic/ \
+ -I${MTK_PLAT}/drivers/pmic_wrap/ \
+ -I${MTK_PLAT}/drivers/ptp3/ \
+ -I${MTK_PLAT}/drivers/rtc/ \
+ -I${MTK_PLAT}/drivers/timer/ \
+ -I${MTK_PLAT}/drivers/uart/ \
+ -I${MTK_PLAT}/include/ \
+ -I${MTK_PLAT_SOC}/drivers/apusys/ \
+ -I${MTK_PLAT_SOC}/drivers/dcm \
+ -I${MTK_PLAT_SOC}/drivers/dfd \
+ -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \
+ -I${MTK_PLAT_SOC}/drivers/gpio/ \
+ -I${MTK_PLAT_SOC}/drivers/mcdi/ \
+ -I${MTK_PLAT_SOC}/drivers/pmic/ \
+ -I${MTK_PLAT_SOC}/drivers/spmc/ \
+ -I${MTK_PLAT_SOC}/drivers/ptp3/ \
+ -I${MTK_PLAT_SOC}/include/
+
+GICV3_SUPPORT_GIC600 := 1
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \
+ ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+
+BL31_SOURCES += common/desc_image_load.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/gpio/gpio.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/cpus/aarch64/cortex_a55.S \
+ lib/cpus/aarch64/cortex_a78.S \
+ plat/common/plat_gicv3.c \
+ ${MTK_PLAT}/common/mtk_plat_common.c \
+ ${MTK_PLAT}/common/mtk_sip_svc.c \
+ ${MTK_PLAT}/common/params_setup.c \
+ ${MTK_PLAT}/common/lpm/mt_lp_rm.c \
+ ${MTK_PLAT}/drivers/cirq/mt_cirq.c \
+ ${MTK_PLAT}/drivers/dp/mt_dp.c \
+ ${MTK_PLAT}/drivers/gic600/mt_gic_v3.c \
+ ${MTK_PLAT}/drivers/gpio/mtgpio_common.c \
+ ${MTK_PLAT}/drivers/pmic/pmic.c \
+ ${MTK_PLAT}/drivers/pmic_wrap/pmic_wrap_init_v2.c \
+ ${MTK_PLAT}/drivers/ptp3/ptp3_common.c \
+ ${MTK_PLAT}/drivers/rtc/rtc_common.c \
+ ${MTK_PLAT}/drivers/rtc/rtc_mt6359p.c \
+ ${MTK_PLAT}/drivers/timer/mt_timer.c \
+ ${MTK_PLAT}/drivers/uart/uart.c \
+ ${MTK_PLAT_SOC}/aarch64/platform_common.c \
+ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
+ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
+ ${MTK_PLAT_SOC}/drivers/apusys/apupll.c \
+ ${MTK_PLAT_SOC}/drivers/apusys/apupwr_clkctl.c \
+ ${MTK_PLAT_SOC}/drivers/apusys/mtk_apusys.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
+ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
+ ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \
+ ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \
+ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \
+ ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c \
+ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
+ ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
+ ${MTK_PLAT_SOC}/plat_pm.c \
+ ${MTK_PLAT_SOC}/plat_sip_calls.c \
+ ${MTK_PLAT_SOC}/plat_topology.c
+
+# Build SPM drivers
+include ${MTK_PLAT_SOC}/drivers/spm/build.mk
+
+# Configs for A78 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+ERRATA_A55_1530923 := 1
+
+ERRATA_A78_1688305 := 1
+ERRATA_A78_1941498 := 1
+ERRATA_A78_1951500 := 1
+ERRATA_A78_1821534 := 1
+ERRATA_A78_2132060 := 1
+ERRATA_A78_2242635 := 1
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8195 := 1
+$(eval $(call add_define,MACH_MT8195))
+
+include lib/coreboot/coreboot.mk
diff --git a/plat/mediatek/topology/armv8_2/topology.c b/plat/mediatek/topology/armv8_2/topology.c
new file mode 100644
index 0000000..1627bbd
--- /dev/null
+++ b/plat/mediatek/topology/armv8_2/topology.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, Mediatek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <lib/psci/psci.h>
+#include <platform_def.h>
+
+#pragma weak plat_get_power_domain_tree_desc
+
+static const unsigned char mtk_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* Number of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return mtk_power_domain_tree_desc;
+}
diff --git a/plat/mediatek/topology/rules.mk b/plat/mediatek/topology/rules.mk
new file mode 100644
index 0000000..29f15bb
--- /dev/null
+++ b/plat/mediatek/topology/rules.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2022, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LOCAL_DIR := $(call GET_LOCAL_DIR)
+
+MODULE := topology
+LOCAL_SRCS-y := $(LOCAL_DIR)/$(ARCH_VERSION)/topology.c
+
+$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
new file mode 100644
index 0000000..6c8c4f0
--- /dev/null
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <cortex_a57.h>
+#include <cpu_macros.S>
+
+#include <platform_def.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+
+#define MIDR_PN_CORTEX_A57 0xD07
+
+/*******************************************************************************
+ * Implementation defined ACTLR_EL3 bit definitions
+ ******************************************************************************/
+#define ACTLR_ELx_L2ACTLR_BIT (U(1) << 6)
+#define ACTLR_ELx_L2ECTLR_BIT (U(1) << 5)
+#define ACTLR_ELx_L2CTLR_BIT (U(1) << 4)
+#define ACTLR_ELx_CPUECTLR_BIT (U(1) << 1)
+#define ACTLR_ELx_CPUACTLR_BIT (U(1) << 0)
+#define ACTLR_ELx_ENABLE_ALL_ACCESS (ACTLR_ELx_L2ACTLR_BIT | \
+ ACTLR_ELx_L2ECTLR_BIT | \
+ ACTLR_ELx_L2CTLR_BIT | \
+ ACTLR_ELx_CPUECTLR_BIT | \
+ ACTLR_ELx_CPUACTLR_BIT)
+
+ /* Global functions */
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_get_my_entrypoint
+ .globl plat_secondary_cold_boot_setup
+ .globl platform_mem_init
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .weak plat_core_pos_by_mpidr
+ .globl tegra_secure_entrypoint
+ .globl plat_reset_handler
+
+ /* Global variables */
+ .globl tegra_sec_entry_point
+ .globl ns_image_entrypoint
+ .globl tegra_bl31_phys_base
+ .globl tegra_console_base
+
+ /* ---------------------
+ * Common CPU init code
+ * ---------------------
+ */
+.macro cpu_init_common
+
+ /* ------------------------------------------------
+ * We enable procesor retention, L2/CPUECTLR NS
+ * access and ECC/Parity protection for A57 CPUs
+ * ------------------------------------------------
+ */
+ mrs x0, midr_el1
+ mov x1, #(MIDR_PN_MASK << MIDR_PN_SHIFT)
+ and x0, x0, x1
+ lsr x0, x0, #MIDR_PN_SHIFT
+ cmp x0, #MIDR_PN_CORTEX_A57
+ b.ne 1f
+
+ /* ---------------------------
+ * Enable processor retention
+ * ---------------------------
+ */
+ mrs x0, CORTEX_A57_L2ECTLR_EL1
+ mov x1, #RETENTION_ENTRY_TICKS_512
+ bic x0, x0, #CORTEX_A57_L2ECTLR_RET_CTRL_MASK
+ orr x0, x0, x1
+ msr CORTEX_A57_L2ECTLR_EL1, x0
+ isb
+
+ mrs x0, CORTEX_A57_ECTLR_EL1
+ mov x1, #RETENTION_ENTRY_TICKS_512
+ bic x0, x0, #CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK
+ orr x0, x0, x1
+ msr CORTEX_A57_ECTLR_EL1, x0
+ isb
+
+ /* -------------------------------------------------------
+ * Enable L2 and CPU ECTLR RW access from non-secure world
+ * -------------------------------------------------------
+ */
+ mrs x0, actlr_el3
+ mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
+ orr x0, x0, x1
+ msr actlr_el3, x0
+ mrs x0, actlr_el2
+ mov x1, #ACTLR_ELx_ENABLE_ALL_ACCESS
+ orr x0, x0, x1
+ msr actlr_el2, x0
+ isb
+
+ /* --------------------------------
+ * Enable the cycle count register
+ * --------------------------------
+ */
+1: mrs x0, pmcr_el0
+ ubfx x0, x0, #11, #5 // read PMCR.N field
+ mov x1, #1
+ lsl x0, x1, x0
+ sub x0, x0, #1 // mask of event counters
+ orr x0, x0, #0x80000000 // disable overflow intrs
+ msr pmintenclr_el1, x0
+ msr pmuserenr_el0, x1 // enable user mode access
+
+ /* ----------------------------------------------------------------
+ * Allow non-privileged access to CNTVCT: Set CNTKCTL (Kernel Count
+ * register), bit 1 (EL0VCTEN) to enable access to CNTVCT/CNTFRQ
+ * registers from EL0.
+ * ----------------------------------------------------------------
+ */
+ mrs x0, cntkctl_el1
+ orr x0, x0, #EL0VCTEN_BIT
+ msr cntkctl_el1, x0
+.endm
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary(void);
+ *
+ * This function checks if this is the Primary CPU
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #TEGRA_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* ----------------------------------------------------------
+ * unsigned int plat_my_core_pos(void);
+ *
+ * result: CorePos = CoreId + (ClusterId * cpus per cluster)
+ * Registers clobbered: x0, x8
+ * ----------------------------------------------------------
+ */
+func plat_my_core_pos
+ mov x8, x30
+ mrs x0, mpidr_el1
+ bl plat_core_pos_by_mpidr
+ ret x8
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between
+ * a cold and warm boot. If the tegra_sec_entry_point for
+ * this CPU is present, then it's a warm boot.
+ *
+ * -----------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ adr x1, tegra_sec_entry_point
+ ldr x0, [x1]
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset. Right
+ * now this is a stub function.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ mov x0, #0
+ ret
+endfunc plat_secondary_cold_boot_setup
+
+ /* --------------------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * Any memory init, relocation to be done before the
+ * platform boots. Called very early in the boot process.
+ * --------------------------------------------------------
+ */
+func platform_mem_init
+ mov x0, #0
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------------
+ * Function to handle a platform reset and store
+ * input parameters passed by BL2.
+ * ---------------------------------------------------
+ */
+func plat_reset_handler
+
+ /* ----------------------------------------------------
+ * Verify if we are running from BL31_BASE address
+ * ----------------------------------------------------
+ */
+ adr x18, bl31_entrypoint
+ mov x17, #BL31_BASE
+ cmp x18, x17
+ b.eq 1f
+
+ /* ----------------------------------------------------
+ * Copy the entire BL31 code to BL31_BASE if we are not
+ * running from it already
+ * ----------------------------------------------------
+ */
+ mov x0, x17
+ mov x1, x18
+ adr x2, __RELA_END__
+ sub x2, x2, x18
+_loop16:
+ cmp x2, #16
+ b.lo _loop1
+ ldp x3, x4, [x1], #16
+ stp x3, x4, [x0], #16
+ sub x2, x2, #16
+ b _loop16
+ /* copy byte per byte */
+_loop1:
+ cbz x2, _end
+ ldrb w3, [x1], #1
+ strb w3, [x0], #1
+ subs x2, x2, #1
+ b.ne _loop1
+
+ /* ----------------------------------------------------
+ * Jump to BL31_BASE and start execution again
+ * ----------------------------------------------------
+ */
+_end: mov x0, x20
+ mov x1, x21
+ br x17
+1:
+
+ /* -----------------------------------
+ * derive and save the phys_base addr
+ * -----------------------------------
+ */
+ adr x17, tegra_bl31_phys_base
+ ldr x18, [x17]
+ cbnz x18, 1f
+ adr x18, bl31_entrypoint
+ str x18, [x17]
+
+1: cpu_init_common
+
+ ret
+endfunc plat_reset_handler
+
+ /* ------------------------------------------------------
+ * int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
+ *
+ * This function implements a part of the critical
+ * interface between the psci generic layer and the
+ * platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error
+ * code (-1) is returned in case the MPIDR is invalid.
+ *
+ * Clobbers: x0-x3
+ * ------------------------------------------------------
+ */
+func plat_core_pos_by_mpidr
+ lsr x1, x0, #MPIDR_AFF0_SHIFT
+ and x1, x1, #MPIDR_AFFLVL_MASK /* core id */
+ lsr x2, x0, #MPIDR_AFF1_SHIFT
+ and x2, x2, #MPIDR_AFFLVL_MASK /* cluster id */
+
+ /* core_id >= PLATFORM_MAX_CPUS_PER_CLUSTER */
+ mov x0, #-1
+ cmp x1, #(PLATFORM_MAX_CPUS_PER_CLUSTER - 1)
+ b.gt 1f
+
+ /* cluster_id >= PLATFORM_CLUSTER_COUNT */
+ cmp x2, #(PLATFORM_CLUSTER_COUNT - 1)
+ b.gt 1f
+
+ /* CorePos = CoreId + (ClusterId * cpus per cluster) */
+ mov x3, #PLATFORM_MAX_CPUS_PER_CLUSTER
+ mul x3, x3, x2
+ add x0, x1, x3
+
+1:
+ ret
+endfunc plat_core_pos_by_mpidr
+
+ /* ----------------------------------------
+ * Secure entrypoint function for CPU boot
+ * ----------------------------------------
+ */
+func tegra_secure_entrypoint _align=6
+
+#if ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT
+
+ /* --------------------------------------------------------
+ * Skip the invalidate BTB workaround for Tegra210B01 SKUs.
+ * --------------------------------------------------------
+ */
+ mov x0, #TEGRA_MISC_BASE
+ add x0, x0, #HARDWARE_REVISION_OFFSET
+ ldr w1, [x0]
+ lsr w1, w1, #CHIP_ID_SHIFT
+ and w1, w1, #CHIP_ID_MASK
+ cmp w1, #TEGRA_CHIPID_TEGRA21 /* T210? */
+ b.ne 2f
+ ldr w1, [x0]
+ lsr w1, w1, #MAJOR_VERSION_SHIFT
+ and w1, w1, #MAJOR_VERSION_MASK
+ cmp w1, #0x02 /* T210 B01? */
+ b.eq 2f
+
+ /* -------------------------------------------------------
+ * Invalidate BTB along with I$ to remove any stale
+ * entries from the branch predictor array.
+ * -------------------------------------------------------
+ */
+ mrs x0, CORTEX_A57_CPUACTLR_EL1
+ orr x0, x0, #1
+ msr CORTEX_A57_CPUACTLR_EL1, x0 /* invalidate BTB and I$ together */
+ dsb sy
+ isb
+ ic iallu /* actual invalidate */
+ dsb sy
+ isb
+
+ mrs x0, CORTEX_A57_CPUACTLR_EL1
+ bic x0, x0, #1
+ msr CORTEX_A57_CPUACTLR_EL1, X0 /* restore original CPUACTLR_EL1 */
+ dsb sy
+ isb
+
+ .rept 7
+ nop /* wait */
+ .endr
+
+ /* -----------------------------------------------
+ * Extract OSLK bit and check if it is '1'. This
+ * bit remains '0' for A53 on warm-resets. If '1',
+ * turn off regional clock gating and request warm
+ * reset.
+ * -----------------------------------------------
+ */
+ mrs x0, oslsr_el1
+ and x0, x0, #2
+ mrs x1, mpidr_el1
+ bics xzr, x0, x1, lsr #7 /* 0 = slow cluster or warm reset */
+ b.eq restore_oslock
+ mov x0, xzr
+ msr oslar_el1, x0 /* os lock stays 0 across warm reset */
+ mov x3, #3
+ movz x4, #0x8000, lsl #48
+ msr CORTEX_A57_CPUACTLR_EL1, x4 /* turn off RCG */
+ isb
+ msr rmr_el3, x3 /* request warm reset */
+ isb
+ dsb sy
+1: wfi
+ b 1b
+
+ /* --------------------------------------------------
+ * These nops are here so that speculative execution
+ * won't harm us before we are done with warm reset.
+ * --------------------------------------------------
+ */
+ .rept 65
+ nop
+ .endr
+2:
+ /* --------------------------------------------------
+ * Do not insert instructions here
+ * --------------------------------------------------
+ */
+#endif
+
+ /* --------------------------------------------------
+ * Restore OS Lock bit
+ * --------------------------------------------------
+ */
+restore_oslock:
+ mov x0, #1
+ msr oslar_el1, x0
+
+ /* --------------------------------------------------
+ * Get secure world's entry point and jump to it
+ * --------------------------------------------------
+ */
+ bl plat_get_my_entrypoint
+ br x0
+endfunc tegra_secure_entrypoint
+
+ .data
+ .align 3
+
+ /* --------------------------------------------------
+ * CPU Secure entry point - resume from suspend
+ * --------------------------------------------------
+ */
+tegra_sec_entry_point:
+ .quad 0
+
+ /* --------------------------------------------------
+ * NS world's cold boot entry point
+ * --------------------------------------------------
+ */
+ns_image_entrypoint:
+ .quad 0
+
+ /* --------------------------------------------------
+ * BL31's physical base address
+ * --------------------------------------------------
+ */
+tegra_bl31_phys_base:
+ .quad 0
+
+ /* --------------------------------------------------
+ * UART controller base for console init
+ * --------------------------------------------------
+ */
+tegra_console_base:
+ .quad 0
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
new file mode 100644
index 0000000..6a3eae0
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <cortex_a57.h>
+#include <denver.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+
+#include <memctrl.h>
+#include <profiler.h>
+#include <smmu.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/* length of Trusty's input parameters (in bytes) */
+#define TRUSTY_PARAMS_LEN_BYTES (4096*2)
+
+/*******************************************************************************
+ * Declarations of linker defined symbols which will help us find the layout
+ * of trusted SRAM
+ ******************************************************************************/
+IMPORT_SYM(uint64_t, __RW_START__, BL31_RW_START);
+
+extern uint64_t tegra_bl31_phys_base;
+
+static entry_point_info_t bl33_image_ep_info, bl32_image_ep_info;
+static plat_params_from_bl2_t plat_bl31_params_from_bl2 = {
+ .tzdram_size = TZDRAM_SIZE
+};
+#ifdef SPD_trusty
+static aapcs64_params_t bl32_args;
+#endif
+
+/*******************************************************************************
+ * This variable holds the non-secure image entry address
+ ******************************************************************************/
+extern uint64_t ns_image_entrypoint;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *ep = NULL;
+
+ /* return BL32 entry point info if it is valid */
+ if (type == NON_SECURE) {
+ ep = &bl33_image_ep_info;
+ } else if ((type == SECURE) && (bl32_image_ep_info.pc != 0U)) {
+ ep = &bl32_image_ep_info;
+ }
+
+ return ep;
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'plat_params_from_bl2_t' structure. The BL2 image
+ * passes this platform specific information.
+ ******************************************************************************/
+plat_params_from_bl2_t *bl31_get_plat_params(void)
+{
+ return &plat_bl31_params_from_bl2;
+}
+
+/*******************************************************************************
+ * Perform any BL31 specific platform actions. Populate the BL33 and BL32 image
+ * info.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ struct tegra_bl31_params *arg_from_bl2 = (struct tegra_bl31_params *) arg0;
+ plat_params_from_bl2_t *plat_params = (plat_params_from_bl2_t *)arg1;
+ int32_t ret;
+
+ /*
+ * For RESET_TO_BL31 systems, BL31 is the first bootloader to run so
+ * there's no argument to relay from a previous bootloader. Platforms
+ * might use custom ways to get arguments.
+ */
+ if (arg_from_bl2 == NULL) {
+ arg_from_bl2 = plat_get_bl31_params();
+ }
+ if (plat_params == NULL) {
+ plat_params = plat_get_bl31_plat_params();
+ }
+
+ /*
+ * Copy BL3-3, BL3-2 entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ assert(arg_from_bl2 != NULL);
+ assert(arg_from_bl2->bl33_ep_info != NULL);
+ bl33_image_ep_info = *arg_from_bl2->bl33_ep_info;
+
+ if (arg_from_bl2->bl32_ep_info != NULL) {
+ bl32_image_ep_info = *arg_from_bl2->bl32_ep_info;
+#ifdef SPD_trusty
+ /* save BL32 boot parameters */
+ memcpy(&bl32_args, &arg_from_bl2->bl32_ep_info->args, sizeof(bl32_args));
+#endif
+ }
+
+ /*
+ * Parse platform specific parameters
+ */
+ assert(plat_params != NULL);
+ plat_bl31_params_from_bl2.tzdram_base = plat_params->tzdram_base;
+ plat_bl31_params_from_bl2.tzdram_size = plat_params->tzdram_size;
+ plat_bl31_params_from_bl2.uart_id = plat_params->uart_id;
+ plat_bl31_params_from_bl2.l2_ecc_parity_prot_dis = plat_params->l2_ecc_parity_prot_dis;
+ plat_bl31_params_from_bl2.sc7entry_fw_size = plat_params->sc7entry_fw_size;
+ plat_bl31_params_from_bl2.sc7entry_fw_base = plat_params->sc7entry_fw_base;
+
+ /*
+ * It is very important that we run either from TZDRAM or TZSRAM base.
+ * Add an explicit check here.
+ */
+ if ((plat_bl31_params_from_bl2.tzdram_base != (uint64_t)BL31_BASE) &&
+ (TEGRA_TZRAM_BASE != BL31_BASE)) {
+ panic();
+ }
+
+ /*
+ * Enable console for the platform
+ */
+ plat_enable_console(plat_params->uart_id);
+
+ /*
+ * The previous bootloader passes the base address of the shared memory
+ * location to store the boot profiler logs. Sanity check the
+ * address and initialise the profiler library, if it looks ok.
+ */
+ ret = bl31_check_ns_address(plat_params->boot_profiler_shmem_base,
+ PROFILER_SIZE_BYTES);
+ if (ret == (int32_t)0) {
+
+ /* store the membase for the profiler lib */
+ plat_bl31_params_from_bl2.boot_profiler_shmem_base =
+ plat_params->boot_profiler_shmem_base;
+
+ /* initialise the profiler library */
+ boot_profiler_init(plat_params->boot_profiler_shmem_base,
+ TEGRA_TMRUS_BASE);
+ }
+
+ /*
+ * Add timestamp for platform early setup entry.
+ */
+ boot_profiler_add_record("[TF] early setup entry");
+
+ /*
+ * Initialize delay timer
+ */
+ tegra_delay_timer_init();
+
+ /* Early platform setup for Tegra SoCs */
+ plat_early_platform_setup();
+
+ /*
+ * Add timestamp for platform early setup exit.
+ */
+ boot_profiler_add_record("[TF] early setup exit");
+
+ INFO("BL3-1: Boot CPU: %s Processor [%lx]\n",
+ (((read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK)
+ == DENVER_IMPL) ? "Denver" : "ARM", read_mpidr());
+}
+
+#ifdef SPD_trusty
+void plat_trusty_set_boot_args(aapcs64_params_t *args)
+{
+ /*
+ * arg0 = TZDRAM aperture available for BL32
+ * arg1 = BL32 boot params
+ * arg2 = EKS Blob Length
+ * arg3 = Boot Profiler Carveout Base
+ */
+ args->arg0 = bl32_args.arg0;
+ args->arg1 = bl32_args.arg2;
+
+ /* update EKS size */
+ args->arg2 = bl32_args.arg4;
+
+ /* Profiler Carveout Base */
+ args->arg3 = bl32_args.arg5;
+}
+#endif
+
+/*******************************************************************************
+ * Initialize the gic, configure the SCR.
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ /*
+ * Add timestamp for platform setup entry.
+ */
+ boot_profiler_add_record("[TF] plat setup entry");
+
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_gic_setup();
+
+ /*
+ * Setup secondary CPU POR infrastructure.
+ */
+ plat_secondary_setup();
+
+ /*
+ * Initial Memory Controller configuration.
+ */
+ tegra_memctrl_setup();
+
+ /*
+ * Late setup handler to allow platforms to performs additional
+ * functionality.
+ * This handler gets called with MMU enabled.
+ */
+ plat_late_platform_setup();
+
+ /*
+ * Add timestamp for platform setup exit.
+ */
+ boot_profiler_add_record("[TF] plat setup exit");
+
+ INFO("BL3-1: Tegra platform setup complete\n");
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 platform runtime setup prior to BL3-1 cold boot exit
+ ******************************************************************************/
+void bl31_plat_runtime_setup(void)
+{
+ /*
+ * Platform specific runtime setup
+ */
+ plat_runtime_setup();
+
+ /*
+ * Add final timestamp before exiting BL31.
+ */
+ boot_profiler_add_record("[TF] bl31 exit");
+ boot_profiler_deinit();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ uint64_t rw_start = BL31_RW_START;
+ uint64_t rw_size = BL_END - BL31_RW_START;
+ uint64_t rodata_start = BL_RO_DATA_BASE;
+ uint64_t rodata_size = BL_RO_DATA_END - BL_RO_DATA_BASE;
+ uint64_t code_base = BL_CODE_BASE;
+ uint64_t code_size = BL_CODE_END - BL_CODE_BASE;
+ const mmap_region_t *plat_mmio_map = NULL;
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+
+ /*
+ * Add timestamp for arch setup entry.
+ */
+ boot_profiler_add_record("[TF] arch setup entry");
+
+ /* add MMIO space */
+ plat_mmio_map = plat_get_mmio_map();
+ if (plat_mmio_map != NULL) {
+ mmap_add(plat_mmio_map);
+ } else {
+ WARN("MMIO map not available\n");
+ }
+
+ /* add memory regions */
+ mmap_add_region(rw_start, rw_start,
+ rw_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(rodata_start, rodata_start,
+ rodata_size,
+ MT_RO_DATA | MT_SECURE);
+ mmap_add_region(code_base, code_base,
+ code_size,
+ MT_CODE | MT_SECURE);
+
+ /* map TZDRAM used by BL31 as coherent memory */
+ if (TEGRA_TZRAM_BASE == tegra_bl31_phys_base) {
+ mmap_add_region(params_from_bl2->tzdram_base,
+ params_from_bl2->tzdram_base,
+ BL31_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ }
+
+ /* set up translation tables */
+ init_xlat_tables();
+
+ /* enable the MMU */
+ enable_mmu_el3(0);
+
+ /*
+ * Add timestamp for arch setup exit.
+ */
+ boot_profiler_add_record("[TF] arch setup exit");
+
+ INFO("BL3-1: Tegra: MMU enabled\n");
+}
+
+/*******************************************************************************
+ * Check if the given NS DRAM range is valid
+ ******************************************************************************/
+int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
+{
+ uint64_t end = base + size_in_bytes - U(1);
+
+ /*
+ * Sanity check the input values
+ */
+ if ((base == 0U) || (size_in_bytes == 0U)) {
+ ERROR("NS address 0x%" PRIx64 " (%" PRId64 " bytes) is invalid\n",
+ base, size_in_bytes);
+ return -EINVAL;
+ }
+
+ /*
+ * Check if the NS DRAM address is valid
+ */
+ if ((base < TEGRA_DRAM_BASE) || (base >= TEGRA_DRAM_END) ||
+ (end > TEGRA_DRAM_END)) {
+
+ ERROR("NS address 0x%" PRIx64 " is out-of-bounds!\n", base);
+ return -EFAULT;
+ }
+
+ /*
+ * TZDRAM aperture contains the BL31 and BL32 images, so we need
+ * to check if the NS DRAM range overlaps the TZDRAM aperture.
+ */
+ if ((base < (uint64_t)TZDRAM_END) && (end > tegra_bl31_phys_base)) {
+ ERROR("NS address 0x%" PRIx64 " overlaps TZDRAM!\n", base);
+ return -ENOTSUP;
+ }
+
+ /* valid NS address */
+ return 0;
+}
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
new file mode 100644
index 0000000..3791018
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := -Iplat/nvidia/tegra/include/drivers \
+ -Iplat/nvidia/tegra/include/lib \
+ -Iplat/nvidia/tegra/include
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+TEGRA_COMMON := plat/nvidia/tegra/common
+TEGRA_DRIVERS := plat/nvidia/tegra/drivers
+TEGRA_LIBS := plat/nvidia/tegra/lib
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+TEGRA_GICv3_SOURCES := $(GICV3_SOURCES) \
+ plat/common/plat_gicv3.c \
+ ${TEGRA_COMMON}/tegra_gicv3.c
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+TEGRA_GICv2_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ ${TEGRA_COMMON}/tegra_gicv2.c
+
+TEGRA_GICv3_SOURCES := drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v3/arm_gicv3_common.c \
+ drivers/arm/gic/v3/gicv3_main.c \
+ drivers/arm/gic/v3/gicv3_helpers.c \
+ plat/common/plat_gicv3.c \
+ ${TEGRA_COMMON}/tegra_gicv3.c
+
+BL31_SOURCES += drivers/delay_timer/delay_timer.c \
+ drivers/io/io_storage.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ ${TEGRA_LIBS}/debug/profiler.c \
+ ${TEGRA_COMMON}/aarch64/tegra_helpers.S \
+ ${TEGRA_LIBS}/debug/profiler.c \
+ ${TEGRA_COMMON}/tegra_bl31_setup.c \
+ ${TEGRA_COMMON}/tegra_delay_timer.c \
+ ${TEGRA_COMMON}/tegra_fiq_glue.c \
+ ${TEGRA_COMMON}/tegra_io_storage.c \
+ ${TEGRA_COMMON}/tegra_platform.c \
+ ${TEGRA_COMMON}/tegra_pm.c \
+ ${TEGRA_COMMON}/tegra_sip_calls.c \
+ ${TEGRA_COMMON}/tegra_sdei.c
+
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+BL31_SOURCES += ${TEGRA_COMMON}/tegra_stack_protector.c
+endif
+ifeq (${EL3_EXCEPTION_HANDLING},1)
+BL31_SOURCES += plat/common/aarch64/plat_ehf.c
+endif
diff --git a/plat/nvidia/tegra/common/tegra_delay_timer.c b/plat/nvidia/tegra/common/tegra_delay_timer.c
new file mode 100644
index 0000000..d9547c4
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_delay_timer.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+
+#include <tegra_def.h>
+#include <tegra_private.h>
+
+static uint32_t tegra_timer_get_value(void)
+{
+ /* enable cntps_tval_el1 timer, mask interrupt */
+ write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT);
+
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. The value is clipped from 64 to 32 bits.
+ */
+ return (uint32_t)(read_cntps_tval_el1());
+}
+
+/*
+ * Initialise the architecture provided counter as the delay timer.
+ */
+void tegra_delay_timer_init(void)
+{
+ static timer_ops_t tegra_timer_ops;
+
+ /* Value in ticks */
+ uint32_t multiplier = MHZ_TICKS_PER_SEC;
+
+ /* Value in ticks per second (Hz) */
+ uint32_t divider = plat_get_syscnt_freq2();
+
+ /* Reduce multiplier and divider by dividing them repeatedly by 10 */
+ while (((multiplier % 10U) == 0U) && ((divider % 10U) == 0U)) {
+ multiplier /= 10U;
+ divider /= 10U;
+ }
+
+ /* enable cntps_tval_el1 timer, mask interrupt */
+ write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT);
+
+ /* register the timer */
+ tegra_timer_ops.get_timer_value = tegra_timer_get_value;
+ tegra_timer_ops.clk_mult = multiplier;
+ tegra_timer_ops.clk_div = divider;
+ timer_init(&tegra_timer_ops);
+}
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
new file mode 100644
index 0000000..5309d98
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <bl31/interrupt_mgmt.h>
+#include <bl31/ehf.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <denver.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <plat/common/platform.h>
+
+#if ENABLE_WDT_LEGACY_FIQ_HANDLING
+#include <flowctrl.h>
+#endif
+#include <tegra_def.h>
+#include <tegra_private.h>
+
+/* Legacy FIQ used by earlier Tegra platforms */
+#define LEGACY_FIQ_PPI_WDT 28U
+
+/*******************************************************************************
+ * Static variables
+ ******************************************************************************/
+static uint64_t ns_fiq_handler_addr;
+static uint32_t fiq_handler_active;
+static pcpu_fiq_state_t fiq_state[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * Handler for FIQ interrupts
+ ******************************************************************************/
+static int tegra_fiq_interrupt_handler(unsigned int id, unsigned int flags,
+ void *handle, void *cookie)
+{
+ cpu_context_t *ctx = cm_get_context(NON_SECURE);
+ el3_state_t *el3state_ctx = get_el3state_ctx(ctx);
+ uint32_t cpu = plat_my_core_pos();
+
+ (void)flags;
+ (void)handle;
+ (void)cookie;
+
+ /*
+ * Jump to NS world only if the NS world's FIQ handler has
+ * been registered
+ */
+ if (ns_fiq_handler_addr != 0U) {
+
+ /*
+ * The FIQ was generated when the execution was in the non-secure
+ * world. Save the context registers to start with.
+ */
+ cm_el1_sysregs_context_save(NON_SECURE);
+
+ /*
+ * Save elr_el3 and spsr_el3 from the saved context, and overwrite
+ * the context with the NS fiq_handler_addr and SPSR value.
+ */
+ fiq_state[cpu].elr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3));
+ fiq_state[cpu].spsr_el3 = read_ctx_reg((el3state_ctx), (uint32_t)(CTX_SPSR_EL3));
+
+ /*
+ * Set the new ELR to continue execution in the NS world using the
+ * FIQ handler registered earlier.
+ */
+ cm_set_elr_el3(NON_SECURE, ns_fiq_handler_addr);
+ }
+
+#if ENABLE_WDT_LEGACY_FIQ_HANDLING
+ /*
+ * Tegra platforms that use LEGACY_FIQ as the watchdog timer FIQ
+ * need to issue an IPI to other CPUs, to allow them to handle
+ * the "system hung" scenario. This interrupt is passed to the GICD
+ * via the Flow Controller. So, once we receive this interrupt,
+ * disable the routing so that we can mark it as "complete" in the
+ * GIC later.
+ */
+ if (id == LEGACY_FIQ_PPI_WDT) {
+ tegra_fc_disable_fiq_to_ccplex_routing();
+ }
+#endif
+
+ /*
+ * Mark this interrupt as complete to avoid a FIQ storm.
+ */
+ plat_ic_end_of_interrupt(id);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Setup handler for FIQ interrupts
+ ******************************************************************************/
+void tegra_fiq_handler_setup(void)
+{
+ /* return if already registered */
+ if (fiq_handler_active == 0U) {
+ /*
+ * Register an interrupt handler for FIQ interrupts generated for
+ * NS interrupt sources
+ */
+ ehf_register_priority_handler(PLAT_TEGRA_WDT_PRIO, tegra_fiq_interrupt_handler);
+
+ /* handler is now active */
+ fiq_handler_active = 1;
+ }
+}
+
+/*******************************************************************************
+ * Validate and store NS world's entrypoint for FIQ interrupts
+ ******************************************************************************/
+void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint)
+{
+ ns_fiq_handler_addr = entrypoint;
+}
+
+/*******************************************************************************
+ * Handler to return the NS EL1/EL0 CPU context
+ ******************************************************************************/
+int32_t tegra_fiq_get_intr_context(void)
+{
+ cpu_context_t *ctx = cm_get_context(NON_SECURE);
+ gp_regs_t *gpregs_ctx = get_gpregs_ctx(ctx);
+ const el1_sysregs_t *el1state_ctx = get_el1_sysregs_ctx(ctx);
+ uint32_t cpu = plat_my_core_pos();
+ uint64_t val;
+
+ /*
+ * We store the ELR_EL3, SPSR_EL3, SP_EL0 and SP_EL1 registers so
+ * that el3_exit() sends these values back to the NS world.
+ */
+ write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X0), (fiq_state[cpu].elr_el3));
+ write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X1), (fiq_state[cpu].spsr_el3));
+
+ val = read_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_SP_EL0));
+ write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X2), (val));
+
+ val = read_ctx_reg((el1state_ctx), (uint32_t)(CTX_SP_EL1));
+ write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X3), (val));
+
+ return 0;
+}
diff --git a/plat/nvidia/tegra/common/tegra_gicv2.c b/plat/nvidia/tegra/common/tegra_gicv2.c
new file mode 100644
index 0000000..012107e
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_gicv2.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <tegra_private.h>
+#include <tegra_def.h>
+
+static unsigned int tegra_target_masks[PLATFORM_CORE_COUNT];
+
+/******************************************************************************
+ * Tegra common helper to setup the GICv2 driver data.
+ *****************************************************************************/
+void tegra_gic_setup(const interrupt_prop_t *interrupt_props,
+ unsigned int interrupt_props_num)
+{
+ /*
+ * Tegra GIC configuration settings
+ */
+ static gicv2_driver_data_t tegra_gic_data;
+
+ /*
+ * Register Tegra GICv2 driver
+ */
+ tegra_gic_data.gicd_base = TEGRA_GICD_BASE;
+ tegra_gic_data.gicc_base = TEGRA_GICC_BASE;
+ tegra_gic_data.interrupt_props = interrupt_props;
+ tegra_gic_data.interrupt_props_num = interrupt_props_num;
+ tegra_gic_data.target_masks = tegra_target_masks;
+ tegra_gic_data.target_masks_num = ARRAY_SIZE(tegra_target_masks);
+ gicv2_driver_init(&tegra_gic_data);
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void tegra_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * Tegra common helper to disable the GICv2 CPU interface
+ *****************************************************************************/
+void tegra_gic_cpuif_deactivate(void)
+{
+ gicv2_cpuif_disable();
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the per cpu distributor interface
+ * in GICv2
+ *****************************************************************************/
+void tegra_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
diff --git a/plat/nvidia/tegra/common/tegra_gicv3.c b/plat/nvidia/tegra/common/tegra_gicv3.c
new file mode 100644
index 0000000..cba2f9b
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_gicv3.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <tegra_private.h>
+#include <tegra_def.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static unsigned int plat_tegra_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+/******************************************************************************
+ * Tegra common helper to setup the GICv3 driver data.
+ *****************************************************************************/
+void tegra_gic_setup(const interrupt_prop_t *interrupt_props,
+ unsigned int interrupt_props_num)
+{
+ /*
+ * Tegra GIC configuration settings
+ */
+ static gicv3_driver_data_t tegra_gic_data;
+
+ /*
+ * Register Tegra GICv3 driver
+ */
+ tegra_gic_data.gicd_base = TEGRA_GICD_BASE;
+ tegra_gic_data.gicr_base = TEGRA_GICR_BASE;
+ tegra_gic_data.rdistif_num = PLATFORM_CORE_COUNT;
+ tegra_gic_data.rdistif_base_addrs = rdistif_base_addrs;
+ tegra_gic_data.mpidr_to_core_pos = plat_tegra_mpidr_to_core_pos;
+ tegra_gic_data.interrupt_props = interrupt_props;
+ tegra_gic_data.interrupt_props_num = interrupt_props_num;
+ gicv3_driver_init(&tegra_gic_data);
+
+ /* initialize the GICD and GICR */
+ tegra_gic_init();
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the GICv3 only driver.
+ *****************************************************************************/
+void tegra_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Tegra common helper to disable the GICv3 CPU interface
+ *****************************************************************************/
+void tegra_gic_cpuif_deactivate(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the per cpu distributor interface
+ * in GICv3
+ *****************************************************************************/
+void tegra_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
diff --git a/plat/nvidia/tegra/common/tegra_io_storage.c b/plat/nvidia/tegra/common/tegra_io_storage.c
new file mode 100644
index 0000000..21641aa
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_io_storage.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <plat/common/platform.h>
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ *
+ * This function is not supported at this time
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ return -ENOTSUP;
+}
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
new file mode 100644
index 0000000..f3aa3ea
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <services/arm_arch_svc.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/*******************************************************************************
+ * Tegra platforms
+ ******************************************************************************/
+typedef enum tegra_platform {
+ TEGRA_PLATFORM_SILICON = 0U,
+ TEGRA_PLATFORM_QT,
+ TEGRA_PLATFORM_FPGA,
+ TEGRA_PLATFORM_EMULATION,
+ TEGRA_PLATFORM_LINSIM,
+ TEGRA_PLATFORM_UNIT_FPGA,
+ TEGRA_PLATFORM_VIRT_DEV_KIT,
+ TEGRA_PLATFORM_MAX,
+} tegra_platform_t;
+
+/*******************************************************************************
+ * Tegra macros defining all the SoC minor versions
+ ******************************************************************************/
+#define TEGRA_MINOR_QT U(0)
+#define TEGRA_MINOR_FPGA U(1)
+#define TEGRA_MINOR_ASIM_QT U(2)
+#define TEGRA_MINOR_ASIM_LINSIM U(3)
+#define TEGRA_MINOR_DSIM_ASIM_LINSIM U(4)
+#define TEGRA_MINOR_UNIT_FPGA U(5)
+#define TEGRA_MINOR_VIRT_DEV_KIT U(6)
+
+/*******************************************************************************
+ * Tegra macros defining all the SoC pre_si_platform
+ ******************************************************************************/
+#define TEGRA_PRE_SI_QT U(1)
+#define TEGRA_PRE_SI_FPGA U(2)
+#define TEGRA_PRE_SI_UNIT_FPGA U(3)
+#define TEGRA_PRE_SI_ASIM_QT U(4)
+#define TEGRA_PRE_SI_ASIM_LINSIM U(5)
+#define TEGRA_PRE_SI_DSIM_ASIM_LINSIM U(6)
+#define TEGRA_PRE_SI_VDK U(8)
+
+/*
+ * Read the chip ID value
+ */
+static uint32_t tegra_get_chipid(void)
+{
+ return mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET);
+}
+
+/*
+ * Read the chip's major version from chip ID value
+ */
+uint32_t tegra_get_chipid_major(void)
+{
+ return (tegra_get_chipid() >> MAJOR_VERSION_SHIFT) & MAJOR_VERSION_MASK;
+}
+
+/*
+ * Read the chip's minor version from the chip ID value
+ */
+uint32_t tegra_get_chipid_minor(void)
+{
+ return (tegra_get_chipid() >> MINOR_VERSION_SHIFT) & MINOR_VERSION_MASK;
+}
+
+/*
+ * Read the chip's pre_si_platform valus from the chip ID value
+ */
+static uint32_t tegra_get_chipid_pre_si_platform(void)
+{
+ return (tegra_get_chipid() >> PRE_SI_PLATFORM_SHIFT) & PRE_SI_PLATFORM_MASK;
+}
+
+bool tegra_chipid_is_t186(void)
+{
+ uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
+
+ return (chip_id == TEGRA_CHIPID_TEGRA18);
+}
+
+bool tegra_chipid_is_t210(void)
+{
+ uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
+
+ return (chip_id == TEGRA_CHIPID_TEGRA21);
+}
+
+bool tegra_chipid_is_t210_b01(void)
+{
+ return (tegra_chipid_is_t210() && (tegra_get_chipid_major() == 0x2U));
+}
+
+bool tegra_chipid_is_t194(void)
+{
+ uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
+
+ return (chip_id == TEGRA_CHIPID_TEGRA19);
+}
+
+/*
+ * Read the chip ID value and derive the platform
+ */
+static tegra_platform_t tegra_get_platform(void)
+{
+ uint32_t major, minor, pre_si_platform;
+ tegra_platform_t ret;
+
+ /* get the major/minor chip ID values */
+ major = tegra_get_chipid_major();
+ minor = tegra_get_chipid_minor();
+ pre_si_platform = tegra_get_chipid_pre_si_platform();
+
+ if (major == 0U) {
+ /*
+ * The minor version number is used by simulation platforms
+ */
+ switch (minor) {
+ /*
+ * Cadence's QuickTurn emulation system is a Solaris-based
+ * chip emulation system
+ */
+ case TEGRA_MINOR_QT:
+ case TEGRA_MINOR_ASIM_QT:
+ ret = TEGRA_PLATFORM_QT;
+ break;
+
+ /*
+ * FPGAs are used during early software/hardware development
+ */
+ case TEGRA_MINOR_FPGA:
+ ret = TEGRA_PLATFORM_FPGA;
+ break;
+ /*
+ * Linsim is a reconfigurable, clock-driven, mixed RTL/cmodel
+ * simulation framework.
+ */
+ case TEGRA_MINOR_ASIM_LINSIM:
+ case TEGRA_MINOR_DSIM_ASIM_LINSIM:
+ ret = TEGRA_PLATFORM_LINSIM;
+ break;
+
+ /*
+ * Unit FPGAs run the actual hardware block IP on the FPGA with
+ * the other parts of the system using Linsim.
+ */
+ case TEGRA_MINOR_UNIT_FPGA:
+ ret = TEGRA_PLATFORM_UNIT_FPGA;
+ break;
+ /*
+ * The Virtualizer Development Kit (VDK) is the standard chip
+ * development from Synopsis.
+ */
+ case TEGRA_MINOR_VIRT_DEV_KIT:
+ ret = TEGRA_PLATFORM_VIRT_DEV_KIT;
+ break;
+
+ default:
+ ret = TEGRA_PLATFORM_MAX;
+ break;
+ }
+
+ } else if (pre_si_platform > 0U) {
+
+ switch (pre_si_platform) {
+ /*
+ * Cadence's QuickTurn emulation system is a Solaris-based
+ * chip emulation system
+ */
+ case TEGRA_PRE_SI_QT:
+ case TEGRA_PRE_SI_ASIM_QT:
+ ret = TEGRA_PLATFORM_QT;
+ break;
+
+ /*
+ * FPGAs are used during early software/hardware development
+ */
+ case TEGRA_PRE_SI_FPGA:
+ ret = TEGRA_PLATFORM_FPGA;
+ break;
+ /*
+ * Linsim is a reconfigurable, clock-driven, mixed RTL/cmodel
+ * simulation framework.
+ */
+ case TEGRA_PRE_SI_ASIM_LINSIM:
+ case TEGRA_PRE_SI_DSIM_ASIM_LINSIM:
+ ret = TEGRA_PLATFORM_LINSIM;
+ break;
+
+ /*
+ * Unit FPGAs run the actual hardware block IP on the FPGA with
+ * the other parts of the system using Linsim.
+ */
+ case TEGRA_PRE_SI_UNIT_FPGA:
+ ret = TEGRA_PLATFORM_UNIT_FPGA;
+ break;
+ /*
+ * The Virtualizer Development Kit (VDK) is the standard chip
+ * development from Synopsis.
+ */
+ case TEGRA_PRE_SI_VDK:
+ ret = TEGRA_PLATFORM_VIRT_DEV_KIT;
+ break;
+
+ default:
+ ret = TEGRA_PLATFORM_MAX;
+ break;
+ }
+
+ } else {
+ /* Actual silicon platforms have a non-zero major version */
+ ret = TEGRA_PLATFORM_SILICON;
+ }
+
+ return ret;
+}
+
+bool tegra_platform_is_silicon(void)
+{
+ return ((tegra_get_platform() == TEGRA_PLATFORM_SILICON) ? true : false);
+}
+
+bool tegra_platform_is_qt(void)
+{
+ return ((tegra_get_platform() == TEGRA_PLATFORM_QT) ? true : false);
+}
+
+bool tegra_platform_is_linsim(void)
+{
+ tegra_platform_t plat = tegra_get_platform();
+
+ return (((plat == TEGRA_PLATFORM_LINSIM) ||
+ (plat == TEGRA_PLATFORM_UNIT_FPGA)) ? true : false);
+}
+
+bool tegra_platform_is_fpga(void)
+{
+ return ((tegra_get_platform() == TEGRA_PLATFORM_FPGA) ? true : false);
+}
+
+bool tegra_platform_is_emulation(void)
+{
+ return (tegra_get_platform() == TEGRA_PLATFORM_EMULATION);
+}
+
+bool tegra_platform_is_unit_fpga(void)
+{
+ return ((tegra_get_platform() == TEGRA_PLATFORM_UNIT_FPGA) ? true : false);
+}
+
+bool tegra_platform_is_virt_dev_kit(void)
+{
+ return ((tegra_get_platform() == TEGRA_PLATFORM_VIRT_DEV_KIT) ? true : false);
+}
+
+/*
+ * This function returns soc version which mainly consist of below fields
+ *
+ * soc_version[30:24] = JEP-106 continuation code for the SiP
+ * soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
+ * soc_version[0:15] = chip identification
+ */
+int32_t plat_get_soc_version(void)
+{
+ uint32_t chip_id = ((tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK);
+ uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_NVIDIA_BKID, JEDEC_NVIDIA_MFID);
+
+ return (int32_t)(manfid | (chip_id & SOC_ID_IMPL_DEF_MASK));
+}
+
+/*
+ * This function returns soc revision in below format
+ *
+ * soc_revision[8:15] = major version number
+ * soc_revision[0:7] = minor version number
+ */
+int32_t plat_get_soc_revision(void)
+{
+ return (int32_t)(((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor()) &
+ SOC_ID_REV_MASK);
+}
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC feature
+ * is availabile for the platform or not.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
new file mode 100644
index 0000000..ec34a85
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/console.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <memctrl.h>
+#include <pmc.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+extern uint64_t tegra_bl31_phys_base;
+extern uint64_t tegra_sec_entry_point;
+
+/*******************************************************************************
+ * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND`
+ * call to get the `power_state` parameter. This allows the platform to encode
+ * the appropriate State-ID field within the `power_state` parameter which can
+ * be utilized in `pwr_domain_suspend()` to suspend to system affinity level.
+******************************************************************************/
+static void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ /* all affinities use system suspend state id */
+ for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) {
+ req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN;
+ }
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to enter standby.
+ ******************************************************************************/
+static void tegra_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t saved_scr_el3;
+
+ (void)cpu_state;
+
+ /* Tegra SoC specific handler */
+ if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS)
+ ERROR("%s failed\n", __func__);
+
+ saved_scr_el3 = read_scr_el3();
+
+ /*
+ * As per ARM ARM D1.17.2, any physical IRQ interrupt received by the
+ * PE will be treated as a wake-up event, if SCR_EL3.IRQ is set to '1',
+ * irrespective of the value of the PSTATE.I bit value.
+ */
+ write_scr_el3(saved_scr_el3 | SCR_IRQ_BIT);
+
+ /*
+ * Enter standby state
+ *
+ * dsb & isb is good practice before using wfi to enter low power states
+ */
+ dsb();
+ isb();
+ wfi();
+
+ /*
+ * Restore saved scr_el3 that has IRQ bit cleared as we don't want EL3
+ * handling any further interrupts
+ */
+ write_scr_el3(saved_scr_el3);
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to be turned on. The
+ * level and mpidr determine the affinity instance.
+ ******************************************************************************/
+static int32_t tegra_pwr_domain_on(u_register_t mpidr)
+{
+ return tegra_soc_pwr_domain_on(mpidr);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void tegra_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ (void)tegra_soc_pwr_domain_off(target_state);
+
+ /* disable GICC */
+ tegra_gic_cpuif_deactivate();
+}
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ * This handler is called with SMP and data cache enabled, when
+ * HW_ASSISTED_COHERENCY = 0
+ ******************************************************************************/
+void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+ tegra_soc_pwr_domain_suspend_pwrdown_early(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ (void)tegra_soc_pwr_domain_suspend(target_state);
+
+ /* disable GICC */
+ tegra_gic_cpuif_deactivate();
+}
+
+/*******************************************************************************
+ * Handler called at the end of the power domain suspend sequence. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ /* call the chip's power down handler */
+ (void)tegra_soc_pwr_domain_power_down_wfi(target_state);
+
+ /* Disable console if we are entering deep sleep. */
+ if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
+ PSTATE_ID_SOC_POWERDN) {
+ INFO("%s: complete. Entering System Suspend...\n", __func__);
+ console_flush();
+ console_switch_state(0);
+ }
+
+ wfi();
+ panic();
+}
+
+/*******************************************************************************
+ * Handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+static void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ const plat_params_from_bl2_t *plat_params;
+
+ /*
+ * Check if we are exiting from deep sleep.
+ */
+ if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
+ PSTATE_ID_SOC_POWERDN) {
+
+ /*
+ * On entering System Suspend state, the GIC loses power
+ * completely. Initialize the GIC global distributor and
+ * GIC cpu interfaces.
+ */
+ tegra_gic_init();
+
+ /* Restart console output. */
+ console_switch_state(CONSOLE_FLAG_RUNTIME);
+
+ /*
+ * Restore Memory Controller settings as it loses state
+ * during system suspend.
+ */
+ tegra_memctrl_restore_settings();
+
+ /*
+ * Security configuration to allow DRAM/device access.
+ */
+ plat_params = bl31_get_plat_params();
+ tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
+ (uint32_t)plat_params->tzdram_size);
+
+ } else {
+ /*
+ * Initialize the GIC cpu and distributor interfaces
+ */
+ tegra_gic_pcpu_init();
+ }
+
+ /*
+ * Reset hardware settings.
+ */
+ (void)tegra_soc_pwr_domain_on_finish(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ ******************************************************************************/
+static void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ tegra_pwr_domain_on_finish(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when the system wants to be powered off
+ ******************************************************************************/
+static __dead2 void tegra_system_off(void)
+{
+ INFO("Powering down system...\n");
+
+ tegra_soc_prepare_system_off();
+}
+
+/*******************************************************************************
+ * Handler called when the system wants to be restarted.
+ ******************************************************************************/
+static __dead2 void tegra_system_reset(void)
+{
+ INFO("Restarting system...\n");
+
+ /* per-SoC system reset handler */
+ (void)tegra_soc_prepare_system_reset();
+
+ /* wait for the system to reset */
+ for (;;) {
+ ;
+ }
+}
+
+/*******************************************************************************
+ * Handler called to check the validity of the power state parameter.
+ ******************************************************************************/
+static int32_t tegra_validate_power_state(uint32_t power_state,
+ psci_power_state_t *req_state)
+{
+ assert(req_state != NULL);
+
+ return tegra_soc_validate_power_state(power_state, req_state);
+}
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the non secure entrypoint.
+ ******************************************************************************/
+static int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ int32_t ret = PSCI_E_INVALID_ADDRESS;
+
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) {
+ ret = PSCI_E_SUCCESS;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static plat_psci_ops_t tegra_plat_psci_ops = {
+ .cpu_standby = tegra_cpu_standby,
+ .pwr_domain_on = tegra_pwr_domain_on,
+ .pwr_domain_off = tegra_pwr_domain_off,
+ .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early,
+ .pwr_domain_suspend = tegra_pwr_domain_suspend,
+ .pwr_domain_on_finish = tegra_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi,
+ .system_off = tegra_system_off,
+ .system_reset = tegra_system_reset,
+ .validate_power_state = tegra_validate_power_state,
+ .validate_ns_entrypoint = tegra_validate_ns_entrypoint,
+ .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops and initialize Power Controller
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } };
+
+ /*
+ * Flush entrypoint variable to PoC since it will be
+ * accessed after a reset with the caches turned off.
+ */
+ tegra_sec_entry_point = sec_entrypoint;
+ flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t));
+
+ /*
+ * Reset hardware settings.
+ */
+ (void)tegra_soc_pwr_domain_on_finish(&target_state);
+
+ /*
+ * Disable System Suspend if the platform does not
+ * support it
+ */
+ if (!plat_supports_system_suspend()) {
+ tegra_plat_psci_ops.get_sys_suspend_power_state = NULL;
+ }
+
+ /*
+ * Initialize PSCI ops struct
+ */
+ *psci_ops = &tegra_plat_psci_ops;
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Platform handler to calculate the proper target power level at the
+ * specified affinity level
+ ******************************************************************************/
+plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
+ const plat_local_state_t *states,
+ unsigned int ncpu)
+{
+ return tegra_soc_get_target_pwr_state(lvl, states, ncpu);
+}
diff --git a/plat/nvidia/tegra/common/tegra_sdei.c b/plat/nvidia/tegra/common/tegra_sdei.c
new file mode 100644
index 0000000..9241b81
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_sdei.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* SDEI configuration for Tegra platforms */
+
+#include <platform_def.h>
+
+#include <bl31/ehf.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <services/sdei.h>
+
+/* Private event mappings */
+static sdei_ev_map_t tegra_sdei_private[] = {
+ /* Event 0 definition */
+ SDEI_DEFINE_EVENT_0(TEGRA_SDEI_SGI_PRIVATE),
+
+ /* Dynamic private events */
+ SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+ SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+ SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+
+ /* General purpose explicit events */
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_0, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_1, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_2, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_3, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_4, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_5, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_6, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_7, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_8, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_9, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_10, SDEI_MAPF_CRITICAL),
+ SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_11, SDEI_MAPF_CRITICAL)
+};
+
+/* Shared event mappings */
+static sdei_ev_map_t tegra_sdei_shared[] = {
+ /* Dynamic shared events */
+ SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+ SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+ SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
+};
+
+void plat_sdei_setup(void)
+{
+ INFO("SDEI platform setup\n");
+}
+
+/* Export Tegra SDEI events */
+REGISTER_SDEI_MAP(tegra_sdei_private, tegra_sdei_shared);
diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c
new file mode 100644
index 0000000..80a2c4d
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_sip_calls.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <memctrl.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/*******************************************************************************
+ * Common Tegra SiP SMCs
+ ******************************************************************************/
+#define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003
+#define TEGRA_SIP_FIQ_NS_ENTRYPOINT 0x82000005
+#define TEGRA_SIP_FIQ_NS_GET_CONTEXT 0x82000006
+
+/*******************************************************************************
+ * This function is responsible for handling all SiP calls
+ ******************************************************************************/
+uintptr_t tegra_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t regval, local_x2_32 = (uint32_t)x2;
+ int32_t err;
+
+ /* Check if this is a SoC specific SiP */
+ err = plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+ if (err == 0) {
+
+ SMC_RET1(handle, (uint64_t)err);
+
+ } else {
+
+ switch (smc_fid) {
+
+ case TEGRA_SIP_NEW_VIDEOMEM_REGION:
+ /* Check whether Video memory resize is enabled */
+ if (mmio_read_32(TEGRA_MC_BASE + MC_VIDEO_PROTECT_REG_CTRL)
+ != MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED) {
+ ERROR("Video Memory Resize isn't enabled! \n");
+ SMC_RET1(handle, (uint64_t)-ENOTSUP);
+ }
+
+ /*
+ * Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
+ * or falls outside of the valid DRAM range
+ */
+ err = bl31_check_ns_address(x1, local_x2_32);
+ if (err != 0) {
+ SMC_RET1(handle, (uint64_t)err);
+ }
+
+ /*
+ * Check if Video Memory is aligned to 1MB.
+ */
+ if (((x1 & 0xFFFFFU) != 0U) || ((local_x2_32 & 0xFFFFFU) != 0U)) {
+ ERROR("Unaligned Video Memory base address!\n");
+ SMC_RET1(handle, (uint64_t)-ENOTSUP);
+ }
+
+ /*
+ * The GPU is the user of the Video Memory region. In order to
+ * transition to the new memory region smoothly, we program the
+ * new base/size ONLY if the GPU is in reset mode.
+ */
+ regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
+ TEGRA_GPU_RESET_REG_OFFSET);
+ if ((regval & GPU_RESET_BIT) == 0U) {
+ ERROR("GPU not in reset! Video Memory setup failed\n");
+ SMC_RET1(handle, (uint64_t)-ENOTSUP);
+ }
+
+ /* new video memory carveout settings */
+ tegra_memctrl_videomem_setup(x1, local_x2_32);
+
+ /*
+ * Ensure again that GPU is still in reset after VPR resize
+ */
+ regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
+ TEGRA_GPU_RESET_REG_OFFSET);
+ if ((regval & GPU_RESET_BIT) == 0U) {
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET,
+ GPU_SET_BIT);
+ }
+
+ SMC_RET1(handle, 0);
+
+ /*
+ * The NS world registers the address of its handler to be
+ * used for processing the FIQ. This is normally used by the
+ * NS FIQ debugger driver to detect system hangs by programming
+ * a watchdog timer to fire a FIQ interrupt.
+ */
+ case TEGRA_SIP_FIQ_NS_ENTRYPOINT:
+
+ if (x1 == 0U) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ /*
+ * TODO: Check if x1 contains a valid DRAM address
+ */
+
+ /* store the NS world's entrypoint */
+ tegra_fiq_set_ns_entrypoint(x1);
+
+ SMC_RET1(handle, 0);
+
+ /*
+ * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0
+ * CPU context when the FIQ interrupt was triggered. This allows the
+ * NS world to understand the CPU state when the watchdog interrupt
+ * triggered.
+ */
+ case TEGRA_SIP_FIQ_NS_GET_CONTEXT:
+
+ /* retrieve context registers when FIQ triggered */
+ (void)tegra_fiq_get_intr_context();
+
+ SMC_RET0(handle);
+
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ break;
+ }
+ }
+
+ SMC_RET1(handle, SMC_UNK);
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ tegra_sip_fast,
+
+ (OEN_SIP_START),
+ (OEN_SIP_END),
+ (SMC_TYPE_FAST),
+ (NULL),
+ (tegra_sip_handler)
+);
diff --git a/plat/nvidia/tegra/common/tegra_stack_protector.c b/plat/nvidia/tegra/common/tegra_stack_protector.c
new file mode 100644
index 0000000..f6c459a
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_stack_protector.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ u_register_t seed;
+
+ /*
+ * Ideally, a random number should be returned instead. As the
+ * platform does not have any random number generator, this is
+ * better than nothing, but not really secure.
+ */
+ seed = mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET);
+ seed <<= 32;
+ seed |= mmio_read_32(TEGRA_TMRUS_BASE);
+
+ return seed ^ read_cntpct_el0();
+}
diff --git a/plat/nvidia/tegra/drivers/bpmp/bpmp.c b/plat/nvidia/tegra/drivers/bpmp/bpmp.c
new file mode 100644
index 0000000..d7db604
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/bpmp/bpmp.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bpmp.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <stdbool.h>
+#include <string.h>
+#include <tegra_def.h>
+
+#define BPMP_TIMEOUT 500 /* 500ms */
+
+static uint32_t channel_base[NR_CHANNELS];
+static uint32_t bpmp_init_state = BPMP_INIT_PENDING;
+
+static uint32_t channel_field(unsigned int ch)
+{
+ return mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET) & CH_MASK(ch);
+}
+
+static bool master_free(unsigned int ch)
+{
+ return channel_field(ch) == MA_FREE(ch);
+}
+
+static bool master_acked(unsigned int ch)
+{
+ return channel_field(ch) == MA_ACKD(ch);
+}
+
+static void signal_slave(unsigned int ch)
+{
+ mmio_write_32(TEGRA_RES_SEMA_BASE + CLR_OFFSET, CH_MASK(ch));
+}
+
+static void free_master(unsigned int ch)
+{
+ mmio_write_32(TEGRA_RES_SEMA_BASE + CLR_OFFSET,
+ MA_ACKD(ch) ^ MA_FREE(ch));
+}
+
+/* should be called with local irqs disabled */
+int32_t tegra_bpmp_send_receive_atomic(int mrq, const void *ob_data, int ob_sz,
+ void *ib_data, int ib_sz)
+{
+ unsigned int ch = (unsigned int)plat_my_core_pos();
+ mb_data_t *p = (mb_data_t *)(uintptr_t)channel_base[ch];
+ int32_t ret = -ETIMEDOUT, timeout = 0;
+
+ if (bpmp_init_state == BPMP_INIT_COMPLETE) {
+
+ /* loop until BPMP is free */
+ for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) {
+ if (master_free(ch) == true) {
+ break;
+ }
+
+ mdelay(1);
+ }
+
+ if (timeout != BPMP_TIMEOUT) {
+
+ /* generate the command struct */
+ p->code = mrq;
+ p->flags = DO_ACK;
+ (void)memcpy((void *)p->data, ob_data, (size_t)ob_sz);
+
+ /* signal command ready to the BPMP */
+ signal_slave(ch);
+ mmio_write_32(TEGRA_PRI_ICTLR_BASE + CPU_IEP_FIR_SET,
+ (1U << INT_SHR_SEM_OUTBOX_FULL));
+
+ /* loop until the command is executed */
+ for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) {
+ if (master_acked(ch) == true) {
+ break;
+ }
+
+ mdelay(1);
+ }
+
+ if (timeout != BPMP_TIMEOUT) {
+
+ /* get the command response */
+ (void)memcpy(ib_data, (const void *)p->data,
+ (size_t)ib_sz);
+
+ /* return error code */
+ ret = p->code;
+
+ /* free this channel */
+ free_master(ch);
+ }
+ }
+
+ } else {
+ /* return error code */
+ ret = -EINVAL;
+ }
+
+ if (timeout == BPMP_TIMEOUT) {
+ ERROR("Timed out waiting for bpmp's response\n");
+ }
+
+ return ret;
+}
+
+int tegra_bpmp_init(void)
+{
+ uint32_t val, base, timeout = BPMP_TIMEOUT;
+ unsigned int ch;
+ int ret = 0;
+
+ if (bpmp_init_state == BPMP_INIT_PENDING) {
+
+ /* check if the bpmp processor is alive. */
+ do {
+ val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+ if (val != SIGN_OF_LIFE) {
+ mdelay(1);
+ timeout--;
+ }
+
+ } while ((val != SIGN_OF_LIFE) && (timeout > 0U));
+
+ if (val == SIGN_OF_LIFE) {
+
+ /* check if clock for the atomics block is enabled */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_ENB_V);
+ if ((val & CAR_ENABLE_ATOMICS) == 0) {
+ ERROR("Clock to the atomics block is disabled\n");
+ }
+
+ /* check if the atomics block is out of reset */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_CLR_V);
+ if ((val & CAR_ENABLE_ATOMICS) == CAR_ENABLE_ATOMICS) {
+ ERROR("Reset to the atomics block is asserted\n");
+ }
+
+ /* base address to get the result from Atomics */
+ base = TEGRA_ATOMICS_BASE + RESULT0_REG_OFFSET;
+
+ /* channel area is setup by BPMP before signaling handshake */
+ for (ch = 0; ch < NR_CHANNELS; ch++) {
+
+ /* issue command to get the channel base address */
+ mmio_write_32(base, (ch << TRIGGER_ID_SHIFT) |
+ ATOMIC_CMD_GET);
+
+ /* get the base address for the channel */
+ channel_base[ch] = mmio_read_32(base);
+
+ /* increment result register offset */
+ base += 4U;
+ }
+
+ /* mark state as "initialized" */
+ bpmp_init_state = BPMP_INIT_COMPLETE;
+
+ /* the channel values have to be visible across all cpus */
+ flush_dcache_range((uint64_t)channel_base,
+ sizeof(channel_base));
+ flush_dcache_range((uint64_t)&bpmp_init_state,
+ sizeof(bpmp_init_state));
+
+ INFO("%s: done\n", __func__);
+
+ } else {
+ ERROR("BPMP not powered on\n");
+
+ /* bpmp is not present in the system */
+ bpmp_init_state = BPMP_NOT_PRESENT;
+
+ /* communication timed out */
+ ret = -ETIMEDOUT;
+ }
+ }
+
+ return ret;
+}
+
+void tegra_bpmp_suspend(void)
+{
+ /* freeze the interface */
+ if (bpmp_init_state == BPMP_INIT_COMPLETE) {
+ bpmp_init_state = BPMP_SUSPEND_ENTRY;
+ flush_dcache_range((uint64_t)&bpmp_init_state,
+ sizeof(bpmp_init_state));
+ }
+}
+
+void tegra_bpmp_resume(void)
+{
+ uint32_t val, timeout = 0;
+
+ if (bpmp_init_state == BPMP_SUSPEND_ENTRY) {
+
+ /* check if the bpmp processor is alive. */
+ do {
+
+ val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+ if (val != SIGN_OF_LIFE) {
+ mdelay(1);
+ timeout++;
+ }
+
+ } while ((val != SIGN_OF_LIFE) && (timeout < BPMP_TIMEOUT));
+
+ if (val == SIGN_OF_LIFE) {
+
+ INFO("%s: BPMP took %d ms to resume\n", __func__, timeout);
+
+ /* mark state as "initialized" */
+ bpmp_init_state = BPMP_INIT_COMPLETE;
+
+ /* state has to be visible across all cpus */
+ flush_dcache_range((uint64_t)&bpmp_init_state,
+ sizeof(bpmp_init_state));
+ } else {
+ ERROR("BPMP not powered on\n");
+ }
+ }
+}
diff --git a/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c b/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c
new file mode 100644
index 0000000..2e90d25
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bpmp_ipc.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <stdbool.h>
+#include <string.h>
+#include <tegra_def.h>
+
+#include "intf.h"
+#include "ivc.h"
+
+/**
+ * Holds IVC channel data
+ */
+struct ccplex_bpmp_channel_data {
+ /* Buffer for incoming data */
+ struct frame_data *ib;
+
+ /* Buffer for outgoing data */
+ struct frame_data *ob;
+};
+
+static struct ccplex_bpmp_channel_data s_channel;
+static struct ivc ivc_ccplex_bpmp_channel;
+
+/*
+ * Helper functions to access the HSP doorbell registers
+ */
+static inline uint32_t hsp_db_read(uint32_t reg)
+{
+ return mmio_read_32((uint32_t)(TEGRA_HSP_DBELL_BASE + reg));
+}
+
+static inline void hsp_db_write(uint32_t reg, uint32_t val)
+{
+ mmio_write_32((uint32_t)(TEGRA_HSP_DBELL_BASE + reg), val);
+}
+
+/*******************************************************************************
+ * IVC wrappers for CCPLEX <-> BPMP communication.
+ ******************************************************************************/
+
+static void tegra_bpmp_ring_bpmp_doorbell(void);
+
+/*
+ * Get the next frame where data can be written.
+ */
+static struct frame_data *tegra_bpmp_get_next_out_frame(void)
+{
+ struct frame_data *frame;
+ const struct ivc *ch = &ivc_ccplex_bpmp_channel;
+
+ frame = (struct frame_data *)tegra_ivc_write_get_next_frame(ch);
+ if (frame == NULL) {
+ ERROR("%s: Error in getting next frame, exiting\n", __func__);
+ } else {
+ s_channel.ob = frame;
+ }
+
+ return frame;
+}
+
+static void tegra_bpmp_signal_slave(void)
+{
+ (void)tegra_ivc_write_advance(&ivc_ccplex_bpmp_channel);
+ tegra_bpmp_ring_bpmp_doorbell();
+}
+
+static int32_t tegra_bpmp_free_master(void)
+{
+ return tegra_ivc_read_advance(&ivc_ccplex_bpmp_channel);
+}
+
+static bool tegra_bpmp_slave_acked(void)
+{
+ struct frame_data *frame;
+ bool ret = true;
+
+ frame = (struct frame_data *)tegra_ivc_read_get_next_frame(&ivc_ccplex_bpmp_channel);
+ if (frame == NULL) {
+ ret = false;
+ } else {
+ s_channel.ib = frame;
+ }
+
+ return ret;
+}
+
+static struct frame_data *tegra_bpmp_get_cur_in_frame(void)
+{
+ return s_channel.ib;
+}
+
+/*
+ * Enables BPMP to ring CCPlex doorbell
+ */
+static void tegra_bpmp_enable_ccplex_doorbell(void)
+{
+ uint32_t reg;
+
+ reg = hsp_db_read(HSP_DBELL_1_ENABLE);
+ reg |= HSP_MASTER_BPMP_BIT;
+ hsp_db_write(HSP_DBELL_1_ENABLE, reg);
+}
+
+/*
+ * CCPlex rings the BPMP doorbell
+ */
+static void tegra_bpmp_ring_bpmp_doorbell(void)
+{
+ /*
+ * Any writes to this register has the same effect,
+ * uses master ID of the write transaction and set
+ * corresponding flag.
+ */
+ hsp_db_write(HSP_DBELL_3_TRIGGER, HSP_MASTER_CCPLEX_BIT);
+}
+
+/*
+ * Returns true if CCPLex can ring BPMP doorbell, otherwise false.
+ * This also signals that BPMP is up and ready.
+ */
+static bool tegra_bpmp_can_ccplex_ring_doorbell(void)
+{
+ uint32_t reg;
+
+ /* check if ccplex can communicate with bpmp */
+ reg = hsp_db_read(HSP_DBELL_3_ENABLE);
+
+ return ((reg & HSP_MASTER_CCPLEX_BIT) != 0U);
+}
+
+static int32_t tegra_bpmp_wait_for_slave_ack(void)
+{
+ uint32_t timeout = TIMEOUT_RESPONSE_FROM_BPMP_US;
+
+ while (!tegra_bpmp_slave_acked() && (timeout != 0U)) {
+ udelay(1);
+ timeout--;
+ };
+
+ return ((timeout == 0U) ? -ETIMEDOUT : 0);
+}
+
+/*
+ * Notification from the ivc layer
+ */
+static void tegra_bpmp_ivc_notify(const struct ivc *ivc)
+{
+ (void)(ivc);
+
+ tegra_bpmp_ring_bpmp_doorbell();
+}
+
+/*
+ * Atomic send/receive API, which means it waits until slave acks
+ */
+static int32_t tegra_bpmp_ipc_send_req_atomic(uint32_t mrq, void *p_out,
+ uint32_t size_out, void *p_in, uint32_t size_in)
+{
+ struct frame_data *frame = tegra_bpmp_get_next_out_frame();
+ const struct frame_data *f_in = NULL;
+ int32_t ret = 0;
+ void *p_fdata;
+
+ if ((p_out == NULL) || (size_out > IVC_DATA_SZ_BYTES) ||
+ (frame == NULL)) {
+ ERROR("%s: invalid parameters, exiting\n", __func__);
+ return -EINVAL;
+ }
+
+ /* prepare the command frame */
+ frame->mrq = mrq;
+ frame->flags = FLAG_DO_ACK;
+ p_fdata = frame->data;
+ (void)memcpy(p_fdata, p_out, (size_t)size_out);
+
+ /* signal the slave */
+ tegra_bpmp_signal_slave();
+
+ /* wait for slave to ack */
+ ret = tegra_bpmp_wait_for_slave_ack();
+ if (ret < 0) {
+ ERROR("%s: wait for slave failed (%d)\n", __func__, ret);
+ return ret;
+ }
+
+ /* retrieve the response frame */
+ if ((size_in <= IVC_DATA_SZ_BYTES) && (p_in != NULL)) {
+
+ f_in = tegra_bpmp_get_cur_in_frame();
+ if (f_in != NULL) {
+ ERROR("Failed to get next input frame!\n");
+ } else {
+ (void)memcpy(p_in, p_fdata, (size_t)size_in);
+ }
+ }
+
+ ret = tegra_bpmp_free_master();
+ if (ret < 0) {
+ ERROR("%s: free master failed (%d)\n", __func__, ret);
+ }
+
+ return ret;
+}
+
+/*
+ * Initializes the BPMP<--->CCPlex communication path.
+ */
+int32_t tegra_bpmp_ipc_init(void)
+{
+ size_t msg_size;
+ uint32_t frame_size, timeout;
+ int32_t error = 0;
+
+ /* allow bpmp to ring CCPLEX's doorbell */
+ tegra_bpmp_enable_ccplex_doorbell();
+
+ /* wait for BPMP to actually ring the doorbell */
+ timeout = TIMEOUT_RESPONSE_FROM_BPMP_US;
+ while ((timeout != 0U) && !tegra_bpmp_can_ccplex_ring_doorbell()) {
+ udelay(1); /* bpmp turn-around time */
+ timeout--;
+ }
+
+ if (timeout == 0U) {
+ ERROR("%s: BPMP firmware is not ready\n", __func__);
+ return -ENOTSUP;
+ }
+
+ INFO("%s: BPMP handshake completed\n", __func__);
+
+ msg_size = tegra_ivc_align(IVC_CMD_SZ_BYTES);
+ frame_size = (uint32_t)tegra_ivc_total_queue_size(msg_size);
+ if (frame_size > TEGRA_BPMP_IPC_CH_MAP_SIZE) {
+ ERROR("%s: carveout size is not sufficient\n", __func__);
+ return -EINVAL;
+ }
+
+ error = tegra_ivc_init(&ivc_ccplex_bpmp_channel,
+ (uint32_t)TEGRA_BPMP_IPC_RX_PHYS_BASE,
+ (uint32_t)TEGRA_BPMP_IPC_TX_PHYS_BASE,
+ 1U, frame_size, tegra_bpmp_ivc_notify);
+ if (error != 0) {
+
+ ERROR("%s: IVC init failed (%d)\n", __func__, error);
+
+ } else {
+
+ /* reset channel */
+ tegra_ivc_channel_reset(&ivc_ccplex_bpmp_channel);
+
+ /* wait for notification from BPMP */
+ while (tegra_ivc_channel_notified(&ivc_ccplex_bpmp_channel) != 0) {
+ /*
+ * Interrupt BPMP with doorbell each time after
+ * tegra_ivc_channel_notified() returns non zero
+ * value.
+ */
+ tegra_bpmp_ring_bpmp_doorbell();
+ }
+
+ INFO("%s: All communication channels initialized\n", __func__);
+ }
+
+ return error;
+}
+
+/* Handler to reset a hardware module */
+int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id)
+{
+ int32_t ret;
+ struct mrq_reset_request req = {
+ .cmd = (uint32_t)CMD_RESET_MODULE,
+ .reset_id = rst_id
+ };
+
+ /* only GPCDMA/XUSB_PADCTL resets are supported */
+ assert((rst_id == TEGRA_RESET_ID_XUSB_PADCTL) ||
+ (rst_id == TEGRA_RESET_ID_GPCDMA));
+
+ ret = tegra_bpmp_ipc_send_req_atomic(MRQ_RESET, &req,
+ (uint32_t)sizeof(req), NULL, 0);
+ if (ret != 0) {
+ ERROR("%s: failed for module %d with error %d\n", __func__,
+ rst_id, ret);
+ }
+
+ return ret;
+}
+
+int tegra_bpmp_ipc_enable_clock(uint32_t clk_id)
+{
+ int ret;
+ struct mrq_clk_request req;
+
+ /* only SE clocks are supported */
+ if (clk_id != TEGRA_CLK_SE) {
+ return -ENOTSUP;
+ }
+
+ /* prepare the MRQ_CLK command */
+ req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_ENABLE, clk_id);
+
+ ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, (uint32_t)sizeof(req),
+ NULL, 0);
+ if (ret != 0) {
+ ERROR("%s: failed for module %d with error %d\n", __func__,
+ clk_id, ret);
+ }
+
+ return ret;
+}
+
+int tegra_bpmp_ipc_disable_clock(uint32_t clk_id)
+{
+ int ret;
+ struct mrq_clk_request req;
+
+ /* only SE clocks are supported */
+ if (clk_id != TEGRA_CLK_SE) {
+ return -ENOTSUP;
+ }
+
+ /* prepare the MRQ_CLK command */
+ req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_DISABLE, clk_id);
+
+ ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, (uint32_t)sizeof(req),
+ NULL, 0);
+ if (ret != 0) {
+ ERROR("%s: failed for module %d with error %d\n", __func__,
+ clk_id, ret);
+ }
+
+ return ret;
+}
diff --git a/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h b/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h
new file mode 100644
index 0000000..d85b906
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BPMP_INTF_H
+#define BPMP_INTF_H
+
+/**
+ * Flags used in IPC req
+ */
+#define FLAG_DO_ACK (U(1) << 0)
+#define FLAG_RING_DOORBELL (U(1) << 1)
+
+/* Bit 1 is designated for CCPlex in secure world */
+#define HSP_MASTER_CCPLEX_BIT (U(1) << 1)
+/* Bit 19 is designated for BPMP in non-secure world */
+#define HSP_MASTER_BPMP_BIT (U(1) << 19)
+/* Timeout to receive response from BPMP is 1 sec */
+#define TIMEOUT_RESPONSE_FROM_BPMP_US U(1000000) /* in microseconds */
+
+/**
+ * IVC protocol defines and command/response frame
+ */
+
+/**
+ * IVC specific defines
+ */
+#define IVC_CMD_SZ_BYTES U(128)
+#define IVC_DATA_SZ_BYTES U(120)
+
+/**
+ * Holds frame data for an IPC request
+ */
+struct frame_data {
+ /* Identification as to what kind of data is being transmitted */
+ uint32_t mrq;
+
+ /* Flags for slave as to how to respond back */
+ uint32_t flags;
+
+ /* Actual data being sent */
+ uint8_t data[IVC_DATA_SZ_BYTES];
+};
+
+/**
+ * Commands send to the BPMP firmware
+ */
+
+/**
+ * MRQ command codes
+ */
+#define MRQ_RESET U(20)
+#define MRQ_CLK U(22)
+
+/**
+ * Reset sub-commands
+ */
+#define CMD_RESET_ASSERT U(1)
+#define CMD_RESET_DEASSERT U(2)
+#define CMD_RESET_MODULE U(3)
+
+/**
+ * Used by the sender of an #MRQ_RESET message to request BPMP to
+ * assert or deassert a given reset line.
+ */
+struct __attribute__((packed)) mrq_reset_request {
+ /* reset action to perform (mrq_reset_commands) */
+ uint32_t cmd;
+ /* id of the reset to affected */
+ uint32_t reset_id;
+};
+
+/**
+ * MRQ_CLK sub-commands
+ *
+ */
+enum {
+ CMD_CLK_GET_RATE = U(1),
+ CMD_CLK_SET_RATE = U(2),
+ CMD_CLK_ROUND_RATE = U(3),
+ CMD_CLK_GET_PARENT = U(4),
+ CMD_CLK_SET_PARENT = U(5),
+ CMD_CLK_IS_ENABLED = U(6),
+ CMD_CLK_ENABLE = U(7),
+ CMD_CLK_DISABLE = U(8),
+ CMD_CLK_GET_ALL_INFO = U(14),
+ CMD_CLK_GET_MAX_CLK_ID = U(15),
+ CMD_CLK_MAX,
+};
+
+/**
+ * Used by the sender of an #MRQ_CLK message to control clocks. The
+ * clk_request is split into several sub-commands. Some sub-commands
+ * require no additional data. Others have a sub-command specific
+ * payload
+ *
+ * |sub-command |payload |
+ * |----------------------------|-----------------------|
+ * |CMD_CLK_GET_RATE |- |
+ * |CMD_CLK_SET_RATE |clk_set_rate |
+ * |CMD_CLK_ROUND_RATE |clk_round_rate |
+ * |CMD_CLK_GET_PARENT |- |
+ * |CMD_CLK_SET_PARENT |clk_set_parent |
+ * |CMD_CLK_IS_ENABLED |- |
+ * |CMD_CLK_ENABLE |- |
+ * |CMD_CLK_DISABLE |- |
+ * |CMD_CLK_GET_ALL_INFO |- |
+ * |CMD_CLK_GET_MAX_CLK_ID |- |
+ *
+ */
+struct mrq_clk_request {
+ /**
+ * sub-command and clock id concatenated to 32-bit word.
+ * - bits[31..24] is the sub-cmd.
+ * - bits[23..0] is the clock id
+ */
+ uint32_t cmd_and_id;
+};
+
+/**
+ * Macro to prepare the MRQ_CLK sub-command
+ */
+#define make_mrq_clk_cmd(cmd, id) (((cmd) << 24) | (id & 0xFFFFFF))
+
+#endif /* BPMP_INTF_H */
diff --git a/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c b/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c
new file mode 100644
index 0000000..d964fc0
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c
@@ -0,0 +1,654 @@
+/*
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "ivc.h"
+
+/*
+ * IVC channel reset protocol.
+ *
+ * Each end uses its tx_channel.state to indicate its synchronization state.
+ */
+enum {
+ /*
+ * This value is zero for backwards compatibility with services that
+ * assume channels to be initially zeroed. Such channels are in an
+ * initially valid state, but cannot be asynchronously reset, and must
+ * maintain a valid state at all times.
+ *
+ * The transmitting end can enter the established state from the sync or
+ * ack state when it observes the receiving endpoint in the ack or
+ * established state, indicating that has cleared the counters in our
+ * rx_channel.
+ */
+ ivc_state_established = U(0),
+
+ /*
+ * If an endpoint is observed in the sync state, the remote endpoint is
+ * allowed to clear the counters it owns asynchronously with respect to
+ * the current endpoint. Therefore, the current endpoint is no longer
+ * allowed to communicate.
+ */
+ ivc_state_sync = U(1),
+
+ /*
+ * When the transmitting end observes the receiving end in the sync
+ * state, it can clear the w_count and r_count and transition to the ack
+ * state. If the remote endpoint observes us in the ack state, it can
+ * return to the established state once it has cleared its counters.
+ */
+ ivc_state_ack = U(2)
+};
+
+/*
+ * This structure is divided into two-cache aligned parts, the first is only
+ * written through the tx_channel pointer, while the second is only written
+ * through the rx_channel pointer. This delineates ownership of the cache lines,
+ * which is critical to performance and necessary in non-cache coherent
+ * implementations.
+ */
+struct ivc_channel_header {
+ struct {
+ /* fields owned by the transmitting end */
+ uint32_t w_count;
+ uint32_t state;
+ uint32_t w_rsvd[IVC_CHHDR_TX_FIELDS - 2];
+ };
+ struct {
+ /* fields owned by the receiving end */
+ uint32_t r_count;
+ uint32_t r_rsvd[IVC_CHHDR_RX_FIELDS - 1];
+ };
+};
+
+static inline bool ivc_channel_empty(const struct ivc *ivc,
+ volatile const struct ivc_channel_header *ch)
+{
+ /*
+ * This function performs multiple checks on the same values with
+ * security implications, so sample the counters' current values in
+ * shared memory to ensure that these checks use the same values.
+ */
+ uint32_t wr_count = ch->w_count;
+ uint32_t rd_count = ch->r_count;
+ bool ret = false;
+
+ (void)ivc;
+
+ /*
+ * Perform an over-full check to prevent denial of service attacks where
+ * a server could be easily fooled into believing that there's an
+ * extremely large number of frames ready, since receivers are not
+ * expected to check for full or over-full conditions.
+ *
+ * Although the channel isn't empty, this is an invalid case caused by
+ * a potentially malicious peer, so returning empty is safer, because it
+ * gives the impression that the channel has gone silent.
+ */
+ if (((wr_count - rd_count) > ivc->nframes) || (wr_count == rd_count)) {
+ ret = true;
+ }
+
+ return ret;
+}
+
+static inline bool ivc_channel_full(const struct ivc *ivc,
+ volatile const struct ivc_channel_header *ch)
+{
+ uint32_t wr_count = ch->w_count;
+ uint32_t rd_count = ch->r_count;
+
+ (void)ivc;
+
+ /*
+ * Invalid cases where the counters indicate that the queue is over
+ * capacity also appear full.
+ */
+ return ((wr_count - rd_count) >= ivc->nframes);
+}
+
+static inline uint32_t ivc_channel_avail_count(const struct ivc *ivc,
+ volatile const struct ivc_channel_header *ch)
+{
+ uint32_t wr_count = ch->w_count;
+ uint32_t rd_count = ch->r_count;
+
+ (void)ivc;
+
+ /*
+ * This function isn't expected to be used in scenarios where an
+ * over-full situation can lead to denial of service attacks. See the
+ * comment in ivc_channel_empty() for an explanation about special
+ * over-full considerations.
+ */
+ return (wr_count - rd_count);
+}
+
+static inline void ivc_advance_tx(struct ivc *ivc)
+{
+ ivc->tx_channel->w_count++;
+
+ if (ivc->w_pos == (ivc->nframes - (uint32_t)1U)) {
+ ivc->w_pos = 0U;
+ } else {
+ ivc->w_pos++;
+ }
+}
+
+static inline void ivc_advance_rx(struct ivc *ivc)
+{
+ ivc->rx_channel->r_count++;
+
+ if (ivc->r_pos == (ivc->nframes - (uint32_t)1U)) {
+ ivc->r_pos = 0U;
+ } else {
+ ivc->r_pos++;
+ }
+}
+
+static inline int32_t ivc_check_read(const struct ivc *ivc)
+{
+ /*
+ * tx_channel->state is set locally, so it is not synchronized with
+ * state from the remote peer. The remote peer cannot reset its
+ * transmit counters until we've acknowledged its synchronization
+ * request, so no additional synchronization is required because an
+ * asynchronous transition of rx_channel->state to ivc_state_ack is not
+ * allowed.
+ */
+ if (ivc->tx_channel->state != ivc_state_established) {
+ return -ECONNRESET;
+ }
+
+ /*
+ * Avoid unnecessary invalidations when performing repeated accesses to
+ * an IVC channel by checking the old queue pointers first.
+ * Synchronization is only necessary when these pointers indicate empty
+ * or full.
+ */
+ if (!ivc_channel_empty(ivc, ivc->rx_channel)) {
+ return 0;
+ }
+
+ return ivc_channel_empty(ivc, ivc->rx_channel) ? -ENOMEM : 0;
+}
+
+static inline int32_t ivc_check_write(const struct ivc *ivc)
+{
+ if (ivc->tx_channel->state != ivc_state_established) {
+ return -ECONNRESET;
+ }
+
+ if (!ivc_channel_full(ivc, ivc->tx_channel)) {
+ return 0;
+ }
+
+ return ivc_channel_full(ivc, ivc->tx_channel) ? -ENOMEM : 0;
+}
+
+bool tegra_ivc_can_read(const struct ivc *ivc)
+{
+ return ivc_check_read(ivc) == 0;
+}
+
+bool tegra_ivc_can_write(const struct ivc *ivc)
+{
+ return ivc_check_write(ivc) == 0;
+}
+
+bool tegra_ivc_tx_empty(const struct ivc *ivc)
+{
+ return ivc_channel_empty(ivc, ivc->tx_channel);
+}
+
+static inline uintptr_t calc_frame_offset(uint32_t frame_index,
+ uint32_t frame_size, uint32_t frame_offset)
+{
+ return ((uintptr_t)frame_index * (uintptr_t)frame_size) +
+ (uintptr_t)frame_offset;
+}
+
+static void *ivc_frame_pointer(const struct ivc *ivc,
+ volatile const struct ivc_channel_header *ch,
+ uint32_t frame)
+{
+ assert(frame < ivc->nframes);
+ return (void *)((uintptr_t)(&ch[1]) +
+ calc_frame_offset(frame, ivc->frame_size, 0));
+}
+
+int32_t tegra_ivc_read(struct ivc *ivc, void *buf, size_t max_read)
+{
+ const void *src;
+ int32_t result;
+
+ if (buf == NULL) {
+ return -EINVAL;
+ }
+
+ if (max_read > ivc->frame_size) {
+ return -E2BIG;
+ }
+
+ result = ivc_check_read(ivc);
+ if (result != 0) {
+ return result;
+ }
+
+ /*
+ * Order observation of w_pos potentially indicating new data before
+ * data read.
+ */
+ dmbish();
+
+ src = ivc_frame_pointer(ivc, ivc->rx_channel, ivc->r_pos);
+
+ (void)memcpy(buf, src, max_read);
+
+ ivc_advance_rx(ivc);
+
+ /*
+ * Ensure our write to r_pos occurs before our read from w_pos.
+ */
+ dmbish();
+
+ /*
+ * Notify only upon transition from full to non-full.
+ * The available count can only asynchronously increase, so the
+ * worst possible side-effect will be a spurious notification.
+ */
+ if (ivc_channel_avail_count(ivc, ivc->rx_channel) == (ivc->nframes - (uint32_t)1U)) {
+ ivc->notify(ivc);
+ }
+
+ return (int32_t)max_read;
+}
+
+/* directly peek at the next frame rx'ed */
+void *tegra_ivc_read_get_next_frame(const struct ivc *ivc)
+{
+ if (ivc_check_read(ivc) != 0) {
+ return NULL;
+ }
+
+ /*
+ * Order observation of w_pos potentially indicating new data before
+ * data read.
+ */
+ dmbld();
+
+ return ivc_frame_pointer(ivc, ivc->rx_channel, ivc->r_pos);
+}
+
+int32_t tegra_ivc_read_advance(struct ivc *ivc)
+{
+ /*
+ * No read barriers or synchronization here: the caller is expected to
+ * have already observed the channel non-empty. This check is just to
+ * catch programming errors.
+ */
+ int32_t result = ivc_check_read(ivc);
+ if (result != 0) {
+ return result;
+ }
+
+ ivc_advance_rx(ivc);
+
+ /*
+ * Ensure our write to r_pos occurs before our read from w_pos.
+ */
+ dmbish();
+
+ /*
+ * Notify only upon transition from full to non-full.
+ * The available count can only asynchronously increase, so the
+ * worst possible side-effect will be a spurious notification.
+ */
+ if (ivc_channel_avail_count(ivc, ivc->rx_channel) == (ivc->nframes - (uint32_t)1U)) {
+ ivc->notify(ivc);
+ }
+
+ return 0;
+}
+
+int32_t tegra_ivc_write(struct ivc *ivc, const void *buf, size_t size)
+{
+ void *p;
+ int32_t result;
+
+ if ((buf == NULL) || (ivc == NULL)) {
+ return -EINVAL;
+ }
+
+ if (size > ivc->frame_size) {
+ return -E2BIG;
+ }
+
+ result = ivc_check_write(ivc);
+ if (result != 0) {
+ return result;
+ }
+
+ p = ivc_frame_pointer(ivc, ivc->tx_channel, ivc->w_pos);
+
+ (void)memset(p, 0, ivc->frame_size);
+ (void)memcpy(p, buf, size);
+
+ /*
+ * Ensure that updated data is visible before the w_pos counter
+ * indicates that it is ready.
+ */
+ dmbst();
+
+ ivc_advance_tx(ivc);
+
+ /*
+ * Ensure our write to w_pos occurs before our read from r_pos.
+ */
+ dmbish();
+
+ /*
+ * Notify only upon transition from empty to non-empty.
+ * The available count can only asynchronously decrease, so the
+ * worst possible side-effect will be a spurious notification.
+ */
+ if (ivc_channel_avail_count(ivc, ivc->tx_channel) == 1U) {
+ ivc->notify(ivc);
+ }
+
+ return (int32_t)size;
+}
+
+/* directly poke at the next frame to be tx'ed */
+void *tegra_ivc_write_get_next_frame(const struct ivc *ivc)
+{
+ if (ivc_check_write(ivc) != 0) {
+ return NULL;
+ }
+
+ return ivc_frame_pointer(ivc, ivc->tx_channel, ivc->w_pos);
+}
+
+/* advance the tx buffer */
+int32_t tegra_ivc_write_advance(struct ivc *ivc)
+{
+ int32_t result = ivc_check_write(ivc);
+
+ if (result != 0) {
+ return result;
+ }
+
+ /*
+ * Order any possible stores to the frame before update of w_pos.
+ */
+ dmbst();
+
+ ivc_advance_tx(ivc);
+
+ /*
+ * Ensure our write to w_pos occurs before our read from r_pos.
+ */
+ dmbish();
+
+ /*
+ * Notify only upon transition from empty to non-empty.
+ * The available count can only asynchronously decrease, so the
+ * worst possible side-effect will be a spurious notification.
+ */
+ if (ivc_channel_avail_count(ivc, ivc->tx_channel) == (uint32_t)1U) {
+ ivc->notify(ivc);
+ }
+
+ return 0;
+}
+
+void tegra_ivc_channel_reset(const struct ivc *ivc)
+{
+ ivc->tx_channel->state = ivc_state_sync;
+ ivc->notify(ivc);
+}
+
+/*
+ * ===============================================================
+ * IVC State Transition Table - see tegra_ivc_channel_notified()
+ * ===============================================================
+ *
+ * local remote action
+ * ----- ------ -----------------------------------
+ * SYNC EST <none>
+ * SYNC ACK reset counters; move to EST; notify
+ * SYNC SYNC reset counters; move to ACK; notify
+ * ACK EST move to EST; notify
+ * ACK ACK move to EST; notify
+ * ACK SYNC reset counters; move to ACK; notify
+ * EST EST <none>
+ * EST ACK <none>
+ * EST SYNC reset counters; move to ACK; notify
+ *
+ * ===============================================================
+ */
+int32_t tegra_ivc_channel_notified(struct ivc *ivc)
+{
+ uint32_t peer_state;
+
+ /* Copy the receiver's state out of shared memory. */
+ peer_state = ivc->rx_channel->state;
+
+ if (peer_state == (uint32_t)ivc_state_sync) {
+ /*
+ * Order observation of ivc_state_sync before stores clearing
+ * tx_channel.
+ */
+ dmbld();
+
+ /*
+ * Reset tx_channel counters. The remote end is in the SYNC
+ * state and won't make progress until we change our state,
+ * so the counters are not in use at this time.
+ */
+ ivc->tx_channel->w_count = 0U;
+ ivc->rx_channel->r_count = 0U;
+
+ ivc->w_pos = 0U;
+ ivc->r_pos = 0U;
+
+ /*
+ * Ensure that counters appear cleared before new state can be
+ * observed.
+ */
+ dmbst();
+
+ /*
+ * Move to ACK state. We have just cleared our counters, so it
+ * is now safe for the remote end to start using these values.
+ */
+ ivc->tx_channel->state = ivc_state_ack;
+
+ /*
+ * Notify remote end to observe state transition.
+ */
+ ivc->notify(ivc);
+
+ } else if ((ivc->tx_channel->state == (uint32_t)ivc_state_sync) &&
+ (peer_state == (uint32_t)ivc_state_ack)) {
+ /*
+ * Order observation of ivc_state_sync before stores clearing
+ * tx_channel.
+ */
+ dmbld();
+
+ /*
+ * Reset tx_channel counters. The remote end is in the ACK
+ * state and won't make progress until we change our state,
+ * so the counters are not in use at this time.
+ */
+ ivc->tx_channel->w_count = 0U;
+ ivc->rx_channel->r_count = 0U;
+
+ ivc->w_pos = 0U;
+ ivc->r_pos = 0U;
+
+ /*
+ * Ensure that counters appear cleared before new state can be
+ * observed.
+ */
+ dmbst();
+
+ /*
+ * Move to ESTABLISHED state. We know that the remote end has
+ * already cleared its counters, so it is safe to start
+ * writing/reading on this channel.
+ */
+ ivc->tx_channel->state = ivc_state_established;
+
+ /*
+ * Notify remote end to observe state transition.
+ */
+ ivc->notify(ivc);
+
+ } else if (ivc->tx_channel->state == (uint32_t)ivc_state_ack) {
+ /*
+ * At this point, we have observed the peer to be in either
+ * the ACK or ESTABLISHED state. Next, order observation of
+ * peer state before storing to tx_channel.
+ */
+ dmbld();
+
+ /*
+ * Move to ESTABLISHED state. We know that we have previously
+ * cleared our counters, and we know that the remote end has
+ * cleared its counters, so it is safe to start writing/reading
+ * on this channel.
+ */
+ ivc->tx_channel->state = ivc_state_established;
+
+ /*
+ * Notify remote end to observe state transition.
+ */
+ ivc->notify(ivc);
+
+ } else {
+ /*
+ * There is no need to handle any further action. Either the
+ * channel is already fully established, or we are waiting for
+ * the remote end to catch up with our current state. Refer
+ * to the diagram in "IVC State Transition Table" above.
+ */
+ }
+
+ return ((ivc->tx_channel->state == (uint32_t)ivc_state_established) ? 0 : -EAGAIN);
+}
+
+size_t tegra_ivc_align(size_t size)
+{
+ return (size + (IVC_ALIGN - 1U)) & ~(IVC_ALIGN - 1U);
+}
+
+size_t tegra_ivc_total_queue_size(size_t queue_size)
+{
+ if ((queue_size & (IVC_ALIGN - 1U)) != 0U) {
+ ERROR("queue_size (%d) must be %d-byte aligned\n",
+ (int32_t)queue_size, IVC_ALIGN);
+ return 0;
+ }
+ return queue_size + sizeof(struct ivc_channel_header);
+}
+
+static int32_t check_ivc_params(uintptr_t queue_base1, uintptr_t queue_base2,
+ uint32_t nframes, uint32_t frame_size)
+{
+ assert((offsetof(struct ivc_channel_header, w_count)
+ & (IVC_ALIGN - 1U)) == 0U);
+ assert((offsetof(struct ivc_channel_header, r_count)
+ & (IVC_ALIGN - 1U)) == 0U);
+ assert((sizeof(struct ivc_channel_header) & (IVC_ALIGN - 1U)) == 0U);
+
+ if (((uint64_t)nframes * (uint64_t)frame_size) >= 0x100000000ULL) {
+ ERROR("nframes * frame_size overflows\n");
+ return -EINVAL;
+ }
+
+ /*
+ * The headers must at least be aligned enough for counters
+ * to be accessed atomically.
+ */
+ if ((queue_base1 & (IVC_ALIGN - 1U)) != 0U) {
+ ERROR("ivc channel start not aligned: %lx\n", queue_base1);
+ return -EINVAL;
+ }
+ if ((queue_base2 & (IVC_ALIGN - 1U)) != 0U) {
+ ERROR("ivc channel start not aligned: %lx\n", queue_base2);
+ return -EINVAL;
+ }
+
+ if ((frame_size & (IVC_ALIGN - 1U)) != 0U) {
+ ERROR("frame size not adequately aligned: %u\n",
+ frame_size);
+ return -EINVAL;
+ }
+
+ if (queue_base1 < queue_base2) {
+ if ((queue_base1 + ((uint64_t)frame_size * nframes)) > queue_base2) {
+ ERROR("queue regions overlap: %lx + %x, %x\n",
+ queue_base1, frame_size,
+ frame_size * nframes);
+ return -EINVAL;
+ }
+ } else {
+ if ((queue_base2 + ((uint64_t)frame_size * nframes)) > queue_base1) {
+ ERROR("queue regions overlap: %lx + %x, %x\n",
+ queue_base2, frame_size,
+ frame_size * nframes);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int32_t tegra_ivc_init(struct ivc *ivc, uintptr_t rx_base, uintptr_t tx_base,
+ uint32_t nframes, uint32_t frame_size,
+ ivc_notify_function notify)
+{
+ int32_t result;
+
+ /* sanity check input params */
+ if ((ivc == NULL) || (notify == NULL)) {
+ return -EINVAL;
+ }
+
+ result = check_ivc_params(rx_base, tx_base, nframes, frame_size);
+ if (result != 0) {
+ return result;
+ }
+
+ /*
+ * All sizes that can be returned by communication functions should
+ * fit in a 32-bit integer.
+ */
+ if (frame_size > (1u << 31)) {
+ return -E2BIG;
+ }
+
+ ivc->rx_channel = (struct ivc_channel_header *)rx_base;
+ ivc->tx_channel = (struct ivc_channel_header *)tx_base;
+ ivc->notify = notify;
+ ivc->frame_size = frame_size;
+ ivc->nframes = nframes;
+ ivc->w_pos = 0U;
+ ivc->r_pos = 0U;
+
+ INFO("%s: done\n", __func__);
+
+ return 0;
+}
diff --git a/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h b/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h
new file mode 100644
index 0000000..1b31821
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017-2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BPMP_IVC_H
+#define BPMP_IVC_H
+
+#include <lib/utils_def.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define IVC_ALIGN U(64)
+#define IVC_CHHDR_TX_FIELDS U(16)
+#define IVC_CHHDR_RX_FIELDS U(16)
+
+struct ivc_channel_header;
+
+struct ivc {
+ struct ivc_channel_header *rx_channel;
+ struct ivc_channel_header *tx_channel;
+ uint32_t w_pos;
+ uint32_t r_pos;
+ void (*notify)(const struct ivc *);
+ uint32_t nframes;
+ uint32_t frame_size;
+};
+
+/* callback handler for notify on receiving a response */
+typedef void (* ivc_notify_function)(const struct ivc *);
+
+int32_t tegra_ivc_init(struct ivc *ivc, uintptr_t rx_base, uintptr_t tx_base,
+ uint32_t nframes, uint32_t frame_size,
+ ivc_notify_function notify);
+size_t tegra_ivc_total_queue_size(size_t queue_size);
+size_t tegra_ivc_align(size_t size);
+int32_t tegra_ivc_channel_notified(struct ivc *ivc);
+void tegra_ivc_channel_reset(const struct ivc *ivc);
+int32_t tegra_ivc_write_advance(struct ivc *ivc);
+void *tegra_ivc_write_get_next_frame(const struct ivc *ivc);
+int32_t tegra_ivc_write(struct ivc *ivc, const void *buf, size_t size);
+int32_t tegra_ivc_read_advance(struct ivc *ivc);
+void *tegra_ivc_read_get_next_frame(const struct ivc *ivc);
+int32_t tegra_ivc_read(struct ivc *ivc, void *buf, size_t max_read);
+bool tegra_ivc_tx_empty(const struct ivc *ivc);
+bool tegra_ivc_can_write(const struct ivc *ivc);
+bool tegra_ivc_can_read(const struct ivc *ivc);
+
+#endif /* BPMP_IVC_H */
diff --git a/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c b/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c
new file mode 100644
index 0000000..8f55554
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <cortex_a53.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <flowctrl.h>
+#include <lib/utils_def.h>
+#include <pmc.h>
+#include <tegra_def.h>
+
+#define CLK_RST_DEV_L_SET 0x300
+#define CLK_RST_DEV_L_CLR 0x304
+#define CLK_BPMP_RST (1 << 1)
+
+#define EVP_BPMP_RESET_VECTOR 0x200
+
+static const uint64_t flowctrl_offset_cpu_csr[4] = {
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU0_CSR),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 8),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 16)
+};
+
+static const uint64_t flowctrl_offset_halt_cpu[4] = {
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU0_EVENTS),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 8),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 16)
+};
+
+static const uint64_t flowctrl_offset_cc4_ctrl[4] = {
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 4),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 8),
+ (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 12)
+};
+
+static inline void tegra_fc_cc4_ctrl(int cpu_id, uint32_t val)
+{
+ mmio_write_32(flowctrl_offset_cc4_ctrl[cpu_id], val);
+ val = mmio_read_32(flowctrl_offset_cc4_ctrl[cpu_id]);
+}
+
+static inline void tegra_fc_cpu_csr(int cpu_id, uint32_t val)
+{
+ mmio_write_32(flowctrl_offset_cpu_csr[cpu_id], val);
+ val = mmio_read_32(flowctrl_offset_cpu_csr[cpu_id]);
+}
+
+static inline void tegra_fc_halt_cpu(int cpu_id, uint32_t val)
+{
+ mmio_write_32(flowctrl_offset_halt_cpu[cpu_id], val);
+ val = mmio_read_32(flowctrl_offset_halt_cpu[cpu_id]);
+}
+
+static void tegra_fc_prepare_suspend(int cpu_id, uint32_t csr)
+{
+ uint32_t val;
+
+ val = FLOWCTRL_HALT_GIC_IRQ | FLOWCTRL_HALT_GIC_FIQ |
+ FLOWCTRL_HALT_LIC_IRQ | FLOWCTRL_HALT_LIC_FIQ |
+ FLOWCTRL_WAITEVENT;
+ tegra_fc_halt_cpu(cpu_id, val);
+
+ val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
+ FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu_id);
+ tegra_fc_cpu_csr(cpu_id, val | csr);
+}
+
+/*******************************************************************************
+ * After this, no core can wake from C7 until the action is reverted.
+ * If a wake up event is asserted, the FC state machine will stall until
+ * the action is reverted.
+ ******************************************************************************/
+void tegra_fc_ccplex_pgexit_lock(void)
+{
+ unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
+ uint32_t flags = tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT) & ~INTERCEPT_IRQ_PENDING;;
+ uint32_t icept_cpu_flags[] = {
+ INTERCEPT_EXIT_PG_CORE0,
+ INTERCEPT_EXIT_PG_CORE1,
+ INTERCEPT_EXIT_PG_CORE2,
+ INTERCEPT_EXIT_PG_CORE3
+ };
+
+ /* set the intercept flags */
+ for (i = 0; i < ARRAY_SIZE(icept_cpu_flags); i++) {
+
+ /* skip current CPU */
+ if (i == cpu)
+ continue;
+
+ /* enable power gate exit intercept locks */
+ flags |= icept_cpu_flags[i];
+ }
+
+ tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, flags);
+ (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
+}
+
+/*******************************************************************************
+ * Revert the ccplex powergate exit locks
+ ******************************************************************************/
+void tegra_fc_ccplex_pgexit_unlock(void)
+{
+ /* clear lock bits, clear pending interrupts */
+ tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, INTERCEPT_IRQ_PENDING);
+ (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
+}
+
+/*******************************************************************************
+ * Powerdn the current CPU
+ ******************************************************************************/
+void tegra_fc_cpu_powerdn(uint32_t mpidr)
+{
+ int cpu = mpidr & MPIDR_CPU_MASK;
+
+ VERBOSE("CPU%d powering down...\n", cpu);
+ tegra_fc_prepare_suspend(cpu, 0);
+}
+
+/*******************************************************************************
+ * Suspend the current CPU cluster
+ ******************************************************************************/
+void tegra_fc_cluster_idle(uint32_t mpidr)
+{
+ int cpu = mpidr & MPIDR_CPU_MASK;
+ uint32_t val;
+
+ VERBOSE("Entering cluster idle state...\n");
+
+ tegra_fc_cc4_ctrl(cpu, 0);
+
+ /* hardware L2 flush is faster for A53 only */
+ tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
+ !!MPIDR_AFFLVL1_VAL(mpidr));
+
+ /* suspend the CPU cluster */
+ val = FLOWCTRL_PG_CPU_NONCPU << FLOWCTRL_ENABLE_EXT;
+ tegra_fc_prepare_suspend(cpu, val);
+}
+
+/*******************************************************************************
+ * Power down the current CPU cluster
+ ******************************************************************************/
+void tegra_fc_cluster_powerdn(uint32_t mpidr)
+{
+ int cpu = mpidr & MPIDR_CPU_MASK;
+ uint32_t val;
+
+ VERBOSE("Entering cluster powerdn state...\n");
+
+ tegra_fc_cc4_ctrl(cpu, 0);
+
+ /* hardware L2 flush is faster for A53 only */
+ tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
+ read_midr() == CORTEX_A53_MIDR);
+
+ /* power down the CPU cluster */
+ val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
+ tegra_fc_prepare_suspend(cpu, val);
+}
+
+/*******************************************************************************
+ * Check if cluster idle or power down state is allowed from this CPU
+ ******************************************************************************/
+bool tegra_fc_is_ccx_allowed(void)
+{
+ unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
+ uint32_t val;
+ bool ccx_allowed = true;
+
+ for (i = 0; i < ARRAY_SIZE(flowctrl_offset_cpu_csr); i++) {
+
+ /* skip current CPU */
+ if (i == cpu)
+ continue;
+
+ /* check if all other CPUs are already halted */
+ val = mmio_read_32(flowctrl_offset_cpu_csr[i]);
+ if ((val & FLOWCTRL_CSR_HALT_MASK) == 0U) {
+ ccx_allowed = false;
+ }
+ }
+
+ return ccx_allowed;
+}
+
+/*******************************************************************************
+ * Suspend the entire SoC
+ ******************************************************************************/
+void tegra_fc_soc_powerdn(uint32_t mpidr)
+{
+ int cpu = mpidr & MPIDR_CPU_MASK;
+ uint32_t val;
+
+ VERBOSE("Entering SoC powerdn state...\n");
+
+ tegra_fc_cc4_ctrl(cpu, 0);
+
+ tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, 1);
+
+ val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
+ tegra_fc_prepare_suspend(cpu, val);
+
+ /* overwrite HALT register */
+ tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
+}
+
+/*******************************************************************************
+ * Power up the CPU
+ ******************************************************************************/
+void tegra_fc_cpu_on(int cpu)
+{
+ tegra_fc_cpu_csr(cpu, FLOWCTRL_CSR_ENABLE);
+ tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT | FLOWCTRL_HALT_SCLK);
+}
+
+/*******************************************************************************
+ * Power down the CPU
+ ******************************************************************************/
+void tegra_fc_cpu_off(int cpu)
+{
+ uint32_t val;
+
+ /*
+ * Flow controller powers down the CPU during wfi. The CPU would be
+ * powered on when it receives any interrupt.
+ */
+ val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
+ FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu);
+ tegra_fc_cpu_csr(cpu, val);
+ tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
+ tegra_fc_cc4_ctrl(cpu, 0);
+}
+
+/*******************************************************************************
+ * Inform the BPMP that we have completed the cluster power up
+ ******************************************************************************/
+void tegra_fc_lock_active_cluster(void)
+{
+ uint32_t val;
+
+ val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
+ val |= FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK;
+ tegra_fc_write_32(FLOWCTRL_BPMP_CLUSTER_CONTROL, val);
+ val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
+}
+
+/*******************************************************************************
+ * Power ON BPMP processor
+ ******************************************************************************/
+void tegra_fc_bpmp_on(uint32_t entrypoint)
+{
+ /* halt BPMP */
+ tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
+
+ /* Assert BPMP reset */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
+
+ /* Set reset address (stored in PMC_SCRATCH39) */
+ mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, entrypoint);
+ while (entrypoint != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
+ ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
+
+ /* Wait for 2us before de-asserting the reset signal. */
+ udelay(2);
+
+ /* De-assert BPMP reset */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST);
+
+ /* Un-halt BPMP */
+ tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
+}
+
+/*******************************************************************************
+ * Power OFF BPMP processor
+ ******************************************************************************/
+void tegra_fc_bpmp_off(void)
+{
+ /* halt BPMP */
+ tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
+
+ /* Assert BPMP reset */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
+
+ /* Clear reset address */
+ mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, 0);
+ while (0 != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
+ ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
+}
+
+/*******************************************************************************
+ * Route legacy FIQ to the GICD
+ ******************************************************************************/
+void tegra_fc_enable_fiq_to_ccplex_routing(void)
+{
+ uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
+
+ /* set the bit to pass FIQs to the GICD */
+ tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val | FLOWCTRL_FIQ2CCPLEX_ENABLE);
+}
+
+/*******************************************************************************
+ * Disable routing legacy FIQ to the GICD
+ ******************************************************************************/
+void tegra_fc_disable_fiq_to_ccplex_routing(void)
+{
+ uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
+
+ /* clear the bit to pass FIQs to the GICD */
+ tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val & ~FLOWCTRL_FIQ2CCPLEX_ENABLE);
+}
diff --git a/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c b/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c
new file mode 100644
index 0000000..d68cdfd
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <gpcdma.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <platform_def.h>
+#include <stdbool.h>
+#include <tegra_def.h>
+
+/* DMA channel registers */
+#define DMA_CH_CSR U(0x0)
+#define DMA_CH_CSR_WEIGHT_SHIFT U(10)
+#define DMA_CH_CSR_XFER_MODE_SHIFT U(21)
+#define DMA_CH_CSR_DMA_MODE_MEM2MEM U(4)
+#define DMA_CH_CSR_DMA_MODE_FIXEDPATTERN U(6)
+#define DMA_CH_CSR_IRQ_MASK_ENABLE (U(1) << 15)
+#define DMA_CH_CSR_RUN_ONCE (U(1) << 27)
+#define DMA_CH_CSR_ENABLE (U(1) << 31)
+
+#define DMA_CH_STAT U(0x4)
+#define DMA_CH_STAT_BUSY (U(1) << 31)
+
+#define DMA_CH_SRC_PTR U(0xC)
+
+#define DMA_CH_DST_PTR U(0x10)
+
+#define DMA_CH_HI_ADR_PTR U(0x14)
+#define DMA_CH_HI_ADR_PTR_SRC_MASK U(0xFF)
+#define DMA_CH_HI_ADR_PTR_DST_SHIFT U(16)
+#define DMA_CH_HI_ADR_PTR_DST_MASK U(0xFF)
+
+#define DMA_CH_MC_SEQ U(0x18)
+#define DMA_CH_MC_SEQ_REQ_CNT_SHIFT U(25)
+#define DMA_CH_MC_SEQ_REQ_CNT_VAL U(0x10)
+#define DMA_CH_MC_SEQ_BURST_SHIFT U(23)
+#define DMA_CH_MC_SEQ_BURST_16_WORDS U(0x3)
+
+#define DMA_CH_WORD_COUNT U(0x20)
+#define DMA_CH_FIXED_PATTERN U(0x34)
+#define DMA_CH_TZ U(0x38)
+#define DMA_CH_TZ_ACCESS_ENABLE U(0)
+#define DMA_CH_TZ_ACCESS_DISABLE U(3)
+
+#define MAX_TRANSFER_SIZE (1U*1024U*1024U*1024U) /* 1GB */
+#define GPCDMA_TIMEOUT_MS U(100)
+#define GPCDMA_RESET_BIT (U(1) << 1)
+
+static bool init_done;
+
+static void tegra_gpcdma_write32(uint32_t offset, uint32_t val)
+{
+ mmio_write_32(TEGRA_GPCDMA_BASE + offset, val);
+}
+
+static uint32_t tegra_gpcdma_read32(uint32_t offset)
+{
+ return mmio_read_32(TEGRA_GPCDMA_BASE + offset);
+}
+
+static void tegra_gpcdma_init(void)
+{
+ /* assert reset for DMA engine */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPCDMA_RST_SET_REG_OFFSET,
+ GPCDMA_RESET_BIT);
+
+ udelay(2);
+
+ /* de-assert reset for DMA engine */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPCDMA_RST_CLR_REG_OFFSET,
+ GPCDMA_RESET_BIT);
+}
+
+static void tegra_gpcdma_memcpy_priv(uint64_t dst_addr, uint64_t src_addr,
+ uint32_t num_bytes, uint32_t mode)
+{
+ uint32_t val, timeout = 0;
+ int32_t ret = 0;
+
+ /* sanity check byte count */
+ if ((num_bytes > MAX_TRANSFER_SIZE) || ((num_bytes & 0x3U) != U(0))) {
+ ret = -EINVAL;
+ }
+
+ /* initialise GPCDMA block */
+ if (!init_done) {
+ tegra_gpcdma_init();
+ init_done = true;
+ }
+
+ /* make sure channel isn't busy */
+ val = tegra_gpcdma_read32(DMA_CH_STAT);
+ if ((val & DMA_CH_STAT_BUSY) == DMA_CH_STAT_BUSY) {
+ ERROR("DMA channel is busy\n");
+ ret = -EBUSY;
+ }
+
+ if (ret == 0) {
+
+ /* disable any DMA transfers */
+ tegra_gpcdma_write32(DMA_CH_CSR, 0);
+
+ /* enable DMA access to TZDRAM */
+ tegra_gpcdma_write32(DMA_CH_TZ, DMA_CH_TZ_ACCESS_ENABLE);
+
+ /* configure MC sequencer */
+ val = (DMA_CH_MC_SEQ_REQ_CNT_VAL << DMA_CH_MC_SEQ_REQ_CNT_SHIFT) |
+ (DMA_CH_MC_SEQ_BURST_16_WORDS << DMA_CH_MC_SEQ_BURST_SHIFT);
+ tegra_gpcdma_write32(DMA_CH_MC_SEQ, val);
+
+ /* reset fixed pattern */
+ tegra_gpcdma_write32(DMA_CH_FIXED_PATTERN, 0);
+
+ /* populate src and dst address registers */
+ tegra_gpcdma_write32(DMA_CH_SRC_PTR, (uint32_t)src_addr);
+ tegra_gpcdma_write32(DMA_CH_DST_PTR, (uint32_t)dst_addr);
+
+ val = (uint32_t)((src_addr >> 32) & DMA_CH_HI_ADR_PTR_SRC_MASK);
+ val |= (uint32_t)(((dst_addr >> 32) & DMA_CH_HI_ADR_PTR_DST_MASK) <<
+ DMA_CH_HI_ADR_PTR_DST_SHIFT);
+ tegra_gpcdma_write32(DMA_CH_HI_ADR_PTR, val);
+
+ /* transfer size (in words) */
+ tegra_gpcdma_write32(DMA_CH_WORD_COUNT, ((num_bytes >> 2) - 1U));
+
+ /* populate value for CSR */
+ val = (mode << DMA_CH_CSR_XFER_MODE_SHIFT) |
+ DMA_CH_CSR_RUN_ONCE | (U(1) << DMA_CH_CSR_WEIGHT_SHIFT) |
+ DMA_CH_CSR_IRQ_MASK_ENABLE;
+ tegra_gpcdma_write32(DMA_CH_CSR, val);
+
+ /* enable transfer */
+ val = tegra_gpcdma_read32(DMA_CH_CSR);
+ val |= DMA_CH_CSR_ENABLE;
+ tegra_gpcdma_write32(DMA_CH_CSR, val);
+
+ /* wait till transfer completes */
+ do {
+
+ /* read the status */
+ val = tegra_gpcdma_read32(DMA_CH_STAT);
+ if ((val & DMA_CH_STAT_BUSY) != DMA_CH_STAT_BUSY) {
+ break;
+ }
+
+ mdelay(1);
+ timeout++;
+
+ } while (timeout < GPCDMA_TIMEOUT_MS);
+
+ /* flag timeout error */
+ if (timeout == GPCDMA_TIMEOUT_MS) {
+ ERROR("DMA transfer timed out\n");
+ }
+
+ dsbsy();
+
+ /* disable DMA access to TZDRAM */
+ tegra_gpcdma_write32(DMA_CH_TZ, DMA_CH_TZ_ACCESS_DISABLE);
+ isb();
+ }
+}
+
+/*******************************************************************************
+ * Memcpy using GPCDMA block (Mem2Mem copy)
+ ******************************************************************************/
+void tegra_gpcdma_memcpy(uint64_t dst_addr, uint64_t src_addr,
+ uint32_t num_bytes)
+{
+ tegra_gpcdma_memcpy_priv(dst_addr, src_addr, num_bytes,
+ DMA_CH_CSR_DMA_MODE_MEM2MEM);
+}
+
+/*******************************************************************************
+ * Memset using GPCDMA block (Fixed pattern write)
+ ******************************************************************************/
+void tegra_gpcdma_zeromem(uint64_t dst_addr, uint32_t num_bytes)
+{
+ tegra_gpcdma_memcpy_priv(dst_addr, 0, num_bytes,
+ DMA_CH_CSR_DMA_MODE_FIXEDPATTERN);
+}
diff --git a/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c b/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c
new file mode 100644
index 0000000..b3dcd2a
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <memctrl.h>
+#include <memctrl_v1.h>
+#include <tegra_def.h>
+
+/* Video Memory base and size (live values) */
+static uint64_t video_mem_base;
+static uint64_t video_mem_size;
+
+/*
+ * Init SMMU.
+ */
+void tegra_memctrl_setup(void)
+{
+ /*
+ * Setup the Memory controller to allow only secure accesses to
+ * the TZDRAM carveout
+ */
+ INFO("Tegra Memory Controller (v1)\n");
+
+ /* allow translations for all MC engines */
+ tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_0_0,
+ (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
+ tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_1_0,
+ (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
+ tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_2_0,
+ (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
+ tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_3_0,
+ (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
+ tegra_mc_write_32(MC_SMMU_TRANSLATION_ENABLE_4_0,
+ (unsigned int)MC_SMMU_TRANSLATION_ENABLE);
+
+ tegra_mc_write_32(MC_SMMU_ASID_SECURITY_0, MC_SMMU_ASID_SECURITY);
+
+ tegra_mc_write_32(MC_SMMU_TLB_CONFIG_0, MC_SMMU_TLB_CONFIG_0_RESET_VAL);
+ tegra_mc_write_32(MC_SMMU_PTC_CONFIG_0, MC_SMMU_PTC_CONFIG_0_RESET_VAL);
+
+ /* flush PTC and TLB */
+ tegra_mc_write_32(MC_SMMU_PTC_FLUSH_0, MC_SMMU_PTC_FLUSH_ALL);
+ (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
+ tegra_mc_write_32(MC_SMMU_TLB_FLUSH_0, MC_SMMU_TLB_FLUSH_ALL);
+
+ /* enable SMMU */
+ tegra_mc_write_32(MC_SMMU_CONFIG_0,
+ MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE);
+ (void)tegra_mc_read_32(MC_SMMU_CONFIG_0); /* read to flush writes */
+
+ /* video memory carveout */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
+ (uint32_t)(video_mem_base >> 32));
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)video_mem_base);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size);
+}
+
+/*
+ * Restore Memory Controller settings after "System Suspend"
+ */
+void tegra_memctrl_restore_settings(void)
+{
+ tegra_memctrl_setup();
+}
+
+/*
+ * Secure the BL31 DRAM aperture.
+ *
+ * phys_base = physical base of TZDRAM aperture
+ * size_in_bytes = size of aperture in bytes
+ */
+void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
+{
+ /*
+ * Setup the Memory controller to allow only secure accesses to
+ * the TZDRAM carveout
+ */
+ INFO("Configuring TrustZone DRAM Memory Carveout\n");
+
+ tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base);
+ tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
+}
+
+static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
+ unsigned long long non_overlap_area_size)
+{
+ int ret;
+
+ /*
+ * Map the NS memory first, clean it and then unmap it.
+ */
+ ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
+ non_overlap_area_start, /* VA */
+ non_overlap_area_size, /* size */
+ MT_NS | MT_RW | MT_EXECUTE_NEVER |
+ MT_NON_CACHEABLE); /* attrs */
+ assert(ret == 0);
+
+ zeromem((void *)non_overlap_area_start, non_overlap_area_size);
+ flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
+
+ mmap_remove_dynamic_region(non_overlap_area_start,
+ non_overlap_area_size);
+}
+
+/*
+ * Program the Video Memory carveout region
+ *
+ * phys_base = physical base of aperture
+ * size_in_bytes = size of aperture in bytes
+ */
+void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
+{
+ uintptr_t vmem_end_old = video_mem_base + (video_mem_size << 20);
+ uintptr_t vmem_end_new = phys_base + size_in_bytes;
+ unsigned long long non_overlap_area_size;
+
+ /*
+ * Setup the Memory controller to restrict CPU accesses to the Video
+ * Memory region
+ */
+ INFO("Configuring Video Memory Carveout\n");
+
+ /*
+ * Configure Memory Controller directly for the first time.
+ */
+ if (video_mem_base == 0)
+ goto done;
+
+ /*
+ * Clear the old regions now being exposed. The following cases
+ * can occur -
+ *
+ * 1. clear whole old region (no overlap with new region)
+ * 2. clear old sub-region below new base
+ * 3. clear old sub-region above new end
+ */
+ INFO("Cleaning previous Video Memory Carveout\n");
+
+ if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
+ tegra_clear_videomem(video_mem_base, video_mem_size << 20);
+ } else {
+ if (video_mem_base < phys_base) {
+ non_overlap_area_size = phys_base - video_mem_base;
+ tegra_clear_videomem(video_mem_base, non_overlap_area_size);
+ }
+ if (vmem_end_old > vmem_end_new) {
+ non_overlap_area_size = vmem_end_old - vmem_end_new;
+ tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
+ }
+ }
+
+done:
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, (uint32_t)(phys_base >> 32));
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
+
+ /* store new values */
+ video_mem_base = phys_base;
+ video_mem_size = size_in_bytes >> 20;
+}
+
+/*
+ * During boot, USB3 and flash media (SDMMC/SATA) devices need access to
+ * IRAM. Because these clients connect to the MC and do not have a direct
+ * path to the IRAM, the MC implements AHB redirection during boot to allow
+ * path to IRAM. In this mode, accesses to a programmed memory address aperture
+ * are directed to the AHB bus, allowing access to the IRAM. The AHB aperture
+ * is defined by the IRAM_BASE_LO and IRAM_BASE_HI registers, which are
+ * initialized to disable this aperture.
+ *
+ * Once bootup is complete, we must program IRAM base to 0xffffffff and
+ * IRAM top to 0x00000000, thus disabling access to IRAM. DRAM is then
+ * potentially accessible in this address range. These aperture registers
+ * also have an access_control/lock bit. After disabling the aperture, the
+ * access_control register should be programmed to lock the registers.
+ */
+void tegra_memctrl_disable_ahb_redirection(void)
+{
+ /* program the aperture registers */
+ tegra_mc_write_32(MC_IRAM_BASE_LO, 0xFFFFFFFF);
+ tegra_mc_write_32(MC_IRAM_TOP_LO, 0);
+ tegra_mc_write_32(MC_IRAM_BASE_TOP_HI, 0);
+
+ /* lock the aperture registers */
+ tegra_mc_write_32(MC_IRAM_REG_CTRL, MC_DISABLE_IRAM_CFG_WRITES);
+}
+
+void tegra_memctrl_clear_pending_interrupts(void)
+{
+ uint32_t mcerr;
+
+ /* check if there are any pending interrupts */
+ mcerr = mmio_read_32(TEGRA_MC_BASE + MC_INTSTATUS);
+
+ if (mcerr != (uint32_t)0U) { /* should not see error here */
+ WARN("MC_INTSTATUS = 0x%x (should be zero)\n", mcerr);
+ mmio_write_32((TEGRA_MC_BASE + MC_INTSTATUS), mcerr);
+ }
+}
diff --git a/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c
new file mode 100644
index 0000000..92120b5
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <mce.h>
+#include <memctrl.h>
+#include <memctrl_v2.h>
+#include <smmu.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/* Video Memory base and size (live values) */
+static uint64_t video_mem_base;
+static uint64_t video_mem_size_mb;
+
+/*
+ * Init Memory controller during boot.
+ */
+void tegra_memctrl_setup(void)
+{
+ INFO("Tegra Memory Controller (v2)\n");
+
+ /* Initialize the System memory management unit */
+ tegra_smmu_init();
+
+ /* allow platforms to program custom memory controller settings */
+ plat_memctrl_setup();
+
+ /*
+ * All requests at boot time, and certain requests during
+ * normal run time, are physically addressed and must bypass
+ * the SMMU. The client hub logic implements a hardware bypass
+ * path around the Translation Buffer Units (TBU). During
+ * boot-time, the SMMU_BYPASS_CTRL register (which defaults to
+ * TBU_BYPASS mode) will be used to steer all requests around
+ * the uninitialized TBUs. During normal operation, this register
+ * is locked into TBU_BYPASS_SID config, which routes requests
+ * with special StreamID 0x7f on the bypass path and all others
+ * through the selected TBU. This is done to disable SMMU Bypass
+ * mode, as it could be used to circumvent SMMU security checks.
+ */
+ tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG,
+ MC_SMMU_BYPASS_CONFIG_SETTINGS);
+}
+
+/*
+ * Restore Memory Controller settings after "System Suspend"
+ */
+void tegra_memctrl_restore_settings(void)
+{
+ /* restore platform's memory controller settings */
+ plat_memctrl_restore();
+
+ /* video memory carveout region */
+ if (video_mem_base != 0ULL) {
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO,
+ (uint32_t)video_mem_base);
+ assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO)
+ == (uint32_t)video_mem_base);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
+ (uint32_t)(video_mem_base >> 32));
+ assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI)
+ == (uint32_t)(video_mem_base >> 32));
+ tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB,
+ (uint32_t)video_mem_size_mb);
+ assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB)
+ == (uint32_t)video_mem_size_mb);
+
+ /*
+ * MCE propagates the VideoMem configuration values across the
+ * CCPLEX.
+ */
+ mce_update_gsc_videomem();
+ }
+}
+
+/*
+ * Secure the BL31 DRAM aperture.
+ *
+ * phys_base = physical base of TZDRAM aperture
+ * size_in_bytes = size of aperture in bytes
+ */
+void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
+{
+ /*
+ * Perform platform specific steps.
+ */
+ plat_memctrl_tzdram_setup(phys_base, size_in_bytes);
+}
+
+/*
+ * Secure the BL31 TZRAM aperture.
+ *
+ * phys_base = physical base of TZRAM aperture
+ * size_in_bytes = size of aperture in bytes
+ */
+void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes)
+{
+ ; /* do nothing */
+}
+
+/*
+ * Save MC settings before "System Suspend" to TZDRAM
+ */
+void tegra_mc_save_context(uint64_t mc_ctx_addr)
+{
+ uint32_t i, num_entries = 0;
+ mc_regs_t *mc_ctx_regs;
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint64_t tzdram_base = params_from_bl2->tzdram_base;
+ uint64_t tzdram_end = tzdram_base + params_from_bl2->tzdram_size;
+
+ assert((mc_ctx_addr >= tzdram_base) && (mc_ctx_addr <= tzdram_end));
+
+ /* get MC context table */
+ mc_ctx_regs = plat_memctrl_get_sys_suspend_ctx();
+ assert(mc_ctx_regs != NULL);
+
+ /*
+ * mc_ctx_regs[0].val contains the size of the context table minus
+ * the last entry. Sanity check the table size before we start with
+ * the context save operation.
+ */
+ while (mc_ctx_regs[num_entries].reg != 0xFFFFFFFFU) {
+ num_entries++;
+ }
+
+ /* panic if the sizes do not match */
+ if (num_entries != mc_ctx_regs[0].val) {
+ ERROR("MC context size mismatch!");
+ panic();
+ }
+
+ /* save MC register values */
+ for (i = 1U; i < num_entries; i++) {
+ mc_ctx_regs[i].val = mmio_read_32(mc_ctx_regs[i].reg);
+ }
+
+ /* increment by 1 to take care of the last entry */
+ num_entries++;
+
+ /* Save MC config settings */
+ (void)memcpy((void *)mc_ctx_addr, mc_ctx_regs,
+ sizeof(mc_regs_t) * num_entries);
+
+ /* save the MC table address */
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO,
+ (uint32_t)mc_ctx_addr);
+ assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_LO)
+ == (uint32_t)mc_ctx_addr);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI,
+ (uint32_t)(mc_ctx_addr >> 32));
+ assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_MC_TABLE_ADDR_HI)
+ == (uint32_t)(mc_ctx_addr >> 32));
+}
+
+static void tegra_lock_videomem_nonoverlap(uint64_t phys_base,
+ uint64_t size_in_bytes)
+{
+ uint32_t index;
+ uint64_t total_128kb_blocks = size_in_bytes >> 17;
+ uint64_t residual_4kb_blocks = (size_in_bytes & (uint32_t)0x1FFFF) >> 12;
+ uint64_t val;
+
+ /*
+ * Reset the access configuration registers to restrict access to
+ * old Videomem aperture
+ */
+ for (index = MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0;
+ index < ((uint32_t)MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 + (uint32_t)MC_GSC_CONFIG_REGS_SIZE);
+ index += 4U) {
+ tegra_mc_write_32(index, 0);
+ }
+
+ /*
+ * Set the base. It must be 4k aligned, at least.
+ */
+ assert((phys_base & (uint64_t)0xFFF) == 0U);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, (uint32_t)phys_base);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI,
+ (uint32_t)(phys_base >> 32) & (uint32_t)MC_GSC_BASE_HI_MASK);
+
+ /*
+ * Set the aperture size
+ *
+ * total size = (number of 128KB blocks) + (number of remaining 4KB
+ * blocks)
+ *
+ */
+ val = (uint32_t)((residual_4kb_blocks << MC_GSC_SIZE_RANGE_4KB_SHIFT) |
+ total_128kb_blocks);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, (uint32_t)val);
+
+ /*
+ * Lock the configuration settings by enabling TZ-only lock and
+ * locking the configuration against any future changes from NS
+ * world.
+ */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_CFG,
+ (uint32_t)MC_GSC_ENABLE_TZ_LOCK_BIT);
+
+ /*
+ * MCE propagates the GSC configuration values across the
+ * CCPLEX.
+ */
+}
+
+static void tegra_unlock_videomem_nonoverlap(void)
+{
+ /* Clear the base */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_LO, 0);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_BASE_HI, 0);
+
+ /* Clear the size */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_CLEAR_SIZE, 0);
+}
+
+static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
+ unsigned long long non_overlap_area_size)
+{
+ int ret;
+
+ INFO("Cleaning previous Video Memory Carveout\n");
+
+ /*
+ * Map the NS memory first, clean it and then unmap it.
+ */
+ ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
+ non_overlap_area_start, /* VA */
+ non_overlap_area_size, /* size */
+ MT_DEVICE | MT_RW | MT_NS); /* attrs */
+ assert(ret == 0);
+
+ zeromem((void *)non_overlap_area_start, non_overlap_area_size);
+ flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
+
+ ret = mmap_remove_dynamic_region(non_overlap_area_start,
+ non_overlap_area_size);
+ assert(ret == 0);
+}
+
+static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base,
+ unsigned long size_in_bytes)
+{
+ uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20);
+ uintptr_t vmem_end_new = phys_base + size_in_bytes;
+ unsigned long long non_overlap_area_size;
+
+ /*
+ * Clear the old regions now being exposed. The following cases
+ * can occur -
+ *
+ * 1. clear whole old region (no overlap with new region)
+ * 2. clear old sub-region below new base
+ * 3. clear old sub-region above new end
+ */
+ if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) {
+ tegra_clear_videomem(video_mem_base,
+ video_mem_size_mb << 20U);
+ } else {
+ if (video_mem_base < phys_base) {
+ non_overlap_area_size = phys_base - video_mem_base;
+ tegra_clear_videomem(video_mem_base, non_overlap_area_size);
+ }
+ if (vmem_end_old > vmem_end_new) {
+ non_overlap_area_size = vmem_end_old - vmem_end_new;
+ tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
+ }
+ }
+}
+
+/*
+ * Program the Video Memory carveout region
+ *
+ * phys_base = physical base of aperture
+ * size_in_bytes = size of aperture in bytes
+ */
+void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
+{
+ /*
+ * Setup the Memory controller to restrict CPU accesses to the Video
+ * Memory region
+ */
+
+ INFO("Configuring Video Memory Carveout\n");
+
+ if (video_mem_base != 0U) {
+ /*
+ * Lock the non overlapping memory being cleared so that
+ * other masters do not accidently write to it. The memory
+ * would be unlocked once the non overlapping region is
+ * cleared and the new memory settings take effect.
+ */
+ tegra_lock_videomem_nonoverlap(video_mem_base,
+ video_mem_size_mb << 20);
+ }
+
+ /* program the Videomem aperture */
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
+ tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
+ (uint32_t)(phys_base >> 32));
+ tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
+
+ /* Redundancy check for Video Protect setting */
+ assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_LO)
+ == (uint32_t)phys_base);
+ assert(tegra_mc_read_32(MC_VIDEO_PROTECT_BASE_HI)
+ == (uint32_t)(phys_base >> 32));
+ assert(tegra_mc_read_32(MC_VIDEO_PROTECT_SIZE_MB)
+ == (size_in_bytes >> 20));
+
+ /*
+ * MCE propagates the VideoMem configuration values across the
+ * CCPLEX.
+ */
+ (void)mce_update_gsc_videomem();
+
+ /* Clear the non-overlapping memory */
+ if (video_mem_base != 0U) {
+ tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes);
+ tegra_unlock_videomem_nonoverlap();
+ }
+
+ /* store new values */
+ video_mem_base = phys_base;
+ video_mem_size_mb = (uint64_t)size_in_bytes >> 20;
+}
+
+/*
+ * This feature exists only for v1 of the Tegra Memory Controller.
+ */
+void tegra_memctrl_disable_ahb_redirection(void)
+{
+ ; /* do nothing */
+}
+
+void tegra_memctrl_clear_pending_interrupts(void)
+{
+ ; /* do nothing */
+}
diff --git a/plat/nvidia/tegra/drivers/pmc/pmc.c b/plat/nvidia/tegra/drivers/pmc/pmc.c
new file mode 100644
index 0000000..6c5a73b
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/pmc/pmc.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <pmc.h>
+#include <tegra_def.h>
+
+#define RESET_ENABLE 0x10U
+
+/* Module IDs used during power ungate procedure */
+static const uint32_t pmc_cpu_powergate_id[4] = {
+ 14, /* CPU 0 */
+ 9, /* CPU 1 */
+ 10, /* CPU 2 */
+ 11 /* CPU 3 */
+};
+
+/*******************************************************************************
+ * Power ungate CPU to start the boot process. CPU reset vectors must be
+ * populated before calling this function.
+ ******************************************************************************/
+void tegra_pmc_cpu_on(int32_t cpu)
+{
+ uint32_t val;
+
+ /*
+ * Check if CPU is already power ungated
+ */
+ val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
+ if ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U) {
+ /*
+ * The PMC deasserts the START bit when it starts the power
+ * ungate process. Loop till no power toggle is in progress.
+ */
+ do {
+ val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
+ } while ((val & PMC_TOGGLE_START) != 0U);
+
+ /*
+ * Start the power ungate procedure
+ */
+ val = pmc_cpu_powergate_id[cpu] | PMC_TOGGLE_START;
+ tegra_pmc_write_32(PMC_PWRGATE_TOGGLE, val);
+
+ /*
+ * The PMC deasserts the START bit when it starts the power
+ * ungate process. Loop till powergate START bit is asserted.
+ */
+ do {
+ val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
+ } while ((val & (1U << 8)) != 0U);
+
+ /* loop till the CPU is power ungated */
+ do {
+ val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
+ } while ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U);
+ }
+}
+
+/*******************************************************************************
+ * Setup CPU vectors for resume from deep sleep
+ ******************************************************************************/
+void tegra_pmc_cpu_setup(uint64_t reset_addr)
+{
+ uint32_t val;
+
+ tegra_pmc_write_32(PMC_SECURE_SCRATCH34,
+ ((uint32_t)reset_addr & 0xFFFFFFFFU) | 1U);
+ val = (uint32_t)(reset_addr >> 32U);
+ tegra_pmc_write_32(PMC_SECURE_SCRATCH35, val & 0x7FFU);
+}
+
+/*******************************************************************************
+ * Lock CPU vectors to restrict further writes
+ ******************************************************************************/
+void tegra_pmc_lock_cpu_vectors(void)
+{
+ uint32_t val;
+
+ /* lock PMC_SECURE_SCRATCH22 */
+ val = tegra_pmc_read_32(PMC_SECURE_DISABLE2);
+ val |= PMC_SECURE_DISABLE2_WRITE22_ON;
+ tegra_pmc_write_32(PMC_SECURE_DISABLE2, val);
+
+ /* lock PMC_SECURE_SCRATCH34/35 */
+ val = tegra_pmc_read_32(PMC_SECURE_DISABLE3);
+ val |= (PMC_SECURE_DISABLE3_WRITE34_ON |
+ PMC_SECURE_DISABLE3_WRITE35_ON);
+ tegra_pmc_write_32(PMC_SECURE_DISABLE3, val);
+}
+
+/*******************************************************************************
+ * Find out if this is the last standing CPU
+ ******************************************************************************/
+bool tegra_pmc_is_last_on_cpu(void)
+{
+ int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
+ uint32_t val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);;
+ bool status = true;
+
+ /* check if this is the last standing CPU */
+ for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) {
+
+ /* skip the current CPU */
+ if (i == cpu)
+ continue;
+
+ /* are other CPUs already power gated? */
+ if ((val & ((uint32_t)1 << pmc_cpu_powergate_id[i])) != 0U) {
+ status = false;
+ }
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+ * Handler to be called on exiting System suspend. Right now only DPD registers
+ * are cleared.
+ ******************************************************************************/
+void tegra_pmc_resume(void)
+{
+
+ /* Clear DPD sample */
+ mmio_write_32((TEGRA_PMC_BASE + PMC_IO_DPD_SAMPLE), 0x0);
+
+ /* Clear DPD Enable */
+ mmio_write_32((TEGRA_PMC_BASE + PMC_DPD_ENABLE_0), 0x0);
+}
+
+/*******************************************************************************
+ * Restart the system
+ ******************************************************************************/
+__dead2 void tegra_pmc_system_reset(void)
+{
+ uint32_t reg;
+
+ reg = tegra_pmc_read_32(PMC_CONFIG);
+ reg |= RESET_ENABLE; /* restart */
+ tegra_pmc_write_32(PMC_CONFIG, reg);
+ wfi();
+
+ ERROR("Tegra System Reset: operation not handled.\n");
+ panic();
+}
diff --git a/plat/nvidia/tegra/drivers/smmu/smmu.c b/plat/nvidia/tegra/drivers/smmu/smmu.c
new file mode 100644
index 0000000..4189b00
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/smmu/smmu.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+
+#include <smmu.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+extern void memcpy16(void *dest, const void *src, unsigned int length);
+
+#define SMMU_NUM_CONTEXTS 64U
+#define SMMU_CONTEXT_BANK_MAX_IDX 64U
+
+#define MISMATCH_DETECTED 0x55AA55AAU
+
+/*
+ * Init SMMU during boot or "System Suspend" exit
+ */
+void tegra_smmu_init(void)
+{
+ uint32_t val, cb_idx, smmu_id, ctx_base;
+ uint32_t num_smmu_devices = plat_get_num_smmu_devices();
+
+ for (smmu_id = 0U; smmu_id < num_smmu_devices; smmu_id++) {
+ /* Program the SMMU pagesize and reset CACHE_LOCK bit */
+ val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
+ val |= SMMU_GSR0_PGSIZE_64K;
+ val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
+
+ /* reset CACHE LOCK bit for NS Aux. Config. Register */
+ val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
+ val &= (uint32_t)~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
+
+ /* disable TCU prefetch for all contexts */
+ ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS)
+ + SMMU_CBn_ACTLR;
+ for (cb_idx = 0U; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
+ val = tegra_smmu_read_32(smmu_id,
+ ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
+ val &= (uint32_t)~SMMU_CBn_ACTLR_CPRE_BIT;
+ tegra_smmu_write_32(smmu_id, ctx_base +
+ (SMMU_GSR0_PGSIZE_64K * cb_idx), val);
+ }
+
+ /* set CACHE LOCK bit for NS Aux. Config. Register */
+ val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
+ val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ tegra_smmu_write_32(smmu_id, SMMU_GNSR_ACR, val);
+
+ /* set CACHE LOCK bit for S Aux. Config. Register */
+ val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
+ val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
+ }
+}
+
+/*
+ * Verify SMMU settings have not been altered during boot
+ */
+void tegra_smmu_verify(void)
+{
+ uint32_t cb_idx, ctx_base, smmu_id, val;
+ uint32_t num_smmu_devices = plat_get_num_smmu_devices();
+ uint32_t mismatch = 0U;
+
+ for (smmu_id = 0U; smmu_id < num_smmu_devices; smmu_id++) {
+ /* check PGSIZE_64K bit inr S Aux. Config. Register */
+ val = tegra_smmu_read_32(smmu_id, SMMU_GSR0_SECURE_ACR);
+ if (0U == (val & SMMU_GSR0_PGSIZE_64K)) {
+ ERROR("%s: PGSIZE_64K Mismatch - smmu_id=%d, GSR0_SECURE_ACR=%x\n",
+ __func__, smmu_id, val);
+ mismatch = MISMATCH_DETECTED;
+ }
+
+ /* check CACHE LOCK bit in S Aux. Config. Register */
+ if (0U == (val & SMMU_ACR_CACHE_LOCK_ENABLE_BIT)) {
+ ERROR("%s: CACHE_LOCK Mismatch - smmu_id=%d, GSR0_SECURE_ACR=%x\n",
+ __func__, smmu_id, val);
+ mismatch = MISMATCH_DETECTED;
+ }
+
+ /* check CACHE LOCK bit in NS Aux. Config. Register */
+ val = tegra_smmu_read_32(smmu_id, SMMU_GNSR_ACR);
+ if (0U == (val & SMMU_ACR_CACHE_LOCK_ENABLE_BIT)) {
+ ERROR("%s: Mismatch - smmu_id=%d, GNSR_ACR=%x\n",
+ __func__, smmu_id, val);
+ mismatch = MISMATCH_DETECTED;
+ }
+
+ /* verify TCU prefetch for all contexts is disabled */
+ ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS) +
+ SMMU_CBn_ACTLR;
+ for (cb_idx = 0U; cb_idx < SMMU_CONTEXT_BANK_MAX_IDX; cb_idx++) {
+ val = tegra_smmu_read_32(smmu_id,
+ ctx_base + (SMMU_GSR0_PGSIZE_64K * cb_idx));
+ if (0U != (val & SMMU_CBn_ACTLR_CPRE_BIT)) {
+ ERROR("%s: Mismatch - smmu_id=%d, cb_idx=%d, GSR0_PGSIZE_64K=%x\n",
+ __func__, smmu_id, cb_idx, val);
+ mismatch = MISMATCH_DETECTED;
+ }
+ }
+ }
+
+ /* Treat configuration mismatch as fatal */
+ if ((mismatch == MISMATCH_DETECTED) && tegra_platform_is_silicon()) {
+ panic();
+ }
+}
diff --git a/plat/nvidia/tegra/drivers/spe/shared_console.S b/plat/nvidia/tegra/drivers/spe/shared_console.S
new file mode 100644
index 0000000..d1b18dd
--- /dev/null
+++ b/plat/nvidia/tegra/drivers/spe/shared_console.S
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <console_macros.S>
+
+#define CONSOLE_NUM_BYTES_SHIFT 24
+#define CONSOLE_FLUSH_DATA_TO_PORT (1 << 26)
+#define CONSOLE_RING_DOORBELL (1 << 31)
+#define CONSOLE_IS_BUSY (1 << 31)
+#define CONSOLE_TIMEOUT 0xC000 /* 50 ms */
+
+ /*
+ * This file contains a driver implementation to make use of the
+ * real console implementation provided by the SPE firmware running
+ * SoCs after Tegra186.
+ *
+ * This console is shared by multiple components and the SPE firmware
+ * finally displays everything on the UART port.
+ */
+
+ .globl console_spe_core_init
+ .globl console_spe_core_putc
+ .globl console_spe_core_getc
+ .globl console_spe_core_flush
+ .globl console_spe_putc
+ .globl console_spe_getc
+ .globl console_spe_flush
+ .globl console_spe_register
+
+.macro check_if_console_is_ready base, tmp1, tmp2, label
+ /* wait until spe is ready or timeout expires */
+ mrs \tmp2, cntps_tval_el1
+1: ldr \tmp1, [\base]
+ and \tmp1, \tmp1, #CONSOLE_IS_BUSY
+ cbz \tmp1, 2f
+ mrs \tmp1, cntps_tval_el1
+ sub \tmp1, \tmp2, \tmp1
+ cmp \tmp1, #CONSOLE_TIMEOUT
+ b.lt 1b
+ b \label
+2:
+.endm
+
+ /* -------------------------------------------------
+ * int console_spe_register(uintptr_t baseaddr,
+ * uint32_t clock, uint32_t baud,
+ * console_t *console);
+ * Function to initialize and register a new spe
+ * console. Storage passed in for the console struct
+ * *must* be persistent (i.e. not from the stack).
+ * In: x0 - UART register base address
+ * w1 - UART clock in Hz
+ * w2 - Baud rate
+ * x3 - pointer to empty console_t struct
+ * Out: return 1 on success, 0 on error
+ * Clobber list : x0, x1, x2, x6, x7, x14
+ * -------------------------------------------------
+ */
+func console_spe_register
+ /* Check the input base address */
+ cbz x0, register_fail
+
+ /* Dont use clock or baud rate, so ok to overwrite them */
+ check_if_console_is_ready x0, x1, x2, register_fail
+
+ cbz x3, register_fail
+ str x0, [x3, #CONSOLE_T_BASE]
+ mov x0, x3
+ finish_console_register spe putc=1, getc=1, flush=1
+
+register_fail:
+ mov w0, wzr
+ ret
+endfunc console_spe_register
+
+ /* --------------------------------------------------------
+ * int console_spe_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, x3
+ * --------------------------------------------------------
+ */
+func console_spe_core_putc
+ /* Check the input parameter */
+ cbz x1, putc_error
+
+ /* Prepend '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne not_eol
+
+ check_if_console_is_ready x1, x2, x3, putc_error
+
+ /* spe is ready */
+ mov w2, #0xD /* '\r' */
+ and w2, w2, #0xFF
+ mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT))
+ orr w2, w2, w3
+ str w2, [x1]
+
+not_eol:
+ check_if_console_is_ready x1, x2, x3, putc_error
+
+ /* spe is ready */
+ mov w2, w0
+ and w2, w2, #0xFF
+ mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT))
+ orr w2, w2, w3
+ str w2, [x1]
+
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+endfunc console_spe_core_putc
+
+ /* --------------------------------------------------------
+ * int console_spe_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_spe_putc
+ ldr x1, [x1, #CONSOLE_T_BASE]
+ b console_spe_core_putc
+endfunc console_spe_putc
+
+ /* ---------------------------------------------
+ * int console_spe_getc(console_t *console)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 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_spe_getc
+ mov w0, #-1
+ ret
+endfunc console_spe_getc
+
+ /* -------------------------------------------------
+ * void console_spe_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 : void.
+ * Clobber list : x0, x1
+ * -------------------------------------------------
+ */
+func console_spe_core_flush
+#if ENABLE_ASSERTIONS
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+ /* flush console */
+ mov w1, #(CONSOLE_RING_DOORBELL | CONSOLE_FLUSH_DATA_TO_PORT)
+ str w1, [x0]
+ ret
+endfunc console_spe_core_flush
+
+ /* ---------------------------------------------
+ * void console_spe_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 : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_spe_flush
+ ldr x0, [x0, #CONSOLE_T_BASE]
+ b console_spe_core_flush
+endfunc console_spe_flush
diff --git a/plat/nvidia/tegra/include/drivers/bpmp.h b/plat/nvidia/tegra/include/drivers/bpmp.h
new file mode 100644
index 0000000..dc3fb6b
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/bpmp.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BPMP_H
+#define BPMP_H
+
+#include <stdint.h>
+
+/* macro to enable clock to the Atomics block */
+#define CAR_ENABLE_ATOMICS (1U << 16)
+
+/* command to get the channel base addresses from bpmp */
+#define ATOMIC_CMD_GET 4U
+
+/* Hardware IRQ # used to signal bpmp of an incoming command */
+#define INT_SHR_SEM_OUTBOX_FULL 6U
+
+/* macros to decode the bpmp's state */
+#define CH_MASK(ch) ((uint32_t)0x3 << ((ch) * 2U))
+#define MA_FREE(ch) ((uint32_t)0x2 << ((ch) * 2U))
+#define MA_ACKD(ch) ((uint32_t)0x3 << ((ch) * 2U))
+
+/* response from bpmp to indicate it has powered up */
+#define SIGN_OF_LIFE 0xAAAAAAAAU
+
+/* flags to indicate bpmp driver's state */
+#define BPMP_NOT_PRESENT 0xF00DBEEFU
+#define BPMP_INIT_COMPLETE 0xBEEFF00DU
+#define BPMP_INIT_PENDING 0xDEADBEEFU
+#define BPMP_SUSPEND_ENTRY 0xF00DCAFEU
+
+/* requests serviced by the bpmp */
+#define MRQ_PING 0
+#define MRQ_QUERY_TAG 1
+#define MRQ_DO_IDLE 2
+#define MRQ_TOLERATE_IDLE 3
+#define MRQ_MODULE_LOAD 4
+#define MRQ_MODULE_UNLOAD 5
+#define MRQ_SWITCH_CLUSTER 6
+#define MRQ_TRACE_MODIFY 7
+#define MRQ_WRITE_TRACE 8
+#define MRQ_THREADED_PING 9
+#define MRQ_CPUIDLE_USAGE 10
+#define MRQ_MODULE_MAIL 11
+#define MRQ_SCX_ENABLE 12
+#define MRQ_BPMPIDLE_USAGE 14
+#define MRQ_HEAP_USAGE 15
+#define MRQ_SCLK_SKIP_SET_RATE 16
+#define MRQ_ENABLE_SUSPEND 17
+#define MRQ_PASR_MASK 18
+#define MRQ_DEBUGFS 19
+#define MRQ_THERMAL 27
+
+/* Tegra PM states as known to BPMP */
+#define TEGRA_PM_CC1 9
+#define TEGRA_PM_CC4 12
+#define TEGRA_PM_CC6 14
+#define TEGRA_PM_CC7 15
+#define TEGRA_PM_SC1 17
+#define TEGRA_PM_SC2 18
+#define TEGRA_PM_SC3 19
+#define TEGRA_PM_SC4 20
+#define TEGRA_PM_SC7 23
+
+/* flag to indicate if entry into a CCx power state is allowed */
+#define BPMP_CCx_ALLOWED 0U
+
+/* number of communication channels to interact with the bpmp */
+#define NR_CHANNELS 4U
+
+/* flag to ask bpmp to acknowledge command packet */
+#define NO_ACK (0U << 0U)
+#define DO_ACK (1U << 0U)
+
+/* size of the command/response data */
+#define MSG_DATA_MAX_SZ 120U
+
+/**
+ * command/response packet to/from the bpmp
+ *
+ * command
+ * -------
+ * code: MRQ_* command
+ * flags: DO_ACK or NO_ACK
+ * data:
+ * [0] = cpu #
+ * [1] = cluster power state (TEGRA_PM_CCx)
+ * [2] = system power state (TEGRA_PM_SCx)
+ *
+ * response
+ * ---------
+ * code: error code
+ * flags: not used
+ * data:
+ * [0-3] = response value
+ */
+typedef struct mb_data {
+ int32_t code;
+ uint32_t flags;
+ uint8_t data[MSG_DATA_MAX_SZ];
+} mb_data_t;
+
+/**
+ * Function to initialise the interface with the bpmp
+ */
+int tegra_bpmp_init(void);
+
+/**
+ * Function to suspend the interface with the bpmp
+ */
+void tegra_bpmp_suspend(void);
+
+/**
+ * Function to resume the interface with the bpmp
+ */
+void tegra_bpmp_resume(void);
+
+/**
+ * Handler to send a MRQ_* command to the bpmp
+ */
+int32_t tegra_bpmp_send_receive_atomic(int mrq, const void *ob_data, int ob_sz,
+ void *ib_data, int ib_sz);
+
+#endif /* BPMP_H */
diff --git a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
new file mode 100644
index 0000000..401a07a
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BPMP_IPC_H
+#define BPMP_IPC_H
+
+#include <lib/utils_def.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+/**
+ * Currently supported reset identifiers
+ */
+#define TEGRA_RESET_ID_XUSB_PADCTL U(114)
+#define TEGRA_RESET_ID_GPCDMA U(70)
+
+/**
+ * Function to initialise the IPC with the bpmp
+ */
+int32_t tegra_bpmp_ipc_init(void);
+
+/**
+ * Handler to reset a module
+ */
+int32_t tegra_bpmp_ipc_reset_module(uint32_t rst_id);
+
+/**
+ * Handler to enable clock to a module. Only SE device is
+ * supported for now.
+ */
+int tegra_bpmp_ipc_enable_clock(uint32_t clk_id);
+
+/**
+ * Handler to disable clock to a module. Only SE device is
+ * supported for now.
+ */
+int tegra_bpmp_ipc_disable_clock(uint32_t clk_id);
+
+#endif /* BPMP_IPC_H */
diff --git a/plat/nvidia/tegra/include/drivers/flowctrl.h b/plat/nvidia/tegra/include/drivers/flowctrl.h
new file mode 100644
index 0000000..e5ab600
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/flowctrl.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FLOWCTRL_H
+#define FLOWCTRL_H
+
+#include <lib/mmio.h>
+
+#include <stdbool.h>
+
+#include <tegra_def.h>
+
+#define FLOWCTRL_HALT_CPU0_EVENTS (0x0U)
+#define FLOWCTRL_WAITEVENT (2U << 29)
+#define FLOWCTRL_WAIT_FOR_INTERRUPT (4U << 29)
+#define FLOWCTRL_JTAG_RESUME (1U << 28)
+#define FLOWCTRL_HALT_SCLK (1U << 27)
+#define FLOWCTRL_HALT_LIC_IRQ (1U << 11)
+#define FLOWCTRL_HALT_LIC_FIQ (1U << 10)
+#define FLOWCTRL_HALT_GIC_IRQ (1U << 9)
+#define FLOWCTRL_HALT_GIC_FIQ (1U << 8)
+#define FLOWCTRL_HALT_BPMP_EVENTS (0x4U)
+#define FLOWCTRL_CPU0_CSR (0x8U)
+#define FLOWCTRL_CSR_HALT_MASK (1U << 22)
+#define FLOWCTRL_CSR_PWR_OFF_STS (1U << 16)
+#define FLOWCTRL_CSR_INTR_FLAG (1U << 15)
+#define FLOWCTRL_CSR_EVENT_FLAG (1U << 14)
+#define FLOWCTRL_CSR_IMMEDIATE_WAKE (1U << 3)
+#define FLOWCTRL_CSR_ENABLE (1U << 0)
+#define FLOWCTRL_HALT_CPU1_EVENTS (0x14U)
+#define FLOWCTRL_CPU1_CSR (0x18U)
+#define FLOW_CTLR_FLOW_DBG_QUAL (0x50U)
+#define FLOWCTRL_FIQ2CCPLEX_ENABLE (1U << 28)
+#define FLOWCTRL_FC_SEQ_INTERCEPT (0x5cU)
+#define INTERCEPT_IRQ_PENDING (0xffU)
+#define INTERCEPT_HVC (U(1) << 21)
+#define INTERCEPT_ENTRY_CC4 (U(1) << 20)
+#define INTERCEPT_ENTRY_PG_NONCPU (U(1) << 19)
+#define INTERCEPT_EXIT_PG_NONCPU (U(1) << 18)
+#define INTERCEPT_ENTRY_RG_CPU (U(1) << 17)
+#define INTERCEPT_EXIT_RG_CPU (U(1) << 16)
+#define INTERCEPT_ENTRY_PG_CORE0 (U(1) << 15)
+#define INTERCEPT_EXIT_PG_CORE0 (U(1) << 14)
+#define INTERCEPT_ENTRY_PG_CORE1 (U(1) << 13)
+#define INTERCEPT_EXIT_PG_CORE1 (U(1) << 12)
+#define INTERCEPT_ENTRY_PG_CORE2 (U(1) << 11)
+#define INTERCEPT_EXIT_PG_CORE2 (U(1) << 10)
+#define INTERCEPT_ENTRY_PG_CORE3 (U(1) << 9)
+#define INTERCEPT_EXIT_PG_CORE3 (U(1) << 8)
+#define INTERRUPT_PENDING_NONCPU (U(1) << 7)
+#define INTERRUPT_PENDING_CRAIL (U(1) << 6)
+#define INTERRUPT_PENDING_CORE0 (U(1) << 5)
+#define INTERRUPT_PENDING_CORE1 (U(1) << 4)
+#define INTERRUPT_PENDING_CORE2 (U(1) << 3)
+#define INTERRUPT_PENDING_CORE3 (U(1) << 2)
+#define CC4_INTERRUPT_PENDING (U(1) << 1)
+#define HVC_INTERRUPT_PENDING (U(1) << 0)
+#define FLOWCTRL_CC4_CORE0_CTRL (0x6cU)
+#define FLOWCTRL_WAIT_WFI_BITMAP (0x100U)
+#define FLOWCTRL_L2_FLUSH_CONTROL (0x94U)
+#define FLOWCTRL_BPMP_CLUSTER_CONTROL (0x98U)
+#define FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK (1U << 2)
+
+#define FLOWCTRL_ENABLE_EXT 12U
+#define FLOWCTRL_ENABLE_EXT_MASK 3U
+#define FLOWCTRL_PG_CPU_NONCPU 0x1U
+#define FLOWCTRL_TURNOFF_CPURAIL 0x2U
+
+static inline uint32_t tegra_fc_read_32(uint32_t off)
+{
+ return mmio_read_32(TEGRA_FLOWCTRL_BASE + off);
+}
+
+static inline void tegra_fc_write_32(uint32_t off, uint32_t val)
+{
+ mmio_write_32(TEGRA_FLOWCTRL_BASE + off, val);
+}
+
+void tegra_fc_bpmp_on(uint32_t entrypoint);
+void tegra_fc_bpmp_off(void);
+void tegra_fc_ccplex_pgexit_lock(void);
+void tegra_fc_ccplex_pgexit_unlock(void);
+void tegra_fc_cluster_idle(uint32_t midr);
+void tegra_fc_cpu_powerdn(uint32_t mpidr);
+void tegra_fc_cluster_powerdn(uint32_t midr);
+void tegra_fc_cpu_on(int cpu);
+void tegra_fc_cpu_off(int cpu);
+void tegra_fc_disable_fiq_to_ccplex_routing(void);
+void tegra_fc_enable_fiq_to_ccplex_routing(void);
+bool tegra_fc_is_ccx_allowed(void);
+void tegra_fc_lock_active_cluster(void);
+void tegra_fc_soc_powerdn(uint32_t midr);
+
+#endif /* FLOWCTRL_H */
diff --git a/plat/nvidia/tegra/include/drivers/gpcdma.h b/plat/nvidia/tegra/include/drivers/gpcdma.h
new file mode 100644
index 0000000..a59df37
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/gpcdma.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPCDMA_H
+#define GPCDMA_H
+
+#include <stdint.h>
+
+void tegra_gpcdma_memcpy(uint64_t dst_addr, uint64_t src_addr,
+ uint32_t num_bytes);
+void tegra_gpcdma_zeromem(uint64_t dst_addr, uint32_t num_bytes);
+
+#endif /* GPCDMA_H */
diff --git a/plat/nvidia/tegra/include/drivers/mce.h b/plat/nvidia/tegra/include/drivers/mce.h
new file mode 100644
index 0000000..5f1bb4f
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/mce.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCE_H
+#define MCE_H
+
+#include <lib/mmio.h>
+
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * MCE commands
+ ******************************************************************************/
+typedef enum mce_cmd {
+ MCE_CMD_ENTER_CSTATE = 0U,
+ MCE_CMD_UPDATE_CSTATE_INFO = 1U,
+ MCE_CMD_UPDATE_CROSSOVER_TIME = 2U,
+ MCE_CMD_READ_CSTATE_STATS = 3U,
+ MCE_CMD_WRITE_CSTATE_STATS = 4U,
+ MCE_CMD_IS_SC7_ALLOWED = 5U,
+ MCE_CMD_ONLINE_CORE = 6U,
+ MCE_CMD_CC3_CTRL = 7U,
+ MCE_CMD_ECHO_DATA = 8U,
+ MCE_CMD_READ_VERSIONS = 9U,
+ MCE_CMD_ENUM_FEATURES = 10U,
+ MCE_CMD_ROC_FLUSH_CACHE_TRBITS = 11U,
+ MCE_CMD_ENUM_READ_MCA = 12U,
+ MCE_CMD_ENUM_WRITE_MCA = 13U,
+ MCE_CMD_ROC_FLUSH_CACHE = 14U,
+ MCE_CMD_ROC_CLEAN_CACHE = 15U,
+ MCE_CMD_ENABLE_LATIC = 16U,
+ MCE_CMD_UNCORE_PERFMON_REQ = 17U,
+ MCE_CMD_MISC_CCPLEX = 18U,
+ MCE_CMD_IS_CCX_ALLOWED = 0xFEU,
+ MCE_CMD_MAX = 0xFFU,
+} mce_cmd_t;
+
+#define MCE_CMD_MASK 0xFFU
+
+/*******************************************************************************
+ * Timeout value used to powerdown a core
+ ******************************************************************************/
+#define MCE_CORE_SLEEP_TIME_INFINITE 0xFFFFFFFFU
+
+/*******************************************************************************
+ * Struct to prepare UPDATE_CSTATE_INFO request
+ ******************************************************************************/
+typedef struct mce_cstate_info {
+ /* cluster cstate value */
+ uint32_t cluster;
+ /* ccplex cstate value */
+ uint32_t ccplex;
+ /* system cstate value */
+ uint32_t system;
+ /* force system state? */
+ uint8_t system_state_force;
+ /* wake mask value */
+ uint32_t wake_mask;
+ /* update the wake mask? */
+ uint8_t update_wake_mask;
+} mce_cstate_info_t;
+
+/* public interfaces */
+int mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1,
+ uint64_t arg2);
+int mce_update_reset_vector(void);
+int mce_update_gsc_videomem(void);
+int mce_update_gsc_tzdram(void);
+__dead2 void mce_enter_ccplex_state(uint32_t state_idx);
+void mce_update_cstate_info(const mce_cstate_info_t *cstate);
+void mce_verify_firmware_version(void);
+
+#endif /* MCE_H */
diff --git a/plat/nvidia/tegra/include/drivers/memctrl.h b/plat/nvidia/tegra/include/drivers/memctrl.h
new file mode 100644
index 0000000..cc85095
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/memctrl.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MEMCTRL_H
+#define MEMCTRL_H
+
+void tegra_memctrl_setup(void);
+void tegra_memctrl_restore_settings(void);
+void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes);
+void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes);
+void tegra_memctrl_disable_ahb_redirection(void);
+void tegra_memctrl_clear_pending_interrupts(void);
+
+#endif /* MEMCTRL_H */
diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v1.h b/plat/nvidia/tegra/include/drivers/memctrl_v1.h
new file mode 100644
index 0000000..8e9f198
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/memctrl_v1.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MEMCTRL_V1_H
+#define MEMCTRL_V1_H
+
+#include <lib/mmio.h>
+
+#include <tegra_def.h>
+
+/* SMMU registers */
+#define MC_SMMU_CONFIG_0 0x10U
+#define MC_SMMU_CONFIG_0_SMMU_ENABLE_DISABLE 0U
+#define MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE 1U
+#define MC_SMMU_TLB_CONFIG_0 0x14U
+#define MC_SMMU_TLB_CONFIG_0_RESET_VAL 0x20000010U
+#define MC_SMMU_PTC_CONFIG_0 0x18U
+#define MC_SMMU_PTC_CONFIG_0_RESET_VAL 0x2000003fU
+#define MC_SMMU_TLB_FLUSH_0 0x30U
+#define TLB_FLUSH_VA_MATCH_ALL 0U
+#define TLB_FLUSH_ASID_MATCH_DISABLE 0U
+#define TLB_FLUSH_ASID_MATCH_SHIFT 31U
+#define MC_SMMU_TLB_FLUSH_ALL \
+ (TLB_FLUSH_VA_MATCH_ALL | \
+ (TLB_FLUSH_ASID_MATCH_DISABLE << TLB_FLUSH_ASID_MATCH_SHIFT))
+#define MC_SMMU_PTC_FLUSH_0 0x34U
+#define MC_SMMU_PTC_FLUSH_ALL 0U
+#define MC_SMMU_ASID_SECURITY_0 0x38U
+#define MC_SMMU_ASID_SECURITY 0U
+#define MC_SMMU_TRANSLATION_ENABLE_0_0 0x228U
+#define MC_SMMU_TRANSLATION_ENABLE_1_0 0x22cU
+#define MC_SMMU_TRANSLATION_ENABLE_2_0 0x230U
+#define MC_SMMU_TRANSLATION_ENABLE_3_0 0x234U
+#define MC_SMMU_TRANSLATION_ENABLE_4_0 0xb98U
+#define MC_SMMU_TRANSLATION_ENABLE (~0)
+
+/* MC IRAM aperture registers */
+#define MC_IRAM_BASE_LO 0x65CU
+#define MC_IRAM_TOP_LO 0x660U
+#define MC_IRAM_BASE_TOP_HI 0x980U
+#define MC_IRAM_REG_CTRL 0x964U
+#define MC_DISABLE_IRAM_CFG_WRITES 1U
+
+static inline uint32_t tegra_mc_read_32(uint32_t off)
+{
+ return mmio_read_32(TEGRA_MC_BASE + off);
+}
+
+static inline void tegra_mc_write_32(uint32_t off, uint32_t val)
+{
+ mmio_write_32(TEGRA_MC_BASE + off, val);
+}
+
+#endif /* MEMCTRL_V1_H */
diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
new file mode 100644
index 0000000..9af3027
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MEMCTRL_V2_H
+#define MEMCTRL_V2_H
+
+#include <arch.h>
+
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * Memory Controller SMMU Bypass config register
+ ******************************************************************************/
+#define MC_SMMU_BYPASS_CONFIG 0x1820U
+#define MC_SMMU_BYPASS_CTRL_MASK 0x3U
+#define MC_SMMU_BYPASS_CTRL_SHIFT 0U
+#define MC_SMMU_CTRL_TBU_BYPASS_ALL (0U << MC_SMMU_BYPASS_CTRL_SHIFT)
+#define MC_SMMU_CTRL_TBU_RSVD (1U << MC_SMMU_BYPASS_CTRL_SHIFT)
+#define MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID (2U << MC_SMMU_BYPASS_CTRL_SHIFT)
+#define MC_SMMU_CTRL_TBU_BYPASS_NONE (3U << MC_SMMU_BYPASS_CTRL_SHIFT)
+#define MC_SMMU_BYPASS_CONFIG_WRITE_ACCESS_BIT (1U << 31)
+#define MC_SMMU_BYPASS_CONFIG_SETTINGS (MC_SMMU_BYPASS_CONFIG_WRITE_ACCESS_BIT | \
+ MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID)
+
+#ifndef __ASSEMBLER__
+
+#include <assert.h>
+
+typedef struct mc_regs {
+ uint32_t reg;
+ uint32_t val;
+} mc_regs_t;
+
+#define mc_smmu_bypass_cfg \
+ { \
+ .reg = TEGRA_MC_BASE + MC_SMMU_BYPASS_CONFIG, \
+ .val = 0x00000000U, \
+ }
+
+#define _START_OF_TABLE_ \
+ { \
+ .reg = 0xCAFE05C7U, \
+ .val = 0x00000000U, \
+ }
+
+#define _END_OF_TABLE_ \
+ { \
+ .reg = 0xFFFFFFFFU, \
+ .val = 0xFFFFFFFFU, \
+ }
+
+#endif /* __ASSEMBLER__ */
+
+#ifndef __ASSEMBLER__
+
+#include <lib/mmio.h>
+
+static inline uint32_t tegra_mc_read_32(uint32_t off)
+{
+ return mmio_read_32(TEGRA_MC_BASE + off);
+}
+
+static inline void tegra_mc_write_32(uint32_t off, uint32_t val)
+{
+ mmio_write_32(TEGRA_MC_BASE + off, val);
+}
+
+#if defined(TEGRA_MC_STREAMID_BASE)
+static inline uint32_t tegra_mc_streamid_read_32(uint32_t off)
+{
+ return mmio_read_32(TEGRA_MC_STREAMID_BASE + off);
+}
+
+static inline void tegra_mc_streamid_write_32(uint32_t off, uint32_t val)
+{
+ mmio_write_32(TEGRA_MC_STREAMID_BASE + off, val);
+ assert(mmio_read_32(TEGRA_MC_STREAMID_BASE + off) == val);
+}
+#endif
+
+void plat_memctrl_setup(void);
+
+void plat_memctrl_restore(void);
+mc_regs_t *plat_memctrl_get_sys_suspend_ctx(void);
+
+/*******************************************************************************
+ * Handler to save MC settings before "System Suspend" to TZDRAM
+ *
+ * Implemented by Tegra common memctrl_v2 driver under common/drivers/memctrl
+ ******************************************************************************/
+void tegra_mc_save_context(uint64_t mc_ctx_addr);
+
+/*******************************************************************************
+ * Handler to program the scratch registers with TZDRAM settings for the
+ * resume firmware.
+ *
+ * Implemented by SoCs under tegra/soc/txxx
+ ******************************************************************************/
+void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* MEMCTRL_V2_H */
diff --git a/plat/nvidia/tegra/include/drivers/pmc.h b/plat/nvidia/tegra/include/drivers/pmc.h
new file mode 100644
index 0000000..8752b84
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/pmc.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMC_H
+#define PMC_H
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <stdbool.h>
+
+#include <tegra_def.h>
+
+#define PMC_CONFIG U(0x0)
+#define PMC_IO_DPD_SAMPLE U(0x20)
+#define PMC_DPD_ENABLE_0 U(0x24)
+#define PMC_PWRGATE_STATUS U(0x38)
+#define PMC_PWRGATE_TOGGLE U(0x30)
+#define PMC_SCRATCH1 U(0x54)
+#define PMC_CRYPTO_OP_0 U(0xf4)
+#define PMC_TOGGLE_START U(0x100)
+#define PMC_SCRATCH31 U(0x118)
+#define PMC_SCRATCH32 U(0x11C)
+#define PMC_SCRATCH33 U(0x120)
+#define PMC_SCRATCH39 U(0x138)
+#define PMC_SCRATCH40 U(0x13C)
+#define PMC_SCRATCH41 U(0x140)
+#define PMC_SCRATCH42 U(0x144)
+#define PMC_SCRATCH43 U(0x22C)
+#define PMC_SCRATCH44 U(0x230)
+#define PMC_SCRATCH45 U(0x234)
+#define PMC_SCRATCH46 U(0x238)
+#define PMC_SCRATCH47 U(0x23C)
+#define PMC_SCRATCH48 U(0x240)
+#define PMC_SCRATCH50 U(0x248)
+#define PMC_SCRATCH51 U(0x24C)
+#define PMC_TSC_MULT_0 U(0x2B4)
+#define PMC_STICKY_BIT U(0x2C0)
+#define PMC_SECURE_DISABLE2 U(0x2C4)
+#define PMC_SECURE_DISABLE2_WRITE22_ON (U(1) << 28)
+#define PMC_FUSE_CONTROL_0 U(0x450)
+#define PMC_SECURE_DISABLE3 U(0x2D8)
+#define PMC_SECURE_DISABLE3_WRITE34_ON (U(1) << 20)
+#define PMC_SECURE_DISABLE3_WRITE35_ON (U(1) << 22)
+#define PMC_SECURE_SCRATCH22 U(0x338)
+#define PMC_SECURE_SCRATCH34 U(0x368)
+#define PMC_SECURE_SCRATCH35 U(0x36c)
+#define PMC_SCRATCH56 U(0x600)
+#define PMC_SCRATCH57 U(0x604)
+#define PMC_SCRATCH201 U(0x844)
+
+static inline uint32_t tegra_pmc_read_32(uint32_t off)
+{
+ return mmio_read_32(TEGRA_PMC_BASE + off);
+}
+
+static inline void tegra_pmc_write_32(uint32_t off, uint32_t val)
+{
+ mmio_write_32(TEGRA_PMC_BASE + off, val);
+}
+
+void tegra_pmc_cpu_on(int32_t cpu);
+void tegra_pmc_cpu_setup(uint64_t reset_addr);
+bool tegra_pmc_is_last_on_cpu(void);
+void tegra_pmc_lock_cpu_vectors(void);
+void tegra_pmc_resume(void);
+__dead2 void tegra_pmc_system_reset(void);
+
+#endif /* PMC_H */
diff --git a/plat/nvidia/tegra/include/drivers/security_engine.h b/plat/nvidia/tegra/include/drivers/security_engine.h
new file mode 100644
index 0000000..5ae6257
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/security_engine.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SECURITY_ENGINE_H
+#define SECURITY_ENGINE_H
+
+/*******************************************************************************
+ * Structure definition
+ ******************************************************************************/
+
+/* Security Engine Linked List */
+struct tegra_se_ll {
+ /* DMA buffer address */
+ uint32_t addr;
+ /* Data length in DMA buffer */
+ uint32_t data_len;
+};
+
+#define SE_LL_MAX_BUFFER_NUM 4
+typedef struct tegra_se_io_lst {
+ volatile uint32_t last_buff_num;
+ volatile struct tegra_se_ll buffer[SE_LL_MAX_BUFFER_NUM];
+} tegra_se_io_lst_t __attribute__((aligned(4)));
+
+/* SE device structure */
+typedef struct tegra_se_dev {
+ /* Security Engine ID */
+ const int se_num;
+ /* SE base address */
+ const uint64_t se_base;
+ /* SE context size in AES blocks */
+ const uint32_t ctx_size_blks;
+ /* pointer to source linked list buffer */
+ tegra_se_io_lst_t *src_ll_buf;
+ /* pointer to destination linked list buffer */
+ tegra_se_io_lst_t *dst_ll_buf;
+ /* LP context buffer pointer */
+ uint32_t *ctx_save_buf;
+} tegra_se_dev_t;
+
+/* PKA1 device structure */
+typedef struct tegra_pka_dev {
+ /* PKA1 base address */
+ uint64_t pka_base;
+} tegra_pka_dev_t;
+
+/*******************************************************************************
+ * Public interface
+ ******************************************************************************/
+void tegra_se_init(void);
+int tegra_se_suspend(void);
+void tegra_se_resume(void);
+int tegra_se_save_tzram(void);
+int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte);
+
+#endif /* SECURITY_ENGINE_H */
diff --git a/plat/nvidia/tegra/include/drivers/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h
new file mode 100644
index 0000000..1de9af6
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/smmu.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SMMU_H
+#define SMMU_H
+
+#include <lib/mmio.h>
+
+#include <memctrl_v2.h>
+#include <tegra_def.h>
+
+#define SMMU_CBn_ACTLR (0x4U)
+
+/*******************************************************************************
+ * SMMU Global Secure Aux. Configuration Register
+ ******************************************************************************/
+#define SMMU_GSR0_SECURE_ACR 0x10U
+#define SMMU_GNSR_ACR (SMMU_GSR0_SECURE_ACR + 0x400U)
+#define SMMU_GSR0_PGSIZE_SHIFT 16U
+#define SMMU_GSR0_PGSIZE_4K (0U << SMMU_GSR0_PGSIZE_SHIFT)
+#define SMMU_GSR0_PGSIZE_64K (1U << SMMU_GSR0_PGSIZE_SHIFT)
+#define SMMU_ACR_CACHE_LOCK_ENABLE_BIT (1ULL << 26U)
+#define SMMU_GSR0_PER (0x20200U)
+
+/*******************************************************************************
+ * SMMU Global Aux. Control Register
+ ******************************************************************************/
+#define SMMU_CBn_ACTLR_CPRE_BIT (1ULL << 1U)
+
+/* SMMU IDs currently supported by the driver */
+enum {
+ TEGRA_SMMU0 = 0U,
+ TEGRA_SMMU1 = 1U,
+ TEGRA_SMMU2 = 2U
+};
+
+static inline uint32_t tegra_smmu_read_32(uint32_t smmu_id, uint32_t off)
+{
+ uint32_t ret = 0U;
+
+#if defined(TEGRA_SMMU0_BASE)
+ if (smmu_id == TEGRA_SMMU0) {
+ ret = mmio_read_32(TEGRA_SMMU0_BASE + (uint64_t)off);
+ }
+#endif
+
+#if defined(TEGRA_SMMU1_BASE)
+ if (smmu_id == TEGRA_SMMU1) {
+ ret = mmio_read_32(TEGRA_SMMU1_BASE + (uint64_t)off);
+ }
+#endif
+
+#if defined(TEGRA_SMMU2_BASE)
+ if (smmu_id == TEGRA_SMMU2) {
+ ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off);
+ }
+#endif
+
+ return ret;
+}
+
+static inline void tegra_smmu_write_32(uint32_t smmu_id,
+ uint32_t off, uint32_t val)
+{
+#if defined(TEGRA_SMMU0_BASE)
+ if (smmu_id == TEGRA_SMMU0) {
+ mmio_write_32(TEGRA_SMMU0_BASE + (uint64_t)off, val);
+ }
+#endif
+
+#if defined(TEGRA_SMMU1_BASE)
+ if (smmu_id == TEGRA_SMMU1) {
+ mmio_write_32(TEGRA_SMMU1_BASE + (uint64_t)off, val);
+ }
+#endif
+
+#if defined(TEGRA_SMMU2_BASE)
+ if (smmu_id == TEGRA_SMMU2) {
+ mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val);
+ }
+#endif
+}
+
+void tegra_smmu_init(void);
+void tegra_smmu_verify(void);
+uint32_t plat_get_num_smmu_devices(void);
+
+#endif /* SMMU_H */
diff --git a/plat/nvidia/tegra/include/drivers/spe.h b/plat/nvidia/tegra/include/drivers/spe.h
new file mode 100644
index 0000000..e0f8714
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/spe.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPE_H
+#define SPE_H
+
+#include <stdint.h>
+
+#include <drivers/console.h>
+
+/*
+ * Initialize a new spe 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.
+ */
+int console_spe_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
+ console_t *console);
+
+#endif /* SPE_H */
diff --git a/plat/nvidia/tegra/include/drivers/tegra_gic.h b/plat/nvidia/tegra/include/drivers/tegra_gic.h
new file mode 100644
index 0000000..6661dff
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/tegra_gic.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA_GIC_H
+#define TEGRA_GIC_H
+
+#include <common/interrupt_props.h>
+
+/*******************************************************************************
+ * Per-CPU struct describing FIQ state to be stored
+ ******************************************************************************/
+typedef struct pcpu_fiq_state {
+ uint64_t elr_el3;
+ uint64_t spsr_el3;
+} pcpu_fiq_state_t;
+
+/*******************************************************************************
+ * Fucntion declarations
+ ******************************************************************************/
+void tegra_gic_cpuif_deactivate(void);
+void tegra_gic_init(void);
+void tegra_gic_pcpu_init(void);
+void tegra_gic_setup(const interrupt_prop_t *interrupt_props,
+ unsigned int interrupt_props_num);
+
+#endif /* TEGRA_GIC_H */
diff --git a/plat/nvidia/tegra/include/lib/profiler.h b/plat/nvidia/tegra/include/lib/profiler.h
new file mode 100644
index 0000000..684c872
--- /dev/null
+++ b/plat/nvidia/tegra/include/lib/profiler.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PROFILER_H
+#define PROFILER_H
+
+/*******************************************************************************
+ * Number of bytes of memory used by the profiler on Tegra
+ ******************************************************************************/
+#define PROFILER_SIZE_BYTES U(0x1000)
+
+void boot_profiler_init(uint64_t shmem_base, uint32_t tmr_base);
+void boot_profiler_add_record(const char *str);
+void boot_profiler_deinit(void);
+
+#endif /* PROFILER_H */
diff --git a/plat/nvidia/tegra/include/plat_macros.S b/plat/nvidia/tegra/include/plat_macros.S
new file mode 100644
index 0000000..2dc3b41
--- /dev/null
+++ b/plat/nvidia/tegra/include/plat_macros.S
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <drivers/arm/gicv2.h>
+#include <tegra_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+/* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31.
+ * ---------------------------------------------
+ */
+.macro plat_crash_print_regs
+#ifdef TEGRA_GICC_BASE
+ mov_imm x16, TEGRA_GICC_BASE
+
+ /* gicc base address is now in x16 */
+ adr x6, gicc_regs /* Load the gicc reg list to x6 */
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x16, #GICC_HPPIR]
+ ldr w9, [x16, #GICC_AHPPIR]
+ ldr w10, [x16, #GICC_CTLR]
+ /* Store to the crash buf and print to cosole */
+ bl str_in_crash_buf_print
+#endif
+ /* Print the GICD_ISPENDR regs */
+ mov_imm x16, TEGRA_GICD_BASE
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+2:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq 1f
+ bl asm_print_hex
+ adr x4, spacer
+ bl asm_print_str
+ ldr w4, [x7], #4
+ bl asm_print_hex
+ adr x4, newline
+ bl asm_print_str
+ b 2b
+1:
+.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/nvidia/tegra/include/platform_def.h b/plat/nvidia/tegra/include/platform_def.h
new file mode 100644
index 0000000..84b3297
--- /dev/null
+++ b/plat/nvidia/tegra/include/platform_def.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * Check and error if SEPARATE_CODE_AND_RODATA is not set to 1
+ ******************************************************************************/
+#if !SEPARATE_CODE_AND_RODATA
+#error "SEPARATE_CODE_AND_RODATA should be set to 1"
+#endif
+
+/*
+ * Platform binary types for linking
+ */
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*
+ * Platform binary types for linking
+ */
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#ifdef IMAGE_BL31
+#define PLATFORM_STACK_SIZE U(0x400)
+#endif
+
+#define TEGRA_PRIMARY_CPU U(0x0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
+ PLATFORM_MAX_CPUS_PER_CLUSTER)
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ PLATFORM_CLUSTER_COUNT + U(1))
+
+/*******************************************************************************
+ * Platform console related constants
+ ******************************************************************************/
+#define TEGRA_CONSOLE_BAUDRATE U(115200)
+#define TEGRA_BOOT_UART_CLK_13_MHZ U(13000000)
+#define TEGRA_BOOT_UART_CLK_408_MHZ U(408000000)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* Size of trusted dram */
+#define TZDRAM_SIZE U(0x00400000)
+#define TZDRAM_END (TZDRAM_BASE + TZDRAM_SIZE)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+#define BL31_BASE TZDRAM_BASE
+#define BL31_LIMIT (TZDRAM_BASE + BL31_SIZE - 1)
+#define BL32_BASE (TZDRAM_BASE + BL31_SIZE)
+#define BL32_LIMIT TZDRAM_END
+
+/*******************************************************************************
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (0x40) /* (U(1) << CACHE_WRITEBACK_SHIFT) */
+
+/*******************************************************************************
+ * Dummy macros to compile io_storage support
+ ******************************************************************************/
+#define MAX_IO_DEVICES U(0)
+#define MAX_IO_HANDLES U(0)
+
+/*******************************************************************************
+ * Platforms macros to support SDEI
+ ******************************************************************************/
+#define TEGRA_SDEI_SGI_PRIVATE U(8)
+
+/*******************************************************************************
+ * Platform macros to support exception handling framework
+ ******************************************************************************/
+#define PLAT_PRI_BITS U(3)
+#define PLAT_RAS_PRI U(0x10)
+#define PLAT_SDEI_CRITICAL_PRI U(0x20)
+#define PLAT_SDEI_NORMAL_PRI U(0x30)
+#define PLAT_TEGRA_WDT_PRIO U(0x40)
+
+#define PLAT_EHF_DESC EHF_PRI_DESC(PLAT_PRI_BITS,\
+ PLAT_TEGRA_WDT_PRIO)
+
+/*******************************************************************************
+ * SDEI events
+ ******************************************************************************/
+/* SDEI dynamic private event numbers */
+#define TEGRA_SDEI_DP_EVENT_0 U(100)
+#define TEGRA_SDEI_DP_EVENT_1 U(101)
+#define TEGRA_SDEI_DP_EVENT_2 U(102)
+
+/* SDEI dynamic shared event numbers */
+#define TEGRA_SDEI_DS_EVENT_0 U(200)
+#define TEGRA_SDEI_DS_EVENT_1 U(201)
+#define TEGRA_SDEI_DS_EVENT_2 U(202)
+
+/* SDEI explicit events */
+#define TEGRA_SDEI_EP_EVENT_0 U(300)
+#define TEGRA_SDEI_EP_EVENT_1 U(301)
+#define TEGRA_SDEI_EP_EVENT_2 U(302)
+#define TEGRA_SDEI_EP_EVENT_3 U(303)
+#define TEGRA_SDEI_EP_EVENT_4 U(304)
+#define TEGRA_SDEI_EP_EVENT_5 U(305)
+#define TEGRA_SDEI_EP_EVENT_6 U(306)
+#define TEGRA_SDEI_EP_EVENT_7 U(307)
+#define TEGRA_SDEI_EP_EVENT_8 U(308)
+#define TEGRA_SDEI_EP_EVENT_9 U(309)
+#define TEGRA_SDEI_EP_EVENT_10 U(310)
+#define TEGRA_SDEI_EP_EVENT_11 U(311)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra186_private.h b/plat/nvidia/tegra/include/t186/tegra186_private.h
new file mode 100644
index 0000000..4514e14
--- /dev/null
+++ b/plat/nvidia/tegra/include/t186/tegra186_private.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA186_PRIVATE_H
+#define TEGRA186_PRIVATE_H
+
+uint64_t tegra186_get_mc_ctx_size(void);
+
+#endif /* TEGRA186_PRIVATE_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
new file mode 100644
index 0000000..a971cec
--- /dev/null
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA_DEF_H
+#define TEGRA_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * Platform BL31 specific defines.
+ ******************************************************************************/
+#define BL31_SIZE U(0x40000)
+
+/*******************************************************************************
+ * MCE apertures used by the ARI interface
+ *
+ * Aperture 0 - Cpu0 (ARM Cortex A-57)
+ * Aperture 1 - Cpu1 (ARM Cortex A-57)
+ * Aperture 2 - Cpu2 (ARM Cortex A-57)
+ * Aperture 3 - Cpu3 (ARM Cortex A-57)
+ * Aperture 4 - Cpu4 (Denver15)
+ * Aperture 5 - Cpu5 (Denver15)
+ ******************************************************************************/
+#define MCE_ARI_APERTURE_0_OFFSET U(0x0)
+#define MCE_ARI_APERTURE_1_OFFSET U(0x10000)
+#define MCE_ARI_APERTURE_2_OFFSET U(0x20000)
+#define MCE_ARI_APERTURE_3_OFFSET U(0x30000)
+#define MCE_ARI_APERTURE_4_OFFSET U(0x40000)
+#define MCE_ARI_APERTURE_5_OFFSET U(0x50000)
+#define MCE_ARI_APERTURE_OFFSET_MAX MCE_APERTURE_5_OFFSET
+
+/* number of apertures */
+#define MCE_ARI_APERTURES_MAX U(6)
+
+/* each ARI aperture is 64KB */
+#define MCE_ARI_APERTURE_SIZE U(0x10000)
+
+/*******************************************************************************
+ * CPU core id macros for the MCE_ONLINE_CORE ARI
+ ******************************************************************************/
+#define MCE_CORE_ID_MAX U(8)
+#define MCE_CORE_ID_MASK U(0x7)
+
+/*******************************************************************************
+ * These values are used by the PSCI implementation during the `CPU_SUSPEND`
+ * and `SYSTEM_SUSPEND` calls as the `state-id` field in the 'power state'
+ * parameter.
+ ******************************************************************************/
+#define PSTATE_ID_CORE_IDLE U(6)
+#define PSTATE_ID_CORE_POWERDN U(7)
+#define PSTATE_ID_SOC_POWERDN U(2)
+
+/*******************************************************************************
+ * Platform power states (used by PSCI framework)
+ *
+ * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID
+ * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID
+ ******************************************************************************/
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(8)
+
+/*******************************************************************************
+ * Chip specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35)
+
+/*******************************************************************************
+ * Secure IRQ definitions
+ ******************************************************************************/
+#define TEGRA186_TOP_WDT_IRQ U(49)
+#define TEGRA186_AON_WDT_IRQ U(50)
+
+#define TEGRA186_SEC_IRQ_TARGET_MASK U(0xF3) /* 4 A57 - 2 Denver */
+
+/*******************************************************************************
+ * Clock identifier for the SE device
+ ******************************************************************************/
+#define TEGRA186_CLK_SE U(103)
+#define TEGRA_CLK_SE TEGRA186_CLK_SE
+
+/*******************************************************************************
+ * Tegra Miscellanous register constants
+ ******************************************************************************/
+#define TEGRA_MISC_BASE U(0x00100000)
+#define HARDWARE_REVISION_OFFSET U(0x4)
+
+#define MISCREG_PFCFG U(0x200C)
+
+/*******************************************************************************
+ * Tegra TSA Controller constants
+ ******************************************************************************/
+#define TEGRA_TSA_BASE U(0x02400000)
+
+/*******************************************************************************
+ * TSA configuration registers
+ ******************************************************************************/
+#define TSA_CONFIG_STATIC0_CSW_SESWR U(0x4010)
+#define TSA_CONFIG_STATIC0_CSW_SESWR_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_ETRW U(0x4038)
+#define TSA_CONFIG_STATIC0_CSW_ETRW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_SDMMCWAB U(0x5010)
+#define TSA_CONFIG_STATIC0_CSW_SDMMCWAB_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_AXISW U(0x7008)
+#define TSA_CONFIG_STATIC0_CSW_AXISW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_HDAW U(0xA008)
+#define TSA_CONFIG_STATIC0_CSW_HDAW_RESET U(0x100)
+#define TSA_CONFIG_STATIC0_CSW_AONDMAW U(0xB018)
+#define TSA_CONFIG_STATIC0_CSW_AONDMAW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_SCEDMAW U(0xD018)
+#define TSA_CONFIG_STATIC0_CSW_SCEDMAW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_BPMPDMAW U(0xD028)
+#define TSA_CONFIG_STATIC0_CSW_BPMPDMAW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_APEDMAW U(0x12018)
+#define TSA_CONFIG_STATIC0_CSW_APEDMAW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_UFSHCW U(0x13008)
+#define TSA_CONFIG_STATIC0_CSW_UFSHCW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_AFIW U(0x13018)
+#define TSA_CONFIG_STATIC0_CSW_AFIW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_SATAW U(0x13028)
+#define TSA_CONFIG_STATIC0_CSW_SATAW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_EQOSW U(0x13038)
+#define TSA_CONFIG_STATIC0_CSW_EQOSW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_XUSB_DEVW U(0x15008)
+#define TSA_CONFIG_STATIC0_CSW_XUSB_DEVW_RESET U(0x1100)
+#define TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW U(0x15018)
+#define TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW_RESET U(0x1100)
+
+#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK (ULL(0x3) << 11)
+#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU (ULL(0) << 11)
+
+/*******************************************************************************
+ * Tegra General Purpose Centralised DMA constants
+ ******************************************************************************/
+#define TEGRA_GPCDMA_BASE ULL(0x2610000)
+
+/*******************************************************************************
+ * Tegra Memory Controller constants
+ ******************************************************************************/
+#define TEGRA_MC_STREAMID_BASE U(0x02C00000)
+#define TEGRA_MC_BASE U(0x02C10000)
+
+/* General Security Carveout register macros */
+#define MC_GSC_CONFIG_REGS_SIZE U(0x40)
+#define MC_GSC_LOCK_CFG_SETTINGS_BIT (U(1) << 1)
+#define MC_GSC_ENABLE_TZ_LOCK_BIT (ULL(1) << 0)
+#define MC_GSC_SIZE_RANGE_4KB_SHIFT U(27)
+#define MC_GSC_BASE_LO_SHIFT U(12)
+#define MC_GSC_BASE_LO_MASK U(0xFFFFF)
+#define MC_GSC_BASE_HI_SHIFT U(0)
+#define MC_GSC_BASE_HI_MASK U(3)
+#define MC_GSC_ENABLE_CPU_SECURE_BIT (U(1) << 31)
+
+/* TZDRAM carveout configuration registers */
+#define MC_SECURITY_CFG0_0 U(0x70)
+#define MC_SECURITY_CFG1_0 U(0x74)
+#define MC_SECURITY_CFG3_0 U(0x9BC)
+
+#define MC_SECURITY_BOM_MASK (U(0xFFF) << 20)
+#define MC_SECURITY_SIZE_MB_MASK (U(0x1FFF) << 0)
+#define MC_SECURITY_BOM_HI_MASK (U(0x3) << 0)
+
+/* Video Memory carveout configuration registers */
+#define MC_VIDEO_PROTECT_BASE_HI U(0x978)
+#define MC_VIDEO_PROTECT_BASE_LO U(0x648)
+#define MC_VIDEO_PROTECT_SIZE_MB U(0x64C)
+#define MC_VIDEO_PROTECT_REG_CTRL U(0x650)
+#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED U(3)
+
+/*
+ * Carveout (MC_SECURITY_CARVEOUT24) registers used to clear the
+ * non-overlapping Video memory region
+ */
+#define MC_VIDEO_PROTECT_CLEAR_CFG U(0x25A0)
+#define MC_VIDEO_PROTECT_CLEAR_BASE_LO U(0x25A4)
+#define MC_VIDEO_PROTECT_CLEAR_BASE_HI U(0x25A8)
+#define MC_VIDEO_PROTECT_CLEAR_SIZE U(0x25AC)
+#define MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 U(0x25B0)
+
+/* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */
+#define MC_TZRAM_CARVEOUT_CFG U(0x2190)
+#define MC_TZRAM_BASE_LO U(0x2194)
+#define MC_TZRAM_BASE_HI U(0x2198)
+#define MC_TZRAM_SIZE U(0x219C)
+#define MC_TZRAM_CLIENT_ACCESS0_CFG0 U(0x21A0)
+#define MC_TZRAM_CLIENT_ACCESS1_CFG0 U(0x21A4)
+#define TZRAM_ALLOW_MPCORER (U(1) << 7)
+#define TZRAM_ALLOW_MPCOREW (U(1) << 25)
+
+/*******************************************************************************
+ * Tegra UART Controller constants
+ ******************************************************************************/
+#define TEGRA_UARTA_BASE U(0x03100000)
+#define TEGRA_UARTB_BASE U(0x03110000)
+#define TEGRA_UARTC_BASE U(0x0C280000)
+#define TEGRA_UARTD_BASE U(0x03130000)
+#define TEGRA_UARTE_BASE U(0x03140000)
+#define TEGRA_UARTF_BASE U(0x03150000)
+#define TEGRA_UARTG_BASE U(0x0C290000)
+
+/*******************************************************************************
+ * Tegra Fuse Controller related constants
+ ******************************************************************************/
+#define TEGRA_FUSE_BASE U(0x03820000)
+#define OPT_SUBREVISION U(0x248)
+#define SUBREVISION_MASK U(0xFF)
+
+/*******************************************************************************
+ * GICv2 & interrupt handling related constants
+ ******************************************************************************/
+#define TEGRA_GICD_BASE U(0x03881000)
+#define TEGRA_GICC_BASE U(0x03882000)
+
+/*******************************************************************************
+ * Security Engine related constants
+ ******************************************************************************/
+#define TEGRA_SE0_BASE U(0x03AC0000)
+#define SE_MUTEX_WATCHDOG_NS_LIMIT U(0x6C)
+#define TEGRA_PKA1_BASE U(0x03AD0000)
+#define PKA_MUTEX_WATCHDOG_NS_LIMIT U(0x8144)
+#define TEGRA_RNG1_BASE U(0x03AE0000)
+#define RNG_MUTEX_WATCHDOG_NS_LIMIT U(0xFE0)
+
+/*******************************************************************************
+ * Tegra HSP doorbell #0 constants
+ ******************************************************************************/
+#define TEGRA_HSP_DBELL_BASE U(0x03C90000)
+#define HSP_DBELL_1_ENABLE U(0x104)
+#define HSP_DBELL_3_TRIGGER U(0x300)
+#define HSP_DBELL_3_ENABLE U(0x304)
+
+/*******************************************************************************
+ * Tegra Clock and Reset Controller constants
+ ******************************************************************************/
+#define TEGRA_CAR_RESET_BASE U(0x05000000)
+#define TEGRA_GPU_RESET_REG_OFFSET U(0x30)
+#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x34)
+#define GPU_RESET_BIT (U(1) << 0)
+#define GPU_SET_BIT (U(1) << 0)
+#define TEGRA_GPCDMA_RST_SET_REG_OFFSET U(0x6A0004)
+#define TEGRA_GPCDMA_RST_CLR_REG_OFFSET U(0x6A0008)
+
+/*******************************************************************************
+ * Tegra micro-seconds timer constants
+ ******************************************************************************/
+#define TEGRA_TMRUS_BASE U(0x0C2E0000)
+#define TEGRA_TMRUS_SIZE U(0x1000)
+
+/*******************************************************************************
+ * Tegra Power Mgmt Controller constants
+ ******************************************************************************/
+#define TEGRA_PMC_BASE U(0x0C360000)
+
+/*******************************************************************************
+ * Tegra scratch registers constants
+ ******************************************************************************/
+#define TEGRA_SCRATCH_BASE U(0x0C390000)
+#define SECURE_SCRATCH_RSV0_HI U(0x654)
+#define SECURE_SCRATCH_RSV1_LO U(0x658)
+#define SECURE_SCRATCH_RSV1_HI U(0x65C)
+#define SECURE_SCRATCH_RSV6 U(0x680)
+#define SECURE_SCRATCH_RSV11_LO U(0x6A8)
+#define SECURE_SCRATCH_RSV11_HI U(0x6AC)
+#define SECURE_SCRATCH_RSV53_LO U(0x7F8)
+#define SECURE_SCRATCH_RSV53_HI U(0x7FC)
+#define SECURE_SCRATCH_RSV55_LO U(0x808)
+#define SECURE_SCRATCH_RSV55_HI U(0x80C)
+#define SECURE_SCRATCH_RSV63_LO U(0x848)
+#define SECURE_SCRATCH_RSV63_HI U(0x84C)
+#define SECURE_SCRATCH_RSV64_LO U(0x850)
+#define SECURE_SCRATCH_RSV64_HI U(0x854)
+#define SECURE_SCRATCH_RSV65_LO U(0x858)
+#define SECURE_SCRATCH_RSV65_HI U(0x85c)
+#define SECURE_SCRATCH_RSV66_LO U(0x860)
+#define SECURE_SCRATCH_RSV66_HI U(0x864)
+#define SECURE_SCRATCH_RSV68_LO U(0x870)
+
+#define SCRATCH_RESET_VECTOR_LO SECURE_SCRATCH_RSV1_LO
+#define SCRATCH_RESET_VECTOR_HI SECURE_SCRATCH_RSV1_HI
+#define SCRATCH_SECURE_BOOTP_FCFG SECURE_SCRATCH_RSV6
+#define SCRATCH_MC_TABLE_ADDR_LO SECURE_SCRATCH_RSV11_LO
+#define SCRATCH_MC_TABLE_ADDR_HI SECURE_SCRATCH_RSV11_HI
+#define SCRATCH_BL31_PARAMS_ADDR SECURE_SCRATCH_RSV53_LO
+#define SCRATCH_BL31_PLAT_PARAMS_ADDR SECURE_SCRATCH_RSV53_HI
+#define SCRATCH_TZDRAM_ADDR_LO SECURE_SCRATCH_RSV55_LO
+#define SCRATCH_TZDRAM_ADDR_HI SECURE_SCRATCH_RSV55_HI
+
+/*******************************************************************************
+ * Tegra Memory Mapped Control Register Access constants
+ ******************************************************************************/
+#define TEGRA_MMCRAB_BASE U(0x0E000000)
+
+/*******************************************************************************
+ * Tegra Memory Mapped Activity Monitor Register Access constants
+ ******************************************************************************/
+#define TEGRA_ARM_ACTMON_CTR_BASE U(0x0E060000)
+#define TEGRA_DENVER_ACTMON_CTR_BASE U(0x0E070000)
+
+/*******************************************************************************
+ * Tegra SMMU Controller constants
+ ******************************************************************************/
+#define TEGRA_SMMU0_BASE U(0x12000000)
+
+/*******************************************************************************
+ * Tegra TZRAM constants
+ ******************************************************************************/
+#define TEGRA_TZRAM_BASE U(0x30000000)
+#define TEGRA_TZRAM_SIZE U(0x40000)
+
+/*******************************************************************************
+ * Tegra CCPLEX-BPMP IPC constants
+ ******************************************************************************/
+#define TEGRA_BPMP_IPC_TX_PHYS_BASE U(0x3004C000)
+#define TEGRA_BPMP_IPC_RX_PHYS_BASE U(0x3004D000)
+#define TEGRA_BPMP_IPC_CH_MAP_SIZE U(0x1000) /* 4KB */
+
+/*******************************************************************************
+ * Tegra DRAM memory base address
+ ******************************************************************************/
+#define TEGRA_DRAM_BASE ULL(0x80000000)
+#define TEGRA_DRAM_END ULL(0x27FFFFFFF)
+
+#endif /* TEGRA_DEF_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra_mc_def.h b/plat/nvidia/tegra/include/t186/tegra_mc_def.h
new file mode 100644
index 0000000..fa44772
--- /dev/null
+++ b/plat/nvidia/tegra/include/t186/tegra_mc_def.h
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA_MC_DEF_H
+#define TEGRA_MC_DEF_H
+
+/*******************************************************************************
+ * Memory Controller's PCFIFO client configuration registers
+ ******************************************************************************/
+#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0U
+
+#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4U
+#define MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL 0x20000U
+#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_UNORDERED (0U << 17)
+#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_MASK (1U << 17)
+#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_UNORDERED (0U << 21)
+#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_MASK (1U << 21)
+#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_UNORDERED (0U << 29)
+#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_MASK (1U << 29)
+
+#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8U
+#define MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL 0x20000U
+#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_UNORDERED (0U << 11)
+#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_MASK (1U << 11)
+#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_UNORDERED (0U << 13)
+#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_MASK (1U << 13)
+
+#define MC_PCFIFO_CLIENT_CONFIG3 0xddcU
+#define MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL 0U
+#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_UNORDERED (0U << 7)
+#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_MASK (1U << 7)
+
+#define MC_PCFIFO_CLIENT_CONFIG4 0xde0U
+#define MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL 0U
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_UNORDERED (0U << 1)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_MASK (1U << 1)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_UNORDERED (0U << 5)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_MASK (1U << 5)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_UNORDERED (0U << 13)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_MASK (1U << 13)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_UNORDERED (0U << 15)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_ORDERED (1U << 15)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_MASK (1U << 15)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_UNORDERED (0U << 17)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_MASK (1U << 17)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_UNORDERED (0U << 22)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_MASK (1U << 22)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_UNORDERED (0U << 26)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_MASK (1U << 26)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_UNORDERED (0U << 30)
+#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_MASK (1U << 30)
+
+#define MC_PCFIFO_CLIENT_CONFIG5 0xbf4U
+#define MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL 0U
+#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_UNORDERED (0U << 0)
+#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_MASK (1U << 0)
+
+/*******************************************************************************
+ * Stream ID Override Config registers
+ ******************************************************************************/
+#define MC_STREAMID_OVERRIDE_CFG_PTCR 0x000U
+#define MC_STREAMID_OVERRIDE_CFG_AFIR 0x070U
+#define MC_STREAMID_OVERRIDE_CFG_HDAR 0x0A8U
+#define MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR 0x0B0U
+#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD 0x0E0U
+#define MC_STREAMID_OVERRIDE_CFG_SATAR 0x0F8U
+#define MC_STREAMID_OVERRIDE_CFG_MPCORER 0x138U
+#define MC_STREAMID_OVERRIDE_CFG_NVENCSWR 0x158U
+#define MC_STREAMID_OVERRIDE_CFG_AFIW 0x188U
+#define MC_STREAMID_OVERRIDE_CFG_HDAW 0x1A8U
+#define MC_STREAMID_OVERRIDE_CFG_MPCOREW 0x1C8U
+#define MC_STREAMID_OVERRIDE_CFG_SATAW 0x1E8U
+#define MC_STREAMID_OVERRIDE_CFG_ISPRA 0x220U
+#define MC_STREAMID_OVERRIDE_CFG_ISPWA 0x230U
+#define MC_STREAMID_OVERRIDE_CFG_ISPWB 0x238U
+#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTR 0x250U
+#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTW 0x258U
+#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVR 0x260U
+#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVW 0x268U
+#define MC_STREAMID_OVERRIDE_CFG_TSECSRD 0x2A0U
+#define MC_STREAMID_OVERRIDE_CFG_TSECSWR 0x2A8U
+#define MC_STREAMID_OVERRIDE_CFG_GPUSRD 0x2C0U
+#define MC_STREAMID_OVERRIDE_CFG_GPUSWR 0x2C8U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCRA 0x300U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAA 0x308U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCR 0x310U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAB 0x318U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCWA 0x320U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAA 0x328U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCW 0x330U
+#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAB 0x338U
+#define MC_STREAMID_OVERRIDE_CFG_VICSRD 0x360U
+#define MC_STREAMID_OVERRIDE_CFG_VICSWR 0x368U
+#define MC_STREAMID_OVERRIDE_CFG_VIW 0x390U
+#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD 0x3C0U
+#define MC_STREAMID_OVERRIDE_CFG_NVDECSWR 0x3C8U
+#define MC_STREAMID_OVERRIDE_CFG_APER 0x3D0U
+#define MC_STREAMID_OVERRIDE_CFG_APEW 0x3D8U
+#define MC_STREAMID_OVERRIDE_CFG_NVJPGSRD 0x3F0U
+#define MC_STREAMID_OVERRIDE_CFG_NVJPGSWR 0x3F8U
+#define MC_STREAMID_OVERRIDE_CFG_SESRD 0x400U
+#define MC_STREAMID_OVERRIDE_CFG_SESWR 0x408U
+#define MC_STREAMID_OVERRIDE_CFG_ETRR 0x420U
+#define MC_STREAMID_OVERRIDE_CFG_ETRW 0x428U
+#define MC_STREAMID_OVERRIDE_CFG_TSECSRDB 0x430U
+#define MC_STREAMID_OVERRIDE_CFG_TSECSWRB 0x438U
+#define MC_STREAMID_OVERRIDE_CFG_GPUSRD2 0x440U
+#define MC_STREAMID_OVERRIDE_CFG_GPUSWR2 0x448U
+#define MC_STREAMID_OVERRIDE_CFG_AXISR 0x460U
+#define MC_STREAMID_OVERRIDE_CFG_AXISW 0x468U
+#define MC_STREAMID_OVERRIDE_CFG_EQOSR 0x470U
+#define MC_STREAMID_OVERRIDE_CFG_EQOSW 0x478U
+#define MC_STREAMID_OVERRIDE_CFG_UFSHCR 0x480U
+#define MC_STREAMID_OVERRIDE_CFG_UFSHCW 0x488U
+#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR 0x490U
+#define MC_STREAMID_OVERRIDE_CFG_BPMPR 0x498U
+#define MC_STREAMID_OVERRIDE_CFG_BPMPW 0x4A0U
+#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAR 0x4A8U
+#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAW 0x4B0U
+#define MC_STREAMID_OVERRIDE_CFG_AONR 0x4B8U
+#define MC_STREAMID_OVERRIDE_CFG_AONW 0x4C0U
+#define MC_STREAMID_OVERRIDE_CFG_AONDMAR 0x4C8U
+#define MC_STREAMID_OVERRIDE_CFG_AONDMAW 0x4D0U
+#define MC_STREAMID_OVERRIDE_CFG_SCER 0x4D8U
+#define MC_STREAMID_OVERRIDE_CFG_SCEW 0x4E0U
+#define MC_STREAMID_OVERRIDE_CFG_SCEDMAR 0x4E8U
+#define MC_STREAMID_OVERRIDE_CFG_SCEDMAW 0x4F0U
+#define MC_STREAMID_OVERRIDE_CFG_APEDMAR 0x4F8U
+#define MC_STREAMID_OVERRIDE_CFG_APEDMAW 0x500U
+#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR1 0x508U
+#define MC_STREAMID_OVERRIDE_CFG_VICSRD1 0x510U
+#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD1 0x518U
+
+/*******************************************************************************
+ * Macro to calculate Security cfg register addr from StreamID Override register
+ ******************************************************************************/
+#define MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(addr) ((addr) + (uint32_t)sizeof(uint32_t))
+
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_SO_DEV (0U << 4)
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_SO_DEV (1U << 4)
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SO_DEV (2U << 4)
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_SO_DEV (3U << 4)
+
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_NORMAL (0U << 8)
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_NORMAL (1U << 8)
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_NORMAL (2U << 8)
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_NORMAL (3U << 8)
+
+#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_ZERO (0U << 12)
+#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_CLIENT_AXI_ID (1U << 12)
+
+/*******************************************************************************
+ * Memory Controller transaction override config registers
+ ******************************************************************************/
+#define MC_TXN_OVERRIDE_CONFIG_HDAR 0x10a8U
+#define MC_TXN_OVERRIDE_CONFIG_BPMPW 0x14a0U
+#define MC_TXN_OVERRIDE_CONFIG_PTCR 0x1000U
+#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR 0x1490U
+#define MC_TXN_OVERRIDE_CONFIG_EQOSW 0x1478U
+#define MC_TXN_OVERRIDE_CONFIG_NVJPGSWR 0x13f8U
+#define MC_TXN_OVERRIDE_CONFIG_ISPRA 0x1220U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAA 0x1328U
+#define MC_TXN_OVERRIDE_CONFIG_VICSRD 0x1360U
+#define MC_TXN_OVERRIDE_CONFIG_MPCOREW 0x11c8U
+#define MC_TXN_OVERRIDE_CONFIG_GPUSRD 0x12c0U
+#define MC_TXN_OVERRIDE_CONFIG_AXISR 0x1460U
+#define MC_TXN_OVERRIDE_CONFIG_SCEDMAW 0x14f0U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCW 0x1330U
+#define MC_TXN_OVERRIDE_CONFIG_EQOSR 0x1470U
+#define MC_TXN_OVERRIDE_CONFIG_APEDMAR 0x14f8U
+#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD 0x10e0U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAB 0x1318U
+#define MC_TXN_OVERRIDE_CONFIG_VICSRD1 0x1510U
+#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAR 0x14a8U
+#define MC_TXN_OVERRIDE_CONFIG_VIW 0x1390U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAA 0x1308U
+#define MC_TXN_OVERRIDE_CONFIG_AXISW 0x1468U
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVR 0x1260U
+#define MC_TXN_OVERRIDE_CONFIG_UFSHCR 0x1480U
+#define MC_TXN_OVERRIDE_CONFIG_TSECSWR 0x12a8U
+#define MC_TXN_OVERRIDE_CONFIG_GPUSWR 0x12c8U
+#define MC_TXN_OVERRIDE_CONFIG_SATAR 0x10f8U
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTW 0x1258U
+#define MC_TXN_OVERRIDE_CONFIG_TSECSWRB 0x1438U
+#define MC_TXN_OVERRIDE_CONFIG_GPUSRD2 0x1440U
+#define MC_TXN_OVERRIDE_CONFIG_SCEDMAR 0x14e8U
+#define MC_TXN_OVERRIDE_CONFIG_GPUSWR2 0x1448U
+#define MC_TXN_OVERRIDE_CONFIG_AONDMAW 0x14d0U
+#define MC_TXN_OVERRIDE_CONFIG_APEDMAW 0x1500U
+#define MC_TXN_OVERRIDE_CONFIG_AONW 0x14c0U
+#define MC_TXN_OVERRIDE_CONFIG_HOST1XDMAR 0x10b0U
+#define MC_TXN_OVERRIDE_CONFIG_ETRR 0x1420U
+#define MC_TXN_OVERRIDE_CONFIG_SESWR 0x1408U
+#define MC_TXN_OVERRIDE_CONFIG_NVJPGSRD 0x13f0U
+#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD 0x13c0U
+#define MC_TXN_OVERRIDE_CONFIG_TSECSRDB 0x1430U
+#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAW 0x14b0U
+#define MC_TXN_OVERRIDE_CONFIG_APER 0x13d0U
+#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD1 0x1518U
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTR 0x1250U
+#define MC_TXN_OVERRIDE_CONFIG_ISPWA 0x1230U
+#define MC_TXN_OVERRIDE_CONFIG_SESRD 0x1400U
+#define MC_TXN_OVERRIDE_CONFIG_SCER 0x14d8U
+#define MC_TXN_OVERRIDE_CONFIG_AONR 0x14b8U
+#define MC_TXN_OVERRIDE_CONFIG_MPCORER 0x1138U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCWA 0x1320U
+#define MC_TXN_OVERRIDE_CONFIG_HDAW 0x11a8U
+#define MC_TXN_OVERRIDE_CONFIG_NVDECSWR 0x13c8U
+#define MC_TXN_OVERRIDE_CONFIG_UFSHCW 0x1488U
+#define MC_TXN_OVERRIDE_CONFIG_AONDMAR 0x14c8U
+#define MC_TXN_OVERRIDE_CONFIG_SATAW 0x11e8U
+#define MC_TXN_OVERRIDE_CONFIG_ETRW 0x1428U
+#define MC_TXN_OVERRIDE_CONFIG_VICSWR 0x1368U
+#define MC_TXN_OVERRIDE_CONFIG_NVENCSWR 0x1158U
+#define MC_TXN_OVERRIDE_CONFIG_AFIR 0x1070U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAB 0x1338U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCRA 0x1300U
+#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR1 0x1508U
+#define MC_TXN_OVERRIDE_CONFIG_ISPWB 0x1238U
+#define MC_TXN_OVERRIDE_CONFIG_BPMPR 0x1498U
+#define MC_TXN_OVERRIDE_CONFIG_APEW 0x13d8U
+#define MC_TXN_OVERRIDE_CONFIG_SDMMCR 0x1310U
+#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVW 0x1268U
+#define MC_TXN_OVERRIDE_CONFIG_TSECSRD 0x12a0U
+#define MC_TXN_OVERRIDE_CONFIG_AFIW 0x1188U
+#define MC_TXN_OVERRIDE_CONFIG_SCEW 0x14e0U
+
+#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_CGID (1U << 0)
+#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_OVERRIDE_SO_DEV (2U << 4)
+#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_SO_DEV_CGID_SO_DEV_CLIENT (1U << 12)
+
+/*******************************************************************************
+ * Non-SO_DEV transactions override values for CGID_TAG bitfield for the
+ * MC_TXN_OVERRIDE_CONFIG_{module} registers
+ ******************************************************************************/
+#define MC_TXN_OVERRIDE_CGID_TAG_DEFAULT 0U
+#define MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID 1U
+#define MC_TXN_OVERRIDE_CGID_TAG_ZERO 2U
+#define MC_TXN_OVERRIDE_CGID_TAG_ADR 3U
+#define MC_TXN_OVERRIDE_CGID_TAG_MASK 3ULL
+
+/*******************************************************************************
+ * Memory Controller Reset Control registers
+ ******************************************************************************/
+#define MC_CLIENT_HOTRESET_CTRL0 0x200U
+#define MC_CLIENT_HOTRESET_CTRL0_RESET_VAL 0U
+#define MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB (1U << 0)
+#define MC_CLIENT_HOTRESET_CTRL0_HC_FLUSH_ENB (1U << 6)
+#define MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB (1U << 7)
+#define MC_CLIENT_HOTRESET_CTRL0_ISP2_FLUSH_ENB (1U << 8)
+#define MC_CLIENT_HOTRESET_CTRL0_MPCORE_FLUSH_ENB (1U << 9)
+#define MC_CLIENT_HOTRESET_CTRL0_NVENC_FLUSH_ENB (1U << 11)
+#define MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB (1U << 15)
+#define MC_CLIENT_HOTRESET_CTRL0_VI_FLUSH_ENB (1U << 17)
+#define MC_CLIENT_HOTRESET_CTRL0_VIC_FLUSH_ENB (1U << 18)
+#define MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB (1U << 19)
+#define MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB (1U << 20)
+#define MC_CLIENT_HOTRESET_CTRL0_TSEC_FLUSH_ENB (1U << 22)
+#define MC_CLIENT_HOTRESET_CTRL0_SDMMC1A_FLUSH_ENB (1U << 29)
+#define MC_CLIENT_HOTRESET_CTRL0_SDMMC2A_FLUSH_ENB (1U << 30)
+#define MC_CLIENT_HOTRESET_CTRL0_SDMMC3A_FLUSH_ENB (1U << 31)
+#define MC_CLIENT_HOTRESET_STATUS0 0x204U
+#define MC_CLIENT_HOTRESET_CTRL1 0x970U
+#define MC_CLIENT_HOTRESET_CTRL1_RESET_VAL 0U
+#define MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB (1U << 0)
+#define MC_CLIENT_HOTRESET_CTRL1_GPU_FLUSH_ENB (1U << 2)
+#define MC_CLIENT_HOTRESET_CTRL1_NVDEC_FLUSH_ENB (1U << 5)
+#define MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB (1U << 6)
+#define MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB (1U << 7)
+#define MC_CLIENT_HOTRESET_CTRL1_NVJPG_FLUSH_ENB (1U << 8)
+#define MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB (1U << 12)
+#define MC_CLIENT_HOTRESET_CTRL1_TSECB_FLUSH_ENB (1U << 13)
+#define MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB (1U << 18)
+#define MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB (1U << 19)
+#define MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB (1U << 20)
+#define MC_CLIENT_HOTRESET_CTRL1_NVDISPLAY_FLUSH_ENB (1U << 21)
+#define MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB (1U << 22)
+#define MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB (1U << 23)
+#define MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB (1U << 24)
+#define MC_CLIENT_HOTRESET_STATUS1 0x974U
+
+#ifndef __ASSEMBLER__
+
+/*******************************************************************************
+ * Structure to hold the transaction override settings to use to override
+ * client inputs
+ ******************************************************************************/
+typedef struct mc_txn_override_cfg {
+ uint32_t offset;
+ uint8_t cgid_tag;
+} mc_txn_override_cfg_t;
+
+#define mc_make_txn_override_cfg(off, val) \
+ { \
+ .offset = MC_TXN_OVERRIDE_CONFIG_ ## off, \
+ .cgid_tag = MC_TXN_OVERRIDE_ ## val \
+ }
+
+/*******************************************************************************
+ * Structure to hold the Stream ID to use to override client inputs
+ ******************************************************************************/
+typedef struct mc_streamid_override_cfg {
+ uint32_t offset;
+ uint8_t stream_id;
+} mc_streamid_override_cfg_t;
+
+/*******************************************************************************
+ * Structure to hold the Stream ID Security Configuration settings
+ ******************************************************************************/
+typedef struct mc_streamid_security_cfg {
+ char *name;
+ uint32_t offset;
+ uint32_t override_enable;
+ uint32_t override_client_inputs;
+ uint32_t override_client_ns_flag;
+} mc_streamid_security_cfg_t;
+
+#define OVERRIDE_DISABLE 1U
+#define OVERRIDE_ENABLE 0U
+#define CLIENT_FLAG_SECURE 0U
+#define CLIENT_FLAG_NON_SECURE 1U
+#define CLIENT_INPUTS_OVERRIDE 1U
+#define CLIENT_INPUTS_NO_OVERRIDE 0U
+
+/*******************************************************************************
+ * StreamID to indicate no SMMU translations (requests to be steered on the
+ * SMMU bypass path)
+ ******************************************************************************/
+#define MC_STREAM_ID_MAX 0x7FU
+
+#define mc_make_sec_cfg(off, ns, ovrrd, access) \
+ { \
+ .name = # off, \
+ .offset = MC_STREAMID_OVERRIDE_TO_SECURITY_CFG( \
+ MC_STREAMID_OVERRIDE_CFG_ ## off), \
+ .override_client_ns_flag = CLIENT_FLAG_ ## ns, \
+ .override_client_inputs = CLIENT_INPUTS_ ## ovrrd, \
+ .override_enable = OVERRIDE_ ## access \
+ }
+
+#define mc_make_sid_override_cfg(name) \
+ { \
+ .reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_CFG_ ## name, \
+ .val = 0x00000000U, \
+ }
+
+#define mc_make_sid_security_cfg(name) \
+ { \
+ .reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(MC_STREAMID_OVERRIDE_CFG_ ## name), \
+ .val = 0x00000000U, \
+ }
+
+#define mc_set_pcfifo_unordered_boot_so_mss(id, client) \
+ ((uint32_t)~MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_MASK | \
+ MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_UNORDERED)
+
+#define mc_set_pcfifo_ordered_boot_so_mss(id, client) \
+ MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_ORDERED
+
+#define mc_set_tsa_passthrough(client) \
+ do { \
+ mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \
+ (TSA_CONFIG_STATIC0_CSW_##client##_RESET & \
+ (uint32_t)~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \
+ (uint32_t)TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \
+ } while (0)
+
+#define mc_set_tsa_w_passthrough(client) \
+ do { \
+ mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \
+ (TSA_CONFIG_STATIC0_CSW_RESET_W & \
+ (uint32_t)~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \
+ (uint32_t)TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \
+ } while (0)
+
+#define mc_set_tsa_r_passthrough(client) \
+ { \
+ mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSR_##client, \
+ (TSA_CONFIG_STATIC0_CSR_RESET_R & \
+ (uint32_t)~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \
+ (uint32_t)TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \
+ } while (0)
+
+#define mc_set_txn_override(client, normal_axi_id, so_dev_axi_id, normal_override, so_dev_override) \
+ do { \
+ tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_##client, \
+ MC_TXN_OVERRIDE_##normal_axi_id | \
+ MC_TXN_OVERRIDE_CONFIG_COH_PATH_##so_dev_override##_SO_DEV | \
+ MC_TXN_OVERRIDE_CONFIG_COH_PATH_##normal_override##_NORMAL | \
+ MC_TXN_OVERRIDE_CONFIG_CGID_##so_dev_axi_id); \
+ } while (0)
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* TEGRA_MC_DEF_H */
diff --git a/plat/nvidia/tegra/include/t194/tegra194_private.h b/plat/nvidia/tegra/include/t194/tegra194_private.h
new file mode 100644
index 0000000..c5a51e9
--- /dev/null
+++ b/plat/nvidia/tegra/include/t194/tegra194_private.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA194_PRIVATE_H
+#define TEGRA194_PRIVATE_H
+
+void tegra194_cpu_reset_handler(void);
+uint64_t tegra194_get_cpu_reset_handler_base(void);
+uint64_t tegra194_get_cpu_reset_handler_size(void);
+uint64_t tegra194_get_mc_ctx_offset(void);
+void tegra194_set_system_suspend_entry(void);
+
+#endif /* TEGRA194_PRIVATE_H */
diff --git a/plat/nvidia/tegra/include/t194/tegra194_ras_private.h b/plat/nvidia/tegra/include/t194/tegra194_ras_private.h
new file mode 100644
index 0000000..336461a
--- /dev/null
+++ b/plat/nvidia/tegra/include/t194/tegra194_ras_private.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA194_RAS_PRIVATE
+#define TEGRA194_RAS_PRIVATE
+
+#include <stdint.h>
+
+/* Implementation defined RAS error and corresponding error message */
+struct ras_error {
+ const char *error_msg;
+ /* IERR(bits[15:8]) from ERR<n>STATUS */
+ uint8_t error_code;
+};
+
+/* RAS error node-specific auxiliary data */
+struct ras_aux_data {
+ /* name for current RAS node. */
+ const char *name;
+ /* point to null-terminated ras_error array to convert error code to msg. */
+ const struct ras_error *error_records;
+ /*
+ * function to return an value which needs to be programmed into ERXCTLR_EL1
+ * to enable all specified RAS errors for current node.
+ */
+ uint64_t (*err_ctrl)(void);
+};
+
+/* IFU Uncorrectable RAS ERROR */
+#define IFU_UNCORR_RAS_ERROR_LIST(X)
+
+/* JSR_RET Uncorrectable RAS ERROR */
+#define JSR_RET_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(JSR_RET, 35, 0x13, "Floating Point Register File Parity Error") \
+ X(JSR_RET, 34, 0x12, "Integer Register File Parity Error") \
+ X(JSR_RET, 33, 0x11, "Garbage Bundle") \
+ X(JSR_RET, 32, 0x10, "Bundle Completion Timeout")
+
+/* JSR_MTS Uncorrectable RAS ERROR */
+#define JSR_MTS_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(JSR_MTS, 40, 0x28, "CoreSight Access Error") \
+ X(JSR_MTS, 39, 0x27, "Dual Execution Uncorrectable Error") \
+ X(JSR_MTS, 37, 0x25, "CTU MMIO Region") \
+ X(JSR_MTS, 36, 0x24, "MTS MMCRAB Region Access") \
+ X(JSR_MTS, 35, 0x23, "MTS_CARVEOUT Access from ARM SW") \
+ X(JSR_MTS, 34, 0x22, "NAFLL PLL Failure to Lock") \
+ X(JSR_MTS, 32, 0x20, "Internal Uncorrectable MTS Error")
+
+/* LSD_STQ Uncorrectable RAS ERROR */
+#define LSD_STQ_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(LSD_STQ, 41, 0x39, "Coherent Cache Data Store Multi-Line ECC Error") \
+ X(LSD_STQ, 40, 0x38, "Coherent Cache Data Store Uncorrectable ECC Error") \
+ X(LSD_STQ, 38, 0x36, "Coherent Cache Data Load Uncorrectable ECC Error") \
+ X(LSD_STQ, 33, 0x31, "Coherent Cache Tag Store Parity Error") \
+ X(LSD_STQ, 32, 0x30, "Coherent Cache Tag Load Parity Error")
+
+/* LSD_DCC Uncorrectable RAS ERROR */
+#define LSD_DCC_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(LSD_DCC, 41, 0x49, "BTU Copy Mini-Cache PPN Multi-Hit Error") \
+ X(LSD_DCC, 39, 0x47, "Coherent Cache Data Uncorrectable ECC Error") \
+ X(LSD_DCC, 37, 0x45, "Version Cache Byte-Enable Parity Error") \
+ X(LSD_DCC, 36, 0x44, "Version Cache Data Uncorrectable ECC Error") \
+ X(LSD_DCC, 33, 0x41, "BTU Copy Coherent Cache PPN Parity Error") \
+ X(LSD_DCC, 32, 0x40, "BTU Copy Coherent Cache VPN Parity Error")
+
+/* LSD_L1HPF Uncorrectable RAS ERROR */
+#define LSD_L1HPF_UNCORR_RAS_ERROR_LIST(X)
+
+/* L2 Uncorrectable RAS ERROR */
+#define L2_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(L2, 56, 0x68, "URT Timeout") \
+ X(L2, 55, 0x67, "L2 Protocol Violation") \
+ X(L2, 54, 0x66, "SCF to L2 Slave Error Read") \
+ X(L2, 53, 0x65, "SCF to L2 Slave Error Write") \
+ X(L2, 52, 0x64, "SCF to L2 Decode Error Read") \
+ X(L2, 51, 0x63, "SCF to L2 Decode Error Write") \
+ X(L2, 50, 0x62, "SCF to L2 Request Response Interface Parity Errors") \
+ X(L2, 49, 0x61, "SCF to L2 Advance notice interface parity errors") \
+ X(L2, 48, 0x60, "SCF to L2 Filldata Parity Errors") \
+ X(L2, 47, 0x5F, "SCF to L2 UnCorrectable ECC Data Error on interface") \
+ X(L2, 45, 0x5D, "Core 1 to L2 Parity Error") \
+ X(L2, 44, 0x5C, "Core 0 to L2 Parity Error") \
+ X(L2, 43, 0x5B, "L2 Multi-Hit") \
+ X(L2, 42, 0x5A, "L2 URT Tag Parity Error") \
+ X(L2, 41, 0x59, "L2 NTT Tag Parity Error") \
+ X(L2, 40, 0x58, "L2 MLT Tag Parity Error") \
+ X(L2, 39, 0x57, "L2 URD Data") \
+ X(L2, 38, 0x56, "L2 NTP Data") \
+ X(L2, 36, 0x54, "L2 MLC Uncorrectable Clean") \
+ X(L2, 35, 0x53, "L2 URD Uncorrectable Dirty") \
+ X(L2, 34, 0x52, "L2 MLC Uncorrectable Dirty")
+
+/* CLUSTER_CLOCKS Uncorrectable RAS ERROR */
+#define CLUSTER_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(CLUSTER_CLOCKS, 32, 0xE4, "Frequency Monitor Error")
+
+/* MMU Uncorrectable RAS ERROR */
+#define MMU_UNCORR_RAS_ERROR_LIST(X)
+
+/* L3 Uncorrectable RAS ERROR */
+#define L3_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(L3, 43, 0x7B, "SNOC Interface Parity Error") \
+ X(L3, 42, 0x7A, "MCF Interface Parity Error") \
+ X(L3, 41, 0x79, "L3 Tag Parity Error") \
+ X(L3, 40, 0x78, "L3 Dir Parity Error") \
+ X(L3, 39, 0x77, "L3 Uncorrectable ECC Error") \
+ X(L3, 37, 0x75, "Multi-Hit CAM Error") \
+ X(L3, 36, 0x74, "Multi-Hit Tag Error") \
+ X(L3, 35, 0x73, "Unrecognized Command Error") \
+ X(L3, 34, 0x72, "L3 Protocol Error")
+
+/* CCPMU Uncorrectable RAS ERROR */
+#define CCPMU_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(CCPMU, 40, 0x87, "CoreSight Access Error") \
+ X(CCPMU, 36, 0x84, "MCE Ucode Error") \
+ X(CCPMU, 35, 0x83, "MCE IL1 Parity Error") \
+ X(CCPMU, 34, 0x82, "MCE Timeout Error") \
+ X(CCPMU, 33, 0x81, "CRAB Access Error") \
+ X(CCPMU, 32, 0x80, "MCE Memory Access Error")
+
+/* SCF_IOB Uncorrectable RAS ERROR */
+#define SCF_IOB_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(SCF_IOB, 41, 0x99, "Request parity error") \
+ X(SCF_IOB, 40, 0x98, "Putdata parity error") \
+ X(SCF_IOB, 39, 0x97, "Uncorrectable ECC on Putdata") \
+ X(SCF_IOB, 38, 0x96, "CBB Interface Error") \
+ X(SCF_IOB, 37, 0x95, "MMCRAB Error") \
+ X(SCF_IOB, 36, 0x94, "IHI Interface Error") \
+ X(SCF_IOB, 35, 0x93, "CRI Error") \
+ X(SCF_IOB, 34, 0x92, "TBX Interface Error") \
+ X(SCF_IOB, 33, 0x91, "EVP Interface Error")
+
+/* SCF_SNOC Uncorrectable RAS ERROR */
+#define SCF_SNOC_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(SCF_SNOC, 42, 0xAA, "Misc Client Parity Error") \
+ X(SCF_SNOC, 41, 0xA9, "Misc Filldata Parity Error") \
+ X(SCF_SNOC, 40, 0xA8, "Uncorrectable ECC Misc Client") \
+ X(SCF_SNOC, 39, 0xA7, "DVMU Interface Parity Error") \
+ X(SCF_SNOC, 38, 0xA6, "DVMU Interface Timeout Error") \
+ X(SCF_SNOC, 37, 0xA5, "CPE Request Error") \
+ X(SCF_SNOC, 36, 0xA4, "CPE Response Error") \
+ X(SCF_SNOC, 35, 0xA3, "CPE Timeout Error") \
+ X(SCF_SNOC, 34, 0xA2, "Uncorrectable Carveout Error")
+
+/* SCF_CTU Uncorrectable RAS ERROR */
+#define SCF_CTU_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(SCF_CTU, 39, 0xB7, "Timeout error for TRC_DMA request") \
+ X(SCF_CTU, 38, 0xB6, "Timeout error for CTU Snp") \
+ X(SCF_CTU, 37, 0xB5, "Parity error in CTU TAG RAM") \
+ X(SCF_CTU, 36, 0xB3, "Parity error in CTU DATA RAM") \
+ X(SCF_CTU, 35, 0xB4, "Parity error for Cluster Rsp") \
+ X(SCF_CTU, 34, 0xB2, "Parity error for TRL requests from 9 agents") \
+ X(SCF_CTU, 33, 0xB1, "Parity error for MCF request") \
+ X(SCF_CTU, 32, 0xB0, "TRC DMA fillsnoop parity error")
+
+/* CMU_CLOCKS Uncorrectable RAS ERROR */
+#define CMU_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \
+ /* Name, ERR_CTRL, IERR, ISA Desc */ \
+ X(CMU_CLOCKS, 39, 0xC7, "Cluster 3 frequency monitor error") \
+ X(CMU_CLOCKS, 38, 0xC6, "Cluster 2 frequency monitor error") \
+ X(CMU_CLOCKS, 37, 0xC5, "Cluster 1 frequency monitor error") \
+ X(CMU_CLOCKS, 36, 0xC3, "Cluster 0 frequency monitor error") \
+ X(CMU_CLOCKS, 35, 0xC4, "Voltage error on ADC1 Monitored Logic") \
+ X(CMU_CLOCKS, 34, 0xC2, "Voltage error on ADC0 Monitored Logic") \
+ X(CMU_CLOCKS, 33, 0xC1, "Lookup Table 1 Parity Error") \
+ X(CMU_CLOCKS, 32, 0xC0, "Lookup Table 0 Parity Error")
+
+/*
+ * Define one ras_error entry.
+ *
+ * This macro wille be used to to generate ras_error records for each node
+ * defined by <NODE_NAME>_UNCORR_RAS_ERROR_LIST macro.
+ */
+#define DEFINE_ONE_RAS_ERROR_MSG(unit, ras_bit, ierr, msg) \
+ { \
+ .error_msg = (msg), \
+ .error_code = (ierr) \
+ },
+
+/*
+ * Set one implementation defined bit in ERR<n>CTLR
+ *
+ * This macro will be used to collect all defined ERR_CTRL bits for each node
+ * defined by <NODE_NAME>_UNCORR_RAS_ERROR_LIST macro.
+ */
+#define DEFINE_ENABLE_RAS_BIT(unit, ras_bit, ierr, msg) \
+ do { \
+ val |= (1ULL << ras_bit##U); \
+ } while (0);
+
+/* Represent one RAS node with 0 or more error bits (ERR_CTLR) enabled */
+#define DEFINE_ONE_RAS_NODE(node) \
+static const struct ras_error node##_uncorr_ras_errors[] = { \
+ node##_UNCORR_RAS_ERROR_LIST(DEFINE_ONE_RAS_ERROR_MSG) \
+ { \
+ NULL, \
+ 0U \
+ }, \
+}; \
+static inline uint64_t node##_err_ctrl(void) \
+{ \
+ uint64_t val = 0ULL; \
+ node##_UNCORR_RAS_ERROR_LIST(DEFINE_ENABLE_RAS_BIT) \
+ return val; \
+}
+
+#define DEFINE_ONE_RAS_AUX_DATA(node) \
+ { \
+ .name = #node, \
+ .error_records = node##_uncorr_ras_errors, \
+ .err_ctrl = &node##_err_ctrl \
+ },
+
+#define PER_CORE_RAS_NODE_LIST(X) \
+ X(IFU) \
+ X(JSR_RET) \
+ X(JSR_MTS) \
+ X(LSD_STQ) \
+ X(LSD_DCC) \
+ X(LSD_L1HPF)
+
+#define PER_CORE_RAS_GROUP_NODES PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define PER_CLUSTER_RAS_NODE_LIST(X) \
+ X(L2) \
+ X(CLUSTER_CLOCKS) \
+ X(MMU)
+
+#define PER_CLUSTER_RAS_GROUP_NODES PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define SCF_L3_BANK_RAS_NODE_LIST(X) X(L3)
+
+/* we have 4 SCF_L3 nodes:3*256 + L3_Bank_ID(0-3) */
+#define SCF_L3_BANK_RAS_GROUP_NODES \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA) \
+ SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define CCPLEX_RAS_NODE_LIST(X) \
+ X(CCPMU) \
+ X(SCF_IOB) \
+ X(SCF_SNOC) \
+ X(SCF_CTU) \
+ X(CMU_CLOCKS)
+
+#define CCPLEX_RAS_GROUP_NODES CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#endif /* TEGRA194_RAS_PRIVATE */
diff --git a/plat/nvidia/tegra/include/t194/tegra_def.h b/plat/nvidia/tegra/include/t194/tegra_def.h
new file mode 100644
index 0000000..abe193f
--- /dev/null
+++ b/plat/nvidia/tegra/include/t194/tegra_def.h
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA_DEF_H
+#define TEGRA_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * Platform BL31 specific defines.
+ ******************************************************************************/
+#define BL31_SIZE U(0x40000)
+
+/*******************************************************************************
+ * Chip specific cluster and cpu numbers
+ ******************************************************************************/
+#define PLATFORM_CLUSTER_COUNT U(4)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2)
+
+/*******************************************************************************
+ * Chip specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40)
+
+/*******************************************************************************
+ * These values are used by the PSCI implementation during the `CPU_SUSPEND`
+ * and `SYSTEM_SUSPEND` calls as the `state-id` field in the 'power state'
+ * parameter.
+ ******************************************************************************/
+#define PSTATE_ID_CORE_IDLE U(6)
+#define PSTATE_ID_CORE_POWERDN U(7)
+#define PSTATE_ID_SOC_POWERDN U(2)
+
+/*******************************************************************************
+ * Platform power states (used by PSCI framework)
+ *
+ * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID
+ * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID
+ ******************************************************************************/
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(8)
+
+/*******************************************************************************
+ * Secure IRQ definitions
+ ******************************************************************************/
+#define TEGRA194_MAX_SEC_IRQS U(2)
+#define TEGRA194_TOP_WDT_IRQ U(49)
+#define TEGRA194_AON_WDT_IRQ U(50)
+
+#define TEGRA194_SEC_IRQ_TARGET_MASK U(0xFF) /* 8 Carmel */
+
+/*******************************************************************************
+ * Clock identifier for the SE device
+ ******************************************************************************/
+#define TEGRA194_CLK_SE U(124)
+#define TEGRA_CLK_SE TEGRA194_CLK_SE
+
+/*******************************************************************************
+ * Tegra Miscellanous register constants
+ ******************************************************************************/
+#define TEGRA_MISC_BASE U(0x00100000)
+
+#define HARDWARE_REVISION_OFFSET U(0x4)
+#define MISCREG_EMU_REVID U(0x3160)
+#define BOARD_MASK_BITS U(0xFF)
+#define BOARD_SHIFT_BITS U(24)
+#define MISCREG_PFCFG U(0x200C)
+
+/*******************************************************************************
+ * Tegra General Purpose Centralised DMA constants
+ ******************************************************************************/
+#define TEGRA_GPCDMA_BASE U(0x02610000)
+
+/*******************************************************************************
+ * Tegra Memory Controller constants
+ ******************************************************************************/
+#define TEGRA_MC_STREAMID_BASE U(0x02C00000)
+#define TEGRA_MC_BASE U(0x02C10000)
+
+/* General Security Carveout register macros */
+#define MC_GSC_CONFIG_REGS_SIZE U(0x40)
+#define MC_GSC_LOCK_CFG_SETTINGS_BIT (U(1) << 1)
+#define MC_GSC_ENABLE_TZ_LOCK_BIT (U(1) << 0)
+#define MC_GSC_SIZE_RANGE_4KB_SHIFT U(27)
+#define MC_GSC_BASE_LO_SHIFT U(12)
+#define MC_GSC_BASE_LO_MASK U(0xFFFFF)
+#define MC_GSC_BASE_HI_SHIFT U(0)
+#define MC_GSC_BASE_HI_MASK U(3)
+#define MC_GSC_ENABLE_CPU_SECURE_BIT (U(1) << 31)
+
+/* TZDRAM carveout configuration registers */
+#define MC_SECURITY_CFG0_0 U(0x70)
+#define MC_SECURITY_CFG1_0 U(0x74)
+#define MC_SECURITY_CFG3_0 U(0x9BC)
+
+#define MC_SECURITY_BOM_MASK (U(0xFFF) << 20)
+#define MC_SECURITY_SIZE_MB_MASK (U(0x1FFF) << 0)
+#define MC_SECURITY_BOM_HI_MASK (U(0x3) << 0)
+
+#define MC_SECURITY_CFG_REG_CTRL_0 U(0x154)
+#define SECURITY_CFG_WRITE_ACCESS_BIT (U(0x1) << 0)
+#define SECURITY_CFG_WRITE_ACCESS_ENABLE U(0x0)
+#define SECURITY_CFG_WRITE_ACCESS_DISABLE U(0x1)
+
+/* Video Memory carveout configuration registers */
+#define MC_VIDEO_PROTECT_BASE_HI U(0x978)
+#define MC_VIDEO_PROTECT_BASE_LO U(0x648)
+#define MC_VIDEO_PROTECT_SIZE_MB U(0x64c)
+#define MC_VIDEO_PROTECT_REG_CTRL U(0x650)
+#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED U(3)
+
+/*
+ * Carveout (MC_SECURITY_CARVEOUT24) registers used to clear the
+ * non-overlapping Video memory region
+ */
+#define MC_VIDEO_PROTECT_CLEAR_CFG U(0x25A0)
+#define MC_VIDEO_PROTECT_CLEAR_BASE_LO U(0x25A4)
+#define MC_VIDEO_PROTECT_CLEAR_BASE_HI U(0x25A8)
+#define MC_VIDEO_PROTECT_CLEAR_SIZE U(0x25AC)
+#define MC_VIDEO_PROTECT_CLEAR_ACCESS_CFG0 U(0x25B0)
+
+/* TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers */
+#define MC_TZRAM_CARVEOUT_CFG U(0x2190)
+#define MC_TZRAM_BASE_LO U(0x2194)
+#define MC_TZRAM_BASE_HI U(0x2198)
+#define MC_TZRAM_SIZE U(0x219C)
+#define MC_TZRAM_CLIENT_ACCESS0_CFG0 U(0x21A0)
+#define MC_TZRAM_CLIENT_ACCESS1_CFG0 U(0x21A4)
+#define TZRAM_ALLOW_MPCORER (U(1) << 7)
+#define TZRAM_ALLOW_MPCOREW (U(1) << 25)
+
+/* Memory Controller Reset Control registers */
+#define MC_CLIENT_HOTRESET_CTRL1_DLAA_FLUSH_ENB (U(1) << 28)
+#define MC_CLIENT_HOTRESET_CTRL1_DLA1A_FLUSH_ENB (U(1) << 29)
+#define MC_CLIENT_HOTRESET_CTRL1_PVA0A_FLUSH_ENB (U(1) << 30)
+#define MC_CLIENT_HOTRESET_CTRL1_PVA1A_FLUSH_ENB (U(1) << 31)
+
+/*******************************************************************************
+ * Tegra UART Controller constants
+ ******************************************************************************/
+#define TEGRA_UARTA_BASE U(0x03100000)
+#define TEGRA_UARTB_BASE U(0x03110000)
+#define TEGRA_UARTC_BASE U(0x0C280000)
+#define TEGRA_UARTD_BASE U(0x03130000)
+#define TEGRA_UARTE_BASE U(0x03140000)
+#define TEGRA_UARTF_BASE U(0x03150000)
+#define TEGRA_UARTG_BASE U(0x0C290000)
+
+/*******************************************************************************
+ * XUSB PADCTL
+ ******************************************************************************/
+#define TEGRA_XUSB_PADCTL_BASE U(0x03520000)
+#define TEGRA_XUSB_PADCTL_SIZE U(0x10000)
+#define XUSB_PADCTL_HOST_AXI_STREAMID_PF_0 U(0x136c)
+#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_0 U(0x1370)
+#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_1 U(0x1374)
+#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_2 U(0x1378)
+#define XUSB_PADCTL_HOST_AXI_STREAMID_VF_3 U(0x137c)
+#define XUSB_PADCTL_DEV_AXI_STREAMID_PF_0 U(0x139c)
+
+/*******************************************************************************
+ * Tegra Fuse Controller related constants
+ ******************************************************************************/
+#define TEGRA_FUSE_BASE U(0x03820000)
+#define OPT_SUBREVISION U(0x248)
+#define SUBREVISION_MASK U(0xF)
+
+/*******************************************************************************
+ * GICv2 & interrupt handling related constants
+ ******************************************************************************/
+#define TEGRA_GICD_BASE U(0x03881000)
+#define TEGRA_GICC_BASE U(0x03882000)
+
+/*******************************************************************************
+ * Security Engine related constants
+ ******************************************************************************/
+#define TEGRA_SE0_BASE U(0x03AC0000)
+#define SE0_MUTEX_WATCHDOG_NS_LIMIT U(0x6C)
+#define SE0_AES0_ENTROPY_SRC_AGE_CTRL U(0x2FC)
+#define TEGRA_PKA1_BASE U(0x03AD0000)
+#define SE_PKA1_CTRL_SE_MUTEX_TMOUT_DFTVAL U(0x144)
+#define PKA1_MUTEX_WATCHDOG_NS_LIMIT SE_PKA1_CTRL_SE_MUTEX_TMOUT_DFTVAL
+#define TEGRA_RNG1_BASE U(0x03AE0000)
+#define RNG1_MUTEX_WATCHDOG_NS_LIMIT U(0xFE0)
+
+/*******************************************************************************
+ * Tegra HSP doorbell #0 constants
+ ******************************************************************************/
+#define TEGRA_HSP_DBELL_BASE U(0x03C90000)
+#define HSP_DBELL_1_ENABLE U(0x104)
+#define HSP_DBELL_3_TRIGGER U(0x300)
+#define HSP_DBELL_3_ENABLE U(0x304)
+
+/*******************************************************************************
+ * Tegra hardware synchronization primitives for the SPE engine
+ ******************************************************************************/
+#define TEGRA_AON_HSP_SM_6_7_BASE U(0x0c190000)
+#define TEGRA_CONSOLE_SPE_BASE (TEGRA_AON_HSP_SM_6_7_BASE + U(0x8000))
+
+/*******************************************************************************
+ * Tegra micro-seconds timer constants
+ ******************************************************************************/
+#define TEGRA_TMRUS_BASE U(0x0C2E0000)
+#define TEGRA_TMRUS_SIZE U(0x10000)
+
+/*******************************************************************************
+ * Tegra Power Mgmt Controller constants
+ ******************************************************************************/
+#define TEGRA_PMC_BASE U(0x0C360000)
+
+/*******************************************************************************
+ * Tegra scratch registers constants
+ ******************************************************************************/
+#define TEGRA_SCRATCH_BASE U(0x0C390000)
+#define SECURE_SCRATCH_RSV68_LO U(0x284)
+#define SECURE_SCRATCH_RSV68_HI U(0x288)
+#define SECURE_SCRATCH_RSV69_LO U(0x28C)
+#define SECURE_SCRATCH_RSV69_HI U(0x290)
+#define SECURE_SCRATCH_RSV70_LO U(0x294)
+#define SECURE_SCRATCH_RSV70_HI U(0x298)
+#define SECURE_SCRATCH_RSV71_LO U(0x29C)
+#define SECURE_SCRATCH_RSV71_HI U(0x2A0)
+#define SECURE_SCRATCH_RSV72_LO U(0x2A4)
+#define SECURE_SCRATCH_RSV72_HI U(0x2A8)
+#define SECURE_SCRATCH_RSV75 U(0x2BC)
+#define SECURE_SCRATCH_RSV81_LO U(0x2EC)
+#define SECURE_SCRATCH_RSV81_HI U(0x2F0)
+#define SECURE_SCRATCH_RSV97 U(0x36C)
+#define SECURE_SCRATCH_RSV99_LO U(0x37C)
+#define SECURE_SCRATCH_RSV99_HI U(0x380)
+#define SECURE_SCRATCH_RSV109_LO U(0x3CC)
+#define SECURE_SCRATCH_RSV109_HI U(0x3D0)
+
+#define SCRATCH_BL31_PARAMS_HI_ADDR SECURE_SCRATCH_RSV75
+#define SCRATCH_BL31_PARAMS_HI_ADDR_MASK U(0xFFFF)
+#define SCRATCH_BL31_PARAMS_HI_ADDR_SHIFT U(0)
+#define SCRATCH_BL31_PARAMS_LO_ADDR SECURE_SCRATCH_RSV81_LO
+#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR SECURE_SCRATCH_RSV75
+#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK U(0xFFFF0000)
+#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT U(16)
+#define SCRATCH_BL31_PLAT_PARAMS_LO_ADDR SECURE_SCRATCH_RSV81_HI
+#define SCRATCH_SECURE_BOOTP_FCFG SECURE_SCRATCH_RSV97
+#define SCRATCH_MC_TABLE_ADDR_LO SECURE_SCRATCH_RSV99_LO
+#define SCRATCH_MC_TABLE_ADDR_HI SECURE_SCRATCH_RSV99_HI
+#define SCRATCH_RESET_VECTOR_LO SECURE_SCRATCH_RSV109_LO
+#define SCRATCH_RESET_VECTOR_HI SECURE_SCRATCH_RSV109_HI
+
+/*******************************************************************************
+ * Tegra Memory Mapped Control Register Access Bus constants
+ ******************************************************************************/
+#define TEGRA_MMCRAB_BASE U(0x0E000000)
+
+/*******************************************************************************
+ * Tegra SMMU Controller constants
+ ******************************************************************************/
+#define TEGRA_SMMU0_BASE U(0x12000000)
+#define TEGRA_SMMU1_BASE U(0x11000000)
+#define TEGRA_SMMU2_BASE U(0x10000000)
+
+/*******************************************************************************
+ * Tegra TZRAM constants
+ ******************************************************************************/
+#define TEGRA_TZRAM_BASE U(0x40000000)
+#define TEGRA_TZRAM_SIZE U(0x40000)
+
+/*******************************************************************************
+ * Tegra CCPLEX-BPMP IPC constants
+ ******************************************************************************/
+#define TEGRA_BPMP_IPC_TX_PHYS_BASE U(0x4004C000)
+#define TEGRA_BPMP_IPC_RX_PHYS_BASE U(0x4004D000)
+#define TEGRA_BPMP_IPC_CH_MAP_SIZE U(0x1000) /* 4KB */
+
+/*******************************************************************************
+ * Tegra Clock and Reset Controller constants
+ ******************************************************************************/
+#define TEGRA_CAR_RESET_BASE U(0x20000000)
+#define TEGRA_GPU_RESET_REG_OFFSET U(0x18)
+#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x1C)
+#define GPU_RESET_BIT (U(1) << 0)
+#define GPU_SET_BIT (U(1) << 0)
+#define TEGRA_GPCDMA_RST_SET_REG_OFFSET U(0x6A0004)
+#define TEGRA_GPCDMA_RST_CLR_REG_OFFSET U(0x6A0008)
+
+/*******************************************************************************
+ * Tegra DRAM memory base address
+ ******************************************************************************/
+#define TEGRA_DRAM_BASE ULL(0x80000000)
+#define TEGRA_DRAM_END ULL(0xFFFFFFFFF)
+
+/*******************************************************************************
+ * XUSB STREAMIDs
+ ******************************************************************************/
+#define TEGRA_SID_XUSB_HOST U(0x1b)
+#define TEGRA_SID_XUSB_DEV U(0x1c)
+#define TEGRA_SID_XUSB_VF0 U(0x5d)
+#define TEGRA_SID_XUSB_VF1 U(0x5e)
+#define TEGRA_SID_XUSB_VF2 U(0x5f)
+#define TEGRA_SID_XUSB_VF3 U(0x60)
+
+/*******************************************************************************
+ * SCR addresses and expected settings
+ ******************************************************************************/
+#define SCRATCH_RSV68_SCR U(0x0C398110)
+#define SCRATCH_RSV68_SCR_VAL U(0x38000101)
+#define SCRATCH_RSV71_SCR U(0x0C39811C)
+#define SCRATCH_RSV71_SCR_VAL U(0x38000101)
+#define SCRATCH_RSV72_SCR U(0x0C398120)
+#define SCRATCH_RSV72_SCR_VAL U(0x38000101)
+#define SCRATCH_RSV75_SCR U(0x0C39812C)
+#define SCRATCH_RSV75_SCR_VAL U(0x3A000005)
+#define SCRATCH_RSV81_SCR U(0x0C398144)
+#define SCRATCH_RSV81_SCR_VAL U(0x3A000105)
+#define SCRATCH_RSV97_SCR U(0x0C398184)
+#define SCRATCH_RSV97_SCR_VAL U(0x38000101)
+#define SCRATCH_RSV99_SCR U(0x0C39818C)
+#define SCRATCH_RSV99_SCR_VAL U(0x38000101)
+#define SCRATCH_RSV109_SCR U(0x0C3981B4)
+#define SCRATCH_RSV109_SCR_VAL U(0x38000101)
+#define MISCREG_SCR_SCRTZWELCK U(0x00109000)
+#define MISCREG_SCR_SCRTZWELCK_VAL U(0x30000100)
+
+#endif /* TEGRA_DEF_H */
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
new file mode 100644
index 0000000..81b25e0
--- /dev/null
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA_DEF_H
+#define TEGRA_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * Platform BL31 specific defines.
+ ******************************************************************************/
+#define BL31_SIZE U(0x40000)
+
+/*******************************************************************************
+ * Power down state IDs
+ ******************************************************************************/
+#define PSTATE_ID_CORE_POWERDN U(7)
+#define PSTATE_ID_CLUSTER_IDLE U(16)
+#define PSTATE_ID_SOC_POWERDN U(27)
+
+/*******************************************************************************
+ * This value is used by the PSCI implementation during the `SYSTEM_SUSPEND`
+ * call as the `state-id` field in the 'power state' parameter.
+ ******************************************************************************/
+#define PLAT_SYS_SUSPEND_STATE_ID PSTATE_ID_SOC_POWERDN
+
+/*******************************************************************************
+ * Platform power states (used by PSCI framework)
+ *
+ * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID
+ * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID
+ ******************************************************************************/
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE (PSTATE_ID_SOC_POWERDN + U(1))
+
+/*******************************************************************************
+ * Chip specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 35)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 35)
+
+/*******************************************************************************
+ * SC7 entry firmware's header size
+ ******************************************************************************/
+#define SC7ENTRY_FW_HEADER_SIZE_BYTES U(0x400)
+
+/*******************************************************************************
+ * Counter-timer physical secure timer PPI
+ ******************************************************************************/
+#define TEGRA210_TIMER1_IRQ 32
+
+/*******************************************************************************
+ * iRAM memory constants
+ ******************************************************************************/
+#define TEGRA_IRAM_BASE U(0x40000000)
+#define TEGRA_IRAM_A_SIZE U(0x10000) /* 64KB */
+#define TEGRA_IRAM_SIZE U(40000) /* 256KB */
+
+/*******************************************************************************
+ * GIC memory map
+ ******************************************************************************/
+#define TEGRA_GICD_BASE U(0x50041000)
+#define TEGRA_GICC_BASE U(0x50042000)
+
+/*******************************************************************************
+ * Secure IRQ definitions
+ ******************************************************************************/
+#define TEGRA210_WDT_CPU_LEGACY_FIQ U(28)
+
+/*******************************************************************************
+ * Tegra Memory Select Switch Controller constants
+ ******************************************************************************/
+#define TEGRA_MSELECT_BASE U(0x50060000)
+
+#define MSELECT_CONFIG U(0x0)
+#define ENABLE_WRAP_INCR_MASTER2_BIT (U(1) << U(29))
+#define ENABLE_WRAP_INCR_MASTER1_BIT (U(1) << U(28))
+#define ENABLE_WRAP_INCR_MASTER0_BIT (U(1) << U(27))
+#define UNSUPPORTED_TX_ERR_MASTER2_BIT (U(1) << U(25))
+#define UNSUPPORTED_TX_ERR_MASTER1_BIT (U(1) << U(24))
+#define ENABLE_UNSUP_TX_ERRORS (UNSUPPORTED_TX_ERR_MASTER2_BIT | \
+ UNSUPPORTED_TX_ERR_MASTER1_BIT)
+#define ENABLE_WRAP_TO_INCR_BURSTS (ENABLE_WRAP_INCR_MASTER2_BIT | \
+ ENABLE_WRAP_INCR_MASTER1_BIT | \
+ ENABLE_WRAP_INCR_MASTER0_BIT)
+
+/*******************************************************************************
+ * Tegra Resource Semaphore constants
+ ******************************************************************************/
+#define TEGRA_RES_SEMA_BASE 0x60001000UL
+#define STA_OFFSET 0UL
+#define SET_OFFSET 4UL
+#define CLR_OFFSET 8UL
+
+/*******************************************************************************
+ * Tegra Primary Interrupt Controller constants
+ ******************************************************************************/
+#define TEGRA_PRI_ICTLR_BASE 0x60004000UL
+#define CPU_IEP_FIR_SET 0x18UL
+
+/*******************************************************************************
+ * Tegra micro-seconds timer constants
+ ******************************************************************************/
+#define TEGRA_TMRUS_BASE U(0x60005010)
+#define TEGRA_TMRUS_SIZE U(0x1000)
+
+/*******************************************************************************
+ * Tegra Clock and Reset Controller constants
+ ******************************************************************************/
+#define TEGRA_CAR_RESET_BASE U(0x60006000)
+#define TEGRA_BOND_OUT_H U(0x74)
+#define APB_DMA_LOCK_BIT (U(1) << 2)
+#define AHB_DMA_LOCK_BIT (U(1) << 1)
+#define TEGRA_BOND_OUT_U U(0x78)
+#define IRAM_D_LOCK_BIT (U(1) << 23)
+#define IRAM_C_LOCK_BIT (U(1) << 22)
+#define IRAM_B_LOCK_BIT (U(1) << 21)
+#define TEGRA_GPU_RESET_REG_OFFSET U(0x28C)
+#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x290)
+#define GPU_RESET_BIT (U(1) << 24)
+#define GPU_SET_BIT (U(1) << 24)
+#define TEGRA_RST_DEV_SET_Y U(0x2a8)
+#define NVENC_RESET_BIT (U(1) << 27)
+#define TSECB_RESET_BIT (U(1) << 14)
+#define APE_RESET_BIT (U(1) << 6)
+#define NVJPG_RESET_BIT (U(1) << 3)
+#define NVDEC_RESET_BIT (U(1) << 2)
+#define TEGRA_RST_DEV_SET_L U(0x300)
+#define HOST1X_RESET_BIT (U(1) << 28)
+#define ISP_RESET_BIT (U(1) << 23)
+#define USBD_RESET_BIT (U(1) << 22)
+#define VI_RESET_BIT (U(1) << 20)
+#define SDMMC4_RESET_BIT (U(1) << 15)
+#define SDMMC1_RESET_BIT (U(1) << 14)
+#define SDMMC2_RESET_BIT (U(1) << 9)
+#define TEGRA_RST_DEV_SET_H U(0x308)
+#define USB2_RESET_BIT (U(1) << 26)
+#define APBDMA_RESET_BIT (U(1) << 2)
+#define AHBDMA_RESET_BIT (U(1) << 1)
+#define TEGRA_RST_DEV_SET_U U(0x310)
+#define XUSB_DEV_RESET_BIT (U(1) << 31)
+#define XUSB_HOST_RESET_BIT (U(1) << 25)
+#define TSEC_RESET_BIT (U(1) << 19)
+#define PCIE_RESET_BIT (U(1) << 6)
+#define SDMMC3_RESET_BIT (U(1) << 5)
+#define TEGRA_RST_DEVICES_V U(0x358)
+#define TEGRA_RST_DEVICES_W U(0x35C)
+#define ENTROPY_CLK_ENB_BIT (U(1) << 21)
+#define TEGRA_CLK_OUT_ENB_V U(0x360)
+#define SE_CLK_ENB_BIT (U(1) << 31)
+#define TEGRA_CLK_OUT_ENB_W U(0x364)
+#define ENTROPY_RESET_BIT (U(1) << 21)
+#define TEGRA_CLK_RST_CTL_CLK_SRC_SE U(0x42C)
+#define SE_CLK_SRC_MASK (U(7) << 29)
+#define SE_CLK_SRC_CLK_M (U(6) << 29)
+#define TEGRA_RST_DEV_SET_V U(0x430)
+#define SE_RESET_BIT (U(1) << 31)
+#define HDA_RESET_BIT (U(1) << 29)
+#define SATA_RESET_BIT (U(1) << 28)
+#define TEGRA_RST_DEV_CLR_V U(0x434)
+#define TEGRA_CLK_ENB_V U(0x440)
+
+/*******************************************************************************
+ * Tegra Flow Controller constants
+ ******************************************************************************/
+#define TEGRA_FLOWCTRL_BASE U(0x60007000)
+
+/*******************************************************************************
+ * Tegra AHB arbitration controller
+ ******************************************************************************/
+#define TEGRA_AHB_ARB_BASE 0x6000C000UL
+
+/*******************************************************************************
+ * Tegra Secure Boot Controller constants
+ ******************************************************************************/
+#define TEGRA_SB_BASE U(0x6000C200)
+
+/*******************************************************************************
+ * Tegra Exception Vectors constants
+ ******************************************************************************/
+#define TEGRA_EVP_BASE U(0x6000F000)
+
+/*******************************************************************************
+ * Tegra Miscellaneous register constants
+ ******************************************************************************/
+#define TEGRA_MISC_BASE U(0x70000000)
+#define HARDWARE_REVISION_OFFSET U(0x804)
+#define APB_SLAVE_SECURITY_ENABLE U(0xC00)
+#define PMC_SECURITY_EN_BIT (U(1) << 13)
+#define PINMUX_AUX_DVFS_PWM U(0x3184)
+#define PINMUX_PWM_TRISTATE (U(1) << 4)
+
+/*******************************************************************************
+ * Tegra UART controller base addresses
+ ******************************************************************************/
+#define TEGRA_UARTA_BASE U(0x70006000)
+#define TEGRA_UARTB_BASE U(0x70006040)
+#define TEGRA_UARTC_BASE U(0x70006200)
+#define TEGRA_UARTD_BASE U(0x70006300)
+#define TEGRA_UARTE_BASE U(0x70006400)
+
+/*******************************************************************************
+ * Tegra Fuse Controller related constants
+ ******************************************************************************/
+#define TEGRA_FUSE_BASE 0x7000F800UL
+#define FUSE_BOOT_SECURITY_INFO 0x268UL
+#define FUSE_ATOMIC_SAVE_CARVEOUT_EN (0x1U << 7)
+#define FUSE_JTAG_SECUREID_VALID (0x104UL)
+#define ECID_VALID (0x1UL)
+
+
+/*******************************************************************************
+ * Tegra Power Mgmt Controller constants
+ ******************************************************************************/
+#define TEGRA_PMC_BASE U(0x7000E400)
+#define TEGRA_PMC_SIZE U(0xC00) /* 3k */
+
+/*******************************************************************************
+ * Tegra Atomics constants
+ ******************************************************************************/
+#define TEGRA_ATOMICS_BASE 0x70016000UL
+#define TRIGGER0_REG_OFFSET 0UL
+#define TRIGGER_WIDTH_SHIFT 4UL
+#define TRIGGER_ID_SHIFT 16UL
+#define RESULT0_REG_OFFSET 0xC00UL
+
+/*******************************************************************************
+ * Tegra Memory Controller constants
+ ******************************************************************************/
+#define TEGRA_MC_BASE U(0x70019000)
+
+/* Memory Controller Interrupt Status */
+#define MC_INTSTATUS 0x00U
+
+/* TZDRAM carveout configuration registers */
+#define MC_SECURITY_CFG0_0 U(0x70)
+#define MC_SECURITY_CFG1_0 U(0x74)
+#define MC_SECURITY_CFG3_0 U(0x9BC)
+
+/* Video Memory carveout configuration registers */
+#define MC_VIDEO_PROTECT_BASE_HI U(0x978)
+#define MC_VIDEO_PROTECT_BASE_LO U(0x648)
+#define MC_VIDEO_PROTECT_SIZE_MB U(0x64c)
+#define MC_VIDEO_PROTECT_REG_CTRL U(0x650)
+#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED U(3)
+
+/* SMMU configuration registers*/
+#define MC_SMMU_PPCS_ASID_0 0x270U
+#define PPCS_SMMU_ENABLE (0x1U << 31)
+
+/*******************************************************************************
+ * Tegra CLDVFS constants
+ ******************************************************************************/
+#define TEGRA_CL_DVFS_BASE U(0x70110000)
+#define DVFS_DFLL_CTRL U(0x00)
+#define ENABLE_OPEN_LOOP U(1)
+#define ENABLE_CLOSED_LOOP U(2)
+#define DVFS_DFLL_OUTPUT_CFG U(0x20)
+#define DFLL_OUTPUT_CFG_I2C_EN_BIT (U(1) << 30)
+#define DFLL_OUTPUT_CFG_CLK_EN_BIT (U(1) << 6)
+
+/*******************************************************************************
+ * Tegra SE constants
+ ******************************************************************************/
+#define TEGRA_SE1_BASE U(0x70012000)
+#define TEGRA_SE2_BASE U(0x70412000)
+#define TEGRA_PKA1_BASE U(0x70420000)
+#define TEGRA_SE2_RANGE_SIZE U(0x2000)
+#define SE_TZRAM_SECURITY U(0x4)
+
+/*******************************************************************************
+ * Tegra TZRAM constants
+ ******************************************************************************/
+#define TEGRA_TZRAM_BASE U(0x7C010000)
+#define TEGRA_TZRAM_SIZE U(0x10000)
+
+/*******************************************************************************
+ * Tegra TZRAM carveout constants
+ ******************************************************************************/
+#define TEGRA_TZRAM_CARVEOUT_BASE U(0x7C04C000)
+#define TEGRA_TZRAM_CARVEOUT_SIZE U(0x4000)
+
+/*******************************************************************************
+ * Tegra DRAM memory base address
+ ******************************************************************************/
+#define TEGRA_DRAM_BASE ULL(0x80000000)
+#define TEGRA_DRAM_END ULL(0x27FFFFFFF)
+
+#endif /* TEGRA_DEF_H */
diff --git a/plat/nvidia/tegra/include/tegra_platform.h b/plat/nvidia/tegra/include/tegra_platform.h
new file mode 100644
index 0000000..ab51dfe
--- /dev/null
+++ b/plat/nvidia/tegra/include/tegra_platform.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA_PLATFORM_H
+#define TEGRA_PLATFORM_H
+
+#include <cdefs.h>
+#include <lib/utils_def.h>
+#include <stdbool.h>
+
+/*******************************************************************************
+ * Tegra major, minor version helper macros
+ ******************************************************************************/
+#define MAJOR_VERSION_SHIFT U(0x4)
+#define MAJOR_VERSION_MASK U(0xF)
+#define MINOR_VERSION_SHIFT U(0x10)
+#define MINOR_VERSION_MASK U(0xF)
+#define CHIP_ID_SHIFT U(8)
+#define CHIP_ID_MASK U(0xFF)
+#define PRE_SI_PLATFORM_SHIFT U(0x14)
+#define PRE_SI_PLATFORM_MASK U(0xF)
+
+/*******************************************************************************
+ * Tegra chip ID values
+ ******************************************************************************/
+#define TEGRA_CHIPID_TEGRA13 U(0x13)
+#define TEGRA_CHIPID_TEGRA21 U(0x21)
+#define TEGRA_CHIPID_TEGRA18 U(0x18)
+#define TEGRA_CHIPID_TEGRA19 U(0x19)
+
+/*******************************************************************************
+ * JEDEC Standard Manufacturer's Identification Code and Bank ID
+ ******************************************************************************/
+#define JEDEC_NVIDIA_MFID U(0x6B)
+#define JEDEC_NVIDIA_BKID U(3)
+
+#ifndef __ASSEMBLER__
+
+/*
+ * Tegra chip ID major/minor identifiers
+ */
+uint32_t tegra_get_chipid_major(void);
+uint32_t tegra_get_chipid_minor(void);
+
+/*
+ * Tegra chip ID identifiers
+ */
+bool tegra_chipid_is_t186(void);
+bool tegra_chipid_is_t210(void);
+bool tegra_chipid_is_t210_b01(void);
+bool tegra_chipid_is_t194(void);
+
+/*
+ * Tegra platform identifiers
+ */
+bool tegra_platform_is_silicon(void);
+bool tegra_platform_is_qt(void);
+bool tegra_platform_is_emulation(void);
+bool tegra_platform_is_linsim(void);
+bool tegra_platform_is_fpga(void);
+bool tegra_platform_is_unit_fpga(void);
+bool tegra_platform_is_virt_dev_kit(void);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* TEGRA_PLATFORM_H */
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
new file mode 100644
index 0000000..cc2ad86
--- /dev/null
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA_PRIVATE_H
+#define TEGRA_PRIVATE_H
+
+#include <platform_def.h>
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/psci/psci.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <tegra_gic.h>
+
+/*******************************************************************************
+ * Implementation defined ACTLR_EL1 bit definitions
+ ******************************************************************************/
+#define ACTLR_EL1_PMSTATE_MASK (ULL(0xF) << 0)
+
+/*******************************************************************************
+ * Implementation defined ACTLR_EL2 bit definitions
+ ******************************************************************************/
+#define ACTLR_EL2_PMSTATE_MASK (ULL(0xF) << 0)
+
+/*******************************************************************************
+ * Struct for parameters received from BL2
+ ******************************************************************************/
+typedef struct plat_params_from_bl2 {
+ /* TZ memory size */
+ uint64_t tzdram_size;
+ /* TZ memory base */
+ uint64_t tzdram_base;
+ /* UART port ID */
+ int32_t uart_id;
+ /* L2 ECC parity protection disable flag */
+ int32_t l2_ecc_parity_prot_dis;
+ /* SHMEM base address for storing the boot logs */
+ uint64_t boot_profiler_shmem_base;
+ /* System Suspend Entry Firmware size */
+ uint64_t sc7entry_fw_size;
+ /* System Suspend Entry Firmware base address */
+ uint64_t sc7entry_fw_base;
+ /* Enable dual execution */
+ uint8_t enable_ccplex_lock_step;
+} plat_params_from_bl2_t;
+
+/*******************************************************************************
+ * Helper function to access l2ctlr_el1 register on Cortex-A57 CPUs
+ ******************************************************************************/
+DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, CORTEX_A57_L2CTLR_EL1)
+
+/*******************************************************************************
+ * Struct describing parameters passed to bl31
+ ******************************************************************************/
+struct tegra_bl31_params {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+};
+
+/*******************************************************************************
+* To suppress Coverity MISRA C-2012 Rule 2.2 violations
+*******************************************************************************/
+#define UNUSED_FUNC_NOP() asm("nop")
+
+/* Declarations for plat_psci_handlers.c */
+int32_t tegra_soc_validate_power_state(uint32_t power_state,
+ psci_power_state_t *req_state);
+
+/* Declarations for plat_setup.c */
+const mmap_region_t *plat_get_mmio_map(void);
+void plat_enable_console(int32_t id);
+void plat_gic_setup(void);
+struct tegra_bl31_params *plat_get_bl31_params(void);
+plat_params_from_bl2_t *plat_get_bl31_plat_params(void);
+void plat_early_platform_setup(void);
+void plat_late_platform_setup(void);
+void plat_relocate_bl32_image(const image_info_t *bl32_img_info);
+bool plat_supports_system_suspend(void);
+void plat_runtime_setup(void);
+
+/* Declarations for plat_secondary.c */
+void plat_secondary_setup(void);
+int32_t plat_lock_cpu_vectors(void);
+
+/* Declarations for tegra_fiq_glue.c */
+void tegra_fiq_handler_setup(void);
+int32_t tegra_fiq_get_intr_context(void);
+void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint);
+
+/* Declarations for tegra_security.c */
+void tegra_security_setup(void);
+void tegra_security_setup_videomem(uintptr_t base, uint64_t size);
+
+/* Declarations for tegra_pm.c */
+void tegra_pm_system_suspend_entry(void);
+void tegra_pm_system_suspend_exit(void);
+int32_t tegra_system_suspended(void);
+int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state);
+int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state);
+int32_t tegra_soc_pwr_domain_on(u_register_t mpidr);
+int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state);
+int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state);
+int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state);
+int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state);
+int32_t tegra_soc_prepare_system_reset(void);
+__dead2 void tegra_soc_prepare_system_off(void);
+plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
+ const plat_local_state_t *states,
+ uint32_t ncpu);
+
+/* Declarations for tegraXXX_pm.c */
+int tegra_prepare_cpu_suspend(unsigned int id, unsigned int afflvl);
+int tegra_prepare_cpu_on_finish(unsigned long mpidr);
+
+/* Declarations for tegra_bl31_setup.c */
+plat_params_from_bl2_t *bl31_get_plat_params(void);
+int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes);
+
+/* Declarations for tegra_delay_timer.c */
+void tegra_delay_timer_init(void);
+
+void tegra_secure_entrypoint(void);
+
+/* Declarations for tegra_sip_calls.c */
+uintptr_t tegra_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags);
+int plat_sip_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ const void *cookie,
+ void *handle,
+ uint64_t flags);
+
+#if RAS_EXTENSION
+void tegra194_ras_enable(void);
+void tegra194_ras_corrected_err_clear(uint64_t *cookie);
+#endif
+
+#endif /* TEGRA_PRIVATE_H */
diff --git a/plat/nvidia/tegra/lib/debug/profiler.c b/plat/nvidia/tegra/lib/debug/profiler.c
new file mode 100644
index 0000000..dd76a4e
--- /dev/null
+++ b/plat/nvidia/tegra/lib/debug/profiler.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*******************************************************************************
+ * The profiler stores the timestamps captured during cold boot to the shared
+ * memory for the non-secure world. The non-secure world driver parses the
+ * shared memory block and writes the contents to a file on the device, which
+ * can be later extracted for analysis.
+ *
+ * Profiler memory map
+ *
+ * TOP --------------------------- ---
+ * Trusted OS timestamps 3KB
+ * --------------------------- ---
+ * Trusted Firmware timestamps 1KB
+ * BASE --------------------------- ---
+ *
+ ******************************************************************************/
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <profiler.h>
+#include <stdbool.h>
+#include <string.h>
+
+static uint64_t shmem_base_addr;
+
+#define MAX_PROFILER_RECORDS U(16)
+#define TAG_LEN_BYTES U(56)
+
+/*******************************************************************************
+ * Profiler entry format
+ ******************************************************************************/
+typedef struct {
+ /* text explaining the timestamp location in code */
+ uint8_t tag[TAG_LEN_BYTES];
+ /* timestamp value */
+ uint64_t timestamp;
+} profiler_rec_t;
+
+static profiler_rec_t *head, *cur, *tail;
+static uint32_t tmr;
+static bool is_shmem_buf_mapped;
+
+/*******************************************************************************
+ * Initialise the profiling library
+ ******************************************************************************/
+void boot_profiler_init(uint64_t shmem_base, uint32_t tmr_base)
+{
+ uint64_t shmem_end_base;
+
+ assert(shmem_base != ULL(0));
+ assert(tmr_base != U(0));
+
+ /* store the buffer address */
+ shmem_base_addr = shmem_base;
+
+ /* calculate the base address of the last record */
+ shmem_end_base = shmem_base + (sizeof(profiler_rec_t) *
+ (MAX_PROFILER_RECORDS - U(1)));
+
+ /* calculate the head, tail and cur values */
+ head = (profiler_rec_t *)shmem_base;
+ tail = (profiler_rec_t *)shmem_end_base;
+ cur = head;
+
+ /* timer used to get the current timestamp */
+ tmr = tmr_base;
+}
+
+/*******************************************************************************
+ * Add tag and timestamp to profiler
+ ******************************************************************************/
+void boot_profiler_add_record(const char *str)
+{
+ unsigned int len;
+
+ /* calculate the length of the tag */
+ if (((unsigned int)strlen(str) + U(1)) > TAG_LEN_BYTES) {
+ len = TAG_LEN_BYTES;
+ } else {
+ len = (unsigned int)strlen(str) + U(1);
+ }
+
+ if (head != NULL) {
+
+ /*
+ * The profiler runs with/without MMU enabled. Check
+ * if MMU is enabled and memmap the shmem buffer, in
+ * case it is.
+ */
+ if ((!is_shmem_buf_mapped) &&
+ ((read_sctlr_el3() & SCTLR_M_BIT) != U(0))) {
+
+ (void)mmap_add_dynamic_region(shmem_base_addr,
+ shmem_base_addr,
+ PROFILER_SIZE_BYTES,
+ (MT_NS | MT_RW | MT_EXECUTE_NEVER));
+
+ is_shmem_buf_mapped = true;
+ }
+
+ /* write the tag and timestamp to buffer */
+ (void)snprintf((char *)cur->tag, len, "%s", str);
+ cur->timestamp = mmio_read_32(tmr);
+
+ /* start from head if we reached the end */
+ if (cur == tail) {
+ cur = head;
+ } else {
+ cur++;
+ }
+ }
+}
+
+/*******************************************************************************
+ * Deinint the profiler
+ ******************************************************************************/
+void boot_profiler_deinit(void)
+{
+ if (shmem_base_addr != ULL(0)) {
+
+ /* clean up resources */
+ cur = NULL;
+ head = NULL;
+ tail = NULL;
+
+ /* flush the shmem for it to be visible to the NS world */
+ flush_dcache_range(shmem_base_addr, PROFILER_SIZE_BYTES);
+
+ /* unmap the shmem buffer */
+ if (is_shmem_buf_mapped) {
+ (void)mmap_remove_dynamic_region(shmem_base_addr,
+ PROFILER_SIZE_BYTES);
+ }
+ }
+}
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
new file mode 100644
index 0000000..6ed1cdf
--- /dev/null
+++ b/plat/nvidia/tegra/platform.mk
@@ -0,0 +1,97 @@
+#
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+SOC_DIR := plat/nvidia/tegra/soc/${TARGET_SOC}
+
+# dump the state on crash console
+CRASH_REPORTING := 1
+$(eval $(call add_define,CRASH_REPORTING))
+
+# enable assert() for release/debug builds
+ENABLE_ASSERTIONS := 1
+PLAT_LOG_LEVEL_ASSERT := 50
+$(eval $(call add_define,PLAT_LOG_LEVEL_ASSERT))
+
+# enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC := 1
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
+
+# Enable exception handling at EL3
+EL3_EXCEPTION_HANDLING := 1
+GICV2_G0_FOR_EL3 := 1
+
+# Enable PSCI v1.0 extended state ID format
+PSCI_EXTENDED_STATE_ID := 1
+
+# code and read-only data should be put on separate memory pages
+SEPARATE_CODE_AND_RODATA := 1
+
+# do not use coherent memory
+USE_COHERENT_MEM := 0
+
+# enable D-cache early during CPU warmboot
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
+
+# remove the standard libc
+OVERRIDE_LIBC := 1
+
+# Flag to enable WDT FIQ interrupt handling for Tegra SoCs
+# prior to Tegra186
+ENABLE_TEGRA_WDT_LEGACY_FIQ_HANDLING ?= 0
+
+# Flag to allow relocation of BL32 image to TZDRAM during boot
+RELOCATE_BL32_IMAGE ?= 0
+
+# Enable stack protection
+ENABLE_STACK_PROTECTOR := strong
+
+# Enable SDEI
+SDEI_SUPPORT := 1
+
+# modify BUILD_PLAT to point to SoC specific build directory
+BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_SOC}/${BUILD_TYPE}
+
+include plat/nvidia/tegra/common/tegra_common.mk
+include ${SOC_DIR}/platform_${TARGET_SOC}.mk
+
+$(eval $(call add_define,ENABLE_TEGRA_WDT_LEGACY_FIQ_HANDLING))
+$(eval $(call add_define,RELOCATE_BL32_IMAGE))
+
+# platform cflags (enable signed comparisons, disable stdlib)
+TF_CFLAGS += -nostdlib
+
+# override with necessary libc files for the Tegra platform
+override LIBC_SRCS := $(addprefix lib/libc/, \
+ aarch64/setjmp.S \
+ assert.c \
+ memchr.c \
+ memcmp.c \
+ memcpy.c \
+ memmove.c \
+ memset.c \
+ printf.c \
+ putchar.c \
+ strrchr.c \
+ strlen.c \
+ snprintf.c)
+
+INCLUDES += -Iinclude/lib/libc \
+ -Iinclude/lib/libc/$(ARCH) \
+
+ifneq ($(findstring armlink,$(notdir $(LD))),)
+# o suppress warnings for section mismatches, undefined symbols
+# o use only those libraries that are specified in the input file
+# list to resolve references
+# o create a static callgraph of functions
+# o resolve undefined symbols to el3_panic
+# o include only required sections
+TF_LDFLAGS += --diag_suppress=L6314,L6332 --no_scanlib --callgraph
+TF_LDFLAGS += --keep="*(__pubsub*)" --keep="*(rt_svc_descs*)" --keep="*(*cpu_ops)"
+ifeq (${ENABLE_PMF},1)
+TF_LDFLAGS += --keep="*(*pmf_svc_descs*)"
+endif
+endif
diff --git a/plat/nvidia/tegra/scat/bl31.scat b/plat/nvidia/tegra/scat/bl31.scat
new file mode 100644
index 0000000..2d6d2b3
--- /dev/null
+++ b/plat/nvidia/tegra/scat/bl31.scat
@@ -0,0 +1,284 @@
+#! armclang -E -x c
+
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#define PAGE_SIZE (1024 * 4)
+
+LR_START BL31_BASE
+{
+ __BL31_START__ +0 FIXED EMPTY 0
+ {
+ /* placeholder */
+ }
+
+ /* BL31_BASE address must be aligned on a page boundary. */
+ ScatterAssert((ImageBase(__BL31_START__) AND 0xFFF) == 0)
+}
+
+LR_TEXT BL31_BASE
+{
+ __TEXT__ +0 FIXED
+ {
+ *(:gdef:bl31_entrypoint, +FIRST)
+ *(.text*)
+ *(.vectors)
+ .ANY1(+RO-CODE)
+ }
+
+ __TEXT_EPILOGUE__ AlignExpr(+0, PAGE_SIZE) FIXED EMPTY 0
+ {
+ /* section delimiter */
+ }
+}
+
+LR_RO_DATA +0
+{
+ __RODATA__ AlignExpr(ImageLimit(LR_TEXT), 0) FIXED
+ {
+ *(.rodata*)
+ .ANY2(+RO-DATA)
+ }
+
+ /* Ensure 8-byte alignment for descriptors and ensure inclusion */
+ __RT_SVC_DESCS__ AlignExpr(ImageLimit(__RODATA__), 8) FIXED
+ {
+ *(rt_svc_descs)
+ }
+
+#if ENABLE_PMF
+ /* Ensure 8-byte alignment for descriptors and ensure inclusion */
+ __PMF_SVC_DESCS__ AlignExpr(ImageLimit(__RT_SVC_DESCS__), 8) FIXED
+ {
+ *(pmf_svc_descs)
+ }
+#endif /* ENABLE_PMF */
+
+ /*
+ * Ensure 8-byte alignment for cpu_ops so that its fields are also
+ * aligned.
+ */
+ __CPU_OPS__ AlignExpr(+0, 8) FIXED
+ {
+ *(cpu_ops)
+ }
+
+ /*
+ * Keep the .got section in the RO section as it is patched
+ * prior to enabling the MMU and having the .got in RO is better for
+ * security. GOT is a table of addresses so ensure 8-byte alignment.
+ */
+ __GOT__ AlignExpr(ImageLimit(__CPU_OPS__), 8) FIXED
+ {
+ *(.got)
+ }
+
+ /* Place pubsub sections for events */
+ __PUBSUB_EVENTS__ AlignExpr(+0, 8) EMPTY 0
+ {
+ /* placeholder */
+ }
+
+#include <lib/el3_runtime/pubsub_events.h>
+
+ __RODATA_EPILOGUE__ AlignExpr(+0, PAGE_SIZE) FIXED EMPTY 0
+ {
+ /* section delimiter */
+ }
+}
+
+ /* cpu_ops must always be defined */
+ ScatterAssert(ImageLength(__CPU_OPS__) > 0)
+
+#if SPM_MM
+LR_SPM +0
+{
+ /*
+ * Exception vectors of the SPM shim layer. They must be aligned to a 2K
+ * address, but we need to place them in a separate page so that we can set
+ * individual permissions to them, so the actual alignment needed is 4K.
+ *
+ * There's no need to include this into the RO section of BL31 because it
+ * doesn't need to be accessed by BL31.
+ */
+ __SPM_SHIM_EXCEPTIONS__ AlignExpr(ImageLimit(LR_RO_DATA), PAGE_SIZE) FIXED
+ {
+ *(.spm_shim_exceptions)
+ }
+
+ __SPM_SHIM_EXCEPTIONS_EPILOGUE__ AlignExpr(ImageLimit(__SPM_SHIM_EXCEPTIONS__), PAGE_SIZE) FIXED
+ {
+ /* placeholder */
+ }
+}
+#endif
+
+LR_RW_DATA +0
+{
+ __DATA__ AlignExpr(+0, 16) FIXED
+ {
+ *(.data*)
+ *(.constdata)
+ *(locale$$data)
+ }
+}
+
+LR_RELA +0
+{
+ /*
+ * .rela.dyn needs to come after .data for the read-elf utility to parse
+ * this section correctly. Ensure 8-byte alignment so that the fields of
+ * RELA data structure are aligned.
+ */
+ __RELA__ AlignExpr(ImageLimit(LR_RW_DATA), 8) FIXED
+ {
+ *(.rela.dyn)
+ }
+}
+
+#ifdef BL31_PROGBITS_LIMIT
+ /* BL31 progbits has exceeded its limit. */
+ ScatterAssert(ImageLimit(LR_RELA) <= BL31_PROGBITS_LIMIT)
+#endif
+
+LR_STACKS +0
+{
+ __STACKS__ AlignExpr(+0, 64) FIXED
+ {
+ *(tzfw_normal_stacks)
+ }
+}
+
+#define __BAKERY_LOCK_SIZE__ (ImageLimit(__BAKERY_LOCKS_EPILOGUE__) - \
+ ImageBase(__BAKERY_LOCKS__))
+#define BAKERY_LOCK_SIZE (__BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1))
+#define __PMF_TIMESTAMP_SIZE__ (ImageLimit(__PMF_TIMESTAMP__) - \
+ ImageBase(__PMF_TIMESTAMP__))
+#define PER_CPU_TIMESTAMP_SIZE (__PMF_TIMESTAMP_SIZE__ * (PLATFORM_CORE_COUNT - 1))
+
+LR_BSS +0
+{
+ __BSS__ AlignExpr(ImageLimit(LR_STACKS), 256) FIXED
+ {
+ *(.bss*)
+ *(COMDAT)
+ }
+
+#if !USE_COHERENT_MEM
+ /*
+ * Bakery locks are stored in normal .bss memory
+ *
+ * Each lock's data is spread across multiple cache lines, one per CPU,
+ * but multiple locks can share the same cache line.
+ * The compiler will allocate enough memory for one CPU's bakery locks,
+ * the remaining cache lines are allocated by the linker script
+ */
+ __BAKERY_LOCKS__ AlignExpr(ImageLimit(__BSS__), CACHE_WRITEBACK_GRANULE) FIXED
+ {
+ *(bakery_lock)
+ }
+
+ __BAKERY_LOCKS_EPILOGUE__ AlignExpr(ImageLimit(__BAKERY_LOCKS__), CACHE_WRITEBACK_GRANULE) FIXED EMPTY 0
+ {
+ /* section delimiter */
+ }
+
+ __PER_CPU_BAKERY_LOCKS__ ImageLimit(__BAKERY_LOCKS_EPILOGUE__) FIXED FILL 0 BAKERY_LOCK_SIZE
+ {
+ /* padded memory section to store per cpu bakery locks */
+ }
+
+#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE
+ /* PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements */
+ ScatterAssert(__PER_CPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE)
+#endif
+#endif
+
+#if ENABLE_PMF
+ /*
+ * Time-stamps are stored in normal .bss memory
+ *
+ * The compiler will allocate enough memory for one CPU's time-stamps,
+ * the remaining memory for other CPU's is allocated by the
+ * linker script
+ */
+ __PMF_TIMESTAMP__ AlignExpr(+0, CACHE_WRITEBACK_GRANULE) FIXED EMPTY CACHE_WRITEBACK_GRANULE
+ {
+ /* store timestamps in this carved out memory */
+ }
+
+ __PMF_TIMESTAMP_EPILOGUE__ AlignExpr(ImageLimit(__PMF_TIMESTAMP__), CACHE_WRITEBACK_GRANULE) FIXED EMPTY 0
+ {
+ /*
+ * placeholder to make __PMF_TIMESTAMP_START__ end on a
+ * CACHE_WRITEBACK_GRANULE boundary
+ */
+ }
+
+ __PER_CPU_TIMESTAMPS__ +0 FIXED FILL 0 PER_CPU_TIMESTAMP_SIZE
+ {
+ /* padded memory section to store per cpu timestamps */
+ }
+#endif /* ENABLE_PMF */
+}
+
+LR_XLAT_TABLE +0
+{
+ xlat_table +0 FIXED
+ {
+ *(xlat_table)
+ }
+}
+
+#if USE_COHERENT_MEM
+LR_COHERENT_RAM +0
+{
+ /*
+ * The base address of the coherent memory section must be page-aligned (4K)
+ * to guarantee that the coherent data are stored on their own pages and
+ * are not mixed with normal data. This is required to set up the correct
+ * memory attributes for the coherent data page tables.
+ */
+ __COHERENT_RAM__ AlignExpr(+0, PAGE_SIZE) FIXED
+ {
+ /*
+ * Bakery locks are stored in coherent memory
+ *
+ * Each lock's data is contiguous and fully allocated by the compiler
+ */
+ *(bakery_lock)
+ *(tzfw_coherent_mem)
+ }
+
+ __COHERENT_RAM_EPILOGUE_UNALIGNED__ +0 FIXED EMPTY 0
+ {
+ /* section delimiter */
+ }
+
+ /*
+ * Memory page(s) mapped to this section will be marked
+ * as device memory. No other unexpected data must creep in.
+ * Ensure the rest of the current memory page is unused.
+ */
+ __COHERENT_RAM_EPILOGUE__ AlignExpr(ImageLimit(__COHERENT_RAM_START__), PAGE_SIZE) FIXED EMPTY 0
+ {
+ /* section delimiter */
+ }
+}
+#endif
+
+LR_END +0
+{
+ __BL31_END__ +0 FIXED EMPTY 0
+ {
+ /* placeholder */
+ }
+
+ /* BL31 image has exceeded its limit. */
+ ScatterAssert(ImageLimit(__BL31_END__) <= BL31_LIMIT)
+}
diff --git a/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h b/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h
new file mode 100644
index 0000000..203f61a
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCE_PRIVATE_H
+#define MCE_PRIVATE_H
+
+#include <lib/mmio.h>
+
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * Macros to prepare CSTATE info request
+ ******************************************************************************/
+/* Description of the parameters for UPDATE_CSTATE_INFO request */
+#define CLUSTER_CSTATE_MASK ULL(0x7)
+#define CLUSTER_CSTATE_SHIFT U(0)
+#define CLUSTER_CSTATE_UPDATE_BIT (ULL(1) << 7)
+#define CCPLEX_CSTATE_MASK ULL(0x3)
+#define CCPLEX_CSTATE_SHIFT ULL(8)
+#define CCPLEX_CSTATE_UPDATE_BIT (ULL(1) << 15)
+#define SYSTEM_CSTATE_MASK ULL(0xF)
+#define SYSTEM_CSTATE_SHIFT ULL(16)
+#define SYSTEM_CSTATE_FORCE_UPDATE_SHIFT ULL(22)
+#define SYSTEM_CSTATE_FORCE_UPDATE_BIT (ULL(1) << 22)
+#define SYSTEM_CSTATE_UPDATE_BIT (ULL(1) << 23)
+#define CSTATE_WAKE_MASK_UPDATE_BIT (ULL(1) << 31)
+#define CSTATE_WAKE_MASK_SHIFT ULL(32)
+#define CSTATE_WAKE_MASK_CLEAR U(0xFFFFFFFF)
+
+/*******************************************************************************
+ * Auto-CC3 control macros
+ ******************************************************************************/
+#define MCE_AUTO_CC3_FREQ_MASK U(0x1FF)
+#define MCE_AUTO_CC3_FREQ_SHIFT U(0)
+#define MCE_AUTO_CC3_VTG_MASK U(0x7F)
+#define MCE_AUTO_CC3_VTG_SHIFT U(16)
+#define MCE_AUTO_CC3_ENABLE_BIT (U(1) << 31)
+
+/*******************************************************************************
+ * Macros for the 'IS_SC7_ALLOWED' command
+ ******************************************************************************/
+#define MCE_SC7_ALLOWED_MASK U(0x7)
+#define MCE_SC7_WAKE_TIME_SHIFT U(32)
+
+/*******************************************************************************
+ * Macros for 'read/write ctats' commands
+ ******************************************************************************/
+#define MCE_CSTATE_STATS_TYPE_SHIFT ULL(32)
+#define MCE_CSTATE_WRITE_DATA_LO_MASK U(0xF)
+
+/*******************************************************************************
+ * Macros for 'update crossover threshold' command
+ ******************************************************************************/
+#define MCE_CROSSOVER_THRESHOLD_TIME_SHIFT U(32)
+
+/*******************************************************************************
+ * MCA argument macros
+ ******************************************************************************/
+#define MCA_ARG_ERROR_MASK U(0xFF)
+#define MCA_ARG_FINISH_SHIFT U(24)
+#define MCA_ARG_FINISH_MASK U(0xFF)
+
+/*******************************************************************************
+ * Uncore PERFMON ARI macros
+ ******************************************************************************/
+#define UNCORE_PERFMON_CMD_READ U(0)
+#define UNCORE_PERFMON_CMD_WRITE U(1)
+
+#define UNCORE_PERFMON_CMD_MASK U(0xFF)
+#define UNCORE_PERFMON_UNIT_GRP_MASK U(0xF)
+#define UNCORE_PERFMON_SELECTOR_MASK U(0xF)
+#define UNCORE_PERFMON_REG_MASK U(0xFF)
+#define UNCORE_PERFMON_CTR_MASK U(0xFF)
+#define UNCORE_PERFMON_RESP_STATUS_MASK U(0xFF)
+
+/*******************************************************************************
+ * Structure populated by arch specific code to export routines which perform
+ * common low level MCE functions
+ ******************************************************************************/
+typedef struct arch_mce_ops {
+ /*
+ * This ARI request sets up the MCE to start execution on assertion
+ * of STANDBYWFI, update the core power state and expected wake time,
+ * then determine the proper power state to enter.
+ */
+ int32_t (*enter_cstate)(uint32_t ari_base, uint32_t state,
+ uint32_t wake_time);
+ /*
+ * This ARI request allows updating of the CLUSTER_CSTATE,
+ * CCPLEX_CSTATE, and SYSTEM_CSTATE register values.
+ */
+ int32_t (*update_cstate_info)(uint32_t ari_base,
+ uint32_t cluster,
+ uint32_t ccplex,
+ uint32_t system,
+ uint8_t sys_state_force,
+ uint32_t wake_mask,
+ uint8_t update_wake_mask);
+ /*
+ * This ARI request allows updating of power state crossover
+ * threshold times. An index value specifies which crossover
+ * state is being updated.
+ */
+ int32_t (*update_crossover_time)(uint32_t ari_base,
+ uint32_t type,
+ uint32_t time);
+ /*
+ * This ARI request allows read access to statistical information
+ * related to power states.
+ */
+ uint64_t (*read_cstate_stats)(uint32_t ari_base,
+ uint32_t state);
+ /*
+ * This ARI request allows write access to statistical information
+ * related to power states.
+ */
+ int32_t (*write_cstate_stats)(uint32_t ari_base,
+ uint32_t state,
+ uint32_t stats);
+ /*
+ * This ARI request allows the CPU to understand the features
+ * supported by the MCE firmware.
+ */
+ uint64_t (*call_enum_misc)(uint32_t ari_base, uint32_t cmd,
+ uint32_t data);
+ /*
+ * This ARI request allows querying the CCPLEX to determine if
+ * the CCx state is allowed given a target core C-state and wake
+ * time. If the CCx state is allowed, the response indicates CCx
+ * must be entered. If the CCx state is not allowed, the response
+ * indicates CC6/CC7 can't be entered
+ */
+ int32_t (*is_ccx_allowed)(uint32_t ari_base, uint32_t state,
+ uint32_t wake_time);
+ /*
+ * This ARI request allows querying the CCPLEX to determine if
+ * the SC7 state is allowed given a target core C-state and wake
+ * time. If the SC7 state is allowed, all cores but the associated
+ * core are offlined (WAKE_EVENTS are set to 0) and the response
+ * indicates SC7 must be entered. If the SC7 state is not allowed,
+ * the response indicates SC7 can't be entered
+ */
+ int32_t (*is_sc7_allowed)(uint32_t ari_base, uint32_t state,
+ uint32_t wake_time);
+ /*
+ * This ARI request allows a core to bring another offlined core
+ * back online to the C0 state. Note that a core is offlined by
+ * entering a C-state where the WAKE_MASK is all 0.
+ */
+ int32_t (*online_core)(uint32_t ari_base, uint32_t cpuid);
+ /*
+ * This ARI request allows the CPU to enable/disable Auto-CC3 idle
+ * state.
+ */
+ int32_t (*cc3_ctrl)(uint32_t ari_base,
+ uint32_t freq,
+ uint32_t volt,
+ uint8_t enable);
+ /*
+ * This ARI request allows updating the reset vector register for
+ * D15 and A57 CPUs.
+ */
+ int32_t (*update_reset_vector)(uint32_t ari_base);
+ /*
+ * This ARI request instructs the ROC to flush A57 data caches in
+ * order to maintain coherency with the Denver cluster.
+ */
+ int32_t (*roc_flush_cache)(uint32_t ari_base);
+ /*
+ * This ARI request instructs the ROC to flush A57 data caches along
+ * with the caches covering ARM code in order to maintain coherency
+ * with the Denver cluster.
+ */
+ int32_t (*roc_flush_cache_trbits)(uint32_t ari_base);
+ /*
+ * This ARI request instructs the ROC to clean A57 data caches along
+ * with the caches covering ARM code in order to maintain coherency
+ * with the Denver cluster.
+ */
+ int32_t (*roc_clean_cache)(uint32_t ari_base);
+ /*
+ * This ARI request reads/writes the Machine Check Arch. (MCA)
+ * registers.
+ */
+ uint64_t (*read_write_mca)(uint32_t ari_base,
+ uint64_t cmd,
+ uint64_t *data);
+ /*
+ * Some MC GSC (General Security Carveout) register values are
+ * expected to be changed by TrustZone secure ARM code after boot.
+ * Since there is no hardware mechanism for the CCPLEX to know
+ * that an MC GSC register has changed to allow it to update its
+ * own internal GSC register, there needs to be a mechanism that
+ * can be used by ARM code to cause the CCPLEX to update its GSC
+ * register value. This ARI request allows updating the GSC register
+ * value for a certain carveout in the CCPLEX.
+ */
+ int32_t (*update_ccplex_gsc)(uint32_t ari_base, uint32_t gsc_idx);
+ /*
+ * This ARI request instructs the CCPLEX to either shutdown or
+ * reset the entire system
+ */
+ void (*enter_ccplex_state)(uint32_t ari_base, uint32_t state_idx);
+ /*
+ * This ARI request reads/writes data from/to Uncore PERFMON
+ * registers
+ */
+ int32_t (*read_write_uncore_perfmon)(uint32_t ari_base,
+ uint64_t req, uint64_t *data);
+ /*
+ * This ARI implements ARI_MISC_CCPLEX commands. This can be
+ * used to enable/disable coresight clock gating.
+ */
+ void (*misc_ccplex)(uint32_t ari_base, uint32_t index,
+ uint32_t value);
+} arch_mce_ops_t;
+
+/* declarations for ARI/NVG handler functions */
+int32_t ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
+ uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
+ uint8_t update_wake_mask);
+int32_t ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time);
+uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state);
+int32_t ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats);
+uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data);
+int32_t ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int32_t ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int32_t ari_online_core(uint32_t ari_base, uint32_t core);
+int32_t ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable);
+int32_t ari_reset_vector_update(uint32_t ari_base);
+int32_t ari_roc_flush_cache_trbits(uint32_t ari_base);
+int32_t ari_roc_flush_cache(uint32_t ari_base);
+int32_t ari_roc_clean_cache(uint32_t ari_base);
+uint64_t ari_read_write_mca(uint32_t ari_base, uint64_t cmd, uint64_t *data);
+int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx);
+void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx);
+int32_t ari_read_write_uncore_perfmon(uint32_t ari_base,
+ uint64_t req, uint64_t *data);
+void ari_misc_ccplex(uint32_t ari_base, uint32_t index, uint32_t value);
+
+int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int32_t nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
+ uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
+ uint8_t update_wake_mask);
+int32_t nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time);
+uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state);
+int32_t nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats);
+int32_t nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int32_t nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
+int32_t nvg_online_core(uint32_t ari_base, uint32_t core);
+int32_t nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable);
+
+extern void nvg_set_request_data(uint64_t req, uint64_t data);
+extern void nvg_set_request(uint64_t req);
+extern uint64_t nvg_get_result(void);
+#endif /* MCE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h b/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h
new file mode 100644
index 0000000..ecfb3f4
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef T18X_ARI_H
+#define T18X_ARI_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * t18x_ari.h
+ *
+ * Global ARI definitions.
+ * ----------------------------------------------------------------------------
+ */
+
+enum {
+ TEGRA_ARI_VERSION_MAJOR = 3U,
+ TEGRA_ARI_VERSION_MINOR = 1U,
+};
+
+typedef enum {
+ /* indexes below get the core lock */
+ TEGRA_ARI_MISC = 0U,
+ /* index 1 is deprecated */
+ /* index 2 is deprecated */
+ /* index 3 is deprecated */
+ TEGRA_ARI_ONLINE_CORE = 4U,
+
+ /* indexes below need cluster lock */
+ TEGRA_ARI_MISC_CLUSTER = 41U,
+ TEGRA_ARI_IS_CCX_ALLOWED = 42U,
+ TEGRA_ARI_CC3_CTRL = 43U,
+
+ /* indexes below need ccplex lock */
+ TEGRA_ARI_ENTER_CSTATE = 80U,
+ TEGRA_ARI_UPDATE_CSTATE_INFO = 81U,
+ TEGRA_ARI_IS_SC7_ALLOWED = 82U,
+ /* index 83 is deprecated */
+ TEGRA_ARI_PERFMON = 84U,
+ TEGRA_ARI_UPDATE_CCPLEX_GSC = 85U,
+ /* index 86 is depracated */
+ /* index 87 is deprecated */
+ TEGRA_ARI_ROC_FLUSH_CACHE_ONLY = 88U,
+ TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS = 89U,
+ TEGRA_ARI_MISC_CCPLEX = 90U,
+ TEGRA_ARI_MCA = 91U,
+ TEGRA_ARI_UPDATE_CROSSOVER = 92U,
+ TEGRA_ARI_CSTATE_STATS = 93U,
+ TEGRA_ARI_WRITE_CSTATE_STATS = 94U,
+ TEGRA_ARI_COPY_MISCREG_AA64_RST = 95U,
+ TEGRA_ARI_ROC_CLEAN_CACHE_ONLY = 96U,
+} tegra_ari_req_id_t;
+
+typedef enum {
+ TEGRA_ARI_MISC_ECHO = 0U,
+ TEGRA_ARI_MISC_VERSION = 1U,
+ TEGRA_ARI_MISC_FEATURE_LEAF_0 = 2U,
+} tegra_ari_misc_index_t;
+
+typedef enum {
+ TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF = 0U,
+ TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT = 1U,
+ TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL = 2U,
+ TEGRA_ARI_MISC_CCPLEX_EDBGREQ = 3U,
+} tegra_ari_misc_ccplex_index_t;
+
+typedef enum {
+ TEGRA_ARI_CORE_C0 = 0U,
+ TEGRA_ARI_CORE_C1 = 1U,
+ TEGRA_ARI_CORE_C6 = 6U,
+ TEGRA_ARI_CORE_C7 = 7U,
+ TEGRA_ARI_CORE_WARMRSTREQ = 8U,
+} tegra_ari_core_sleep_state_t;
+
+typedef enum {
+ TEGRA_ARI_CLUSTER_CC0 = 0U,
+ TEGRA_ARI_CLUSTER_CC1 = 1U,
+ TEGRA_ARI_CLUSTER_CC6 = 6U,
+ TEGRA_ARI_CLUSTER_CC7 = 7U,
+} tegra_ari_cluster_sleep_state_t;
+
+typedef enum {
+ TEGRA_ARI_CCPLEX_CCP0 = 0U,
+ TEGRA_ARI_CCPLEX_CCP1 = 1U,
+ TEGRA_ARI_CCPLEX_CCP3 = 3U, /* obsoleted */
+} tegra_ari_ccplex_sleep_state_t;
+
+typedef enum {
+ TEGRA_ARI_SYSTEM_SC0 = 0U,
+ TEGRA_ARI_SYSTEM_SC1 = 1U, /* obsoleted */
+ TEGRA_ARI_SYSTEM_SC2 = 2U, /* obsoleted */
+ TEGRA_ARI_SYSTEM_SC3 = 3U, /* obsoleted */
+ TEGRA_ARI_SYSTEM_SC4 = 4U, /* obsoleted */
+ TEGRA_ARI_SYSTEM_SC7 = 7U,
+ TEGRA_ARI_SYSTEM_SC8 = 8U,
+} tegra_ari_system_sleep_state_t;
+
+typedef enum {
+ TEGRA_ARI_CROSSOVER_C1_C6 = 0U,
+ TEGRA_ARI_CROSSOVER_CC1_CC6 = 1U,
+ TEGRA_ARI_CROSSOVER_CC1_CC7 = 2U,
+ TEGRA_ARI_CROSSOVER_CCP1_CCP3 = 3U, /* obsoleted */
+ TEGRA_ARI_CROSSOVER_CCP3_SC2 = 4U, /* obsoleted */
+ TEGRA_ARI_CROSSOVER_CCP3_SC3 = 5U, /* obsoleted */
+ TEGRA_ARI_CROSSOVER_CCP3_SC4 = 6U, /* obsoleted */
+ TEGRA_ARI_CROSSOVER_CCP3_SC7 = 7U, /* obsoleted */
+ TEGRA_ARI_CROSSOVER_SC0_SC7 = 7U,
+ TEGRA_ARI_CROSSOVER_CCP3_SC1 = 8U, /* obsoleted */
+} tegra_ari_crossover_index_t;
+
+typedef enum {
+ TEGRA_ARI_CSTATE_STATS_CLEAR = 0U,
+ TEGRA_ARI_CSTATE_STATS_SC7_ENTRIES = 1U,
+ TEGRA_ARI_CSTATE_STATS_SC4_ENTRIES, /* obsoleted */
+ TEGRA_ARI_CSTATE_STATS_SC3_ENTRIES, /* obsoleted */
+ TEGRA_ARI_CSTATE_STATS_SC2_ENTRIES, /* obsoleted */
+ TEGRA_ARI_CSTATE_STATS_CCP3_ENTRIES, /* obsoleted */
+ TEGRA_ARI_CSTATE_STATS_A57_CC6_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_A57_CC7_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_D15_CC6_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_D15_CC7_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_D15_0_C6_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_D15_1_C6_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_D15_0_C7_ENTRIES = 14U,
+ TEGRA_ARI_CSTATE_STATS_D15_1_C7_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_A57_0_C7_ENTRIES = 18U,
+ TEGRA_ARI_CSTATE_STATS_A57_1_C7_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_A57_2_C7_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_A57_3_C7_ENTRIES,
+ TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0,
+ TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1,
+ TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 26U,
+ TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1,
+ TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2,
+ TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3,
+} tegra_ari_cstate_stats_index_t;
+
+typedef enum {
+ TEGRA_ARI_GSC_ALL = 0U,
+ TEGRA_ARI_GSC_BPMP = 6U,
+ TEGRA_ARI_GSC_APE = 7U,
+ TEGRA_ARI_GSC_SPE = 8U,
+ TEGRA_ARI_GSC_SCE = 9U,
+ TEGRA_ARI_GSC_APR = 10U,
+ TEGRA_ARI_GSC_TZRAM = 11U,
+ TEGRA_ARI_GSC_SE = 12U,
+ TEGRA_ARI_GSC_BPMP_TO_SPE = 16U,
+ TEGRA_ARI_GSC_SPE_TO_BPMP = 17U,
+ TEGRA_ARI_GSC_CPU_TZ_TO_BPMP = 18U,
+ TEGRA_ARI_GSC_BPMP_TO_CPU_TZ = 19U,
+ TEGRA_ARI_GSC_CPU_NS_TO_BPMP = 20U,
+ TEGRA_ARI_GSC_BPMP_TO_CPU_NS = 21U,
+ TEGRA_ARI_GSC_IPC_SE_SPE_SCE_BPMP = 22U,
+ TEGRA_ARI_GSC_SC7_RESUME_FW = 23U,
+ TEGRA_ARI_GSC_TZ_DRAM_IDX = 34U,
+ TEGRA_ARI_GSC_VPR_IDX = 35U,
+} tegra_ari_gsc_index_t;
+
+/* This macro will produce enums for __name##_LSB, __name##_MSB and __name##_MSK */
+#define TEGRA_ARI_ENUM_MASK_LSB_MSB(__name, __lsb, __msb) __name##_LSB = __lsb, __name##_MSB = __msb
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE, 0U, 2U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE_PRESENT, 7U, 7U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE, 8U, 9U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE_PRESENT, 15U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE, 16U, 19U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__IGNORE_CROSSOVERS, 22U, 22U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE_PRESENT, 23U, 23U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__WAKE_MASK_PRESENT, 31U, 31U),
+} tegra_ari_update_cstate_info_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL__EN, 0U, 0U),
+} tegra_ari_misc_ccplex_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_FREQ, 0U, 8U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_VOLT, 16U, 23U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__ENABLE, 31U, 31U),
+} tegra_ari_cc3_ctrl_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_MCA_NOP = 0U,
+ TEGRA_ARI_MCA_READ_SERR = 1U,
+ TEGRA_ARI_MCA_WRITE_SERR = 2U,
+ TEGRA_ARI_MCA_CLEAR_SERR = 4U,
+ TEGRA_ARI_MCA_REPORT_SERR = 5U,
+ TEGRA_ARI_MCA_READ_INTSTS = 6U,
+ TEGRA_ARI_MCA_WRITE_INTSTS = 7U,
+ TEGRA_ARI_MCA_READ_PREBOOT_SERR = 8U,
+} tegra_ari_mca_commands_t;
+
+typedef enum {
+ TEGRA_ARI_MCA_RD_WR_DPMU = 0U,
+ TEGRA_ARI_MCA_RD_WR_IOB = 1U,
+ TEGRA_ARI_MCA_RD_WR_MCB = 2U,
+ TEGRA_ARI_MCA_RD_WR_CCE = 3U,
+ TEGRA_ARI_MCA_RD_WR_CQX = 4U,
+ TEGRA_ARI_MCA_RD_WR_CTU = 5U,
+ TEGRA_ARI_MCA_RD_WR_JSR_MTS = 7U,
+ TEGRA_ARI_MCA_RD_BANK_INFO = 0x0fU,
+ TEGRA_ARI_MCA_RD_BANK_TEMPLATE = 0x10U,
+ TEGRA_ARI_MCA_RD_WR_SECURE_ACCESS_REGISTER = 0x11U,
+ TEGRA_ARI_MCA_RD_WR_GLOBAL_CONFIG_REGISTER = 0x12U,
+} tegra_ari_mca_rd_wr_indexes_t;
+
+typedef enum {
+ TEGRA_ARI_MCA_RD_WR_ASERRX_CTRL = 0U,
+ TEGRA_ARI_MCA_RD_WR_ASERRX_STATUS = 1U,
+ TEGRA_ARI_MCA_RD_WR_ASERRX_ADDR = 2U,
+ TEGRA_ARI_MCA_RD_WR_ASERRX_MISC1 = 3U,
+ TEGRA_ARI_MCA_RD_WR_ASERRX_MISC2 = 4U,
+} tegra_ari_mca_read_asserx_subindexes_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_SETTING_ENABLES_NS_PERMITTED, 0U, 0U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_READING_STATUS_NS_PERMITTED, 1U, 1U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_PENDING_MCA_ERRORS_NS_PERMITTED, 2U, 2U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_CLEARING_MCA_INTERRUPTS_NS_PERMITTED, 3U, 3U),
+} tegra_ari_mca_secure_register_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_SERR_ERR_CODE, 0U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM_ERR, 16U, 16U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_CRAB_ERR, 17U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_RD_WR_N, 18U, 18U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UCODE_ERR, 19U, 19U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM, 20U, 23U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_AV, 58U, 58U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_MV, 59U, 59U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_EN, 60U, 60U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UC, 61U, 61U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_OVF, 62U, 62U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_VAL, 63U, 63U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_ADDR, 0U, 41U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_UCODE_ERRCD, 42U, 52U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_PWM_ERR, 0U, 0U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_CRAB_ERR, 1U, 1U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_UCODE_ERR, 3U, 3U),
+} tegra_ari_mca_aserr0_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_SERR_ERR_CODE, 0U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MSI_ERR, 16U, 16U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_IHI_ERR, 17U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CRI_ERR, 18U, 18U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MMCRAB_ERR, 19U, 19U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CSI_ERR, 20U, 20U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RD_WR_N, 21U, 21U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_REQ_ERRT, 22U, 23U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RESP_ERRT, 24U, 25U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AV, 58U, 58U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MV, 59U, 59U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_EN, 60U, 60U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_UC, 61U, 61U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_OVF, 62U, 62U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_VAL, 63U, 63U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AXI_ID, 0U, 7U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_ID, 8U, 27U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CID, 28U, 31U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CMD, 32U, 35U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MSI_ERR, 0U, 0U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_IHI_ERR, 1U, 1U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CRI_ERR, 2U, 2U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MMCRAB_ERR, 3U, 3U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CSI_ERR, 4U, 4U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_MISC_ADDR, 0U, 41U),
+} tegra_ari_mca_aserr1_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SERR_ERR_CODE, 0U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MC_ERR, 16U, 16U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SYSRAM_ERR, 17U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_CLIENT_ID, 18U, 19U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_AV, 58U, 58U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MV, 59U, 59U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_EN, 60U, 60U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_UC, 61U, 61U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_OVF, 62U, 62U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_VAL, 63U, 63U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ID, 0U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_CMD, 18U, 21U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ADDR, 22U, 53U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_CTRL_EN_MC_ERR, 0U, 0U),
+} tegra_ari_mca_aserr2_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_SERR_ERR_CODE, 0U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_TO_ERR, 16U, 16U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_STAT_ERR, 17U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_DST_ERR, 18U, 18U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UNC_ERR, 19U, 19U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MH_ERR, 20U, 20U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PERR, 21U, 21U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PSN_ERR, 22U, 22U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_AV, 58U, 58U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MV, 59U, 59U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_EN, 60U, 60U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UC, 61U, 61U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_OVF, 62U, 62U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_VAL, 63U, 63U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_CMD, 0U, 5U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_ADDR, 6U, 47U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TO, 0U, 0U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_DIV4, 1U, 1U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TLIMIT, 2U, 11U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_PSN_ERR_CORR_MSK, 12U, 25U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_MORE_INFO, 0U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TO_INFO, 18U, 43U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_SRC, 44U, 45U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TID, 46U, 52U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_TO_ERR, 0U, 0U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_STAT_ERR, 1U, 1U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_DST_ERR, 2U, 2U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_UNC_ERR, 3U, 3U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_MH_ERR, 4U, 4U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PERR, 5U, 5U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PSN_ERR, 6U, 19U),
+} tegra_ari_mca_aserr3_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SERR_ERR_CODE, 0U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SRC_ERR, 16U, 16U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_DST_ERR, 17U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_REQ_ERR, 18U, 18U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_RSP_ERR, 19U, 19U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_AV, 58U, 58U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_MV, 59U, 59U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_EN, 60U, 60U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_UC, 61U, 61U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_OVF, 62U, 62U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_VAL, 63U, 63U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_CTRL_EN_CPE_ERR, 0U, 0U),
+} tegra_ari_mca_aserr4_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_SERR_ERR_CODE, 0U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_CTUPAR, 16U, 16U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MULTI, 17U, 17U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_AV, 58U, 58U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MV, 59U, 59U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_EN, 60U, 60U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_UC, 61U, 61U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_OVF, 62U, 62U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_VAL, 63U, 63U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_SRC, 0U, 7U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ID, 8U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_DATA, 16U, 26U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_CMD, 32U, 35U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ADDR, 36U, 45U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_CTRL_EN_CTUPAR, 0U, 0U),
+} tegra_ari_mca_aserr5_bitmasks_t;
+
+typedef enum {
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_SERR_ERR_CODE, 0U, 15U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_AV, 58U, 58U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_MV, 59U, 59U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_EN, 60U, 60U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_UC, 61U, 61U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_OVF, 62U, 62U),
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_VAL, 63U, 63U),
+
+ TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_ADDR_TBD_INFO, 0U, 63U),
+} tegra_ari_mca_serr1_bitmasks_t;
+
+#undef TEGRA_ARI_ENUM_MASK_LSB_MSB
+
+typedef enum {
+ TEGRA_NVG_CHANNEL_PMIC = 0U,
+ TEGRA_NVG_CHANNEL_POWER_PERF = 1U,
+ TEGRA_NVG_CHANNEL_POWER_MODES = 2U,
+ TEGRA_NVG_CHANNEL_WAKE_TIME = 3U,
+ TEGRA_NVG_CHANNEL_CSTATE_INFO = 4U,
+ TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 = 5U,
+ TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC6 = 6U,
+ TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC7 = 7U,
+ TEGRA_NVG_CHANNEL_CROSSOVER_CCP1_CCP3 = 8U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC2 = 9U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC3 = 10U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC4 = 11U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC7 = 12U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CROSSOVER_SC0_SC7 = 12U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR = 13U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_SC7_ENTRIES = 14U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_SC4_ENTRIES = 15U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_SC3_ENTRIES = 16U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_SC2_ENTRIES = 17U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_CCP3_ENTRIES = 18U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC6_ENTRIES = 19U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC7_ENTRIES = 20U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC6_ENTRIES = 21U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC7_ENTRIES = 22U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C6_ENTRIES = 23U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C6_ENTRIES = 24U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C6_ENTRIES = 25U, /* Reserved (for Denver15 core 2) */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C6_ENTRIES = 26U, /* Reserved (for Denver15 core 3) */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C7_ENTRIES = 27U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C7_ENTRIES = 28U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C7_ENTRIES = 29U, /* Reserved (for Denver15 core 2) */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C7_ENTRIES = 30U, /* Reserved (for Denver15 core 3) */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_0_C7_ENTRIES = 31U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_1_C7_ENTRIES = 32U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_2_C7_ENTRIES = 33U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_3_C7_ENTRIES = 34U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0 = 35U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1 = 36U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_2 = 37U, /* Reserved (for Denver15 core 2) */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_3 = 38U, /* Reserved (for Denver15 core 3) */
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 39U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1 = 40U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2 = 41U,
+ TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3 = 42U,
+ TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = 43U,
+ TEGRA_NVG_CHANNEL_ONLINE_CORE = 44U,
+ TEGRA_NVG_CHANNEL_CC3_CTRL = 45U,
+ TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC1 = 46U, /* obsoleted */
+ TEGRA_NVG_CHANNEL_LAST_INDEX,
+} tegra_nvg_channel_id_t;
+
+#endif /* T18X_ARI_H */
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S
new file mode 100644
index 0000000..e3591ce
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+ .globl nvg_set_request_data
+ .globl nvg_set_request
+ .globl nvg_get_result
+
+/* void nvg_set_request_data(uint64_t req, uint64_t data) */
+func nvg_set_request_data
+ msr s3_0_c15_c1_2, x0
+ msr s3_0_c15_c1_3, x1
+ ret
+endfunc nvg_set_request_data
+
+/* void nvg_set_request(uint64_t req) */
+func nvg_set_request
+ msr s3_0_c15_c1_2, x0
+ ret
+endfunc nvg_set_request
+
+/* uint64_t nvg_get_result(void) */
+func nvg_get_result
+ mrs x0, s3_0_c15_c1_3
+ ret
+endfunc nvg_get_result
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
new file mode 100644
index 0000000..a57bc11
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
@@ -0,0 +1,564 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <denver.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <mce_private.h>
+#include <t18x_ari.h>
+
+/*******************************************************************************
+ * Register offsets for ARI request/results
+ ******************************************************************************/
+#define ARI_REQUEST 0x0U
+#define ARI_REQUEST_EVENT_MASK 0x4U
+#define ARI_STATUS 0x8U
+#define ARI_REQUEST_DATA_LO 0xCU
+#define ARI_REQUEST_DATA_HI 0x10U
+#define ARI_RESPONSE_DATA_LO 0x14U
+#define ARI_RESPONSE_DATA_HI 0x18U
+
+/* Status values for the current request */
+#define ARI_REQ_PENDING 1U
+#define ARI_REQ_ONGOING 3U
+#define ARI_REQUEST_VALID_BIT (1U << 8)
+#define ARI_EVT_MASK_STANDBYWFI_BIT (1U << 7)
+
+/* default timeout (us) to wait for ARI completion */
+#define ARI_MAX_RETRY_COUNT U(2000000)
+
+/*******************************************************************************
+ * ARI helper functions
+ ******************************************************************************/
+static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg)
+{
+ return mmio_read_32((uint64_t)ari_base + (uint64_t)reg);
+}
+
+static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg)
+{
+ mmio_write_32((uint64_t)ari_base + (uint64_t)reg, val);
+}
+
+static inline uint32_t ari_get_request_low(uint32_t ari_base)
+{
+ return ari_read_32(ari_base, ARI_REQUEST_DATA_LO);
+}
+
+static inline uint32_t ari_get_request_high(uint32_t ari_base)
+{
+ return ari_read_32(ari_base, ARI_REQUEST_DATA_HI);
+}
+
+static inline uint32_t ari_get_response_low(uint32_t ari_base)
+{
+ return ari_read_32(ari_base, ARI_RESPONSE_DATA_LO);
+}
+
+static inline uint32_t ari_get_response_high(uint32_t ari_base)
+{
+ return ari_read_32(ari_base, ARI_RESPONSE_DATA_HI);
+}
+
+static inline void ari_clobber_response(uint32_t ari_base)
+{
+ ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO);
+ ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI);
+}
+
+static int32_t ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req,
+ uint32_t lo, uint32_t hi)
+{
+ uint32_t retries = (uint32_t)ARI_MAX_RETRY_COUNT;
+ uint32_t status;
+ int32_t ret = 0;
+
+ /* program the request, event_mask, hi and lo registers */
+ ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO);
+ ari_write_32(ari_base, hi, ARI_REQUEST_DATA_HI);
+ ari_write_32(ari_base, evt_mask, ARI_REQUEST_EVENT_MASK);
+ ari_write_32(ari_base, req | ARI_REQUEST_VALID_BIT, ARI_REQUEST);
+
+ /*
+ * For commands that have an event trigger, we should bypass
+ * ARI_STATUS polling, since MCE is waiting for SW to trigger
+ * the event.
+ */
+ if (evt_mask != 0U) {
+ ret = 0;
+ } else {
+ /* For shutdown/reboot commands, we dont have to check for timeouts */
+ if ((req == TEGRA_ARI_MISC_CCPLEX) &&
+ ((lo == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) ||
+ (lo == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT))) {
+ ret = 0;
+ } else {
+ /*
+ * Wait for the command response for not more than the timeout
+ */
+ while (retries != 0U) {
+
+ /* read the command status */
+ status = ari_read_32(ari_base, ARI_STATUS);
+ if ((status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) == 0U) {
+ break;
+ }
+
+ /* delay 1 us */
+ udelay(1);
+
+ /* decrement the retry count */
+ retries--;
+ }
+
+ /* assert if the command timed out */
+ if (retries == 0U) {
+ ERROR("ARI request timed out: req %d on CPU %d\n",
+ req, plat_my_core_pos());
+ assert(retries != 0U);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int32_t ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+ int32_t ret = 0;
+
+ /* check for allowed power state */
+ if ((state != TEGRA_ARI_CORE_C0) &&
+ (state != TEGRA_ARI_CORE_C1) &&
+ (state != TEGRA_ARI_CORE_C6) &&
+ (state != TEGRA_ARI_CORE_C7)) {
+ ERROR("%s: unknown cstate (%d)\n", __func__, state);
+ ret = EINVAL;
+ } else {
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /* Enter the cstate, to be woken up after wake_time (TSC ticks) */
+ ret = ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT,
+ (uint32_t)TEGRA_ARI_ENTER_CSTATE, state, wake_time);
+ }
+
+ return ret;
+}
+
+int32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
+ uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
+ uint8_t update_wake_mask)
+{
+ uint64_t val = 0U;
+
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /* update CLUSTER_CSTATE? */
+ if (cluster != 0U) {
+ val |= (cluster & CLUSTER_CSTATE_MASK) |
+ CLUSTER_CSTATE_UPDATE_BIT;
+ }
+
+ /* update CCPLEX_CSTATE? */
+ if (ccplex != 0U) {
+ val |= ((ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) |
+ CCPLEX_CSTATE_UPDATE_BIT;
+ }
+
+ /* update SYSTEM_CSTATE? */
+ if (system != 0U) {
+ val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
+ (((uint64_t)sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) |
+ SYSTEM_CSTATE_UPDATE_BIT);
+ }
+
+ /* update wake mask value? */
+ if (update_wake_mask != 0U) {
+ val |= CSTATE_WAKE_MASK_UPDATE_BIT;
+ }
+
+ /* set the updated cstate info */
+ return ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_UPDATE_CSTATE_INFO,
+ (uint32_t)val, wake_mask);
+}
+
+int32_t ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time)
+{
+ int32_t ret = 0;
+
+ /* sanity check crossover type */
+ if ((type == TEGRA_ARI_CROSSOVER_C1_C6) ||
+ (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)) {
+ ret = EINVAL;
+ } else {
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /* update crossover threshold time */
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_UPDATE_CROSSOVER, type, time);
+ }
+
+ return ret;
+}
+
+uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state)
+{
+ int32_t ret;
+ uint64_t result;
+
+ /* sanity check crossover type */
+ if (state == 0U) {
+ result = EINVAL;
+ } else {
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_CSTATE_STATS, state, 0U);
+ if (ret != 0) {
+ result = EINVAL;
+ } else {
+ result = (uint64_t)ari_get_response_low(ari_base);
+ }
+ }
+ return result;
+}
+
+int32_t ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats)
+{
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /* write the cstate stats */
+ return ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_WRITE_CSTATE_STATS,
+ state, stats);
+}
+
+uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data)
+{
+ uint64_t resp;
+ int32_t ret;
+ uint32_t local_data = data;
+
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /* ARI_REQUEST_DATA_HI is reserved for commands other than 'ECHO' */
+ if (cmd != TEGRA_ARI_MISC_ECHO) {
+ local_data = 0U;
+ }
+
+ ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_MISC, cmd, local_data);
+ if (ret != 0) {
+ resp = (uint64_t)ret;
+ } else {
+ /* get the command response */
+ resp = ari_get_response_low(ari_base);
+ resp |= ((uint64_t)ari_get_response_high(ari_base) << 32);
+ }
+
+ return resp;
+}
+
+int32_t ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+ int32_t ret;
+ uint32_t result;
+
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_IS_CCX_ALLOWED,
+ state & 0x7U, wake_time);
+ if (ret != 0) {
+ ERROR("%s: failed (%d)\n", __func__, ret);
+ result = 0U;
+ } else {
+ result = ari_get_response_low(ari_base) & 0x1U;
+ }
+
+ /* 1 = CCx allowed, 0 = CCx not allowed */
+ return (int32_t)result;
+}
+
+int32_t ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+ int32_t ret, result;
+
+ /* check for allowed power state */
+ if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) &&
+ (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) {
+ ERROR("%s: unknown cstate (%d)\n", __func__, state);
+ result = EINVAL;
+ } else {
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_IS_SC7_ALLOWED, state, wake_time);
+ if (ret != 0) {
+ ERROR("%s: failed (%d)\n", __func__, ret);
+ result = 0;
+ } else {
+ /* 1 = SC7 allowed, 0 = SC7 not allowed */
+ result = (ari_get_response_low(ari_base) != 0U) ? 1 : 0;
+ }
+ }
+
+ return result;
+}
+
+int32_t ari_online_core(uint32_t ari_base, uint32_t core)
+{
+ uint64_t cpu = read_mpidr() & (MPIDR_CPU_MASK);
+ uint64_t cluster = (read_mpidr() & (MPIDR_CLUSTER_MASK)) >>
+ (MPIDR_AFFINITY_BITS);
+ uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+ int32_t ret;
+
+ /* construct the current CPU # */
+ cpu |= (cluster << 2);
+
+ /* sanity check target core id */
+ if ((core >= MCE_CORE_ID_MAX) || (cpu == (uint64_t)core)) {
+ ERROR("%s: unsupported core id (%d)\n", __func__, core);
+ ret = EINVAL;
+ } else {
+ /*
+ * The Denver cluster has 2 CPUs only - 0, 1.
+ */
+ if ((impl == DENVER_IMPL) && ((core == 2U) || (core == 3U))) {
+ ERROR("%s: unknown core id (%d)\n", __func__, core);
+ ret = EINVAL;
+ } else {
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_ONLINE_CORE, core, 0U);
+ }
+ }
+
+ return ret;
+}
+
+int32_t ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable)
+{
+ uint32_t val;
+
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /*
+ * If the enable bit is cleared, Auto-CC3 will be disabled by setting
+ * the SW visible voltage/frequency request registers for all non
+ * floorswept cores valid independent of StandbyWFI and disabling
+ * the IDLE voltage/frequency request register. If set, Auto-CC3
+ * will be enabled by setting the ARM SW visible voltage/frequency
+ * request registers for all non floorswept cores to be enabled by
+ * StandbyWFI or the equivalent signal, and always keeping the IDLE
+ * voltage/frequency request register enabled.
+ */
+ val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\
+ ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\
+ ((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U));
+
+ return ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_CC3_CTRL, val, 0U);
+}
+
+int32_t ari_reset_vector_update(uint32_t ari_base)
+{
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /*
+ * Need to program the CPU reset vector one time during cold boot
+ * and SC7 exit
+ */
+ (void)ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_COPY_MISCREG_AA64_RST, 0U, 0U);
+
+ return 0;
+}
+
+int32_t ari_roc_flush_cache_trbits(uint32_t ari_base)
+{
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ return ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS, 0U, 0U);
+}
+
+int32_t ari_roc_flush_cache(uint32_t ari_base)
+{
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ return ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_ROC_FLUSH_CACHE_ONLY, 0U, 0U);
+}
+
+int32_t ari_roc_clean_cache(uint32_t ari_base)
+{
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ return ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_ROC_CLEAN_CACHE_ONLY, 0U, 0U);
+}
+
+uint64_t ari_read_write_mca(uint32_t ari_base, uint64_t cmd, uint64_t *data)
+{
+ uint64_t mca_arg_data, result = 0;
+ uint32_t resp_lo, resp_hi;
+ uint32_t mca_arg_err, mca_arg_finish;
+ int32_t ret;
+
+ /* Set data (write) */
+ mca_arg_data = (data != NULL) ? *data : 0ULL;
+
+ /* Set command */
+ ari_write_32(ari_base, (uint32_t)cmd, ARI_RESPONSE_DATA_LO);
+ ari_write_32(ari_base, (uint32_t)(cmd >> 32U), ARI_RESPONSE_DATA_HI);
+
+ ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_MCA,
+ (uint32_t)mca_arg_data,
+ (uint32_t)(mca_arg_data >> 32U));
+ if (ret == 0) {
+ resp_lo = ari_get_response_low(ari_base);
+ resp_hi = ari_get_response_high(ari_base);
+
+ mca_arg_err = resp_lo & MCA_ARG_ERROR_MASK;
+ mca_arg_finish = (resp_hi >> MCA_ARG_FINISH_SHIFT) &
+ MCA_ARG_FINISH_MASK;
+
+ if (mca_arg_finish == 0U) {
+ result = (uint64_t)mca_arg_err;
+ } else {
+ if (data != NULL) {
+ resp_lo = ari_get_request_low(ari_base);
+ resp_hi = ari_get_request_high(ari_base);
+ *data = ((uint64_t)resp_hi << 32U) |
+ (uint64_t)resp_lo;
+ }
+ }
+ }
+
+ return result;
+}
+
+int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx)
+{
+ int32_t ret = 0;
+ /* sanity check GSC ID */
+ if (gsc_idx > TEGRA_ARI_GSC_VPR_IDX) {
+ ret = EINVAL;
+ } else {
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /*
+ * The MCE code will read the GSC carveout value, corrseponding to
+ * the ID, from the MC registers and update the internal GSC registers
+ * of the CCPLEX.
+ */
+ (void)ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0U);
+ }
+
+ return ret;
+}
+
+void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx)
+{
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /*
+ * The MCE will shutdown or restart the entire system
+ */
+ (void)ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_MISC_CCPLEX, state_idx, 0U);
+}
+
+int32_t ari_read_write_uncore_perfmon(uint32_t ari_base, uint64_t req,
+ uint64_t *data)
+{
+ int32_t ret, result;
+ uint32_t val, req_status;
+ uint8_t req_cmd;
+
+ req_cmd = (uint8_t)(req & UNCORE_PERFMON_CMD_MASK);
+
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+
+ /* sanity check input parameters */
+ if ((req_cmd == UNCORE_PERFMON_CMD_READ) && (data == NULL)) {
+ ERROR("invalid parameters\n");
+ result = EINVAL;
+ } else {
+ /*
+ * For "write" commands get the value that has to be written
+ * to the uncore perfmon registers
+ */
+ val = (req_cmd == UNCORE_PERFMON_CMD_WRITE) ?
+ (uint32_t)*data : 0U;
+
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_PERFMON, val, (uint32_t)req);
+ if (ret != 0) {
+ result = ret;
+ } else {
+ /* read the command status value */
+ req_status = ari_get_response_high(ari_base) &
+ UNCORE_PERFMON_RESP_STATUS_MASK;
+
+ /*
+ * For "read" commands get the data from the uncore
+ * perfmon registers
+ */
+ req_status &= UNCORE_PERFMON_RESP_STATUS_MASK;
+ if ((req_status == 0U) && (req_cmd == UNCORE_PERFMON_CMD_READ)) {
+ *data = ari_get_response_low(ari_base);
+ }
+ result = (int32_t)req_status;
+ }
+ }
+
+ return result;
+}
+
+void ari_misc_ccplex(uint32_t ari_base, uint32_t index, uint32_t value)
+{
+ /*
+ * This invokes the ARI_MISC_CCPLEX commands. This can be
+ * used to enable/disable coresight clock gating.
+ */
+
+ if ((index > TEGRA_ARI_MISC_CCPLEX_EDBGREQ) ||
+ ((index == TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL) &&
+ (value > 1U))) {
+ ERROR("%s: invalid parameters \n", __func__);
+ } else {
+ /* clean the previous response state */
+ ari_clobber_response(ari_base);
+ (void)ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_MISC_CCPLEX, index, value);
+ }
+}
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
new file mode 100644
index 0000000..aebaceb
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <denver.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+
+#include <mce.h>
+#include <mce_private.h>
+#include <t18x_ari.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+
+/* NVG functions handlers */
+static arch_mce_ops_t nvg_mce_ops = {
+ .enter_cstate = nvg_enter_cstate,
+ .update_cstate_info = nvg_update_cstate_info,
+ .update_crossover_time = nvg_update_crossover_time,
+ .read_cstate_stats = nvg_read_cstate_stats,
+ .write_cstate_stats = nvg_write_cstate_stats,
+ .call_enum_misc = ari_enumeration_misc,
+ .is_ccx_allowed = nvg_is_ccx_allowed,
+ .is_sc7_allowed = nvg_is_sc7_allowed,
+ .online_core = nvg_online_core,
+ .cc3_ctrl = nvg_cc3_ctrl,
+ .update_reset_vector = ari_reset_vector_update,
+ .roc_flush_cache = ari_roc_flush_cache,
+ .roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
+ .roc_clean_cache = ari_roc_clean_cache,
+ .read_write_mca = ari_read_write_mca,
+ .update_ccplex_gsc = ari_update_ccplex_gsc,
+ .enter_ccplex_state = ari_enter_ccplex_state,
+ .read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
+ .misc_ccplex = ari_misc_ccplex
+};
+
+/* ARI functions handlers */
+static arch_mce_ops_t ari_mce_ops = {
+ .enter_cstate = ari_enter_cstate,
+ .update_cstate_info = ari_update_cstate_info,
+ .update_crossover_time = ari_update_crossover_time,
+ .read_cstate_stats = ari_read_cstate_stats,
+ .write_cstate_stats = ari_write_cstate_stats,
+ .call_enum_misc = ari_enumeration_misc,
+ .is_ccx_allowed = ari_is_ccx_allowed,
+ .is_sc7_allowed = ari_is_sc7_allowed,
+ .online_core = ari_online_core,
+ .cc3_ctrl = ari_cc3_ctrl,
+ .update_reset_vector = ari_reset_vector_update,
+ .roc_flush_cache = ari_roc_flush_cache,
+ .roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
+ .roc_clean_cache = ari_roc_clean_cache,
+ .read_write_mca = ari_read_write_mca,
+ .update_ccplex_gsc = ari_update_ccplex_gsc,
+ .enter_ccplex_state = ari_enter_ccplex_state,
+ .read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
+ .misc_ccplex = ari_misc_ccplex
+};
+
+typedef struct {
+ uint32_t ari_base;
+ arch_mce_ops_t *ops;
+} mce_config_t;
+
+/* Table to hold the per-CPU ARI base address and function handlers */
+static mce_config_t mce_cfg_table[MCE_ARI_APERTURES_MAX] = {
+ {
+ /* A57 Core 0 */
+ .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET,
+ .ops = &ari_mce_ops,
+ },
+ {
+ /* A57 Core 1 */
+ .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET,
+ .ops = &ari_mce_ops,
+ },
+ {
+ /* A57 Core 2 */
+ .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET,
+ .ops = &ari_mce_ops,
+ },
+ {
+ /* A57 Core 3 */
+ .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET,
+ .ops = &ari_mce_ops,
+ },
+ {
+ /* D15 Core 0 */
+ .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET,
+ .ops = &nvg_mce_ops,
+ },
+ {
+ /* D15 Core 1 */
+ .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET,
+ .ops = &nvg_mce_ops,
+ }
+};
+
+static uint32_t mce_get_curr_cpu_ari_base(void)
+{
+ uint64_t mpidr = read_mpidr();
+ uint64_t cpuid = mpidr & MPIDR_CPU_MASK;
+ uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+
+ /*
+ * T186 has 2 CPU clusters, one with Denver CPUs and the other with
+ * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
+ * numbers start from 0. In order to get the proper arch_mce_ops_t
+ * struct, we have to convert the Denver CPU ids to the corresponding
+ * indices in the mce_ops_table array.
+ */
+ if (impl == DENVER_IMPL) {
+ cpuid |= 0x4U;
+ }
+
+ return mce_cfg_table[cpuid].ari_base;
+}
+
+static arch_mce_ops_t *mce_get_curr_cpu_ops(void)
+{
+ uint64_t mpidr = read_mpidr();
+ uint64_t cpuid = mpidr & MPIDR_CPU_MASK;
+ uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) &
+ MIDR_IMPL_MASK;
+
+ /*
+ * T186 has 2 CPU clusters, one with Denver CPUs and the other with
+ * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
+ * numbers start from 0. In order to get the proper arch_mce_ops_t
+ * struct, we have to convert the Denver CPU ids to the corresponding
+ * indices in the mce_ops_table array.
+ */
+ if (impl == DENVER_IMPL) {
+ cpuid |= 0x4U;
+ }
+
+ return mce_cfg_table[cpuid].ops;
+}
+
+/*******************************************************************************
+ * Common handler for all MCE commands
+ ******************************************************************************/
+int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1,
+ uint64_t arg2)
+{
+ const arch_mce_ops_t *ops;
+ gp_regs_t *gp_regs = get_gpregs_ctx(cm_get_context(NON_SECURE));
+ uint32_t cpu_ari_base;
+ uint64_t ret64 = 0, arg3, arg4, arg5;
+ int32_t ret = 0;
+
+ assert(gp_regs != NULL);
+
+ /* get a pointer to the CPU's arch_mce_ops_t struct */
+ ops = mce_get_curr_cpu_ops();
+
+ /* get the CPU's ARI base address */
+ cpu_ari_base = mce_get_curr_cpu_ari_base();
+
+ switch (cmd) {
+ case (uint64_t)MCE_CMD_ENTER_CSTATE:
+ ret = ops->enter_cstate(cpu_ari_base, arg0, arg1);
+
+ break;
+
+ case (uint64_t)MCE_CMD_UPDATE_CSTATE_INFO:
+ /*
+ * get the parameters required for the update cstate info
+ * command
+ */
+ arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4);
+ arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5);
+ arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6);
+
+ ret = ops->update_cstate_info(cpu_ari_base, (uint32_t)arg0,
+ (uint32_t)arg1, (uint32_t)arg2, (uint8_t)arg3,
+ (uint32_t)arg4, (uint8_t)arg5);
+
+ write_ctx_reg(gp_regs, CTX_GPREG_X4, (0ULL));
+ write_ctx_reg(gp_regs, CTX_GPREG_X5, (0ULL));
+ write_ctx_reg(gp_regs, CTX_GPREG_X6, (0ULL));
+
+ break;
+
+ case (uint64_t)MCE_CMD_UPDATE_CROSSOVER_TIME:
+ ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1);
+
+ break;
+
+ case (uint64_t)MCE_CMD_READ_CSTATE_STATS:
+ ret64 = ops->read_cstate_stats(cpu_ari_base, arg0);
+
+ /* update context to return cstate stats value */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
+ write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64));
+
+ break;
+
+ case (uint64_t)MCE_CMD_WRITE_CSTATE_STATS:
+ ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1);
+
+ break;
+
+ case (uint64_t)MCE_CMD_IS_CCX_ALLOWED:
+ ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1);
+
+ /* update context to return CCx status value */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret));
+
+ break;
+
+ case (uint64_t)MCE_CMD_IS_SC7_ALLOWED:
+ ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1);
+
+ /* update context to return SC7 status value */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret));
+ write_ctx_reg(gp_regs, CTX_GPREG_X3, (uint64_t)(ret));
+
+ break;
+
+ case (uint64_t)MCE_CMD_ONLINE_CORE:
+ ret = ops->online_core(cpu_ari_base, arg0);
+
+ break;
+
+ case (uint64_t)MCE_CMD_CC3_CTRL:
+ ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2);
+
+ break;
+
+ case (uint64_t)MCE_CMD_ECHO_DATA:
+ ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO,
+ arg0);
+
+ /* update context to return if echo'd data matched source */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, ((ret64 == arg0) ?
+ 1ULL : 0ULL));
+ write_ctx_reg(gp_regs, CTX_GPREG_X2, ((ret64 == arg0) ?
+ 1ULL : 0ULL));
+
+ break;
+
+ case (uint64_t)MCE_CMD_READ_VERSIONS:
+ ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION,
+ arg0);
+
+ /*
+ * version = minor(63:32) | major(31:0). Update context
+ * to return major and minor version number.
+ */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
+ write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64 >> 32ULL));
+
+ break;
+
+ case (uint64_t)MCE_CMD_ENUM_FEATURES:
+ ret64 = ops->call_enum_misc(cpu_ari_base,
+ TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0);
+
+ /* update context to return features value */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
+
+ break;
+
+ case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
+ ret = ops->roc_flush_cache_trbits(cpu_ari_base);
+
+ break;
+
+ case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE:
+ ret = ops->roc_flush_cache(cpu_ari_base);
+
+ break;
+
+ case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE:
+ ret = ops->roc_clean_cache(cpu_ari_base);
+
+ break;
+
+ case (uint64_t)MCE_CMD_ENUM_READ_MCA:
+ ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1);
+
+ /* update context to return MCA data/error */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
+ write_ctx_reg(gp_regs, CTX_GPREG_X2, (arg1));
+ write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64));
+
+ break;
+
+ case (uint64_t)MCE_CMD_ENUM_WRITE_MCA:
+ ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1);
+
+ /* update context to return MCA error */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
+ write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64));
+
+ break;
+
+#if ENABLE_CHIP_VERIFICATION_HARNESS
+ case (uint64_t)MCE_CMD_ENABLE_LATIC:
+ /*
+ * This call is not for production use. The constant value,
+ * 0xFFFF0000, is specific to allowing for enabling LATIC on
+ * pre-production parts for the chip verification harness.
+ *
+ * Enabling LATIC allows S/W to read the MINI ISPs in the
+ * CCPLEX. The ISMs are used for various measurements relevant
+ * to particular locations in the Silicon. They are small
+ * counters which can be polled to determine how fast a
+ * particular location in the Silicon is.
+ */
+ ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(),
+ 0xFFFF0000);
+
+ break;
+#endif
+
+ case (uint64_t)MCE_CMD_UNCORE_PERFMON_REQ:
+ ret = ops->read_write_uncore_perfmon(cpu_ari_base, arg0, &arg1);
+
+ /* update context to return data */
+ write_ctx_reg(gp_regs, CTX_GPREG_X1, (arg1));
+ break;
+
+ case (uint64_t)MCE_CMD_MISC_CCPLEX:
+ ops->misc_ccplex(cpu_ari_base, arg0, arg1);
+
+ break;
+
+ default:
+ ERROR("unknown MCE command (%" PRIu64 ")\n", cmd);
+ ret = EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Handler to update the reset vector for CPUs
+ ******************************************************************************/
+int32_t mce_update_reset_vector(void)
+{
+ const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
+
+ ops->update_reset_vector(mce_get_curr_cpu_ari_base());
+
+ return 0;
+}
+
+static int32_t mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx)
+{
+ const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
+
+ ops->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Handler to update carveout values for Video Memory Carveout region
+ ******************************************************************************/
+int32_t mce_update_gsc_videomem(void)
+{
+ return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX);
+}
+
+/*******************************************************************************
+ * Handler to update carveout values for TZDRAM aperture
+ ******************************************************************************/
+int32_t mce_update_gsc_tzdram(void)
+{
+ return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX);
+}
+
+/*******************************************************************************
+ * Handler to shutdown/reset the entire system
+ ******************************************************************************/
+__dead2 void mce_enter_ccplex_state(uint32_t state_idx)
+{
+ const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
+
+ /* sanity check state value */
+ if ((state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) &&
+ (state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT)) {
+ panic();
+ }
+
+ ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx);
+
+ /* wait till the CCPLEX powers down */
+ for (;;) {
+ ;
+ }
+
+}
+
+/*******************************************************************************
+ * Handler to issue the UPDATE_CSTATE_INFO request
+ ******************************************************************************/
+void mce_update_cstate_info(const mce_cstate_info_t *cstate)
+{
+ const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
+
+ /* issue the UPDATE_CSTATE_INFO request */
+ ops->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster,
+ cstate->ccplex, cstate->system, cstate->system_state_force,
+ cstate->wake_mask, cstate->update_wake_mask);
+}
+
+/*******************************************************************************
+ * Handler to read the MCE firmware version and check if it is compatible
+ * with interface header the BL3-1 was compiled against
+ ******************************************************************************/
+void mce_verify_firmware_version(void)
+{
+ const arch_mce_ops_t *ops;
+ uint32_t cpu_ari_base;
+ uint64_t version;
+ uint32_t major, minor;
+
+ /*
+ * MCE firmware is not supported on simulation platforms.
+ */
+ if (tegra_platform_is_emulation()) {
+
+ INFO("MCE firmware is not supported\n");
+
+ } else {
+ /* get a pointer to the CPU's arch_mce_ops_t struct */
+ ops = mce_get_curr_cpu_ops();
+
+ /* get the CPU's ARI base address */
+ cpu_ari_base = mce_get_curr_cpu_ari_base();
+
+ /*
+ * Read the MCE firmware version and extract the major and minor
+ * version fields
+ */
+ version = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, 0);
+ major = (uint32_t)version;
+ minor = (uint32_t)(version >> 32);
+
+ INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor,
+ TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR);
+
+ /*
+ * Verify that the MCE firmware version and the interface header
+ * match
+ */
+ if (major != TEGRA_ARI_VERSION_MAJOR) {
+ ERROR("ARI major version mismatch\n");
+ panic();
+ }
+
+ if (minor < TEGRA_ARI_VERSION_MINOR) {
+ ERROR("ARI minor version mismatch\n");
+ panic();
+ }
+ }
+}
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
new file mode 100644
index 0000000..cbc9aa3
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <lib/mmio.h>
+
+#include <mce_private.h>
+#include <t18x_ari.h>
+#include <tegra_private.h>
+
+int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+ int32_t ret = 0;
+ uint64_t val = 0ULL;
+
+ (void)ari_base;
+
+ /* check for allowed power state */
+ if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) &&
+ (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) {
+ ERROR("%s: unknown cstate (%d)\n", __func__, state);
+ ret = EINVAL;
+ } else {
+ /* time (TSC ticks) until the core is expected to get a wake event */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time);
+
+ /* set the core cstate */
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | (uint64_t)state);
+ }
+
+ return ret;
+}
+
+/*
+ * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and
+ * SYSTEM_CSTATE values.
+ */
+int32_t nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
+ uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
+ uint8_t update_wake_mask)
+{
+ uint64_t val = 0ULL;
+
+ (void)ari_base;
+
+ /* update CLUSTER_CSTATE? */
+ if (cluster != 0U) {
+ val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) |
+ CLUSTER_CSTATE_UPDATE_BIT;
+ }
+
+ /* update CCPLEX_CSTATE? */
+ if (ccplex != 0U) {
+ val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) |
+ CCPLEX_CSTATE_UPDATE_BIT;
+ }
+
+ /* update SYSTEM_CSTATE? */
+ if (system != 0U) {
+ val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
+ (((uint64_t)sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) |
+ SYSTEM_CSTATE_UPDATE_BIT);
+ }
+
+ /* update wake mask value? */
+ if (update_wake_mask != 0U) {
+ val |= CSTATE_WAKE_MASK_UPDATE_BIT;
+ }
+
+ /* set the wake mask */
+ val &= CSTATE_WAKE_MASK_CLEAR;
+ val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT);
+
+ /* set the updated cstate info */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
+
+ return 0;
+}
+
+int32_t nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time)
+{
+ int32_t ret = 0;
+
+ (void)ari_base;
+
+ /* sanity check crossover type */
+ if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1) {
+ ret = EINVAL;
+ } else {
+ /*
+ * The crossover threshold limit types start from
+ * TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7.
+ * The command indices for updating the threshold be generated
+ * by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6
+ * command index.
+ */
+ nvg_set_request_data((TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 +
+ (uint64_t)type), (uint64_t)time);
+ }
+
+ return ret;
+}
+
+uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state)
+{
+ uint64_t ret;
+
+ (void)ari_base;
+
+ /* sanity check state */
+ if (state == 0U) {
+ ret = EINVAL;
+ } else {
+ /*
+ * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
+ * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
+ * reading the threshold can be generated by adding the type to
+ * the NVG_CLEAR_CSTATE_STATS command index.
+ */
+ nvg_set_request((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR +
+ (uint64_t)state));
+ ret = nvg_get_result();
+ }
+
+ return ret;
+}
+
+int32_t nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats)
+{
+ uint64_t val;
+
+ (void)ari_base;
+
+ /*
+ * The only difference between a CSTATE_STATS_WRITE and
+ * CSTATE_STATS_READ is the usage of the 63:32 in the request.
+ * 63:32 are set to '0' for a read, while a write contains the
+ * actual stats value to be written.
+ */
+ val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state;
+
+ /*
+ * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
+ * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
+ * reading the threshold can be generated by adding the type to
+ * the NVG_CLEAR_CSTATE_STATS command index.
+ */
+ nvg_set_request_data((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR +
+ (uint64_t)state), val);
+
+ return 0;
+}
+
+int32_t nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+ (void)ari_base;
+ (void)state;
+ (void)wake_time;
+
+ /* This does not apply to the Denver cluster */
+ return 0;
+}
+
+int32_t nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
+{
+ uint64_t val;
+ int32_t ret;
+
+ (void)ari_base;
+
+ /* check for allowed power state */
+ if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) &&
+ (state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) {
+ ERROR("%s: unknown cstate (%d)\n", __func__, state);
+ ret = EINVAL;
+ } else {
+ /*
+ * Request format -
+ * 63:32 = wake time
+ * 31:0 = C-state for this core
+ */
+ val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) |
+ ((uint64_t)state & MCE_SC7_ALLOWED_MASK);
+
+ /* issue command to check if SC7 is allowed */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val);
+
+ /* 1 = SC7 allowed, 0 = SC7 not allowed */
+ ret = (nvg_get_result() != 0ULL) ? 1 : 0;
+ }
+
+ return ret;
+}
+
+int32_t nvg_online_core(uint32_t ari_base, uint32_t core)
+{
+ uint64_t cpu = read_mpidr() & MPIDR_CPU_MASK;
+ uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+ int32_t ret = 0;
+
+ (void)ari_base;
+
+ /* sanity check code id */
+ if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) {
+ ERROR("%s: unsupported core id (%d)\n", __func__, core);
+ ret = EINVAL;
+ } else {
+ /*
+ * The Denver cluster has 2 CPUs only - 0, 1.
+ */
+ if ((impl == DENVER_IMPL) && ((core == 2U) || (core == 3U))) {
+ ERROR("%s: unknown core id (%d)\n", __func__, core);
+ ret = EINVAL;
+ } else {
+ /* get a core online */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_ONLINE_CORE,
+ ((uint64_t)core & MCE_CORE_ID_MASK));
+ }
+ }
+
+ return ret;
+}
+
+int32_t nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable)
+{
+ uint32_t val;
+
+ (void)ari_base;
+
+ /*
+ * If the enable bit is cleared, Auto-CC3 will be disabled by setting
+ * the SW visible voltage/frequency request registers for all non
+ * floorswept cores valid independent of StandbyWFI and disabling
+ * the IDLE voltage/frequency request register. If set, Auto-CC3
+ * will be enabled by setting the ARM SW visible voltage/frequency
+ * request registers for all non floorswept cores to be enabled by
+ * StandbyWFI or the equivalent signal, and always keeping the IDLE
+ * voltage/frequency request register enabled.
+ */
+ val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\
+ ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\
+ ((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U));
+
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CC3_CTRL, (uint64_t)val);
+
+ return 0;
+}
diff --git a/plat/nvidia/tegra/soc/t186/drivers/se/se.c b/plat/nvidia/tegra/soc/t186/drivers/se/se.c
new file mode 100644
index 0000000..25f8cd0
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/se/se.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <string.h>
+
+#include <bpmp_ipc.h>
+#include <pmc.h>
+#include <security_engine.h>
+#include <tegra_private.h>
+
+#include "se_private.h"
+
+/*******************************************************************************
+ * Constants and Macros
+ ******************************************************************************/
+#define SE0_MAX_BUSY_TIMEOUT_MS U(100) /* 100ms */
+#define BYTES_IN_WORD U(4)
+#define SHA256_MAX_HASH_RESULT U(7)
+#define SHA256_DST_SIZE U(32)
+#define SHA_FIRST_OP U(1)
+#define MAX_SHA_ENGINE_CHUNK_SIZE U(0xFFFFFF)
+#define SHA256_MSG_LENGTH_ONETIME U(0xffff)
+
+/*
+ * Check that SE operation has completed after kickoff
+ * This function is invoked after an SE operation has been started,
+ * and it checks the following conditions:
+ * 1. SE0_INT_STATUS = SE0_OP_DONE
+ * 2. SE0_STATUS = IDLE
+ * 3. SE0_ERR_STATUS is clean.
+ */
+static int32_t tegra_se_operation_complete(void)
+{
+ uint32_t val = 0U;
+
+ /* Read SE0 interrupt register to ensure H/W operation complete */
+ val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+ if (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
+ ERROR("%s: Engine busy state too many times! val = 0x%x\n",
+ __func__, val);
+ return -ETIMEDOUT;
+ }
+
+ /* Read SE0 status idle to ensure H/W operation complete */
+ val = tegra_se_read_32(SE0_SHA_STATUS_0);
+ if (val != SE0_SHA_STATUS_IDLE) {
+ ERROR("%s: Idle state timeout! val = 0x%x\n", __func__,
+ val);
+ return -ETIMEDOUT;
+ }
+
+ /* Ensure that no errors are thrown during operation */
+ val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
+ if (val != SE0_ERR_STATUS_CLEAR) {
+ ERROR("%s: Error during SE operation! val = 0x%x",
+ __func__, val);
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+/*
+ * Security engine primitive normal operations
+ */
+static int32_t tegra_se_start_normal_operation(uint64_t src_addr,
+ uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes)
+{
+ int32_t ret = 0;
+ uint32_t val = 0U;
+ uint32_t src_in_lo;
+ uint32_t src_in_msb;
+ uint32_t src_in_hi;
+
+ if ((src_addr == 0UL) || (nbytes == 0U))
+ return -EINVAL;
+
+ src_in_lo = (uint32_t)src_addr;
+ src_in_msb = ((uint32_t)(src_addr >> 32U) & 0xffU);
+ src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) |
+ (nbytes & 0xffffffU));
+
+ /* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/
+ tegra_se_write_32(SE0_IN_ADDR, src_in_lo);
+ tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi);
+
+ val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+ if (val > 0U) {
+ tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x00000U);
+ }
+
+ /* Enable SHA interrupt for SE0 Operation */
+ tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU);
+
+ /* flush to DRAM for SE to use the updated contents */
+ flush_dcache_range(src_addr, src_len_inbytes);
+
+ /* Start SHA256 operation */
+ if (last_buf == 1U) {
+ tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START |
+ SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD);
+ } else {
+ tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START);
+ }
+
+ /* Wait for SE-operation to finish */
+ udelay(SE0_MAX_BUSY_TIMEOUT_MS * 100U);
+
+ /* Check SE0 operation status */
+ ret = tegra_se_operation_complete();
+ if (ret != 0) {
+ ERROR("SE operation complete Failed! 0x%x", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr,
+ uint32_t src_len_inbyte)
+{
+ uint32_t val, last_buf, i;
+ int32_t ret = 0;
+ uint32_t operations;
+ uint64_t src_len_inbits;
+ uint32_t len_bits_msb;
+ uint32_t len_bits_lsb;
+ uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes;
+
+ if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) {
+ ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte);
+ return -EINVAL;
+ }
+
+ if (src_addr == 0UL) {
+ return -EINVAL;
+ }
+
+ /* number of bytes per operation */
+ max_bytes = SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME;
+
+ src_len_inbits = src_len_inbyte * 8U;
+ len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
+ len_bits_lsb = (uint32_t)(src_len_inbits & 0xFFFFFFFF);
+
+ /* program SE0_CONFIG for SHA256 operation */
+ val = SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 |
+ SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG;
+ tegra_se_write_32(SE0_SHA_CONFIG, val);
+
+ /* set SE0_SHA_MSG_LENGTH registers */
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb);
+
+ /* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U);
+
+ number_of_operations = src_len_inbyte / max_bytes;
+ remaining_bytes = src_len_inbyte % max_bytes;
+ if (remaining_bytes > 0U) {
+ number_of_operations += 1U;
+ }
+
+ /*
+ * 1. Operations == 1: program SE0_SHA_TASK register to initiate SHA256
+ * hash generation by setting
+ * 1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK
+ * and start SHA256-normal operation.
+ * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to
+ * 0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load
+ * intermediate SHA256 digest result from
+ * HASH_RESULT register to continue SHA256
+ * generation and start SHA256-normal operation.
+ * 3. Operations == number_of_operations: continue with step 2 and set
+ * max_bytes to bytes_left to process final
+ * hash-result generation and
+ * start SHA256-normal operation.
+ */
+ bytes_left = src_len_inbyte;
+ for (operations = 1U; operations <= number_of_operations;
+ operations++) {
+ if (operations == SHA_FIRST_OP) {
+ val = SE0_SHA_CONFIG_HW_INIT_HASH;
+ } else {
+ /* Load intermediate SHA digest result to
+ * SHA:HASH_RESULT(0..7) to continue the SHA
+ * calculation and tell the SHA engine to use it.
+ */
+ for (i = 0U; (i / BYTES_IN_WORD) <=
+ SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) {
+ val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 +
+ i);
+ tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i,
+ val);
+ }
+ val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE;
+ if (len_bits_lsb <= (max_bytes * 8U)) {
+ len_bits_lsb = (remaining_bytes * 8U);
+ } else {
+ len_bits_lsb -= (max_bytes * 8U);
+ }
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+ }
+ tegra_se_write_32(SE0_SHA_TASK_CONFIG, val);
+
+ max_bytes = (SHA256_HASH_SIZE_BYTES *
+ SHA256_MSG_LENGTH_ONETIME);
+ if (bytes_left < max_bytes) {
+ max_bytes = bytes_left;
+ last_buf = 1U;
+ } else {
+ bytes_left = bytes_left - max_bytes;
+ last_buf = 0U;
+ }
+ /* start operation */
+ ret = tegra_se_start_normal_operation(src_addr, max_bytes,
+ last_buf, src_len_inbyte);
+ if (ret != 0) {
+ ERROR("Error during SE operation! 0x%x", ret);
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Handler to generate SHA256 and save SHA256 hash to PMC-Scratch register.
+ */
+int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte)
+{
+ int32_t ret = 0;
+ uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U, security;
+
+ /*
+ * Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE
+ * registers.
+ */
+ security = tegra_se_read_32(SE0_SECURITY);
+ tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING);
+
+ ret = tegra_se_calculate_sha256_hash(bl31_base, src_len_inbyte);
+ if (ret != 0L) {
+ ERROR("%s: SHA256 generation failed\n", __func__);
+ return ret;
+ }
+
+ /*
+ * Reset SE_SECURE to previous value.
+ */
+ tegra_se_write_32(SE0_SECURITY, security);
+
+ /* read SHA256_HASH_RESULT and save to PMC Scratch registers */
+ scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
+ while (scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END) {
+
+ val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
+ mmio_write_32(TEGRA_SCRATCH_BASE + scratch_offset, val);
+
+ hash_offset += BYTES_IN_WORD;
+ scratch_offset += BYTES_IN_WORD;
+ }
+
+ return ret;
+}
+
diff --git a/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h
new file mode 100644
index 0000000..7aa0dd6
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SE_PRIVATE_H
+#define SE_PRIVATE_H
+
+#include <lib/utils_def.h>
+
+/* SE0 security register */
+#define SE0_SECURITY U(0x18)
+#define SE0_SECURITY_SE_SOFT_SETTING (((uint32_t)1) << 16U)
+
+/* SE0 config register */
+#define SE0_SHA_CONFIG U(0x104)
+#define SE0_SHA_TASK_CONFIG U(0x108)
+#define SE0_SHA_CONFIG_HW_INIT_HASH ((1U) << 0U)
+#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE U(0)
+
+#define SE0_CONFIG_ENC_ALG_SHIFT U(12)
+#define SE0_CONFIG_ENC_ALG_SHA \
+ (((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT)
+#define SE0_CONFIG_DEC_ALG_SHIFT U(8)
+#define SE0_CONFIG_DEC_ALG_NOP \
+ (((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT)
+#define SE0_CONFIG_DST_SHIFT U(2)
+#define SE0_CONFIG_DST_HASHREG \
+ (((uint32_t)1) << SE0_CONFIG_DST_SHIFT)
+#define SHA256_HASH_SIZE_BYTES U(256)
+
+#define SE0_CONFIG_ENC_MODE_SHIFT U(24)
+#define SE0_CONFIG_ENC_MODE_SHA256 \
+ (((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT)
+
+/* SHA input message length */
+#define SE0_SHA_MSG_LENGTH_0 U(0x11c)
+#define SE0_SHA_MSG_LENGTH_1 U(0x120)
+#define SE0_SHA_MSG_LENGTH_2 U(0x124)
+#define SE0_SHA_MSG_LENGTH_3 U(0x128)
+
+/* SHA input message left */
+#define SE0_SHA_MSG_LEFT_0 U(0x12c)
+#define SE0_SHA_MSG_LEFT_1 U(0x130)
+#define SE0_SHA_MSG_LEFT_2 U(0x134)
+#define SE0_SHA_MSG_LEFT_3 U(0x138)
+
+/* SE Hash Result */
+#define SE0_SHA_HASH_RESULT_0 U(0x13c)
+
+/* SE OPERATION */
+#define SE0_OPERATION_REG_OFFSET U(0x17c)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT U(16)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD \
+ (((uint32_t)0x1) << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT)
+#define SE0_OPERATION_SHIFT U(0)
+#define SE0_OP_START \
+ (((uint32_t)0x1) << SE0_OPERATION_SHIFT)
+
+/* SE Interrupt */
+#define SE0_SHA_INT_ENABLE U(0x180)
+
+#define SE0_INT_STATUS_REG_OFFSET U(0x184)
+#define SE0_INT_OP_DONE_SHIFT U(4)
+#define SE0_INT_OP_DONE_CLEAR \
+ (((uint32_t)0) << SE0_INT_OP_DONE_SHIFT)
+#define SE0_INT_OP_DONE(x) \
+ ((x) & (((uint32_t)0x1) << SE0_INT_OP_DONE_SHIFT))
+
+/* SE SHA status */
+#define SE0_SHA_STATUS_0 U(0x188)
+#define SE0_SHA_STATUS_IDLE U(0)
+
+/* SE error status */
+#define SE0_ERR_STATUS_REG_OFFSET U(0x18c)
+#define SE0_ERR_STATUS_CLEAR U(0)
+#define SE0_IN_ADDR U(0x10c)
+#define SE0_IN_HI_ADDR_HI U(0x110)
+#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT U(24)
+
+/* SE error status */
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START SECURE_SCRATCH_RSV63_LO
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END SECURE_SCRATCH_RSV66_HI
+
+/*******************************************************************************
+ * Inline functions definition
+ ******************************************************************************/
+
+static inline uint32_t tegra_se_read_32(uint32_t offset)
+{
+ return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset));
+}
+
+static inline void tegra_se_write_32(uint32_t offset, uint32_t val)
+{
+ mmio_write_32(((uint32_t)(TEGRA_SE0_BASE + offset)), val);
+}
+
+#endif /* SE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
new file mode 100644
index 0000000..81de674
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+
+#include <mce.h>
+#include <memctrl_v2.h>
+#include <tegra186_private.h>
+#include <tegra_mc_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+extern uint64_t tegra_bl31_phys_base;
+
+/*******************************************************************************
+ * Array to hold stream_id override config register offsets
+ ******************************************************************************/
+const static uint32_t tegra186_streamid_override_regs[] = {
+ MC_STREAMID_OVERRIDE_CFG_SDMMCRA,
+ MC_STREAMID_OVERRIDE_CFG_SDMMCRAA,
+ MC_STREAMID_OVERRIDE_CFG_SDMMCR,
+ MC_STREAMID_OVERRIDE_CFG_SDMMCRAB,
+ MC_STREAMID_OVERRIDE_CFG_SDMMCWA,
+ MC_STREAMID_OVERRIDE_CFG_SDMMCWAA,
+ MC_STREAMID_OVERRIDE_CFG_SDMMCW,
+ MC_STREAMID_OVERRIDE_CFG_SDMMCWAB,
+};
+
+/*******************************************************************************
+ * Array to hold the security configs for stream IDs
+ ******************************************************************************/
+const static mc_streamid_security_cfg_t tegra186_streamid_sec_cfgs[] = {
+ mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(AFIR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(AFIW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(XUSB_DEVR, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(VICSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(TSECSRDB, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(AXISW, SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCWAB, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(AONDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(GPUSWR2, SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SESWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(GPUSRD, SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(ISPWA, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(XUSB_HOSTW, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(TSECSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCRAA, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(VIW, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(ISPRA, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(XUSB_DEVW, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(XUSB_HOSTR, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(AONDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(AONW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCRA, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, DISABLE),
+ mc_make_sec_cfg(AONR, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(SESRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(GPUSWR, SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(ISPWB, NON_SECURE, OVERRIDE, ENABLE),
+ mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, DISABLE),
+ mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+};
+
+/*******************************************************************************
+ * Array to hold the transaction override configs
+ ******************************************************************************/
+const static mc_txn_override_cfg_t tegra186_txn_override_cfgs[] = {
+ mc_make_txn_override_cfg(BPMPW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(EQOSW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(NVJPGSWR, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SDMMCWAA, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(MPCOREW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SCEDMAW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SDMMCW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(AXISW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(TSECSWR, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(GPUSWR, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(XUSB_HOSTW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(TSECSWRB, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(GPUSWR2, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(AONDMAW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(AONW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SESWR, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(BPMPDMAW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SDMMCWA, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(HDAW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(NVDECSWR, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(UFSHCW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SATAW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(ETRW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(VICSWR, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(NVENCSWR, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SDMMCWAB, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(ISPWB, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(APEW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(XUSB_DEVW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(AFIW, CGID_TAG_ADR),
+ mc_make_txn_override_cfg(SCEW, CGID_TAG_ADR),
+};
+
+static void tegra186_memctrl_reconfig_mss_clients(void)
+{
+#if ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS
+ uint32_t val, wdata_0, wdata_1;
+
+ /*
+ * Assert Memory Controller's HOTRESET_FLUSH_ENABLE signal for
+ * boot and strongly ordered MSS clients to flush existing memory
+ * traffic and stall future requests.
+ */
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL0);
+ assert(val == MC_CLIENT_HOTRESET_CTRL0_RESET_VAL);
+
+ wdata_0 = MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB;
+ tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
+
+ /* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
+ do {
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0);
+ } while ((val & wdata_0) != wdata_0);
+
+ /* Wait one more time due to SW WAR for known legacy issue */
+ do {
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0);
+ } while ((val & wdata_0) != wdata_0);
+
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL1);
+ assert(val == MC_CLIENT_HOTRESET_CTRL1_RESET_VAL);
+
+ wdata_1 = MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB |
+ MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB;
+ tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
+
+ /* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
+ do {
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1);
+ } while ((val & wdata_1) != wdata_1);
+
+ /* Wait one more time due to SW WAR for known legacy issue */
+ do {
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1);
+ } while ((val & wdata_1) != wdata_1);
+
+ /*
+ * Change MEMTYPE_OVERRIDE from SO_DEV -> PASSTHRU for boot and
+ * strongly ordered MSS clients. ROC needs to be single point
+ * of control on overriding the memory type. So, remove TSA's
+ * memtype override.
+ *
+ * MC clients with default SO_DEV override still enabled at TSA:
+ * AONW, BPMPW, SCEW, APEW
+ */
+ mc_set_tsa_passthrough(AFIW);
+ mc_set_tsa_passthrough(HDAW);
+ mc_set_tsa_passthrough(SATAW);
+ mc_set_tsa_passthrough(XUSB_HOSTW);
+ mc_set_tsa_passthrough(XUSB_DEVW);
+ mc_set_tsa_passthrough(SDMMCWAB);
+ mc_set_tsa_passthrough(APEDMAW);
+ mc_set_tsa_passthrough(SESWR);
+ mc_set_tsa_passthrough(ETRW);
+ mc_set_tsa_passthrough(AXISW);
+ mc_set_tsa_passthrough(EQOSW);
+ mc_set_tsa_passthrough(UFSHCW);
+ mc_set_tsa_passthrough(BPMPDMAW);
+ mc_set_tsa_passthrough(AONDMAW);
+ mc_set_tsa_passthrough(SCEDMAW);
+
+ /* Parker has no IO Coherency support and need the following:
+ * Ordered MC Clients on Parker are AFI, EQOS, SATA, XUSB.
+ * ISO clients(DISP, VI, EQOS) should never snoop caches and
+ * don't need ROC/PCFIFO ordering.
+ * ISO clients(EQOS) that need ordering should use PCFIFO ordering
+ * and bypass ROC ordering by using FORCE_NON_COHERENT path.
+ * FORCE_NON_COHERENT/FORCE_COHERENT config take precedence
+ * over SMMU attributes.
+ * Force all Normal memory transactions from ISO and non-ISO to be
+ * non-coherent(bypass ROC, avoid cache snoop to avoid perf hit).
+ * Force the SO_DEV transactions from ordered ISO clients(EQOS) to
+ * non-coherent path and enable MC PCFIFO interlock for ordering.
+ * Force the SO_DEV transactions from ordered non-ISO clients (PCIe,
+ * XUSB, SATA) to coherent so that the transactions are
+ * ordered by ROC.
+ * PCFIFO ensure write ordering.
+ * Read after Write ordering is maintained/enforced by MC clients.
+ * Clients that need PCIe type write ordering must
+ * go through ROC ordering.
+ * Ordering enable for Read clients is not necessary.
+ * R5's and A9 would get necessary ordering from AXI and
+ * don't need ROC ordering enable:
+ * - MMIO ordering is through dev mapping and MMIO
+ * accesses bypass SMMU.
+ * - Normal memory is accessed through SMMU and ordering is
+ * ensured by client and AXI.
+ * - Ack point for Normal memory is WCAM in MC.
+ * - MMIO's can be early acked and AXI ensures dev memory ordering,
+ * Client ensures read/write direction change ordering.
+ * - See Bug 200312466 for more details.
+ *
+ * CGID_TAG_ADR is only present from T186 A02. As this code is common
+ * between A01 and A02, tegra_memctrl_set_overrides() programs
+ * CGID_TAG_ADR for the necessary clients on A02.
+ */
+ mc_set_txn_override(HDAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(BPMPW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(PTCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVDISPLAYR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(EQOSW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVJPGSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(ISPRA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SDMMCWAA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(VICSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(MPCOREW, CGID_TAG_DEFAULT, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
+ mc_set_txn_override(GPUSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(AXISR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SCEDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SDMMCW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(EQOSR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ /* See bug 200131110 comment #35*/
+ mc_set_txn_override(APEDMAR, CGID_TAG_CLIENT_AXI_ID, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVENCSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SDMMCRAB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(VICSRD1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(BPMPDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(VIW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SDMMCRAA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(AXISW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(XUSB_DEVR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(UFSHCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(TSECSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(GPUSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SATAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(XUSB_HOSTW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT);
+ mc_set_txn_override(TSECSWRB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(GPUSRD2, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SCEDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(GPUSWR2, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(AONDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ /* See bug 200131110 comment #35*/
+ mc_set_txn_override(APEDMAW, CGID_TAG_CLIENT_AXI_ID, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(AONW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(HOST1XDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(ETRR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SESWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVJPGSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVDECSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(TSECSRDB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(BPMPDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(APER, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVDECSRD1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(XUSB_HOSTR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(ISPWA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SESRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SCER, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(AONR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(MPCORER, CGID_TAG_DEFAULT, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
+ mc_set_txn_override(SDMMCWA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(HDAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVDECSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(UFSHCW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(AONDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SATAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT);
+ mc_set_txn_override(ETRW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(VICSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVENCSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ /* See bug 200131110 comment #35 */
+ mc_set_txn_override(AFIR, CGID_TAG_DEFAULT, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SDMMCWAB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SDMMCRA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(NVDISPLAYR1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(ISPWB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(BPMPR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(APEW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(SDMMCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ mc_set_txn_override(XUSB_DEVW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT);
+ mc_set_txn_override(TSECSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+ /*
+ * See bug 200131110 comment #35 - there are no normal requests
+ * and AWID for SO/DEV requests is hardcoded in RTL for a
+ * particular PCIE controller
+ */
+ mc_set_txn_override(AFIW, CGID_TAG_DEFAULT, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_COHERENT);
+ mc_set_txn_override(SCEW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
+
+ /*
+ * At this point, ordering can occur at ROC. So, remove PCFIFO's
+ * control over ordering requests.
+ *
+ * Change PCFIFO_*_ORDERED_CLIENT from ORDERED -> UNORDERED for
+ * boot and strongly ordered MSS clients
+ */
+ val = MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL &
+ mc_set_pcfifo_unordered_boot_so_mss(1, AFIW) &
+ mc_set_pcfifo_unordered_boot_so_mss(1, HDAW) &
+ mc_set_pcfifo_unordered_boot_so_mss(1, SATAW);
+ tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG1, val);
+
+ val = MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL &
+ mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_HOSTW) &
+ mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_DEVW);
+ tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG2, val);
+
+ val = MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL &
+ mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCWAB);
+ tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG3, val);
+
+ val = MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL &
+ mc_set_pcfifo_unordered_boot_so_mss(4, SESWR) &
+ mc_set_pcfifo_unordered_boot_so_mss(4, ETRW) &
+ mc_set_pcfifo_unordered_boot_so_mss(4, AXISW) &
+ mc_set_pcfifo_unordered_boot_so_mss(4, UFSHCW) &
+ mc_set_pcfifo_unordered_boot_so_mss(4, BPMPDMAW) &
+ mc_set_pcfifo_unordered_boot_so_mss(4, AONDMAW) &
+ mc_set_pcfifo_unordered_boot_so_mss(4, SCEDMAW);
+ /* EQOSW is the only client that has PCFIFO order enabled. */
+ val |= mc_set_pcfifo_ordered_boot_so_mss(4, EQOSW);
+ tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG4, val);
+
+ val = MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL &
+ mc_set_pcfifo_unordered_boot_so_mss(5, APEDMAW);
+ tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG5, val);
+
+ /*
+ * Deassert HOTRESET FLUSH_ENABLE for boot and strongly ordered MSS
+ * clients to allow memory traffic from all clients to start passing
+ * through ROC
+ */
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL0);
+ assert(val == wdata_0);
+
+ wdata_0 = MC_CLIENT_HOTRESET_CTRL0_RESET_VAL;
+ tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
+
+ val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL1);
+ assert(val == wdata_1);
+
+ wdata_1 = MC_CLIENT_HOTRESET_CTRL1_RESET_VAL;
+ tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
+
+#endif
+}
+
+static void tegra186_memctrl_set_overrides(void)
+{
+ uint32_t i, val;
+
+ /*
+ * Set the MC_TXN_OVERRIDE registers for write clients.
+ */
+ if ((tegra_chipid_is_t186()) &&
+ (!tegra_platform_is_silicon() ||
+ (tegra_platform_is_silicon() && (tegra_get_chipid_minor() == 1U)))) {
+
+ /*
+ * GPU and NVENC settings for Tegra186 simulation and
+ * Silicon rev. A01
+ */
+ val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR);
+ val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+ tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR,
+ val | MC_TXN_OVERRIDE_CGID_TAG_ZERO);
+
+ val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2);
+ val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+ tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2,
+ val | MC_TXN_OVERRIDE_CGID_TAG_ZERO);
+
+ val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR);
+ val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+ tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR,
+ val | MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID);
+
+ } else {
+
+ /*
+ * Settings for Tegra186 silicon rev. A02 and onwards.
+ */
+ for (i = 0; i < ARRAY_SIZE(tegra186_txn_override_cfgs); i++) {
+ val = tegra_mc_read_32(tegra186_txn_override_cfgs[i].offset);
+ val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+ tegra_mc_write_32(tegra186_txn_override_cfgs[i].offset,
+ val | tegra186_txn_override_cfgs[i].cgid_tag);
+ }
+ }
+}
+
+
+/*******************************************************************************
+ * Array to hold MC context for Tegra186
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra186_mc_context[] = {
+ _START_OF_TABLE_,
+ mc_make_sid_security_cfg(SCEW),
+ mc_make_sid_security_cfg(AFIR),
+ mc_make_sid_security_cfg(NVDISPLAYR1),
+ mc_make_sid_security_cfg(XUSB_DEVR),
+ mc_make_sid_security_cfg(VICSRD1),
+ mc_make_sid_security_cfg(NVENCSWR),
+ mc_make_sid_security_cfg(TSECSRDB),
+ mc_make_sid_security_cfg(AXISW),
+ mc_make_sid_security_cfg(SDMMCWAB),
+ mc_make_sid_security_cfg(AONDMAW),
+ mc_make_sid_security_cfg(GPUSWR2),
+ mc_make_sid_security_cfg(SATAW),
+ mc_make_sid_security_cfg(UFSHCW),
+ mc_make_sid_security_cfg(AFIW),
+ mc_make_sid_security_cfg(SDMMCR),
+ mc_make_sid_security_cfg(SCEDMAW),
+ mc_make_sid_security_cfg(UFSHCR),
+ mc_make_sid_security_cfg(SDMMCWAA),
+ mc_make_sid_security_cfg(APEDMAW),
+ mc_make_sid_security_cfg(SESWR),
+ mc_make_sid_security_cfg(MPCORER),
+ mc_make_sid_security_cfg(PTCR),
+ mc_make_sid_security_cfg(BPMPW),
+ mc_make_sid_security_cfg(ETRW),
+ mc_make_sid_security_cfg(GPUSRD),
+ mc_make_sid_security_cfg(VICSWR),
+ mc_make_sid_security_cfg(SCEDMAR),
+ mc_make_sid_security_cfg(HDAW),
+ mc_make_sid_security_cfg(ISPWA),
+ mc_make_sid_security_cfg(EQOSW),
+ mc_make_sid_security_cfg(XUSB_HOSTW),
+ mc_make_sid_security_cfg(TSECSWR),
+ mc_make_sid_security_cfg(SDMMCRAA),
+ mc_make_sid_security_cfg(APER),
+ mc_make_sid_security_cfg(VIW),
+ mc_make_sid_security_cfg(APEW),
+ mc_make_sid_security_cfg(AXISR),
+ mc_make_sid_security_cfg(SDMMCW),
+ mc_make_sid_security_cfg(BPMPDMAW),
+ mc_make_sid_security_cfg(ISPRA),
+ mc_make_sid_security_cfg(NVDECSWR),
+ mc_make_sid_security_cfg(XUSB_DEVW),
+ mc_make_sid_security_cfg(NVDECSRD),
+ mc_make_sid_security_cfg(MPCOREW),
+ mc_make_sid_security_cfg(NVDISPLAYR),
+ mc_make_sid_security_cfg(BPMPDMAR),
+ mc_make_sid_security_cfg(NVJPGSWR),
+ mc_make_sid_security_cfg(NVDECSRD1),
+ mc_make_sid_security_cfg(TSECSRD),
+ mc_make_sid_security_cfg(NVJPGSRD),
+ mc_make_sid_security_cfg(SDMMCWA),
+ mc_make_sid_security_cfg(SCER),
+ mc_make_sid_security_cfg(XUSB_HOSTR),
+ mc_make_sid_security_cfg(VICSRD),
+ mc_make_sid_security_cfg(AONDMAR),
+ mc_make_sid_security_cfg(AONW),
+ mc_make_sid_security_cfg(SDMMCRA),
+ mc_make_sid_security_cfg(HOST1XDMAR),
+ mc_make_sid_security_cfg(EQOSR),
+ mc_make_sid_security_cfg(SATAR),
+ mc_make_sid_security_cfg(BPMPR),
+ mc_make_sid_security_cfg(HDAR),
+ mc_make_sid_security_cfg(SDMMCRAB),
+ mc_make_sid_security_cfg(ETRR),
+ mc_make_sid_security_cfg(AONR),
+ mc_make_sid_security_cfg(APEDMAR),
+ mc_make_sid_security_cfg(SESRD),
+ mc_make_sid_security_cfg(NVENCSRD),
+ mc_make_sid_security_cfg(GPUSWR),
+ mc_make_sid_security_cfg(TSECSWRB),
+ mc_make_sid_security_cfg(ISPWB),
+ mc_make_sid_security_cfg(GPUSRD2),
+ mc_make_sid_override_cfg(APER),
+ mc_make_sid_override_cfg(VICSRD),
+ mc_make_sid_override_cfg(NVENCSRD),
+ mc_make_sid_override_cfg(NVJPGSWR),
+ mc_make_sid_override_cfg(AONW),
+ mc_make_sid_override_cfg(BPMPR),
+ mc_make_sid_override_cfg(BPMPW),
+ mc_make_sid_override_cfg(HDAW),
+ mc_make_sid_override_cfg(NVDISPLAYR1),
+ mc_make_sid_override_cfg(APEDMAR),
+ mc_make_sid_override_cfg(AFIR),
+ mc_make_sid_override_cfg(AXISR),
+ mc_make_sid_override_cfg(VICSRD1),
+ mc_make_sid_override_cfg(TSECSRD),
+ mc_make_sid_override_cfg(BPMPDMAW),
+ mc_make_sid_override_cfg(MPCOREW),
+ mc_make_sid_override_cfg(XUSB_HOSTR),
+ mc_make_sid_override_cfg(GPUSWR),
+ mc_make_sid_override_cfg(XUSB_DEVR),
+ mc_make_sid_override_cfg(UFSHCW),
+ mc_make_sid_override_cfg(XUSB_HOSTW),
+ mc_make_sid_override_cfg(SDMMCWAB),
+ mc_make_sid_override_cfg(SATAW),
+ mc_make_sid_override_cfg(SCEDMAR),
+ mc_make_sid_override_cfg(HOST1XDMAR),
+ mc_make_sid_override_cfg(SDMMCWA),
+ mc_make_sid_override_cfg(APEDMAW),
+ mc_make_sid_override_cfg(SESWR),
+ mc_make_sid_override_cfg(AXISW),
+ mc_make_sid_override_cfg(AONDMAW),
+ mc_make_sid_override_cfg(TSECSWRB),
+ mc_make_sid_override_cfg(MPCORER),
+ mc_make_sid_override_cfg(ISPWB),
+ mc_make_sid_override_cfg(AONR),
+ mc_make_sid_override_cfg(BPMPDMAR),
+ mc_make_sid_override_cfg(HDAR),
+ mc_make_sid_override_cfg(SDMMCRA),
+ mc_make_sid_override_cfg(ETRW),
+ mc_make_sid_override_cfg(GPUSWR2),
+ mc_make_sid_override_cfg(EQOSR),
+ mc_make_sid_override_cfg(TSECSWR),
+ mc_make_sid_override_cfg(ETRR),
+ mc_make_sid_override_cfg(NVDECSRD),
+ mc_make_sid_override_cfg(TSECSRDB),
+ mc_make_sid_override_cfg(SDMMCRAA),
+ mc_make_sid_override_cfg(NVDECSRD1),
+ mc_make_sid_override_cfg(SDMMCR),
+ mc_make_sid_override_cfg(NVJPGSRD),
+ mc_make_sid_override_cfg(SCEDMAW),
+ mc_make_sid_override_cfg(SDMMCWAA),
+ mc_make_sid_override_cfg(APEW),
+ mc_make_sid_override_cfg(AONDMAR),
+ mc_make_sid_override_cfg(PTCR),
+ mc_make_sid_override_cfg(SCER),
+ mc_make_sid_override_cfg(ISPRA),
+ mc_make_sid_override_cfg(ISPWA),
+ mc_make_sid_override_cfg(VICSWR),
+ mc_make_sid_override_cfg(SESRD),
+ mc_make_sid_override_cfg(SDMMCW),
+ mc_make_sid_override_cfg(SDMMCRAB),
+ mc_make_sid_override_cfg(EQOSW),
+ mc_make_sid_override_cfg(GPUSRD2),
+ mc_make_sid_override_cfg(SCEW),
+ mc_make_sid_override_cfg(GPUSRD),
+ mc_make_sid_override_cfg(NVDECSWR),
+ mc_make_sid_override_cfg(XUSB_DEVW),
+ mc_make_sid_override_cfg(SATAR),
+ mc_make_sid_override_cfg(NVDISPLAYR),
+ mc_make_sid_override_cfg(VIW),
+ mc_make_sid_override_cfg(UFSHCR),
+ mc_make_sid_override_cfg(NVENCSWR),
+ mc_make_sid_override_cfg(AFIW),
+ mc_smmu_bypass_cfg, /* TBU settings */
+ _END_OF_TABLE_,
+};
+
+/*******************************************************************************
+ * Handler to return the pointer to the MC's context struct
+ ******************************************************************************/
+mc_regs_t *plat_memctrl_get_sys_suspend_ctx(void)
+{
+ /* index of _END_OF_TABLE_ */
+ tegra186_mc_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_mc_context)) - 1U;
+
+ return tegra186_mc_context;
+}
+
+void plat_memctrl_setup(void)
+{
+ uint32_t val;
+ unsigned int i;
+
+ /* Program all the Stream ID overrides */
+ for (i = 0U; i < ARRAY_SIZE(tegra186_streamid_override_regs); i++) {
+ tegra_mc_streamid_write_32(tegra186_streamid_override_regs[i],
+ MC_STREAM_ID_MAX);
+ }
+
+ /* Program the security config settings for all Stream IDs */
+ for (i = 0U; i < ARRAY_SIZE(tegra186_streamid_sec_cfgs); i++) {
+ val = (tegra186_streamid_sec_cfgs[i].override_enable << 16) |
+ (tegra186_streamid_sec_cfgs[i].override_client_inputs << 8) |
+ (tegra186_streamid_sec_cfgs[i].override_client_ns_flag << 0);
+ tegra_mc_streamid_write_32(tegra186_streamid_sec_cfgs[i].offset, val);
+ }
+
+ /*
+ * Re-configure MSS to allow ROC to deal with ordering of the
+ * Memory Controller traffic. This is needed as the Memory Controller
+ * boots with MSS having all control, but ROC provides a performance
+ * boost as compared to MSS.
+ */
+ tegra186_memctrl_reconfig_mss_clients();
+
+ /* Program overrides for MC transactions */
+ tegra186_memctrl_set_overrides();
+}
+
+/*******************************************************************************
+ * Handler to restore platform specific settings to the memory controller
+ ******************************************************************************/
+void plat_memctrl_restore(void)
+{
+ /*
+ * Re-configure MSS to allow ROC to deal with ordering of the
+ * Memory Controller traffic. This is needed as the Memory Controller
+ * boots with MSS having all control, but ROC provides a performance
+ * boost as compared to MSS.
+ */
+ tegra186_memctrl_reconfig_mss_clients();
+
+ /* Program overrides for MC transactions */
+ tegra186_memctrl_set_overrides();
+}
+
+/*******************************************************************************
+ * Handler to program the scratch registers with TZDRAM settings for the
+ * resume firmware
+ ******************************************************************************/
+void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes)
+{
+ uint32_t val;
+
+ /*
+ * Setup the Memory controller to allow only secure accesses to
+ * the TZDRAM carveout
+ */
+ INFO("Configuring TrustZone DRAM Memory Carveout\n");
+
+ tegra_mc_write_32(MC_SECURITY_CFG0_0, (uint32_t)phys_base);
+ tegra_mc_write_32(MC_SECURITY_CFG3_0, (uint32_t)(phys_base >> 32));
+ tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
+
+ /*
+ * When TZ encryption is enabled, we need to setup TZDRAM
+ * before CPU accesses TZ Carveout, else CPU will fetch
+ * non-decrypted data. So save TZDRAM setting for SC7 resume
+ * FW to restore.
+ *
+ * Scratch registers map:
+ * RSV55_0 = CFG1[12:0] | CFG0[31:20]
+ * RSV55_1 = CFG3[1:0]
+ */
+ val = tegra_mc_read_32(MC_SECURITY_CFG1_0) & MC_SECURITY_SIZE_MB_MASK;
+ val |= tegra_mc_read_32(MC_SECURITY_CFG0_0) & MC_SECURITY_BOM_MASK;
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_LO, val);
+
+ val = tegra_mc_read_32(MC_SECURITY_CFG3_0) & MC_SECURITY_BOM_HI_MASK;
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_HI, val);
+
+ /*
+ * MCE propagates the security configuration values across the
+ * CCPLEX.
+ */
+ (void)mce_update_gsc_tzdram();
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
new file mode 100644
index 0000000..af4182e
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <cortex_a57.h>
+#include <denver.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <bpmp_ipc.h>
+#include <mce.h>
+#include <memctrl_v2.h>
+#include <security_engine.h>
+#include <smmu.h>
+#include <t18x_ari.h>
+#include <tegra186_private.h>
+#include <tegra_private.h>
+
+extern void memcpy16(void *dest, const void *src, unsigned int length);
+
+/* state id mask */
+#define TEGRA186_STATE_ID_MASK 0xFU
+/* constants to get power state's wake time */
+#define TEGRA186_WAKE_TIME_MASK 0x0FFFFFF0U
+#define TEGRA186_WAKE_TIME_SHIFT 4U
+/* default core wake mask for CPU_SUSPEND */
+#define TEGRA186_CORE_WAKE_MASK 0x180cU
+/* context size to save during system suspend */
+#define TEGRA186_SE_CONTEXT_SIZE 3U
+
+static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE];
+static struct tegra_psci_percpu_data {
+ uint32_t wake_time;
+} __aligned(CACHE_WRITEBACK_GRANULE) tegra_percpu_data[PLATFORM_CORE_COUNT];
+
+int32_t tegra_soc_validate_power_state(uint32_t power_state,
+ psci_power_state_t *req_state)
+{
+ uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK;
+ uint32_t cpu = plat_my_core_pos();
+ int32_t ret = PSCI_E_SUCCESS;
+
+ /* save the core wake time (in TSC ticks)*/
+ tegra_percpu_data[cpu].wake_time = (power_state & TEGRA186_WAKE_TIME_MASK)
+ << TEGRA186_WAKE_TIME_SHIFT;
+
+ /*
+ * Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that
+ * the correct value is read in tegra_soc_pwr_domain_suspend(), which
+ * is called with caches disabled. It is possible to read a stale value
+ * from DRAM in that function, because the L2 cache is not flushed
+ * unless the cluster is entering CC6/CC7.
+ */
+ clean_dcache_range((uint64_t)&tegra_percpu_data[cpu],
+ sizeof(tegra_percpu_data[cpu]));
+
+ /* Sanity check the requested state id */
+ switch (state_id) {
+ case PSTATE_ID_CORE_IDLE:
+ case PSTATE_ID_CORE_POWERDN:
+
+ if (psci_get_pstate_type(power_state) != PSTATE_TYPE_POWERDOWN) {
+ ret = PSCI_E_INVALID_PARAMS;
+ break;
+ }
+
+ /* Core powerdown request */
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id;
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
+
+ break;
+
+ default:
+ ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
+ ret = PSCI_E_INVALID_PARAMS;
+ break;
+ }
+
+ return ret;
+}
+
+int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
+{
+ (void)cpu_state;
+ return PSCI_E_SUCCESS;
+}
+
+int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ const plat_local_state_t *pwr_domain_state;
+ uint8_t stateid_afflvl0, stateid_afflvl2;
+ uint32_t cpu = plat_my_core_pos();
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ mce_cstate_info_t cstate_info = { 0 };
+ uint64_t mc_ctx_base;
+ uint32_t val;
+
+ /* get the state ID */
+ pwr_domain_state = target_state->pwr_domain_state;
+ stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
+ TEGRA186_STATE_ID_MASK;
+ stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
+ TEGRA186_STATE_ID_MASK;
+
+ if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ||
+ (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
+
+ /* Enter CPU idle/powerdown */
+ val = (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ?
+ (uint32_t)TEGRA_ARI_CORE_C6 : (uint32_t)TEGRA_ARI_CORE_C7;
+ (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, (uint64_t)val,
+ tegra_percpu_data[cpu].wake_time, 0U);
+
+ } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+ /* save SE registers */
+ se_regs[0] = mmio_read_32(TEGRA_SE0_BASE +
+ SE_MUTEX_WATCHDOG_NS_LIMIT);
+ se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE +
+ RNG_MUTEX_WATCHDOG_NS_LIMIT);
+ se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE +
+ PKA_MUTEX_WATCHDOG_NS_LIMIT);
+
+ /* save 'Secure Boot' Processor Feature Config Register */
+ val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
+
+ /* save MC context to TZDRAM */
+ mc_ctx_base = params_from_bl2->tzdram_base;
+ tegra_mc_save_context((uintptr_t)mc_ctx_base);
+
+ /* Prepare for system suspend */
+ cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
+ cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC7;
+ cstate_info.system_state_force = 1;
+ cstate_info.update_wake_mask = 1;
+ mce_update_cstate_info(&cstate_info);
+
+ /* Loop until system suspend is allowed */
+ do {
+ val = (uint32_t)mce_command_handler(
+ (uint64_t)MCE_CMD_IS_SC7_ALLOWED,
+ (uint64_t)TEGRA_ARI_CORE_C7,
+ MCE_CORE_SLEEP_TIME_INFINITE,
+ 0U);
+ } while (val == 0U);
+
+ /* Instruct the MCE to enter system suspend state */
+ (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
+ (uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U);
+
+ } else {
+ ; /* do nothing */
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Helper function to check if this is the last ON CPU in the cluster
+ ******************************************************************************/
+static bool tegra_last_cpu_in_cluster(const plat_local_state_t *states,
+ uint32_t ncpu)
+{
+ plat_local_state_t target;
+ bool last_on_cpu = true;
+ uint32_t num_cpus = ncpu, pos = 0;
+
+ do {
+ target = states[pos];
+ if (target != PLAT_MAX_OFF_STATE) {
+ last_on_cpu = false;
+ }
+ --num_cpus;
+ pos++;
+ } while (num_cpus != 0U);
+
+ return last_on_cpu;
+}
+
+/*******************************************************************************
+ * Helper function to get target power state for the cluster
+ ******************************************************************************/
+static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states,
+ uint32_t ncpu)
+{
+ uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK;
+ uint32_t cpu = plat_my_core_pos();
+ int32_t ret;
+ plat_local_state_t target = states[core_pos];
+ mce_cstate_info_t cstate_info = { 0 };
+
+ /* CPU suspend */
+ if (target == PSTATE_ID_CORE_POWERDN) {
+ /* Program default wake mask */
+ cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK;
+ cstate_info.update_wake_mask = 1;
+ mce_update_cstate_info(&cstate_info);
+
+ /* Check if CCx state is allowed. */
+ ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED,
+ (uint64_t)TEGRA_ARI_CORE_C7,
+ tegra_percpu_data[cpu].wake_time,
+ 0U);
+ if (ret == 0) {
+ target = PSCI_LOCAL_STATE_RUN;
+ }
+ }
+
+ /* CPU off */
+ if (target == PLAT_MAX_OFF_STATE) {
+ /* Enable cluster powerdn from last CPU in the cluster */
+ if (tegra_last_cpu_in_cluster(states, ncpu)) {
+ /* Enable CC7 state and turn off wake mask */
+ cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
+ cstate_info.update_wake_mask = 1;
+ mce_update_cstate_info(&cstate_info);
+
+ /* Check if CCx state is allowed. */
+ ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED,
+ (uint64_t)TEGRA_ARI_CORE_C7,
+ MCE_CORE_SLEEP_TIME_INFINITE,
+ 0U);
+ if (ret == 0) {
+ target = PSCI_LOCAL_STATE_RUN;
+ }
+
+ } else {
+
+ /* Turn off wake_mask */
+ cstate_info.update_wake_mask = 1;
+ mce_update_cstate_info(&cstate_info);
+ target = PSCI_LOCAL_STATE_RUN;
+ }
+ }
+
+ return target;
+}
+
+/*******************************************************************************
+ * Platform handler to calculate the proper target power level at the
+ * specified affinity level
+ ******************************************************************************/
+plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
+ const plat_local_state_t *states,
+ uint32_t ncpu)
+{
+ plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
+ uint32_t cpu = plat_my_core_pos();
+
+ /* System Suspend */
+ if ((lvl == (uint32_t)MPIDR_AFFLVL2) &&
+ (states[cpu] == PSTATE_ID_SOC_POWERDN)) {
+ target = PSTATE_ID_SOC_POWERDN;
+ }
+
+ /* CPU off, CPU suspend */
+ if (lvl == (uint32_t)MPIDR_AFFLVL1) {
+ target = tegra_get_afflvl1_pwr_state(states, ncpu);
+ }
+
+ /* target cluster/system state */
+ return target;
+}
+
+int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
+{
+ const plat_local_state_t *pwr_domain_state =
+ target_state->pwr_domain_state;
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
+ TEGRA186_STATE_ID_MASK;
+ uint64_t val;
+ uint64_t src_len_in_bytes = (uint64_t)(((uintptr_t)(&__BL31_END__) -
+ (uintptr_t)BL31_BASE));
+ int32_t ret;
+
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+ val = params_from_bl2->tzdram_base +
+ tegra186_get_mc_ctx_size();
+
+ /* Initialise communication channel with BPMP */
+ assert(tegra_bpmp_ipc_init() == 0);
+
+ /* Enable SE clock */
+ ret = tegra_bpmp_ipc_enable_clock(TEGRA186_CLK_SE);
+ if (ret != 0) {
+ ERROR("Failed to enable clock\n");
+ return ret;
+ }
+
+ /*
+ * Generate/save SHA256 of ATF during SC7 entry
+ */
+ if (tegra_se_save_sha256_hash(BL31_BASE,
+ (uint32_t)src_len_in_bytes) != 0) {
+ ERROR("Hash calculation failed. Reboot\n");
+ (void)tegra_soc_prepare_system_reset();
+ }
+
+ /*
+ * The TZRAM loses power when we enter system suspend. To
+ * allow graceful exit from system suspend, we need to copy
+ * BL3-1 over to TZDRAM.
+ */
+ val = params_from_bl2->tzdram_base +
+ tegra186_get_mc_ctx_size();
+ memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
+ (uintptr_t)BL31_END - (uintptr_t)BL31_BASE);
+
+ /*
+ * Save code base and size; this would be used by SC7-RF to
+ * verify binary
+ */
+ mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV68_LO,
+ (uint32_t)val);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV0_HI,
+ (uint32_t)src_len_in_bytes);
+
+ ret = tegra_bpmp_ipc_disable_clock(TEGRA186_CLK_SE);
+ if (ret != 0) {
+ ERROR("Failed to disable clock\n");
+ return ret;
+ }
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int32_t tegra_soc_pwr_domain_on(u_register_t mpidr)
+{
+ int32_t ret = PSCI_E_SUCCESS;
+ uint64_t target_cpu = mpidr & MPIDR_CPU_MASK;
+ uint64_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >>
+ MPIDR_AFFINITY_BITS;
+
+ if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) {
+
+ ERROR("%s: unsupported CPU (0x%lx)\n", __func__, mpidr);
+ ret = PSCI_E_NOT_PRESENT;
+
+ } else {
+ /* construct the target CPU # */
+ target_cpu |= (target_cluster << 2);
+
+ (void)mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U);
+ }
+
+ return ret;
+}
+
+int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
+ uint8_t stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0];
+ mce_cstate_info_t cstate_info = { 0 };
+ uint64_t impl, val;
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+
+ impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+
+ /*
+ * Enable ECC and Parity Protection for Cortex-A57 CPUs (Tegra186
+ * A02p and beyond).
+ */
+ if ((plat_params->l2_ecc_parity_prot_dis != 1) && (impl != DENVER_IMPL)) {
+
+ val = read_l2ctlr_el1();
+ val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
+ write_l2ctlr_el1(val);
+ }
+
+ /*
+ * Reset power state info for CPUs when onlining, we set
+ * deepest power when offlining a core but that may not be
+ * requested by non-secure sw which controls idle states. It
+ * will re-init this info from non-secure software when the
+ * core come online.
+ */
+ if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) {
+
+ cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC1;
+ cstate_info.update_wake_mask = 1;
+ mce_update_cstate_info(&cstate_info);
+ }
+
+ /*
+ * Check if we are exiting from deep sleep and restore SE
+ * context if we are.
+ */
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+ mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT,
+ se_regs[0]);
+ mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT,
+ se_regs[1]);
+ mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT,
+ se_regs[2]);
+
+ /* Init SMMU */
+ tegra_smmu_init();
+
+ /*
+ * Reset power state info for the last core doing SC7
+ * entry and exit, we set deepest power state as CC7
+ * and SC7 for SC7 entry which may not be requested by
+ * non-secure SW which controls idle states.
+ */
+ cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
+ cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC1;
+ cstate_info.update_wake_mask = 1;
+ mce_update_cstate_info(&cstate_info);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK;
+
+ (void)target_state;
+
+ /* Disable Denver's DCO operations */
+ if (impl == DENVER_IMPL) {
+ denver_disable_dco();
+ }
+
+ /* Turn off CPU */
+ (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
+ (uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U);
+
+ return PSCI_E_SUCCESS;
+}
+
+__dead2 void tegra_soc_prepare_system_off(void)
+{
+ /* power off the entire system */
+ mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF);
+
+ wfi();
+
+ /* wait for the system to power down */
+ for (;;) {
+ ;
+ }
+}
+
+int32_t tegra_soc_prepare_system_reset(void)
+{
+ mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT);
+
+ return PSCI_E_SUCCESS;
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_secondary.c b/plat/nvidia/tegra/soc/t186/plat_secondary.c
new file mode 100644
index 0000000..fbb550a
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/plat_secondary.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mce.h>
+#include <tegra_def.h>
+#include <tegra_private.h>
+
+#define SCRATCH_SECURE_RSV1_SCRATCH_0 0x658U
+#define SCRATCH_SECURE_RSV1_SCRATCH_1 0x65CU
+
+#define CPU_RESET_MODE_AA64 1U
+
+/*******************************************************************************
+ * Setup secondary CPU vectors
+ ******************************************************************************/
+void plat_secondary_setup(void)
+{
+ uint32_t addr_low, addr_high;
+
+ INFO("Setting up secondary CPU boot\n");
+
+ /* TZDRAM base will be used as the "resume" address */
+ addr_low = (uintptr_t)&tegra_secure_entrypoint | CPU_RESET_MODE_AA64;
+ addr_high = (uintptr_t)(((uintptr_t)&tegra_secure_entrypoint >> 32U) & 0x7ffU);
+
+ /* save reset vector to be used during SYSTEM_SUSPEND exit */
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO,
+ addr_low);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI,
+ addr_high);
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
new file mode 100644
index 0000000..d6d090a
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/ep_info.h>
+#include <common/interrupt_props.h>
+#include <context.h>
+#include <cortex_a57.h>
+#include <denver.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <mce.h>
+#include <memctrl.h>
+#include <smmu.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+extern void memcpy16(void *dest, const void *src, unsigned int length);
+
+/*******************************************************************************
+ * Tegra186 CPU numbers in cluster #0
+ *******************************************************************************
+ */
+#define TEGRA186_CLUSTER0_CORE2 2U
+#define TEGRA186_CLUSTER0_CORE3 3U
+
+/*******************************************************************************
+ * The Tegra power domain tree has a single system level power domain i.e. a
+ * single root node. The first entry in the power domain descriptor specifies
+ * the number of power domains at the highest power level.
+ *******************************************************************************
+ */
+static const uint8_t tegra_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ 1,
+ /* No of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of CPU cores - cluster0 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+ /* No of CPU cores - cluster1 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the Tegra default topology tree information.
+ ******************************************************************************/
+const uint8_t *plat_get_power_domain_tree_desc(void)
+{
+ return tegra_power_domain_tree_desc;
+}
+
+/*
+ * Table of regions to map using the MMU.
+ */
+static const mmap_region_t tegra_mmap[] = {
+ MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_TSA_BASE, 0x20000U, /* 128KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000U, /* 128KB - UART A, B*/
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000U, /* 192KB - UART D, E, F */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000U, /* 128KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000U, /* 256KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_TMRUS_BASE, 0x1000U, /* 4KB */
+ MT_DEVICE | MT_RO | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000U, /* 384KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_ARM_ACTMON_CTR_BASE, 0x20000U, /* 128KB - ARM/Denver */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x1000000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x10000U, /* 64KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_BPMP_IPC_TX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_BPMP_IPC_RX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ {0}
+};
+
+/*******************************************************************************
+ * Set up the pagetables as per the platform memory map & initialize the MMU
+ ******************************************************************************/
+const mmap_region_t *plat_get_mmio_map(void)
+{
+ /* MMIO space */
+ return tegra_mmap;
+}
+
+/*******************************************************************************
+ * Handler to get the System Counter Frequency
+ ******************************************************************************/
+uint32_t plat_get_syscnt_freq2(void)
+{
+ return 31250000;
+}
+
+/*******************************************************************************
+ * Maximum supported UART controllers
+ ******************************************************************************/
+#define TEGRA186_MAX_UART_PORTS 7
+
+/*******************************************************************************
+ * This variable holds the UART port base addresses
+ ******************************************************************************/
+static uint32_t tegra186_uart_addresses[TEGRA186_MAX_UART_PORTS + 1] = {
+ 0, /* undefined - treated as an error case */
+ TEGRA_UARTA_BASE,
+ TEGRA_UARTB_BASE,
+ TEGRA_UARTC_BASE,
+ TEGRA_UARTD_BASE,
+ TEGRA_UARTE_BASE,
+ TEGRA_UARTF_BASE,
+ TEGRA_UARTG_BASE,
+};
+
+/*******************************************************************************
+ * Enable console corresponding to the console ID
+ ******************************************************************************/
+void plat_enable_console(int32_t id)
+{
+ static console_t uart_console;
+ uint32_t console_clock;
+
+ if ((id > 0) && (id < TEGRA186_MAX_UART_PORTS)) {
+ /*
+ * Reference clock used by the FPGAs is a lot slower.
+ */
+ if (tegra_platform_is_fpga()) {
+ console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
+ } else {
+ console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
+ }
+
+ (void)console_16550_register(tegra186_uart_addresses[id],
+ console_clock,
+ TEGRA_CONSOLE_BAUDRATE,
+ &uart_console);
+ console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+ }
+}
+
+/*******************************************************************************
+ * Handler for early platform setup
+ ******************************************************************************/
+void plat_early_platform_setup(void)
+{
+ uint64_t impl, val;
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+ const struct tegra_bl31_params *arg_from_bl2 = plat_get_bl31_params();
+
+ /* Verify chip id is t186 */
+ assert(tegra_chipid_is_t186());
+
+ /* sanity check MCE firmware compatibility */
+ mce_verify_firmware_version();
+
+ /*
+ * Do initial security configuration to allow DRAM/device access.
+ */
+ tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
+ (uint32_t)plat_params->tzdram_size);
+
+ impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK;
+
+ /*
+ * Enable ECC and Parity Protection for Cortex-A57 CPUs (Tegra186
+ * A02p and beyond).
+ */
+ if ((plat_params->l2_ecc_parity_prot_dis != 1) &&
+ (impl != (uint64_t)DENVER_IMPL)) {
+
+ val = read_l2ctlr_el1();
+ val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
+ write_l2ctlr_el1(val);
+ }
+
+ /*
+ * The previous bootloader might not have placed the BL32 image
+ * inside the TZDRAM. Platform handler to allow relocation of BL32
+ * image to TZDRAM memory. This behavior might change per platform.
+ */
+ plat_relocate_bl32_image(arg_from_bl2->bl32_image_info);
+}
+
+/*******************************************************************************
+ * Handler for late platform setup
+ ******************************************************************************/
+void plat_late_platform_setup(void)
+{
+ ; /* do nothing */
+}
+
+/* Secure IRQs for Tegra186 */
+static const interrupt_prop_t tegra186_interrupt_props[] = {
+ INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(TEGRA186_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(TEGRA186_AON_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE)
+};
+
+/*******************************************************************************
+ * Initialize the GIC and SGIs
+ ******************************************************************************/
+void plat_gic_setup(void)
+{
+ tegra_gic_setup(tegra186_interrupt_props, ARRAY_SIZE(tegra186_interrupt_props));
+ tegra_gic_init();
+
+ /*
+ * Initialize the FIQ handler only if the platform supports any
+ * FIQ interrupt sources.
+ */
+ tegra_fiq_handler_setup();
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 params from previous bootloader
+ ******************************************************************************/
+struct tegra_bl31_params *plat_get_bl31_params(void)
+{
+ uint32_t val;
+
+ val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_ADDR);
+
+ return (struct tegra_bl31_params *)(uintptr_t)val;
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 platform params from previous bootloader
+ ******************************************************************************/
+plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
+{
+ uint32_t val;
+
+ val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_ADDR);
+
+ return (plat_params_from_bl2_t *)(uintptr_t)val;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ u_register_t cluster_id, cpu_id, pos;
+ int32_t ret;
+
+ cluster_id = (mpidr >> (u_register_t)MPIDR_AFF1_SHIFT) & (u_register_t)MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> (u_register_t)MPIDR_AFF0_SHIFT) & (u_register_t)MPIDR_AFFLVL_MASK;
+
+ /*
+ * Validate cluster_id by checking whether it represents
+ * one of the two clusters present on the platform.
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if ((cluster_id >= (u_register_t)PLATFORM_CLUSTER_COUNT) ||
+ (cpu_id >= (u_register_t)PLATFORM_MAX_CPUS_PER_CLUSTER)) {
+ ret = PSCI_E_NOT_PRESENT;
+ } else {
+ /* calculate the core position */
+ pos = cpu_id + (cluster_id << 2U);
+
+ /* check for non-existent CPUs */
+ if ((pos == TEGRA186_CLUSTER0_CORE2) || (pos == TEGRA186_CLUSTER0_CORE3)) {
+ ret = PSCI_E_NOT_PRESENT;
+ } else {
+ ret = (int32_t)pos;
+ }
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Handler to relocate BL32 image to TZDRAM
+ ******************************************************************************/
+void plat_relocate_bl32_image(const image_info_t *bl32_img_info)
+{
+ const plat_params_from_bl2_t *plat_bl31_params = plat_get_bl31_plat_params();
+ const entry_point_info_t *bl32_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+ uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end;
+
+ if ((bl32_img_info != NULL) && (bl32_ep_info != NULL)) {
+
+ /* Relocate BL32 if it resides outside of the TZDRAM */
+ tzdram_start = plat_bl31_params->tzdram_base;
+ tzdram_end = plat_bl31_params->tzdram_base +
+ plat_bl31_params->tzdram_size;
+ bl32_start = bl32_img_info->image_base;
+ bl32_end = bl32_img_info->image_base + bl32_img_info->image_size;
+
+ assert(tzdram_end > tzdram_start);
+ assert(bl32_end > bl32_start);
+ assert(bl32_ep_info->pc > tzdram_start);
+ assert(bl32_ep_info->pc < tzdram_end);
+
+ /* relocate BL32 */
+ if ((bl32_start >= tzdram_end) || (bl32_end <= tzdram_start)) {
+
+ INFO("Relocate BL32 to TZDRAM\n");
+
+ (void)memcpy16((void *)(uintptr_t)bl32_ep_info->pc,
+ (void *)(uintptr_t)bl32_start,
+ bl32_img_info->image_size);
+
+ /* clean up non-secure intermediate buffer */
+ zeromem((void *)(uintptr_t)bl32_start,
+ bl32_img_info->image_size);
+ }
+ }
+}
+
+/*******************************************************************************
+ * Handler to indicate support for System Suspend
+ ******************************************************************************/
+bool plat_supports_system_suspend(void)
+{
+ return true;
+}
+/*******************************************************************************
+ * Platform specific runtime setup.
+ ******************************************************************************/
+void plat_runtime_setup(void)
+{
+ /*
+ * During cold boot, it is observed that the arbitration
+ * bit is set in the Memory controller leading to false
+ * error interrupts in the non-secure world. To avoid
+ * this, clean the interrupt status register before
+ * booting into the non-secure world
+ */
+ tegra_memctrl_clear_pending_interrupts();
+
+ /*
+ * During boot, USB3 and flash media (SDMMC/SATA) devices need
+ * access to IRAM. Because these clients connect to the MC and
+ * do not have a direct path to the IRAM, the MC implements AHB
+ * redirection during boot to allow path to IRAM. In this mode
+ * accesses to a programmed memory address aperture are directed
+ * to the AHB bus, allowing access to the IRAM. This mode must be
+ * disabled before we jump to the non-secure world.
+ */
+ tegra_memctrl_disable_ahb_redirection();
+
+ /*
+ * Verify the integrity of the previously configured SMMU(s)
+ * settings
+ */
+ tegra_smmu_verify();
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
new file mode 100644
index 0000000..4de8a9e
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <denver.h>
+#include <lib/el3_runtime/context_mgmt.h>
+
+#include <mce.h>
+#include <memctrl.h>
+#include <t18x_ari.h>
+#include <tegra_private.h>
+
+/*******************************************************************************
+ * Offset to read the ref_clk counter value
+ ******************************************************************************/
+#define REF_CLK_OFFSET 4ULL
+
+/*******************************************************************************
+ * Tegra186 SiP SMCs
+ ******************************************************************************/
+#define TEGRA_SIP_GET_ACTMON_CLK_COUNTERS 0xC2FFFE02
+#define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0xC2FFFF00
+#define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0xC2FFFF01
+#define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0xC2FFFF02
+#define TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS 0xC2FFFF03
+#define TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS 0xC2FFFF04
+#define TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED 0xC2FFFF05
+
+#define TEGRA_SIP_MCE_CMD_CC3_CTRL 0xC2FFFF07
+#define TEGRA_SIP_MCE_CMD_ECHO_DATA 0xC2FFFF08
+#define TEGRA_SIP_MCE_CMD_READ_VERSIONS 0xC2FFFF09
+#define TEGRA_SIP_MCE_CMD_ENUM_FEATURES 0xC2FFFF0A
+#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS 0xC2FFFF0B
+#define TEGRA_SIP_MCE_CMD_ENUM_READ_MCA 0xC2FFFF0C
+#define TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA 0xC2FFFF0D
+#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0xC2FFFF0E
+#define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0xC2FFFF0F
+#define TEGRA_SIP_MCE_CMD_ENABLE_LATIC 0xC2FFFF10
+#define TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ 0xC2FFFF11
+#define TEGRA_SIP_MCE_CMD_MISC_CCPLEX 0xC2FFFF12
+
+/*******************************************************************************
+ * This function is responsible for handling all T186 SiP calls
+ ******************************************************************************/
+int32_t plat_sip_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ const void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ int32_t mce_ret, ret = 0;
+ uint32_t impl, cpu;
+ uint32_t base, core_clk_ctr, ref_clk_ctr;
+ uint32_t local_smc_fid = smc_fid;
+ uint64_t local_x1 = x1, local_x2 = x2, local_x3 = x3;
+
+ (void)x4;
+ (void)cookie;
+ (void)flags;
+
+ if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) {
+ /* 32-bit function, clear top parameter bits */
+
+ local_x1 = (uint32_t)x1;
+ local_x2 = (uint32_t)x2;
+ local_x3 = (uint32_t)x3;
+ }
+
+ /*
+ * Convert SMC FID to SMC64, to support SMC32/SMC64 configurations
+ */
+ local_smc_fid |= (SMC_64 << FUNCID_CC_SHIFT);
+
+ switch (local_smc_fid) {
+ /*
+ * Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 -
+ * 0x82FFFFFF SiP SMC space
+ */
+ case TEGRA_SIP_MCE_CMD_ENTER_CSTATE:
+ case TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO:
+ case TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME:
+ case TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS:
+ case TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS:
+ case TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED:
+ case TEGRA_SIP_MCE_CMD_CC3_CTRL:
+ case TEGRA_SIP_MCE_CMD_ECHO_DATA:
+ case TEGRA_SIP_MCE_CMD_READ_VERSIONS:
+ case TEGRA_SIP_MCE_CMD_ENUM_FEATURES:
+ case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
+ case TEGRA_SIP_MCE_CMD_ENUM_READ_MCA:
+ case TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA:
+ case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE:
+ case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE:
+ case TEGRA_SIP_MCE_CMD_ENABLE_LATIC:
+ case TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ:
+ case TEGRA_SIP_MCE_CMD_MISC_CCPLEX:
+
+ /* clean up the high bits */
+ local_smc_fid &= MCE_CMD_MASK;
+
+ /* execute the command and store the result */
+ mce_ret = mce_command_handler(local_smc_fid, local_x1, local_x2, local_x3);
+ write_ctx_reg(get_gpregs_ctx(handle),
+ CTX_GPREG_X0, (uint64_t)(mce_ret));
+ break;
+
+ /*
+ * This function ID reads the Activity monitor's core/ref clock
+ * counter values for a core/cluster.
+ *
+ * x1 = MPIDR of the target core
+ * x2 = MIDR of the target core
+ */
+ case TEGRA_SIP_GET_ACTMON_CLK_COUNTERS:
+
+ cpu = (uint32_t)x1 & MPIDR_CPU_MASK;
+ impl = ((uint32_t)x2 >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+
+ /* sanity check target CPU number */
+ if (cpu > (uint32_t)PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ ret = -EINVAL;
+ } else {
+ /* get the base address for the current CPU */
+ base = (impl == DENVER_IMPL) ? TEGRA_DENVER_ACTMON_CTR_BASE :
+ TEGRA_ARM_ACTMON_CTR_BASE;
+
+ /* read the clock counter values */
+ core_clk_ctr = mmio_read_32(base + (8ULL * cpu));
+ ref_clk_ctr = mmio_read_32(base + (8ULL * cpu) + REF_CLK_OFFSET);
+
+ /* return the counter values as two different parameters */
+ write_ctx_reg(get_gpregs_ctx(handle),
+ CTX_GPREG_X1, (core_clk_ctr));
+ write_ctx_reg(get_gpregs_ctx(handle),
+ CTX_GPREG_X2, (ref_clk_ctr));
+ }
+
+ break;
+
+ default:
+ ret = -ENOTSUP;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_smmu.c b/plat/nvidia/tegra/soc/t186/plat_smmu.c
new file mode 100644
index 0000000..f1bc235
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/plat_smmu.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+
+#include <smmu.h>
+#include <tegra_def.h>
+#include <tegra_mc_def.h>
+
+#define MAX_NUM_SMMU_DEVICES U(1)
+
+/*******************************************************************************
+ * Handler to return the support SMMU devices number
+ ******************************************************************************/
+uint32_t plat_get_num_smmu_devices(void)
+{
+ return MAX_NUM_SMMU_DEVICES;
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_trampoline.S b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
new file mode 100644
index 0000000..2fc2046
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <memctrl_v2.h>
+#include <plat/common/common_def.h>
+#include <tegra_def.h>
+
+#define TEGRA186_MC_CTX_SIZE 0x93
+
+ .globl tegra186_get_mc_ctx_size
+
+ /*
+ * Tegra186 reset data (offset 0x0 - 0x420)
+ *
+ * 0x000: MC context start
+ * 0x420: MC context end
+ */
+
+ .align 4
+__tegra186_mc_context:
+ .rept TEGRA186_MC_CTX_SIZE
+ .quad 0
+ .endr
+
+ .align 4
+__tegra186_mc_context_end:
+
+/* return the size of the MC context */
+func tegra186_get_mc_ctx_size
+ adr x0, __tegra186_mc_context_end
+ adr x1, __tegra186_mc_context
+ sub x0, x0, x1
+ ret
+endfunc tegra186_get_mc_ctx_size
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
new file mode 100644
index 0000000..5275b8e
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -0,0 +1,77 @@
+#
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# platform configs
+ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS := 1
+$(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS))
+
+ENABLE_CHIP_VERIFICATION_HARNESS := 0
+$(eval $(call add_define,ENABLE_CHIP_VERIFICATION_HARNESS))
+
+RESET_TO_BL31 := 1
+
+PROGRAMMABLE_RESET_ADDRESS := 0
+
+COLD_BOOT_SINGLE_CPU := 1
+
+RELOCATE_BL32_IMAGE := 1
+
+# platform settings
+TZDRAM_BASE := 0x30000000
+$(eval $(call add_define,TZDRAM_BASE))
+
+PLATFORM_CLUSTER_COUNT := 2
+$(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
+
+PLATFORM_MAX_CPUS_PER_CLUSTER := 4
+$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
+
+MAX_XLAT_TABLES := 25
+$(eval $(call add_define,MAX_XLAT_TABLES))
+
+MAX_MMAP_REGIONS := 30
+$(eval $(call add_define,MAX_MMAP_REGIONS))
+
+# platform files
+PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t186 \
+ -I${SOC_DIR}/drivers/include
+
+BL31_SOURCES += ${TEGRA_GICv2_SOURCES} \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/denver.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ ${TEGRA_DRIVERS}/bpmp_ipc/intf.c \
+ ${TEGRA_DRIVERS}/bpmp_ipc/ivc.c \
+ ${TEGRA_DRIVERS}/gpcdma/gpcdma.c \
+ ${TEGRA_DRIVERS}/memctrl/memctrl_v2.c \
+ ${TEGRA_DRIVERS}/smmu/smmu.c \
+ ${SOC_DIR}/drivers/mce/mce.c \
+ ${SOC_DIR}/drivers/mce/ari.c \
+ ${SOC_DIR}/drivers/mce/nvg.c \
+ ${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \
+ $(SOC_DIR)/drivers/se/se.c \
+ ${SOC_DIR}/plat_memctrl.c \
+ ${SOC_DIR}/plat_psci_handlers.c \
+ ${SOC_DIR}/plat_setup.c \
+ ${SOC_DIR}/plat_secondary.c \
+ ${SOC_DIR}/plat_sip_calls.c \
+ ${SOC_DIR}/plat_smmu.c \
+ ${SOC_DIR}/plat_trampoline.S
+
+# Enable workarounds for selected Cortex-A57 erratas.
+A57_DISABLE_NON_TEMPORAL_HINT := 1
+ERRATA_A57_806969 := 1
+ERRATA_A57_813419 := 1
+ERRATA_A57_813420 := 1
+ERRATA_A57_826974 := 1
+ERRATA_A57_826977 := 1
+ERRATA_A57_828024 := 1
+ERRATA_A57_829520 := 1
+ERRATA_A57_833471 := 1
+
+# Enable higher performance Non-cacheable load forwarding
+A57_ENABLE_NONCACHEABLE_LOAD_FWD := 1
diff --git a/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
new file mode 100644
index 0000000..ef16980
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MCE_PRIVATE_H
+#define MCE_PRIVATE_H
+
+#include <stdbool.h>
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * Macros to prepare CSTATE info request
+ ******************************************************************************/
+/* Description of the parameters for UPDATE_CSTATE_INFO request */
+#define CLUSTER_CSTATE_MASK 0x7U
+#define CLUSTER_CSTATE_SHIFT 0X0U
+#define CLUSTER_CSTATE_UPDATE_BIT (1U << 7)
+#define CCPLEX_CSTATE_MASK 0x7U
+#define CCPLEX_CSTATE_SHIFT 8U
+#define CCPLEX_CSTATE_UPDATE_BIT (1U << 15)
+#define SYSTEM_CSTATE_MASK 0xFU
+#define SYSTEM_CSTATE_SHIFT 16U
+#define SYSTEM_CSTATE_UPDATE_BIT (1U << 23)
+#define CSTATE_WAKE_MASK_UPDATE_BIT (1U << 31)
+#define CSTATE_WAKE_MASK_SHIFT 32U
+#define CSTATE_WAKE_MASK_CLEAR 0xFFFFFFFFU
+
+/*******************************************************************************
+ * Core ID mask (bits 3:0 in the online request)
+ ******************************************************************************/
+#define MCE_CORE_ID_MASK 0xFU
+
+/*******************************************************************************
+ * C-state statistics macros
+ ******************************************************************************/
+#define MCE_STAT_ID_SHIFT 16U
+
+/*******************************************************************************
+ * Security config macros
+ ******************************************************************************/
+#define STRICT_CHECKING_ENABLED_SET (1UL << 0)
+#define STRICT_CHECKING_LOCKED_SET (1UL << 1)
+
+/* declarations for NVG handler functions */
+uint64_t nvg_get_version(void);
+void nvg_set_wake_time(uint32_t wake_time);
+void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex,
+ uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask);
+int32_t nvg_set_cstate_stat_query_value(uint64_t data);
+uint64_t nvg_get_cstate_stat_query_value(void);
+int32_t nvg_is_sc7_allowed(void);
+int32_t nvg_online_core(uint32_t core);
+int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx);
+int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time);
+int32_t nvg_roc_clean_cache_trbits(void);
+void nvg_enable_strict_checking_mode(void);
+void nvg_verify_strict_checking_mode(void);
+void nvg_system_shutdown(void);
+void nvg_system_reboot(void);
+void nvg_clear_hsm_corr_status(void);
+
+/* declarations for assembly functions */
+void nvg_set_request_data(uint64_t req, uint64_t data);
+void nvg_set_request(uint64_t req);
+uint64_t nvg_get_result(void);
+uint64_t nvg_cache_clean(void);
+uint64_t nvg_cache_clean_inval(void);
+uint64_t nvg_cache_inval_all(void);
+
+/* MCE helper functions */
+void mce_enable_strict_checking(void);
+void mce_verify_strict_checking(void);
+void mce_system_shutdown(void);
+void mce_system_reboot(void);
+void mce_clear_hsm_corr_status(void);
+
+#endif /* MCE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t194/drivers/include/se.h b/plat/nvidia/tegra/soc/t194/drivers/include/se.h
new file mode 100644
index 0000000..7de55a7
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/se.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SE_H
+#define SE_H
+
+int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
+ uint32_t src_len_inbyte);
+int32_t tegra_se_suspend(void);
+void tegra_se_resume(void);
+
+#endif /* SE_H */
diff --git a/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h b/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h
new file mode 100644
index 0000000..7a68a43
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef T194_NVG_H
+#define T194_NVG_H
+
+#include <lib/utils_def.h>
+
+/**
+ * t194_nvg.h - Header for the NVIDIA Generic interface (NVG).
+ * Official documentation for this interface is included as part
+ * of the T194 TRM.
+ */
+
+/**
+ * Current version - Major version increments may break backwards
+ * compatiblity and binary compatibility. Minor version increments
+ * occur when there is only new functionality.
+ */
+enum {
+ TEGRA_NVG_VERSION_MAJOR = U(6),
+ TEGRA_NVG_VERSION_MINOR = U(7)
+};
+
+typedef enum {
+ TEGRA_NVG_CHANNEL_VERSION = U(0),
+ TEGRA_NVG_CHANNEL_POWER_PERF = U(1),
+ TEGRA_NVG_CHANNEL_POWER_MODES = U(2),
+ TEGRA_NVG_CHANNEL_WAKE_TIME = U(3),
+ TEGRA_NVG_CHANNEL_CSTATE_INFO = U(4),
+ TEGRA_NVG_CHANNEL_CROSSOVER_C6_LOWER_BOUND = U(5),
+ TEGRA_NVG_CHANNEL_CROSSOVER_CC6_LOWER_BOUND = U(6),
+ TEGRA_NVG_CHANNEL_CROSSOVER_CG7_LOWER_BOUND = U(8),
+ TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_REQUEST = U(10),
+ TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_VALUE = U(11),
+ TEGRA_NVG_CHANNEL_NUM_CORES = U(20),
+ TEGRA_NVG_CHANNEL_UNIQUE_LOGICAL_ID = U(21),
+ TEGRA_NVG_CHANNEL_LOGICAL_TO_PHYSICAL_MAPPING = U(22),
+ TEGRA_NVG_CHANNEL_LOGICAL_TO_MPIDR = U(23),
+ TEGRA_NVG_CHANNEL_SHUTDOWN = U(42),
+ TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = U(43),
+ TEGRA_NVG_CHANNEL_ONLINE_CORE = U(44),
+ TEGRA_NVG_CHANNEL_CC3_CTRL = U(45),
+ TEGRA_NVG_CHANNEL_CCPLEX_CACHE_CONTROL = U(49),
+ TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC = U(50),
+ TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL = U(53),
+ TEGRA_NVG_CHANNEL_SECURITY_CONFIG = U(54),
+ TEGRA_NVG_CHANNEL_DEBUG_CONFIG = U(55),
+ TEGRA_NVG_CHANNEL_DDA_SNOC_MCF = U(56),
+ TEGRA_NVG_CHANNEL_DDA_MCF_ORD1 = U(57),
+ TEGRA_NVG_CHANNEL_DDA_MCF_ORD2 = U(58),
+ TEGRA_NVG_CHANNEL_DDA_MCF_ORD3 = U(59),
+ TEGRA_NVG_CHANNEL_DDA_MCF_ISO = U(60),
+ TEGRA_NVG_CHANNEL_DDA_MCF_SISO = U(61),
+ TEGRA_NVG_CHANNEL_DDA_MCF_NISO = U(62),
+ TEGRA_NVG_CHANNEL_DDA_MCF_NISO_REMOTE = U(63),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_ISO = U(64),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_SISO = U(65),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_NISO = U(66),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_NISO_REMOTE = U(67),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3FILL = U(68),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3WR = U(69),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_RSP_L3RD_DMA = U(70),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_RSP_MCFRD_DMA = U(71),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_GLOBAL = U(72),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_LL = U(73),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3D = U(74),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_FCM_RD = U(75),
+ TEGRA_NVG_CHANNEL_DDA_L3CTRL_FCM_WR = U(76),
+ TEGRA_NVG_CHANNEL_DDA_SNOC_GLOBAL_CTRL = U(77),
+ TEGRA_NVG_CHANNEL_DDA_SNOC_CLIENT_REQ_CTRL = U(78),
+ TEGRA_NVG_CHANNEL_DDA_SNOC_CLIENT_REPLENTISH_CTRL = U(79),
+ TEGRA_NVG_CHANNEL_RT_SAFE_MASK = U(80),
+ TEGRA_NVG_CHANNEL_RT_WINDOW_US = U(81),
+ TEGRA_NVG_CHANNEL_RT_FWD_PROGRESS_US = U(82),
+
+ TEGRA_NVG_CHANNEL_LAST_INDEX
+} tegra_nvg_channel_id_t;
+
+typedef enum {
+ NVG_STAT_QUERY_SC7_ENTRIES = U(1),
+ NVG_STAT_QUERY_CC6_ENTRIES = U(6),
+ NVG_STAT_QUERY_CG7_ENTRIES = U(7),
+ NVG_STAT_QUERY_C6_ENTRIES = U(10),
+ NVG_STAT_QUERY_C7_ENTRIES = U(14),
+ NVG_STAT_QUERY_SC7_RESIDENCY_SUM = U(32),
+ NVG_STAT_QUERY_CC6_RESIDENCY_SUM = U(41),
+ NVG_STAT_QUERY_CG7_RESIDENCY_SUM = U(46),
+ NVG_STAT_QUERY_C6_RESIDENCY_SUM = U(51),
+ NVG_STAT_QUERY_C7_RESIDENCY_SUM = U(56),
+ NVG_STAT_QUERY_SC7_ENTRY_TIME_SUM = U(60),
+ NVG_STAT_QUERY_CC6_ENTRY_TIME_SUM = U(61),
+ NVG_STAT_QUERY_CG7_ENTRY_TIME_SUM = U(62),
+ NVG_STAT_QUERY_C6_ENTRY_TIME_SUM = U(63),
+ NVG_STAT_QUERY_C7_ENTRY_TIME_SUM = U(64),
+ NVG_STAT_QUERY_SC7_EXIT_TIME_SUM = U(70),
+ NVG_STAT_QUERY_CC6_EXIT_TIME_SUM = U(71),
+ NVG_STAT_QUERY_CG7_EXIT_TIME_SUM = U(72),
+ NVG_STAT_QUERY_C6_EXIT_TIME_SUM = U(73),
+ NVG_STAT_QUERY_C7_EXIT_TIME_SUM = U(74),
+ NVG_STAT_QUERY_SC7_ENTRY_LAST = U(80),
+ NVG_STAT_QUERY_CC6_ENTRY_LAST = U(81),
+ NVG_STAT_QUERY_CG7_ENTRY_LAST = U(82),
+ NVG_STAT_QUERY_C6_ENTRY_LAST = U(83),
+ NVG_STAT_QUERY_C7_ENTRY_LAST = U(84),
+ NVG_STAT_QUERY_SC7_EXIT_LAST = U(90),
+ NVG_STAT_QUERY_CC6_EXIT_LAST = U(91),
+ NVG_STAT_QUERY_CG7_EXIT_LAST = U(92),
+ NVG_STAT_QUERY_C6_EXIT_LAST = U(93),
+ NVG_STAT_QUERY_C7_EXIT_LAST = U(94)
+
+} tegra_nvg_stat_query_t;
+
+typedef enum {
+ TEGRA_NVG_CORE_C0 = U(0),
+ TEGRA_NVG_CORE_C1 = U(1),
+ TEGRA_NVG_CORE_C6 = U(6),
+ TEGRA_NVG_CORE_C7 = U(7),
+ TEGRA_NVG_CORE_WARMRSTREQ = U(8)
+} tegra_nvg_core_sleep_state_t;
+
+typedef enum {
+ TEGRA_NVG_SHUTDOWN = U(0),
+ TEGRA_NVG_REBOOT = U(1)
+} tegra_nvg_shutdown_reboot_state_t;
+
+typedef enum {
+ TEGRA_NVG_CLUSTER_CC0 = U(0),
+ TEGRA_NVG_CLUSTER_AUTO_CC1 = U(1),
+ TEGRA_NVG_CLUSTER_CC6 = U(6)
+} tegra_nvg_cluster_sleep_state_t;
+
+typedef enum {
+ TEGRA_NVG_CG_CG0 = U(0),
+ TEGRA_NVG_CG_CG7 = U(7)
+} tegra_nvg_cluster_group_sleep_state_t;
+
+typedef enum {
+ TEGRA_NVG_SYSTEM_SC0 = U(0),
+ TEGRA_NVG_SYSTEM_SC7 = U(7),
+ TEGRA_NVG_SYSTEM_SC8 = U(8)
+} tegra_nvg_system_sleep_state_t;
+
+// ---------------------------------------------------------------------------
+// NVG Data subformats
+// ---------------------------------------------------------------------------
+
+typedef union {
+ uint64_t flat;
+ struct nvg_version_channel_t {
+ uint32_t minor_version : U(32);
+ uint32_t major_version : U(32);
+ } bits;
+} nvg_version_data_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t perf_per_watt : U(1);
+ uint32_t reserved_31_1 : U(31);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_power_perf_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t low_battery : U(1);
+ uint32_t reserved_1_1 : U(1);
+ uint32_t battery_save : U(1);
+ uint32_t reserved_31_3 : U(29);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_power_modes_channel_t;
+
+typedef union nvg_channel_1_data_u {
+ uint64_t flat;
+ struct nvg_channel_1_data_s {
+ uint32_t perf_per_watt_mode : U(1);
+ uint32_t reserved_31_1 : U(31);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_channel_1_data_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t gpu_ways : U(5);
+ uint32_t reserved_7_5 : U(3);
+ uint32_t gpu_only_ways : U(5);
+ uint32_t reserved_31_13 : U(19);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_ccplex_cache_control_channel_t;
+
+typedef union nvg_channel_2_data_u {
+ uint64_t flat;
+ struct nvg_channel_2_data_s {
+ uint32_t reserved_1_0 : U(2);
+ uint32_t battery_saver_mode : U(1);
+ uint32_t reserved_31_3 : U(29);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_channel_2_data_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t wake_time : U(32);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_wake_time_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t cluster_state : U(3);
+ uint32_t reserved_6_3 : U(4);
+ uint32_t update_cluster : U(1);
+ uint32_t cg_cstate : U(3);
+ uint32_t reserved_14_11 : U(4);
+ uint32_t update_cg : U(1);
+ uint32_t system_cstate : U(4);
+ uint32_t reserved_22_20 : U(3);
+ uint32_t update_system : U(1);
+ uint32_t reserved_30_24 : U(7);
+ uint32_t update_wake_mask : U(1);
+ union {
+ uint32_t flat : U(32);
+ struct {
+ uint32_t vfiq : U(1);
+ uint32_t virq : U(1);
+ uint32_t fiq : U(1);
+ uint32_t irq : U(1);
+ uint32_t serror : U(1);
+ uint32_t reserved_10_5 : U(6);
+ uint32_t fiqout : U(1);
+ uint32_t irqout : U(1);
+ uint32_t reserved_31_13 : U(19);
+ } carmel;
+ } wake_mask;
+ } bits;
+} nvg_cstate_info_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t crossover_value : U(32);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_lower_bound_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t unit_id : U(4);
+ uint32_t reserved_15_4 : U(12);
+ uint32_t stat_id : U(16);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_cstate_stat_query_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t num_cores : U(4);
+ uint32_t reserved_31_4 : U(28);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_num_cores_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t unique_core_id : U(3);
+ uint32_t reserved_31_3 : U(29);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_unique_logical_id_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t lcore0_pcore_id : U(4);
+ uint32_t lcore1_pcore_id : U(4);
+ uint32_t lcore2_pcore_id : U(4);
+ uint32_t lcore3_pcore_id : U(4);
+ uint32_t lcore4_pcore_id : U(4);
+ uint32_t lcore5_pcore_id : U(4);
+ uint32_t lcore6_pcore_id : U(4);
+ uint32_t lcore7_pcore_id : U(4);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_logical_to_physical_mappings_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct nvg_logical_to_mpidr_channel_write_t {
+ uint32_t lcore_id : U(3);
+ uint32_t reserved_31_3 : U(29);
+ uint32_t reserved_63_32 : U(32);
+ } write;
+ struct nvg_logical_to_mpidr_channel_read_t {
+ uint32_t mpidr : U(32);
+ uint32_t reserved_63_32 : U(32);
+ } read;
+} nvg_logical_to_mpidr_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t is_sc7_allowed : U(1);
+ uint32_t reserved_31_1 : U(31);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_is_sc7_allowed_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t core_id : U(4);
+ uint32_t reserved_31_4 : U(28);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_core_online_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t freq_req : U(9);
+ uint32_t reserved_30_9 : U(22);
+ uint32_t enable : U(1);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_cc3_control_channel_t;
+
+typedef enum {
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_ALL = U(0),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_NVDEC = U(1),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_WPR1 = U(2),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_WPR2 = U(3),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_TSECA = U(4),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_TSECB = U(5),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP = U(6),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_APE = U(7),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_SPE = U(8),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_SCE = U(9),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_APR = U(10),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_TZRAM = U(11),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_IPC_SE_TSEC = U(12),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_RCE = U(13),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_MCE = U(14),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_SE_SC7 = U(15),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_SPE = U(16),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_RCE = U(17),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_CPU_TZ_TO_BPMP = U(18),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_VM_ENCR1 = U(19),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_CPU_NS_TO_BPMP = U(20),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_OEM_SC7 = U(21),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_IPC_SE_SPE_SCE_BPMP = U(22),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_SC7_RESUME_FW = U(23),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_CAMERA_TASKLIST = U(24),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_XUSB = U(25),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_CV = U(26),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_VM_ENCR2 = U(27),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_HYPERVISOR_SW = U(28),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_SMMU_PAGETABLES = U(29),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_30 = U(30),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_31 = U(31),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_TZ_DRAM = U(32),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_NVLINK = U(33),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_SBS = U(34),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR = U(35),
+ TEGRA_NVG_CHANNEL_UPDATE_GSC_LAST_INDEX
+} tegra_nvg_channel_update_gsc_gsc_enum_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t gsc_enum : U(16);
+ uint32_t reserved_31_16 : U(16);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_update_ccplex_gsc_channel_t;
+
+typedef union {
+ uint64_t flat;
+ struct nvg_security_config_channel_t {
+ uint32_t strict_checking_enabled : U(1);
+ uint32_t strict_checking_locked : U(1);
+ uint32_t reserved_31_2 : U(30);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_security_config_t;
+
+typedef union {
+ uint64_t flat;
+ struct nvg_shutdown_channel_t {
+ uint32_t reboot : U(1);
+ uint32_t reserved_31_1 : U(31);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_shutdown_t;
+
+typedef union {
+ uint64_t flat;
+ struct nvg_debug_config_channel_t {
+ uint32_t enter_debug_state_on_mca : U(1);
+ uint32_t reserved_31_1 : U(31);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_debug_config_t;
+
+typedef union {
+ uint64_t flat;
+ struct {
+ uint32_t uncorr : U(1);
+ uint32_t corr : U(1);
+ uint32_t reserved_31_2 : U(30);
+ uint32_t reserved_63_32 : U(32);
+ } bits;
+} nvg_hsm_error_ctrl_channel_t;
+
+extern nvg_debug_config_t nvg_debug_config;
+
+#endif /* T194_NVG_H */
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S b/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S
new file mode 100644
index 0000000..3c47208
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+ .globl nvg_set_request_data
+ .globl nvg_set_request
+ .globl nvg_get_result
+ .globl nvg_cache_clean
+ .globl nvg_cache_clean_inval
+ .globl nvg_cache_inval_all
+
+/* void nvg_set_request_data(uint64_t req, uint64_t data) */
+func nvg_set_request_data
+ msr s3_0_c15_c1_2, x0
+ msr s3_0_c15_c1_3, x1
+ ret
+endfunc nvg_set_request_data
+
+/* void nvg_set_request(uint64_t req) */
+func nvg_set_request
+ msr s3_0_c15_c1_2, x0
+ ret
+endfunc nvg_set_request
+
+/* uint64_t nvg_get_result(void) */
+func nvg_get_result
+ mrs x0, s3_0_c15_c1_3
+ ret
+endfunc nvg_get_result
+
+/* uint64_t nvg_cache_clean(void) */
+func nvg_cache_clean
+ mrs x0, s3_0_c15_c3_5
+ ret
+endfunc nvg_cache_clean
+
+/* uint64_t nvg_cache_clean_inval(void) */
+func nvg_cache_clean_inval
+ mrs x0, s3_0_c15_c3_6
+ ret
+endfunc nvg_cache_clean_inval
+
+/* uint64_t nvg_cache_inval_all(void) */
+func nvg_cache_inval_all
+ mrs x0, s3_0_c15_c3_7
+ ret
+endfunc nvg_cache_inval_all \ No newline at end of file
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
new file mode 100644
index 0000000..af1c0aa
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <mce.h>
+#include <mce_private.h>
+#include <platform_def.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <t194_nvg.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/* Handler to check if MCE firmware is supported */
+static bool mce_firmware_not_supported(void)
+{
+ bool status;
+
+ /* these platforms do not load MCE firmware */
+ status = tegra_platform_is_linsim() || tegra_platform_is_qt() ||
+ tegra_platform_is_virt_dev_kit();
+
+ return status;
+}
+
+/*******************************************************************************
+ * Common handler for all MCE commands
+ ******************************************************************************/
+int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1,
+ uint64_t arg2)
+{
+ int32_t ret = 0;
+
+ switch (cmd) {
+ case (uint64_t)MCE_CMD_ENTER_CSTATE:
+ ret = nvg_enter_cstate((uint32_t)arg0, (uint32_t)arg1);
+ if (ret < 0) {
+ ERROR("%s: enter_cstate failed(%d)\n", __func__, ret);
+ }
+
+ break;
+
+ case (uint64_t)MCE_CMD_IS_SC7_ALLOWED:
+ ret = nvg_is_sc7_allowed();
+ if (ret < 0) {
+ ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret);
+ }
+
+ break;
+
+ case (uint64_t)MCE_CMD_ONLINE_CORE:
+ ret = nvg_online_core((uint32_t)arg0);
+ if (ret < 0) {
+ ERROR("%s: online_core failed(%d)\n", __func__, ret);
+ }
+
+ break;
+
+ default:
+ ERROR("unknown MCE command (%" PRIu64 ")\n", cmd);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Handler to update carveout values for Video Memory Carveout region
+ ******************************************************************************/
+int32_t mce_update_gsc_videomem(void)
+{
+ int32_t ret;
+
+ /*
+ * MCE firmware is not running on simulation platforms.
+ */
+ if (mce_firmware_not_supported()) {
+ ret = -EINVAL;
+ } else {
+ ret = nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR);
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Handler to update carveout values for TZDRAM aperture
+ ******************************************************************************/
+int32_t mce_update_gsc_tzdram(void)
+{
+ int32_t ret;
+
+ /*
+ * MCE firmware is not running on simulation platforms.
+ */
+ if (mce_firmware_not_supported()) {
+ ret = -EINVAL;
+ } else {
+ ret = nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_TZ_DRAM);
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * Handler to issue the UPDATE_CSTATE_INFO request
+ ******************************************************************************/
+void mce_update_cstate_info(const mce_cstate_info_t *cstate)
+{
+ /* issue the UPDATE_CSTATE_INFO request */
+ nvg_update_cstate_info(cstate->cluster, cstate->ccplex, cstate->system,
+ cstate->wake_mask, cstate->update_wake_mask);
+}
+
+/*******************************************************************************
+ * Handler to read the MCE firmware version and check if it is compatible
+ * with interface header the BL3-1 was compiled against
+ ******************************************************************************/
+void mce_verify_firmware_version(void)
+{
+ uint64_t version;
+ uint32_t major, minor;
+
+ /*
+ * MCE firmware is not running on simulation platforms.
+ */
+ if (mce_firmware_not_supported()) {
+ return;
+ }
+
+ /*
+ * Read the MCE firmware version and extract the major and minor
+ * version fields
+ */
+ version = nvg_get_version();
+ minor = (uint32_t)version;
+ major = (uint32_t)(version >> 32);
+
+ INFO("MCE Version - HW=%u:%u, SW=%u:%u\n", major, minor,
+ TEGRA_NVG_VERSION_MAJOR, TEGRA_NVG_VERSION_MINOR);
+
+ /*
+ * Verify that the MCE firmware version and the interface header
+ * match
+ */
+ if (major != (uint32_t)TEGRA_NVG_VERSION_MAJOR) {
+ ERROR("MCE major version mismatch\n");
+ panic();
+ }
+
+ if (minor < (uint32_t)TEGRA_NVG_VERSION_MINOR) {
+ ERROR("MCE minor version mismatch\n");
+ panic();
+ }
+}
+
+#if ENABLE_STRICT_CHECKING_MODE
+/*******************************************************************************
+ * Handler to enable the strict checking mode
+ ******************************************************************************/
+void mce_enable_strict_checking(void)
+{
+ uint64_t sctlr = read_sctlr_el3();
+ int32_t ret = 0;
+
+ if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) {
+ /*
+ * Step1: TZ-DRAM and TZRAM should be setup before the MMU is
+ * enabled.
+ *
+ * The common code makes sure that TZDRAM/TZRAM are already
+ * enabled before calling into this handler. If this is not the
+ * case, the following sequence must be executed before moving
+ * on to step 2.
+ *
+ * tlbialle1is();
+ * tlbialle3is();
+ * dsbsy();
+ * isb();
+ *
+ */
+ if ((sctlr & (uint64_t)SCTLR_M_BIT) == (uint64_t)SCTLR_M_BIT) {
+ tlbialle1is();
+ tlbialle3is();
+ dsbsy();
+ isb();
+ }
+
+ /*
+ * Step2: SCF flush - Clean and invalidate caches and clear the
+ * TR-bits
+ */
+ ret = nvg_roc_clean_cache_trbits();
+ if (ret < 0) {
+ ERROR("%s: flush cache_trbits failed(%d)\n", __func__,
+ ret);
+ return;
+ }
+
+ /*
+ * Step3: Issue the SECURITY_CONFIG request to MCE to enable
+ * strict checking mode.
+ */
+ nvg_enable_strict_checking_mode();
+ }
+}
+void mce_verify_strict_checking(void)
+{
+ bool is_silicon = tegra_platform_is_silicon();
+ bool is_fpga = tegra_platform_is_fpga();
+
+ if (is_silicon || is_fpga) {
+ nvg_verify_strict_checking_mode();
+ }
+}
+#endif
+
+/*******************************************************************************
+ * Handler to power down the entire system
+ ******************************************************************************/
+void mce_system_shutdown(void)
+{
+ nvg_system_shutdown();
+}
+
+/*******************************************************************************
+ * Handler to reboot the entire system
+ ******************************************************************************/
+void mce_system_reboot(void)
+{
+ nvg_system_reboot();
+}
+
+/*******************************************************************************
+ * Handler to clear CCPLEX->HSM correctable RAS error signal.
+ ******************************************************************************/
+void mce_clear_hsm_corr_status(void)
+{
+ nvg_clear_hsm_corr_status();
+}
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
new file mode 100644
index 0000000..f76ab14
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <lib/mmio.h>
+
+#include <mce_private.h>
+#include <platform_def.h>
+#include <t194_nvg.h>
+#include <tegra_private.h>
+
+#define ID_AFR0_EL1_CACHE_OPS_SHIFT U(12)
+#define ID_AFR0_EL1_CACHE_OPS_MASK U(0xF)
+/*
+ * Reports the major and minor version of this interface.
+ *
+ * NVGDATA[0:31]: SW(R) Minor Version
+ * NVGDATA[32:63]: SW(R) Major Version
+ */
+uint64_t nvg_get_version(void)
+{
+ nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_VERSION);
+
+ return (uint64_t)nvg_get_result();
+}
+
+/*
+ * Set the expected wake time in TSC ticks for the next low-power state the
+ * core enters.
+ *
+ * NVGDATA[0:31]: SW(RW), WAKE_TIME
+ */
+void nvg_set_wake_time(uint32_t wake_time)
+{
+ /* time (TSC ticks) until the core is expected to get a wake event */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, (uint64_t)wake_time);
+}
+
+/*
+ * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and
+ * SYSTEM_CSTATE values.
+ *
+ * NVGDATA[0:2]: SW(RW), CLUSTER_CSTATE
+ * NVGDATA[7]: SW(W), update cluster flag
+ * NVGDATA[8:10]: SW(RW), CG_CSTATE
+ * NVGDATA[15]: SW(W), update ccplex flag
+ * NVGDATA[16:19]: SW(RW), SYSTEM_CSTATE
+ * NVGDATA[23]: SW(W), update system flag
+ * NVGDATA[31]: SW(W), update wake mask flag
+ * NVGDATA[32:63]: SW(RW), WAKE_MASK
+ */
+void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex,
+ uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask)
+{
+ uint64_t val = 0;
+
+ /* update CLUSTER_CSTATE? */
+ if (cluster != 0U) {
+ val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) |
+ CLUSTER_CSTATE_UPDATE_BIT;
+ }
+
+ /* update CCPLEX_CSTATE? */
+ if (ccplex != 0U) {
+ val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) |
+ CCPLEX_CSTATE_UPDATE_BIT;
+ }
+
+ /* update SYSTEM_CSTATE? */
+ if (system != 0U) {
+ val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
+ SYSTEM_CSTATE_UPDATE_BIT;
+ }
+
+ /* update wake mask value? */
+ if (update_wake_mask != 0U) {
+ val |= CSTATE_WAKE_MASK_UPDATE_BIT;
+ }
+
+ /* set the wake mask */
+ val |= ((uint64_t)wake_mask & CSTATE_WAKE_MASK_CLEAR) << CSTATE_WAKE_MASK_SHIFT;
+
+ /* set the updated cstate info */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
+}
+
+/*
+ * Return a non-zero value if the CCPLEX is able to enter SC7
+ *
+ * NVGDATA[0]: SW(R), Is allowed result
+ */
+int32_t nvg_is_sc7_allowed(void)
+{
+ /* issue command to check if SC7 is allowed */
+ nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED);
+
+ /* 1 = SC7 allowed, 0 = SC7 not allowed */
+ return (int32_t)nvg_get_result();
+}
+
+/*
+ * Wake an offlined logical core. Note that a core is offlined by entering
+ * a C-state where the WAKE_MASK is all 0.
+ *
+ * NVGDATA[0:3]: SW(W) logical core to online
+ */
+int32_t nvg_online_core(uint32_t core)
+{
+ int32_t ret = 0;
+
+ /* sanity check the core ID value */
+ if (core > (uint32_t)PLATFORM_CORE_COUNT) {
+ ERROR("%s: unknown core id (%d)\n", __func__, core);
+ ret = -EINVAL;
+ } else {
+ /* get a core online */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_ONLINE_CORE,
+ (uint64_t)core & MCE_CORE_ID_MASK);
+ }
+
+ return ret;
+}
+
+/*
+ * MC GSC (General Security Carveout) register values are expected to be
+ * changed by TrustZone ARM code after boot.
+ *
+ * NVGDATA[0:15] SW(R) GSC enun
+ */
+int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx)
+{
+ int32_t ret = 0;
+
+ /* sanity check GSC ID */
+ if (gsc_idx > (uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR) {
+ ERROR("%s: unknown gsc_idx (%u)\n", __func__, gsc_idx);
+ ret = -EINVAL;
+ } else {
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC,
+ (uint64_t)gsc_idx);
+ }
+
+ return ret;
+}
+
+/*
+ * Cache clean and invalidate, clear TR-bit operation for all CCPLEX caches.
+ */
+int32_t nvg_roc_clean_cache_trbits(void)
+{
+ int32_t ret = 0;
+
+ /* check if cache flush through mts is supported */
+ if (((read_id_afr0_el1() >> ID_AFR0_EL1_CACHE_OPS_SHIFT) &
+ ID_AFR0_EL1_CACHE_OPS_MASK) == 1U) {
+ if (nvg_cache_inval_all() == 0U) {
+ ERROR("%s: failed\n", __func__);
+ ret = -ENODEV;
+ }
+ } else {
+ ret = -ENOTSUP;
+ }
+
+ return ret;
+}
+
+/*
+ * Set the power state for a core
+ */
+int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time)
+{
+ int32_t ret = 0;
+ uint64_t val = 0ULL;
+
+ /* check for allowed power state */
+ if ((state != (uint32_t)TEGRA_NVG_CORE_C0) &&
+ (state != (uint32_t)TEGRA_NVG_CORE_C1) &&
+ (state != (uint32_t)TEGRA_NVG_CORE_C6) &&
+ (state != (uint32_t)TEGRA_NVG_CORE_C7))
+ {
+ ERROR("%s: unknown cstate (%u)\n", __func__, state);
+ ret = -EINVAL;
+ } else {
+ /* time (TSC ticks) until the core is expected to get a wake event */
+ nvg_set_wake_time(wake_time);
+
+ /* set the core cstate */
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | (uint64_t)state);
+ }
+
+ return ret;
+}
+
+#if ENABLE_STRICT_CHECKING_MODE
+/*
+ * Enable strict checking mode
+ *
+ * NVGDATA[3] strict_check ON + lock
+ */
+void nvg_enable_strict_checking_mode(void)
+{
+ uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET |
+ STRICT_CHECKING_LOCKED_SET);
+
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG, params);
+}
+
+void nvg_verify_strict_checking_mode(void)
+{
+ uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET |
+ STRICT_CHECKING_LOCKED_SET);
+
+ nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG);
+ assert(params == (uint64_t)nvg_get_result());
+}
+#endif
+
+/*
+ * Request a reboot
+ *
+ * NVGDATA[0]: reboot command
+ */
+void nvg_system_reboot(void)
+{
+ /* issue command for reboot */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN,
+ (uint64_t)TEGRA_NVG_REBOOT);
+}
+
+/*
+ * Request a shutdown
+ *
+ * NVGDATA[0]: shutdown command
+ */
+void nvg_system_shutdown(void)
+{
+ /* issue command for shutdown */
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN,
+ (uint64_t)TEGRA_NVG_SHUTDOWN);
+}
+
+/*
+ * Request to clear CCPLEX->HSM correctable error signal.
+ * NVGDATA[1]: A write of 1 clears the CCPLEX->HSM correctable error signal,
+ * A write of 0 has no effect.
+ */
+void nvg_clear_hsm_corr_status(void)
+{
+ nvg_hsm_error_ctrl_channel_t status = { .bits = { .corr = 1U, }, };
+
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL, status.flat);
+}
diff --git a/plat/nvidia/tegra/soc/t194/drivers/se/se.c b/plat/nvidia/tegra/soc/t194/drivers/se/se.c
new file mode 100644
index 0000000..31b0e26
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/se/se.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <bpmp_ipc.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <se.h>
+#include <tegra_platform.h>
+
+#include "se_private.h"
+
+/*******************************************************************************
+ * Constants and Macros
+ ******************************************************************************/
+#define ERR_STATUS_SW_CLEAR U(0xFFFFFFFF)
+#define INT_STATUS_SW_CLEAR U(0xFFFFFFFF)
+#define MAX_TIMEOUT_MS U(1000) /* Max. timeout of 1s */
+#define NUM_SE_REGS_TO_SAVE U(4)
+
+#define BYTES_IN_WORD U(4)
+#define SHA256_MAX_HASH_RESULT U(7)
+#define SHA256_DST_SIZE U(32)
+#define SHA_FIRST_OP U(1)
+#define MAX_SHA_ENGINE_CHUNK_SIZE U(0xFFFFFF)
+#define SHA256_MSG_LENGTH_ONETIME U(0xFFFF)
+
+/*******************************************************************************
+ * Data structure and global variables
+ ******************************************************************************/
+static uint32_t se_regs[NUM_SE_REGS_TO_SAVE];
+
+/*
+ * Check that SE operation has completed after kickoff.
+ *
+ * This function is invoked after an SE operation has been started,
+ * and it checks the following conditions:
+ *
+ * 1. SE_STATUS = IDLE
+ * 2. AHB bus data transfer is complete.
+ * 3. SE_ERR_STATUS is clean.
+ */
+static bool tegra_se_is_operation_complete(void)
+{
+ uint32_t val = 0, timeout = 0, sha_status, aes_status;
+ int32_t ret = 0;
+ bool se_is_busy, txn_has_errors, txn_successful;
+
+ /*
+ * Poll the status register to check if the operation
+ * completed.
+ */
+ do {
+ val = tegra_se_read_32(CTX_SAVE_AUTO_STATUS);
+ se_is_busy = ((val & CTX_SAVE_AUTO_SE_BUSY) != 0U);
+
+ /* sleep until SE finishes */
+ if (se_is_busy) {
+ mdelay(1);
+ timeout++;
+ }
+
+ } while (se_is_busy && (timeout < MAX_TIMEOUT_MS));
+
+ /* any transaction errors? */
+ txn_has_errors = (tegra_se_read_32(SHA_ERR_STATUS) != 0U) ||
+ (tegra_se_read_32(AES0_ERR_STATUS) != 0U);
+
+ /* transaction successful? */
+ sha_status = tegra_se_read_32(SHA_INT_STATUS) & SHA_SE_OP_DONE;
+ aes_status = tegra_se_read_32(AES0_INT_STATUS) & AES0_SE_OP_DONE;
+ txn_successful = (sha_status == SHA_SE_OP_DONE) &&
+ (aes_status == AES0_SE_OP_DONE);
+
+ if ((timeout == MAX_TIMEOUT_MS) || txn_has_errors || !txn_successful) {
+ ERROR("%s: Atomic context save operation failed!\n",
+ __func__);
+ ret = -ECANCELED;
+ }
+
+ return (ret == 0);
+}
+
+/*
+ * Wait for SE engine to be idle and clear any pending interrupts, before
+ * starting the next SE operation.
+ */
+static bool tegra_se_is_ready(void)
+{
+ int32_t ret = 0;
+ uint32_t val = 0, timeout = 0;
+ bool se_is_ready;
+
+ /* Wait for previous operation to finish */
+ do {
+ val = tegra_se_read_32(CTX_SAVE_AUTO_STATUS);
+ se_is_ready = (val == CTX_SAVE_AUTO_SE_READY);
+
+ /* sleep until SE is ready */
+ if (!se_is_ready) {
+ mdelay(1);
+ timeout++;
+ }
+
+ } while (!se_is_ready && (timeout < MAX_TIMEOUT_MS));
+
+ if (timeout == MAX_TIMEOUT_MS) {
+ ERROR("%s: SE is not ready!\n", __func__);
+ ret = -ETIMEDOUT;
+ }
+
+ /* Clear any pending interrupts from previous operation */
+ tegra_se_write_32(AES0_INT_STATUS, INT_STATUS_SW_CLEAR);
+ tegra_se_write_32(AES1_INT_STATUS, INT_STATUS_SW_CLEAR);
+ tegra_se_write_32(RSA_INT_STATUS, INT_STATUS_SW_CLEAR);
+ tegra_se_write_32(SHA_INT_STATUS, INT_STATUS_SW_CLEAR);
+
+ /* Clear error status for each engine seen from current port */
+ tegra_se_write_32(AES0_ERR_STATUS, ERR_STATUS_SW_CLEAR);
+ tegra_se_write_32(AES1_ERR_STATUS, ERR_STATUS_SW_CLEAR);
+ tegra_se_write_32(RSA_ERR_STATUS, ERR_STATUS_SW_CLEAR);
+ tegra_se_write_32(SHA_ERR_STATUS, ERR_STATUS_SW_CLEAR);
+
+ return (ret == 0);
+}
+
+/*
+ * During System Suspend, this handler triggers the hardware context
+ * save operation.
+ */
+static int32_t tegra_se_save_context(void)
+{
+ int32_t ret = -ECANCELED;
+
+ /*
+ * 1. Ensure all SE Driver including RNG1/PKA1 are shut down.
+ * TSEC/R5s are powergated/idle. All tasks on SE1~SE4, RNG1,
+ * PKA1 are wrapped up. SE0 is ready for use.
+ * 2. Clear interrupt/error in SE0 status register.
+ * 3. Scrub SE0 register to avoid false failure for illegal
+ * configuration. Probably not needed, dependent on HW
+ * implementation.
+ * 4. Check SE is ready for HW CTX_SAVE by polling
+ * SE_CTX_SAVE_AUTO_STATUS.SE_READY.
+ *
+ * Steps 1-4 are executed by tegra_se_is_ready().
+ *
+ * 5. Issue context save command.
+ * 6. Check SE is busy with CTX_SAVE, the command in step5 was not
+ * dropped for ongoing traffic in any of SE port/engine.
+ * 7. Poll SE register or wait for SE APB interrupt for task completion
+ * a. Polling: Read SE_CTX_SAVE_AUTO_STATUS.BUSY till it reports IDLE
+ * b. Interrupt: After receiving interrupt from SE APB, read
+ * SE_CTX_SAVE_AUTO_STATUS.BUSY till it reports IDLE.
+ * 8. Check AES0 and SHA ERR_STATUS to ensure no error case.
+ * 9. Check AES0 and SHA INT_STATUS to ensure operation has successfully
+ * completed.
+ *
+ * Steps 6-9 are executed by tegra_se_is_operation_complete().
+ */
+ if (tegra_se_is_ready()) {
+
+ /* Issue context save command */
+ tegra_se_write_32(AES0_OPERATION, SE_OP_CTX_SAVE);
+
+ /* Wait for operation to finish */
+ if (tegra_se_is_operation_complete()) {
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Check that SE operation has completed after kickoff
+ * This function is invoked after an SE operation has been started,
+ * and it checks the following conditions:
+ * 1. SE0_INT_STATUS = SE0_OP_DONE
+ * 2. SE0_STATUS = IDLE
+ * 3. SE0_ERR_STATUS is clean.
+ */
+static int32_t tegra_se_sha256_hash_operation_complete(void)
+{
+ uint32_t val = 0U;
+
+ /* Poll the SE interrupt register to ensure H/W operation complete */
+ val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+ while (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
+ val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+ if (SE0_INT_OP_DONE(val) != SE0_INT_OP_DONE_CLEAR) {
+ break;
+ }
+ }
+
+ /* Poll the SE status idle to ensure H/W operation complete */
+ val = tegra_se_read_32(SE0_SHA_STATUS_0);
+ while (val != SE0_SHA_STATUS_IDLE) {
+ val = tegra_se_read_32(SE0_SHA_STATUS_0);
+ if (val == SE0_SHA_STATUS_IDLE) {
+ break;
+ }
+ }
+
+ /* Ensure that no errors are thrown during operation */
+ val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
+ if (val != 0U) {
+ ERROR("%s: error during SE operation! 0x%x", __func__,
+ val);
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+/*
+ * Security engine primitive normal operations
+ */
+static int32_t tegra_se_start_normal_operation(uint64_t src_addr,
+ uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes)
+{
+ uint32_t val = 0U;
+ uint32_t src_in_lo;
+ uint32_t src_in_msb;
+ uint32_t src_in_hi;
+ int32_t ret = 0;
+
+ if ((src_addr == 0ULL) || (nbytes == 0U))
+ return -EINVAL;
+
+ src_in_lo = (uint32_t)src_addr;
+ src_in_msb = (uint32_t)((src_addr >> 32U) & 0xFFU);
+ src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) |
+ (nbytes & MAX_SHA_ENGINE_CHUNK_SIZE));
+
+ /* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/
+ tegra_se_write_32(SE0_IN_ADDR, src_in_lo);
+ tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi);
+
+ val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
+ if (val > 0U) {
+ tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x0U);
+ }
+
+ /* Enable SHA interrupt for SE0 Operation */
+ tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU);
+
+ /* flush to DRAM for SE to use the updated contents */
+ flush_dcache_range(src_addr, src_len_inbytes);
+
+ /* Start SHA256 operation */
+ if (last_buf == 1U) {
+ tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START |
+ SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD);
+ } else {
+ tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START);
+ }
+
+ return ret;
+}
+
+static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr,
+ uint32_t src_len_inbyte)
+{
+ uint32_t val, last_buf, i;
+ int32_t ret = 0;
+ uint32_t operations;
+ uint64_t src_len_inbits;
+ uint32_t len_bits_msb;
+ uint32_t len_bits_lsb;
+ uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes;
+
+ if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) {
+ ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte);
+ return -EINVAL;
+ }
+
+ if (src_addr == 0ULL) {
+ return -EINVAL;
+ }
+
+ /* number of bytes per operation */
+ max_bytes = (SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME);
+
+ src_len_inbits = (uint32_t)(src_len_inbyte * 8U);
+ len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
+ len_bits_lsb = (uint32_t)src_len_inbits;
+
+ /* program SE0_CONFIG for SHA256 operation */
+ val = (uint32_t)(SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 |
+ SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG);
+ tegra_se_write_32(SE0_SHA_CONFIG, val);
+
+ /* set SE0_SHA_MSG_LENGTH registers */
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb);
+
+ /* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U);
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U);
+
+ number_of_operations = (src_len_inbyte / max_bytes);
+ remaining_bytes = (src_len_inbyte % max_bytes);
+ if (remaining_bytes > 0U) {
+ number_of_operations += 1U;
+ }
+
+ /*
+ * 1. Operations == 1: program SE0_SHA_TASK register to initiate SHA256
+ * hash generation by setting
+ * 1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK
+ * and start SHA256-normal operation.
+ * 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to
+ * 0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load
+ * intermediate SHA256 digest result from
+ * HASH_RESULT register to continue SHA256
+ * generation and start SHA256-normal operation.
+ * 3. Operations == number_of_operations: continue with step 2 and set
+ * max_bytes to bytes_left to process final
+ * hash-result generation and start SHA256-normal
+ * operation.
+ */
+ bytes_left = src_len_inbyte;
+ for (operations = 1U; operations <= number_of_operations;
+ operations++) {
+ if (operations == SHA_FIRST_OP) {
+ val = SE0_SHA_CONFIG_HW_INIT_HASH;
+ } else {
+ /* Load intermediate SHA digest result to
+ * SHA:HASH_RESULT(0..7) to continue the SHA
+ * calculation and tell the SHA engine to use it.
+ */
+ for (i = 0U; (i / BYTES_IN_WORD) <=
+ SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) {
+ val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 +
+ i);
+ tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i,
+ val);
+ }
+ val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE;
+ if (len_bits_lsb <= (max_bytes * 8U)) {
+ len_bits_lsb = (remaining_bytes * 8U);
+ } else {
+ len_bits_lsb -= (max_bytes * 8U);
+ }
+ tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
+ }
+ tegra_se_write_32(SE0_SHA_TASK_CONFIG, val);
+
+ max_bytes = (SHA256_HASH_SIZE_BYTES *
+ SHA256_MSG_LENGTH_ONETIME);
+ if (bytes_left < max_bytes) {
+ max_bytes = bytes_left;
+ last_buf = 1U;
+ } else {
+ bytes_left = bytes_left - max_bytes;
+ last_buf = 0U;
+ }
+ /* start operation */
+ ret = tegra_se_start_normal_operation(src_addr, max_bytes,
+ last_buf, src_len_inbyte);
+ if (ret != 0) {
+ ERROR("Error during SE operation! 0x%x", ret);
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+static int32_t tegra_se_save_sha256_pmc_scratch(void)
+{
+ uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U;
+ int32_t ret;
+
+ /* Check SE0 operation status */
+ ret = tegra_se_sha256_hash_operation_complete();
+ if (ret != 0) {
+ ERROR("SE operation complete Failed! 0x%x", ret);
+ return ret;
+ }
+
+ for (scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
+ scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END;
+ scratch_offset += BYTES_IN_WORD) {
+ val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
+ mmio_write_32((uint32_t)(TEGRA_SCRATCH_BASE + scratch_offset),
+ val);
+ hash_offset += BYTES_IN_WORD;
+ }
+ return 0;
+}
+
+/*
+ * Handler to generate SHA256 and save HASH-result to pmc-scratch register
+ */
+int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
+ uint32_t src_len_inbyte)
+{
+ uint32_t security;
+ int32_t val = 0;
+
+ /* Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE
+ * registers.
+ */
+ security = tegra_se_read_32(SE0_SECURITY);
+ tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING);
+
+ /* Bootrom enable IN_ID bit in SE0_SHA_GSCID_0 register during SC7-exit, causing
+ * SE0 ignores SE0 operation, and therefore failure of 2nd iteration of SC7 cycle.
+ */
+ tegra_se_write_32(SE0_SHA_GSCID_0, 0x0U);
+
+ /* Calculate SHA256 of BL31 */
+ val = tegra_se_calculate_sha256_hash(src_addr, src_len_inbyte);
+ if (val != 0) {
+ ERROR("%s: SHA256 generation failed\n", __func__);
+ return val;
+ }
+
+ /*
+ * Reset SE_SECURE to previous value.
+ */
+ tegra_se_write_32(SE0_SECURITY, security);
+
+ /* copy sha256_dst to PMC Scratch register */
+ val = tegra_se_save_sha256_pmc_scratch();
+ if (val != 0) {
+ ERROR("%s: SE0 status Error.\n", __func__);
+ }
+
+ return val;
+}
+
+/*
+ * Handler to power down the SE hardware blocks - SE, RNG1 and PKA1. This
+ * needs to be called only during System Suspend.
+ */
+int32_t tegra_se_suspend(void)
+{
+ int32_t ret = 0;
+
+ /* initialise communication channel with BPMP */
+ assert(tegra_bpmp_ipc_init() == 0);
+
+ /* Enable SE clock before SE context save */
+ ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
+ assert(ret == 0);
+
+ /* save SE registers */
+ se_regs[0] = mmio_read_32(TEGRA_SE0_BASE + SE0_MUTEX_WATCHDOG_NS_LIMIT);
+ se_regs[1] = mmio_read_32(TEGRA_SE0_BASE + SE0_AES0_ENTROPY_SRC_AGE_CTRL);
+ se_regs[2] = mmio_read_32(TEGRA_RNG1_BASE + RNG1_MUTEX_WATCHDOG_NS_LIMIT);
+ se_regs[3] = mmio_read_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT);
+
+ /* Save SE context. The BootROM restores it during System Resume */
+ ret = tegra_se_save_context();
+ if (ret != 0) {
+ ERROR("%s: context save failed (%d)\n", __func__, ret);
+ }
+
+ /* Disable SE clock after SE context save */
+ ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
+ assert(ret == 0);
+
+ return ret;
+}
+
+/*
+ * Handler to power up the SE hardware block(s) during System Resume.
+ */
+void tegra_se_resume(void)
+{
+ int32_t ret = 0;
+
+ /* initialise communication channel with BPMP */
+ assert(tegra_bpmp_ipc_init() == 0);
+
+ /* Enable SE clock before SE context restore */
+ ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
+ assert(ret == 0);
+
+ /*
+ * When TZ takes over after System Resume, TZ should first reconfigure
+ * SE_MUTEX_WATCHDOG_NS_LIMIT, PKA1_MUTEX_WATCHDOG_NS_LIMIT,
+ * RNG1_MUTEX_WATCHDOG_NS_LIMIT and SE_ENTROPY_SRC_AGE_CTRL before
+ * other operations.
+ */
+ mmio_write_32(TEGRA_SE0_BASE + SE0_MUTEX_WATCHDOG_NS_LIMIT, se_regs[0]);
+ mmio_write_32(TEGRA_SE0_BASE + SE0_AES0_ENTROPY_SRC_AGE_CTRL, se_regs[1]);
+ mmio_write_32(TEGRA_RNG1_BASE + RNG1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[2]);
+ mmio_write_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[3]);
+
+ /* Disable SE clock after SE context restore */
+ ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
+ assert(ret == 0);
+}
diff --git a/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
new file mode 100644
index 0000000..fc118aa
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SE_PRIVATE_H
+#define SE_PRIVATE_H
+
+#include <lib/utils_def.h>
+#include <tegra_def.h>
+
+/* SE0 security register */
+#define SE0_SECURITY U(0x18)
+#define SE0_SECURITY_SE_SOFT_SETTING (((uint32_t)1) << 16U)
+
+/* SE0 SHA GSCID register */
+#define SE0_SHA_GSCID_0 U(0x100)
+
+/* SE0 config register */
+#define SE0_SHA_CONFIG U(0x104)
+#define SE0_SHA_TASK_CONFIG U(0x108)
+#define SE0_SHA_CONFIG_HW_INIT_HASH (((uint32_t)1) << 0U)
+#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE U(0)
+
+#define SE0_CONFIG_ENC_ALG_SHIFT U(12)
+#define SE0_CONFIG_ENC_ALG_SHA \
+ (((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT)
+#define SE0_CONFIG_DEC_ALG_SHIFT U(8)
+#define SE0_CONFIG_DEC_ALG_NOP \
+ (((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT)
+#define SE0_CONFIG_DST_SHIFT U(2)
+#define SE0_CONFIG_DST_HASHREG \
+ (((uint32_t)1) << SE0_CONFIG_DST_SHIFT)
+#define SHA256_HASH_SIZE_BYTES U(256)
+
+#define SE0_CONFIG_ENC_MODE_SHIFT U(24)
+#define SE0_CONFIG_ENC_MODE_SHA256 \
+ (((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT)
+
+/* SHA input message length */
+#define SE0_IN_ADDR U(0x10c)
+#define SE0_IN_HI_ADDR_HI U(0x110)
+#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT U(24)
+
+/* SHA input message length */
+#define SE0_SHA_MSG_LENGTH_0 U(0x11c)
+#define SE0_SHA_MSG_LENGTH_1 U(0x120)
+#define SE0_SHA_MSG_LENGTH_2 U(0x124)
+#define SE0_SHA_MSG_LENGTH_3 U(0x128)
+
+/* SHA input message left */
+#define SE0_SHA_MSG_LEFT_0 U(0x12c)
+#define SE0_SHA_MSG_LEFT_1 U(0x130)
+#define SE0_SHA_MSG_LEFT_2 U(0x134)
+#define SE0_SHA_MSG_LEFT_3 U(0x138)
+
+/* SE HASH-RESULT */
+#define SE0_SHA_HASH_RESULT_0 U(0x13c)
+
+/* SE OPERATION */
+#define SE0_OPERATION_REG_OFFSET U(0x17c)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT U(16)
+#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD \
+ ((uint32_t)0x1 << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT)
+#define SE0_OPERATION_SHIFT U(0)
+#define SE0_OP_START \
+ (((uint32_t)0x1) << SE0_OPERATION_SHIFT)
+
+/* SE Interrupt */
+#define SE0_SHA_INT_ENABLE U(0x180)
+
+#define SE0_INT_STATUS_REG_OFFSET U(0x184)
+#define SE0_INT_OP_DONE_SHIFT U(4)
+#define SE0_INT_OP_DONE_CLEAR \
+ (((uint32_t)0U) << SE0_INT_OP_DONE_SHIFT)
+#define SE0_INT_OP_DONE(x) \
+ ((x) & (((uint32_t)0x1U) << SE0_INT_OP_DONE_SHIFT))
+
+/* SE SHA Status */
+#define SE0_SHA_STATUS_0 U(0x188)
+#define SE0_SHA_STATUS_IDLE U(0)
+
+/* SE error status */
+#define SE0_ERR_STATUS_REG_OFFSET U(0x18c)
+#define SE0_ERR_STATUS_CLEAR U(0)
+
+/* SE error status */
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START SECURE_SCRATCH_RSV68_LO
+#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END SECURE_SCRATCH_RSV71_HI
+
+/* SE0_INT_ENABLE_0 */
+#define SE0_INT_ENABLE U(0x88)
+#define SE0_DISABLE_ALL_INT U(0x0)
+
+/* SE0_INT_STATUS_0 */
+#define SE0_INT_STATUS U(0x8C)
+#define SE0_CLEAR_ALL_INT_STATUS U(0x3F)
+
+/* SE0_SHA_INT_STATUS_0 */
+#define SHA_INT_STATUS U(0x184)
+#define SHA_SE_OP_DONE (U(1) << 4)
+
+/* SE0_SHA_ERR_STATUS_0 */
+#define SHA_ERR_STATUS U(0x18C)
+
+/* SE0_AES0_INT_STATUS_0 */
+#define AES0_INT_STATUS U(0x2F0)
+#define AES0_SE_OP_DONE (U(1) << 4)
+
+/* SE0_AES0_ERR_STATUS_0 */
+#define AES0_ERR_STATUS U(0x2F8)
+
+/* SE0_AES1_INT_STATUS_0 */
+#define AES1_INT_STATUS U(0x4F0)
+
+/* SE0_AES1_ERR_STATUS_0 */
+#define AES1_ERR_STATUS U(0x4F8)
+
+/* SE0_RSA_INT_STATUS_0 */
+#define RSA_INT_STATUS U(0x758)
+
+/* SE0_RSA_ERR_STATUS_0 */
+#define RSA_ERR_STATUS U(0x760)
+
+/* SE0_AES0_OPERATION_0 */
+#define AES0_OPERATION U(0x238)
+#define OP_MASK_BITS U(0x7)
+#define SE_OP_CTX_SAVE U(0x3)
+
+/* SE0_AES0_CTX_SAVE_CONFIG_0 */
+#define CTX_SAVE_CONFIG U(0x2D4)
+
+/* SE0_AES0_CTX_SAVE_AUTO_STATUS_0 */
+#define CTX_SAVE_AUTO_STATUS U(0x300)
+#define CTX_SAVE_AUTO_SE_READY U(0xFF)
+#define CTX_SAVE_AUTO_SE_BUSY (U(0x1) << 31)
+
+/* SE0_AES0_CTX_SAVE_AUTO_CTRL_0 */
+#define CTX_SAVE_AUTO_CTRL U(0x304)
+#define SE_CTX_SAVE_AUTO_EN (U(0x1) << 0)
+#define SE_CTX_SAVE_AUTO_LOCK_EN (U(0x1) << 1)
+
+/* SE0_AES0_CTX_SAVE_AUTO_START_ADDR_0 */
+#define CTX_SAVE_AUTO_START_ADDR U(0x308)
+
+/* SE0_AES0_CTX_SAVE_AUTO_START_ADDR_HI_0 */
+#define CTX_SAVE_AUTO_START_ADDR_HI U(0x30C)
+
+/*******************************************************************************
+ * Inline functions definition
+ ******************************************************************************/
+
+static inline uint32_t tegra_se_read_32(uint32_t offset)
+{
+ return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset));
+}
+
+static inline void tegra_se_write_32(uint32_t offset, uint32_t val)
+{
+ mmio_write_32((uint32_t)(TEGRA_SE0_BASE + offset), val);
+}
+
+#endif /* SE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
new file mode 100644
index 0000000..9ddcacf
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <mce.h>
+#include <memctrl_v2.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/*******************************************************************************
+ * Array to hold MC context for Tegra194
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra194_mc_context[] = {
+ _START_OF_TABLE_,
+ mc_smmu_bypass_cfg, /* TBU settings */
+ _END_OF_TABLE_,
+};
+
+/*******************************************************************************
+ * Handler to return the pointer to the MC's context struct
+ ******************************************************************************/
+mc_regs_t *plat_memctrl_get_sys_suspend_ctx(void)
+{
+ /* index of _END_OF_TABLE_ */
+ tegra194_mc_context[0].val = (uint32_t)ARRAY_SIZE(tegra194_mc_context) - 1U;
+
+ return tegra194_mc_context;
+}
+
+/*******************************************************************************
+ * Handler to restore platform specific settings to the memory controller
+ ******************************************************************************/
+void plat_memctrl_restore(void)
+{
+ UNUSED_FUNC_NOP(); /* do nothing */
+}
+
+/*******************************************************************************
+ * Handler to program platform specific settings to the memory controller
+ ******************************************************************************/
+void plat_memctrl_setup(void)
+{
+ UNUSED_FUNC_NOP(); /* do nothing */
+}
+
+/*******************************************************************************
+ * Handler to program the scratch registers with TZDRAM settings for the
+ * resume firmware
+ ******************************************************************************/
+void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes)
+{
+ uint32_t sec_reg_ctrl = tegra_mc_read_32(MC_SECURITY_CFG_REG_CTRL_0);
+ uint32_t phys_base_lo = (uint32_t)phys_base & 0xFFF00000;
+ uint32_t phys_base_hi = (uint32_t)(phys_base >> 32);
+
+ /*
+ * Check TZDRAM carveout register access status. Setup TZDRAM fence
+ * only if access is enabled.
+ */
+ if ((sec_reg_ctrl & SECURITY_CFG_WRITE_ACCESS_BIT) ==
+ SECURITY_CFG_WRITE_ACCESS_ENABLE) {
+
+ /*
+ * Setup the Memory controller to allow only secure accesses to
+ * the TZDRAM carveout
+ */
+ INFO("Configuring TrustZone DRAM Memory Carveout\n");
+
+ tegra_mc_write_32(MC_SECURITY_CFG0_0, phys_base_lo);
+ tegra_mc_write_32(MC_SECURITY_CFG3_0, phys_base_hi);
+ tegra_mc_write_32(MC_SECURITY_CFG1_0, (uint32_t)(size_in_bytes >> 20));
+
+ /*
+ * MCE propagates the security configuration values across the
+ * CCPLEX.
+ */
+ (void)mce_update_gsc_tzdram();
+ }
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
new file mode 100644
index 0000000..41a85ee
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <bpmp_ipc.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/delay_timer.h>
+#include <denver.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/psci/psci.h>
+#include <mce.h>
+#include <mce_private.h>
+#include <memctrl_v2.h>
+#include <plat/common/platform.h>
+#include <se.h>
+#include <smmu.h>
+#include <t194_nvg.h>
+#include <tegra194_private.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+extern uint32_t __tegra194_cpu_reset_handler_data,
+ __tegra194_cpu_reset_handler_end;
+
+/* TZDRAM offset for saving SMMU context */
+#define TEGRA194_SMMU_CTX_OFFSET 16U
+
+/* state id mask */
+#define TEGRA194_STATE_ID_MASK 0xFU
+/* constants to get power state's wake time */
+#define TEGRA194_WAKE_TIME_MASK 0x0FFFFFF0U
+#define TEGRA194_WAKE_TIME_SHIFT 4U
+/* default core wake mask for CPU_SUSPEND */
+#define TEGRA194_CORE_WAKE_MASK 0x180cU
+
+static struct t19x_psci_percpu_data {
+ uint32_t wake_time;
+} __aligned(CACHE_WRITEBACK_GRANULE) t19x_percpu_data[PLATFORM_CORE_COUNT];
+
+int32_t tegra_soc_validate_power_state(uint32_t power_state,
+ psci_power_state_t *req_state)
+{
+ uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) &
+ TEGRA194_STATE_ID_MASK;
+ uint32_t cpu = plat_my_core_pos();
+ int32_t ret = PSCI_E_SUCCESS;
+
+ /* save the core wake time (in TSC ticks)*/
+ t19x_percpu_data[cpu].wake_time = (power_state & TEGRA194_WAKE_TIME_MASK)
+ << TEGRA194_WAKE_TIME_SHIFT;
+
+ /*
+ * Clean t19x_percpu_data[cpu] to DRAM. This needs to be done to ensure
+ * that the correct value is read in tegra_soc_pwr_domain_suspend(),
+ * which is called with caches disabled. It is possible to read a stale
+ * value from DRAM in that function, because the L2 cache is not flushed
+ * unless the cluster is entering CC6/CC7.
+ */
+ clean_dcache_range((uint64_t)&t19x_percpu_data[cpu],
+ sizeof(t19x_percpu_data[cpu]));
+
+ /* Sanity check the requested state id */
+ switch (state_id) {
+ case PSTATE_ID_CORE_IDLE:
+
+ if (psci_get_pstate_type(power_state) != PSTATE_TYPE_STANDBY) {
+ ret = PSCI_E_INVALID_PARAMS;
+ break;
+ }
+
+ /* Core idle request */
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = PSCI_LOCAL_STATE_RUN;
+ break;
+
+ default:
+ ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
+ ret = PSCI_E_INVALID_PARAMS;
+ break;
+ }
+
+ return ret;
+}
+
+int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
+{
+ uint32_t cpu = plat_my_core_pos();
+ mce_cstate_info_t cstate_info = { 0 };
+
+ /* Program default wake mask */
+ cstate_info.wake_mask = TEGRA194_CORE_WAKE_MASK;
+ cstate_info.update_wake_mask = 1;
+ mce_update_cstate_info(&cstate_info);
+
+ /* Enter CPU idle */
+ (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
+ (uint64_t)TEGRA_NVG_CORE_C6,
+ t19x_percpu_data[cpu].wake_time,
+ 0U);
+
+ return PSCI_E_SUCCESS;
+}
+
+int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ const plat_local_state_t *pwr_domain_state;
+ uint8_t stateid_afflvl2;
+ plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint64_t mc_ctx_base;
+ uint32_t val;
+ mce_cstate_info_t sc7_cstate_info = {
+ .cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6,
+ .ccplex = (uint32_t)TEGRA_NVG_CG_CG7,
+ .system = (uint32_t)TEGRA_NVG_SYSTEM_SC7,
+ .system_state_force = 1U,
+ .update_wake_mask = 1U,
+ };
+ int32_t ret = 0;
+
+ /* get the state ID */
+ pwr_domain_state = target_state->pwr_domain_state;
+ stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
+ TEGRA194_STATE_ID_MASK;
+
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+ /* save 'Secure Boot' Processor Feature Config Register */
+ val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
+
+ /* save MC context */
+ mc_ctx_base = params_from_bl2->tzdram_base +
+ tegra194_get_mc_ctx_offset();
+ tegra_mc_save_context((uintptr_t)mc_ctx_base);
+
+ /*
+ * Suspend SE, RNG1 and PKA1 only on silcon and fpga,
+ * since VDK does not support atomic se ctx save
+ */
+ if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) {
+ ret = tegra_se_suspend();
+ assert(ret == 0);
+ }
+
+ /* Prepare for system suspend */
+ mce_update_cstate_info(&sc7_cstate_info);
+
+ do {
+ val = (uint32_t)mce_command_handler(
+ (uint32_t)MCE_CMD_IS_SC7_ALLOWED,
+ (uint32_t)TEGRA_NVG_CORE_C7,
+ MCE_CORE_SLEEP_TIME_INFINITE,
+ 0U);
+ } while (val == 0U);
+
+ /* Instruct the MCE to enter system suspend state */
+ ret = mce_command_handler(
+ (uint64_t)MCE_CMD_ENTER_CSTATE,
+ (uint64_t)TEGRA_NVG_CORE_C7,
+ MCE_CORE_SLEEP_TIME_INFINITE,
+ 0U);
+ assert(ret == 0);
+
+ /* set system suspend state for house-keeping */
+ tegra194_set_system_suspend_entry();
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Helper function to check if this is the last ON CPU in the cluster
+ ******************************************************************************/
+static bool tegra_last_on_cpu_in_cluster(const plat_local_state_t *states,
+ uint32_t ncpu)
+{
+ plat_local_state_t target;
+ bool last_on_cpu = true;
+ uint32_t num_cpus = ncpu, pos = 0;
+
+ do {
+ target = states[pos];
+ if (target != PLAT_MAX_OFF_STATE) {
+ last_on_cpu = false;
+ }
+ --num_cpus;
+ pos++;
+ } while (num_cpus != 0U);
+
+ return last_on_cpu;
+}
+
+/*******************************************************************************
+ * Helper function to get target power state for the cluster
+ ******************************************************************************/
+static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states,
+ uint32_t ncpu)
+{
+ uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK;
+ plat_local_state_t target = states[core_pos];
+ mce_cstate_info_t cstate_info = { 0 };
+
+ /* CPU off */
+ if (target == PLAT_MAX_OFF_STATE) {
+
+ /* Enable cluster powerdn from last CPU in the cluster */
+ if (tegra_last_on_cpu_in_cluster(states, ncpu)) {
+
+ /* Enable CC6 state and turn off wake mask */
+ cstate_info.cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6;
+ cstate_info.ccplex = (uint32_t)TEGRA_NVG_CG_CG7;
+ cstate_info.system_state_force = 1;
+ cstate_info.update_wake_mask = 1U;
+ mce_update_cstate_info(&cstate_info);
+
+ } else {
+
+ /* Turn off wake_mask */
+ cstate_info.update_wake_mask = 1U;
+ mce_update_cstate_info(&cstate_info);
+ target = PSCI_LOCAL_STATE_RUN;
+ }
+ }
+
+ return target;
+}
+
+/*******************************************************************************
+ * Platform handler to calculate the proper target power level at the
+ * specified affinity level
+ ******************************************************************************/
+plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
+ const plat_local_state_t *states,
+ uint32_t ncpu)
+{
+ plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
+ uint32_t cpu = plat_my_core_pos();
+
+ /* System Suspend */
+ if ((lvl == (uint32_t)MPIDR_AFFLVL2) && (states[cpu] == PSTATE_ID_SOC_POWERDN)) {
+ target = PSTATE_ID_SOC_POWERDN;
+ }
+
+ /* CPU off, CPU suspend */
+ if (lvl == (uint32_t)MPIDR_AFFLVL1) {
+ target = tegra_get_afflvl1_pwr_state(states, ncpu);
+ }
+
+ /* target cluster/system state */
+ return target;
+}
+
+int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
+{
+ const plat_local_state_t *pwr_domain_state =
+ target_state->pwr_domain_state;
+ plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
+ TEGRA194_STATE_ID_MASK;
+ uint64_t src_len_in_bytes = (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE;
+ uint64_t val;
+ int32_t ret = PSCI_E_SUCCESS;
+
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+ val = params_from_bl2->tzdram_base +
+ tegra194_get_cpu_reset_handler_size();
+
+ /* initialise communication channel with BPMP */
+ ret = tegra_bpmp_ipc_init();
+ assert(ret == 0);
+
+ /* Enable SE clock before SE context save */
+ ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
+ assert(ret == 0);
+
+ /*
+ * It is very unlikely that the BL31 image would be
+ * bigger than 2^32 bytes
+ */
+ assert(src_len_in_bytes < UINT32_MAX);
+
+ if (tegra_se_calculate_save_sha256(BL31_BASE,
+ (uint32_t)src_len_in_bytes) != 0) {
+ ERROR("Hash calculation failed. Reboot\n");
+ (void)tegra_soc_prepare_system_reset();
+ }
+
+ /*
+ * The TZRAM loses power when we enter system suspend. To
+ * allow graceful exit from system suspend, we need to copy
+ * BL3-1 over to TZDRAM.
+ */
+ val = params_from_bl2->tzdram_base +
+ tegra194_get_cpu_reset_handler_size();
+ memcpy((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
+ src_len_in_bytes);
+
+ /* Disable SE clock after SE context save */
+ ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
+ assert(ret == 0);
+ }
+
+ return ret;
+}
+
+int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int32_t tegra_soc_pwr_domain_on(u_register_t mpidr)
+{
+ uint64_t target_cpu = mpidr & MPIDR_CPU_MASK;
+ uint64_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >>
+ MPIDR_AFFINITY_BITS;
+ int32_t ret = 0;
+
+ if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) {
+ ERROR("%s: unsupported CPU (0x%lx)\n", __func__ , mpidr);
+ return PSCI_E_NOT_PRESENT;
+ }
+
+ /* construct the target CPU # */
+ target_cpu += (target_cluster << 1U);
+
+ ret = mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U);
+ if (ret < 0) {
+ return PSCI_E_DENIED;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint8_t enable_ccplex_lock_step = params_from_bl2->enable_ccplex_lock_step;
+ uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
+ cpu_context_t *ctx = cm_get_context(NON_SECURE);
+ uint64_t actlr_elx;
+
+ /*
+ * Reset power state info for CPUs when onlining, we set
+ * deepest power when offlining a core but that may not be
+ * requested by non-secure sw which controls idle states. It
+ * will re-init this info from non-secure software when the
+ * core come online.
+ */
+ actlr_elx = read_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1));
+ actlr_elx &= ~DENVER_CPU_PMSTATE_MASK;
+ actlr_elx |= DENVER_CPU_PMSTATE_C1;
+ write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
+
+ /*
+ * Check if we are exiting from deep sleep and restore SE
+ * context if we are.
+ */
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+#if ENABLE_STRICT_CHECKING_MODE
+ /*
+ * Enable strict checking after programming the GSC for
+ * enabling TZSRAM and TZDRAM
+ */
+ mce_enable_strict_checking();
+#endif
+
+ /* Init SMMU */
+ tegra_smmu_init();
+
+ /* Resume SE, RNG1 and PKA1 */
+ tegra_se_resume();
+
+ /*
+ * Program XUSB STREAMIDs
+ * ======================
+ * T19x XUSB has support for XUSB virtualization. It will
+ * have one physical function (PF) and four Virtual functions
+ * (VF)
+ *
+ * There were below two SIDs for XUSB until T186.
+ * 1) #define TEGRA_SID_XUSB_HOST 0x1bU
+ * 2) #define TEGRA_SID_XUSB_DEV 0x1cU
+ *
+ * We have below four new SIDs added for VF(s)
+ * 3) #define TEGRA_SID_XUSB_VF0 0x5dU
+ * 4) #define TEGRA_SID_XUSB_VF1 0x5eU
+ * 5) #define TEGRA_SID_XUSB_VF2 0x5fU
+ * 6) #define TEGRA_SID_XUSB_VF3 0x60U
+ *
+ * When virtualization is enabled then we have to disable SID
+ * override and program above SIDs in below newly added SID
+ * registers in XUSB PADCTL MMIO space. These registers are
+ * TZ protected and so need to be done in ATF.
+ *
+ * a) #define XUSB_PADCTL_HOST_AXI_STREAMID_PF_0 (0x136cU)
+ * b) #define XUSB_PADCTL_DEV_AXI_STREAMID_PF_0 (0x139cU)
+ * c) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_0 (0x1370U)
+ * d) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_1 (0x1374U)
+ * e) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_2 (0x1378U)
+ * f) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_3 (0x137cU)
+ *
+ * This change disables SID override and programs XUSB SIDs
+ * in above registers to support both virtualization and
+ * non-virtualization platforms
+ */
+ if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) {
+
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_HOST);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_HOST);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_0, TEGRA_SID_XUSB_VF0);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_0) == TEGRA_SID_XUSB_VF0);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_1, TEGRA_SID_XUSB_VF1);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_1) == TEGRA_SID_XUSB_VF1);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_2, TEGRA_SID_XUSB_VF2);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_2) == TEGRA_SID_XUSB_VF2);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_3, TEGRA_SID_XUSB_VF3);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_3) == TEGRA_SID_XUSB_VF3);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_DEV_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_DEV);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_DEV_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_DEV);
+ }
+ }
+
+ /*
+ * Enable dual execution optimized translations for all ELx.
+ */
+ if (enable_ccplex_lock_step != 0U) {
+ actlr_elx = read_actlr_el3();
+ actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL3;
+ write_actlr_el3(actlr_elx);
+
+ actlr_elx = read_actlr_el2();
+ actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL2;
+ write_actlr_el2(actlr_elx);
+
+ actlr_elx = read_actlr_el1();
+ actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL1;
+ write_actlr_el1(actlr_elx);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+ int32_t ret = 0;
+
+ (void)target_state;
+
+ /* Disable Denver's DCO operations */
+ if (impl == DENVER_IMPL) {
+ denver_disable_dco();
+ }
+
+ /* Turn off CPU */
+ ret = mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
+ (uint64_t)TEGRA_NVG_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U);
+ assert(ret == 0);
+
+ return PSCI_E_SUCCESS;
+}
+
+__dead2 void tegra_soc_prepare_system_off(void)
+{
+ /* System power off */
+ mce_system_shutdown();
+
+ wfi();
+
+ /* wait for the system to power down */
+ for (;;) {
+ ;
+ }
+}
+
+int32_t tegra_soc_prepare_system_reset(void)
+{
+ /* System reboot */
+ mce_system_reboot();
+
+ return PSCI_E_SUCCESS;
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_ras.c b/plat/nvidia/tegra/soc/t194/plat_ras.c
new file mode 100644
index 0000000..02f6158
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_ras.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/cassert.h>
+#include <lib/extensions/ras.h>
+#include <lib/utils_def.h>
+#include <services/sdei.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <tegra194_ras_private.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/*
+ * ERR<n>FR bits[63:32], it indicates supported RAS errors which can be enabled
+ * by setting corresponding bits in ERR<n>CTLR
+ */
+#define ERR_FR_EN_BITS_MASK 0xFFFFFFFF00000000ULL
+
+/*
+ * Number of RAS errors will be cleared per 'tegra194_ras_corrected_err_clear'
+ * function call.
+ */
+#define RAS_ERRORS_PER_CALL 8
+
+/*
+ * the max possible RAS node index value.
+ */
+#define RAS_NODE_INDEX_MAX 0x1FFFFFFFU
+
+/* bakery lock for platform RAS handler. */
+static DEFINE_BAKERY_LOCK(ras_handler_lock);
+#define ras_lock() bakery_lock_get(&ras_handler_lock)
+#define ras_unlock() bakery_lock_release(&ras_handler_lock)
+
+/*
+ * Function to handle an External Abort received at EL3.
+ * This function is invoked by RAS framework.
+ */
+static void tegra194_ea_handler(unsigned int ea_reason, uint64_t syndrome,
+ void *cookie, void *handle, uint64_t flags)
+{
+ int32_t ret;
+
+ ras_lock();
+
+ ERROR("MPIDR 0x%lx: exception reason=%u syndrome=0x%" PRIx64 "\n",
+ read_mpidr(), ea_reason, syndrome);
+
+ /* Call RAS EA handler */
+ ret = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+ if (ret != 0) {
+ ERROR("RAS error handled!\n");
+ ret = sdei_dispatch_event(TEGRA_SDEI_EP_EVENT_0 +
+ plat_my_core_pos());
+ if (ret != 0)
+ ERROR("sdei_dispatch_event returned %d\n", ret);
+ } else {
+ ERROR("Not a RAS error!\n");
+ }
+
+ ras_unlock();
+}
+
+/*
+ * Function to enable all supported RAS error report.
+ *
+ * Uncorrected errors are set to report as External abort (SError)
+ * Corrected errors are set to report as interrupt.
+ */
+void tegra194_ras_enable(void)
+{
+ VERBOSE("%s\n", __func__);
+
+ /* skip RAS enablement if not a silicon platform. */
+ if (!tegra_platform_is_silicon()) {
+ return;
+ }
+
+ /*
+ * Iterate for each group(num_idx ERRSELRs starting from idx_start)
+ * use normal for loop instead of for_each_err_record_info to get rid
+ * of MISRA noise..
+ */
+ for (uint32_t i = 0U; i < err_record_mappings.num_err_records; i++) {
+
+ const struct err_record_info *info = &err_record_mappings.err_records[i];
+
+ uint32_t idx_start = info->sysreg.idx_start;
+ uint32_t num_idx = info->sysreg.num_idx;
+ const struct ras_aux_data *aux_data = (const struct ras_aux_data *)info->aux_data;
+
+ assert(aux_data != NULL);
+
+ for (uint32_t j = 0; j < num_idx; j++) {
+
+ /* ERR<n>CTLR register value. */
+ uint64_t err_ctrl = 0ULL;
+ /* all supported errors for this node. */
+ uint64_t err_fr;
+ /* uncorrectable errors */
+ uint64_t uncorr_errs;
+ /* correctable errors */
+ uint64_t corr_errs;
+
+ /*
+ * Catch error if something wrong with the RAS aux data
+ * record table.
+ */
+ assert(aux_data[j].err_ctrl != NULL);
+
+ /*
+ * Write to ERRSELR_EL1 to select the RAS error node.
+ * Always program this at first to select corresponding
+ * RAS node before any other RAS register r/w.
+ */
+ ser_sys_select_record(idx_start + j);
+
+ err_fr = read_erxfr_el1() & ERR_FR_EN_BITS_MASK;
+ uncorr_errs = aux_data[j].err_ctrl();
+ corr_errs = ~uncorr_errs & err_fr;
+
+ /* enable error reporting */
+ ERR_CTLR_ENABLE_FIELD(err_ctrl, ED);
+
+ /* enable SError reporting for uncorrectable errors */
+ if ((uncorr_errs & err_fr) != 0ULL) {
+ ERR_CTLR_ENABLE_FIELD(err_ctrl, UE);
+ }
+
+ /* generate interrupt for corrected errors. */
+ if (corr_errs != 0ULL) {
+ ERR_CTLR_ENABLE_FIELD(err_ctrl, CFI);
+ }
+
+ /* enable the supported errors */
+ err_ctrl |= err_fr;
+
+ VERBOSE("errselr_el1:0x%x, erxfr:0x%" PRIx64 ", err_ctrl:0x%" PRIx64 "\n",
+ idx_start + j, err_fr, err_ctrl);
+
+ /* enable specified errors, or set to 0 if no supported error */
+ write_erxctlr_el1(err_ctrl);
+ }
+ }
+}
+
+/*
+ * Function to clear RAS ERR<n>STATUS for corrected RAS error.
+ *
+ * This function clears number of 'RAS_ERRORS_PER_CALL' RAS errors at most.
+ * 'cookie' - in/out cookie parameter to specify/store last visited RAS
+ * error record index. it is set to '0' to indicate no more RAS
+ * error record to clear.
+ */
+void tegra194_ras_corrected_err_clear(uint64_t *cookie)
+{
+ /*
+ * 'last_node' and 'last_idx' represent last visited RAS node index from
+ * previous function call. they are set to 0 when first smc call is made
+ * or all RAS error are visited by followed multipile smc calls.
+ */
+ union prev_record {
+ struct record {
+ uint32_t last_node;
+ uint32_t last_idx;
+ } rec;
+ uint64_t value;
+ } prev;
+
+ uint64_t clear_ce_status = 0ULL;
+ int32_t nerrs_per_call = RAS_ERRORS_PER_CALL;
+ uint32_t i;
+
+ if (cookie == NULL) {
+ return;
+ }
+
+ prev.value = *cookie;
+
+ if ((prev.rec.last_node >= RAS_NODE_INDEX_MAX) ||
+ (prev.rec.last_idx >= RAS_NODE_INDEX_MAX)) {
+ return;
+ }
+
+ ERR_STATUS_SET_FIELD(clear_ce_status, AV, 0x1UL);
+ ERR_STATUS_SET_FIELD(clear_ce_status, V, 0x1UL);
+ ERR_STATUS_SET_FIELD(clear_ce_status, OF, 0x1UL);
+ ERR_STATUS_SET_FIELD(clear_ce_status, MV, 0x1UL);
+ ERR_STATUS_SET_FIELD(clear_ce_status, CE, 0x3UL);
+
+
+ for (i = prev.rec.last_node; i < err_record_mappings.num_err_records; i++) {
+
+ const struct err_record_info *info = &err_record_mappings.err_records[i];
+ uint32_t idx_start = info->sysreg.idx_start;
+ uint32_t num_idx = info->sysreg.num_idx;
+
+ uint32_t j;
+
+ j = (i == prev.rec.last_node && prev.value != 0UL) ?
+ (prev.rec.last_idx + 1U) : 0U;
+
+ for (; j < num_idx; j++) {
+
+ uint64_t status;
+ uint32_t err_idx = idx_start + j;
+
+ if (err_idx >= RAS_NODE_INDEX_MAX) {
+ return;
+ }
+
+ write_errselr_el1(err_idx);
+ status = read_erxstatus_el1();
+
+ if (ERR_STATUS_GET_FIELD(status, CE) != 0U) {
+ write_erxstatus_el1(clear_ce_status);
+ }
+
+ --nerrs_per_call;
+
+ /* only clear 'nerrs_per_call' errors each time. */
+ if (nerrs_per_call <= 0) {
+ prev.rec.last_idx = j;
+ prev.rec.last_node = i;
+ /* save last visited error record index
+ * into cookie.
+ */
+ *cookie = prev.value;
+
+ return;
+ }
+ }
+ }
+
+ /*
+ * finish if all ras error records are checked or provided index is out
+ * of range.
+ */
+ *cookie = 0ULL;
+ return;
+}
+
+/* Function to probe an error from error record group. */
+static int32_t tegra194_ras_record_probe(const struct err_record_info *info,
+ int *probe_data)
+{
+ /* Skip probing if not a silicon platform */
+ if (!tegra_platform_is_silicon()) {
+ return 0;
+ }
+
+ return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, probe_data);
+}
+
+/* Function to handle error from one given node */
+static int32_t tegra194_ras_node_handler(uint32_t errselr, const char *name,
+ const struct ras_error *errors, uint64_t status)
+{
+ bool found = false;
+ uint32_t ierr = (uint32_t)ERR_STATUS_GET_FIELD(status, IERR);
+ uint32_t serr = (uint32_t)ERR_STATUS_GET_FIELD(status, SERR);
+ uint64_t val = 0;
+
+ /* not a valid error. */
+ if (ERR_STATUS_GET_FIELD(status, V) == 0U) {
+ return 0;
+ }
+
+ ERR_STATUS_SET_FIELD(val, V, 1);
+
+ /* keep the log print same as linux arm64_ras driver. */
+ ERROR("**************************************\n");
+ ERROR("RAS Error in %s, ERRSELR_EL1=0x%x:\n", name, errselr);
+ ERROR("\tStatus = 0x%" PRIx64 "\n", status);
+
+ /* Print uncorrectable errror information. */
+ if (ERR_STATUS_GET_FIELD(status, UE) != 0U) {
+
+ ERR_STATUS_SET_FIELD(val, UE, 1);
+ ERR_STATUS_SET_FIELD(val, UET, 1);
+
+ /* IERR to error message */
+ for (uint32_t i = 0; errors[i].error_msg != NULL; i++) {
+ if (ierr == errors[i].error_code) {
+ ERROR("\tIERR = %s: 0x%x\n",
+ errors[i].error_msg, ierr);
+
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ ERROR("\tUnknown IERR: 0x%x\n", ierr);
+ }
+
+ ERROR("SERR = %s: 0x%x\n", ras_serr_to_str(serr), serr);
+
+ /* Overflow, multiple errors have been detected. */
+ if (ERR_STATUS_GET_FIELD(status, OF) != 0U) {
+ ERROR("\tOverflow (there may be more errors) - "
+ "Uncorrectable\n");
+ ERR_STATUS_SET_FIELD(val, OF, 1);
+ }
+
+ ERROR("\tUncorrectable (this is fatal)\n");
+
+ /* Miscellaneous Register Valid. */
+ if (ERR_STATUS_GET_FIELD(status, MV) != 0U) {
+ ERROR("\tMISC0 = 0x%lx\n", read_erxmisc0_el1());
+ ERROR("\tMISC1 = 0x%lx\n", read_erxmisc1_el1());
+ ERR_STATUS_SET_FIELD(val, MV, 1);
+ }
+
+ /* Address Valid. */
+ if (ERR_STATUS_GET_FIELD(status, AV) != 0U) {
+ ERROR("\tADDR = 0x%lx\n", read_erxaddr_el1());
+ ERR_STATUS_SET_FIELD(val, AV, 1);
+ }
+
+ /* Deferred error */
+ if (ERR_STATUS_GET_FIELD(status, DE) != 0U) {
+ ERROR("\tDeferred error\n");
+ ERR_STATUS_SET_FIELD(val, DE, 1);
+ }
+
+ } else {
+ /* For corrected error, simply clear it. */
+ VERBOSE("corrected RAS error is cleared: ERRSELR_EL1:0x%x, "
+ "IERR:0x%x, SERR:0x%x\n", errselr, ierr, serr);
+ ERR_STATUS_SET_FIELD(val, CE, 1);
+ }
+
+ ERROR("**************************************\n");
+
+ /* Write to clear reported errors. */
+ write_erxstatus_el1(val);
+
+ /* error handled */
+ return 0;
+}
+
+/* Function to handle one error node from an error record group. */
+static int32_t tegra194_ras_record_handler(const struct err_record_info *info,
+ int probe_data, const struct err_handler_data *const data __unused)
+{
+ uint32_t num_idx = info->sysreg.num_idx;
+ uint32_t idx_start = info->sysreg.idx_start;
+ const struct ras_aux_data *aux_data = info->aux_data;
+ const struct ras_error *errors;
+ uint32_t offset;
+ const char *node_name;
+
+ uint64_t status = 0ULL;
+
+ VERBOSE("%s\n", __func__);
+
+ assert(probe_data >= 0);
+ assert((uint32_t)probe_data < num_idx);
+
+ offset = (uint32_t)probe_data;
+ errors = aux_data[offset].error_records;
+ node_name = aux_data[offset].name;
+
+ assert(errors != NULL);
+
+ /* Write to ERRSELR_EL1 to select the error record */
+ ser_sys_select_record(idx_start + offset);
+
+ /* Retrieve status register from the error record */
+ status = read_erxstatus_el1();
+
+ return tegra194_ras_node_handler(idx_start + offset, node_name,
+ errors, status);
+}
+
+
+/* Instantiate RAS nodes */
+PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+
+/* Instantiate RAS node groups */
+static struct ras_aux_data per_core_ras_group[] = {
+ PER_CORE_RAS_GROUP_NODES
+};
+CASSERT(ARRAY_SIZE(per_core_ras_group) < RAS_NODE_INDEX_MAX,
+ assert_max_per_core_ras_group_size);
+
+static struct ras_aux_data per_cluster_ras_group[] = {
+ PER_CLUSTER_RAS_GROUP_NODES
+};
+CASSERT(ARRAY_SIZE(per_cluster_ras_group) < RAS_NODE_INDEX_MAX,
+ assert_max_per_cluster_ras_group_size);
+
+static struct ras_aux_data scf_l3_ras_group[] = {
+ SCF_L3_BANK_RAS_GROUP_NODES
+};
+CASSERT(ARRAY_SIZE(scf_l3_ras_group) < RAS_NODE_INDEX_MAX,
+ assert_max_scf_l3_ras_group_size);
+
+static struct ras_aux_data ccplex_ras_group[] = {
+ CCPLEX_RAS_GROUP_NODES
+};
+CASSERT(ARRAY_SIZE(ccplex_ras_group) < RAS_NODE_INDEX_MAX,
+ assert_max_ccplex_ras_group_size);
+
+/*
+ * We have same probe and handler for each error record group, use a macro to
+ * simply the record definition.
+ */
+#define ADD_ONE_ERR_GROUP(errselr_start, group) \
+ ERR_RECORD_SYSREG_V1((errselr_start), (uint32_t)ARRAY_SIZE((group)), \
+ &tegra194_ras_record_probe, \
+ &tegra194_ras_record_handler, (group))
+
+/* RAS error record group information */
+static struct err_record_info carmel_ras_records[] = {
+ /*
+ * Per core ras error records
+ * ERRSELR starts from 0*256 + Logical_CPU_ID*16 + 0 to
+ * 0*256 + Logical_CPU_ID*16 + 5 for each group.
+ * 8 cores/groups, 6 * 8 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x000, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x010, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x020, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x030, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x040, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x050, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x060, per_core_ras_group),
+ ADD_ONE_ERR_GROUP(0x070, per_core_ras_group),
+
+ /*
+ * Per cluster ras error records
+ * ERRSELR starts from 2*256 + Logical_Cluster_ID*16 + 0 to
+ * 2*256 + Logical_Cluster_ID*16 + 3.
+ * 4 clusters/groups, 3 * 4 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x200, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x210, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x220, per_cluster_ras_group),
+ ADD_ONE_ERR_GROUP(0x230, per_cluster_ras_group),
+
+ /*
+ * SCF L3_Bank ras error records
+ * ERRSELR: 3*256 + L3_Bank_ID, L3_Bank_ID: 0-3
+ * 1 groups, 4 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x300, scf_l3_ras_group),
+
+ /*
+ * CCPLEX ras error records
+ * ERRSELR: 4*256 + Unit_ID, Unit_ID: 0 - 4
+ * 1 groups, 5 nodes in total.
+ */
+ ADD_ONE_ERR_GROUP(0x400, ccplex_ras_group),
+};
+
+CASSERT(ARRAY_SIZE(carmel_ras_records) < RAS_NODE_INDEX_MAX,
+ assert_max_carmel_ras_records_size);
+
+REGISTER_ERR_RECORD_INFO(carmel_ras_records);
+
+/* dummy RAS interrupt */
+static struct ras_interrupt carmel_ras_interrupts[] = {};
+REGISTER_RAS_INTERRUPTS(carmel_ras_interrupts);
+
+/*******************************************************************************
+ * RAS handler for the platform
+ ******************************************************************************/
+void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags)
+{
+#if RAS_EXTENSION
+ tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+#else
+ plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+#endif
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_secondary.c b/plat/nvidia/tegra/soc/t194/plat_secondary.c
new file mode 100644
index 0000000..1cb14ad
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_secondary.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <mce.h>
+#include <tegra194_private.h>
+#include <tegra_def.h>
+#include <tegra_private.h>
+
+extern uint64_t tegra_bl31_phys_base;
+
+#define MISCREG_AA64_RST_LOW 0x2004U
+#define MISCREG_AA64_RST_HIGH 0x2008U
+
+#define CPU_RESET_MODE_AA64 1U
+
+/*******************************************************************************
+ * Setup secondary CPU vectors
+ ******************************************************************************/
+void plat_secondary_setup(void)
+{
+ uint32_t addr_low, addr_high;
+ plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint64_t cpu_reset_handler_base, cpu_reset_handler_size, tzdram_addr;
+ uint64_t src_len_bytes = BL_END - tegra_bl31_phys_base;
+
+ INFO("Setting up secondary CPU boot\n");
+
+ tzdram_addr = params_from_bl2->tzdram_base +
+ tegra194_get_cpu_reset_handler_size();
+
+ /*
+ * The BL31 code resides in the TZSRAM which loses state
+ * when we enter System Suspend. Copy the wakeup trampoline
+ * code to TZDRAM to help us exit from System Suspend.
+ */
+ cpu_reset_handler_base = tegra194_get_cpu_reset_handler_base();
+ cpu_reset_handler_size = tegra194_get_cpu_reset_handler_size();
+ memcpy((void *)((uintptr_t)params_from_bl2->tzdram_base),
+ (void *)((uintptr_t)cpu_reset_handler_base),
+ cpu_reset_handler_size);
+
+ /* TZDRAM base will be used as the "resume" address */
+ addr_low = (uint32_t)params_from_bl2->tzdram_base | CPU_RESET_MODE_AA64;
+ addr_high = (uint32_t)((params_from_bl2->tzdram_base >> 32U) & 0x7ffU);
+
+ /* write lower 32 bits first, then the upper 11 bits */
+ mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_LOW, addr_low);
+ assert(mmio_read_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_LOW) == addr_low);
+ mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_HIGH, addr_high);
+ assert(mmio_read_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_HIGH) == addr_high);
+
+ /* save reset vector to be used during SYSTEM_SUSPEND exit */
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO,
+ addr_low);
+ assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO) == addr_low);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI,
+ addr_high);
+ assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI) == addr_high);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO,
+ (uint32_t)tzdram_addr);
+ assert(mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO) == (uint32_t)tzdram_addr);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI,
+ (uint32_t)src_len_bytes);
+ assert(mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI) == (uint32_t)src_len_bytes);
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
new file mode 100644
index 0000000..8f7d1e9
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/console.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <cortex_a57.h>
+#include <common/debug.h>
+#include <denver.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <bl31/interrupt_mgmt.h>
+#include <mce.h>
+#include <mce_private.h>
+#include <memctrl.h>
+#include <plat/common/platform.h>
+#include <smmu.h>
+#include <spe.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+/* ID for spe-console */
+#define TEGRA_CONSOLE_SPE_ID 0xFE
+
+/*******************************************************************************
+ * Structure to store the SCR addresses and its expected settings.
+ *******************************************************************************
+ */
+typedef struct {
+ uint32_t scr_addr;
+ uint32_t scr_val;
+} scr_settings_t;
+
+static const scr_settings_t t194_scr_settings[] = {
+ { SCRATCH_RSV68_SCR, SCRATCH_RSV68_SCR_VAL },
+ { SCRATCH_RSV71_SCR, SCRATCH_RSV71_SCR_VAL },
+ { SCRATCH_RSV72_SCR, SCRATCH_RSV72_SCR_VAL },
+ { SCRATCH_RSV75_SCR, SCRATCH_RSV75_SCR_VAL },
+ { SCRATCH_RSV81_SCR, SCRATCH_RSV81_SCR_VAL },
+ { SCRATCH_RSV97_SCR, SCRATCH_RSV97_SCR_VAL },
+ { SCRATCH_RSV99_SCR, SCRATCH_RSV99_SCR_VAL },
+ { SCRATCH_RSV109_SCR, SCRATCH_RSV109_SCR_VAL },
+ { MISCREG_SCR_SCRTZWELCK, MISCREG_SCR_SCRTZWELCK_VAL }
+};
+
+/*******************************************************************************
+ * The Tegra power domain tree has a single system level power domain i.e. a
+ * single root node. The first entry in the power domain descriptor specifies
+ * the number of power domains at the highest power level.
+ *******************************************************************************
+ */
+static const uint8_t tegra_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ 1,
+ /* No of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of CPU cores - cluster0 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+ /* No of CPU cores - cluster1 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+ /* No of CPU cores - cluster2 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+ /* No of CPU cores - cluster3 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the Tegra default topology tree information.
+ ******************************************************************************/
+const uint8_t *plat_get_power_domain_tree_desc(void)
+{
+ return tegra_power_domain_tree_desc;
+}
+
+/*
+ * Table of regions to map using the MMU.
+ */
+static const mmap_region_t tegra_mmap[] = {
+ MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x4000U, /* 16KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_GPCDMA_BASE, 0x10000U, /* 64KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x8000U, /* 32KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_MC_BASE, 0x8000U, /* 32KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#if !ENABLE_CONSOLE_SPE
+ MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000U, /* 128KB - UART A, B*/
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000U, /* 192KB - UART D, E, F */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#endif
+ MAP_REGION_FLAT(TEGRA_XUSB_PADCTL_BASE, 0x2000U, /* 8KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x1000, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_GICC_BASE, 0x1000, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x1000U, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x1000U, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x1000U, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x1000U, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#if ENABLE_CONSOLE_SPE
+ MAP_REGION_FLAT(TEGRA_CONSOLE_SPE_BASE, 0x1000U, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+#endif
+ MAP_REGION_FLAT(TEGRA_TMRUS_BASE, TEGRA_TMRUS_SIZE, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x1000U, /* 4KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SMMU2_BASE, 0x800000U, /* 8MB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SMMU1_BASE, 0x800000U, /* 8MB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x800000U, /* 8MB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_BPMP_IPC_TX_PHYS_BASE, 0x10000U, /* 64KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE),
+ {0}
+};
+
+/*******************************************************************************
+ * Set up the pagetables as per the platform memory map & initialize the MMU
+ ******************************************************************************/
+const mmap_region_t *plat_get_mmio_map(void)
+{
+ /* MMIO space */
+ return tegra_mmap;
+}
+
+/*******************************************************************************
+ * Handler to get the System Counter Frequency
+ ******************************************************************************/
+uint32_t plat_get_syscnt_freq2(void)
+{
+ return 31250000;
+}
+
+#if !ENABLE_CONSOLE_SPE
+/*******************************************************************************
+ * Maximum supported UART controllers
+ ******************************************************************************/
+#define TEGRA194_MAX_UART_PORTS 7
+
+/*******************************************************************************
+ * This variable holds the UART port base addresses
+ ******************************************************************************/
+static uint32_t tegra194_uart_addresses[TEGRA194_MAX_UART_PORTS + 1] = {
+ 0, /* undefined - treated as an error case */
+ TEGRA_UARTA_BASE,
+ TEGRA_UARTB_BASE,
+ TEGRA_UARTC_BASE,
+ TEGRA_UARTD_BASE,
+ TEGRA_UARTE_BASE,
+ TEGRA_UARTF_BASE,
+ TEGRA_UARTG_BASE
+};
+#endif
+
+/*******************************************************************************
+ * Enable console corresponding to the console ID
+ ******************************************************************************/
+void plat_enable_console(int32_t id)
+{
+ uint32_t console_clock = 0U;
+
+#if ENABLE_CONSOLE_SPE
+ static console_t spe_console;
+
+ if (id == TEGRA_CONSOLE_SPE_ID) {
+ (void)console_spe_register(TEGRA_CONSOLE_SPE_BASE,
+ console_clock,
+ TEGRA_CONSOLE_BAUDRATE,
+ &spe_console);
+ console_set_scope(&spe_console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+ }
+#else
+ static console_t uart_console;
+
+ if ((id > 0) && (id < TEGRA194_MAX_UART_PORTS)) {
+ /*
+ * Reference clock used by the FPGAs is a lot slower.
+ */
+ if (tegra_platform_is_fpga()) {
+ console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
+ } else {
+ console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
+ }
+
+ (void)console_16550_register(tegra194_uart_addresses[id],
+ console_clock,
+ TEGRA_CONSOLE_BAUDRATE,
+ &uart_console);
+ console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+ }
+#endif
+}
+
+/*******************************************************************************
+ * Verify SCR settings
+ ******************************************************************************/
+static inline bool tegra194_is_scr_valid(void)
+{
+ uint32_t scr_val;
+ bool ret = true;
+
+ for (uint8_t i = 0U; i < ARRAY_SIZE(t194_scr_settings); i++) {
+ scr_val = mmio_read_32((uintptr_t)t194_scr_settings[i].scr_addr);
+ if (scr_val != t194_scr_settings[i].scr_val) {
+ ERROR("Mismatch at SCR addr = 0x%x\n", t194_scr_settings[i].scr_addr);
+ ret = false;
+ }
+ }
+ return ret;
+}
+
+/*******************************************************************************
+ * Handler for early platform setup
+ ******************************************************************************/
+void plat_early_platform_setup(void)
+{
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ uint8_t enable_ccplex_lock_step = params_from_bl2->enable_ccplex_lock_step;
+ uint64_t actlr_elx;
+
+ /* Verify chip id is t194 */
+ assert(tegra_chipid_is_t194());
+
+ /* Verify SCR settings */
+ if (tegra_platform_is_silicon()) {
+ assert(tegra194_is_scr_valid());
+ }
+
+ /* sanity check MCE firmware compatibility */
+ mce_verify_firmware_version();
+
+#if RAS_EXTENSION
+ /* Enable Uncorrectable RAS error */
+ tegra194_ras_enable();
+#endif
+
+ /*
+ * Program XUSB STREAMIDs
+ * ======================
+ * T19x XUSB has support for XUSB virtualization. It will have one
+ * physical function (PF) and four Virtual function (VF)
+ *
+ * There were below two SIDs for XUSB until T186.
+ * 1) #define TEGRA_SID_XUSB_HOST 0x1bU
+ * 2) #define TEGRA_SID_XUSB_DEV 0x1cU
+ *
+ * We have below four new SIDs added for VF(s)
+ * 3) #define TEGRA_SID_XUSB_VF0 0x5dU
+ * 4) #define TEGRA_SID_XUSB_VF1 0x5eU
+ * 5) #define TEGRA_SID_XUSB_VF2 0x5fU
+ * 6) #define TEGRA_SID_XUSB_VF3 0x60U
+ *
+ * When virtualization is enabled then we have to disable SID override
+ * and program above SIDs in below newly added SID registers in XUSB
+ * PADCTL MMIO space. These registers are TZ protected and so need to
+ * be done in ATF.
+ * a) #define XUSB_PADCTL_HOST_AXI_STREAMID_PF_0 (0x136cU)
+ * b) #define XUSB_PADCTL_DEV_AXI_STREAMID_PF_0 (0x139cU)
+ * c) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_0 (0x1370U)
+ * d) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_1 (0x1374U)
+ * e) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_2 (0x1378U)
+ * f) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_3 (0x137cU)
+ *
+ * This change disables SID override and programs XUSB SIDs in
+ * above registers to support both virtualization and
+ * non-virtualization platforms
+ */
+ if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) {
+
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_HOST);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_HOST);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_0, TEGRA_SID_XUSB_VF0);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_0) == TEGRA_SID_XUSB_VF0);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_1, TEGRA_SID_XUSB_VF1);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_1) == TEGRA_SID_XUSB_VF1);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_2, TEGRA_SID_XUSB_VF2);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_2) == TEGRA_SID_XUSB_VF2);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_3, TEGRA_SID_XUSB_VF3);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_HOST_AXI_STREAMID_VF_3) == TEGRA_SID_XUSB_VF3);
+ mmio_write_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_DEV_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_DEV);
+ assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE +
+ XUSB_PADCTL_DEV_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_DEV);
+ }
+
+ /*
+ * Enable dual execution optimized translations for all ELx.
+ */
+ if (enable_ccplex_lock_step != 0U) {
+ actlr_elx = read_actlr_el3();
+ actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL3;
+ write_actlr_el3(actlr_elx);
+ /* check if the bit is actually set */
+ assert((read_actlr_el3() & DENVER_CPU_ENABLE_DUAL_EXEC_EL3) != 0ULL);
+
+ actlr_elx = read_actlr_el2();
+ actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL2;
+ write_actlr_el2(actlr_elx);
+ /* check if the bit is actually set */
+ assert((read_actlr_el2() & DENVER_CPU_ENABLE_DUAL_EXEC_EL2) != 0ULL);
+
+ actlr_elx = read_actlr_el1();
+ actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL1;
+ write_actlr_el1(actlr_elx);
+ /* check if the bit is actually set */
+ assert((read_actlr_el1() & DENVER_CPU_ENABLE_DUAL_EXEC_EL1) != 0ULL);
+ }
+}
+
+/* Secure IRQs for Tegra194 */
+static const interrupt_prop_t tegra194_interrupt_props[] = {
+ INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(TEGRA194_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE)
+};
+
+/*******************************************************************************
+ * Initialize the GIC and SGIs
+ ******************************************************************************/
+void plat_gic_setup(void)
+{
+ tegra_gic_setup(tegra194_interrupt_props, ARRAY_SIZE(tegra194_interrupt_props));
+ tegra_gic_init();
+
+ /*
+ * Initialize the FIQ handler
+ */
+ tegra_fiq_handler_setup();
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 params from previous bootloader
+ ******************************************************************************/
+struct tegra_bl31_params *plat_get_bl31_params(void)
+{
+ uint64_t val;
+
+ val = (mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_HI_ADDR) &
+ SCRATCH_BL31_PARAMS_HI_ADDR_MASK) >> SCRATCH_BL31_PARAMS_HI_ADDR_SHIFT;
+ val <<= 32;
+ val |= mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_LO_ADDR);
+
+ return (struct tegra_bl31_params *)(uintptr_t)val;
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 platform params from previous bootloader
+ ******************************************************************************/
+plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
+{
+ uint64_t val;
+
+ val = (mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_HI_ADDR) &
+ SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK) >> SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT;
+ val <<= 32;
+ val |= mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_LO_ADDR);
+
+ return (plat_params_from_bl2_t *)(uintptr_t)val;
+}
+
+/*******************************************************************************
+ * Handler for late platform setup
+ ******************************************************************************/
+void plat_late_platform_setup(void)
+{
+#if ENABLE_STRICT_CHECKING_MODE
+ /*
+ * Enable strict checking after programming the GSC for
+ * enabling TZSRAM and TZDRAM
+ */
+ mce_enable_strict_checking();
+ mce_verify_strict_checking();
+#endif
+}
+
+/*******************************************************************************
+ * Handler to indicate support for System Suspend
+ ******************************************************************************/
+bool plat_supports_system_suspend(void)
+{
+ return true;
+}
+
+/*******************************************************************************
+ * Platform specific runtime setup.
+ ******************************************************************************/
+void plat_runtime_setup(void)
+{
+ /*
+ * During cold boot, it is observed that the arbitration
+ * bit is set in the Memory controller leading to false
+ * error interrupts in the non-secure world. To avoid
+ * this, clean the interrupt status register before
+ * booting into the non-secure world
+ */
+ tegra_memctrl_clear_pending_interrupts();
+
+ /*
+ * During boot, USB3 and flash media (SDMMC/SATA) devices need
+ * access to IRAM. Because these clients connect to the MC and
+ * do not have a direct path to the IRAM, the MC implements AHB
+ * redirection during boot to allow path to IRAM. In this mode
+ * accesses to a programmed memory address aperture are directed
+ * to the AHB bus, allowing access to the IRAM. This mode must be
+ * disabled before we jump to the non-secure world.
+ */
+ tegra_memctrl_disable_ahb_redirection();
+
+ /*
+ * Verify the integrity of the previously configured SMMU(s) settings
+ */
+ tegra_smmu_verify();
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
new file mode 100644
index 0000000..1eef559
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <common/debug.h>
+#include <errno.h>
+#include <mce.h>
+#include <mce_private.h>
+#include <memctrl.h>
+#include <common/runtime_svc.h>
+#include <tegra_private.h>
+#include <tegra_platform.h>
+#include <smmu.h>
+#include <stdbool.h>
+
+/*******************************************************************************
+ * Tegra194 SiP SMCs
+ ******************************************************************************/
+#define TEGRA_SIP_GET_SMMU_PER 0xC200FF00U
+#define TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS 0xC200FF01U
+
+/*******************************************************************************
+ * This function is responsible for handling all T194 SiP calls
+ ******************************************************************************/
+int32_t plat_sip_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ const void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ int32_t ret = 0;
+ uint32_t i, smmu_per[6] = {0};
+ uint32_t num_smmu_devices = plat_get_num_smmu_devices();
+ uint64_t per[3] = {0ULL};
+
+ (void)x1;
+ (void)x4;
+ (void)cookie;
+ (void)flags;
+
+ switch (smc_fid) {
+ case TEGRA_SIP_GET_SMMU_PER:
+
+ /* make sure we dont go past the array length */
+ assert(num_smmu_devices <= ARRAY_SIZE(smmu_per));
+
+ /* read all supported SMMU_PER records */
+ for (i = 0U; i < num_smmu_devices; i++) {
+ smmu_per[i] = tegra_smmu_read_32(i, SMMU_GSR0_PER);
+ }
+
+ /* pack results into 3 64bit variables. */
+ per[0] = smmu_per[0] | ((uint64_t)smmu_per[1] << 32U);
+ per[1] = smmu_per[2] | ((uint64_t)smmu_per[3] << 32U);
+ per[2] = smmu_per[4] | ((uint64_t)smmu_per[5] << 32U);
+
+ /* provide the results via X1-X3 CPU registers */
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, per[0]);
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X2, per[1]);
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X3, per[2]);
+
+ break;
+
+#if RAS_EXTENSION
+ case TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS:
+ {
+ /*
+ * clear all RAS error records for corrected errors at first.
+ * x1 shall be 0 for first SMC call after FHI is asserted.
+ * */
+ uint64_t local_x1 = x1;
+
+ tegra194_ras_corrected_err_clear(&local_x1);
+ if (local_x1 == 0ULL) {
+ /* clear HSM corrected error status after all corrected
+ * RAS errors are cleared.
+ */
+ mce_clear_hsm_corr_status();
+ }
+
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, local_x1);
+
+ break;
+ }
+#endif
+
+ default:
+ ret = -ENOTSUP;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_smmu.c b/plat/nvidia/tegra/soc/t194/plat_smmu.c
new file mode 100644
index 0000000..310e951
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_smmu.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <smmu.h>
+#include <tegra_def.h>
+
+#define BOARD_SYSTEM_FPGA_BASE U(1)
+#define BASE_CONFIG_SMMU_DEVICES U(2)
+#define MAX_NUM_SMMU_DEVICES U(3)
+
+static uint32_t tegra_misc_read_32(uint32_t off)
+{
+ return mmio_read_32((uintptr_t)TEGRA_MISC_BASE + off);
+}
+
+/*******************************************************************************
+ * Handler to return the support SMMU devices number
+ ******************************************************************************/
+uint32_t plat_get_num_smmu_devices(void)
+{
+ uint32_t ret_num = MAX_NUM_SMMU_DEVICES;
+ uint32_t board_revid = ((tegra_misc_read_32(MISCREG_EMU_REVID) >> \
+ BOARD_SHIFT_BITS) & BOARD_MASK_BITS);
+
+ if (board_revid == BOARD_SYSTEM_FPGA_BASE) {
+ ret_num = BASE_CONFIG_SMMU_DEVICES;
+ }
+
+ return ret_num;
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_trampoline.S b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
new file mode 100644
index 0000000..0ff5407
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_trampoline.S
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <plat/common/common_def.h>
+#include <memctrl_v2.h>
+#include <tegra_def.h>
+
+#define TEGRA194_STATE_SYSTEM_SUSPEND 0x5C7
+#define TEGRA194_STATE_SYSTEM_RESUME 0x600D
+#define TEGRA194_MC_CTX_SIZE 0xFB
+
+ .align 4
+ .globl tegra194_cpu_reset_handler
+
+/* CPU reset handler routine */
+func tegra194_cpu_reset_handler
+ /* check if we are exiting system suspend state */
+ adr x0, __tegra194_system_suspend_state
+ ldr x1, [x0]
+ mov x2, #TEGRA194_STATE_SYSTEM_SUSPEND
+ lsl x2, x2, #16
+ add x2, x2, #TEGRA194_STATE_SYSTEM_SUSPEND
+ cmp x1, x2
+ bne boot_cpu
+
+ /* set system resume state */
+ mov x1, #TEGRA194_STATE_SYSTEM_RESUME
+ lsl x1, x1, #16
+ mov x2, #TEGRA194_STATE_SYSTEM_RESUME
+ add x1, x1, x2
+ str x1, [x0]
+ dsb sy
+
+ /* prepare to relocate to TZSRAM */
+ mov x0, #BL31_BASE
+ adr x1, __tegra194_cpu_reset_handler_end
+ adr x2, __tegra194_cpu_reset_handler_data
+ ldr x2, [x2, #8]
+
+ /* memcpy16 */
+m_loop16:
+ cmp x2, #16
+ b.lt m_loop1
+ ldp x3, x4, [x1], #16
+ stp x3, x4, [x0], #16
+ sub x2, x2, #16
+ b m_loop16
+ /* copy byte per byte */
+m_loop1:
+ cbz x2, boot_cpu
+ ldrb w3, [x1], #1
+ strb w3, [x0], #1
+ subs x2, x2, #1
+ b.ne m_loop1
+
+ /*
+ * Synchronization barriers to make sure that memory is flushed out
+ * before we start execution in SysRAM.
+ */
+ dsb sy
+ isb
+
+boot_cpu:
+ adr x0, __tegra194_cpu_reset_handler_data
+ ldr x0, [x0]
+ br x0
+endfunc tegra194_cpu_reset_handler
+
+ /*
+ * Tegra194 reset data (offset 0x0 - 0x2490)
+ *
+ * 0x0000: secure world's entrypoint
+ * 0x0008: BL31 size (RO + RW)
+ * 0x0010: MC context start
+ * 0x2490: MC context end
+ */
+
+ .align 4
+ .type __tegra194_cpu_reset_handler_data, %object
+ .globl __tegra194_cpu_reset_handler_data
+__tegra194_cpu_reset_handler_data:
+ .quad tegra_secure_entrypoint
+ .quad __BL31_END__ - BL31_BASE
+ .globl __tegra194_system_suspend_state
+__tegra194_system_suspend_state:
+ .quad 0
+
+ .align 4
+__tegra194_mc_context:
+ .rept TEGRA194_MC_CTX_SIZE
+ .quad 0
+ .endr
+ .size __tegra194_cpu_reset_handler_data, \
+ . - __tegra194_cpu_reset_handler_data
+
+ .align 4
+ .globl __tegra194_cpu_reset_handler_end
+__tegra194_cpu_reset_handler_end:
+
+ .globl tegra194_get_cpu_reset_handler_size
+ .globl tegra194_get_cpu_reset_handler_base
+ .globl tegra194_get_mc_ctx_offset
+ .globl tegra194_set_system_suspend_entry
+
+/* return size of the CPU reset handler */
+func tegra194_get_cpu_reset_handler_size
+ adr x0, __tegra194_cpu_reset_handler_end
+ adr x1, tegra194_cpu_reset_handler
+ sub x0, x0, x1
+ ret
+endfunc tegra194_get_cpu_reset_handler_size
+
+/* return the start address of the CPU reset handler */
+func tegra194_get_cpu_reset_handler_base
+ adr x0, tegra194_cpu_reset_handler
+ ret
+endfunc tegra194_get_cpu_reset_handler_base
+
+/* return the size of the MC context */
+func tegra194_get_mc_ctx_offset
+ adr x0, __tegra194_mc_context
+ adr x1, tegra194_cpu_reset_handler
+ sub x0, x0, x1
+ ret
+endfunc tegra194_get_mc_ctx_offset
+
+/* set system suspend state before SC7 entry */
+func tegra194_set_system_suspend_entry
+ mov x0, #TEGRA_MC_BASE
+ mov x3, #MC_SECURITY_CFG3_0
+ ldr w1, [x0, x3]
+ lsl x1, x1, #32
+ mov x3, #MC_SECURITY_CFG0_0
+ ldr w2, [x0, x3]
+ orr x3, x1, x2 /* TZDRAM base */
+ adr x0, __tegra194_system_suspend_state
+ adr x1, tegra194_cpu_reset_handler
+ sub x2, x0, x1 /* offset in TZDRAM */
+ mov x0, #TEGRA194_STATE_SYSTEM_SUSPEND
+ lsl x0, x0, #16
+ add x0, x0, #TEGRA194_STATE_SYSTEM_SUSPEND
+ str x0, [x3, x2] /* set value in TZDRAM */
+ dsb sy
+ ret
+endfunc tegra194_set_system_suspend_entry
diff --git a/plat/nvidia/tegra/soc/t194/platform_t194.mk b/plat/nvidia/tegra/soc/t194/platform_t194.mk
new file mode 100644
index 0000000..631c926
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/platform_t194.mk
@@ -0,0 +1,85 @@
+#
+# Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+# platform configs
+ENABLE_CONSOLE_SPE := 1
+$(eval $(call add_define,ENABLE_CONSOLE_SPE))
+
+ENABLE_STRICT_CHECKING_MODE := 1
+$(eval $(call add_define,ENABLE_STRICT_CHECKING_MODE))
+
+USE_GPC_DMA := 1
+$(eval $(call add_define,USE_GPC_DMA))
+
+RESET_TO_BL31 := 1
+
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+# platform settings
+TZDRAM_BASE := 0x40000000
+$(eval $(call add_define,TZDRAM_BASE))
+
+MAX_XLAT_TABLES := 25
+$(eval $(call add_define,MAX_XLAT_TABLES))
+
+MAX_MMAP_REGIONS := 30
+$(eval $(call add_define,MAX_MMAP_REGIONS))
+
+# enable RAS handling
+HANDLE_EA_EL3_FIRST_NS := 1
+RAS_EXTENSION := 1
+
+# platform files
+PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t194 \
+ -I${SOC_DIR}/drivers/include
+
+BL31_SOURCES += ${TEGRA_GICv2_SOURCES} \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/denver.S \
+ ${TEGRA_DRIVERS}/bpmp_ipc/intf.c \
+ ${TEGRA_DRIVERS}/bpmp_ipc/ivc.c \
+ ${TEGRA_DRIVERS}/memctrl/memctrl_v2.c \
+ ${TEGRA_DRIVERS}/smmu/smmu.c \
+ ${SOC_DIR}/drivers/mce/mce.c \
+ ${SOC_DIR}/drivers/mce/nvg.c \
+ ${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \
+ ${SOC_DIR}/drivers/se/se.c \
+ ${SOC_DIR}/plat_memctrl.c \
+ ${SOC_DIR}/plat_psci_handlers.c \
+ ${SOC_DIR}/plat_setup.c \
+ ${SOC_DIR}/plat_secondary.c \
+ ${SOC_DIR}/plat_sip_calls.c \
+ ${SOC_DIR}/plat_smmu.c \
+ ${SOC_DIR}/plat_trampoline.S
+
+ifeq (${USE_GPC_DMA}, 1)
+BL31_SOURCES += ${TEGRA_DRIVERS}/gpcdma/gpcdma.c
+endif
+
+ifeq (${ENABLE_CONSOLE_SPE},1)
+BL31_SOURCES += ${TEGRA_DRIVERS}/spe/shared_console.S
+endif
+
+# RAS sources
+ifeq (${RAS_EXTENSION},1)
+BL31_SOURCES += lib/extensions/ras/std_err_record.c \
+ lib/extensions/ras/ras_common.c \
+ ${SOC_DIR}/plat_ras.c
+endif
+
+# SPM dispatcher
+ifeq (${SPD},spmd)
+include lib/libfdt/libfdt.mk
+# sources to support spmd
+BL31_SOURCES += plat/common/plat_spmd_manifest.c \
+ ${LIBFDT_SRCS}
+
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+endif
diff --git a/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
new file mode 100644
index 0000000..c44b0fc
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
@@ -0,0 +1,663 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SE_PRIVATE_H
+#define SE_PRIVATE_H
+
+#include <stdbool.h>
+#include <security_engine.h>
+
+/*
+ * PMC registers
+ */
+
+/* SC7 context save scratch register for T210 */
+#define PMC_SCRATCH43_REG_OFFSET U(0x22C)
+
+/* Secure scratch registers */
+#define PMC_SECURE_SCRATCH4_OFFSET 0xC0U
+#define PMC_SECURE_SCRATCH5_OFFSET 0xC4U
+#define PMC_SECURE_SCRATCH6_OFFSET 0x224U
+#define PMC_SECURE_SCRATCH7_OFFSET 0x228U
+#define PMC_SECURE_SCRATCH116_OFFSET 0xB28U
+#define PMC_SECURE_SCRATCH117_OFFSET 0xB2CU
+#define PMC_SECURE_SCRATCH120_OFFSET 0xB38U
+#define PMC_SECURE_SCRATCH121_OFFSET 0xB3CU
+#define PMC_SECURE_SCRATCH122_OFFSET 0xB40U
+#define PMC_SECURE_SCRATCH123_OFFSET 0xB44U
+
+/*
+ * AHB arbitration memory write queue
+ */
+#define ARAHB_MEM_WRQUE_MST_ID_OFFSET 0xFCU
+#define ARAHB_MST_ID_SE2_MASK (0x1U << 13)
+#define ARAHB_MST_ID_SE_MASK (0x1U << 14)
+
+/**
+ * SE registers
+ */
+#define TEGRA_SE_AES_KEYSLOT_COUNT 16
+#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
+
+/* SE Status register */
+#define SE_STATUS_OFFSET 0x800U
+#define SE_STATUS_SHIFT 0
+#define SE_STATUS_IDLE \
+ ((0U) << SE_STATUS_SHIFT)
+#define SE_STATUS_BUSY \
+ ((1U) << SE_STATUS_SHIFT)
+#define SE_STATUS(x) \
+ ((x) & ((0x3U) << SE_STATUS_SHIFT))
+
+#define SE_MEM_INTERFACE_SHIFT 2
+#define SE_MEM_INTERFACE_IDLE 0
+#define SE_MEM_INTERFACE_BUSY 1
+#define SE_MEM_INTERFACE(x) ((x) << SE_STATUS_SHIFT)
+
+/* SE register definitions */
+#define SE_SECURITY_REG_OFFSET 0x0
+#define SE_SECURITY_TZ_LOCK_SOFT_SHIFT 5
+#define SE_SECURE 0x0
+#define SE_SECURITY_TZ_LOCK_SOFT(x) ((x) << SE_SECURITY_TZ_LOCK_SOFT_SHIFT)
+
+#define SE_SEC_ENG_DIS_SHIFT 1
+#define SE_DISABLE_FALSE 0
+#define SE_DISABLE_TRUE 1
+#define SE_SEC_ENG_DISABLE(x)((x) << SE_SEC_ENG_DIS_SHIFT)
+
+/* SE config register */
+#define SE_CONFIG_REG_OFFSET 0x14U
+#define SE_CONFIG_ENC_ALG_SHIFT 12
+#define SE_CONFIG_ENC_ALG_AES_ENC \
+ ((1U) << SE_CONFIG_ENC_ALG_SHIFT)
+#define SE_CONFIG_ENC_ALG_RNG \
+ ((2U) << SE_CONFIG_ENC_ALG_SHIFT)
+#define SE_CONFIG_ENC_ALG_SHA \
+ ((3U) << SE_CONFIG_ENC_ALG_SHIFT)
+#define SE_CONFIG_ENC_ALG_RSA \
+ ((4U) << SE_CONFIG_ENC_ALG_SHIFT)
+#define SE_CONFIG_ENC_ALG_NOP \
+ ((0U) << SE_CONFIG_ENC_ALG_SHIFT)
+#define SE_CONFIG_ENC_ALG(x) \
+ ((x) & ((0xFU) << SE_CONFIG_ENC_ALG_SHIFT))
+
+#define SE_CONFIG_DEC_ALG_SHIFT 8
+#define SE_CONFIG_DEC_ALG_AES \
+ ((1U) << SE_CONFIG_DEC_ALG_SHIFT)
+#define SE_CONFIG_DEC_ALG_NOP \
+ ((0U) << SE_CONFIG_DEC_ALG_SHIFT)
+#define SE_CONFIG_DEC_ALG(x) \
+ ((x) & ((0xFU) << SE_CONFIG_DEC_ALG_SHIFT))
+
+#define SE_CONFIG_DST_SHIFT 2
+#define SE_CONFIG_DST_MEMORY \
+ ((0U) << SE_CONFIG_DST_SHIFT)
+#define SE_CONFIG_DST_HASHREG \
+ ((1U) << SE_CONFIG_DST_SHIFT)
+#define SE_CONFIG_DST_KEYTAB \
+ ((2U) << SE_CONFIG_DST_SHIFT)
+#define SE_CONFIG_DST_SRK \
+ ((3U) << SE_CONFIG_DST_SHIFT)
+#define SE_CONFIG_DST_RSAREG \
+ ((4U) << SE_CONFIG_DST_SHIFT)
+#define SE_CONFIG_DST(x) \
+ ((x) & ((0x7U) << SE_CONFIG_DST_SHIFT))
+
+#define SE_CONFIG_ENC_MODE_SHIFT 24
+#define SE_CONFIG_ENC_MODE_KEY128 \
+ ((0UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE_KEY192 \
+ ((1UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE_KEY256 \
+ ((2UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE_SHA1 \
+ ((0UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE_SHA224 \
+ ((4UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE_SHA256 \
+ ((5UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE_SHA384 \
+ ((6UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE_SHA512 \
+ ((7UL) << SE_CONFIG_ENC_MODE_SHIFT)
+#define SE_CONFIG_ENC_MODE(x)\
+ ((x) & ((0xFFUL) << SE_CONFIG_ENC_MODE_SHIFT))
+
+#define SE_CONFIG_DEC_MODE_SHIFT 16
+#define SE_CONFIG_DEC_MODE_KEY128 \
+ ((0UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE_KEY192 \
+ ((1UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE_KEY256 \
+ ((2UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE_SHA1 \
+ ((0UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE_SHA224 \
+ ((4UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE_SHA256 \
+ ((5UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE_SHA384 \
+ ((6UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE_SHA512 \
+ ((7UL) << SE_CONFIG_DEC_MODE_SHIFT)
+#define SE_CONFIG_DEC_MODE(x)\
+ ((x) & ((0xFFUL) << SE_CONFIG_DEC_MODE_SHIFT))
+
+
+/* DRBG random number generator config */
+#define SE_RNG_CONFIG_REG_OFFSET 0x340
+
+#define DRBG_MODE_SHIFT 0
+#define DRBG_MODE_NORMAL \
+ ((0U) << DRBG_MODE_SHIFT)
+#define DRBG_MODE_FORCE_INSTANTION \
+ ((1U) << DRBG_MODE_SHIFT)
+#define DRBG_MODE_FORCE_RESEED \
+ ((2U) << DRBG_MODE_SHIFT)
+#define SE_RNG_CONFIG_MODE(x) \
+ ((x) & ((0x3U) << DRBG_MODE_SHIFT))
+
+#define DRBG_SRC_SHIFT 2
+#define DRBG_SRC_NONE \
+ ((0U) << DRBG_SRC_SHIFT)
+#define DRBG_SRC_ENTROPY \
+ ((1U) << DRBG_SRC_SHIFT)
+#define DRBG_SRC_LFSR \
+ ((2U) << DRBG_SRC_SHIFT)
+#define SE_RNG_SRC_CONFIG_MODE(x) \
+ ((x) & ((0x3U) << DRBG_SRC_SHIFT))
+
+/* DRBG random number generator entropy config */
+
+#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344U
+
+#define DRBG_RO_ENT_SRC_SHIFT 1
+#define DRBG_RO_ENT_SRC_ENABLE \
+ ((1U) << DRBG_RO_ENT_SRC_SHIFT)
+#define DRBG_RO_ENT_SRC_DISABLE \
+ ((0U) << DRBG_RO_ENT_SRC_SHIFT)
+#define SE_RNG_SRC_CONFIG_RO_ENT_SRC(x) \
+ ((x) & ((0x1U) << DRBG_RO_ENT_SRC_SHIFT))
+
+#define DRBG_RO_ENT_SRC_LOCK_SHIFT 0
+#define DRBG_RO_ENT_SRC_LOCK_ENABLE \
+ ((1U) << DRBG_RO_ENT_SRC_LOCK_SHIFT)
+#define DRBG_RO_ENT_SRC_LOCK_DISABLE \
+ ((0U) << DRBG_RO_ENT_SRC_LOCK_SHIFT)
+#define SE_RNG_SRC_CONFIG_RO_ENT_SRC_LOCK(x) \
+ ((x) & ((0x1U) << DRBG_RO_ENT_SRC_LOCK_SHIFT))
+
+#define DRBG_RO_ENT_IGNORE_MEM_SHIFT 12
+#define DRBG_RO_ENT_IGNORE_MEM_ENABLE \
+ ((1U) << DRBG_RO_ENT_IGNORE_MEM_SHIFT)
+#define DRBG_RO_ENT_IGNORE_MEM_DISABLE \
+ ((0U) << DRBG_RO_ENT_IGNORE_MEM_SHIFT)
+#define SE_RNG_SRC_CONFIG_RO_ENT_IGNORE_MEM(x) \
+ ((x) & ((0x1U) << DRBG_RO_ENT_IGNORE_MEM_SHIFT))
+
+#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348
+
+/* SE CRYPTO */
+#define SE_CRYPTO_REG_OFFSET 0x304
+#define SE_CRYPTO_HASH_SHIFT 0
+#define SE_CRYPTO_HASH_DISABLE \
+ ((0U) << SE_CRYPTO_HASH_SHIFT)
+#define SE_CRYPTO_HASH_ENABLE \
+ ((1U) << SE_CRYPTO_HASH_SHIFT)
+
+#define SE_CRYPTO_XOR_POS_SHIFT 1
+#define SE_CRYPTO_XOR_BYPASS \
+ ((0U) << SE_CRYPTO_XOR_POS_SHIFT)
+#define SE_CRYPTO_XOR_TOP \
+ ((2U) << SE_CRYPTO_XOR_POS_SHIFT)
+#define SE_CRYPTO_XOR_BOTTOM \
+ ((3U) << SE_CRYPTO_XOR_POS_SHIFT)
+
+#define SE_CRYPTO_INPUT_SEL_SHIFT 3
+#define SE_CRYPTO_INPUT_AHB \
+ ((0U) << SE_CRYPTO_INPUT_SEL_SHIFT)
+#define SE_CRYPTO_INPUT_RANDOM \
+ ((1U) << SE_CRYPTO_INPUT_SEL_SHIFT)
+#define SE_CRYPTO_INPUT_AESOUT \
+ ((2U) << SE_CRYPTO_INPUT_SEL_SHIFT)
+#define SE_CRYPTO_INPUT_LNR_CTR \
+ ((3U) << SE_CRYPTO_INPUT_SEL_SHIFT)
+
+#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5
+#define SE_CRYPTO_VCTRAM_AHB \
+ ((0U) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
+#define SE_CRYPTO_VCTRAM_AESOUT \
+ ((2U) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
+#define SE_CRYPTO_VCTRAM_PREVAHB \
+ ((3U) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
+
+#define SE_CRYPTO_IV_SEL_SHIFT 7
+#define SE_CRYPTO_IV_ORIGINAL \
+ ((0U) << SE_CRYPTO_IV_SEL_SHIFT)
+#define SE_CRYPTO_IV_UPDATED \
+ ((1U) << SE_CRYPTO_IV_SEL_SHIFT)
+
+#define SE_CRYPTO_CORE_SEL_SHIFT 8
+#define SE_CRYPTO_CORE_DECRYPT \
+ ((0U) << SE_CRYPTO_CORE_SEL_SHIFT)
+#define SE_CRYPTO_CORE_ENCRYPT \
+ ((1U) << SE_CRYPTO_CORE_SEL_SHIFT)
+
+#define SE_CRYPTO_KEY_INDEX_SHIFT 24
+#define SE_CRYPTO_KEY_INDEX(x) (x << SE_CRYPTO_KEY_INDEX_SHIFT)
+
+#define SE_CRYPTO_MEMIF_AHB \
+ ((0U) << SE_CRYPTO_MEMIF_SHIFT)
+#define SE_CRYPTO_MEMIF_MCCIF \
+ ((1U) << SE_CRYPTO_MEMIF_SHIFT)
+#define SE_CRYPTO_MEMIF_SHIFT 31
+
+/* KEY TABLE */
+#define SE_KEYTABLE_REG_OFFSET 0x31C
+
+/* KEYIV PKT - key slot */
+#define SE_KEYTABLE_SLOT_SHIFT 4
+#define SE_KEYTABLE_SLOT(x) (x << SE_KEYTABLE_SLOT_SHIFT)
+
+/* KEYIV PKT - KEYIV select */
+#define SE_KEYIV_PKT_KEYIV_SEL_SHIFT 3
+#define SE_CRYPTO_KEYIV_KEY \
+ ((0U) << SE_KEYIV_PKT_KEYIV_SEL_SHIFT)
+#define SE_CRYPTO_KEYIV_IVS \
+ ((1U) << SE_KEYIV_PKT_KEYIV_SEL_SHIFT)
+
+/* KEYIV PKT - IV select */
+#define SE_KEYIV_PKT_IV_SEL_SHIFT 2
+#define SE_CRYPTO_KEYIV_IVS_OIV \
+ ((0U) << SE_KEYIV_PKT_IV_SEL_SHIFT)
+#define SE_CRYPTO_KEYIV_IVS_UIV \
+ ((1U) << SE_KEYIV_PKT_IV_SEL_SHIFT)
+
+/* KEYIV PKT - key word */
+#define SE_KEYIV_PKT_KEY_WORD_SHIFT 0
+#define SE_KEYIV_PKT_KEY_WORD(x) \
+ ((x) << SE_KEYIV_PKT_KEY_WORD_SHIFT)
+
+/* KEYIV PKT - iv word */
+#define SE_KEYIV_PKT_IV_WORD_SHIFT 0
+#define SE_KEYIV_PKT_IV_WORD(x) \
+ ((x) << SE_KEYIV_PKT_IV_WORD_SHIFT)
+
+/* SE OPERATION */
+#define SE_OPERATION_REG_OFFSET 0x8U
+#define SE_OPERATION_SHIFT 0
+#define SE_OP_ABORT \
+ ((0x0U) << SE_OPERATION_SHIFT)
+#define SE_OP_START \
+ ((0x1U) << SE_OPERATION_SHIFT)
+#define SE_OP_RESTART \
+ ((0x2U) << SE_OPERATION_SHIFT)
+#define SE_OP_CTX_SAVE \
+ ((0x3U) << SE_OPERATION_SHIFT)
+#define SE_OP_RESTART_IN \
+ ((0x4U) << SE_OPERATION_SHIFT)
+#define SE_OPERATION(x) \
+ ((x) & ((0x7U) << SE_OPERATION_SHIFT))
+
+/* SE CONTEXT */
+#define SE_CTX_SAVE_CONFIG_REG_OFFSET 0x70
+#define SE_CTX_SAVE_WORD_QUAD_SHIFT 0
+#define SE_CTX_SAVE_WORD_QUAD(x) \
+ (x << SE_CTX_SAVE_WORD_QUAD_SHIFT)
+#define SE_CTX_SAVE_WORD_QUAD_KEYS_0_3 \
+ ((0U) << SE_CTX_SAVE_WORD_QUAD_SHIFT)
+#define SE_CTX_SAVE_WORD_QUAD_KEYS_4_7 \
+ ((1U) << SE_CTX_SAVE_WORD_QUAD_SHIFT)
+#define SE_CTX_SAVE_WORD_QUAD_ORIG_IV \
+ ((2U) << SE_CTX_SAVE_WORD_QUAD_SHIFT)
+#define SE_CTX_SAVE_WORD_QUAD_UPD_IV \
+ ((3U) << SE_CTX_SAVE_WORD_QUAD_SHIFT)
+
+#define SE_CTX_SAVE_KEY_INDEX_SHIFT 8
+#define SE_CTX_SAVE_KEY_INDEX(x) (x << SE_CTX_SAVE_KEY_INDEX_SHIFT)
+
+#define SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT 24
+#define SE_CTX_SAVE_STICKY_WORD_QUAD_STICKY_0_3 \
+ ((0U) << SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT)
+#define SE_CTX_SAVE_STICKY_WORD_QUAD_STICKY_4_7 \
+ ((1U) << SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT)
+#define SE_CTX_SAVE_STICKY_WORD_QUAD(x) \
+ (x << SE_CTX_SAVE_STICKY_WORD_QUAD_SHIFT)
+
+#define SE_CTX_SAVE_SRC_SHIFT 29
+#define SE_CTX_SAVE_SRC_STICKY_BITS \
+ ((0U) << SE_CTX_SAVE_SRC_SHIFT)
+#define SE_CTX_SAVE_SRC_RSA_KEYTABLE \
+ ((1U) << SE_CTX_SAVE_SRC_SHIFT)
+#define SE_CTX_SAVE_SRC_AES_KEYTABLE \
+ ((2U) << SE_CTX_SAVE_SRC_SHIFT)
+#define SE_CTX_SAVE_SRC_PKA1_STICKY_BITS \
+ ((3U) << SE_CTX_SAVE_SRC_SHIFT)
+#define SE_CTX_SAVE_SRC_MEM \
+ ((4U) << SE_CTX_SAVE_SRC_SHIFT)
+#define SE_CTX_SAVE_SRC_SRK \
+ ((6U) << SE_CTX_SAVE_SRC_SHIFT)
+#define SE_CTX_SAVE_SRC_PKA1_KEYTABLE \
+ ((7U) << SE_CTX_SAVE_SRC_SHIFT)
+
+#define SE_CTX_STICKY_WORD_QUAD_SHIFT 24
+#define SE_CTX_STICKY_WORD_QUAD_WORDS_0_3 \
+ ((0U) << SE_CTX_STICKY_WORD_QUAD_SHIFT)
+#define SE_CTX_STICKY_WORD_QUAD_WORDS_4_7 \
+ ((1U) << SE_CTX_STICKY_WORD_QUAD_SHIFT)
+#define SE_CTX_STICKY_WORD_QUAD(x) (x << SE_CTX_STICKY_WORD_QUAD_SHIFT)
+
+#define SE_CTX_SAVE_RSA_KEY_INDEX_SHIFT 16
+#define SE_CTX_SAVE_RSA_KEY_INDEX(x) \
+ (x << SE_CTX_SAVE_RSA_KEY_INDEX_SHIFT)
+
+#define SE_CTX_RSA_WORD_QUAD_SHIFT 12
+#define SE_CTX_RSA_WORD_QUAD(x) \
+ (x << SE_CTX_RSA_WORD_QUAD_SHIFT)
+
+#define SE_CTX_PKA1_WORD_QUAD_L_SHIFT 0
+#define SE_CTX_PKA1_WORD_QUAD_L_SIZE \
+ ((true ? 4:0) - \
+ (false ? 4:0) + 1)
+#define SE_CTX_PKA1_WORD_QUAD_L(x)\
+ (((x) << SE_CTX_PKA1_WORD_QUAD_L_SHIFT) & 0x1f)
+
+#define SE_CTX_PKA1_WORD_QUAD_H_SHIFT 12
+#define SE_CTX_PKA1_WORD_QUAD_H(x)\
+ ((((x) >> SE_CTX_PKA1_WORD_QUAD_L_SIZE) & 0xf) \
+ << SE_CTX_PKA1_WORD_QUAD_H_SHIFT)
+
+#define SE_RSA_KEY_INDEX_SLOT0_EXP 0
+#define SE_RSA_KEY_INDEX_SLOT0_MOD 1
+#define SE_RSA_KEY_INDEX_SLOT1_EXP 2
+#define SE_RSA_KEY_INDEX_SLOT1_MOD 3
+
+
+/* SE_CTX_SAVE_AUTO */
+#define SE_CTX_SAVE_AUTO_REG_OFFSET 0x74U
+
+/* Enable */
+#define SE_CTX_SAVE_AUTO_ENABLE_SHIFT 0
+#define SE_CTX_SAVE_AUTO_DIS \
+ ((0U) << SE_CTX_SAVE_AUTO_ENABLE_SHIFT)
+#define SE_CTX_SAVE_AUTO_EN \
+ ((1U) << SE_CTX_SAVE_AUTO_ENABLE_SHIFT)
+#define SE_CTX_SAVE_AUTO_ENABLE(x) \
+ ((x) & ((0x1U) << SE_CTX_SAVE_AUTO_ENABLE_SHIFT))
+
+/* Lock */
+#define SE_CTX_SAVE_AUTO_LOCK_SHIFT 8
+#define SE_CTX_SAVE_AUTO_LOCK_EN \
+ ((1U) << SE_CTX_SAVE_AUTO_LOCK_SHIFT)
+#define SE_CTX_SAVE_AUTO_LOCK_DIS \
+ ((0U) << SE_CTX_SAVE_AUTO_LOCK_SHIFT)
+#define SE_CTX_SAVE_AUTO_LOCK(x) \
+ ((x) & ((0x1U) << SE_CTX_SAVE_AUTO_LOCK_SHIFT))
+
+/* Current context save number of blocks*/
+#define SE_CTX_SAVE_AUTO_CURR_CNT_SHIFT 16
+#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK 0x3FFU
+#define SE_CTX_SAVE_GET_BLK_COUNT(x) \
+ (((x) >> SE_CTX_SAVE_AUTO_CURR_CNT_SHIFT) & \
+ SE_CTX_SAVE_AUTO_CURR_CNT_MASK)
+
+#define SE_CTX_SAVE_SIZE_BLOCKS_SE1 133
+#define SE_CTX_SAVE_SIZE_BLOCKS_SE2 646
+
+/* SE TZRAM OPERATION - only for SE1 */
+#define SE_TZRAM_OPERATION 0x540U
+
+#define SE_TZRAM_OP_MODE_SHIFT 1
+#define SE_TZRAM_OP_COMMAND_INIT 1
+#define SE_TZRAM_OP_COMMAND_SHIFT 0
+#define SE_TZRAM_OP_MODE_SAVE \
+ ((0U) << SE_TZRAM_OP_MODE_SHIFT)
+#define SE_TZRAM_OP_MODE_RESTORE \
+ ((1U) << SE_TZRAM_OP_MODE_SHIFT)
+#define SE_TZRAM_OP_MODE(x) \
+ ((x) & ((0x1U) << SE_TZRAM_OP_MODE_SHIFT))
+
+#define SE_TZRAM_OP_BUSY_SHIFT 2
+#define SE_TZRAM_OP_BUSY_OFF \
+ ((0U) << SE_TZRAM_OP_BUSY_SHIFT)
+#define SE_TZRAM_OP_BUSY_ON \
+ ((1U) << SE_TZRAM_OP_BUSY_SHIFT)
+#define SE_TZRAM_OP_BUSY(x) \
+ ((x) & ((0x1U) << SE_TZRAM_OP_BUSY_SHIFT))
+
+#define SE_TZRAM_OP_REQ_SHIFT 0
+#define SE_TZRAM_OP_REQ_IDLE \
+ ((0U) << SE_TZRAM_OP_REQ_SHIFT)
+#define SE_TZRAM_OP_REQ_INIT \
+ ((1U) << SE_TZRAM_OP_REQ_SHIFT)
+#define SE_TZRAM_OP_REQ(x) \
+ ((x) & ((0x1U) << SE_TZRAM_OP_REQ_SHIFT))
+
+/* SE Interrupt */
+#define SE_INT_ENABLE_REG_OFFSET U(0xC)
+#define SE_INT_STATUS_REG_OFFSET 0x10U
+#define SE_INT_OP_DONE_SHIFT 4
+#define SE_INT_OP_DONE_CLEAR \
+ ((0U) << SE_INT_OP_DONE_SHIFT)
+#define SE_INT_OP_DONE_ACTIVE \
+ ((1U) << SE_INT_OP_DONE_SHIFT)
+#define SE_INT_OP_DONE(x) \
+ ((x) & ((0x1U) << SE_INT_OP_DONE_SHIFT))
+
+/* SE TZRAM SECURITY */
+#define SE_TZRAM_SEC_REG_OFFSET 0x4
+
+#define SE_TZRAM_SEC_SETTING_SHIFT 0
+#define SE_TZRAM_SECURE \
+ ((0UL) << SE_TZRAM_SEC_SETTING_SHIFT)
+#define SE_TZRAM_NONSECURE \
+ ((1UL) << SE_TZRAM_SEC_SETTING_SHIFT)
+#define SE_TZRAM_SEC_SETTING(x) \
+ ((x) & ((0x1UL) << SE_TZRAM_SEC_SETTING_SHIFT))
+
+/* PKA1 KEY SLOTS */
+#define TEGRA_SE_PKA1_KEYSLOT_COUNT 4
+
+
+/* SE error status */
+#define SE_ERR_STATUS_REG_OFFSET 0x804U
+#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0x330
+#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
+#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \
+ (x << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT)
+
+#define SE_KEY_INDEX_SHIFT 8
+#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) (x << SE_KEY_INDEX_SHIFT)
+
+
+/* SE linked list (LL) register */
+#define SE_IN_LL_ADDR_REG_OFFSET 0x18U
+#define SE_OUT_LL_ADDR_REG_OFFSET 0x24U
+#define SE_BLOCK_COUNT_REG_OFFSET 0x318U
+
+/* AES data sizes */
+#define TEGRA_SE_KEY_256_SIZE 32
+#define TEGRA_SE_KEY_192_SIZE 24
+#define TEGRA_SE_KEY_128_SIZE 16
+#define TEGRA_SE_AES_BLOCK_SIZE 16
+#define TEGRA_SE_AES_MIN_KEY_SIZE 16
+#define TEGRA_SE_AES_MAX_KEY_SIZE 32
+#define TEGRA_SE_AES_IV_SIZE 16
+
+#define TEGRA_SE_RNG_IV_SIZE 16
+#define TEGRA_SE_RNG_DT_SIZE 16
+#define TEGRA_SE_RNG_KEY_SIZE 16
+#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
+ TEGRA_SE_RNG_KEY_SIZE + \
+ TEGRA_SE_RNG_DT_SIZE)
+#define TEGRA_SE_RSA512_DIGEST_SIZE 64
+#define TEGRA_SE_RSA1024_DIGEST_SIZE 128
+#define TEGRA_SE_RSA1536_DIGEST_SIZE 192
+#define TEGRA_SE_RSA2048_DIGEST_SIZE 256
+
+#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
+#define SE_KEY_READ_DISABLE_SHIFT 0
+
+#define SE_CTX_BUFER_SIZE 1072
+#define SE_CTX_DRBG_BUFER_SIZE 2112
+
+/* SE blobs size in bytes */
+#define SE_CTX_SAVE_RSA_KEY_LENGTH 1024
+#define SE_CTX_SAVE_RANDOM_DATA_SIZE 16
+#define SE_CTX_SAVE_STICKY_BITS_SIZE 16
+#define SE2_CONTEXT_SAVE_PKA1_STICKY_BITS_LENGTH 16
+#define SE2_CONTEXT_SAVE_PKA1_KEYS_LENGTH 8192
+#define SE_CTX_KNOWN_PATTERN_SIZE 16
+#define SE_CTX_KNOWN_PATTERN_SIZE_WORDS (SE_CTX_KNOWN_PATTERN_SIZE/4)
+
+/* SE RSA */
+#define TEGRA_SE_RSA_KEYSLOT_COUNT 2
+#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404
+#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408
+#define SE_RSA_MAX_EXP_BIT_SIZE 2048
+#define SE_RSA_MAX_EXP_SIZE32 \
+ (SE_RSA_MAX_EXP_BIT_SIZE >> 5)
+#define SE_RSA_MAX_MOD_BIT_SIZE 2048
+#define SE_RSA_MAX_MOD_SIZE32 \
+ (SE_RSA_MAX_MOD_BIT_SIZE >> 5)
+
+/* SE_RSA_KEYTABLE_ADDR */
+#define SE_RSA_KEYTABLE_ADDR 0x420
+#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0
+#define RSA_KEY_PKT_EXPMOD_SEL_SHIFT \
+ ((6U) << RSA_KEY_PKT_WORD_ADDR_SHIFT)
+#define RSA_KEY_MOD \
+ ((1U) << RSA_KEY_PKT_EXPMOD_SEL_SHIFT)
+#define RSA_KEY_EXP \
+ ((0U) << RSA_KEY_PKT_EXPMOD_SEL_SHIFT)
+#define RSA_KEY_PKT_SLOT_SHIFT 7
+#define RSA_KEY_SLOT_1 \
+ ((0U) << RSA_KEY_PKT_SLOT_SHIFT)
+#define RSA_KEY_SLOT_2 \
+ ((1U) << RSA_KEY_PKT_SLOT_SHIFT)
+#define RSA_KEY_PKT_INPUT_MODE_SHIFT 8
+#define RSA_KEY_REG_INPUT \
+ ((0U) << RSA_KEY_PKT_INPUT_MODE_SHIFT)
+#define RSA_KEY_DMA_INPUT \
+ ((1U) << RSA_KEY_PKT_INPUT_MODE_SHIFT)
+
+/* SE_RSA_KEYTABLE_DATA */
+#define SE_RSA_KEYTABLE_DATA 0x424
+
+/* SE_RSA_CONFIG register */
+#define SE_RSA_CONFIG 0x400
+#define RSA_KEY_SLOT_SHIFT 24
+#define RSA_KEY_SLOT(x) \
+ ((x) << RSA_KEY_SLOT_SHIFT)
+
+/*******************************************************************************
+ * Structure definition
+ ******************************************************************************/
+
+/* SE context blob */
+#pragma pack(push, 1)
+typedef struct tegra_aes_key_slot {
+ /* 0 - 7 AES key */
+ uint32_t key[8];
+ /* 8 - 11 Original IV */
+ uint32_t oiv[4];
+ /* 12 - 15 Updated IV */
+ uint32_t uiv[4];
+} tegra_se_aes_key_slot_t;
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef struct tegra_se_context {
+ /* random number */
+ unsigned char rand_data[SE_CTX_SAVE_RANDOM_DATA_SIZE];
+ /* Sticky bits */
+ unsigned char sticky_bits[SE_CTX_SAVE_STICKY_BITS_SIZE * 2];
+ /* AES key slots */
+ tegra_se_aes_key_slot_t key_slots[TEGRA_SE_AES_KEYSLOT_COUNT];
+ /* RSA key slots */
+ unsigned char rsa_keys[SE_CTX_SAVE_RSA_KEY_LENGTH];
+} tegra_se_context_t;
+#pragma pack(pop)
+
+/* PKA context blob */
+#pragma pack(push, 1)
+typedef struct tegra_pka_context {
+ unsigned char sticky_bits[SE2_CONTEXT_SAVE_PKA1_STICKY_BITS_LENGTH];
+ unsigned char pka_keys[SE2_CONTEXT_SAVE_PKA1_KEYS_LENGTH];
+} tegra_pka_context_t;
+#pragma pack(pop)
+
+/* SE context blob */
+#pragma pack(push, 1)
+typedef struct tegra_se_context_blob {
+ /* SE context */
+ tegra_se_context_t se_ctx;
+ /* Known Pattern */
+ unsigned char known_pattern[SE_CTX_KNOWN_PATTERN_SIZE];
+} tegra_se_context_blob_t;
+#pragma pack(pop)
+
+/* SE2 and PKA1 context blob */
+#pragma pack(push, 1)
+typedef struct tegra_se2_context_blob {
+ /* SE2 context */
+ tegra_se_context_t se_ctx;
+ /* PKA1 context */
+ tegra_pka_context_t pka_ctx;
+ /* Known Pattern */
+ unsigned char known_pattern[SE_CTX_KNOWN_PATTERN_SIZE];
+} tegra_se2_context_blob_t;
+#pragma pack(pop)
+
+/* SE AES key type 128bit, 192bit, 256bit */
+typedef enum {
+ SE_AES_KEY128,
+ SE_AES_KEY192,
+ SE_AES_KEY256,
+} tegra_se_aes_key_type_t;
+
+/* SE RSA key slot */
+typedef struct tegra_se_rsa_key_slot {
+ /* 0 - 63 exponent key */
+ uint32_t exponent[SE_RSA_MAX_EXP_SIZE32];
+ /* 64 - 127 modulus key */
+ uint32_t modulus[SE_RSA_MAX_MOD_SIZE32];
+} tegra_se_rsa_key_slot_t;
+
+
+/*******************************************************************************
+ * Inline functions definition
+ ******************************************************************************/
+
+static inline uint32_t tegra_se_read_32(const tegra_se_dev_t *dev, uint32_t offset)
+{
+ return mmio_read_32(dev->se_base + offset);
+}
+
+static inline void tegra_se_write_32(const tegra_se_dev_t *dev, uint32_t offset, uint32_t val)
+{
+ mmio_write_32(dev->se_base + offset, val);
+}
+
+static inline uint32_t tegra_pka_read_32(tegra_pka_dev_t *dev, uint32_t offset)
+{
+ return mmio_read_32(dev->pka_base + offset);
+}
+
+static inline void tegra_pka_write_32(tegra_pka_dev_t *dev, uint32_t offset,
+uint32_t val)
+{
+ mmio_write_32(dev->pka_base + offset, val);
+}
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+int tegra_se_start_normal_operation(const tegra_se_dev_t *, uint32_t);
+int tegra_se_start_ctx_save_operation(const tegra_se_dev_t *, uint32_t);
+
+#endif /* SE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
new file mode 100644
index 0000000..4860858
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
@@ -0,0 +1,1071 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <se_private.h>
+#include <security_engine.h>
+#include <tegra_platform.h>
+
+/*******************************************************************************
+ * Constants and Macros
+ ******************************************************************************/
+
+#define TIMEOUT_100MS 100U /* Timeout in 100ms */
+#define RNG_AES_KEY_INDEX 1
+
+/*******************************************************************************
+ * Data structure and global variables
+ ******************************************************************************/
+
+/* The security engine contexts are formatted as follows:
+ *
+ * SE1 CONTEXT:
+ * #--------------------------------#
+ * | Random Data 1 Block |
+ * #--------------------------------#
+ * | Sticky Bits 2 Blocks |
+ * #--------------------------------#
+ * | Key Table 64 Blocks |
+ * | For each Key (x16): |
+ * | Key: 2 Blocks |
+ * | Original-IV: 1 Block |
+ * | Updated-IV: 1 Block |
+ * #--------------------------------#
+ * | RSA Keys 64 Blocks |
+ * #--------------------------------#
+ * | Known Pattern 1 Block |
+ * #--------------------------------#
+ *
+ * SE2/PKA1 CONTEXT:
+ * #--------------------------------#
+ * | Random Data 1 Block |
+ * #--------------------------------#
+ * | Sticky Bits 2 Blocks |
+ * #--------------------------------#
+ * | Key Table 64 Blocks |
+ * | For each Key (x16): |
+ * | Key: 2 Blocks |
+ * | Original-IV: 1 Block |
+ * | Updated-IV: 1 Block |
+ * #--------------------------------#
+ * | RSA Keys 64 Blocks |
+ * #--------------------------------#
+ * | PKA sticky bits 1 Block |
+ * #--------------------------------#
+ * | PKA keys 512 Blocks |
+ * #--------------------------------#
+ * | Known Pattern 1 Block |
+ * #--------------------------------#
+ */
+
+/* Known pattern data for T210 */
+static const uint8_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE] = {
+ /* 128 bit AES block */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+/* SE input and output linked list buffers */
+static tegra_se_io_lst_t se1_src_ll_buf;
+static tegra_se_io_lst_t se1_dst_ll_buf;
+
+/* SE2 input and output linked list buffers */
+static tegra_se_io_lst_t se2_src_ll_buf;
+static tegra_se_io_lst_t se2_dst_ll_buf;
+
+/* SE1 context buffer, 132 blocks */
+static __aligned(64) uint8_t se1_ctx_buf[SE_CTX_DRBG_BUFER_SIZE];
+
+/* SE1 security engine device handle */
+static tegra_se_dev_t se_dev_1 = {
+ .se_num = 1,
+ /* Setup base address for se */
+ .se_base = TEGRA_SE1_BASE,
+ /* Setup context size in AES blocks */
+ .ctx_size_blks = SE_CTX_SAVE_SIZE_BLOCKS_SE1,
+ /* Setup SRC buffers for SE operations */
+ .src_ll_buf = &se1_src_ll_buf,
+ /* Setup DST buffers for SE operations */
+ .dst_ll_buf = &se1_dst_ll_buf,
+ /* Setup context save destination */
+ .ctx_save_buf = (uint32_t *)&se1_ctx_buf
+};
+
+/* SE2 security engine device handle (T210B01 only) */
+static tegra_se_dev_t se_dev_2 = {
+ .se_num = 2,
+ /* Setup base address for se */
+ .se_base = TEGRA_SE2_BASE,
+ /* Setup context size in AES blocks */
+ .ctx_size_blks = SE_CTX_SAVE_SIZE_BLOCKS_SE2,
+ /* Setup SRC buffers for SE operations */
+ .src_ll_buf = &se2_src_ll_buf,
+ /* Setup DST buffers for SE operations */
+ .dst_ll_buf = &se2_dst_ll_buf,
+ /* Setup context save destination */
+ .ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000)
+};
+
+static bool ecid_valid;
+
+/*******************************************************************************
+ * Functions Definition
+ ******************************************************************************/
+
+static void tegra_se_make_data_coherent(const tegra_se_dev_t *se_dev)
+{
+ flush_dcache_range(((uint64_t)(se_dev->src_ll_buf)),
+ sizeof(tegra_se_io_lst_t));
+ flush_dcache_range(((uint64_t)(se_dev->dst_ll_buf)),
+ sizeof(tegra_se_io_lst_t));
+}
+
+/*
+ * Check that SE operation has completed after kickoff
+ * This function is invoked after an SE operation has been started,
+ * and it checks the following conditions:
+ * 1. SE_INT_STATUS = SE_OP_DONE
+ * 2. SE_STATUS = IDLE
+ * 3. AHB bus data transfer complete.
+ * 4. SE_ERR_STATUS is clean.
+ */
+static int32_t tegra_se_operation_complete(const tegra_se_dev_t *se_dev)
+{
+ uint32_t val = 0;
+ int32_t ret = 0;
+ uint32_t timeout;
+
+ /* Poll the SE interrupt register to ensure H/W operation complete */
+ val = tegra_se_read_32(se_dev, SE_INT_STATUS_REG_OFFSET);
+ for (timeout = 0; (SE_INT_OP_DONE(val) == SE_INT_OP_DONE_CLEAR) &&
+ (timeout < TIMEOUT_100MS); timeout++) {
+ mdelay(1);
+ val = tegra_se_read_32(se_dev, SE_INT_STATUS_REG_OFFSET);
+ }
+
+ if (timeout == TIMEOUT_100MS) {
+ ERROR("%s: ERR: Atomic context save operation timeout!\n",
+ __func__);
+ ret = -ETIMEDOUT;
+ }
+
+ /* Poll the SE status idle to ensure H/W operation complete */
+ if (ret == 0) {
+ val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET);
+ for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS);
+ timeout++) {
+ mdelay(1);
+ val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET);
+ }
+
+ if (timeout == TIMEOUT_100MS) {
+ ERROR("%s: ERR: MEM_INTERFACE and SE state "
+ "idle state timeout.\n", __func__);
+ ret = -ETIMEDOUT;
+ }
+ }
+
+ /* Check AHB bus transfer complete */
+ if (ret == 0) {
+ val = mmio_read_32(TEGRA_AHB_ARB_BASE + ARAHB_MEM_WRQUE_MST_ID_OFFSET);
+ for (timeout = 0; ((val & (ARAHB_MST_ID_SE_MASK | ARAHB_MST_ID_SE2_MASK)) != 0U) &&
+ (timeout < TIMEOUT_100MS); timeout++) {
+ mdelay(1);
+ val = mmio_read_32(TEGRA_AHB_ARB_BASE + ARAHB_MEM_WRQUE_MST_ID_OFFSET);
+ }
+
+ if (timeout == TIMEOUT_100MS) {
+ ERROR("%s: SE write over AHB timeout.\n", __func__);
+ ret = -ETIMEDOUT;
+ }
+ }
+
+ /* Ensure that no errors are thrown during operation */
+ if (ret == 0) {
+ val = tegra_se_read_32(se_dev, SE_ERR_STATUS_REG_OFFSET);
+ if (val != 0U) {
+ ERROR("%s: error during SE operation! 0x%x", __func__, val);
+ ret = -ENOTSUP;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Wait for SE engine to be idle and clear pending interrupts before
+ * starting the next SE operation.
+ */
+static int32_t tegra_se_operation_prepare(const tegra_se_dev_t *se_dev)
+{
+ int32_t ret = 0;
+ uint32_t val = 0;
+ uint32_t timeout;
+
+ /* disable SE interrupt to prevent interrupt issued by SE operation */
+ tegra_se_write_32(se_dev, SE_INT_ENABLE_REG_OFFSET, 0U);
+
+ /* Wait for previous operation to finish */
+ val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET);
+ for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS); timeout++) {
+ mdelay(1);
+ val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET);
+ }
+
+ if (timeout == TIMEOUT_100MS) {
+ ERROR("%s: ERR: SE status is not idle!\n", __func__);
+ ret = -ETIMEDOUT;
+ }
+
+ /* Clear any pending interrupts from previous operation */
+ val = tegra_se_read_32(se_dev, SE_INT_STATUS_REG_OFFSET);
+ tegra_se_write_32(se_dev, SE_INT_STATUS_REG_OFFSET, val);
+ return ret;
+}
+
+/*
+ * SE atomic context save. At SC7 entry, SE driver triggers the
+ * hardware automatically performs the context save operation.
+ */
+static int32_t tegra_se_context_save_atomic(const tegra_se_dev_t *se_dev)
+{
+ int32_t ret = 0;
+ uint32_t val = 0;
+ uint32_t blk_count_limit = 0;
+ uint32_t block_count;
+
+ /* Check that previous operation is finalized */
+ ret = tegra_se_operation_prepare(se_dev);
+
+ /* Read the context save progress counter: block_count
+ * Ensure no previous context save has been triggered
+ * SE_CTX_SAVE_AUTO.CURR_CNT == 0
+ */
+ if (ret == 0) {
+ val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET);
+ block_count = SE_CTX_SAVE_GET_BLK_COUNT(val);
+ if (block_count != 0U) {
+ ERROR("%s: ctx_save triggered multiple times\n",
+ __func__);
+ ret = -EALREADY;
+ }
+ }
+
+ /* Set the destination block count when the context save complete */
+ if (ret == 0) {
+ blk_count_limit = block_count + se_dev->ctx_size_blks;
+ }
+
+ /* Program SE_CONFIG register as for RNG operation
+ * SE_CONFIG.ENC_ALG = RNG
+ * SE_CONFIG.DEC_ALG = NOP
+ * SE_CONFIG.ENC_MODE is ignored
+ * SE_CONFIG.DEC_MODE is ignored
+ * SE_CONFIG.DST = MEMORY
+ */
+ if (ret == 0) {
+ val = (SE_CONFIG_ENC_ALG_RNG |
+ SE_CONFIG_DEC_ALG_NOP |
+ SE_CONFIG_DST_MEMORY);
+ tegra_se_write_32(se_dev, SE_CONFIG_REG_OFFSET, val);
+
+ tegra_se_make_data_coherent(se_dev);
+
+ /* SE_CTX_SAVE operation */
+ tegra_se_write_32(se_dev, SE_OPERATION_REG_OFFSET,
+ SE_OP_CTX_SAVE);
+
+ ret = tegra_se_operation_complete(se_dev);
+ }
+
+ /* Check that context has written the correct number of blocks */
+ if (ret == 0) {
+ val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET);
+ if (SE_CTX_SAVE_GET_BLK_COUNT(val) != blk_count_limit) {
+ ERROR("%s: expected %d blocks but %d were written\n",
+ __func__, blk_count_limit, val);
+ ret = -ECANCELED;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Security engine primitive operations, including normal operation
+ * and the context save operation.
+ */
+static int tegra_se_perform_operation(const tegra_se_dev_t *se_dev, uint32_t nbytes,
+ bool context_save)
+{
+ uint32_t nblocks = nbytes / TEGRA_SE_AES_BLOCK_SIZE;
+ int ret = 0;
+
+ assert(se_dev);
+
+ /* Use device buffers for in and out */
+ tegra_se_write_32(se_dev, SE_OUT_LL_ADDR_REG_OFFSET, ((uint64_t)(se_dev->dst_ll_buf)));
+ tegra_se_write_32(se_dev, SE_IN_LL_ADDR_REG_OFFSET, ((uint64_t)(se_dev->src_ll_buf)));
+
+ /* Check that previous operation is finalized */
+ ret = tegra_se_operation_prepare(se_dev);
+ if (ret != 0) {
+ goto op_error;
+ }
+
+ /* Program SE operation size */
+ if (nblocks) {
+ tegra_se_write_32(se_dev, SE_BLOCK_COUNT_REG_OFFSET, nblocks - 1);
+ }
+
+ /* Make SE LL data coherent before the SE operation */
+ tegra_se_make_data_coherent(se_dev);
+
+ /* Start hardware operation */
+ if (context_save)
+ tegra_se_write_32(se_dev, SE_OPERATION_REG_OFFSET, SE_OP_CTX_SAVE);
+ else
+ tegra_se_write_32(se_dev, SE_OPERATION_REG_OFFSET, SE_OP_START);
+
+ /* Wait for operation to finish */
+ ret = tegra_se_operation_complete(se_dev);
+
+op_error:
+ return ret;
+}
+
+/*
+ * Normal security engine operations other than the context save
+ */
+int tegra_se_start_normal_operation(const tegra_se_dev_t *se_dev, uint32_t nbytes)
+{
+ return tegra_se_perform_operation(se_dev, nbytes, false);
+}
+
+/*
+ * Security engine context save operation
+ */
+int tegra_se_start_ctx_save_operation(const tegra_se_dev_t *se_dev, uint32_t nbytes)
+{
+ return tegra_se_perform_operation(se_dev, nbytes, true);
+}
+
+/*
+ * Security Engine sequence to generat SRK
+ * SE and SE2 will generate different SRK by different
+ * entropy seeds.
+ */
+static int tegra_se_generate_srk(const tegra_se_dev_t *se_dev)
+{
+ int ret = PSCI_E_INTERN_FAIL;
+ uint32_t val;
+
+ /* Confgure the following hardware register settings:
+ * SE_CONFIG.DEC_ALG = NOP
+ * SE_CONFIG.ENC_ALG = RNG
+ * SE_CONFIG.DST = SRK
+ * SE_OPERATION.OP = START
+ * SE_CRYPTO_LAST_BLOCK = 0
+ */
+ se_dev->src_ll_buf->last_buff_num = 0;
+ se_dev->dst_ll_buf->last_buff_num = 0;
+
+ /* Configure random number generator */
+ if (ecid_valid)
+ val = (DRBG_MODE_FORCE_INSTANTION | DRBG_SRC_ENTROPY);
+ else
+ val = (DRBG_MODE_FORCE_RESEED | DRBG_SRC_ENTROPY);
+ tegra_se_write_32(se_dev, SE_RNG_CONFIG_REG_OFFSET, val);
+
+ /* Configure output destination = SRK */
+ val = (SE_CONFIG_ENC_ALG_RNG |
+ SE_CONFIG_DEC_ALG_NOP |
+ SE_CONFIG_DST_SRK);
+ tegra_se_write_32(se_dev, SE_CONFIG_REG_OFFSET, val);
+
+ /* Perform hardware operation */
+ ret = tegra_se_start_normal_operation(se_dev, 0);
+
+ return ret;
+}
+
+/*
+ * Generate plain text random data to some memory location using
+ * SE/SE2's SP800-90 random number generator. The random data size
+ * must be some multiple of the AES block size (16 bytes).
+ */
+static int tegra_se_lp_generate_random_data(tegra_se_dev_t *se_dev)
+{
+ int ret = 0;
+ uint32_t val;
+
+ /* Set some arbitrary memory location to store the random data */
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ if (!se_dev->ctx_save_buf) {
+ ERROR("%s: ERR: context save buffer NULL pointer!\n", __func__);
+ return PSCI_E_NOT_PRESENT;
+ }
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(((tegra_se_context_t *)
+ se_dev->ctx_save_buf)->rand_data)));
+ se_dev->dst_ll_buf->buffer[0].data_len = SE_CTX_SAVE_RANDOM_DATA_SIZE;
+
+
+ /* Confgure the following hardware register settings:
+ * SE_CONFIG.DEC_ALG = NOP
+ * SE_CONFIG.ENC_ALG = RNG
+ * SE_CONFIG.ENC_MODE = KEY192
+ * SE_CONFIG.DST = MEMORY
+ */
+ val = (SE_CONFIG_ENC_ALG_RNG |
+ SE_CONFIG_DEC_ALG_NOP |
+ SE_CONFIG_ENC_MODE_KEY192 |
+ SE_CONFIG_DST_MEMORY);
+ tegra_se_write_32(se_dev, SE_CONFIG_REG_OFFSET, val);
+
+ /* Program the RNG options in SE_CRYPTO_CONFIG as follows:
+ * XOR_POS = BYPASS
+ * INPUT_SEL = RANDOM (Entropy or LFSR)
+ * HASH_ENB = DISABLE
+ */
+ val = (SE_CRYPTO_INPUT_RANDOM |
+ SE_CRYPTO_XOR_BYPASS |
+ SE_CRYPTO_CORE_ENCRYPT |
+ SE_CRYPTO_HASH_DISABLE |
+ SE_CRYPTO_KEY_INDEX(RNG_AES_KEY_INDEX) |
+ SE_CRYPTO_IV_ORIGINAL);
+ tegra_se_write_32(se_dev, SE_CRYPTO_REG_OFFSET, val);
+
+ /* Configure RNG */
+ if (ecid_valid)
+ val = (DRBG_MODE_FORCE_INSTANTION | DRBG_SRC_LFSR);
+ else
+ val = (DRBG_MODE_FORCE_RESEED | DRBG_SRC_LFSR);
+ tegra_se_write_32(se_dev, SE_RNG_CONFIG_REG_OFFSET, val);
+
+ /* SE normal operation */
+ ret = tegra_se_start_normal_operation(se_dev, SE_CTX_SAVE_RANDOM_DATA_SIZE);
+
+ return ret;
+}
+
+/*
+ * Encrypt memory blocks with SRK as part of the security engine context.
+ * The data blocks include: random data and the known pattern data, where
+ * the random data is the first block and known pattern is the last block.
+ */
+static int tegra_se_lp_data_context_save(tegra_se_dev_t *se_dev,
+ uint64_t src_addr, uint64_t dst_addr, uint32_t data_size)
+{
+ int ret = 0;
+
+ se_dev->src_ll_buf->last_buff_num = 0;
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ se_dev->src_ll_buf->buffer[0].addr = src_addr;
+ se_dev->src_ll_buf->buffer[0].data_len = data_size;
+ se_dev->dst_ll_buf->buffer[0].addr = dst_addr;
+ se_dev->dst_ll_buf->buffer[0].data_len = data_size;
+
+ /* By setting the context source from memory and calling the context save
+ * operation, the SE encrypts the memory data with SRK.
+ */
+ tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, SE_CTX_SAVE_SRC_MEM);
+
+ ret = tegra_se_start_ctx_save_operation(se_dev, data_size);
+
+ return ret;
+}
+
+/*
+ * Context save the key table access control sticky bits and
+ * security status of each key-slot. The encrypted sticky-bits are
+ * 32 bytes (2 AES blocks) and formatted as the following structure:
+ * { bit in registers bit in context save
+ * SECURITY_0[4] 158
+ * SE_RSA_KEYTABLE_ACCE4SS_1[2:0] 157:155
+ * SE_RSA_KEYTABLE_ACCE4SS_0[2:0] 154:152
+ * SE_RSA_SECURITY_PERKEY_0[1:0] 151:150
+ * SE_CRYPTO_KEYTABLE_ACCESS_15[7:0] 149:142
+ * ...,
+ * SE_CRYPTO_KEYTABLE_ACCESS_0[7:0] 29:22
+ * SE_CRYPTO_SECURITY_PERKEY_0[15:0] 21:6
+ * SE_TZRAM_SECURITY_0[1:0] 5:4
+ * SE_SECURITY_0[16] 3:3
+ * SE_SECURITY_0[2:0] } 2:0
+ */
+static int tegra_se_lp_sticky_bits_context_save(tegra_se_dev_t *se_dev)
+{
+ int ret = PSCI_E_INTERN_FAIL;
+ uint32_t val = 0;
+
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ if (!se_dev->ctx_save_buf) {
+ ERROR("%s: ERR: context save buffer NULL pointer!\n", __func__);
+ return PSCI_E_NOT_PRESENT;
+ }
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(((tegra_se_context_t *)
+ se_dev->ctx_save_buf)->sticky_bits)));
+ se_dev->dst_ll_buf->buffer[0].data_len = SE_CTX_SAVE_STICKY_BITS_SIZE;
+
+ /*
+ * The 1st AES block save the sticky-bits context 1 - 16 bytes (0 - 3 words).
+ * The 2nd AES block save the sticky-bits context 17 - 32 bytes (4 - 7 words).
+ */
+ for (int i = 0; i < 2; i++) {
+ val = SE_CTX_SAVE_SRC_STICKY_BITS |
+ SE_CTX_SAVE_STICKY_WORD_QUAD(i);
+ tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val);
+
+ /* SE context save operation */
+ ret = tegra_se_start_ctx_save_operation(se_dev,
+ SE_CTX_SAVE_STICKY_BITS_SIZE);
+ if (ret)
+ break;
+ se_dev->dst_ll_buf->buffer[0].addr += SE_CTX_SAVE_STICKY_BITS_SIZE;
+ }
+
+ return ret;
+}
+
+static int tegra_se_aeskeytable_context_save(tegra_se_dev_t *se_dev)
+{
+ uint32_t val = 0;
+ int ret = 0;
+
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ if (!se_dev->ctx_save_buf) {
+ ERROR("%s: ERR: context save buffer NULL pointer!\n", __func__);
+ ret = -EINVAL;
+ goto aes_keytable_save_err;
+ }
+
+ /* AES key context save */
+ for (int slot = 0; slot < TEGRA_SE_AES_KEYSLOT_COUNT; slot++) {
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(
+ ((tegra_se_context_t *)se_dev->
+ ctx_save_buf)->key_slots[slot].key)));
+ se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_KEY_128_SIZE;
+ for (int i = 0; i < 2; i++) {
+ val = SE_CTX_SAVE_SRC_AES_KEYTABLE |
+ SE_CTX_SAVE_KEY_INDEX(slot) |
+ SE_CTX_SAVE_WORD_QUAD(i);
+ tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val);
+
+ /* SE context save operation */
+ ret = tegra_se_start_ctx_save_operation(se_dev,
+ TEGRA_SE_KEY_128_SIZE);
+ if (ret) {
+ ERROR("%s: ERR: AES key CTX_SAVE OP failed, "
+ "slot=%d, word_quad=%d.\n",
+ __func__, slot, i);
+ goto aes_keytable_save_err;
+ }
+ se_dev->dst_ll_buf->buffer[0].addr += TEGRA_SE_KEY_128_SIZE;
+ }
+
+ /* OIV context save */
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(
+ ((tegra_se_context_t *)se_dev->
+ ctx_save_buf)->key_slots[slot].oiv)));
+ se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_AES_IV_SIZE;
+
+ val = SE_CTX_SAVE_SRC_AES_KEYTABLE |
+ SE_CTX_SAVE_KEY_INDEX(slot) |
+ SE_CTX_SAVE_WORD_QUAD_ORIG_IV;
+ tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val);
+
+ /* SE context save operation */
+ ret = tegra_se_start_ctx_save_operation(se_dev, TEGRA_SE_AES_IV_SIZE);
+ if (ret) {
+ ERROR("%s: ERR: OIV CTX_SAVE OP failed, slot=%d.\n",
+ __func__, slot);
+ goto aes_keytable_save_err;
+ }
+
+ /* UIV context save */
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(
+ ((tegra_se_context_t *)se_dev->
+ ctx_save_buf)->key_slots[slot].uiv)));
+ se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_AES_IV_SIZE;
+
+ val = SE_CTX_SAVE_SRC_AES_KEYTABLE |
+ SE_CTX_SAVE_KEY_INDEX(slot) |
+ SE_CTX_SAVE_WORD_QUAD_UPD_IV;
+ tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET, val);
+
+ /* SE context save operation */
+ ret = tegra_se_start_ctx_save_operation(se_dev, TEGRA_SE_AES_IV_SIZE);
+ if (ret) {
+ ERROR("%s: ERR: UIV CTX_SAVE OP failed, slot=%d\n",
+ __func__, slot);
+ goto aes_keytable_save_err;
+ }
+ }
+
+aes_keytable_save_err:
+ return ret;
+}
+
+static int tegra_se_lp_rsakeytable_context_save(tegra_se_dev_t *se_dev)
+{
+ uint32_t val = 0;
+ int ret = 0;
+ /* For T210, First the modulus and then exponent must be
+ * encrypted and saved. This is repeated for SLOT 0
+ * and SLOT 1. Hence the order:
+ * SLOT 0 modulus : RSA_KEY_INDEX : 1
+ * SLOT 0 exponent : RSA_KEY_INDEX : 0
+ * SLOT 1 modulus : RSA_KEY_INDEX : 3
+ * SLOT 1 exponent : RSA_KEY_INDEX : 2
+ */
+ const unsigned int key_index_mod[TEGRA_SE_RSA_KEYSLOT_COUNT][2] = {
+ /* RSA key slot 0 */
+ {SE_RSA_KEY_INDEX_SLOT0_MOD, SE_RSA_KEY_INDEX_SLOT0_EXP},
+ /* RSA key slot 1 */
+ {SE_RSA_KEY_INDEX_SLOT1_MOD, SE_RSA_KEY_INDEX_SLOT1_EXP},
+ };
+
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(
+ ((tegra_se_context_t *)se_dev->
+ ctx_save_buf)->rsa_keys)));
+ se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_KEY_128_SIZE;
+
+ for (int slot = 0; slot < TEGRA_SE_RSA_KEYSLOT_COUNT; slot++) {
+ /* loop for modulus and exponent */
+ for (int index = 0; index < 2; index++) {
+ for (int word_quad = 0; word_quad < 16; word_quad++) {
+ val = SE_CTX_SAVE_SRC_RSA_KEYTABLE |
+ SE_CTX_SAVE_RSA_KEY_INDEX(
+ key_index_mod[slot][index]) |
+ SE_CTX_RSA_WORD_QUAD(word_quad);
+ tegra_se_write_32(se_dev,
+ SE_CTX_SAVE_CONFIG_REG_OFFSET, val);
+
+ /* SE context save operation */
+ ret = tegra_se_start_ctx_save_operation(se_dev,
+ TEGRA_SE_KEY_128_SIZE);
+ if (ret) {
+ ERROR("%s: ERR: slot=%d.\n",
+ __func__, slot);
+ goto rsa_keytable_save_err;
+ }
+
+ /* Update the pointer to the next word quad */
+ se_dev->dst_ll_buf->buffer[0].addr +=
+ TEGRA_SE_KEY_128_SIZE;
+ }
+ }
+ }
+
+rsa_keytable_save_err:
+ return ret;
+}
+
+static int tegra_se_pkakeytable_sticky_bits_save(tegra_se_dev_t *se_dev)
+{
+ int ret = 0;
+
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(
+ ((tegra_se2_context_blob_t *)se_dev->
+ ctx_save_buf)->pka_ctx.sticky_bits)));
+ se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_AES_BLOCK_SIZE;
+
+ /* PKA1 sticky bits are 1 AES block (16 bytes) */
+ tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET,
+ SE_CTX_SAVE_SRC_PKA1_STICKY_BITS |
+ SE_CTX_STICKY_WORD_QUAD_WORDS_0_3);
+
+ /* SE context save operation */
+ ret = tegra_se_start_ctx_save_operation(se_dev, 0);
+ if (ret) {
+ ERROR("%s: ERR: PKA1 sticky bits CTX_SAVE OP failed\n",
+ __func__);
+ goto pka_sticky_bits_save_err;
+ }
+
+pka_sticky_bits_save_err:
+ return ret;
+}
+
+static int tegra_se_pkakeytable_context_save(tegra_se_dev_t *se_dev)
+{
+ uint32_t val = 0;
+ int ret = 0;
+
+ se_dev->dst_ll_buf->last_buff_num = 0;
+ se_dev->dst_ll_buf->buffer[0].addr = ((uint64_t)(&(
+ ((tegra_se2_context_blob_t *)se_dev->
+ ctx_save_buf)->pka_ctx.pka_keys)));
+ se_dev->dst_ll_buf->buffer[0].data_len = TEGRA_SE_KEY_128_SIZE;
+
+ /* for each slot, save word quad 0-127 */
+ for (int slot = 0; slot < TEGRA_SE_PKA1_KEYSLOT_COUNT; slot++) {
+ for (int word_quad = 0; word_quad < 512/4; word_quad++) {
+ val = SE_CTX_SAVE_SRC_PKA1_KEYTABLE |
+ SE_CTX_PKA1_WORD_QUAD_L((slot * 128) +
+ word_quad) |
+ SE_CTX_PKA1_WORD_QUAD_H((slot * 128) +
+ word_quad);
+ tegra_se_write_32(se_dev,
+ SE_CTX_SAVE_CONFIG_REG_OFFSET, val);
+
+ /* SE context save operation */
+ ret = tegra_se_start_ctx_save_operation(se_dev,
+ TEGRA_SE_KEY_128_SIZE);
+ if (ret) {
+ ERROR("%s: ERR: pka1 keytable ctx save error\n",
+ __func__);
+ goto pka_keytable_save_err;
+ }
+
+ /* Update the pointer to the next word quad */
+ se_dev->dst_ll_buf->buffer[0].addr +=
+ TEGRA_SE_KEY_128_SIZE;
+ }
+ }
+
+pka_keytable_save_err:
+ return ret;
+}
+
+static int tegra_se_save_SRK(tegra_se_dev_t *se_dev)
+{
+ tegra_se_write_32(se_dev, SE_CTX_SAVE_CONFIG_REG_OFFSET,
+ SE_CTX_SAVE_SRC_SRK);
+
+ /* SE context save operation */
+ return tegra_se_start_ctx_save_operation(se_dev, 0);
+}
+
+/*
+ * Lock both SE from non-TZ clients.
+ */
+static inline void tegra_se_lock(tegra_se_dev_t *se_dev)
+{
+ uint32_t val;
+
+ assert(se_dev);
+ val = tegra_se_read_32(se_dev, SE_SECURITY_REG_OFFSET);
+ val |= SE_SECURITY_TZ_LOCK_SOFT(SE_SECURE);
+ tegra_se_write_32(se_dev, SE_SECURITY_REG_OFFSET, val);
+}
+
+/*
+ * Use SRK to encrypt SE state and save to TZRAM carveout
+ */
+static int tegra_se_context_save_sw(tegra_se_dev_t *se_dev)
+{
+ int err = 0;
+
+ assert(se_dev);
+
+ /* Lock entire SE/SE2 as TZ protected */
+ tegra_se_lock(se_dev);
+
+ INFO("%s: generate SRK\n", __func__);
+ /* Generate SRK */
+ err = tegra_se_generate_srk(se_dev);
+ if (err) {
+ ERROR("%s: ERR: SRK generation failed\n", __func__);
+ return err;
+ }
+
+ INFO("%s: generate random data\n", __func__);
+ /* Generate random data */
+ err = tegra_se_lp_generate_random_data(se_dev);
+ if (err) {
+ ERROR("%s: ERR: LP random pattern generation failed\n", __func__);
+ return err;
+ }
+
+ INFO("%s: encrypt random data\n", __func__);
+ /* Encrypt the random data block */
+ err = tegra_se_lp_data_context_save(se_dev,
+ ((uint64_t)(&(((tegra_se_context_t *)se_dev->
+ ctx_save_buf)->rand_data))),
+ ((uint64_t)(&(((tegra_se_context_t *)se_dev->
+ ctx_save_buf)->rand_data))),
+ SE_CTX_SAVE_RANDOM_DATA_SIZE);
+ if (err) {
+ ERROR("%s: ERR: random pattern encryption failed\n", __func__);
+ return err;
+ }
+
+ INFO("%s: save SE sticky bits\n", __func__);
+ /* Save AES sticky bits context */
+ err = tegra_se_lp_sticky_bits_context_save(se_dev);
+ if (err) {
+ ERROR("%s: ERR: sticky bits context save failed\n", __func__);
+ return err;
+ }
+
+ INFO("%s: save AES keytables\n", __func__);
+ /* Save AES key table context */
+ err = tegra_se_aeskeytable_context_save(se_dev);
+ if (err) {
+ ERROR("%s: ERR: LP keytable save failed\n", __func__);
+ return err;
+ }
+
+ /* RSA key slot table context save */
+ INFO("%s: save RSA keytables\n", __func__);
+ err = tegra_se_lp_rsakeytable_context_save(se_dev);
+ if (err) {
+ ERROR("%s: ERR: rsa key table context save failed\n", __func__);
+ return err;
+ }
+
+ /* Only SE2 has an interface with PKA1; thus, PKA1's context is saved
+ * via SE2.
+ */
+ if (se_dev->se_num == 2) {
+ /* Encrypt PKA1 sticky bits on SE2 only */
+ INFO("%s: save PKA sticky bits\n", __func__);
+ err = tegra_se_pkakeytable_sticky_bits_save(se_dev);
+ if (err) {
+ ERROR("%s: ERR: PKA sticky bits context save failed\n", __func__);
+ return err;
+ }
+
+ /* Encrypt PKA1 keyslots on SE2 only */
+ INFO("%s: save PKA keytables\n", __func__);
+ err = tegra_se_pkakeytable_context_save(se_dev);
+ if (err) {
+ ERROR("%s: ERR: PKA key table context save failed\n", __func__);
+ return err;
+ }
+ }
+
+ /* Encrypt known pattern */
+ if (se_dev->se_num == 1) {
+ err = tegra_se_lp_data_context_save(se_dev,
+ ((uint64_t)(&se_ctx_known_pattern_data)),
+ ((uint64_t)(&(((tegra_se_context_blob_t *)se_dev->ctx_save_buf)->known_pattern))),
+ SE_CTX_KNOWN_PATTERN_SIZE);
+ } else if (se_dev->se_num == 2) {
+ err = tegra_se_lp_data_context_save(se_dev,
+ ((uint64_t)(&se_ctx_known_pattern_data)),
+ ((uint64_t)(&(((tegra_se2_context_blob_t *)se_dev->ctx_save_buf)->known_pattern))),
+ SE_CTX_KNOWN_PATTERN_SIZE);
+ }
+ if (err) {
+ ERROR("%s: ERR: save LP known pattern failure\n", __func__);
+ return err;
+ }
+
+ /* Write lp context buffer address into PMC scratch register */
+ if (se_dev->se_num == 1) {
+ /* SE context address, support T210 only */
+ mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SCRATCH43_REG_OFFSET,
+ ((uint64_t)(se_dev->ctx_save_buf)));
+ } else if (se_dev->se_num == 2) {
+ /* SE2 & PKA1 context address */
+ mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SECURE_SCRATCH116_OFFSET,
+ ((uint64_t)(se_dev->ctx_save_buf)));
+ }
+
+ /* Saves SRK to PMC secure scratch registers for BootROM, which
+ * verifies and restores the security engine context on warm boot.
+ */
+ err = tegra_se_save_SRK(se_dev);
+ if (err < 0) {
+ ERROR("%s: ERR: LP SRK save failure\n", __func__);
+ return err;
+ }
+
+ INFO("%s: SE context save done \n", __func__);
+
+ return err;
+}
+
+/*
+ * Initialize the SE engine handle
+ */
+void tegra_se_init(void)
+{
+ uint32_t val = 0;
+ INFO("%s: start SE init\n", __func__);
+
+ /* Generate random SRK to initialize DRBG */
+ tegra_se_generate_srk(&se_dev_1);
+
+ if (tegra_chipid_is_t210_b01()) {
+ tegra_se_generate_srk(&se_dev_2);
+ }
+
+ /* determine if ECID is valid */
+ val = mmio_read_32(TEGRA_FUSE_BASE + FUSE_JTAG_SECUREID_VALID);
+ ecid_valid = (val == ECID_VALID);
+
+ INFO("%s: SE init done\n", __func__);
+}
+
+static void tegra_se_enable_clocks(void)
+{
+ uint32_t val = 0;
+
+ /* Enable entropy clock */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W);
+ val |= ENTROPY_CLK_ENB_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W, val);
+
+ /* De-Assert Entropy Reset */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W);
+ val &= ~ENTROPY_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W, val);
+
+ /*
+ * Switch SE clock source to CLK_M, to make sure SE clock
+ * is on when saving SE context
+ */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_RST_CTL_CLK_SRC_SE,
+ SE_CLK_SRC_CLK_M);
+
+ /* Enable SE clock */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V);
+ val |= SE_CLK_ENB_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V, val);
+
+ /* De-Assert SE Reset */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_V);
+ val &= ~SE_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_V, val);
+}
+
+static void tegra_se_disable_clocks(void)
+{
+ uint32_t val = 0;
+
+ /* Disable entropy clock */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W);
+ val &= ~ENTROPY_CLK_ENB_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_W, val);
+
+ /* Disable SE clock */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V);
+ val &= ~SE_CLK_ENB_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V, val);
+}
+
+/*
+ * Security engine power suspend entry point.
+ * This function is invoked from PSCI power domain suspend handler.
+ */
+int32_t tegra_se_suspend(void)
+{
+ int32_t ret = 0;
+ uint32_t val = 0;
+
+ /* SE does not use SMMU in EL3, disable SMMU.
+ * This will be re-enabled by kernel on resume */
+ val = mmio_read_32(TEGRA_MC_BASE + MC_SMMU_PPCS_ASID_0);
+ val &= ~PPCS_SMMU_ENABLE;
+ mmio_write_32(TEGRA_MC_BASE + MC_SMMU_PPCS_ASID_0, val);
+
+ tegra_se_enable_clocks();
+
+ if (tegra_chipid_is_t210_b01()) {
+ /* It is T210 B01, Atomic context save se2 and pka1 */
+ INFO("%s: SE2/PKA1 atomic context save\n", __func__);
+ ret = tegra_se_context_save_atomic(&se_dev_2);
+ if (ret != 0) {
+ ERROR("%s: SE2 ctx save failed (%d)\n", __func__, ret);
+ }
+
+ ret = tegra_se_context_save_atomic(&se_dev_1);
+ if (ret != 0) {
+ ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
+ }
+ } else {
+ /* It is T210, SW context save se */
+ INFO("%s: SE1 legacy(SW) context save\n", __func__);
+ ret = tegra_se_context_save_sw(&se_dev_1);
+ if (ret != 0) {
+ ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
+ }
+ }
+
+ tegra_se_disable_clocks();
+
+ return ret;
+}
+
+/*
+ * Save TZRAM to shadow TZRAM in AON
+ */
+int32_t tegra_se_save_tzram(void)
+{
+ uint32_t val = 0;
+ int32_t ret = 0;
+ uint32_t timeout;
+
+ INFO("%s: SE TZRAM save start\n", __func__);
+ tegra_se_enable_clocks();
+
+ val = (SE_TZRAM_OP_REQ_INIT | SE_TZRAM_OP_MODE_SAVE);
+ tegra_se_write_32(&se_dev_1, SE_TZRAM_OPERATION, val);
+
+ val = tegra_se_read_32(&se_dev_1, SE_TZRAM_OPERATION);
+ for (timeout = 0; (SE_TZRAM_OP_BUSY(val) == SE_TZRAM_OP_BUSY_ON) &&
+ (timeout < TIMEOUT_100MS); timeout++) {
+ mdelay(1);
+ val = tegra_se_read_32(&se_dev_1, SE_TZRAM_OPERATION);
+ }
+
+ if (timeout == TIMEOUT_100MS) {
+ ERROR("%s: ERR: TZRAM save timeout!\n", __func__);
+ ret = -ETIMEDOUT;
+ }
+
+ if (ret == 0) {
+ INFO("%s: SE TZRAM save done!\n", __func__);
+ }
+
+ tegra_se_disable_clocks();
+
+ return ret;
+}
+
+/*
+ * The function is invoked by SE resume
+ */
+static void tegra_se_warm_boot_resume(const tegra_se_dev_t *se_dev)
+{
+ uint32_t val;
+
+ assert(se_dev);
+
+ /* Lock RNG source to ENTROPY on resume */
+ val = DRBG_RO_ENT_IGNORE_MEM_ENABLE |
+ DRBG_RO_ENT_SRC_LOCK_ENABLE |
+ DRBG_RO_ENT_SRC_ENABLE;
+ tegra_se_write_32(se_dev, SE_RNG_SRC_CONFIG_REG_OFFSET, val);
+
+ /* Set a random value to SRK to initialize DRBG */
+ tegra_se_generate_srk(se_dev);
+}
+
+/*
+ * The function is invoked on SC7 resume
+ */
+void tegra_se_resume(void)
+{
+ tegra_se_warm_boot_resume(&se_dev_1);
+
+ if (tegra_chipid_is_t210_b01()) {
+ tegra_se_warm_boot_resume(&se_dev_2);
+ }
+}
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
new file mode 100644
index 0000000..7f73ea5
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <cortex_a57.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <bpmp.h>
+#include <flowctrl.h>
+#include <lib/utils.h>
+#include <memctrl.h>
+#include <pmc.h>
+#include <platform_def.h>
+#include <security_engine.h>
+#include <tegra_def.h>
+#include <tegra_private.h>
+#include <tegra_platform.h>
+
+/*
+ * Register used to clear CPU reset signals. Each CPU has two reset
+ * signals: CPU reset (3:0) and Core reset (19:16).
+ */
+#define CPU_CMPLX_RESET_CLR 0x454
+#define CPU_CORE_RESET_MASK 0x10001
+
+/* Clock and Reset controller registers for system clock's settings */
+#define SCLK_RATE 0x30
+#define SCLK_BURST_POLICY 0x28
+#define SCLK_BURST_POLICY_DEFAULT 0x10000000
+
+static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
+static bool tegra_bpmp_available = true;
+
+int32_t tegra_soc_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int state_id = psci_get_pstate_id(power_state);
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+
+ /* Sanity check the requested state id */
+ switch (state_id) {
+ case PSTATE_ID_CORE_POWERDN:
+ /*
+ * Core powerdown request only for afflvl 0
+ */
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id & 0xff;
+
+ break;
+
+ case PSTATE_ID_CLUSTER_IDLE:
+
+ /*
+ * Cluster idle request for afflvl 0
+ */
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN;
+ req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
+ break;
+
+ case PSTATE_ID_SOC_POWERDN:
+
+ /*
+ * sc7entry-fw must be present in the system when the bpmp
+ * firmware is not present, for a successful System Suspend
+ * entry.
+ */
+ if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base)
+ return PSCI_E_NOT_SUPPORTED;
+
+ /*
+ * System powerdown request only for afflvl 2
+ */
+ for (uint32_t i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] =
+ PLAT_SYS_SUSPEND_STATE_ID;
+
+ break;
+
+ default:
+ ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler to calculate the proper target power level at the
+ * specified affinity level.
+ ******************************************************************************/
+plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
+ const plat_local_state_t *states,
+ unsigned int ncpu)
+{
+ plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
+ int cpu = plat_my_core_pos();
+ int core_pos = read_mpidr() & MPIDR_CPU_MASK;
+ uint32_t bpmp_reply, data[3], val;
+ int ret;
+
+ /* get the power state at this level */
+ if (lvl == MPIDR_AFFLVL1)
+ target = *(states + core_pos);
+ if (lvl == MPIDR_AFFLVL2)
+ target = *(states + cpu);
+
+ if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_IDLE)) {
+
+ /* initialize the bpmp interface */
+ ret = tegra_bpmp_init();
+ if (ret != 0U) {
+
+ /*
+ * flag to indicate that BPMP firmware is not
+ * available and the CPU has to handle entry/exit
+ * for all power states
+ */
+ tegra_bpmp_available = false;
+
+ /* Cluster idle not allowed */
+ target = PSCI_LOCAL_STATE_RUN;
+
+ /*******************************************
+ * BPMP is not present, so handle CC6 entry
+ * from the CPU
+ ******************************************/
+
+ /* check if cluster idle state has been enabled */
+ val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL);
+ if (val == ENABLE_CLOSED_LOOP) {
+ /*
+ * Acquire the cluster idle lock to stop
+ * other CPUs from powering up.
+ */
+ tegra_fc_ccplex_pgexit_lock();
+
+ /* Cluster idle only from the last standing CPU */
+ if (tegra_pmc_is_last_on_cpu() && tegra_fc_is_ccx_allowed()) {
+ /* Cluster idle allowed */
+ target = PSTATE_ID_CLUSTER_IDLE;
+ } else {
+ /* release cluster idle lock */
+ tegra_fc_ccplex_pgexit_unlock();
+ }
+ }
+ } else {
+
+ /* Cluster power-down */
+ data[0] = (uint32_t)cpu;
+ data[1] = TEGRA_PM_CC6;
+ data[2] = TEGRA_PM_SC1;
+ ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE,
+ (void *)&data, (int)sizeof(data),
+ (void *)&bpmp_reply,
+ (int)sizeof(bpmp_reply));
+
+ /* check if cluster power down is allowed */
+ if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) {
+
+ /* Cluster power down not allowed */
+ target = PSCI_LOCAL_STATE_RUN;
+ }
+ }
+
+ } else if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) &&
+ (target == PSTATE_ID_SOC_POWERDN)) {
+
+ /* System Suspend */
+ target = PSTATE_ID_SOC_POWERDN;
+
+ } else {
+ ; /* do nothing */
+ }
+
+ return target;
+}
+
+int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
+{
+ (void)cpu_state;
+ return PSCI_E_SUCCESS;
+}
+
+int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr();
+ const plat_local_state_t *pwr_domain_state =
+ target_state->pwr_domain_state;
+ unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2];
+ unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1];
+ unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0];
+ uint32_t cfg;
+ int ret = PSCI_E_SUCCESS;
+ uint32_t val;
+
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+ assert((stateid_afflvl0 == PLAT_MAX_OFF_STATE) ||
+ (stateid_afflvl0 == PSTATE_ID_SOC_POWERDN));
+ assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) ||
+ (stateid_afflvl1 == PSTATE_ID_SOC_POWERDN));
+
+ /* Suspend se/se2 and pka1 for T210 B01 and se for T210 */
+ if (tegra_se_suspend() != 0) {
+ ret = PSCI_E_INTERN_FAIL;
+ }
+
+ } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
+
+ assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
+
+ if (!tegra_bpmp_available) {
+
+ /*
+ * When disabled, DFLL loses its state. Enable
+ * open loop state for the DFLL as we dont want
+ * garbage values being written to the pmic
+ * when we enter cluster idle state.
+ */
+ mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
+ ENABLE_OPEN_LOOP);
+
+ /* Find if the platform uses OVR2/MAX77621 PMIC */
+ cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
+ if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
+ /* OVR2 */
+
+ /* PWM tristate */
+ val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
+ val |= PINMUX_PWM_TRISTATE;
+ mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
+
+ /*
+ * SCRATCH201[1] is being used to identify CPU
+ * PMIC in warmboot code.
+ * 0 : OVR2
+ * 1 : MAX77621
+ */
+ tegra_pmc_write_32(PMC_SCRATCH201, 0x0);
+ } else {
+ /* MAX77621 */
+ tegra_pmc_write_32(PMC_SCRATCH201, 0x2);
+ }
+ }
+
+ /* Prepare for cluster idle */
+ tegra_fc_cluster_idle(mpidr);
+
+ } else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
+
+ /* Prepare for cpu powerdn */
+ tegra_fc_cpu_powerdn(mpidr);
+
+ } else {
+ ERROR("%s: Unknown state id (%d, %d, %d)\n", __func__,
+ stateid_afflvl2, stateid_afflvl1, stateid_afflvl0);
+ ret = PSCI_E_NOT_SUPPORTED;
+ }
+
+ return ret;
+}
+
+static void tegra_reset_all_dma_masters(void)
+{
+ uint32_t val, mask;
+
+ /*
+ * Reset all possible DMA masters in the system.
+ */
+ val = GPU_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET, val);
+
+ val = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
+ NVJPG_RESET_BIT | NVDEC_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y, val);
+
+ val = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
+ VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
+ SDMMC2_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L, val);
+
+ val = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H, val);
+
+ val = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
+ PCIE_RESET_BIT | SDMMC3_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U, val);
+
+ val = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V, val);
+
+ /*
+ * If any of the DMA masters are still alive, assume
+ * that the system has been compromised and reboot.
+ */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET);
+ mask = GPU_RESET_BIT;
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
+ NVJPG_RESET_BIT | NVDEC_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
+ VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
+ SDMMC2_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
+ PCIE_RESET_BIT | SDMMC3_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V);
+ mask = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+}
+
+int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr();
+ const plat_local_state_t *pwr_domain_state =
+ target_state->pwr_domain_state;
+ unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL];
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+ uint32_t val;
+
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+ if (tegra_chipid_is_t210_b01()) {
+ /* Save tzram contents */
+ tegra_se_save_tzram();
+ }
+
+ /* de-init the interface */
+ tegra_bpmp_suspend();
+
+ /*
+ * The CPU needs to load the System suspend entry firmware
+ * if nothing is running on the BPMP.
+ */
+ if (!tegra_bpmp_available) {
+
+ /*
+ * BPMP firmware is not running on the co-processor, so
+ * we need to explicitly load the firmware to enable
+ * entry/exit to/from System Suspend and set the BPMP
+ * on its way.
+ */
+
+ /* Power off BPMP before we proceed */
+ tegra_fc_bpmp_off();
+
+ /* bond out IRAM banks B, C and D */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_U,
+ IRAM_B_LOCK_BIT | IRAM_C_LOCK_BIT |
+ IRAM_D_LOCK_BIT);
+
+ /* bond out APB/AHB DMAs */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_H,
+ APB_DMA_LOCK_BIT | AHB_DMA_LOCK_BIT);
+
+ /* Power off BPMP before we proceed */
+ tegra_fc_bpmp_off();
+
+ /*
+ * Reset all the hardware blocks that can act as DMA
+ * masters on the bus.
+ */
+ tegra_reset_all_dma_masters();
+
+ /*
+ * Mark PMC as accessible to the non-secure world
+ * to allow the COP to execute System Suspend
+ * sequence
+ */
+ val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+ val &= ~PMC_SECURITY_EN_BIT;
+ mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+
+ /* clean up IRAM of any cruft */
+ zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE,
+ TEGRA_IRAM_A_SIZE);
+
+ /* Copy the firmware to BPMP's internal RAM */
+ (void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE,
+ (const void *)(plat_params->sc7entry_fw_base + SC7ENTRY_FW_HEADER_SIZE_BYTES),
+ plat_params->sc7entry_fw_size - SC7ENTRY_FW_HEADER_SIZE_BYTES);
+
+ /* Power on the BPMP and execute from IRAM base */
+ tegra_fc_bpmp_on(TEGRA_IRAM_BASE);
+
+ /* Wait until BPMP powers up */
+ do {
+ val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
+ } while (val != SIGN_OF_LIFE);
+ }
+
+ /* enter system suspend */
+ tegra_fc_soc_powerdn(mpidr);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+ uint32_t cfg;
+ uint32_t val, entrypoint = 0;
+ uint64_t offset;
+
+ /* platform parameter passed by the previous bootloader */
+ if (plat_params->l2_ecc_parity_prot_dis != 1) {
+ /* Enable ECC Parity Protection for Cortex-A57 CPUs */
+ val = read_l2ctlr_el1();
+ val |= (uint64_t)CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
+ write_l2ctlr_el1(val);
+ }
+
+ /*
+ * Check if we are exiting from SOC_POWERDN.
+ */
+ if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
+ PLAT_SYS_SUSPEND_STATE_ID) {
+
+ /*
+ * Security engine resume
+ */
+ if (tegra_chipid_is_t210_b01()) {
+ tegra_se_resume();
+ }
+
+ /*
+ * Lock scratch registers which hold the CPU vectors
+ */
+ tegra_pmc_lock_cpu_vectors();
+
+ /*
+ * Enable WRAP to INCR burst type conversions for
+ * incoming requests on the AXI slave ports.
+ */
+ val = mmio_read_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG);
+ val &= ~ENABLE_UNSUP_TX_ERRORS;
+ val |= ENABLE_WRAP_TO_INCR_BURSTS;
+ mmio_write_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG, val);
+
+ /*
+ * Restore Boot and Power Management Processor (BPMP) reset
+ * address and reset it, if it is supported by the platform.
+ */
+ if (!tegra_bpmp_available) {
+ tegra_fc_bpmp_off();
+ } else {
+ entrypoint = tegra_pmc_read_32(PMC_SCRATCH39);
+ tegra_fc_bpmp_on(entrypoint);
+
+ /* initialise the interface */
+ tegra_bpmp_resume();
+ }
+
+ if (plat_params->sc7entry_fw_base != 0U) {
+ /* sc7entry-fw is part of TZDRAM area */
+ offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base;
+ tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base,
+ plat_params->tzdram_size + offset);
+ }
+
+ if (!tegra_chipid_is_t210_b01()) {
+ /* restrict PMC access to secure world */
+ val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+ val |= PMC_SECURITY_EN_BIT;
+ mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+ }
+ }
+
+ /*
+ * Check if we are exiting cluster idle state
+ */
+ if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
+ PSTATE_ID_CLUSTER_IDLE) {
+
+ if (!tegra_bpmp_available) {
+
+ /* PWM un-tristate */
+ cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG);
+ if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) {
+ val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
+ val &= ~PINMUX_PWM_TRISTATE;
+ mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val);
+
+ /* make sure the setting took effect */
+ val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM);
+ assert((val & PINMUX_PWM_TRISTATE) == 0U);
+ }
+
+ /*
+ * Restore operation mode for the DFLL ring
+ * oscillator
+ */
+ mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL,
+ ENABLE_CLOSED_LOOP);
+
+ /* release cluster idle lock */
+ tegra_fc_ccplex_pgexit_unlock();
+ }
+ }
+
+ /*
+ * Mark this CPU as ON in the cpu_powergate_mask[],
+ * so that we use Flow Controller for all subsequent
+ * power ups.
+ */
+ cpu_powergate_mask[plat_my_core_pos()] = 1;
+
+ /*
+ * T210 has a dedicated ARMv7 boot and power mgmt processor, BPMP. It's
+ * used for power management and boot purposes. Inform the BPMP that
+ * we have completed the cluster power up.
+ */
+ tegra_fc_lock_active_cluster();
+
+ /*
+ * Resume PMC hardware block for Tegra210 platforms
+ */
+ if (!tegra_chipid_is_t210_b01()) {
+ tegra_pmc_resume();
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int tegra_soc_pwr_domain_on(u_register_t mpidr)
+{
+ int cpu = mpidr & MPIDR_CPU_MASK;
+ uint32_t mask = CPU_CORE_RESET_MASK << cpu;
+
+ /* Deassert CPU reset signals */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask);
+
+ /* Turn on CPU using flow controller or PMC */
+ if (cpu_powergate_mask[cpu] == 0) {
+ tegra_pmc_cpu_on(cpu);
+ } else {
+ tegra_fc_cpu_on(cpu);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
+ return PSCI_E_SUCCESS;
+}
+
+int tegra_soc_prepare_system_reset(void)
+{
+ /*
+ * Set System Clock (SCLK) to POR default so that the clock source
+ * for the PMC APB clock would not be changed due to system reset.
+ */
+ mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY,
+ SCLK_BURST_POLICY_DEFAULT);
+ mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0);
+
+ /* Wait 1 ms to make sure clock source/device logic is stabilized. */
+ mdelay(1);
+
+ /*
+ * Program the PMC in order to restart the system.
+ */
+ tegra_pmc_system_reset();
+
+ return PSCI_E_SUCCESS;
+}
+
+__dead2 void tegra_soc_prepare_system_off(void)
+{
+ ERROR("Tegra System Off: operation not handled.\n");
+ panic();
+}
diff --git a/plat/nvidia/tegra/soc/t210/plat_secondary.c b/plat/nvidia/tegra/soc/t210/plat_secondary.c
new file mode 100644
index 0000000..e0242cf
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/plat_secondary.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <pmc.h>
+#include <tegra_def.h>
+
+#define SB_CSR 0x0
+#define SB_CSR_NS_RST_VEC_WR_DIS (1 << 1)
+
+/* CPU reset vector */
+#define SB_AA64_RESET_LOW 0x30 /* width = 31:0 */
+#define SB_AA64_RESET_HI 0x34 /* width = 11:0 */
+
+extern void tegra_secure_entrypoint(void);
+
+/*******************************************************************************
+ * Setup secondary CPU vectors
+ ******************************************************************************/
+void plat_secondary_setup(void)
+{
+ uint32_t val;
+ uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint;
+
+ INFO("Setting up secondary CPU boot\n");
+
+ /* setup secondary CPU vector */
+ mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_LOW,
+ (reset_addr & 0xFFFFFFFF) | 1);
+ val = reset_addr >> 32;
+ mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_HI, val & 0x7FF);
+
+ /* configure PMC */
+ tegra_pmc_cpu_setup(reset_addr);
+ tegra_pmc_lock_cpu_vectors();
+}
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
new file mode 100644
index 0000000..68cd38e
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <cortex_a57.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/console.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <bl31/interrupt_mgmt.h>
+
+#include <bpmp.h>
+#include <flowctrl.h>
+#include <memctrl.h>
+#include <plat/common/platform.h>
+#include <security_engine.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/* sets of MMIO ranges setup */
+#define MMIO_RANGE_0_ADDR 0x50000000
+#define MMIO_RANGE_1_ADDR 0x60000000
+#define MMIO_RANGE_2_ADDR 0x70000000
+#define MMIO_RANGE_SIZE 0x200000
+
+/*
+ * Table of regions to map using the MMU.
+ */
+static const mmap_region_t tegra_mmap[] = {
+ MAP_REGION_FLAT(TEGRA_IRAM_BASE, 0x40000, /* 256KB */
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MMIO_RANGE_0_ADDR, MMIO_RANGE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MMIO_RANGE_1_ADDR, MMIO_RANGE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(MMIO_RANGE_2_ADDR, MMIO_RANGE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ {0}
+};
+
+/*******************************************************************************
+ * Set up the pagetables as per the platform memory map & initialize the MMU
+ ******************************************************************************/
+const mmap_region_t *plat_get_mmio_map(void)
+{
+ /* Add the map region for security engine SE2 */
+ if (tegra_chipid_is_t210_b01()) {
+ mmap_add_region((uint64_t)TEGRA_SE2_BASE,
+ (uint64_t)TEGRA_SE2_BASE,
+ (uint64_t)TEGRA_SE2_RANGE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ }
+
+ /* MMIO space */
+ return tegra_mmap;
+}
+
+/*******************************************************************************
+ * The Tegra power domain tree has a single system level power domain i.e. a
+ * single root node. The first entry in the power domain descriptor specifies
+ * the number of power domains at the highest power level.
+ *******************************************************************************
+ */
+const unsigned char tegra_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ 1,
+ /* No of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of CPU cores - cluster0 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+ /* No of CPU cores - cluster1 */
+ PLATFORM_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the Tegra default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return tegra_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * Handler to get the System Counter Frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return 19200000;
+}
+
+/*******************************************************************************
+ * Maximum supported UART controllers
+ ******************************************************************************/
+#define TEGRA210_MAX_UART_PORTS 5
+
+/*******************************************************************************
+ * This variable holds the UART port base addresses
+ ******************************************************************************/
+static uint32_t tegra210_uart_addresses[TEGRA210_MAX_UART_PORTS + 1] = {
+ 0, /* undefined - treated as an error case */
+ TEGRA_UARTA_BASE,
+ TEGRA_UARTB_BASE,
+ TEGRA_UARTC_BASE,
+ TEGRA_UARTD_BASE,
+ TEGRA_UARTE_BASE,
+};
+
+/*******************************************************************************
+ * Enable console corresponding to the console ID
+ ******************************************************************************/
+void plat_enable_console(int32_t id)
+{
+ static console_t uart_console;
+ uint32_t console_clock;
+
+ if ((id > 0) && (id < TEGRA210_MAX_UART_PORTS)) {
+ /*
+ * Reference clock used by the FPGAs is a lot slower.
+ */
+ if (tegra_platform_is_fpga()) {
+ console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
+ } else {
+ console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
+ }
+
+ (void)console_16550_register(tegra210_uart_addresses[id],
+ console_clock,
+ TEGRA_CONSOLE_BAUDRATE,
+ &uart_console);
+ console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
+ }
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 params from previous bootloader
+ ******************************************************************************/
+struct tegra_bl31_params *plat_get_bl31_params(void)
+{
+ return NULL;
+}
+
+/*******************************************************************************
+ * Return pointer to the BL31 platform params from previous bootloader
+ ******************************************************************************/
+plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
+{
+ return NULL;
+}
+
+/*******************************************************************************
+ * Handler for early platform setup
+ ******************************************************************************/
+void plat_early_platform_setup(void)
+{
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+ uint64_t val;
+
+ /* Verify chip id is t210 */
+ assert(tegra_chipid_is_t210());
+
+ /*
+ * Do initial security configuration to allow DRAM/device access.
+ */
+ tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
+ (uint32_t)plat_params->tzdram_size);
+
+ /* platform parameter passed by the previous bootloader */
+ if (plat_params->l2_ecc_parity_prot_dis != 1) {
+ /* Enable ECC Parity Protection for Cortex-A57 CPUs */
+ val = read_l2ctlr_el1();
+ val |= (uint64_t)CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
+ write_l2ctlr_el1(val);
+ }
+
+ /* Initialize security engine driver */
+ tegra_se_init();
+}
+
+/* Secure IRQs for Tegra186 */
+static const interrupt_prop_t tegra210_interrupt_props[] = {
+ INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(TEGRA210_TIMER1_IRQ, PLAT_TEGRA_WDT_PRIO,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(TEGRA210_WDT_CPU_LEGACY_FIQ, PLAT_TEGRA_WDT_PRIO,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+};
+
+/*******************************************************************************
+ * Handler for late platform setup
+ ******************************************************************************/
+void plat_late_platform_setup(void)
+{
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+ uint64_t sc7entry_end, offset;
+ int ret;
+ uint32_t val;
+
+ /* memmap TZDRAM area containing the SC7 Entry Firmware */
+ if (plat_params->sc7entry_fw_base && plat_params->sc7entry_fw_size) {
+
+ assert(plat_params->sc7entry_fw_size <= TEGRA_IRAM_A_SIZE);
+
+ /*
+ * Verify that the SC7 entry firmware resides inside the TZDRAM
+ * aperture, _before_ the BL31 code and the start address is
+ * exactly 1MB from BL31 base.
+ */
+
+ /* sc7entry-fw must be _before_ BL31 base */
+ assert(plat_params->tzdram_base > plat_params->sc7entry_fw_base);
+
+ sc7entry_end = plat_params->sc7entry_fw_base +
+ plat_params->sc7entry_fw_size;
+ assert(sc7entry_end < plat_params->tzdram_base);
+
+ /* sc7entry-fw start must be exactly 1MB behind BL31 base */
+ offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base;
+ assert(offset == 0x100000);
+
+ /* secure TZDRAM area */
+ tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base,
+ plat_params->tzdram_size + offset);
+
+ /* power off BPMP processor until SC7 entry */
+ tegra_fc_bpmp_off();
+
+ /* memmap SC7 entry firmware code */
+ ret = mmap_add_dynamic_region(plat_params->sc7entry_fw_base,
+ plat_params->sc7entry_fw_base,
+ plat_params->sc7entry_fw_size,
+ MT_SECURE | MT_RO_DATA);
+ assert(ret == 0);
+
+ /* restrict PMC access to secure world */
+ val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+ val |= PMC_SECURITY_EN_BIT;
+ mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+ }
+
+ if (!tegra_chipid_is_t210_b01()) {
+ /* restrict PMC access to secure world */
+ val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+ val |= PMC_SECURITY_EN_BIT;
+ mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+ }
+}
+
+/*******************************************************************************
+ * Initialize the GIC and SGIs
+ ******************************************************************************/
+void plat_gic_setup(void)
+{
+ tegra_gic_setup(tegra210_interrupt_props, ARRAY_SIZE(tegra210_interrupt_props));
+ tegra_gic_init();
+
+ /* Enable handling for FIQs */
+ tegra_fiq_handler_setup();
+
+ /*
+ * Enable routing watchdog FIQs from the flow controller to
+ * the GICD.
+ */
+ tegra_fc_enable_fiq_to_ccplex_routing();
+}
+/*******************************************************************************
+ * Handler to indicate support for System Suspend
+ ******************************************************************************/
+bool plat_supports_system_suspend(void)
+{
+ const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+
+ /*
+ * sc7entry-fw is only supported by Tegra210 SoCs.
+ */
+ if (!tegra_chipid_is_t210_b01() && (plat_params->sc7entry_fw_base != 0U)) {
+ return true;
+ } else if (tegra_chipid_is_t210_b01()) {
+ return true;
+ } else {
+ return false;
+ }
+}
+/*******************************************************************************
+ * Platform specific runtime setup.
+ ******************************************************************************/
+void plat_runtime_setup(void)
+{
+ /*
+ * During cold boot, it is observed that the arbitration
+ * bit is set in the Memory controller leading to false
+ * error interrupts in the non-secure world. To avoid
+ * this, clean the interrupt status register before
+ * booting into the non-secure world
+ */
+ tegra_memctrl_clear_pending_interrupts();
+
+ /*
+ * During boot, USB3 and flash media (SDMMC/SATA) devices need
+ * access to IRAM. Because these clients connect to the MC and
+ * do not have a direct path to the IRAM, the MC implements AHB
+ * redirection during boot to allow path to IRAM. In this mode
+ * accesses to a programmed memory address aperture are directed
+ * to the AHB bus, allowing access to the IRAM. This mode must be
+ * disabled before we jump to the non-secure world.
+ */
+ tegra_memctrl_disable_ahb_redirection();
+}
diff --git a/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
new file mode 100644
index 0000000..e3484be
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/plat_sip_calls.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <memctrl.h>
+#include <pmc.h>
+#include <tegra_private.h>
+#include <tegra_platform.h>
+#include <tegra_def.h>
+
+/*******************************************************************************
+ * PMC parameters
+ ******************************************************************************/
+#define PMC_READ U(0xaa)
+#define PMC_WRITE U(0xbb)
+
+/*******************************************************************************
+ * Tegra210 SiP SMCs
+ ******************************************************************************/
+#define TEGRA_SIP_PMC_COMMANDS U(0xC2FFFE00)
+
+/*******************************************************************************
+ * This function is responsible for handling all T210 SiP calls
+ ******************************************************************************/
+int plat_sip_handler(uint32_t smc_fid,
+ uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ const void *cookie,
+ void *handle,
+ uint64_t flags)
+{
+ uint32_t val, ns;
+
+ /* Determine which security state this SMC originated from */
+ ns = is_caller_non_secure(flags);
+ if (!ns)
+ SMC_RET1(handle, SMC_UNK);
+
+ if (smc_fid == TEGRA_SIP_PMC_COMMANDS) {
+ /* check the address is within PMC range and is 4byte aligned */
+ if ((x2 >= TEGRA_PMC_SIZE) || (x2 & 0x3))
+ return -EINVAL;
+
+ switch (x2) {
+ /* Black listed PMC registers */
+ case PMC_SCRATCH1:
+ case PMC_SCRATCH31 ... PMC_SCRATCH33:
+ case PMC_SCRATCH40:
+ case PMC_SCRATCH42:
+ case PMC_SCRATCH43 ... PMC_SCRATCH48:
+ case PMC_SCRATCH50 ... PMC_SCRATCH51:
+ case PMC_SCRATCH56 ... PMC_SCRATCH57:
+ /* PMC secure-only registers are not accessible */
+ case PMC_DPD_ENABLE_0:
+ case PMC_FUSE_CONTROL_0:
+ case PMC_CRYPTO_OP_0:
+ case PMC_TSC_MULT_0:
+ case PMC_STICKY_BIT:
+ ERROR("%s: error offset=0x%" PRIx64 "\n", __func__, x2);
+ return -EFAULT;
+ default:
+ /* Valid register */
+ break;
+ }
+
+ /* Perform PMC read/write */
+ if (x1 == PMC_READ) {
+ val = mmio_read_32((uint32_t)(TEGRA_PMC_BASE + x2));
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, val);
+ } else if (x1 == PMC_WRITE) {
+ mmio_write_32((uint32_t)(TEGRA_PMC_BASE + x2), (uint32_t)x3);
+ } else {
+ return -EINVAL;
+ }
+ } else {
+ return -ENOTSUP;
+ }
+ return 0;
+}
diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk
new file mode 100644
index 0000000..724cfc3
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TZDRAM_BASE := 0xFF800000
+$(eval $(call add_define,TZDRAM_BASE))
+
+ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT := 1
+$(eval $(call add_define,ERRATA_TEGRA_INVALIDATE_BTB_AT_BOOT))
+
+PLATFORM_CLUSTER_COUNT := 2
+$(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
+
+PLATFORM_MAX_CPUS_PER_CLUSTER := 4
+$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
+
+MAX_XLAT_TABLES := 10
+$(eval $(call add_define,MAX_XLAT_TABLES))
+
+MAX_MMAP_REGIONS := 16
+$(eval $(call add_define,MAX_MMAP_REGIONS))
+
+ENABLE_TEGRA_WDT_LEGACY_FIQ_HANDLING := 1
+
+PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t210 \
+ -I${SOC_DIR}/drivers/se
+
+BL31_SOURCES += ${TEGRA_GICv2_SOURCES} \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ ${TEGRA_DRIVERS}/bpmp/bpmp.c \
+ ${TEGRA_DRIVERS}/flowctrl/flowctrl.c \
+ ${TEGRA_DRIVERS}/memctrl/memctrl_v1.c \
+ ${TEGRA_DRIVERS}/pmc/pmc.c \
+ ${SOC_DIR}/plat_psci_handlers.c \
+ ${SOC_DIR}/plat_setup.c \
+ ${SOC_DIR}/drivers/se/security_engine.c \
+ ${SOC_DIR}/plat_secondary.c \
+ ${SOC_DIR}/plat_sip_calls.c
+
+# Enable workarounds for selected Cortex-A57 erratas.
+A57_DISABLE_NON_TEMPORAL_HINT := 1
+ERRATA_A57_826974 := 1
+ERRATA_A57_826977 := 1
+ERRATA_A57_828024 := 1
+ERRATA_A57_833471 := 1
+
+# Enable workarounds for selected Cortex-A53 erratas.
+A53_DISABLE_NON_TEMPORAL_HINT := 1
+ERRATA_A53_826319 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_855873 := 1
+
+# Skip L1 $ flush when powering down Cortex-A57 CPUs
+SKIP_A57_L1_FLUSH_PWR_DWN := 1
+
+# Enable higher performance Non-cacheable load forwarding
+A57_ENABLE_NONCACHEABLE_LOAD_FWD := 1
diff --git a/plat/nxp/common/aarch64/bl31_data.S b/plat/nxp/common/aarch64/bl31_data.S
new file mode 100644
index 0000000..cc91540
--- /dev/null
+++ b/plat/nxp/common/aarch64/bl31_data.S
@@ -0,0 +1,558 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <asm_macros.S>
+
+#include "bl31_data.h"
+#include "plat_psci.h"
+#include "platform_def.h"
+
+.global _getCoreData
+.global _setCoreData
+.global _getCoreState
+.global _setCoreState
+.global _init_global_data
+.global _get_global_data
+.global _set_global_data
+.global _initialize_psci
+.global _init_task_flags
+.global _set_task1_start
+.global _set_task1_done
+
+
+/* Function returns the specified data field value from the specified cpu
+ * core data area
+ * in: x0 = core mask lsb
+ * x1 = data field name/offset
+ * out: x0 = data value
+ * uses x0, x1, x2, [x13, x14, x15]
+ */
+func _getCoreData
+
+ /* generate a 0-based core number from the input mask */
+ clz x2, x0
+ mov x0, #63
+ sub x0, x0, x2
+
+ /* x0 = core number (0-based) */
+ /* x1 = field offset */
+
+ /* determine if this is bootcore or secondary core */
+ cbnz x0, 1f
+
+ /* get base address for bootcore data */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, x1
+ b 2f
+
+1: /* get base address for secondary core data */
+
+ /* x0 = core number (0-based) */
+ /* x1 = field offset */
+
+ /* generate number of regions to offset */
+ mov x2, #SEC_REGION_SIZE
+ mul x2, x2, x0
+
+ /* x1 = field offset */
+ /* x2 = region offset */
+
+ /* generate the total offset to data element */
+ sub x1, x2, x1
+
+ /* x1 = total offset to data element */
+
+ /* get the base address */
+ ldr x2, =SECONDARY_TOP
+
+ /* apply offset to base addr */
+ sub x2, x2, x1
+2:
+ /* x2 = data element address */
+
+ dc ivac, x2
+ dsb sy
+ isb
+ /* read data */
+ ldr x0, [x2]
+
+ ret
+endfunc _getCoreData
+
+
+/* Function returns the SoC-specific state of the specified cpu
+ * in: x0 = core mask lsb
+ * out: x0 = data value
+ * uses x0, x1, x2, [x13, x14, x15]
+ */
+func _getCoreState
+
+ mov x1, #CORE_STATE_DATA
+
+ /* generate a 0-based core number from the input mask */
+ clz x2, x0
+ mov x0, #63
+ sub x0, x0, x2
+
+ /* x0 = core number (0-based) */
+ /* x1 = field offset */
+
+ /* determine if this is bootcore or secondary core */
+ cbnz x0, 1f
+
+ /* get base address for bootcore data */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, x1
+ b 2f
+
+1: /* get base address for secondary core data */
+
+ /* x0 = core number (0-based) */
+ /* x1 = field offset */
+
+ /* generate number of regions to offset */
+ mov x2, #SEC_REGION_SIZE
+ mul x2, x2, x0
+
+ /* x1 = field offset */
+ /* x2 = region offset */
+
+ /* generate the total offset to data element */
+ sub x1, x2, x1
+
+ /* x1 = total offset to data element */
+
+ /* get the base address */
+ ldr x2, =SECONDARY_TOP
+
+ /* apply offset to base addr */
+ sub x2, x2, x1
+2:
+ /* x2 = data element address */
+
+ dc ivac, x2
+ dsb sy
+ isb
+
+ /* read data */
+ ldr x0, [x2]
+
+ ret
+endfunc _getCoreState
+
+
+/* Function writes the specified data value into the specified cpu
+ * core data area
+ * in: x0 = core mask lsb
+ * x1 = data field offset
+ * x2 = data value to write/store
+ * out: none
+ * uses x0, x1, x2, x3, [x13, x14, x15]
+ */
+func _setCoreData
+ /* x0 = core mask */
+ /* x1 = field offset */
+ /* x2 = data value */
+
+ clz x3, x0
+ mov x0, #63
+ sub x0, x0, x3
+
+ /* x0 = core number (0-based) */
+ /* x1 = field offset */
+ /* x2 = data value */
+
+ /* determine if this is bootcore or secondary core */
+ cbnz x0, 1f
+
+ /* get base address for bootcore data */
+ ldr x3, =BC_PSCI_BASE
+ add x3, x3, x1
+ b 2f
+
+1: /* get base address for secondary core data */
+
+ /* x0 = core number (0-based) */
+ /* x1 = field offset */
+ /* x2 = data value */
+
+ /* generate number of regions to offset */
+ mov x3, #SEC_REGION_SIZE
+ mul x3, x3, x0
+
+ /* x1 = field offset */
+ /* x2 = data value */
+ /* x3 = region offset */
+
+ /* generate the total offset to data element */
+ sub x1, x3, x1
+
+ /* x1 = total offset to data element */
+ /* x2 = data value */
+
+ ldr x3, =SECONDARY_TOP
+
+ /* apply offset to base addr */
+ sub x3, x3, x1
+
+2:
+ /* x2 = data value */
+ /* x3 = data element address */
+
+ str x2, [x3]
+
+ dc cvac, x3
+ dsb sy
+ isb
+ ret
+endfunc _setCoreData
+
+
+/* Function stores the specified core state
+ * in: x0 = core mask lsb
+ * x1 = data value to write/store
+ * out: none
+ * uses x0, x1, x2, x3, [x13, x14, x15]
+ */
+func _setCoreState
+ mov x2, #CORE_STATE_DATA
+
+ clz x3, x0
+ mov x0, #63
+ sub x0, x0, x3
+
+ /* x0 = core number (0-based) */
+ /* x1 = data value */
+ /* x2 = field offset */
+
+ /* determine if this is bootcore or secondary core */
+ cbnz x0, 1f
+
+ /* get base address for bootcore data */
+ ldr x3, =BC_PSCI_BASE
+ add x3, x3, x2
+ b 2f
+
+1: /* get base address for secondary core data */
+
+ /* x0 = core number (0-based) */
+ /* x1 = data value */
+ /* x2 = field offset */
+
+ /* generate number of regions to offset */
+ mov x3, #SEC_REGION_SIZE
+ mul x3, x3, x0
+
+ /* x1 = data value */
+ /* x2 = field offset */
+ /* x3 = region offset */
+
+ /* generate the total offset to data element */
+ sub x2, x3, x2
+
+ /* x1 = data value */
+ /* x2 = total offset to data element */
+
+ ldr x3, =SECONDARY_TOP
+
+ /* apply offset to base addr */
+ sub x3, x3, x2
+
+2:
+ /* x1 = data value */
+ /* x3 = data element address */
+
+ str x1, [x3]
+
+ dc civac, x3
+ dsb sy
+ isb
+ ret
+endfunc _setCoreState
+
+
+/* Function sets the task1 start
+ * in: w0 = value to set flag to
+ * out: none
+ * uses x0, x1
+ */
+func _set_task1_start
+
+ ldr x1, =SMC_TASK1_BASE
+
+ add x1, x1, #TSK_START_OFFSET
+ str w0, [x1]
+ dc cvac, x1
+ dsb sy
+ isb
+ ret
+endfunc _set_task1_start
+
+
+/* Function sets the state of the task 1 done flag
+ * in: w0 = value to set flag to
+ * out: none
+ * uses x0, x1
+ */
+func _set_task1_done
+
+ ldr x1, =SMC_TASK1_BASE
+
+ add x1, x1, #TSK_DONE_OFFSET
+ str w0, [x1]
+ dc cvac, x1
+ dsb sy
+ isb
+ ret
+endfunc _set_task1_done
+
+
+/* Function initializes the smc global data entries
+ * Note: the constant LAST_SMC_GLBL_OFFSET must reference the last entry in the
+ * smc global region
+ * in: none
+ * out: none
+ * uses x0, x1, x2
+ */
+func _init_global_data
+
+ ldr x1, =SMC_GLBL_BASE
+
+ /* x1 = SMC_GLBL_BASE */
+
+ mov x2, #LAST_SMC_GLBL_OFFSET
+ add x2, x2, x1
+1:
+ str xzr, [x1]
+ dc cvac, x1
+ cmp x2, x1
+ add x1, x1, #8
+ b.hi 1b
+
+ dsb sy
+ isb
+ ret
+endfunc _init_global_data
+
+
+/* Function gets the value of the specified global data element
+ * in: x0 = offset of data element
+ * out: x0 = requested data element
+ * uses x0, x1
+ */
+func _get_global_data
+
+ ldr x1, =SMC_GLBL_BASE
+ add x1, x1, x0
+ dc ivac, x1
+ isb
+
+ ldr x0, [x1]
+ ret
+endfunc _get_global_data
+
+
+/* Function sets the value of the specified global data element
+ * in: x0 = offset of data element
+ * x1 = value to write
+ * out: none
+ * uses x0, x1, x2
+ */
+func _set_global_data
+
+ ldr x2, =SMC_GLBL_BASE
+ add x0, x0, x2
+ str x1, [x0]
+ dc cvac, x0
+
+ dsb sy
+ isb
+ ret
+endfunc _set_global_data
+
+
+/* Function initializes the core data areas
+ * only executed by the boot core
+ * in: none
+ * out: none
+ * uses: x0, x1, x2, x3, x4, x5, x6, x7, [x13, x14, x15]
+ */
+func _initialize_psci
+ mov x7, x30
+
+ /* initialize the bootcore psci data */
+ ldr x5, =BC_PSCI_BASE
+ mov x6, #CORE_RELEASED
+
+ str x6, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5], #8
+ dc cvac, x5
+ str xzr, [x5]
+ dc cvac, x5
+ dsb sy
+ isb
+
+ /* see if we have any secondary cores */
+ mov x4, #PLATFORM_CORE_COUNT
+ sub x4, x4, #1
+ cbz x4, 3f
+
+ /* initialize the secondary core's psci data */
+ ldr x5, =SECONDARY_TOP
+ /* core mask lsb for core 1 */
+ mov x3, #2
+ sub x5, x5, #SEC_REGION_SIZE
+
+ /* x3 = core1 mask lsb */
+ /* x4 = number of secondary cores */
+ /* x5 = core1 psci data base address */
+2:
+ /* set core state in x6 */
+ mov x0, x3
+ mov x6, #CORE_IN_RESET
+ bl _soc_ck_disabled
+ cbz x0, 1f
+ mov x6, #CORE_DISABLED
+1:
+ add x2, x5, #CORE_STATE_DATA
+ str x6, [x2]
+ dc cvac, x2
+ add x2, x5, #SPSR_EL3_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #CNTXT_ID_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #START_ADDR_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #LINK_REG_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #GICC_CTLR_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #ABORT_FLAG_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #SCTLR_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #CPUECTLR_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #AUX_01_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #AUX_02_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #AUX_03_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #AUX_04_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #AUX_05_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #SCR_EL3_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ add x2, x5, #HCR_EL2_DATA
+ str xzr, [x2]
+ dc cvac, x2
+ dsb sy
+ isb
+
+ sub x4, x4, #1
+ cbz x4, 3f
+
+ /* generate next core mask */
+ lsl x3, x3, #1
+
+ /* decrement base address to next data area */
+ sub x5, x5, #SEC_REGION_SIZE
+ b 2b
+3:
+ mov x30, x7
+ ret
+endfunc _initialize_psci
+
+
+/* Function initializes the soc init task flags
+ * in: none
+ * out: none
+ * uses x0, x1, [x13, x14, x15]
+ */
+func _init_task_flags
+
+ /* get the base address of the first task structure */
+ ldr x0, =SMC_TASK1_BASE
+
+ /* x0 = task1 base address */
+
+ str wzr, [x0, #TSK_START_OFFSET]
+ str wzr, [x0, #TSK_DONE_OFFSET]
+ str wzr, [x0, #TSK_CORE_OFFSET]
+ dc cvac, x0
+
+ /* move to task2 structure */
+ add x0, x0, #SMC_TASK_OFFSET
+
+ str wzr, [x0, #TSK_START_OFFSET]
+ str wzr, [x0, #TSK_DONE_OFFSET]
+ str wzr, [x0, #TSK_CORE_OFFSET]
+ dc cvac, x0
+
+ /* move to task3 structure */
+ add x0, x0, #SMC_TASK_OFFSET
+
+ str wzr, [x0, #TSK_START_OFFSET]
+ str wzr, [x0, #TSK_DONE_OFFSET]
+ str wzr, [x0, #TSK_CORE_OFFSET]
+ dc cvac, x0
+
+ /* move to task4 structure */
+ add x0, x0, #SMC_TASK_OFFSET
+
+ str wzr, [x0, #TSK_START_OFFSET]
+ str wzr, [x0, #TSK_DONE_OFFSET]
+ str wzr, [x0, #TSK_CORE_OFFSET]
+ dc cvac, x0
+
+ dsb sy
+ isb
+ ret
+endfunc _init_task_flags
diff --git a/plat/nxp/common/aarch64/ls_helpers.S b/plat/nxp/common/aarch64/ls_helpers.S
new file mode 100644
index 0000000..311dce1
--- /dev/null
+++ b/plat/nxp/common/aarch64/ls_helpers.S
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <asm_macros.S>
+#include <cortex_a53.h>
+#include <drivers/console.h>
+#include <lib/cpus/aarch64/cortex_a72.h>
+
+#include <platform_def.h>
+
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_core_pos
+ .globl plat_my_core_pos
+ .globl plat_core_mask
+ .globl plat_my_core_mask
+ .globl plat_core_pos_by_mpidr
+ .globl _disable_ldstr_pfetch_A53
+ .globl _disable_ldstr_pfetch_A72
+ .global _set_smmu_pagesz_64
+
+ /* int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ */
+
+ /* int plat_crash_console_init(void)
+ * Use normal console by default. Switch it to crash
+ * mode so serial consoles become active again.
+ * NOTE: This default implementation will only work for
+ * crashes that occur after a normal console (marked
+ * valid for the crash state) has been registered with
+ * the console framework. To debug crashes that occur
+ * earlier, the platform has to override these functions
+ * with an implementation that initializes a console
+ * driver with hardcoded parameters. See
+ * docs/porting-guide.rst for more information.
+ */
+func plat_crash_console_init
+ mov x3, x30
+ mov x0, #CONSOLE_FLAG_CRASH
+ bl console_switch_state
+ mov x0, #1
+ ret x3
+endfunc plat_crash_console_init
+
+ /* void plat_crash_console_putc(int character)
+ * Output through the normal console by default.
+ */
+func plat_crash_console_putc
+ b console_putc
+endfunc plat_crash_console_putc
+
+ /* void plat_crash_console_flush(void)
+ * Flush normal console by default.
+ */
+func plat_crash_console_flush
+ b console_flush
+endfunc plat_crash_console_flush
+
+/* This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ */
+func plat_core_pos_by_mpidr
+
+ b plat_core_pos
+
+endfunc plat_core_pos_by_mpidr
+
+#if (SYMMETRICAL_CLUSTERS)
+/* unsigned int plat_my_core_mask(void)
+ * generate a mask bit for this core
+ */
+func plat_my_core_mask
+ mrs x0, MPIDR_EL1
+ b plat_core_mask
+endfunc plat_my_core_mask
+
+/* unsigned int plat_core_mask(u_register_t mpidr)
+ * generate a lsb-based mask bit for the core specified by mpidr in x0.
+ *
+ * SoC core = ((cluster * cpu_per_cluster) + core)
+ * mask = (1 << SoC core)
+ */
+func plat_core_mask
+ mov w1, wzr
+ mov w2, wzr
+
+ /* extract cluster */
+ bfxil w1, w0, #8, #8
+ /* extract cpu # */
+ bfxil w2, w0, #0, #8
+
+ mov w0, wzr
+
+ /* error checking */
+ cmp w1, #NUMBER_OF_CLUSTERS
+ b.ge 1f
+ cmp w2, #CORES_PER_CLUSTER
+ b.ge 1f
+
+ mov w0, #CORES_PER_CLUSTER
+ mul w1, w1, w0
+ add w1, w1, w2
+ mov w2, #0x1
+ lsl w0, w2, w1
+1:
+ ret
+endfunc plat_core_mask
+
+/*
+ * unsigned int plat_my_core_pos(void)
+ * generate a linear core number for this core
+ */
+func plat_my_core_pos
+ mrs x0, MPIDR_EL1
+ b plat_core_pos
+endfunc plat_my_core_pos
+
+/*
+ * unsigned int plat_core_pos(u_register_t mpidr)
+ * Generate a linear core number for the core specified by mpidr.
+ *
+ * SoC core = ((cluster * cpu_per_cluster) + core)
+ * Returns -1 if mpidr invalid
+ */
+func plat_core_pos
+ mov w1, wzr
+ mov w2, wzr
+ bfxil w1, w0, #8, #8 /* extract cluster */
+ bfxil w2, w0, #0, #8 /* extract cpu # */
+
+ mov w0, #-1
+
+ /* error checking */
+ cmp w1, #NUMBER_OF_CLUSTERS
+ b.ge 1f
+ cmp w2, #CORES_PER_CLUSTER
+ b.ge 1f
+
+ mov w0, #CORES_PER_CLUSTER
+ mul w1, w1, w0
+ add w0, w1, w2
+1:
+ ret
+endfunc plat_core_pos
+
+#endif
+
+/* this function disables the load-store prefetch of the calling core
+ * Note: this function is for A53 cores ONLY
+ * in: none
+ * out: none
+ * uses x0
+ */
+func _disable_ldstr_pfetch_A53
+ mrs x0, CORTEX_A53_CPUACTLR_EL1
+ tst x0, #CORTEX_A53_CPUACTLR_EL1_L1PCTL
+ b.ne 1f
+ b 2f
+
+.align 6
+1:
+ dsb sy
+ isb
+ bic x0, x0, #CORTEX_A53_CPUACTLR_EL1_L1PCTL
+ msr CORTEX_A53_CPUACTLR_EL1, x0
+ isb
+
+2:
+ ret
+endfunc _disable_ldstr_pfetch_A53
+
+
+/* this function disables the load-store prefetch of the calling core
+ * Note: this function is for A72 cores ONLY
+ * in: none
+ * out: none
+ * uses x0
+ */
+func _disable_ldstr_pfetch_A72
+
+ mrs x0, CORTEX_A72_CPUACTLR_EL1
+ tst x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH
+ b.eq 1f
+ b 2f
+
+.align 6
+1:
+ dsb sy
+ isb
+ orr x0, x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH
+ msr CORTEX_A72_CPUACTLR_EL1, x0
+ isb
+
+2:
+ ret
+endfunc _disable_ldstr_pfetch_A72
+
+/*
+ * Function sets the SACR pagesize to 64k
+ */
+func _set_smmu_pagesz_64
+
+ ldr x1, =NXP_SMMU_ADDR
+ ldr w0, [x1, #0x10]
+ orr w0, w0, #1 << 16 /* setting to 64K page */
+ str w0, [x1, #0x10]
+
+ ret
+endfunc _set_smmu_pagesz_64
diff --git a/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h b/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h
new file mode 100644
index 0000000..65aef14
--- /dev/null
+++ b/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_DEF_FIP_UUID_H
+#define PLAT_DEF_FIP_UUID_H
+
+/* PHy images configs */
+#define UUID_DDR_IMEM_UDIMM_1D \
+ {{0x5b, 0xdb, 0xe3, 0x83}, {0xd1, 0x9f}, {0xc7, 0x06}, 0xd4, 0x91, {0x76, 0x4f, 0x9d, 0x23, 0x2d, 0x2d} }
+
+#define UUID_DDR_IMEM_UDIMM_2D \
+ {{0xfa, 0x0e, 0xeb, 0x21}, {0xe0, 0x7f}, {0x8e, 0x65}, 0x95, 0xd8, {0x2b, 0x94, 0xf6, 0xb8, 0x28, 0x0a} }
+
+#define UUID_DDR_DMEM_UDIMM_1D \
+ {{0xba, 0xbb, 0xfd, 0x7e}, {0x5b, 0xf0}, {0xeb, 0xb8}, 0xeb, 0x71, {0xb1, 0x85, 0x07, 0xdd, 0xe1, 0x32} }
+
+#define UUID_DDR_DMEM_UDIMM_2D \
+ {{0xb6, 0x99, 0x61, 0xda}, {0xf9, 0x92}, {0x4b, 0x9e}, 0x0c, 0x49, {0x74, 0xa5, 0xe0, 0x5c, 0xbe, 0xc3} }
+
+#define UUID_DDR_IMEM_RDIMM_1D \
+ {{0x42, 0x33, 0x66, 0x52}, {0xd8, 0x94}, {0x4d, 0xc1}, 0x91, 0xcc, {0x26, 0x8f, 0x7a, 0x67, 0xf1, 0xa2} }
+
+#define UUID_DDR_IMEM_RDIMM_2D \
+ {{0x2e, 0x95, 0x73, 0xba}, {0xb5, 0xca}, {0x7c, 0xc7}, 0xef, 0xc9, {0x5e, 0xb0, 0x42, 0xec, 0x08, 0x7a} }
+
+#define UUID_DDR_DMEM_RDIMM_1D \
+ {{0x1c, 0x51, 0x17, 0xed}, {0x30, 0x0d}, {0xae, 0xba}, 0x87, 0x03, {0x1f, 0x37, 0x85, 0xec, 0xe1, 0x44} }
+
+#define UUID_DDR_DMEM_RDIMM_2D \
+ {{0xe9, 0x0a, 0x90, 0x78}, {0x11, 0xd6}, {0x8b, 0xba}, 0x24, 0x35, {0xec, 0x10, 0x75, 0x4f, 0x56, 0xa5} }
+
+#define UUID_DDR_FW_KEY_CERT \
+ {{0xac, 0x4b, 0xb8, 0x9c}, {0x8f, 0xb9}, {0x11, 0xea}, 0xbc, 0x55, {0x02, 0x42, 0xac, 0x12, 0x00, 0x03} }
+
+#define UUID_DDR_UDIMM_FW_CONTENT_CERT \
+ {{0x2c, 0x7f, 0x52, 0x54}, {0x70, 0x92}, {0x48, 0x40}, 0x8c, 0x34, {0x87, 0x4b, 0xbf, 0xbd, 0x9d, 0x89} }
+
+#define UUID_DDR_RDIMM_FW_CONTENT_CERT \
+ {{0x94, 0xc3, 0x63, 0x30}, {0x7c, 0xf7}, {0x4f, 0x1d}, 0xaa, 0xcd, {0xb5, 0x80, 0xb2, 0xc2, 0x40, 0xa5} }
+
+#define UUID_FUSE_PROV \
+ {{0xec, 0x45, 0x90, 0x42}, {0x30, 0x0d}, {0xae, 0xba}, 0x87, 0x03, {0x1f, 0x37, 0x85, 0xec, 0xe1, 0x44} }
+
+#define UUID_FUSE_UP \
+ {{0x89, 0x46, 0xef, 0x78}, {0x11, 0xd6}, {0x8b, 0xba}, 0x24, 0x35, {0xec, 0x10, 0x75, 0x4f, 0x56, 0xa5} }
+
+#endif /* PLAT_DEF_FIP_UUID_H */
diff --git a/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h b/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h
new file mode 100644
index 0000000..9856f70
--- /dev/null
+++ b/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef NXP_IMG_DEF_H
+#define NXP_IMG_DEF_H
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+#ifdef CONFIG_DDR_FIP_IMAGE
+/* DDR FIP IMAGE ID */
+#define DDR_FIP_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS
+
+#define DDR_IMEM_UDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 1
+#define DDR_IMEM_UDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 2
+
+#define DDR_DMEM_UDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 3
+#define DDR_DMEM_UDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 4
+
+#define DDR_IMEM_RDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 5
+#define DDR_IMEM_RDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 6
+
+#define DDR_DMEM_RDIMM_1D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 7
+#define DDR_DMEM_RDIMM_2D_IMAGE_ID MAX_IMG_IDS_WITH_SPMDS + 8
+
+#define DDR_FW_KEY_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 9
+#define DDR_UDIMM_FW_CONTENT_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 10
+#define DDR_RDIMM_FW_CONTENT_CERT_ID MAX_IMG_IDS_WITH_SPMDS + 11
+/* Max Images */
+#define MAX_IMG_WITH_DDR_IDS MAX_IMG_IDS_WITH_SPMDS + 12
+#else
+#define MAX_IMG_WITH_DDR_IDS MAX_IMG_IDS_WITH_SPMDS
+#endif
+
+#ifdef POLICY_FUSE_PROVISION
+/* FUSE FIP IMAGE ID */
+#define FUSE_FIP_IMAGE_ID MAX_IMG_WITH_DDR_IDS
+
+#define FUSE_PROV_IMAGE_ID MAX_IMG_WITH_DDR_IDS + 1
+
+#define FUSE_UP_IMAGE_ID MAX_IMG_WITH_DDR_IDS + 2
+
+#define MAX_IMG_WITH_FIMG_IDS MAX_IMG_WITH_DDR_IDS + 3
+#else
+#define MAX_IMG_WITH_FIMG_IDS MAX_IMG_WITH_DDR_IDS
+#endif
+
+#define MAX_NUMBER_IDS MAX_IMG_WITH_FIMG_IDS
+
+#endif /* NXP_IMG_DEF_H */
diff --git a/plat/nxp/common/fip_handler/common/platform_oid.h b/plat/nxp/common/fip_handler/common/platform_oid.h
new file mode 100644
index 0000000..bbd6041
--- /dev/null
+++ b/plat/nxp/common/fip_handler/common/platform_oid.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#define DDR_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2200.1"
+#define DDR_IMEM_UDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.2"
+#define DDR_IMEM_UDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.3"
+#define DDR_DMEM_UDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.4"
+#define DDR_DMEM_UDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.5"
+#define DDR_IMEM_RDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.6"
+#define DDR_IMEM_RDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.7"
+#define DDR_DMEM_RDIMM_1D_HASH_OID "1.3.6.1.4.1.4128.2200.8"
+#define DDR_DMEM_RDIMM_2D_HASH_OID "1.3.6.1.4.1.4128.2200.9"
diff --git a/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk b/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk
new file mode 100644
index 0000000..7d673ba
--- /dev/null
+++ b/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk
@@ -0,0 +1,38 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-----------------------------------------------------------------------------
+ifeq (${DDR_FIP_IO_STORAGE_ADDED},)
+
+$(eval $(call add_define, PLAT_DEF_FIP_UUID))
+$(eval $(call add_define, PLAT_TBBR_IMG_DEF))
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+
+DDR_FIP_IO_STORAGE_ADDED := 1
+$(eval $(call add_define,CONFIG_DDR_FIP_IMAGE))
+
+FIP_HANDLER_PATH := ${PLAT_COMMON_PATH}/fip_handler
+FIP_HANDLER_COMMON_PATH := ${FIP_HANDLER_PATH}/common
+DDR_FIP_IO_STORAGE_PATH := ${FIP_HANDLER_PATH}/ddr_fip
+
+PLAT_INCLUDES += -I${FIP_HANDLER_COMMON_PATH}\
+ -I$(DDR_FIP_IO_STORAGE_PATH)
+
+DDR_FIP_IO_SOURCES += $(DDR_FIP_IO_STORAGE_PATH)/ddr_io_storage.c
+
+$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR})
+
+ifeq (${BL_COMM_DDR_FIP_IO_NEEDED},yes)
+BL_COMMON_SOURCES += ${DDR_FIP_IO_SOURCES}
+else
+ifeq (${BL2_DDR_FIP_IO_NEEDED},yes)
+BL2_SOURCES += ${DDR_FIP_IO_SOURCES}
+endif
+ifeq (${BL31_DDR_FIP_IO_NEEDED},yes)
+BL31_SOURCES += ${DDR_FIP_IO_SOURCES}
+endif
+endif
+endif
+#------------------------------------------------
diff --git a/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c
new file mode 100644
index 0000000..fc3c4a4
--- /dev/null
+++ b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <io_block.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <lib/utils.h>
+#include <tools_share/firmware_image_package.h>
+#include "ddr_io_storage.h"
+#include "plat_common.h"
+#include "platform_def.h"
+
+
+/* TBD - Move these defined to the platform_def.h file.
+ * Keeping them for reference here
+ */
+extern uintptr_t backend_dev_handle;
+
+static uint32_t ddr_fip;
+
+static uintptr_t ddr_fip_dev_handle;
+
+static io_block_spec_t ddr_fip_block_spec = {
+ .offset = PLAT_DDR_FIP_OFFSET,
+ .length = PLAT_DDR_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t ddr_imem_udimm_1d_uuid_spec = {
+ .uuid = UUID_DDR_IMEM_UDIMM_1D,
+};
+
+static const io_uuid_spec_t ddr_imem_udimm_2d_uuid_spec = {
+ .uuid = UUID_DDR_IMEM_UDIMM_2D,
+};
+
+static const io_uuid_spec_t ddr_dmem_udimm_1d_uuid_spec = {
+ .uuid = UUID_DDR_DMEM_UDIMM_1D,
+};
+
+static const io_uuid_spec_t ddr_dmem_udimm_2d_uuid_spec = {
+ .uuid = UUID_DDR_DMEM_UDIMM_2D,
+};
+
+static const io_uuid_spec_t ddr_imem_rdimm_1d_uuid_spec = {
+ .uuid = UUID_DDR_IMEM_RDIMM_1D,
+};
+
+static const io_uuid_spec_t ddr_imem_rdimm_2d_uuid_spec = {
+ .uuid = UUID_DDR_IMEM_RDIMM_2D,
+};
+
+static const io_uuid_spec_t ddr_dmem_rdimm_1d_uuid_spec = {
+ .uuid = UUID_DDR_DMEM_RDIMM_1D,
+};
+
+static const io_uuid_spec_t ddr_dmem_rdimm_2d_uuid_spec = {
+ .uuid = UUID_DDR_DMEM_RDIMM_2D,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t ddr_fw_key_cert_uuid_spec = {
+ .uuid = UUID_DDR_FW_KEY_CERT,
+};
+static const io_uuid_spec_t ddr_udimm_fw_cert_uuid_spec = {
+ .uuid = UUID_DDR_UDIMM_FW_CONTENT_CERT,
+};
+static const io_uuid_spec_t ddr_rdimm_fw_cert_uuid_spec = {
+ .uuid = UUID_DDR_RDIMM_FW_CONTENT_CERT,
+};
+#endif
+
+static int open_ddr_fip(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, ARM platforms load images from the FIP */
+static const struct plat_io_policy ddr_policies[] = {
+ [DDR_FIP_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &backend_dev_handle,
+ (uintptr_t)&ddr_fip_block_spec,
+ NULL
+ },
+ [DDR_IMEM_UDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_imem_udimm_1d_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_IMEM_UDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_imem_udimm_2d_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_DMEM_UDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_dmem_udimm_1d_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_DMEM_UDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_dmem_udimm_2d_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_IMEM_RDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_imem_rdimm_1d_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_IMEM_RDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_imem_rdimm_2d_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_DMEM_RDIMM_1D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_dmem_rdimm_1d_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_DMEM_RDIMM_2D_IMAGE_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_dmem_rdimm_2d_uuid_spec,
+ open_ddr_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [DDR_FW_KEY_CERT_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_fw_key_cert_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_UDIMM_FW_CONTENT_CERT_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_udimm_fw_cert_uuid_spec,
+ open_ddr_fip
+ },
+ [DDR_RDIMM_FW_CONTENT_CERT_ID - DDR_FIP_IMAGE_ID] = {
+ &ddr_fip_dev_handle,
+ (uintptr_t)&ddr_rdimm_fw_cert_uuid_spec,
+ open_ddr_fip
+ },
+#endif
+};
+
+static int open_ddr_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(ddr_fip_dev_handle, (uintptr_t)DDR_FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(ddr_fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+/* The image can be one of the DDR PHY images, which can be sleected via DDR
+ * policies
+ */
+int plat_get_ddr_fip_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec,
+ int (*check)(const uintptr_t spec))
+{
+ int result = -1;
+ const struct plat_io_policy *policy;
+
+ if (image_id >= (DDR_FIP_IMAGE_ID + ARRAY_SIZE(ddr_policies))) {
+ return result;
+ }
+
+ policy = &ddr_policies[image_id - DDR_FIP_IMAGE_ID];
+ if (image_id == DDR_FIP_IMAGE_ID) {
+ result = check(policy->image_spec);
+ } else {
+ result = policy->check(policy->image_spec);
+ }
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ }
+ return result;
+}
+
+int ddr_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev)
+{
+ int io_result;
+ size_t ddr_fip_offset = PLAT_DDR_FIP_OFFSET;
+
+ /* Open connections to ddr fip and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)&ddr_fip,
+ &ddr_fip_dev_handle);
+ assert(io_result == 0);
+
+ switch (boot_dev) {
+#if QSPI_BOOT
+ case BOOT_DEVICE_QSPI:
+ ddr_fip_offset += NXP_QSPI_FLASH_ADDR;
+ break;
+#endif
+#if NOR_BOOT
+ case BOOT_DEVICE_IFC_NOR:
+ ddr_fip_offset += NXP_NOR_FLASH_ADDR;
+ break;
+#endif
+#if FLEXSPI_NOR_BOOT
+ case BOOT_DEVICE_FLEXSPI_NOR:
+ ddr_fip_offset += NXP_FLEXSPI_FLASH_ADDR;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ ddr_fip_block_spec.offset = ddr_fip_offset;
+
+ return io_result;
+}
diff --git a/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h
new file mode 100644
index 0000000..6df3902
--- /dev/null
+++ b/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DDR_IO_STORAGE_H
+#define DDR_IO_STORAGE_H
+
+#include <drivers/io/io_driver.h>
+
+#ifndef PLAT_DDR_FIP_OFFSET
+#define PLAT_DDR_FIP_OFFSET 0x800000
+#endif
+
+#ifndef PLAT_DDR_FIP_MAX_SIZE
+#define PLAT_DDR_FIP_MAX_SIZE 0x32000
+#endif
+
+int ddr_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev);
+int plat_get_ddr_fip_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec,
+ int (*check)(const uintptr_t spec));
+
+#endif /* DDR_IO_STORAGE_H */
diff --git a/plat/nxp/common/fip_handler/fuse_fip/fuse.mk b/plat/nxp/common/fip_handler/fuse_fip/fuse.mk
new file mode 100644
index 0000000..d8f5ae6
--- /dev/null
+++ b/plat/nxp/common/fip_handler/fuse_fip/fuse.mk
@@ -0,0 +1,100 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+NEED_FUSE := yes
+
+$(eval $(call add_define, PLAT_DEF_FIP_UUID))
+$(eval $(call add_define, POLICY_FUSE_PROVISION))
+$(eval $(call add_define, PLAT_TBBR_IMG_DEF))
+
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,GPIO_NEEDED,BL2))
+
+FIP_HANDLER_PATH := ${PLAT_COMMON_PATH}/fip_handler
+FIP_HANDLER_COMMON_PATH := ${FIP_HANDLER_PATH}/common
+
+FUSE_SOURCES := ${FIP_HANDLER_PATH}/fuse_fip/fuse_io_storage.c
+
+PLAT_INCLUDES += -I${FIP_HANDLER_COMMON_PATH}\
+ -I${FIP_HANDLER_PATH}/fuse_fip
+
+FUSE_FIP_NAME := fuse_fip.bin
+
+fip_fuse: ${BUILD_PLAT}/${FUSE_FIP_NAME}
+
+ifeq (${FUSE_PROV_FILE},)
+
+$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR})
+
+else
+ifeq (${TRUSTED_BOARD_BOOT},1)
+FUSE_PROV_FILE_SB = $(notdir ${FUSE_PROV_FILE})_prov.sb
+FUSE_FIP_ARGS += --fuse-prov ${BUILD_PLAT}/${FUSE_PROV_FILE_SB}
+FUSE_FIP_DEPS += ${BUILD_PLAT}/${FUSE_PROV_FILE_SB}
+else
+FUSE_FIP_ARGS += --fuse-prov ${FUSE_PROV_FILE}
+FUSE_FIP_DEPS += ${FUSE_PROV_FILE}
+endif
+endif
+
+ifeq (${FUSE_UP_FILE},)
+else
+ifeq (${TRUSTED_BOARD_BOOT},1)
+FUSE_UP_FILE_SB = $(notdir ${FUSE_UP_FILE})_up.sb
+FUSE_FIP_ARGS += --fuse-up ${BUILD_PLAT}/${FUSE_UP_FILE_SB}
+FUSE_FIP_DEPS += ${BUILD_PLAT}/${FUSE_UP_FILE_SB}
+else
+FUSE_FIP_ARGS += --fuse-up ${FUSE_UP_FILE}
+FUSE_FIP_DEPS += ${FUSE_UP_FILE}
+endif
+endif
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+
+ifeq (${MBEDTLS_DIR},)
+else
+ $(error Error: Trusted Board Boot with X509 certificates not supported with FUSE_PROG build option)
+endif
+
+# 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
+
+ifeq (${FUSE_INPUT_FILE},)
+FUSE_INPUT_FILE := $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/${CSF_FILE}
+endif
+
+ifeq (${FUSE_PROV_FILE},)
+else
+${BUILD_PLAT}/${FUSE_PROV_FILE_SB}: ${FUSE_PROV_FILE}
+ @echo " Generating CSF Header for $@ $<"
+ $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \
+ --app $< ${FUSE_INPUT_FILE}
+endif
+
+ifeq (${FUSE_UP_FILE},)
+else
+${BUILD_PLAT}/${FUSE_UP_FILE_SB}: ${FUSE_UP_FILE}
+ @echo " Generating CSF Header for $@ $<"
+ $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \
+ --app $< ${FUSE_INPUT_FILE}
+endif
+
+endif
+
+${BUILD_PLAT}/${FUSE_FIP_NAME}: fiptool ${FUSE_FIP_DEPS}
+ifeq (${FUSE_FIP_DEPS},)
+ $(error "Error: FUSE_PROV_FILE or/and FUSE_UP_FILE needs to point to the right file")
+endif
+ ${FIPTOOL} create ${FUSE_FIP_ARGS} $@
+ ${FIPTOOL} info $@
+ @${ECHO_BLANK_LINE}
+ @echo "Built $@ successfully"
+ @${ECHO_BLANK_LINE}
diff --git a/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h b/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h
new file mode 100644
index 0000000..e8775d0
--- /dev/null
+++ b/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef FUSE_IO_H
+#define FUSE_IO_H
+
+#include <drivers/io/io_driver.h>
+
+/* Can be overridden from platform_def.h file.
+ */
+#ifndef PLAT_FUSE_FIP_OFFSET
+#define PLAT_FUSE_FIP_OFFSET 0x880000
+#endif
+#ifndef PLAT_FUSE_FIP_MAX_SIZE
+#define PLAT_FUSE_FIP_MAX_SIZE 0x80000
+#endif
+
+int fip_fuse_provisioning(uintptr_t image_buf, uint32_t size);
+int fuse_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev);
+int plat_get_fuse_image_source(unsigned int image_id,
+ uintptr_t *dev_handle,
+ uintptr_t *image_spec,
+ int (*check)(const uintptr_t spec));
+#endif /* FUSE_IO_H */
diff --git a/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c b/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c
new file mode 100644
index 0000000..017ffcf
--- /dev/null
+++ b/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <dcfg.h>
+#include <drivers/delay_timer.h>
+#include <fuse_prov.h>
+#include <io_block.h>
+#include <io_driver.h>
+#include <io_fip.h>
+#include <io_memmap.h>
+#include <io_storage.h>
+#include <lib/utils.h>
+#include <nxp_gpio.h>
+#include <sfp.h>
+#include <sfp_error_codes.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "fuse_io.h"
+#include <load_img.h>
+#include <plat/common/platform.h>
+#include "plat_common.h"
+#include "platform_def.h"
+
+extern uintptr_t backend_dev_handle;
+
+static uint32_t fuse_fip;
+
+static uintptr_t fuse_fip_dev_handle;
+
+static io_block_spec_t fuse_fip_block_spec = {
+ .offset = PLAT_FUSE_FIP_OFFSET,
+ .length = PLAT_FUSE_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t fuse_prov_uuid_spec = {
+ .uuid = UUID_FUSE_PROV,
+};
+
+static const io_uuid_spec_t fuse_up_uuid_spec = {
+ .uuid = UUID_FUSE_UP,
+};
+
+static int open_fuse_fip(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, ARM platforms load images from the FIP */
+static const struct plat_io_policy fuse_policies[] = {
+ [FUSE_FIP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = {
+ &backend_dev_handle,
+ (uintptr_t)&fuse_fip_block_spec,
+ NULL
+ },
+ [FUSE_PROV_IMAGE_ID - FUSE_FIP_IMAGE_ID] = {
+ &fuse_fip_dev_handle,
+ (uintptr_t)&fuse_prov_uuid_spec,
+ open_fuse_fip
+ },
+ [FUSE_UP_IMAGE_ID - FUSE_FIP_IMAGE_ID] = {
+ &fuse_fip_dev_handle,
+ (uintptr_t)&fuse_up_uuid_spec,
+ open_fuse_fip
+ }
+};
+
+static int open_fuse_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fuse_fip_dev_handle, (uintptr_t)FUSE_FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fuse_fip_dev_handle,
+ spec,
+ &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+/* The image can be one of the DDR PHY images, which can be sleected via DDR
+ * policies
+ */
+int plat_get_fuse_image_source(unsigned int image_id,
+ uintptr_t *dev_handle,
+ uintptr_t *image_spec,
+ int (*check)(const uintptr_t spec))
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < (FUSE_FIP_IMAGE_ID + ARRAY_SIZE(fuse_policies)));
+
+ policy = &fuse_policies[image_id - FUSE_FIP_IMAGE_ID];
+
+ if (image_id == FUSE_FIP_IMAGE_ID) {
+ result = check(policy->image_spec);
+ } else {
+ result = policy->check(policy->image_spec);
+ }
+
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ }
+ return result;
+}
+
+int fuse_fip_setup(const io_dev_connector_t *fip_dev_con, unsigned int boot_dev)
+{
+ int io_result;
+ size_t fuse_fip_offset = PLAT_FUSE_FIP_OFFSET;
+
+ /* Open connections to fuse fip and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)&fuse_fip,
+ &fuse_fip_dev_handle);
+
+ assert(io_result == 0);
+
+ switch (boot_dev) {
+#if QSPI_BOOT
+ case BOOT_DEVICE_QSPI:
+ fuse_fip_offset += NXP_QSPI_FLASH_ADDR;
+ break;
+#endif
+#if NOR_BOOT
+ case BOOT_DEVICE_IFC_NOR:
+ fuse_fip_offset += NXP_NOR_FLASH_ADDR;
+ break;
+#endif
+#if FLEXSPI_NOR_BOOT
+ case BOOT_DEVICE_FLEXSPI_NOR:
+ fuse_fip_offset += NXP_FLEXSPI_FLASH_ADDR;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ fuse_fip_block_spec.offset = fuse_fip_offset;
+
+ return io_result;
+}
+
+int fip_fuse_provisioning(uintptr_t image_buf, uint32_t size)
+{
+ uint32_t bit_num;
+ uint32_t *gpio_base_addr = NULL;
+ struct fuse_hdr_t *fuse_hdr = NULL;
+ uint8_t barker[] = {0x68U, 0x39U, 0x27U, 0x81U};
+ int ret = -1;
+
+ if (sfp_check_oem_wp() == 0) {
+ ret = load_img(FUSE_PROV_IMAGE_ID, &image_buf, &size);
+ if (ret != 0) {
+ ERROR("Failed to load FUSE PRIV image\n");
+ assert(ret == 0);
+ }
+ fuse_hdr = (struct fuse_hdr_t *)image_buf;
+
+ /* Check barker code */
+ if (memcmp(fuse_hdr->barker, barker, sizeof(barker)) != 0) {
+ ERROR("FUSE Barker code mismatch.\n");
+ error_handler(ERROR_FUSE_BARKER);
+ return 1;
+ }
+
+ /* Check if GPIO pin to be set for POVDD */
+ if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) {
+ gpio_base_addr =
+ select_gpio_n_bitnum(fuse_hdr->povdd_gpio,
+ &bit_num);
+ /*
+ * Add delay so that Efuse gets the power
+ * when GPIO is enabled.
+ */
+ ret = set_gpio_bit(gpio_base_addr, bit_num);
+ mdelay(EFUSE_POWERUP_DELAY_mSec);
+ } else {
+ ret = (board_enable_povdd() == true) ? 0 : PLAT_ERROR_ENABLE_POVDD;
+ }
+ if (ret != 0) {
+ ERROR("Error enabling board POVDD: %d\n", ret);
+ ERROR("Only SFP mirror register will be set.\n");
+ }
+
+ provision_fuses(image_buf, ret == 0);
+
+ /* Check if GPIO pin to be reset for POVDD */
+ if (((fuse_hdr->flags >> FLAG_POVDD_SHIFT) & 0x1) != 0) {
+ if (gpio_base_addr == NULL) {
+ gpio_base_addr =
+ select_gpio_n_bitnum(
+ fuse_hdr->povdd_gpio,
+ &bit_num);
+ }
+ ret = clr_gpio_bit(gpio_base_addr, bit_num);
+ } else {
+ ret = board_disable_povdd() ? 0 : PLAT_ERROR_DISABLE_POVDD;
+ }
+
+ if (ret != 0) {
+ ERROR("Error disabling board POVDD: %d\n", ret);
+ }
+ }
+ return 0;
+}
diff --git a/plat/nxp/common/img_loadr/img_loadr.mk b/plat/nxp/common/img_loadr/img_loadr.mk
new file mode 100644
index 0000000..f64b1fa
--- /dev/null
+++ b/plat/nxp/common/img_loadr/img_loadr.mk
@@ -0,0 +1,21 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+IMG_LOADR_DRIVERS_PATH := ${PLAT_COMMON_PATH}/img_loadr
+
+IMG_LOADR_SOURCES := $(IMG_LOADR_DRIVERS_PATH)/load_img.c
+PLAT_INCLUDES += -I$(IMG_LOADR_DRIVERS_PATH)
+
+ifeq (${BL_COMM_IMG_LOADR_NEEDED},yes)
+BL_COMMON_SOURCES += ${IMG_LOADR_SOURCES}
+else
+ifeq (${BL2_IMG_LOADR_NEEDED},yes)
+BL2_SOURCES += ${IMG_LOADR_SOURCES}
+endif
+ifeq (${BL31_IMG_LOADR_NEEDED},yes)
+BL31_SOURCES += ${IMG_LOADR_SOURCES}
+endif
+endif
diff --git a/plat/nxp/common/img_loadr/load_img.c b/plat/nxp/common/img_loadr/load_img.c
new file mode 100644
index 0000000..51011e4
--- /dev/null
+++ b/plat/nxp/common/img_loadr/load_img.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include "load_img.h"
+
+/******************************************************************************
+ * This function can be used to load DDR PHY/FUSE Images
+ *
+ * @param [in] image_id Image ID to be loaded
+ *
+ * @param [in,out] image_base Location at which the image should be loaded
+ * In case image is prepended by a CSF header,
+ * image_base is pointer to actual image after
+ * the header
+ *
+ * @param [in,out] image_size User should pass the maximum size of the image
+ * possible.(Buffer size starting from image_base)
+ * Actual size of the image loaded is returned
+ * back.
+ *****************************************************************************/
+int load_img(unsigned int image_id, uintptr_t *image_base,
+ uint32_t *image_size)
+{
+ int err = 0;
+
+ image_desc_t img_info = {
+ .image_id = image_id,
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t, 0),
+#ifdef CSF_HEADER_PREPENDED
+ .image_info.image_base = *image_base - CSF_HDR_SZ,
+ .image_info.image_max_size = *image_size + CSF_HDR_SZ,
+#else
+ .image_info.image_base = *image_base,
+ .image_info.image_max_size = *image_size,
+#endif
+ };
+
+ /* Create MMU entry for the CSF header */
+#if PLAT_XLAT_TABLES_DYNAMIC
+#ifdef CSF_HEADER_PREPENDED
+ err = mmap_add_dynamic_region(img_info.image_info.image_base,
+ img_info.image_info.image_base,
+ CSF_HDR_SZ,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ if (err != 0) {
+ ERROR("Failed to add dynamic memory region.\n");
+ return err;
+ }
+#endif
+#endif
+
+ VERBOSE("BL2: Loading IMG %d\n", image_id);
+ err = load_auth_image(image_id, &img_info.image_info);
+ if (err != 0) {
+ VERBOSE("Failed to load IMG %d\n", image_id);
+ return err;
+ }
+
+#ifdef CSF_HEADER_PREPENDED
+ *image_base = img_info.image_info.image_base + CSF_HDR_SZ;
+ *image_size = img_info.image_info.image_size - CSF_HDR_SZ;
+#if PLAT_XLAT_TABLES_DYNAMIC
+ mmap_remove_dynamic_region(img_info.image_info.image_base,
+ CSF_HDR_SZ);
+#endif
+#else
+ *image_base = img_info.image_info.image_base;
+ *image_size = img_info.image_info.image_size;
+#endif
+
+ return err;
+}
diff --git a/plat/nxp/common/img_loadr/load_img.h b/plat/nxp/common/img_loadr/load_img.h
new file mode 100644
index 0000000..6f9de32
--- /dev/null
+++ b/plat/nxp/common/img_loadr/load_img.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef LOAD_IMAGE_H
+#define LOAD_IMAGE_H
+
+int load_img(unsigned int image_id, uintptr_t *image_base,
+ uint32_t *image_size);
+
+#endif /* LOAD_IMAGE_H */
diff --git a/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h b/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h
new file mode 100644
index 0000000..6296aef
--- /dev/null
+++ b/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SOC_DEFAULT_BASE_ADDR_H
+#define SOC_DEFAULT_BASE_ADDR_H
+
+/* CCSR mmu_def.h */
+#define NXP_CCSR_ADDR 0x01000000
+#define NXP_CCSR_SIZE 0x0F000000
+
+#define NXP_DCSR_ADDR 0x20000000
+#define NXP_DCSR_SIZE 0x4000000
+
+/* Flex-SPI controller address */
+#define NXP_FLEXSPI_ADDR 0x020C0000
+/* QSPI Flash Start address */
+#define NXP_QSPI_FLASH_ADDR 0x40000000
+/* NOR Flash Start address */
+#define NXP_IFC_REGION_ADDR 0x60000000
+#define NXP_NOR_FLASH_ADDR NXP_IFC_REGION_ADDR
+
+/* MMU 500 soc.c*/
+#define NXP_SMMU_ADDR 0x09000000
+
+#define NXP_SNVS_ADDR 0x01E90000
+
+#define NXP_DCFG_ADDR 0x01EE0000
+#define NXP_SFP_ADDR 0x01E80000
+#define NXP_RCPM_ADDR 0x01EE2000
+#define NXP_CSU_ADDR 0x01510000
+#define NXP_IFC_ADDR 0x01530000
+#define NXP_SCFG_ADDR 0x01570000
+#define NXP_DCSR_ADDR 0x20000000
+#define NXP_DCSR_DCFG_ADDR (NXP_DCSR_ADDR + 0x00140000)
+#define NXP_I2C_ADDR 0x02180000
+#define NXP_ESDHC_ADDR 0x01560000
+#define NXP_UART_ADDR 0x021C0500
+#define NXP_UART1_ADDR 0x021C0600
+
+#define NXP_GPIO1_ADDR 0x02300000
+#define NXP_GPIO2_ADDR 0x02310000
+#define NXP_GPIO3_ADDR 0x02320000
+#define NXP_GPIO4_ADDR 0x02330000
+
+#define NXP_WDOG1_NS_ADDR 0x02390000
+#define NXP_WDOG2_NS_ADDR 0x023A0000
+#define NXP_WDOG1_TZ_ADDR 0x023B0000
+#define NXP_WDOG2_TZ_ADDR 0x023C0000
+
+#define NXP_TIMER_STATUS_ADDR 0x023F0000
+
+#define NXP_GICD_4K_ADDR 0x01401000
+#define NXP_GICC_4K_ADDR 0x01402000
+#define NXP_GICD_64K_ADDR 0x01410000
+#define NXP_GICC_64K_ADDR 0x01420000
+
+#define NXP_CAAM_ADDR 0x01700000
+
+#define NXP_TZC_ADDR 0x01500000
+#define NXP_DDR_ADDR 0x01080000
+
+#define NXP_TIMER_ADDR 0x02B00000
+#define NXP_CCI_ADDR 0x01180000
+#define NXP_RESET_ADDR 0x01E60000
+#define NXP_SEC_REGFILE_ADDR 0x01E88000
+#endif /* SOC_DEFAULT_BASE_ADDR_H */
diff --git a/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h b/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h
new file mode 100644
index 0000000..928ac05
--- /dev/null
+++ b/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SOC_DEFAULT_HELPER_MACROS_H
+#define SOC_DEFAULT_HELPER_MACROS_H
+
+#ifdef NXP_OCRAM_TZPC_ADDR
+
+/* 0x1: means 4 KB
+ * 0x2: means 8 KB
+ */
+#define TZPC_BLOCK_SIZE 0x1000
+#endif
+
+/* DDR controller offsets and defines */
+#ifdef NXP_DDR_ADDR
+
+#define DDR_CFG_2_OFFSET 0x114
+#define CFG_2_FORCE_REFRESH 0x80000000
+
+#endif /* NXP_DDR_ADDR */
+
+ /* Reset block register offsets */
+#ifdef NXP_RESET_ADDR
+
+/* Register Offset */
+#define RST_RSTCR_OFFSET 0x0
+#define RST_RSTRQMR1_OFFSET 0x10
+#define RST_RSTRQSR1_OFFSET 0x18
+#define BRR_OFFSET 0x60
+
+/* helper macros */
+#define RSTRQSR1_SWRR 0x800
+#define RSTRQMR_RPTOE_MASK (1 << 19)
+
+#endif /* NXP_RESET_ADDR */
+
+/* Secure-Register-File register offsets and bit masks */
+#ifdef NXP_RST_ADDR
+/* Register Offset */
+#define CORE_HOLD_OFFSET 0x140
+#define RSTCNTL_OFFSET 0x180
+
+/* Helper macros */
+#define SW_RST_REQ_INIT 0x1
+#endif
+
+#ifdef NXP_RCPM_ADDR
+/* RCPM Register Offsets */
+#define RCPM_PCPH20SETR_OFFSET 0x0D4
+#define RCPM_PCPH20CLRR_OFFSET 0x0D8
+#define RCPM_POWMGTCSR_OFFSET 0x130
+#define RCPM_IPPDEXPCR0_OFFSET 0x140
+#define RCPM_POWMGTCSR_LPM20_REQ 0x00100000
+
+#define RCPM2_IPSTPCR0_OFFSET 0x8
+#define RCPM2_IPSTPCR1_OFFSET 0xC
+#define RCPM2_IPSTPCR2_OFFSET 0x10
+#define RCPM2_IPSTPCR3_OFFSET 0x14
+#define RCPM2_IPSTPCR4_OFFSET 0x28
+
+#define RCPM2_IPSTPACKR0_OFFSET 0x18
+#define RCPM2_IPSTPACKR1_OFFSET 0x1C
+#define RCPM2_IPSTPACKR2_OFFSET 0x20
+#define RCPM2_IPSTPACKR3_OFFSET 0x24
+#define RCPM2_IPSTPACKR4_OFFSET 0x2C
+#define RCPM2_POWMGTDCR_OFFSET 0x0
+
+/* bitfield masks */
+#define POWMGTDCR_OVRD_EN 0x80000000
+
+#endif /* NXP_RCPM_ADDR */
+
+#define DCFG_SBEESR2_ADDR 0x20140534
+#define DCFG_MBEESR2_ADDR 0x20140544
+/* SBEESR and MBEESR bit mask */
+#define OCRAM_EESR_MASK 0x00000060
+
+#endif /* SOC_DEFAULT_HELPER_MACROS_H */
diff --git a/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h b/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h
new file mode 100644
index 0000000..8d64f04
--- /dev/null
+++ b/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2021-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SOC_DEFAULT_BASE_ADDR_H
+#define SOC_DEFAULT_BASE_ADDR_H
+
+/* CCSR mmu_def.h */
+#define NXP_CCSR_ADDR 0x1000000
+#define NXP_CCSR_SIZE 0xF000000
+
+#define NXP_DCSR_ADDR 0x700000000
+#define NXP_DCSR_SIZE 0x40000000
+
+/* Quad SPI Region #1 base address */
+#define NXP_QSPI_FLASH_ADDR 0x20000000
+
+/* IFC Region #1 base address */
+#define NXP_NOR_FLASH_ADDR 0x30000000
+
+/* MMU 500 */
+#define NXP_SMMU_ADDR 0x05000000
+
+#define NXP_SNVS_ADDR 0x01E90000
+
+#define NXP_DCFG_ADDR 0x01E00000
+#define NXP_PMU_CCSR_ADDR 0x01E30000
+#define NXP_PMU_DCSR_ADDR 0x700123000
+#define NXP_PMU_ADDR NXP_PMU_CCSR_ADDR
+#define NXP_SFP_ADDR 0x01E80000
+#define NXP_SCFG_ADDR 0x01FC0000
+#define NXP_I2C_ADDR 0x02000000
+#define NXP_ESDHC_ADDR 0x02140000
+#define NXP_ESDHC2_ADDR 0x02150000
+#ifndef NXP_UART_ADDR
+#define NXP_UART_ADDR 0x021C0500
+#endif
+#ifndef NXP_UART1_ADDR
+#define NXP_UART1_ADDR 0x021C0600
+#endif
+
+#define NXP_GPIO1_ADDR 0x02300000
+#define NXP_GPIO2_ADDR 0x02310000
+#define NXP_GPIO3_ADDR 0x02320000
+#define NXP_GPIO4_ADDR 0x02330000
+
+#define NXP_WDOG1_NS_ADDR 0x02390000
+#define NXP_WDOG2_NS_ADDR 0x023A0000
+#define NXP_WDOG1_TZ_ADDR 0x023B0000
+#define NXP_WDOG2_TZ_ADDR 0x023C0000
+
+#define NXP_TIMER_STATUS_ADDR 0x023F0000
+
+#define NXP_GICD_ADDR 0x06000000
+#define NXP_GICR_ADDR 0x06100000
+#define NXP_GICR_SGI_ADDR 0x06110000
+
+#define NXP_CAAM_ADDR 0x08000000
+
+#define NXP_TZC_ADDR 0x01100000
+#define NXP_TZC2_ADDR 0x01110000
+#define NXP_TZC3_ADDR 0x01120000
+
+#define NXP_RESET_ADDR 0x01E60000
+#define NXP_SEC_REGFILE_ADDR 0x01E88000
+
+#define NXP_RST_ADDR 0x01E88000
+
+/* DDR memory Map */
+#define NXP_DDR_ADDR 0x01080000
+#define NXP_DDR2_ADDR 0x01090000
+#define NXP_DDR3_ADDR 0x08210000
+
+/* QuadSPI base address */
+#define NXP_QSPI_ADDR 0x020C0000
+/* IFC base address */
+#define NXP_IFC_ADDR 0x02240000
+
+/* CCI400 base address */
+#define NXP_CCI_ADDR 0x04090000
+
+/* Global Generic Reference Timer base address */
+#define NXP_TIMER_ADDR 0x023E0000
+
+/* OCRAM TZPC base address */
+#define NXP_OCRAM_TZPC_ADDR 0x02200000
+
+#define NXP_EPU_ADDR 0x700060000
+
+#define NXP_CCN_ADDR 0x04000000
+#define NXP_CCN_HNI_ADDR 0x04080000
+#define NXP_CCN_HN_F_0_ADDR 0x04200000
+#define NXP_CCN_HN_F_1_ADDR 0x04210000
+
+#define TPMWAKEMR0_ADDR 0x700123c50
+
+#endif /* SOC_DEFAULT_BASE_ADDR_H */
diff --git a/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h b/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h
new file mode 100644
index 0000000..8e68367
--- /dev/null
+++ b/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef SOC_DEFAULT_HELPER_MACROS_H
+#define SOC_DEFAULT_HELPER_MACROS_H
+
+#ifdef NXP_OCRAM_TZPC_ADDR
+#define TZPC_BLOCK_SIZE 0x1000
+#endif
+
+/* Reset block register offsets */
+#ifdef NXP_RESET_ADDR
+
+/* Register Offset */
+#define RST_RSTCR_OFFSET 0x0
+#define RST_RSTRQMR1_OFFSET 0x10
+#define RST_RSTRQSR1_OFFSET 0x18
+#define BRR_OFFSET 0x60
+
+/* helper macros */
+#define RSTRQMR_RPTOE_MASK (1 << 19)
+#endif /* NXP_RESET_ADDR */
+
+#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8
+#define PoS_CONTROL_REG_OFFSET 0x0
+#define POS_EARLY_WR_COMP_EN 0x20
+#define HNI_POS_EN 0x01
+#define POS_TERMINATE_BARRIERS 0x10
+#define SERIALIZE_DEV_nGnRnE_WRITES 0x200
+#define ENABLE_ERR_SIGNAL_TO_MN 0x4
+#define ENABLE_RESERVE_BIT53 0x400
+#define ENABLE_WUO 0x10
+
+#define PORT_S0_CTRL_REG_RNI 0x010
+#define PORT_S1_CTRL_REG_RNI 0x110
+#define PORT_S2_CTRL_REG_RNI 0x210
+#define ENABLE_FORCE_RD_QUO 0x20
+#define QOS_SETTING 0x00FF000C
+
+/* epu register offsets and values */
+#define EPU_EPGCR_OFFSET 0x0
+#define EPU_EPIMCR10_OFFSET 0x128
+#define EPU_EPCTR10_OFFSET 0xa28
+#define EPU_EPCCR10_OFFSET 0x828
+#ifndef EPU_EPCCR10_VAL
+#define EPU_EPCCR10_VAL 0xb2800000
+#endif
+#define EPU_EPIMCR10_VAL 0xba000000
+#define EPU_EPCTR10_VAL 0x0
+#define EPU_EPGCR_VAL (1 << 31)
+
+#ifdef NXP_CCN_ADDR
+#define NXP_CCN_HN_F_1_ADDR 0x04210000
+
+#define CCN_HN_F_SAM_NODEID_MASK 0x7f
+#define CCN_HN_F_SNP_DMN_CTL_OFFSET 0x200
+#define CCN_HN_F_SNP_DMN_CTL_SET_OFFSET 0x210
+#define CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET 0x220
+#define CCN_HN_F_SNP_DMN_CTL_MASK 0x80a00
+#define CCN_HNF_NODE_COUNT 8
+#define CCN_HNF_OFFSET 0x10000
+
+#define SA_AUX_CTRL_REG_OFFSET 0x500
+#define NUM_HNI_NODE 2
+#define CCN_HNI_MEMORY_MAP_SIZE 0x10000
+
+#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8
+#define PoS_CONTROL_REG_OFFSET 0x0
+#define POS_EARLY_WR_COMP_EN 0x20
+#define HNI_POS_EN 0x01
+#define POS_TERMINATE_BARRIERS 0x10
+#define SERIALIZE_DEV_nGnRnE_WRITES 0x200
+#define ENABLE_ERR_SIGNAL_TO_MN 0x4
+#define ENABLE_RESERVE_BIT53 0x400
+#define ENABLE_WUO 0x10
+#endif
+
+/* reset register bit */
+#define RSTRQMR_RPTOE_MASK (1 << 19)
+
+/* secmon register offsets and bitfields */
+#define SECMON_HPCOMR_OFFSET 0x4
+#define SECMON_HPCOMR_NPSWAEN 0x80000000
+
+/* Secure-Register-File register offsets and bit masks */
+#ifdef NXP_RST_ADDR
+/* Register Offset */
+#define CORE_HOLD_OFFSET 0x140
+#endif
+
+#define DCFG_SBEESR2_ADDR 0x00100534
+#define DCFG_MBEESR2_ADDR 0x00100544
+/* SBEESR and MBEESR bit mask */
+#define OCRAM_EESR_MASK 0x00000008
+
+#endif /* SOC_DEFAULT_HELPER_MACROS_H */
diff --git a/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h b/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h
new file mode 100644
index 0000000..0a4228b
--- /dev/null
+++ b/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SOC_DEFAULT_BASE_ADDR_H
+#define SOC_DEFAULT_BASE_ADDR_H
+
+/* CCSR mmu_def.h */
+#define NXP_CCSR_ADDR 0x1000000
+#define NXP_CCSR_SIZE 0xF000000
+
+#define NXP_DCSR_ADDR 0x700000000
+#define NXP_DCSR_SIZE 0x40000000
+
+/* Flex-SPI controller address */
+#define NXP_FLEXSPI_ADDR 0x020C0000
+/* Flex-SPI Flash Start address */
+#define NXP_FLEXSPI_FLASH_ADDR 0x20000000
+
+/* MMU 500 soc.c*/
+#define NXP_SMMU_ADDR 0x05000000
+
+/* CCI400 base address */
+#define NXP_CCI_ADDR 0x04090000
+
+#define NXP_SNVS_ADDR 0x01E90000
+
+#define NXP_DCFG_ADDR 0x01E00000
+#define NXP_PMU_CCSR_ADDR 0x01E30000
+#define NXP_PMU_DCSR_ADDR 0x700123000
+#define NXP_PMU_ADDR NXP_PMU_CCSR_ADDR
+#define NXP_SFP_ADDR 0x01E80000
+#define NXP_SCFG_ADDR 0x01FC0000
+#define NXP_I2C_ADDR 0x02000000
+#define NXP_ESDHC_ADDR 0x02140000
+#define NXP_ESDHC2_ADDR 0x02150000
+#define NXP_UART_ADDR 0x021C0000
+#define NXP_UART1_ADDR 0x021D0000
+
+#define NXP_GPIO1_ADDR 0x02300000
+#define NXP_GPIO2_ADDR 0x02310000
+#define NXP_GPIO3_ADDR 0x02320000
+#define NXP_GPIO4_ADDR 0x02330000
+
+#define NXP_WDOG1_NS_ADDR 0x02390000
+#define NXP_WDOG2_NS_ADDR 0x023A0000
+#define NXP_WDOG1_TZ_ADDR 0x023B0000
+#define NXP_WDOG2_TZ_ADDR 0x023C0000
+
+#define NXP_TIMER_STATUS_ADDR 0x023F0000
+
+#define NXP_GICD_ADDR 0x06000000
+#define NXP_GICR_ADDR 0x06200000
+#define NXP_GICR_SGI_ADDR 0x06210000
+
+#define NXP_CAAM_ADDR 0x08000000
+
+#define NXP_TZC_ADDR 0x01100000
+#define NXP_TZC2_ADDR 0x01110000
+#define NXP_TZC3_ADDR 0x01120000
+
+#define NXP_TIMER_ADDR 0x023E0000
+
+#define NXP_RESET_ADDR 0x01E60000
+#define NXP_SEC_REGFILE_ADDR 0x01E88000
+#define NXP_RST_ADDR 0x01E88000
+
+#define TPMWAKEMR0_ADDR 0x700123c50
+#define TZPC_BLOCK_SIZE 0x1000
+
+#define NXP_TZC_ADDR 0x01100000
+#define NXP_TZC2_ADDR 0x01110000
+#define NXP_TZC3_ADDR 0x01120000
+#define NXP_TZC4_ADDR 0x01130000
+#define NXP_DDR_ADDR 0x01080000
+#define NXP_DDR2_ADDR 0x01090000
+
+#define NXP_OCRAM_TZPC_ADDR 0x02200000
+
+#define NXP_CCN_ADDR 0x04000000
+#define NXP_CCN_HNI_ADDR 0x04080000
+#define NXP_CCN_HN_F_0_ADDR 0x04200000
+
+#define NXP_EPU_ADDR 0x700060000
+#endif /* SOC_DEFAULT_BASE_ADDR_H */
diff --git a/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h b/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h
new file mode 100644
index 0000000..1edd28d
--- /dev/null
+++ b/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SOC_DEFAULT_HELPER_MACROS_H
+#define SOC_DEFAULT_HELPER_MACROS_H
+
+#ifdef NXP_OCRAM_TZPC_ADDR
+
+/* 0x1: means 4 KB
+ * 0x2: means 8 KB
+ */
+#define TZPC_BLOCK_SIZE 0x1000
+#endif
+
+/* DDR controller offsets and defines */
+#ifdef NXP_DDR_ADDR
+
+#define DDR_CFG_2_OFFSET 0x114
+#define CFG_2_FORCE_REFRESH 0x80000000
+
+#endif /* NXP_DDR_ADDR */
+
+ /* Reset block register offsets */
+#ifdef NXP_RESET_ADDR
+
+/* Register Offset */
+#define RST_RSTCR_OFFSET 0x0
+#define RST_RSTRQMR1_OFFSET 0x10
+#define RST_RSTRQSR1_OFFSET 0x18
+#define BRR_OFFSET 0x60
+
+/* helper macros */
+#define RSTRQSR1_SWRR 0x800
+#define RSTRQMR_RPTOE_MASK (1 << 19)
+
+#endif /* NXP_RESET_ADDR */
+
+/* secmon register offsets and bitfields */
+#define SECMON_HPCOMR_OFFSET 0x4
+#define SECMON_HPCOMR_NPSWAEN 0x80000000
+
+/* Secure-Register-File register offsets and bit masks */
+#ifdef NXP_RST_ADDR
+/* Register Offset */
+#define CORE_HOLD_OFFSET 0x140
+#define RSTCNTL_OFFSET 0x180
+
+/* Helper macros */
+#define SW_RST_REQ_INIT 0x1
+#endif
+
+#ifdef NXP_CCN_ADDR
+#define NXP_CCN_HN_F_1_ADDR 0x04210000
+
+#define CCN_HN_F_SAM_NODEID_MASK 0x7f
+#define CCN_HN_F_SNP_DMN_CTL_OFFSET 0x200
+#define CCN_HN_F_SNP_DMN_CTL_SET_OFFSET 0x210
+#define CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET 0x220
+#define CCN_HN_F_SNP_DMN_CTL_MASK 0x80a00
+#define CCN_HNF_NODE_COUNT 8
+#define CCN_HNF_OFFSET 0x10000
+
+#define SA_AUX_CTRL_REG_OFFSET 0x500
+#define NUM_HNI_NODE 2
+#define CCN_HNI_MEMORY_MAP_SIZE 0x10000
+
+#define PCIeRC_RN_I_NODE_ID_OFFSET 0x8
+#define PoS_CONTROL_REG_OFFSET 0x0
+#define POS_EARLY_WR_COMP_EN 0x20
+#define HNI_POS_EN 0x01
+#define POS_TERMINATE_BARRIERS 0x10
+#define SERIALIZE_DEV_nGnRnE_WRITES 0x200
+#define ENABLE_ERR_SIGNAL_TO_MN 0x4
+#define ENABLE_RESERVE_BIT53 0x400
+#define ENABLE_WUO 0x10
+#endif /* NXP_CCN_ADDR */
+
+#define DCFG_SBEESR2_ADDR 0x00100534
+#define DCFG_MBEESR2_ADDR 0x00100544
+/* SBEESR and MBEESR bit mask */
+#define OCRAM_EESR_MASK 0x00000008
+
+#endif /* SOC_DEFAULT_HELPER_MACROS_H */
diff --git a/plat/nxp/common/include/default/plat_default_def.h b/plat/nxp/common/include/default/plat_default_def.h
new file mode 100644
index 0000000..43320bb
--- /dev/null
+++ b/plat/nxp/common/include/default/plat_default_def.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_DEFAULT_DEF_H
+#define PLAT_DEFAULT_DEF_H
+
+/*
+ * Platform binary types for linking
+ */
+#ifdef __aarch64__
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+#else
+#define PLATFORM_LINKER_FORMAT "elf32-littlearm"
+#define PLATFORM_LINKER_ARCH arm
+#endif /* __aarch64__ */
+
+#define LS_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+/* NXP Platforms have DRAM divided into banks.
+ * DRAM0 Bank: Maximum size of this bank is fixed to 2GB
+ * DRAM1 Bank: Greater than 2GB belongs to bank1 and size of bank1 varies from
+ * one platform to other platform.
+ * DRAMn Bank:
+ *
+ * Except a few, all the platforms have 2GB size as DRAM0 BANK.
+ * Hence common for all the platforms.
+ * For platforms where DRAM0 Size is < 2GB, it is defined in platform_def.h
+ */
+#ifndef PLAT_DEF_DRAM0_SIZE
+#define PLAT_DEF_DRAM0_SIZE 0x80000000 /* 2G */
+#endif
+
+/* This is common for all platforms where: */
+#ifndef NXP_NS_DRAM_ADDR
+#define NXP_NS_DRAM_ADDR NXP_DRAM0_ADDR
+#endif
+
+/* 1 MB is reserved for dma of sd */
+#ifndef NXP_SD_BLOCK_BUF_SIZE
+#define NXP_SD_BLOCK_BUF_SIZE (1 * 1024 * 1024)
+#endif
+
+/* 64MB is reserved for Secure memory */
+#ifndef NXP_SECURE_DRAM_SIZE
+#define NXP_SECURE_DRAM_SIZE (64 * 1024 * 1024)
+#endif
+
+/* 2M Secure EL1 Payload Shared Memory */
+#ifndef NXP_SP_SHRD_DRAM_SIZE
+#define NXP_SP_SHRD_DRAM_SIZE (2 * 1024 * 1024)
+#endif
+
+#ifndef NXP_NS_DRAM_SIZE
+/* Non secure memory */
+#define NXP_NS_DRAM_SIZE (PLAT_DEF_DRAM0_SIZE - \
+ (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE))
+#endif
+
+#ifndef NXP_SD_BLOCK_BUF_ADDR
+#define NXP_SD_BLOCK_BUF_ADDR (NXP_NS_DRAM_ADDR)
+#endif
+
+#ifndef NXP_SECURE_DRAM_ADDR
+#ifdef TEST_BL31
+#define NXP_SECURE_DRAM_ADDR 0
+#else
+#define NXP_SECURE_DRAM_ADDR (NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \
+ (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE))
+#endif
+#endif
+
+#ifndef NXP_SP_SHRD_DRAM_ADDR
+#define NXP_SP_SHRD_DRAM_ADDR (NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \
+ NXP_SP_SHRD_DRAM_SIZE)
+#endif
+
+#ifndef BL31_BASE
+/* 2 MB reserved in secure memory for DDR */
+#define BL31_BASE NXP_SECURE_DRAM_ADDR
+#endif
+
+#ifndef BL31_SIZE
+#define BL31_SIZE (0x200000)
+#endif
+
+#ifndef BL31_LIMIT
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+#endif
+
+/* Put BL32 in secure memory */
+#ifndef BL32_BASE
+#define BL32_BASE (NXP_SECURE_DRAM_ADDR + BL31_SIZE)
+#endif
+
+#ifndef BL32_LIMIT
+#define BL32_LIMIT (NXP_SECURE_DRAM_ADDR + \
+ NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)
+#endif
+
+/* BL33 memory region */
+/* Hardcoded based on current address in u-boot */
+#ifndef BL33_BASE
+#define BL33_BASE 0x82000000
+#endif
+
+#ifndef BL33_LIMIT
+#define BL33_LIMIT (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE)
+#endif
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#ifndef FUSE_BUF
+#define FUSE_BUF ULL(0x81000000)
+#endif
+
+#ifndef FUSE_SZ
+#define FUSE_SZ 0x80000
+#endif
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 2
+#endif
+
+#ifndef PLAT_FIP_OFFSET
+#define PLAT_FIP_OFFSET 0x100000
+#endif
+
+#ifndef PLAT_FIP_MAX_SIZE
+#define PLAT_FIP_MAX_SIZE 0x400000
+#endif
+
+/* Check if this size can be determined from array size */
+#if defined(IMAGE_BL2)
+#ifndef MAX_MMAP_REGIONS
+#define MAX_MMAP_REGIONS 8
+#endif
+#ifndef MAX_XLAT_TABLES
+#define MAX_XLAT_TABLES 6
+#endif
+#elif defined(IMAGE_BL31)
+#ifndef MAX_MMAP_REGIONS
+#define MAX_MMAP_REGIONS 9
+#endif
+#ifndef MAX_XLAT_TABLES
+#define MAX_XLAT_TABLES 9
+#endif
+#elif defined(IMAGE_BL32)
+#ifndef MAX_MMAP_REGIONS
+#define MAX_MMAP_REGIONS 8
+#endif
+#ifndef MAX_XLAT_TABLES
+#define MAX_XLAT_TABLES 9
+#endif
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#ifndef BL32_IRQ_SEC_PHY_TIMER
+#define BL32_IRQ_SEC_PHY_TIMER 29
+#endif
+
+#endif /* PLAT_DEFAULT_DEF_H */
diff --git a/plat/nxp/common/nv_storage/nv_storage.mk b/plat/nxp/common/nv_storage/nv_storage.mk
new file mode 100644
index 0000000..dddba5f
--- /dev/null
+++ b/plat/nxp/common/nv_storage/nv_storage.mk
@@ -0,0 +1,29 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# NXP Non-Volatile data flag storage used and then cleared by SW on boot-up
+
+$(eval $(call add_define,NXP_NV_SW_MAINT_LAST_EXEC_DATA))
+
+ifeq ($(NXP_COINED_BB),yes)
+$(eval $(call add_define,NXP_COINED_BB))
+# BL2 : To read the reset cause from LP SECMON GPR register
+# BL31: To write the reset cause to LP SECMON GPR register
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL_COMM))
+
+# BL2: DDR training data is stored on Flexspi NOR.
+ifneq (${BOOT_MODE},flexspi_nor)
+$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2))
+endif
+
+else
+$(eval $(call add_define_val,DEFAULT_NV_STORAGE_BASE_ADDR,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - 2 * ${NXP_XSPI_NOR_UNIT_SIZE}'))
+$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL_COMM))
+endif
+
+NV_STORAGE_INCLUDES += -I${PLAT_COMMON_PATH}/nv_storage
+
+NV_STORAGE_SOURCES += ${PLAT_COMMON_PATH}/nv_storage/plat_nv_storage.c
diff --git a/plat/nxp/common/nv_storage/plat_nv_storage.c b/plat/nxp/common/nv_storage/plat_nv_storage.c
new file mode 100644
index 0000000..af3b966
--- /dev/null
+++ b/plat/nxp/common/nv_storage/plat_nv_storage.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <platform_def.h>
+#include <common/debug.h>
+#ifndef NXP_COINED_BB
+#include <flash_info.h>
+#include <fspi.h>
+#include <fspi_api.h>
+#endif
+#include <lib/mmio.h>
+#ifdef NXP_COINED_BB
+#include <snvs.h>
+#else
+#include <xspi_error_codes.h>
+#endif
+
+#include <plat_nv_storage.h>
+
+/*This structure will be a static structure and
+ * will be populated as first step of BL2 booting-up.
+ * fspi_strorage.c . To be located in the fspi driver folder.
+ */
+
+static nv_app_data_t nv_app_data;
+
+int read_nv_app_data(void)
+{
+ int ret = 0;
+
+#ifdef NXP_COINED_BB
+ uint8_t *nv_app_data_array = (uint8_t *) &nv_app_data;
+ uint8_t offset = 0U;
+
+ ret = snvs_read_app_data();
+ do {
+ nv_app_data_array[offset] = snvs_read_app_data_bit(offset);
+ offset++;
+
+ } while (offset < APP_DATA_MAX_OFFSET);
+ snvs_clear_app_data();
+#else
+ uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR;
+
+ ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR);
+
+ if (ret != XSPI_SUCCESS) {
+ ERROR("Failed to initialized driver flexspi-nor.\n");
+ ERROR("exiting warm-reset request.\n");
+ return -ENODEV;
+ }
+
+ xspi_read(nv_base_addr,
+ (uint32_t *)&nv_app_data, sizeof(nv_app_data_t));
+ xspi_sector_erase((uint32_t) nv_base_addr,
+ F_SECTOR_ERASE_SZ);
+#endif
+ return ret;
+}
+
+int wr_nv_app_data(int data_offset,
+ uint8_t *data,
+ int data_size)
+{
+ int ret = 0;
+#ifdef NXP_COINED_BB
+#if !TRUSTED_BOARD_BOOT
+ snvs_disable_zeroize_lp_gpr();
+#endif
+ /* In case LP SecMon General purpose register,
+ * only 1 bit flags can be saved.
+ */
+ if ((data_size > 1) || (*data != DEFAULT_SET_VALUE)) {
+ ERROR("Only binary value is allowed to be written.\n");
+ ERROR("Use flash instead of SNVS GPR as NV location.\n");
+ return -ENODEV;
+ }
+ snvs_write_app_data_bit(data_offset);
+#else
+ uint8_t read_val[sizeof(nv_app_data_t)];
+ uint8_t ready_to_write_val[sizeof(nv_app_data_t)];
+ uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR;
+
+ assert((nv_base_addr + data_offset + data_size) > (nv_base_addr + F_SECTOR_ERASE_SZ));
+
+ ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR);
+
+ if (ret != XSPI_SUCCESS) {
+ ERROR("Failed to initialized driver flexspi-nor.\n");
+ ERROR("exiting warm-reset request.\n");
+ return -ENODEV;
+ }
+
+ ret = xspi_read(nv_base_addr + data_offset, (uint32_t *)read_val, data_size);
+
+ memset(ready_to_write_val, READY_TO_WRITE_VALUE, ARRAY_SIZE(ready_to_write_val));
+
+ if (memcmp(read_val, ready_to_write_val, data_size) == 0) {
+ xspi_write(nv_base_addr + data_offset, data, data_size);
+ }
+#endif
+
+ return ret;
+}
+
+const nv_app_data_t *get_nv_data(void)
+{
+ return (const nv_app_data_t *) &nv_app_data;
+}
diff --git a/plat/nxp/common/nv_storage/plat_nv_storage.h b/plat/nxp/common/nv_storage/plat_nv_storage.h
new file mode 100644
index 0000000..1f5264a
--- /dev/null
+++ b/plat/nxp/common/nv_storage/plat_nv_storage.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_NV_STRG_H
+#define PLAT_NV_STRG_H
+
+#define DEFAULT_SET_VALUE 0xA1
+#define READY_TO_WRITE_VALUE 0xFF
+
+#ifndef NV_STORAGE_BASE_ADDR
+#define NV_STORAGE_BASE_ADDR DEFAULT_NV_STORAGE_BASE_ADDR
+#endif
+
+typedef struct {
+uint8_t warm_rst_flag;
+uint8_t wdt_rst_flag;
+uint8_t dummy[2];
+} nv_app_data_t;
+
+
+/*below enum and above structure should be in-sync. */
+enum app_data_offset {
+ WARM_RESET_FLAG_OFFSET,
+ WDT_RESET_FLAG_OFFSET,
+ APP_DATA_MAX_OFFSET,
+};
+
+int read_nv_app_data(void);
+
+int wr_nv_app_data(int data_offset,
+ uint8_t *data,
+ int data_size);
+
+const nv_app_data_t *get_nv_data(void);
+
+#endif /* PLAT_NV_STRG_H */
diff --git a/plat/nxp/common/ocram/aarch64/ocram.S b/plat/nxp/common/ocram/aarch64/ocram.S
new file mode 100644
index 0000000..ec53341
--- /dev/null
+++ b/plat/nxp/common/ocram/aarch64/ocram.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+#include <soc_default_base_addr.h>
+#include <soc_default_helper_macros.h>
+
+.global ocram_init
+
+/*
+ * void ocram_init(uintptr_t start_addr, size_t size)
+ *
+ * This function will do OCRAM ECC.
+ * OCRAM is initialized with 64-bit writes and then a write
+ * performed to address 0x0010_0534 with the value 0x0000_0008.
+ *
+ * x0: start_addr
+ * x1: size in bytes
+ * Called from C
+ */
+
+func ocram_init
+ /* save the aarch32/64 non-volatile registers */
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ /* convert bytes to 64-byte chunks */
+ lsr x1, x1, #6
+1:
+ /* for each location, read and write-back */
+ dc ivac, x0
+ dsb sy
+ ldp x4, x5, [x0]
+ ldp x6, x7, [x0, #16]
+ ldp x8, x9, [x0, #32]
+ ldp x10, x11, [x0, #48]
+ stp x4, x5, [x0]
+ stp x6, x7, [x0, #16]
+ stp x8, x9, [x0, #32]
+ stp x10, x11, [x0, #48]
+ dc cvac, x0
+
+ sub x1, x1, #1
+ cbz x1, 2f
+ add x0, x0, #64
+ b 1b
+2:
+ /* Clear OCRAM ECC status bit in SBEESR2 and MBEESR2 */
+ ldr w1, =OCRAM_EESR_MASK
+ ldr x0, =DCFG_SBEESR2_ADDR
+ str w1, [x0]
+ ldr x0, =DCFG_MBEESR2_ADDR
+ str w1, [x0]
+
+ /* restore the aarch32/64 non-volatile registers */
+ ldp x18, x30, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ ret
+endfunc ocram_init
diff --git a/plat/nxp/common/ocram/ocram.h b/plat/nxp/common/ocram/ocram.h
new file mode 100644
index 0000000..479de61
--- /dev/null
+++ b/plat/nxp/common/ocram/ocram.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef OCRAM_H
+#define OCRAM_H
+
+void ocram_init(uintptr_t start_addr, size_t size);
+
+#endif /* OCRAM_H */
diff --git a/plat/nxp/common/ocram/ocram.mk b/plat/nxp/common/ocram/ocram.mk
new file mode 100644
index 0000000..c77bd4a
--- /dev/null
+++ b/plat/nxp/common/ocram/ocram.mk
@@ -0,0 +1,14 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+PLAT_OCRAM_PATH := $(PLAT_COMMON_PATH)/ocram
+
+OCRAM_SOURCES := ${PLAT_OCRAM_PATH}/$(ARCH)/ocram.S
+
+BL2_SOURCES += ${OCRAM_SOURCES}
+
+PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/ocram
diff --git a/plat/nxp/common/plat_make_helper/plat_build_macros.mk b/plat/nxp/common/plat_make_helper/plat_build_macros.mk
new file mode 100644
index 0000000..bba5e36
--- /dev/null
+++ b/plat/nxp/common/plat_make_helper/plat_build_macros.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2020, NXP.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+define SET_NXP_MAKE_FLAG
+$1 := yes
+$2_$1 := yes
+endef
diff --git a/plat/nxp/common/plat_make_helper/plat_common_def.mk b/plat/nxp/common/plat_make_helper/plat_common_def.mk
new file mode 100644
index 0000000..86dacf8
--- /dev/null
+++ b/plat/nxp/common/plat_make_helper/plat_common_def.mk
@@ -0,0 +1,103 @@
+# Copyright 2020-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Include build macros, for example: SET_NXP_MAKE_FLAG
+include plat/nxp/common/plat_make_helper/plat_build_macros.mk
+
+# Adding platform specific defines
+
+$(eval $(call add_define_val,BOARD,'"${BOARD}"'))
+
+ifeq (${POVDD_ENABLE},yes)
+$(eval $(call add_define,CONFIG_POVDD_ENABLE))
+endif
+
+ifneq (${FLASH_TYPE},)
+$(eval $(call add_define,CONFIG_${FLASH_TYPE}))
+endif
+
+ifneq (${XSPI_FLASH_SZ},)
+$(eval $(call add_define_val,NXP_FLEXSPI_FLASH_SIZE,${XSPI_FLASH_SZ}))
+endif
+
+ifneq (${QSPI_FLASH_SZ},)
+$(eval $(call add_define_val,NXP_QSPI_FLASH_SIZE,${QSPI_FLASH_SZ}))
+endif
+
+ifneq (${NOR_FLASH_SZ},)
+$(eval $(call add_define_val,NXP_NOR_FLASH_SIZE,${NOR_FLASH_SZ}))
+endif
+
+
+ifneq (${FSPI_ERASE_4K},)
+$(eval $(call add_define_val,CONFIG_FSPI_ERASE_4K,${FSPI_ERASE_4K}))
+endif
+
+ifneq (${NUM_OF_DDRC},)
+$(eval $(call add_define_val,NUM_OF_DDRC,${NUM_OF_DDRC}))
+endif
+
+ifeq (${CONFIG_DDR_NODIMM},1)
+$(eval $(call add_define,CONFIG_DDR_NODIMM))
+DDRC_NUM_DIMM := 1
+endif
+
+ifneq (${DDRC_NUM_DIMM},)
+$(eval $(call add_define_val,DDRC_NUM_DIMM,${DDRC_NUM_DIMM}))
+endif
+
+ifneq (${DDRC_NUM_CS},)
+$(eval $(call add_define_val,DDRC_NUM_CS,${DDRC_NUM_CS}))
+endif
+
+ifeq (${DDR_ADDR_DEC},yes)
+$(eval $(call add_define,CONFIG_DDR_ADDR_DEC))
+endif
+
+ifeq (${DDR_ECC_EN},yes)
+$(eval $(call add_define,CONFIG_DDR_ECC_EN))
+endif
+
+ifeq (${CONFIG_STATIC_DDR},1)
+$(eval $(call add_define,CONFIG_STATIC_DDR))
+endif
+
+# Platform can control the base address for non-volatile storage.
+#$(eval $(call add_define_val,NV_STORAGE_BASE_ADDR,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - 2 * ${NXP_XSPI_NOR_UNIT_SIZE}'))
+
+ifeq (${WARM_BOOT},yes)
+$(eval $(call add_define_val,PHY_TRAINING_REGS_ON_FLASH,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - ${NXP_XSPI_NOR_UNIT_SIZE}'))
+endif
+
+# Selecting Boot Source for the TFA images.
+define add_boot_mode_define
+ ifeq ($(1),qspi)
+ $$(eval $$(call SET_NXP_MAKE_FLAG,QSPI_NEEDED,BL2))
+ $$(eval $$(call add_define,QSPI_BOOT))
+ else ifeq ($(1),sd)
+ $$(eval $$(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2))
+ $$(eval $$(call add_define,SD_BOOT))
+ else ifeq ($(1),emmc)
+ $$(eval $$(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2))
+ $$(eval $$(call add_define,EMMC_BOOT))
+ else ifeq ($(1),nor)
+ $$(eval $$(call SET_NXP_MAKE_FLAG,IFC_NOR_NEEDED,BL2))
+ $$(eval $$(call add_define,NOR_BOOT))
+ else ifeq ($(1),nand)
+ $$(eval $$(call SET_NXP_MAKE_FLAG,IFC_NAND_NEEDED,BL2))
+ $$(eval $$(call add_define,NAND_BOOT))
+ else ifeq ($(1),flexspi_nor)
+ $$(eval $$(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2))
+ $$(eval $$(call add_define,FLEXSPI_NOR_BOOT))
+ else
+ $$(error $(PLAT) Cannot Support Boot Mode: $(BOOT_MODE))
+ endif
+endef
+
+ifneq (,$(findstring $(BOOT_MODE),$(SUPPORTED_BOOT_MODE)))
+ $(eval $(call add_boot_mode_define,$(strip $(BOOT_MODE))))
+else
+ $(error $(PLAT) Un-supported Boot Mode = $(BOOT_MODE))
+endif
diff --git a/plat/nxp/common/plat_make_helper/soc_common_def.mk b/plat/nxp/common/plat_make_helper/soc_common_def.mk
new file mode 100644
index 0000000..52f2867
--- /dev/null
+++ b/plat/nxp/common/plat_make_helper/soc_common_def.mk
@@ -0,0 +1,117 @@
+# Copyright 2020-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Adding SoC specific defines
+
+ifneq (${CACHE_LINE},)
+$(eval $(call add_define_val,PLATFORM_CACHE_LINE_SHIFT,${CACHE_LINE}))
+$(eval CACHE_WRITEBACK_GRANULE=$(shell echo $$((1 << $(CACHE_LINE)))))
+$(eval $(call add_define_val,CACHE_WRITEBACK_GRANULE,$(CACHE_WRITEBACK_GRANULE)))
+endif
+
+ifneq (${INTERCONNECT},)
+$(eval $(call add_define,NXP_HAS_${INTERCONNECT}))
+ifeq (${INTERCONNECT}, CCI400)
+ICNNCT_ID := 0x420
+$(eval $(call add_define,ICNNCT_ID))
+endif
+endif
+
+ifneq (${CHASSIS},)
+$(eval $(call add_define,CONFIG_CHASSIS_${CHASSIS}))
+endif
+
+ifneq (${PLAT_DDR_PHY},)
+$(eval $(call add_define,NXP_DDR_${PLAT_DDR_PHY}))
+endif
+
+ifneq (${PHYS_SYS},)
+$(eval $(call add_define,CONFIG_PHYS_64BIT))
+endif
+
+ifneq (${CSF_HDR_SZ},)
+$(eval $(call add_define_val,CSF_HDR_SZ,${CSF_HDR_SZ}))
+endif
+
+ifneq (${OCRAM_START_ADDR},)
+$(eval $(call add_define_val,NXP_OCRAM_ADDR,${OCRAM_START_ADDR}))
+endif
+
+ifneq (${OCRAM_SIZE},)
+$(eval $(call add_define_val,NXP_OCRAM_SIZE,${OCRAM_SIZE}))
+endif
+
+ifneq (${NXP_ROM_RSVD},)
+$(eval $(call add_define_val,NXP_ROM_RSVD,${NXP_ROM_RSVD}))
+endif
+
+ifneq (${BL2_BASE},)
+$(eval $(call add_define_val,BL2_BASE,${BL2_BASE}))
+endif
+
+ifeq (${SEC_MEM_NON_COHERENT},yes)
+$(eval $(call add_define,SEC_MEM_NON_COHERENT))
+endif
+
+ifneq (${NXP_ESDHC_ENDIANNESS},)
+$(eval $(call add_define,NXP_ESDHC_${NXP_ESDHC_ENDIANNESS}))
+endif
+
+ifneq (${NXP_SFP_VER},)
+$(eval $(call add_define,NXP_SFP_VER_${NXP_SFP_VER}))
+endif
+
+ifneq (${NXP_SFP_ENDIANNESS},)
+$(eval $(call add_define,NXP_SFP_${NXP_SFP_ENDIANNESS}))
+endif
+
+ifneq (${NXP_GPIO_ENDIANNESS},)
+$(eval $(call add_define,NXP_GPIO_${NXP_GPIO_ENDIANNESS}))
+endif
+
+ifneq (${NXP_SNVS_ENDIANNESS},)
+$(eval $(call add_define,NXP_SNVS_${NXP_SNVS_ENDIANNESS}))
+endif
+
+ifneq (${NXP_GUR_ENDIANNESS},)
+$(eval $(call add_define,NXP_GUR_${NXP_GUR_ENDIANNESS}))
+endif
+
+ifneq (${NXP_FSPI_ENDIANNESS},)
+$(eval $(call add_define,NXP_FSPI_${NXP_FSPI_ENDIANNESS}))
+endif
+
+ifneq (${NXP_SEC_ENDIANNESS},)
+$(eval $(call add_define,NXP_SEC_${NXP_SEC_ENDIANNESS}))
+endif
+
+ifneq (${NXP_DDR_ENDIANNESS},)
+$(eval $(call add_define,NXP_DDR_${NXP_DDR_ENDIANNESS}))
+endif
+
+ifneq (${NXP_QSPI_ENDIANNESS},)
+$(eval $(call add_define,NXP_QSPI_${NXP_QSPI_ENDIANNESS}))
+endif
+
+ifneq (${NXP_SCFG_ENDIANNESS},)
+$(eval $(call add_define,NXP_SCFG_${NXP_SCFG_ENDIANNESS}))
+endif
+
+ifneq (${NXP_IFC_ENDIANNESS},)
+$(eval $(call add_define,NXP_IFC_${NXP_IFC_ENDIANNESS}))
+endif
+
+ifneq (${NXP_DDR_INTLV_256B},)
+$(eval $(call add_define,NXP_DDR_INTLV_256B))
+endif
+
+ifneq (${PLAT_XLAT_TABLES_DYNAMIC},)
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
+endif
+
+ifeq (${OCRAM_ECC_EN},yes)
+$(eval $(call add_define,CONFIG_OCRAM_ECC_EN))
+include ${PLAT_COMMON_PATH}/ocram/ocram.mk
+endif
diff --git a/plat/nxp/common/psci/aarch64/psci_utils.S b/plat/nxp/common/psci/aarch64/psci_utils.S
new file mode 100644
index 0000000..ec69aea
--- /dev/null
+++ b/plat/nxp/common/psci/aarch64/psci_utils.S
@@ -0,0 +1,1155 @@
+
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+
+#include <lib/psci/psci.h>
+
+#include <bl31_data.h>
+#include <plat_psci.h>
+
+
+#define RESET_RETRY_CNT 800
+#define PSCI_ABORT_CNT 100
+
+#if (SOC_CORE_RELEASE)
+
+.global _psci_cpu_on
+
+/*
+ * int _psci_cpu_on(u_register_t core_mask)
+ * x0 = target cpu core mask
+ *
+ * Called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ *
+ */
+
+func _psci_cpu_on
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x6, x0
+
+ /* x0 = core mask (lsb)
+ * x6 = core mask (lsb)
+ */
+
+ /* check if core disabled */
+ bl _soc_ck_disabled /* 0-2 */
+ cbnz w0, psci_disabled
+
+ /* check core data area to see if core cannot be turned on
+ * read the core state
+ */
+ mov x0, x6
+ bl _getCoreState /* 0-5 */
+ mov x9, x0
+
+ /* x6 = core mask (lsb)
+ * x9 = core state (from data area)
+ */
+
+ cmp x9, #CORE_DISABLED
+ mov x0, #PSCI_E_DISABLED
+ b.eq cpu_on_done
+
+ cmp x9, #CORE_PENDING
+ mov x0, #PSCI_E_ON_PENDING
+ b.eq cpu_on_done
+
+ cmp x9, #CORE_RELEASED
+ mov x0, #PSCI_E_ALREADY_ON
+ b.eq cpu_on_done
+
+8:
+ /* x6 = core mask (lsb)
+ * x9 = core state (from data area)
+ */
+
+ cmp x9, #CORE_WFE
+ b.eq core_in_wfe
+ cmp x9, #CORE_IN_RESET
+ b.eq core_in_reset
+ cmp x9, #CORE_OFF
+ b.eq core_is_off
+ cmp x9, #CORE_OFF_PENDING
+
+ /* if state == CORE_OFF_PENDING, set abort */
+ mov x0, x6
+ mov x1, #ABORT_FLAG_DATA
+ mov x2, #CORE_ABORT_OP
+ bl _setCoreData /* 0-3, [13-15] */
+
+ ldr x3, =PSCI_ABORT_CNT
+7:
+ /* watch for abort to take effect */
+ mov x0, x6
+ bl _getCoreState /* 0-5 */
+ cmp x0, #CORE_OFF
+ b.eq core_is_off
+ cmp x0, #CORE_PENDING
+ mov x0, #PSCI_E_SUCCESS
+ b.eq cpu_on_done
+
+ /* loop til finished */
+ sub x3, x3, #1
+ cbnz x3, 7b
+
+ /* if we didn't see either CORE_OFF or CORE_PENDING, then this
+ * core is in CORE_OFF_PENDING - exit with success, as the core will
+ * respond to the abort request
+ */
+ mov x0, #PSCI_E_SUCCESS
+ b cpu_on_done
+
+/* this is where we start up a core out of reset */
+core_in_reset:
+ /* see if the soc-specific module supports this op */
+ ldr x7, =SOC_CORE_RELEASE
+ cbnz x7, 3f
+
+ mov x0, #PSCI_E_NOT_SUPPORTED
+ b cpu_on_done
+
+ /* x6 = core mask (lsb) */
+3:
+ /* set core state in data area */
+ mov x0, x6
+ mov x1, #CORE_PENDING
+ bl _setCoreState /* 0-3, [13-15] */
+
+ /* release the core from reset */
+ mov x0, x6
+ bl _soc_core_release /* 0-3 */
+ mov x0, #PSCI_E_SUCCESS
+ b cpu_on_done
+
+ /* Start up the core that has been powered-down via CPU_OFF
+ */
+core_is_off:
+ /* see if the soc-specific module supports this op
+ */
+ ldr x7, =SOC_CORE_RESTART
+ cbnz x7, 2f
+
+ mov x0, #PSCI_E_NOT_SUPPORTED
+ b cpu_on_done
+
+ /* x6 = core mask (lsb) */
+2:
+ /* set core state in data area */
+ mov x0, x6
+ mov x1, #CORE_WAKEUP
+ bl _setCoreState /* 0-3, [13-15] */
+
+ /* put the core back into service */
+ mov x0, x6
+#if (SOC_CORE_RESTART)
+ bl _soc_core_restart /* 0-5 */
+#endif
+ mov x0, #PSCI_E_SUCCESS
+ b cpu_on_done
+
+/* this is where we release a core that is being held in wfe */
+core_in_wfe:
+ /* x6 = core mask (lsb) */
+
+ /* set core state in data area */
+ mov x0, x6
+ mov x1, #CORE_PENDING
+ bl _setCoreState /* 0-3, [13-15] */
+ dsb sy
+ isb
+
+ /* put the core back into service */
+ sev
+ sev
+ isb
+ mov x0, #PSCI_E_SUCCESS
+
+cpu_on_done:
+ /* restore the aarch32/64 non-volatile registers */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_cpu_on
+
+#endif
+
+
+#if (SOC_CORE_OFF)
+
+.global _psci_cpu_prep_off
+.global _psci_cpu_off_wfi
+
+/*
+ * void _psci_cpu_prep_off(u_register_t core_mask)
+ * this function performs the SoC-specific programming prior
+ * to shutting the core down
+ * x0 = core_mask
+ *
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_cpu_prep_off
+
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x10, x0 /* x10 = core_mask */
+
+ /* the core does not return from cpu_off, so no need
+ * to save/restore non-volatile registers
+ */
+
+ /* mask interrupts by setting DAIF[7:4] to 'b1111 */
+ msr DAIFSet, #0xF
+
+ /* read cpuectlr and save current value */
+ mrs x4, CPUECTLR_EL1
+ mov x1, #CPUECTLR_DATA
+ mov x2, x4
+ mov x0, x10
+ bl _setCoreData
+
+ /* remove the core from coherency */
+ bic x4, x4, #CPUECTLR_SMPEN_MASK
+ msr CPUECTLR_EL1, x4
+
+ /* save scr_el3 */
+ mov x0, x10
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* x4 = scr_el3 */
+
+ /* secure SGI (FIQ) taken to EL3, set SCR_EL3[FIQ] */
+ orr x4, x4, #SCR_FIQ_MASK
+ msr scr_el3, x4
+
+ /* x10 = core_mask */
+
+ /* prep the core for shutdown */
+ mov x0, x10
+ bl _soc_core_prep_off
+
+ /* restore the aarch32/64 non-volatile registers */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_cpu_prep_off
+
+/*
+ * void _psci_cpu_off_wfi(u_register_t core_mask, u_register_t resume_addr)
+ * - this function shuts down the core
+ * - this function does not return!!
+ */
+
+func _psci_cpu_off_wfi
+ /* save the wakeup address */
+ mov x29, x1
+
+ /* x0 = core_mask */
+
+ /* shutdown the core */
+ bl _soc_core_entr_off
+
+ /* branch to resume execution */
+ br x29
+endfunc _psci_cpu_off_wfi
+
+#endif
+
+
+#if (SOC_CORE_RESTART)
+
+.global _psci_wakeup
+
+/*
+ * void _psci_wakeup(u_register_t core_mask)
+ * this function performs the SoC-specific programming
+ * after a core wakes up from OFF
+ * x0 = core mask
+ *
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_wakeup
+
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x4, x0 /* x4 = core mask */
+
+ /* restore scr_el3 */
+ mov x0, x4
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ /* x4 = core mask */
+
+ /* restore CPUECTLR */
+ mov x0, x4
+ mov x1, #CPUECTLR_DATA
+ bl _getCoreData
+ orr x0, x0, #CPUECTLR_SMPEN_MASK
+ msr CPUECTLR_EL1, x0
+
+ /* x4 = core mask */
+
+ /* start the core back up */
+ mov x0, x4
+ bl _soc_core_exit_off
+
+ /* restore the aarch32/64 non-volatile registers
+ */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_wakeup
+
+#endif
+
+
+#if (SOC_SYSTEM_RESET)
+
+.global _psci_system_reset
+
+func _psci_system_reset
+
+ /* system reset is mandatory
+ * system reset is soc-specific
+ * Note: under no circumstances do we return from this call
+ */
+ bl _soc_sys_reset
+endfunc _psci_system_reset
+
+#endif
+
+
+#if (SOC_SYSTEM_OFF)
+
+.global _psci_system_off
+
+func _psci_system_off
+
+ /* system off is mandatory
+ * system off is soc-specific
+ * Note: under no circumstances do we return from this call */
+ b _soc_sys_off
+endfunc _psci_system_off
+
+#endif
+
+
+#if (SOC_CORE_STANDBY)
+
+.global _psci_core_entr_stdby
+.global _psci_core_prep_stdby
+.global _psci_core_exit_stdby
+
+/*
+ * void _psci_core_entr_stdby(u_register_t core_mask) - this
+ * is the fast-path for simple core standby
+ */
+
+func _psci_core_entr_stdby
+ stp x4, x5, [sp, #-16]!
+ stp x6, x30, [sp, #-16]!
+
+ mov x5, x0 /* x5 = core mask */
+
+ /* save scr_el3 */
+ mov x0, x5
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* x4 = SCR_EL3
+ * x5 = core mask
+ */
+
+ /* allow interrupts @ EL3 */
+ orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK)
+ msr SCR_EL3, x4
+
+ /* x5 = core mask */
+
+ /* put the core into standby */
+ mov x0, x5
+ bl _soc_core_entr_stdby
+
+ /* restore scr_el3 */
+ mov x0, x5
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ ldp x6, x30, [sp], #16
+ ldp x4, x5, [sp], #16
+ isb
+ ret
+endfunc _psci_core_entr_stdby
+
+/*
+ * void _psci_core_prep_stdby(u_register_t core_mask) - this
+ * sets up the core to enter standby state thru the normal path
+ */
+
+func _psci_core_prep_stdby
+ stp x4, x5, [sp, #-16]!
+ stp x6, x30, [sp, #-16]!
+
+ mov x5, x0
+
+ /* x5 = core mask */
+
+ /* save scr_el3 */
+ mov x0, x5
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* allow interrupts @ EL3 */
+ orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK)
+ msr SCR_EL3, x4
+
+ /* x5 = core mask */
+
+ /* call for any SoC-specific programming */
+ mov x0, x5
+ bl _soc_core_prep_stdby
+
+ ldp x6, x30, [sp], #16
+ ldp x4, x5, [sp], #16
+ isb
+ ret
+endfunc _psci_core_prep_stdby
+
+/*
+ * void _psci_core_exit_stdby(u_register_t core_mask) - this
+ * exits the core from standby state thru the normal path
+ */
+
+func _psci_core_exit_stdby
+ stp x4, x5, [sp, #-16]!
+ stp x6, x30, [sp, #-16]!
+
+ mov x5, x0
+
+ /* x5 = core mask */
+
+ /* restore scr_el3 */
+ mov x0, x5
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ /* x5 = core mask */
+
+ /* perform any SoC-specific programming after standby state */
+ mov x0, x5
+ bl _soc_core_exit_stdby
+
+ ldp x6, x30, [sp], #16
+ ldp x4, x5, [sp], #16
+ isb
+ ret
+endfunc _psci_core_exit_stdby
+
+#endif
+
+
+#if (SOC_CORE_PWR_DWN)
+
+.global _psci_core_prep_pwrdn
+.global _psci_cpu_pwrdn_wfi
+.global _psci_core_exit_pwrdn
+
+/*
+ * void _psci_core_prep_pwrdn_(u_register_t core_mask)
+ * this function prepares the core for power-down
+ * x0 = core mask
+ *
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_core_prep_pwrdn
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x6, x0
+
+ /* x6 = core mask */
+
+ /* mask interrupts by setting DAIF[7:4] to 'b1111 */
+ msr DAIFSet, #0xF
+
+ /* save scr_el3 */
+ mov x0, x6
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* allow interrupts @ EL3 */
+ orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK)
+ msr SCR_EL3, x4
+
+ /* save cpuectlr */
+ mov x0, x6
+ mov x1, #CPUECTLR_DATA
+ mrs x2, CPUECTLR_EL1
+ bl _setCoreData
+
+ /* x6 = core mask */
+
+ /* SoC-specific programming for power-down */
+ mov x0, x6
+ bl _soc_core_prep_pwrdn
+
+ /* restore the aarch32/64 non-volatile registers
+ */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_core_prep_pwrdn
+
+/*
+ * void _psci_cpu_pwrdn_wfi(u_register_t core_mask, u_register_t resume_addr)
+ * this function powers down the core
+ */
+
+func _psci_cpu_pwrdn_wfi
+ /* save the wakeup address */
+ mov x29, x1
+
+ /* x0 = core mask */
+
+ /* shutdown the core */
+ bl _soc_core_entr_pwrdn
+
+ /* branch to resume execution */
+ br x29
+endfunc _psci_cpu_pwrdn_wfi
+
+/*
+ * void _psci_core_exit_pwrdn_(u_register_t core_mask)
+ * this function cleans up after a core power-down
+ * x0 = core mask
+ *
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_core_exit_pwrdn
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x5, x0 /* x5 = core mask */
+
+ /* restore scr_el3 */
+ mov x0, x5
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ /* x5 = core mask */
+
+ /* restore cpuectlr */
+ mov x0, x5
+ mov x1, #CPUECTLR_DATA
+ bl _getCoreData
+ /* make sure smp is set */
+ orr x0, x0, #CPUECTLR_SMPEN_MASK
+ msr CPUECTLR_EL1, x0
+
+ /* x5 = core mask */
+
+ /* SoC-specific cleanup */
+ mov x0, x5
+ bl _soc_core_exit_pwrdn
+
+ /* restore the aarch32/64 non-volatile registers
+ */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_core_exit_pwrdn
+
+#endif
+
+#if (SOC_CLUSTER_STANDBY)
+
+.global _psci_clstr_prep_stdby
+.global _psci_clstr_exit_stdby
+
+/*
+ * void _psci_clstr_prep_stdby(u_register_t core_mask) - this
+ * sets up the clstr to enter standby state thru the normal path
+ */
+
+func _psci_clstr_prep_stdby
+ stp x4, x5, [sp, #-16]!
+ stp x6, x30, [sp, #-16]!
+
+ mov x5, x0
+
+ /* x5 = core mask */
+
+ /* save scr_el3 */
+ mov x0, x5
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* allow interrupts @ EL3 */
+ orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK)
+ msr SCR_EL3, x4
+
+ /* x5 = core mask */
+
+ /* call for any SoC-specific programming */
+ mov x0, x5
+ bl _soc_clstr_prep_stdby
+
+ ldp x6, x30, [sp], #16
+ ldp x4, x5, [sp], #16
+ isb
+ ret
+endfunc _psci_clstr_prep_stdby
+
+/*
+ * void _psci_clstr_exit_stdby(u_register_t core_mask) - this
+ * exits the clstr from standby state thru the normal path
+ */
+
+func _psci_clstr_exit_stdby
+ stp x4, x5, [sp, #-16]!
+ stp x6, x30, [sp, #-16]!
+
+ mov x5, x0 /* x5 = core mask */
+
+ /* restore scr_el3 */
+ mov x0, x5
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ /* x5 = core mask */
+
+ /* perform any SoC-specific programming after standby state */
+ mov x0, x5
+ bl _soc_clstr_exit_stdby
+
+ ldp x6, x30, [sp], #16
+ ldp x4, x5, [sp], #16
+ isb
+ ret
+endfunc _psci_clstr_exit_stdby
+
+#endif
+
+#if (SOC_CLUSTER_PWR_DWN)
+
+.global _psci_clstr_prep_pwrdn
+.global _psci_clstr_exit_pwrdn
+
+/*
+ * void _psci_clstr_prep_pwrdn_(u_register_t core_mask)
+ * this function prepares the cluster+core for power-down
+ * x0 = core mask
+ *
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_clstr_prep_pwrdn
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x6, x0 /* x6 = core mask */
+
+ /* mask interrupts by setting DAIF[7:4] to 'b1111 */
+ msr DAIFSet, #0xF
+
+ /* save scr_el3 */
+ mov x0, x6
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* allow interrupts @ EL3 */
+ orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK)
+ msr SCR_EL3, x4
+
+ /* save cpuectlr */
+ mov x0, x6
+ mov x1, #CPUECTLR_DATA
+ mrs x2, CPUECTLR_EL1
+ mov x4, x2
+ bl _setCoreData
+
+ /* remove core from coherency */
+ bic x4, x4, #CPUECTLR_SMPEN_MASK
+ msr CPUECTLR_EL1, x4
+
+ /* x6 = core mask */
+
+ /* SoC-specific programming for power-down */
+ mov x0, x6
+ bl _soc_clstr_prep_pwrdn
+
+ /* restore the aarch32/64 non-volatile registers
+ */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_clstr_prep_pwrdn
+
+/*
+ * void _psci_clstr_exit_pwrdn_(u_register_t core_mask)
+ * this function cleans up after a cluster power-down
+ * x0 = core mask
+ *
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_clstr_exit_pwrdn
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x4, x0 /* x4 = core mask */
+
+ /* restore scr_el3 */
+ mov x0, x4
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ /* x4 = core mask */
+
+ /* restore cpuectlr */
+ mov x0, x4
+ mov x1, #CPUECTLR_DATA
+ bl _getCoreData
+ /* make sure smp is set */
+ orr x0, x0, #CPUECTLR_SMPEN_MASK
+ msr CPUECTLR_EL1, x0
+
+ /* x4 = core mask */
+
+ /* SoC-specific cleanup */
+ mov x0, x4
+ bl _soc_clstr_exit_pwrdn
+
+ /* restore the aarch32/64 non-volatile registers
+ */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_clstr_exit_pwrdn
+
+#endif
+
+#if (SOC_SYSTEM_STANDBY)
+
+.global _psci_sys_prep_stdby
+.global _psci_sys_exit_stdby
+
+/*
+ * void _psci_sys_prep_stdby(u_register_t core_mask) - this
+ * sets up the system to enter standby state thru the normal path
+ */
+
+func _psci_sys_prep_stdby
+ stp x4, x5, [sp, #-16]!
+ stp x6, x30, [sp, #-16]!
+
+ mov x5, x0 /* x5 = core mask */
+
+ /* save scr_el3 */
+ mov x0, x5
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* allow interrupts @ EL3 */
+ orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK)
+ msr SCR_EL3, x4
+
+ /* x5 = core mask */
+
+ /* call for any SoC-specific programming */
+ mov x0, x5
+ bl _soc_sys_prep_stdby
+
+ ldp x6, x30, [sp], #16
+ ldp x4, x5, [sp], #16
+ isb
+ ret
+endfunc _psci_sys_prep_stdby
+
+/*
+ * void _psci_sys_exit_stdby(u_register_t core_mask) - this
+ * exits the system from standby state thru the normal path
+ */
+
+func _psci_sys_exit_stdby
+ stp x4, x5, [sp, #-16]!
+ stp x6, x30, [sp, #-16]!
+
+ mov x5, x0
+
+ /* x5 = core mask */
+
+ /* restore scr_el3 */
+ mov x0, x5
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ /* x5 = core mask */
+
+ /* perform any SoC-specific programming after standby state */
+ mov x0, x5
+ bl _soc_sys_exit_stdby
+
+ ldp x6, x30, [sp], #16
+ ldp x4, x5, [sp], #16
+ isb
+ ret
+endfunc _psci_sys_exit_stdby
+
+#endif
+
+#if (SOC_SYSTEM_PWR_DWN)
+
+.global _psci_sys_prep_pwrdn
+.global _psci_sys_pwrdn_wfi
+.global _psci_sys_exit_pwrdn
+
+/*
+ * void _psci_sys_prep_pwrdn_(u_register_t core_mask)
+ * this function prepares the system+core for power-down
+ * x0 = core mask
+ *
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_sys_prep_pwrdn
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x6, x0 /* x6 = core mask */
+
+ /* mask interrupts by setting DAIF[7:4] to 'b1111 */
+ msr DAIFSet, #0xF
+
+ /* save scr_el3 */
+ mov x0, x6
+ mrs x4, SCR_EL3
+ mov x2, x4
+ mov x1, #SCR_EL3_DATA
+ bl _setCoreData
+
+ /* allow interrupts @ EL3 */
+ orr x4, x4, #(SCR_IRQ_MASK | SCR_FIQ_MASK)
+ msr SCR_EL3, x4
+
+ /* save cpuectlr */
+ mov x0, x6
+ mov x1, #CPUECTLR_DATA
+ mrs x2, CPUECTLR_EL1
+ mov x4, x2
+ bl _setCoreData
+
+ /* remove core from coherency */
+ bic x4, x4, #CPUECTLR_SMPEN_MASK
+ msr CPUECTLR_EL1, x4
+
+ /* x6 = core mask */
+
+ /* SoC-specific programming for power-down */
+ mov x0, x6
+ bl _soc_sys_prep_pwrdn
+
+ /* restore the aarch32/64 non-volatile registers
+ */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_sys_prep_pwrdn
+
+
+/*
+ * void _psci_sys_pwrdn_wfi(u_register_t core_mask, u_register_t resume_addr)
+ * this function powers down the system
+ */
+
+func _psci_sys_pwrdn_wfi
+ /* save the wakeup address */
+ mov x29, x1
+
+ /* x0 = core mask */
+
+ /* shutdown the system */
+ bl _soc_sys_pwrdn_wfi
+
+ /* branch to resume execution */
+ br x29
+endfunc _psci_sys_pwrdn_wfi
+
+/*
+ * void _psci_sys_exit_pwrdn_(u_register_t core_mask)
+ * this function cleans up after a system power-down
+ * x0 = core mask
+ *
+ * Called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+
+func _psci_sys_exit_pwrdn
+
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x14, x15, [sp, #-16]!
+ stp x16, x17, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ mov x4, x0 /* x4 = core mask */
+
+ /* restore scr_el3 */
+ mov x0, x4
+ mov x1, #SCR_EL3_DATA
+ bl _getCoreData
+
+ /* x0 = saved scr_el3 */
+ msr SCR_EL3, x0
+
+ /* x4 = core mask */
+
+ /* restore cpuectlr */
+ mov x0, x4
+ mov x1, #CPUECTLR_DATA
+ bl _getCoreData
+
+ /* make sure smp is set */
+ orr x0, x0, #CPUECTLR_SMPEN_MASK
+ msr CPUECTLR_EL1, x0
+
+ /* x4 = core mask */
+
+ /* SoC-specific cleanup */
+ mov x0, x4
+ bl _soc_sys_exit_pwrdn
+
+ /* restore the aarch32/64 non-volatile registers
+ */
+ ldp x18, x30, [sp], #16
+ ldp x16, x17, [sp], #16
+ ldp x14, x15, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ b psci_completed
+endfunc _psci_sys_exit_pwrdn
+
+#endif
+
+
+/* psci std returns */
+func psci_disabled
+ ldr w0, =PSCI_E_DISABLED
+ b psci_completed
+endfunc psci_disabled
+
+
+func psci_not_present
+ ldr w0, =PSCI_E_NOT_PRESENT
+ b psci_completed
+endfunc psci_not_present
+
+
+func psci_on_pending
+ ldr w0, =PSCI_E_ON_PENDING
+ b psci_completed
+endfunc psci_on_pending
+
+
+func psci_already_on
+ ldr w0, =PSCI_E_ALREADY_ON
+ b psci_completed
+endfunc psci_already_on
+
+
+func psci_failure
+ ldr w0, =PSCI_E_INTERN_FAIL
+ b psci_completed
+endfunc psci_failure
+
+
+func psci_unimplemented
+ ldr w0, =PSCI_E_NOT_SUPPORTED
+ b psci_completed
+endfunc psci_unimplemented
+
+
+func psci_denied
+ ldr w0, =PSCI_E_DENIED
+ b psci_completed
+endfunc psci_denied
+
+
+func psci_invalid
+ ldr w0, =PSCI_E_INVALID_PARAMS
+ b psci_completed
+endfunc psci_invalid
+
+
+func psci_success
+ mov x0, #PSCI_E_SUCCESS
+endfunc psci_success
+
+
+func psci_completed
+ /* x0 = status code */
+ ret
+endfunc psci_completed
diff --git a/plat/nxp/common/psci/include/plat_psci.h b/plat/nxp/common/psci/include/plat_psci.h
new file mode 100644
index 0000000..7fc48fb
--- /dev/null
+++ b/plat/nxp/common/psci/include/plat_psci.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_PSCI_H
+#define PLAT_PSCI_H
+#include <cortex_a53.h>
+#include <cortex_a72.h>
+
+ /* core abort current op */
+#define CORE_ABORT_OP 0x1
+
+ /* psci power levels - these are actually affinity levels
+ * in the psci_power_state_t array
+ */
+#define PLAT_CORE_LVL PSCI_CPU_PWR_LVL
+#define PLAT_CLSTR_LVL U(1)
+#define PLAT_SYS_LVL U(2)
+#define PLAT_MAX_LVL PLAT_SYS_LVL
+
+ /* core state */
+ /* OFF states 0x0 - 0xF */
+#define CORE_IN_RESET 0x0
+#define CORE_DISABLED 0x1
+#define CORE_OFF 0x2
+#define CORE_STANDBY 0x3
+#define CORE_PWR_DOWN 0x4
+#define CORE_WFE 0x6
+#define CORE_WFI 0x7
+#define CORE_LAST 0x8
+#define CORE_OFF_PENDING 0x9
+#define CORE_WORKING_INIT 0xA
+#define SYS_OFF_PENDING 0xB
+#define SYS_OFF 0xC
+
+ /* ON states 0x10 - 0x1F */
+#define CORE_PENDING 0x10
+#define CORE_RELEASED 0x11
+#define CORE_WAKEUP 0x12
+ /* highest off state */
+#define CORE_OFF_MAX 0xF
+ /* lowest on state */
+#define CORE_ON_MIN CORE_PENDING
+
+#define DAIF_SET_MASK 0x3C0
+#define SCTLR_I_C_M_MASK 0x00001005
+#define SCTLR_C_MASK 0x00000004
+#define SCTLR_I_MASK 0x00001000
+#define CPUACTLR_L1PCTL_MASK 0x0000E000
+#define DCSR_RCPM2_BASE 0x20170000
+#define CPUECTLR_SMPEN_MASK 0x40
+#define CPUECTLR_SMPEN_EN 0x40
+#define CPUECTLR_RET_MASK 0x7
+#define CPUECTLR_RET_SET 0x2
+#define CPUECTLR_TIMER_MASK 0x7
+#define CPUECTLR_TIMER_8TICKS 0x2
+#define CPUECTLR_TIMER_2TICKS 0x1
+#define SCR_IRQ_MASK 0x2
+#define SCR_FIQ_MASK 0x4
+
+/* pwr mgmt features supported in the soc-specific code:
+ * value == 0x0, the soc code does not support this feature
+ * value != 0x0, the soc code supports this feature
+ */
+#ifndef SOC_CORE_RELEASE
+#define SOC_CORE_RELEASE 0x1
+#endif
+
+#ifndef SOC_CORE_RESTART
+#define SOC_CORE_RESTART 0x1
+#endif
+
+#ifndef SOC_CORE_OFF
+#define SOC_CORE_OFF 0x1
+#endif
+
+#ifndef SOC_CORE_STANDBY
+#define SOC_CORE_STANDBY 0x1
+#endif
+
+#ifndef SOC_CORE_PWR_DWN
+#define SOC_CORE_PWR_DWN 0x1
+#endif
+
+#ifndef SOC_CLUSTER_STANDBY
+#define SOC_CLUSTER_STANDBY 0x1
+#endif
+
+#ifndef SOC_CLUSTER_PWR_DWN
+#define SOC_CLUSTER_PWR_DWN 0x1
+#endif
+
+#ifndef SOC_SYSTEM_STANDBY
+#define SOC_SYSTEM_STANDBY 0x1
+#endif
+
+#ifndef SOC_SYSTEM_PWR_DWN
+#define SOC_SYSTEM_PWR_DWN 0x1
+#endif
+
+#ifndef SOC_SYSTEM_OFF
+#define SOC_SYSTEM_OFF 0x1
+#endif
+
+#ifndef SOC_SYSTEM_RESET
+#define SOC_SYSTEM_RESET 0x1
+#endif
+
+#ifndef SOC_SYSTEM_RESET2
+#define SOC_SYSTEM_RESET2 0x1
+#endif
+
+#ifndef __ASSEMBLER__
+
+void __dead2 _psci_system_reset(void);
+void __dead2 _psci_system_off(void);
+int _psci_cpu_on(u_register_t core_mask);
+void _psci_cpu_prep_off(u_register_t core_mask);
+void __dead2 _psci_cpu_off_wfi(u_register_t core_mask,
+ u_register_t wakeup_address);
+void __dead2 _psci_cpu_pwrdn_wfi(u_register_t core_mask,
+ u_register_t wakeup_address);
+void __dead2 _psci_sys_pwrdn_wfi(u_register_t core_mask,
+ u_register_t wakeup_address);
+void _psci_wakeup(u_register_t core_mask);
+void _psci_core_entr_stdby(u_register_t core_mask);
+void _psci_core_prep_stdby(u_register_t core_mask);
+void _psci_core_exit_stdby(u_register_t core_mask);
+void _psci_core_prep_pwrdn(u_register_t core_mask);
+void _psci_core_exit_pwrdn(u_register_t core_mask);
+void _psci_clstr_prep_stdby(u_register_t core_mask);
+void _psci_clstr_exit_stdby(u_register_t core_mask);
+void _psci_clstr_prep_pwrdn(u_register_t core_mask);
+void _psci_clstr_exit_pwrdn(u_register_t core_mask);
+void _psci_sys_prep_stdby(u_register_t core_mask);
+void _psci_sys_exit_stdby(u_register_t core_mask);
+void _psci_sys_prep_pwrdn(u_register_t core_mask);
+void _psci_sys_exit_pwrdn(u_register_t core_mask);
+
+#endif
+
+#endif /* __PLAT_PSCI_H__ */
diff --git a/plat/nxp/common/psci/plat_psci.c b/plat/nxp/common/psci/plat_psci.c
new file mode 100644
index 0000000..9281e97
--- /dev/null
+++ b/plat/nxp/common/psci/plat_psci.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/debug.h>
+
+#include <plat_gic.h>
+#include <plat_common.h>
+#include <plat_psci.h>
+#ifdef NXP_WARM_BOOT
+#include <plat_warm_rst.h>
+#endif
+
+#include <platform_def.h>
+
+#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN)
+static void __dead2 _no_return_wfi(void)
+{
+_bl31_dead_wfi:
+ wfi();
+ goto _bl31_dead_wfi;
+}
+#endif
+
+#if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN)
+ /* the entry for core warm boot */
+static uintptr_t warmboot_entry = (uintptr_t) NULL;
+#endif
+
+#if (SOC_CORE_RELEASE)
+static int _pwr_domain_on(u_register_t mpidr)
+{
+ int core_pos = plat_core_pos(mpidr);
+ int rc = PSCI_E_INVALID_PARAMS;
+ u_register_t core_mask;
+
+ if (core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT) {
+
+ _soc_set_start_addr(warmboot_entry);
+
+ dsb();
+ isb();
+
+ core_mask = (1 << core_pos);
+ rc = _psci_cpu_on(core_mask);
+ }
+
+ return (rc);
+}
+#endif
+
+#if (SOC_CORE_OFF)
+static void _pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t core_mask = plat_my_core_mask();
+ u_register_t core_state = _getCoreState(core_mask);
+
+ /* set core state in internal data */
+ core_state = CORE_OFF_PENDING;
+ _setCoreState(core_mask, core_state);
+
+ _psci_cpu_prep_off(core_mask);
+}
+#endif
+
+#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN)
+static void __dead2 _pwr_down_wfi(const psci_power_state_t *target_state)
+{
+ u_register_t core_mask = plat_my_core_mask();
+ u_register_t core_state = _getCoreState(core_mask);
+
+ switch (core_state) {
+#if (SOC_CORE_OFF)
+ case CORE_OFF_PENDING:
+ /* set core state in internal data */
+ core_state = CORE_OFF;
+ _setCoreState(core_mask, core_state);
+
+ /* turn the core off */
+ _psci_cpu_off_wfi(core_mask, warmboot_entry);
+ break;
+#endif
+#if (SOC_CORE_PWR_DWN)
+ case CORE_PWR_DOWN:
+ /* power-down the core */
+ _psci_cpu_pwrdn_wfi(core_mask, warmboot_entry);
+ break;
+#endif
+#if (SOC_SYSTEM_PWR_DWN)
+ case SYS_OFF_PENDING:
+ /* set core state in internal data */
+ core_state = SYS_OFF;
+ _setCoreState(core_mask, core_state);
+
+ /* power-down the system */
+ _psci_sys_pwrdn_wfi(core_mask, warmboot_entry);
+ break;
+#endif
+ default:
+ _no_return_wfi();
+ break;
+ }
+}
+#endif
+
+#if (SOC_CORE_RELEASE || SOC_CORE_RESTART)
+static void _pwr_domain_wakeup(const psci_power_state_t *target_state)
+{
+ u_register_t core_mask = plat_my_core_mask();
+ u_register_t core_state = _getCoreState(core_mask);
+
+ switch (core_state) {
+ case CORE_PENDING: /* this core is coming out of reset */
+
+ /* soc per cpu setup */
+ soc_init_percpu();
+
+ /* gic per cpu setup */
+ plat_gic_pcpu_init();
+
+ /* set core state in internal data */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+ break;
+
+#if (SOC_CORE_RESTART)
+ case CORE_WAKEUP:
+
+ /* this core is waking up from OFF */
+ _psci_wakeup(core_mask);
+
+ /* set core state in internal data */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+
+ break;
+#endif
+ }
+}
+#endif
+
+#if (SOC_CORE_STANDBY)
+static void _pwr_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t core_mask = plat_my_core_mask();
+ u_register_t core_state;
+
+ if (cpu_state == PLAT_MAX_RET_STATE) {
+
+ /* set core state to standby */
+ core_state = CORE_STANDBY;
+ _setCoreState(core_mask, core_state);
+
+ _psci_core_entr_stdby(core_mask);
+
+ /* when we are here, the core is waking up
+ * set core state to released
+ */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+ }
+}
+#endif
+
+#if (SOC_CORE_PWR_DWN)
+static void _pwr_suspend(const psci_power_state_t *state)
+{
+
+ u_register_t core_mask = plat_my_core_mask();
+ u_register_t core_state;
+
+ if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) {
+#if (SOC_SYSTEM_PWR_DWN)
+ _psci_sys_prep_pwrdn(core_mask);
+
+ /* set core state */
+ core_state = SYS_OFF_PENDING;
+ _setCoreState(core_mask, core_state);
+#endif
+ } else if (state->pwr_domain_state[PLAT_MAX_LVL]
+ == PLAT_MAX_RET_STATE) {
+#if (SOC_SYSTEM_STANDBY)
+ _psci_sys_prep_stdby(core_mask);
+
+ /* set core state */
+ core_state = CORE_STANDBY;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
+ PLAT_MAX_OFF_STATE) {
+#if (SOC_CLUSTER_PWR_DWN)
+ _psci_clstr_prep_pwrdn(core_mask);
+
+ /* set core state */
+ core_state = CORE_PWR_DOWN;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
+ PLAT_MAX_RET_STATE) {
+#if (SOC_CLUSTER_STANDBY)
+ _psci_clstr_prep_stdby(core_mask);
+
+ /* set core state */
+ core_state = CORE_STANDBY;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) {
+#if (SOC_CORE_PWR_DWN)
+ /* prep the core for power-down */
+ _psci_core_prep_pwrdn(core_mask);
+
+ /* set core state */
+ core_state = CORE_PWR_DOWN;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) {
+#if (SOC_CORE_STANDBY)
+ _psci_core_prep_stdby(core_mask);
+
+ /* set core state */
+ core_state = CORE_STANDBY;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+}
+#endif
+
+#if (SOC_CORE_PWR_DWN)
+static void _pwr_suspend_finish(const psci_power_state_t *state)
+{
+
+ u_register_t core_mask = plat_my_core_mask();
+ u_register_t core_state;
+
+
+ if (state->pwr_domain_state[PLAT_MAX_LVL] == PLAT_MAX_OFF_STATE) {
+#if (SOC_SYSTEM_PWR_DWN)
+ _psci_sys_exit_pwrdn(core_mask);
+
+ /* when we are here, the core is back up
+ * set core state to released
+ */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+#endif
+ } else if (state->pwr_domain_state[PLAT_MAX_LVL]
+ == PLAT_MAX_RET_STATE) {
+#if (SOC_SYSTEM_STANDBY)
+ _psci_sys_exit_stdby(core_mask);
+
+ /* when we are here, the core is waking up
+ * set core state to released
+ */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
+ PLAT_MAX_OFF_STATE) {
+#if (SOC_CLUSTER_PWR_DWN)
+ _psci_clstr_exit_pwrdn(core_mask);
+
+ /* when we are here, the core is waking up
+ * set core state to released
+ */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CLSTR_LVL] ==
+ PLAT_MAX_RET_STATE) {
+#if (SOC_CLUSTER_STANDBY)
+ _psci_clstr_exit_stdby(core_mask);
+
+ /* when we are here, the core is waking up
+ * set core state to released
+ */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_OFF_STATE) {
+#if (SOC_CORE_PWR_DWN)
+ _psci_core_exit_pwrdn(core_mask);
+
+ /* when we are here, the core is back up
+ * set core state to released
+ */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+ else if (state->pwr_domain_state[PLAT_CORE_LVL] == PLAT_MAX_RET_STATE) {
+#if (SOC_CORE_STANDBY)
+ _psci_core_exit_stdby(core_mask);
+
+ /* when we are here, the core is waking up
+ * set core state to released
+ */
+ core_state = CORE_RELEASED;
+ _setCoreState(core_mask, core_state);
+#endif
+ }
+
+}
+#endif
+
+#if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN)
+
+#define PWR_STATE_TYPE_MASK 0x00010000
+#define PWR_STATE_TYPE_STNDBY 0x0
+#define PWR_STATE_TYPE_PWRDWN 0x00010000
+#define PWR_STATE_LVL_MASK 0x03000000
+#define PWR_STATE_LVL_CORE 0x0
+#define PWR_STATE_LVL_CLSTR 0x01000000
+#define PWR_STATE_LVL_SYS 0x02000000
+#define PWR_STATE_LVL_MAX 0x03000000
+
+ /* turns a requested power state into a target power state
+ * based on SoC capabilities
+ */
+static int _pwr_state_validate(uint32_t pwr_state,
+ psci_power_state_t *state)
+{
+ int stat = PSCI_E_INVALID_PARAMS;
+ int pwrdn = (pwr_state & PWR_STATE_TYPE_MASK);
+ int lvl = (pwr_state & PWR_STATE_LVL_MASK);
+
+ switch (lvl) {
+ case PWR_STATE_LVL_MAX:
+ if (pwrdn && SOC_SYSTEM_PWR_DWN)
+ state->pwr_domain_state[PLAT_MAX_LVL] =
+ PLAT_MAX_OFF_STATE;
+ else if (SOC_SYSTEM_STANDBY)
+ state->pwr_domain_state[PLAT_MAX_LVL] =
+ PLAT_MAX_RET_STATE;
+ /* intentional fall-thru condition */
+ case PWR_STATE_LVL_SYS:
+ if (pwrdn && SOC_SYSTEM_PWR_DWN)
+ state->pwr_domain_state[PLAT_SYS_LVL] =
+ PLAT_MAX_OFF_STATE;
+ else if (SOC_SYSTEM_STANDBY)
+ state->pwr_domain_state[PLAT_SYS_LVL] =
+ PLAT_MAX_RET_STATE;
+ /* intentional fall-thru condition */
+ case PWR_STATE_LVL_CLSTR:
+ if (pwrdn && SOC_CLUSTER_PWR_DWN)
+ state->pwr_domain_state[PLAT_CLSTR_LVL] =
+ PLAT_MAX_OFF_STATE;
+ else if (SOC_CLUSTER_STANDBY)
+ state->pwr_domain_state[PLAT_CLSTR_LVL] =
+ PLAT_MAX_RET_STATE;
+ /* intentional fall-thru condition */
+ case PWR_STATE_LVL_CORE:
+ stat = PSCI_E_SUCCESS;
+
+ if (pwrdn && SOC_CORE_PWR_DWN)
+ state->pwr_domain_state[PLAT_CORE_LVL] =
+ PLAT_MAX_OFF_STATE;
+ else if (SOC_CORE_STANDBY)
+ state->pwr_domain_state[PLAT_CORE_LVL] =
+ PLAT_MAX_RET_STATE;
+ break;
+ }
+ return (stat);
+}
+
+#endif
+
+#if (SOC_SYSTEM_PWR_DWN)
+static void _pwr_state_sys_suspend(psci_power_state_t *req_state)
+{
+
+ /* if we need to have per-SoC settings, then we need to
+ * extend this by calling into psci_utils.S and from there
+ * on down to the SoC.S files
+ */
+
+ req_state->pwr_domain_state[PLAT_MAX_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[PLAT_SYS_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[PLAT_CLSTR_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[PLAT_CORE_LVL] = PLAT_MAX_OFF_STATE;
+
+}
+#endif
+
+#if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2)
+static int psci_system_reset2(int is_vendor,
+ int reset_type,
+ u_register_t cookie)
+{
+ int ret = 0;
+
+ INFO("Executing the sequence of warm reset.\n");
+ ret = prep_n_execute_warm_reset();
+
+ return ret;
+}
+#endif
+
+static plat_psci_ops_t _psci_pm_ops = {
+#if (SOC_SYSTEM_OFF)
+ .system_off = _psci_system_off,
+#endif
+#if (SOC_SYSTEM_RESET)
+ .system_reset = _psci_system_reset,
+#endif
+#if defined(NXP_WARM_BOOT) && (SOC_SYSTEM_RESET2)
+ .system_reset2 = psci_system_reset2,
+#endif
+#if (SOC_CORE_RELEASE || SOC_CORE_RESTART)
+ /* core released or restarted */
+ .pwr_domain_on_finish = _pwr_domain_wakeup,
+#endif
+#if (SOC_CORE_OFF)
+ /* core shutting down */
+ .pwr_domain_off = _pwr_domain_off,
+#endif
+#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN)
+ .pwr_domain_pwr_down_wfi = _pwr_down_wfi,
+#endif
+#if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN)
+ /* cpu_suspend */
+ .validate_power_state = _pwr_state_validate,
+#if (SOC_CORE_STANDBY)
+ .cpu_standby = _pwr_cpu_standby,
+#endif
+#if (SOC_CORE_PWR_DWN)
+ .pwr_domain_suspend = _pwr_suspend,
+ .pwr_domain_suspend_finish = _pwr_suspend_finish,
+#endif
+#endif
+#if (SOC_SYSTEM_PWR_DWN)
+ .get_sys_suspend_power_state = _pwr_state_sys_suspend,
+#endif
+#if (SOC_CORE_RELEASE)
+ /* core executing psci_cpu_on */
+ .pwr_domain_on = _pwr_domain_on
+#endif
+};
+
+#if (SOC_CORE_RELEASE || SOC_CORE_PWR_DWN)
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ warmboot_entry = sec_entrypoint;
+ *psci_ops = &_psci_pm_ops;
+ return 0;
+}
+
+#else
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &_psci_pm_ops;
+ return 0;
+}
+#endif
diff --git a/plat/nxp/common/psci/psci.mk b/plat/nxp/common/psci/psci.mk
new file mode 100644
index 0000000..a2791c2
--- /dev/null
+++ b/plat/nxp/common/psci/psci.mk
@@ -0,0 +1,35 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# Select the PSCI files
+#
+# -----------------------------------------------------------------------------
+
+ifeq (${ADD_PSCI},)
+
+ADD_PSCI := 1
+PLAT_PSCI_PATH := $(PLAT_COMMON_PATH)/psci
+
+PSCI_SOURCES := ${PLAT_PSCI_PATH}/plat_psci.c \
+ ${PLAT_PSCI_PATH}/$(ARCH)/psci_utils.S \
+ plat/common/plat_psci_common.c
+
+PLAT_INCLUDES += -I${PLAT_PSCI_PATH}/include
+
+ifeq (${BL_COMM_PSCI_NEEDED},yes)
+BL_COMMON_SOURCES += ${PSCI_SOURCES}
+else
+ifeq (${BL2_PSCI_NEEDED},yes)
+BL2_SOURCES += ${PSCI_SOURCES}
+endif
+ifeq (${BL31_PSCI_NEEDED},yes)
+BL31_SOURCES += ${PSCI_SOURCES}
+endif
+endif
+endif
+# -----------------------------------------------------------------------------
diff --git a/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c b/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c
new file mode 100644
index 0000000..7463d47
--- /dev/null
+++ b/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#ifdef CSF_HEADER_PREPENDED
+#include <csf_hdr.h>
+#endif
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = LS_BL31_PLAT_PARAM_VAL,
+#endif
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+#ifdef CSF_HEADER_PREPENDED
+ .image_info.image_base = BL31_BASE - CSF_HDR_SZ,
+ .image_info.image_max_size = (BL31_LIMIT - BL31_BASE) +
+ CSF_HDR_SZ,
+#else
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = (BL31_LIMIT - BL31_BASE),
+#endif
+
+# ifdef NXP_LOAD_BL32
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+# ifdef NXP_LOAD_BL32
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+#ifdef CSF_HEADER_PREPENDED
+ .image_info.image_base = BL32_BASE - CSF_HDR_SZ,
+ .image_info.image_max_size = (BL32_LIMIT - BL32_BASE) +
+ CSF_HDR_SZ,
+#else
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = (BL32_LIMIT - BL32_BASE),
+#endif
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+ .ep_info.pc = BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+#ifdef CSF_HEADER_PREPENDED
+ .image_info.image_base = BL33_BASE - CSF_HDR_SZ,
+ .image_info.image_max_size = (BL33_LIMIT - BL33_BASE) +
+ CSF_HDR_SZ,
+#else
+ .image_info.image_base = BL33_BASE,
+ .image_info.image_max_size = BL33_LIMIT - BL33_BASE,
+#endif
+ .ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/nxp/common/setup/common.mk b/plat/nxp/common/setup/common.mk
new file mode 100644
index 0000000..1fcf1d0
--- /dev/null
+++ b/plat/nxp/common/setup/common.mk
@@ -0,0 +1,105 @@
+#
+# Copyright 2018-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+###############################################################################
+# Flow begins in BL2 at EL3 mode
+BL2_AT_EL3 := 1
+
+# Though one core is powered up by default, there are
+# platform specific ways to release more than one core
+COLD_BOOT_SINGLE_CPU := 0
+
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+USE_COHERENT_MEM := 0
+
+# Use generic OID definition (tbbr_oid.h)
+USE_TBBR_DEFS := 1
+
+PLAT_XLAT_TABLES_DYNAMIC := 0
+
+ENABLE_SVE_FOR_NS := 0
+
+ENABLE_STACK_PROTECTOR := 0
+
+ERROR_DEPRECATED := 0
+
+LS_DISABLE_TRUSTED_WDOG := 1
+
+# On ARM platforms, separate the code and read-only data sections to allow
+# mapping the former as executable and the latter as execute-never.
+SEPARATE_CODE_AND_RODATA := 1
+
+# Enable new version of image loading on ARM platforms
+LOAD_IMAGE_V2 := 1
+
+RCW := ""
+
+ifneq (${SPD},none)
+$(eval $(call add_define, NXP_LOAD_BL32))
+endif
+
+###############################################################################
+
+PLAT_TOOL_PATH := tools/nxp
+CREATE_PBL_TOOL_PATH := ${PLAT_TOOL_PATH}/create_pbl
+PLAT_SETUP_PATH := ${PLAT_PATH}/common/setup
+
+PLAT_INCLUDES += -I${PLAT_SETUP_PATH}/include \
+ -Iinclude/plat/arm/common \
+ -Iinclude/drivers/arm \
+ -Iinclude/lib \
+ -Iinclude/drivers/io \
+ -Ilib/psci
+
+# Required without TBBR.
+# To include the defines for DDR PHY Images.
+PLAT_INCLUDES += -Iinclude/common/tbbr
+
+include ${PLAT_SETUP_PATH}/core.mk
+PLAT_BL_COMMON_SOURCES += ${CPU_LIBS} \
+ plat/nxp/common/setup/ls_err.c \
+ plat/nxp/common/setup/ls_common.c
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += ${PLAT_SETUP_PATH}/ls_stack_protector.c
+endif
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+BL2_SOURCES += drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ common/desc_image_load.c \
+ plat/nxp/common/setup/ls_image_load.c \
+ plat/nxp/common/setup/ls_io_storage.c \
+ plat/nxp/common/setup/ls_bl2_el3_setup.c \
+ plat/nxp/common/setup/${ARCH}/ls_bl2_mem_params_desc.c
+
+BL31_SOURCES += plat/nxp/common/setup/ls_bl31_setup.c \
+
+ifeq (${LS_EL3_INTERRUPT_HANDLER}, yes)
+$(eval $(call add_define, LS_EL3_INTERRUPT_HANDLER))
+BL31_SOURCES += plat/nxp/common/setup/ls_interrupt_mgmt.c
+endif
+
+ifeq (${TEST_BL31}, 1)
+BL31_SOURCES += ${TEST_SOURCES}
+endif
+
+# Verify build config
+# -------------------
+
+ifneq (${LOAD_IMAGE_V2}, 1)
+ $(error Error: Layerscape needs LOAD_IMAGE_V2=1)
+else
+$(eval $(call add_define,LOAD_IMAGE_V2))
+endif
+
+include $(CREATE_PBL_TOOL_PATH)/create_pbl.mk
diff --git a/plat/nxp/common/setup/core.mk b/plat/nxp/common/setup/core.mk
new file mode 100644
index 0000000..82ce30e
--- /dev/null
+++ b/plat/nxp/common/setup/core.mk
@@ -0,0 +1,22 @@
+# Copyright 2018-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# Select the CORE files
+#
+# -----------------------------------------------------------------------------
+
+CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S
+
+ifeq (,$(filter $(CORE_TYPE),a53 a72))
+$(error "CORE_TYPE not specified or incorrect")
+else
+UPPER_CORE_TYPE=$(shell echo $(CORE_TYPE) | tr a-z A-Z)
+$(eval $(call add_define_val,CPUECTLR_EL1,CORTEX_$(UPPER_CORE_TYPE)_ECTLR_EL1))
+CPU_LIBS += lib/cpus/${ARCH}/cortex_$(CORE_TYPE).S
+endif
+
+# -----------------------------------------------------------------------------
diff --git a/plat/nxp/common/setup/include/bl31_data.h b/plat/nxp/common/setup/include/bl31_data.h
new file mode 100644
index 0000000..dd20d43
--- /dev/null
+++ b/plat/nxp/common/setup/include/bl31_data.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef BL31_DATA_H
+#define BL31_DATA_H
+
+#define SECURE_DATA_BASE NXP_OCRAM_ADDR
+#define SECURE_DATA_SIZE NXP_OCRAM_SIZE
+#define SECURE_DATA_TOP (SECURE_DATA_BASE + SECURE_DATA_SIZE)
+#define SMC_REGION_SIZE 0x80
+#define SMC_GLBL_BASE (SECURE_DATA_TOP - SMC_REGION_SIZE)
+#define BC_PSCI_DATA_SIZE 0xC0
+#define BC_PSCI_BASE (SMC_GLBL_BASE - BC_PSCI_DATA_SIZE)
+#define SECONDARY_TOP BC_PSCI_BASE
+
+#define SEC_PSCI_DATA_SIZE 0xC0
+#define SEC_REGION_SIZE SEC_PSCI_DATA_SIZE
+
+/* SMC global data */
+#define BOOTLOC_OFFSET 0x0
+#define BOOT_SVCS_OSET 0x8
+
+/* offset to prefetch disable mask */
+#define PREFETCH_DIS_OFFSET 0x10
+/* must reference last smc global entry */
+#define LAST_SMC_GLBL_OFFSET 0x18
+
+#define SMC_TASK_OFFSET 0xC
+#define TSK_START_OFFSET 0x0
+#define TSK_DONE_OFFSET 0x4
+#define TSK_CORE_OFFSET 0x8
+#define SMC_TASK1_BASE (SMC_GLBL_BASE + 32)
+#define SMC_TASK2_BASE (SMC_TASK1_BASE + SMC_TASK_OFFSET)
+#define SMC_TASK3_BASE (SMC_TASK2_BASE + SMC_TASK_OFFSET)
+#define SMC_TASK4_BASE (SMC_TASK3_BASE + SMC_TASK_OFFSET)
+
+/* psci data area offsets */
+#define CORE_STATE_DATA 0x0
+#define SPSR_EL3_DATA 0x8
+#define CNTXT_ID_DATA 0x10
+#define START_ADDR_DATA 0x18
+#define LINK_REG_DATA 0x20
+#define GICC_CTLR_DATA 0x28
+#define ABORT_FLAG_DATA 0x30
+#define SCTLR_DATA 0x38
+#define CPUECTLR_DATA 0x40
+#define AUX_01_DATA 0x48 /* usage defined per SoC */
+#define AUX_02_DATA 0x50 /* usage defined per SoC */
+#define AUX_03_DATA 0x58 /* usage defined per SoC */
+#define AUX_04_DATA 0x60 /* usage defined per SoC */
+#define AUX_05_DATA 0x68 /* usage defined per SoC */
+#define AUX_06_DATA 0x70 /* usage defined per SoC */
+#define AUX_07_DATA 0x78 /* usage defined per SoC */
+#define SCR_EL3_DATA 0x80
+#define HCR_EL2_DATA 0x88
+
+#endif /* BL31_DATA_H */
diff --git a/plat/nxp/common/setup/include/ls_interrupt_mgmt.h b/plat/nxp/common/setup/include/ls_interrupt_mgmt.h
new file mode 100644
index 0000000..7dbddfb
--- /dev/null
+++ b/plat/nxp/common/setup/include/ls_interrupt_mgmt.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef LS_EL3_INTRPT_MGMT_H
+#define LS_EL3_INTRPT_MGMT_H
+
+#include <bl31/interrupt_mgmt.h>
+
+#define MAX_INTR_EL3 128
+
+/*
+ * Register handler to specific GIC entrance
+ * for INTR_TYPE_EL3 type of interrupt
+ */
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler);
+
+void ls_el3_interrupt_config(void);
+
+#endif /* LS_EL3_INTRPT_MGMT_H */
diff --git a/plat/nxp/common/setup/include/mmu_def.h b/plat/nxp/common/setup/include/mmu_def.h
new file mode 100644
index 0000000..2a7771b
--- /dev/null
+++ b/plat/nxp/common/setup/include/mmu_def.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef MMU_MAP_DEF_H
+#define MMU_MAP_DEF_H
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+#include <platform_def.h>
+
+
+#define LS_MAP_CCSR MAP_REGION_FLAT(NXP_CCSR_ADDR, \
+ NXP_CCSR_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#ifdef NXP_DCSR_ADDR
+#define LS_MAP_DCSR MAP_REGION_FLAT(NXP_DCSR_ADDR, \
+ NXP_DCSR_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#define LS_MAP_CONSOLE MAP_REGION_FLAT(NXP_DUART1_ADDR, \
+ NXP_DUART_SIZE, \
+ MT_DEVICE | MT_RW | MT_NS)
+
+#define LS_MAP_OCRAM MAP_REGION_FLAT(NXP_OCRAM_ADDR, \
+ NXP_OCRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#endif /* MMU_MAP_DEF_H */
diff --git a/plat/nxp/common/setup/include/plat_common.h b/plat/nxp/common/setup/include/plat_common.h
new file mode 100644
index 0000000..e13f45c
--- /dev/null
+++ b/plat/nxp/common/setup/include/plat_common.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_COMMON_H
+#define PLAT_COMMON_H
+
+#include <stdbool.h>
+
+#include <dcfg.h>
+#include <lib/el3_runtime/cpu_data.h>
+
+#include <platform_def.h>
+
+#ifdef IMAGE_BL31
+
+#define BL31_END (uintptr_t)(&__BL31_END__)
+
+/*******************************************************************************
+ * This structure represents the superset of information that can be passed to
+ * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be
+ * populated only if BL2 detects its presence. A pointer to a structure of this
+ * type should be passed in X0 to BL31's cold boot entrypoint.
+ *
+ * Use of this structure and the X0 parameter is not mandatory: the BL31
+ * platform code can use other mechanisms to provide the necessary information
+ * about BL32 and BL33 to the common and SPD code.
+ *
+ * BL31 image information is mandatory if this structure is used. If either of
+ * the optional BL32 and BL33 image information is not provided, this is
+ * indicated by the respective image_info pointers being zero.
+ ******************************************************************************/
+typedef struct bl31_params {
+ param_header_t h;
+ image_info_t *bl31_image_info;
+ entry_point_info_t *bl32_ep_info;
+ image_info_t *bl32_image_info;
+ entry_point_info_t *bl33_ep_info;
+ image_info_t *bl33_image_info;
+} bl31_params_t;
+
+/* BL3 utility functions */
+void ls_bl31_early_platform_setup(void *from_bl2,
+ void *plat_params_from_bl2);
+/* LS Helper functions */
+unsigned int plat_my_core_mask(void);
+unsigned int plat_core_mask(u_register_t mpidr);
+unsigned int plat_core_pos(u_register_t mpidr);
+//unsigned int plat_my_core_pos(void);
+
+/* BL31 Data API(s) */
+void _init_global_data(void);
+void _initialize_psci(void);
+uint32_t _getCoreState(u_register_t core_mask);
+void _setCoreState(u_register_t core_mask, u_register_t core_state);
+
+/* SoC defined structure and API(s) */
+void soc_runtime_setup(void);
+void soc_init(void);
+void soc_platform_setup(void);
+void soc_early_platform_setup2(void);
+#endif /* IMAGE_BL31 */
+
+#ifdef IMAGE_BL2
+void soc_early_init(void);
+void soc_mem_access(void);
+void soc_preload_setup(void);
+void soc_bl2_prepare_exit(void);
+
+/* IO storage utility functions */
+int plat_io_setup(void);
+int open_backend(const uintptr_t spec);
+
+void ls_bl2_plat_arch_setup(void);
+void ls_bl2_el3_plat_arch_setup(void);
+
+enum boot_device {
+ BOOT_DEVICE_IFC_NOR,
+ BOOT_DEVICE_IFC_NAND,
+ BOOT_DEVICE_QSPI,
+ BOOT_DEVICE_EMMC,
+ BOOT_DEVICE_SDHC2_EMMC,
+ BOOT_DEVICE_FLEXSPI_NOR,
+ BOOT_DEVICE_FLEXSPI_NAND,
+ BOOT_DEVICE_NONE
+};
+
+enum boot_device get_boot_dev(void);
+
+/* DDR Related functions */
+#if DDR_INIT
+#ifdef NXP_WARM_BOOT
+long long init_ddr(uint32_t wrm_bt_flg);
+#else
+long long init_ddr(void);
+#endif
+#endif
+
+/* Board specific weak functions */
+bool board_enable_povdd(void);
+bool board_disable_povdd(void);
+
+void mmap_add_ddr_region_dynamically(void);
+#endif /* IMAGE_BL2 */
+
+typedef struct {
+ uint64_t addr;
+ uint64_t size;
+} region_info_t;
+
+typedef struct {
+ uint64_t num_dram_regions;
+ int64_t total_dram_size;
+ region_info_t region[NUM_DRAM_REGIONS];
+} dram_regions_info_t;
+
+dram_regions_info_t *get_dram_regions_info(void);
+
+void ls_setup_page_tables(uintptr_t total_base,
+ size_t total_size,
+ uintptr_t code_start,
+ uintptr_t code_limit,
+ uintptr_t rodata_start,
+ uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ , uintptr_t coh_start,
+ uintptr_t coh_limit
+#endif
+);
+
+#define SOC_NAME_MAX_LEN (20)
+
+/* Structure to define SoC personality */
+struct soc_type {
+ char name[SOC_NAME_MAX_LEN];
+ uint32_t version;
+ uint8_t num_clusters;
+ uint8_t cores_per_cluster;
+};
+void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count,
+ uint8_t *num_clusters, uint8_t *cores_per_cluster);
+
+#define SOC_ENTRY(n, v, ncl, nc) { \
+ .name = #n, \
+ .version = SVR_##v, \
+ .num_clusters = (ncl), \
+ .cores_per_cluster = (nc)}
+
+#endif /* PLAT_COMMON_H */
diff --git a/plat/nxp/common/setup/include/plat_macros.S b/plat/nxp/common/setup/include/plat_macros.S
new file mode 100644
index 0000000..69a3b08
--- /dev/null
+++ b/plat/nxp/common/setup/include/plat_macros.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/nxp/common/setup/ls_bl2_el3_setup.c b/plat/nxp/common/setup/ls_bl2_el3_setup.c
new file mode 100644
index 0000000..a4cbaef
--- /dev/null
+++ b/plat/nxp/common/setup/ls_bl2_el3_setup.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+
+#include <common/desc_image_load.h>
+#include <dcfg.h>
+#ifdef POLICY_FUSE_PROVISION
+#include <fuse_io.h>
+#endif
+#include <mmu_def.h>
+#include <plat_common.h>
+#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA
+#include <plat_nv_storage.h>
+#endif
+
+#pragma weak bl2_el3_early_platform_setup
+#pragma weak bl2_el3_plat_arch_setup
+#pragma weak bl2_el3_plat_prepare_exit
+
+static dram_regions_info_t dram_regions_info = {0};
+
+/*******************************************************************************
+ * Return the pointer to the 'dram_regions_info structure of the DRAM.
+ * This structure is populated after init_ddr().
+ ******************************************************************************/
+dram_regions_info_t *get_dram_regions_info(void)
+{
+ return &dram_regions_info;
+}
+
+#ifdef DDR_INIT
+static void populate_dram_regions_info(void)
+{
+ long long dram_remain_size = dram_regions_info.total_dram_size;
+ uint8_t reg_id = 0U;
+
+ dram_regions_info.region[reg_id].addr = NXP_DRAM0_ADDR;
+ dram_regions_info.region[reg_id].size =
+ dram_remain_size > NXP_DRAM0_MAX_SIZE ?
+ NXP_DRAM0_MAX_SIZE : dram_remain_size;
+
+ if (dram_regions_info.region[reg_id].size != NXP_DRAM0_SIZE) {
+ ERROR("Incorrect DRAM0 size is defined in platform_def.h\n");
+ }
+
+ dram_remain_size -= dram_regions_info.region[reg_id].size;
+ dram_regions_info.region[reg_id].size -= (NXP_SECURE_DRAM_SIZE
+ + NXP_SP_SHRD_DRAM_SIZE);
+
+ assert(dram_regions_info.region[reg_id].size > 0);
+
+ /* Reducing total dram size by 66MB */
+ dram_regions_info.total_dram_size -= (NXP_SECURE_DRAM_SIZE
+ + NXP_SP_SHRD_DRAM_SIZE);
+
+#if defined(NXP_DRAM1_ADDR) && defined(NXP_DRAM1_MAX_SIZE)
+ if (dram_remain_size > 0) {
+ reg_id++;
+ dram_regions_info.region[reg_id].addr = NXP_DRAM1_ADDR;
+ dram_regions_info.region[reg_id].size =
+ dram_remain_size > NXP_DRAM1_MAX_SIZE ?
+ NXP_DRAM1_MAX_SIZE : dram_remain_size;
+ dram_remain_size -= dram_regions_info.region[reg_id].size;
+ }
+#endif
+#if defined(NXP_DRAM2_ADDR) && defined(NXP_DRAM2_MAX_SIZE)
+ if (dram_remain_size > 0) {
+ reg_id++;
+ dram_regions_info.region[reg_id].addr = NXP_DRAM1_ADDR;
+ dram_regions_info.region[reg_id].size =
+ dram_remain_size > NXP_DRAM1_MAX_SIZE ?
+ NXP_DRAM1_MAX_SIZE : dram_remain_size;
+ dram_remain_size -= dram_regions_info.region[reg_id].size;
+ }
+#endif
+ reg_id++;
+ dram_regions_info.num_dram_regions = reg_id;
+}
+#endif
+
+#ifdef IMAGE_BL32
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+static uint32_t ls_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0U;
+}
+#endif
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+#ifndef AARCH32
+static uint32_t ls_get_spsr_for_bl33_entry(void)
+{
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#else
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+static uint32_t ls_get_spsr_for_bl33_entry(void)
+{
+ unsigned int hyp_status, mode, spsr;
+
+ hyp_status = GET_VIRT_EXT(read_id_pfr1());
+
+ mode = (hyp_status) ? MODE32_hyp : MODE32_svc;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_MODE32(mode, plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+#endif /* AARCH32 */
+
+void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ /*
+ * SoC specific early init
+ * Any errata handling or SoC specific early initialization can
+ * be done here
+ * Set Counter Base Frequency in CNTFID0 and in cntfrq_el0.
+ * Initialize the interconnect.
+ * Enable coherency for primary CPU cluster
+ */
+ soc_early_init();
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_io_setup();
+
+ if (dram_regions_info.total_dram_size > 0) {
+ populate_dram_regions_info();
+ }
+
+#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA
+ read_nv_app_data();
+#if DEBUG
+ const nv_app_data_t *nv_app_data = get_nv_data();
+
+ INFO("Value of warm_reset flag = 0x%x\n", nv_app_data->warm_rst_flag);
+ INFO("Value of WDT flag = 0x%x\n", nv_app_data->wdt_rst_flag);
+#endif
+#endif
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only initializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void ls_bl2_el3_plat_arch_setup(void)
+{
+ unsigned int flags = 0U;
+ /* Initialise the IO layer and register platform IO devices */
+ ls_setup_page_tables(
+#if SEPARATE_BL2_NOLOAD_REGION
+ BL2_START,
+ BL2_LIMIT - BL2_START,
+#else
+ BL2_BASE,
+ (unsigned long)(&__BL2_END__) - BL2_BASE,
+#endif
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+
+ if ((dram_regions_info.region[0].addr == 0)
+ && (dram_regions_info.total_dram_size == 0)) {
+ flags = XLAT_TABLE_NC;
+ }
+
+#ifdef AARCH32
+ enable_mmu_secure(0);
+#else
+ enable_mmu_el3(flags);
+#endif
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ ls_bl2_el3_plat_arch_setup();
+}
+
+void bl2_platform_setup(void)
+{
+ /*
+ * Perform platform setup before loading the image.
+ */
+}
+
+/* Handling image information by platform. */
+int ls_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL31_IMAGE_ID:
+ bl_mem_params->ep_info.args.arg3 =
+ (u_register_t) &dram_regions_info;
+
+ /* Pass the value of PORSR1 register in Argument 4 */
+ bl_mem_params->ep_info.args.arg4 =
+ (u_register_t)read_reg_porsr1();
+ flush_dcache_range((uintptr_t)&dram_regions_info,
+ sizeof(dram_regions_info));
+ break;
+#if defined(AARCH64) && defined(IMAGE_BL32)
+ case BL32_IMAGE_ID:
+ bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl32_entry();
+ break;
+#endif
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = ls_get_spsr_for_bl33_entry();
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return ls_bl2_handle_post_image_load(image_id);
+}
+
+void bl2_el3_plat_prepare_exit(void)
+{
+ return soc_bl2_prepare_exit();
+}
+
+/* Called to do the dynamic initialization required
+ * before loading the next image.
+ */
+void bl2_plat_preload_setup(void)
+{
+
+ soc_preload_setup();
+
+#ifdef DDR_INIT
+ if (dram_regions_info.total_dram_size <= 0) {
+ ERROR("Asserting as the DDR is not initialized yet.");
+ assert(false);
+ }
+#endif
+
+ if ((dram_regions_info.region[0].addr == 0)
+ && (dram_regions_info.total_dram_size > 0)) {
+ populate_dram_regions_info();
+#ifdef PLAT_XLAT_TABLES_DYNAMIC
+ mmap_add_ddr_region_dynamically();
+#endif
+ }
+
+ /* setup the memory region access permissions */
+ soc_mem_access();
+
+#ifdef POLICY_FUSE_PROVISION
+ fip_fuse_provisioning((uintptr_t)FUSE_BUF, FUSE_SZ);
+#endif
+}
diff --git a/plat/nxp/common/setup/ls_bl31_setup.c b/plat/nxp/common/setup/ls_bl31_setup.c
new file mode 100644
index 0000000..bd0ab4f
--- /dev/null
+++ b/plat/nxp/common/setup/ls_bl31_setup.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#ifdef LS_EL3_INTERRUPT_HANDLER
+#include <ls_interrupt_mgmt.h>
+#endif
+#include <mmu_def.h>
+#include <plat_common.h>
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+#ifdef TEST_BL31
+#define SPSR_FOR_EL2H 0x3C9
+#define SPSR_FOR_EL1H 0x3C5
+#else
+static entry_point_info_t bl31_image_ep_info;
+#endif
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+static dram_regions_info_t dram_regions_info = {0};
+static uint64_t rcw_porsr1;
+
+/* Return the pointer to the 'dram_regions_info structure of the DRAM.
+ * This structure is populated after init_ddr().
+ */
+dram_regions_info_t *get_dram_regions_info(void)
+{
+ return &dram_regions_info;
+}
+
+/* Return the RCW.PORSR1 value which was passed in from BL2
+ */
+uint64_t bl31_get_porsr1(void)
+{
+ return rcw_porsr1;
+}
+
+/*
+ * Return pointer to the 'entry_point_info' structure of the next image for the
+ * security state specified:
+ * - BL33 corresponds to the non-secure image type; while
+ * - BL32 corresponds to the secure image type.
+ * - A NULL pointer is returned, if the image does not exist.
+ */
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+
+#ifdef TEST_BL31
+ next_image_info->pc = _get_test_entry();
+ next_image_info->spsr = SPSR_FOR_EL2H;
+ next_image_info->h.attr = NON_SECURE;
+#endif
+
+ if (next_image_info->pc != 0U) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * Perform any BL31 early platform setup common to NXP platforms.
+ * - Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & S-EL3 in BL1) before they are lost (potentially).
+ * - This needs to be done before the MMU is initialized so that the
+ * memory layout can be used while creating page tables.
+ * - BL2 has flushed this information to memory, in order to fetch latest data.
+ */
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+#ifndef TEST_BL31
+ int i = 0;
+ void *from_bl2 = (void *)arg0;
+#endif
+ soc_early_platform_setup2();
+
+#ifdef TEST_BL31
+ dram_regions_info.num_dram_regions = 2;
+ dram_regions_info.total_dram_size = 0x100000000;
+ dram_regions_info.region[0].addr = 0x80000000;
+ dram_regions_info.region[0].size = 0x80000000;
+ dram_regions_info.region[1].addr = 0x880000000;
+ dram_regions_info.region[1].size = 0x80000000;
+
+ bl33_image_ep_info.pc = _get_test_entry();
+#else
+ /*
+ * Check params passed from BL2 should not be NULL,
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params != NULL) {
+ if (bl_params->image_id == BL31_IMAGE_ID) {
+ bl31_image_ep_info = *bl_params->ep_info;
+ dram_regions_info_t *loc_dram_regions_info =
+ (dram_regions_info_t *) bl31_image_ep_info.args.arg3;
+
+ dram_regions_info.num_dram_regions =
+ loc_dram_regions_info->num_dram_regions;
+ dram_regions_info.total_dram_size =
+ loc_dram_regions_info->total_dram_size;
+ VERBOSE("Number of DRAM Regions = %" PRIx64 "\n",
+ dram_regions_info.num_dram_regions);
+
+ for (i = 0; i < dram_regions_info.num_dram_regions;
+ i++) {
+ dram_regions_info.region[i].addr =
+ loc_dram_regions_info->region[i].addr;
+ dram_regions_info.region[i].size =
+ loc_dram_regions_info->region[i].size;
+ VERBOSE("DRAM%d Size = %" PRIx64 "\n", i,
+ dram_regions_info.region[i].size);
+ }
+ rcw_porsr1 = bl31_image_ep_info.args.arg4;
+ }
+
+ if (bl_params->image_id == BL32_IMAGE_ID) {
+ bl32_image_ep_info = *bl_params->ep_info;
+ }
+
+ if (bl_params->image_id == BL33_IMAGE_ID) {
+ bl33_image_ep_info = *bl_params->ep_info;
+ }
+
+ bl_params = bl_params->next_params_info;
+ }
+#endif /* TEST_BL31 */
+
+ if (bl33_image_ep_info.pc == 0) {
+ panic();
+ }
+
+ /*
+ * perform basic initialization on the soc
+ */
+ soc_init();
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ NOTICE("Welcome to %s BL31 Phase\n", BOARD);
+ soc_platform_setup();
+
+ /* Console logs gone missing as part going to
+ * EL1 for initilizing Bl32 if present.
+ * console flush is necessary to avoid it.
+ */
+ (void)console_flush();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+#ifdef LS_EL3_INTERRUPT_HANDLER
+ ls_el3_interrupt_config();
+#endif
+ soc_runtime_setup();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup shared between
+ * ARM standard platforms. This only does basic initialization. Later
+ * architectural setup (bl31_arch_setup()) does not do anything platform
+ * specific.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+
+ ls_setup_page_tables(BL31_BASE,
+ BL31_END - BL31_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END
+#endif
+ );
+ enable_mmu_el3(0);
+}
diff --git a/plat/nxp/common/setup/ls_common.c b/plat/nxp/common/setup/ls_common.c
new file mode 100644
index 0000000..28d6b72
--- /dev/null
+++ b/plat/nxp/common/setup/ls_common.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <mmu_def.h>
+#include <plat/common/platform.h>
+
+#include "plat_common.h"
+#include "platform_def.h"
+
+const mmap_region_t *plat_ls_get_mmap(void);
+
+/*
+ * Table of memory regions for various BL stages to map using the MMU.
+ * This doesn't include Trusted SRAM as arm_setup_page_tables() already
+ * takes care of mapping it.
+ *
+ * The flash needs to be mapped as writable in order to erase the FIP's Table of
+ * Contents in case of unrecoverable error (see plat_error_handler()).
+ */
+#ifdef IMAGE_BL2
+const mmap_region_t plat_ls_mmap[] = {
+ LS_MAP_CCSR,
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL31
+const mmap_region_t plat_ls_mmap[] = {
+ LS_MAP_CCSR,
+#ifdef NXP_DCSR_ADDR
+ LS_MAP_DCSR,
+#endif
+ LS_MAP_OCRAM,
+ {0}
+};
+#endif
+#ifdef IMAGE_BL32
+const mmap_region_t plat_ls_mmap[] = {
+ LS_MAP_CCSR,
+ LS_MAP_BL32_SEC_MEM,
+ {0}
+};
+#endif
+
+/* Weak definitions may be overridden in specific NXP SoC */
+#pragma weak plat_get_ns_image_entrypoint
+#pragma weak plat_ls_get_mmap
+
+#if defined(IMAGE_BL31) || !defined(CONFIG_DDR_FIP_IMAGE)
+static void mmap_add_ddr_regions_statically(void)
+{
+ int i = 0;
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+ /* MMU map for Non-Secure DRAM Regions */
+ VERBOSE("DRAM Region %d: %p - %p\n", i,
+ (void *) info_dram_regions->region[i].addr,
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size
+ - 1));
+ mmap_add_region(info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].size,
+ MT_MEMORY | MT_RW | MT_NS);
+
+ /* MMU map for Secure DDR Region on DRAM-0 */
+ if (info_dram_regions->region[i].size >
+ (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) {
+ VERBOSE("Secure DRAM Region %d: %p - %p\n", i,
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size),
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size
+ + NXP_SECURE_DRAM_SIZE
+ + NXP_SP_SHRD_DRAM_SIZE
+ - 1));
+ mmap_add_region((info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size),
+ (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size),
+ (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE),
+ MT_MEMORY | MT_RW | MT_SECURE);
+ }
+
+#ifdef IMAGE_BL31
+ for (i = 1; i < info_dram_regions->num_dram_regions; i++) {
+ if (info_dram_regions->region[i].size == 0)
+ break;
+ VERBOSE("DRAM Region %d: %p - %p\n", i,
+ (void *) info_dram_regions->region[i].addr,
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size
+ - 1));
+ mmap_add_region(info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].size,
+ MT_MEMORY | MT_RW | MT_NS);
+ }
+#endif
+}
+#endif
+
+#if defined(PLAT_XLAT_TABLES_DYNAMIC)
+void mmap_add_ddr_region_dynamically(void)
+{
+ int ret, i = 0;
+
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+ /* MMU map for Non-Secure DRAM Regions */
+ VERBOSE("DRAM Region %d: %p - %p\n", i,
+ (void *) info_dram_regions->region[i].addr,
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size
+ - 1));
+ ret = mmap_add_dynamic_region(info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].size,
+ MT_MEMORY | MT_RW | MT_NS);
+ if (ret != 0) {
+ ERROR("Failed to add dynamic memory region\n");
+ panic();
+ }
+
+ /* MMU map for Secure DDR Region on DRAM-0 */
+ if (info_dram_regions->region[i].size >
+ (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE)) {
+ VERBOSE("Secure DRAM Region %d: %p - %p\n", i,
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size),
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size
+ + NXP_SECURE_DRAM_SIZE
+ + NXP_SP_SHRD_DRAM_SIZE
+ - 1));
+ ret = mmap_add_dynamic_region((info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size),
+ (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size),
+ (NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE),
+ MT_MEMORY | MT_RW | MT_SECURE);
+ if (ret != 0) {
+ ERROR("Failed to add dynamic memory region\n");
+ panic();
+ }
+ }
+
+#ifdef IMAGE_BL31
+ for (i = 1; i < info_dram_regions->num_dram_regions; i++) {
+ if (info_dram_regions->region[i].size == 0) {
+ break;
+ }
+ VERBOSE("DRAM Region %d: %p - %p\n", i,
+ (void *) info_dram_regions->region[i].addr,
+ (void *) (info_dram_regions->region[i].addr
+ + info_dram_regions->region[i].size
+ - 1));
+ ret = mmap_add_dynamic_region(info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].addr,
+ info_dram_regions->region[i].size,
+ MT_MEMORY | MT_RW | MT_NS);
+ if (ret != 0) {
+ ERROR("Failed to add dynamic memory region\n");
+ panic();
+ }
+ }
+#endif
+}
+#endif
+
+/*
+ * Set up the page tables for the generic and platform-specific memory regions.
+ * The extents of the generic memory regions are specified by the function
+ * arguments and consist of:
+ * - Trusted SRAM seen by the BL image;
+ * - Code section;
+ * - Read-only data section;
+ * - Coherent memory region, if applicable.
+ */
+void ls_setup_page_tables(uintptr_t total_base,
+ size_t total_size,
+ uintptr_t code_start,
+ uintptr_t code_limit,
+ uintptr_t rodata_start,
+ uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ ,
+ uintptr_t coh_start,
+ uintptr_t coh_limit
+#endif
+ )
+{
+ /*
+ * Map the Trusted SRAM with appropriate memory attributes.
+ * Subsequent mappings will adjust the attributes for specific regions.
+ */
+ VERBOSE("Memory seen by this BL image: %p - %p\n",
+ (void *) total_base, (void *) (total_base + total_size));
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ /* Re-map the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *) code_start, (void *) code_limit);
+ mmap_add_region(code_start, code_start,
+ code_limit - code_start,
+ MT_CODE | MT_SECURE);
+
+ /* Re-map the read-only data section */
+ VERBOSE("Read-only data region: %p - %p\n",
+ (void *) rodata_start, (void *) rodata_limit);
+ mmap_add_region(rodata_start, rodata_start,
+ rodata_limit - rodata_start,
+ MT_RO_DATA | MT_SECURE);
+
+#if USE_COHERENT_MEM
+ /* Re-map the coherent memory region */
+ VERBOSE("Coherent region: %p - %p\n",
+ (void *) coh_start, (void *) coh_limit);
+ mmap_add_region(coh_start, coh_start,
+ coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+ /* Now (re-)map the platform-specific memory regions */
+ mmap_add(plat_ls_get_mmap());
+
+
+#if defined(IMAGE_BL31) || !defined(CONFIG_DDR_FIP_IMAGE)
+ mmap_add_ddr_regions_statically();
+#endif
+
+ /* Create the page tables to reflect the above mappings */
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Returns NXP platform specific memory map regions.
+ ******************************************************************************/
+const mmap_region_t *plat_ls_get_mmap(void)
+{
+ return plat_ls_mmap;
+}
+
+/*
+ * This function get the number of clusters and cores count per cluster
+ * in the SoC.
+ */
+void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count,
+ uint8_t *num_clusters, uint8_t *cores_per_cluster)
+{
+ const soc_info_t *soc_info = get_soc_info();
+ *num_clusters = NUMBER_OF_CLUSTERS;
+ *cores_per_cluster = CORES_PER_CLUSTER;
+ unsigned int i;
+
+ for (i = 0U; i < ps_count; i++) {
+ if (soc_list[i].version == soc_info->svr_reg.bf_ver.version) {
+ *num_clusters = soc_list[i].num_clusters;
+ *cores_per_cluster = soc_list[i].cores_per_cluster;
+ break;
+ }
+ }
+
+ VERBOSE("NUM of cluster = 0x%x, Cores per cluster = 0x%x\n",
+ *num_clusters, *cores_per_cluster);
+}
diff --git a/plat/nxp/common/setup/ls_err.c b/plat/nxp/common/setup/ls_err.c
new file mode 100644
index 0000000..845cd15
--- /dev/null
+++ b/plat/nxp/common/setup/ls_err.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#if TRUSTED_BOARD_BOOT
+#include <dcfg.h>
+#include <snvs.h>
+#endif
+
+#include "plat_common.h"
+
+/*
+ * Error handler
+ */
+void plat_error_handler(int err)
+{
+#if TRUSTED_BOARD_BOOT
+ uint32_t mode;
+ bool sb = check_boot_mode_secure(&mode);
+#endif
+
+ switch (err) {
+ case -ENOENT:
+ case -EAUTH:
+ printf("Authentication failure\n");
+#if TRUSTED_BOARD_BOOT
+ /* For SB production mode i.e ITS = 1 */
+ if (sb == true) {
+ if (mode == 1U) {
+ transition_snvs_soft_fail();
+ } else {
+ transition_snvs_non_secure();
+ }
+ }
+#endif
+ break;
+ default:
+ /* Unexpected error */
+ break;
+ }
+
+ /* Loop until the watchdog resets the system */
+ for (;;)
+ wfi();
+}
diff --git a/plat/nxp/common/setup/ls_image_load.c b/plat/nxp/common/setup/ls_image_load.c
new file mode 100644
index 0000000..259ab31
--- /dev/null
+++ b/plat/nxp/common/setup/ls_image_load.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/desc_image_load.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/nxp/common/setup/ls_interrupt_mgmt.c b/plat/nxp/common/setup/ls_interrupt_mgmt.c
new file mode 100644
index 0000000..a81cb2b
--- /dev/null
+++ b/plat/nxp/common/setup/ls_interrupt_mgmt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <bl31/interrupt_mgmt.h>
+#include <common/debug.h>
+#include <ls_interrupt_mgmt.h>
+#include <plat/common/platform.h>
+
+static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3];
+
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
+{
+ /* Validate 'handler' and 'id' parameters */
+ if (!handler || id >= MAX_INTR_EL3) {
+ return -EINVAL;
+ }
+
+ /* Check if a handler has already been registered */
+ if (type_el3_interrupt_table[id] != NULL) {
+ return -EALREADY;
+ }
+
+ type_el3_interrupt_table[id] = handler;
+
+ return 0;
+}
+
+static uint64_t ls_el3_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint32_t intr_id;
+ interrupt_type_handler_t handler;
+
+ intr_id = plat_ic_get_pending_interrupt_id();
+
+ INFO("Interrupt recvd is %d\n", intr_id);
+
+ handler = type_el3_interrupt_table[intr_id];
+ if (handler != NULL) {
+ handler(intr_id, flags, handle, cookie);
+ }
+
+ /*
+ * Mark this interrupt as complete to avoid a interrupt storm.
+ */
+ plat_ic_end_of_interrupt(intr_id);
+
+ return 0U;
+}
+
+void ls_el3_interrupt_config(void)
+{
+ uint64_t flags = 0U;
+ uint64_t rc;
+
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_EL3,
+ ls_el3_interrupt_handler, flags);
+ if (rc != 0U) {
+ panic();
+ }
+}
diff --git a/plat/nxp/common/setup/ls_io_storage.c b/plat/nxp/common/setup/ls_io_storage.c
new file mode 100644
index 0000000..7f01e72
--- /dev/null
+++ b/plat/nxp/common/setup/ls_io_storage.c
@@ -0,0 +1,556 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <endian.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#ifdef FLEXSPI_NOR_BOOT
+#include <flexspi_nor.h>
+#endif
+#if defined(NAND_BOOT)
+#include <ifc_nand.h>
+#endif
+#if defined(NOR_BOOT)
+#include <ifc_nor.h>
+#endif
+#if defined(QSPI_BOOT)
+#include <qspi.h>
+#endif
+#if defined(SD_BOOT) || defined(EMMC_BOOT)
+#include <sd_mmc.h>
+#endif
+#include <tools_share/firmware_image_package.h>
+
+#ifdef CONFIG_DDR_FIP_IMAGE
+#include <ddr_io_storage.h>
+#endif
+#ifdef POLICY_FUSE_PROVISION
+#include <fuse_io.h>
+#endif
+#include "plat_common.h"
+#include "platform_def.h"
+
+uint32_t fip_device;
+/* IO devices */
+uintptr_t backend_dev_handle;
+
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *backend_dev_con;
+
+static io_block_spec_t fip_block_spec = {
+ .offset = PLAT_FIP_OFFSET,
+ .length = PLAT_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t fuse_bl2_uuid_spec = {
+ .uuid = UUID_SCP_FIRMWARE_SCP_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+static const io_uuid_spec_t tb_fw_config_uuid_spec = {
+ .uuid = UUID_TB_FW_CONFIG,
+};
+
+static const io_uuid_spec_t hw_config_uuid_spec = {
+ .uuid = UUID_HW_CONFIG,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t fuse_key_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t fuse_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, ARM platforms load images from the FIP */
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &backend_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_backend
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [SCP_BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&fuse_bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+ [TB_FW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_config_uuid_spec,
+ open_fip
+ },
+ [HW_CONFIG_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&hw_config_uuid_spec,
+ open_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ open_fip
+ },
+ [SCP_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&fuse_key_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [SCP_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&fuse_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ open_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_io_setup
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ */
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+
+int open_backend(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(backend_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(backend_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+#if defined(SD_BOOT) || defined(EMMC_BOOT) || defined(NAND_BOOT)
+static int plat_io_block_setup(size_t fip_offset, uintptr_t block_dev_spec)
+{
+ int io_result;
+
+ fip_block_spec.offset = fip_offset;
+
+ io_result = register_io_dev_block(&backend_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(backend_dev_con, block_dev_spec,
+ &backend_dev_handle);
+ assert(io_result == 0);
+
+ return io_result;
+}
+#endif
+
+#if defined(FLEXSPI_NOR_BOOT) || defined(QSPI_BOOT) || defined(NOR_BOOT)
+static int plat_io_memmap_setup(size_t fip_offset)
+{
+ int io_result;
+
+ fip_block_spec.offset = fip_offset;
+
+ io_result = register_io_dev_memmap(&backend_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(backend_dev_con, (uintptr_t)NULL,
+ &backend_dev_handle);
+ assert(io_result == 0);
+
+ return io_result;
+}
+#endif
+
+static int ls_io_fip_setup(unsigned int boot_dev)
+{
+ int io_result;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)&fip_device,
+ &fip_dev_handle);
+ assert(io_result == 0);
+
+#ifdef CONFIG_DDR_FIP_IMAGE
+ /* Open connection to DDR FIP image if available */
+ io_result = ddr_fip_setup(fip_dev_con, boot_dev);
+
+ assert(io_result == 0);
+#endif
+
+#ifdef POLICY_FUSE_PROVISION
+ /* Open connection to FUSE FIP image if available */
+ io_result = fuse_fip_setup(fip_dev_con, boot_dev);
+
+ assert(io_result == 0);
+#endif
+
+ return io_result;
+}
+
+int ls_qspi_io_setup(void)
+{
+#ifdef QSPI_BOOT
+ qspi_io_setup(NXP_QSPI_FLASH_ADDR,
+ NXP_QSPI_FLASH_SIZE,
+ PLAT_FIP_OFFSET);
+ return plat_io_memmap_setup(NXP_QSPI_FLASH_ADDR + PLAT_FIP_OFFSET);
+#else
+ ERROR("QSPI driver not present. Check your BUILD\n");
+
+ /* Should never reach here */
+ assert(false);
+ return -1;
+#endif
+}
+
+int emmc_sdhc2_io_setup(void)
+{
+#if defined(EMMC_BOOT) && defined(NXP_ESDHC2_ADDR)
+ uintptr_t block_dev_spec;
+ int ret;
+
+ ret = sd_emmc_init(&block_dev_spec,
+ NXP_ESDHC2_ADDR,
+ NXP_SD_BLOCK_BUF_ADDR,
+ NXP_SD_BLOCK_BUF_SIZE,
+ false);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec);
+#else
+ ERROR("EMMC driver not present. Check your BUILD\n");
+
+ /* Should never reach here */
+ assert(false);
+ return -1;
+#endif
+}
+
+int emmc_io_setup(void)
+{
+/* On the platforms which only has one ESDHC controller,
+ * eMMC-boot will use the first ESDHC controller.
+ */
+#if defined(SD_BOOT) || defined(EMMC_BOOT)
+ uintptr_t block_dev_spec;
+ int ret;
+
+ ret = sd_emmc_init(&block_dev_spec,
+ NXP_ESDHC_ADDR,
+ NXP_SD_BLOCK_BUF_ADDR,
+ NXP_SD_BLOCK_BUF_SIZE,
+ true);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec);
+#else
+ ERROR("SD driver not present. Check your BUILD\n");
+
+ /* Should never reach here */
+ assert(false);
+ return -1;
+#endif
+}
+
+int ifc_nor_io_setup(void)
+{
+#if defined(NOR_BOOT)
+ int ret;
+
+ ret = ifc_nor_init(NXP_NOR_FLASH_ADDR,
+ NXP_NOR_FLASH_SIZE);
+
+ if (ret != 0) {
+ return ret;
+ }
+
+ return plat_io_memmap_setup(NXP_NOR_FLASH_ADDR + PLAT_FIP_OFFSET);
+#else
+ ERROR("NOR driver not present. Check your BUILD\n");
+
+ /* Should never reach here */
+ assert(false);
+ return -1;
+#endif
+}
+
+int ifc_nand_io_setup(void)
+{
+#if defined(NAND_BOOT)
+ uintptr_t block_dev_spec;
+ int ret;
+
+ ret = ifc_nand_init(&block_dev_spec,
+ NXP_IFC_REGION_ADDR,
+ NXP_IFC_ADDR,
+ NXP_IFC_SRAM_BUFFER_SIZE,
+ NXP_SD_BLOCK_BUF_ADDR,
+ NXP_SD_BLOCK_BUF_SIZE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return plat_io_block_setup(PLAT_FIP_OFFSET, block_dev_spec);
+#else
+
+ ERROR("NAND driver not present. Check your BUILD\n");
+
+ /* Should never reach here */
+ assert(false);
+ return -1;
+#endif
+}
+
+int ls_flexspi_nor_io_setup(void)
+{
+#ifdef FLEXSPI_NOR_BOOT
+ int ret = 0;
+
+ ret = flexspi_nor_io_setup(NXP_FLEXSPI_FLASH_ADDR,
+ NXP_FLEXSPI_FLASH_SIZE,
+ NXP_FLEXSPI_ADDR);
+
+ if (ret != 0) {
+ ERROR("FlexSPI NOR driver initialization error.\n");
+ /* Should never reach here */
+ assert(0);
+ panic();
+ return -1;
+ }
+
+ return plat_io_memmap_setup(NXP_FLEXSPI_FLASH_ADDR + PLAT_FIP_OFFSET);
+#else
+ ERROR("FlexSPI NOR driver not present. Check your BUILD\n");
+
+ /* Should never reach here */
+ assert(false);
+ return -1;
+#endif
+}
+
+static int (* const ls_io_setup_table[])(void) = {
+ [BOOT_DEVICE_IFC_NOR] = ifc_nor_io_setup,
+ [BOOT_DEVICE_IFC_NAND] = ifc_nand_io_setup,
+ [BOOT_DEVICE_QSPI] = ls_qspi_io_setup,
+ [BOOT_DEVICE_EMMC] = emmc_io_setup,
+ [BOOT_DEVICE_SDHC2_EMMC] = emmc_sdhc2_io_setup,
+ [BOOT_DEVICE_FLEXSPI_NOR] = ls_flexspi_nor_io_setup,
+ [BOOT_DEVICE_FLEXSPI_NAND] = ls_flexspi_nor_io_setup,
+};
+
+
+int plat_io_setup(void)
+{
+ int (*io_setup)(void);
+ unsigned int boot_dev = BOOT_DEVICE_NONE;
+ int ret;
+
+ boot_dev = get_boot_dev();
+ if (boot_dev == BOOT_DEVICE_NONE) {
+ ERROR("Boot Device detection failed, Check RCW_SRC\n");
+ return -EINVAL;
+ }
+
+ io_setup = ls_io_setup_table[boot_dev];
+ ret = io_setup();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = ls_io_fip_setup(boot_dev);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result = -1;
+ const struct plat_io_policy *policy;
+
+ if (image_id < ARRAY_SIZE(policies)) {
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ }
+ }
+#ifdef CONFIG_DDR_FIP_IMAGE
+ else {
+ VERBOSE("Trying alternative IO\n");
+ result = plat_get_ddr_fip_image_source(image_id, dev_handle,
+ image_spec, open_backend);
+ }
+#endif
+#ifdef POLICY_FUSE_PROVISION
+ if (result != 0) {
+ VERBOSE("Trying FUSE IO\n");
+ result = plat_get_fuse_image_source(image_id, dev_handle,
+ image_spec, open_backend);
+ }
+#endif
+
+ return result;
+}
diff --git a/plat/nxp/common/setup/ls_stack_protector.c b/plat/nxp/common/setup/ls_stack_protector.c
new file mode 100644
index 0000000..ab78f88
--- /dev/null
+++ b/plat/nxp/common/setup/ls_stack_protector.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * TBD: Generate Random Number from NXP CAAM Block.
+ */
+ return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
diff --git a/plat/nxp/common/sip_svc/aarch64/sipsvc.S b/plat/nxp/common/sip_svc/aarch64/sipsvc.S
new file mode 100644
index 0000000..6a47cbf
--- /dev/null
+++ b/plat/nxp/common/sip_svc/aarch64/sipsvc.S
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <asm_macros.S>
+#include <bl31_data.h>
+
+.global el2_2_aarch32
+.global prefetch_disable
+
+#define SPSR_EL3_M4 0x10
+#define SPSR_EL_MASK 0xC
+#define SPSR_EL2 0x8
+#define SCR_EL3_4_EL2_AARCH32 0x131
+#define SPSR32_EL2_LE 0x1DA
+
+#define MIDR_PARTNUM_START 4
+#define MIDR_PARTNUM_WIDTH 12
+#define MIDR_PARTNUM_A53 0xD03
+#define MIDR_PARTNUM_A57 0xD07
+#define MIDR_PARTNUM_A72 0xD08
+
+/*
+ * uint64_t el2_2_aarch32(u_register_t smc_id,
+ * u_register_t start_addr,
+ * u_register_t parm1,
+ * u_register_t parm2)
+ * this function allows changing the execution width of EL2 from Aarch64
+ * to Aarch32
+ * Note: MUST be called from EL2 @ Aarch64
+ * in: x0 = smc function id
+ * x1 = start address for EL2 @ Aarch32
+ * x2 = first parameter to pass to EL2 @ Aarch32
+ * x3 = second parameter to pass to EL2 @ Aarch32
+ * out: x0 = 0, on success
+ * x0 = -1, on failure
+ * uses x0, x1, x2, x3
+ */
+func el2_2_aarch32
+
+ /* check that caller is EL2 @ Aarch64 - err return if not */
+ mrs x0, spsr_el3
+ /* see if we were called from Aarch32 */
+ tst x0, #SPSR_EL3_M4
+ b.ne 2f
+
+ /* see if we were called from EL2 */
+ and x0, x0, SPSR_EL_MASK
+ cmp x0, SPSR_EL2
+ b.ne 2f
+
+ /* set ELR_EL3 */
+ msr elr_el3, x1
+
+ /* set scr_el3 */
+ mov x0, #SCR_EL3_4_EL2_AARCH32
+ msr scr_el3, x0
+
+ /* set sctlr_el2 */
+ ldr x1, =SCTLR_EL2_RES1
+ msr sctlr_el2, x1
+
+ /* set spsr_el3 */
+ ldr x0, =SPSR32_EL2_LE
+ msr spsr_el3, x0
+
+ /* x2 = parm 1
+ * x3 = parm2
+ */
+
+ /* set the parameters to be passed-thru to EL2 @ Aarch32 */
+ mov x1, x2
+ mov x2, x3
+
+ /* x1 = parm 1
+ * x2 = parm2
+ */
+
+ mov x0, xzr
+ /* invalidate the icache */
+ ic iallu
+ dsb sy
+ isb
+ b 1f
+2:
+ /* error return */
+ mvn x0, xzr
+ ret
+1:
+ eret
+endfunc el2_2_aarch32
+
+/*
+ * int prefetch_disable(u_register_t smc_id, u_register_t mask)
+ * this function marks cores which need to have the prefetch disabled -
+ * secondary cores have prefetch disabled when they are released from reset -
+ * the bootcore has prefetch disabled when this call is made
+ * in: x0 = function id
+ * x1 = core mask, where bit[0]=core0, bit[1]=core1, etc
+ * if a bit in the mask is set, then prefetch is disabled for that
+ * core
+ * out: x0 = SMC_SUCCESS
+ */
+func prefetch_disable
+ stp x4, x30, [sp, #-16]!
+
+ mov x3, x1
+
+ /* x1 = core prefetch disable mask */
+ /* x3 = core prefetch disable mask */
+
+ /* store the mask */
+ mov x0, #PREFETCH_DIS_OFFSET
+ bl _set_global_data
+
+ /* x3 = core prefetch disable mask */
+
+ /* see if we need to disable prefetch on THIS core */
+ bl plat_my_core_mask
+
+ /* x0 = core mask lsb */
+ /* x3 = core prefetch disable mask */
+
+ tst x3, x0
+ b.eq 1f
+
+ /* read midr_el1 */
+ mrs x1, midr_el1
+
+ /* x1 = midr_el1 */
+
+ mov x0, xzr
+ bfxil x0, x1, #MIDR_PARTNUM_START, #MIDR_PARTNUM_WIDTH
+
+ /* x0 = part number (a53, a57, a72, etc) */
+
+ /* branch on cpu-specific */
+ cmp x0, #MIDR_PARTNUM_A57
+ b.eq 1f
+ cmp x0, #MIDR_PARTNUM_A72
+ b.ne 1f
+
+ bl _disable_ldstr_pfetch_A72
+ b 1f
+1:
+ ldp x4, x30, [sp], #16
+ mov x0, xzr
+ ret
+endfunc prefetch_disable
diff --git a/plat/nxp/common/sip_svc/include/sipsvc.h b/plat/nxp/common/sip_svc/include/sipsvc.h
new file mode 100644
index 0000000..d9e61e9
--- /dev/null
+++ b/plat/nxp/common/sip_svc/include/sipsvc.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SIPSVC_H
+#define SIPSVC_H
+
+#include <stdint.h>
+
+#define SMC_FUNC_MASK 0x0000ffff
+#define SMC32_PARAM_MASK 0xffffffff
+
+/* SMC function IDs for SiP Service queries */
+#define SIP_SVC_CALL_COUNT 0xff00
+#define SIP_SVC_UID 0xff01
+#define SIP_SVC_VERSION 0xff03
+#define SIP_SVC_PRNG 0xff10
+#define SIP_SVC_RNG 0xff11
+#define SIP_SVC_MEM_BANK 0xff12
+#define SIP_SVC_PREFETCH_DIS 0xff13
+#define SIP_SVC_HUK 0xff14
+#define SIP_SVC_ALLOW_L1L2_ERR 0xff15
+#define SIP_SVC_ALLOW_L2_CLR 0xff16
+#define SIP_SVC_2_AARCH32 0xff17
+#define SIP_SVC_PORSR1 0xff18
+
+/* Layerscape SiP Service Calls version numbers */
+#define LS_SIP_SVC_VERSION_MAJOR 0x0
+#define LS_SIP_SVC_VERSION_MINOR 0x1
+
+/* Number of Layerscape SiP Calls implemented */
+#define LS_COMMON_SIP_NUM_CALLS 10
+
+/* Parameter Type Constants */
+#define SIP_PARAM_TYPE_NONE 0x0
+#define SIP_PARAM_TYPE_VALUE_INPUT 0x1
+#define SIP_PARAM_TYPE_VALUE_OUTPUT 0x2
+#define SIP_PARAM_TYPE_VALUE_INOUT 0x3
+#define SIP_PARAM_TYPE_MEMREF_INPUT 0x5
+#define SIP_PARAM_TYPE_MEMREF_OUTPUT 0x6
+#define SIP_PARAM_TYPE_MEMREF_INOUT 0x7
+
+#define SIP_PARAM_TYPE_MASK 0xF
+
+/*
+ * The macro SIP_PARAM_TYPES can be used to construct a value that you can
+ * compare against an incoming paramTypes to check the type of all the
+ * parameters in one comparison.
+ */
+#define SIP_PARAM_TYPES(t0, t1, t2, t3) \
+ ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12))
+
+/*
+ * The macro SIP_PARAM_TYPE_GET can be used to extract the type of a given
+ * parameter from paramTypes if you need more fine-grained type checking.
+ */
+#define SIP_PARAM_TYPE_GET(t, i) ((((uint32_t)(t)) >> ((i) * 4)) & 0xF)
+
+/*
+ * The macro SIP_PARAM_TYPE_SET can be used to load the type of a given
+ * parameter from paramTypes without specifying all types (SIP_PARAM_TYPES)
+ */
+#define SIP_PARAM_TYPE_SET(t, i) (((uint32_t)(t) & 0xF) << ((i) * 4))
+
+#define SIP_SVC_RNG_PARAMS (SIP_PARAM_TYPE_VALUE_INPUT, \
+ SIP_PARAM_TYPE_MEMREF_OUTPUT, \
+ SIP_PARAM_TYPE_NONE, \
+ SIP_PARAM_TYPE_NONE)
+
+/* Layerscape SiP Calls error code */
+enum {
+ LS_SIP_SUCCESS = 0,
+ LS_SIP_INVALID_PARAM = -1,
+ LS_SIP_NOT_SUPPORTED = -2,
+};
+
+#endif /* SIPSVC_H */
diff --git a/plat/nxp/common/sip_svc/sip_svc.c b/plat/nxp/common/sip_svc/sip_svc.c
new file mode 100644
index 0000000..1c8668e
--- /dev/null
+++ b/plat/nxp/common/sip_svc/sip_svc.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <caam.h>
+#include <common/runtime_svc.h>
+#include <dcfg.h>
+#include <lib/mmio.h>
+#include <tools_share/uuid.h>
+
+#include <plat_common.h>
+#include <sipsvc.h>
+
+/* Layerscape SiP Service UUID */
+DEFINE_SVC_UUID2(nxp_sip_svc_uid,
+ 0x871de4ef, 0xedfc, 0x4209, 0xa4, 0x23,
+ 0x8d, 0x23, 0x75, 0x9d, 0x3b, 0x9f);
+
+#pragma weak nxp_plat_sip_handler
+static uintptr_t nxp_plat_sip_handler(unsigned int smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
+
+uint64_t el2_2_aarch32(u_register_t smc_id, u_register_t start_addr,
+ u_register_t parm1, u_register_t parm2);
+
+uint64_t prefetch_disable(u_register_t smc_id, u_register_t mask);
+uint64_t bl31_get_porsr1(void);
+
+static void clean_top_32b_of_param(uint32_t smc_fid,
+ u_register_t *px1,
+ u_register_t *px2,
+ u_register_t *px3,
+ u_register_t *px4)
+{
+ /* if parameters from SMC32. Clean top 32 bits */
+ if (GET_SMC_CC(smc_fid) == SMC_32) {
+ *px1 = *px1 & SMC32_PARAM_MASK;
+ *px2 = *px2 & SMC32_PARAM_MASK;
+ *px3 = *px3 & SMC32_PARAM_MASK;
+ *px4 = *px4 & SMC32_PARAM_MASK;
+ }
+}
+
+/* This function handles Layerscape defined SiP Calls */
+static uintptr_t nxp_sip_handler(unsigned int smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t ns;
+ uint64_t ret;
+ dram_regions_info_t *info_dram_regions;
+
+ /* if parameter is sent from SMC32. Clean top 32 bits */
+ clean_top_32b_of_param(smc_fid, &x1, &x2, &x3, &x4);
+
+ /* Determine which security state this SMC originated from */
+ ns = is_caller_non_secure(flags);
+ if (ns == 0) {
+ /* SiP SMC service secure world's call */
+ ;
+ } else {
+ /* SiP SMC service normal world's call */
+ ;
+ }
+
+ switch (smc_fid & SMC_FUNC_MASK) {
+ case SIP_SVC_RNG:
+ if (is_sec_enabled() == false) {
+ NOTICE("SEC is disabled.\n");
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ /* Return zero on failure */
+ ret = get_random((int)x1);
+ if (ret != 0) {
+ SMC_RET2(handle, SMC_OK, ret);
+ } else {
+ SMC_RET1(handle, SMC_UNK);
+ }
+ /* break is not required as SMC_RETx return */
+ case SIP_SVC_HUK:
+ if (is_sec_enabled() == false) {
+ NOTICE("SEC is disabled.\n");
+ SMC_RET1(handle, SMC_UNK);
+ }
+ ret = get_hw_unq_key_blob_hw((uint8_t *) x1, (uint32_t) x2);
+
+ if (ret == SMC_OK) {
+ SMC_RET1(handle, SMC_OK);
+ } else {
+ SMC_RET1(handle, SMC_UNK);
+ }
+ /* break is not required as SMC_RETx return */
+ case SIP_SVC_MEM_BANK:
+ VERBOSE("Handling SMC SIP_SVC_MEM_BANK.\n");
+ info_dram_regions = get_dram_regions_info();
+
+ if (x1 == -1) {
+ SMC_RET2(handle, SMC_OK,
+ info_dram_regions->total_dram_size);
+ } else if (x1 >= info_dram_regions->num_dram_regions) {
+ SMC_RET1(handle, SMC_UNK);
+ } else {
+ SMC_RET3(handle, SMC_OK,
+ info_dram_regions->region[x1].addr,
+ info_dram_regions->region[x1].size);
+ }
+ /* break is not required as SMC_RETx return */
+ case SIP_SVC_PREFETCH_DIS:
+ VERBOSE("In SIP_SVC_PREFETCH_DIS call\n");
+ ret = prefetch_disable(smc_fid, x1);
+ if (ret == SMC_OK) {
+ SMC_RET1(handle, SMC_OK);
+ } else {
+ SMC_RET1(handle, SMC_UNK);
+ }
+ /* break is not required as SMC_RETx return */
+ case SIP_SVC_2_AARCH32:
+ ret = el2_2_aarch32(smc_fid, x1, x2, x3);
+
+ /* In success case, control should not reach here. */
+ NOTICE("SMC: SIP_SVC_2_AARCH32 Failed.\n");
+ SMC_RET1(handle, SMC_UNK);
+ /* break is not required as SMC_RETx return */
+ case SIP_SVC_PORSR1:
+ ret = bl31_get_porsr1();
+ SMC_RET2(handle, SMC_OK, ret);
+ /* break is not required as SMC_RETx return */
+ default:
+ return nxp_plat_sip_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ }
+}
+
+/* This function is responsible for handling all SiP calls */
+static uintptr_t sip_smc_handler(unsigned int smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ switch (smc_fid & SMC_FUNC_MASK) {
+ case SIP_SVC_CALL_COUNT:
+ /* Return the number of Layerscape SiP Service Calls. */
+ SMC_RET1(handle, LS_COMMON_SIP_NUM_CALLS);
+ break;
+ case SIP_SVC_UID:
+ /* Return UID to the caller */
+ SMC_UUID_RET(handle, nxp_sip_svc_uid);
+ break;
+ case SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ SMC_RET2(handle, LS_SIP_SVC_VERSION_MAJOR,
+ LS_SIP_SVC_VERSION_MINOR);
+ break;
+ default:
+ return nxp_sip_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ }
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ nxp_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ sip_smc_handler
+);
diff --git a/plat/nxp/common/sip_svc/sipsvc.mk b/plat/nxp/common/sip_svc/sipsvc.mk
new file mode 100644
index 0000000..c3a57de
--- /dev/null
+++ b/plat/nxp/common/sip_svc/sipsvc.mk
@@ -0,0 +1,35 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# Select the SIP SVC files
+#
+# -----------------------------------------------------------------------------
+
+ifeq (${ADD_SIPSVC},)
+
+ADD_SIPSVC := 1
+
+PLAT_SIPSVC_PATH := $(PLAT_COMMON_PATH)/sip_svc
+
+SIPSVC_SOURCES := ${PLAT_SIPSVC_PATH}/sip_svc.c \
+ ${PLAT_SIPSVC_PATH}/$(ARCH)/sipsvc.S
+
+PLAT_INCLUDES += -I${PLAT_SIPSVC_PATH}/include
+
+ifeq (${BL_COMM_SIPSVC_NEEDED},yes)
+BL_COMMON_SOURCES += ${SIPSVC_SOURCES}
+else
+ifeq (${BL2_SIPSVC_NEEDED},yes)
+BL2_SOURCES += ${SIPSVC_SOURCES}
+endif
+ifeq (${BL31_SIPSVC_NEEDED},yes)
+BL31_SOURCES += ${SIPSVC_SOURCES}
+endif
+endif
+endif
+# -----------------------------------------------------------------------------
diff --git a/plat/nxp/common/soc_errata/errata.c b/plat/nxp/common/soc_errata/errata.c
new file mode 100644
index 0000000..55ef604
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/debug.h>
+
+#include "errata_list.h"
+
+void soc_errata(void)
+{
+#ifdef ERRATA_SOC_A050426
+ INFO("SoC workaround for Errata A050426 was applied\n");
+ erratum_a050426();
+#endif
+#ifdef ERRATA_SOC_A008850
+ INFO("SoC workaround for Errata A008850 Early-Phase was applied\n");
+ erratum_a008850_early();
+#endif
+#if ERRATA_SOC_A009660
+ INFO("SoC workaround for Errata A009660 was applied\n");
+ erratum_a009660();
+#endif
+#if ERRATA_SOC_A010539
+ INFO("SoC workaround for Errata A010539 was applied\n");
+ erratum_a010539();
+#endif
+
+ /*
+ * The following DDR Erratas workaround are implemented in DDR driver,
+ * but print information here.
+ */
+#if ERRATA_DDR_A011396
+ INFO("SoC workaround for DDR Errata A011396 was applied\n");
+#endif
+#if ERRATA_DDR_A050450
+ INFO("SoC workaround for DDR Errata A050450 was applied\n");
+#endif
+#if ERRATA_DDR_A050958
+ INFO("SoC workaround for DDR Errata A050958 was applied\n");
+#endif
+#if ERRATA_DDR_A008511
+ INFO("SoC workaround for DDR Errata A008511 was applied\n");
+#endif
+#if ERRATA_DDR_A009803
+ INFO("SoC workaround for DDR Errata A009803 was applied\n");
+#endif
+#if ERRATA_DDR_A009942
+ INFO("SoC workaround for DDR Errata A009942 was applied\n");
+#endif
+#if ERRATA_DDR_A010165
+ INFO("SoC workaround for DDR Errata A010165 was applied\n");
+#endif
+#if ERRATA_DDR_A009663
+ INFO("SoC workaround for DDR Errata A009663 was applied\n");
+#endif
+}
diff --git a/plat/nxp/common/soc_errata/errata.h b/plat/nxp/common/soc_errata/errata.h
new file mode 100644
index 0000000..ab67995
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef ERRATA_H
+#define ERRATA_H
+
+#include "errata_list.h"
+
+void soc_errata(void);
+
+#endif /* ERRATA_H */
diff --git a/plat/nxp/common/soc_errata/errata.mk b/plat/nxp/common/soc_errata/errata.mk
new file mode 100644
index 0000000..3deef3d
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2021-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform Errata Build flags.
+# These should be enabled by the platform if the erratum workaround needs to be
+# applied.
+
+ERRATA := \
+ ERRATA_SOC_A050426 \
+ ERRATA_SOC_A008850 \
+ ERRATA_SOC_A009660 \
+ ERRATA_SOC_A010539
+
+define enable_errata
+ $(1) ?= 0
+ ifeq ($$($(1)),1)
+ $$(eval $$(call add_define,$(1)))
+ BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata_a$(shell echo $(1)|awk -F '_A' '{print $$NF}').c
+ endif
+endef
+
+$(foreach e,$(ERRATA),$(eval $(call enable_errata,$(strip $(e)))))
+
+BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata.c
diff --git a/plat/nxp/common/soc_errata/errata_a008850.c b/plat/nxp/common/soc_errata/errata_a008850.c
new file mode 100644
index 0000000..e8c0f64
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata_a008850.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <cci.h>
+#include <common/debug.h>
+#include <ls_interconnect.h>
+#include <mmio.h>
+
+#include <platform_def.h>
+
+void erratum_a008850_early(void)
+{
+ /* part 1 of 2 */
+ uintptr_t cci_base = NXP_CCI_ADDR;
+ uint32_t val = mmio_read_32(cci_base + CTRL_OVERRIDE_REG);
+
+ /* enabling forced barrier termination on CCI400 */
+ mmio_write_32(cci_base + CTRL_OVERRIDE_REG,
+ (val | CCI_TERMINATE_BARRIER_TX));
+
+}
+
+void erratum_a008850_post(void)
+{
+ /* part 2 of 2 */
+ uintptr_t cci_base = NXP_CCI_ADDR;
+ uint32_t val = mmio_read_32(cci_base + CTRL_OVERRIDE_REG);
+
+ /* Clear the BARRIER_TX bit */
+ val = val & ~(CCI_TERMINATE_BARRIER_TX);
+
+ /*
+ * Disable barrier termination on CCI400, allowing
+ * barriers to propagate across CCI
+ */
+ mmio_write_32(cci_base + CTRL_OVERRIDE_REG, val);
+
+ INFO("SoC workaround for Errata A008850 Post-Phase was applied\n");
+}
diff --git a/plat/nxp/common/soc_errata/errata_a009660.c b/plat/nxp/common/soc_errata/errata_a009660.c
new file mode 100644
index 0000000..d31a4d7
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata_a009660.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <mmio.h>
+#include <soc_default_base_addr.h>
+
+void erratum_a009660(void)
+{
+ mmio_write_32(NXP_SCFG_ADDR + 0x20c, 0x63b20042);
+}
diff --git a/plat/nxp/common/soc_errata/errata_a010539.c b/plat/nxp/common/soc_errata/errata_a010539.c
new file mode 100644
index 0000000..3dcbdc8
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata_a010539.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <mmio.h>
+
+#include <plat_common.h>
+
+void erratum_a010539(void)
+{
+ if (get_boot_dev() == BOOT_DEVICE_QSPI) {
+ unsigned int *porsr1 = (void *)(NXP_DCFG_ADDR +
+ DCFG_PORSR1_OFFSET);
+ uint32_t val;
+
+ val = (gur_in32(porsr1) & ~PORSR1_RCW_MASK);
+ mmio_write_32((uint32_t)(NXP_DCSR_DCFG_ADDR +
+ DCFG_DCSR_PORCR1_OFFSET), htobe32(val));
+ /* Erratum need to set '1' to all bits for reserved SCFG register 0x1a8 */
+ mmio_write_32((uint32_t)(NXP_SCFG_ADDR + 0x1a8),
+ htobe32(0xffffffff));
+ }
+}
diff --git a/plat/nxp/common/soc_errata/errata_a050426.c b/plat/nxp/common/soc_errata/errata_a050426.c
new file mode 100644
index 0000000..ba4f71f
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata_a050426.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2021-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/debug.h>
+#include <mmio.h>
+
+void erratum_a050426(void)
+{
+ uint32_t i, val3, val4;
+
+ /*
+ * Part of this Errata is implemented in RCW and SCRATCHRW5
+ * register is updated to hold Errata number.
+ * Validate whether RCW has already included required changes
+ */
+ if (mmio_read_32(0x01e00210) != 0x00050426) {
+ ERROR("%s: Invalid RCW : ERR050426 not implemented\n", __func__);
+ }
+
+ /* Enable BIST to access Internal memory locations */
+ val3 = mmio_read_32(0x700117E60);
+ mmio_write_32(0x700117E60, (val3 | 0x80000001));
+ val4 = mmio_read_32(0x700117E90);
+ mmio_write_32(0x700117E90, (val4 & 0xFFDFFFFF));
+
+ /* wriop Internal Memory.*/
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x706312000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706312400 + (i * 4), 0x55555555);
+ mmio_write_32(0x706312800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706314000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706314400 + (i * 4), 0x55555555);
+ mmio_write_32(0x706314800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706314c00 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 3U; i++) {
+ mmio_write_32(0x706316000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706320000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706320400 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 2U; i++) {
+ mmio_write_32(0x70640a000 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 3U; i++) {
+ mmio_write_32(0x706518000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706519000 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x706522000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706522800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706523000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706523800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706524000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706524800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706608000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706608800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706609000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706609800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70660a000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70660a800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70660b000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70660b800 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 3U; i++) {
+ mmio_write_32(0x70660c000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70660c800 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 2U; i++) {
+ mmio_write_32(0x706718000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706718800 + (i * 4), 0x55555555);
+ }
+ mmio_write_32(0x706b0a000, 0x55555555);
+
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x706b0e000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706b0e800 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 2U; i++) {
+ mmio_write_32(0x706b10000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706b10400 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x706b14000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706b14800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706b15000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706b15800 + (i * 4), 0x55555555);
+ }
+ mmio_write_32(0x706e12000, 0x55555555);
+
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x706e14000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e14800 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 2U; i++) {
+ mmio_write_32(0x706e16000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e16400 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 3U; i++) {
+ mmio_write_32(0x706e1a000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1a800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1b000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1b800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1c000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1c800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1e000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1e800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1f000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e1f800 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e20000 + (i * 4), 0x55555555);
+ mmio_write_32(0x706e20800 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x707108000 + (i * 4), 0x55555555);
+ mmio_write_32(0x707109000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70710a000 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 2U; i++) {
+ mmio_write_32(0x70711c000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70711c800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70711d000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70711d800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70711e000 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x707120000 + (i * 4), 0x55555555);
+ mmio_write_32(0x707121000 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 3U; i++) {
+ mmio_write_32(0x707122000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725a000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725b000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725c000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725e000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725e400 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725e800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725ec00 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725f000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70725f400 + (i * 4), 0x55555555);
+ mmio_write_32(0x707340000 + (i * 4), 0x55555555);
+ mmio_write_32(0x707346000 + (i * 4), 0x55555555);
+ mmio_write_32(0x707484000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70748a000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70748b000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70748c000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70748d000 + (i * 4), 0x55555555);
+ }
+
+ /* EDMA Internal Memory.*/
+ for (i = 0U; i < 5U; i++) {
+ mmio_write_32(0x70a208000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70a208800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70a209000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70a209800 + (i * 4), 0x55555555);
+ }
+
+ /* QDMA Internal Memory.*/
+ for (i = 0U; i < 5U; i++) {
+ mmio_write_32(0x70b008000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b00c000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b010000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b014000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b018000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b018400 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01a000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01a400 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01c000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01d000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01e000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01e800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01f000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b01f800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b020000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b020400 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b020800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b020c00 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b022000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b022400 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b024000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b024800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b025000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b025800 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 4U; i++) {
+ mmio_write_32(0x70b026000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b026200 + (i * 4), 0x55555555);
+ }
+ for (i = 0U; i < 5U; i++) {
+ mmio_write_32(0x70b028000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b028800 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b029000 + (i * 4), 0x55555555);
+ mmio_write_32(0x70b029800 + (i * 4), 0x55555555);
+ }
+
+ /* Disable BIST */
+ mmio_write_32(0x700117E60, val3);
+ mmio_write_32(0x700117E90, val4);
+}
diff --git a/plat/nxp/common/soc_errata/errata_list.h b/plat/nxp/common/soc_errata/errata_list.h
new file mode 100644
index 0000000..f6741e2
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata_list.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef ERRATA_LIST_H
+#define ERRATA_LIST_H
+
+#ifdef ERRATA_SOC_A050426
+void erratum_a050426(void);
+#endif
+
+#ifdef ERRATA_SOC_A008850
+void erratum_a008850_early(void);
+void erratum_a008850_post(void);
+#endif
+
+#ifdef ERRATA_SOC_A009660
+void erratum_a009660(void);
+#endif
+
+#ifdef ERRATA_SOC_A010539
+void erratum_a010539(void);
+#endif
+
+#endif /* ERRATA_LIST_H */
diff --git a/plat/nxp/common/tbbr/csf_tbbr.c b/plat/nxp/common/tbbr/csf_tbbr.c
new file mode 100644
index 0000000..8f38f3e
--- /dev/null
+++ b/plat/nxp/common/tbbr/csf_tbbr.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ *
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <csf_hdr.h>
+#include <dcfg.h>
+#include <drivers/auth/crypto_mod.h>
+#include <snvs.h>
+
+#include <plat/common/platform.h>
+#include "plat_common.h"
+
+extern bool rotpk_not_dpld;
+extern uint8_t rotpk_hash_table[MAX_KEY_ENTRIES][SHA256_BYTES];
+extern uint32_t num_rotpk_hash_entries;
+
+/*
+ * In case of secure boot, return ptr of rotpk_hash table in key_ptr and
+ * number of hashes in key_len
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ uint32_t mode = 0U;
+ *flags = ROTPK_NOT_DEPLOYED;
+
+ /* ROTPK hash table must be available for secure boot */
+ if (rotpk_not_dpld == true) {
+ if (check_boot_mode_secure(&mode) == true) {
+ /* Production mode, don;t continue further */
+ if (mode == 1U) {
+ return -EAUTH;
+ }
+
+ /* For development mode, rotpk flag false
+ * indicates that SRK hash comparison might
+ * have failed. This is not fatal error.
+ * Continue in this case but transition SNVS
+ * to non-secure state
+ */
+ transition_snvs_non_secure();
+ return 0;
+ } else {
+ return 0;
+ }
+ }
+
+ /*
+ * We return the complete hash table and number of entries in
+ * table for NXP platform specific implementation.
+ * Here hash is always assume as SHA-256
+ */
+ *key_ptr = rotpk_hash_table;
+ *key_len = num_rotpk_hash_entries;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ /*
+ * No support for non-volatile counter. Update the ROT key to protect
+ * the system against rollback.
+ */
+ *nv_ctr = 0U;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 0;
+}
diff --git a/plat/nxp/common/tbbr/nxp_rotpk.S b/plat/nxp/common/tbbr/nxp_rotpk.S
new file mode 100644
index 0000000..8e084d1
--- /dev/null
+++ b/plat/nxp/common/tbbr/nxp_rotpk.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ *
+ */
+
+#ifndef _CSF_HDR_H_
+
+ .global nxp_rotpk_hash
+ .global nxp_rotpk_hash_end
+ .section .rodata.nxp_rotpk_hash, "a"
+nxp_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+nxp_rotpk_hash_end:
+#endif
diff --git a/plat/nxp/common/tbbr/tbbr.mk b/plat/nxp/common/tbbr/tbbr.mk
new file mode 100644
index 0000000..4aac9d6
--- /dev/null
+++ b/plat/nxp/common/tbbr/tbbr.mk
@@ -0,0 +1,162 @@
+#
+# Copyright 2020-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# For TRUSTED_BOARD_BOOT platforms need to include this makefile
+# Following definations are to be provided by platform.mk file or
+# by user - BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE
+
+ifeq ($(CHASSIS), 2)
+include $(PLAT_DRIVERS_PATH)/csu/csu.mk
+CSF_FILE := input_blx_ch${CHASSIS}
+BL2_CSF_FILE := input_bl2_ch${CHASSIS}
+else
+ifeq ($(CHASSIS), 3)
+CSF_FILE := input_blx_ch${CHASSIS}
+BL2_CSF_FILE := input_bl2_ch${CHASSIS}
+PBI_CSF_FILE := input_pbi_ch${CHASSIS}
+$(eval $(call add_define, CSF_HDR_CH3))
+else
+ifeq ($(CHASSIS), 3_2)
+CSF_FILE := input_blx_ch3
+BL2_CSF_FILE := input_bl2_ch${CHASSIS}
+PBI_CSF_FILE := input_pbi_ch${CHASSIS}
+$(eval $(call add_define, CSF_HDR_CH3))
+else
+ $(error -> CHASSIS not set!)
+endif
+endif
+endif
+
+PLAT_AUTH_PATH := $(PLAT_DRIVERS_PATH)/auth
+
+
+ifeq (${BL2_INPUT_FILE},)
+ BL2_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${BL2_CSF_FILE}
+endif
+
+ifeq (${PBI_INPUT_FILE},)
+ PBI_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${PBI_CSF_FILE}
+endif
+
+# If MBEDTLS_DIR is not specified, use CSF Header option
+ifeq (${MBEDTLS_DIR},)
+ # Generic image processing filters to prepend CSF header
+ ifeq (${BL33_INPUT_FILE},)
+ BL33_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE}
+ endif
+
+ ifeq (${BL31_INPUT_FILE},)
+ BL31_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE}
+ endif
+
+ ifeq (${BL32_INPUT_FILE},)
+ BL32_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE}
+ endif
+
+ ifeq (${FUSE_INPUT_FILE},)
+ FUSE_INPUT_FILE := $(PLAT_AUTH_PATH)/csf_hdr_parser/${CSF_FILE}
+ endif
+
+ PLAT_INCLUDES += -I$(PLAT_DRIVERS_PATH)/sfp
+ PLAT_TBBR_SOURCES += $(PLAT_AUTH_PATH)/csf_hdr_parser/cot.c \
+ $(PLAT_COMMON_PATH)/tbbr/csf_tbbr.c
+ # IMG PARSER here is CSF header parser
+ include $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/csf_hdr.mk
+ PLAT_TBBR_SOURCES += $(CSF_HDR_SOURCES)
+
+ SCP_BL2_PRE_TOOL_FILTER := CST_SCP_BL2
+ BL31_PRE_TOOL_FILTER := CST_BL31
+ BL32_PRE_TOOL_FILTER := CST_BL32
+ BL33_PRE_TOOL_FILTER := CST_BL33
+else
+
+ ifeq (${DISABLE_FUSE_WRITE}, 1)
+ $(eval $(call add_define,DISABLE_FUSE_WRITE))
+ endif
+
+ # For Mbedtls currently crypto is not supported via CAAM
+ # enable it when that support is there
+ CAAM_INTEG := 0
+ KEY_ALG := rsa
+ KEY_SIZE := 2048
+
+ $(eval $(call add_define,MBEDTLS_X509))
+ ifeq (${PLAT_DDR_PHY},PHY_GEN2)
+ $(eval $(call add_define,PLAT_DEF_OID))
+ endif
+ include drivers/auth/mbedtls/mbedtls_x509.mk
+
+
+ PLAT_TBBR_SOURCES += $(PLAT_AUTH_PATH)/tbbr/tbbr_cot.c \
+ $(PLAT_COMMON_PATH)/tbbr/nxp_rotpk.S \
+ $(PLAT_COMMON_PATH)/tbbr/x509_tbbr.c
+
+ #ROTPK key is embedded in BL2 image
+ ifeq (${ROT_KEY},)
+ ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ endif
+
+ ifeq (${SAVE_KEYS},1)
+
+ ifeq (${TRUSTED_WORLD_KEY},)
+ TRUSTED_WORLD_KEY = ${BUILD_PLAT}/trusted.pem
+ endif
+
+ ifeq (${NON_TRUSTED_WORLD_KEY},)
+ NON_TRUSTED_WORLD_KEY = ${BUILD_PLAT}/non-trusted.pem
+ endif
+
+ ifeq (${BL31_KEY},)
+ BL31_KEY = ${BUILD_PLAT}/soc.pem
+ endif
+
+ ifeq (${BL32_KEY},)
+ BL32_KEY = ${BUILD_PLAT}/trusted_os.pem
+ endif
+
+ ifeq (${BL33_KEY},)
+ BL33_KEY = ${BUILD_PLAT}/non-trusted_os.pem
+ endif
+
+ endif
+
+ ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+ $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+
+ $(BUILD_PLAT)/bl2/nxp_rotpk.o: $(ROTPK_HASH)
+
+ certificates: $(ROT_KEY)
+ $(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ @if [ ! -f $(ROT_KEY) ]; then \
+ ${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null; \
+ fi
+
+ $(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+
+endif #MBEDTLS_DIR
+
+PLAT_INCLUDES += -Iinclude/common/tbbr
+
+# Generic files for authentication framework
+TBBR_SOURCES += drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ plat/common/tbbr/plat_tbbr.c \
+ ${PLAT_TBBR_SOURCES}
+
+# If CAAM_INTEG is not defined (would be scenario with MBED TLS)
+# include mbedtls_crypto
+ifeq (${CAAM_INTEG},0)
+ include drivers/auth/mbedtls/mbedtls_crypto.mk
+else
+ include $(PLAT_DRIVERS_PATH)/crypto/caam/src/auth/auth.mk
+ TBBR_SOURCES += ${AUTH_SOURCES}
+endif
diff --git a/plat/nxp/common/tbbr/x509_tbbr.c b/plat/nxp/common/tbbr/x509_tbbr.c
new file mode 100644
index 0000000..ec87674
--- /dev/null
+++ b/plat/nxp/common/tbbr/x509_tbbr.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/cassert.h>
+#include <sfp.h>
+#include <tools_share/tbbr_oid.h>
+
+#include <plat/common/platform.h>
+#include "plat_common.h"
+
+extern char nxp_rotpk_hash[], nxp_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = nxp_rotpk_hash;
+ *key_len = nxp_rotpk_hash_end - nxp_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ const char *oid;
+ uint32_t uid_num;
+ uint32_t val = 0U;
+
+ assert(cookie != NULL);
+ assert(nv_ctr != NULL);
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ uid_num = 3U;
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ uid_num = 4U;
+ } else {
+ return 1;
+ }
+
+ val = sfp_read_oem_uid(uid_num);
+
+ INFO("SFP Value read is %x from UID %d\n", val, uid_num);
+ if (val == 0U) {
+ *nv_ctr = 0U;
+ } else {
+ *nv_ctr = (32U - __builtin_clz(val));
+ }
+
+ INFO("NV Counter value for UID %d is %d\n", uid_num, *nv_ctr);
+ return 0;
+
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ const char *oid;
+ uint32_t uid_num, sfp_val;
+
+ assert(cookie != NULL);
+
+ /* Counter values upto 32 are supported */
+ if (nv_ctr > 32U) {
+ return 1;
+ }
+
+ oid = (const char *)cookie;
+ if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ uid_num = 3U;
+ } else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+ uid_num = 4U;
+ } else {
+ return 1;
+ }
+ sfp_val = (1U << (nv_ctr - 1));
+
+ if (sfp_write_oem_uid(uid_num, sfp_val) == 1) {
+ /* Enable POVDD on board */
+ if (board_enable_povdd()) {
+ sfp_program_fuses();
+ }
+
+ /* Disable POVDD on board */
+ board_disable_povdd();
+ } else {
+ ERROR("Invalid OEM UID sent.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/nxp/common/warm_reset/plat_warm_reset.c b/plat/nxp/common/warm_reset/plat_warm_reset.c
new file mode 100644
index 0000000..966a73c
--- /dev/null
+++ b/plat/nxp/common/warm_reset/plat_warm_reset.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#ifndef NXP_COINED_BB
+#include <flash_info.h>
+#include <fspi.h>
+#include <fspi_api.h>
+#endif
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#ifdef NXP_COINED_BB
+#include <snvs.h>
+#endif
+
+#include <plat_nv_storage.h>
+#include "plat_warm_rst.h"
+#include "platform_def.h"
+
+#if defined(IMAGE_BL2)
+
+uint32_t is_warm_boot(void)
+{
+ uint32_t ret = mmio_read_32(NXP_RESET_ADDR + RST_RSTRQSR1_OFFSET)
+ & ~(RSTRQSR1_SWRR);
+
+ const nv_app_data_t *nv_app_data = get_nv_data();
+
+ if (ret == 0U) {
+ INFO("Not a SW(Warm) triggered reset.\n");
+ return 0U;
+ }
+
+ ret = (nv_app_data->warm_rst_flag == WARM_BOOT_SUCCESS) ? 1 : 0;
+
+ if (ret != 0U) {
+ INFO("Warm Reset was triggered..\n");
+ } else {
+ INFO("Warm Reset was not triggered..\n");
+ }
+
+ return ret;
+}
+
+#endif
+
+#if defined(IMAGE_BL31)
+int prep_n_execute_warm_reset(void)
+{
+#ifdef NXP_COINED_BB
+#if !TRUSTED_BOARD_BOOT
+ snvs_disable_zeroize_lp_gpr();
+#endif
+#else
+ int ret;
+ uint8_t warm_reset = WARM_BOOT_SUCCESS;
+
+ ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR);
+
+ if (ret != 0) {
+ ERROR("Failed to initialized driver flexspi-nor.\n");
+ ERROR("exiting warm-reset request.\n");
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ /* Sector starting from NV_STORAGE_BASE_ADDR is already
+ * erased for writing.
+ */
+
+#if (ERLY_WRM_RST_FLG_FLSH_UPDT)
+ ret = xspi_write((uint32_t)NV_STORAGE_BASE_ADDR,
+ &warm_reset,
+ sizeof(warm_reset));
+#else
+ /* Preparation for writing the Warm reset flag. */
+ ret = xspi_wren((uint32_t)NV_STORAGE_BASE_ADDR);
+
+ /* IP Control Register0 - SF Address to be read */
+ fspi_out32((NXP_FLEXSPI_ADDR + FSPI_IPCR0),
+ (uint32_t) NV_STORAGE_BASE_ADDR);
+
+ while ((fspi_in32(NXP_FLEXSPI_ADDR + FSPI_INTR) &
+ FSPI_INTR_IPTXWE_MASK) == 0) {
+ ;
+ }
+ /* Write TX FIFO Data Register */
+ fspi_out32(NXP_FLEXSPI_ADDR + FSPI_TFDR, (uint32_t) warm_reset);
+
+ fspi_out32(NXP_FLEXSPI_ADDR + FSPI_INTR, FSPI_INTR_IPTXWE);
+
+ /* IP Control Register1 - SEQID_WRITE operation, Size = 1 Byte */
+ fspi_out32(NXP_FLEXSPI_ADDR + FSPI_IPCR1,
+ (uint32_t)(FSPI_WRITE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) |
+ (uint16_t) sizeof(warm_reset));
+
+ /* Trigger XSPI-IP-Write cmd only if:
+ * - Putting DDR in-self refresh mode is successfully.
+ * to complete the writing of the warm-reset flag
+ * to flash.
+ *
+ * This code is as part of assembly.
+ */
+#endif
+#endif
+ INFO("Doing DDR Self refresh.\n");
+ _soc_sys_warm_reset();
+
+ /* Expected behaviour is to do the power cycle */
+ while (1 != 0)
+ ;
+
+ return -1;
+}
+#endif
diff --git a/plat/nxp/common/warm_reset/plat_warm_rst.h b/plat/nxp/common/warm_reset/plat_warm_rst.h
new file mode 100644
index 0000000..e0c39c5
--- /dev/null
+++ b/plat/nxp/common/warm_reset/plat_warm_rst.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_WARM_RST_H
+#define PLAT_WARM_RST_H
+
+#ifndef NXP_COINED_BB
+#define ERLY_WRM_RST_FLG_FLSH_UPDT 0
+#endif
+
+#ifndef __ASSEMBLER__
+
+#if defined(IMAGE_BL2)
+uint32_t is_warm_boot(void);
+#endif
+
+#if defined(IMAGE_BL31)
+int prep_n_execute_warm_reset(void);
+int _soc_sys_warm_reset(void);
+#endif
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* PLAT_WARM_RST_H */
diff --git a/plat/nxp/common/warm_reset/warm_reset.mk b/plat/nxp/common/warm_reset/warm_reset.mk
new file mode 100644
index 0000000..236004f
--- /dev/null
+++ b/plat/nxp/common/warm_reset/warm_reset.mk
@@ -0,0 +1,20 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-----------------------------------------------------------------------------
+ifeq (${WARM_RST_ADDED},)
+
+WARM_RST_ADDED := 1
+NXP_NV_SW_MAINT_LAST_EXEC_DATA := yes
+
+$(eval $(call add_define,NXP_WARM_BOOT))
+
+
+WARM_RST_INCLUDES += -I${PLAT_COMMON_PATH}/warm_reset
+WARM_RST_BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}_warm_rst.S
+
+WARM_RST_BL_COMM_SOURCES += ${PLAT_COMMON_PATH}/warm_reset/plat_warm_reset.c
+
+endif
diff --git a/plat/nxp/soc-ls1028a/aarch64/ls1028a.S b/plat/nxp/soc-ls1028a/aarch64/ls1028a.S
new file mode 100644
index 0000000..404c39e
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/aarch64/ls1028a.S
@@ -0,0 +1,1387 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .section .text, "ax"
+
+#include <asm_macros.S>
+
+#include <lib/psci/psci.h>
+#include <nxp_timer.h>
+#include <plat_gic.h>
+#include <pmu.h>
+
+#include <bl31_data.h>
+#include <plat_psci.h>
+#include <platform_def.h>
+
+ .global soc_init_lowlevel
+ .global soc_init_percpu
+ .global _set_platform_security
+ .global _soc_set_start_addr
+
+ .global _soc_core_release
+ .global _soc_ck_disabled
+ .global _soc_core_restart
+ .global _soc_core_prep_off
+ .global _soc_core_entr_off
+ .global _soc_core_exit_off
+ .global _soc_sys_reset
+ .global _soc_sys_off
+ .global _soc_core_prep_stdby
+ .global _soc_core_entr_stdby
+ .global _soc_core_exit_stdby
+ .global _soc_core_prep_pwrdn
+ .global _soc_core_entr_pwrdn
+ .global _soc_core_exit_pwrdn
+ .global _soc_clstr_prep_stdby
+ .global _soc_clstr_exit_stdby
+ .global _soc_clstr_prep_pwrdn
+ .global _soc_clstr_exit_pwrdn
+ .global _soc_sys_prep_stdby
+ .global _soc_sys_exit_stdby
+ .global _soc_sys_prep_pwrdn
+ .global _soc_sys_pwrdn_wfi
+ .global _soc_sys_exit_pwrdn
+
+ .equ TZPCDECPROT_0_SET_BASE, 0x02200804
+ .equ TZPCDECPROT_1_SET_BASE, 0x02200810
+ .equ TZPCDECPROT_2_SET_BASE, 0x0220081C
+
+ .equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110
+
+/*
+ * This function initialize the soc.
+ * in: void
+ * out: void
+ * uses x0 - x11
+ */
+func soc_init_lowlevel
+ /*
+ * Called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ /*
+ * Make sure the personality has been established by releasing cores
+ * that are marked "to-be-disabled" from reset
+ */
+ bl release_disabled /* 0-8 */
+
+ /* Set SCRATCHRW7 to 0x0 */
+ ldr x0, =DCFG_SCRATCHRW7_OFFSET
+ mov x1, xzr
+ bl _write_reg_dcfg
+
+ /* Restore the aarch32/64 non-volatile registers */
+ ldp x18, x30, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ ret
+endfunc soc_init_lowlevel
+
+/*
+ * void soc_init_percpu(void)
+ *
+ * This function performs any soc-specific initialization that is needed on
+ * a per-core basis
+ * in: none
+ * out: none
+ * uses x0 - x3
+ */
+func soc_init_percpu
+ stp x4, x30, [sp, #-16]!
+
+ bl plat_my_core_mask
+ mov x2, x0
+
+ /* x2 = core mask */
+
+ /* see if this core is marked for prefetch disable */
+ mov x0, #PREFETCH_DIS_OFFSET
+ bl _get_global_data /* 0-1 */
+ tst x0, x2
+ b.eq 1f
+ bl _disable_ldstr_pfetch_A72 /* 0 */
+1:
+ mov x0, #NXP_PMU_ADDR
+ bl enable_timer_base_to_cluster
+
+ ldp x4, x30, [sp], #16
+ ret
+endfunc soc_init_percpu
+
+/*
+ * This function determines if a core is disabled via COREDISABLEDSR
+ * in: w0 = core_mask_lsb
+ * out: w0 = 0, core not disabled
+ * w0 != 0, core disabled
+ * uses x0, x1
+ */
+func _soc_ck_disabled
+ /* get base addr of dcfg block */
+ ldr x1, =NXP_DCFG_ADDR
+
+ /* read COREDISABLEDSR */
+ ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET]
+
+ /* test core bit */
+ and w0, w1, w0
+
+ ret
+endfunc _soc_ck_disabled
+
+/*
+ * This function sets the security mechanisms in the SoC to implement the
+ * Platform Security Policy
+ */
+func _set_platform_security
+ mov x3, x30
+
+#if (!SUPPRESS_TZC)
+ /* initialize the tzpc */
+ bl init_tzpc
+#endif
+
+#if (!SUPPRESS_SEC)
+ /* initialize secmon */
+ bl initSecMon
+#endif
+
+ mov x30, x3
+ ret
+endfunc _set_platform_security
+
+/*
+ * Part of CPU_ON
+ *
+ * This function releases a secondary core from reset
+ * in: x0 = core_mask_lsb
+ * out: none
+ * uses: x0 - x3
+ */
+_soc_core_release:
+ mov x3, x30
+
+ /*
+ * Write to CORE_HOLD to tell the bootrom that we want this core
+ * to run
+ */
+ ldr x1, =NXP_SEC_REGFILE_ADDR
+ str w0, [x1, #CORE_HOLD_OFFSET]
+
+ /* Read-modify-write BRRL to release core */
+ mov x1, #NXP_RESET_ADDR
+ ldr w2, [x1, #BRR_OFFSET]
+ orr w2, w2, w0
+ str w2, [x1, #BRR_OFFSET]
+ dsb sy
+ isb
+
+ /* Send event */
+ sev
+ isb
+
+ mov x30, x3
+ ret
+
+/*
+ * This function writes a 64-bit address to bootlocptrh/l
+ * in: x0, 64-bit address to write to BOOTLOCPTRL/H
+ * uses x0, x1, x2
+ */
+func _soc_set_start_addr
+ /* Get the 64-bit base address of the dcfg block */
+ ldr x2, =NXP_DCFG_ADDR
+
+ /* Write the 32-bit BOOTLOCPTRL register */
+ mov x1, x0
+ str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET]
+
+ /* Write the 32-bit BOOTLOCPTRH register */
+ lsr x1, x0, #32
+ str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET]
+ ret
+endfunc _soc_set_start_addr
+
+/*
+ * Part of CPU_ON
+ *
+ * This function restarts a core shutdown via _soc_core_entr_off
+ * in: x0 = core mask lsb (of the target cpu)
+ * out: x0 == 0, on success
+ * x0 != 0, on failure
+ * uses x0 - x6
+ */
+_soc_core_restart:
+ mov x6, x30
+ mov x4, x0
+
+ /* pgm GICD_CTLR - enable secure grp0 */
+ mov x5, #NXP_GICD_ADDR
+ ldr w2, [x5, #GICD_CTLR_OFFSET]
+ orr w2, w2, #GICD_CTLR_EN_GRP_0
+ str w2, [x5, #GICD_CTLR_OFFSET]
+ dsb sy
+ isb
+
+ /* Poll on RWP til write completes */
+4:
+ ldr w2, [x5, #GICD_CTLR_OFFSET]
+ tst w2, #GICD_CTLR_RWP
+ b.ne 4b
+
+ /*
+ * x4 = core mask lsb
+ * x5 = gicd base addr
+ */
+
+ mov x0, x4
+ bl get_mpidr_value
+
+ /* Generate target list bit */
+ and x1, x0, #MPIDR_AFFINITY0_MASK
+ mov x2, #1
+ lsl x2, x2, x1
+
+ /* Get the affinity1 field */
+ and x1, x0, #MPIDR_AFFINITY1_MASK
+ lsl x1, x1, #8
+ orr x2, x2, x1
+
+ /* Insert the INTID for SGI15 */
+ orr x2, x2, #ICC_SGI0R_EL1_INTID
+
+ /* Fire the SGI */
+ msr ICC_SGI0R_EL1, x2
+ dsb sy
+ isb
+
+ /* Load '0' on success */
+ mov x0, xzr
+
+ mov x30, x6
+ ret
+
+/*
+ * Part of CPU_OFF
+ *
+ * This function programs SoC & GIC registers in preparation for shutting down
+ * the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0 - x7
+ */
+_soc_core_prep_off:
+ mov x8, x30
+ mov x7, x0
+
+ /* x7 = core mask lsb */
+
+ mrs x1, CPUECTLR_EL1
+
+ /* Set smp and disable L2 snoops in cpuectlr */
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
+ bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK
+ bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK
+
+ /* Set retention control in cpuectlr */
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ orr x1, x1, #CPUECTLR_TIMER_2TICKS
+ msr CPUECTLR_EL1, x1
+
+ /* Get redistributor rd base addr for this core */
+ mov x0, x7
+ bl get_gic_rd_base
+ mov x6, x0
+
+ /* Get redistributor sgi base addr for this core */
+ mov x0, x7
+ bl get_gic_sgi_base
+ mov x5, x0
+
+ /*
+ * x5 = gicr sgi base addr
+ * x6 = gicr rd base addr
+ * x7 = core mask lsb
+ */
+
+ /* Disable SGI 15 at redistributor - GICR_ICENABLER0 */
+ mov w3, #GICR_ICENABLER0_SGI15
+ str w3, [x5, #GICR_ICENABLER0_OFFSET]
+2:
+ /* Poll on rwp bit in GICR_CTLR */
+ ldr w4, [x6, #GICR_CTLR_OFFSET]
+ tst w4, #GICR_CTLR_RWP
+ b.ne 2b
+
+ /* Disable GRP1 interrupts at cpu interface */
+ msr ICC_IGRPEN1_EL3, xzr
+
+ /* Disable GRP0 ints at cpu interface */
+ msr ICC_IGRPEN0_EL1, xzr
+
+ /* Program the redistributor - poll on GICR_CTLR.RWP as needed */
+
+ /* Define SGI 15 as Grp0 - GICR_IGROUPR0 */
+ ldr w4, [x5, #GICR_IGROUPR0_OFFSET]
+ bic w4, w4, #GICR_IGROUPR0_SGI15
+ str w4, [x5, #GICR_IGROUPR0_OFFSET]
+
+ /* Define SGI 15 as Grp0 - GICR_IGRPMODR0 */
+ ldr w3, [x5, #GICR_IGRPMODR0_OFFSET]
+ bic w3, w3, #GICR_IGRPMODR0_SGI15
+ str w3, [x5, #GICR_IGRPMODR0_OFFSET]
+
+ /* Set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */
+ ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+ bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK
+ str w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+
+ /* Enable SGI 15 at redistributor - GICR_ISENABLER0 */
+ mov w3, #GICR_ISENABLER0_SGI15
+ str w3, [x5, #GICR_ISENABLER0_OFFSET]
+ dsb sy
+ isb
+3:
+ /* Poll on rwp bit in GICR_CTLR */
+ ldr w4, [x6, #GICR_CTLR_OFFSET]
+ tst w4, #GICR_CTLR_RWP
+ b.ne 3b
+
+ /* Quiesce the debug interfaces */
+ mrs x3, osdlr_el1
+ orr x3, x3, #OSDLR_EL1_DLK_LOCK
+ msr osdlr_el1, x3
+ isb
+
+ /* Enable grp0 ints */
+ mov x3, #ICC_IGRPEN0_EL1_EN
+ msr ICC_IGRPEN0_EL1, x3
+
+ /*
+ * x5 = gicr sgi base addr
+ * x6 = gicr rd base addr
+ * x7 = core mask lsb
+ */
+
+ /* Clear any pending interrupts */
+ mvn w1, wzr
+ str w1, [x5, #GICR_ICPENDR0_OFFSET]
+
+ /* Make sure system counter is enabled */
+ ldr x3, =NXP_TIMER_ADDR
+ ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 4f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+4:
+ /* Enable the core timer and mask timer interrupt */
+ mov x1, #CNTP_CTL_EL0_EN
+ orr x1, x1, #CNTP_CTL_EL0_IMASK
+ msr cntp_ctl_el0, x1
+
+ isb
+ mov x30, x8
+ ret
+
+/*
+ * Part of CPU_OFF
+ *
+ * This function performs the final steps to shutdown the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0 - x5
+ */
+_soc_core_entr_off:
+ mov x5, x30
+ mov x4, x0
+
+ /* x4 = core mask */
+1:
+ /* Enter low-power state by executing wfi */
+ wfi
+
+ /* See if SGI15 woke us up */
+ mrs x2, ICC_IAR0_EL1
+ mov x3, #ICC_IAR0_EL1_SGI15
+ cmp x2, x3
+ b.ne 1b
+
+ /* Deactivate the int */
+ msr ICC_EOIR0_EL1, x2
+
+ /* x4 = core mask */
+2:
+ /* Check if core has been turned on */
+ mov x0, x4
+ bl _getCoreState
+
+ /* x0 = core state */
+
+ cmp x0, #CORE_WAKEUP
+ b.ne 1b
+
+ /* If we get here, then we have exited the wfi */
+ mov x30, x5
+ ret
+
+/*
+ * Part of CPU_OFF
+ *
+ * This function starts the process of starting a core back up
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6
+ */
+_soc_core_exit_off:
+ mov x6, x30
+ mov x5, x0
+
+ /* Disable forwarding of GRP0 ints at cpu interface */
+ msr ICC_IGRPEN0_EL1, xzr
+
+ /* Get redistributor sgi base addr for this core */
+ mov x0, x5
+ bl get_gic_sgi_base
+ mov x4, x0
+
+ /* x4 = gicr sgi base addr */
+ /* x5 = core mask */
+
+ /* Disable SGI 15 at redistributor - GICR_ICENABLER0 */
+ mov w1, #GICR_ICENABLER0_SGI15
+ str w1, [x4, #GICR_ICENABLER0_OFFSET]
+
+ /* Get redistributor rd base addr for this core */
+ mov x0, x5
+ bl get_gic_rd_base
+ mov x4, x0
+
+ /* x4 = gicr rd base addr */
+2:
+ /* Poll on rwp bit in GICR_CTLR */
+ ldr w2, [x4, #GICR_CTLR_OFFSET]
+ tst w2, #GICR_CTLR_RWP
+ b.ne 2b
+
+ /* x4 = gicr rd base addr */
+
+ /* Unlock the debug interfaces */
+ mrs x3, osdlr_el1
+ bic x3, x3, #OSDLR_EL1_DLK_LOCK
+ msr osdlr_el1, x3
+ isb
+
+ dsb sy
+ isb
+ mov x30, x6
+ ret
+
+/*
+ * This function requests a reset of the entire SOC
+ * in: none
+ * out: none
+ * uses: x0, x1, x2, x3, x4, x5, x6
+ */
+_soc_sys_reset:
+ mov x3, x30
+
+ /* Make sure the mask is cleared in the reset request mask register */
+ mov x0, #RST_RSTRQMR1_OFFSET
+ mov w1, wzr
+ bl _write_reg_reset
+
+ /* Set the reset request */
+ mov x4, #RST_RSTCR_OFFSET
+ mov x0, x4
+ mov w1, #RSTCR_RESET_REQ
+ bl _write_reg_reset
+
+ /* x4 = RST_RSTCR_OFFSET */
+
+ /*
+ * Just in case this address range is mapped as cacheable,
+ * flush the write out of the dcaches
+ */
+ mov x2, #NXP_RESET_ADDR
+ add x2, x2, x4
+ dc cvac, x2
+ dsb st
+ isb
+
+ /* This function does not return */
+1:
+ wfi
+ b 1b
+
+/*
+ * Part of SYSTEM_OFF
+ *
+ * This function turns off the SoC clocks
+ * Note: this function is not intended to return, and the only allowable
+ * recovery is POR
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+_soc_sys_off:
+ /*
+ * Disable sec, spi and flexspi
+ * TBD - Check if eNETC needs to be disabled
+ */
+ ldr x2, =NXP_DCFG_ADDR
+ ldr x0, =DCFG_DEVDISR1_OFFSET
+ ldr w1, =DCFG_DEVDISR1_SEC
+ str w1, [x2, x0]
+ ldr x0, =DCFG_DEVDISR4_OFFSET
+ ldr w1, =DCFG_DEVDISR4_SPI_QSPI
+ str w1, [x2, x0]
+
+ /* Set TPMWAKEMR0 */
+ ldr x0, =TPMWAKEMR0_ADDR
+ mov w1, #0x1
+ str w1, [x0]
+
+ /* Disable icache, dcache, mmu @ EL1 */
+ mov x1, #SCTLR_I_C_M_MASK
+ mrs x0, sctlr_el1
+ bic x0, x0, x1
+ msr sctlr_el1, x0
+
+ /* Disable L2 prefetches */
+ mrs x0, CPUECTLR_EL1
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ bic x0, x0, #CPUECTLR_TIMER_MASK
+ orr x0, x0, #CPUECTLR_TIMER_2TICKS
+ msr CPUECTLR_EL1, x0
+ dsb sy
+ isb
+
+ /* Disable CCI snoop domain */
+ ldr x0, =NXP_CCI_ADDR
+ mov w1, #0x1
+ str w1, [x0]
+
+ bl get_pmu_idle_core_mask
+
+ /* x3 = pmu base addr */
+ mov x3, #NXP_PMU_ADDR
+4:
+ ldr w1, [x3, #PMU_PCPW20SR_OFFSET]
+ cmp w1, w0
+ b.ne 4b
+
+ bl get_pmu_idle_cluster_mask
+ mov x3, #NXP_PMU_ADDR
+ str w0, [x3, #PMU_CLAINACTSETR_OFFSET]
+
+ bl get_pmu_idle_core_mask
+ mov x3, #NXP_PMU_ADDR
+1:
+ ldr w1, [x3, #PMU_PCPW20SR_OFFSET]
+ cmp w1, w0
+ b.ne 1b
+
+ bl get_pmu_flush_cluster_mask
+ mov x3, #NXP_PMU_ADDR
+ str w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET]
+2:
+ ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET]
+ cmp w1, w0
+ b.ne 2b
+
+ str w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET]
+
+ str w0, [x3, #PMU_CLSINACTSETR_OFFSET]
+
+ mov x2, #DAIF_SET_MASK
+ mrs x1, spsr_el1
+ orr x1, x1, x2
+ msr spsr_el1, x1
+
+ mrs x1, spsr_el2
+ orr x1, x1, x2
+ msr spsr_el2, x1
+
+ /* Force the debug interface to be quiescent */
+ mrs x0, osdlr_el1
+ orr x0, x0, #0x1
+ msr osdlr_el1, x0
+
+ /* Invalidate all TLB entries at all 3 exception levels */
+ tlbi alle1
+ tlbi alle2
+ tlbi alle3
+
+ /* x3 = pmu base addr */
+
+ /* Request lpm20 */
+ ldr x0, =PMU_POWMGTCSR_OFFSET
+ ldr w1, =PMU_POWMGTCSR_VAL
+ str w1, [x3, x0]
+ isb
+ dsb sy
+5:
+ wfe
+ b.eq 5b
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_core_prep_stdby:
+ /* Clear CPUECTLR_EL1[2:0] */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CPUECTLR_EL1, x1
+
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function puts the calling core into standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_stdby:
+ /* X0 = core mask lsb */
+ dsb sy
+ isb
+ wfi
+
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_core_exit_stdby:
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2
+ */
+_soc_core_prep_pwrdn:
+ /* Make sure system counter is enabled */
+ ldr x2, =NXP_TIMER_ADDR
+ ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 1f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+ /*
+ * Enable dynamic retention control (CPUECTLR[2:0])
+ * Set the SMPEN bit (CPUECTLR[6])
+ */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_RET_MASK
+ orr x1, x1, #CPUECTLR_TIMER_2TICKS
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ msr CPUECTLR_EL1, x1
+
+ isb
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function puts the calling core into a power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_pwrdn:
+ /* X0 = core mask lsb */
+ dsb sy
+ isb
+ wfi
+
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_core_exit_pwrdn:
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_clstr_prep_stdby:
+ /* Clear CPUECTLR_EL1[2:0] */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CPUECTLR_EL1, x1
+
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_clstr_exit_stdby:
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2
+ */
+_soc_clstr_prep_pwrdn:
+ /* Make sure system counter is enabled */
+ ldr x2, =NXP_TIMER_ADDR
+ ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 1f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+ /*
+ * Enable dynamic retention control (CPUECTLR[2:0])
+ * Set the SMPEN bit (CPUECTLR[6])
+ */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_RET_MASK
+ orr x1, x1, #CPUECTLR_TIMER_2TICKS
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ msr CPUECTLR_EL1, x1
+
+ isb
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_clstr_exit_pwrdn:
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_prep_stdby:
+ /* Clear CPUECTLR_EL1[2:0] */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CPUECTLR_EL1, x1
+
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_sys_exit_stdby:
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to
+ * suspend-to-power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4
+ */
+_soc_sys_prep_pwrdn:
+ /* Set retention control */
+ mrs x0, CPUECTLR_EL1
+ bic x0, x0, #CPUECTLR_TIMER_MASK
+ orr x0, x0, #CPUECTLR_TIMER_2TICKS
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ msr CPUECTLR_EL1, x0
+ dsb sy
+ isb
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function puts the calling core, and potentially the soc, into a
+ * low-power state
+ * in: x0 = core mask lsb
+ * out: x0 = 0, success
+ * x0 < 0, failure
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x13, x14, x15,
+ * x16, x17, x18
+ */
+_soc_sys_pwrdn_wfi:
+ mov x18, x30
+
+ mov x3, #NXP_PMU_ADDR
+
+ /* x3 = pmu base addr */
+
+ /* Backup epu registers to stack */
+ ldr x2, =NXP_EPU_ADDR
+ ldr w4, [x2, #EPU_EPIMCR10_OFFSET]
+ ldr w5, [x2, #EPU_EPCCR10_OFFSET]
+ ldr w6, [x2, #EPU_EPCTR10_OFFSET]
+ ldr w7, [x2, #EPU_EPGCR_OFFSET]
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+
+ /*
+ * x2 = epu base addr
+ * x3 = pmu base addr
+ */
+
+ /* Set up EPU event to receive the wake signal from PMU */
+ mov w4, #EPU_EPIMCR10_VAL
+ mov w5, #EPU_EPCCR10_VAL
+ mov w6, #EPU_EPCTR10_VAL
+ mov w7, #EPU_EPGCR_VAL
+ str w4, [x2, #EPU_EPIMCR10_OFFSET]
+ str w5, [x2, #EPU_EPCCR10_OFFSET]
+ str w6, [x2, #EPU_EPCTR10_OFFSET]
+ str w7, [x2, #EPU_EPGCR_OFFSET]
+
+ ldr x2, =NXP_GICD_ADDR
+
+ /*
+ * x2 = gicd base addr
+ * x3 = pmu base addr
+ */
+
+ /* Backup flextimer/mmc/usb interrupt router */
+ ldr x0, =GICD_IROUTER60_OFFSET
+ ldr x1, =GICD_IROUTER76_OFFSET
+ ldr w4, [x2, x0]
+ ldr w5, [x2, x1]
+ ldr x0, =GICD_IROUTER112_OFFSET
+ ldr x1, =GICD_IROUTER113_OFFSET
+ ldr w6, [x2, x0]
+ ldr w7, [x2, x1]
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+
+ /*
+ * x2 = gicd base addr
+ * x3 = pmu base addr
+ * x0 = GICD_IROUTER112_OFFSET
+ * x1 = GICD_IROUTER113_OFFSET
+ */
+
+ /* Re-route interrupt to cluster 1 */
+ ldr w4, =GICD_IROUTER_VALUE
+ str w4, [x2, x0]
+ str w4, [x2, x1]
+ ldr x0, =GICD_IROUTER60_OFFSET
+ ldr x1, =GICD_IROUTER76_OFFSET
+ str w4, [x2, x0]
+ str w4, [x2, x1]
+ dsb sy
+ isb
+
+ /* x3 = pmu base addr */
+
+ /* Disable sec, Check for eNETC, spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+ ldr x0, =DCFG_DEVDISR1_OFFSET
+ ldr w1, =DCFG_DEVDISR1_SEC
+ str w1, [x2, x0]
+
+ ldr x0, =DCFG_DEVDISR4_OFFSET
+ ldr w1, =DCFG_DEVDISR4_SPI_QSPI
+ str w1, [x2, x0]
+
+ /* x3 = pmu base addr */
+
+ /* Set TPMWAKEMR0 */
+ ldr x0, =TPMWAKEMR0_ADDR
+ mov w1, #0x1
+ str w1, [x0]
+
+ /* Disable CCI snoop domain */
+ ldr x0, =NXP_CCI_ADDR
+ mov w1, #0x1
+ str w1, [x0]
+
+ /* Setup retention control */
+ mrs x0, CPUECTLR_EL1
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ orr x0, x0, #CPUECTLR_TIMER_2TICKS
+ msr CPUECTLR_EL1, x0
+ dsb sy
+ isb
+
+ bl get_pmu_idle_core_mask
+ mov x3, #NXP_PMU_ADDR
+8:
+ ldr w1, [x3, #PMU_PCPW20SR_OFFSET]
+ cmp w1, w0
+ b.ne 8b
+
+ /* x3 = NXP_PMU_ADDR */
+ /* 1 cluster SoC */
+
+ bl get_pmu_idle_cluster_mask
+ mov x3, #NXP_PMU_ADDR
+
+ str w0, [x3, #PMU_CLAINACTSETR_OFFSET]
+
+ bl get_pmu_idle_core_mask
+ /* x3 = NXP_PMU_ADDR */
+ mov x3, #NXP_PMU_ADDR
+1:
+ ldr w1, [x3, #PMU_PCPW20SR_OFFSET]
+ cmp w1, w0
+ b.ne 1b
+
+ /* x3 = NXP_PMU_ADDR */
+ bl get_pmu_flush_cluster_mask
+ mov x3, #NXP_PMU_ADDR
+
+ str w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET]
+
+ /* x3 = NXP_PMU_ADDR */
+2:
+ ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET]
+ cmp w1, w0
+ b.ne 2b
+
+ /* x3 = NXP_PMU_ADDR */
+
+ str w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET]
+
+ str w0, [x3, #PMU_CLSINACTSETR_OFFSET]
+
+ /* Force the debug interface to be quiescent */
+ mrs x0, osdlr_el1
+ orr x0, x0, #0x1
+ msr osdlr_el1, x0
+
+ /*
+ * Enable the WakeRequest signal
+ * x3 is cpu mask starting from cpu1 to cpu0
+ */
+ bl get_tot_num_cores
+ sub x0, x0, #1
+ mov x3, #0x1
+ lsl x3, x3, x0
+2:
+ mov x0, x3
+ bl get_gic_rd_base // 0-2
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ orr w1, w1, #GICR_WAKER_SLEEP_BIT
+ str w1, [x0, #GICR_WAKER_OFFSET]
+1:
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ cmp w1, #GICR_WAKER_ASLEEP
+ b.ne 1b
+
+ lsr x3, x3, #1
+ cbnz x3, 2b
+
+ /* Invalidate all TLB entries at all 3 exception levels */
+ tlbi alle1
+ tlbi alle2
+ tlbi alle3
+
+ /* Request lpm20 */
+ mov x3, #NXP_PMU_ADDR
+ ldr x0, =PMU_POWMGTCSR_OFFSET
+ ldr w1, =PMU_POWMGTCSR_VAL
+ str w1, [x3, x0]
+
+ ldr x5, =NXP_EPU_ADDR
+4:
+ wfe
+ ldr w1, [x5, #EPU_EPCTR10_OFFSET]
+ cmp w1, #0
+ b.eq 4b
+
+ /* x3 = NXP_PMU_ADDR */
+
+ bl get_pmu_idle_cluster_mask
+ mov x3, NXP_PMU_ADDR
+
+ /* Re-enable the GPP ACP */
+ str w0, [x3, #PMU_CLAINACTCLRR_OFFSET]
+ str w0, [x3, #PMU_CLSINACTCLRR_OFFSET]
+
+ /* x3 = NXP_PMU_ADDR */
+3:
+ ldr w1, [x3, #PMU_CLAINACTSETR_OFFSET]
+ cbnz w1, 3b
+4:
+ ldr w1, [x3, #PMU_CLSINACTSETR_OFFSET]
+ cbnz w1, 4b
+
+ /*
+ * Enable the WakeRequest signal on cpu 0-1
+ * x3 is cpu mask starting from cpu1
+ */
+ bl get_tot_num_cores
+ sub x0, x0, #1
+ mov x3, #0x1
+ lsl x3, x3, x0
+2:
+ mov x0, x3
+ bl get_gic_rd_base // 0-2
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ bic w1, w1, #GICR_WAKER_SLEEP_BIT
+ str w1, [x0, #GICR_WAKER_OFFSET]
+1:
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ cbnz w1, 1b
+
+ lsr x3, x3, #1
+ cbnz x3, 2b
+
+ /* Enable CCI snoop domain */
+ ldr x0, =NXP_CCI_ADDR
+ str wzr, [x0]
+ dsb sy
+ isb
+
+ ldr x3, =NXP_EPU_ADDR
+
+ /* x3 = epu base addr */
+
+ /* Enable sec, enetc, spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+ str wzr, [x2, #DCFG_DEVDISR1_OFFSET]
+ str wzr, [x2, #DCFG_DEVDISR2_OFFSET]
+ str wzr, [x2, #DCFG_DEVDISR4_OFFSET]
+
+ /* Restore flextimer/mmc/usb interrupt router */
+ ldr x3, =NXP_GICD_ADDR
+ ldp x0, x2, [sp], #16
+ ldr x1, =GICD_IROUTER113_OFFSET
+ str w2, [x3, x1]
+ ldr x1, =GICD_IROUTER112_OFFSET
+ str w0, [x3, x1]
+ ldp x0, x2, [sp], #16
+ ldr x1, =GICD_IROUTER76_OFFSET
+ str w2, [x3, x1]
+ ldr x1, =GICD_IROUTER60_OFFSET
+ str w0, [x3, x1]
+
+ /* Restore EPU registers */
+ ldr x3, =NXP_EPU_ADDR
+ ldp x0, x2, [sp], #16
+ str w2, [x3, #EPU_EPGCR_OFFSET]
+ str w0, [x3, #EPU_EPCTR10_OFFSET]
+ ldp x2, x1, [sp], #16
+ str w1, [x3, #EPU_EPCCR10_OFFSET]
+ str w2, [x3, #EPU_EPIMCR10_OFFSET]
+
+ dsb sy
+ isb
+ mov x30, x18
+ ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_exit_pwrdn:
+ /* Enable stack alignment checking */
+ mrs x1, SCTLR_EL1
+ orr x1, x1, #0x4
+ msr SCTLR_EL1, x1
+
+ /* Enable debug interface */
+ mrs x1, osdlr_el1
+ bic x1, x1, #OSDLR_EL1_DLK_LOCK
+ msr osdlr_el1, x1
+
+ /* Enable i-cache */
+ mrs x1, SCTLR_EL3
+ orr x1, x1, #SCTLR_I_MASK
+ msr SCTLR_EL3, x1
+
+ isb
+ ret
+
+/*
+ * This function setc up the TrustZone Address Space Controller (TZASC)
+ * in: none
+ * out: none
+ * uses x0, x1
+ */
+init_tzpc:
+ /* Set Non Secure access for all devices protected via TZPC */
+ ldr x1, =TZPCDECPROT_0_SET_BASE /* decode Protection-0 Set Reg */
+ mov w0, #0xFF /* set decode region to NS, Bits[7:0] */
+ str w0, [x1]
+
+ ldr x1, =TZPCDECPROT_1_SET_BASE /* decode Protection-1 Set Reg */
+ mov w0, #0xFF /* set decode region to NS, Bits[7:0] */
+ str w0, [x1]
+
+ ldr x1, =TZPCDECPROT_2_SET_BASE /* decode Protection-2 Set Reg */
+ mov w0, #0xFF /* set decode region to NS, Bits[7:0] */
+ str w0, [x1]
+
+ /* entire SRAM as NS */
+ ldr x1, =NXP_OCRAM_TZPC_ADDR /* secure RAM region size Reg */
+ mov w0, #0x00000000 /* 0x00000000 = no secure region */
+ str w0, [x1]
+
+ ret
+
+/*
+ * This function performs any needed initialization on SecMon for
+ * boot services
+ */
+initSecMon:
+ /* Read the register hpcomr */
+ ldr x1, =NXP_SNVS_ADDR
+ ldr w0, [x1, #SECMON_HPCOMR_OFFSET]
+ /* Turn off secure access for the privileged registers */
+ orr w0, w0, #SECMON_HPCOMR_NPSWAEN
+ /* Write back */
+ str w0, [x1, #SECMON_HPCOMR_OFFSET]
+
+ ret
+
+/*
+ * This function checks to see if cores which are to be disabled have been
+ * released from reset - if not, it releases them
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
+ */
+release_disabled:
+ stp x18, x30, [sp, #-16]!
+
+ /*
+ * Get the number of cpus on this device
+ * Calling the below c function.
+ * No need to Callee saved registers x9-x15,
+ * as these registers are not used by the callee
+ * prior to calling the below C-routine.
+ */
+ bl get_tot_num_cores
+ mov x6, x0
+
+ /* Read COREDISABLESR */
+ mov x0, #NXP_DCFG_ADDR
+ ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
+
+ mov x0, #NXP_RESET_ADDR
+ ldr w5, [x0, #BRR_OFFSET]
+
+ /* Load the core mask for the first core */
+ mov x7, #1
+
+ /*
+ * x4 = COREDISABLESR
+ * x5 = BRR
+ * x6 = loop count
+ * x7 = core mask bit
+ */
+2:
+ /* Check if the core is to be disabled */
+ tst x4, x7
+ b.eq 1f
+
+ /* See if disabled cores have already been released from reset */
+ tst x5, x7
+ b.ne 1f
+
+ /* If core has not been released, then release it (0-3) */
+ mov x0, x7
+ bl _soc_core_release
+
+ /* Record the core state in the data area (0-3) */
+ mov x0, x7
+ mov x1, #CORE_DISABLED
+ bl _setCoreState
+1:
+ /* Decrement the counter */
+ subs x6, x6, #1
+ b.le 3f
+ /* Shift the core mask to the next core */
+ lsl x7, x7, #1
+ /* Continue */
+ b 2b
+3:
+ ldp x18, x30, [sp], #16
+ ret
+
+/*
+ * Write a register in the DCFG block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2
+ */
+_write_reg_dcfg:
+ ldr x2, =NXP_DCFG_ADDR
+ str w1, [x2, x0]
+ ret
+
+/*
+ * Read a register in the DCFG block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+_read_reg_dcfg:
+ ldr x2, =NXP_DCFG_ADDR
+ ldr w1, [x2, x0]
+ mov w0, w1
+ ret
+
+/*
+ * This function returns an mpidr value for a core, given a core_mask_lsb
+ * in: x0 = core mask lsb
+ * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits
+ * uses x0, x1
+ */
+get_mpidr_value:
+ /* Convert a core mask to an SoC core number */
+ clz w0, w0
+ mov w1, #31
+ sub w0, w1, w0
+
+ /* Get the mpidr core number from the SoC core number */
+ mov w1, wzr
+ tst x0, #1
+ b.eq 1f
+ orr w1, w1, #1
+1:
+ /* Extract the cluster number */
+ lsr w0, w0, #1
+ orr w0, w1, w0, lsl #8
+
+ ret
+
+/*
+ * This function returns the redistributor base address for the core specified
+ * in x1
+ * in: x0 - core mask lsb of specified core
+ * out: x0 = redistributor rd base address for specified core
+ * uses x0, x1, x2
+ */
+get_gic_rd_base:
+ /* Get the 0-based core number */
+ clz w1, w0
+ mov w2, #0x20
+ sub w2, w2, w1
+ sub w2, w2, #1
+
+ /* x2 = core number / loop counter */
+ ldr x0, =NXP_GICR_ADDR
+ mov x1, #GIC_RD_OFFSET
+2:
+ cbz x2, 1f
+ add x0, x0, x1
+ sub x2, x2, #1
+ b 2b
+1:
+ ret
+
+/*
+ * This function returns the redistributor base address for the core specified
+ * in x1
+ * in: x0 - core mask lsb of specified core
+ * out: x0 = redistributor sgi base address for specified core
+ * uses x0, x1, x2
+ */
+get_gic_sgi_base:
+ /* Get the 0-based core number */
+ clz w1, w0
+ mov w2, #0x20
+ sub w2, w2, w1
+ sub w2, w2, #1
+
+ /* x2 = core number / loop counter */
+ ldr x0, =NXP_GICR_SGI_ADDR
+ mov x1, #GIC_SGI_OFFSET
+2:
+ cbz x2, 1f
+ add x0, x0, x1
+ sub x2, x2, #1
+ b 2b
+1:
+ ret
+
+/*
+ * Write a register in the RESET block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2
+ */
+_write_reg_reset:
+ ldr x2, =NXP_RESET_ADDR
+ str w1, [x2, x0]
+ ret
+
+/*
+ * Read a register in the RESET block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1
+ */
+_read_reg_reset:
+ ldr x1, =NXP_RESET_ADDR
+ ldr w0, [x1, x0]
+ ret
diff --git a/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S b/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S
new file mode 100644
index 0000000..ec67529
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+#include <platform_def.h>
+
+.globl plat_secondary_cold_boot_setup
+.globl plat_is_my_cpu_primary
+.globl plat_reset_handler
+.globl platform_mem_init
+
+func platform_mem1_init
+ ret
+endfunc platform_mem1_init
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+func apply_platform_errata
+ ret
+endfunc apply_platform_errata
+
+func plat_reset_handler
+ mov x29, x30
+ bl apply_platform_errata
+
+#if defined(IMAGE_BL31)
+ ldr x0, =POLICY_SMMU_PAGESZ_64K
+ cbz x0, 1f
+ /* Set the SMMU page size in the sACR register */
+ bl _set_smmu_pagesz_64
+#endif
+1:
+ mov x30, x29
+ ret
+endfunc plat_reset_handler
+
+/*
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ */
+func plat_secondary_cold_boot_setup
+ /* ls1028a does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+/*
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, 0x0
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/nxp/soc-ls1028a/include/soc.h b/plat/nxp/soc-ls1028a/include/soc.h
new file mode 100644
index 0000000..b1d044a
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/include/soc.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+/* Chassis specific defines - common across SoC's of a particular platform */
+#include <dcfg_lsch3.h>
+#include <soc_default_base_addr.h>
+#include <soc_default_helper_macros.h>
+
+/*
+ * SVR Definition of LS1028A
+ * (not include major and minor rev)
+ * These info is listed in Table B-6. DCFG differences
+ * between LS1028A and LS1027A of LS1028ARM(Reference Manual)
+ */
+#define SVR_LS1017AN 0x870B25
+#define SVR_LS1017AE 0x870B24
+#define SVR_LS1018AN 0x870B21
+#define SVR_LS1018AE 0x870B20
+#define SVR_LS1027AN 0x870B05
+#define SVR_LS1027AE 0x870B04
+#define SVR_LS1028AN 0x870B01
+#define SVR_LS1028AE 0x870B00
+
+/* Number of cores in platform */
+#define PLATFORM_CORE_COUNT 2
+#define NUMBER_OF_CLUSTERS 1
+#define CORES_PER_CLUSTER 2
+
+/* Set to 0 if the clusters are not symmetrical */
+#define SYMMETRICAL_CLUSTERS 1
+
+#define NUM_DRAM_REGIONS 3
+
+#define NXP_DRAM0_ADDR 0x80000000
+#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2GB */
+
+#define NXP_DRAM1_ADDR 0x2080000000
+#define NXP_DRAM1_MAX_SIZE 0x1F80000000 /* 126G */
+
+#define NXP_DRAM2_ADDR 0x6000000000
+#define NXP_DRAM2_MAX_SIZE 0x2000000000 /* 128G */
+
+/* DRAM0 Size defined in platform_def.h */
+#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE
+
+/* CCSR space memory Map */
+#undef NXP_UART_ADDR
+#define NXP_UART_ADDR 0x021C0500
+
+#undef NXP_UART1_ADDR
+#define NXP_UART1_ADDR 0x021C0600
+
+#undef NXP_WDOG1_TZ_ADDR
+#define NXP_WDOG1_TZ_ADDR 0x023C0000
+
+#undef NXP_GICR_ADDR
+#define NXP_GICR_ADDR 0x06040000
+
+#undef NXP_GICR_SGI_ADDR
+#define NXP_GICR_SGI_ADDR 0x06050000
+
+/* EPU register offsets and values */
+#define EPU_EPGCR_OFFSET 0x0
+#define EPU_EPIMCR10_OFFSET 0x128
+#define EPU_EPCTR10_OFFSET 0xa28
+#define EPU_EPCCR10_OFFSET 0x828
+#define EPU_EPCCR10_VAL 0xb2800000
+#define EPU_EPIMCR10_VAL 0xba000000
+#define EPU_EPCTR10_VAL 0x0
+#define EPU_EPGCR_VAL (1 << 31)
+
+/* PORSR1 */
+#define PORSR1_RCW_MASK 0x07800000
+#define PORSR1_RCW_SHIFT 23
+
+#define SDHC1_VAL 0x8
+#define SDHC2_VAL 0x9
+#define I2C1_VAL 0xa
+#define FLEXSPI_NAND2K_VAL 0xc
+#define FLEXSPI_NAND4K_VAL 0xd
+#define FLEXSPI_NOR 0xf
+
+/*
+ * Required LS standard platform porting definitions
+ * for CCI-400
+ */
+#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4
+
+/* Defines required for using XLAT tables from ARM common code */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40)
+
+/* Clock Divisors */
+#define NXP_PLATFORM_CLK_DIVIDER 1
+#define NXP_UART_CLK_DIVIDER 2
+
+/* dcfg register offsets and values */
+#define DCFG_DEVDISR2_ENETC (1 << 31)
+
+#define MPIDR_AFFINITY0_MASK 0x00FF
+#define MPIDR_AFFINITY1_MASK 0xFF00
+#define CPUECTLR_DISABLE_TWALK_PREFETCH 0x4000000000
+#define CPUECTLR_INS_PREFETCH_MASK 0x1800000000
+#define CPUECTLR_DAT_PREFETCH_MASK 0x0300000000
+#define OSDLR_EL1_DLK_LOCK 0x1
+#define CNTP_CTL_EL0_EN 0x1
+#define CNTP_CTL_EL0_IMASK 0x2
+
+#define SYSTEM_PWR_DOMAINS 1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ NUMBER_OF_CLUSTERS + \
+ SYSTEM_PWR_DOMAINS)
+
+/* Power state coordination occurs at the system level */
+#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL
+
+/* Local power state for power domains in Run state */
+#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN
+
+/* define retention state */
+#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1)
+#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE
+
+/* define power-down state */
+#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1)
+#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE
+
+/* One cache line needed for bakery locks on ARM platforms */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+#ifndef __ASSEMBLER__
+/* CCI slave interfaces */
+static const int cci_map[] = {
+ NXP_CCI_CLUSTER0_SL_IFACE_IX,
+};
+void soc_init_lowlevel(void);
+void soc_init_percpu(void);
+void _soc_set_start_addr(unsigned long addr);
+void _set_platform_security(void);
+#endif
+
+#endif /* SOC_H */
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c b/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c
new file mode 100644
index 0000000..d82be51
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+const struct ddr_cfg_regs static_1600 = {
+ .cs[0].config = U(0x80040422),
+ .cs[0].bnds = U(0xFF),
+ .sdram_cfg[0] = U(0xE50C0004),
+ .sdram_cfg[1] = U(0x401100),
+ .timing_cfg[0] = U(0x91550018),
+ .timing_cfg[1] = U(0xBAB40C42),
+ .timing_cfg[2] = U(0x48C111),
+ .timing_cfg[3] = U(0x1111000),
+ .timing_cfg[4] = U(0x2),
+ .timing_cfg[5] = U(0x3401400),
+ .timing_cfg[7] = U(0x23300000),
+ .timing_cfg[8] = U(0x2114600),
+ .sdram_mode[0] = U(0x3010210),
+ .sdram_mode[9] = U(0x4000000),
+ .sdram_mode[8] = U(0x500),
+ .sdram_mode[2] = U(0x10210),
+ .sdram_mode[10] = U(0x400),
+ .sdram_mode[11] = U(0x4000000),
+ .sdram_mode[4] = U(0x10210),
+ .sdram_mode[12] = U(0x400),
+ .sdram_mode[13] = U(0x4000000),
+ .sdram_mode[6] = U(0x10210),
+ .sdram_mode[14] = U(0x400),
+ .sdram_mode[15] = U(0x4000000),
+ .interval = U(0x18600618),
+ .data_init = U(0xdeadbeef),
+ .zq_cntl = U(0x8A090705),
+ .clk_cntl = U(0x2000000),
+ .cdr[0] = U(0x80040000),
+ .cdr[1] = U(0xA181),
+ .wrlvl_cntl[0] = U(0x8675F605),
+ .wrlvl_cntl[1] = U(0x6070700),
+ .wrlvl_cntl[2] = U(0x0000008),
+ .dq_map[0] = U(0x5b65b658),
+ .dq_map[1] = U(0xd96d8000),
+ .dq_map[2] = U(0),
+ .dq_map[3] = U(0x1600000),
+ .debug[28] = U(0x00700046),
+};
+
+unsigned long long board_static_ddr(struct ddr_info *priv)
+{
+ memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600));
+ return ULL(0x100000000);
+}
+
+#else
+
+static const struct rc_timing rcz[] = {
+ {1600, 8, 5},
+ {}
+};
+
+static const struct board_timing ram[] = {
+ {0x1f, rcz, 0x1020200, 0x00000003},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ int ret;
+ struct memctl_opt *popts = &priv->opt;
+
+ ret = cal_board_params(priv, ram, ARRAY_SIZE(ram));
+ if (ret != 0) {
+ return ret;
+ }
+
+ popts->bstopre = U(0x40); /* precharge value */
+ popts->half_strength_drive_en = 1;
+ popts->cpo_sample = U(0x46);
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
+ DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
+ DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */
+
+ popts->addr_hash = 1; /* address hashing */
+ return 0;
+}
+
+/* DDR model number: MT40A1G8SA-075:E */
+struct dimm_params ddr_raw_timing = {
+ .n_ranks = U(1),
+ .rank_density = ULL(4294967296),
+ .capacity = ULL(4294967296),
+ .primary_sdram_width = U(32),
+ .ec_sdram_width = U(4),
+ .rdimm = U(0),
+ .mirrored_dimm = U(0),
+ .n_row_addr = U(16),
+ .n_col_addr = U(10),
+ .bank_group_bits = U(2),
+ .edc_config = U(2),
+ .burst_lengths_bitmask = U(0x0c),
+ .tckmin_x_ps = 750,
+ .tckmax_ps = 1900,
+ .caslat_x = U(0x0001FFE00),
+ .taa_ps = 13500,
+ .trcd_ps = 13500,
+ .trp_ps = 13500,
+ .tras_ps = 32000,
+ .trc_ps = 45500,
+ .twr_ps = 15000,
+ .trfc1_ps = 350000,
+ .trfc2_ps = 260000,
+ .trfc4_ps = 160000,
+ .tfaw_ps = 21000,
+ .trrds_ps = 3000,
+ .trrdl_ps = 4900,
+ .tccdl_ps = 5000,
+ .refresh_rate_ps = U(7800000),
+ .dq_mapping[0] = U(0x16),
+ .dq_mapping[1] = U(0x36),
+ .dq_mapping[2] = U(0x16),
+ .dq_mapping[3] = U(0x36),
+ .dq_mapping[4] = U(0x16),
+ .dq_mapping[5] = U(0x36),
+ .dq_mapping[6] = U(0x16),
+ .dq_mapping[7] = U(0x36),
+ .dq_mapping[8] = U(0x16),
+ .dq_mapping[9] = U(0x0),
+ .dq_mapping[10] = U(0x0),
+ .dq_mapping[11] = U(0x0),
+ .dq_mapping[12] = U(0x0),
+ .dq_mapping[13] = U(0x0),
+ .dq_mapping[14] = U(0x0),
+ .dq_mapping[15] = U(0x0),
+ .dq_mapping[16] = U(0x0),
+ .dq_mapping[17] = U(0x0),
+ .dq_mapping_ors = U(0),
+ .rc = U(0x1f),
+};
+
+int ddr_get_ddr_params(struct dimm_params *pdimm,
+ struct ddr_conf *conf)
+{
+ static const char dimm_model[] = "Fixed DDR on board";
+
+ conf->dimm_in_use[0] = 1;
+ memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params));
+ memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+
+ return 1;
+}
+#endif
+
+int64_t init_ddr(void)
+{
+ struct ddr_info info;
+ struct sysinfo sys;
+ int64_t dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ get_clocks(&sys);
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+
+ zeromem(&info, sizeof(struct ddr_info));
+ info.num_ctlrs = 1;
+ info.dimm_on_ctlr = 1;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+ dram_size = dram_init(&info);
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h b/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h
new file mode 100644
index 0000000..63c0219
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+#include <cortex_a72.h>
+/*
+ * Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+#define NXP_SPD_EEPROM0 0x51
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0xC000)
+
+#ifdef SD_BOOT
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+ - NXP_SD_BLOCK_BUF_SIZE)
+#else
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+#endif
+#define BL2_TEXT_LIMIT (BL2_LIMIT)
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES 4
+#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_HANDLES 4
+
+#define BL31_WDOG_SEC 89
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+
+/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
+#define PLAT_LS_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+#endif /* PLAT_DEF_H */
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform.c b/plat/nxp/soc-ls1028a/ls1028ardb/platform.c
new file mode 100644
index 0000000..65d508c
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk b/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk
new file mode 100644
index 0000000..c455000
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk
@@ -0,0 +1,33 @@
+#
+# Copyright 2020-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Board-specific build parameters
+BOOT_MODE ?= flexspi_nor
+BOARD := ls1028ardb
+POVDD_ENABLE := no
+WARM_BOOT := no
+
+# DDR build parameters
+NUM_OF_DDRC := 1
+CONFIG_DDR_NODIMM := 1
+DDR_ECC_EN := yes
+
+# On-board flash
+FLASH_TYPE := MT35XU02G
+XSPI_FLASH_SZ := 0x10000000
+
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := flexspi_nor \
+ sd \
+ emmc
+
+# Add platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Add SoC build info
+include plat/nxp/soc-ls1028a/soc.mk
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h b/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h
new file mode 100644
index 0000000..bbad293
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/policy.h b/plat/nxp/soc-ls1028a/ls1028ardb/policy.h
new file mode 100644
index 0000000..67a8b45
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/policy.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/*
+ * Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1028a/soc.c b/plat/nxp/soc-ls1028a/soc.c
new file mode 100644
index 0000000..2fb353f
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/soc.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <endian.h>
+
+#include <arch.h>
+#include <caam.h>
+#include <cassert.h>
+#include <cci.h>
+#include <common/debug.h>
+#include <dcfg.h>
+#include <i2c.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <ls_interconnect.h>
+#include <mmio.h>
+#ifdef POLICY_FUSE_PROVISION
+#include <nxp_gpio.h>
+#endif
+#if TRUSTED_BOARD_BOOT
+#include <nxp_smmu.h>
+#endif
+#include <nxp_timer.h>
+#include <plat_console.h>
+#include <plat_gic.h>
+#include <plat_tzc400.h>
+#include <pmu.h>
+#include <scfg.h>
+#if defined(NXP_SFP_ENABLED)
+#include <sfp.h>
+#endif
+
+#include <errata.h>
+#ifdef CONFIG_OCRAM_ECC_EN
+#include <ocram.h>
+#endif
+#include "plat_common.h"
+#include "platform_def.h"
+#include "soc.h"
+
+static dcfg_init_info_t dcfg_init_data = {
+ .g_nxp_dcfg_addr = NXP_DCFG_ADDR,
+ .nxp_sysclk_freq = NXP_SYSCLK_FREQ,
+ .nxp_ddrclk_freq = NXP_DDRCLK_FREQ,
+ .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER,
+};
+
+static struct soc_type soc_list[] = {
+ SOC_ENTRY(LS1017AN, LS1017AN, 1, 1),
+ SOC_ENTRY(LS1017AE, LS1017AE, 1, 1),
+ SOC_ENTRY(LS1018AN, LS1018AN, 1, 1),
+ SOC_ENTRY(LS1018AE, LS1018AE, 1, 1),
+ SOC_ENTRY(LS1027AN, LS1027AN, 1, 2),
+ SOC_ENTRY(LS1027AE, LS1027AE, 1, 2),
+ SOC_ENTRY(LS1028AN, LS1028AN, 1, 2),
+ SOC_ENTRY(LS1028AE, LS1028AE, 1, 2),
+};
+
+CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256,
+ assert_invalid_ls1028a_cluster_count);
+
+/*
+ * Function returns the base counter frequency
+ * after reading the first entry at CNTFID0 (0x20 offset).
+ *
+ * Function is used by:
+ * 1. ARM common code for PSCI management.
+ * 2. ARM Generic Timer init.
+ *
+ */
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+ /*
+ * Below register specifies the base frequency of the system counter.
+ * As per NXP Board Manuals:
+ * The system counter always works with SYS_REF_CLK/4 frequency clock.
+ */
+ counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF);
+
+ return counter_base_frequency;
+}
+
+#ifdef IMAGE_BL2
+
+#ifdef POLICY_FUSE_PROVISION
+static gpio_init_info_t gpio_init_data = {
+ .gpio1_base_addr = NXP_GPIO1_ADDR,
+ .gpio2_base_addr = NXP_GPIO2_ADDR,
+ .gpio3_base_addr = NXP_GPIO3_ADDR,
+};
+#endif
+
+void soc_preload_setup(void)
+{
+}
+
+void soc_early_init(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+#ifdef CONFIG_OCRAM_ECC_EN
+ ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE);
+#endif
+ dcfg_init(&dcfg_init_data);
+ enable_timer_base_to_cluster(NXP_PMU_ADDR);
+ enable_core_tb(NXP_PMU_ADDR);
+ dram_regions_info_t *dram_regions_info = get_dram_regions_info();
+
+#ifdef POLICY_FUSE_PROVISION
+ gpio_init(&gpio_init_data);
+ sec_init(NXP_CAAM_ADDR);
+#endif
+
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+ enum boot_device dev = get_boot_dev();
+ /*
+ * Mark the buffer for SD in OCRAM as non secure.
+ * The buffer is assumed to be at end of OCRAM for
+ * the logic below to calculate TZPC programming
+ */
+ if (dev == BOOT_DEVICE_EMMC || dev == BOOT_DEVICE_SDHC2_EMMC) {
+ /*
+ * Calculate the region in OCRAM which is secure
+ * The buffer for SD needs to be marked non-secure
+ * to allow SD to do DMA operations on it
+ */
+ uint32_t secure_region = (NXP_OCRAM_SIZE - NXP_SD_BLOCK_BUF_SIZE);
+ uint32_t mask = secure_region/TZPC_BLOCK_SIZE;
+
+ mmio_write_32(NXP_OCRAM_TZPC_ADDR, mask);
+
+ /* Add the entry for buffer in MMU Table */
+ mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR,
+ NXP_SD_BLOCK_BUF_SIZE, MT_DEVICE | MT_RW | MT_NS);
+ }
+
+#if TRUSTED_BOARD_BOOT
+ uint32_t mode;
+
+ sfp_init(NXP_SFP_ADDR);
+
+ /*
+ * For secure boot disable SMMU.
+ * Later when platform security policy comes in picture,
+ * this might get modified based on the policy
+ */
+ if (check_boot_mode_secure(&mode) == true) {
+ bypass_smmu(NXP_SMMU_ADDR);
+ }
+
+ /*
+ * For Mbedtls currently crypto is not supported via CAAM
+ * enable it when that support is there. In tbbr.mk
+ * the CAAM_INTEG is set as 0.
+ */
+#ifndef MBEDTLS_X509
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled()) {
+ sec_init(NXP_CAAM_ADDR);
+ } else {
+ INFO("SEC is disabled.\n");
+ }
+#endif
+#endif
+
+ /* Set eDDRTQ for DDR performance */
+ scfg_setbits32((void *)(NXP_SCFG_ADDR + 0x210), 0x1f1f1f1f);
+
+ soc_errata();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ plat_ls_interconnect_enter_coherency(num_clusters);
+
+ delay_timer_init(NXP_TIMER_ADDR);
+ i2c_init(NXP_I2C_ADDR);
+ dram_regions_info->total_dram_size = init_ddr();
+}
+
+void soc_bl2_prepare_exit(void)
+{
+#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE)
+ set_sfp_wr_disable();
+#endif
+}
+
+/*
+ * This function returns the boot device based on RCW_SRC
+ */
+enum boot_device get_boot_dev(void)
+{
+ enum boot_device src = BOOT_DEVICE_NONE;
+ uint32_t porsr1;
+ uint32_t rcw_src;
+
+ porsr1 = read_reg_porsr1();
+
+ rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT;
+ switch (rcw_src) {
+ case FLEXSPI_NOR:
+ src = BOOT_DEVICE_FLEXSPI_NOR;
+ INFO("RCW BOOT SRC is FLEXSPI NOR\n");
+ break;
+ case FLEXSPI_NAND2K_VAL:
+ case FLEXSPI_NAND4K_VAL:
+ INFO("RCW BOOT SRC is FLEXSPI NAND\n");
+ src = BOOT_DEVICE_FLEXSPI_NAND;
+ break;
+ case SDHC1_VAL:
+ src = BOOT_DEVICE_EMMC;
+ INFO("RCW BOOT SRC is SD\n");
+ break;
+ case SDHC2_VAL:
+ src = BOOT_DEVICE_SDHC2_EMMC;
+ INFO("RCW BOOT SRC is EMMC\n");
+ break;
+ default:
+ break;
+ }
+
+ return src;
+}
+
+/*
+ * This function sets up access permissions on memory regions
+ ****************************************************************************/
+void soc_mem_access(void)
+{
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+ struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION];
+ int dram_idx = 0;
+ /* index 0 is reserved for region-0 */
+ int index = 1;
+
+ for (dram_idx = 0; dram_idx < info_dram_regions->num_dram_regions;
+ dram_idx++) {
+ if (info_dram_regions->region[dram_idx].size == 0) {
+ ERROR("DDR init failure, or");
+ ERROR("DRAM regions not populated correctly.\n");
+ break;
+ }
+
+ index = populate_tzc400_reg_list(tzc400_reg_list,
+ dram_idx, index,
+ info_dram_regions->region[dram_idx].addr,
+ info_dram_regions->region[dram_idx].size,
+ NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE);
+ }
+
+ mem_access_setup(NXP_TZC_ADDR, index, tzc400_reg_list);
+}
+
+#else
+
+static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2];
+/*
+ * This function dynamically constructs the topology according to
+ * SoC Flavor and returns it.
+ */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+ unsigned int i;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ /*
+ * The highest level is the system level. The next level is constituted
+ * by clusters and then cores in clusters.
+ */
+ _power_domain_tree_desc[0] = 1;
+ _power_domain_tree_desc[1] = num_clusters;
+
+ for (i = 0; i < _power_domain_tree_desc[1]; i++)
+ _power_domain_tree_desc[i + 2] = cores_per_cluster;
+
+ return _power_domain_tree_desc;
+}
+
+/*
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ */
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ return num_clusters;
+}
+
+void soc_early_platform_setup2(void)
+{
+ dcfg_init(&dcfg_init_data);
+ /* Initialize system level generic timer for Socs */
+ delay_timer_init(NXP_TIMER_ADDR);
+
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+}
+
+void soc_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ static uintptr_t target_mask_array[PLATFORM_CORE_COUNT];
+ static interrupt_prop_t ls_interrupt_props[] = {
+ PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0)
+ };
+
+ plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR,
+ PLATFORM_CORE_COUNT,
+ ls_interrupt_props,
+ ARRAY_SIZE(ls_interrupt_props),
+ target_mask_array,
+ plat_core_pos);
+
+ plat_ls_gic_init();
+ enable_init_timer();
+}
+
+/* This function initializes the soc from the BL31 module */
+void soc_init(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+
+ /* Low-level init of the soc */
+ soc_init_lowlevel();
+ _init_global_data();
+ soc_init_percpu();
+ _initialize_psci();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+ /* Enable Interconnect coherency for the primary CPU's cluster. */
+ plat_ls_interconnect_enter_coherency(num_clusters);
+
+ /* Set platform security policies */
+ _set_platform_security();
+
+ /* Init SEC Engine which will be used by SiP */
+ if (is_sec_enabled()) {
+ sec_init(NXP_CAAM_ADDR);
+ } else {
+ INFO("SEC is disabled.\n");
+ }
+}
+
+#ifdef NXP_WDOG_RESTART
+static uint64_t wdog_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint8_t data = WDOG_RESET_FLAG;
+
+ wr_nv_app_data(WDT_RESET_FLAG_OFFSET,
+ (uint8_t *)&data, sizeof(data));
+
+ mmio_write_32(NXP_RST_ADDR + RSTCNTL_OFFSET, SW_RST_REQ_INIT);
+
+ return 0;
+}
+#endif
+
+void soc_runtime_setup(void)
+{
+#ifdef NXP_WDOG_RESTART
+ request_intr_type_el3(BL31_NS_WDOG_WS1, wdog_interrupt_handler);
+#endif
+}
+
+/* This function returns the total number of cores in the SoC. */
+unsigned int get_tot_num_cores(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ return (num_clusters * cores_per_cluster);
+}
+
+/* This function returns the PMU IDLE Cluster mask. */
+unsigned int get_pmu_idle_cluster_mask(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ return ((1 << num_clusters) - 2);
+}
+
+/* This function returns the PMU Flush Cluster mask. */
+unsigned int get_pmu_flush_cluster_mask(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ return ((1 << num_clusters) - 2);
+}
+
+/* This function returns the PMU idle core mask. */
+unsigned int get_pmu_idle_core_mask(void)
+{
+ return ((1 << get_tot_num_cores()) - 2);
+}
+
+/* Function to return the SoC SYS CLK */
+unsigned int get_sys_clk(void)
+{
+ return NXP_SYSCLK_FREQ;
+}
+#endif
diff --git a/plat/nxp/soc-ls1028a/soc.def b/plat/nxp/soc-ls1028a/soc.def
new file mode 100644
index 0000000..c23c1bb
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/soc.def
@@ -0,0 +1,97 @@
+#
+# Copyright 2018-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# This file contains the basic architecture definitions that drive the build
+#
+# -----------------------------------------------------------------------------
+
+CORE_TYPE := a72
+
+CACHE_LINE := 6
+
+# Set to GIC400 or GIC500
+GIC := GIC500
+
+# Set to CCI400 or CCN504 or CCN508
+INTERCONNECT := CCI400
+
+# Layerscape chassis level - set to 3=LSCH3 or 2=LSCH2
+CHASSIS := 3_2
+
+# TZC used is TZC380 or TZC400
+TZC_ID := TZC400
+
+# CONSOLE is NS16550 or PL011
+CONSOLE := NS16550
+
+# DDR PHY generation to be used
+PLAT_DDR_PHY := PHY_GEN1
+
+PHYS_SYS := 64
+
+# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def
+# Input to CST create_hdr_esbc tool
+CSF_HDR_SZ := 0x3000
+
+# In IMAGE_BL2, compile time flag for handling Cache coherency
+# with CAAM for BL2 running from OCRAM
+SEC_MEM_NON_COHERENT := yes
+
+# OCRAM MAP for BL2
+# Before BL2
+# 0x18000000 - 0x18009fff -> Used by ROM code
+# 0x1800a000 - 0x1800dfff -> CSF header for BL2
+# For FlexSFlexSPI boot
+# 0x1800e000 - 0x18040000 -> Reserved for BL2 binary
+# For SD boot
+# 0x1800e000 - 0x18030000 -> Reserved for BL2 binary
+# 0x18030000 - 0x18040000 -> Reserved for SD buffer
+OCRAM_START_ADDR := 0x18000000
+OCRAM_SIZE := 0x40000
+
+# Area of OCRAM reserved by ROM code
+NXP_ROM_RSVD := 0xa000
+
+# Location of BL2 on OCRAM
+BL2_BASE_ADDR := $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) + $(CSF_HDR_SZ) )))
+
+# Covert to HEX to be used by create_pbl.mk
+BL2_BASE := $(shell echo "0x"$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc))
+
+# BL2_HDR_LOC is at (BL2_BASE + NXP_ROM_RSVD)
+# This value BL2_HDR_LOC + CSF_HDR_SZ should not
+# overalp with BL2_BASE
+# Input to CST create_hdr_isbc tool
+BL2_HDR_LOC := 0x1800A000
+
+# SoC ERRATAS to be enabled
+ERRATA_SOC_A008850 := 1
+
+ERRATA_DDR_A009803 := 1
+ERRATA_DDR_A009942 := 1
+ERRATA_DDR_A010165 := 1
+
+# Enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC := 1
+
+# Define Endianness of each module
+NXP_GUR_ENDIANNESS := LE
+NXP_DDR_ENDIANNESS := LE
+NXP_SEC_ENDIANNESS := LE
+NXP_SFP_ENDIANNESS := LE
+NXP_SNVS_ENDIANNESS := LE
+NXP_ESDHC_ENDIANNESS := LE
+NXP_QSPI_ENDIANNESS := LE
+NXP_FSPI_ENDIANNESS := LE
+NXP_SCFG_ENDIANNESS := LE
+NXP_GPIO_ENDIANNESS := LE
+
+NXP_SFP_VER := 3_4
+
+# OCRAM ECC Enabled
+OCRAM_ECC_EN := yes
diff --git a/plat/nxp/soc-ls1028a/soc.mk b/plat/nxp/soc-ls1028a/soc.mk
new file mode 100644
index 0000000..92d8e98
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/soc.mk
@@ -0,0 +1,113 @@
+#
+# Copyright 2020-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SoC-specific build parameters
+SOC := ls1028a
+PLAT_PATH := plat/nxp
+PLAT_COMMON_PATH := plat/nxp/common
+PLAT_DRIVERS_PATH := drivers/nxp
+PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC}
+BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD}
+
+# Get SoC-specific definitions
+include ${PLAT_SOC_PATH}/soc.def
+include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk
+include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2))
+SECURE_BOOT := yes
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM))
+
+$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+
+# Selecting PSCI & SIP_SVC support
+$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31))
+
+PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\
+ -I${BOARD_PATH}\
+ -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
+ -I${PLAT_SOC_PATH}/include\
+ -I${PLAT_COMMON_PATH}/soc_errata
+
+ifeq (${SECURE_BOOT},yes)
+include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
+endif
+
+ifeq ($(WARM_BOOT),yes)
+include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk
+endif
+
+ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes)
+include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk
+endif
+
+ifeq (${PSCI_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/psci/psci.mk
+endif
+
+ifeq (${SIPSVC_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk
+endif
+
+ifeq (${DDR_FIP_IO_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/fip_handler/ddr_fip/ddr_fip_io.mk
+endif
+
+# For fuse-fip & fuse-programming
+ifeq (${FUSE_PROG}, 1)
+include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk
+endif
+
+ifeq (${IMG_LOADR_NEEDED},yes)
+include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk
+endif
+
+# Adding source files for the above selected drivers.
+include ${PLAT_DRIVERS_PATH}/drivers.mk
+
+# Adding SoC specific files
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
+
+PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\
+ ${WARM_RST_INCLUDES}
+
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\
+ ${WARM_RST_BL31_SOURCES}\
+ ${PSCI_SOURCES}\
+ ${SIPSVC_SOURCES}\
+ ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S
+
+PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\
+ ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\
+ ${NV_STORAGE_SOURCES}\
+ ${WARM_RST_BL_COMM_SOURCES}\
+ ${PLAT_SOC_PATH}/soc.c
+
+ifeq (${TEST_BL31}, 1)
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S \
+ ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S
+endif
+
+BL2_SOURCES += ${DDR_CNTLR_SOURCES}\
+ ${TBBR_SOURCES}\
+ ${FUSE_SOURCES}
+
+# Adding TFA setup files
+include ${PLAT_PATH}/common/setup/common.mk
diff --git a/plat/nxp/soc-ls1043a/aarch64/ls1043a.S b/plat/nxp/soc-ls1043a/aarch64/ls1043a.S
new file mode 100644
index 0000000..a1baf79
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/aarch64/ls1043a.S
@@ -0,0 +1,1637 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <cortex_a53.h>
+#include <dcfg_lsch2.h>
+#include <plat_gic.h>
+#include <scfg.h>
+
+#include <bl31_data.h>
+#include <plat_psci.h>
+#include <platform_def.h>
+
+/* the BASE address for these offsets is AUX_01_DATA in the */
+/* bootcore's psci data region */
+#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */
+#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */
+#define CPUACTLR_DATA_OFFSET 0x10 /* references AUX_03_DATA */
+/* the BASE address for these offsets is AUX_04_DATA in the */
+/* bootcore's psci data region */
+#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */
+#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */
+
+#define DAIF_DATA AUX_06_DATA /* references AUX_06_DATA */
+
+#define IPSTPACK_RETRY_CNT 0x10000
+#define DDR_SLEEP_RETRY_CNT 0x10000
+#define CPUACTLR_EL1 S3_1_C15_C2_0
+#define DDR_SDRAM_CFG_2_FRCSR 0x80000000
+#define DDR_SDRAM_CFG_2_OFFSET 0x114
+#define DDR_TIMING_CFG_4_OFFSET 0x160
+#define DDR_CNTRL_BASE_ADDR 0x01080000
+
+#define DLL_LOCK_MASK 0x3
+#define DLL_LOCK_VALUE 0x2
+
+#define ERROR_DDR_SLEEP -1
+#define ERROR_DDR_WAKE -2
+#define ERROR_NO_QUIESCE -3
+
+#define CORE_RESTARTABLE 0
+#define CORE_NOT_RESTARTABLE 1
+
+#define RESET_RETRY_CNT 800
+
+.global soc_init_lowlevel
+.global soc_init_percpu
+.global _soc_core_release
+.global _soc_core_restart
+.global _soc_ck_disabled
+.global _soc_sys_reset
+.global _soc_sys_off
+.global _getGICD_BaseAddr
+.global _getGICC_BaseAddr
+.global _soc_set_start_addr
+.global _soc_core_prep_off
+.global _soc_core_entr_off
+.global _soc_core_exit_off
+.global _soc_core_prep_stdby
+.global _soc_core_entr_stdby
+.global _soc_core_exit_stdby
+.global _soc_core_prep_pwrdn
+.global _soc_core_entr_pwrdn
+.global _soc_core_exit_pwrdn
+.global _soc_clstr_prep_stdby
+.global _soc_clstr_exit_stdby
+.global _soc_clstr_prep_pwrdn
+.global _soc_clstr_exit_pwrdn
+.global _soc_sys_prep_stdby
+.global _soc_sys_exit_stdby
+.global _soc_sys_prep_pwrdn
+.global _soc_sys_pwrdn_wfi
+.global _soc_sys_exit_pwrdn
+
+/*
+ * This function initialize the soc.
+ * in: void
+ * out: void
+ */
+func soc_init_lowlevel
+ ret
+endfunc soc_init_lowlevel
+
+/*
+ * void soc_init_percpu(void)
+ * this function performs any soc-specific initialization that is needed on
+ * a per-core basis
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+func soc_init_percpu
+ mov x3, x30
+
+ bl plat_my_core_mask
+ mov x2, x0
+
+ /* see if this core is marked for prefetch disable */
+ mov x0, #PREFETCH_DIS_OFFSET
+ bl _get_global_data /* 0-1 */
+ tst x0, x2
+ b.eq 1f
+ bl _disable_ldstr_pfetch_A53 /* 0 */
+1:
+ mov x30, x3
+ ret
+endfunc soc_init_percpu
+
+/*
+ * part of CPU_ON
+ * this function releases a secondary core from reset
+ * in: x0 = core_mask_lsb
+ * out: none
+ * uses: x0, x1, x2, x3
+ */
+_soc_core_release:
+
+#if (TEST_BL31)
+ mov w2, w0
+ CoreMaskMsb w2, w3
+ /* x2 = core mask msb */
+#else
+ mov x2, x0
+#endif
+ /* write COREBCR */
+ ldr x1, =NXP_SCFG_ADDR
+ rev w3, w2
+ str w3, [x1, #SCFG_COREBCR_OFFSET]
+ isb
+
+ /* read-modify-write BRR */
+ mov x1, #NXP_DCFG_ADDR
+ ldr w2, [x1, #DCFG_BRR_OFFSET]
+ rev w3, w2
+ orr w3, w3, w0
+ rev w2, w3
+ str w2, [x1, #DCFG_BRR_OFFSET]
+ isb
+
+ /* send event */
+ sev
+ isb
+ ret
+
+
+/*
+ * part of CPU_ON
+ * this function restarts a core shutdown via _soc_core_entr_off
+ * in: x0 = core mask lsb (of the target cpu)
+ * out: x0 == 0, on success
+ * x0 != 0, on failure
+ * uses x0 ~ x5
+ */
+_soc_core_restart:
+ mov x5, x30
+ mov x3, x0
+
+ /* x3 = core mask lsb */
+ bl _getGICD_BaseAddr
+ mov x4, x0
+
+ /* x4 = GICD_BASE_ADDR */
+ /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */
+ ldr w1, [x4, #GICD_CTLR_OFFSET]
+ orr w1, w1, #GICD_CTLR_EN_GRP0
+ str w1, [x4, #GICD_CTLR_OFFSET]
+ dsb sy
+ isb
+
+ /*
+ * fire SGI by writing to GICD_SGIR the following values:
+ * [25:24] = 0x0 (forward interrupt to the CPU interfaces specified in CPUTargetList field)
+ * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu)
+ * [15] = 0 (forward SGI only if it is configured as group 0 interrupt)
+ * [3:0] = 0xF (interrupt ID = 15)
+ */
+ lsl w1, w3, #16
+ orr w1, w1, #0xF
+ str w1, [x4, #GICD_SGIR_OFFSET]
+ dsb sy
+ isb
+
+ /* load '0' on success */
+ mov x0, xzr
+
+ mov x30, x5
+ ret
+
+/*
+ * this function determines if a core is disabled via COREDISR
+ * in: w0 = core_mask_lsb
+ * out: w0 = 0, core not disabled
+ * w0 != 0, core disabled
+ * uses x0, x1, x2
+ */
+_soc_ck_disabled:
+
+ /* get base addr of dcfg block */
+ ldr x1, =NXP_DCFG_ADDR
+
+ /* read COREDISR */
+ ldr w1, [x1, #DCFG_COREDISR_OFFSET]
+ rev w2, w1
+
+ /* test core bit */
+ and w0, w2, w0
+ ret
+
+/*
+ * this function resets the system via SoC-specific methods
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+_soc_sys_reset:
+
+ ldr x2, =NXP_DCFG_ADDR
+
+ /* make sure the mask is cleared in the reset request mask register */
+ mov w1, wzr
+ str w1, [x2, #DCFG_RSTRQMR1_OFFSET]
+
+ /* x2 = NXP_DCFG_ADDR */
+
+ /* set the reset request */
+ ldr w1, =RSTCR_RESET_REQ
+ ldr x3, =DCFG_RSTCR_OFFSET
+ rev w0, w1
+ str w0, [x2, x3]
+
+ /* x2 = NXP_DCFG_ADDR */
+ /* x3 = DCFG_RSTCR_OFFSET */
+
+ /* just in case this address range is mapped as cacheable,
+ * flush the write out of the dcaches */
+ add x3, x2, x3
+ dc cvac, x3
+ dsb st
+ isb
+
+ /* Note: this function does not return */
+1:
+ wfi
+ b 1b
+
+
+/*
+ * part of SYSTEM_OFF
+ * this function turns off the SoC clocks
+ * Note: this function is not intended to return, and the only allowable
+ * recovery is POR
+ * in: none
+ * out: none
+ * uses x0 ~ x8
+ */
+_soc_sys_off:
+
+ /* mask interrupts at the core */
+ mrs x1, DAIF
+ mov x0, #DAIF_SET_MASK
+ orr x0, x1, x0
+ msr DAIF, x0
+
+ /* disable icache, dcache, mmu @ EL1 */
+ mov x1, #SCTLR_I_C_M_MASK
+ mrs x0, sctlr_el1
+ bic x0, x0, x1
+ msr sctlr_el1, x0
+
+ /* disable dcache for EL3 */
+ mrs x1, SCTLR_EL3
+ bic x1, x1, #SCTLR_C_MASK
+ /* make sure icache is enabled */
+ orr x1, x1, #SCTLR_I_MASK
+ msr SCTLR_EL3, x1
+ isb
+
+ /* set WFIL2_EN in SCFG_COREPMCR */
+ ldr x0, =SCFG_COREPMCR_OFFSET
+ ldr x1, =COREPMCR_WFIL2
+ bl write_reg_scfg
+
+ /* set OVRD_EN in RCPM2_POWMGTDCR */
+ ldr x0, =RCPM2_POWMGTDCR_OFFSET
+ ldr x1, =POWMGTDCR_OVRD_EN
+ bl write_reg_rcpm2
+
+ /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */
+ ldr x0, =RCPM_IPPDEXPCR0_OFFSET
+ bl read_reg_rcpm
+ mov x7, x0
+
+ /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */
+ mov x5, xzr
+ ldr x6, =IPPDEXPCR_MASK2
+ and x6, x6, x7
+ cbz x6, 1f
+
+ /* x5 = override mask
+ * x6 = IPPDEXPCR bits for DEVDISR5
+ * x7 = IPPDEXPCR */
+
+ /* get the overrides */
+ orr x4, x5, #DEVDISR5_I2C_1
+ tst x6, #IPPDEXPCR_I2C1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_LPUART1
+ tst x6, #IPPDEXPCR_LPUART1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_FLX_TMR
+ tst x6, #IPPDEXPCR_FLX_TMR1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_OCRAM1
+ tst x6, #IPPDEXPCR_OCRAM1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_GPIO
+ tst x6, #IPPDEXPCR_GPIO1
+ csel x5, x5, x4, EQ
+1:
+ /* store the DEVDISR5 override mask */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ str w5, [x2, #DEVDISR5_MASK_OFFSET]
+
+ /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */
+ mov x5, xzr
+ ldr x6, =IPPDEXPCR_MASK1
+ and x6, x6, x7
+ cbz x6, 2f
+
+ /* x5 = override mask */
+ /* x6 = IPPDEXPCR bits for DEVDISR2 */
+
+ /* get the overrides */
+ orr x4, x5, #DEVDISR2_FMAN1_MAC1
+ tst x6, #IPPDEXPCR_MAC1_1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC2
+ tst x6, #IPPDEXPCR_MAC1_2
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC3
+ tst x6, #IPPDEXPCR_MAC1_3
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC4
+ tst x6, #IPPDEXPCR_MAC1_4
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC5
+ tst x6, #IPPDEXPCR_MAC1_5
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC6
+ tst x6, #IPPDEXPCR_MAC1_6
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC9
+ tst x6, #IPPDEXPCR_MAC1_9
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1
+ tst x6, #IPPDEXPCR_FM1
+ csel x5, x5, x4, EQ
+
+2:
+ /* store the DEVDISR2 override mask */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ str w5, [x2, #DEVDISR2_MASK_OFFSET]
+
+ /* x5 = DEVDISR2 override mask */
+
+ /* write IPSTPCR0 - no overrides */
+ ldr x0, =RCPM2_IPSTPCR0_OFFSET
+ ldr x1, =IPSTPCR0_VALUE
+ bl write_reg_rcpm2
+
+ /* x5 = DEVDISR2 override mask */
+
+ /* write IPSTPCR1 - overrides possible */
+ ldr x0, =RCPM2_IPSTPCR1_OFFSET
+ ldr x1, =IPSTPCR1_VALUE
+ bic x1, x1, x5
+ bl write_reg_rcpm2
+
+ /* write IPSTPCR2 - no overrides */
+ ldr x0, =RCPM2_IPSTPCR2_OFFSET
+ ldr x1, =IPSTPCR2_VALUE
+ bl write_reg_rcpm2
+
+ /* write IPSTPCR3 - no overrides */
+ ldr x0, =RCPM2_IPSTPCR3_OFFSET
+ ldr x1, =IPSTPCR3_VALUE
+ bl write_reg_rcpm2
+
+ /* write IPSTPCR4 - overrides possible */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ ldr w6, [x2, #DEVDISR5_MASK_OFFSET]
+ ldr x0, =RCPM2_IPSTPCR4_OFFSET
+ ldr x1, =IPSTPCR4_VALUE
+ bic x1, x1, x6
+ bl write_reg_rcpm2
+
+ /* x5 = DEVDISR2 override mask */
+ /* x6 = DEVDISR5 override mask */
+
+ /* poll on IPSTPACK0 */
+ ldr x3, =RCPM2_IPSTPACKR0_OFFSET
+ ldr x4, =IPSTPCR0_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+3:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 14f
+ sub x7, x7, #1
+ cbnz x7, 3b
+
+14:
+ /* poll on IPSTPACK1 */
+ ldr x3, =IPSTPCR1_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+ bic x4, x3, x5
+ ldr x3, =RCPM2_IPSTPACKR1_OFFSET
+4:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 15f
+ sub x7, x7, #1
+ cbnz x7, 4b
+
+15:
+ /* poll on IPSTPACK2 */
+ ldr x3, =RCPM2_IPSTPACKR2_OFFSET
+ ldr x4, =IPSTPCR2_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+5:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 16f
+ sub x7, x7, #1
+ cbnz x7, 5b
+
+16:
+ /* poll on IPSTPACK3 */
+ ldr x3, =RCPM2_IPSTPACKR3_OFFSET
+ ldr x4, =IPSTPCR3_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+6:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 17f
+ sub x7, x7, #1
+ cbnz x7, 6b
+
+17:
+ /* poll on IPSTPACK4 */
+ ldr x3, =IPSTPCR4_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+ bic x4, x3, x6
+ ldr x3, =RCPM2_IPSTPACKR4_OFFSET
+7:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 18f
+ sub x7, x7, #1
+ cbnz x7, 7b
+
+18:
+ ldr x7, =BC_PSCI_BASE
+ add x7, x7, #AUX_01_DATA
+
+ /* x5 = DEVDISR2 override mask
+ * x6 = DEVDISR5 override mask
+ * x7 = [soc_data_area] */
+
+ /* DEVDISR1 - load new value */
+ mov x0, #DCFG_DEVDISR1_OFFSET
+ bl read_reg_dcfg
+ mov x0, #DCFG_DEVDISR1_OFFSET
+ ldr x1, =DEVDISR1_VALUE
+ bl write_reg_dcfg
+
+ /* DEVDISR2 - load new value */
+ mov x0, #DCFG_DEVDISR2_OFFSET
+ bl read_reg_dcfg
+ mov x0, #DCFG_DEVDISR2_OFFSET
+ ldr x1, =DEVDISR2_VALUE
+ bic x1, x1, x5
+ bl write_reg_dcfg
+
+ /* x6 = DEVDISR5 override mask */
+ /* x7 = [soc_data_area] */
+
+ /* DEVDISR3 - load new value */
+ mov x0, #DCFG_DEVDISR3_OFFSET
+ bl read_reg_dcfg
+ mov x0, #DCFG_DEVDISR3_OFFSET
+ ldr x1, =DEVDISR3_VALUE
+ bl write_reg_dcfg
+
+ /* DEVDISR4 - load new value */
+ mov x0, #DCFG_DEVDISR4_OFFSET
+ bl read_reg_dcfg
+ mov x0, #DCFG_DEVDISR4_OFFSET
+ ldr x1, =DEVDISR4_VALUE
+ bl write_reg_dcfg
+
+ /* DEVDISR5 - load new value */
+ mov x0, #DCFG_DEVDISR5_OFFSET
+ bl read_reg_dcfg
+ mov x0, #DCFG_DEVDISR5_OFFSET
+ ldr x1, =DEVDISR5_VALUE
+ bic x1, x1, x6
+ bl write_reg_dcfg
+
+ /* x7 = [soc_data_area] */
+
+ /* disable data prefetch */
+ mrs x0, CPUACTLR_EL1
+ bic x0, x0, #CPUACTLR_L1PCTL_MASK
+ msr CPUACTLR_EL1, x0
+
+ /* x6 = DEVDISR5 override mask */
+
+ /* setup registers for cache-only execution */
+ ldr x5, =IPSTPCR4_VALUE
+ bic x5, x5, x6
+ mov x6, #DDR_CNTRL_BASE_ADDR
+ mov x7, #DCSR_RCPM2_BASE
+ mov x8, #NXP_DCFG_ADDR
+ dsb sy
+ isb
+
+ /* set the DLL_LOCK cycle count */
+ ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
+ rev w2, w1
+ bic w2, w2, #DLL_LOCK_MASK
+ orr w2, w2, #DLL_LOCK_VALUE
+ rev w1, w2
+ str w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
+
+ /* x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
+ * x6 = DDR_CNTRL_BASE_ADDR
+ * x7 = DCSR_RCPM2_BASE
+ * x8 = NXP_DCFG_ADDR */
+
+ /* enter the cache-only sequence - there is no return */
+ b final_shutdown
+
+
+/*
+ * part of CPU_OFF
+ * this function programs SoC & GIC registers in preparation for shutting down
+ * the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0 ~ x7
+ */
+_soc_core_prep_off:
+ mov x7, x30
+ mov x6, x0
+
+ /* make sure the smpen bit is set */
+ mrs x2, CORTEX_A53_ECTLR_EL1
+ orr x2, x2, #CPUECTLR_SMPEN_MASK
+ msr CORTEX_A53_ECTLR_EL1, x2
+ isb
+
+ /* configure the cpu interface */
+
+ /* disable signaling of ints */
+ bl _getGICC_BaseAddr // 0-1
+ mov x4, x0
+
+ ldr w3, [x4, #GICC_CTLR_OFFSET]
+ bic w3, w3, #GICC_CTLR_EN_GRP0
+ bic w3, w3, #GICC_CTLR_EN_GRP1
+ str w3, [x4, #GICC_CTLR_OFFSET]
+ dsb sy
+ isb
+
+ /*
+ * x3 = GICC_CTRL
+ * x4 = GICC_BASE_ADDR
+ * x6 = core mask
+ */
+
+ /* set the priority filter */
+ ldr w2, [x4, #GICC_PMR_OFFSET]
+ orr w2, w2, #GICC_PMR_FILTER
+ str w2, [x4, #GICC_PMR_OFFSET]
+
+ /* setup GICC_CTLR */
+ bic w3, w3, #GICC_CTLR_ACKCTL_MASK
+ orr w3, w3, #GICC_CTLR_FIQ_EN_MASK
+ orr w3, w3, #GICC_CTLR_EOImodeS_MASK
+ orr w3, w3, #GICC_CTLR_CBPR_MASK
+ str w3, [x4, #GICC_CTLR_OFFSET]
+
+ /* x3 = GICC_CTRL */
+ /* x4 = GICC_BASE_ADDR */
+
+ /* setup the banked-per-core GICD registers */
+ bl _getGICD_BaseAddr
+
+ /*
+ * x0 = GICD_BASE_ADDR
+ * x3 = GICC_CTRL
+ * x4 = GICC_BASE_ADDR
+ * x6 = core mask
+ */
+
+ /* define SGI15 as Grp0 */
+ ldr w2, [x0, #GICD_IGROUPR0_OFFSET]
+ bic w2, w2, #GICD_IGROUP0_SGI15
+ str w2, [x0, #GICD_IGROUPR0_OFFSET]
+
+ /* set priority of SGI 15 to highest... */
+ ldr w2, [x0, #GICD_IPRIORITYR3_OFFSET]
+ bic w2, w2, #GICD_IPRIORITY_SGI15_MASK
+ str w2, [x0, #GICD_IPRIORITYR3_OFFSET]
+
+ /* enable SGI 15 */
+ ldr w2, [x0, #GICD_ISENABLER0_OFFSET]
+ orr w2, w2, #GICD_ISENABLE0_SGI15
+ str w2, [x0, #GICD_ISENABLER0_OFFSET]
+
+ /* enable the cpu interface */
+ orr w3, w3, #GICC_CTLR_EN_GRP0
+ str w3, [x4, #GICC_CTLR_OFFSET]
+
+ /* x0 = GICD_BASE_ADDR
+ * x6 = core mask */
+
+ /* clear any pending SGIs */
+ add x0, x0, #GICD_CPENDSGIR3_OFFSET
+ ldr x2, =GICD_CPENDSGIR_CLR_MASK
+ str w2, [x0]
+
+ dsb sy
+ isb
+ mov x30, x7
+ ret
+
+/*
+ * part of CPU_OFF
+ * this function performs the final steps to shutdown the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0 ~ x5
+ */
+_soc_core_entr_off:
+ mov x5, x30
+ mov x4, x0
+
+ bl _getGICD_BaseAddr
+ mov x3, x0
+
+ /* x3 = GICD_BASE_ADDR */
+ /* x4 = core mask (lsb) */
+
+3:
+ /* enter low-power state by executing wfi */
+ wfi
+
+ /* x3 = GICD_BASE_ADDR */
+ /* x4 = core mask (lsb) */
+
+ /* see if we got hit by SGI 15 */
+ add x0, x3, #GICD_SPENDSGIR3_OFFSET
+ ldr w2, [x0]
+ and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK
+ cbz w2, 4f
+
+ /* clear the pending SGI */
+ ldr x2, =GICD_CPENDSGIR_CLR_MASK
+ add x0, x3, #GICD_CPENDSGIR3_OFFSET
+ str w2, [x0]
+4:
+ /* check if core has been turned on */
+ mov x0, x4
+ bl _getCoreState
+
+ /* x0 = core state */
+ cmp x0, #CORE_WAKEUP
+ b.ne 3b
+
+ /* if we get here, then we have exited the wfi */
+ dsb sy
+ isb
+ mov x30, x5
+ ret
+
+/*
+ * part of CPU_OFF
+ * this function starts the process of starting a core back up
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0 ~ x5
+ */
+_soc_core_exit_off:
+ mov x5, x30
+ mov x4, x0
+
+ /* x4 = core mask */
+
+ bl _getGICC_BaseAddr
+ mov x2, x0
+
+ /* read GICC_IAR */
+ ldr w0, [x2, #GICC_IAR_OFFSET]
+
+ /* write GICC_EIOR - signal end-of-interrupt */
+ str w0, [x2, #GICC_EOIR_OFFSET]
+
+ /* write GICC_DIR - disable interrupt */
+ str w0, [x2, #GICC_DIR_OFFSET]
+
+ /* x2 = GICC_BASE_ADDR */
+
+ /* disable signaling of grp0 ints */
+ ldr w1, [x2, #GICC_CTLR_OFFSET]
+ bic w1, w1, #GICC_CTLR_EN_GRP0
+ str w1, [x2, #GICC_CTLR_OFFSET]
+
+ dsb sy
+ isb
+ mov x30, x5
+ ret
+
+/*
+ * this function loads a 64-bit execution address of the core in the soc registers
+ * BOOTLOCPTRL/H
+ * in: x0, 64-bit address to write to BOOTLOCPTRL/H
+ * uses x0, x1, x2, x3
+ */
+_soc_set_start_addr:
+ /* get the 64-bit base address of the scfg block */
+ ldr x2, =NXP_SCFG_ADDR
+
+ /* write the 32-bit BOOTLOCPTRL register (offset 0x604 in the scfg block) */
+ mov x1, x0
+ rev w3, w1
+ str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET]
+
+ /* write the 32-bit BOOTLOCPTRH register (offset 0x600 in the scfg block) */
+ lsr x1, x0, #32
+ rev w3, w1
+ str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET]
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function puts the calling core into standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_stdby:
+ dsb sy
+ isb
+ wfi
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_core_prep_stdby:
+ /* clear CORTEX_A53_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A53_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A53_ECTLR_EL1, x1
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_core_exit_stdby:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_core_prep_pwrdn:
+ /* make sure the smp bit is set */
+ mrs x1, CORTEX_A53_ECTLR_EL1
+ orr x1, x1, #CPUECTLR_SMPEN_MASK
+ msr CORTEX_A53_ECTLR_EL1, x1
+ isb
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function puts the calling core into a power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_pwrdn:
+ dsb sy
+ isb
+ wfi
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_core_exit_pwrdn:
+ ret
+
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_clstr_prep_stdby:
+ /* clear CORTEX_A53_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A53_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A53_ECTLR_EL1, x1
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_clstr_exit_stdby:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_clstr_prep_pwrdn:
+ /* make sure the smp bit is set */
+ mrs x1, CORTEX_A53_ECTLR_EL1
+ orr x1, x1, #CPUECTLR_SMPEN_MASK
+ msr CORTEX_A53_ECTLR_EL1, x1
+ isb
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_clstr_exit_pwrdn:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_prep_stdby:
+ /* clear CORTEX_A53_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A53_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A53_ECTLR_EL1, x1
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_sys_exit_stdby:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to
+ * suspend-to-power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4
+ */
+_soc_sys_prep_pwrdn:
+ mov x4, x30
+ /* make sure the smp bit is set */
+ mrs x1, CORTEX_A53_ECTLR_EL1
+ orr x1, x1, #CPUECTLR_SMPEN_MASK
+ msr CORTEX_A53_ECTLR_EL1, x1
+ isb
+
+ /* set WFIL2_EN in SCFG_COREPMCR */
+ ldr x0, =SCFG_COREPMCR_OFFSET
+ ldr x1, =COREPMCR_WFIL2
+ bl write_reg_scfg // 0-3
+
+ /* set OVRD_EN in RCPM2_POWMGTDCR */
+ ldr x0, =RCPM2_POWMGTDCR_OFFSET
+ ldr x1, =POWMGTDCR_OVRD_EN
+ bl write_reg_rcpm2 // 0-3
+
+ mov x30, x4
+ ret
+/*
+ * part of CPU_SUSPEND
+ * this function puts the calling core, and potentially the soc, into a
+ * low-power state
+ * in: x0 = core mask lsb
+ * out: x0 = 0, success
+ * x0 < 0, failure
+ * uses x0 ~ x9
+ */
+_soc_sys_pwrdn_wfi:
+ mov x18, x30
+
+ /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */
+ ldr x0, =RCPM_IPPDEXPCR0_OFFSET
+ bl read_reg_rcpm
+ mov x7, x0
+
+ /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */
+ mov x5, xzr
+ ldr x6, =IPPDEXPCR_MASK2
+ and x6, x6, x7
+ cbz x6, 1f
+
+ /* x5 = override mask
+ * x6 = IPPDEXPCR bits for DEVDISR5
+ * x7 = IPPDEXPCR */
+
+ /* get the overrides */
+ orr x4, x5, #DEVDISR5_I2C_1
+ tst x6, #IPPDEXPCR_I2C1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_LPUART1
+ tst x6, #IPPDEXPCR_LPUART1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_FLX_TMR
+ tst x6, #IPPDEXPCR_FLX_TMR1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_OCRAM1
+ tst x6, #IPPDEXPCR_OCRAM1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR5_GPIO
+ tst x6, #IPPDEXPCR_GPIO1
+ csel x5, x5, x4, EQ
+1:
+ /* store the DEVDISR5 override mask */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ str w5, [x2, #DEVDISR5_MASK_OFFSET]
+
+ /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */
+ mov x5, xzr
+ ldr x6, =IPPDEXPCR_MASK1
+ and x6, x6, x7
+ cbz x6, 2f
+
+ /* x5 = override mask */
+ /* x6 = IPPDEXPCR bits for DEVDISR2 */
+
+ /* get the overrides */
+ orr x4, x5, #DEVDISR2_FMAN1_MAC1
+ tst x6, #IPPDEXPCR_MAC1_1
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC2
+ tst x6, #IPPDEXPCR_MAC1_2
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC3
+ tst x6, #IPPDEXPCR_MAC1_3
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC4
+ tst x6, #IPPDEXPCR_MAC1_4
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC5
+ tst x6, #IPPDEXPCR_MAC1_5
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC6
+ tst x6, #IPPDEXPCR_MAC1_6
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1_MAC9
+ tst x6, #IPPDEXPCR_MAC1_9
+ csel x5, x5, x4, EQ
+
+ orr x4, x5, #DEVDISR2_FMAN1
+ tst x6, #IPPDEXPCR_FM1
+ csel x5, x5, x4, EQ
+
+2:
+ /* store the DEVDISR2 override mask */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ str w5, [x2, #DEVDISR2_MASK_OFFSET]
+
+ /* x5 = DEVDISR2 override mask */
+
+ /* write IPSTPCR0 - no overrides */
+ ldr x0, =RCPM2_IPSTPCR0_OFFSET
+ ldr x1, =IPSTPCR0_VALUE
+ bl write_reg_rcpm2
+
+ /* x5 = DEVDISR2 override mask */
+
+ /* write IPSTPCR1 - overrides possible */
+ ldr x0, =RCPM2_IPSTPCR1_OFFSET
+ ldr x1, =IPSTPCR1_VALUE
+ bic x1, x1, x5
+ bl write_reg_rcpm2
+
+ /* write IPSTPCR2 - no overrides */
+ ldr x0, =RCPM2_IPSTPCR2_OFFSET
+ ldr x1, =IPSTPCR2_VALUE
+ bl write_reg_rcpm2
+
+ /* write IPSTPCR3 - no overrides */
+ ldr x0, =RCPM2_IPSTPCR3_OFFSET
+ ldr x1, =IPSTPCR3_VALUE
+ bl write_reg_rcpm2
+
+ /* write IPSTPCR4 - overrides possible */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ ldr w6, [x2, #DEVDISR5_MASK_OFFSET]
+ ldr x0, =RCPM2_IPSTPCR4_OFFSET
+ ldr x1, =IPSTPCR4_VALUE
+ bic x1, x1, x6
+ bl write_reg_rcpm2
+
+ /* x5 = DEVDISR2 override mask */
+ /* x6 = DEVDISR5 override mask */
+
+ /* poll on IPSTPACK0 */
+ ldr x3, =RCPM2_IPSTPACKR0_OFFSET
+ ldr x4, =IPSTPCR0_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+3:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 14f
+ sub x7, x7, #1
+ cbnz x7, 3b
+
+14:
+ /* poll on IPSTPACK1 */
+ ldr x3, =IPSTPCR1_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+ bic x4, x3, x5
+ ldr x3, =RCPM2_IPSTPACKR1_OFFSET
+4:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 15f
+ sub x7, x7, #1
+ cbnz x7, 4b
+
+15:
+ /* poll on IPSTPACK2 */
+ ldr x3, =RCPM2_IPSTPACKR2_OFFSET
+ ldr x4, =IPSTPCR2_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+5:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 16f
+ sub x7, x7, #1
+ cbnz x7, 5b
+
+16:
+ /* poll on IPSTPACK3 */
+ ldr x3, =RCPM2_IPSTPACKR3_OFFSET
+ ldr x4, =IPSTPCR3_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+6:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 17f
+ sub x7, x7, #1
+ cbnz x7, 6b
+
+17:
+ /* poll on IPSTPACK4 */
+ ldr x3, =IPSTPCR4_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+ bic x4, x3, x6
+ ldr x3, =RCPM2_IPSTPACKR4_OFFSET
+7:
+ mov x0, x3
+ bl read_reg_rcpm2
+ cmp x0, x4
+ b.eq 18f
+ sub x7, x7, #1
+ cbnz x7, 7b
+
+18:
+ ldr x7, =BC_PSCI_BASE
+ add x7, x7, #AUX_01_DATA
+
+ /* x5 = DEVDISR2 override mask
+ * x6 = DEVDISR5 override mask
+ * x7 = [soc_data_area] */
+
+ /* save DEVDISR1 and load new value */
+ mov x0, #DCFG_DEVDISR1_OFFSET
+ bl read_reg_dcfg
+ mov w13, w0
+ mov x0, #DCFG_DEVDISR1_OFFSET
+ ldr x1, =DEVDISR1_VALUE
+ bl write_reg_dcfg
+
+ /* save DEVDISR2 and load new value */
+ mov x0, #DCFG_DEVDISR2_OFFSET
+ bl read_reg_dcfg
+ mov w14, w0
+ mov x0, #DCFG_DEVDISR2_OFFSET
+ ldr x1, =DEVDISR2_VALUE
+ bic x1, x1, x5
+ bl write_reg_dcfg
+
+ /* x6 = DEVDISR5 override mask */
+ /* x7 = [soc_data_area] */
+
+ /* save DEVDISR3 and load new value */
+ mov x0, #DCFG_DEVDISR3_OFFSET
+ bl read_reg_dcfg
+ mov w15, w0
+ mov x0, #DCFG_DEVDISR3_OFFSET
+ ldr x1, =DEVDISR3_VALUE
+ bl write_reg_dcfg
+
+ /* save DEVDISR4 and load new value */
+ mov x0, #DCFG_DEVDISR4_OFFSET
+ bl read_reg_dcfg
+ mov w16, w0
+ mov x0, #DCFG_DEVDISR4_OFFSET
+ ldr x1, =DEVDISR4_VALUE
+ bl write_reg_dcfg
+
+ /* save DEVDISR5 and load new value */
+ mov x0, #DCFG_DEVDISR5_OFFSET
+ bl read_reg_dcfg
+ mov w17, w0
+ mov x0, #DCFG_DEVDISR5_OFFSET
+ ldr x1, =DEVDISR5_VALUE
+ bic x1, x1, x6
+ bl write_reg_dcfg
+
+ /* x7 = [soc_data_area] */
+
+ /* save cpuactlr and disable data prefetch */
+ mrs x0, CPUACTLR_EL1
+ str w0, [x7, #CPUACTLR_DATA_OFFSET]
+ bic x0, x0, #CPUACTLR_L1PCTL_MASK
+ msr CPUACTLR_EL1, x0
+
+ /* x6 = DEVDISR5 override mask */
+
+ /* setup registers for cache-only execution */
+ ldr x5, =IPSTPCR4_VALUE
+ bic x5, x5, x6
+ mov x6, #DDR_CNTRL_BASE_ADDR
+ mov x7, #DCSR_RCPM2_BASE
+ mov x8, #NXP_DCFG_ADDR
+ dsb sy
+ isb
+
+ /* set the DLL_LOCK cycle count */
+ ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
+ rev w2, w1
+ bic w2, w2, #DLL_LOCK_MASK
+ orr w2, w2, #DLL_LOCK_VALUE
+ rev w1, w2
+ str w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
+
+ /*
+ * x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
+ * x6 = DDR_CNTRL_BASE_ADDR
+ * x7 = DCSR_RCPM2_BASE
+ * x8 = NXP_DCFG_ADDR
+ * w13 = DEVDISR1 saved value
+ * w14 = DEVDISR2 saved value
+ * w15 = DEVDISR3 saved value
+ * w16 = DEVDISR4 saved value
+ * w17 = DEVDISR5 saved value
+ */
+
+ /* enter the cache-only sequence */
+ mov x9, #CORE_RESTARTABLE
+ bl final_pwrdown
+
+ /* when we are here, the core has come out of wfi and the SoC is back up */
+
+ mov x30, x18
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_exit_pwrdn:
+ /* clear POWMGTDCR */
+ mov x1, #DCSR_RCPM2_BASE
+ str wzr, [x1, #RCPM2_POWMGTDCR_OFFSET]
+
+ /* clear WFIL2_EN in SCFG_COREPMCR */
+ mov x1, #NXP_SCFG_ADDR
+ str wzr, [x1, #SCFG_COREPMCR_OFFSET]
+
+ ret
+
+/*
+ * write a register in the SCFG block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2, x3
+ */
+write_reg_scfg:
+ ldr x2, =NXP_SCFG_ADDR
+ /* swap for BE */
+ rev w3, w1
+ str w3, [x2, x0]
+ ret
+/*
+ * read a register in the SCFG block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+read_reg_scfg:
+ ldr x2, =NXP_SCFG_ADDR
+ ldr w1, [x2, x0]
+ /* swap for BE */
+ rev w0, w1
+ ret
+
+/*
+ * write a register in the DCFG block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2, x3
+ */
+write_reg_dcfg:
+ ldr x2, =NXP_DCFG_ADDR
+ /* swap for BE */
+ rev w3, w1
+ str w3, [x2, x0]
+ ret
+
+/*
+ * read a register in the DCFG block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+read_reg_dcfg:
+ ldr x2, =NXP_DCFG_ADDR
+ ldr w1, [x2, x0]
+ /* swap for BE */
+ rev w0, w1
+ ret
+
+/*
+ * write a register in the RCPM block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2, x3
+ */
+write_reg_rcpm:
+ ldr x2, =NXP_RCPM_ADDR
+ /* swap for BE */
+ rev w3, w1
+ str w3, [x2, x0]
+ ret
+
+/*
+ * read a register in the RCPM block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+read_reg_rcpm:
+ ldr x2, =NXP_RCPM_ADDR
+ ldr w1, [x2, x0]
+ /* swap for BE */
+ rev w0, w1
+ ret
+
+/*
+ * write a register in the DCSR-RCPM2 block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2, x3
+ */
+write_reg_rcpm2:
+ ldr x2, =DCSR_RCPM2_BASE
+ /* swap for BE */
+ rev w3, w1
+ str w3, [x2, x0]
+ ret
+
+/*
+ * read a register in the DCSR-RCPM2 block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+read_reg_rcpm2:
+ ldr x2, =DCSR_RCPM2_BASE
+ ldr w1, [x2, x0]
+ /* swap for BE */
+ rev w0, w1
+ ret
+
+/*
+ * this function returns the base address of the gic distributor
+ * in: none
+ * out: x0 = base address of gic distributor
+ * uses x0, x1
+ */
+_getGICD_BaseAddr:
+ /* read SVR and get the SoC version */
+ mov x0, #NXP_DCFG_ADDR
+ ldr w1, [x0, #DCFG_SVR_OFFSET]
+ rev w0, w1
+
+ /* x0 = svr */
+ and w0, w0, #SVR_MIN_VER_MASK
+ cmp w0, #SVR_MINOR_VER_0
+ b.ne 8f
+
+ /* load the gic base addresses for rev 1.0 parts */
+ ldr x0, =NXP_GICD_4K_ADDR
+ b 10f
+8:
+ /* for rev 1.1 and later parts, the GIC base addresses */
+ /* can be at 4k or 64k offsets */
+
+ /* read the scfg reg GIC400_ADDR_ALIGN */
+ mov x0, #NXP_SCFG_ADDR
+ ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET]
+ rev w0, w1
+
+ /* x0 = GIC400_ADDR_ALIGN value */
+ and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK
+ mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN
+ cmp x0, x1
+ b.ne 9f
+
+ /* load the base addresses for 4k offsets */
+ ldr x0, =NXP_GICD_4K_ADDR
+ b 10f
+9:
+ /* load the base address for 64k offsets */
+ ldr x0, =NXP_GICD_64K_ADDR
+10:
+ ret
+
+/*
+ * this function returns the base address of the gic distributor
+ * in: none
+ * out: x0 = base address of gic controller
+ * uses x0, x1
+ */
+_getGICC_BaseAddr:
+ /* read SVR and get the SoC version */
+ mov x0, #NXP_DCFG_ADDR
+ ldr w1, [x0, #DCFG_SVR_OFFSET]
+ rev w0, w1
+
+ /* x0 = svr */
+ and w0, w0, #SVR_MIN_VER_MASK
+ cmp w0, #SVR_MINOR_VER_0
+ b.ne 8f
+
+ /* load the gic base addresses for rev 1.0 parts */
+ ldr x0, =NXP_GICC_4K_ADDR
+ b 10f
+8:
+ /* for rev 1.1 and later parts, the GIC base addresses */
+ /* can be at 4k or 64k offsets */
+
+ /* read the scfg reg GIC400_ADDR_ALIGN */
+ mov x0, #NXP_SCFG_ADDR
+ ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET]
+ rev w0, w1
+
+ /* x0 = GIC400_ADDR_ALIGN value */
+ and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK
+ mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN
+ cmp x0, x1
+ b.ne 9f
+
+ /* load the base addresses for 4k offsets */
+ ldr x0, =NXP_GICC_4K_ADDR
+ b 10f
+9:
+ /* load the base address for 64k offsets */
+ ldr x0, =NXP_GICC_64K_ADDR
+10:
+ ret
+
+/*
+ * this function will pwrdown ddr and the final core - it will do this
+ * by loading itself into the icache and then executing from there
+ * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
+ * x6 = DDR_CNTRL_BASE_ADDR
+ * x7 = DCSR_RCPM2_BASE
+ * x8 = NXP_DCFG_ADDR
+ * x9 = 0, restartable
+ * = 1, non-restartable
+ * w13 = DEVDISR1 saved value
+ * w14 = DEVDISR2 saved value
+ * w15 = DEVDISR3 saved value
+ * w16 = DEVDISR4 saved value
+ * w17 = DEVDISR5 saved value
+ * out: none
+ * uses x0 ~ x9
+ */
+
+/* 4Kb aligned */
+.align 12
+final_pwrdown:
+ mov x0, xzr
+ b touch_line_0
+start_line_0:
+ mov x0, #1
+ mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */
+ ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
+ rev w4, w3
+ orr w4, w4, w2
+ rev w3, w4
+ str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */
+ orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */
+ rev w4, w3
+ str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */
+
+ mov w3, #DEVDISR5_MEM
+ rev w3, w3 /* polling mask */
+ mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */
+touch_line_0:
+ cbz x0, touch_line_1
+
+start_line_1:
+ ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET]
+ tst w1, w3
+ b.ne 1f
+ subs x2, x2, #1
+ b.gt start_line_1 /* poll on ipstpack4 - end */
+
+ /* if we get here, we have a timeout err */
+ rev w4, w5
+ str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clks interface */
+ mov x0, #ERROR_DDR_SLEEP /* load error code */
+ b 2f
+1:
+ str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */
+5:
+ wfi /* stop the final core */
+
+ cbnz x9, 5b /* if non-restartable, keep in wfi */
+ rev w4, w5
+ str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* re-enable ddr in devdisr5 */
+ str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clk in ipstpcr4 */
+touch_line_1:
+ cbz x0, touch_line_2
+
+start_line_2:
+ ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] /* poll on ipstpack4 - start */
+ tst w1, w3
+ b.eq 2f
+ nop
+ b start_line_2 /* poll on ipstpack4 - end */
+2:
+ mov x2, #DDR_SDRAM_CFG_2_FRCSR /* take ddr out-of self refresh - start */
+ ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
+ rev w4, w3
+ bic w4, w4, w2
+ rev w3, w4
+ mov x1, #DDR_SLEEP_RETRY_CNT /* wait for ddr cntrlr clock - start */
+3:
+ subs x1, x1, #1
+ b.gt 3b /* wait for ddr cntrlr clock - end */
+ str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* take ddr out-of self refresh - end */
+ rev w1, w17
+touch_line_2:
+ cbz x0, touch_line_3
+
+start_line_3:
+ str w1, [x8, #DCFG_DEVDISR5_OFFSET] /* reset devdisr5 */
+ rev w1, w16
+ str w1, [x8, #DCFG_DEVDISR4_OFFSET] /* reset devdisr4 */
+ rev w1, w15
+ str w1, [x8, #DCFG_DEVDISR3_OFFSET] /* reset devdisr3 */
+ rev w1, w14
+ str w1, [x8, #DCFG_DEVDISR2_OFFSET] /* reset devdisr2 */
+ rev w1, w13
+ str w1, [x8, #DCFG_DEVDISR1_OFFSET] /* reset devdisr1 */
+ str wzr, [x7, #RCPM2_IPSTPCR4_OFFSET] /* reset ipstpcr4 */
+ str wzr, [x7, #RCPM2_IPSTPCR3_OFFSET] /* reset ipstpcr3 */
+ str wzr, [x7, #RCPM2_IPSTPCR2_OFFSET] /* reset ipstpcr2 */
+ str wzr, [x7, #RCPM2_IPSTPCR1_OFFSET] /* reset ipstpcr1 */
+ str wzr, [x7, #RCPM2_IPSTPCR0_OFFSET] /* reset ipstpcr0 */
+ b continue_restart
+touch_line_3:
+ cbz x0, start_line_0
+
+/* execute here after ddr is back up */
+continue_restart:
+ /*
+ * if x0 = 1, all is well
+ * if x0 < 1, we had an error
+ */
+ cmp x0, #1
+ b.ne 4f
+ mov x0, #0
+4:
+ ret
+
+/*
+ * Note: there is no return from this function
+ * this function will shutdown ddr and the final core - it will do this
+ * by loading itself into the icache and then executing from there
+ * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
+ * x6 = DDR_CNTRL_BASE_ADDR
+ * x7 = DCSR_RCPM2_BASE
+ * x8 = NXP_DCFG_ADDR
+ * out: none
+ * uses x0 ~ x8
+ */
+
+/* 4Kb aligned */
+.align 12
+final_shutdown:
+
+ mov x0, xzr
+ b touch_line0
+start_line0:
+ mov x0, #1
+ mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */
+ ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
+ rev w4, w3
+ orr w4, w4, w2
+ rev w3, w4
+ str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */
+ orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */
+ rev w4, w3
+ str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */
+
+ mov w3, #DEVDISR5_MEM
+ rev w3, w3 /* polling mask */
+ mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */
+touch_line0:
+ cbz x0, touch_line1
+
+start_line1:
+ ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET]
+ tst w1, w3
+ b.ne 1f
+ subs x2, x2, #1
+ b.gt start_line1 /* poll on ipstpack4 - end */
+ nop
+ nop
+ nop
+ nop
+1:
+ str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */
+5:
+ wfi /* stop the final core */
+ b 5b /* stay here until POR */
+ nop
+ nop
+ nop
+touch_line1:
+ cbz x0, start_line0
diff --git a/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S b/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S
new file mode 100644
index 0000000..bc88886
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_is_my_cpu_primary
+ .globl plat_reset_handler
+ .globl platform_mem_init
+
+func platform_mem1_init
+ ret
+endfunc platform_mem1_init
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+func apply_platform_errata
+ ret
+endfunc apply_platform_errata
+
+func plat_reset_handler
+ mov x29, x30
+ bl apply_platform_errata
+
+#if defined(IMAGE_BL31)
+ ldr x0, =POLICY_SMMU_PAGESZ_64K
+ cbz x0, 1f
+ /* Set the SMMU page size in the sACR register */
+ bl _set_smmu_pagesz_64
+#endif
+1:
+ mov x30, x29
+ ret
+endfunc plat_reset_handler
+
+/*
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ */
+func plat_secondary_cold_boot_setup
+ /* ls1043a does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+/*
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, 0x0
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/nxp/soc-ls1043a/include/ns_access.h b/plat/nxp/soc-ls1043a/include/ns_access.h
new file mode 100644
index 0000000..423c454
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/include/ns_access.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018, 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NS_ACCESS_H
+#define NS_ACCESS_H
+
+#include <csu.h>
+
+enum csu_cslx_ind {
+ CSU_CSLX_PCIE2_IO = 0,
+ CSU_CSLX_PCIE1_IO,
+ CSU_CSLX_MG2TPR_IP,
+ CSU_CSLX_IFC_MEM,
+ CSU_CSLX_OCRAM,
+ CSU_CSLX_GIC,
+ CSU_CSLX_PCIE1,
+ CSU_CSLX_OCRAM2,
+ CSU_CSLX_QSPI_MEM,
+ CSU_CSLX_PCIE2,
+ CSU_CSLX_SATA,
+ CSU_CSLX_USB1,
+ CSU_CSLX_QM_BM_SWPORTAL,
+ CSU_CSLX_PCIE3 = 16,
+ CSU_CSLX_PCIE3_IO,
+ CSU_CSLX_USB3 = 20,
+ CSU_CSLX_USB2,
+ CSU_CSLX_PFE = 23,
+ CSU_CSLX_SERDES = 32,
+ CSU_CSLX_QDMA,
+ CSU_CSLX_LPUART2,
+ CSU_CSLX_LPUART1,
+ CSU_CSLX_LPUART4,
+ CSU_CSLX_LPUART3,
+ CSU_CSLX_LPUART6,
+ CSU_CSLX_LPUART5,
+ CSU_CSLX_DSPI1 = 41,
+ CSU_CSLX_QSPI,
+ CSU_CSLX_ESDHC,
+ CSU_CSLX_IFC = 45,
+ CSU_CSLX_I2C1,
+ CSU_CSLX_USB_2,
+ CSU_CSLX_I2C3 = 48,
+ CSU_CSLX_I2C2,
+ CSU_CSLX_DUART2 = 50,
+ CSU_CSLX_DUART1,
+ CSU_CSLX_WDT2,
+ CSU_CSLX_WDT1,
+ CSU_CSLX_EDMA,
+ CSU_CSLX_SYS_CNT,
+ CSU_CSLX_DMA_MUX2,
+ CSU_CSLX_DMA_MUX1,
+ CSU_CSLX_DDR,
+ CSU_CSLX_QUICC,
+ CSU_CSLX_DCFG_CCU_RCPM = 60,
+ CSU_CSLX_SECURE_BOOTROM,
+ CSU_CSLX_SFP,
+ CSU_CSLX_TMU,
+ CSU_CSLX_SECURE_MONITOR,
+ CSU_CSLX_SCFG,
+ CSU_CSLX_FM = 66,
+ CSU_CSLX_SEC5_5,
+ CSU_CSLX_BM,
+ CSU_CSLX_QM,
+ CSU_CSLX_GPIO2 = 70,
+ CSU_CSLX_GPIO1,
+ CSU_CSLX_GPIO4,
+ CSU_CSLX_GPIO3,
+ CSU_CSLX_PLATFORM_CONT,
+ CSU_CSLX_CSU,
+ CSU_CSLX_IIC4 = 77,
+ CSU_CSLX_WDT4,
+ CSU_CSLX_WDT3,
+ CSU_CSLX_ESDHC2 = 80,
+ CSU_CSLX_WDT5 = 81,
+ CSU_CSLX_SAI2,
+ CSU_CSLX_SAI1,
+ CSU_CSLX_SAI4,
+ CSU_CSLX_SAI3,
+ CSU_CSLX_FTM2 = 86,
+ CSU_CSLX_FTM1,
+ CSU_CSLX_FTM4,
+ CSU_CSLX_FTM3,
+ CSU_CSLX_FTM6 = 90,
+ CSU_CSLX_FTM5,
+ CSU_CSLX_FTM8,
+ CSU_CSLX_FTM7,
+ CSU_CSLX_DSCR = 121,
+};
+
+struct csu_ns_dev_st ns_dev[] = {
+ {CSU_CSLX_PCIE2_IO, CSU_ALL_RW},
+ {CSU_CSLX_PCIE1_IO, CSU_ALL_RW},
+ {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW},
+ {CSU_CSLX_IFC_MEM, CSU_ALL_RW},
+ {CSU_CSLX_OCRAM, CSU_S_SUP_RW},
+ {CSU_CSLX_GIC, CSU_ALL_RW},
+ {CSU_CSLX_PCIE1, CSU_ALL_RW},
+ {CSU_CSLX_OCRAM2, CSU_S_SUP_RW},
+ {CSU_CSLX_QSPI_MEM, CSU_ALL_RW},
+ {CSU_CSLX_PCIE2, CSU_ALL_RW},
+ {CSU_CSLX_SATA, CSU_ALL_RW},
+ {CSU_CSLX_USB1, CSU_ALL_RW},
+ {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW},
+ {CSU_CSLX_PCIE3, CSU_ALL_RW},
+ {CSU_CSLX_PCIE3_IO, CSU_ALL_RW},
+ {CSU_CSLX_USB3, CSU_ALL_RW},
+ {CSU_CSLX_USB2, CSU_ALL_RW},
+ {CSU_CSLX_PFE, CSU_ALL_RW},
+ {CSU_CSLX_SERDES, CSU_ALL_RW},
+ {CSU_CSLX_QDMA, CSU_ALL_RW},
+ {CSU_CSLX_LPUART2, CSU_ALL_RW},
+ {CSU_CSLX_LPUART1, CSU_ALL_RW},
+ {CSU_CSLX_LPUART4, CSU_ALL_RW},
+ {CSU_CSLX_LPUART3, CSU_ALL_RW},
+ {CSU_CSLX_LPUART6, CSU_ALL_RW},
+ {CSU_CSLX_LPUART5, CSU_ALL_RW},
+ {CSU_CSLX_DSPI1, CSU_ALL_RW},
+ {CSU_CSLX_QSPI, CSU_ALL_RW},
+ {CSU_CSLX_ESDHC, CSU_ALL_RW},
+ {CSU_CSLX_IFC, CSU_ALL_RW},
+ {CSU_CSLX_I2C1, CSU_ALL_RW},
+ {CSU_CSLX_USB_2, CSU_ALL_RW},
+ {CSU_CSLX_I2C3, CSU_ALL_RW},
+ {CSU_CSLX_I2C2, CSU_ALL_RW},
+ {CSU_CSLX_DUART2, CSU_ALL_RW},
+ {CSU_CSLX_DUART1, CSU_ALL_RW},
+ {CSU_CSLX_WDT2, CSU_ALL_RW},
+ {CSU_CSLX_WDT1, CSU_ALL_RW},
+ {CSU_CSLX_EDMA, CSU_ALL_RW},
+ {CSU_CSLX_SYS_CNT, CSU_ALL_RW},
+ {CSU_CSLX_DMA_MUX2, CSU_ALL_RW},
+ {CSU_CSLX_DMA_MUX1, CSU_ALL_RW},
+ {CSU_CSLX_DDR, CSU_ALL_RW},
+ {CSU_CSLX_QUICC, CSU_ALL_RW},
+ {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW},
+ {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW},
+ {CSU_CSLX_SFP, CSU_ALL_RW},
+ {CSU_CSLX_TMU, CSU_ALL_RW},
+ {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW},
+ {CSU_CSLX_SCFG, CSU_ALL_RW},
+ {CSU_CSLX_FM, CSU_ALL_RW},
+ {CSU_CSLX_SEC5_5, CSU_ALL_RW},
+ {CSU_CSLX_BM, CSU_ALL_RW},
+ {CSU_CSLX_QM, CSU_ALL_RW},
+ {CSU_CSLX_GPIO2, CSU_ALL_RW},
+ {CSU_CSLX_GPIO1, CSU_ALL_RW},
+ {CSU_CSLX_GPIO4, CSU_ALL_RW},
+ {CSU_CSLX_GPIO3, CSU_ALL_RW},
+ {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW},
+ {CSU_CSLX_CSU, CSU_ALL_RW},
+ {CSU_CSLX_IIC4, CSU_ALL_RW},
+ {CSU_CSLX_WDT4, CSU_ALL_RW},
+ {CSU_CSLX_WDT3, CSU_ALL_RW},
+ {CSU_CSLX_ESDHC2, CSU_ALL_RW},
+ {CSU_CSLX_WDT5, CSU_ALL_RW},
+ {CSU_CSLX_SAI2, CSU_ALL_RW},
+ {CSU_CSLX_SAI1, CSU_ALL_RW},
+ {CSU_CSLX_SAI4, CSU_ALL_RW},
+ {CSU_CSLX_SAI3, CSU_ALL_RW},
+ {CSU_CSLX_FTM2, CSU_ALL_RW},
+ {CSU_CSLX_FTM1, CSU_ALL_RW},
+ {CSU_CSLX_FTM4, CSU_ALL_RW},
+ {CSU_CSLX_FTM3, CSU_ALL_RW},
+ {CSU_CSLX_FTM6, CSU_ALL_RW},
+ {CSU_CSLX_FTM5, CSU_ALL_RW},
+ {CSU_CSLX_FTM8, CSU_ALL_RW},
+ {CSU_CSLX_FTM7, CSU_ALL_RW},
+ {CSU_CSLX_DSCR, CSU_ALL_RW},
+};
+
+#endif /* NS_ACCESS_H */
diff --git a/plat/nxp/soc-ls1043a/include/soc.h b/plat/nxp/soc-ls1043a/include/soc.h
new file mode 100644
index 0000000..e018102
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/include/soc.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2017-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+/* Chassis specific defines - common across SoC's of a particular platform */
+#include "dcfg_lsch2.h"
+#include "soc_default_base_addr.h"
+#include "soc_default_helper_macros.h"
+
+/* DDR Regions Info */
+#define NUM_DRAM_REGIONS 3
+#define NXP_DRAM0_ADDR 0x80000000
+#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */
+
+#define NXP_DRAM1_ADDR 0x880000000
+#define NXP_DRAM1_MAX_SIZE 0x780000000 /* 30 GB */
+
+#define NXP_DRAM2_ADDR 0x8800000000
+#define NXP_DRAM2_MAX_SIZE 0x7800000000 /* 480 GB */
+/* DRAM0 Size defined in platform_def.h */
+#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE
+
+/*
+ * P23: 23 x 23 package
+ * A: without security
+ * AE: with security
+ * SVR Definition (not include major and minor rev)
+ */
+#define SVR_LS1023A 0x879209
+#define SVR_LS1023AE 0x879208
+#define SVR_LS1023A_P23 0x87920B
+#define SVR_LS1023AE_P23 0x87920A
+#define SVR_LS1043A 0x879201
+#define SVR_LS1043AE 0x879200
+#define SVR_LS1043A_P23 0x879203
+#define SVR_LS1043AE_P23 0x879202
+
+/* Number of cores in platform */
+#define PLATFORM_CORE_COUNT 4
+#define NUMBER_OF_CLUSTERS 1
+#define CORES_PER_CLUSTER 4
+
+/* set to 0 if the clusters are not symmetrical */
+#define SYMMETRICAL_CLUSTERS 1
+
+/*
+ * Required LS standard platform porting definitions
+ * for CCI-400
+ */
+#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4
+
+/* ls1043 version info for GIC configuration */
+#define REV1_0 0x10
+#define REV1_1 0x11
+#define GIC_ADDR_BIT 31
+
+/* Errata */
+#define NXP_ERRATUM_A009663
+#define NXP_ERRATUM_A009942
+
+#define NUM_OF_DDRC 1
+
+/* Defines required for using XLAT tables from ARM common code */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40)
+
+/* Clock Divisors */
+#define NXP_PLATFORM_CLK_DIVIDER 1
+#define NXP_UART_CLK_DIVIDER 1
+
+/*
+ * Set this switch to 1 if you need to keep the debug block
+ * clocked during system power-down.
+ */
+#define DEBUG_ACTIVE 0
+
+#define IPPDEXPCR_MAC1_1 0x80000000 // DEVDISR2_FMAN1_MAC1
+#define IPPDEXPCR_MAC1_2 0x40000000 // DEVDISR2_FMAN1_MAC2
+#define IPPDEXPCR_MAC1_3 0x20000000 // DEVDISR2_FMAN1_MAC3
+#define IPPDEXPCR_MAC1_4 0x10000000 // DEVDISR2_FMAN1_MAC4
+#define IPPDEXPCR_MAC1_5 0x08000000 // DEVDISR2_FMAN1_MAC5
+#define IPPDEXPCR_MAC1_6 0x04000000 // DEVDISR2_FMAN1_MAC6
+#define IPPDEXPCR_MAC1_9 0x00800000 // DEVDISR2_FMAN1_MAC9
+#define IPPDEXPCR_I2C1 0x00080000 // DEVDISR5_I2C_1
+#define IPPDEXPCR_LPUART1 0x00040000 // DEVDISR5_LPUART1
+#define IPPDEXPCR_FLX_TMR1 0x00020000 // DEVDISR5_FLX_TMR
+#define IPPDEXPCR_OCRAM1 0x00010000 // DEVDISR5_OCRAM1
+#define IPPDEXPCR_GPIO1 0x00000040 // DEVDISR5_GPIO
+#define IPPDEXPCR_FM1 0x00000008 // DEVDISR2_FMAN1
+
+#define IPPDEXPCR_MASK1 0xFC800008 // overrides for DEVDISR2
+#define IPPDEXPCR_MASK2 0x000F0040 // overriddes for DEVDISR5
+
+#define IPSTPCR0_VALUE 0xA000C201
+#define IPSTPCR1_VALUE 0x00000080
+#define IPSTPCR2_VALUE 0x000C0000
+#define IPSTPCR3_VALUE 0x38000000
+#if (DEBUG_ACTIVE)
+ #define IPSTPCR4_VALUE 0x10833BFC
+#else
+ #define IPSTPCR4_VALUE 0x10A33BFC
+#endif
+
+#define DEVDISR1_QE 0x00000001
+#define DEVDISR1_SEC 0x00000200
+#define DEVDISR1_USB1 0x00004000
+#define DEVDISR1_SATA 0x00008000
+#define DEVDISR1_USB2 0x00010000
+#define DEVDISR1_USB3 0x00020000
+#define DEVDISR1_DMA2 0x00400000
+#define DEVDISR1_DMA1 0x00800000
+#define DEVDISR1_ESDHC 0x20000000
+#define DEVDISR1_PBL 0x80000000
+
+#define DEVDISR2_FMAN1 0x00000080
+#define DEVDISR2_FMAN1_MAC9 0x00800000
+#define DEVDISR2_FMAN1_MAC6 0x04000000
+#define DEVDISR2_FMAN1_MAC5 0x08000000
+#define DEVDISR2_FMAN1_MAC4 0x10000000
+#define DEVDISR2_FMAN1_MAC3 0x20000000
+#define DEVDISR2_FMAN1_MAC2 0x40000000
+#define DEVDISR2_FMAN1_MAC1 0x80000000
+
+#define DEVDISR3_BMAN 0x00040000
+#define DEVDISR3_QMAN 0x00080000
+#define DEVDISR3_PEX3 0x20000000
+#define DEVDISR3_PEX2 0x40000000
+#define DEVDISR3_PEX1 0x80000000
+
+#define DEVDISR4_QSPI 0x08000000
+#define DEVDISR4_DUART2 0x10000000
+#define DEVDISR4_DUART1 0x20000000
+
+#define DEVDISR5_ICMMU 0x00000001
+#define DEVDISR5_I2C_1 0x00000002
+#define DEVDISR5_I2C_2 0x00000004
+#define DEVDISR5_I2C_3 0x00000008
+#define DEVDISR5_I2C_4 0x00000010
+#define DEVDISR5_WDG_5 0x00000020
+#define DEVDISR5_WDG_4 0x00000040
+#define DEVDISR5_WDG_3 0x00000080
+#define DEVDISR5_DSPI1 0x00000100
+#define DEVDISR5_WDG_2 0x00000200
+#define DEVDISR5_FLX_TMR 0x00000400
+#define DEVDISR5_WDG_1 0x00000800
+#define DEVDISR5_LPUART6 0x00001000
+#define DEVDISR5_LPUART5 0x00002000
+#define DEVDISR5_LPUART3 0x00008000
+#define DEVDISR5_LPUART2 0x00010000
+#define DEVDISR5_LPUART1 0x00020000
+#define DEVDISR5_DBG 0x00200000
+#define DEVDISR5_GPIO 0x00400000
+#define DEVDISR5_IFC 0x00800000
+#define DEVDISR5_OCRAM2 0x01000000
+#define DEVDISR5_OCRAM1 0x02000000
+#define DEVDISR5_LPUART4 0x10000000
+#define DEVDISR5_DDR 0x80000000
+#define DEVDISR5_MEM 0x80000000
+
+#define DEVDISR1_VALUE 0xA0C3C201
+#define DEVDISR2_VALUE 0xCC0C0080
+#define DEVDISR3_VALUE 0xE00C0000
+#define DEVDISR4_VALUE 0x38000000
+#if (DEBUG_ACTIVE)
+ #define DEVDISR5_VALUE 0x10833BFC
+#else
+ #define DEVDISR5_VALUE 0x10A33BFC
+#endif
+
+/*
+ * PWR mgmt features supported in the soc-specific code:
+ * value == 0x0 the soc code does not support this feature
+ * value != 0x0 the soc code supports this feature
+ */
+#define SOC_CORE_RELEASE 0x1
+#define SOC_CORE_RESTART 0x1
+#define SOC_CORE_OFF 0x1
+#define SOC_CORE_STANDBY 0x1
+#define SOC_CORE_PWR_DWN 0x1
+#define SOC_CLUSTER_STANDBY 0x1
+#define SOC_CLUSTER_PWR_DWN 0x1
+#define SOC_SYSTEM_STANDBY 0x1
+#define SOC_SYSTEM_PWR_DWN 0x1
+#define SOC_SYSTEM_OFF 0x1
+#define SOC_SYSTEM_RESET 0x1
+
+/* PSCI-specific defines */
+#define SYSTEM_PWR_DOMAINS 1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ NUMBER_OF_CLUSTERS + \
+ SYSTEM_PWR_DOMAINS)
+
+/* Power state coordination occurs at the system level */
+#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL
+
+/* Local power state for power domains in Run state */
+#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN
+
+/* define retention state */
+#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1)
+#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE
+
+/* define power-down state */
+#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1)
+#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ * CACHE_WRITEBACK_GRANULE is defined in soc.def
+ */
+
+/* One cache line needed for bakery locks on ARM platforms */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+#ifndef __ASSEMBLER__
+/* CCI slave interfaces */
+static const int cci_map[] = {
+ NXP_CCI_CLUSTER0_SL_IFACE_IX,
+};
+void soc_init_lowlevel(void);
+void soc_init_percpu(void);
+void _soc_set_start_addr(unsigned long addr);
+
+#endif
+
+#endif /* SOC_H */
diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c b/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c
new file mode 100644
index 0000000..28e2dab
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+
+#include <errata.h>
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+const struct ddr_cfg_regs static_1600 = {
+ .cs[0].config = U(0x80040322),
+ .cs[0].bnds = U(0x7F),
+ .sdram_cfg[0] = U(0xC50C0000),
+ .sdram_cfg[1] = U(0x401100),
+ .timing_cfg[0] = U(0x91550018),
+ .timing_cfg[1] = U(0xBBB48C42),
+ .timing_cfg[2] = U(0x48C111),
+ .timing_cfg[3] = U(0x10C1000),
+ .timing_cfg[4] = U(0x2),
+ .timing_cfg[5] = U(0x3401400),
+ .timing_cfg[7] = U(0x13300000),
+ .timing_cfg[8] = U(0x2115600),
+ .sdram_mode[0] = U(0x3010210),
+ .sdram_mode[9] = U(0x4000000),
+ .sdram_mode[8] = U(0x500),
+ .sdram_mode[2] = U(0x10210),
+ .sdram_mode[10] = U(0x400),
+ .sdram_mode[11] = U(0x4000000),
+ .sdram_mode[4] = U(0x10210),
+ .sdram_mode[12] = U(0x400),
+ .sdram_mode[13] = U(0x4000000),
+ .sdram_mode[6] = U(0x10210),
+ .sdram_mode[14] = U(0x400),
+ .sdram_mode[15] = U(0x4000000),
+ .interval = U(0x18600618),
+ .zq_cntl = U(0x8A090705),
+ .clk_cntl = U(0x3000000),
+ .cdr[0] = U(0x80040000),
+ .cdr[1] = U(0xA181),
+ .wrlvl_cntl[0] = U(0x8675F607),
+ .wrlvl_cntl[1] = U(0x7090807,
+ .wrlvl_cntl[2] = U(0x7070707),
+ .debug[28] = U(0x00700046),
+};
+
+uint64_t board_static_ddr(struct ddr_info *priv)
+{
+ memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600));
+
+ return ULL(0x80000000);
+}
+
+#else
+static const struct rc_timing rcz[] = {
+ {1600, 12, 7},
+ {}
+};
+
+static const struct board_timing ram[] = {
+ {0x1f, rcz, 0x00020100, 0},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ int ret;
+ struct memctl_opt *popts = &priv->opt;
+
+ ret = cal_board_params(priv, ram, ARRAY_SIZE(ram));
+ if (ret)
+ return ret;
+
+ popts->cpo_sample = U(0x46);
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
+ DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
+ DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */
+
+ return 0;
+}
+
+/* DDR model number: MT40A1G8SA-062E:R */
+struct dimm_params ddr_raw_timing = {
+ .n_ranks = U(1),
+ .rank_density = ULL(2147483648),
+ .capacity = ULL(2147483648),
+ .primary_sdram_width = U(32),
+ .ec_sdram_width = U(4),
+ .rdimm = U(0),
+ .mirrored_dimm = U(0),
+ .n_row_addr = U(16),
+ .n_col_addr = U(10),
+ .bank_group_bits = U(2),
+ .edc_config = U(2),
+ .burst_lengths_bitmask = U(0x0c),
+ .tckmin_x_ps = 625,
+ .tckmax_ps = 2200,
+ .caslat_x = U(0x0001FFE00),
+ .taa_ps = 13500,
+ .trcd_ps = 13500,
+ .trp_ps = 13500,
+ .tras_ps = 32000,
+ .trc_ps = 45500,
+ .twr_ps = 15000,
+ .trfc1_ps = 350000,
+ .trfc2_ps = 260000,
+ .trfc4_ps = 160000,
+ .tfaw_ps = 21000,
+ .trrds_ps = 3000,
+ .trrdl_ps = 4900,
+ .tccdl_ps = 5000,
+ .refresh_rate_ps = U(7800000),
+ .rc = U(0x1f),
+};
+
+int ddr_get_ddr_params(struct dimm_params *pdimm,
+ struct ddr_conf *conf)
+{
+ static const char dimm_model[] = "Fixed DDR on board";
+
+ conf->dimm_in_use[0] = 1;
+ memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params));
+ memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+
+ return 1;
+}
+#endif
+
+int64_t init_ddr(void)
+{
+ struct ddr_info info;
+ struct sysinfo sys;
+ int64_t dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ get_clocks(&sys);
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
+
+ zeromem(&info, sizeof(struct ddr_info));
+ info.num_ctlrs = 1;
+ info.dimm_on_ctlr = 1;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+ dram_size = dram_init(&info);
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed\n");
+ }
+
+#ifdef ERRATA_SOC_A008850
+ erratum_a008850_post();
+#endif
+ return dram_size;
+}
diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h b/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h
new file mode 100644
index 0000000..249f457
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+/*
+ * Required without TBBR.
+ * To include the defines for DDR PHY Images.
+ */
+#include <tbbr_img_def.h>
+
+#include "policy.h"
+#include <soc.h>
+
+#define NXP_SPD_EEPROM0 0x51
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0x00100000)
+#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000)
+
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES 3
+#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_HANDLES 4
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES 2
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 1
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define BL32_IRQ_SEC_PHY_TIMER 29
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_LS_G0_IRQ_PROPS(grp)
+
+#endif /* PLAT_DEF_H */
diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform.c b/plat/nxp/soc-ls1043a/ls1043ardb/platform.c
new file mode 100644
index 0000000..65d508c
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk b/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk
new file mode 100644
index 0000000..5d23356
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk
@@ -0,0 +1,40 @@
+#
+# Copyright 2018-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+
+BOOT_MODE ?= nor
+BOARD := ls1043ardb
+POVDD_ENABLE := no
+
+# DDR Compilation Configs
+CONFIG_DDR_NODIMM := 1
+NUM_OF_DDRC := 1
+DDRC_NUM_DIMM := 0
+DDRC_NUM_CS := 4
+DDR_ECC_EN := no
+CONFIG_STATIC_DDR := 0
+
+# On-Board Flash Details
+# 128MB IFC NOR Flash
+NOR_FLASH_SZ := 0x8000000
+
+# Platform specific features.
+WARM_BOOT := no
+
+# Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := nor \
+ sd \
+ nand
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-ls1043a/soc.mk
diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h b/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h
new file mode 100644
index 0000000..4721a32
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1043a/ls1043ardb/policy.h b/plat/nxp/soc-ls1043a/ls1043ardb/policy.h
new file mode 100644
index 0000000..843b5e2
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/ls1043ardb/policy.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/*
+ * Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1043a/soc.c b/plat/nxp/soc-ls1043a/soc.c
new file mode 100644
index 0000000..7badf8c
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/soc.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <caam.h>
+#include <cassert.h>
+#include <cci.h>
+#include <common/debug.h>
+#include <dcfg.h>
+#ifdef I2C_INIT
+#include <i2c.h>
+#endif
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <ls_interconnect.h>
+#ifdef POLICY_FUSE_PROVISION
+#include <nxp_gpio.h>
+#endif
+#if TRUSTED_BOARD_BOOT
+#include <nxp_smmu.h>
+#endif
+#include <nxp_timer.h>
+#include <plat_console.h>
+#include <plat_gic.h>
+#include <plat_tzc380.h>
+#include <scfg.h>
+#if defined(NXP_SFP_ENABLED)
+#include <sfp.h>
+#endif
+
+#include <errata.h>
+#include <ns_access.h>
+#ifdef CONFIG_OCRAM_ECC_EN
+#include <ocram.h>
+#endif
+#include <plat_common.h>
+#include <platform_def.h>
+#include <soc.h>
+
+static dcfg_init_info_t dcfg_init_data = {
+ .g_nxp_dcfg_addr = NXP_DCFG_ADDR,
+ .nxp_sysclk_freq = NXP_SYSCLK_FREQ,
+ .nxp_ddrclk_freq = NXP_DDRCLK_FREQ,
+ .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER,
+ };
+
+
+/* Function to return the SoC SYS CLK */
+unsigned int get_sys_clk(void)
+{
+ return NXP_SYSCLK_FREQ;
+}
+
+/*
+ * Function returns the base counter frequency
+ * after reading the first entry at CNTFID0 (0x20 offset).
+ *
+ * Function is used by:
+ * 1. ARM common code for PSCI management.
+ * 2. ARM Generic Timer init.
+ *
+ */
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+
+ counter_base_frequency = get_sys_clk()/4;
+
+ return counter_base_frequency;
+}
+
+#ifdef IMAGE_BL2
+
+static struct soc_type soc_list[] = {
+ SOC_ENTRY(LS1023A, LS1023A, 1, 2),
+ SOC_ENTRY(LS1023AE, LS1023AE, 1, 2),
+ SOC_ENTRY(LS1023A_P23, LS1023A_P23, 1, 2),
+ SOC_ENTRY(LS1023AE_P23, LS1023AE_P23, 1, 2),
+ SOC_ENTRY(LS1043A, LS1043A, 1, 4),
+ SOC_ENTRY(LS1043AE, LS1043AE, 1, 4),
+ SOC_ENTRY(LS1043A_P23, LS1043A_P23, 1, 4),
+ SOC_ENTRY(LS1043AE_P23, LS1043AE_P23, 1, 4),
+};
+
+#ifdef POLICY_FUSE_PROVISION
+static gpio_init_info_t gpio_init_data = {
+ .gpio1_base_addr = NXP_GPIO1_ADDR,
+ .gpio2_base_addr = NXP_GPIO2_ADDR,
+ .gpio3_base_addr = NXP_GPIO3_ADDR,
+ .gpio4_base_addr = NXP_GPIO4_ADDR,
+};
+#endif
+
+/*
+ * Function to set the base counter frequency at
+ * the first entry of the Frequency Mode Table,
+ * at CNTFID0 (0x20 offset).
+ *
+ * Set the value of the pirmary core register cntfrq_el0.
+ */
+static void set_base_freq_CNTFID0(void)
+{
+ /*
+ * Below register specifies the base frequency of the system counter.
+ * As per NXP Board Manuals:
+ * The system counter always works with SYS_REF_CLK/4 frequency clock.
+ *
+ */
+ unsigned int counter_base_frequency = get_sys_clk()/4;
+
+ /*
+ * Setting the frequency in the Frequency modes table.
+ *
+ * Note: The value for ls1046ardb board at this offset
+ * is not RW as stated. This offset have the
+ * fixed value of 100000400 Hz.
+ *
+ * The below code line has no effect.
+ * Keeping it for other platforms where it has effect.
+ */
+ mmio_write_32(NXP_TIMER_ADDR + CNTFID_OFF, counter_base_frequency);
+
+ write_cntfrq_el0(counter_base_frequency);
+}
+
+void soc_preload_setup(void)
+{
+
+}
+
+/*******************************************************************************
+ * This function implements soc specific erratas
+ * This is called before DDR is initialized or MMU is enabled
+ ******************************************************************************/
+void soc_early_init(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+ dram_regions_info_t *dram_regions_info = get_dram_regions_info();
+
+#ifdef CONFIG_OCRAM_ECC_EN
+ ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE);
+#endif
+ dcfg_init(&dcfg_init_data);
+#ifdef POLICY_FUSE_PROVISION
+ gpio_init(&gpio_init_data);
+ sec_init(NXP_CAAM_ADDR);
+#endif
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+ set_base_freq_CNTFID0();
+
+ /* Enable snooping on SEC read and write transactions */
+ scfg_setbits32((void *)(NXP_SCFG_ADDR + SCFG_SNPCNFGCR_OFFSET),
+ SCFG_SNPCNFGCR_SECRDSNP | SCFG_SNPCNFGCR_SECWRSNP);
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ plat_ls_interconnect_enter_coherency(num_clusters);
+
+#if TRUSTED_BOARD_BOOT
+ uint32_t mode;
+
+ sfp_init(NXP_SFP_ADDR);
+ /*
+ * For secure boot disable SMMU.
+ * Later when platform security policy comes in picture,
+ * this might get modified based on the policy
+ */
+ if (check_boot_mode_secure(&mode) == true) {
+ bypass_smmu(NXP_SMMU_ADDR);
+ }
+
+ /*
+ * For Mbedtls currently crypto is not supported via CAAM
+ * enable it when that support is there. In tbbr.mk
+ * the CAAM_INTEG is set as 0.
+ */
+
+#ifndef MBEDTLS_X509
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false) {
+ INFO("SEC is disabled.\n");
+ } else {
+ sec_init(NXP_CAAM_ADDR);
+ }
+#endif
+#elif defined(POLICY_FUSE_PROVISION)
+ gpio_init(&gpio_init_data);
+ sfp_init(NXP_SFP_ADDR);
+ sec_init(NXP_CAAM_ADDR);
+#endif
+
+ soc_errata();
+
+ /*
+ * Initialize system level generic timer for Layerscape Socs.
+ */
+ delay_timer_init(NXP_TIMER_ADDR);
+
+#ifdef DDR_INIT
+ i2c_init(NXP_I2C_ADDR);
+ dram_regions_info->total_dram_size = init_ddr();
+#endif
+}
+
+void soc_bl2_prepare_exit(void)
+{
+#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE)
+ set_sfp_wr_disable();
+#endif
+}
+
+/*****************************************************************************
+ * This function returns the boot device based on RCW_SRC
+ ****************************************************************************/
+enum boot_device get_boot_dev(void)
+{
+ enum boot_device src = BOOT_DEVICE_NONE;
+ uint32_t porsr1;
+ uint32_t rcw_src, val;
+
+ porsr1 = read_reg_porsr1();
+
+ rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT;
+
+ val = rcw_src & RCW_SRC_NAND_MASK;
+
+ if (val == RCW_SRC_NAND_VAL) {
+ val = rcw_src & NAND_RESERVED_MASK;
+ if ((val != NAND_RESERVED_1) && (val != NAND_RESERVED_2)) {
+ src = BOOT_DEVICE_IFC_NAND;
+ INFO("RCW BOOT SRC is IFC NAND\n");
+ }
+ } else {
+ /* RCW SRC NOR */
+ val = rcw_src & RCW_SRC_NOR_MASK;
+ if (val == NOR_8B_VAL || val == NOR_16B_VAL) {
+ src = BOOT_DEVICE_IFC_NOR;
+ INFO("RCW BOOT SRC is IFC NOR\n");
+ } else {
+ switch (rcw_src) {
+ case QSPI_VAL1:
+ case QSPI_VAL2:
+ src = BOOT_DEVICE_QSPI;
+ INFO("RCW BOOT SRC is QSPI\n");
+ break;
+ case SD_VAL:
+ src = BOOT_DEVICE_EMMC;
+ INFO("RCW BOOT SRC is SD/EMMC\n");
+ break;
+ default:
+ src = BOOT_DEVICE_NONE;
+ }
+ }
+ }
+
+ return src;
+}
+
+/* This function sets up access permissions on memory regions */
+void soc_mem_access(void)
+{
+ struct tzc380_reg tzc380_reg_list[MAX_NUM_TZC_REGION];
+ int dram_idx, index = 0U;
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+
+ for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions;
+ dram_idx++) {
+ if (info_dram_regions->region[dram_idx].size == 0) {
+ ERROR("DDR init failure, or");
+ ERROR("DRAM regions not populated correctly.\n");
+ break;
+ }
+
+ index = populate_tzc380_reg_list(tzc380_reg_list,
+ dram_idx, index,
+ info_dram_regions->region[dram_idx].addr,
+ info_dram_regions->region[dram_idx].size,
+ NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE);
+ }
+
+ mem_access_setup(NXP_TZC_ADDR, index, tzc380_reg_list);
+
+ /* Configure CSU secure access register to disable TZASC bypass mux */
+ mmio_write_32((uintptr_t)(NXP_CSU_ADDR +
+ CSU_SEC_ACCESS_REG_OFFSET),
+ bswap32(TZASC_BYPASS_MUX_DISABLE));
+}
+
+
+#else
+const unsigned char _power_domain_tree_desc[] = {1, 1, 4};
+
+CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256,
+ assert_invalid_ls1043_cluster_count);
+
+/* This function returns the SoC topology */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+
+ return _power_domain_tree_desc;
+}
+
+/*
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ */
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr)
+{
+ return CORES_PER_CLUSTER;
+}
+
+void soc_early_platform_setup2(void)
+{
+ dcfg_init(&dcfg_init_data);
+ /* Initialize system level generic timer for Socs */
+ delay_timer_init(NXP_TIMER_ADDR);
+
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+}
+
+/*
+ * For LS1043a rev1.0, GIC base address align with 4k.
+ * For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT]
+ * is set, GIC base address align with 4K, or else align
+ * with 64k.
+ */
+void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base)
+{
+ uint32_t *ccsr_svr = (uint32_t *)(NXP_DCFG_ADDR + DCFG_SVR_OFFSET);
+ uint32_t *gic_align = (uint32_t *)(NXP_SCFG_ADDR +
+ SCFG_GIC400_ADDR_ALIGN_OFFSET);
+ uint32_t val;
+
+ val = be32toh(mmio_read_32((uintptr_t)ccsr_svr));
+
+ if ((val & 0xff) == REV1_1) {
+ val = be32toh(mmio_read_32((uintptr_t)gic_align));
+ if (val & (1L << GIC_ADDR_BIT)) {
+ *gicc_base = NXP_GICC_4K_ADDR;
+ *gicd_base = NXP_GICD_4K_ADDR;
+ } else {
+ *gicc_base = NXP_GICC_64K_ADDR;
+ *gicd_base = NXP_GICD_64K_ADDR;
+ }
+ } else {
+ *gicc_base = NXP_GICC_4K_ADDR;
+ *gicd_base = NXP_GICD_4K_ADDR;
+ }
+}
+
+void soc_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ static uint32_t target_mask_array[PLATFORM_CORE_COUNT];
+ /*
+ * On a GICv2 system, the Group 1 secure interrupts are treated
+ * as Group 0 interrupts.
+ */
+ static interrupt_prop_t ls_interrupt_props[] = {
+ PLAT_LS_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ PLAT_LS_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+ };
+ static uint32_t gicc_base, gicd_base;
+
+ get_gic_offset(&gicc_base, &gicd_base);
+ plat_ls_gic_driver_init(gicd_base, gicc_base,
+ PLATFORM_CORE_COUNT,
+ ls_interrupt_props,
+ ARRAY_SIZE(ls_interrupt_props),
+ target_mask_array);
+
+ plat_ls_gic_init();
+ enable_init_timer();
+}
+
+/* This function initializes the soc from the BL31 module */
+void soc_init(void)
+{
+ /* low-level init of the soc */
+ soc_init_lowlevel();
+ _init_global_data();
+ soc_init_percpu();
+ _initialize_psci();
+
+ /*
+ * Initialize the interconnect during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable coherency in interconnect for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this but we can't
+ * assume so. No harm in executing this code twice.
+ */
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+
+ /* Init CSU to enable non-secure access to peripherals */
+ enable_layerscape_ns_access(ns_dev, ARRAY_SIZE(ns_dev), NXP_CSU_ADDR);
+
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false) {
+ INFO("SEC is disabled.\n");
+ } else {
+ sec_init(NXP_CAAM_ADDR);
+ }
+}
+
+void soc_runtime_setup(void)
+{
+
+}
+#endif
diff --git a/plat/nxp/soc-ls1043a/soc.def b/plat/nxp/soc-ls1043a/soc.def
new file mode 100644
index 0000000..b174bd6
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/soc.def
@@ -0,0 +1,107 @@
+#
+# Copyright 2017-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# This file contains the basic architecture definitions that drive the build
+#
+# -----------------------------------------------------------------------------
+
+CORE_TYPE := a53
+
+CACHE_LINE := 6
+
+# set to GIC400 or GIC500
+GIC := GIC400
+
+# set to CCI400 or CCN504 or CCN508
+INTERCONNECT := CCI400
+
+# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2
+CHASSIS := 2
+
+# TZC IP Details TZC used is TZC380 or TZC400
+TZC_ID := TZC380
+
+# CONSOLE Details available is NS16550 or PL011
+CONSOLE := NS16550
+
+# Select the DDR PHY generation to be used
+PLAT_DDR_PHY := PHY_GEN1
+
+PHYS_SYS := 64
+
+# ddr controller - set to MMDC or NXP
+DDRCNTLR := NXP
+
+# ddr phy - set to NXP or SNPS
+DDRPHY := NXP
+
+# Area of OCRAM reserved by ROM code
+NXP_ROM_RSVD := 0x5900
+
+# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def
+# Input to CST create_hdr_esbc tool
+CSF_HDR_SZ := 0x3000
+
+# In IMAGE_BL2, compile time flag for handling Cache coherency
+# with CAAM for BL2 running from OCRAM
+SEC_MEM_NON_COHERENT := yes
+
+# OCRAM MAP
+OCRAM_START_ADDR := 0x10000000
+OCRAM_SIZE := 0x20000
+
+# BL2 binary is placed at start of OCRAM.
+# Also used by create_pbl.mk.
+BL2_BASE := 0x10000000
+
+# After BL2 bin, OCRAM is used by ROM Code:
+# (OCRAM_START_ADDR + BL2_BIN_SIZE) -> (NXP_ROM_RSVD - 1)
+
+# After ROM Code, OCRAM is used by CSF header.
+# (OCRAM_START_ADDR + BL2_TEXT_LIMIT + NXP_ROM_RSVD) -> (CSF_HDR_SZ - 1)
+
+# BL2_HDR_LOC has to be (OCRAM_START_ADDR + OCRAM_SIZE - NXP_ROM_RSVD - CSF_HDR_SZ)
+# This value should be greater than BL2_TEXT_LIMIT
+# Input to CST create_hdr_isbc tool
+BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(OCRAM_SIZE) - $(NXP_ROM_RSVD) - $(CSF_HDR_SZ))))
+# Covert to HEX to be used by create_pbl.mk
+BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc)
+
+# Core Errata
+ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
+
+# SoC ERRATAS to be enabled
+ERRATA_SOC_A008850 := 1
+ERRATA_SOC_A010539 := 1
+ERRATA_SOC_A009660 := 1
+
+# DDR Errata
+ERRATA_DDR_A009663 := 1
+ERRATA_DDR_A009942 := 1
+
+# enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC := 1
+
+# Define Endianness of each module
+NXP_GUR_ENDIANNESS := BE
+NXP_DDR_ENDIANNESS := BE
+NXP_SEC_ENDIANNESS := BE
+NXP_SFP_ENDIANNESS := BE
+NXP_SNVS_ENDIANNESS := BE
+NXP_ESDHC_ENDIANNESS := BE
+NXP_QSPI_ENDIANNESS := BE
+NXP_FSPI_ENDIANNESS := BE
+NXP_SCFG_ENDIANNESS := BE
+NXP_GPIO_ENDIANNESS := BE
+NXP_IFC_ENDIANNESS := BE
+
+NXP_SFP_VER := 3_2
+
+# OCRAM ECC Enabled
+OCRAM_ECC_EN := yes
diff --git a/plat/nxp/soc-ls1043a/soc.mk b/plat/nxp/soc-ls1043a/soc.mk
new file mode 100644
index 0000000..b6ce14e
--- /dev/null
+++ b/plat/nxp/soc-ls1043a/soc.mk
@@ -0,0 +1,114 @@
+#
+# Copyright 2018-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SoC-specific build parameters
+SOC := ls1043a
+PLAT_PATH := plat/nxp
+PLAT_COMMON_PATH := plat/nxp/common
+PLAT_DRIVERS_PATH := drivers/nxp
+PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC}
+BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD}
+
+# get SoC-specific defnitions
+include ${PLAT_SOC_PATH}/soc.def
+include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk
+include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
+
+# For Security Features
+DISABLE_FUSE_WRITE := 1
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2))
+SECURE_BOOT := yes
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM))
+
+# Selecting Drivers for SoC
+$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,CSU_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+
+# Selecting PSCI & SIP_SVC support
+$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31))
+
+# Source File Addition
+PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\
+ -I${BOARD_PATH}\
+ -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
+ -I${PLAT_SOC_PATH}/include\
+ -I${PLAT_COMMON_PATH}/soc_errata
+
+ifeq (${SECURE_BOOT},yes)
+include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
+endif
+
+ifeq ($(WARM_BOOT),yes)
+include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk
+endif
+
+ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes)
+include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk
+endif
+
+ifeq (${PSCI_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/psci/psci.mk
+endif
+
+ifeq (${SIPSVC_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk
+endif
+
+# for fuse-fip & fuse-programming
+ifeq (${FUSE_PROG}, 1)
+include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk
+endif
+
+ifeq (${IMG_LOADR_NEEDED},yes)
+include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk
+endif
+
+# Adding source files for the above selected drivers.
+include ${PLAT_DRIVERS_PATH}/drivers.mk
+
+# Adding SoC specific files
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
+
+PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\
+ ${WARM_RST_INCLUDES}
+
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\
+ ${WARM_RST_BL31_SOURCES}\
+ ${PSCI_SOURCES}\
+ ${SIPSVC_SOURCES}\
+ ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S
+
+PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\
+ ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\
+ ${NV_STORAGE_SOURCES}\
+ ${WARM_RST_BL_COMM_SOURCES}\
+ ${PLAT_SOC_PATH}/soc.c
+
+ifeq (${TEST_BL31}, 1)
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\
+ ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S
+endif
+
+BL2_SOURCES += ${DDR_CNTLR_SOURCES}\
+ ${TBBR_SOURCES}\
+ ${FUSE_SOURCES}
+
+# Adding TFA setup files
+include ${PLAT_PATH}/common/setup/common.mk
diff --git a/plat/nxp/soc-ls1046a/aarch64/ls1046a.S b/plat/nxp/soc-ls1046a/aarch64/ls1046a.S
new file mode 100644
index 0000000..daa0542
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/aarch64/ls1046a.S
@@ -0,0 +1,937 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <asm_macros.S>
+#include <dcfg_lsch2.h>
+#include <nxp_timer.h>
+#include <plat_gic.h>
+#include <scfg.h>
+
+#include <bl31_data.h>
+#include <plat_psci.h>
+#include <platform_def.h>
+
+#define DAIF_DATA AUX_01_DATA
+#define TIMER_CNTRL_DATA AUX_02_DATA
+
+.global soc_init_lowlevel
+.global soc_init_percpu
+.global _soc_core_release
+.global _soc_core_restart
+.global _soc_ck_disabled
+.global _soc_sys_reset
+.global _soc_sys_off
+.global _soc_set_start_addr
+.global _getGICC_BaseAddr
+.global _getGICD_BaseAddr
+.global _soc_core_prep_off
+.global _soc_core_entr_off
+.global _soc_core_exit_off
+.global _soc_core_prep_stdby
+.global _soc_core_entr_stdby
+.global _soc_core_exit_stdby
+.global _soc_core_prep_pwrdn
+.global _soc_core_entr_pwrdn
+.global _soc_core_exit_pwrdn
+.global _soc_clstr_prep_stdby
+.global _soc_clstr_exit_stdby
+.global _soc_clstr_prep_pwrdn
+.global _soc_clstr_exit_pwrdn
+.global _soc_sys_prep_stdby
+.global _soc_sys_exit_stdby
+.global _soc_sys_prep_pwrdn
+.global _soc_sys_pwrdn_wfi
+.global _soc_sys_exit_pwrdn
+
+
+/* This function initialize the soc
+ * in: void
+ * out: void
+ */
+func soc_init_lowlevel
+ ret
+endfunc soc_init_lowlevel
+
+
+/* void soc_init_percpu(void)
+ * this function performs any soc-specific initialization that is needed on
+ * a per-core basis
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+func soc_init_percpu
+ mov x3, x30
+
+ bl plat_my_core_mask
+ mov x2, x0
+
+ /* see if this core is marked for prefetch disable */
+ mov x0, #PREFETCH_DIS_OFFSET
+ bl _get_global_data /* 0-1 */
+ tst x0, x2
+ b.eq 1f
+ bl _disable_ldstr_pfetch_A72 /* 0 */
+1:
+ mov x30, x3
+ ret
+endfunc soc_init_percpu
+
+/* part of CPU_ON
+ * this function releases a secondary core from reset
+ * in: x0 = core_mask_lsb
+ * out: none
+ * uses: x0, x1, x2, x3
+ */
+func _soc_core_release
+
+#if (TEST_BL31)
+ rbit w2, w0
+ /* x2 = core mask msb */
+#else
+ mov x2, x0
+#endif
+ /* write COREBCR */
+ mov x1, #NXP_SCFG_ADDR
+ rev w3, w2
+ str w3, [x1, #SCFG_COREBCR_OFFSET]
+ isb
+
+ /* read-modify-write BRR */
+ mov x1, #NXP_DCFG_ADDR
+ ldr w2, [x1, #DCFG_BRR_OFFSET]
+ rev w3, w2
+ orr w3, w3, w0
+ rev w2, w3
+ str w2, [x1, #DCFG_BRR_OFFSET]
+ isb
+
+ /* send event */
+ sev
+ isb
+ ret
+endfunc _soc_core_release
+
+
+/* part of CPU_ON
+ * this function restarts a core shutdown via _soc_core_entr_off
+ * in: x0 = core mask lsb (of the target cpu)
+ * out: x0 == 0, on success
+ * x0 != 0, on failure
+ * uses x0, x1, x2, x3, x4, x5
+ */
+func _soc_core_restart
+ mov x5, x30
+ mov x3, x0
+
+ /*
+ * unset ph20 request in RCPM_PCPH20CLEARR
+ * this is an lsb-0 register
+ */
+ ldr x1, =NXP_RCPM_ADDR
+ rev w2, w3
+ str w2, [x1, #RCPM_PCPH20CLRR_OFFSET]
+ dsb sy
+ isb
+
+ bl _getGICD_BaseAddr
+ mov x4, x0
+
+ /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */
+ ldr w1, [x4, #GICD_CTLR_OFFSET]
+ orr w1, w1, #GICD_CTLR_EN_GRP0
+ str w1, [x4, #GICD_CTLR_OFFSET]
+ dsb sy
+ isb
+
+
+ /*
+ * fire SGI by writing to GICD_SGIR the following values:
+ * [25:24] = 0x0 (forward interrupt to the CPU interfaces
+ * specified in CPUTargetList field)
+ * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu)
+ * [15] = 0 (forward SGI only if it is configured as group 0 interrupt)
+ * [3:0] = 0xF (interrupt ID = 15)
+ */
+ lsl w1, w3, #16
+ orr w1, w1, #0xF
+ str w1, [x4, #GICD_SGIR_OFFSET]
+ dsb sy
+ isb
+
+ /* load '0' on success */
+ mov x0, xzr
+
+ mov x30, x5
+ ret
+endfunc _soc_core_restart
+
+/*
+ * This function determines if a core is disabled via COREDISR
+ * in: w0 = core_mask_lsb
+ * out: w0 = 0, core not disabled
+ * w0 != 0, core disabled
+ * uses x0, x1, x2
+ */
+func _soc_ck_disabled
+ /* get base addr of dcfg block */
+ mov x1, #NXP_DCFG_ADDR
+
+ /* read COREDISR */
+ ldr w1, [x1, #DCFG_COREDISR_OFFSET]
+ rev w2, w1
+
+ /* test core bit */
+ and w0, w2, w0
+ ret
+endfunc _soc_ck_disabled
+
+/*
+ *This function resets the system via SoC-specific methods
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+func _soc_sys_reset
+ ldr x2, =NXP_DCFG_ADDR
+
+ /* make sure the mask is cleared in the reset request mask register */
+ mov w1, wzr
+ str w1, [x2, #DCFG_RSTRQMR1_OFFSET]
+
+ /* set the reset request */
+ ldr w1, =RSTCR_RESET_REQ
+ ldr x3, =DCFG_RSTCR_OFFSET
+ rev w0, w1
+ str w0, [x2, x3]
+
+ /*
+ * just in case this address range is mapped as cacheable,
+ * flush the write out of the dcaches
+ */
+ add x3, x2, x3
+ dc cvac, x3
+ dsb st
+ isb
+
+ /* Note: this function does not return */
+1:
+ wfi
+ b 1b
+endfunc _soc_sys_reset
+
+/*
+ * Part of SYSTEM_OFF
+ * this function turns off the SoC clocks
+ * Note: this function is not intended to return, and the only allowable
+ * recovery is POR
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9
+ */
+func _soc_sys_off
+
+ /* mask interrupts at the core */
+ mrs x1, DAIF
+ mov x0, #DAIF_SET_MASK
+ orr x0, x1, x0
+ msr DAIF, x0
+
+ /* disable icache, dcache, mmu @ EL1 */
+ mov x1, #SCTLR_I_C_M_MASK
+ mrs x0, sctlr_el1
+ bic x0, x0, x1
+ msr sctlr_el1, x0
+
+ /* disable dcache for EL3 */
+ mrs x1, SCTLR_EL3
+ bic x1, x1, #SCTLR_C_MASK
+ /* make sure icache is enabled */
+ orr x1, x1, #SCTLR_I_MASK
+ msr SCTLR_EL3, x1
+ isb
+
+ /* Enable dynamic retention ctrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */
+ mrs x0, CORTEX_A72_ECTLR_EL1
+ orr x0, x0, #CPUECTLR_TIMER_8TICKS
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ msr CORTEX_A72_ECTLR_EL1, x0
+
+ /* set WFIL2EN in SCFG_CLUSTERPMCR */
+ ldr x0, =SCFG_COREPMCR_OFFSET
+ ldr x1, =COREPMCR_WFIL2
+ bl write_reg_scfg
+
+ /* request LPM20 */
+ mov x0, #RCPM_POWMGTCSR_OFFSET
+ bl read_reg_rcpm
+ orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ
+ mov x0, #RCPM_POWMGTCSR_OFFSET
+ bl write_reg_rcpm
+
+ dsb sy
+ isb
+1:
+ wfi
+ b 1b
+endfunc _soc_sys_off
+
+/*
+ * Write a register in the RCPM block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2, x3
+ */
+func write_reg_rcpm
+ ldr x2, =NXP_RCPM_ADDR
+ /* swap for BE */
+ rev w3, w1
+ str w3, [x2, x0]
+ ret
+endfunc write_reg_rcpm
+
+/*
+ * Read a register in the RCPM block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+func read_reg_rcpm
+ ldr x2, =NXP_RCPM_ADDR
+ ldr w1, [x2, x0]
+ /* swap for BE */
+ rev w0, w1
+ ret
+endfunc read_reg_rcpm
+
+/*
+ * Write a register in the SCFG block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2, x3
+ */
+func write_reg_scfg
+ mov x2, #NXP_SCFG_ADDR
+ /* swap for BE */
+ rev w3, w1
+ str w3, [x2, x0]
+ ret
+endfunc write_reg_scfg
+
+/*
+ * Read a register in the SCFG block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+func read_reg_scfg
+ mov x2, #NXP_SCFG_ADDR
+ ldr w1, [x2, x0]
+ /* swap for BE */
+ rev w0, w1
+ ret
+endfunc read_reg_scfg
+
+/*
+ * Part of CPU_OFF
+ * this function programs SoC & GIC registers in preparation for shutting down
+ * the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7
+ */
+func _soc_core_prep_off
+ mov x7, x30
+ mov x6, x0
+
+ /* Set retention control in CPUECTLR make sure smpen bit is set */
+ mrs x4, CORTEX_A72_ECTLR_EL1
+ bic x4, x4, #CPUECTLR_RET_MASK
+ orr x4, x4, #CPUECTLR_TIMER_8TICKS
+ orr x4, x4, #CPUECTLR_SMPEN_EN
+ msr CORTEX_A72_ECTLR_EL1, x4
+
+ /* save timer control current value */
+ mov x5, #NXP_TIMER_ADDR
+ ldr w4, [x5, #SYS_COUNTER_CNTCR_OFFSET]
+ mov w2, w4
+ mov x0, x6
+ mov x1, #TIMER_CNTRL_DATA
+ bl _setCoreData
+
+ /* enable the timer */
+ orr w4, w4, #CNTCR_EN_MASK
+ str w4, [x5, #SYS_COUNTER_CNTCR_OFFSET]
+
+ bl _getGICC_BaseAddr
+ mov x5, x0
+
+ /* disable signaling of ints */
+ ldr w3, [x5, #GICC_CTLR_OFFSET]
+ bic w3, w3, #GICC_CTLR_EN_GRP0
+ bic w3, w3, #GICC_CTLR_EN_GRP1
+ str w3, [x5, #GICC_CTLR_OFFSET]
+ dsb sy
+ isb
+
+
+ /*
+ * set retention control in SCFG_RETREQCR
+ * Note: this register is msb 0
+ */
+ ldr x4, =SCFG_RETREQCR_OFFSET
+ mov x0, x4
+ bl read_reg_scfg
+ rbit w1, w6
+ orr w1, w0, w1
+ mov x0, x4
+ bl write_reg_scfg
+
+ /* set the priority filter */
+ ldr w2, [x5, #GICC_PMR_OFFSET]
+ orr w2, w2, #GICC_PMR_FILTER
+ str w2, [x5, #GICC_PMR_OFFSET]
+
+ /* setup GICC_CTLR */
+ bic w3, w3, #GICC_CTLR_ACKCTL_MASK
+ orr w3, w3, #GICC_CTLR_FIQ_EN_MASK
+ orr w3, w3, #GICC_CTLR_EOImodeS_MASK
+ orr w3, w3, #GICC_CTLR_CBPR_MASK
+ str w3, [x5, #GICC_CTLR_OFFSET]
+
+ /* setup the banked-per-core GICD registers */
+ bl _getGICD_BaseAddr
+ mov x5, x0
+
+ /* define SGI15 as Grp0 */
+ ldr w2, [x5, #GICD_IGROUPR0_OFFSET]
+ bic w2, w2, #GICD_IGROUP0_SGI15
+ str w2, [x5, #GICD_IGROUPR0_OFFSET]
+
+ /* set priority of SGI 15 to highest... */
+ ldr w2, [x5, #GICD_IPRIORITYR3_OFFSET]
+ bic w2, w2, #GICD_IPRIORITY_SGI15_MASK
+ str w2, [x5, #GICD_IPRIORITYR3_OFFSET]
+
+ /* enable SGI 15 */
+ ldr w2, [x5, #GICD_ISENABLER0_OFFSET]
+ orr w2, w2, #GICD_ISENABLE0_SGI15
+ str w2, [x5, #GICD_ISENABLER0_OFFSET]
+
+ /* enable the cpu interface */
+ bl _getGICC_BaseAddr
+ mov x2, x0
+ orr w3, w3, #GICC_CTLR_EN_GRP0
+ str w3, [x2, #GICC_CTLR_OFFSET]
+
+
+ /* clear any pending SGIs */
+ ldr x2, =GICD_CPENDSGIR_CLR_MASK
+ add x0, x5, #GICD_CPENDSGIR3_OFFSET
+ str w2, [x0]
+
+ /*
+ * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR
+ * this is an lsb-0 register
+ */
+ mov x1, x6
+ mov x0, #RCPM_PCPH20SETR_OFFSET
+ bl write_reg_rcpm
+
+ dsb sy
+ isb
+ mov x30, x7
+ ret
+endfunc _soc_core_prep_off
+
+/*
+ * Part of CPU_OFF
+ * this function performs the final steps to shutdown the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5
+ */
+func _soc_core_entr_off
+ mov x5, x30
+ mov x4, x0
+
+ bl _getGICD_BaseAddr
+ mov x3, x0
+
+3:
+ /* enter low-power state by executing wfi */
+ wfi
+
+ /* see if we got hit by SGI 15 */
+ add x0, x3, #GICD_SPENDSGIR3_OFFSET
+ ldr w2, [x0]
+ and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK
+ cbz w2, 4f
+
+ /* clear the pending SGI */
+ ldr x2, =GICD_CPENDSGIR_CLR_MASK
+ add x0, x3, #GICD_CPENDSGIR3_OFFSET
+ str w2, [x0]
+4:
+ /* check if core has been turned on */
+ mov x0, x4
+ bl _getCoreState
+
+ cmp x0, #CORE_WAKEUP
+ b.ne 3b
+
+ /* if we get here, then we have exited the wfi */
+ dsb sy
+ isb
+ mov x30, x5
+ ret
+endfunc _soc_core_entr_off
+
+/*
+ * Part of CPU_OFF
+ * this function starts the process of starting a core back up
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6
+ */
+func _soc_core_exit_off
+ mov x6, x30
+ mov x5, x0
+
+ /*
+ * Clear ph20 request in RCPM_PCPH20CLRR - no need
+ * to do that here, it has been done in _soc_core_restart
+ */
+ bl _getGICC_BaseAddr
+ mov x1, x0
+
+ /* read GICC_IAR */
+ ldr w0, [x1, #GICC_IAR_OFFSET]
+
+ /* write GICC_EIOR - signal end-of-interrupt */
+ str w0, [x1, #GICC_EOIR_OFFSET]
+
+ /* write GICC_DIR - disable interrupt */
+ str w0, [x1, #GICC_DIR_OFFSET]
+
+ /* disable signaling of grp0 ints */
+ ldr w3, [x1, #GICC_CTLR_OFFSET]
+ bic w3, w3, #GICC_CTLR_EN_GRP0
+ str w3, [x1, #GICC_CTLR_OFFSET]
+
+ /*
+ * Unset retention request in SCFG_RETREQCR
+ * Note: this register is msb-0
+ */
+ ldr x4, =SCFG_RETREQCR_OFFSET
+ mov x0, x4
+ bl read_reg_scfg
+ rbit w1, w5
+ bic w1, w0, w1
+ mov x0, x4
+ bl write_reg_scfg
+
+ /* restore timer ctrl */
+ mov x0, x5
+ mov x1, #TIMER_CNTRL_DATA
+ bl _getCoreData
+ /* w0 = timer ctrl saved value */
+ mov x2, #NXP_TIMER_ADDR
+ str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+
+ dsb sy
+ isb
+ mov x30, x6
+ ret
+endfunc _soc_core_exit_off
+
+/*
+ * Function loads a 64-bit execution address of the core in the soc registers
+ * BOOTLOCPTRL/H
+ * in: x0, 64-bit address to write to BOOTLOCPTRL/H
+ * uses x0, x1, x2, x3
+ */
+func _soc_set_start_addr
+ /* get the 64-bit base address of the scfg block */
+ ldr x2, =NXP_SCFG_ADDR
+
+ /* write the 32-bit BOOTLOCPTRL register */
+ mov x1, x0
+ rev w3, w1
+ str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET]
+
+ /* write the 32-bit BOOTLOCPTRH register */
+ lsr x1, x0, #32
+ rev w3, w1
+ str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET]
+ ret
+endfunc _soc_set_start_addr
+
+/*
+ * This function returns the base address of the gic distributor
+ * in: none
+ * out: x0 = base address of gic distributor
+ * uses x0
+ */
+func _getGICD_BaseAddr
+#if (TEST_BL31)
+ /* defect in simulator - gic base addresses are on 4Kb boundary */
+ ldr x0, =NXP_GICD_4K_ADDR
+#else
+ ldr x0, =NXP_GICD_64K_ADDR
+#endif
+ ret
+endfunc _getGICD_BaseAddr
+
+/*
+ * This function returns the base address of the gic controller
+ * in: none
+ * out: x0 = base address of gic controller
+ * uses x0
+ */
+func _getGICC_BaseAddr
+#if (TEST_BL31)
+ /* defect in simulator - gic base addresses are on 4Kb boundary */
+ ldr x0, =NXP_GICC_4K_ADDR
+#else
+ ldr x0, =NXP_GICC_64K_ADDR
+#endif
+ ret
+endfunc _getGICC_BaseAddr
+
+/*
+ * Part of CPU_SUSPEND
+ * this function puts the calling core into standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+func _soc_core_entr_stdby
+ dsb sy
+ isb
+ wfi
+
+ ret
+endfunc _soc_core_entr_stdby
+
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+func _soc_core_prep_stdby
+ /* clear CORTEX_A72_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ ret
+endfunc _soc_core_prep_stdby
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_core_exit_stdby
+ ret
+endfunc _soc_core_exit_stdby
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5
+ */
+func _soc_core_prep_pwrdn
+ mov x5, x30
+ mov x4, x0
+
+ /* enable CPU retention + set smp */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ orr x1, x1, #0x1
+ orr x1, x1, #CPUECTLR_SMPEN_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ /*
+ * set the retention request in SCFG_RETREQCR
+ * this is an msb-0 register
+ */
+ ldr x3, =SCFG_RETREQCR_OFFSET
+ mov x0, x3
+ bl read_reg_scfg
+ rbit w1, w4
+ orr w1, w0, w1
+ mov x0, x3
+ bl write_reg_scfg
+
+ /*
+ * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR
+ * this is an lsb-0 register
+ */
+ mov x1, x4
+ mov x0, #RCPM_PCPH20SETR_OFFSET
+ bl write_reg_rcpm
+
+ mov x30, x5
+ ret
+endfunc _soc_core_prep_pwrdn
+
+/*
+ * Part of CPU_SUSPEND
+ * this function puts the calling core into a power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+func _soc_core_entr_pwrdn
+ dsb sy
+ isb
+ wfi
+
+ ret
+endfunc _soc_core_entr_pwrdn
+
+/*
+ * Part of CPU_SUSPEND
+ * this function cleans up after a core exits power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5
+ */
+func _soc_core_exit_pwrdn
+ mov x5, x30
+ mov x4, x0
+
+ /*
+ * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR
+ * this is an lsb-0 register
+ */
+ mov x1, x4
+ mov x0, #RCPM_PCPH20CLRR_OFFSET
+ bl write_reg_rcpm
+
+ /*
+ * Unset the retention request in SCFG_RETREQCR
+ * this is an msb-0 register
+ */
+ ldr x3, =SCFG_RETREQCR_OFFSET
+ mov x0, x3
+ bl read_reg_scfg
+ rbit w1, w4
+ bic w1, w0, w1
+ mov x0, x3
+ bl write_reg_scfg
+
+ mov x30, x5
+ ret
+endfunc _soc_core_exit_pwrdn
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_clstr_prep_stdby
+ /* clear CORTEX_A72_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ ret
+endfunc _soc_clstr_prep_stdby
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_clstr_exit_stdby
+ ret
+endfunc _soc_clstr_exit_stdby
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5
+ */
+func _soc_clstr_prep_pwrdn
+ mov x5, x30
+ mov x4, x0
+
+ /* enable CPU retention + set smp */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ orr x1, x1, #0x1
+ orr x1, x1, #CPUECTLR_SMPEN_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ /*
+ * Set the retention request in SCFG_RETREQCR
+ * this is an msb-0 register.
+ */
+ ldr x3, =SCFG_RETREQCR_OFFSET
+ mov x0, x3
+ bl read_reg_scfg
+ rbit w1, w4
+ orr w1, w0, w1
+ mov x0, x3
+ bl write_reg_scfg
+
+ /*
+ * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR
+ * this is an lsb-0 register.
+ */
+ mov x1, x4
+ mov x0, #RCPM_PCPH20SETR_OFFSET
+ bl write_reg_rcpm
+
+ mov x30, x5
+ ret
+endfunc _soc_clstr_prep_pwrdn
+
+/*
+ * Part of CPU_SUSPEND
+ * this function cleans up after a core exits power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5
+ */
+func _soc_clstr_exit_pwrdn
+ mov x5, x30
+ mov x4, x0
+
+ /*
+ * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR
+ * this is an lsb-0 register.
+ */
+ mov x1, x4
+ mov x0, #RCPM_PCPH20CLRR_OFFSET
+ bl write_reg_rcpm
+
+ /*
+ * Unset the retention request in SCFG_RETREQCR
+ * this is an msb-0 register.
+ */
+ ldr x3, =SCFG_RETREQCR_OFFSET
+ mov x0, x3
+ bl read_reg_scfg
+ rbit w1, w4
+ bic w1, w0, w1
+ mov x0, x3
+ bl write_reg_scfg
+
+ mov x30, x5
+ ret
+endfunc _soc_clstr_exit_pwrdn
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_sys_prep_stdby
+ /* clear CORTEX_A72_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ ret
+endfunc _soc_sys_prep_stdby
+
+/* Part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_sys_exit_stdby
+ ret
+endfunc _soc_sys_exit_stdby
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to
+ * suspend-to-power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4
+ */
+func _soc_sys_prep_pwrdn
+ mov x4, x30
+
+ /* Enable dynamic retention contrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */
+ mrs x0, CORTEX_A72_ECTLR_EL1
+ bic x0, x0, #CPUECTLR_TIMER_MASK
+ orr x0, x0, #CPUECTLR_TIMER_8TICKS
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ msr CORTEX_A72_ECTLR_EL1, x0
+
+ /* Set WFIL2EN in SCFG_CLUSTERPMCR */
+ ldr x0, =SCFG_COREPMCR_OFFSET
+ ldr x1, =COREPMCR_WFIL2
+ bl write_reg_scfg
+
+ isb
+ mov x30, x4
+ ret
+endfunc _soc_sys_prep_pwrdn
+
+/*
+ * Part of CPU_SUSPEND
+ * this function puts the calling core, and potentially the soc, into a
+ * low-power state
+ * in: x0 = core mask lsb
+ * out: x0 = 0, success
+ * x0 < 0, failure
+ * uses x0, x1, x2, x3, x4
+ */
+func _soc_sys_pwrdn_wfi
+ mov x4, x30
+
+ /* request LPM20 */
+ mov x0, #RCPM_POWMGTCSR_OFFSET
+ bl read_reg_rcpm
+ orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ
+ mov x0, #RCPM_POWMGTCSR_OFFSET
+ bl write_reg_rcpm
+
+ dsb sy
+ isb
+ wfi
+
+ mov x30, x4
+ ret
+endfunc _soc_sys_pwrdn_wfi
+
+/*
+ * Part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+func _soc_sys_exit_pwrdn
+ /* clear WFIL2_EN in SCFG_COREPMCR */
+ mov x1, #NXP_SCFG_ADDR
+ str wzr, [x1, #SCFG_COREPMCR_OFFSET]
+
+ ret
+endfunc _soc_sys_exit_pwrdn
diff --git a/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S b/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S
new file mode 100644
index 0000000..d2a48ea
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_is_my_cpu_primary
+ .globl plat_reset_handler
+ .globl platform_mem_init
+
+func platform_mem1_init
+ ret
+endfunc platform_mem1_init
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+func l2_mem_init
+ /* Initialize the L2 RAM latency */
+ mrs x1, S3_1_c11_c0_2
+ mov x0, #0x1C7
+ /* Clear L2 Tag RAM latency and L2 Data RAM latency */
+ bic x1, x1, x0
+ /* Set L2 data ram latency bits [2:0] */
+ orr x1, x1, #0x2
+ /* set L2 tag ram latency bits [8:6] */
+ orr x1, x1, #0x80
+ msr S3_1_c11_c0_2, x1
+ isb
+ ret
+endfunc l2_mem_init
+
+func apply_platform_errata
+ ret
+endfunc apply_platform_errata
+
+func plat_reset_handler
+ mov x29, x30
+#if (defined(IMAGE_BL2) && BL2_AT_EL3)
+ bl l2_mem_init
+#endif
+ bl apply_platform_errata
+
+#if defined(IMAGE_BL31)
+ ldr x0, =POLICY_SMMU_PAGESZ_64K
+ cbz x0, 1f
+ /* Set the SMMU page size in the SACR register */
+ bl _set_smmu_pagesz_64
+#endif
+1:
+ /*
+ * May be cntfrq_el0 needs to be assigned
+ * the value COUNTER_FREQUENCY
+ */
+ mov x30, x29
+ ret
+endfunc plat_reset_handler
+
+/*
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ */
+func plat_secondary_cold_boot_setup
+ /* ls1046a does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+/*
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary cpu.
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, 0x0
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/nxp/soc-ls1046a/include/ns_access.h b/plat/nxp/soc-ls1046a/include/ns_access.h
new file mode 100644
index 0000000..25c1964
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/include/ns_access.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2017-2018, 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NS_ACCESS_H
+#define NS_ACCESS_H
+
+#include <csu.h>
+
+enum csu_cslx_ind {
+ CSU_CSLX_PCIE2_IO = 0,
+ CSU_CSLX_PCIE1_IO,
+ CSU_CSLX_MG2TPR_IP,
+ CSU_CSLX_IFC_MEM,
+ CSU_CSLX_OCRAM,
+ CSU_CSLX_GIC,
+ CSU_CSLX_PCIE1,
+ CSU_CSLX_OCRAM2,
+ CSU_CSLX_QSPI_MEM,
+ CSU_CSLX_PCIE2,
+ CSU_CSLX_SATA,
+ CSU_CSLX_USB1,
+ CSU_CSLX_QM_BM_SWPORTAL,
+ CSU_CSLX_PCIE3 = 16,
+ CSU_CSLX_PCIE3_IO,
+ CSU_CSLX_USB3 = 20,
+ CSU_CSLX_USB2,
+ CSU_CSLX_PFE = 23,
+ CSU_CSLX_SERDES = 32,
+ CSU_CSLX_QDMA,
+ CSU_CSLX_LPUART2,
+ CSU_CSLX_LPUART1,
+ CSU_CSLX_LPUART4,
+ CSU_CSLX_LPUART3,
+ CSU_CSLX_LPUART6,
+ CSU_CSLX_LPUART5,
+ CSU_CSLX_DSPI1 = 41,
+ CSU_CSLX_QSPI,
+ CSU_CSLX_ESDHC,
+ CSU_CSLX_IFC = 45,
+ CSU_CSLX_I2C1,
+ CSU_CSLX_USB_2,
+ CSU_CSLX_I2C3 = 48,
+ CSU_CSLX_I2C2,
+ CSU_CSLX_DUART2 = 50,
+ CSU_CSLX_DUART1,
+ CSU_CSLX_WDT2,
+ CSU_CSLX_WDT1,
+ CSU_CSLX_EDMA,
+ CSU_CSLX_SYS_CNT,
+ CSU_CSLX_DMA_MUX2,
+ CSU_CSLX_DMA_MUX1,
+ CSU_CSLX_DDR,
+ CSU_CSLX_QUICC,
+ CSU_CSLX_DCFG_CCU_RCPM = 60,
+ CSU_CSLX_SECURE_BOOTROM,
+ CSU_CSLX_SFP,
+ CSU_CSLX_TMU,
+ CSU_CSLX_SECURE_MONITOR,
+ CSU_CSLX_SCFG,
+ CSU_CSLX_FM = 66,
+ CSU_CSLX_SEC5_5,
+ CSU_CSLX_BM,
+ CSU_CSLX_QM,
+ CSU_CSLX_GPIO2 = 70,
+ CSU_CSLX_GPIO1,
+ CSU_CSLX_GPIO4,
+ CSU_CSLX_GPIO3,
+ CSU_CSLX_PLATFORM_CONT,
+ CSU_CSLX_CSU,
+ CSU_CSLX_IIC4 = 77,
+ CSU_CSLX_WDT4,
+ CSU_CSLX_WDT3,
+ CSU_CSLX_ESDHC2 = 80,
+ CSU_CSLX_WDT5 = 81,
+ CSU_CSLX_SAI2,
+ CSU_CSLX_SAI1,
+ CSU_CSLX_SAI4,
+ CSU_CSLX_SAI3,
+ CSU_CSLX_FTM2 = 86,
+ CSU_CSLX_FTM1,
+ CSU_CSLX_FTM4,
+ CSU_CSLX_FTM3,
+ CSU_CSLX_FTM6 = 90,
+ CSU_CSLX_FTM5,
+ CSU_CSLX_FTM8,
+ CSU_CSLX_FTM7,
+ CSU_CSLX_DSCR = 121,
+};
+
+struct csu_ns_dev_st ns_dev[] = {
+ {CSU_CSLX_PCIE2_IO, CSU_ALL_RW},
+ {CSU_CSLX_PCIE1_IO, CSU_ALL_RW},
+ {CSU_CSLX_MG2TPR_IP, CSU_ALL_RW},
+ {CSU_CSLX_IFC_MEM, CSU_ALL_RW},
+ {CSU_CSLX_OCRAM, CSU_S_SUP_RW},
+ {CSU_CSLX_GIC, CSU_ALL_RW},
+ {CSU_CSLX_PCIE1, CSU_ALL_RW},
+ {CSU_CSLX_OCRAM2, CSU_S_SUP_RW},
+ {CSU_CSLX_QSPI_MEM, CSU_ALL_RW},
+ {CSU_CSLX_PCIE2, CSU_ALL_RW},
+ {CSU_CSLX_SATA, CSU_ALL_RW},
+ {CSU_CSLX_USB1, CSU_ALL_RW},
+ {CSU_CSLX_QM_BM_SWPORTAL, CSU_ALL_RW},
+ {CSU_CSLX_PCIE3, CSU_ALL_RW},
+ {CSU_CSLX_PCIE3_IO, CSU_ALL_RW},
+ {CSU_CSLX_USB3, CSU_ALL_RW},
+ {CSU_CSLX_USB2, CSU_ALL_RW},
+ {CSU_CSLX_PFE, CSU_ALL_RW},
+ {CSU_CSLX_SERDES, CSU_ALL_RW},
+ {CSU_CSLX_QDMA, CSU_ALL_RW},
+ {CSU_CSLX_LPUART2, CSU_ALL_RW},
+ {CSU_CSLX_LPUART1, CSU_ALL_RW},
+ {CSU_CSLX_LPUART4, CSU_ALL_RW},
+ {CSU_CSLX_LPUART3, CSU_ALL_RW},
+ {CSU_CSLX_LPUART6, CSU_ALL_RW},
+ {CSU_CSLX_LPUART5, CSU_ALL_RW},
+ {CSU_CSLX_DSPI1, CSU_ALL_RW},
+ {CSU_CSLX_QSPI, CSU_ALL_RW},
+ {CSU_CSLX_ESDHC, CSU_ALL_RW},
+ {CSU_CSLX_IFC, CSU_ALL_RW},
+ {CSU_CSLX_I2C1, CSU_ALL_RW},
+ {CSU_CSLX_USB_2, CSU_ALL_RW},
+ {CSU_CSLX_I2C3, CSU_ALL_RW},
+ {CSU_CSLX_I2C2, CSU_ALL_RW},
+ {CSU_CSLX_DUART2, CSU_ALL_RW},
+ {CSU_CSLX_DUART1, CSU_ALL_RW},
+ {CSU_CSLX_WDT2, CSU_ALL_RW},
+ {CSU_CSLX_WDT1, CSU_ALL_RW},
+ {CSU_CSLX_EDMA, CSU_ALL_RW},
+ {CSU_CSLX_SYS_CNT, CSU_ALL_RW},
+ {CSU_CSLX_DMA_MUX2, CSU_ALL_RW},
+ {CSU_CSLX_DMA_MUX1, CSU_ALL_RW},
+ {CSU_CSLX_DDR, CSU_ALL_RW},
+ {CSU_CSLX_QUICC, CSU_ALL_RW},
+ {CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW},
+ {CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW},
+ {CSU_CSLX_SFP, CSU_ALL_RW},
+ {CSU_CSLX_TMU, CSU_ALL_RW},
+ {CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW},
+ {CSU_CSLX_SCFG, CSU_ALL_RW},
+ {CSU_CSLX_FM, CSU_ALL_RW},
+ {CSU_CSLX_SEC5_5, CSU_ALL_RW},
+ {CSU_CSLX_BM, CSU_ALL_RW},
+ {CSU_CSLX_QM, CSU_ALL_RW},
+ {CSU_CSLX_GPIO2, CSU_ALL_RW},
+ {CSU_CSLX_GPIO1, CSU_ALL_RW},
+ {CSU_CSLX_GPIO4, CSU_ALL_RW},
+ {CSU_CSLX_GPIO3, CSU_ALL_RW},
+ {CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW},
+ {CSU_CSLX_CSU, CSU_ALL_RW},
+ {CSU_CSLX_IIC4, CSU_ALL_RW},
+ {CSU_CSLX_WDT4, CSU_ALL_RW},
+ {CSU_CSLX_WDT3, CSU_ALL_RW},
+ {CSU_CSLX_ESDHC2, CSU_ALL_RW},
+ {CSU_CSLX_WDT5, CSU_ALL_RW},
+ {CSU_CSLX_SAI2, CSU_ALL_RW},
+ {CSU_CSLX_SAI1, CSU_ALL_RW},
+ {CSU_CSLX_SAI4, CSU_ALL_RW},
+ {CSU_CSLX_SAI3, CSU_ALL_RW},
+ {CSU_CSLX_FTM2, CSU_ALL_RW},
+ {CSU_CSLX_FTM1, CSU_ALL_RW},
+ {CSU_CSLX_FTM4, CSU_ALL_RW},
+ {CSU_CSLX_FTM3, CSU_ALL_RW},
+ {CSU_CSLX_FTM6, CSU_ALL_RW},
+ {CSU_CSLX_FTM5, CSU_ALL_RW},
+ {CSU_CSLX_FTM8, CSU_ALL_RW},
+ {CSU_CSLX_FTM7, CSU_ALL_RW},
+ {CSU_CSLX_DSCR, CSU_ALL_RW},
+};
+
+#endif /* NS_ACCESS_H */
diff --git a/plat/nxp/soc-ls1046a/include/soc.h b/plat/nxp/soc-ls1046a/include/soc.h
new file mode 100644
index 0000000..67810c3
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/include/soc.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+/* Chassis specific defines - common across SoC's of a particular platform */
+#include <dcfg_lsch2.h>
+
+#include <soc_default_base_addr.h>
+#include <soc_default_helper_macros.h>
+
+/* DDR Regions Info */
+#define NUM_DRAM_REGIONS U(3)
+#define NXP_DRAM0_ADDR ULL(0x80000000)
+#define NXP_DRAM0_MAX_SIZE ULL(0x80000000) /* 2 GB */
+
+#define NXP_DRAM1_ADDR ULL(0x880000000)
+#define NXP_DRAM1_MAX_SIZE ULL(0x780000000) /* 30 GB */
+
+#define NXP_DRAM2_ADDR ULL(0x8800000000)
+#define NXP_DRAM2_MAX_SIZE ULL(0x7800000000) /* 480 GB */
+
+/*DRAM0 Size defined in platform_def.h */
+#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE
+
+/*
+ * SVR Definition (not include major and minor rev)
+ * A: without security
+ * AE: with security
+ */
+#define SVR_LS1026A 0x870709
+#define SVR_LS1026AE 0x870708
+#define SVR_LS1046A 0x870701
+#define SVR_LS1046AE 0x870700
+
+/* Number of cores in platform */
+/* Used by common code for array initialization */
+#define NUMBER_OF_CLUSTERS U(1)
+#define CORES_PER_CLUSTER U(4)
+#define PLATFORM_CORE_COUNT (NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER)
+
+/*
+ * Required LS standard platform porting definitions
+ * for CCI-400
+ */
+#define NXP_CCI_CLUSTER0_SL_IFACE_IX 4
+
+
+/* Defines required for using XLAT tables from ARM common code */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 40)
+
+/* Clock Divisors */
+#define NXP_PLATFORM_CLK_DIVIDER U(1)
+#define NXP_UART_CLK_DIVIDER U(2)
+
+/* set to 0 if the clusters are not symmetrical */
+#define SYMMETRICAL_CLUSTERS U(1)
+
+ /*
+ * set this switch to 1 if you need to keep the debug block
+ * clocked during system power-down
+ */
+#define DEBUG_ACTIVE 0
+
+ /*
+ * pwr mgmt features supported in the soc-specific code:
+ * value == 0x0 the soc code does not support this feature
+ * value != 0x0 the soc code supports this feature
+ */
+#define SOC_CORE_RELEASE 0x1
+#define SOC_CORE_RESTART 0x1
+#define SOC_CORE_OFF 0x1
+#define SOC_CORE_STANDBY 0x1
+#define SOC_CORE_PWR_DWN 0x1
+#define SOC_CLUSTER_STANDBY 0x1
+#define SOC_CLUSTER_PWR_DWN 0x1
+#define SOC_SYSTEM_STANDBY 0x1
+#define SOC_SYSTEM_PWR_DWN 0x1
+#define SOC_SYSTEM_OFF 0x1
+#define SOC_SYSTEM_RESET 0x1
+
+/* Start: Macros used by lib/psci files */
+#define SYSTEM_PWR_DOMAINS 1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ NUMBER_OF_CLUSTERS + \
+ SYSTEM_PWR_DOMAINS)
+
+/* Power state coordination occurs at the system level */
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/* define retention state */
+#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1)
+
+/* define power-down state */
+#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ *
+ * CACHE_WRITEBACK_GRANULE is defined in soc.def
+ */
+
+ /* One cache line needed for bakery locks on ARM platforms */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+#ifndef __ASSEMBLER__
+/* CCI slave interfaces */
+static const int cci_map[] = {
+ NXP_CCI_CLUSTER0_SL_IFACE_IX,
+};
+
+void soc_init_lowlevel(void);
+void soc_init_percpu(void);
+void _soc_set_start_addr(unsigned long addr);
+#endif
+
+#endif /* SOC_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c b/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c
new file mode 100644
index 0000000..3d561c7
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+
+#include <errata.h>
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+const struct ddr_cfg_regs static_1600 = {
+ .cs[0].config = U(0x80010412),
+ .cs[0].bnds = U(0x7F),
+ .sdram_cfg[0] = U(0xE50C0008),
+ .sdram_cfg[1] = U(0x00401010),
+ .sdram_cfg[2] = U(0x1),
+ .timing_cfg[0] = U(0xFA550018),
+ .timing_cfg[1] = U(0xBAB40C52),
+ .timing_cfg[2] = U(0x0048C11C),
+ .timing_cfg[3] = U(0x01111000),
+ .timing_cfg[4] = U(0x00000002),
+ .timing_cfg[5] = U(0x03401400),
+ .timing_cfg[6] = U(0x0),
+ .timing_cfg[7] = U(0x23300000),
+ .timing_cfg[8] = U(0x02116600),
+ .timing_cfg[9] = U(0x0),
+ .dq_map[0] = U(0x0),
+ .dq_map[1] = U(0x0),
+ .dq_map[2] = U(0x0),
+ .dq_map[3] = U(0x0),
+ .sdram_mode[0] = U(0x01010210),
+ .sdram_mode[1] = U(0x0),
+ .sdram_mode[8] = U(0x00000500),
+ .sdram_mode[9] = U(0x04000000),
+ .interval = U(0x18600618),
+ .zq_cntl = U(0x8A090705),
+ .ddr_sr_cntr = U(0x0),
+ .clk_cntl = U(0x2000000),
+ .cdr[0] = U(0x80040000),
+ .cdr[1] = U(0xC1),
+ .wrlvl_cntl[0] = U(0x86550607),
+ .wrlvl_cntl[1] = U(0x07070708),
+ .wrlvl_cntl[2] = U(0x0808088),
+};
+
+long long board_static_ddr(struct ddr_info *priv)
+{
+ memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600));
+
+ return 0x80000000ULL;
+}
+#else /* ifndef CONFIG_STATIC_DDR */
+static const struct rc_timing rcz[] = {
+ {U(1600), U(8), U(7)},
+ {U(2100), U(8), U(7)},
+ {}
+};
+
+static const struct board_timing ram[] = {
+ {U(0x1f), rcz, U(0x01010101), U(0x01010101)},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ int ret;
+ struct memctl_opt *popts = &priv->opt;
+
+ ret = cal_board_params(priv, ram, ARRAY_SIZE(ram));
+ if (ret != 0) {
+ return ret;
+ }
+
+ popts->bstopre = 0;
+ popts->half_strength_drive_en = 1;
+ popts->cpo_sample = U(0x46);
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_50ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_50ohm) |
+ DDR_CDR2_VREF_TRAIN_EN;
+ popts->output_driver_impedance = 1;
+
+ return 0;
+}
+
+/* DDR model number: MT40A512M16JY-083E:B */
+struct dimm_params ddr_raw_timing = {
+ .n_ranks = U(1),
+ .rank_density = ULL(4294967296),
+ .capacity = ULL(4294967296),
+ .primary_sdram_width = U(64),
+ .ec_sdram_width = U(8),
+ .rdimm = U(0),
+ .mirrored_dimm = U(0),
+ .n_row_addr = U(16),
+ .n_col_addr = U(10),
+ .bank_group_bits = U(1),
+ .edc_config = U(2),
+ .burst_lengths_bitmask = U(0x0c),
+ .tckmin_x_ps = 750,
+ .tckmax_ps = 1900,
+ .caslat_x = U(0x0001FFE00),
+ .taa_ps = 13500,
+ .trcd_ps = 13500,
+ .trp_ps = 13500,
+ .tras_ps = 33000,
+ .trc_ps = 46500,
+ .twr_ps = 15000,
+ .trfc1_ps = 350000,
+ .trfc2_ps = 260000,
+ .trfc4_ps = 160000,
+ .tfaw_ps = 30000,
+ .trrds_ps = 5300,
+ .trrdl_ps = 6400,
+ .tccdl_ps = 5355,
+ .refresh_rate_ps = U(7800000),
+ .dq_mapping[0] = U(0x0),
+ .dq_mapping[1] = U(0x0),
+ .dq_mapping[2] = U(0x0),
+ .dq_mapping[3] = U(0x0),
+ .dq_mapping[4] = U(0x0),
+ .dq_mapping_ors = U(0),
+ .rc = U(0x1f),
+};
+
+int ddr_get_ddr_params(struct dimm_params *pdimm, struct ddr_conf *conf)
+{
+ static const char dimm_model[] = "Fixed DDR on board";
+
+ conf->dimm_in_use[0] = 1;
+ memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params));
+ memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+
+ return 1;
+}
+#endif /* ifdef CONFIG_STATIC_DDR */
+
+long long init_ddr(void)
+{
+ int spd_addr[] = {NXP_SPD_EEPROM0};
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys)) {
+ ERROR("System clocks are not set\n");
+ assert(0);
+ }
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
+
+ zeromem(&info, sizeof(struct ddr_info));
+ info.num_ctlrs = 1;
+ info.dimm_on_ctlr = 1;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+ dram_size = dram_init(&info);
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+#ifdef ERRATA_SOC_A008850
+ erratum_a008850_post();
+#endif
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h b/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h
new file mode 100644
index 0000000..5134a00
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+/*
+ * Required without TBBR.
+ * To include the defines for DDR PHY Images.
+ */
+#include <tbbr_img_def.h>
+
+#include "policy.h"
+#include <soc.h>
+
+#define NXP_SPD_EEPROM0 0x51
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0x8000)
+#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000)
+
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_BLOCK_DEVICES U(1)
+#define MAX_IO_HANDLES U(4)
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES U(2)
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES U(1)
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define BL32_IRQ_SEC_PHY_TIMER 29
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_LS_G0_IRQ_PROPS(grp)
+
+#endif /* PLAT_DEF_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c
new file mode 100644
index 0000000..cef920f
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk
new file mode 100644
index 0000000..1f7fad6
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk
@@ -0,0 +1,39 @@
+#
+# Copyright 2018-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+
+BOOT_MODE ?= qspi
+BOARD := ls1046afrwy
+POVDD_ENABLE := no
+
+# DDR Compilation Configs
+CONFIG_STATIC_DDR := 0
+CONFIG_DDR_NODIMM := 1
+DDRC_NUM_DIMM := 0
+NUM_OF_DDRC := 1
+DDRC_NUM_CS := 1
+DDR_ECC_EN := yes
+
+# On-Board Flash Details
+QSPI_FLASH_SZ := 0x20000000
+NOR_FLASH_SZ := 0x20000000
+
+# Platform specific features.
+WARM_BOOT := no
+
+# Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := qspi \
+ sd
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-ls1046a/soc.mk
diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h b/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h
new file mode 100644
index 0000000..7f98bb1
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h b/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h
new file mode 100644
index 0000000..c6c325f
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/* Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c b/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c
new file mode 100644
index 0000000..89c9c0a
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+
+#include <errata.h>
+#include "platform_def.h"
+
+static const struct rc_timing rce[] = {
+ {U(1600), U(8), U(7)},
+ {U(1867), U(8), U(7)},
+ {U(2134), U(8), U(9)},
+ {}
+};
+
+static const struct board_timing udimm[] = {
+ {U(0x04), rce, U(0x01020304), U(0x06070805)},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ int ret;
+ struct memctl_opt *popts = &priv->opt;
+
+ if (popts->rdimm) {
+ debug("RDIMM parameters not set.\n");
+ return -EINVAL;
+ }
+
+ ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm));
+ if (ret != 0) {
+ return ret;
+ }
+
+ popts->wrlvl_override = U(1);
+ popts->wrlvl_sample = U(0x0); /* 32 clocks */
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
+ DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
+ DDR_CDR2_VREF_TRAIN_EN |
+ DDR_CDR2_VREF_RANGE_2;
+
+ /* optimize cpo for erratum A-009942 */
+ popts->cpo_sample = U(0x70);
+
+ return 0;
+}
+
+long long init_ddr(void)
+{
+ int spd_addr[] = { NXP_SPD_EEPROM0 };
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys)) {
+ ERROR("System clocks are not set\n");
+ assert(0);
+ }
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
+
+ zeromem(&info, sizeof(struct ddr_info));
+ info.num_ctlrs = 1;
+ info.dimm_on_ctlr = 1;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+ dram_size = dram_init(&info);
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+#ifdef ERRATA_SOC_A008850
+ erratum_a008850_post();
+#endif
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h b/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h
new file mode 100644
index 0000000..aa69a66
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+/* Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+#define NXP_SPD_EEPROM0 0x51
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0x00100000)
+#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000)
+
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_BLOCK_DEVICES U(1)
+#define MAX_IO_HANDLES U(4)
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES U(2)
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES U(1)
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define BL32_IRQ_SEC_PHY_TIMER 29
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_LS_G0_IRQ_PROPS(grp)
+
+#endif
diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/platform.c b/plat/nxp/soc-ls1046a/ls1046aqds/platform.c
new file mode 100644
index 0000000..cef920f
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046aqds/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk b/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk
new file mode 100644
index 0000000..9600b93
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk
@@ -0,0 +1,39 @@
+#
+# Copyright 2018-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+BOOT_MODE ?= qspi
+BOARD := ls1046aqds
+POVDD_ENABLE := no
+
+ # DDR Compilation Configs
+NUM_OF_DDRC := 1
+DDRC_NUM_DIMM := 1
+DDRC_NUM_CS := 4
+DDR_ECC_EN := yes
+CONFIG_STATIC_DDR := 0
+
+# On-Board Flash Details
+QSPI_FLASH_SZ := 0x20000000
+NOR_FLASH_SZ := 0x20000000
+
+# Platform specific features.
+WARM_BOOT := no
+
+# Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := qspi \
+ sd \
+ nor \
+ nand
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-ls1046a/soc.mk
diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h b/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h
new file mode 100644
index 0000000..7f98bb1
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046aqds/policy.h b/plat/nxp/soc-ls1046a/ls1046aqds/policy.h
new file mode 100644
index 0000000..c6c325f
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046aqds/policy.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/* Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c b/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c
new file mode 100644
index 0000000..b9940cf
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+
+#include <errata.h>
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+const struct ddr_cfg_regs static_2100 = {
+ .cs[0].config = U(0x80040322),
+ .cs[0].bnds = U(0x1FF),
+ .cs[1].config = U(0x80000322),
+ .cs[1].bnds = U(0x1FF),
+ .sdram_cfg[0] = U(0xE5004000),
+ .sdram_cfg[1] = U(0x401151),
+ .timing_cfg[0] = U(0xD1770018),
+ .timing_cfg[1] = U(0xF2FC9245),
+ .timing_cfg[2] = U(0x594197),
+ .timing_cfg[3] = U(0x2101100),
+ .timing_cfg[4] = U(0x220002),
+ .timing_cfg[5] = U(0x5401400),
+ .timing_cfg[7] = U(0x26600000),
+ .timing_cfg[8] = U(0x5446A00),
+ .dq_map[0] = U(0x32C57554),
+ .dq_map[1] = U(0xD4BB0BD4),
+ .dq_map[2] = U(0x2EC2F554),
+ .dq_map[3] = U(0xD95D4001),
+ .sdram_mode[0] = U(0x3010631),
+ .sdram_mode[1] = U(0x100200),
+ .sdram_mode[9] = U(0x8400000),
+ .sdram_mode[8] = U(0x500),
+ .sdram_mode[2] = U(0x10631),
+ .sdram_mode[3] = U(0x100200),
+ .sdram_mode[10] = U(0x400),
+ .sdram_mode[11] = U(0x8400000),
+ .sdram_mode[4] = U(0x10631),
+ .sdram_mode[5] = U(0x100200),
+ .sdram_mode[12] = U(0x400),
+ .sdram_mode[13] = U(0x8400000),
+ .sdram_mode[6] = U(0x10631),
+ .sdram_mode[7] = U(0x100200),
+ .sdram_mode[14] = U(0x400),
+ .sdram_mode[15] = U(0x8400000),
+ .interval = U(0x1FFE07FF),
+ .zq_cntl = U(0x8A090705),
+ .clk_cntl = U(0x2000000),
+ .cdr[0] = U(0x80040000),
+ .cdr[1] = U(0xC1),
+ .wrlvl_cntl[0] = U(0x86750609),
+ .wrlvl_cntl[1] = U(0xA0B0C0D),
+ .wrlvl_cntl[2] = U(0xF10110E),
+};
+
+const struct ddr_cfg_regs static_1800 = {
+ .cs[0].config = U(0x80040322),
+ .cs[0].bnds = U(0x1FF),
+ .cs[1].config = U(0x80000322),
+ .cs[1].bnds = U(0x1FF),
+ .sdram_cfg[0] = U(0xE5004000),
+ .sdram_cfg[1] = U(0x401151),
+ .timing_cfg[0] = U(0x91660018),
+ .timing_cfg[1] = U(0xDDD82045),
+ .timing_cfg[2] = U(0x512153),
+ .timing_cfg[3] = U(0x10E1100),
+ .timing_cfg[4] = U(0x220002),
+ .timing_cfg[5] = U(0x4401400),
+ .timing_cfg[7] = U(0x14400000),
+ .timing_cfg[8] = U(0x3335900),
+ .dq_map[0] = U(0x32C57554),
+ .dq_map[1] = U(0xD4BB0BD4),
+ .dq_map[2] = U(0x2EC2F554),
+ .dq_map[3] = U(0xD95D4001),
+ .sdram_mode[0] = U(0x3010421),
+ .sdram_mode[1] = U(0x80200),
+ .sdram_mode[9] = U(0x4400000),
+ .sdram_mode[8] = U(0x500),
+ .sdram_mode[2] = U(0x10421),
+ .sdram_mode[3] = U(0x80200),
+ .sdram_mode[10] = U(0x400),
+ .sdram_mode[11] = U(0x4400000),
+ .sdram_mode[4] = U(0x10421),
+ .sdram_mode[5] = U(0x80200),
+ .sdram_mode[12] = U(0x400),
+ .sdram_mode[13] = U(0x4400000),
+ .sdram_mode[6] = U(0x10421),
+ .sdram_mode[7] = U(0x80200),
+ .sdram_mode[14] = U(0x400),
+ .sdram_mode[15] = U(0x4400000),
+ .interval = U(0x1B6C06DB),
+ .zq_cntl = U(0x8A090705),
+ .clk_cntl = U(0x2000000),
+ .cdr[0] = U(0x80040000),
+ .cdr[1] = U(0xC1),
+ .wrlvl_cntl[0] = U(0x86750607),
+ .wrlvl_cntl[1] = U(0x8090A0B),
+ .wrlvl_cntl[2] = U(0xD0E0F0C),
+};
+
+const struct ddr_cfg_regs static_1600 = {
+ .cs[0].config = U(0x80040322),
+ .cs[0].bnds = U(0x1FF),
+ .cs[1].config = U(0x80000322),
+ .cs[1].bnds = U(0x1FF),
+ .sdram_cfg[0] = U(0xE5004000),
+ .sdram_cfg[1] = U(0x401151),
+ .sdram_cfg[2] = U(0x0),
+ .timing_cfg[0] = U(0x91550018),
+ .timing_cfg[1] = U(0xBAB48E44),
+ .timing_cfg[2] = U(0x490111),
+ .timing_cfg[3] = U(0x10C1000),
+ .timing_cfg[4] = U(0x220002),
+ .timing_cfg[5] = U(0x3401400),
+ .timing_cfg[6] = U(0x0),
+ .timing_cfg[7] = U(0x13300000),
+ .timing_cfg[8] = U(0x1224800),
+ .timing_cfg[9] = U(0x0),
+ .dq_map[0] = U(0x32C57554),
+ .dq_map[1] = U(0xD4BB0BD4),
+ .dq_map[2] = U(0x2EC2F554),
+ .dq_map[3] = U(0xD95D4001),
+ .sdram_mode[0] = U(0x3010211),
+ .sdram_mode[1] = U(0x0),
+ .sdram_mode[9] = U(0x400000),
+ .sdram_mode[8] = U(0x500),
+ .sdram_mode[2] = U(0x10211),
+ .sdram_mode[3] = U(0x0),
+ .sdram_mode[10] = U(0x400),
+ .sdram_mode[11] = U(0x400000),
+ .sdram_mode[4] = U(0x10211),
+ .sdram_mode[5] = U(0x0),
+ .sdram_mode[12] = U(0x400),
+ .sdram_mode[13] = U(0x400000),
+ .sdram_mode[6] = U(0x10211),
+ .sdram_mode[7] = U(0x0),
+ .sdram_mode[14] = U(0x400),
+ .sdram_mode[15] = U(0x400000),
+ .interval = U(0x18600618),
+ .zq_cntl = U(0x8A090705),
+ .ddr_sr_cntr = U(0x0),
+ .clk_cntl = U(0x2000000),
+ .cdr[0] = U(0x80040000),
+ .cdr[1] = U(0xC1),
+ .wrlvl_cntl[0] = U(0x86750607),
+ .wrlvl_cntl[1] = U(0x8090A0B),
+ .wrlvl_cntl[2] = U(0xD0E0F0C),
+};
+
+struct static_table {
+ unsigned long rate;
+ const struct ddr_cfg_regs *regs;
+};
+
+const struct static_table table[] = {
+ {1600, &static_1600},
+ {1800, &static_1800},
+ {2100, &static_2100},
+};
+
+long long board_static_ddr(struct ddr_info *priv)
+{
+ const unsigned long clk = priv->clk / 1000000;
+ long long size = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(table); i++) {
+ if (table[i].rate >= clk) {
+ break;
+ }
+ }
+ if (i < ARRAY_SIZE(table)) {
+ VERBOSE("Found static setting for rate %ld\n", table[i].rate);
+ memcpy(&priv->ddr_reg, table[i].regs,
+ sizeof(struct ddr_cfg_regs));
+ size = 0x200000000UL;
+ } else {
+ ERROR("Not static settings for rate %ld\n", clk);
+ }
+
+ return size;
+}
+#else /* ifndef CONFIG_STATIC_DDR */
+static const struct rc_timing rce[] = {
+ {U(1600), U(8), U(7)},
+ {U(1867), U(8), U(7)},
+ {U(2134), U(8), U(9)},
+ {}
+};
+
+static const struct board_timing udimm[] = {
+ {U(0x04), rce, U(0x01020304), U(0x06070805)},
+ {U(0x1f), rce, U(0x01020304), U(0x06070805)},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ int ret;
+ struct memctl_opt *popts = &priv->opt;
+
+ if (popts->rdimm) {
+ debug("RDIMM parameters not set.\n");
+ return -EINVAL;
+ }
+
+ ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm));
+ if (ret != 0) {
+ return ret;
+ }
+
+ popts->wrlvl_override = U(1);
+ popts->wrlvl_sample = U(0x0); /* 32 clocks */
+ popts->cpo_sample = U(0x61);
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
+ DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
+ DDR_CDR2_VREF_TRAIN_EN |
+ DDR_CDR2_VREF_RANGE_2;
+ popts->bstopre = U(0);
+
+ return 0;
+}
+#endif /* ifdef CONFIG_STATIC_DDR */
+
+long long init_ddr(void)
+{
+ int spd_addr[] = {NXP_SPD_EEPROM0};
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys)) {
+ ERROR("System clocks are not set\n");
+ assert(0);
+ }
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
+
+ zeromem(&info, sizeof(struct ddr_info));
+ info.num_ctlrs = U(1);
+ info.dimm_on_ctlr = U(1);
+ info.clk = get_ddr_freq(&sys, 0);
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+ dram_size = dram_init(&info);
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+#ifdef ERRATA_SOC_A008850
+ erratum_a008850_post();
+#endif
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h b/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h
new file mode 100644
index 0000000..b5e66ae
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+/*
+ * Required without TBBR.
+ * To include the defines for DDR PHY Images.
+ */
+#include <tbbr_img_def.h>
+
+#include "policy.h"
+#include <soc.h>
+
+#define NXP_SPD_EEPROM0 0x51
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0x00100000)
+#define NXP_SD_BLOCK_BUF_ADDR ULL(0x80000000)
+
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_BLOCK_DEVICES U(1)
+#define MAX_IO_HANDLES U(4)
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES U(2)
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES U(1)
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define BL32_IRQ_SEC_PHY_TIMER 29
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_LS_G0_IRQ_PROPS(grp)
+
+#endif /* PLAT_DEF_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/platform.c b/plat/nxp/soc-ls1046a/ls1046ardb/platform.c
new file mode 100644
index 0000000..cef920f
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046ardb/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk b/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk
new file mode 100644
index 0000000..32e6db5
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk
@@ -0,0 +1,38 @@
+#
+# Copyright 2018-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+BOOT_MODE ?= qspi
+BOARD := ls1046ardb
+POVDD_ENABLE := no
+
+# DDR Compilation Configs
+NUM_OF_DDRC := 1
+DDRC_NUM_DIMM := 1
+DDRC_NUM_CS := 4
+DDR_ECC_EN := yes
+CONFIG_STATIC_DDR := 0
+
+# On-Board Flash Details
+QSPI_FLASH_SZ := 0x20000000
+NOR_FLASH_SZ := 0x20000000
+
+# Platform specific features.
+WARM_BOOT := no
+
+# Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := qspi \
+ sd \
+ emmc
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-ls1046a/soc.mk
diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h b/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h
new file mode 100644
index 0000000..7f98bb1
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1046a/ls1046ardb/policy.h b/plat/nxp/soc-ls1046a/ls1046ardb/policy.h
new file mode 100644
index 0000000..c6c325f
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/ls1046ardb/policy.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/* Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1046a/soc.c b/plat/nxp/soc-ls1046a/soc.c
new file mode 100644
index 0000000..d17e672
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/soc.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2018-2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <caam.h>
+#include <cassert.h>
+#include <cci.h>
+#include <common/debug.h>
+#include <dcfg.h>
+#ifdef I2C_INIT
+#include <i2c.h>
+#endif
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <ls_interconnect.h>
+#ifdef POLICY_FUSE_PROVISION
+#include <nxp_gpio.h>
+#endif
+#if TRUSTED_BOARD_BOOT
+#include <nxp_smmu.h>
+#endif
+#include <nxp_timer.h>
+#include <plat_console.h>
+#include <plat_gic.h>
+#include <plat_tzc400.h>
+#include <scfg.h>
+#if defined(NXP_SFP_ENABLED)
+#include <sfp.h>
+#endif
+
+#include <errata.h>
+#include <ns_access.h>
+#ifdef CONFIG_OCRAM_ECC_EN
+#include <ocram.h>
+#endif
+#include <plat_common.h>
+#include <platform_def.h>
+#include <soc.h>
+
+static dcfg_init_info_t dcfg_init_data = {
+ .g_nxp_dcfg_addr = NXP_DCFG_ADDR,
+ .nxp_sysclk_freq = NXP_SYSCLK_FREQ,
+ .nxp_ddrclk_freq = NXP_DDRCLK_FREQ,
+ .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER,
+};
+
+/* Function to return the SoC SYS CLK */
+static unsigned int get_sys_clk(void)
+{
+ return NXP_SYSCLK_FREQ;
+}
+
+/*
+ * Function returns the base counter frequency
+ * after reading the first entry at CNTFID0 (0x20 offset).
+ *
+ * Function is used by:
+ * 1. ARM common code for PSCI management.
+ * 2. ARM Generic Timer init.
+ *
+ */
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+
+ counter_base_frequency = get_sys_clk() / 4;
+
+ return counter_base_frequency;
+}
+
+#ifdef IMAGE_BL2
+/* Functions for BL2 */
+
+static struct soc_type soc_list[] = {
+ SOC_ENTRY(LS1046A, LS1046A, 1, 4),
+ SOC_ENTRY(LS1046AE, LS1046AE, 1, 4),
+ SOC_ENTRY(LS1026A, LS1026A, 1, 2),
+ SOC_ENTRY(LS1026AE, LS1026AE, 1, 2),
+};
+
+#ifdef POLICY_FUSE_PROVISION
+static gpio_init_info_t gpio_init_data = {
+ .gpio1_base_addr = NXP_GPIO1_ADDR,
+ .gpio2_base_addr = NXP_GPIO2_ADDR,
+ .gpio3_base_addr = NXP_GPIO3_ADDR,
+ .gpio4_base_addr = NXP_GPIO4_ADDR,
+};
+#endif
+
+/*
+ * Function to set the base counter frequency at
+ * the first entry of the Frequency Mode Table,
+ * at CNTFID0 (0x20 offset).
+ *
+ * Set the value of the pirmary core register cntfrq_el0.
+ */
+static void set_base_freq_CNTFID0(void)
+{
+ /*
+ * Below register specifies the base frequency of the system counter.
+ * As per NXP Board Manuals:
+ * The system counter always works with SYS_REF_CLK/4 frequency clock.
+ */
+ unsigned int counter_base_frequency = get_sys_clk() / 4;
+
+ /* Setting the frequency in the Frequency modes table.
+ *
+ * Note: The value for ls1046ardb board at this offset
+ * is not RW as stated. This offset have the
+ * fixed value of 100000400 Hz.
+ *
+ * The below code line has no effect.
+ * Keeping it for other platforms where it has effect.
+ */
+ mmio_write_32(NXP_TIMER_ADDR + CNTFID_OFF, counter_base_frequency);
+
+ write_cntfrq_el0(counter_base_frequency);
+}
+
+void soc_preload_setup(void)
+{
+
+}
+
+/*
+ * This function implements soc specific erratas
+ * This is called before DDR is initialized or MMU is enabled
+ */
+void soc_early_init(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+ dram_regions_info_t *dram_regions_info = get_dram_regions_info();
+
+#ifdef CONFIG_OCRAM_ECC_EN
+ ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE);
+#endif
+ dcfg_init(&dcfg_init_data);
+#ifdef POLICY_FUSE_PROVISION
+ gpio_init(&gpio_init_data);
+ sec_init(NXP_CAAM_ADDR);
+#endif
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+ set_base_freq_CNTFID0();
+
+ /* Enable snooping on SEC read and write transactions */
+ scfg_setbits32((void *)(NXP_SCFG_ADDR + SCFG_SNPCNFGCR_OFFSET),
+ SCFG_SNPCNFGCR_SECRDSNP | SCFG_SNPCNFGCR_SECWRSNP);
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ plat_ls_interconnect_enter_coherency(num_clusters);
+
+#if TRUSTED_BOARD_BOOT
+ uint32_t mode;
+
+ sfp_init(NXP_SFP_ADDR);
+ /*
+ * For secure boot disable SMMU.
+ * Later when platform security policy comes in picture,
+ * this might get modified based on the policy
+ */
+ if (check_boot_mode_secure(&mode) == true) {
+ bypass_smmu(NXP_SMMU_ADDR);
+ }
+
+ /*
+ * For Mbedtls currently crypto is not supported via CAAM
+ * enable it when that support is there. In tbbr.mk
+ * the CAAM_INTEG is set as 0.
+ */
+#ifndef MBEDTLS_X509
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false) {
+ INFO("SEC is disabled.\n");
+ } else {
+ sec_init(NXP_CAAM_ADDR);
+ }
+#endif
+#elif defined(POLICY_FUSE_PROVISION)
+ gpio_init(&gpio_init_data);
+ sfp_init(NXP_SFP_ADDR);
+ sec_init(NXP_CAAM_ADDR);
+#endif
+
+ soc_errata();
+
+ /* Initialize system level generic timer for Layerscape Socs. */
+ delay_timer_init(NXP_TIMER_ADDR);
+
+#ifdef DDR_INIT
+ i2c_init(NXP_I2C_ADDR);
+ dram_regions_info->total_dram_size = init_ddr();
+#endif
+}
+
+void soc_bl2_prepare_exit(void)
+{
+#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE)
+ set_sfp_wr_disable();
+#endif
+}
+
+/* This function returns the boot device based on RCW_SRC */
+enum boot_device get_boot_dev(void)
+{
+ enum boot_device src = BOOT_DEVICE_NONE;
+ uint32_t porsr1;
+ uint32_t rcw_src, val;
+
+ porsr1 = read_reg_porsr1();
+
+ rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT;
+
+ val = rcw_src & RCW_SRC_NAND_MASK;
+
+ if (val == RCW_SRC_NAND_VAL) {
+ val = rcw_src & NAND_RESERVED_MASK;
+ if ((val != NAND_RESERVED_1) && (val != NAND_RESERVED_2)) {
+ src = BOOT_DEVICE_IFC_NAND;
+ INFO("RCW BOOT SRC is IFC NAND\n");
+ }
+ } else {
+ /* RCW SRC NOR */
+ val = rcw_src & RCW_SRC_NOR_MASK;
+ if (val == NOR_8B_VAL || val == NOR_16B_VAL) {
+ src = BOOT_DEVICE_IFC_NOR;
+ INFO("RCW BOOT SRC is IFC NOR\n");
+ } else {
+ switch (rcw_src) {
+ case QSPI_VAL1:
+ case QSPI_VAL2:
+ src = BOOT_DEVICE_QSPI;
+ INFO("RCW BOOT SRC is QSPI\n");
+ break;
+ case SD_VAL:
+ src = BOOT_DEVICE_EMMC;
+ INFO("RCW BOOT SRC is SD/EMMC\n");
+ break;
+ default:
+ src = BOOT_DEVICE_NONE;
+ }
+ }
+ }
+
+ return src;
+}
+
+/* This function sets up access permissions on memory regions */
+void soc_mem_access(void)
+{
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+ struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION];
+ unsigned int dram_idx, index = 0U;
+
+ for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions;
+ dram_idx++) {
+ if (info_dram_regions->region[dram_idx].size == 0) {
+ ERROR("DDR init failure, or");
+ ERROR("DRAM regions not populated correctly.\n");
+ break;
+ }
+
+ index = populate_tzc400_reg_list(tzc400_reg_list,
+ dram_idx, index,
+ info_dram_regions->region[dram_idx].addr,
+ info_dram_regions->region[dram_idx].size,
+ NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE);
+ }
+
+ mem_access_setup(NXP_TZC_ADDR, index, tzc400_reg_list);
+}
+
+#else /* IMAGE_BL2 */
+/* Functions for BL31 */
+
+const unsigned char _power_domain_tree_desc[] = {1, 1, 4};
+
+CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256,
+ assert_invalid_ls1046_cluster_count);
+
+/* This function returns the SoC topology */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return _power_domain_tree_desc;
+}
+
+/*
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ */
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr)
+{
+ return CORES_PER_CLUSTER;
+}
+
+void soc_early_platform_setup2(void)
+{
+ dcfg_init(&dcfg_init_data);
+ /* Initialize system level generic timer for SoCs */
+ delay_timer_init(NXP_TIMER_ADDR);
+
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+}
+
+void soc_platform_setup(void)
+{
+ static uint32_t target_mask_array[PLATFORM_CORE_COUNT];
+ /*
+ * On a GICv2 system, the Group 1 secure interrupts are treated
+ * as Group 0 interrupts.
+ */
+ static interrupt_prop_t ls_interrupt_props[] = {
+ PLAT_LS_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+ PLAT_LS_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+ };
+
+ plat_ls_gic_driver_init(
+#if (TEST_BL31)
+ /* Defect in simulator - GIC base addresses (4Kb aligned) */
+ NXP_GICD_4K_ADDR,
+ NXP_GICC_4K_ADDR,
+#else
+ NXP_GICD_64K_ADDR,
+ NXP_GICC_64K_ADDR,
+#endif
+ PLATFORM_CORE_COUNT,
+ ls_interrupt_props,
+ ARRAY_SIZE(ls_interrupt_props),
+ target_mask_array);
+
+ plat_ls_gic_init();
+ enable_init_timer();
+}
+
+/* This function initializes the soc from the BL31 module */
+void soc_init(void)
+{
+ /* low-level init of the soc */
+ soc_init_lowlevel();
+ _init_global_data();
+ soc_init_percpu();
+ _initialize_psci();
+
+ /*
+ * Initialize the interconnect during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable coherency in interconnect for the primary CPU's cluster.
+ * Earlier bootloader stages might already do this but we can't
+ * assume so. No harm in executing this code twice.
+ */
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+
+ /* Init CSU to enable non-secure access to peripherals */
+ enable_layerscape_ns_access(ns_dev, ARRAY_SIZE(ns_dev), NXP_CSU_ADDR);
+
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false) {
+ INFO("SEC is disabled.\n");
+ } else {
+ sec_init(NXP_CAAM_ADDR);
+ }
+}
+
+void soc_runtime_setup(void)
+{
+
+}
+
+#endif /* IMAGE_BL2 */
diff --git a/plat/nxp/soc-ls1046a/soc.def b/plat/nxp/soc-ls1046a/soc.def
new file mode 100644
index 0000000..e6b37c0
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/soc.def
@@ -0,0 +1,107 @@
+#
+# Copyright 2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# This file contains the basic architecture definitions that drive the build
+#
+# -----------------------------------------------------------------------------
+
+CORE_TYPE := a72
+
+CACHE_LINE := 6
+
+# set to GIC400 or GIC500
+GIC := GIC400
+
+# set to CCI400 or CCN504 or CCN508
+INTERCONNECT := CCI400
+
+# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2
+CHASSIS := 2
+
+# TZC IP Details TZC used is TZC380 or TZC400
+TZC_ID := TZC400
+
+# CONSOLE Details available is NS16550 or PL011
+CONSOLE := NS16550
+
+ # Select the DDR PHY generation to be used
+PLAT_DDR_PHY := PHY_GEN1
+
+PHYS_SYS := 64
+
+# ddr controller - set to MMDC or NXP
+DDRCNTLR := NXP
+
+# ddr phy - set to NXP or SNPS
+DDRPHY := NXP
+
+# Area of OCRAM reserved by ROM code
+NXP_ROM_RSVD := 0x5900
+
+# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def
+# Input to CST create_hdr_esbc tool
+CSF_HDR_SZ := 0x3000
+
+# In IMAGE_BL2, compile time flag for handling Cache coherency
+# with CAAM for BL2 running from OCRAM
+SEC_MEM_NON_COHERENT := yes
+
+# OCRAM MAP
+OCRAM_START_ADDR := 0x10000000
+OCRAM_SIZE := 0x20000
+
+# BL2 binary is placed at start of OCRAM.
+# Also used by create_pbl.mk.
+BL2_BASE := 0x10000000
+
+# After BL2 bin, OCRAM is used by ROM Code:
+# (OCRAM_START_ADDR + BL2_BIN_SIZE) -> (NXP_ROM_RSVD - 1)
+
+# After ROM Code, OCRAM is used by CSF header.
+# (OCRAM_START_ADDR + BL2_TEXT_LIMIT + NXP_ROM_RSVD) -> (CSF_HDR_SZ - 1)
+
+# BL2_HDR_LOC has to be (OCRAM_START_ADDR + OCRAM_SIZE - NXP_ROM_RSVD - CSF_HDR_SZ)
+# This value should be greater than BL2_TEXT_LIMIT
+# Input to CST create_hdr_isbc tool
+BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(OCRAM_SIZE) - $(NXP_ROM_RSVD) - $(CSF_HDR_SZ))))
+# Covert to HEX to be used by create_pbl.mk
+BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc)
+
+# Core Errata
+ERRATA_A72_859971 := 1
+
+# SoC ERRATAS
+ERRATA_SOC_A008850 := 1
+ERRATA_SOC_A010539 := 1
+
+# DDR Errata
+ERRATA_DDR_A008511 := 1
+ERRATA_DDR_A009803 := 1
+ERRATA_DDR_A009942 := 1
+ERRATA_DDR_A010165 := 1
+
+# enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC := 1
+
+# Define Endianness of each module
+NXP_GUR_ENDIANNESS := BE
+NXP_DDR_ENDIANNESS := BE
+NXP_SEC_ENDIANNESS := BE
+NXP_SFP_ENDIANNESS := BE
+NXP_SNVS_ENDIANNESS := BE
+NXP_ESDHC_ENDIANNESS := BE
+NXP_QSPI_ENDIANNESS := BE
+NXP_FSPI_ENDIANNESS := BE
+NXP_SCFG_ENDIANNESS := BE
+NXP_GPIO_ENDIANNESS := BE
+NXP_IFC_ENDIANNESS := BE
+
+NXP_SFP_VER := 3_2
+
+# OCRAM ECC Enabled
+OCRAM_ECC_EN := yes
diff --git a/plat/nxp/soc-ls1046a/soc.mk b/plat/nxp/soc-ls1046a/soc.mk
new file mode 100644
index 0000000..8207dcd
--- /dev/null
+++ b/plat/nxp/soc-ls1046a/soc.mk
@@ -0,0 +1,114 @@
+#
+# Copyright 2018-2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SoC-specific build parameters
+SOC := ls1046a
+PLAT_PATH := plat/nxp
+PLAT_COMMON_PATH:= plat/nxp/common
+PLAT_DRIVERS_PATH:= drivers/nxp
+PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC}
+BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD}
+
+# Get SoC-specific defnitions
+include ${PLAT_SOC_PATH}/soc.def
+include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk
+include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
+
+# For Security Features
+DISABLE_FUSE_WRITE := 1
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2))
+SECURE_BOOT := yes
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM))
+
+# Selecting Drivers for SoC
+$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,CSU_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+
+# Selecting PSCI & SIP_SVC support
+$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31))
+
+# Source File Addition
+PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\
+ -I${BOARD_PATH}\
+ -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
+ -I${PLAT_SOC_PATH}/include\
+ -I${PLAT_COMMON_PATH}/soc_errata
+
+ifeq (${SECURE_BOOT},yes)
+include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
+endif
+
+ifeq ($(WARM_BOOT),yes)
+include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk
+endif
+
+ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes)
+include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk
+endif
+
+ifeq (${PSCI_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/psci/psci.mk
+endif
+
+ifeq (${SIPSVC_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk
+endif
+
+# For fuse-fip & fuse-programming
+ifeq (${FUSE_PROG}, 1)
+include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk
+endif
+
+ifeq (${IMG_LOADR_NEEDED},yes)
+include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk
+endif
+
+# Adding source files for the above selected drivers.
+include ${PLAT_DRIVERS_PATH}/drivers.mk
+
+# Adding SoC specific files
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
+
+PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\
+ ${WARM_RST_INCLUDES}
+
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\
+ ${WARM_RST_BL31_SOURCES}\
+ ${PSCI_SOURCES}\
+ ${SIPSVC_SOURCES}\
+ ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S
+
+PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\
+ ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\
+ ${NV_STORAGE_SOURCES}\
+ ${WARM_RST_BL_COMM_SOURCES}\
+ ${PLAT_SOC_PATH}/soc.c
+
+ifeq (${TEST_BL31}, 1)
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\
+ ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S
+endif
+
+BL2_SOURCES += ${DDR_CNTLR_SOURCES}\
+ ${TBBR_SOURCES}\
+ ${FUSE_SOURCES}
+
+# Adding TFA setup files
+include ${PLAT_PATH}/common/setup/common.mk
diff --git a/plat/nxp/soc-ls1088a/aarch64/ls1088a.S b/plat/nxp/soc-ls1088a/aarch64/ls1088a.S
new file mode 100644
index 0000000..0c6b7ea
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/aarch64/ls1088a.S
@@ -0,0 +1,1817 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+.section .text, "ax"
+
+#include <asm_macros.S>
+#include <lib/psci/psci.h>
+#include <nxp_timer.h>
+#include <plat_gic.h>
+
+#include "bl31_data.h"
+#include "plat_psci.h"
+#include "platform_def.h"
+
+/*
+ * the BASE address for these offsets is AUX_01_DATA in the
+ * bootcore's psci data region
+ */
+#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */
+#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */
+
+/*
+ * the BASE address for these offsets is AUX_04_DATA in the
+ * bootcore's psci data region
+ */
+#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */
+#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */
+
+#define IPSTPACK_RETRY_CNT 0x10000
+#define DDR_SLEEP_RETRY_CNT 0x10000
+#define CPUACTLR_EL1 S3_1_C15_C2_0
+#define DDR_SDRAM_CFG_2_FRCSR 0x80000000
+#define DDR_SDRAM_CFG_2_OFFSET 0x114
+#define DDR_TIMING_CFG_4_OFFSET 0x160
+#define DDR_CNTRL_BASE_ADDR 0x01080000
+
+#define DLL_LOCK_MASK 0x3
+#define DLL_LOCK_VALUE 0x2
+
+#define ERROR_DDR_SLEEP -1
+#define ERROR_DDR_WAKE -2
+#define ERROR_NO_QUIESCE -3
+
+#define CORE_RESTARTABLE 0
+#define CORE_NOT_RESTARTABLE 1
+
+.global soc_init_lowlevel
+.global soc_init_percpu
+
+.global _soc_core_release
+.global _soc_core_restart
+.global _soc_ck_disabled
+.global _soc_sys_reset
+.global _soc_sys_off
+
+.global _soc_core_prep_off
+.global _soc_core_entr_off
+.global _soc_core_exit_off
+
+.global _soc_core_prep_stdby
+.global _soc_core_entr_stdby
+.global _soc_core_exit_stdby
+.global _soc_core_prep_pwrdn
+.global _soc_core_entr_pwrdn
+.global _soc_core_exit_pwrdn
+.global _soc_clstr_prep_stdby
+.global _soc_clstr_exit_stdby
+.global _soc_clstr_prep_pwrdn
+.global _soc_clstr_exit_pwrdn
+.global _soc_sys_prep_stdby
+.global _soc_sys_exit_stdby
+.global _soc_sys_prep_pwrdn
+.global _soc_sys_pwrdn_wfi
+.global _soc_sys_exit_pwrdn
+
+.global _set_platform_security
+.global _soc_set_start_addr
+
+.equ TZPCDECPROT_0_SET_BASE, 0x02200804
+.equ TZPCDECPROT_1_SET_BASE, 0x02200810
+.equ TZPCDECPROT_2_SET_BASE, 0x0220081C
+
+.equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110
+
+.equ MPIDR_AFFINITY0_MASK, 0x00FF
+.equ MPIDR_AFFINITY1_MASK, 0xFF00
+.equ CPUECTLR_DISABLE_TWALK_PREFETCH, 0x4000000000
+.equ CPUECTLR_INS_PREFETCH_MASK, 0x1800000000
+.equ CPUECTLR_DAT_PREFETCH_MASK, 0x0300000000
+.equ OSDLR_EL1_DLK_LOCK, 0x1
+.equ CNTP_CTL_EL0_EN, 0x1
+.equ CNTP_CTL_EL0_IMASK, 0x2
+/* shifted value for incrementing cluster count in mpidr */
+.equ MPIDR_CLUSTER, 0x100
+
+/*
+ * This function initialize the soc,
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11
+ */
+func soc_init_lowlevel
+ /*
+ * called from C, so save the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ */
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ /*
+ * make sure the personality has been established by releasing cores
+ * that are marked "to-be-disabled" from reset
+ */
+ bl release_disabled
+
+ /* set SCRATCHRW7 to 0x0 */
+ ldr x0, =DCFG_SCRATCHRW7_OFFSET
+ mov x1, xzr
+ bl _write_reg_dcfg
+
+ /* restore the aarch32/64 non-volatile registers */
+ ldp x18, x30, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ ret
+endfunc soc_init_lowlevel
+
+/*
+ * void soc_init_percpu(void)
+ * this function performs any soc-specific initialization that is needed on
+ * a per-core basis
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+func soc_init_percpu
+ stp x4, x30, [sp, #-16]!
+
+ bl plat_my_core_mask
+ mov x2, x0
+
+ /* x2 = core mask */
+
+ /* see if this core is marked for prefetch disable */
+ mov x0, #PREFETCH_DIS_OFFSET
+ bl _get_global_data
+ tst x0, x2
+ b.eq 1f
+ bl _disable_ldstr_pfetch_A53
+1:
+ mov x0, #NXP_PMU_ADDR
+ bl enable_timer_base_to_cluster
+ ldp x4, x30, [sp], #16
+ ret
+endfunc soc_init_percpu
+
+/*
+ * this function sets the security mechanisms in the SoC to implement the
+ * Platform Security Policy
+ */
+func _set_platform_security
+ mov x3, x30
+
+#if (!SUPPRESS_TZC)
+ /* initialize the tzpc */
+ bl init_tzpc
+#endif
+
+#if (!SUPPRESS_SEC)
+ /* initialize secmon */
+ bl initSecMon
+#endif
+ mov x30, x3
+ ret
+endfunc _set_platform_security
+
+/*
+ * this function writes a 64-bit address to bootlocptrh/l
+ * in: x0, 64-bit address to write to BOOTLOCPTRL/H
+ * out: none
+ * uses x0, x1, x2
+ */
+func _soc_set_start_addr
+ /* get the 64-bit base address of the dcfg block */
+ ldr x2, =NXP_DCFG_ADDR
+
+ /* write the 32-bit BOOTLOCPTRL register */
+ mov x1, x0
+ str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET]
+
+ /* write the 32-bit BOOTLOCPTRH register */
+ lsr x1, x0, #32
+ str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET]
+ ret
+endfunc _soc_set_start_addr
+
+/*
+ * part of CPU_ON
+ * this function releases a secondary core from reset
+ * in: x0 = core_mask_lsb
+ * out: none
+ * uses: x0, x1, x2, x3
+ */
+_soc_core_release:
+ mov x3, x30
+
+ /* x0 = core mask */
+
+ ldr x1, =NXP_SEC_REGFILE_ADDR
+ /*
+ * write to CORE_HOLD to tell the bootrom that we want this core
+ * to run
+ */
+ str w0, [x1, #CORE_HOLD_OFFSET]
+
+ /* x0 = core mask */
+
+ /* read-modify-write BRRL to release core */
+ mov x1, #NXP_RESET_ADDR
+ ldr w2, [x1, #BRR_OFFSET]
+ orr w2, w2, w0
+ str w2, [x1, #BRR_OFFSET]
+ dsb sy
+ isb
+
+ /* send event */
+ sev
+ isb
+
+ mov x30, x3
+ ret
+
+/*
+ * this function determines if a core is disabled via COREDISABLEDSR
+ * in: w0 = core_mask_lsb
+ * out: w0 = 0, core not disabled
+ * w0 != 0, core disabled
+ * uses x0, x1
+ */
+_soc_ck_disabled:
+ /* get base addr of dcfg block */
+ ldr x1, =NXP_DCFG_ADDR
+
+ /* read COREDISABLEDSR */
+ ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET]
+
+ /* test core bit */
+ and w0, w1, w0
+
+ ret
+
+/*
+ * part of CPU_ON
+ * this function restarts a core shutdown via _soc_core_entr_off
+ * in: x0 = core mask lsb (of the target cpu)
+ * out: x0 == 0, on success
+ * x0 != 0, on failure
+ * uses x0, x1, x2, x3, x4, x5, x6
+ */
+_soc_core_restart:
+ mov x6, x30
+ mov x4, x0
+
+ /* x4 = core mask lsb */
+
+ /* pgm GICD_CTLR - enable secure grp0 */
+ mov x5, #NXP_GICD_ADDR
+ ldr w2, [x5, #GICD_CTLR_OFFSET]
+ orr w2, w2, #GICD_CTLR_EN_GRP_0
+ str w2, [x5, #GICD_CTLR_OFFSET]
+ dsb sy
+ isb
+ /* poll on RWP til write completes */
+4:
+ ldr w2, [x5, #GICD_CTLR_OFFSET]
+ tst w2, #GICD_CTLR_RWP
+ b.ne 4b
+
+ /*
+ * x4 = core mask lsb
+ * x5 = gicd base addr
+ */
+
+ mov x0, x4
+ bl get_mpidr_value
+
+ /*
+ * x0 = mpidr of target core
+ * x4 = core mask lsb of target core
+ * x5 = gicd base addr
+ */
+
+ /* generate target list bit */
+ and x1, x0, #MPIDR_AFFINITY0_MASK
+ mov x2, #1
+ lsl x2, x2, x1
+ /* get the affinity1 field */
+ and x1, x0, #MPIDR_AFFINITY1_MASK
+ lsl x1, x1, #8
+ orr x2, x2, x1
+ /* insert the INTID for SGI15 */
+ orr x2, x2, #ICC_SGI0R_EL1_INTID
+ /* fire the SGI */
+ msr ICC_SGI0R_EL1, x2
+ dsb sy
+ isb
+
+ /* load '0' on success */
+ mov x0, xzr
+
+ mov x30, x6
+ ret
+
+/*
+ * part of CPU_OFF
+ * this function programs SoC & GIC registers in preparation for shutting down
+ * the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7
+ */
+_soc_core_prep_off:
+ mov x8, x30
+ mov x7, x0
+
+ /* x7 = core mask lsb */
+
+ mrs x1, CPUECTLR_EL1
+ /* set smp and disable L2 snoops in cpuectlr */
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
+ bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK
+ bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK
+ /* set retention control in cpuectlr */
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ orr x1, x1, #CPUECTLR_TIMER_8TICKS
+ msr CPUECTLR_EL1, x1
+
+ /* get redistributor rd base addr for this core */
+ mov x0, x7
+ bl get_gic_rd_base
+ mov x6, x0
+
+ /* get redistributor sgi base addr for this core */
+ mov x0, x7
+ bl get_gic_sgi_base
+ mov x5, x0
+
+ /* x5 = gicr sgi base addr
+ * x6 = gicr rd base addr
+ * x7 = core mask lsb
+ */
+
+ /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
+ mov w3, #GICR_ICENABLER0_SGI15
+ str w3, [x5, #GICR_ICENABLER0_OFFSET]
+2:
+ /* poll on rwp bit in GICR_CTLR */
+ ldr w4, [x6, #GICR_CTLR_OFFSET]
+ tst w4, #GICR_CTLR_RWP
+ b.ne 2b
+
+ /* disable GRP1 interrupts at cpu interface */
+ msr ICC_IGRPEN1_EL3, xzr
+
+ /* disable GRP0 ints at cpu interface */
+ msr ICC_IGRPEN0_EL1, xzr
+
+ /* program the redistributor - poll on GICR_CTLR.RWP as needed */
+
+ /* define SGI 15 as Grp0 - GICR_IGROUPR0 */
+ ldr w4, [x5, #GICR_IGROUPR0_OFFSET]
+ bic w4, w4, #GICR_IGROUPR0_SGI15
+ str w4, [x5, #GICR_IGROUPR0_OFFSET]
+
+ /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */
+ ldr w3, [x5, #GICR_IGRPMODR0_OFFSET]
+ bic w3, w3, #GICR_IGRPMODR0_SGI15
+ str w3, [x5, #GICR_IGRPMODR0_OFFSET]
+
+ /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */
+ ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+ bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK
+ str w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+
+ /* enable SGI 15 at redistributor - GICR_ISENABLER0 */
+ mov w3, #GICR_ISENABLER0_SGI15
+ str w3, [x5, #GICR_ISENABLER0_OFFSET]
+ dsb sy
+ isb
+3:
+ /* poll on rwp bit in GICR_CTLR */
+ ldr w4, [x6, #GICR_CTLR_OFFSET]
+ tst w4, #GICR_CTLR_RWP
+ b.ne 3b
+
+ /* quiesce the debug interfaces */
+ mrs x3, osdlr_el1
+ orr x3, x3, #OSDLR_EL1_DLK_LOCK
+ msr osdlr_el1, x3
+ isb
+
+ /* enable grp0 ints */
+ mov x3, #ICC_IGRPEN0_EL1_EN
+ msr ICC_IGRPEN0_EL1, x3
+
+ /*
+ * x5 = gicr sgi base addr
+ * x6 = gicr rd base addr
+ * x7 = core mask lsb
+ */
+
+ /* clear any pending interrupts */
+ mvn w1, wzr
+ str w1, [x5, #GICR_ICPENDR0_OFFSET]
+
+ /* make sure system counter is enabled */
+ ldr x3, =NXP_TIMER_ADDR
+ ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 4f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+4:
+ /* enable the core timer and mask timer interrupt */
+ mov x1, #CNTP_CTL_EL0_EN
+ orr x1, x1, #CNTP_CTL_EL0_IMASK
+ msr cntp_ctl_el0, x1
+
+ mov x30, x8
+ ret
+
+/*
+ * part of CPU_OFF
+ * this function performs the final steps to shutdown the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5
+ */
+_soc_core_entr_off:
+ mov x5, x30
+ mov x4, x0
+
+ /* x4 = core mask */
+1:
+ /* enter low-power state by executing wfi */
+ wfi
+
+ /* see if SGI15 woke us up */
+ mrs x2, ICC_IAR0_EL1
+ mov x3, #ICC_IAR0_EL1_SGI15
+ cmp x2, x3
+ b.ne 2f
+
+ /* deactivate the int */
+ msr ICC_EOIR0_EL1, x2
+
+ /* x4 = core mask */
+2:
+ /* check if core has been turned on */
+ mov x0, x4
+ bl _getCoreState
+
+ /* x0 = core state */
+
+ cmp x0, #CORE_WAKEUP
+ b.ne 1b
+
+ /* if we get here, then we have exited the wfi */
+
+ mov x30, x5
+ ret
+
+/*
+ * part of CPU_OFF
+ * this function starts the process of starting a core back up
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6
+ */
+_soc_core_exit_off:
+ mov x6, x30
+ mov x5, x0
+
+ /* disable forwarding of GRP0 ints at cpu interface */
+ msr ICC_IGRPEN0_EL1, xzr
+
+ /* get redistributor sgi base addr for this core */
+ mov x0, x5
+ bl get_gic_sgi_base
+ mov x4, x0
+
+ /*
+ * x4 = gicr sgi base addr
+ * x5 = core mask
+ */
+
+ /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
+ mov w1, #GICR_ICENABLER0_SGI15
+ str w1, [x4, #GICR_ICENABLER0_OFFSET]
+
+ /* get redistributor rd base addr for this core */
+ mov x0, x5
+ bl get_gic_rd_base
+ mov x4, x0
+
+ /* x4 = gicr rd base addr */
+2:
+ /* poll on rwp bit in GICR_CTLR */
+ ldr w2, [x4, #GICR_CTLR_OFFSET]
+ tst w2, #GICR_CTLR_RWP
+ b.ne 2b
+
+ /* x4 = gicr rd base addr */
+
+ /* unlock the debug interfaces */
+ mrs x3, osdlr_el1
+ bic x3, x3, #OSDLR_EL1_DLK_LOCK
+ msr osdlr_el1, x3
+ isb
+
+ dsb sy
+ isb
+ mov x30, x6
+ ret
+
+/*
+ * this function requests a reset of the entire SOC
+ * in: none
+ * out: none
+ * uses: x0, x1, x2, x3, x4, x5, x6
+ */
+_soc_sys_reset:
+ mov x3, x30
+
+ /* make sure the mask is cleared in the reset request mask register */
+ mov x0, #RST_RSTRQMR1_OFFSET
+ mov w1, wzr
+ bl _write_reg_reset
+
+ /* set the reset request */
+ mov x4, #RST_RSTCR_OFFSET
+ mov x0, x4
+ mov w1, #RSTCR_RESET_REQ
+ bl _write_reg_reset
+
+ /* x4 = RST_RSTCR_OFFSET */
+
+ /*
+ * just in case this address range is mapped as cacheable,
+ * flush the write out of the dcaches
+ */
+ mov x2, #NXP_RESET_ADDR
+ add x2, x2, x4
+ dc cvac, x2
+ dsb st
+ isb
+
+ /* this function does not return */
+ b .
+
+/*
+ * this function turns off the SoC
+ * Note: this function is not intended to return, and the only allowable
+ * recovery is POR
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+_soc_sys_off:
+ /*
+ * A-009810: LPM20 entry sequence might cause
+ * spurious timeout reset request
+ * workaround: MASK RESET REQ RPTOE
+ */
+ ldr x0, =NXP_RESET_ADDR
+ ldr w1, [x0, #RST_RSTRQMR1_OFFSET]
+ orr w1, w1, #RSTRQMR_RPTOE_MASK
+ str w1, [x0, #RST_RSTRQMR1_OFFSET]
+
+ /* disable SEC, QBman spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+ ldr x0, =DCFG_DEVDISR1_OFFSET
+ ldr w1, =DCFG_DEVDISR1_SEC
+ str w1, [x2, x0]
+ ldr x0, =DCFG_DEVDISR3_OFFSET
+ ldr w1, =DCFG_DEVDISR3_QBMAIN
+ str w1, [x2, x0]
+ ldr x0, =DCFG_DEVDISR4_OFFSET
+ ldr w1, =DCFG_DEVDISR4_SPI_QSPI
+ str w1, [x2, x0]
+
+ /* set TPMWAKEMR0 */
+ ldr x0, =TPMWAKEMR0_ADDR
+ mov w1, #0x1
+ str w1, [x0]
+
+ /* disable icache, dcache, mmu @ EL1 */
+ mov x1, #SCTLR_I_C_M_MASK
+ mrs x0, sctlr_el1
+ bic x0, x0, x1
+ msr sctlr_el1, x0
+
+ /* disable L2 prefetches */
+ mrs x0, CPUECTLR_EL1
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ orr x0, x0, #CPUECTLR_TIMER_8TICKS
+ msr CPUECTLR_EL1, x0
+ dsb sy
+ isb
+
+ /* disable CCN snoop domain */
+ ldr x0, =NXP_CCI_ADDR
+ mov w1, #0x1
+ str w1, [x0]
+
+ mov x2, #DAIF_SET_MASK
+
+ mrs x1, spsr_el1
+ orr x1, x1, x2
+ msr spsr_el1, x1
+
+ mrs x1, spsr_el2
+ orr x1, x1, x2
+ msr spsr_el2, x1
+
+ bl get_pmu_idle_cluster_mask
+ mov x3, #NXP_PMU_ADDR
+
+ /* x3 = pmu base addr */
+
+ /* idle the ACP interfaces */
+ str w0, [x3, #PMU_CLAINACTSETR_OFFSET]
+
+ /* force the debug interface to be quiescent */
+ mrs x0, osdlr_el1
+ orr x0, x0, #0x1
+ msr osdlr_el1, x0
+
+ bl get_pmu_flush_cluster_mask
+ /* x3 = pmu base addr */
+ mov x3, #NXP_PMU_ADDR
+
+ /* clear flush request and status */
+ ldr x2, =PMU_CLSL2FLUSHCLRR_OFFSET
+ str w0, [x3, x2]
+
+ /* close the Skyros master port */
+ ldr x2, =PMU_CLSINACTSETR_OFFSET
+ str w0, [x3, x2]
+
+ /* request lpm20 */
+ ldr x0, =PMU_POWMGTCSR_OFFSET
+ ldr w1, =PMU_POWMGTCSR_VAL
+ str w1, [x3, x0]
+
+ /* this function does not return */
+1:
+ wfi
+ b 1b
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_core_prep_stdby:
+ /* clear CPUECTLR_EL1[2:0] */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CPUECTLR_EL1, x1
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function puts the calling core into standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_stdby:
+ /* X0 = core mask lsb */
+ dsb sy
+ isb
+ wfi
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_core_exit_stdby:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+_soc_core_prep_pwrdn:
+ /* make sure system counter is enabled */
+ ldr x3, =NXP_TIMER_ADDR
+ ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 1f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+ /*
+ * enable dynamic retention control (CPUECTLR[2:0])
+ * set the SMPEN bit (CPUECTLR[6])
+ */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_RET_MASK
+ orr x1, x1, #CPUECTLR_TIMER_8TICKS
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ msr CPUECTLR_EL1, x1
+
+ isb
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function puts the calling core into a power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_pwrdn:
+ /* X0 = core mask lsb */
+ dsb sy
+ isb
+ wfi
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function cleans up after a core exits power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses
+ */
+_soc_core_exit_pwrdn:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_clstr_prep_stdby:
+ /* clear CPUECTLR_EL1[2:0] */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CPUECTLR_EL1, x1
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_clstr_exit_stdby:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+_soc_clstr_prep_pwrdn:
+ /* make sure system counter is enabled */
+ ldr x3, =NXP_TIMER_ADDR
+ ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 1f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+ /*
+ * enable dynamic retention control (CPUECTLR[2:0])
+ * set the SMPEN bit (CPUECTLR[6])
+ */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_RET_MASK
+ orr x1, x1, #CPUECTLR_TIMER_8TICKS
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ msr CPUECTLR_EL1, x1
+
+ isb
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function cleans up after a core exits power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses
+ */
+_soc_clstr_exit_pwrdn:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_prep_stdby:
+ /* clear CPUECTLR_EL1[2:0] */
+ mrs x1, CPUECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CPUECTLR_EL1, x1
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_sys_exit_stdby:
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs SoC-specific programming prior to
+ * suspend-to-power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_sys_prep_pwrdn:
+ /* set retention control */
+ mrs x0, CPUECTLR_EL1
+ bic x0, x0, #CPUECTLR_TIMER_MASK
+ orr x0, x0, #CPUECTLR_TIMER_8TICKS
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ msr CPUECTLR_EL1, x0
+ dsb sy
+ isb
+
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function puts the calling core, and potentially the soc, into a
+ * low-power state
+ * in: x0 = core mask lsb
+ * out: x0 = 0, success
+ * x0 < 0, failure
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
+ */
+_soc_sys_pwrdn_wfi:
+ /* Save LR to stack */
+ stp x18, x30, [sp, #-16]!
+
+ /* Poll PCPW20SR for all secondary cores to be placed in PW20 */
+ bl get_tot_num_cores
+ mov x3, #0x1
+ lsl x3, x3, x0
+ sub x3, x3, #2
+1:
+ mov x0, #NXP_PMU_ADDR
+ ldr w1, [x0, #PMU_PCPW20SR_OFFSET]
+ cmp w1, w3
+ b.ne 1b
+
+ /* backup EPU registers to stack */
+ mov x3, #NXP_PMU_ADDR
+ ldr x2, =NXP_EPU_ADDR
+ ldr w4, [x2, #EPU_EPIMCR10_OFFSET]
+ ldr w5, [x2, #EPU_EPCCR10_OFFSET]
+ ldr w6, [x2, #EPU_EPCTR10_OFFSET]
+ ldr w7, [x2, #EPU_EPGCR_OFFSET]
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+
+ /*
+ * x2 = epu base addr
+ * x3 = pmu base addr
+ */
+
+ /* set up EPU event to receive the wake signal from PMU */
+ mov w4, #EPU_EPIMCR10_VAL
+ mov w5, #EPU_EPCCR10_VAL
+ mov w6, #EPU_EPCTR10_VAL
+ mov w7, #EPU_EPGCR_VAL
+ str w4, [x2, #EPU_EPIMCR10_OFFSET]
+ str w5, [x2, #EPU_EPCCR10_OFFSET]
+ str w6, [x2, #EPU_EPCTR10_OFFSET]
+ str w7, [x2, #EPU_EPGCR_OFFSET]
+
+ /*
+ * A-010194: There is logic problem
+ * in the path of GIC-to-PMU to issue
+ * wake request to core0
+ * Workaround: Re-target the wakeup interrupts
+ * to a core other than the last active core0
+ */
+ ldr x2, =NXP_GICD_ADDR
+
+ /* backup flextimer/mmc/usb interrupt router */
+ ldr x0, =GICD_IROUTER60_OFFSET
+ ldr x1, =GICD_IROUTER76_OFFSET
+ ldr w4, [x2, x0]
+ ldr w5, [x2, x1]
+ ldr x0, =GICD_IROUTER112_OFFSET
+ ldr x1, =GICD_IROUTER113_OFFSET
+ ldr w6, [x2, x0]
+ ldr w7, [x2, x1]
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+
+ /*
+ * x2 = gicd base addr
+ * x0 = GICD_IROUTER112_OFFSET
+ * x1 = GICD_IROUTER113_OFFSET
+ */
+
+ /* re-route interrupt to cluster 1 */
+ ldr w4, =GICD_IROUTER_VALUE
+ str w4, [x2, x0]
+ str w4, [x2, x1]
+ ldr x0, =GICD_IROUTER60_OFFSET
+ ldr x1, =GICD_IROUTER76_OFFSET
+ str w4, [x2, x0]
+ str w4, [x2, x1]
+ dsb sy
+ isb
+
+ /* backup flextimer/mmc/usb interrupt enabler */
+ ldr x0, =GICD_ISENABLER_1
+ ldr w4, [x2, x0]
+ ldr x1, =GICD_ISENABLER_2
+ ldr w5, [x2, x1]
+ stp x4, x5, [sp, #-16]!
+
+ ldr x0, =GICD_ISENABLER_3
+ ldr w4, [x2, x0]
+ ldr x1, =GICD_ICENABLER_1
+ ldr w5, [x2, x1]
+ stp x4, x5, [sp, #-16]!
+
+ ldr x0, =GICD_ICENABLER_2
+ ldr w4, [x2, x0]
+ ldr x1, =GICD_ICENABLER_3
+ ldr w5, [x2, x1]
+ stp x4, x5, [sp, #-16]!
+
+ /* enable related interrupt routing */
+ ldr w4, =GICD_ISENABLER_1_VALUE
+ ldr x0, =GICD_ISENABLER_1
+ str w4, [x2, x0]
+ dsb sy
+ isb
+
+ ldr w4, =GICD_ISENABLER_2_VALUE
+ ldr x0, =GICD_ISENABLER_2
+ str w4, [x2, x0]
+ dsb sy
+ isb
+
+ ldr w4, =GICD_ISENABLER_3_VALUE
+ ldr x0, =GICD_ISENABLER_3
+ str w4, [x2, x0]
+ dsb sy
+ isb
+
+ /* set POWMGTDCR [STP_PV_EN] = 1 */
+ ldr x2, =NXP_POWMGTDCR
+ ldr w4, =0x01
+ str w4, [x2]
+
+ /* program IPSTPCR for override stop request (except DDR) */
+ mov x3, #NXP_PMU_ADDR
+
+ /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */
+ ldr x2, =PMU_IPPDEXPCR4_OFFSET
+ ldr w7, [x3, x2]
+
+ mov x5, xzr
+ ldr x6, =IPPDEXPCR4_MASK
+ and x6, x6, x7
+ cbz x6, 1f
+
+ /*
+ * x5 = override mask
+ * x6 = IPPDEXPCR bits for DEVDISR5
+ * x7 = IPPDEXPCR
+ */
+
+ /* get the overrides */
+ orr x4, x5, #DEVDISR5_FLX_TMR
+ tst x6, #IPPDEXPCR_FLX_TMR
+ csel x5, x5, x4, EQ
+1:
+ /* store the DEVDISR5 override mask */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ str w5, [x2, #DEVDISR5_MASK_OFFSET]
+
+ mov x3, #NXP_PMU_ADDR
+
+ /* write IPSTPCR0 - no overrides */
+ ldr x2, =PMU_IPSTPCR0_OFFSET
+ ldr w5, =IPSTPCR0_VALUE
+ str w5, [x3, x2]
+
+ /* write IPSTPCR1 - no overrides */
+ ldr x2, =PMU_IPSTPCR1_OFFSET
+ ldr w5, =IPSTPCR1_VALUE
+ str w5, [x3, x2]
+
+ /* write IPSTPCR2 - no overrides */
+ ldr x2, =PMU_IPSTPCR2_OFFSET
+ ldr w5, =IPSTPCR2_VALUE
+ str w5, [x3, x2]
+
+ /* write IPSTPCR3 - no overrides */
+ ldr x2, =PMU_IPSTPCR3_OFFSET
+ ldr w5, =IPSTPCR3_VALUE
+ str w5, [x3, x2]
+
+ /* write IPSTPCR4 - overrides possible */
+ ldr x2, =BC_PSCI_BASE
+ add x2, x2, #AUX_01_DATA
+ ldr w6, [x2, #DEVDISR5_MASK_OFFSET]
+ ldr x2, =PMU_IPSTPCR4_OFFSET
+ ldr w5, =IPSTPCR4_VALUE
+ bic x5, x5, x6
+ str w5, [x3, x2]
+
+ /* write IPSTPCR5 - no overrides */
+ ldr x2, =PMU_IPSTPCR5_OFFSET
+ ldr w5, =IPSTPCR5_VALUE
+ str w5, [x3, x2]
+
+ /* write IPSTPCR6 - no overrides */
+ ldr x2, =PMU_IPSTPCR6_OFFSET
+ ldr w5, =IPSTPCR6_VALUE
+ str w5, [x3, x2]
+
+ /* poll IPSTPACK for IP stop acknowledgment (except DDR) */
+ mov x3, #NXP_PMU_ADDR
+
+ /* poll on IPSTPACK0 */
+ ldr x2, =PMU_IPSTPACK0_OFFSET
+ ldr x4, =IPSTPCR0_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+3:
+ ldr w0, [x3, x2]
+ cmp x0, x4
+ b.eq 14f
+ sub x7, x7, #1
+ cbnz x7, 3b
+
+14:
+ /* poll on IPSTPACK1 */
+ ldr x2, =PMU_IPSTPACK1_OFFSET
+ ldr x4, =IPSTPCR1_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+4:
+ ldr w0, [x3, x2]
+ cmp x0, x4
+ b.eq 15f
+ sub x7, x7, #1
+ cbnz x7, 4b
+
+15:
+ /* poll on IPSTPACK2 */
+ ldr x2, =PMU_IPSTPACK2_OFFSET
+ ldr x4, =IPSTPCR2_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+5:
+ ldr w0, [x3, x2]
+ cmp x0, x4
+ b.eq 16f
+ sub x7, x7, #1
+ cbnz x7, 5b
+
+16:
+ /* poll on IPSTPACK3 */
+ ldr x2, =PMU_IPSTPACK3_OFFSET
+ ldr x4, =IPSTPCR3_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+6:
+ ldr w0, [x3, x2]
+ cmp x0, x4
+ b.eq 17f
+ sub x7, x7, #1
+ cbnz x7, 6b
+
+17:
+ /* poll on IPSTPACK4 */
+ ldr x2, =PMU_IPSTPACK4_OFFSET
+ ldr x4, =IPSTPCR4_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+7:
+ ldr w0, [x3, x2]
+ cmp x0, x4
+ b.eq 18f
+ sub x7, x7, #1
+ cbnz x7, 7b
+
+18:
+ /* poll on IPSTPACK5 */
+ ldr x2, =PMU_IPSTPACK5_OFFSET
+ ldr x4, =IPSTPCR5_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+8:
+ ldr w0, [x3, x2]
+ cmp x0, x4
+ b.eq 19f
+ sub x7, x7, #1
+ cbnz x7, 8b
+
+19:
+ /* poll on IPSTPACK6 */
+ ldr x2, =PMU_IPSTPACK6_OFFSET
+ ldr x4, =IPSTPCR6_VALUE
+ ldr x7, =IPSTPACK_RETRY_CNT
+9:
+ ldr w0, [x3, x2]
+ cmp x0, x4
+ b.eq 20f
+ sub x7, x7, #1
+ cbnz x7, 9b
+
+20:
+ /* save current DEVDISR states to DDR. */
+ ldr x2, =NXP_DCFG_ADDR
+
+ /* save DEVDISR1 and load new value */
+ ldr x0, =DCFG_DEVDISR1_OFFSET
+ ldr w1, [x2, x0]
+ mov w13, w1
+ ldr x1, =DEVDISR1_VALUE
+ str w1, [x2, x0]
+ /* save DEVDISR2 and load new value */
+ ldr x0, =DCFG_DEVDISR2_OFFSET
+ ldr w1, [x2, x0]
+ mov w14, w1
+ ldr x1, =DEVDISR2_VALUE
+ str w1, [x2, x0]
+
+ /* x6 = DEVDISR5 override mask */
+
+ /* save DEVDISR3 and load new value */
+ ldr x0, =DCFG_DEVDISR3_OFFSET
+ ldr w1, [x2, x0]
+ mov w15, w1
+ ldr x1, =DEVDISR3_VALUE
+ str w1, [x2, x0]
+
+ /* save DEVDISR4 and load new value */
+ ldr x0, =DCFG_DEVDISR4_OFFSET
+ ldr w1, [x2, x0]
+ mov w16, w1
+ /* not stop uart print */
+ ldr x1, =0x0000332
+ str w1, [x2, x0]
+
+ /* save DEVDISR5 and load new value */
+ ldr x0, =DCFG_DEVDISR5_OFFSET
+ ldr w1, [x2, x0]
+ mov w17, w1
+ /* Enable this wakeup will fail, should enable OCRAM */
+ ldr x1, =0x00102300
+ str w1, [x2, x0]
+
+ /* save DEVDISR6 and load new value */
+ ldr x0, =DCFG_DEVDISR6_OFFSET
+ ldr w1, [x2, x0]
+ mov w18, w1
+ ldr x1, =DEVDISR6_VALUE
+ str w1, [x2, x0]
+
+ /*
+ * w13 = DEVDISR1 saved value
+ * w14 = DEVDISR2 saved value
+ * w15 = DEVDISR3 saved value
+ * w16 = DEVDISR4 saved value
+ * w17 = DEVDISR5 saved value
+ * w18 = DEVDISR6 saved value
+ */
+ /*
+ * A-009810: LPM20 entry sequence might cause
+ * spurious timeout reset request
+ * workaround: MASK RESET REQ RPTOE
+ */
+ ldr x0, =NXP_RESET_ADDR
+ ldr w1, =RSTRQMR_RPTOE_MASK
+ str w1, [x0, #RST_RSTRQMR1_OFFSET]
+
+ /* disable SEC, QBman spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+ ldr x0, =DCFG_DEVDISR1_OFFSET
+ ldr w1, =DCFG_DEVDISR1_SEC
+ str w1, [x2, x0]
+ ldr x0, =DCFG_DEVDISR3_OFFSET
+ ldr w1, =DCFG_DEVDISR3_QBMAIN
+ str w1, [x2, x0]
+ ldr x0, =DCFG_DEVDISR4_OFFSET
+ ldr w1, =DCFG_DEVDISR4_SPI_QSPI
+ str w1, [x2, x0]
+
+ /*
+ * write the GICR_WAKER.ProcessorSleep bits to 1
+ * enable the WakeRequest signal
+ * x3 is cpu mask starting from cpu7
+ */
+ bl get_tot_num_cores
+ sub x0, x0, #1
+ mov x3, #0x1
+ lsl x3, x3, x0
+2:
+ mov x0, x3
+ bl get_gic_rd_base
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ orr w1, w1, #GICR_WAKER_SLEEP_BIT
+ str w1, [x0, #GICR_WAKER_OFFSET]
+1:
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ cmp w1, #GICR_WAKER_ASLEEP
+ b.ne 1b
+
+ lsr x3, x3, #1
+ cbnz x3, 2b
+
+ /* x3 = pmu base addr */
+
+ /* perform Icache Warming Sequence */
+ ldr x5, =IPSTPCR4_VALUE
+ mov x6, DDR_CNTRL_BASE_ADDR
+ mov x7, #NXP_PMU_ADDR
+ mov x8, #NXP_DCFG_ADDR
+ mov x10, #PMU_IPSTPCR4_OFFSET
+ mov x11, #PMU_IPSTPACK4_OFFSET
+ mov x12, #PMU_IPSTPCR3_OFFSET
+ mov x18, #PMU_IPSTPCR2_OFFSET
+ mov x19, #PMU_IPSTPCR1_OFFSET
+ mov x21, #PMU_IPSTPCR0_OFFSET
+ ldr x22, =DCFG_DEVDISR5_OFFSET
+ ldr x23, =NXP_EPU_ADDR
+ mov x9, #CORE_RESTARTABLE
+ bl final_pwrdown
+
+ /*
+ * disable the WakeRequest signal on cpu 0-7
+ * x3 is cpu mask starting from cpu7
+ */
+ bl get_tot_num_cores
+ sub x0, x0, #1
+ mov x3, #0x1
+ lsl x3, x3, x0
+2:
+ mov x0, x3
+ bl get_gic_rd_base
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ bic w1, w1, #GICR_WAKER_SLEEP_BIT
+ str w1, [x0, #GICR_WAKER_OFFSET]
+1:
+ ldr w1, [x0, #GICR_WAKER_OFFSET]
+ cbnz w1, 1b
+
+ lsr x3, x3, #1
+ cbnz x3, 2b
+
+ /* set SGI for secondary core wakeup */
+ ldr x0, =0x1000002
+ msr S3_0_C12_C11_7, x0
+ isb
+ ldr x0, =0x2000004
+ msr S3_0_C12_C11_7, x0
+ isb
+ ldr x0, =0x3000008
+ msr S3_0_C12_C11_7, x0
+ isb
+ ldr x0, =0x4010001
+ msr S3_0_C12_C11_7, x0
+ isb
+ ldr x0, =0x5010002
+ msr S3_0_C12_C11_7, x0
+ isb
+ ldr x0, =0x6010004
+ msr S3_0_C12_C11_7, x0
+ isb
+ ldr x0, =0x7010008
+ msr S3_0_C12_C11_7, x0
+
+ /* enable SEC, QBman spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+ str wzr, [x2, #DCFG_DEVDISR1_OFFSET]
+ str wzr, [x2, #DCFG_DEVDISR3_OFFSET]
+ str wzr, [x2, #DCFG_DEVDISR4_OFFSET]
+
+ /* clear POWMGTDCR [STP_PV_EN] */
+ ldr x2, =NXP_POWMGTDCR
+ ldr w4, [x2]
+ bic w4, w4, #0x01
+ str w4, [x2]
+
+ /* restore flextimer/mmc/usb interrupt enabler */
+ ldr x3, =NXP_GICD_ADDR
+ ldp x0, x2, [sp], #16
+ ldr x1, =GICD_ICENABLER_2
+ mvn w0, w0
+ str w0, [x3, x1]
+ ldr x1, =GICD_ICENABLER_3
+ mvn w2, w2
+ str w2, [x3, x1]
+
+ ldp x0, x2, [sp], #16
+ ldr x1, =GICD_ISENABLER_3
+ str w0, [x3, x1]
+ ldr x1, =GICD_ICENABLER_1
+ mvn w2, w2
+ str w0, [x3, x1]
+
+ ldp x0, x2, [sp], #16
+ ldr x1, =GICD_ISENABLER_1
+ str w0, [x3, x1]
+ ldr x1, =GICD_ISENABLER_2
+ str w0, [x3, x1]
+
+ /* restore flextimer/mmc/usb interrupt router */
+ ldr x3, =NXP_GICD_ADDR
+ ldp x0, x2, [sp], #16
+ ldr x1, =GICD_IROUTER113_OFFSET
+ str w2, [x3, x1]
+ ldr x1, =GICD_IROUTER112_OFFSET
+ str w0, [x3, x1]
+ ldp x0, x2, [sp], #16
+ ldr x1, =GICD_IROUTER76_OFFSET
+ str w2, [x3, x1]
+ ldr x1, =GICD_IROUTER60_OFFSET
+ str w0, [x3, x1]
+
+ /* restore EPU registers */
+ ldr x3, =NXP_EPU_ADDR
+ ldp x0, x2, [sp], #16
+ str w2, [x3, #EPU_EPGCR_OFFSET]
+ str w0, [x3, #EPU_EPCTR10_OFFSET]
+ ldp x2, x1, [sp], #16
+ str w1, [x3, #EPU_EPCCR10_OFFSET]
+ str w2, [x3, #EPU_EPIMCR10_OFFSET]
+
+ isb
+ /* Restor LR */
+ ldp x18, x30, [sp], #16
+ ret
+
+/*
+ * part of CPU_SUSPEND
+ * this function performs any SoC-specific cleanup after power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_exit_pwrdn:
+ mrs x1, SCTLR_EL1
+ orr x1, x1, #SCTLR_I_MASK
+ msr SCTLR_EL1, x1
+ isb
+ ret
+
+/*
+ * this function checks to see if cores which are to be disabled have been
+ * released from reset - if not, it releases them
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
+ */
+release_disabled:
+ mov x8, x30
+
+ /* read COREDISABLESR */
+ mov x0, #NXP_DCFG_ADDR
+ ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
+
+ /* get the number of cpus on this device */
+ mov x6, #PLATFORM_CORE_COUNT
+
+ mov x0, #NXP_RESET_ADDR
+ ldr w5, [x0, #BRR_OFFSET]
+
+ /* load the core mask for the first core */
+ mov x7, #1
+
+ /*
+ * x4 = COREDISABLESR
+ * x5 = BRR
+ * x6 = loop count
+ * x7 = core mask bit
+ */
+2:
+ /* check if the core is to be disabled */
+ tst x4, x7
+ b.eq 1f
+
+ /* see if disabled cores have already been released from reset */
+ tst x5, x7
+ b.ne 1f
+
+ /* if core has not been released, then release it (0-3) */
+ mov x0, x7
+ bl _soc_core_release
+
+ /* record the core state in the data area (0-3) */
+ mov x0, x7
+ mov x1, #CORE_DISABLED
+ bl _setCoreState
+
+1:
+ /* decrement the counter */
+ subs x6, x6, #1
+ b.le 3f
+
+ /* shift the core mask to the next core */
+ lsl x7, x7, #1
+ /* continue */
+ b 2b
+3:
+ mov x30, x8
+ ret
+
+/*
+ * write a register in the DCFG block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2
+ */
+_write_reg_dcfg:
+ ldr x2, =NXP_DCFG_ADDR
+ str w1, [x2, x0]
+ ret
+
+/*
+ * read a register in the DCFG block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1
+ */
+_read_reg_dcfg:
+ ldr x1, =NXP_DCFG_ADDR
+ ldr w0, [x1, x0]
+ ret
+
+/*
+ * this function sets up the TrustZone Address Space Controller (TZASC)
+ * in: none
+ * out: none
+ * uses x0, x1
+ */
+init_tzpc:
+ /*
+ * set Non Secure access for all devices protected via TZPC
+ * decode Protection-0 Set Reg
+ */
+ ldr x1, =TZPCDECPROT_0_SET_BASE
+ /* set decode region to NS, Bits[7:0] */
+ mov w0, #0xFF
+ str w0, [x1]
+
+ /* decode Protection-1 Set Reg */
+ ldr x1, =TZPCDECPROT_1_SET_BASE
+ /* set decode region to NS, Bits[7:0] */
+ mov w0, #0xFF
+ str w0, [x1]
+
+ /* decode Protection-2 Set Reg */
+ ldr x1, =TZPCDECPROT_2_SET_BASE
+ /* set decode region to NS, Bits[7:0] */
+ mov w0, #0xFF
+ str w0, [x1]
+
+ /*
+ * entire SRAM as NS
+ * secure RAM region size Reg
+ */
+ ldr x1, =NXP_OCRAM_TZPC_ADDR
+ /* 0x00000000 = no secure region */
+ mov w0, #0x00000000
+ str w0, [x1]
+
+ ret
+
+/* this function performs initialization on SecMon for boot services */
+initSecMon:
+ /* read the register hpcomr */
+ ldr x1, =NXP_SNVS_ADDR
+ ldr w0, [x1, #SECMON_HPCOMR_OFFSET]
+ /* turn off secure access for the privileged registers */
+ orr w0, w0, #SECMON_HPCOMR_NPSWAEN
+ /* write back */
+ str w0, [x1, #SECMON_HPCOMR_OFFSET]
+
+ ret
+
+/*
+ * this function returns the redistributor base address for the core specified
+ * in x1
+ * in: x0 - core mask lsb of specified core
+ * out: x0 = redistributor rd base address for specified core
+ * uses x0, x1, x2
+ */
+get_gic_rd_base:
+ /* get the 0-based core number */
+ clz w1, w0
+ mov w2, #0x20
+ sub w2, w2, w1
+ sub w2, w2, #1
+
+ /* x2 = core number / loop counter */
+
+ ldr x0, =NXP_GICR_ADDR
+ mov x1, #GIC_RD_OFFSET
+2:
+ cbz x2, 1f
+ add x0, x0, x1
+ sub x2, x2, #1
+ b 2b
+1:
+ ret
+
+/*
+ * this function returns the redistributor base address for the core specified
+ * in x1
+ * in: x0 - core mask lsb of specified core
+ * out: x0 = redistributor sgi base address for specified core
+ * uses x0, x1, x2
+ */
+get_gic_sgi_base:
+ /* get the 0-based core number */
+ clz w1, w0
+ mov w2, #0x20
+ sub w2, w2, w1
+ sub w2, w2, #1
+
+ /* x2 = core number / loop counter */
+
+ ldr x0, =NXP_GICR_SGI_ADDR
+ mov x1, #GIC_SGI_OFFSET
+2:
+ cbz x2, 1f
+ add x0, x0, x1
+ sub x2, x2, #1
+ b 2b
+1:
+ ret
+
+/*
+ * this function returns an mpidr value for a core, given a core_mask_lsb
+ * in: x0 = core mask lsb
+ * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits
+ * uses x0, x1
+ */
+get_mpidr_value:
+ /* convert a core mask to an SoC core number */
+ clz w0, w0
+ mov w1, #31
+ sub w0, w1, w0
+
+ /* w0 = SoC core number */
+
+ mov w1, wzr
+2:
+ cmp w0, #CORES_PER_CLUSTER
+ b.lt 1f
+ sub w0, w0, #CORES_PER_CLUSTER
+ add w1, w1, #MPIDR_CLUSTER
+ b 2b
+
+ /* insert the mpidr core number */
+1:
+ orr w0, w1, w0
+ ret
+
+/*
+ * write a register in the RESET block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2
+ */
+_write_reg_reset:
+ ldr x2, =NXP_RESET_ADDR
+ str w1, [x2, x0]
+ ret
+
+/*
+ * read a register in the RESET block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1
+ */
+_read_reg_reset:
+ ldr x1, =NXP_RESET_ADDR
+ ldr w0, [x1, x0]
+ ret
+
+/*
+ * this function will pwrdown ddr and the final core - it will do this
+ * by loading itself into the icache and then executing from there
+ * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
+ * x6 = DDR_CNTRL_BASE_ADDR
+ * x7 = NXP_PMU_ADDR
+ * x8 = NXP_DCFG_ADDR
+ * x9 = 0, restartable
+ * = 1, non-restartable
+ * x10 = PMU_IPSTPCR4_OFFSET
+ * x11 = PMU_IPSTPACK4_OFFSET
+ * x12 = PMU_IPSTPCR3_OFFSET
+ * x18 = PMU_IPSTPCR2_OFFSET
+ * x19 = PMU_IPSTPCR1_OFFSET
+ * x21 = PMU_IPSTPCR0_OFFSET
+ * w13 = DEVDISR1 saved value
+ * w14 = DEVDISR2 saved value
+ * w15 = DEVDISR3 saved value
+ * w16 = DEVDISR4 saved value
+ * w17 = DEVDISR5 saved value
+ * x22 = DCFG_DEVDISR5_OFFSET
+ * x23 = NXP_EPU_ADDR
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, x17
+ * x10, x11, x12, x18, x19, x21, x22, x23
+ */
+
+final_pwrdown:
+ /* delay */
+ mov w4, #0xffffff
+554:
+ sub w4, w4, #1
+ cmp w4, #0
+ b.ge 554b
+
+ mov x0, xzr
+ b touch_line_0
+
+/* 4Kb aligned */
+.align 12
+start_line_0:
+ mov x0, #1
+ /* put ddr in self refresh - start */
+ mov x2, #DDR_SDRAM_CFG_2_FRCSR
+ ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
+ orr w3, w3, w2
+ /* put ddr in self refresh - end */
+ str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
+ nop
+ nop
+touch_line_0:
+ cbz x0, touch_line_1
+
+start_line_1:
+ /* quiesce ddr clocks - start */
+ orr w3, w5, #DCFG_DEVDISR5_MEM
+ mov w4, w3
+ /* quiesce ddr clocks - end */
+ str w4, [x7, x10]
+ mov w3, #DCFG_DEVDISR5_MEM
+ /* poll on ipstpack4 - start */
+ mov x2, #DDR_SLEEP_RETRY_CNT
+ nop
+ nop
+touch_line_1:
+ cbz x0, touch_line_2
+
+start_line_2:
+ /* x11 = PMU_IPSTPACK4_OFFSET */
+ ldr w1, [x7, x11]
+ tst w1, w3
+ b.ne 5f
+ subs x2, x2, #1
+ /* poll on ipstpack4 - end */
+ b.gt start_line_2
+
+ /* if we get here, we have a timeout err */
+ mov w4, w5
+ /* x10 = PMU_IPSTPCR4_OFFSET re-enable ddr clks interface */
+ str w4, [x7, x10]
+touch_line_2:
+ cbz x0, touch_line_3
+
+start_line_3:
+ /* load error code */
+ mov x0, #ERROR_DDR_SLEEP
+ b 2f
+5:
+ wfe
+ ldr w1, [x23, #EPU_EPCTR10_OFFSET]
+ cbz w1, 5b
+
+ mov w4, w5
+touch_line_3:
+ cbz x0, touch_line_4
+
+start_line_4:
+ /* re-enable ddr in devdisr5 */
+ str w4, [x8, x22]
+ /* re-enable ddr clk in ipstpcr4 */
+ str w4, [x7, x10]
+13:
+ /* poll on ipstpack4 - start */
+ ldr w1, [x7, x11]
+ tst w1, w3
+ b.eq 2f
+ nop
+ b 13b
+ /* poll on ipstpack4 - end */
+2:
+touch_line_4:
+ cbz x0, touch_line_5
+
+start_line_5:
+ /* take ddr out-of self refresh - start */
+ mov x2, #DDR_SDRAM_CFG_2_FRCSR
+ ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
+ mov w4, w3
+ bic w4, w4, w2
+ mov w3, w4
+ /* wait for ddr cntrlr clock- start */
+ mov x1, #DDR_SLEEP_RETRY_CNT
+3:
+ subs x1, x1, #1
+touch_line_5:
+ cbz x0, touch_line_6
+
+start_line_6:
+ /* wait for ddr cntrlr clock - end */
+ b.gt 3b
+ /* take ddr out-of self refresh - end */
+ str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
+ mov w1, w17
+ /* reset devdisr5 */
+ str w1, [x8, #DCFG_DEVDISR5_OFFSET]
+ mov w1, w16
+ /* reset devdisr4 */
+ str w1, [x8, #DCFG_DEVDISR4_OFFSET]
+ mov w1, w15
+touch_line_6:
+ cbz x0, touch_line_7
+
+start_line_7:
+ /* reset devdisr3 */
+ str w1, [x8, #DCFG_DEVDISR3_OFFSET]
+ mov w1, w14
+ /* reset devdisr2 */
+ str w1, [x8, #DCFG_DEVDISR2_OFFSET]
+ mov w1, w13
+ /* reset devdisr1 */
+ str w1, [x8, #DCFG_DEVDISR1_OFFSET]
+ /* reset ipstpcr4 */
+ str wzr, [x7, x10]
+ /* reset ipstpcr3 */
+ str wzr, [x7, x12]
+touch_line_7:
+ cbz x0, touch_line_8
+
+start_line_8:
+ /* reset ipstpcr2 */
+ str wzr, [x7, x18]
+ /* reset ipstpcr1 */
+ str wzr, [x7, x19]
+ /* reset ipstpcr0 */
+ str wzr, [x7, x21]
+
+touch_line_8:
+ cbz x0, touch_line_9
+
+start_line_9:
+ b continue_restart
+touch_line_9:
+ cbz x0, start_line_0
+
+/* execute here after ddr is back up */
+continue_restart:
+ /*
+ * if x0 = 1, all is well
+ * if x0 < 1, we had an error
+ */
+ cmp x0, #1
+ b.ne 4f
+ mov x0, #0
+4:
+ ret
diff --git a/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S b/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S
new file mode 100644
index 0000000..890cf81
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_is_my_cpu_primary
+ .globl plat_reset_handler
+ .globl platform_mem_init
+
+func platform_mem1_init
+ ret
+endfunc platform_mem1_init
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+func apply_platform_errata
+ ret
+endfunc apply_platform_errata
+
+func plat_reset_handler
+ mov x29, x30
+ bl apply_platform_errata
+
+#if defined(IMAGE_BL31)
+ ldr x0, =POLICY_SMMU_PAGESZ_64K
+ cbz x0, 1f
+ /* Set the SMMU page size in the sACR register */
+ bl _set_smmu_pagesz_64
+#endif
+1:
+ mov x30, x29
+ ret
+endfunc plat_reset_handler
+
+ /*
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ */
+func plat_secondary_cold_boot_setup
+ /* ls1088a does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+ /*
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, 0x0
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/nxp/soc-ls1088a/include/soc.h b/plat/nxp/soc-ls1088a/include/soc.h
new file mode 100644
index 0000000..eb36c2e
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/include/soc.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+/* Chassis specific defines - common across SoC's of a particular platform */
+#include "dcfg_lsch3.h"
+#include "soc_default_base_addr.h"
+#include "soc_default_helper_macros.h"
+
+/*
+ * SVR Definition of LS1088A
+ * A: without security
+ * AE: with security
+ * (not include major and minor rev)
+ */
+#define SVR_LS1044A 0x870323
+#define SVR_LS1044AE 0x870322
+#define SVR_LS1048A 0x870321
+#define SVR_LS1048AE 0x870320
+#define SVR_LS1084A 0x870303
+#define SVR_LS1084AE 0x870302
+#define SVR_LS1088A 0x870301
+#define SVR_LS1088AE 0x870300
+
+#define SVR_WO_E 0xFFFFFE
+
+/* Number of cores in platform */
+#define NUMBER_OF_CLUSTERS 2
+#define CORES_PER_CLUSTER 4
+#define PLATFORM_CORE_COUNT (NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER)
+
+/* set to 0 if the clusters are not symmetrical */
+#define SYMMETRICAL_CLUSTERS 1
+
+
+#define NUM_DRAM_REGIONS 2
+#define NXP_DRAM0_ADDR 0x80000000
+#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */
+
+#define NXP_DRAM1_ADDR 0x8080000000
+#define NXP_DRAM1_MAX_SIZE 0x7F80000000 /* 510 G */
+
+/* DRAM0 Size defined in platform_def.h */
+#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE
+
+#define NXP_POWMGTDCR 0x700123C20
+
+/* epu register offsets and values */
+#define EPU_EPGCR_OFFSET 0x0
+#define EPU_EPIMCR10_OFFSET 0x128
+#define EPU_EPCTR10_OFFSET 0xa28
+#define EPU_EPCCR10_OFFSET 0x828
+
+#ifdef EPU_EPCCR10_VAL
+#undef EPU_EPCCR10_VAL
+#endif
+#define EPU_EPCCR10_VAL 0xf2800000
+
+#define EPU_EPIMCR10_VAL 0xba000000
+#define EPU_EPCTR10_VAL 0x0
+#define EPU_EPGCR_VAL (1 << 31)
+
+/* pmu register offsets and values */
+#define PMU_PCPW20SR_OFFSET 0x830
+#define PMU_CLAINACTSETR_OFFSET 0x1100
+#define PMU_CLAINACTCLRR_OFFSET 0x1104
+#define PMU_CLSINACTSETR_OFFSET 0x1108
+#define PMU_CLSINACTCLRR_OFFSET 0x110C
+#define PMU_CLL2FLUSHSETR_OFFSET 0x1110
+#define PMU_CLSL2FLUSHCLRR_OFFSET 0x1114
+#define PMU_CLL2FLUSHSR_OFFSET 0x1118
+#define PMU_POWMGTCSR_OFFSET 0x4000
+#define PMU_IPPDEXPCR0_OFFSET 0x4040
+#define PMU_IPPDEXPCR1_OFFSET 0x4044
+#define PMU_IPPDEXPCR2_OFFSET 0x4048
+#define PMU_IPPDEXPCR3_OFFSET 0x404C
+#define PMU_IPPDEXPCR4_OFFSET 0x4050
+#define PMU_IPPDEXPCR5_OFFSET 0x4054
+#define PMU_IPSTPCR0_OFFSET 0x4120
+#define PMU_IPSTPCR1_OFFSET 0x4124
+#define PMU_IPSTPCR2_OFFSET 0x4128
+#define PMU_IPSTPCR3_OFFSET 0x412C
+#define PMU_IPSTPCR4_OFFSET 0x4130
+#define PMU_IPSTPCR5_OFFSET 0x4134
+#define PMU_IPSTPCR6_OFFSET 0x4138
+#define PMU_IPSTPACK0_OFFSET 0x4140
+#define PMU_IPSTPACK1_OFFSET 0x4144
+#define PMU_IPSTPACK2_OFFSET 0x4148
+#define PMU_IPSTPACK3_OFFSET 0x414C
+#define PMU_IPSTPACK4_OFFSET 0x4150
+#define PMU_IPSTPACK5_OFFSET 0x4154
+#define PMU_IPSTPACK6_OFFSET 0x4158
+#define PMU_POWMGTCSR_VAL (1 << 20)
+
+#define IPPDEXPCR0_MASK 0xFFFFFFFF
+#define IPPDEXPCR1_MASK 0xFFFFFFFF
+#define IPPDEXPCR2_MASK 0xFFFFFFFF
+#define IPPDEXPCR3_MASK 0xFFFFFFFF
+#define IPPDEXPCR4_MASK 0xFFFFFFFF
+#define IPPDEXPCR5_MASK 0xFFFFFFFF
+
+/* DEVDISR5_FLX_TMR */
+#define IPPDEXPCR_FLX_TMR 0x00004000
+#define DEVDISR5_FLX_TMR 0x00004000
+
+#define IPSTPCR0_VALUE 0x0041310C
+#define IPSTPCR1_VALUE 0x000003FF
+#define IPSTPCR2_VALUE 0x00013006
+
+/* Dont' stop UART */
+#define IPSTPCR3_VALUE 0x0000033A
+
+#define IPSTPCR4_VALUE 0x00103300
+#define IPSTPCR5_VALUE 0x00000001
+#define IPSTPCR6_VALUE 0x00000000
+
+
+#define TZPC_BLOCK_SIZE 0x1000
+
+/* PORSR1 */
+#define PORSR1_RCW_MASK 0xFF800000
+#define PORSR1_RCW_SHIFT 23
+
+/* CFG_RCW_SRC[6:0] */
+#define RCW_SRC_TYPE_MASK 0x70
+
+/* RCW SRC NOR */
+#define NOR_16B_VAL 0x20
+
+/*
+ * RCW SRC Serial Flash
+ * 1. SERAIL NOR (QSPI)
+ * 2. OTHERS (SD/MMC, SPI, I2C1)
+ */
+#define RCW_SRC_SERIAL_MASK 0x7F
+#define QSPI_VAL 0x62
+#define SDHC_VAL 0x40
+#define EMMC_VAL 0x41
+
+/*
+ * Required LS standard platform porting definitions
+ * for CCN-504 - Read from RN-F node ID register
+ */
+#define PLAT_CLUSTER_TO_CCN_ID_MAP 1, 9, 11, 19
+
+/* Defines required for using XLAT tables from ARM common code */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 40)
+
+/*
+ * Clock Divisors
+ */
+#define NXP_PLATFORM_CLK_DIVIDER 1
+#define NXP_UART_CLK_DIVIDER 2
+
+/* dcfg register offsets and values */
+#define DCFG_DEVDISR1_OFFSET 0x70
+#define DCFG_DEVDISR2_OFFSET 0x74
+#define DCFG_DEVDISR3_OFFSET 0x78
+#define DCFG_DEVDISR5_OFFSET 0x80
+#define DCFG_DEVDISR6_OFFSET 0x84
+
+#define DCFG_DEVDISR1_SEC (1 << 22)
+#define DCFG_DEVDISR3_QBMAIN (1 << 12)
+#define DCFG_DEVDISR4_SPI_QSPI (1 << 4 | 1 << 5)
+#define DCFG_DEVDISR5_MEM (1 << 0)
+
+#define DEVDISR1_VALUE 0x0041310c
+#define DEVDISR2_VALUE 0x000003ff
+#define DEVDISR3_VALUE 0x00013006
+#define DEVDISR4_VALUE 0x0000033e
+#define DEVDISR5_VALUE 0x00103300
+#define DEVDISR6_VALUE 0x00000001
+
+/*
+ * pwr mgmt features supported in the soc-specific code:
+ * value == 0x0, the soc code does not support this feature
+ * value != 0x0, the soc code supports this feature
+ */
+#define SOC_CORE_RELEASE 0x1
+#define SOC_CORE_RESTART 0x1
+#define SOC_CORE_OFF 0x1
+#define SOC_CORE_STANDBY 0x1
+#define SOC_CORE_PWR_DWN 0x1
+#define SOC_CLUSTER_STANDBY 0x1
+#define SOC_CLUSTER_PWR_DWN 0x1
+#define SOC_SYSTEM_STANDBY 0x1
+#define SOC_SYSTEM_PWR_DWN 0x1
+#define SOC_SYSTEM_OFF 0x1
+#define SOC_SYSTEM_RESET 0x1
+
+#define SYSTEM_PWR_DOMAINS 1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ NUMBER_OF_CLUSTERS + \
+ SYSTEM_PWR_DOMAINS)
+
+/* Power state coordination occurs at the system level */
+#define PLAT_PD_COORD_LVL MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LVL PLAT_PD_COORD_LVL
+
+/* Local power state for power domains in Run state */
+#define LS_LOCAL_STATE_RUN PSCI_LOCAL_STATE_RUN
+
+/* define retention state */
+#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1)
+#define LS_LOCAL_STATE_RET PLAT_MAX_RET_STATE
+
+/* define power-down state */
+#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1)
+#define LS_LOCAL_STATE_OFF PLAT_MAX_OFF_STATE
+
+#ifndef __ASSEMBLER__
+/* CCI slave interfaces */
+static const int cci_map[] = {
+ 3,
+ 4,
+};
+void soc_init_lowlevel(void);
+void soc_init_percpu(void);
+void _soc_set_start_addr(unsigned long addr);
+void _set_platform_security(void);
+#endif
+
+#endif /* SOC_H */
diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c b/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c
new file mode 100644
index 0000000..b7397ba
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <utils.h>
+
+#include <errata.h>
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+#error No static value defined
+#endif
+
+static const struct rc_timing rce[] = {
+ {U(1600), U(8), U(8)},
+ {U(1867), U(8), U(8)},
+ {U(2134), U(8), U(9)},
+ {}
+};
+
+static const struct board_timing udimm[] = {
+ {U(0x04), rce, U(0x01020307), U(0x08090b06)},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ int ret;
+ struct memctl_opt *popts = &priv->opt;
+
+ if (popts->rdimm != 0) {
+ debug("RDIMM parameters not set.\n");
+ return -EINVAL;
+ }
+
+ ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm));
+ if (ret != 0) {
+ return ret;
+ }
+
+ popts->addr_hash = 1;
+ popts->cpo_sample = U(0x7b);
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
+ DDR_CDR1_ODT(DDR_CDR_ODT_60ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) |
+ DDR_CDR2_VREF_TRAIN_EN |
+ DDR_CDR2_VREF_RANGE_2;
+
+ return 0;
+}
+
+long long init_ddr(void)
+{
+ int spd_addr[] = { NXP_SPD_EEPROM0 };
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ get_clocks(&sys);
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL %lu\n", sys.freq_ddr_pll0);
+
+ zeromem(&info, sizeof(struct ddr_info));
+ info.num_ctlrs = NUM_OF_DDRC;
+ info.dimm_on_ctlr = DDRC_NUM_DIMM;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+ dram_size = dram_init(&info);
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+ erratum_a008850_post();
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h b/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h
new file mode 100644
index 0000000..ebd3a26
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+/*
+ * Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+#define NXP_SPD_EEPROM0 0x51
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+#define BL2_START NXP_OCRAM_ADDR
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+#define BL2_NOLOAD_START NXP_OCRAM_ADDR
+#define BL2_NOLOAD_LIMIT BL2_BASE
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES 4
+#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_HANDLES 4
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES 2
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 1
+#endif
+
+#define BL32_IRQ_SEC_PHY_TIMER 29
+#define BL31_WDOG_SEC 89
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
+#define PLAT_LS_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+
+#endif /* PLAT_DEF_H */
diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/platform.c b/plat/nxp/soc-ls1088a/ls1088aqds/platform.c
new file mode 100644
index 0000000..8b3eada
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088aqds/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk b/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk
new file mode 100644
index 0000000..97ccf26
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk
@@ -0,0 +1,31 @@
+#
+# Copyright 2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+BOOT_MODE ?= qspi
+BOARD := ls1088aqds
+
+# DDR Compilation Configs
+NUM_OF_DDRC := 1
+DDRC_NUM_DIMM := 1
+DDR_ECC_EN := yes
+
+# On-Board Flash Details
+QSPI_FLASH_SZ := 0x4000000
+NOR_FLASH_SZ := 0x20000000
+
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := qspi \
+ sd \
+ nor
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-ls1088a/soc.mk
diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h b/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h
new file mode 100644
index 0000000..7daf1c0
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1088a/ls1088aqds/policy.h b/plat/nxp/soc-ls1088a/ls1088aqds/policy.h
new file mode 100644
index 0000000..0eaafae
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088aqds/policy.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/*
+ * Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c b/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c
new file mode 100644
index 0000000..c88583f
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <utils.h>
+
+#include <errata.h>
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+#error No static value defined
+#endif
+
+static const struct rc_timing rce[] = {
+ {U(1600), U(8), U(8)},
+ {U(1867), U(8), U(8)},
+ {U(2134), U(8), U(9)},
+ {}
+};
+
+static const struct board_timing udimm[] = {
+ {U(0x04), rce, U(0x01030508), U(0x090b0d06)},
+ {U(0x1f), rce, U(0x01030508), U(0x090b0d06)},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ int ret;
+ struct memctl_opt *popts = &priv->opt;
+
+ if (popts->rdimm != 0) {
+ debug("RDIMM parameters not set.\n");
+ return -EINVAL;
+ }
+
+ ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm));
+ if (ret != 0) {
+ return ret;
+ }
+
+ popts->addr_hash = 1;
+ popts->cpo_sample = U(0x7b);
+ popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
+ DDR_CDR1_ODT(DDR_CDR_ODT_60ohm);
+ popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) |
+ DDR_CDR2_VREF_TRAIN_EN |
+ DDR_CDR2_VREF_RANGE_2;
+
+ return 0;
+}
+
+long long init_ddr(void)
+{
+ int spd_addr[] = { NXP_SPD_EEPROM0 };
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ get_clocks(&sys);
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL %lu\n", sys.freq_ddr_pll0);
+
+ zeromem(&info, sizeof(struct ddr_info));
+ info.num_ctlrs = NUM_OF_DDRC;
+ info.dimm_on_ctlr = DDRC_NUM_DIMM;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+ dram_size = dram_init(&info);
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+ erratum_a008850_post();
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h b/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h
new file mode 100644
index 0000000..a6b14fe
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+/*
+ * Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+#define NXP_SPD_EEPROM0 0x51
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+#define BL2_START NXP_OCRAM_ADDR
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+#define BL2_NOLOAD_START NXP_OCRAM_ADDR
+#define BL2_NOLOAD_LIMIT BL2_BASE
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES 4
+#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_HANDLES 4
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES 2
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 1
+#endif
+
+#define BL32_IRQ_SEC_PHY_TIMER 29
+#define BL31_WDOG_SEC 89
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
+#define PLAT_LS_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#endif /* PLAT_DEF_H */
diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/platform.c b/plat/nxp/soc-ls1088a/ls1088ardb/platform.c
new file mode 100644
index 0000000..8b3eada
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088ardb/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk b/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk
new file mode 100644
index 0000000..6884faf
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+BOOT_MODE ?= qspi
+BOARD := ls1088ardb
+
+# DDR Compilation Configs
+NUM_OF_DDRC := 1
+DDRC_NUM_DIMM := 1
+DDR_ECC_EN := yes
+
+# On-Board Flash Details
+QSPI_FLASH_SZ := 0x4000000
+
+# Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c \
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := qspi \
+ sd
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-ls1088a/soc.mk
diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h b/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h
new file mode 100644
index 0000000..7daf1c0
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1088a/ls1088ardb/policy.h b/plat/nxp/soc-ls1088a/ls1088ardb/policy.h
new file mode 100644
index 0000000..af206f9
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/ls1088ardb/policy.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/* Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1088a/soc.c b/plat/nxp/soc-ls1088a/soc.c
new file mode 100644
index 0000000..5f9f313
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/soc.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright 2022 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <caam.h>
+#include <cci.h>
+#include <common/debug.h>
+#include <dcfg.h>
+#ifdef I2C_INIT
+#include <i2c.h>
+#endif
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <ls_interconnect.h>
+#if TRUSTED_BOARD_BOOT
+#include <nxp_smmu.h>
+#endif
+#include <nxp_timer.h>
+#include <plat_console.h>
+#include <plat_gic.h>
+#include <plat_tzc400.h>
+#include <pmu.h>
+#if defined(NXP_SFP_ENABLED)
+#include <sfp.h>
+#endif
+
+#include <errata.h>
+#ifdef CONFIG_OCRAM_ECC_EN
+#include <ocram.h>
+#endif
+#include <plat_common.h>
+#include <platform_def.h>
+#include <soc.h>
+
+static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2];
+static struct soc_type soc_list[] = {
+ SOC_ENTRY(LS1044A, LS1044A, 1, 4),
+ SOC_ENTRY(LS1044AE, LS1044AE, 1, 4),
+ SOC_ENTRY(LS1048A, LS1048A, 1, 4),
+ SOC_ENTRY(LS1048AE, LS1048AE, 1, 4),
+ SOC_ENTRY(LS1084A, LS1084A, 2, 4),
+ SOC_ENTRY(LS1084AE, LS1084AE, 2, 4),
+ SOC_ENTRY(LS1088A, LS1088A, 2, 4),
+ SOC_ENTRY(LS1088AE, LS1088AE, 2, 4),
+};
+
+static dcfg_init_info_t dcfg_init_data = {
+ .g_nxp_dcfg_addr = NXP_DCFG_ADDR,
+ .nxp_sysclk_freq = NXP_SYSCLK_FREQ,
+ .nxp_ddrclk_freq = NXP_DDRCLK_FREQ,
+ .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER,
+};
+
+/*
+ * This function dynamically constructs the topology according to
+ * SoC Flavor and returns it.
+ */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ unsigned int i;
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+
+ /*
+ * The highest level is the system level. The next level is constituted
+ * by clusters and then cores in clusters.
+ */
+ _power_domain_tree_desc[0] = 1;
+ _power_domain_tree_desc[1] = num_clusters;
+
+ for (i = 0; i < _power_domain_tree_desc[1]; i++) {
+ _power_domain_tree_desc[i + 2] = cores_per_cluster;
+ }
+
+
+ return _power_domain_tree_desc;
+}
+
+CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256,
+ assert_invalid_ls1088a_cluster_count);
+
+/*
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ */
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr)
+{
+ return CORES_PER_CLUSTER;
+}
+
+/*
+ * This function returns the total number of cores in the SoC
+ */
+unsigned int get_tot_num_cores(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+
+ return (num_clusters * cores_per_cluster);
+}
+
+/*
+ * This function returns the PMU IDLE Cluster mask.
+ */
+unsigned int get_pmu_idle_cluster_mask(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+
+ return ((1 << num_clusters) - 2);
+}
+
+/*
+ * This function returns the PMU Flush Cluster mask.
+ */
+unsigned int get_pmu_flush_cluster_mask(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+
+ return ((1 << num_clusters) - 2);
+}
+
+/*
+ * This function returns the PMU IDLE Core mask.
+ */
+unsigned int get_pmu_idle_core_mask(void)
+{
+ return ((1 << get_tot_num_cores()) - 2);
+}
+
+#ifdef IMAGE_BL2
+
+void soc_bl2_prepare_exit(void)
+{
+#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE)
+ set_sfp_wr_disable();
+#endif
+}
+
+void soc_preload_setup(void)
+{
+
+}
+
+/*
+ * This function returns the boot device based on RCW_SRC
+ */
+enum boot_device get_boot_dev(void)
+{
+ enum boot_device src = BOOT_DEVICE_NONE;
+ uint32_t porsr1;
+ uint32_t rcw_src, val;
+
+ porsr1 = read_reg_porsr1();
+
+ rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT;
+
+ /* RCW SRC NOR */
+ val = rcw_src & RCW_SRC_TYPE_MASK;
+ if (val == NOR_16B_VAL) {
+ src = BOOT_DEVICE_IFC_NOR;
+ INFO("RCW BOOT SRC is IFC NOR\n");
+ } else {
+ val = rcw_src & RCW_SRC_SERIAL_MASK;
+ switch (val) {
+ case QSPI_VAL:
+ src = BOOT_DEVICE_QSPI;
+ INFO("RCW BOOT SRC is QSPI\n");
+ break;
+ case SDHC_VAL:
+ src = BOOT_DEVICE_EMMC;
+ INFO("RCW BOOT SRC is SD/EMMC\n");
+ break;
+ case EMMC_VAL:
+ src = BOOT_DEVICE_EMMC;
+ INFO("RCW BOOT SRC is SD/EMMC\n");
+ break;
+ default:
+ src = BOOT_DEVICE_NONE;
+ }
+ }
+
+ return src;
+}
+
+/*
+ * This function sets up access permissions on memory regions
+ */
+void soc_mem_access(void)
+{
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+ int i = 0;
+ struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION];
+ int dram_idx, index = 1;
+
+ for (dram_idx = 0; dram_idx < info_dram_regions->num_dram_regions;
+ dram_idx++) {
+ if (info_dram_regions->region[i].size == 0) {
+ ERROR("DDR init failure, or");
+ ERROR("DRAM regions not populated correctly.\n");
+ break;
+ }
+
+ index = populate_tzc400_reg_list(tzc400_reg_list,
+ dram_idx, index,
+ info_dram_regions->region[dram_idx].addr,
+ info_dram_regions->region[dram_idx].size,
+ NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE);
+ }
+
+ mem_access_setup(NXP_TZC_ADDR, index,
+ tzc400_reg_list);
+}
+
+/*
+ * This function implements soc specific erratum
+ * This is called before DDR is initialized or MMU is enabled
+ */
+void soc_early_init(void)
+{
+ enum boot_device dev;
+ dram_regions_info_t *dram_regions_info = get_dram_regions_info();
+
+#ifdef CONFIG_OCRAM_ECC_EN
+ ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE);
+#endif
+ dcfg_init(&dcfg_init_data);
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+ enable_timer_base_to_cluster(NXP_PMU_ADDR);
+ enable_core_tb(NXP_PMU_ADDR);
+
+ /*
+ * Use the region(NXP_SD_BLOCK_BUF_ADDR + NXP_SD_BLOCK_BUF_SIZE)
+ * as dma of sd
+ */
+ dev = get_boot_dev();
+ if (dev == BOOT_DEVICE_EMMC) {
+ mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR,
+ NXP_SD_BLOCK_BUF_SIZE,
+ MT_DEVICE | MT_RW | MT_NS);
+ }
+
+#if TRUSTED_BOARD_BOOT
+ uint32_t mode;
+
+ sfp_init(NXP_SFP_ADDR);
+ /*
+ * For secure boot disable SMMU.
+ * Later when platform security policy comes in picture,
+ * this might get modified based on the policy
+ */
+ if (check_boot_mode_secure(&mode) == true) {
+ bypass_smmu(NXP_SMMU_ADDR);
+ }
+
+ /*
+ * For Mbedtls currently crypto is not supported via CAAM
+ * enable it when that support is there. In tbbr.mk
+ * the CAAM_INTEG is set as 0.
+ */
+#ifndef MBEDTLS_X509
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false) {
+ INFO("SEC is disabled.\n");
+ } else {
+ sec_init(NXP_CAAM_ADDR);
+ }
+#endif
+#endif
+
+ soc_errata();
+
+ delay_timer_init(NXP_TIMER_ADDR);
+ i2c_init(NXP_I2C_ADDR);
+ dram_regions_info->total_dram_size = init_ddr();
+}
+#else /* !IMAGE_BL2 */
+
+void soc_early_platform_setup2(void)
+{
+ dcfg_init(&dcfg_init_data);
+ /*
+ * Initialize system level generic timer for Socs
+ */
+ delay_timer_init(NXP_TIMER_ADDR);
+
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+}
+
+void soc_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ static uintptr_t target_mask_array[PLATFORM_CORE_COUNT];
+ static interrupt_prop_t ls_interrupt_props[] = {
+ PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0)
+ };
+
+ plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR,
+ PLATFORM_CORE_COUNT,
+ ls_interrupt_props,
+ ARRAY_SIZE(ls_interrupt_props),
+ target_mask_array,
+ plat_core_pos);
+
+ plat_ls_gic_init();
+ enable_init_timer();
+}
+
+/*
+ * This function initializes the soc from the BL31 module
+ */
+void soc_init(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ /* low-level init of the soc */
+ soc_init_lowlevel();
+ _init_global_data();
+ soc_init_percpu();
+ _initialize_psci();
+
+ /*
+ * Initialize Interconnect for this cluster during cold boot.
+ * No need for locks as no other CPU is active.
+ */
+ cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+ plat_ls_interconnect_enter_coherency(num_clusters);
+
+ /* set platform security policies */
+ _set_platform_security();
+
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false) {
+ INFO("SEC is disabled.\n");
+ } else {
+ sec_init(NXP_CAAM_ADDR);
+ }
+}
+
+void soc_runtime_setup(void)
+{
+
+}
+#endif /* IMAGE_BL2 */
+
+/*
+ * Function to return the SoC SYS CLK
+ */
+unsigned int get_sys_clk(void)
+{
+ return NXP_SYSCLK_FREQ;
+}
+
+/*
+ * Function returns the base counter frequency
+ * after reading the first entry at CNTFID0 (0x20 offset).
+ *
+ * Function is used by:
+ * 1. ARM common code for PSCI management.
+ * 2. ARM Generic Timer init.
+ */
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+ /*
+ * Below register specifies the base frequency of the system counter.
+ * As per NXP Board Manuals:
+ * The system counter always works with SYS_REF_CLK/4 frequency clock.
+ */
+ counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF);
+
+ return counter_base_frequency;
+}
diff --git a/plat/nxp/soc-ls1088a/soc.def b/plat/nxp/soc-ls1088a/soc.def
new file mode 100644
index 0000000..25d0847
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/soc.def
@@ -0,0 +1,87 @@
+#
+# Copyright 2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# This file contains the basic architecture definitions that drive the build
+#
+# -----------------------------------------------------------------------------
+
+CORE_TYPE := a53
+
+CACHE_LINE := 6
+
+# Set to GIC400 or GIC500
+GIC := GIC500
+
+# Set to CCI400 or CCN504 or CCN508
+INTERCONNECT := CCI400
+
+# Select the DDR PHY generation to be used
+PLAT_DDR_PHY := PHY_GEN1
+
+PHYS_SYS := 64
+
+# Indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2
+CHASSIS := 3
+
+# TZC IP Details TZC used is TZC380 or TZC400
+TZC_ID := TZC400
+
+# CONSOLE Details available is NS16550 or PL011
+CONSOLE := NS16550
+
+NXP_SFP_VER := 3_4
+
+# In IMAGE_BL2, compile time flag for handling Cache coherency
+# with CAAM for BL2 running from OCRAM
+SEC_MEM_NON_COHERENT := yes
+
+
+# OCRAM MAP for BL2
+# Before BL2
+# 0x18000000 - 0x18009fff -> Used by ROM code, (TBD - can it be used for xlat tables)
+# 0x1800a000 - 0x1801Cfff -> Reserved for BL2 binary (76 KB)
+# 0x1801D000 - 0x1801ffff -> CSF header for BL2 (12 KB)
+OCRAM_START_ADDR := 0x18000000
+OCRAM_SIZE := 0x20000
+
+CSF_HDR_SZ := 0x3000
+
+# Area of OCRAM reserved by ROM code
+NXP_ROM_RSVD := 0xa000
+
+# Input to CST create_hdr_isbc tool
+BL2_HDR_LOC := 0x1801D000
+
+# Location of BL2 on OCRAM
+# BL2_BASE=OCRAM_START_ADDR+NXP_ROM_RSVD
+BL2_BASE := 0x1800a000
+
+# SoC ERRATUM to be enabled
+ERRATA_SOC_A008850 := 1
+
+# ARM Erratum
+ERRATA_A53_855873 := 1
+
+# DDR Erratum
+ERRATA_DDR_A008511 := 1
+ERRATA_DDR_A009803 := 1
+ERRATA_DDR_A009942 := 1
+ERRATA_DDR_A010165 := 1
+
+# Define Endianness of each module
+NXP_ESDHC_ENDIANNESS := LE
+NXP_SFP_ENDIANNESS := LE
+NXP_GPIO_ENDIANNESS := LE
+NXP_SNVS_ENDIANNESS := LE
+NXP_GUR_ENDIANNESS := LE
+NXP_SEC_ENDIANNESS := LE
+NXP_DDR_ENDIANNESS := LE
+NXP_QSPI_ENDIANNESS := LE
+
+# OCRAM ECC Enabled
+OCRAM_ECC_EN := yes
diff --git a/plat/nxp/soc-ls1088a/soc.mk b/plat/nxp/soc-ls1088a/soc.mk
new file mode 100644
index 0000000..83ac9d0
--- /dev/null
+++ b/plat/nxp/soc-ls1088a/soc.mk
@@ -0,0 +1,110 @@
+#
+# Copyright 2022 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SoC-specific build parameters
+SOC := ls1088a
+PLAT_PATH := plat/nxp
+PLAT_COMMON_PATH:= plat/nxp/common
+PLAT_DRIVERS_PATH:= drivers/nxp
+PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC}
+BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD}
+
+# Separate BL2 NOLOAD region (.bss, stack, page tables). need to
+# define BL2_NOLOAD_START and BL2_NOLOAD_LIMIT
+SEPARATE_BL2_NOLOAD_REGION := 1
+
+# get SoC-specific defnitions
+include ${PLAT_SOC_PATH}/soc.def
+include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk
+include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
+
+# For Security Features
+DISABLE_FUSE_WRITE := 1
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+ifeq (${GENERATE_COT},1)
+# Save Keys to be used by DDR FIP image
+SAVE_KEYS=1
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2))
+# Used by create_pbl tool to
+# create bl2_<boot_mode>_sec.pbl image
+SECURE_BOOT := yes
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM))
+
+# Selecting Drivers for SoC
+$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+
+# Selecting PSCI & SIP_SVC support
+$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31))
+
+
+# Adding SoC specific files
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
+
+PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\
+ -I${BOARD_PATH}\
+ -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
+ -I${PLAT_COMMON_PATH}/soc_errata\
+ -I${PLAT_COMMON_PATH}/include\
+ -I${PLAT_SOC_PATH}/include
+
+ifeq (${SECURE_BOOT},yes)
+include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
+endif
+
+ifeq (${PSCI_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/psci/psci.mk
+endif
+
+ifeq (${SIPSVC_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk
+endif
+
+# for fuse-fip & fuse-programming
+ifeq (${FUSE_PROG}, 1)
+include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk
+endif
+
+ifeq (${IMG_LOADR_NEEDED},yes)
+include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk
+endif
+
+# Adding source files for the above selected drivers.
+include ${PLAT_DRIVERS_PATH}/drivers.mk
+
+PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\
+ ${PLAT_SOC_PATH}/${ARCH}/${SOC}_helpers.S\
+ ${PLAT_SOC_PATH}/soc.c
+
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\
+ ${PSCI_SOURCES}\
+ ${SIPSVC_SOURCES}\
+ ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S
+
+ifeq (${TEST_BL31}, 1)
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S \
+ ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S
+endif
+
+BL2_SOURCES += ${DDR_CNTLR_SOURCES}\
+ ${TBBR_SOURCES}\
+ ${FUSE_SOURCES}
+
+# Adding TFA setup files
+include ${PLAT_PATH}/common/setup/common.mk
diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
new file mode 100644
index 0000000..cc679f2
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
@@ -0,0 +1,1816 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+.section .text, "ax"
+
+#include <asm_macros.S>
+
+#include <lib/psci/psci.h>
+#include <nxp_timer.h>
+#include <plat_gic.h>
+#include <pmu.h>
+
+#include <bl31_data.h>
+#include <plat_psci.h>
+#include <platform_def.h>
+
+.global soc_init_start
+.global soc_init_percpu
+.global soc_init_finish
+.global _set_platform_security
+.global _soc_set_start_addr
+
+.global _soc_core_release
+.global _soc_ck_disabled
+.global _soc_core_restart
+.global _soc_core_prep_off
+.global _soc_core_entr_off
+.global _soc_core_exit_off
+.global _soc_sys_reset
+.global _soc_sys_off
+.global _soc_core_prep_stdby
+.global _soc_core_entr_stdby
+.global _soc_core_exit_stdby
+.global _soc_core_prep_pwrdn
+.global _soc_core_entr_pwrdn
+.global _soc_core_exit_pwrdn
+.global _soc_clstr_prep_stdby
+.global _soc_clstr_exit_stdby
+.global _soc_clstr_prep_pwrdn
+.global _soc_clstr_exit_pwrdn
+.global _soc_sys_prep_stdby
+.global _soc_sys_exit_stdby
+.global _soc_sys_prep_pwrdn
+.global _soc_sys_pwrdn_wfi
+.global _soc_sys_exit_pwrdn
+
+.equ TZPC_BASE, 0x02200000
+.equ TZPCDECPROT_0_SET_BASE, 0x02200804
+.equ TZPCDECPROT_1_SET_BASE, 0x02200810
+.equ TZPCDECPROT_2_SET_BASE, 0x0220081C
+
+#define CLUSTER_3_CORES_MASK 0xC0
+#define CLUSTER_3_IN_RESET 1
+#define CLUSTER_3_NORMAL 0
+
+/* cluster 3 handling no longer based on frequency, but rather on RCW[850],
+ * which is bit 18 of RCWSR27
+ */
+#define CLUSTER_3_RCW_BIT 0x40000
+
+/* retry count for clock-stop acks */
+.equ CLOCK_RETRY_CNT, 800
+
+/* disable prefetching in the A72 core */
+#define CPUACTLR_DIS_LS_HW_PRE 0x100000000000000
+#define CPUACTLR_DIS_L2_TLB_PRE 0x200000
+
+/* Function starts the initialization tasks of the soc,
+ * using secondary cores if they are available
+ *
+ * Called from C, saving the non-volatile regs
+ * save these as pairs of registers to maintain the
+ * required 16-byte alignment on the stack
+ *
+ * in:
+ * out:
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11
+ */
+func soc_init_start
+ stp x4, x5, [sp, #-16]!
+ stp x6, x7, [sp, #-16]!
+ stp x8, x9, [sp, #-16]!
+ stp x10, x11, [sp, #-16]!
+ stp x12, x13, [sp, #-16]!
+ stp x18, x30, [sp, #-16]!
+
+ /* make sure the personality has been
+ * established by releasing cores that
+ * are marked "to-be-disabled" from reset
+ */
+ bl release_disabled /* 0-9 */
+
+ /* init the task flags */
+ bl _init_task_flags /* 0-1 */
+
+ /* set SCRATCHRW7 to 0x0 */
+ ldr x0, =DCFG_SCRATCHRW7_OFFSET
+ mov x1, xzr
+ bl _write_reg_dcfg
+
+1:
+ /* restore the aarch32/64 non-volatile registers */
+ ldp x18, x30, [sp], #16
+ ldp x12, x13, [sp], #16
+ ldp x10, x11, [sp], #16
+ ldp x8, x9, [sp], #16
+ ldp x6, x7, [sp], #16
+ ldp x4, x5, [sp], #16
+ ret
+endfunc soc_init_start
+
+
+/* Function performs any soc-specific initialization that is needed on
+ * a per-core basis.
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+func soc_init_percpu
+ stp x4, x30, [sp, #-16]!
+
+ bl plat_my_core_mask
+ mov x2, x0 /* x2 = core mask */
+
+ /* Check if this core is marked for prefetch disable
+ */
+ mov x0, #PREFETCH_DIS_OFFSET
+ bl _get_global_data /* 0-1 */
+ tst x0, x2
+ b.eq 1f
+ bl _disable_ldstr_pfetch_A72 /* 0 */
+1:
+ mov x0, #NXP_PMU_ADDR
+ bl enable_timer_base_to_cluster
+ ldp x4, x30, [sp], #16
+ ret
+endfunc soc_init_percpu
+
+
+/* Function completes the initialization tasks of the soc
+ * in:
+ * out:
+ * uses x0, x1, x2, x3, x4
+ */
+func soc_init_finish
+ stp x4, x30, [sp, #-16]!
+
+ ldp x4, x30, [sp], #16
+ ret
+endfunc soc_init_finish
+
+
+/* Function sets the security mechanisms in the SoC to implement the
+ * Platform Security Policy
+ */
+func _set_platform_security
+ mov x8, x30
+
+#if (!SUPPRESS_TZC)
+ /* initialize the tzpc */
+ bl init_tzpc
+#endif
+
+#if (!SUPPRESS_SEC)
+ /* initialize secmon */
+#ifdef NXP_SNVS_ENABLED
+ mov x0, #NXP_SNVS_ADDR
+ bl init_sec_mon
+#endif
+#endif
+
+ mov x30, x8
+ ret
+endfunc _set_platform_security
+
+
+/* Function writes a 64-bit address to bootlocptrh/l
+ * in: x0, 64-bit address to write to BOOTLOCPTRL/H
+ * uses x0, x1, x2
+ */
+func _soc_set_start_addr
+ /* Get the 64-bit base address of the dcfg block */
+ ldr x2, =NXP_DCFG_ADDR
+
+ /* write the 32-bit BOOTLOCPTRL register */
+ mov x1, x0
+ str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET]
+
+ /* write the 32-bit BOOTLOCPTRH register */
+ lsr x1, x0, #32
+ str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET]
+ ret
+endfunc _soc_set_start_addr
+
+/* Function releases a secondary core from reset
+ * in: x0 = core_mask_lsb
+ * out: none
+ * uses: x0, x1, x2, x3
+ */
+func _soc_core_release
+ mov x3, x30
+
+ ldr x1, =NXP_SEC_REGFILE_ADDR
+ /* write to CORE_HOLD to tell
+ * the bootrom that this core is
+ * expected to run.
+ */
+ str w0, [x1, #CORE_HOLD_OFFSET]
+
+ /* read-modify-write BRRL to release core */
+ mov x1, #NXP_RESET_ADDR
+ ldr w2, [x1, #BRR_OFFSET]
+
+ /* x0 = core mask */
+ orr w2, w2, w0
+ str w2, [x1, #BRR_OFFSET]
+ dsb sy
+ isb
+
+ /* send event */
+ sev
+ isb
+
+ mov x30, x3
+ ret
+endfunc _soc_core_release
+
+
+/* Function determines if a core is disabled via COREDISABLEDSR
+ * in: w0 = core_mask_lsb
+ * out: w0 = 0, core not disabled
+ * w0 != 0, core disabled
+ * uses x0, x1
+ */
+func _soc_ck_disabled
+
+ /* get base addr of dcfg block */
+ ldr x1, =NXP_DCFG_ADDR
+
+ /* read COREDISABLEDSR */
+ ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET]
+
+ /* test core bit */
+ and w0, w1, w0
+
+ ret
+endfunc _soc_ck_disabled
+
+
+/* Part of CPU_ON
+ * Function restarts a core shutdown via _soc_core_entr_off
+ * in: x0 = core mask lsb (of the target cpu)
+ * out: x0 == 0, on success
+ * x0 != 0, on failure
+ * uses x0, x1, x2, x3, x4, x5, x6
+ */
+func _soc_core_restart
+ mov x6, x30
+ mov x4, x0
+
+ /* pgm GICD_CTLR - enable secure grp0 */
+ mov x5, #NXP_GICD_ADDR
+ ldr w2, [x5, #GICD_CTLR_OFFSET]
+ orr w2, w2, #GICD_CTLR_EN_GRP_0
+ str w2, [x5, #GICD_CTLR_OFFSET]
+ dsb sy
+ isb
+
+ /* poll on RWP til write completes */
+4:
+ ldr w2, [x5, #GICD_CTLR_OFFSET]
+ tst w2, #GICD_CTLR_RWP
+ b.ne 4b
+
+ /* x4 = core mask lsb
+ * x5 = gicd base addr
+ */
+ mov x0, x4
+ bl get_mpidr_value
+
+ /* x0 = mpidr of target core
+ * x4 = core mask lsb of target core
+ * x5 = gicd base addr
+ */
+
+ /* generate target list bit */
+ and x1, x0, #MPIDR_AFFINITY0_MASK
+ mov x2, #1
+ lsl x2, x2, x1
+
+ /* get the affinity1 field */
+ and x1, x0, #MPIDR_AFFINITY1_MASK
+ lsl x1, x1, #8
+ orr x2, x2, x1
+
+ /* insert the INTID for SGI15 */
+ orr x2, x2, #ICC_SGI0R_EL1_INTID
+
+ /* fire the SGI */
+ msr ICC_SGI0R_EL1, x2
+ dsb sy
+ isb
+
+ /* load '0' on success */
+ mov x0, xzr
+
+ mov x30, x6
+ ret
+endfunc _soc_core_restart
+
+
+/* Part of CPU_OFF
+ * Function programs SoC & GIC registers in preparation for shutting down
+ * the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7
+ */
+func _soc_core_prep_off
+ mov x8, x30
+ mov x7, x0 /* x7 = core mask lsb */
+
+ mrs x1, CORTEX_A72_ECTLR_EL1
+
+ /* set smp and disable L2 snoops in cpuectlr */
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
+ bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK
+ bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK
+
+ /* set retention control in cpuectlr */
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ orr x1, x1, #CPUECTLR_TIMER_8TICKS
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ /* get redistributor rd base addr for this core */
+ mov x0, x7
+ bl get_gic_rd_base
+ mov x6, x0
+
+ /* get redistributor sgi base addr for this core */
+ mov x0, x7
+ bl get_gic_sgi_base
+ mov x5, x0
+
+ /* x5 = gicr sgi base addr
+ * x6 = gicr rd base addr
+ * x7 = core mask lsb
+ */
+
+ /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
+ mov w3, #GICR_ICENABLER0_SGI15
+ str w3, [x5, #GICR_ICENABLER0_OFFSET]
+2:
+ /* poll on rwp bit in GICR_CTLR */
+ ldr w4, [x6, #GICR_CTLR_OFFSET]
+ tst w4, #GICR_CTLR_RWP
+ b.ne 2b
+
+ /* disable GRP1 interrupts at cpu interface */
+ msr ICC_IGRPEN1_EL3, xzr
+
+ /* disable GRP0 ints at cpu interface */
+ msr ICC_IGRPEN0_EL1, xzr
+
+ /* program the redistributor - poll on GICR_CTLR.RWP as needed */
+
+ /* define SGI 15 as Grp0 - GICR_IGROUPR0 */
+ ldr w4, [x5, #GICR_IGROUPR0_OFFSET]
+ bic w4, w4, #GICR_IGROUPR0_SGI15
+ str w4, [x5, #GICR_IGROUPR0_OFFSET]
+
+ /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */
+ ldr w3, [x5, #GICR_IGRPMODR0_OFFSET]
+ bic w3, w3, #GICR_IGRPMODR0_SGI15
+ str w3, [x5, #GICR_IGRPMODR0_OFFSET]
+
+ /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */
+ ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+ bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK
+ str w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+
+ /* enable SGI 15 at redistributor - GICR_ISENABLER0 */
+ mov w3, #GICR_ISENABLER0_SGI15
+ str w3, [x5, #GICR_ISENABLER0_OFFSET]
+ dsb sy
+ isb
+3:
+ /* poll on rwp bit in GICR_CTLR */
+ ldr w4, [x6, #GICR_CTLR_OFFSET]
+ tst w4, #GICR_CTLR_RWP
+ b.ne 3b
+
+ /* quiesce the debug interfaces */
+ mrs x3, osdlr_el1
+ orr x3, x3, #OSDLR_EL1_DLK_LOCK
+ msr osdlr_el1, x3
+ isb
+
+ /* enable grp0 ints */
+ mov x3, #ICC_IGRPEN0_EL1_EN
+ msr ICC_IGRPEN0_EL1, x3
+
+ /* x5 = gicr sgi base addr
+ * x6 = gicr rd base addr
+ * x7 = core mask lsb
+ */
+
+ /* clear any pending interrupts */
+ mvn w1, wzr
+ str w1, [x5, #GICR_ICPENDR0_OFFSET]
+
+ /* make sure system counter is enabled */
+ ldr x3, =NXP_TIMER_ADDR
+ ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 4f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+4:
+ /* enable the core timer and mask timer interrupt */
+ mov x1, #CNTP_CTL_EL0_EN
+ orr x1, x1, #CNTP_CTL_EL0_IMASK
+ msr cntp_ctl_el0, x1
+
+ isb
+ mov x30, x8
+ ret
+endfunc _soc_core_prep_off
+
+
+/* Part of CPU_OFF:
+ * Function performs the final steps to shutdown the core
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5
+ */
+func _soc_core_entr_off
+ mov x5, x30
+ mov x4, x0
+
+1:
+ /* enter low-power state by executing wfi */
+ wfi
+
+ /* see if SGI15 woke us up */
+ mrs x2, ICC_IAR0_EL1
+ mov x3, #ICC_IAR0_EL1_SGI15
+ cmp x2, x3
+ b.ne 2f
+
+ /* deactivate the intrrupts. */
+ msr ICC_EOIR0_EL1, x2
+
+2:
+ /* check if core is turned ON */
+ mov x0, x4
+ /* Fetched the core state in x0 */
+ bl _getCoreState
+
+ cmp x0, #CORE_WAKEUP
+ b.ne 1b
+
+ /* Reached here, exited the wfi */
+
+ mov x30, x5
+ ret
+endfunc _soc_core_entr_off
+
+
+/* Part of CPU_OFF:
+ * Function starts the process of starting a core back up
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6
+ */
+func _soc_core_exit_off
+ mov x6, x30
+ mov x5, x0
+
+ /* disable forwarding of GRP0 ints at cpu interface */
+ msr ICC_IGRPEN0_EL1, xzr
+
+ /* get redistributor sgi base addr for this core */
+ mov x0, x5
+ bl get_gic_sgi_base
+ mov x4, x0
+
+ /* x4 = gicr sgi base addr
+ * x5 = core mask
+ */
+
+ /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
+ mov w1, #GICR_ICENABLER0_SGI15
+ str w1, [x4, #GICR_ICENABLER0_OFFSET]
+
+ /* get redistributor rd base addr for this core */
+ mov x0, x5
+ bl get_gic_rd_base
+ mov x4, x0
+
+2:
+ /* poll on rwp bit in GICR_CTLR */
+ ldr w2, [x4, #GICR_CTLR_OFFSET]
+ tst w2, #GICR_CTLR_RWP
+ b.ne 2b
+
+ /* unlock the debug interfaces */
+ mrs x3, osdlr_el1
+ bic x3, x3, #OSDLR_EL1_DLK_LOCK
+ msr osdlr_el1, x3
+ isb
+
+ dsb sy
+ isb
+ mov x30, x6
+ ret
+endfunc _soc_core_exit_off
+
+
+/* Function requests a reset of the entire SOC
+ * in: none
+ * out: none
+ * uses: x0, x1, x2, x3, x4, x5, x6
+ */
+func _soc_sys_reset
+ mov x6, x30
+
+ ldr x2, =NXP_RST_ADDR
+ /* clear the RST_REQ_MSK and SW_RST_REQ */
+
+ mov w0, #0x00000000
+ str w0, [x2, #RSTCNTL_OFFSET]
+
+ /* initiate the sw reset request */
+ mov w0, #SW_RST_REQ_INIT
+ str w0, [x2, #RSTCNTL_OFFSET]
+
+ /* In case this address range is mapped as cacheable,
+ * flush the write out of the dcaches.
+ */
+ add x2, x2, #RSTCNTL_OFFSET
+ dc cvac, x2
+ dsb st
+ isb
+
+ /* Function does not return */
+ b .
+endfunc _soc_sys_reset
+
+
+/* Part of SYSTEM_OFF:
+ * Function turns off the SoC clocks
+ * Note: Function is not intended to return, and the only allowable
+ * recovery is POR
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+func _soc_sys_off
+
+ /* disable sec, QBman, spi and qspi */
+ ldr x2, =NXP_DCFG_ADDR
+ ldr x0, =DCFG_DEVDISR1_OFFSET
+ ldr w1, =DCFG_DEVDISR1_SEC
+ str w1, [x2, x0]
+ ldr x0, =DCFG_DEVDISR3_OFFSET
+ ldr w1, =DCFG_DEVDISR3_QBMAIN
+ str w1, [x2, x0]
+ ldr x0, =DCFG_DEVDISR4_OFFSET
+ ldr w1, =DCFG_DEVDISR4_SPI_QSPI
+ str w1, [x2, x0]
+
+ /* set TPMWAKEMR0 */
+ ldr x0, =TPMWAKEMR0_ADDR
+ mov w1, #0x1
+ str w1, [x0]
+
+ /* disable icache, dcache, mmu @ EL1 */
+ mov x1, #SCTLR_I_C_M_MASK
+ mrs x0, sctlr_el1
+ bic x0, x0, x1
+ msr sctlr_el1, x0
+
+ /* disable L2 prefetches */
+ mrs x0, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ orr x0, x0, #CPUECTLR_SMPEN_EN
+ orr x0, x0, #CPUECTLR_TIMER_8TICKS
+ msr CORTEX_A72_ECTLR_EL1, x0
+ isb
+
+ /* disable CCN snoop domain */
+ mov x1, #NXP_CCN_HN_F_0_ADDR
+ ldr x0, =CCN_HN_F_SNP_DMN_CTL_MASK
+ str x0, [x1, #CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET]
+3:
+ ldr w2, [x1, #CCN_HN_F_SNP_DMN_CTL_OFFSET]
+ cmp w2, #0x2
+ b.ne 3b
+
+ mov x3, #NXP_PMU_ADDR
+
+4:
+ ldr w1, [x3, #PMU_PCPW20SR_OFFSET]
+ cmp w1, #PMU_IDLE_CORE_MASK
+ b.ne 4b
+
+ mov w1, #PMU_IDLE_CLUSTER_MASK
+ str w1, [x3, #PMU_CLAINACTSETR_OFFSET]
+
+1:
+ ldr w1, [x3, #PMU_PCPW20SR_OFFSET]
+ cmp w1, #PMU_IDLE_CORE_MASK
+ b.ne 1b
+
+ mov w1, #PMU_FLUSH_CLUSTER_MASK
+ str w1, [x3, #PMU_CLL2FLUSHSETR_OFFSET]
+
+2:
+ ldr w1, [x3, #PMU_CLL2FLUSHSR_OFFSET]
+ cmp w1, #PMU_FLUSH_CLUSTER_MASK
+ b.ne 2b
+
+ mov w1, #PMU_FLUSH_CLUSTER_MASK
+ str w1, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET]
+
+ mov w1, #PMU_FLUSH_CLUSTER_MASK
+ str w1, [x3, #PMU_CLSINACTSETR_OFFSET]
+
+ mov x2, #DAIF_SET_MASK
+ mrs x1, spsr_el1
+ orr x1, x1, x2
+ msr spsr_el1, x1
+
+ mrs x1, spsr_el2
+ orr x1, x1, x2
+ msr spsr_el2, x1
+
+ /* force the debug interface to be quiescent */
+ mrs x0, osdlr_el1
+ orr x0, x0, #0x1
+ msr osdlr_el1, x0
+
+ /* invalidate all TLB entries at all 3 exception levels */
+ tlbi alle1
+ tlbi alle2
+ tlbi alle3
+
+ /* x3 = pmu base addr */
+
+ /* request lpm20 */
+ ldr x0, =PMU_POWMGTCSR_OFFSET
+ ldr w1, =PMU_POWMGTCSR_VAL
+ str w1, [x3, x0]
+
+5:
+ wfe
+ b.eq 5b
+endfunc _soc_sys_off
+
+
+/* Part of CPU_SUSPEND
+ * Function puts the calling core into standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+func _soc_core_entr_stdby
+
+ dsb sy
+ isb
+ wfi
+
+ ret
+endfunc _soc_core_entr_stdby
+
+
+/* Part of CPU_SUSPEND
+ * Function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+func _soc_core_prep_stdby
+
+ /* clear CORTEX_A72_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ ret
+endfunc _soc_core_prep_stdby
+
+
+/* Part of CPU_SUSPEND
+ * Function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_core_exit_stdby
+
+ ret
+endfunc _soc_core_exit_stdby
+
+
+/* Part of CPU_SUSPEND
+ * Function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_core_prep_pwrdn
+
+ /* make sure system counter is enabled */
+ ldr x2, =NXP_TIMER_ADDR
+ ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 1f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+
+ /* enable dynamic retention control (CPUECTLR[2:0])
+ * set the SMPEN bit (CPUECTLR[6])
+ */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_RET_MASK
+ orr x1, x1, #CPUECTLR_TIMER_8TICKS
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ isb
+ ret
+endfunc _soc_core_prep_pwrdn
+
+
+/* Part of CPU_SUSPEND
+ * Function puts the calling core into a power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+func _soc_core_entr_pwrdn
+
+ /* X0 = core mask lsb */
+
+ dsb sy
+ isb
+ wfi
+
+ ret
+endfunc _soc_core_entr_pwrdn
+
+
+/* Part of CPU_SUSPEND
+ * Function performs any SoC-specific cleanup after power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_core_exit_pwrdn
+
+ ret
+endfunc _soc_core_exit_pwrdn
+
+
+/* Part of CPU_SUSPEND
+ * Function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+func _soc_clstr_prep_stdby
+
+ /* clear CORTEX_A72_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ ret
+endfunc _soc_clstr_prep_stdby
+
+
+/* Part of CPU_SUSPEND
+ * Function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_clstr_exit_stdby
+
+ ret
+endfunc _soc_clstr_exit_stdby
+
+
+/* Part of CPU_SUSPEND
+ * Function performs SoC-specific programming prior to power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_clstr_prep_pwrdn
+
+ /* make sure system counter is enabled */
+ ldr x2, =NXP_TIMER_ADDR
+ ldr w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+ tst w0, #SYS_COUNTER_CNTCR_EN
+ b.ne 1f
+ orr w0, w0, #SYS_COUNTER_CNTCR_EN
+ str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+
+ /* enable dynamic retention control (CPUECTLR[2:0])
+ * set the SMPEN bit (CPUECTLR[6])
+ */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_RET_MASK
+ orr x1, x1, #CPUECTLR_TIMER_8TICKS
+ orr x1, x1, #CPUECTLR_SMPEN_EN
+ msr CORTEX_A72_ECTLR_EL1, x1
+
+ isb
+ ret
+endfunc _soc_clstr_prep_pwrdn
+
+
+/* Part of CPU_SUSPEND
+ * Function performs any SoC-specific cleanup after power-down state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_clstr_exit_pwrdn
+
+ ret
+endfunc _soc_clstr_exit_pwrdn
+
+
+/* Part of CPU_SUSPEND
+ * Function performs SoC-specific programming prior to standby
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+func _soc_sys_prep_stdby
+
+ /* clear CORTEX_A72_ECTLR_EL1[2:0] */
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ bic x1, x1, #CPUECTLR_TIMER_MASK
+ msr CORTEX_A72_ECTLR_EL1, x1
+ ret
+endfunc _soc_sys_prep_stdby
+
+
+/* Part of CPU_SUSPEND
+ * Function performs any SoC-specific cleanup after standby state
+ * in: x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+func _soc_sys_exit_stdby
+
+ ret
+endfunc _soc_sys_exit_stdby
+
+
+/* Part of CPU_SUSPEND
+ * Function performs SoC-specific programming prior to
+ * suspend-to-power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+func _soc_sys_prep_pwrdn
+
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ /* make sure the smp bit is set */
+ orr x1, x1, #CPUECTLR_SMPEN_MASK
+ /* set the retention control */
+ orr x1, x1, #CPUECTLR_RET_8CLK
+ /* disable tablewalk prefetch */
+ orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
+ msr CORTEX_A72_ECTLR_EL1, x1
+ isb
+
+ ret
+endfunc _soc_sys_prep_pwrdn
+
+
+/* Part of CPU_SUSPEND
+ * Function puts the calling core, and potentially the soc, into a
+ * low-power state
+ * in: x0 = core mask lsb
+ * out: x0 = 0, success
+ * x0 < 0, failure
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14,
+ * x15, x16, x17, x18, x19, x20, x21, x28
+ */
+func _soc_sys_pwrdn_wfi
+ mov x28, x30
+
+ /* disable cluster snooping in the CCN-508 */
+ ldr x1, =NXP_CCN_HN_F_0_ADDR
+ ldr x7, [x1, #CCN_HN_F_SNP_DMN_CTL_OFFSET]
+ mov x6, #CCN_HNF_NODE_COUNT
+1:
+ str x7, [x1, #CCN_HN_F_SNP_DMN_CTL_CLR_OFFSET]
+ sub x6, x6, #1
+ add x1, x1, #CCN_HNF_OFFSET
+ cbnz x6, 1b
+
+ /* x0 = core mask
+ * x7 = hnf sdcr
+ */
+
+ ldr x1, =NXP_PMU_CCSR_ADDR
+ ldr x2, =NXP_PMU_DCSR_ADDR
+
+ /* enable the stop-request-override */
+ mov x3, #PMU_POWMGTDCR0_OFFSET
+ mov x4, #POWMGTDCR_STP_OV_EN
+ str w4, [x2, x3]
+
+ /* x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ * x7 = hnf sdcr
+ */
+
+ /* disable prefetching in the A72 core */
+ mrs x8, CORTEX_A72_CPUACTLR_EL1
+ tst x8, #CPUACTLR_DIS_LS_HW_PRE
+ b.ne 2f
+ dsb sy
+ isb
+ /* disable data prefetch */
+ orr x16, x8, #CPUACTLR_DIS_LS_HW_PRE
+ /* disable tlb prefetch */
+ orr x16, x16, #CPUACTLR_DIS_L2_TLB_PRE
+ msr CORTEX_A72_CPUACTLR_EL1, x16
+ isb
+
+ /* x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ * x7 = hnf sdcr
+ * x8 = cpuactlr
+ */
+
+2:
+ /* save hnf-sdcr and cpuactlr to stack */
+ stp x7, x8, [sp, #-16]!
+
+ /* x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ */
+
+ /* save the IPSTPCRn registers to stack */
+ mov x15, #PMU_IPSTPCR0_OFFSET
+ ldr w9, [x1, x15]
+ mov x16, #PMU_IPSTPCR1_OFFSET
+ ldr w10, [x1, x16]
+ mov x17, #PMU_IPSTPCR2_OFFSET
+ ldr w11, [x1, x17]
+ mov x18, #PMU_IPSTPCR3_OFFSET
+ ldr w12, [x1, x18]
+ mov x19, #PMU_IPSTPCR4_OFFSET
+ ldr w13, [x1, x19]
+ mov x20, #PMU_IPSTPCR5_OFFSET
+ ldr w14, [x1, x20]
+
+ stp x9, x10, [sp, #-16]!
+ stp x11, x12, [sp, #-16]!
+ stp x13, x14, [sp, #-16]!
+
+ /* x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ * x15 = PMU_IPSTPCR0_OFFSET
+ * x16 = PMU_IPSTPCR1_OFFSET
+ * x17 = PMU_IPSTPCR2_OFFSET
+ * x18 = PMU_IPSTPCR3_OFFSET
+ * x19 = PMU_IPSTPCR4_OFFSET
+ * x20 = PMU_IPSTPCR5_OFFSET
+ */
+
+ /* load the full clock mask for IPSTPCR0 */
+ ldr x3, =DEVDISR1_MASK
+ /* get the exclusions */
+ mov x21, #PMU_IPPDEXPCR0_OFFSET
+ ldr w4, [x1, x21]
+ /* apply the exclusions to the mask */
+ bic w7, w3, w4
+ /* stop the clocks in IPSTPCR0 */
+ str w7, [x1, x15]
+
+ /* use same procedure for IPSTPCR1-IPSTPCR5 */
+
+ /* stop the clocks in IPSTPCR1 */
+ ldr x5, =DEVDISR2_MASK
+ mov x21, #PMU_IPPDEXPCR1_OFFSET
+ ldr w6, [x1, x21]
+ bic w8, w5, w6
+ str w8, [x1, x16]
+
+ /* stop the clocks in IPSTPCR2 */
+ ldr x3, =DEVDISR3_MASK
+ mov x21, #PMU_IPPDEXPCR2_OFFSET
+ ldr w4, [x1, x21]
+ bic w9, w3, w4
+ str w9, [x1, x17]
+
+ /* stop the clocks in IPSTPCR3 */
+ ldr x5, =DEVDISR4_MASK
+ mov x21, #PMU_IPPDEXPCR3_OFFSET
+ ldr w6, [x1, x21]
+ bic w10, w5, w6
+ str w10, [x1, x18]
+
+ /* stop the clocks in IPSTPCR4
+ * - exclude the ddr clocks as we are currently executing
+ * out of *some* memory, might be ddr
+ * - exclude the OCRAM clk so that we retain any code/data in
+ * OCRAM
+ * - may need to exclude the debug clock if we are testing
+ */
+ ldr x3, =DEVDISR5_MASK
+ mov w6, #DEVDISR5_MASK_ALL_MEM
+ bic w3, w3, w6
+
+ mov w5, #POLICY_DEBUG_ENABLE
+ cbz w5, 3f
+ mov w6, #DEVDISR5_MASK_DBG
+ bic w3, w3, w6
+3:
+ mov x21, #PMU_IPPDEXPCR4_OFFSET
+ ldr w4, [x1, x21]
+ bic w11, w3, w4
+ str w11, [x1, x19]
+
+ /* stop the clocks in IPSTPCR5 */
+ ldr x5, =DEVDISR6_MASK
+ mov x21, #PMU_IPPDEXPCR5_OFFSET
+ ldr w6, [x1, x21]
+ bic w12, w5, w6
+ str w12, [x1, x20]
+
+ /* x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ * x7 = IPSTPCR0
+ * x8 = IPSTPCR1
+ * x9 = IPSTPCR2
+ * x10 = IPSTPCR3
+ * x11 = IPSTPCR4
+ * x12 = IPSTPCR5
+ */
+
+ /* poll until the clocks are stopped in IPSTPACKSR0 */
+ mov w4, #CLOCK_RETRY_CNT
+ mov x21, #PMU_IPSTPACKSR0_OFFSET
+4:
+ ldr w5, [x1, x21]
+ cmp w5, w7
+ b.eq 5f
+ sub w4, w4, #1
+ cbnz w4, 4b
+
+ /* poll until the clocks are stopped in IPSTPACKSR1 */
+5:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x21, #PMU_IPSTPACKSR1_OFFSET
+6:
+ ldr w5, [x1, x21]
+ cmp w5, w8
+ b.eq 7f
+ sub w4, w4, #1
+ cbnz w4, 6b
+
+ /* poll until the clocks are stopped in IPSTPACKSR2 */
+7:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x21, #PMU_IPSTPACKSR2_OFFSET
+8:
+ ldr w5, [x1, x21]
+ cmp w5, w9
+ b.eq 9f
+ sub w4, w4, #1
+ cbnz w4, 8b
+
+ /* poll until the clocks are stopped in IPSTPACKSR3 */
+9:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x21, #PMU_IPSTPACKSR3_OFFSET
+10:
+ ldr w5, [x1, x21]
+ cmp w5, w10
+ b.eq 11f
+ sub w4, w4, #1
+ cbnz w4, 10b
+
+ /* poll until the clocks are stopped in IPSTPACKSR4 */
+11:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x21, #PMU_IPSTPACKSR4_OFFSET
+12:
+ ldr w5, [x1, x21]
+ cmp w5, w11
+ b.eq 13f
+ sub w4, w4, #1
+ cbnz w4, 12b
+
+ /* poll until the clocks are stopped in IPSTPACKSR5 */
+13:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x21, #PMU_IPSTPACKSR5_OFFSET
+14:
+ ldr w5, [x1, x21]
+ cmp w5, w12
+ b.eq 15f
+ sub w4, w4, #1
+ cbnz w4, 14b
+
+ /* x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ * x7 = IPSTPCR0
+ * x8 = IPSTPCR1
+ * x9 = IPSTPCR2
+ * x10 = IPSTPCR3
+ * x11 = IPSTPCR4
+ * x12 = IPSTPCR5
+ */
+
+15:
+ mov x3, #NXP_DCFG_ADDR
+
+ /* save the devdisr registers to stack */
+ ldr w13, [x3, #DCFG_DEVDISR1_OFFSET]
+ ldr w14, [x3, #DCFG_DEVDISR2_OFFSET]
+ ldr w15, [x3, #DCFG_DEVDISR3_OFFSET]
+ ldr w16, [x3, #DCFG_DEVDISR4_OFFSET]
+ ldr w17, [x3, #DCFG_DEVDISR5_OFFSET]
+ ldr w18, [x3, #DCFG_DEVDISR6_OFFSET]
+
+ stp x13, x14, [sp, #-16]!
+ stp x15, x16, [sp, #-16]!
+ stp x17, x18, [sp, #-16]!
+
+ /* power down the IP in DEVDISR1 - corresponds to IPSTPCR0 */
+ str w7, [x3, #DCFG_DEVDISR1_OFFSET]
+
+ /* power down the IP in DEVDISR2 - corresponds to IPSTPCR1 */
+ str w8, [x3, #DCFG_DEVDISR2_OFFSET]
+
+ /* power down the IP in DEVDISR3 - corresponds to IPSTPCR2 */
+ str w9, [x3, #DCFG_DEVDISR3_OFFSET]
+
+ /* power down the IP in DEVDISR4 - corresponds to IPSTPCR3 */
+ str w10, [x3, #DCFG_DEVDISR4_OFFSET]
+
+ /* power down the IP in DEVDISR5 - corresponds to IPSTPCR4 */
+ str w11, [x3, #DCFG_DEVDISR5_OFFSET]
+
+ /* power down the IP in DEVDISR6 - corresponds to IPSTPCR5 */
+ str w12, [x3, #DCFG_DEVDISR6_OFFSET]
+
+ /* setup register values for the cache-only sequence */
+ mov x4, #NXP_DDR_ADDR
+ mov x5, #NXP_DDR2_ADDR
+ mov x6, x11
+ mov x7, x17
+ ldr x12, =PMU_CLAINACTSETR_OFFSET
+ ldr x13, =PMU_CLSINACTSETR_OFFSET
+ ldr x14, =PMU_CLAINACTCLRR_OFFSET
+ ldr x15, =PMU_CLSINACTCLRR_OFFSET
+
+ /* x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ * x3 = NXP_DCFG_ADDR
+ * x4 = NXP_DDR_ADDR
+ * x5 = NXP_DDR2_ADDR
+ * w6 = IPSTPCR4
+ * w7 = DEVDISR5
+ * x12 = PMU_CLAINACTSETR_OFFSET
+ * x13 = PMU_CLSINACTSETR_OFFSET
+ * x14 = PMU_CLAINACTCLRR_OFFSET
+ * x15 = PMU_CLSINACTCLRR_OFFSET
+ */
+
+ mov x8, #POLICY_DEBUG_ENABLE
+ cbnz x8, 29f
+ /* force the debug interface to be quiescent */
+ mrs x9, OSDLR_EL1
+ orr x9, x9, #0x1
+ msr OSDLR_EL1, x9
+
+ /* enter the cache-only sequence */
+29:
+ bl final_pwrdown
+
+ /* when we are here, the core has come out of wfi and the
+ * ddr is back up
+ */
+
+ mov x8, #POLICY_DEBUG_ENABLE
+ cbnz x8, 30f
+ /* restart the debug interface */
+ mrs x9, OSDLR_EL1
+ mov x10, #1
+ bic x9, x9, x10
+ msr OSDLR_EL1, x9
+
+ /* get saved DEVDISR regs off stack */
+30:
+ ldp x17, x18, [sp], #16
+ ldp x15, x16, [sp], #16
+ ldp x13, x14, [sp], #16
+ /* restore DEVDISR regs */
+ str w18, [x3, #DCFG_DEVDISR6_OFFSET]
+ str w17, [x3, #DCFG_DEVDISR5_OFFSET]
+ str w16, [x3, #DCFG_DEVDISR4_OFFSET]
+ str w15, [x3, #DCFG_DEVDISR3_OFFSET]
+ str w14, [x3, #DCFG_DEVDISR2_OFFSET]
+ str w13, [x3, #DCFG_DEVDISR1_OFFSET]
+ isb
+
+ /* get saved IPSTPCRn regs off stack */
+ ldp x13, x14, [sp], #16
+ ldp x11, x12, [sp], #16
+ ldp x9, x10, [sp], #16
+
+ /* restore IPSTPCRn regs */
+ mov x15, #PMU_IPSTPCR5_OFFSET
+ str w14, [x1, x15]
+ mov x16, #PMU_IPSTPCR4_OFFSET
+ str w13, [x1, x16]
+ mov x17, #PMU_IPSTPCR3_OFFSET
+ str w12, [x1, x17]
+ mov x18, #PMU_IPSTPCR2_OFFSET
+ str w11, [x1, x18]
+ mov x19, #PMU_IPSTPCR1_OFFSET
+ str w10, [x1, x19]
+ mov x20, #PMU_IPSTPCR0_OFFSET
+ str w9, [x1, x20]
+ isb
+
+ /* poll on IPSTPACKCRn regs til IP clocks are restarted */
+ mov w4, #CLOCK_RETRY_CNT
+ mov x15, #PMU_IPSTPACKSR5_OFFSET
+16:
+ ldr w5, [x1, x15]
+ and w5, w5, w14
+ cbz w5, 17f
+ sub w4, w4, #1
+ cbnz w4, 16b
+
+17:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x15, #PMU_IPSTPACKSR4_OFFSET
+18:
+ ldr w5, [x1, x15]
+ and w5, w5, w13
+ cbz w5, 19f
+ sub w4, w4, #1
+ cbnz w4, 18b
+
+19:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x15, #PMU_IPSTPACKSR3_OFFSET
+20:
+ ldr w5, [x1, x15]
+ and w5, w5, w12
+ cbz w5, 21f
+ sub w4, w4, #1
+ cbnz w4, 20b
+
+21:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x15, #PMU_IPSTPACKSR2_OFFSET
+22:
+ ldr w5, [x1, x15]
+ and w5, w5, w11
+ cbz w5, 23f
+ sub w4, w4, #1
+ cbnz w4, 22b
+
+23:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x15, #PMU_IPSTPACKSR1_OFFSET
+24:
+ ldr w5, [x1, x15]
+ and w5, w5, w10
+ cbz w5, 25f
+ sub w4, w4, #1
+ cbnz w4, 24b
+
+25:
+ mov w4, #CLOCK_RETRY_CNT
+ mov x15, #PMU_IPSTPACKSR0_OFFSET
+26:
+ ldr w5, [x1, x15]
+ and w5, w5, w9
+ cbz w5, 27f
+ sub w4, w4, #1
+ cbnz w4, 26b
+
+27:
+ /* disable the stop-request-override */
+ mov x8, #PMU_POWMGTDCR0_OFFSET
+ mov w9, #POWMGTDCR_STP_OV_EN
+ str w9, [x2, x8]
+ isb
+
+ /* get hnf-sdcr and cpuactlr off stack */
+ ldp x7, x8, [sp], #16
+
+ /* restore cpuactlr */
+ msr CORTEX_A72_CPUACTLR_EL1, x8
+ isb
+
+ /* restore snooping in the hnf nodes */
+ ldr x9, =NXP_CCN_HN_F_0_ADDR
+ mov x6, #CCN_HNF_NODE_COUNT
+28:
+ str x7, [x9, #CCN_HN_F_SNP_DMN_CTL_SET_OFFSET]
+ sub x6, x6, #1
+ add x9, x9, #CCN_HNF_OFFSET
+ cbnz x6, 28b
+ isb
+
+ mov x30, x28
+ ret
+endfunc _soc_sys_pwrdn_wfi
+
+
+/* Part of CPU_SUSPEND
+ * Function performs any SoC-specific cleanup after power-down
+ * in: x0 = core mask lsb
+ * out: none
+ * uses x0,
+ */
+func _soc_sys_exit_pwrdn
+
+ mrs x1, CORTEX_A72_ECTLR_EL1
+ /* make sure the smp bit is set */
+ orr x1, x1, #CPUECTLR_SMPEN_MASK
+ /* clr the retention control */
+ mov x2, #CPUECTLR_RET_8CLK
+ bic x1, x1, x2
+ /* enable tablewalk prefetch */
+ mov x2, #CPUECTLR_DISABLE_TWALK_PREFETCH
+ bic x1, x1, x2
+ msr CORTEX_A72_ECTLR_EL1, x1
+ isb
+
+ ret
+endfunc _soc_sys_exit_pwrdn
+
+
+/* Function will pwrdown ddr and the final core - it will do this
+ * by loading itself into the icache and then executing from there
+ * in:
+ * x0 = core mask
+ * x1 = NXP_PMU_CCSR_ADDR
+ * x2 = NXP_PMU_DCSR_ADDR
+ * x3 = NXP_DCFG_ADDR
+ * x4 = NXP_DDR_ADDR
+ * x5 = NXP_DDR2_ADDR
+ * w6 = IPSTPCR4
+ * w7 = DEVDISR5
+ * x12 = PMU_CLAINACTSETR_OFFSET
+ * x13 = PMU_CLSINACTSETR_OFFSET
+ * x14 = PMU_CLAINACTCLRR_OFFSET
+ * x15 = PMU_CLSINACTCLRR_OFFSET
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16,
+ * x17, x18
+ */
+
+/* 4Kb aligned */
+.align 12
+func final_pwrdown
+
+ mov x0, xzr
+ b touch_line_0
+start_line_0:
+ mov x0, #1
+ /* put ddr controller 1 into self-refresh */
+ ldr w8, [x4, #DDR_CFG_2_OFFSET]
+ orr w8, w8, #CFG_2_FORCE_REFRESH
+ str w8, [x4, #DDR_CFG_2_OFFSET]
+
+ /* put ddr controller 2 into self-refresh */
+ ldr w8, [x5, #DDR_CFG_2_OFFSET]
+ orr w8, w8, #CFG_2_FORCE_REFRESH
+ str w8, [x5, #DDR_CFG_2_OFFSET]
+
+ /* stop the clocks in both ddr controllers */
+ mov w10, #DEVDISR5_MASK_DDR
+ mov x16, #PMU_IPSTPCR4_OFFSET
+ orr w9, w6, w10
+ str w9, [x1, x16]
+ isb
+
+ mov x17, #PMU_IPSTPACKSR4_OFFSET
+touch_line_0:
+ cbz x0, touch_line_1
+
+start_line_1:
+ /* poll IPSTPACKSR4 until
+ * ddr controller clocks are stopped.
+ */
+1:
+ ldr w8, [x1, x17]
+ and w8, w8, w10
+ cmp w8, w10
+ b.ne 1b
+
+ /* shut down power to the ddr controllers */
+ orr w9, w7, #DEVDISR5_MASK_DDR
+ str w9, [x3, #DCFG_DEVDISR5_OFFSET]
+
+ /* disable cluster acp ports */
+ mov w8, #CLAINACT_DISABLE_ACP
+ str w8, [x1, x12]
+
+ /* disable skyros ports */
+ mov w9, #CLSINACT_DISABLE_SKY
+ str w9, [x1, x13]
+ isb
+
+touch_line_1:
+ cbz x0, touch_line_2
+
+start_line_2:
+ isb
+3:
+ wfi
+
+ /* if we are here then we are awake
+ * - bring this device back up
+ */
+
+ /* enable skyros ports */
+ mov w9, #CLSINACT_DISABLE_SKY
+ str w9, [x1, x15]
+
+ /* enable acp ports */
+ mov w8, #CLAINACT_DISABLE_ACP
+ str w8, [x1, x14]
+ isb
+
+ /* bring up the ddr controllers */
+ str w7, [x3, #DCFG_DEVDISR5_OFFSET]
+ isb
+ str w6, [x1, x16]
+ isb
+
+ nop
+touch_line_2:
+ cbz x0, touch_line_3
+
+start_line_3:
+ /* poll IPSTPACKSR4 until
+ * ddr controller clocks are running
+ */
+ mov w10, #DEVDISR5_MASK_DDR
+2:
+ ldr w8, [x1, x17]
+ and w8, w8, w10
+ cbnz w8, 2b
+
+ /* take ddr controller 2 out of self-refresh */
+ mov w8, #CFG_2_FORCE_REFRESH
+ ldr w9, [x5, #DDR_CFG_2_OFFSET]
+ bic w9, w9, w8
+ str w9, [x5, #DDR_CFG_2_OFFSET]
+
+ /* take ddr controller 1 out of self-refresh */
+ ldr w9, [x4, #DDR_CFG_2_OFFSET]
+ bic w9, w9, w8
+ str w9, [x4, #DDR_CFG_2_OFFSET]
+ isb
+
+ nop
+ nop
+ nop
+touch_line_3:
+ cbz x0, start_line_0
+
+ /* execute here after ddr is back up */
+
+ ret
+endfunc final_pwrdown
+
+/* Function returns CLUSTER_3_NORMAL if the cores of cluster 3 are
+ * to be handled normally, and it returns CLUSTER_3_IN_RESET if the cores
+ * are to be held in reset
+ * in: none
+ * out: x0 = #CLUSTER_3_NORMAL, cluster 3 treated normal
+ * x0 = #CLUSTER_3_IN_RESET, cluster 3 cores held in reset
+ * uses x0, x1, x2
+ */
+func cluster3InReset
+
+ /* default return is treat cores normal */
+ mov x0, #CLUSTER_3_NORMAL
+
+ /* read RCW_SR27 register */
+ mov x1, #NXP_DCFG_ADDR
+ ldr w2, [x1, #RCW_SR27_OFFSET]
+
+ /* test the cluster 3 bit */
+ tst w2, #CLUSTER_3_RCW_BIT
+ b.eq 1f
+
+ /* if we are here, then the bit was set */
+ mov x0, #CLUSTER_3_IN_RESET
+1:
+ ret
+endfunc cluster3InReset
+
+
+/* Function checks to see if cores which are to be disabled have been
+ * released from reset - if not, it releases them
+ * Note: there may be special handling of cluster 3 cores depending upon the
+ * sys clk frequency
+ * in: none
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9
+ */
+func release_disabled
+ mov x9, x30
+
+ /* check if we need to keep cluster 3 cores in reset */
+ bl cluster3InReset /* 0-2 */
+ mov x8, x0
+
+ /* x8 = cluster 3 handling */
+
+ /* read COREDISABLESR */
+ mov x0, #NXP_DCFG_ADDR
+ ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
+ cmp x8, #CLUSTER_3_IN_RESET
+ b.ne 4f
+
+ /* the cluster 3 cores are to be held in reset, so remove
+ * them from the disable mask
+ */
+ bic x4, x4, #CLUSTER_3_CORES_MASK
+4:
+ /* get the number of cpus on this device */
+ mov x6, #PLATFORM_CORE_COUNT
+
+ mov x0, #NXP_RESET_ADDR
+ ldr w5, [x0, #BRR_OFFSET]
+
+ /* load the core mask for the first core */
+ mov x7, #1
+
+ /* x4 = COREDISABLESR
+ * x5 = BRR
+ * x6 = loop count
+ * x7 = core mask bit
+ */
+2:
+ /* check if the core is to be disabled */
+ tst x4, x7
+ b.eq 1f
+
+ /* see if disabled cores have already been released from reset */
+ tst x5, x7
+ b.ne 5f
+
+ /* if core has not been released, then release it (0-3) */
+ mov x0, x7
+ bl _soc_core_release
+
+ /* record the core state in the data area (0-3) */
+ mov x0, x7
+ mov x1, #CORE_STATE_DATA
+ mov x2, #CORE_DISABLED
+ bl _setCoreData
+
+1:
+ /* see if this is a cluster 3 core */
+ mov x3, #CLUSTER_3_CORES_MASK
+ tst x3, x7
+ b.eq 5f
+
+ /* this is a cluster 3 core - see if it needs to be held in reset */
+ cmp x8, #CLUSTER_3_IN_RESET
+ b.ne 5f
+
+ /* record the core state as disabled in the data area (0-3) */
+ mov x0, x7
+ mov x1, #CORE_STATE_DATA
+ mov x2, #CORE_DISABLED
+ bl _setCoreData
+
+5:
+ /* decrement the counter */
+ subs x6, x6, #1
+ b.le 3f
+
+ /* shift the core mask to the next core */
+ lsl x7, x7, #1
+ /* continue */
+ b 2b
+3:
+ cmp x8, #CLUSTER_3_IN_RESET
+ b.ne 6f
+
+ /* we need to hold the cluster 3 cores in reset,
+ * so mark them in the COREDISR and COREDISABLEDSR registers as
+ * "disabled", and the rest of the sw stack will leave them alone
+ * thinking that they have been disabled
+ */
+ mov x0, #NXP_DCFG_ADDR
+ ldr w1, [x0, #DCFG_COREDISR_OFFSET]
+ orr w1, w1, #CLUSTER_3_CORES_MASK
+ str w1, [x0, #DCFG_COREDISR_OFFSET]
+
+ ldr w2, [x0, #DCFG_COREDISABLEDSR_OFFSET]
+ orr w2, w2, #CLUSTER_3_CORES_MASK
+ str w2, [x0, #DCFG_COREDISABLEDSR_OFFSET]
+ dsb sy
+ isb
+
+#if (PSCI_TEST)
+ /* x0 = NXP_DCFG_ADDR : read COREDISABLESR */
+ ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
+ /* read COREDISR */
+ ldr w3, [x0, #DCFG_COREDISR_OFFSET]
+#endif
+
+6:
+ mov x30, x9
+ ret
+
+endfunc release_disabled
+
+
+/* Function setc up the TrustZone Address Space Controller (TZASC)
+ * in: none
+ * out: none
+ * uses x0, x1
+ */
+func init_tzpc
+
+ /* set Non Secure access for all devices protected via TZPC */
+
+ /* decode Protection-0 Set Reg */
+ ldr x1, =TZPCDECPROT_0_SET_BASE
+ /* set decode region to NS, Bits[7:0] */
+ mov w0, #0xFF
+ str w0, [x1]
+
+ /* decode Protection-1 Set Reg */
+ ldr x1, =TZPCDECPROT_1_SET_BASE
+ /* set decode region to NS, Bits[7:0] */
+ mov w0, #0xFF
+ str w0, [x1]
+
+ /* decode Protection-2 Set Reg */
+ ldr x1, =TZPCDECPROT_2_SET_BASE
+ /* set decode region to NS, Bits[7:0] */
+ mov w0, #0xFF
+ str w0, [x1]
+
+ /* entire SRAM as NS */
+ /* secure RAM region size Reg */
+ ldr x1, =TZPC_BASE
+ /* 0x00000000 = no secure region */
+ mov w0, #0x00000000
+ str w0, [x1]
+
+ ret
+endfunc init_tzpc
+
+/* write a register in the DCFG block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2
+ */
+func _write_reg_dcfg
+ ldr x2, =NXP_DCFG_ADDR
+ str w1, [x2, x0]
+ ret
+endfunc _write_reg_dcfg
+
+
+/* read a register in the DCFG block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+func _read_reg_dcfg
+ ldr x2, =NXP_DCFG_ADDR
+ ldr w1, [x2, x0]
+ mov w0, w1
+ ret
+endfunc _read_reg_dcfg
+
+
+/* Function returns an mpidr value for a core, given a core_mask_lsb
+ * in: x0 = core mask lsb
+ * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits
+ * uses x0, x1
+ */
+func get_mpidr_value
+
+ /* convert a core mask to an SoC core number */
+ clz w0, w0
+ mov w1, #31
+ sub w0, w1, w0
+
+ /* get the mpidr core number from the SoC core number */
+ mov w1, wzr
+ tst x0, #1
+ b.eq 1f
+ orr w1, w1, #1
+
+1:
+ /* extract the cluster number */
+ lsr w0, w0, #1
+ orr w0, w1, w0, lsl #8
+
+ ret
+endfunc get_mpidr_value
+
+
+/* Function returns the redistributor base address for the core specified
+ * in x1
+ * in: x0 - core mask lsb of specified core
+ * out: x0 = redistributor rd base address for specified core
+ * uses x0, x1, x2
+ */
+func get_gic_rd_base
+ clz w1, w0
+ mov w2, #0x20
+ sub w2, w2, w1
+ sub w2, w2, #1
+
+ ldr x0, =NXP_GICR_ADDR
+ mov x1, #GIC_RD_OFFSET
+
+ /* x2 = core number
+ * loop counter
+ */
+2:
+ cbz x2, 1f
+ add x0, x0, x1
+ sub x2, x2, #1
+ b 2b
+1:
+ ret
+endfunc get_gic_rd_base
+
+
+/* Function returns the redistributor base address for the core specified
+ * in x1
+ * in: x0 - core mask lsb of specified core
+ * out: x0 = redistributor sgi base address for specified core
+ * uses x0, x1, x2
+ */
+func get_gic_sgi_base
+ clz w1, w0
+ mov w2, #0x20
+ sub w2, w2, w1
+ sub w2, w2, #1
+
+ ldr x0, =NXP_GICR_SGI_ADDR
+ mov x1, #GIC_SGI_OFFSET
+
+ /* loop counter */
+2:
+ cbz x2, 1f /* x2 = core number */
+ add x0, x0, x1
+ sub x2, x2, #1
+ b 2b
+1:
+ ret
+endfunc get_gic_sgi_base
+
+/* Function writes a register in the RESET block
+ * in: x0 = offset
+ * in: w1 = value to write
+ * uses x0, x1, x2
+ */
+func _write_reg_reset
+ ldr x2, =NXP_RESET_ADDR
+ str w1, [x2, x0]
+ ret
+endfunc _write_reg_reset
+
+
+/* Function reads a register in the RESET block
+ * in: x0 = offset
+ * out: w0 = value read
+ * uses x0, x1
+ */
+func _read_reg_reset
+ ldr x1, =NXP_RESET_ADDR
+ ldr w0, [x1, x0]
+ ret
+endfunc _read_reg_reset
diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S
new file mode 100644
index 0000000..c364dec
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+#include <platform_def.h>
+
+.globl plat_secondary_cold_boot_setup
+.globl plat_is_my_cpu_primary
+.globl plat_reset_handler
+.globl platform_mem_init
+
+
+func platform_mem1_init
+ ret
+endfunc platform_mem1_init
+
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+
+func apply_platform_errata
+
+ ret
+endfunc apply_platform_errata
+
+
+func plat_reset_handler
+ mov x29, x30
+ bl apply_platform_errata
+
+#if defined(IMAGE_BL31)
+ ldr x0, =POLICY_SMMU_PAGESZ_64K
+ cbz x0, 1f
+ /* Set the SMMU page size in the sACR register */
+ bl _set_smmu_pagesz_64
+#endif
+1:
+ mov x30, x29
+
+ ret
+endfunc plat_reset_handler
+
+
+/* void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ */
+func plat_secondary_cold_boot_setup
+ /* lx2160a does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+
+/* unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, 0x0
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S
new file mode 100644
index 0000000..9dec3f2
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+.section .text, "ax"
+
+#include <asm_macros.S>
+
+#ifndef NXP_COINED_BB
+#include <flash_info.h>
+#include <fspi.h>
+#endif
+#include <regs.h>
+#ifdef NXP_COINED_BB
+#include <snvs.h>
+#endif
+
+#include <plat_warm_rst.h>
+#include <platform_def.h>
+
+#define SDRAM_CFG 0x110
+#define SDRAM_CFG_2 0x114
+#define SDRAM_MD_CNTL 0x120
+#define SDRAM_INTERVAL 0x124
+#define TIMING_CFG_10 0x258
+#define DEBUG_2 0xF04
+#define DEBUG_26 0xF64
+#define DDR_DSR2 0xB24
+
+#define DDR_CNTRLR_2 0x2
+#define COUNT_100 1000
+
+ .globl _soc_sys_warm_reset
+ .align 12
+
+func _soc_sys_warm_reset
+ mov x3, xzr
+ b touch_line0
+start_line0:
+ mov x3, #1
+ mov x2, #NUM_OF_DDRC
+ ldr x1, =NXP_DDR_ADDR
+1:
+ ldr w0, [x1, #SDRAM_CFG]
+ orr w0, w0, #SDRAM_CFG_MEM_HLT
+ str w0, [x1, #SDRAM_CFG]
+2:
+ ldr w0, [x1, #DEBUG_2]
+ and w0, w0, #DDR_DBG_2_MEM_IDLE
+ cbz w0, 2b
+
+ ldr w0, [x1, #DEBUG_26]
+ orr w0, w0, #DDR_DEBUG_26_BIT_12
+ orr w0, w0, #DDR_DEBUG_26_BIT_13
+ orr w0, w0, #DDR_DEBUG_26_BIT_14
+touch_line0:
+ cbz x3, touch_line1
+
+ orr w0, w0, #DDR_DEBUG_26_BIT_15
+ orr w0, w0, #DDR_DEBUG_26_BIT_16
+ str w0, [x1, #DEBUG_26]
+
+ ldr w0, [x1, #SDRAM_CFG_2]
+ orr w0, w0, #SDRAM_CFG2_FRC_SR
+ str w0, [x1, #SDRAM_CFG_2]
+
+3:
+ ldr w0, [x1, #DDR_DSR2]
+ orr w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT
+ str w0, [x1, #DDR_DSR2]
+ ldr w0, [x1, #DDR_DSR2]
+ and w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT
+ cbnz w0, 3b
+
+ ldr w0, [x1, #SDRAM_INTERVAL]
+ and w0, w0, #SDRAM_INTERVAL_REFINT_CLEAR
+ str w0, [x1, #SDRAM_INTERVAL]
+touch_line1:
+ cbz x3, touch_line2
+
+ ldr w0, [x1, #SDRAM_MD_CNTL]
+ orr w0, w0, #MD_CNTL_CKE(1)
+ orr w0, w0, #MD_CNTL_MD_EN
+ str w0, [x1, #SDRAM_MD_CNTL]
+
+ ldr w0, [x1, #TIMING_CFG_10]
+ orr w0, w0, #DDR_TIMING_CFG_10_T_STAB
+ str w0, [x1, #TIMING_CFG_10]
+
+ ldr w0, [x1, #SDRAM_CFG_2]
+ and w0, w0, #SDRAM_CFG2_FRC_SR_CLEAR
+ str w0, [x1, #SDRAM_CFG_2]
+
+4:
+ ldr w0, [x1, #DDR_DSR2]
+ and w0, w0, #DDR_DSR_2_PHY_INIT_CMPLT
+ cbz w0, 4b
+ nop
+touch_line2:
+ cbz x3, touch_line3
+
+ ldr w0, [x1, #DEBUG_26]
+ orr w0, w0, #DDR_DEBUG_26_BIT_25
+ and w0, w0, #DDR_DEBUG_26_BIT_24_CLEAR
+ str w0, [x1, #DEBUG_26]
+
+ cmp x2, #DDR_CNTRLR_2
+ b.ne 5f
+ ldr x1, =NXP_DDR2_ADDR
+ mov x2, xzr
+ b 1b
+
+5:
+ mov x5, xzr
+6:
+ add x5, x5, #1
+ cmp x5, #COUNT_100
+ b.ne 6b
+ nop
+touch_line3:
+ cbz x3, touch_line4
+#ifdef NXP_COINED_BB
+ ldr x1, =NXP_SNVS_ADDR
+ ldr w0, [x1, #NXP_APP_DATA_LP_GPR_OFFSET]
+
+ /* On Warm Boot is enabled, then zeroth bit
+ * of SNVS LP GPR register 0 will used
+ * to save the status of warm-reset as a cause.
+ */
+ orr w0, w0, #(1 << NXP_LPGPR_ZEROTH_BIT)
+
+ /* write back */
+ str w0, [x1, #NXP_APP_DATA_LP_GPR_OFFSET]
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+touch_line4:
+ cbz x3, touch_line6
+#elif !(ERLY_WRM_RST_FLG_FLSH_UPDT)
+ ldr x1, =NXP_FLEXSPI_ADDR
+ ldr w0, [x1, #FSPI_IPCMD]
+ orr w0, w0, #FSPI_IPCMD_TRG_MASK
+ str w0, [x1, #FSPI_IPCMD]
+7:
+ ldr w0, [x1, #FSPI_INTR]
+ and w0, w0, #FSPI_INTR_IPCMDDONE_MASK
+ cmp w0, #0
+ b.eq 7b
+
+ ldr w0, [x1, #FSPI_IPTXFCR]
+ orr w0, w0, #FSPI_IPTXFCR_CLR
+ str w0, [x1, #FSPI_IPTXFCR]
+
+ ldr w0, [x1, #FSPI_INTR]
+ orr w0, w0, #FSPI_INTR_IPCMDDONE_MASK
+ str w0, [x1, #FSPI_INTR]
+ nop
+touch_line4:
+ cbz x3, touch_line5
+ /* flexspi driver has an api
+ * is_flash_busy().
+ * Impelementation of the api will not
+ * fit-in in 1 cache line.
+ * instead a nop-cycles are introduced to
+ * simulate the wait time for flash write
+ * completion.
+ *
+ * Note: This wait time varies from flash to flash.
+ */
+
+ mov x0, #FLASH_WR_COMP_WAIT_BY_NOP_COUNT
+8:
+ sub x0, x0, #1
+ nop
+ cmp x0, #0
+ b.ne 8b
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+touch_line5:
+ cbz x3, touch_line6
+#endif
+ ldr x2, =NXP_RST_ADDR
+ /* clear the RST_REQ_MSK and SW_RST_REQ */
+ mov w0, #0x00000000
+ str w0, [x2, #RSTCNTL_OFFSET]
+
+ /* initiate the sw reset request */
+ mov w0, #SW_RST_REQ_INIT
+ str w0, [x2, #RSTCNTL_OFFSET]
+
+ /* In case this address range is mapped as cacheable,
+ * flush the write out of the dcaches.
+ */
+ add x2, x2, #RSTCNTL_OFFSET
+ dc cvac, x2
+ dsb st
+ isb
+
+ /* Function does not return */
+ b .
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+touch_line6:
+ cbz x3, start_line0
+
+endfunc _soc_sys_warm_reset
diff --git a/plat/nxp/soc-lx2160a/ddr_fip.mk b/plat/nxp/soc-lx2160a/ddr_fip.mk
new file mode 100644
index 0000000..f14a9e8
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/ddr_fip.mk
@@ -0,0 +1,97 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+DDR_PHY_BIN_PATH ?= ./ddr-phy-binary/lx2160a
+
+ifeq (${DDR_IMEM_UDIMM_1D},)
+ DDR_IMEM_UDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_pmu_train_imem.bin
+endif
+
+ifeq (${DDR_IMEM_UDIMM_2D},)
+ DDR_IMEM_UDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_2d_pmu_train_imem.bin
+endif
+
+ifeq (${DDR_DMEM_UDIMM_1D},)
+ DDR_DMEM_UDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_pmu_train_dmem.bin
+endif
+
+ifeq (${DDR_DMEM_UDIMM_2D},)
+ DDR_DMEM_UDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_2d_pmu_train_dmem.bin
+endif
+
+ifeq (${DDR_IMEM_RDIMM_1D},)
+ DDR_IMEM_RDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm_pmu_train_imem.bin
+endif
+
+ifeq (${DDR_IMEM_RDIMM_2D},)
+ DDR_IMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_imem.bin
+endif
+
+ifeq (${DDR_DMEM_RDIMM_1D},)
+ DDR_DMEM_RDIMM_1D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm_pmu_train_dmem.bin
+endif
+
+ifeq (${DDR_DMEM_RDIMM_2D},)
+ DDR_DMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_dmem.bin
+endif
+
+$(shell mkdir -p '${BUILD_PLAT}')
+
+ifeq (${DDR_FIP_NAME},)
+ifeq (${TRUSTED_BOARD_BOOT},1)
+ DDR_FIP_NAME := ddr_fip_sec.bin
+else
+ DDR_FIP_NAME := ddr_fip.bin
+endif
+endif
+
+ifneq (${TRUSTED_BOARD_BOOT},1)
+
+DDR_FIP_ARGS += --ddr-immem-udimm-1d ${DDR_IMEM_UDIMM_1D} \
+ --ddr-immem-udimm-2d ${DDR_IMEM_UDIMM_2D} \
+ --ddr-dmmem-udimm-1d ${DDR_DMEM_UDIMM_1D} \
+ --ddr-dmmem-udimm-2d ${DDR_DMEM_UDIMM_2D} \
+ --ddr-immem-rdimm-1d ${DDR_IMEM_RDIMM_1D} \
+ --ddr-immem-rdimm-2d ${DDR_IMEM_RDIMM_2D} \
+ --ddr-dmmem-rdimm-1d ${DDR_DMEM_RDIMM_1D} \
+ --ddr-dmmem-rdimm-2d ${DDR_DMEM_RDIMM_2D}
+endif
+
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+ifeq (${MBEDTLS_DIR},)
+include plat/nxp/soc-lx2160a/ddr_sb.mk
+else
+include plat/nxp/soc-lx2160a/ddr_tbbr.mk
+
+# Variables for use with Certificate Generation Tool
+CRTTOOLPATH ?= tools/cert_create
+CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT}
+
+ifneq (${GENERATE_COT},0)
+ddr_certificates: ${DDR_CRT_DEPS} ${CRTTOOL}
+ ${Q}${CRTTOOL} ${DDR_CRT_ARGS}
+ @${ECHO_BLANK_LINE}
+ @echo "Built $@ successfully"
+ @echo "DDR certificates can be found in ${BUILD_PLAT}"
+ @${ECHO_BLANK_LINE}
+endif
+endif
+endif
+
+# Variables for use with Firmware Image Package
+FIPTOOLPATH ?= tools/fiptool
+FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT}
+
+${BUILD_PLAT}/${DDR_FIP_NAME}: ${DDR_FIP_DEPS} ${FIPTOOL}
+ $(eval ${CHECK_DDR_FIP_CMD})
+ ${Q}${FIPTOOL} create ${DDR_FIP_ARGS} $@
+ ${Q}${FIPTOOL} info $@
+ @${ECHO_BLANK_LINE}
+ @echo "Built $@ successfully"
+ @${ECHO_BLANK_LINE}
+
+fip_ddr: ${BUILD_PLAT}/${DDR_FIP_NAME}
diff --git a/plat/nxp/soc-lx2160a/ddr_sb.mk b/plat/nxp/soc-lx2160a/ddr_sb.mk
new file mode 100644
index 0000000..c11651e
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/ddr_sb.mk
@@ -0,0 +1,43 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+ifeq (${GENERATE_COT},0)
+
+DDR_FIP_ARGS += --ddr-immem-udimm-1d ${DDR_IMEM_UDIMM_1D}.sb \
+ --ddr-immem-udimm-2d ${DDR_IMEM_UDIMM_2D}.sb \
+ --ddr-dmmem-udimm-1d ${DDR_DMEM_UDIMM_1D}.sb \
+ --ddr-dmmem-udimm-2d ${DDR_DMEM_UDIMM_2D}.sb \
+ --ddr-immem-rdimm-1d ${DDR_IMEM_RDIMM_1D}.sb \
+ --ddr-immem-rdimm-2d ${DDR_IMEM_RDIMM_2D}.sb \
+ --ddr-dmmem-rdimm-1d ${DDR_DMEM_RDIMM_1D}.sb \
+ --ddr-dmmem-rdimm-2d ${DDR_DMEM_RDIMM_2D}.sb
+endif
+
+UDIMM_DEPS = ${DDR_IMEM_UDIMM_1D}.sb ${DDR_IMEM_UDIMM_2D}.sb ${DDR_DMEM_UDIMM_1D}.sb ${DDR_DMEM_UDIMM_2D}.sb
+RDIMM_DEPS = ${DDR_IMEM_RDIMM_1D}.sb ${DDR_IMEM_RDIMM_2D}.sb ${DDR_DMEM_RDIMM_1D}.sb ${DDR_DMEM_RDIMM_2D}.sb
+DDR_FIP_DEPS += ${UDIMM_DEPS}
+DDR_FIP_DEPS += ${RDIMM_DEPS}
+
+# Max Size of CSF header (CSF_HDR_SZ = 0x3000).
+# Image will be appended at this offset of the header.
+# 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
+
+ifeq (${DDR_INPUT_FILE},)
+DDR_INPUT_FILE:= drivers/nxp/auth/csf_hdr_parser/${CSF_FILE}
+endif
+
+%.sb: %
+ @echo " Generating CSF Header for $@ $<"
+ $(CST_DIR)/create_hdr_esbc --in $< --out $@ --app_off ${CSF_HDR_SZ} \
+ --app $< ${DDR_INPUT_FILE}
+
+endif
diff --git a/plat/nxp/soc-lx2160a/ddr_tbbr.mk b/plat/nxp/soc-lx2160a/ddr_tbbr.mk
new file mode 100644
index 0000000..deb475b
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/ddr_tbbr.mk
@@ -0,0 +1,95 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# This file defines the keys and certificates that must be created to establish
+# a Chain of Trust for the DDR FW. These definitions include the
+# command line options passed to the cert_create and fiptool commands for DDR FW.
+# A DDR FW key is used for signing the DDR Firmware. The DDR key is authenticated
+# by the Trusted World Key. Two content certificates are created:
+# For DDR RDIMM Images [ signed by DDR FW Key]
+# For DDR UDIMM Images [ signed by DDR FW Key]
+#
+# Expected environment:
+#
+# BUILD_PLAT: output directory
+#
+# Build options added by this file:
+#
+# KEY_ALG
+# KEY_SIZE
+# TRUSTED_WORLD_KEY
+# NON_TRUSTED_WORLD_KEY
+#
+
+# Copy the tbbr.mk from PLAT_TOOL_PATH/cert_create_helper
+# to the ${PLAT_DIR}. So that cert_create is enabled
+# to create certificates for DDR
+$(shell cp ${PLAT_TOOL_PATH}/cert_create_helper/cert_create_tbbr.mk ${PLAT_DIR})
+
+# Certificate generation tool default parameters
+DDR_FW_CERT := ${BUILD_PLAT}/ddr_fw_key_cert.crt
+
+# Default non-volatile counter values (overridable by the platform)
+TFW_NVCTR_VAL ?= 0
+NTFW_NVCTR_VAL ?= 0
+
+# Pass the non-volatile counters to the cert_create tool
+$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr,DDR_))
+
+$(shell mkdir -p '${BUILD_PLAT}')
+
+ifeq (${DDR_KEY},)
+DDR_KEY=${BUILD_PLAT}/ddr.pem
+endif
+
+ifeq (${TRUSTED_KEY_CERT},)
+$(info Generating: Trusted key certificate as part of DDR cert creation)
+TRUSTED_KEY_CERT := ${BUILD_PLAT}/trusted_key.crt
+$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert,))
+$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert,,DDR_))
+else
+$(info Using: Trusted key certificate as part of DDR cert creation)
+DDR_FIP_ARGS += --trusted-key-cert ${TRUSTED_KEY_CERT}
+endif
+
+# Add the keys to the cert_create command line options (private keys are NOT
+# packed in the FIP). Developers can use their own keys by specifying the proper
+# build option in the command line when building the Trusted Firmware
+$(if ${KEY_ALG},$(eval $(call CERT_ADD_CMD_OPT,${KEY_ALG},--key-alg,DDR_)))
+$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size,DDR_)))
+$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg,DDR_)))
+$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,DDR_)))
+$(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key,DDR_)))
+$(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key, DDR_)))
+
+# Add the DDR CoT (key cert + img cert)
+$(if ${DDR_KEY},$(eval $(call CERT_ADD_CMD_OPT,${DDR_KEY},--ddr-fw-key,DDR_)))
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_fw_key.crt,--ddr-fw-key-cert,,DDR_))
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_udimm_fw_content.crt,--ddr-udimm-fw-cert,,DDR_))
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/ddr_rdimm_fw_content.crt,--ddr-rdimm-fw-cert,,DDR_))
+
+$(eval $(call TOOL_ADD_IMG,DDR_IMEM_UDIMM_1D,--ddr-immem-udimm-1d,DDR_))
+$(eval $(call TOOL_ADD_IMG,DDR_IMEM_UDIMM_2D,--ddr-immem-udimm-2d,DDR_))
+$(eval $(call TOOL_ADD_IMG,DDR_DMEM_UDIMM_1D,--ddr-dmmem-udimm-1d,DDR_))
+$(eval $(call TOOL_ADD_IMG,DDR_DMEM_UDIMM_2D,--ddr-dmmem-udimm-2d,DDR_))
+
+$(eval $(call TOOL_ADD_IMG,DDR_IMEM_RDIMM_1D,--ddr-immem-rdimm-1d,DDR_))
+$(eval $(call TOOL_ADD_IMG,DDR_IMEM_RDIMM_2D,--ddr-immem-rdimm-2d,DDR_))
+$(eval $(call TOOL_ADD_IMG,DDR_DMEM_RDIMM_1D,--ddr-dmmem-rdimm-1d,DDR_))
+$(eval $(call TOOL_ADD_IMG,DDR_DMEM_RDIMM_2D,--ddr-dmmem-rdimm-2d,DDR_))
+
+DDR_FIP_DEPS += ddr_certificates
+
+# Process TBB related flags
+ifneq (${GENERATE_COT},0)
+ # Common cert_create options
+ ifneq (${CREATE_KEYS},0)
+ $(eval DDR_CRT_ARGS += -n)
+ ifneq (${SAVE_KEYS},0)
+ $(eval DDR_CRT_ARGS += -k)
+ endif
+ endif
+endif
diff --git a/plat/nxp/soc-lx2160a/include/soc.h b/plat/nxp/soc-lx2160a/include/soc.h
new file mode 100644
index 0000000..7cc4a03
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/include/soc.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _SOC_H
+#define _SOC_H
+
+/* Chassis specific defines - common across SoC's of a particular platform */
+#include <dcfg_lsch3.h>
+#include <soc_default_base_addr.h>
+#include <soc_default_helper_macros.h>
+
+
+#define NUM_DRAM_REGIONS 3
+#define NXP_DRAM0_ADDR 0x80000000
+#define NXP_DRAM0_MAX_SIZE 0x80000000 /* 2 GB */
+
+#define NXP_DRAM1_ADDR 0x2080000000
+#define NXP_DRAM1_MAX_SIZE 0x1F80000000 /* 126 G */
+
+#define NXP_DRAM2_ADDR 0x6000000000
+#define NXP_DRAM2_MAX_SIZE 0x2000000000 /* 128G */
+
+/*DRAM0 Size defined in platform_def.h */
+#define NXP_DRAM0_SIZE PLAT_DEF_DRAM0_SIZE
+
+#define DDR_PLL_FIX
+#define NXP_DDR_PHY1_ADDR 0x01400000
+#define NXP_DDR_PHY2_ADDR 0x01600000
+
+#if defined(IMAGE_BL31)
+#define LS_SYS_TIMCTL_BASE 0x2890000
+
+#ifdef LS_SYS_TIMCTL_BASE
+#define PLAT_LS_NSTIMER_FRAME_ID 0
+#define LS_CONFIG_CNTACR 1
+#endif
+#endif
+
+/* Start: Macros used by soc.c: get_boot_dev */
+#define PORSR1_RCW_MASK 0x07800000
+#define PORSR1_RCW_SHIFT 23
+
+#define SDHC1_VAL 0x8
+#define SDHC2_VAL 0x9
+#define I2C1_VAL 0xa
+#define FLEXSPI_NAND2K_VAL 0xc
+#define FLEXSPI_NAND4K_VAL 0xd
+#define FLEXSPI_NOR 0xf
+/* End: Macros used by soc.c: get_boot_dev */
+
+/* SVR Definition (not include major and minor rev) */
+#define SVR_LX2160A 0x873601
+#define SVR_LX2120A 0x873621
+#define SVR_LX2080A 0x873603
+
+/* Number of cores in platform */
+/* Used by common code for array initialization */
+#define NUMBER_OF_CLUSTERS 8
+#define CORES_PER_CLUSTER 2
+#define PLATFORM_CORE_COUNT NUMBER_OF_CLUSTERS * CORES_PER_CLUSTER
+
+/*
+ * Required LS standard platform porting definitions
+ * for CCN-508
+ */
+#define PLAT_CLUSTER_TO_CCN_ID_MAP 11, 15, 27, 31, 12, 28, 16, 0
+#define PLAT_6CLUSTER_TO_CCN_ID_MAP 11, 15, 27, 31, 12, 28
+
+
+/* Defines required for using XLAT tables from ARM common code */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 40)
+
+/* Clock Divisors */
+#define NXP_PLATFORM_CLK_DIVIDER 2
+#define NXP_UART_CLK_DIVIDER 4
+
+/* Start: Macros used by lx2160a.S */
+#define MPIDR_AFFINITY0_MASK 0x00FF
+#define MPIDR_AFFINITY1_MASK 0xFF00
+#define CPUECTLR_DISABLE_TWALK_PREFETCH 0x4000000000
+#define CPUECTLR_INS_PREFETCH_MASK 0x1800000000
+#define CPUECTLR_DAT_PREFETCH_MASK 0x0300000000
+#define CPUECTLR_RET_8CLK 0x2
+#define OSDLR_EL1_DLK_LOCK 0x1
+#define CNTP_CTL_EL0_EN 0x1
+#define CNTP_CTL_EL0_IMASK 0x2
+/* set to 0 if the clusters are not symmetrical */
+#define SYMMETRICAL_CLUSTERS 1
+/* End: Macros used by lx2160a.S */
+
+/* Start: Macros used by lib/psci files */
+#define SYSTEM_PWR_DOMAINS 1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ NUMBER_OF_CLUSTERS + \
+ SYSTEM_PWR_DOMAINS)
+
+/* Power state coordination occurs at the system level */
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/* define retention state */
+#define PLAT_MAX_RET_STATE (PSCI_LOCAL_STATE_RUN + 1)
+
+/* define power-down state */
+#define PLAT_MAX_OFF_STATE (PLAT_MAX_RET_STATE + 1)
+/* End: Macros used by lib/psci files */
+
+/* Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ *
+ * CACHE_WRITEBACK_GRANULE is defined in soc.def
+ *
+ * One cache line needed for bakery locks on ARM platforms
+ */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+#ifndef WDOG_RESET_FLAG
+#define WDOG_RESET_FLAG DEFAULT_SET_VALUE
+#endif
+
+#ifndef WARM_BOOT_SUCCESS
+#define WARM_BOOT_SUCCESS DEFAULT_SET_VALUE
+#endif
+
+#ifndef __ASSEMBLER__
+
+void set_base_freq_CNTFID0(void);
+void soc_init_start(void);
+void soc_init_finish(void);
+void soc_init_percpu(void);
+void _soc_set_start_addr(unsigned long addr);
+void _set_platform_security(void);
+
+#endif
+
+#endif /* _SOC_H */
diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c
new file mode 100644
index 0000000..d44733c
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2018-2020 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 <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+#include <load_img.h>
+
+#include "plat_common.h"
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+
+const struct ddr_cfg_regs static_3200 = {
+ .cs[0].bnds = U(0x03FF),
+ .cs[1].bnds = U(0x03FF),
+ .cs[0].config = U(0x80050422),
+ .cs[1].config = U(0x80000422),
+ .cs[2].bnds = U(0x00),
+ .cs[3].bnds = U(0x00),
+ .cs[2].config = U(0x00),
+ .cs[3].config = U(0x00),
+ .timing_cfg[0] = U(0xFFAA0018),
+ .timing_cfg[1] = U(0x646A8844),
+ .timing_cfg[2] = U(0x00058022),
+ .timing_cfg[3] = U(0x13622100),
+ .timing_cfg[4] = U(0x02),
+ .timing_cfg[5] = U(0x07401400),
+ .timing_cfg[7] = U(0x3BB00000),
+ .timing_cfg[8] = U(0x0944AC00),
+ .sdram_cfg[0] = U(0x65044008),
+ .sdram_cfg[1] = U(0x00401011),
+ .sdram_cfg[2] = U(0x00),
+ .sdram_mode[0] = U(0x06010C50),
+ .sdram_mode[1] = U(0x00280400),
+ .sdram_mode[2] = U(0x00),
+ .sdram_mode[3] = U(0x00),
+ .sdram_mode[4] = U(0x00),
+ .sdram_mode[5] = U(0x00),
+ .sdram_mode[6] = U(0x00),
+ .sdram_mode[7] = U(0x00),
+ .sdram_mode[8] = U(0x0500),
+ .sdram_mode[9] = U(0x10240000),
+ .sdram_mode[10] = U(0x00),
+ .sdram_mode[11] = U(0x00),
+ .sdram_mode[12] = U(0x00),
+ .sdram_mode[13] = U(0x00),
+ .sdram_mode[14] = U(0x00),
+ .sdram_mode[15] = U(0x00),
+ .md_cntl = U(0x00),
+ .interval = U(0x30C00000),
+ .data_init = U(0xDEADBEEF),
+ .init_addr = U(0x00),
+ .zq_cntl = U(0x8A090705),
+ .sdram_rcw[0] = U(0x00),
+ .sdram_rcw[1] = U(0x00),
+ .sdram_rcw[2] = U(0x00),
+ .sdram_rcw[3] = U(0x00),
+ .sdram_rcw[4] = U(0x00),
+ .sdram_rcw[5] = U(0x00),
+ .err_disable = U(0x00),
+ .err_int_en = U(0x00),
+};
+
+const struct ddr_cfg_regs static_2900 = {
+ .cs[0].bnds = U(0x03FF),
+ .cs[1].bnds = U(0x03FF),
+ .cs[0].config = U(0x80050422),
+ .cs[1].config = U(0x80000422),
+ .cs[2].bnds = U(0x00),
+ .cs[3].bnds = U(0x00),
+ .cs[2].config = U(0x00),
+ .cs[3].config = U(0x00),
+ .timing_cfg[0] = U(0xFF990018),
+ .timing_cfg[1] = U(0x4F4A4844),
+ .timing_cfg[2] = U(0x0005601F),
+ .timing_cfg[3] = U(0x125F2100),
+ .timing_cfg[4] = U(0x02),
+ .timing_cfg[5] = U(0x07401400),
+ .timing_cfg[7] = U(0x3AA00000),
+ .timing_cfg[8] = U(0x09449B00),
+ .sdram_cfg[0] = U(0x65044008),
+ .sdram_cfg[1] = U(0x00401011),
+ .sdram_cfg[2] = U(0x00),
+ .sdram_mode[0] = U(0x06010C50),
+ .sdram_mode[1] = U(0x00280400),
+ .sdram_mode[2] = U(0x00),
+ .sdram_mode[3] = U(0x00),
+ .sdram_mode[4] = U(0x00),
+ .sdram_mode[5] = U(0x00),
+ .sdram_mode[6] = U(0x00),
+ .sdram_mode[7] = U(0x00),
+ .sdram_mode[8] = U(0x0500),
+ .sdram_mode[9] = U(0x10240000),
+ .sdram_mode[10] = U(0x00),
+ .sdram_mode[11] = U(0x00),
+ .sdram_mode[12] = U(0x00),
+ .sdram_mode[13] = U(0x00),
+ .sdram_mode[14] = U(0x00),
+ .sdram_mode[15] = U(0x00),
+ .md_cntl = U(0x00),
+ .interval = U(0x2C2E0000),
+ .data_init = U(0xDEADBEEF),
+ .init_addr = U(0x00),
+ .zq_cntl = U(0x8A090705),
+ .sdram_rcw[0] = U(0x00),
+ .sdram_rcw[1] = U(0x00),
+ .sdram_rcw[2] = U(0x00),
+ .sdram_rcw[3] = U(0x00),
+ .sdram_rcw[4] = U(0x00),
+ .sdram_rcw[5] = U(0x00),
+ .err_disable = U(0x00),
+ .err_int_en = U(0x00),
+};
+
+const struct ddr_cfg_regs static_2600 = {
+ .cs[0].bnds = U(0x03FF),
+ .cs[1].bnds = U(0x03FF),
+ .cs[0].config = U(0x80050422),
+ .cs[1].config = U(0x80000422),
+ .cs[2].bnds = U(0x00),
+ .cs[3].bnds = U(0x00),
+ .cs[2].config = U(0x00),
+ .cs[3].config = U(0x00),
+ .timing_cfg[0] = U(0xFF880018),
+ .timing_cfg[1] = U(0x2A24F444),
+ .timing_cfg[2] = U(0x007141DC),
+ .timing_cfg[3] = U(0x125B2100),
+ .timing_cfg[4] = U(0x02),
+ .timing_cfg[5] = U(0x06401400),
+ .timing_cfg[7] = U(0x28800000),
+ .timing_cfg[8] = U(0x07338A00),
+ .sdram_cfg[0] = U(0x65044008),
+ .sdram_cfg[1] = U(0x00401011),
+ .sdram_cfg[2] = U(0x00),
+ .sdram_mode[0] = U(0x06010A70),
+ .sdram_mode[1] = U(0x00200400),
+ .sdram_mode[2] = U(0x00),
+ .sdram_mode[3] = U(0x00),
+ .sdram_mode[4] = U(0x00),
+ .sdram_mode[5] = U(0x00),
+ .sdram_mode[6] = U(0x00),
+ .sdram_mode[7] = U(0x00),
+ .sdram_mode[8] = U(0x0500),
+ .sdram_mode[9] = U(0x0C240000),
+ .sdram_mode[10] = U(0x00),
+ .sdram_mode[11] = U(0x00),
+ .sdram_mode[12] = U(0x00),
+ .sdram_mode[13] = U(0x00),
+ .sdram_mode[14] = U(0x00),
+ .sdram_mode[15] = U(0x00),
+ .md_cntl = U(0x00),
+ .interval = U(0x279C0000),
+ .data_init = U(0xDEADBEEF),
+ .init_addr = U(0x00),
+ .zq_cntl = U(0x8A090705),
+ .sdram_rcw[0] = U(0x00),
+ .sdram_rcw[1] = U(0x00),
+ .sdram_rcw[2] = U(0x00),
+ .sdram_rcw[3] = U(0x00),
+ .sdram_rcw[4] = U(0x00),
+ .sdram_rcw[5] = U(0x00),
+ .err_disable = U(0x00),
+ .err_int_en = U(0x00),
+};
+
+const struct dimm_params static_dimm = {
+ .rdimm = U(0),
+ .primary_sdram_width = U(64),
+ .ec_sdram_width = U(8),
+ .n_ranks = U(2),
+ .device_width = U(8),
+ .mirrored_dimm = U(1),
+};
+
+/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */
+unsigned long long board_static_ddr(struct ddr_info *priv)
+{
+ (void)memcpy(&priv->ddr_reg, &static_2900, sizeof(static_2900));
+ (void)memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm));
+ priv->conf.cs_on_dimm[0] = 0x3;
+ ddr_board_options(priv);
+ compute_ddr_phy(priv);
+
+ return ULL(0x400000000);
+}
+
+#elif defined(CONFIG_DDR_NODIMM)
+/*
+ * Sample code to bypass reading SPD. This is a sample, not recommended
+ * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1.
+ */
+
+const struct dimm_params ddr_raw_timing = {
+ .n_ranks = U(2),
+ .rank_density = U(4294967296u),
+ .capacity = U(8589934592u),
+ .primary_sdram_width = U(64),
+ .ec_sdram_width = U(8),
+ .device_width = U(8),
+ .die_density = U(0x4),
+ .rdimm = U(0),
+ .mirrored_dimm = U(1),
+ .n_row_addr = U(15),
+ .n_col_addr = U(10),
+ .bank_addr_bits = U(0),
+ .bank_group_bits = U(2),
+ .edc_config = U(2),
+ .burst_lengths_bitmask = U(0x0c),
+ .tckmin_x_ps = 750,
+ .tckmax_ps = 1600,
+ .caslat_x = U(0x00FFFC00),
+ .taa_ps = 13750,
+ .trcd_ps = 13750,
+ .trp_ps = 13750,
+ .tras_ps = 32000,
+ .trc_ps = 457500,
+ .twr_ps = 15000,
+ .trfc1_ps = 260000,
+ .trfc2_ps = 160000,
+ .trfc4_ps = 110000,
+ .tfaw_ps = 21000,
+ .trrds_ps = 3000,
+ .trrdl_ps = 4900,
+ .tccdl_ps = 5000,
+ .refresh_rate_ps = U(7800000),
+};
+
+int ddr_get_ddr_params(struct dimm_params *pdimm,
+ struct ddr_conf *conf)
+{
+ static const char dimm_model[] = "Fixed DDR on board";
+
+ conf->dimm_in_use[0] = 1; /* Modify accordingly */
+ memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params));
+ memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+
+ /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */
+ return 0x5;
+}
+#endif /* CONFIG_DDR_NODIMM */
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ struct memctl_opt *popts = &priv->opt;
+ const struct ddr_conf *conf = &priv->conf;
+
+ popts->vref_dimm = U(0x24); /* range 1, 83.4% */
+ popts->rtt_override = 0;
+ popts->rtt_park = U(240);
+ popts->otf_burst_chop_en = 0;
+ popts->burst_length = U(DDR_BL8);
+ popts->trwt_override = U(1);
+ popts->bstopre = U(0); /* auto precharge */
+ popts->addr_hash = 1;
+
+ /* Set ODT impedance on PHY side */
+ switch (conf->cs_on_dimm[1]) {
+ case 0xc: /* Two slots dual rank */
+ case 0x4: /* Two slots single rank, not valid for interleaving */
+ popts->trwt = U(0xf);
+ popts->twrt = U(0x7);
+ popts->trrt = U(0x7);
+ popts->twwt = U(0x7);
+ popts->vref_phy = U(0x6B); /* 83.6% */
+ popts->odt = U(60);
+ popts->phy_tx_impedance = U(28);
+ break;
+ case 0: /* One slot used */
+ default:
+ popts->trwt = U(0x3);
+ popts->twrt = U(0x3);
+ popts->trrt = U(0x3);
+ popts->twwt = U(0x3);
+ popts->vref_phy = U(0x60); /* 75% */
+ popts->odt = U(48);
+ popts->phy_tx_impedance = U(28);
+ break;
+ }
+
+ return 0;
+}
+
+#ifdef NXP_WARM_BOOT
+long long init_ddr(uint32_t wrm_bt_flg)
+#else
+long long init_ddr(void)
+#endif
+{
+ int spd_addr[] = {0x51U, 0x52U, 0x53U, 0x54U};
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys) == 1) {
+ ERROR("System clocks are not set.\n");
+ panic();
+ }
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
+
+ zeromem(&info, sizeof(info));
+
+ /* Set two DDRC. Unused DDRC will be removed automatically. */
+ info.num_ctlrs = NUM_OF_DDRC;
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+ info.ddr[1] = (void *)NXP_DDR2_ADDR;
+ info.phy[0] = (void *)NXP_DDR_PHY1_ADDR;
+ info.phy[1] = (void *)NXP_DDR_PHY2_ADDR;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.img_loadr = load_img;
+ info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER;
+ if (info.clk == 0) {
+ info.clk = get_ddr_freq(&sys, 1);
+ }
+ info.dimm_on_ctlr = DDRC_NUM_DIMM;
+
+ info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED;
+#ifdef NXP_WARM_BOOT
+ info.warm_boot_flag = DDR_COLD_BOOT;
+ if (wrm_bt_flg != 0U) {
+ info.warm_boot_flag = DDR_WARM_BOOT;
+ } else {
+ info.warm_boot_flag = DDR_COLD_BOOT;
+ }
+#endif
+
+ dram_size = dram_init(&info
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+ , NXP_CCN_HN_F_0_ADDR
+#endif
+ );
+
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h b/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h
new file mode 100644
index 0000000..f480f92
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+#include <cortex_a72.h>
+/* Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+#if defined(IMAGE_BL31)
+#define LS_SYS_TIMCTL_BASE 0x2890000
+#define PLAT_LS_NSTIMER_FRAME_ID 0
+#define LS_CONFIG_CNTACR 1
+#endif
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0x8000)
+#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+ - NXP_SD_BLOCK_BUF_SIZE)
+
+#ifdef SD_BOOT
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+ - NXP_SD_BLOCK_BUF_SIZE)
+#else
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+#endif
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES 4
+#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_HANDLES 4
+
+#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ)
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES 3
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 2
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define BL32_IRQ_SEC_PHY_TIMER 29
+
+#define BL31_WDOG_SEC 89
+
+#define BL31_NS_WDOG_WS1 108
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+
+/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
+#define NXP_IRQ_SEC_SGI_7 15
+
+#define PLAT_LS_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+#endif
diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/platform.c b/plat/nxp/soc-lx2160a/lx2160aqds/platform.c
new file mode 100644
index 0000000..b00adb5
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160aqds/platform.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk b/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk
new file mode 100644
index 0000000..226b22b
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk
@@ -0,0 +1,51 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+
+BOOT_MODE ?= flexspi_nor
+BOARD ?= lx2160aqds
+POVDD_ENABLE := no
+NXP_COINED_BB := no
+
+ # DDR Compilation Configs
+NUM_OF_DDRC := 1
+DDRC_NUM_DIMM := 1
+DDRC_NUM_CS := 2
+DDR_ECC_EN := yes
+ #enable address decoding feature
+DDR_ADDR_DEC := yes
+APPLY_MAX_CDD := yes
+
+# DDR Errata
+ERRATA_DDR_A011396 := 1
+ERRATA_DDR_A050450 := 1
+
+ # On-Board Flash Details
+FLASH_TYPE := MT35XU512A
+XSPI_FLASH_SZ := 0x10000000
+NXP_XSPI_NOR_UNIT_SIZE := 0x20000
+BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000
+# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This
+# config is enabled for future use cases.
+FSPI_ERASE_4K := 0
+
+# Platform specific features.
+WARM_BOOT := yes
+
+# Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := flexspi_nor \
+ sd \
+ emmc
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-lx2160a/soc.mk
diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h b/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h
new file mode 100644
index 0000000..5fa774e
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include "plat_def.h"
+#include "plat_default_def.h"
+
+#endif
diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/policy.h b/plat/nxp/soc-lx2160a/lx2160aqds/policy.h
new file mode 100644
index 0000000..05d23e2
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160aqds/policy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/* Following defines affect the PLATFORM SECURITY POLICY */
+
+/* set this to 0x0 if the platform is not using/responding to ECC errors
+ * set this to 0x1 if ECC is being used (we have to do some init)
+ */
+#define POLICY_USING_ECC 0x0
+
+/* Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+/*
+ * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I
+ * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7
+ * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23
+ */
+#define POLICY_PERF_WRIOP 0
+
+/*
+ * set this to '1' if the debug clocks need to remain enabled during
+ * system entry to low-power (LPM20) - this should only be necessary
+ * for testing and NEVER set for normal production
+ */
+#define POLICY_DEBUG_ENABLE 0
+
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c b/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c
new file mode 100644
index 0000000..8669b1d
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c
@@ -0,0 +1,212 @@
+/*
+ * 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 <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+#include <load_img.h>
+
+#include "plat_common.h"
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+const struct ddr_cfg_regs static_1600 = {
+ .cs[0].config = U(0xA8050322),
+ .cs[1].config = U(0x80000322),
+ .cs[0].bnds = U(0x3FF),
+ .cs[1].bnds = U(0x3FF),
+ .sdram_cfg[0] = U(0xE5044000),
+ .sdram_cfg[1] = U(0x401011),
+ .timing_cfg[0] = U(0xFF550018),
+ .timing_cfg[1] = U(0xBAB48C42),
+ .timing_cfg[2] = U(0x48C111),
+ .timing_cfg[3] = U(0x10C1000),
+ .timing_cfg[4] = U(0x2),
+ .timing_cfg[5] = U(0x3401400),
+ .timing_cfg[7] = U(0x13300000),
+ .timing_cfg[8] = U(0x2114600),
+ .sdram_mode[0] = U(0x6010210),
+ .sdram_mode[8] = U(0x500),
+ .sdram_mode[9] = U(0x4240000),
+ .interval = U(0x18600000),
+ .data_init = U(0xDEADBEEF),
+ .zq_cntl = U(0x8A090705),
+};
+
+const struct dimm_params static_dimm = {
+ .rdimm = U(0),
+ .primary_sdram_width = U(64),
+ .ec_sdram_width = U(8),
+ .n_ranks = U(2),
+ .device_width = U(8),
+ .mirrored_dimm = U(1),
+};
+
+/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */
+unsigned long long board_static_ddr(struct ddr_info *priv)
+{
+ memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600));
+ memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm));
+ priv->conf.cs_on_dimm[0] = 0x3;
+ ddr_board_options(priv);
+ compute_ddr_phy(priv);
+
+ return ULL(0x400000000);
+}
+
+#elif defined(CONFIG_DDR_NODIMM)
+/*
+ * Sample code to bypass reading SPD. This is a sample, not recommended
+ * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1.
+ */
+
+const struct dimm_params ddr_raw_timing = {
+ .n_ranks = U(2),
+ .rank_density = U(4294967296u),
+ .capacity = U(8589934592u),
+ .primary_sdram_width = U(64),
+ .ec_sdram_width = U(8),
+ .device_width = U(8),
+ .die_density = U(0x4),
+ .rdimm = U(0),
+ .mirrored_dimm = U(1),
+ .n_row_addr = U(15),
+ .n_col_addr = U(10),
+ .bank_addr_bits = U(0),
+ .bank_group_bits = U(2),
+ .edc_config = U(2),
+ .burst_lengths_bitmask = U(0x0c),
+ .tckmin_x_ps = 750,
+ .tckmax_ps = 1600,
+ .caslat_x = U(0x00FFFC00),
+ .taa_ps = 13750,
+ .trcd_ps = 13750,
+ .trp_ps = 13750,
+ .tras_ps = 32000,
+ .trc_ps = 457500,
+ .twr_ps = 15000,
+ .trfc1_ps = 260000,
+ .trfc2_ps = 160000,
+ .trfc4_ps = 110000,
+ .tfaw_ps = 21000,
+ .trrds_ps = 3000,
+ .trrdl_ps = 4900,
+ .tccdl_ps = 5000,
+ .refresh_rate_ps = U(7800000),
+};
+
+int ddr_get_ddr_params(struct dimm_params *pdimm,
+ struct ddr_conf *conf)
+{
+ static const char dimm_model[] = "Fixed DDR on board";
+
+ conf->dimm_in_use[0] = 1; /* Modify accordingly */
+ memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params));
+ memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+
+ /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */
+ return 0x5;
+}
+#endif /* CONFIG_DDR_NODIMM */
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ struct memctl_opt *popts = &priv->opt;
+ const struct ddr_conf *conf = &priv->conf;
+
+ popts->vref_dimm = U(0x24); /* range 1, 83.4% */
+ popts->rtt_override = 0;
+ popts->rtt_park = U(240);
+ popts->otf_burst_chop_en = 0;
+ popts->burst_length = U(DDR_BL8);
+ popts->trwt_override = U(1);
+ popts->bstopre = U(0); /* auto precharge */
+ popts->addr_hash = 1;
+
+ /* Set ODT impedance on PHY side */
+ switch (conf->cs_on_dimm[1]) {
+ case 0xc: /* Two slots dual rank */
+ case 0x4: /* Two slots single rank, not valid for interleaving */
+ popts->trwt = U(0xf);
+ popts->twrt = U(0x7);
+ popts->trrt = U(0x7);
+ popts->twwt = U(0x7);
+ popts->vref_phy = U(0x6B); /* 83.6% */
+ popts->odt = U(60);
+ popts->phy_tx_impedance = U(28);
+ break;
+ case 0: /* One slot used */
+ default:
+ popts->trwt = U(0x3);
+ popts->twrt = U(0x3);
+ popts->trrt = U(0x3);
+ popts->twwt = U(0x3);
+ popts->vref_phy = U(0x60); /* 75% */
+ popts->odt = U(48);
+ popts->phy_tx_impedance = U(28);
+ break;
+ }
+
+ return 0;
+}
+
+long long init_ddr(void)
+{
+ int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 };
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys) != 0) {
+ ERROR("System clocks are not set\n");
+ panic();
+ }
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
+
+ zeromem(&info, sizeof(info));
+
+ /* Set two DDRC. Unused DDRC will be removed automatically. */
+ info.num_ctlrs = NUM_OF_DDRC;
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+ info.ddr[1] = (void *)NXP_DDR2_ADDR;
+ info.phy[0] = (void *)NXP_DDR_PHY1_ADDR;
+ info.phy[1] = (void *)NXP_DDR_PHY2_ADDR;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.img_loadr = load_img;
+ info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER;
+ if (info.clk == 0) {
+ info.clk = get_ddr_freq(&sys, 1);
+ }
+ info.dimm_on_ctlr = DDRC_NUM_DIMM;
+
+ info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED;
+
+ dram_size = dram_init(&info
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+ , NXP_CCN_HN_F_0_ADDR
+#endif
+ );
+
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h b/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h
new file mode 100644
index 0000000..02f51e7
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+#include <cortex_a72.h>
+/* Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+#if defined(IMAGE_BL31)
+#define LS_SYS_TIMCTL_BASE 0x2890000
+#define PLAT_LS_NSTIMER_FRAME_ID 0
+#define LS_CONFIG_CNTACR 1
+#endif
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0x8000)
+#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+ - NXP_SD_BLOCK_BUF_SIZE)
+
+#ifdef SD_BOOT
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+ - NXP_SD_BLOCK_BUF_SIZE)
+#else
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+#endif
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES 4
+#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_HANDLES 4
+
+#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ)
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES 3
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 2
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define BL32_IRQ_SEC_PHY_TIMER 29
+
+#define BL31_WDOG_SEC 89
+
+#define BL31_NS_WDOG_WS1 108
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+
+/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
+#define NXP_IRQ_SEC_SGI_7 15
+
+#define PLAT_LS_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+#endif
diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/platform.c b/plat/nxp/soc-lx2160a/lx2160ardb/platform.c
new file mode 100644
index 0000000..b00adb5
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160ardb/platform.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk b/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk
new file mode 100644
index 0000000..ffb5fad
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk
@@ -0,0 +1,51 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+
+BOOT_MODE ?= flexspi_nor
+BOARD ?= lx2160ardb
+POVDD_ENABLE := no
+NXP_COINED_BB := no
+
+ # DDR Compilation Configs
+NUM_OF_DDRC := 2
+DDRC_NUM_DIMM := 2
+DDRC_NUM_CS := 4
+DDR_ECC_EN := yes
+ #enable address decoding feature
+DDR_ADDR_DEC := yes
+APPLY_MAX_CDD := yes
+
+# DDR Errata
+ERRATA_DDR_A011396 := 1
+ERRATA_DDR_A050450 := 1
+
+ # On-Board Flash Details
+FLASH_TYPE := MT35XU512A
+XSPI_FLASH_SZ := 0x10000000
+NXP_XSPI_NOR_UNIT_SIZE := 0x20000
+BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000
+# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This
+# config is enabled for future use cases.
+FSPI_ERASE_4K := 0
+
+ # Platform specific features.
+WARM_BOOT := no
+
+ # Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := flexspi_nor \
+ sd \
+ emmc
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+ # Adding SoC build info
+include plat/nxp/soc-lx2160a/soc.mk
diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h b/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h
new file mode 100644
index 0000000..6660998
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include "plat_def.h"
+#include "plat_default_def.h"
+
+#endif
diff --git a/plat/nxp/soc-lx2160a/lx2160ardb/policy.h b/plat/nxp/soc-lx2160a/lx2160ardb/policy.h
new file mode 100644
index 0000000..19ad6db
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2160ardb/policy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/* Following defines affect the PLATFORM SECURITY POLICY */
+
+/* set this to 0x0 if the platform is not using/responding to ECC errors
+ * set this to 0x1 if ECC is being used (we have to do some init)
+ */
+#define POLICY_USING_ECC 0x0
+
+/* Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+/*
+ * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I
+ * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7
+ * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23
+ */
+#define POLICY_PERF_WRIOP 0
+
+/*
+ * set this to '1' if the debug clocks need to remain enabled during
+ * system entry to low-power (LPM20) - this should only be necessary
+ * for testing and NEVER set for normal production
+ */
+#define POLICY_DEBUG_ENABLE 0
+
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c b/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c
new file mode 100644
index 0000000..73bcc93
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2018-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 <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+#include <load_img.h>
+
+#include "plat_common.h"
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+
+const struct ddr_cfg_regs static_3200 = {
+ .cs[0].bnds = U(0x03FFU),
+ .cs[1].bnds = U(0x03FF),
+ .cs[0].config = U(0x80050422),
+ .cs[1].config = U(0x80000422),
+ .cs[2].bnds = U(0x00),
+ .cs[3].bnds = U(0x00),
+ .cs[2].config = U(0x00),
+ .cs[3].config = U(0x00),
+ .timing_cfg[0] = U(0xFFAA0018),
+ .timing_cfg[1] = U(0x646A8844),
+ .timing_cfg[2] = U(0x00058022),
+ .timing_cfg[3] = U(0x13622100),
+ .timing_cfg[4] = U(0x02),
+ .timing_cfg[5] = U(0x07401400),
+ .timing_cfg[7] = U(0x3BB00000),
+ .timing_cfg[8] = U(0x0944AC00),
+ .sdram_cfg[0] = U(0x65044008),
+ .sdram_cfg[1] = U(0x00401011),
+ .sdram_cfg[2] = U(0x00),
+ .sdram_mode[0] = U(0x06010C50),
+ .sdram_mode[1] = U(0x00280400),
+ .sdram_mode[2] = U(0x00),
+ .sdram_mode[3] = U(0x00),
+ .sdram_mode[4] = U(0x00),
+ .sdram_mode[5] = U(0x00),
+ .sdram_mode[6] = U(0x00),
+ .sdram_mode[7] = U(0x00),
+ .sdram_mode[8] = U(0x0500),
+ .sdram_mode[9] = U(0x10240000),
+ .sdram_mode[10] = U(0x00),
+ .sdram_mode[11] = U(0x00),
+ .sdram_mode[12] = U(0x00),
+ .sdram_mode[13] = U(0x00),
+ .sdram_mode[14] = U(0x00),
+ .sdram_mode[15] = U(0x00),
+ .md_cntl = U(0x00),
+ .interval = U(0x30C00000),
+ .data_init = U(0xDEADBEEF),
+ .init_addr = U(0x00),
+ .zq_cntl = U(0x8A090705),
+ .sdram_rcw[0] = U(0x00),
+ .sdram_rcw[1] = U(0x00),
+ .sdram_rcw[2] = U(0x00),
+ .sdram_rcw[3] = U(0x00),
+ .sdram_rcw[4] = U(0x00),
+ .sdram_rcw[5] = U(0x00),
+ .err_disable = U(0x00),
+ .err_int_en = U(0x00),
+};
+
+const struct ddr_cfg_regs static_2900 = {
+ .cs[0].bnds = U(0x03FF),
+ .cs[1].bnds = U(0x03FF),
+ .cs[0].config = U(0x80050422),
+ .cs[1].config = U(0x80000422),
+ .cs[2].bnds = U(0x00),
+ .cs[3].bnds = U(0x00),
+ .cs[2].config = U(0x00),
+ .cs[3].config = U(0x00),
+ .timing_cfg[0] = U(0xFF990018),
+ .timing_cfg[1] = U(0x4F4A4844),
+ .timing_cfg[2] = U(0x0005601F),
+ .timing_cfg[3] = U(0x125F2100),
+ .timing_cfg[4] = U(0x02),
+ .timing_cfg[5] = U(0x07401400),
+ .timing_cfg[7] = U(0x3AA00000),
+ .timing_cfg[8] = U(0x09449B00),
+ .sdram_cfg[0] = U(0x65044008),
+ .sdram_cfg[1] = U(0x00401011),
+ .sdram_cfg[2] = U(0x00),
+ .sdram_mode[0] = U(0x06010C50),
+ .sdram_mode[1] = U(0x00280400),
+ .sdram_mode[2] = U(0x00),
+ .sdram_mode[3] = U(0x00),
+ .sdram_mode[4] = U(0x00),
+ .sdram_mode[5] = U(0x00),
+ .sdram_mode[6] = U(0x00),
+ .sdram_mode[7] = U(0x00),
+ .sdram_mode[8] = U(0x0500),
+ .sdram_mode[9] = U(0x10240000),
+ .sdram_mode[10] = U(0x00),
+ .sdram_mode[11] = U(0x00),
+ .sdram_mode[12] = U(0x00),
+ .sdram_mode[13] = U(0x00),
+ .sdram_mode[14] = U(0x00),
+ .sdram_mode[15] = U(0x00),
+ .md_cntl = U(0x00),
+ .interval = U(0x2C2E0000),
+ .data_init = U(0xDEADBEEF),
+ .init_addr = U(0x00),
+ .zq_cntl = U(0x8A090705),
+ .sdram_rcw[0] = U(0x00),
+ .sdram_rcw[1] = U(0x00),
+ .sdram_rcw[2] = U(0x00),
+ .sdram_rcw[3] = U(0x00),
+ .sdram_rcw[4] = U(0x00),
+ .sdram_rcw[5] = U(0x00),
+ .err_disable = U(0x00),
+ .err_int_en = U(0x00),
+};
+
+const struct ddr_cfg_regs static_2600 = {
+ .cs[0].bnds = U(0x03FF),
+ .cs[1].bnds = U(0x03FF),
+ .cs[0].config = U(0x80050422),
+ .cs[1].config = U(0x80000422),
+ .cs[2].bnds = U(0x00),
+ .cs[3].bnds = U(0x00),
+ .cs[2].config = U(0x00),
+ .cs[3].config = U(0x00),
+ .timing_cfg[0] = U(0xFF880018),
+ .timing_cfg[1] = U(0x2A24F444),
+ .timing_cfg[2] = U(0x007141DC),
+ .timing_cfg[3] = U(0x125B2100),
+ .timing_cfg[4] = U(0x02),
+ .timing_cfg[5] = U(0x06401400),
+ .timing_cfg[7] = U(0x28800000),
+ .timing_cfg[8] = U(0x07338A00),
+ .sdram_cfg[0] = U(0x65044008),
+ .sdram_cfg[1] = U(0x00401011),
+ .sdram_cfg[2] = U(0x00),
+ .sdram_mode[0] = U(0x06010A70),
+ .sdram_mode[1] = U(0x00200400),
+ .sdram_mode[2] = U(0x00),
+ .sdram_mode[3] = U(0x00),
+ .sdram_mode[4] = U(0x00),
+ .sdram_mode[5] = U(0x00),
+ .sdram_mode[6] = U(0x00),
+ .sdram_mode[7] = U(0x00),
+ .sdram_mode[8] = U(0x0500),
+ .sdram_mode[9] = U(0x0C240000),
+ .sdram_mode[10] = U(0x00),
+ .sdram_mode[11] = U(0x00),
+ .sdram_mode[12] = U(0x00),
+ .sdram_mode[13] = U(0x00),
+ .sdram_mode[14] = U(0x00),
+ .sdram_mode[15] = U(0x00),
+ .md_cntl = U(0x00),
+ .interval = U(0x279C0000),
+ .data_init = U(0xDEADBEEF),
+ .init_addr = U(0x00),
+ .zq_cntl = U(0x8A090705),
+ .sdram_rcw[0] = U(0x00),
+ .sdram_rcw[1] = U(0x00),
+ .sdram_rcw[2] = U(0x00),
+ .sdram_rcw[3] = U(0x00),
+ .sdram_rcw[4] = U(0x00),
+ .sdram_rcw[5] = U(0x00),
+ .err_disable = U(0x00),
+ .err_int_en = U(0x00),
+};
+
+const struct dimm_params static_dimm = {
+ .rdimm = 0U,
+ .primary_sdram_width = 64U,
+ .ec_sdram_width = 8U,
+ .n_ranks = 2U,
+ .device_width = 8U,
+ .mirrored_dimm = 1U,
+};
+
+/* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */
+unsigned long long board_static_ddr(struct ddr_info *priv)
+{
+ memcpy(&priv->ddr_reg, &static_2900, sizeof(static_2900));
+ memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm));
+ priv->conf.cs_on_dimm[0] = 0x3;
+ ddr_board_options(priv);
+ compute_ddr_phy(priv);
+
+ return ULL(0x400000000);
+}
+
+#elif defined(CONFIG_DDR_NODIMM)
+/*
+ * Sample code to bypass reading SPD. This is a sample, not recommended
+ * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1.
+ */
+struct dimm_params ddr_raw_timing = {
+ .n_ranks = 2U,
+ .rank_density = U(0x200000000),
+ .capacity = U(0x400000000),
+ .primary_sdram_width = 64U,
+ .ec_sdram_width = 8U,
+ .device_width = 8U,
+ .die_density = U(0x5),
+ .rdimm = 0U,
+ .mirrored_dimm = 1U,
+ .n_row_addr = 16U,
+ .n_col_addr = 10U,
+ .bank_addr_bits = 0U,
+ .bank_group_bits = 2U,
+ .edc_config = 2U,
+ .burst_lengths_bitmask = U(0x0c),
+ .tckmin_x_ps = 625,
+ .tckmax_ps = 1600,
+ .caslat_x = U(0x15FFFC00),
+ .taa_ps = 13750,
+ .trcd_ps = 13750,
+ .trp_ps = 13750,
+ .tras_ps = 32000,
+ .trc_ps = 457500,
+ .twr_ps = 15000,
+ .trfc1_ps = 350000,
+ .trfc2_ps = 260000,
+ .trfc4_ps = 160000,
+ .tfaw_ps = 21000,
+ .trrds_ps = 2500,
+ .trrdl_ps = 4900,
+ .tccdl_ps = 5000,
+ .refresh_rate_ps = 7800000U,
+};
+
+int ddr_get_ddr_params(struct dimm_params *pdimm,
+ struct ddr_conf *conf)
+{
+ static const char dimm_model[] = "Fixed DDR on board";
+
+ conf->dimm_in_use[0] = 1; /* Modify accordingly */
+ memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params));
+ memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+
+ /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */
+ return 0x5;
+}
+#endif /* CONFIG_DDR_NODIMM */
+
+int ddr_board_options(struct ddr_info *priv)
+{
+ struct memctl_opt *popts = &priv->opt;
+ const struct ddr_conf *conf = &priv->conf;
+
+ popts->vref_dimm = U(0x19); /* range 1, 83.4% */
+ popts->rtt_override = 1U;
+ popts->rtt_override_value = 0x5U; /* RTT being used as 60 ohm */
+ popts->rtt_park = 120U;
+ popts->otf_burst_chop_en = 0;
+ popts->burst_length = DDR_BL8;
+ popts->trwt_override = 1U;
+ popts->bstopre = 0U; /* auto precharge */
+ popts->addr_hash = 1;
+
+ /* Set ODT impedance on PHY side */
+ switch (conf->cs_on_dimm[1]) {
+ case 0xc: /* Two slots dual rank */
+ case 0x4: /* Two slots single rank, not valid for interleaving */
+ popts->trwt = U(0xf);
+ popts->twrt = U(0x7);
+ popts->trrt = U(0x7);
+ popts->twwt = U(0x7);
+ popts->vref_phy = U(0x6B); /* 83.6% */
+ popts->odt = 60U;
+ popts->phy_tx_impedance = 28U;
+ break;
+ case 0: /* Ont slot used */
+ default:
+ popts->trwt = U(0x3);
+ popts->twrt = U(0x3);
+ popts->trrt = U(0x3);
+ popts->twwt = U(0x3);
+ popts->vref_phy = U(0x5D); /* 72% */
+ popts->odt = 60U;
+ popts->phy_tx_impedance = 28U;
+ break;
+ }
+
+ return 0;
+}
+
+#ifdef NXP_WARM_BOOT
+long long init_ddr(uint32_t wrm_bt_flg)
+#else
+long long init_ddr(void)
+#endif
+{
+ int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 };
+ struct ddr_info info;
+ struct sysinfo sys;
+ long long dram_size;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys) != 0) {
+ ERROR("System clocks are not set\n");
+ panic();
+ }
+ debug("platform clock %lu\n", sys.freq_platform);
+ debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+ debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
+
+ zeromem(&info, sizeof(info));
+
+ /* Set two DDRC. Unused DDRC will be removed automatically. */
+ info.num_ctlrs = NUM_OF_DDRC;
+ info.spd_addr = spd_addr;
+ info.ddr[0] = (void *)NXP_DDR_ADDR;
+ info.ddr[1] = (void *)NXP_DDR2_ADDR;
+ info.phy[0] = (void *)NXP_DDR_PHY1_ADDR;
+ info.phy[1] = (void *)NXP_DDR_PHY2_ADDR;
+ info.clk = get_ddr_freq(&sys, 0);
+ info.img_loadr = load_img;
+ info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER;
+ if (info.clk == 0) {
+ info.clk = get_ddr_freq(&sys, 1);
+ }
+ info.dimm_on_ctlr = DDRC_NUM_DIMM;
+
+ info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED;
+#ifdef NXP_WARM_BOOT
+ if (wrm_bt_flg != 0) {
+ info.warm_boot_flag = DDR_WARM_BOOT;
+ } else {
+ info.warm_boot_flag = DDR_COLD_BOOT;
+ }
+#endif
+
+ dram_size = dram_init(&info
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+ , NXP_CCN_HN_F_0_ADDR
+#endif
+ );
+
+
+ if (dram_size < 0) {
+ ERROR("DDR init failed.\n");
+ }
+
+ return dram_size;
+}
diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h b/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h
new file mode 100644
index 0000000..de2d244
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+#include <cortex_a72.h>
+/* Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+#if defined(IMAGE_BL31)
+#define LS_SYS_TIMCTL_BASE 0x2890000
+#define PLAT_LS_NSTIMER_FRAME_ID 0
+#define LS_CONFIG_CNTACR 1
+#endif
+
+#define NXP_SYSCLK_FREQ 100000000
+#define NXP_DDRCLK_FREQ 100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE 115200
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE 0x2000
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE (0x8000)
+#define NXP_SD_BLOCK_BUF_ADDR (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+ - NXP_SD_BLOCK_BUF_SIZE)
+
+#ifdef SD_BOOT
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+ - NXP_SD_BLOCK_BUF_SIZE)
+#else
+#define BL2_LIMIT (NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+#endif
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES 4
+#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_HANDLES 4
+
+#define PHY_GEN2_FW_IMAGE_BUFFER (NXP_OCRAM_ADDR + CSF_HDR_SZ)
+
+/*
+ * FIP image defines - Offset at which FIP Image would be present
+ * Image would include Bl31 , Bl33 and Bl32 (optional)
+ */
+#ifdef POLICY_FUSE_PROVISION
+#define MAX_FIP_DEVICES 3
+#endif
+
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 2
+#endif
+
+/*
+ * ID of the secure physical generic timer interrupt used by the BL32.
+ */
+#define BL32_IRQ_SEC_PHY_TIMER 29
+
+#define BL31_WDOG_SEC 89
+
+#define BL31_NS_WDOG_WS1 108
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+
+/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
+#define NXP_IRQ_SEC_SGI_7 15
+
+#define PLAT_LS_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(BL31_NS_WDOG_WS1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(NXP_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+#endif
diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/platform.c b/plat/nxp/soc-lx2160a/lx2162aqds/platform.c
new file mode 100644
index 0000000..7622cf0
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2162aqds/platform.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk b/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk
new file mode 100644
index 0000000..2b4712c
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk
@@ -0,0 +1,52 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# board-specific build parameters
+
+BOOT_MODE ?= flexspi_nor
+BOARD ?= lx2162aqds
+POVDD_ENABLE := no
+NXP_COINED_BB := no
+
+ # DDR Compilation Configs
+NUM_OF_DDRC := 1
+DDRC_NUM_DIMM := 1
+DDRC_NUM_CS := 2
+DDR_ECC_EN := yes
+ #enable address decoding feature
+DDR_ADDR_DEC := yes
+APPLY_MAX_CDD := yes
+
+# DDR Errata
+ERRATA_DDR_A011396 := 1
+ERRATA_DDR_A050450 := 1
+
+
+# On-Board Flash Details
+FLASH_TYPE := MT35XU512A
+XSPI_FLASH_SZ := 0x10000000
+NXP_XSPI_NOR_UNIT_SIZE := 0x20000
+BL2_BIN_XSPI_NOR_END_ADDRESS := 0x100000
+# CONFIG_FSPI_ERASE_4K is required to erase 4K sector sizes. This
+# config is enabled for future use cases.
+FSPI_ERASE_4K := 0
+
+# Platform specific features.
+WARM_BOOT := yes
+
+# Adding Platform files build files
+BL2_SOURCES += ${BOARD_PATH}/ddr_init.c\
+ ${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE := flexspi_nor \
+ sd \
+ emmc
+
+# Adding platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Adding SoC build info
+include plat/nxp/soc-lx2160a/soc.mk
diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h b/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h
new file mode 100644
index 0000000..5fa774e
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include "plat_def.h"
+#include "plat_default_def.h"
+
+#endif
diff --git a/plat/nxp/soc-lx2160a/lx2162aqds/policy.h b/plat/nxp/soc-lx2160a/lx2162aqds/policy.h
new file mode 100644
index 0000000..1095f38
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/lx2162aqds/policy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+/* Following defines affect the PLATFORM SECURITY POLICY */
+
+/* set this to 0x0 if the platform is not using/responding to ECC errors
+ * set this to 0x1 if ECC is being used (we have to do some init)
+ */
+#define POLICY_USING_ECC 0x0
+
+/* Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+/*
+ * POLICY_PERF_WRIOP = 0 : No Performance enhancement for WRIOP RN-I
+ * POLICY_PERF_WRIOP = 1 : No Performance enhancement for WRIOP RN-I = 7
+ * POLICY_PERF_WRIOP = 2 : No Performance enhancement for WRIOP RN-I = 23
+ */
+#define POLICY_PERF_WRIOP 0
+
+/*
+ * set this to '1' if the debug clocks need to remain enabled during
+ * system entry to low-power (LPM20) - this should only be necessary
+ * for testing and NEVER set for normal production
+ */
+#define POLICY_DEBUG_ENABLE 0
+
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-lx2160a/soc.c b/plat/nxp/soc-lx2160a/soc.c
new file mode 100644
index 0000000..2209fda
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/soc.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <bl31/interrupt_mgmt.h>
+#include <caam.h>
+#include <cassert.h>
+#include <ccn.h>
+#include <common/debug.h>
+#include <dcfg.h>
+#ifdef I2C_INIT
+#include <i2c.h>
+#endif
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <ls_interconnect.h>
+#ifdef POLICY_FUSE_PROVISION
+#include <nxp_gpio.h>
+#endif
+#if TRUSTED_BOARD_BOOT
+#include <nxp_smmu.h>
+#endif
+#include <nxp_timer.h>
+#include <plat_console.h>
+#include <plat_gic.h>
+#include <plat_tzc400.h>
+#include <pmu.h>
+#if defined(NXP_SFP_ENABLED)
+#include <sfp.h>
+#endif
+
+#include <errata.h>
+#include <ls_interrupt_mgmt.h>
+#include "plat_common.h"
+#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA
+#include <plat_nv_storage.h>
+#endif
+#ifdef NXP_WARM_BOOT
+#include <plat_warm_rst.h>
+#endif
+#include "platform_def.h"
+#include "soc.h"
+
+static struct soc_type soc_list[] = {
+ SOC_ENTRY(LX2160A, LX2160A, 8, 2),
+ SOC_ENTRY(LX2080A, LX2080A, 8, 1),
+ SOC_ENTRY(LX2120A, LX2120A, 6, 2),
+};
+
+static dcfg_init_info_t dcfg_init_data = {
+ .g_nxp_dcfg_addr = NXP_DCFG_ADDR,
+ .nxp_sysclk_freq = NXP_SYSCLK_FREQ,
+ .nxp_ddrclk_freq = NXP_DDRCLK_FREQ,
+ .nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER,
+ };
+static const unsigned char master_to_6rn_id_map[] = {
+ PLAT_6CLUSTER_TO_CCN_ID_MAP
+};
+
+static const unsigned char master_to_rn_id_map[] = {
+ PLAT_CLUSTER_TO_CCN_ID_MAP
+};
+
+CASSERT(ARRAY_SIZE(master_to_rn_id_map) == NUMBER_OF_CLUSTERS,
+ assert_invalid_cluster_count_for_ccn_variant);
+
+static const ccn_desc_t plat_six_cluster_ccn_desc = {
+ .periphbase = NXP_CCN_ADDR,
+ .num_masters = ARRAY_SIZE(master_to_6rn_id_map),
+ .master_to_rn_id_map = master_to_6rn_id_map
+};
+
+static const ccn_desc_t plat_ccn_desc = {
+ .periphbase = NXP_CCN_ADDR,
+ .num_masters = ARRAY_SIZE(master_to_rn_id_map),
+ .master_to_rn_id_map = master_to_rn_id_map
+};
+
+/******************************************************************************
+ * Function returns the base counter frequency
+ * after reading the first entry at CNTFID0 (0x20 offset).
+ *
+ * Function is used by:
+ * 1. ARM common code for PSCI management.
+ * 2. ARM Generic Timer init.
+ *
+ *****************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+ /*
+ * Below register specifies the base frequency of the system counter.
+ * As per NXP Board Manuals:
+ * The system counter always works with SYS_REF_CLK/4 frequency clock.
+ *
+ *
+ */
+ counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF);
+
+ return counter_base_frequency;
+}
+
+#ifdef IMAGE_BL2
+
+#ifdef POLICY_FUSE_PROVISION
+static gpio_init_info_t gpio_init_data = {
+ .gpio1_base_addr = NXP_GPIO1_ADDR,
+ .gpio2_base_addr = NXP_GPIO2_ADDR,
+ .gpio3_base_addr = NXP_GPIO3_ADDR,
+ .gpio4_base_addr = NXP_GPIO4_ADDR,
+};
+#endif
+
+static void soc_interconnect_config(void)
+{
+ unsigned long long val = 0x0U;
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list),
+ &num_clusters, &cores_per_cluster);
+
+ if (num_clusters == 6U) {
+ ccn_init(&plat_six_cluster_ccn_desc);
+ } else {
+ ccn_init(&plat_ccn_desc);
+ }
+
+ /*
+ * Enable Interconnect coherency for the primary CPU's cluster.
+ */
+ plat_ls_interconnect_enter_coherency(num_clusters);
+
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 13, PCIeRC_RN_I_NODE_ID_OFFSET);
+ val |= (1 << 17);
+ ccn_write_node_reg(NODE_TYPE_HNI, 13, PCIeRC_RN_I_NODE_ID_OFFSET, val);
+
+ /* PCIe is Connected to RN-I 17 which is connected to HN-I 13. */
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 30, PCIeRC_RN_I_NODE_ID_OFFSET);
+ val |= (1 << 17);
+ ccn_write_node_reg(NODE_TYPE_HNI, 30, PCIeRC_RN_I_NODE_ID_OFFSET, val);
+
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET);
+ val |= SERIALIZE_DEV_nGnRnE_WRITES;
+ ccn_write_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET, val);
+
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET);
+ val &= ~(ENABLE_RESERVE_BIT53);
+ val |= SERIALIZE_DEV_nGnRnE_WRITES;
+ ccn_write_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET, val);
+
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 13, PoS_CONTROL_REG_OFFSET);
+ val &= ~(HNI_POS_EN);
+ ccn_write_node_reg(NODE_TYPE_HNI, 13, PoS_CONTROL_REG_OFFSET, val);
+
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 30, PoS_CONTROL_REG_OFFSET);
+ val &= ~(HNI_POS_EN);
+ ccn_write_node_reg(NODE_TYPE_HNI, 30, PoS_CONTROL_REG_OFFSET, val);
+
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET);
+ val &= ~(POS_EARLY_WR_COMP_EN);
+ ccn_write_node_reg(NODE_TYPE_HNI, 13, SA_AUX_CTRL_REG_OFFSET, val);
+
+ val = ccn_read_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET);
+ val &= ~(POS_EARLY_WR_COMP_EN);
+ ccn_write_node_reg(NODE_TYPE_HNI, 30, SA_AUX_CTRL_REG_OFFSET, val);
+
+#if POLICY_PERF_WRIOP
+ uint16_t wriop_rni = 0U;
+
+ if (POLICY_PERF_WRIOP == 1) {
+ wriop_rni = 7U;
+ } else if (POLICY_PERF_WRIOP == 2) {
+ wriop_rni = 23U;
+ } else {
+ ERROR("Incorrect WRIOP selected.\n");
+ panic();
+ }
+
+ val = ccn_read_node_reg(NODE_TYPE_RNI, wriop_rni,
+ SA_AUX_CTRL_REG_OFFSET);
+ val |= ENABLE_WUO;
+ ccn_write_node_reg(NODE_TYPE_HNI, wriop_rni, SA_AUX_CTRL_REG_OFFSET,
+ val);
+#else
+ val = ccn_read_node_reg(NODE_TYPE_RNI, 17, SA_AUX_CTRL_REG_OFFSET);
+ val |= ENABLE_WUO;
+ ccn_write_node_reg(NODE_TYPE_RNI, 17, SA_AUX_CTRL_REG_OFFSET, val);
+#endif
+}
+
+
+void soc_preload_setup(void)
+{
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+#if defined(NXP_WARM_BOOT)
+ bool warm_reset = is_warm_boot();
+#endif
+ info_dram_regions->total_dram_size =
+#if defined(NXP_WARM_BOOT)
+ init_ddr(warm_reset);
+#else
+ init_ddr();
+#endif
+}
+
+/*******************************************************************************
+ * This function implements soc specific erratas
+ * This is called before DDR is initialized or MMU is enabled
+ ******************************************************************************/
+void soc_early_init(void)
+{
+ dcfg_init(&dcfg_init_data);
+#ifdef POLICY_FUSE_PROVISION
+ gpio_init(&gpio_init_data);
+ sec_init(NXP_CAAM_ADDR);
+#endif
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+
+ enable_timer_base_to_cluster(NXP_PMU_ADDR);
+ soc_interconnect_config();
+
+ enum boot_device dev = get_boot_dev();
+ /* Mark the buffer for SD in OCRAM as non secure.
+ * The buffer is assumed to be at end of OCRAM for
+ * the logic below to calculate TZPC programming
+ */
+ if (dev == BOOT_DEVICE_EMMC || dev == BOOT_DEVICE_SDHC2_EMMC) {
+ /* Calculate the region in OCRAM which is secure
+ * The buffer for SD needs to be marked non-secure
+ * to allow SD to do DMA operations on it
+ */
+ uint32_t secure_region = (NXP_OCRAM_SIZE
+ - NXP_SD_BLOCK_BUF_SIZE);
+ uint32_t mask = secure_region/TZPC_BLOCK_SIZE;
+
+ mmio_write_32(NXP_OCRAM_TZPC_ADDR, mask);
+
+ /* Add the entry for buffer in MMU Table */
+ mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR,
+ NXP_SD_BLOCK_BUF_SIZE,
+ MT_DEVICE | MT_RW | MT_NS);
+ }
+
+ soc_errata();
+
+#if (TRUSTED_BOARD_BOOT) || defined(POLICY_FUSE_PROVISION)
+ sfp_init(NXP_SFP_ADDR);
+#endif
+
+#if TRUSTED_BOARD_BOOT
+ uint32_t mode;
+
+ /* For secure boot disable SMMU.
+ * Later when platform security policy comes in picture,
+ * this might get modified based on the policy
+ */
+ if (check_boot_mode_secure(&mode) == true) {
+ bypass_smmu(NXP_SMMU_ADDR);
+ }
+
+ /* For Mbedtls currently crypto is not supported via CAAM
+ * enable it when that support is there. In tbbr.mk
+ * the CAAM_INTEG is set as 0.
+ */
+
+#ifndef MBEDTLS_X509
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false)
+ INFO("SEC is disabled.\n");
+ else
+ sec_init(NXP_CAAM_ADDR);
+#endif
+#endif
+
+ /*
+ * Initialize system level generic timer for Layerscape Socs.
+ */
+ delay_timer_init(NXP_TIMER_ADDR);
+ i2c_init(NXP_I2C_ADDR);
+}
+
+void soc_bl2_prepare_exit(void)
+{
+#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE)
+ set_sfp_wr_disable();
+#endif
+}
+
+/*****************************************************************************
+ * This function returns the boot device based on RCW_SRC
+ ****************************************************************************/
+enum boot_device get_boot_dev(void)
+{
+ enum boot_device src = BOOT_DEVICE_NONE;
+ uint32_t porsr1;
+ uint32_t rcw_src;
+
+ porsr1 = read_reg_porsr1();
+
+ rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT;
+
+ switch (rcw_src) {
+ case FLEXSPI_NOR:
+ src = BOOT_DEVICE_FLEXSPI_NOR;
+ INFO("RCW BOOT SRC is FLEXSPI NOR\n");
+ break;
+ case FLEXSPI_NAND2K_VAL:
+ case FLEXSPI_NAND4K_VAL:
+ INFO("RCW BOOT SRC is FLEXSPI NAND\n");
+ src = BOOT_DEVICE_FLEXSPI_NAND;
+ break;
+ case SDHC1_VAL:
+ src = BOOT_DEVICE_EMMC;
+ INFO("RCW BOOT SRC is SD\n");
+ break;
+ case SDHC2_VAL:
+ src = BOOT_DEVICE_SDHC2_EMMC;
+ INFO("RCW BOOT SRC is EMMC\n");
+ break;
+ default:
+ break;
+ }
+
+ return src;
+}
+
+
+void soc_mem_access(void)
+{
+ const devdisr5_info_t *devdisr5_info = get_devdisr5_info();
+ dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+ struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION];
+ int dram_idx, index = 0U;
+
+ for (dram_idx = 0U; dram_idx < info_dram_regions->num_dram_regions;
+ dram_idx++) {
+ if (info_dram_regions->region[dram_idx].size == 0) {
+ ERROR("DDR init failure, or");
+ ERROR("DRAM regions not populated correctly.\n");
+ break;
+ }
+
+ index = populate_tzc400_reg_list(tzc400_reg_list,
+ dram_idx, index,
+ info_dram_regions->region[dram_idx].addr,
+ info_dram_regions->region[dram_idx].size,
+ NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE);
+ }
+
+ if (devdisr5_info->ddrc1_present != 0) {
+ INFO("DDR Controller 1.\n");
+ mem_access_setup(NXP_TZC_ADDR, index,
+ tzc400_reg_list);
+ mem_access_setup(NXP_TZC3_ADDR, index,
+ tzc400_reg_list);
+ }
+ if (devdisr5_info->ddrc2_present != 0) {
+ INFO("DDR Controller 2.\n");
+ mem_access_setup(NXP_TZC2_ADDR, index,
+ tzc400_reg_list);
+ mem_access_setup(NXP_TZC4_ADDR, index,
+ tzc400_reg_list);
+ }
+}
+
+#else
+const unsigned char _power_domain_tree_desc[] = {1, 8, 2, 2, 2, 2, 2, 2, 2, 2};
+
+CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256,
+ assert_invalid_lx2160a_cluster_count);
+
+/******************************************************************************
+ * This function returns the SoC topology
+ ****************************************************************************/
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+
+ return _power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr)
+{
+ return CORES_PER_CLUSTER;
+}
+
+
+void soc_early_platform_setup2(void)
+{
+ dcfg_init(&dcfg_init_data);
+ /*
+ * Initialize system level generic timer for Socs
+ */
+ delay_timer_init(NXP_TIMER_ADDR);
+
+#if LOG_LEVEL > 0
+ /* Initialize the console to provide early debug support */
+ plat_console_init(NXP_CONSOLE_ADDR,
+ NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+}
+
+void soc_platform_setup(void)
+{
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ static uintptr_t target_mask_array[PLATFORM_CORE_COUNT];
+ static interrupt_prop_t ls_interrupt_props[] = {
+ PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0)
+ };
+
+ plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR,
+ PLATFORM_CORE_COUNT,
+ ls_interrupt_props,
+ ARRAY_SIZE(ls_interrupt_props),
+ target_mask_array,
+ plat_core_pos);
+
+ plat_ls_gic_init();
+ enable_init_timer();
+#ifdef LS_SYS_TIMCTL_BASE
+ ls_configure_sys_timer(LS_SYS_TIMCTL_BASE,
+ LS_CONFIG_CNTACR,
+ PLAT_LS_NSTIMER_FRAME_ID);
+#endif
+}
+
+/*******************************************************************************
+ * This function initializes the soc from the BL31 module
+ ******************************************************************************/
+void soc_init(void)
+{
+ uint8_t num_clusters, cores_per_cluster;
+
+ get_cluster_info(soc_list, ARRAY_SIZE(soc_list),
+ &num_clusters, &cores_per_cluster);
+
+ /* low-level init of the soc */
+ soc_init_start();
+ soc_init_percpu();
+ _init_global_data();
+ _initialize_psci();
+
+ if (ccn_get_part0_id(NXP_CCN_ADDR) != CCN_508_PART0_ID) {
+ ERROR("Unrecognized CCN variant detected.");
+ ERROR("Only CCN-508 is supported\n");
+ panic();
+ }
+
+ if (num_clusters == 6U) {
+ ccn_init(&plat_six_cluster_ccn_desc);
+ } else {
+ ccn_init(&plat_ccn_desc);
+ }
+
+ plat_ls_interconnect_enter_coherency(num_clusters);
+
+ /* Set platform security policies */
+ _set_platform_security();
+
+ /* make sure any parallel init tasks are finished */
+ soc_init_finish();
+
+ /* Initialize the crypto accelerator if enabled */
+ if (is_sec_enabled() == false) {
+ INFO("SEC is disabled.\n");
+ } else {
+ sec_init(NXP_CAAM_ADDR);
+ }
+
+}
+
+#ifdef NXP_WDOG_RESTART
+static uint64_t wdog_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint8_t data = WDOG_RESET_FLAG;
+
+ wr_nv_app_data(WDT_RESET_FLAG_OFFSET,
+ (uint8_t *)&data, sizeof(data));
+
+ mmio_write_32(NXP_RST_ADDR + RSTCNTL_OFFSET, SW_RST_REQ_INIT);
+
+ return 0;
+}
+#endif
+
+void soc_runtime_setup(void)
+{
+
+#ifdef NXP_WDOG_RESTART
+ request_intr_type_el3(BL31_NS_WDOG_WS1, wdog_interrupt_handler);
+#endif
+}
+#endif
diff --git a/plat/nxp/soc-lx2160a/soc.def b/plat/nxp/soc-lx2160a/soc.def
new file mode 100644
index 0000000..81d6744
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/soc.def
@@ -0,0 +1,116 @@
+#
+# Copyright (c) 2015, 2016 Freescale Semiconductor, Inc.
+# Copyright 2017-2022 NXP Semiconductors
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# This file contains the basic architecture definitions that drive the build
+#
+# -----------------------------------------------------------------------------
+
+CORE_TYPE := a72
+
+CACHE_LINE := 6
+
+# set to GIC400 or GIC500
+GIC := GIC500
+
+# set to CCI400 or CCN504 or CCN508
+INTERCONNECT := CCN508
+
+# indicate layerscape chassis level - set to 3=LSCH3 or 2=LSCH2
+CHASSIS := 3_2
+
+# TZC IP Details TZC used is TZC380 or TZC400
+TZC_ID := TZC400
+
+# CONSOLE Details available is NS16550 or PL011
+CONSOLE := PL011
+
+# Select the DDR PHY generation to be used
+PLAT_DDR_PHY := PHY_GEN2
+
+PHYS_SYS := 64
+
+# Area of OCRAM reserved by ROM code
+NXP_ROM_RSVD := 0xa000
+
+# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def
+# Input to CST create_hdr_esbc tool
+CSF_HDR_SZ := 0x3000
+
+NXP_SFP_VER := 3_4
+
+# In IMAGE_BL2, compile time flag for handling Cache coherency
+# with CAAM for BL2 running from OCRAM
+SEC_MEM_NON_COHERENT := yes
+
+# Defining the endianness for NXP ESDHC
+NXP_ESDHC_ENDIANNESS := LE
+
+# Defining the endianness for NXP SFP
+NXP_SFP_ENDIANNESS := LE
+
+# Defining the endianness for NXP GPIO
+NXP_GPIO_ENDIANNESS := LE
+
+# Defining the endianness for NXP SNVS
+NXP_SNVS_ENDIANNESS := LE
+
+# Defining the endianness for NXP CCSR GUR register
+NXP_GUR_ENDIANNESS := LE
+
+# Defining the endianness for NXP FSPI register
+NXP_FSPI_ENDIANNESS := LE
+
+# Defining the endianness for NXP SEC
+NXP_SEC_ENDIANNESS := LE
+
+# Defining the endianness for NXP DDR
+NXP_DDR_ENDIANNESS := LE
+
+NXP_DDR_INTLV_256B := 1
+
+# OCRAM MAP for BL2
+# Before BL2
+# 0x18000000 - 0x18009fff -> Used by ROM code
+# 0x1800a000 - 0x1800dfff -> CSF header for BL2
+# (The above area i.e 0x18000000 - 0x1800dfff is available
+# for DDR PHY images scratch pad region during BL2 run time)
+# For FlexSPI boot
+# 0x1800e000 - 0x18040000 -> Reserved for BL2 binary
+# For SD boot
+# 0x1800e000 - 0x18030000 -> Reserved for BL2 binary
+# 0x18030000 - 0x18040000 -> Reserved for SD buffer
+OCRAM_START_ADDR := 0x18000000
+OCRAM_SIZE := 0x40000
+
+# Location of BL2 on OCRAM
+BL2_BASE_ADDR := $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) + $(CSF_HDR_SZ) )))
+# Covert to HEX to be used by create_pbl.mk
+BL2_BASE := $(shell echo "0x"$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc))
+
+# BL2_HDR_LOC is at (OCRAM_ADDR + NXP_ROM_RSVD)
+# This value BL2_HDR_LOC + CSF_HDR_SZ should not overalp with BL2_BASE
+BL2_HDR_LOC_HDR ?= $(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) )))
+# Covert to HEX to be used by create_pbl.mk
+BL2_HDR_LOC := $$(echo "obase=16; ${BL2_HDR_LOC_HDR}" | bc)
+
+# SoC ERRATAS to be enabled
+#
+# Core Errata
+ERRATA_A72_859971 := 1
+
+# SoC Errata
+ERRATA_SOC_A050426 := 1
+
+# DDR Errata
+ERRATA_DDR_A011396 := 1
+ERRATA_DDR_A050450 := 1
+ERRATA_DDR_A050958 := 1
+
+# enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC := 1
diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk
new file mode 100644
index 0000000..75a3af2
--- /dev/null
+++ b/plat/nxp/soc-lx2160a/soc.mk
@@ -0,0 +1,174 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+ # SoC-specific build parameters
+SOC := lx2160a
+PLAT_PATH := plat/nxp
+PLAT_COMMON_PATH:= plat/nxp/common
+PLAT_DRIVERS_PATH:= drivers/nxp
+PLAT_SOC_PATH := ${PLAT_PATH}/soc-${SOC}
+BOARD_PATH := ${PLAT_SOC_PATH}/${BOARD}
+
+ # get SoC-specific defnitions
+include ${PLAT_SOC_PATH}/soc.def
+include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk
+include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
+
+ # SoC-specific
+NXP_WDOG_RESTART := yes
+
+
+ # Selecting dependent module,
+ # Selecting dependent drivers, and
+ # Adding defines.
+
+ # for features enabled above.
+ifeq (${NXP_WDOG_RESTART}, yes)
+NXP_NV_SW_MAINT_LAST_EXEC_DATA := yes
+LS_EL3_INTERRUPT_HANDLER := yes
+$(eval $(call add_define, NXP_WDOG_RESTART))
+endif
+
+
+ # For Security Features
+DISABLE_FUSE_WRITE := 1
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+ifeq (${GENERATE_COT},1)
+# Save Keys to be used by DDR FIP image
+SAVE_KEYS=1
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2))
+# Used by create_pbl tool to
+# create bl2_<boot_mode>_sec.pbl image
+SECURE_BOOT := yes
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM))
+
+
+ # Selecting Drivers for SoC
+$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM))
+
+$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+
+
+ # Selecting PSCI & SIP_SVC support
+$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31))
+
+
+ # Selecting Boot Source for the TFA images.
+ifeq (${BOOT_MODE}, flexspi_nor)
+$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2))
+$(eval $(call add_define,FLEXSPI_NOR_BOOT))
+else
+ifeq (${BOOT_MODE}, sd)
+$(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2))
+$(eval $(call add_define,SD_BOOT))
+else
+ifeq (${BOOT_MODE}, emmc)
+$(eval $(call SET_NXP_MAKE_FLAG,SD_MMC_NEEDED,BL2))
+$(eval $(call add_define,EMMC_BOOT))
+else
+$(error Un-supported Boot Mode = ${BOOT_MODE})
+endif
+endif
+endif
+
+
+ # Separate DDR-FIP image to be loaded.
+$(eval $(call SET_NXP_MAKE_FLAG,DDR_FIP_IO_NEEDED,BL2))
+
+
+# Source File Addition
+# #####################
+
+PLAT_INCLUDES += -I${PLAT_COMMON_PATH}/include/default\
+ -I${BOARD_PATH}\
+ -I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
+ -I${PLAT_SOC_PATH}/include\
+ -I${PLAT_COMMON_PATH}/soc_errata
+
+ifeq (${SECURE_BOOT},yes)
+include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
+endif
+
+ifeq ($(WARM_BOOT),yes)
+include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk
+endif
+
+ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes)
+include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk
+endif
+
+ifeq (${PSCI_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/psci/psci.mk
+endif
+
+ifeq (${SIPSVC_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk
+endif
+
+ifeq (${DDR_FIP_IO_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/fip_handler/ddr_fip/ddr_fip_io.mk
+endif
+
+ # for fuse-fip & fuse-programming
+ifeq (${FUSE_PROG}, 1)
+include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk
+endif
+
+ifeq (${IMG_LOADR_NEEDED},yes)
+include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk
+endif
+
+ # Adding source files for the above selected drivers.
+include ${PLAT_DRIVERS_PATH}/drivers.mk
+
+ # Adding SoC specific files
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
+
+PLAT_INCLUDES += ${NV_STORAGE_INCLUDES}\
+ ${WARM_RST_INCLUDES}
+
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\
+ ${WARM_RST_BL31_SOURCES}\
+ ${PSCI_SOURCES}\
+ ${SIPSVC_SOURCES}\
+ ${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S
+
+PLAT_BL_COMMON_SOURCES += ${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\
+ ${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\
+ ${NV_STORAGE_SOURCES}\
+ ${WARM_RST_BL_COMM_SOURCES}\
+ ${PLAT_SOC_PATH}/soc.c
+
+ifeq (${TEST_BL31}, 1)
+BL31_SOURCES += ${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S\
+ ${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S
+endif
+
+BL2_SOURCES += ${DDR_CNTLR_SOURCES}\
+ ${TBBR_SOURCES}\
+ ${FUSE_SOURCES}
+
+
+ # Adding TFA setup files
+include ${PLAT_PATH}/common/setup/common.mk
+
+
+ # Adding source files to generate separate DDR FIP image
+include ${PLAT_SOC_PATH}/ddr_fip.mk
diff --git a/plat/qemu/common/aarch32/plat_helpers.S b/plat/qemu/common/aarch32/plat_helpers.S
new file mode 100644
index 0000000..5e346d5
--- /dev/null
+++ b/plat/qemu/common/aarch32/plat_helpers.S
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015-2020, 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 <platform_def.h>
+
+ .globl plat_my_core_pos
+ .globl plat_get_my_entrypoint
+ .globl platform_mem_init
+ .globl plat_qemu_calc_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+
+
+func plat_my_core_pos
+ ldcopr r0, MPIDR
+ b plat_qemu_calc_core_pos
+endfunc plat_my_core_pos
+
+/*
+ * unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
+ * With this function: CorePos = (ClusterId * 4) + CoreId
+ */
+func plat_qemu_calc_core_pos
+ and r1, r0, #MPIDR_CPU_MASK
+ and r0, r0, #MPIDR_CLUSTER_MASK
+ add r0, r1, r0, LSR #6
+ bx lr
+endfunc plat_qemu_calc_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ ldcopr r0, MPIDR
+ ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ and r0, r1
+ cmp r0, #QEMU_PRIMARY_CPU
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* Calculate address of our hold entry */
+ bl plat_my_core_pos
+ lsl r0, r0, #PLAT_QEMU_HOLD_ENTRY_SHIFT
+ mov_imm r2, PLAT_QEMU_HOLD_BASE
+
+ /* Wait until we have a go */
+poll_mailbox:
+ ldr r1, [r2, r0]
+ cmp r1, #PLAT_QEMU_HOLD_STATE_WAIT
+ beq 1f
+
+ /* Clear the mailbox again ready for next time. */
+ mov r1, #PLAT_QEMU_HOLD_STATE_WAIT
+ str r1, [r2, r0]
+
+ /* Jump to the provided entrypoint. */
+ mov_imm r0, PLAT_QEMU_TRUSTED_MAILBOX_BASE
+ ldr r1, [r0]
+ bx r1
+1:
+ wfe
+ b poll_mailbox
+endfunc plat_secondary_cold_boot_setup
+
+func plat_get_my_entrypoint
+ /* TODO support warm boot */
+ mov r0, #0
+ bx lr
+endfunc plat_get_my_entrypoint
+
+func platform_mem_init
+ bx lr
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm r0, PLAT_QEMU_CRASH_UART_BASE
+ mov_imm r1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ
+ mov_imm r2, PLAT_QEMU_CONSOLE_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm r1, PLAT_QEMU_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush(int c)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm r0, PLAT_QEMU_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
+
diff --git a/plat/qemu/common/aarch64/plat_helpers.S b/plat/qemu/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..08b2817
--- /dev/null
+++ b/plat/qemu/common/aarch64/plat_helpers.S
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015-2020, 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 <platform_def.h>
+
+ .globl plat_my_core_pos
+ .globl plat_get_my_entrypoint
+ .globl platform_mem_init
+ .globl plat_qemu_calc_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_qemu_calc_core_pos
+endfunc plat_my_core_pos
+
+/*
+ * unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
+ * With this function: CorePos = (ClusterId * 4) + CoreId
+ */
+func plat_qemu_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #(MPIDR_AFFINITY_BITS -\
+ PLATFORM_CPU_PER_CLUSTER_SHIFT)
+ ret
+endfunc plat_qemu_calc_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #QEMU_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* Calculate address of our hold entry */
+ bl plat_my_core_pos
+ lsl x0, x0, #PLAT_QEMU_HOLD_ENTRY_SHIFT
+ mov_imm x2, PLAT_QEMU_HOLD_BASE
+
+ /* Wait until we have a go */
+poll_mailbox:
+ ldr x1, [x2, x0]
+ cbz x1, 1f
+
+ /* Clear the mailbox again ready for next time. */
+ mov x1, #PLAT_QEMU_HOLD_STATE_WAIT
+ str x1, [x2, x0]
+
+ /* Jump to the provided entrypoint. */
+ mov_imm x0, PLAT_QEMU_TRUSTED_MAILBOX_BASE
+ ldr x1, [x0]
+ br x1
+1:
+ wfe
+ b poll_mailbox
+endfunc plat_secondary_cold_boot_setup
+
+func plat_get_my_entrypoint
+ /* TODO support warm boot */
+ mov x0, #0
+ ret
+endfunc plat_get_my_entrypoint
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_QEMU_CRASH_UART_BASE
+ mov_imm x1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ
+ mov_imm x2, PLAT_QEMU_CONSOLE_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_QEMU_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush(int c)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, PLAT_QEMU_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
+
diff --git a/plat/qemu/common/include/plat_macros.S b/plat/qemu/common/include/plat_macros.S
new file mode 100644
index 0000000..b6cdb07
--- /dev/null
+++ b/plat/qemu/common/include/plat_macros.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+#include <platform_def.h>
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x17, GICC_BASE
+ mov_imm x16, GICD_BASE
+ arm_print_gic_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/qemu/common/qemu_bl1_setup.c b/plat/qemu/common/qemu_bl1_setup.c
new file mode 100644
index 0000000..67f3327
--- /dev/null
+++ b/plat/qemu/common/qemu_bl1_setup.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+
+#include "qemu_private.h"
+
+/* Data structure which holds the extents of the trusted SRAM for BL1*/
+static meminfo_t bl1_tzram_layout;
+
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ /* Initialize the console to provide early debug support */
+ qemu_console_init();
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = BL_RAM_BASE;
+ bl1_tzram_layout.total_size = BL_RAM_SIZE;
+}
+
+/******************************************************************************
+ * Perform the very early platform specific architecture setup. This only
+ * does basic initialization. Later architectural setup (bl1_arch_setup())
+ * does not do anything platform specific.
+ *****************************************************************************/
+#ifdef __aarch64__
+#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_el3(__VA_ARGS__)
+#else
+#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_svc_mon(__VA_ARGS__)
+#endif
+
+void bl1_plat_arch_setup(void)
+{
+ QEMU_CONFIGURE_BL1_MMU(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL_CODE_BASE, BL1_CODE_END,
+ BL1_RO_DATA_BASE, BL1_RO_DATA_END,
+ BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
+}
+
+void bl1_platform_setup(void)
+{
+ plat_qemu_io_setup();
+}
diff --git a/plat/qemu/common/qemu_bl2_mem_params_desc.c b/plat/qemu/common/qemu_bl2_mem_params_desc.c
new file mode 100644
index 0000000..5af3a22
--- /dev/null
+++ b/plat/qemu/common/qemu_bl2_mem_params_desc.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+#ifdef EL3_PAYLOAD_BASE
+ /* Fill EL3 payload related information (BL31 is EL3 payload) */
+ { .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = EL3_PAYLOAD_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#else /* EL3_PAYLOAD_BASE */
+#ifdef __aarch64__
+ /* Fill BL31 related information */
+ { .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+# if DEBUG
+ .ep_info.args.arg1 = QEMU_BL31_PLAT_PARAM_VAL,
+# endif
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef QEMU_LOAD_BL32
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+#endif /* __aarch64__ */
+# ifdef QEMU_LOAD_BL32
+
+#ifdef __aarch64__
+#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE)
+#define BL32_IMG_ATTRIBS 0
+#else
+#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE | EP_FIRST_EXE)
+#define BL32_IMG_ATTRIBS IMAGE_ATTRIB_PLAT_SETUP
+#endif
+
+ /* Fill BL32 related information */
+ { .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t, BL32_EP_ATTRIBS),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, BL32_IMG_ATTRIBS),
+
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the
+ * pager image.
+ */
+ { .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the
+ * paged image.
+ */
+ { .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
+ .image_info.image_base = QEMU_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = QEMU_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* QEMU_LOAD_BL32 */
+
+ /* Fill BL33 related information */
+ { .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t, NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+# else /* PRELOADED_BL33_BASE */
+ .ep_info.pc = NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
+ 0),
+ .image_info.image_base = NS_IMAGE_OFFSET,
+ .image_info.image_max_size = NS_IMAGE_MAX_SIZE,
+# endif /* !PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+#endif /* !EL3_PAYLOAD_BASE */
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
new file mode 100644
index 0000000..2c0da15
--- /dev/null
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/fdt_fixup.h>
+#include <lib/optee_utils.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include "qemu_private.h"
+
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ meminfo_t *mem_layout = (void *)arg1;
+
+ /* Initialize the console to provide early debug support */
+ qemu_console_init();
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ plat_qemu_io_setup();
+}
+
+static void security_setup(void)
+{
+ /*
+ * This is where a TrustZone address space controller and other
+ * security related peripherals, would be configured.
+ */
+}
+
+static void update_dt(void)
+{
+ int ret;
+ void *fdt = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE;
+
+ ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
+ if (ret < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret);
+ return;
+ }
+
+ if (dt_add_psci_node(fdt)) {
+ ERROR("Failed to add PSCI Device Tree node\n");
+ return;
+ }
+
+ if (dt_add_psci_cpu_enable_methods(fdt)) {
+ ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
+ return;
+ }
+
+ ret = fdt_pack(fdt);
+ if (ret < 0)
+ ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, ret);
+}
+
+void bl2_platform_setup(void)
+{
+ security_setup();
+ update_dt();
+
+ /* TODO Initialize timer */
+}
+
+#ifdef __aarch64__
+#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_el1(__VA_ARGS__)
+#else
+#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_svc_mon(__VA_ARGS__)
+#endif
+
+void bl2_plat_arch_setup(void)
+{
+ QEMU_CONFIGURE_BL2_MMU(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END,
+ BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+static uint32_t qemu_get_spsr_for_bl32_entry(void)
+{
+#ifdef __aarch64__
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL3-2 image.
+ */
+ return 0;
+#else
+ return SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS);
+#endif
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+static uint32_t qemu_get_spsr_for_bl33_entry(void)
+{
+ uint32_t spsr;
+#ifdef __aarch64__
+ unsigned int mode;
+
+ /* Figure out what mode we enter the non-secure world in */
+ mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
+
+ /*
+ * TODO: Consider the possibility of specifying the SPSR in
+ * the FIP ToC and allowing the platform to have a say as
+ * well.
+ */
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+#else
+ spsr = SPSR_MODE32(MODE32_svc,
+ plat_get_ns_image_entrypoint() & 0x1,
+ SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
+#endif
+ return spsr;
+}
+
+static int qemu_bl2_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+#if defined(SPD_spmd)
+ unsigned int mode_rw = MODE_RW_64;
+ uint64_t pagable_part = 0;
+#endif
+
+ assert(bl_mem_params);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0) {
+ WARN("OPTEE header parse error.\n");
+ }
+#if defined(SPD_spmd)
+ mode_rw = bl_mem_params->ep_info.args.arg0;
+ pagable_part = bl_mem_params->ep_info.args.arg1;
+#endif
+#endif
+
+#if defined(SPD_spmd)
+ bl_mem_params->ep_info.args.arg0 = ARM_PRELOADED_DTB_BASE;
+ bl_mem_params->ep_info.args.arg1 = pagable_part;
+ bl_mem_params->ep_info.args.arg2 = mode_rw;
+ bl_mem_params->ep_info.args.arg3 = 0;
+#elif defined(SPD_opteed)
+ /*
+ * OP-TEE expect to receive DTB address in x2.
+ * This will be copied into x2 by dispatcher.
+ */
+ bl_mem_params->ep_info.args.arg3 = ARM_PRELOADED_DTB_BASE;
+#elif defined(AARCH32_SP_OPTEE)
+ bl_mem_params->ep_info.args.arg0 =
+ bl_mem_params->ep_info.args.arg1;
+ bl_mem_params->ep_info.args.arg1 = 0;
+ bl_mem_params->ep_info.args.arg2 = ARM_PRELOADED_DTB_BASE;
+ bl_mem_params->ep_info.args.arg3 = 0;
+#endif
+ bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl32_entry();
+ break;
+
+ case BL33_IMAGE_ID:
+#ifdef AARCH32_SP_OPTEE
+ /* AArch32 only core: OP-TEE expects NSec EP in register LR */
+ pager_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
+ assert(pager_mem_params);
+ pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
+#endif
+
+#if ARM_LINUX_KERNEL_AS_BL33
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of
+ * the Linux kernel tree, Linux expects the physical address of
+ * the device tree blob (DTB) in x0, while x1-x3 are reserved
+ * for future use and must be 0.
+ */
+ bl_mem_params->ep_info.args.arg0 =
+ (u_register_t)ARM_PRELOADED_DTB_BASE;
+ bl_mem_params->ep_info.args.arg1 = 0U;
+ bl_mem_params->ep_info.args.arg2 = 0U;
+ bl_mem_params->ep_info.args.arg3 = 0U;
+#else
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+#endif
+
+ bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry();
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return qemu_bl2_handle_post_image_load(image_id);
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+ return NS_IMAGE_OFFSET;
+}
diff --git a/plat/qemu/common/qemu_bl31_setup.c b/plat/qemu/common/qemu_bl31_setup.c
new file mode 100644
index 0000000..4f60eb1
--- /dev/null
+++ b/plat/qemu/common/qemu_bl31_setup.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <drivers/arm/pl061_gpio.h>
+#include <plat/common/platform.h>
+
+#include "qemu_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL3-1 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ /* Initialize the console to provide early debug support */
+ qemu_console_init();
+
+ /*
+ * Check params passed from BL2
+ */
+ bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
+
+ assert(params_from_bl2);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (!bl33_image_ep_info.pc)
+ panic();
+}
+
+void bl31_plat_arch_setup(void)
+{
+ qemu_configure_mmu_el3(BL31_BASE, (BL31_END - BL31_BASE),
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END,
+ BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
+}
+
+static void qemu_gpio_init(void)
+{
+#ifdef SECURE_GPIO_BASE
+ pl061_gpio_init();
+ pl061_gpio_register(SECURE_GPIO_BASE, 0);
+#endif
+}
+
+void bl31_platform_setup(void)
+{
+ plat_qemu_gic_init();
+ qemu_gpio_init();
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image
+ * for the security state specified. BL3-3 corresponds to the non-secure
+ * image type while BL3-2 corresponds to the secure image type. A NULL
+ * pointer is returned if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
new file mode 100644
index 0000000..0c184f4
--- /dev/null
+++ b/plat/qemu/common/qemu_common.c
@@ -0,0 +1,169 @@
+
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <plat/common/platform.h>
+#include "qemu_private.h"
+
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#ifdef DEVICE1_BASE
+#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \
+ DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#ifdef DEVICE2_BASE
+#define MAP_DEVICE2 MAP_REGION_FLAT(DEVICE2_BASE, \
+ DEVICE2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \
+ SHARED_RAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_FLASH0 MAP_REGION_FLAT(QEMU_FLASH0_BASE, QEMU_FLASH0_SIZE, \
+ MT_MEMORY | MT_RO | MT_SECURE)
+
+#define MAP_FLASH1 MAP_REGION_FLAT(QEMU_FLASH1_BASE, QEMU_FLASH1_SIZE, \
+ MT_MEMORY | MT_RO | MT_SECURE)
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * arm_configure_mmu_elx() will give the available subset of that,
+ */
+#ifdef IMAGE_BL1
+static const mmap_region_t plat_qemu_mmap[] = {
+ MAP_FLASH0,
+ MAP_FLASH1,
+ MAP_SHARED_RAM,
+ MAP_DEVICE0,
+#ifdef MAP_DEVICE1
+ MAP_DEVICE1,
+#endif
+#ifdef MAP_DEVICE2
+ MAP_DEVICE2,
+#endif
+ {0}
+};
+#endif
+#ifdef IMAGE_BL2
+static const mmap_region_t plat_qemu_mmap[] = {
+ MAP_FLASH0,
+ MAP_FLASH1,
+ MAP_SHARED_RAM,
+ MAP_DEVICE0,
+#ifdef MAP_DEVICE1
+ MAP_DEVICE1,
+#endif
+#ifdef MAP_DEVICE2
+ MAP_DEVICE2,
+#endif
+ MAP_NS_DRAM0,
+#if SPM_MM
+ QEMU_SP_IMAGE_MMAP,
+#else
+ MAP_BL32_MEM,
+#endif
+ {0}
+};
+#endif
+#ifdef IMAGE_BL31
+static const mmap_region_t plat_qemu_mmap[] = {
+ MAP_SHARED_RAM,
+ MAP_DEVICE0,
+#ifdef MAP_DEVICE1
+ MAP_DEVICE1,
+#endif
+#ifdef MAP_DEVICE2
+ MAP_DEVICE2,
+#endif
+#if SPM_MM
+ MAP_NS_DRAM0,
+ QEMU_SPM_BUF_EL3_MMAP,
+#else
+ MAP_BL32_MEM,
+#endif
+ {0}
+};
+#endif
+#ifdef IMAGE_BL32
+static const mmap_region_t plat_qemu_mmap[] = {
+ MAP_SHARED_RAM,
+ MAP_DEVICE0,
+#ifdef MAP_DEVICE1
+ MAP_DEVICE1,
+#endif
+#ifdef MAP_DEVICE2
+ MAP_DEVICE2,
+#endif
+ {0}
+};
+#endif
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void qemu_configure_mmu_##_el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long code_start, \
+ unsigned long code_limit, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(code_start, code_start, \
+ code_limit - code_start, \
+ MT_CODE | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_RO_DATA | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(plat_qemu_mmap); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_##_el(0); \
+ }
+
+/* Define EL1 and EL3 variants of the function initialising the MMU */
+#ifdef __aarch64__
+DEFINE_CONFIGURE_MMU_EL(el1)
+DEFINE_CONFIGURE_MMU_EL(el3)
+#else
+DEFINE_CONFIGURE_MMU_EL(svc_mon)
+#endif
+
+#if MEASURED_BOOT || TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
+#endif
diff --git a/plat/qemu/common/qemu_console.c b/plat/qemu/common/qemu_console.c
new file mode 100644
index 0000000..1f00f8a
--- /dev/null
+++ b/plat/qemu/common/qemu_console.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/console.h>
+#include <drivers/arm/pl011.h>
+
+static console_t console;
+
+void qemu_console_init(void)
+{
+ (void)console_pl011_register(PLAT_QEMU_BOOT_UART_BASE,
+ PLAT_QEMU_BOOT_UART_CLK_IN_HZ,
+ PLAT_QEMU_CONSOLE_BAUDRATE, &console);
+
+ console_set_scope(&console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME);
+}
+
diff --git a/plat/qemu/common/qemu_gicv2.c b/plat/qemu/common/qemu_gicv2.c
new file mode 100644
index 0000000..2c358ea
--- /dev/null
+++ b/plat/qemu/common/qemu_gicv2.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gic_common.h>
+#include <platform_def.h>
+
+static const interrupt_prop_t qemu_interrupt_props[] = {
+ PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
+ PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
+};
+
+static const struct gicv2_driver_data plat_gicv2_driver_data = {
+ .gicd_base = GICD_BASE,
+ .gicc_base = GICC_BASE,
+ .interrupt_props = qemu_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(qemu_interrupt_props),
+};
+
+void plat_qemu_gic_init(void)
+{
+ /* Initialize the gic cpu and distributor interfaces */
+ gicv2_driver_init(&plat_gicv2_driver_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+void qemu_pwr_gic_on_finish(void)
+{
+ /* TODO: This setup is needed only after a cold boot */
+ gicv2_pcpu_distif_init();
+
+ /* Enable the gic cpu interface */
+ gicv2_cpuif_enable();
+}
+
+void qemu_pwr_gic_off(void)
+{
+ gicv2_cpuif_disable();
+}
diff --git a/plat/qemu/common/qemu_gicv3.c b/plat/qemu/common/qemu_gicv3.c
new file mode 100644
index 0000000..0d35446
--- /dev/null
+++ b/plat/qemu/common/qemu_gicv3.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, Linaro Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/gicv3.h>
+#include <drivers/arm/gic_common.h>
+#include <platform_def.h>
+#include <plat/common/platform.h>
+
+static const interrupt_prop_t qemu_interrupt_props[] = {
+ PLATFORM_G1S_PROPS(INTR_GROUP1S),
+ PLATFORM_G0_PROPS(INTR_GROUP0)
+};
+
+static uintptr_t qemu_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static unsigned int qemu_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+static const gicv3_driver_data_t qemu_gicv3_driver_data = {
+ .gicd_base = GICD_BASE,
+ .gicr_base = GICR_BASE,
+ .interrupt_props = qemu_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(qemu_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = qemu_rdistif_base_addrs,
+ .mpidr_to_core_pos = qemu_mpidr_to_core_pos
+};
+
+void plat_qemu_gic_init(void)
+{
+ gicv3_driver_init(&qemu_gicv3_driver_data);
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void qemu_pwr_gic_on_finish(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void qemu_pwr_gic_off(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+ gicv3_rdistif_off(plat_my_core_pos());
+}
diff --git a/plat/qemu/common/qemu_image_load.c b/plat/qemu/common/qemu_image_load.c
new file mode 100644
index 0000000..9970d1d
--- /dev/null
+++ b/plat/qemu/common/qemu_image_load.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+
+/*******************************************************************************
+ * This function is a wrapper of a common function which flushes the data
+ * structures so that they are visible in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function is a wrapper of a common function which returns the list of
+ * loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function is a wrapper of a common function which returns the data
+ * structures of the next BL image.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/qemu/common/qemu_io_storage.c b/plat/qemu/common/qemu_io_storage.c
new file mode 100644
index 0000000..1107e44
--- /dev/null
+++ b/plat/qemu/common/qemu_io_storage.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_encrypted.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_semihosting.h>
+#include <drivers/io/io_storage.h>
+#include <lib/semihosting.h>
+#include <tools_share/firmware_image_package.h>
+
+/* Semihosting filenames */
+#define BL2_IMAGE_NAME "bl2.bin"
+#define BL31_IMAGE_NAME "bl31.bin"
+#define BL32_IMAGE_NAME "bl32.bin"
+#define BL32_EXTRA1_IMAGE_NAME "bl32_extra1.bin"
+#define BL32_EXTRA2_IMAGE_NAME "bl32_extra2.bin"
+#define BL33_IMAGE_NAME "bl33.bin"
+
+#if TRUSTED_BOARD_BOOT
+#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt"
+#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
+#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt"
+#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt"
+#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt"
+#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt"
+#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt"
+#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+static const io_dev_connector_t *sh_dev_con;
+static uintptr_t sh_dev_handle;
+#ifndef DECRYPTION_SUPPORT_none
+static const io_dev_connector_t *enc_dev_con;
+static uintptr_t enc_dev_handle;
+#endif
+
+static const io_block_spec_t fip_block_spec = {
+ .offset = PLAT_QEMU_FIP_BASE,
+ .length = PLAT_QEMU_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static const io_file_spec_t sh_file_spec[] = {
+ [BL2_IMAGE_ID] = {
+ .path = BL2_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL31_IMAGE_ID] = {
+ .path = BL31_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL32_IMAGE_ID] = {
+ .path = BL32_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ .path = BL32_EXTRA1_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ .path = BL32_EXTRA2_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [BL33_IMAGE_ID] = {
+ .path = BL33_IMAGE_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ .path = TRUSTED_BOOT_FW_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ .path = TRUSTED_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ .path = SOC_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ .path = TOS_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ .path = NT_FW_KEY_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ .path = SOC_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ .path = TOS_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ .path = NT_FW_CONTENT_CERT_NAME,
+ .mode = FOPEN_MODE_RB
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+#ifndef DECRYPTION_SUPPORT_none
+static int open_enc_fip(const uintptr_t spec);
+#endif
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, ARM platforms load images from the FIP */
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+ [ENC_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)NULL,
+ open_fip
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+#if ENCRYPT_BL31 && !defined(DECRYPTION_SUPPORT_none)
+ [BL31_IMAGE_ID] = {
+ &enc_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_enc_fip
+ },
+#else
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+#endif
+#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none)
+ [BL32_IMAGE_ID] = {
+ &enc_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_enc_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &enc_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_enc_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &enc_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_enc_fip
+ },
+#else
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
+#endif
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ open_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0 && spec != (uintptr_t)NULL) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+#ifndef DECRYPTION_SUPPORT_none
+static int open_enc_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if an encrypted FIP is available */
+ result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(enc_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using encrypted FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+#endif
+
+static int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+static int open_semihosting(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if the file exists on semi-hosting.*/
+ result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(sh_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Semi-hosting IO\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+void plat_qemu_io_setup(void)
+{
+ int io_result;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+ assert(io_result == 0);
+
+#ifndef DECRYPTION_SUPPORT_none
+ io_result = register_io_dev_enc(&enc_dev_con);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
+ &enc_dev_handle);
+ assert(io_result == 0);
+#endif
+
+ /* Register the additional IO devices on this platform */
+ io_result = register_io_dev_sh(&sh_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
+ assert(io_result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)io_result;
+}
+
+static int get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
+
+ if (result == 0) {
+ *dev_handle = sh_dev_handle;
+ *image_spec = (uintptr_t)&sh_file_spec[image_id];
+ }
+
+ return result;
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ } else {
+ VERBOSE("Trying alternative IO\n");
+ result = get_alt_image_source(image_id, dev_handle, image_spec);
+ }
+
+ return result;
+}
diff --git a/plat/qemu/common/qemu_pm.c b/plat/qemu/common/qemu_pm.c
new file mode 100644
index 0000000..c2b5091
--- /dev/null
+++ b/plat/qemu/common/qemu_pm.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/psci/psci.h>
+#include <lib/semihosting.h>
+#include <plat/common/platform.h>
+#include <drivers/gpio.h>
+
+#include "qemu_private.h"
+
+#define ADP_STOPPED_APPLICATION_EXIT 0x20026
+
+/*
+ * The secure entry point to be used on warm reset.
+ */
+static unsigned long secure_entrypoint;
+
+/* Make composite power state parameter till power level 0 */
+#if PSCI_EXTENDED_STATE_ID
+
+#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+#else
+#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+#endif /* PSCI_EXTENDED_STATE_ID */
+
+
+#define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \
+ qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+
+
+
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+static const unsigned int qemu_pm_idle_states[] = {
+ /* State-id - 0x01 */
+ qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET,
+ MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x02 */
+ qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x22 */
+ qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+ 0,
+};
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the power state
+ * parameter. The power state parameter has to be a composite power state.
+ ******************************************************************************/
+static int qemu_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ int i;
+
+ assert(req_state);
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
+ */
+ for (i = 0; !!qemu_pm_idle_states[i]; i++) {
+ if (power_state == qemu_pm_idle_states[i])
+ break;
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!qemu_pm_idle_states[i])
+ return PSCI_E_INVALID_PARAMS;
+
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id &
+ PLAT_LOCAL_PSTATE_MASK;
+ state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the non secure
+ * entrypoint.
+ ******************************************************************************/
+static int qemu_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /*
+ * Check if the non secure entrypoint lies within the non
+ * secure DRAM.
+ */
+ if ((entrypoint >= NS_DRAM0_BASE) &&
+ (entrypoint < (NS_DRAM0_BASE + NS_DRAM0_SIZE)))
+ return PSCI_E_SUCCESS;
+ return PSCI_E_INVALID_ADDRESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+static void qemu_cpu_standby(plat_local_state_t cpu_state)
+{
+
+ assert(cpu_state == PLAT_LOCAL_STATE_RET);
+
+ /*
+ * Enter standby state
+ * dsb is good practice before using wfi to enter low power states
+ */
+ dsb();
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int qemu_pwr_domain_on(u_register_t mpidr)
+{
+ int rc = PSCI_E_SUCCESS;
+ unsigned pos = plat_core_pos_by_mpidr(mpidr);
+ uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE;
+
+ hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO;
+ sev();
+
+ return rc;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void qemu_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ qemu_pwr_gic_off();
+}
+
+void __dead2 plat_secondary_cold_boot_setup(void);
+
+static void __dead2
+qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+ disable_mmu_el3();
+ plat_secondary_cold_boot_setup();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void qemu_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ qemu_pwr_gic_on_finish();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ ******************************************************************************/
+void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ assert(0);
+}
+
+/*******************************************************************************
+ * Platform handlers to shutdown/reboot the system
+ ******************************************************************************/
+
+static void __dead2 qemu_system_off(void)
+{
+#ifdef SECURE_GPIO_BASE
+ ERROR("QEMU System Power off: with GPIO.\n");
+ gpio_set_direction(SECURE_GPIO_POWEROFF, GPIO_DIR_OUT);
+ gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_LOW);
+ gpio_set_value(SECURE_GPIO_POWEROFF, GPIO_LEVEL_HIGH);
+#else
+ semihosting_exit(ADP_STOPPED_APPLICATION_EXIT, 0);
+ ERROR("QEMU System Off: semihosting call unexpectedly returned.\n");
+#endif
+ panic();
+}
+
+static void __dead2 qemu_system_reset(void)
+{
+ ERROR("QEMU System Reset: with GPIO.\n");
+#ifdef SECURE_GPIO_BASE
+ gpio_set_direction(SECURE_GPIO_RESET, GPIO_DIR_OUT);
+ gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(SECURE_GPIO_RESET, GPIO_LEVEL_HIGH);
+#else
+ ERROR("QEMU System Reset: operation not handled.\n");
+#endif
+ panic();
+}
+
+static const plat_psci_ops_t plat_qemu_psci_pm_ops = {
+ .cpu_standby = qemu_cpu_standby,
+ .pwr_domain_on = qemu_pwr_domain_on,
+ .pwr_domain_off = qemu_pwr_domain_off,
+ .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi,
+ .pwr_domain_suspend = qemu_pwr_domain_suspend,
+ .pwr_domain_on_finish = qemu_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish,
+ .system_off = qemu_system_off,
+ .system_reset = qemu_system_reset,
+ .validate_power_state = qemu_validate_power_state,
+ .validate_ns_entrypoint = qemu_validate_ns_entrypoint
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ uintptr_t *mailbox = (void *) PLAT_QEMU_TRUSTED_MAILBOX_BASE;
+
+ *mailbox = sec_entrypoint;
+ secure_entrypoint = (unsigned long) sec_entrypoint;
+ *psci_ops = &plat_qemu_psci_pm_ops;
+
+ return 0;
+}
diff --git a/plat/qemu/common/qemu_private.h b/plat/qemu/common/qemu_private.h
new file mode 100644
index 0000000..c313cb6
--- /dev/null
+++ b/plat/qemu/common/qemu_private.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QEMU_PRIVATE_H
+#define QEMU_PRIVATE_H
+
+#include <stdint.h>
+
+void qemu_configure_mmu_svc_mon(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long code_start, unsigned long code_limit,
+ unsigned long ro_start, unsigned long ro_limit,
+ unsigned long coh_start, unsigned long coh_limit);
+
+void qemu_configure_mmu_el1(unsigned long total_base, unsigned long total_size,
+ unsigned long code_start, unsigned long code_limit,
+ unsigned long ro_start, unsigned long ro_limit,
+ unsigned long coh_start, unsigned long coh_limit);
+
+void qemu_configure_mmu_el3(unsigned long total_base, unsigned long total_size,
+ unsigned long code_start, unsigned long code_limit,
+ unsigned long ro_start, unsigned long ro_limit,
+ unsigned long coh_start, unsigned long coh_limit);
+
+void plat_qemu_io_setup(void);
+unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
+
+void qemu_console_init(void);
+
+void plat_qemu_gic_init(void);
+void qemu_pwr_gic_on_finish(void);
+void qemu_pwr_gic_off(void);
+
+int qemu_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+ size_t log_size);
+
+int qemu_set_nt_fw_info(
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this option should be removed when feature is supported.
+ */
+#ifdef SPD_opteed
+ uintptr_t log_addr,
+#endif
+ size_t log_size,
+ uintptr_t *ns_log_addr);
+
+#endif /* QEMU_PRIVATE_H */
diff --git a/plat/qemu/common/qemu_rotpk.S b/plat/qemu/common/qemu_rotpk.S
new file mode 100644
index 0000000..5d1b83f
--- /dev/null
+++ b/plat/qemu/common/qemu_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global qemu_rotpk_hash
+ .global qemu_rotpk_hash_end
+qemu_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+qemu_rotpk_hash_end:
diff --git a/plat/qemu/common/qemu_spm.c b/plat/qemu/common/qemu_spm.c
new file mode 100644
index 0000000..c66f47e
--- /dev/null
+++ b/plat/qemu/common/qemu_spm.c
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2020, Linaro Limited and Contributors. All rights reserved.
+ */
+
+#include <libfdt.h>
+
+#include <bl31/ehf.h>
+#include <common/debug.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/spm_mm_partition.h>
+
+#include <platform_def.h>
+
+/* Region equivalent to MAP_DEVICE1 suitable for mapping at EL0 */
+#define MAP_DEVICE1_EL0 MAP_REGION_FLAT(DEVICE1_BASE, \
+ DEVICE1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+
+mmap_region_t plat_qemu_secure_partition_mmap[] = {
+ QEMU_SP_IMAGE_NS_BUF_MMAP, /* must be placed at first entry */
+ MAP_DEVICE1_EL0, /* for the UART */
+ QEMU_SP_IMAGE_MMAP,
+ QEMU_SPM_BUF_EL0_MMAP,
+ QEMU_SP_IMAGE_RW_MMAP,
+ MAP_SECURE_VARSTORE,
+ {0}
+};
+
+/* Boot information passed to a secure partition during initialisation. */
+static spm_mm_mp_info_t sp_mp_info[PLATFORM_CORE_COUNT];
+
+spm_mm_boot_info_t plat_qemu_secure_partition_boot_info = {
+ .h.type = PARAM_SP_IMAGE_BOOT_INFO,
+ .h.version = VERSION_1,
+ .h.size = sizeof(spm_mm_boot_info_t),
+ .h.attr = 0,
+ .sp_mem_base = PLAT_QEMU_SP_IMAGE_BASE,
+ .sp_mem_limit = BL32_LIMIT,
+ .sp_image_base = PLAT_QEMU_SP_IMAGE_BASE,
+ .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
+ .sp_heap_base = PLAT_QEMU_SP_IMAGE_HEAP_BASE,
+ .sp_ns_comm_buf_base = PLAT_QEMU_SP_IMAGE_NS_BUF_BASE,
+ .sp_shared_buf_base = PLAT_SPM_BUF_BASE,
+ .sp_image_size = PLAT_QEMU_SP_IMAGE_SIZE,
+ .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+ .sp_heap_size = PLAT_QEMU_SP_IMAGE_HEAP_SIZE,
+ .sp_ns_comm_buf_size = PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE,
+ .sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
+ .num_sp_mem_regions = PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS,
+ .num_cpus = PLATFORM_CORE_COUNT,
+ .mp_info = sp_mp_info
+};
+
+/* Enumeration of priority levels on QEMU platforms. */
+ehf_pri_desc_t qemu_exceptions[] = {
+ EHF_PRI_DESC(QEMU_PRI_BITS, PLAT_SP_PRI)
+};
+
+static void qemu_initialize_mp_info(spm_mm_mp_info_t *mp_info)
+{
+ unsigned int i, j;
+ spm_mm_mp_info_t *tmp = mp_info;
+
+ for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) {
+ for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) {
+ tmp->mpidr = (0x80000000 | (i << MPIDR_AFF1_SHIFT)) + j;
+ /*
+ * Linear indices and flags will be filled
+ * in the spm_mm service.
+ */
+ tmp->linear_id = 0;
+ tmp->flags = 0;
+ tmp++;
+ }
+ }
+}
+
+int dt_add_ns_buf_node(uintptr_t *base)
+{
+ uintptr_t addr;
+ size_t size;
+ uintptr_t ns_buf_addr;
+ int node;
+ int err;
+ void *fdt = (void *)ARM_PRELOADED_DTB_BASE;
+
+ err = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
+ if (err < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", fdt, err);
+ return err;
+ }
+
+ /*
+ * reserved-memory for standaloneMM non-secure buffer
+ * is allocated at the top of the first system memory region.
+ */
+ node = fdt_path_offset(fdt, "/memory");
+
+ err = fdt_get_reg_props_by_index(fdt, node, 0, &addr, &size);
+ if (err < 0) {
+ ERROR("Failed to get the memory node information\n");
+ return err;
+ }
+ INFO("System RAM @ 0x%lx - 0x%lx\n", addr, addr + size - 1);
+
+ ns_buf_addr = addr + (size - PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
+ INFO("reserved-memory for spm-mm @ 0x%lx - 0x%llx\n", ns_buf_addr,
+ ns_buf_addr + PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE - 1);
+
+ err = fdt_add_reserved_memory(fdt, "ns-buf-spm-mm", ns_buf_addr,
+ PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE);
+ if (err < 0) {
+ ERROR("Failed to add the reserved-memory node\n");
+ return err;
+ }
+
+ *base = ns_buf_addr;
+ return 0;
+}
+
+/* Plug in QEMU exceptions to Exception Handling Framework. */
+EHF_REGISTER_PRIORITIES(qemu_exceptions, ARRAY_SIZE(qemu_exceptions),
+ QEMU_PRI_BITS);
+
+const mmap_region_t *plat_get_secure_partition_mmap(void *cookie)
+{
+ uintptr_t ns_buf_base;
+
+ dt_add_ns_buf_node(&ns_buf_base);
+
+ plat_qemu_secure_partition_mmap[0].base_pa = ns_buf_base;
+ plat_qemu_secure_partition_mmap[0].base_va = ns_buf_base;
+ plat_qemu_secure_partition_boot_info.sp_ns_comm_buf_base = ns_buf_base;
+
+ return plat_qemu_secure_partition_mmap;
+}
+
+const spm_mm_boot_info_t *
+plat_get_secure_partition_boot_info(void *cookie)
+{
+ qemu_initialize_mp_info(sp_mp_info);
+
+ return &plat_qemu_secure_partition_boot_info;
+}
diff --git a/plat/qemu/common/qemu_spmd_manifest.c b/plat/qemu/common/qemu_spmd_manifest.c
new file mode 100644
index 0000000..fd46e26
--- /dev/null
+++ b/plat/qemu/common/qemu_spmd_manifest.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <services/spm_core_manifest.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
+ const void *pm_addr)
+{
+ entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+
+ assert(ep_info != NULL);
+ assert(manifest != NULL);
+
+ manifest->major_version = 1;
+ manifest->minor_version = 0;
+ manifest->exec_state = ep_info->args.arg2;
+ manifest->load_address = BL32_BASE;
+ manifest->entrypoint = BL32_BASE;
+ manifest->binary_size = BL32_LIMIT - BL32_BASE;
+ manifest->spmc_id = 0x8000;
+
+ return 0;
+}
diff --git a/plat/qemu/common/qemu_stack_protector.c b/plat/qemu/common/qemu_stack_protector.c
new file mode 100644
index 0000000..15ce3d6
--- /dev/null
+++ b/plat/qemu/common/qemu_stack_protector.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <arch_features.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+#if ENABLE_FEAT_RNG
+ /* Use the RNDR instruction if the CPU supports it */
+ if (is_armv8_5_rng_present()) {
+ return read_rndr();
+ }
+#endif
+
+ /*
+ * Ideally, a random number should be returned above. If a random
+ * number generator is not supported, return instead a
+ * combination of a timer's value and a compile-time constant.
+ * This is better than nothing but not necessarily really secure.
+ */
+ return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
+
diff --git a/plat/qemu/common/qemu_trusted_boot.c b/plat/qemu/common/qemu_trusted_boot.c
new file mode 100644
index 0000000..6a8edca
--- /dev/null
+++ b/plat/qemu/common/qemu_trusted_boot.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char qemu_rotpk_hash[], qemu_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = qemu_rotpk_hash;
+ *key_len = qemu_rotpk_hash_end - qemu_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
diff --git a/plat/qemu/common/sp_min/sp_min-qemu.mk b/plat/qemu/common/sp_min/sp_min-qemu.mk
new file mode 100644
index 0000000..e93a0c2
--- /dev/null
+++ b/plat/qemu/common/sp_min/sp_min-qemu.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_SOURCES += plat/qemu/sp_min/sp_min_setup.c \
+ plat/qemu/aarch32/plat_helpers.S \
+ plat/qemu/qemu_pm.c \
+ plat/qemu/topology.c
+
+BL32_SOURCES += lib/cpus/aarch32/aem_generic.S \
+ lib/cpus/aarch32/cortex_a15.S
+
+BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \
+ plat/common/plat_psci_common.c \
+ plat/common/plat_gicv2.c
+
+
+BL32_SOURCES += drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/arm/gic/common/gic_common.c
diff --git a/plat/qemu/common/sp_min/sp_min_setup.c b/plat/qemu/common/sp_min/sp_min_setup.c
new file mode 100644
index 0000000..7ec657b
--- /dev/null
+++ b/plat/qemu/common/sp_min/sp_min_setup.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+
+#include "../qemu_private.h"
+
+#if RESET_TO_SP_MIN
+#error qemu does not support RESET_TO_SP_MIN
+#endif
+
+static entry_point_info_t bl33_image_ep_info;
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+#define PLATFORM_G1S_PROPS(grp) \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL)
+
+#define PLATFORM_G0_PROPS(grp)
+
+static const interrupt_prop_t stih410_interrupt_props[] = {
+ PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
+ PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const struct gicv2_driver_data plat_gicv2_driver_data = {
+ .gicd_base = GICD_BASE,
+ .gicc_base = GICC_BASE,
+ .interrupt_props = stih410_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(stih410_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+ entry_point_info_t *next_image_info = &bl33_image_ep_info;
+
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
+
+ /* Initialize the console to provide early debug support */
+ qemu_console_init();
+
+ ERROR("qemu sp_min, console init\n");
+ /*
+ * Check params passed from BL2
+ */
+ assert(params_from_bl2);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 entry point information from BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (!bl33_image_ep_info.pc)
+ panic();
+}
+
+void sp_min_plat_arch_setup(void)
+{
+ qemu_configure_mmu_svc_mon(BL32_RO_BASE, BL32_END - BL32_RO_BASE,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END);
+
+}
+
+void sp_min_platform_setup(void)
+{
+ /* Initialize the gic cpu and distributor interfaces */
+ gicv2_driver_init(&plat_gicv2_driver_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+void sp_min_plat_fiq_handler(uint32_t id)
+{
+ VERBOSE("[sp_min] interrupt #%d\n", id);
+}
diff --git a/plat/qemu/common/topology.c b/plat/qemu/common/topology.c
new file mode 100644
index 0000000..6352706
--- /dev/null
+++ b/plat/qemu/common/topology.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+
+#include "qemu_private.h"
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* Number of children for the second node */
+ PLATFORM_CLUSTER1_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return plat_qemu_calc_core_pos(mpidr);
+}
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
new file mode 100644
index 0000000..c9ed640
--- /dev/null
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define QEMU_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define PLATFORM_STACK_SIZE 0x1000
+
+#if ARM_ARCH_MAJOR == 7
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#else
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+/*
+ * Define the number of cores per cluster used in calculating core position.
+ * The cluster number is shifted by this value and added to the core ID,
+ * so its value represents log2(cores/cluster).
+ * Default is 2**(2) = 4 cores per cluster.
+ */
+#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(2)
+
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#endif
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \
+ PLATFORM_CLUSTER1_CORE_COUNT)
+
+#define QEMU_PRIMARY_CPU U(0)
+
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF 2
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH 4
+#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Partition memory into secure ROM, non-secure DRAM, secure "SRAM",
+ * and secure DRAM.
+ */
+#define SEC_ROM_BASE 0x00000000
+#define SEC_ROM_SIZE 0x00020000
+
+#define NS_DRAM0_BASE ULL(0x40000000)
+#define NS_DRAM0_SIZE ULL(0xc0000000)
+
+#define SEC_SRAM_BASE 0x0e000000
+#define SEC_SRAM_SIZE 0x00100000
+
+#define SEC_DRAM_BASE 0x0e100000
+#define SEC_DRAM_SIZE 0x00f00000
+
+#define SECURE_GPIO_BASE 0x090b0000
+#define SECURE_GPIO_SIZE 0x00001000
+#define SECURE_GPIO_POWEROFF 0
+#define SECURE_GPIO_RESET 1
+
+/* Load pageable part of OP-TEE 2MB above secure DRAM base */
+#define QEMU_OPTEE_PAGEABLE_LOAD_BASE (SEC_DRAM_BASE + 0x00200000)
+#define QEMU_OPTEE_PAGEABLE_LOAD_SIZE 0x00400000
+
+/*
+ * ARM-TF lives in SRAM, partition it here
+ */
+
+#define SHARED_RAM_BASE SEC_SRAM_BASE
+#define SHARED_RAM_SIZE 0x00001000
+
+#define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE
+#define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE)
+#define PLAT_QEMU_HOLD_BASE (PLAT_QEMU_TRUSTED_MAILBOX_BASE + 8)
+#define PLAT_QEMU_HOLD_SIZE (PLATFORM_CORE_COUNT * \
+ PLAT_QEMU_HOLD_ENTRY_SIZE)
+#define PLAT_QEMU_HOLD_ENTRY_SHIFT 3
+#define PLAT_QEMU_HOLD_ENTRY_SIZE (1 << PLAT_QEMU_HOLD_ENTRY_SHIFT)
+#define PLAT_QEMU_HOLD_STATE_WAIT 0
+#define PLAT_QEMU_HOLD_STATE_GO 1
+
+#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE)
+#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+
+/*
+ * BL1 specific defines.
+ *
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
+ */
+#define BL1_RO_BASE SEC_ROM_BASE
+#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
+#define BL1_RW_BASE (BL1_RW_LIMIT - 0x12000)
+#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+
+/*
+ * BL2 specific defines.
+ *
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define BL2_BASE (BL31_BASE - 0x25000)
+#define BL2_LIMIT BL31_BASE
+
+/*
+ * BL3-1 specific defines.
+ *
+ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL3-1 debug size plus a little space for growth.
+ */
+#define BL31_BASE (BL31_LIMIT - 0x60000)
+#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+#define BL31_PROGBITS_LIMIT BL1_RW_BASE
+
+
+/*
+ * BL3-2 specific defines.
+ *
+ * BL3-2 can execute from Secure SRAM, or Secure DRAM.
+ */
+#define BL32_SRAM_BASE BL_RAM_BASE
+#define BL32_SRAM_LIMIT BL31_BASE
+#define BL32_DRAM_BASE SEC_DRAM_BASE
+#define BL32_DRAM_LIMIT (SEC_DRAM_BASE + SEC_DRAM_SIZE)
+
+#define SEC_SRAM_ID 0
+#define SEC_DRAM_ID 1
+
+#if BL32_RAM_LOCATION_ID == SEC_SRAM_ID
+# define BL32_MEM_BASE BL_RAM_BASE
+# define BL32_MEM_SIZE BL_RAM_SIZE
+# define BL32_BASE BL32_SRAM_BASE
+# define BL32_LIMIT BL32_SRAM_LIMIT
+#elif BL32_RAM_LOCATION_ID == SEC_DRAM_ID
+# define BL32_MEM_BASE SEC_DRAM_BASE
+# define BL32_MEM_SIZE SEC_DRAM_SIZE
+# define BL32_BASE BL32_DRAM_BASE
+# define BL32_LIMIT BL32_DRAM_LIMIT
+#else
+# error "Unsupported BL32_RAM_LOCATION_ID value"
+#endif
+
+#define NS_IMAGE_OFFSET (NS_DRAM0_BASE + 0x20000000)
+#define NS_IMAGE_MAX_SIZE (NS_DRAM0_SIZE - 0x20000000)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_MMAP_REGIONS 11
+#define MAX_XLAT_TABLES 6
+#define MAX_IO_DEVICES 4
+#define MAX_IO_HANDLES 4
+
+/*
+ * PL011 related constants
+ */
+#define UART0_BASE 0x09000000
+#define UART1_BASE 0x09040000
+#define UART0_CLK_IN_HZ 1
+#define UART1_CLK_IN_HZ 1
+
+#define PLAT_QEMU_BOOT_UART_BASE UART0_BASE
+#define PLAT_QEMU_BOOT_UART_CLK_IN_HZ UART0_CLK_IN_HZ
+
+#define PLAT_QEMU_CRASH_UART_BASE UART1_BASE
+#define PLAT_QEMU_CRASH_UART_CLK_IN_HZ UART1_CLK_IN_HZ
+
+#define PLAT_QEMU_CONSOLE_BAUDRATE 115200
+
+#define QEMU_FLASH0_BASE 0x00000000
+#define QEMU_FLASH0_SIZE 0x04000000
+#define QEMU_FLASH1_BASE 0x04000000
+#define QEMU_FLASH1_SIZE 0x04000000
+
+#define PLAT_QEMU_FIP_BASE 0x00040000
+#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000
+
+#define DEVICE0_BASE 0x08000000
+#define DEVICE0_SIZE 0x01000000
+#define DEVICE1_BASE 0x09000000
+#define DEVICE1_SIZE 0x00c00000
+
+/*
+ * GIC related constants
+ */
+
+#define GICD_BASE 0x8000000
+#define GICC_BASE 0x8010000
+#define GICR_BASE 0x80A0000
+
+
+#define QEMU_IRQ_SEC_SGI_0 8
+#define QEMU_IRQ_SEC_SGI_1 9
+#define QEMU_IRQ_SEC_SGI_2 10
+#define QEMU_IRQ_SEC_SGI_3 11
+#define QEMU_IRQ_SEC_SGI_4 12
+#define QEMU_IRQ_SEC_SGI_5 13
+#define QEMU_IRQ_SEC_SGI_6 14
+#define QEMU_IRQ_SEC_SGI_7 15
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+#define PLATFORM_G1S_PROPS(grp) \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp)
+
+/*
+ * DT related constants
+ */
+#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE
+#define PLAT_QEMU_DT_MAX_SIZE 0x100000
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16)
+
+/*
+ * Maximum size of Event Log buffer used in Measured Boot Event Log driver
+ */
+#define PLAT_EVENT_LOG_MAX_SIZE UL(0x400)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
new file mode 100644
index 0000000..6becc32
--- /dev/null
+++ b/plat/qemu/qemu/platform.mk
@@ -0,0 +1,266 @@
+#
+# Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Use the GICv2 driver on QEMU by default
+QEMU_USE_GIC_DRIVER := QEMU_GICV2
+
+ifeq (${ARM_ARCH_MAJOR},7)
+# ARMv7 Qemu support in trusted firmware expects the Cortex-A15 model.
+# Qemu Cortex-A15 model does not implement the virtualization extension.
+# For this reason, we cannot set ARM_CORTEX_A15=yes and must define all
+# the ARMv7 build directives.
+MARCH32_DIRECTIVE := -mcpu=cortex-a15
+$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING))
+$(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER))
+$(eval $(call add_define,ARMV7_SUPPORTS_VFP))
+# Qemu expects a BL32 boot stage.
+NEED_BL32 := yes
+endif # ARMv7
+
+ifeq (${SPD},opteed)
+add-lib-optee := yes
+endif
+ifeq ($(AARCH32_SP),optee)
+add-lib-optee := yes
+endif
+ifeq ($(SPMC_OPTEE),1)
+$(eval $(call add_define,SPMC_OPTEE))
+add-lib-optee := yes
+endif
+
+include lib/libfdt/libfdt.mk
+
+ifeq ($(NEED_BL32),yes)
+$(eval $(call add_define,QEMU_LOAD_BL32))
+endif
+
+PLAT_QEMU_PATH := plat/qemu/qemu
+PLAT_QEMU_COMMON_PATH := plat/qemu/common
+PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
+ -I${PLAT_QEMU_COMMON_PATH}/include \
+ -I${PLAT_QEMU_PATH}/include \
+ -Iinclude/common/tbbr
+
+ifeq (${ARM_ARCH_MAJOR},8)
+PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH}
+endif
+
+PLAT_BL_COMMON_SOURCES := ${PLAT_QEMU_COMMON_PATH}/qemu_common.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_console.c \
+ drivers/arm/pl011/${ARCH}/pl011_console.S
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+ AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c
+
+ BL1_SOURCES += ${AUTH_SOURCES} \
+ bl1/tbbr/tbbr_img_desc.c \
+ plat/common/tbbr/plat_tbbr.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \
+ $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl1.c
+
+ BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c \
+ $(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+ include drivers/auth/mbedtls/mbedtls_x509.mk
+
+ ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+ $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+
+ $(BUILD_PLAT)/bl1/qemu_rotpk.o: $(ROTPK_HASH)
+ $(BUILD_PLAT)/bl2/qemu_rotpk.o: $(ROTPK_HASH)
+
+ certificates: $(ROT_KEY)
+
+ $(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
+
+ $(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
+
+# Include Measured Boot makefile before any Crypto library makefile.
+# Crypto library makefile may need default definitions of Measured Boot build
+# flags present in Measured Boot makefile.
+ifeq (${MEASURED_BOOT},1)
+ MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk
+ $(info Including ${MEASURED_BOOT_MK})
+ include ${MEASURED_BOOT_MK}
+
+ ifneq (${MBOOT_EL_HASH_ALG}, sha256)
+ $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
+ endif
+
+ BL2_SOURCES += plat/qemu/qemu/qemu_measured_boot.c \
+ plat/qemu/qemu/qemu_common_measured_boot.c \
+ plat/qemu/qemu/qemu_helpers.c \
+ ${EVENT_LOG_SOURCES}
+
+ BL1_SOURCES += plat/qemu/qemu/qemu_bl1_measured_boot.c
+
+endif
+
+ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),)
+ CRYPTO_SOURCES := drivers/auth/crypto_mod.c
+
+ BL1_SOURCES += ${CRYPTO_SOURCES}
+ BL2_SOURCES += ${CRYPTO_SOURCES}
+
+ # We expect to locate the *.mk files under the directories specified below
+ #
+ include drivers/auth/mbedtls/mbedtls_crypto.mk
+endif
+
+BL1_SOURCES += drivers/io/io_semihosting.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
+ ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c
+
+ifeq (${ARM_ARCH_MAJOR},8)
+BL1_SOURCES += lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/cpus/aarch64/qemu_max.S \
+
+else
+BL1_SOURCES += lib/cpus/${ARCH}/cortex_a15.S
+endif
+
+BL2_SOURCES += drivers/io/io_semihosting.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
+ ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_setup.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_image_load.c \
+ common/fdt_fixup.c \
+ common/fdt_wrappers.c \
+ common/desc_image_load.c
+
+ifeq ($(add-lib-optee),yes)
+BL2_SOURCES += lib/optee/optee_utils.c
+endif
+
+ifneq (${DECRYPTION_SUPPORT},none)
+BL1_SOURCES += drivers/io/io_encrypted.c
+BL2_SOURCES += drivers/io/io_encrypted.c
+endif
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+QEMU_GICV2_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_gicv2.c
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+QEMU_GICV3_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c
+
+ifeq (${QEMU_USE_GIC_DRIVER}, QEMU_GICV2)
+QEMU_GIC_SOURCES := ${QEMU_GICV2_SOURCES}
+else ifeq (${QEMU_USE_GIC_DRIVER}, QEMU_GICV3)
+QEMU_GIC_SOURCES := ${QEMU_GICV3_SOURCES}
+else
+$(error "Incorrect GIC driver chosen for QEMU platform")
+endif
+
+ifeq (${ARM_ARCH_MAJOR},8)
+BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/cpus/aarch64/qemu_max.S \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ plat/common/plat_psci_common.c \
+ drivers/arm/pl061/pl061_gpio.c \
+ drivers/gpio/gpio.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_pm.c \
+ ${PLAT_QEMU_COMMON_PATH}/topology.c \
+ ${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \
+ ${QEMU_GIC_SOURCES}
+
+ifeq (${SPD},spmd)
+BL31_SOURCES += plat/qemu/common/qemu_spmd_manifest.c
+endif
+endif
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+ifneq (${DECRYPTION_SUPPORT},none)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
+else
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+endif
+ifneq ($(BL32_EXTRA2),)
+ifneq (${DECRYPTION_SUPPORT},none)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
+else
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+endif
+
+SEPARATE_CODE_AND_RODATA := 1
+ENABLE_STACK_PROTECTOR := 0
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+ PLAT_BL_COMMON_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_stack_protector.c
+endif
+
+BL32_RAM_LOCATION := tdram
+ifeq (${BL32_RAM_LOCATION}, tsram)
+ BL32_RAM_LOCATION_ID = SEC_SRAM_ID
+else ifeq (${BL32_RAM_LOCATION}, tdram)
+ BL32_RAM_LOCATION_ID = SEC_DRAM_ID
+else
+ $(error "Unsupported BL32_RAM_LOCATION value")
+endif
+
+# Process flags
+$(eval $(call add_define,BL32_RAM_LOCATION_ID))
+
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33 := 0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
+
+ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE
+$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
+# Later QEMU versions support SME and SVE.
+ifneq (${ARCH},aarch32)
+ ENABLE_SVE_FOR_NS := 1
+ ENABLE_SME_FOR_NS := 1
+endif
diff --git a/plat/qemu/qemu/qemu_bl1_measured_boot.c b/plat/qemu/qemu/qemu_bl1_measured_boot.c
new file mode 100644
index 0000000..3d20f97
--- /dev/null
+++ b/plat/qemu/qemu/qemu_bl1_measured_boot.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Linaro.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <common/desc_image_load.h>
+
+/*
+ * Add dummy functions for measured boot for BL1.
+ * In most of the SoC's, ROM/BL1 code is pre-built. So we are assumimg that
+ * it doesn't have the capability to do measurements and extend eventlog.
+ * hence these are dummy functions.
+ */
+void bl1_plat_mboot_init(void)
+{
+}
+
+void bl1_plat_mboot_finish(void)
+{
+}
+
+int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
+{
+ return 0;
+}
diff --git a/plat/qemu/qemu/qemu_common_measured_boot.c b/plat/qemu/qemu/qemu_common_measured_boot.c
new file mode 100644
index 0000000..41f7f87
--- /dev/null
+++ b/plat/qemu/qemu/qemu_common_measured_boot.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, Linaro.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/desc_image_load.h>
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <plat/common/platform.h>
+
+extern event_log_metadata_t qemu_event_log_metadata[];
+
+const event_log_metadata_t *plat_event_log_get_metadata(void)
+{
+ return qemu_event_log_metadata;
+}
+
+int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
+{
+ /* Calculate image hash and record data in Event Log */
+ int err = event_log_measure_and_record(image_data->image_base,
+ image_data->image_size,
+ image_id);
+ if (err != 0) {
+ ERROR("%s%s image id %u (%i)\n",
+ "Failed to ", "record", image_id, err);
+ return err;
+ }
+
+ return 0;
+}
diff --git a/plat/qemu/qemu/qemu_helpers.c b/plat/qemu/qemu/qemu_helpers.c
new file mode 100644
index 0000000..1b31ab5
--- /dev/null
+++ b/plat/qemu/qemu/qemu_helpers.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2022, Linaro.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#if MEASURED_BOOT
+#include <common/desc_image_load.h>
+#endif
+#include <common/fdt_wrappers.h>
+#include <platform_def.h>
+
+#include <libfdt.h>
+
+#ifdef SPD_opteed
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this property should be removed when this feature is supported.
+ */
+#define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr"
+#endif
+
+#define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr"
+#define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size"
+
+#if MEASURED_BOOT
+
+#ifdef SPD_opteed
+int qemu_set_tee_fw_info(uintptr_t config_base, uintptr_t log_addr,
+ size_t log_size)
+{
+ int offs, err = 0;
+ void *dtb = (void *)config_base;
+ const char *compatible = "arm,tpm_event_log";
+ uint64_t sec_base = cpu_to_fdt64(log_addr);
+ uint32_t sz = cpu_to_fdt32(log_size);
+
+ offs = fdtw_find_or_add_subnode(dtb, 0, "tpm-event-log");
+ if (offs < 0) {
+ ERROR("Failed to add node tpm-event-log %d\n", offs);
+ return offs;
+ }
+
+ if (fdt_appendprop(dtb, offs, "compatible", compatible,
+ strlen(compatible) + 1) < 0) {
+ return -1;
+ }
+
+ err = fdt_setprop(dtb, offs, DTB_PROP_HW_SM_LOG_ADDR, &sec_base, 8);
+ if (err < 0) {
+ ERROR("Failed to add log addr err %d\n", err);
+ return err;
+ }
+
+ err = fdt_setprop(dtb, offs, DTB_PROP_HW_LOG_SIZE, &sz, 4);
+ if (err < 0) {
+ ERROR("Failed to add log addr err %d\n", err);
+ return err;
+ }
+
+ return err;
+}
+#endif
+
+/*
+ * Write the Event Log address and its size in the DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+static int qemu_set_event_log_info(uintptr_t config_base,
+#ifdef SPD_opteed
+ uintptr_t sm_log_addr,
+#endif
+ uintptr_t log_addr, size_t log_size)
+{
+ /* As libfdt uses void *, we can't avoid this cast */
+ void *dtb = (void *)config_base;
+ const char *compatible_tpm = "tcg,tpm-tis-mmio";
+ uint64_t base = cpu_to_fdt64(log_addr);
+ uint32_t sz = cpu_to_fdt32(log_size);
+ int err, node;
+
+ err = fdt_open_into(dtb, dtb, PLAT_QEMU_DT_MAX_SIZE);
+ if (err < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
+ return err;
+ }
+
+ /*
+ * Verify that the DTB is valid, before attempting to write to it,
+ * and get the DTB root node.
+ */
+
+ /* Check if the pointer to DT is correct */
+ err = fdt_check_header(dtb);
+ if (err < 0) {
+ WARN("Invalid DTB file passed\n");
+ return err;
+ }
+
+ /*
+ * Find the TPM node in device tree. On qemu, we assume it will
+ * be sw-tpm.
+ */
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_tpm);
+ if (node < 0) {
+ ERROR("The compatible property '%s' not%s", compatible_tpm,
+ " found in the config\n");
+ return node;
+ }
+
+ err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_ADDR, &base, 8);
+ if (err < 0) {
+ ERROR("Failed to add log addr err %d\n", err);
+ return err;
+ }
+
+ err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_SIZE, &sz, 4);
+ if (err < 0) {
+ ERROR("Failed to add log addr err %d\n", err);
+ return err;
+ }
+
+#ifdef SPD_opteed
+ err = qemu_set_tee_fw_info(config_base, sm_log_addr, log_size);
+ if (err < 0) {
+ ERROR("Failed to add tpm-event-node at %p: err %d\n", dtb, err);
+ return err;
+ }
+#endif
+
+ err = fdt_pack(dtb);
+ if (err < 0) {
+ ERROR("Failed to pack Device Tree at %p: err %d\n", dtb, err);
+ return err;
+ }
+
+ /*
+ * Ensure that the info written to the DTB is visible
+ * to other images.
+ */
+ flush_dcache_range(config_base, fdt_totalsize(dtb));
+
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the TOS_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int qemu_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+ size_t log_size)
+{
+ int err = 0;
+
+ assert(config_base != 0UL);
+ assert(log_addr != 0UL);
+
+ /*
+ * FIXME - add code to add/update Log address and it's
+ * size in TOS FW CONFIG.
+ * For now we don't have support for TOS FW config in OP-TEE.
+ * So leave this function blank
+ */
+
+ return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the QEMU DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ * 0 = success
+ * < 0 = error
+ */
+int qemu_set_nt_fw_info(
+#ifdef SPD_opteed
+ uintptr_t log_addr,
+#endif
+ size_t log_size, uintptr_t *ns_log_addr)
+{
+ uintptr_t ns_addr;
+ int err;
+
+ assert(ns_log_addr != NULL);
+
+ ns_addr = PLAT_QEMU_DT_BASE + PLAT_QEMU_DT_MAX_SIZE;
+
+ /* Write the Event Log address and its size in the DTB */
+ err = qemu_set_event_log_info(PLAT_QEMU_DT_BASE,
+#ifdef SPD_opteed
+ log_addr,
+#endif
+ ns_addr, log_size);
+
+ /* Return Event Log address in Non-secure memory */
+ *ns_log_addr = (err < 0) ? 0UL : ns_addr;
+ return err;
+}
+#endif /* MEASURED_BOOT */
diff --git a/plat/qemu/qemu/qemu_measured_boot.c b/plat/qemu/qemu/qemu_measured_boot.c
new file mode 100644
index 0000000..d9e475a
--- /dev/null
+++ b/plat/qemu/qemu/qemu_measured_boot.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Linaro.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log/event_log.h>
+#include <plat/common/common_def.h>
+#include <tools_share/tbbr_oid.h>
+
+#include "../common/qemu_private.h"
+
+/* Event Log data */
+static uint8_t event_log[PLAT_EVENT_LOG_MAX_SIZE];
+static uint64_t event_log_base;
+
+/* FVP table with platform specific image IDs, names and PCRs */
+const event_log_metadata_t qemu_event_log_metadata[] = {
+ { BL31_IMAGE_ID, EVLOG_BL31_STRING, PCR_0 },
+ { BL32_IMAGE_ID, EVLOG_BL32_STRING, PCR_0 },
+ { BL32_EXTRA1_IMAGE_ID, EVLOG_BL32_EXTRA1_STRING, PCR_0 },
+ { BL32_EXTRA2_IMAGE_ID, EVLOG_BL32_EXTRA2_STRING, PCR_0 },
+ { BL33_IMAGE_ID, EVLOG_BL33_STRING, PCR_0 },
+ { HW_CONFIG_ID, EVLOG_HW_CONFIG_STRING, PCR_0 },
+ { NT_FW_CONFIG_ID, EVLOG_NT_FW_CONFIG_STRING, PCR_0 },
+ { SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 },
+ { SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 },
+ { TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 },
+
+ { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
+};
+
+void bl2_plat_mboot_init(void)
+{
+ /*
+ * Here we assume that BL1/ROM code doesn't have the driver
+ * to measure the BL2 code which is a common case for
+ * already existing platforms
+ */
+ event_log_init(event_log, event_log + sizeof(event_log));
+ event_log_write_header();
+
+ /*
+ * TBD - Add code to do self measurement of BL2 code and add an
+ * event for BL2 measurement
+ */
+
+ event_log_base = (uintptr_t)event_log;
+}
+
+void bl2_plat_mboot_finish(void)
+{
+ int rc;
+
+ /* Event Log address in Non-Secure memory */
+ uintptr_t ns_log_addr;
+
+ /* Event Log filled size */
+ size_t event_log_cur_size;
+
+ event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
+
+ rc = qemu_set_nt_fw_info(
+#ifdef SPD_opteed
+ (uintptr_t)event_log_base,
+#endif
+ event_log_cur_size, &ns_log_addr);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "NT");
+ /*
+ * It is a fatal error because on QEMU secure world software
+ * assumes that a valid event log exists and will use it to
+ * record the measurements into the fTPM or sw-tpm.
+ * Note: In QEMU platform, OP-TEE uses nt_fw_config to get the
+ * secure Event Log buffer address.
+ */
+ panic();
+ }
+
+ /* Copy Event Log to Non-secure memory */
+ (void)memcpy((void *)ns_log_addr, (const void *)event_log_base,
+ event_log_cur_size);
+
+ /* Ensure that the Event Log is visible in Non-secure memory */
+ flush_dcache_range(ns_log_addr, event_log_cur_size);
+
+#if defined(SPD_tspd) || defined(SPD_spmd)
+ /* Set Event Log data in TOS_FW_CONFIG */
+ rc = qemu_set_tos_fw_info((uintptr_t)event_log_base,
+ event_log_cur_size);
+ if (rc != 0) {
+ ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+ __func__, "TOS");
+ panic();
+ }
+#endif /* defined(SPD_tspd) || defined(SPD_spmd) */
+
+ dump_event_log((uint8_t *)event_log_base, event_log_cur_size);
+}
diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h
new file mode 100644
index 0000000..d971ebe
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/include/platform_def.h
@@ -0,0 +1,378 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2019-2020, Linaro Limited and Contributors.
+ * All rights reserved.
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <plat/common/common_def.h>
+#include <tbbr_img_def.h>
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define QEMU_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define PLATFORM_STACK_SIZE 0x1000
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8)
+/*
+ * Define the number of cores per cluster used in calculating core position.
+ * The cluster number is shifted by this value and added to the core ID,
+ * so its value represents log2(cores/cluster).
+ * Default is 2**(3) = 8 cores per cluster.
+ */
+#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(3)
+#define PLATFORM_CLUSTER_COUNT U(64)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
+ PLATFORM_MAX_CPUS_PER_CLUSTER)
+#define QEMU_PRIMARY_CPU U(0)
+
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+
+#define PLAT_MAX_RET_STATE 1
+#define PLAT_MAX_OFF_STATE 2
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN 0
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET 1
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF 2
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH 4
+#define PLAT_LOCAL_PSTATE_MASK ((1 << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Partition memory into secure ROM, non-secure DRAM, secure "SRAM",
+ * and secure DRAM.
+ */
+#define SEC_ROM_BASE 0x00000000
+#define SEC_ROM_SIZE 0x00020000
+
+#define NS_DRAM0_BASE 0x10000000000ULL
+#define NS_DRAM0_SIZE 0x00020000000
+
+#define SEC_SRAM_BASE 0x20000000
+#define SEC_SRAM_SIZE 0x20000000
+
+/*
+ * RAD just placeholders, need to be chosen after finalizing mem map
+ */
+#define SEC_DRAM_BASE 0x1000
+#define SEC_DRAM_SIZE 0x1000
+
+/* Load pageable part of OP-TEE 2MB above secure DRAM base */
+#define QEMU_OPTEE_PAGEABLE_LOAD_BASE (SEC_DRAM_BASE + 0x00200000)
+#define QEMU_OPTEE_PAGEABLE_LOAD_SIZE 0x00400000
+
+/*
+ * ARM-TF lives in SRAM, partition it here
+ */
+
+#define SHARED_RAM_BASE SEC_SRAM_BASE
+#define SHARED_RAM_SIZE 0x00002000
+
+#define PLAT_QEMU_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE
+#define PLAT_QEMU_TRUSTED_MAILBOX_SIZE (8 + PLAT_QEMU_HOLD_SIZE)
+#define PLAT_QEMU_HOLD_BASE (PLAT_QEMU_TRUSTED_MAILBOX_BASE + 8)
+#define PLAT_QEMU_HOLD_SIZE (PLATFORM_CORE_COUNT * \
+ PLAT_QEMU_HOLD_ENTRY_SIZE)
+#define PLAT_QEMU_HOLD_ENTRY_SHIFT 3
+#define PLAT_QEMU_HOLD_ENTRY_SIZE (1 << PLAT_QEMU_HOLD_ENTRY_SHIFT)
+#define PLAT_QEMU_HOLD_STATE_WAIT 0
+#define PLAT_QEMU_HOLD_STATE_GO 1
+
+#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE)
+#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+
+/*
+ * BL1 specific defines.
+ *
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
+ */
+#define BL1_SIZE 0x12000
+#define BL1_RO_BASE SEC_ROM_BASE
+#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
+#define BL1_RW_BASE (BL1_RW_LIMIT - BL1_SIZE)
+#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+
+/*
+ * BL2 specific defines.
+ *
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define BL2_SIZE 0x1D000
+#define BL2_BASE (BL31_BASE - BL2_SIZE)
+#define BL2_LIMIT BL31_BASE
+
+/*
+ * BL3-1 specific defines.
+ *
+ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL3-1 debug size plus a little space for growth.
+ */
+#define BL31_SIZE 0x300000
+#define BL31_BASE (BL31_LIMIT - BL31_SIZE)
+#define BL31_LIMIT (BL1_RW_BASE)
+#define BL31_PROGBITS_LIMIT BL1_RW_BASE
+
+
+/*
+ * BL3-2 specific defines.
+ *
+ * BL3-2 can execute from Secure SRAM, or Secure DRAM.
+ */
+#define BL32_SRAM_BASE BL_RAM_BASE
+#define BL32_SRAM_LIMIT BL2_BASE
+
+#define BL32_MEM_BASE BL_RAM_BASE
+#define BL32_MEM_SIZE (BL_RAM_SIZE - BL1_SIZE - \
+ BL2_SIZE - BL31_SIZE)
+#define BL32_BASE BL32_SRAM_BASE
+#define BL32_LIMIT BL32_SRAM_LIMIT
+
+#define NS_IMAGE_OFFSET (NS_DRAM0_BASE + 0x20000000)
+#define NS_IMAGE_MAX_SIZE (NS_DRAM0_SIZE - 0x20000000)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 42)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 42)
+#if SPM_MM
+#define MAX_MMAP_REGIONS 12
+#define MAX_XLAT_TABLES 12
+#else
+#define MAX_MMAP_REGIONS 11
+#define MAX_XLAT_TABLES 11
+#endif
+#define MAX_IO_DEVICES 3
+#define MAX_IO_HANDLES 4
+
+#if SPM_MM && defined(IMAGE_BL31)
+# define PLAT_SP_IMAGE_MMAP_REGIONS 30
+# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 50
+#endif
+
+/*
+ * PL011 related constants
+ */
+#define UART0_BASE 0x60000000
+#define UART1_BASE 0x60030000
+#define UART0_CLK_IN_HZ 1
+#define UART1_CLK_IN_HZ 1
+
+/* Secure UART */
+#define UART2_BASE 0x60040000
+#define UART2_CLK_IN_HZ 1
+
+#define PLAT_QEMU_BOOT_UART_BASE UART0_BASE
+#define PLAT_QEMU_BOOT_UART_CLK_IN_HZ UART0_CLK_IN_HZ
+
+#define PLAT_QEMU_CRASH_UART_BASE UART1_BASE
+#define PLAT_QEMU_CRASH_UART_CLK_IN_HZ UART1_CLK_IN_HZ
+
+#define PLAT_QEMU_CONSOLE_BAUDRATE 115200
+
+#define QEMU_FLASH0_BASE 0x00000000
+#define QEMU_FLASH0_SIZE 0x10000000
+#define QEMU_FLASH1_BASE 0x10000000
+#define QEMU_FLASH1_SIZE 0x10000000
+
+#define PLAT_QEMU_FIP_BASE 0x00008000
+#define PLAT_QEMU_FIP_MAX_SIZE 0x00400000
+
+/* This is map from GIC_DIST up to last CPU (255) GIC_REDISTR */
+#define DEVICE0_BASE 0x40000000
+#define DEVICE0_SIZE 0x04080000
+/* This is map from NORMAL_UART up to SECURE_UART_MM */
+#define DEVICE1_BASE 0x60000000
+#define DEVICE1_SIZE 0x10041000
+/* This is a map for SECURE_EC */
+#define DEVICE2_BASE 0x50000000
+#define DEVICE2_SIZE 0x00001000
+
+/*
+ * GIC related constants
+ * We use GICv3 where CPU Interface registers are not memory mapped
+ */
+#define GICD_BASE 0x40060000
+#define GICR_BASE 0x40080000
+#define GICC_BASE 0x0
+
+#define QEMU_IRQ_SEC_SGI_0 8
+#define QEMU_IRQ_SEC_SGI_1 9
+#define QEMU_IRQ_SEC_SGI_2 10
+#define QEMU_IRQ_SEC_SGI_3 11
+#define QEMU_IRQ_SEC_SGI_4 12
+#define QEMU_IRQ_SEC_SGI_5 13
+#define QEMU_IRQ_SEC_SGI_6 14
+#define QEMU_IRQ_SEC_SGI_7 15
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+#define PLATFORM_G1S_PROPS(grp) \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp)
+
+/*
+ * DT related constants
+ */
+#define PLAT_QEMU_DT_BASE NS_DRAM0_BASE
+#define PLAT_QEMU_DT_MAX_SIZE 0x100000
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS ((1000 * 1000 * 1000) / 16)
+
+#if SPM_MM
+#define PLAT_QEMU_SP_IMAGE_BASE BL_RAM_BASE
+#define PLAT_QEMU_SP_IMAGE_SIZE ULL(0x300000)
+
+#ifdef IMAGE_BL2
+/* In BL2 all memory allocated to the SPM Payload image is marked as RW. */
+# define QEMU_SP_IMAGE_MMAP MAP_REGION_FLAT( \
+ PLAT_QEMU_SP_IMAGE_BASE, \
+ PLAT_QEMU_SP_IMAGE_SIZE, \
+ MT_MEMORY | MT_RW | \
+ MT_SECURE)
+#elif IMAGE_BL31
+/* All SPM Payload memory is marked as code in S-EL0 */
+# define QEMU_SP_IMAGE_MMAP MAP_REGION2(PLAT_QEMU_SP_IMAGE_BASE, \
+ PLAT_QEMU_SP_IMAGE_BASE, \
+ PLAT_QEMU_SP_IMAGE_SIZE, \
+ MT_CODE | MT_SECURE | \
+ MT_USER, \
+ PAGE_SIZE)
+#endif
+
+/*
+ * EL3 -> S-EL0 secure shared memory
+ */
+#define PLAT_SPM_BUF_PCPU_SIZE ULL(0x10000)
+#define PLAT_SPM_BUF_SIZE (PLATFORM_CORE_COUNT * \
+ PLAT_SPM_BUF_PCPU_SIZE)
+#define PLAT_SPM_BUF_BASE (BL32_LIMIT - PLAT_SPM_BUF_SIZE)
+
+#define QEMU_SPM_BUF_EL3_MMAP MAP_REGION_FLAT(PLAT_SPM_BUF_BASE, \
+ PLAT_SPM_BUF_SIZE, \
+ MT_RW_DATA | MT_SECURE)
+
+#define QEMU_SPM_BUF_EL0_MMAP MAP_REGION2(PLAT_SPM_BUF_BASE, \
+ PLAT_SPM_BUF_BASE, \
+ PLAT_SPM_BUF_SIZE, \
+ MT_RO_DATA | MT_SECURE | \
+ MT_USER, \
+ PAGE_SIZE)
+
+/*
+ * Shared memory between Normal world and S-EL0 for
+ * passing data during service requests. It will be marked as RW and NS.
+ * This buffer is allocated at the top of NS_DRAM, the base address is
+ * overridden in SPM initialization.
+ */
+#define PLAT_QEMU_SP_IMAGE_NS_BUF_BASE (PLAT_QEMU_DT_BASE + \
+ PLAT_QEMU_DT_MAX_SIZE)
+#define PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE ULL(0x200000)
+
+#define QEMU_SP_IMAGE_NS_BUF_MMAP MAP_REGION2( \
+ PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
+ PLAT_QEMU_SP_IMAGE_NS_BUF_BASE, \
+ PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE, \
+ MT_RW_DATA | MT_NS | \
+ MT_USER, \
+ PAGE_SIZE)
+
+#define PLAT_SP_IMAGE_NS_BUF_BASE PLAT_QEMU_SP_IMAGE_NS_BUF_BASE
+#define PLAT_SP_IMAGE_NS_BUF_SIZE PLAT_QEMU_SP_IMAGE_NS_BUF_SIZE
+
+#define PLAT_QEMU_SP_IMAGE_HEAP_BASE (PLAT_QEMU_SP_IMAGE_BASE + \
+ PLAT_QEMU_SP_IMAGE_SIZE)
+#define PLAT_QEMU_SP_IMAGE_HEAP_SIZE ULL(0x800000)
+
+#define PLAT_SP_IMAGE_STACK_BASE (PLAT_QEMU_SP_IMAGE_HEAP_BASE + \
+ PLAT_QEMU_SP_IMAGE_HEAP_SIZE)
+#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x10000)
+#define QEMU_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \
+ PLAT_SP_IMAGE_STACK_PCPU_SIZE)
+
+#define QEMU_SP_IMAGE_RW_MMAP MAP_REGION2( \
+ PLAT_QEMU_SP_IMAGE_HEAP_BASE, \
+ PLAT_QEMU_SP_IMAGE_HEAP_BASE, \
+ (QEMU_SP_IMAGE_STACK_TOTAL_SIZE + \
+ PLAT_QEMU_SP_IMAGE_HEAP_SIZE), \
+ MT_RW_DATA | MT_SECURE | \
+ MT_USER, \
+ PAGE_SIZE)
+
+/*
+ * Secure variable storage is located at Secure Flash.
+ */
+#if SPM_MM
+#define QEMU_SECURE_VARSTORE_BASE 0x01000000
+#define QEMU_SECURE_VARSTORE_SIZE 0x00100000
+#define MAP_SECURE_VARSTORE MAP_REGION_FLAT( \
+ QEMU_SECURE_VARSTORE_BASE, \
+ QEMU_SECURE_VARSTORE_SIZE, \
+ MT_DEVICE | MT_RW | \
+ MT_SECURE | MT_USER)
+#endif
+
+/* Total number of memory regions with distinct properties */
+#define PLAT_QEMU_SP_IMAGE_NUM_MEM_REGIONS 6
+
+/*
+ * Name of the section to put the translation tables used by the S-EL1/S-EL0
+ * context of a Secure Partition.
+ */
+#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "qemu_sp_xlat_table"
+#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME "qemu_sp_xlat_table"
+
+/* Cookies passed to the Secure Partition at boot. Not used by QEMU platforms.*/
+#define PLAT_SPM_COOKIE_0 ULL(0)
+#define PLAT_SPM_COOKIE_1 ULL(0)
+#endif
+
+#define QEMU_PRI_BITS 2
+#define PLAT_SP_PRI 0x20
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qemu/qemu_sbsa/platform.mk b/plat/qemu/qemu_sbsa/platform.mk
new file mode 100644
index 0000000..5a6b1e1
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/platform.mk
@@ -0,0 +1,127 @@
+#
+# Copyright (c) 2019-2021, Linaro Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include common/fdt_wrappers.mk
+
+CRASH_REPORTING := 1
+
+include lib/libfdt/libfdt.mk
+
+ifeq (${SPM_MM},1)
+NEED_BL32 := yes
+EL3_EXCEPTION_HANDLING := 1
+GICV2_G0_FOR_EL3 := 1
+endif
+
+# Enable new version of image loading on QEMU platforms
+LOAD_IMAGE_V2 := 1
+
+ifeq ($(NEED_BL32),yes)
+$(eval $(call add_define,QEMU_LOAD_BL32))
+endif
+
+PLAT_QEMU_PATH := plat/qemu/qemu_sbsa
+PLAT_QEMU_COMMON_PATH := plat/qemu/common
+PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
+ -I${PLAT_QEMU_COMMON_PATH}/include \
+ -I${PLAT_QEMU_PATH}/include \
+ -Iinclude/common/tbbr
+
+PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH}
+
+PLAT_BL_COMMON_SOURCES := ${PLAT_QEMU_COMMON_PATH}/qemu_common.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_console.c \
+ drivers/arm/pl011/${ARCH}/pl011_console.S
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+BL1_SOURCES += drivers/io/io_semihosting.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
+ ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_bl1_setup.c
+
+BL1_SOURCES += lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/cpus/aarch64/qemu_max.S \
+
+BL2_SOURCES += drivers/io/io_semihosting.c \
+ drivers/io/io_storage.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_io_storage.c \
+ ${PLAT_QEMU_COMMON_PATH}/${ARCH}/plat_helpers.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_setup.c \
+ common/fdt_fixup.c \
+ $(LIBFDT_SRCS)
+ifeq (${LOAD_IMAGE_V2},1)
+BL2_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_bl2_mem_params_desc.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_image_load.c \
+ common/desc_image_load.c
+endif
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+QEMU_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_gicv3.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a57.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ lib/cpus/aarch64/qemu_max.S \
+ lib/semihosting/semihosting.c \
+ lib/semihosting/${ARCH}/semihosting_call.S \
+ plat/common/plat_psci_common.c \
+ ${PLAT_QEMU_PATH}/sbsa_pm.c \
+ ${PLAT_QEMU_PATH}/sbsa_topology.c \
+ ${PLAT_QEMU_COMMON_PATH}/aarch64/plat_helpers.S \
+ ${PLAT_QEMU_COMMON_PATH}/qemu_bl31_setup.c \
+ common/fdt_fixup.c \
+ ${QEMU_GIC_SOURCES}
+
+BL31_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+ifeq (${SPM_MM},1)
+ BL31_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_spm.c
+endif
+
+SEPARATE_CODE_AND_RODATA := 1
+ENABLE_STACK_PROTECTOR := 0
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+ PLAT_BL_COMMON_SOURCES += ${PLAT_QEMU_COMMON_PATH}/qemu_stack_protector.c
+endif
+
+MULTI_CONSOLE_API := 1
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT := 0
+
+# Use known base for UEFI if not given from command line
+# By default BL33 is at FLASH1 base
+PRELOADED_BL33_BASE ?= 0x10000000
+
+# Qemu SBSA plafrom only support SEC_SRAM
+BL32_RAM_LOCATION_ID = SEC_SRAM_ID
+$(eval $(call add_define,BL32_RAM_LOCATION_ID))
+
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33 := 0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
+
+ARM_PRELOADED_DTB_BASE := PLAT_QEMU_DT_BASE
+$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/qemu/qemu_sbsa/sbsa_pm.c b/plat/qemu/qemu_sbsa/sbsa_pm.c
new file mode 100644
index 0000000..8d1e1d4
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/sbsa_pm.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2020, Nuvia Inc
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+#include "sbsa_private.h"
+
+#define ADP_STOPPED_APPLICATION_EXIT 0x20026
+
+/*
+ * Define offset and commands for the fake EC device
+ */
+#define SBSA_SECURE_EC_OFFSET 0x50000000
+
+#define SBSA_SECURE_EC_CMD_SHUTDOWN 0x01
+#define SBSA_SECURE_EC_CMD_REBOOT 0x02
+
+/*
+ * The secure entry point to be used on warm reset.
+ */
+static unsigned long secure_entrypoint;
+
+/* Make composite power state parameter till power level 0 */
+#if PSCI_EXTENDED_STATE_ID
+
+#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+#else
+#define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+#endif /* PSCI_EXTENDED_STATE_ID */
+
+
+#define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \
+ qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+
+
+
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+static const unsigned int qemu_pm_idle_states[] = {
+ /* State-id - 0x01 */
+ qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET,
+ MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x02 */
+ qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x22 */
+ qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+ 0
+};
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the power state
+ * parameter. The power state parameter has to be a composite power state.
+ ******************************************************************************/
+static int qemu_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ unsigned int i;
+
+ assert(req_state != NULL);
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justifies the additional complexity.
+ */
+ for (i = 0U; qemu_pm_idle_states[i] != 0U; i++) {
+ if (power_state == qemu_pm_idle_states[i]) {
+ break;
+ }
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (qemu_pm_idle_states[i] == 0U) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ i = 0U;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id != 0U) {
+ req_state->pwr_domain_state[i++] = state_id &
+ PLAT_LOCAL_PSTATE_MASK;
+ state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+static void qemu_cpu_standby(plat_local_state_t cpu_state)
+{
+
+ assert(cpu_state == PLAT_LOCAL_STATE_RET);
+
+ /*
+ * Enter standby state
+ * dsb is good practice before using wfi to enter low power states
+ */
+ dsb();
+ wfi();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int qemu_pwr_domain_on(u_register_t mpidr)
+{
+ int pos = plat_core_pos_by_mpidr(mpidr);
+ uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE;
+
+ if (pos < 0) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO;
+ dsb();
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void qemu_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ qemu_pwr_gic_off();
+}
+
+void __dead2 plat_secondary_cold_boot_setup(void);
+
+static void __dead2
+qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+ disable_mmu_el3();
+ plat_secondary_cold_boot_setup();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void qemu_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ assert(false);
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+ qemu_pwr_gic_on_finish();
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ ******************************************************************************/
+void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ assert(false);
+}
+
+/*******************************************************************************
+ * Platform handlers to shutdown/reboot the system
+ ******************************************************************************/
+static void __dead2 qemu_system_off(void)
+{
+ mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_SHUTDOWN);
+ panic();
+}
+
+static void __dead2 qemu_system_reset(void)
+{
+ mmio_write_32(SBSA_SECURE_EC_OFFSET, SBSA_SECURE_EC_CMD_REBOOT);
+ panic();
+}
+
+static const plat_psci_ops_t plat_qemu_psci_pm_ops = {
+ .cpu_standby = qemu_cpu_standby,
+ .pwr_domain_on = qemu_pwr_domain_on,
+ .pwr_domain_off = qemu_pwr_domain_off,
+ .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi,
+ .pwr_domain_suspend = qemu_pwr_domain_suspend,
+ .pwr_domain_on_finish = qemu_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish,
+ .system_off = qemu_system_off,
+ .system_reset = qemu_system_reset,
+ .validate_power_state = qemu_validate_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ uintptr_t *mailbox = (uintptr_t *)PLAT_QEMU_TRUSTED_MAILBOX_BASE;
+
+ *mailbox = sec_entrypoint;
+ secure_entrypoint = (unsigned long)sec_entrypoint;
+ *psci_ops = &plat_qemu_psci_pm_ops;
+
+ return 0;
+}
diff --git a/plat/qemu/qemu_sbsa/sbsa_private.h b/plat/qemu/qemu_sbsa/sbsa_private.h
new file mode 100644
index 0000000..a9f4601
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/sbsa_private.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, Nuvia Inc
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SBSA_PRIVATE_H
+#define SBSA_PRIVATE_H
+
+#include <stdint.h>
+
+unsigned int plat_qemu_calc_core_pos(u_register_t mpidr);
+
+void qemu_pwr_gic_on_finish(void);
+void qemu_pwr_gic_off(void);
+
+#endif /* SBSA_PRIVATE_H */
diff --git a/plat/qemu/qemu_sbsa/sbsa_topology.c b/plat/qemu/qemu_sbsa/sbsa_topology.c
new file mode 100644
index 0000000..bd8d16b
--- /dev/null
+++ b/plat/qemu/qemu_sbsa/sbsa_topology.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, Nuvia Inc
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/debug.h>
+
+#include <platform_def.h>
+#include "sbsa_private.h"
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[PLATFORM_CLUSTER_COUNT + 1];
+
+/*******************************************************************************
+ * This function returns the sbsa-ref default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ unsigned int i;
+
+ power_domain_tree_desc[0] = PLATFORM_CLUSTER_COUNT;
+
+ for (i = 0U; i < PLATFORM_CLUSTER_COUNT; i++) {
+ power_domain_tree_desc[i + 1] = PLATFORM_MAX_CPUS_PER_CLUSTER;
+ }
+
+ return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+ if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) {
+ ERROR("Invalid MPIDR\n");
+ return -1;
+ }
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ ERROR("cluster_id >= PLATFORM_CLUSTER_COUNT define\n");
+ return -1;
+ }
+
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ ERROR("cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER define\n");
+ return -1;
+ }
+
+ return plat_qemu_calc_core_pos(mpidr);
+}
diff --git a/plat/qti/common/inc/aarch64/plat_macros.S b/plat/qti/common/inc/aarch64/plat_macros.S
new file mode 100644
index 0000000..2e292fb
--- /dev/null
+++ b/plat/qti/common/inc/aarch64/plat_macros.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_MACROS_S__
+#define __PLAT_MACROS_S__
+
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+ .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+/** Macro : plat_crash_print_regs
+ * This macro allows the crash reporting routine to print GIC registers
+ * in case of an unhandled exception in BL31. This aids in debugging and
+ * this macro can be defined to be empty in case GIC register reporting is
+ * not desired.
+ * The below required platform porting macro
+ * prints out relevant GIC registers whenever an
+ * unhandled exception is taken in BL31.
+ * Clobbers: x0 - x10, x26, x27, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+print_gic_regs:
+ ldr x26, =QTI_GICD_BASE
+ ldr x27, =QTI_GICC_BASE
+
+ /* Check for GICv3 system register access */
+ mrs x7, id_aa64pfr0_el1
+ ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x7, #1
+ b.ne print_gicv2
+
+ /* Check for SRE enable */
+ mrs x8, ICC_SRE_EL3
+ tst x8, #ICC_SRE_SRE_BIT
+ b.eq print_gicv2
+
+ /* Load the icc reg list to x6 */
+ adr x6, icc_regs
+ /* Load the icc regs to gp regs used by str_in_crash_buf_print */
+ mrs x8, ICC_HPPIR0_EL1
+ mrs x9, ICC_HPPIR1_EL1
+ mrs x10, ICC_CTLR_EL3
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ b print_gic_common
+
+print_gicv2:
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x27, #GICC_HPPIR]
+ ldr w9, [x27, #GICC_AHPPIR]
+ ldr w10, [x27, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+print_gic_common:
+ /* Print the GICD_ISPENDR regs */
+ add x7, x26, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x26
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+
+ .endm
+
+#endif /* __PLAT_MACROS_S__ */
diff --git a/plat/qti/common/inc/qti_board_def.h b/plat/qti/common/inc/qti_board_def.h
new file mode 100644
index 0000000..c95e4c0
--- /dev/null
+++ b/plat/qti/common/inc/qti_board_def.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_BOARD_DEF_H
+#define QTI_BOARD_DEF_H
+
+/*
+ * Required platform porting definitions common to all ARM
+ * development platforms
+ */
+
+/*
+ * Defines used to retrieve QTI SOC Version
+ */
+#define JEDEC_QTI_BKID U(0x0)
+#define JEDEC_QTI_MFID U(0x70)
+#define QTI_SOC_CONTINUATION_SHIFT U(24)
+#define QTI_SOC_IDENTIFICATION_SHIFT U(16)
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE 0x1000
+
+/*
+ * PLAT_QTI_MMAP_ENTRIES depends on the number of entries in the
+ * plat_qti_mmap array defined for each BL stage.
+ */
+#define PLAT_QTI_MMAP_ENTRIES 12
+
+/*
+ * Platform specific page table and MMU setup constants
+ */
+#define MAX_XLAT_TABLES 12
+
+#endif /* QTI_BOARD_DEF_H */
diff --git a/plat/qti/common/inc/qti_cpu.h b/plat/qti/common/inc/qti_cpu.h
new file mode 100644
index 0000000..3316f7b
--- /dev/null
+++ b/plat/qti/common/inc/qti_cpu.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTI_CPU_H
+#define QTI_CPU_H
+
+/* KRYO-4xx Gold MIDR */
+#define QTI_KRYO4_GOLD_MIDR 0x517F804D
+
+/* KRYO-4xx Silver MIDR */
+#define QTI_KRYO4_SILVER_MIDR 0x517F805D
+
+/* KRYO-6xx Gold MIDR */
+#define QTI_KRYO6_GOLD_MIDR 0x412FD410
+
+/* KRYO-6xx Silver MIDR */
+#define QTI_KRYO6_SILVER_MIDR 0x412FD050
+
+#endif /* QTI_CPU_H */
diff --git a/plat/qti/common/inc/qti_interrupt_svc.h b/plat/qti/common/inc/qti_interrupt_svc.h
new file mode 100644
index 0000000..59bde86
--- /dev/null
+++ b/plat/qti/common/inc/qti_interrupt_svc.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTI_INTERRUPT_SVC_H
+#define QTI_INTERRUPT_SVC_H
+
+int qti_interrupt_svc_init(void);
+
+#endif /* QTI_INTERRUPT_SVC_H */
diff --git a/plat/qti/common/inc/qti_plat.h b/plat/qti/common/inc/qti_plat.h
new file mode 100644
index 0000000..7483c49
--- /dev/null
+++ b/plat/qti/common/inc/qti_plat.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTI_PLAT_H
+#define QTI_PLAT_H
+
+#include <stdint.h>
+
+#include <common/bl_common.h>
+#include <lib/cassert.h>
+#include <lib/el3_runtime/cpu_data.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+/*
+ * Utility functions common to QTI platforms
+ */
+int qti_mmap_add_dynamic_region(uintptr_t base_pa, size_t size,
+ unsigned int attr);
+int qti_mmap_remove_dynamic_region(uintptr_t base_va, size_t size);
+
+/*
+ * Utility functions common to ARM standard platforms
+ */
+void qti_setup_page_tables(
+ uintptr_t total_base,
+ size_t total_size,
+ uintptr_t code_start,
+ uintptr_t code_limit,
+ uintptr_t rodata_start,
+ uintptr_t rodata_limit
+ );
+
+/*
+ * Mandatory functions required in ARM standard platforms
+ */
+void plat_qti_gic_driver_init(void);
+void plat_qti_gic_init(void);
+void plat_qti_gic_cpuif_enable(void);
+void plat_qti_gic_cpuif_disable(void);
+void plat_qti_gic_pcpu_init(void);
+
+/*
+ * Optional functions required in ARM standard platforms
+ */
+unsigned int plat_qti_core_pos_by_mpidr(u_register_t mpidr);
+unsigned int plat_qti_my_cluster_pos(void);
+
+void gic_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr);
+
+void qti_pmic_prepare_reset(void);
+void qti_pmic_prepare_shutdown(void);
+
+typedef struct chip_id_info {
+ uint16_t jtag_id;
+ uint16_t chipinfo_id;
+} chip_id_info_t;
+
+#endif /* QTI_PLAT_H */
diff --git a/plat/qti/common/inc/qti_rng.h b/plat/qti/common/inc/qti_rng.h
new file mode 100644
index 0000000..62c31f3
--- /dev/null
+++ b/plat/qti/common/inc/qti_rng.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTI_RNG_H
+#define QTI_RNG_H
+
+#include <stdint.h>
+
+int qti_rng_get_data(uint8_t *out, uint32_t out_len);
+
+#endif /* QTI_RNG_H */
diff --git a/plat/qti/common/inc/qti_uart_console.h b/plat/qti/common/inc/qti_uart_console.h
new file mode 100644
index 0000000..c5a65d6
--- /dev/null
+++ b/plat/qti/common/inc/qti_uart_console.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTI_UART_CONSOLE_H
+#define QTI_UART_CONSOLE_H
+
+#include <drivers/console.h>
+
+#ifndef __ASSEMBLER__
+
+int qti_console_uart_register(console_t *console, uintptr_t uart_base_addr);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* QTI_UART_CONSOLE_H */
diff --git a/plat/qti/common/inc/spmi_arb.h b/plat/qti/common/inc/spmi_arb.h
new file mode 100644
index 0000000..362f740
--- /dev/null
+++ b/plat/qti/common/inc/spmi_arb.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPMI_ARB_H
+#define SPMI_ARB_H
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * WARNING: This driver does not arbitrate access with the kernel. These APIs
+ * must only be called when the kernel is known to be quiesced (such as before
+ * boot or while the system is shutting down).
+ ******************************************************************************/
+
+/* 32-bit addresses combine (U)SID, PID and register address. */
+
+int spmi_arb_read8(uint32_t addr);
+int spmi_arb_write8(uint32_t addr, uint8_t data);
+
+#endif /* SPMI_ARB_H */
diff --git a/plat/qti/common/src/aarch64/qti_helpers.S b/plat/qti/common/src/aarch64/qti_helpers.S
new file mode 100644
index 0000000..d34b530
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_helpers.S
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/console.h>
+
+#include <platform_def.h>
+
+ .globl plat_my_core_pos
+ .globl plat_qti_core_pos_by_mpidr
+ .globl plat_reset_handler
+ .globl plat_panic_handler
+
+ /* -----------------------------------------------------
+ * unsigned int plat_qti_core_pos_by_mpidr(uint64_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function:
+ * CorePos = (ClusterId * 4) + CoreId
+ * - In ARM v8 (MPIDR_EL1[24]=0)
+ * ClusterId = MPIDR_EL1[15:8]
+ * CoreId = MPIDR_EL1[7:0]
+ * - In ARM v8.1 (MPIDR_EL1[24]=1)
+ * ClusterId = MPIDR_EL1[23:15]
+ * CoreId = MPIDR_EL1[15:8]
+ * Clobbers: x0 & x1.
+ * -----------------------------------------------------
+ */
+func plat_qti_core_pos_by_mpidr
+ mrs x1, mpidr_el1
+ tst x1, #MPIDR_MT_MASK
+ beq plat_qti_core_pos_by_mpidr_no_mt
+ /* Right shift mpidr by one affinity level when MT=1. */
+ lsr x0, x0, #MPIDR_AFFINITY_BITS
+plat_qti_core_pos_by_mpidr_no_mt:
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_qti_core_pos_by_mpidr
+
+ /* --------------------------------------------------------------------
+ * void plat_panic_handler(void)
+ * calls SDI and reset system
+ * --------------------------------------------------------------------
+ */
+func plat_panic_handler
+ msr spsel, #0
+ bl plat_set_my_stack
+ b qtiseclib_panic
+endfunc plat_panic_handler
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_qti_calc_core_pos()
+ * definition to get the index of the calling CPU
+ * Clobbers: x0 & x1.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_qti_core_pos_by_mpidr
+endfunc plat_my_core_pos
+
+func plat_reset_handler
+ /* save the lr */
+ mov x18, x30
+
+ /* pass cold boot status. */
+ ldr w0, g_qti_bl31_cold_booted
+ /* Execuete CPUSS boot set up on every core. */
+ bl qtiseclib_cpuss_reset_asm
+
+ ret x18
+endfunc plat_reset_handler
diff --git a/plat/qti/common/src/aarch64/qti_kryo4_gold.S b/plat/qti/common/src/aarch64/qti_kryo4_gold.S
new file mode 100644
index 0000000..9bcdf54
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo4_gold.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+ .p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Gold
+ * -------------------------------------------------
+ */
+func qti_kryo4_gold_reset_func
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+ adr x0, wa_cve_2017_5715_bpiall_vbar
+ msr vbar_el3, x0
+ isb
+#endif
+
+ mov x19, x30
+
+ bl qtiseclib_kryo4_gold_reset_asm
+ mov x30, x19
+ b cortex_a76_reset_func
+
+endfunc qti_kryo4_gold_reset_func
+
+/* -------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Gold
+ * -------------------------------------------------------
+ */
+func qti_kryo4_gold_cluster_pwr_dwn
+ ret
+endfunc qti_kryo4_gold_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Gold. Must follow AAPCS.
+ */
+func qti_kryo4_gold_errata_report
+ /* TODO : Need to add support. Required only for debug bl31 image.*/
+ ret
+endfunc qti_kryo4_gold_errata_report
+#endif
+
+/* ---------------------------------------------
+ * This function provides kryo4_gold specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_gold_regs, "aS"
+qti_kryo4_gold_regs: /* The ASCII list of register names to be reported */
+ .asciz ""
+
+func qti_kryo4_gold_cpu_reg_dump
+ adr x6, qti_kryo4_gold_regs
+ ret
+endfunc qti_kryo4_gold_cpu_reg_dump
+
+declare_cpu_ops_wa qti_kryo4_gold, QTI_KRYO4_GOLD_MIDR, \
+ qti_kryo4_gold_reset_func, \
+ CPU_NO_EXTRA1_FUNC, \
+ cortex_a76_disable_wa_cve_2018_3639, \
+ cortex_a76_core_pwr_dwn, \
+ qti_kryo4_gold_cluster_pwr_dwn
diff --git a/plat/qti/common/src/aarch64/qti_kryo4_silver.S b/plat/qti/common/src/aarch64/qti_kryo4_silver.S
new file mode 100644
index 0000000..36374b7
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo4_silver.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+ .p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Silver
+ * -------------------------------------------------
+ */
+func qti_kryo4_silver_reset_func
+ mov x19, x30
+
+ bl qtiseclib_kryo4_silver_reset_asm
+ mov x30, x19
+ b cortex_a55_reset_func
+
+endfunc qti_kryo4_silver_reset_func
+
+/* ---------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Silver
+ * ---------------------------------------------------------
+ */
+func qti_kryo4_silver_cluster_pwr_dwn
+ ret
+endfunc qti_kryo4_silver_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Silver. Must follow AAPCS.
+ */
+func qti_kryo4_silver_errata_report
+ /* TODO : Need to add support. Required only for debug bl31 image.*/
+ ret
+endfunc qti_kryo4_silver_errata_report
+#endif
+
+
+/* ---------------------------------------------
+ * This function provides kryo4_silver specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_silver_regs, "aS"
+qti_kryo4_silver_regs: /* The ASCII list of register names to be reported */
+ .asciz ""
+
+func qti_kryo4_silver_cpu_reg_dump
+ adr x6, qti_kryo4_silver_regs
+ ret
+endfunc qti_kryo4_silver_cpu_reg_dump
+
+
+declare_cpu_ops qti_kryo4_silver, QTI_KRYO4_SILVER_MIDR, \
+ qti_kryo4_silver_reset_func, \
+ cortex_a55_core_pwr_dwn, \
+ qti_kryo4_silver_cluster_pwr_dwn
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_gold.S b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
new file mode 100644
index 0000000..577e7ff
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+ .p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Gold
+ * -------------------------------------------------
+ */
+func qti_kryo6_gold_reset_func
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+ adr x0, wa_cve_2017_5715_bpiall_vbar
+ msr vbar_el3, x0
+ isb
+#endif
+
+ mov x19, x30
+
+ bl qtiseclib_kryo6_gold_reset_asm
+ mov x30, x19
+ b cortex_a78_reset_func
+
+endfunc qti_kryo6_gold_reset_func
+
+/* -------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Gold
+ * -------------------------------------------------------
+ */
+func qti_kryo6_gold_cluster_pwr_dwn
+ ret
+endfunc qti_kryo6_gold_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Gold. Must follow AAPCS.
+ */
+func qti_kryo6_gold_errata_report
+ /* TODO : Need to add support. Required only for debug bl31 image.*/
+ ret
+endfunc qti_kryo6_gold_errata_report
+#endif
+
+/* ---------------------------------------------
+ * This function provides kryo4_gold specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_gold_regs, "aS"
+qti_kryo6_gold_regs: /* The ASCII list of register names to be reported */
+ .asciz ""
+
+func qti_kryo6_gold_cpu_reg_dump
+ adr x6, qti_kryo6_gold_regs
+ ret
+endfunc qti_kryo6_gold_cpu_reg_dump
+
+declare_cpu_ops qti_kryo6_gold, QTI_KRYO6_GOLD_MIDR, \
+ qti_kryo6_gold_reset_func, \
+ cortex_a78_core_pwr_dwn, \
+ qti_kryo6_gold_cluster_pwr_dwn
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_silver.S b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
new file mode 100644
index 0000000..6ad0bca
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+ .p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Silver
+ * -------------------------------------------------
+ */
+func qti_kryo6_silver_reset_func
+ mov x19, x30
+
+ bl qtiseclib_kryo6_silver_reset_asm
+ mov x30, x19
+ b cortex_a55_reset_func
+
+endfunc qti_kryo6_silver_reset_func
+
+/* ---------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Silver
+ * ---------------------------------------------------------
+ */
+func qti_kryo6_silver_cluster_pwr_dwn
+ ret
+endfunc qti_kryo6_silver_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Silver. Must follow AAPCS.
+ */
+func qti_kryo6_silver_errata_report
+ /* TODO : Need to add support. Required only for debug bl31 image.*/
+ ret
+endfunc qti_kryo6_silver_errata_report
+#endif
+
+
+/* ---------------------------------------------
+ * This function provides kryo4_silver specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_silver_regs, "aS"
+qti_kryo6_silver_regs: /* The ASCII list of register names to be reported */
+ .asciz ""
+
+func qti_kryo6_silver_cpu_reg_dump
+ adr x6, qti_kryo6_silver_regs
+ ret
+endfunc qti_kryo6_silver_cpu_reg_dump
+
+
+declare_cpu_ops qti_kryo6_silver, QTI_KRYO6_SILVER_MIDR, \
+ qti_kryo6_silver_reset_func, \
+ cortex_a55_core_pwr_dwn, \
+ qti_kryo6_silver_cluster_pwr_dwn
diff --git a/plat/qti/common/src/aarch64/qti_uart_console.S b/plat/qti/common/src/aarch64/qti_uart_console.S
new file mode 100644
index 0000000..2eb33d9
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_uart_console.S
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <console_macros.S>
+
+#include <platform_def.h>
+#include <qti_uart_console.h>
+
+/*
+ * This driver implements console logging into a ring buffer.
+ */
+
+ .globl qti_console_uart_register
+
+ /* -----------------------------------------------
+ * int qti_console_uart_register(console_t *console,
+ * uintptr_t uart_base_addr)
+ * Registers uart console instance.
+ * In: x0 - pointer to empty console_t struct
+ * x1 - start address of uart block.
+ * Out: x0 - 1 to indicate success
+ * Clobber list: x0, x1, x14
+ * -----------------------------------------------
+ */
+func qti_console_uart_register
+ str x1, [x0, #CONSOLE_T_BASE] /* Save UART base. */
+ finish_console_register uart putc=1, flush=1
+endfunc qti_console_uart_register
+
+ /* -----------------------------------------------
+ * int qti_console_uart_puts(int c, console_t *console)
+ * Writes a character to the UART console.
+ * The character must be preserved in x0.
+ * In: x0 - character to be stored
+ * x1 - pointer to console_t struct
+ * Clobber list: x1, x2
+ * -----------------------------------------------
+ */
+func console_uart_putc
+ /* set x1 = UART base. */
+ ldr x1, [x1, #CONSOLE_T_BASE]
+
+ /* Loop until M_GENI_CMD_ACTIVE bit not clear. */
+1: ldr w2, [x1, #GENI_STATUS_REG]
+ and w2, w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK
+ cmp w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK
+ b.eq 1b
+
+ /* Transmit data. */
+ cmp w0, #0xA
+ b.ne 3f
+
+ /* Add '\r' when input char is '\n' */
+ mov w2, #0x1
+ mov w0, #0xD
+ str w2, [x1, #UART_TX_TRANS_LEN_REG]
+ mov w2, #GENI_M_CMD_TX
+ str w2, [x1, #GENI_M_CMD0_REG]
+ str w0, [x1, #GENI_TX_FIFOn_REG]
+ mov w0, #0xA
+
+ /* Loop until M_GENI_CMD_ACTIVE bit not clear. */
+2: ldr w2, [x1, #GENI_STATUS_REG]
+ and w2, w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK
+ cmp w2, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK
+ b.eq 2b
+
+ /* Transmit i/p data. */
+3: mov w2, #0x1
+ str w2, [x1, #UART_TX_TRANS_LEN_REG]
+ mov w2, #GENI_M_CMD_TX
+ str w2, [x1, #GENI_M_CMD0_REG]
+ str w0, [x1, #GENI_TX_FIFOn_REG]
+
+ ret
+endfunc console_uart_putc
+
+ /* -----------------------------------------------
+ * int qti_console_uart_flush(console_t *console)
+ * In: x0 - pointer to console_t struct
+ * Out: x0 - 0 for success
+ * Clobber list: x0, x1
+ * -----------------------------------------------
+ */
+func console_uart_flush
+ /* set x0 = UART base. */
+ ldr x0, [x0, #CONSOLE_T_BASE]
+
+ /* Loop until M_GENI_CMD_ACTIVE bit not clear. */
+1: ldr w1, [x0, #GENI_STATUS_REG]
+ and w1, w1, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK
+ cmp w1, #GENI_STATUS_M_GENI_CMD_ACTIVE_MASK
+ b.eq 1b
+
+ mov w0, #0
+ ret
+endfunc console_uart_flush
diff --git a/plat/qti/common/src/pm_ps_hold.c b/plat/qti/common/src/pm_ps_hold.c
new file mode 100644
index 0000000..208345c
--- /dev/null
+++ b/plat/qti/common/src/pm_ps_hold.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/delay_timer.h>
+
+#include <qti_plat.h>
+#include <spmi_arb.h>
+
+/*
+ * This driver implements PON support for PM8998-compatible PMICs. This can
+ * include other part numbers like PM6150.
+ */
+
+#define RESET_TYPE_WARM_RESET 1
+#define RESET_TYPE_SHUTDOWN 4
+
+#define S2_RESET_EN BIT(7)
+
+static void configure_ps_hold(uint32_t reset_type)
+{
+ /* QTI recommends disabling reset for 10 cycles before reconfiguring. */
+ spmi_arb_write8(PON_PS_HOLD_RESET_CTL2, 0);
+ mdelay(1);
+
+ spmi_arb_write8(PON_PS_HOLD_RESET_CTL, reset_type);
+ spmi_arb_write8(PON_PS_HOLD_RESET_CTL2, S2_RESET_EN);
+ mdelay(1);
+}
+
+void qti_pmic_prepare_reset(void)
+{
+ configure_ps_hold(RESET_TYPE_WARM_RESET);
+}
+
+void qti_pmic_prepare_shutdown(void)
+{
+ configure_ps_hold(RESET_TYPE_SHUTDOWN);
+}
diff --git a/plat/qti/common/src/qti_bl31_setup.c b/plat/qti/common/src/qti_bl31_setup.c
new file mode 100644
index 0000000..dac0253
--- /dev/null
+++ b/plat/qti/common/src/qti_bl31_setup.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/bl_aux_params/bl_aux_params.h>
+#include <lib/coreboot.h>
+#include <lib/spinlock.h>
+
+#include <platform.h>
+#include <qti_interrupt_svc.h>
+#include <qti_plat.h>
+#include <qti_uart_console.h>
+#include <qtiseclib_interface.h>
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl33_image_ep_info;
+
+/*
+ * Variable to hold counter frequency for the CPU's generic timer. In this
+ * platform coreboot image configure counter frequency for boot core before
+ * reaching TF-A.
+ */
+static uint64_t g_qti_cpu_cntfrq;
+
+/*
+ * Variable to hold bl31 cold boot status. Default value 0x0 means yet to boot.
+ * Any other value means cold booted.
+ */
+uint32_t g_qti_bl31_cold_booted;
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup common to ARM standard platforms.
+ * Here is an opportunity to copy parameters passed by the calling EL (S-EL1
+ * in BL2 & S-EL3 in BL1) before they are lost (potentially). This needs to be
+ * done before the MMU is initialized so that the memory layout can be used
+ * while creating page tables. BL2 has flushed this information to memory, so
+ * we are guaranteed to pick up good data.
+ ******************************************************************************/
+void bl31_early_platform_setup(u_register_t from_bl2,
+ u_register_t plat_params_from_bl2)
+{
+
+ g_qti_cpu_cntfrq = read_cntfrq_el0();
+
+ bl_aux_params_parse(plat_params_from_bl2, NULL);
+
+#if COREBOOT
+ if (coreboot_serial.baseaddr != 0) {
+ static console_t g_qti_console_uart;
+
+ qti_console_uart_register(&g_qti_console_uart,
+ coreboot_serial.baseaddr);
+ }
+#endif
+
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl31_params_parse_helper(from_bl2, NULL, &bl33_image_ep_info);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ bl31_early_platform_setup(arg0, arg1);
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ qti_setup_page_tables(
+ BL31_START,
+ BL31_END-BL31_START,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_RO_DATA_BASE,
+ BL_RO_DATA_END
+ );
+ enable_mmu_el3(0);
+}
+
+/*******************************************************************************
+ * Perform any BL31 platform setup common to ARM standard platforms
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ generic_delay_timer_init();
+ /* Initialize the GIC driver, CPU and distributor interfaces */
+ plat_qti_gic_driver_init();
+ plat_qti_gic_init();
+ qti_interrupt_svc_init();
+ qtiseclib_bl31_platform_setup();
+
+ /* set boot state to cold boot complete. */
+ g_qti_bl31_cold_booted = 0x1;
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for the
+ * security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ /* QTI platform don't have BL32 implementation. */
+ assert(type == NON_SECURE);
+ assert(bl33_image_ep_info.h.type == PARAM_EP);
+ assert(bl33_image_ep_info.h.attr == NON_SECURE);
+ /*
+ * None of the images on the platforms can have 0x0
+ * as the entrypoint.
+ */
+ if (bl33_image_ep_info.pc) {
+ return &bl33_image_ep_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * This function is used by the architecture setup code to retrieve the counter
+ * frequency for the CPU's generic timer. This value will be programmed into the
+ * CNTFRQ_EL0 register. In Arm standard platforms, it returns the base frequency
+ * of the system counter, which is retrieved from the first entry in the
+ * frequency modes table. This will be used later in warm boot (psci_arch_setup)
+ * of CPUs to set when CPU frequency.
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+ assert(g_qti_cpu_cntfrq != 0);
+ return g_qti_cpu_cntfrq;
+}
diff --git a/plat/qti/common/src/qti_common.c b/plat/qti/common/src/qti_common.c
new file mode 100644
index 0000000..74ccb5b
--- /dev/null
+++ b/plat/qti/common/src/qti_common.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <services/arm_arch_svc.h>
+
+#include <platform_def.h>
+#include <qti_map_chipinfo.h>
+#include <qti_plat.h>
+#include <qtiseclib_interface.h>
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * qti_configure_mmu_elx() will give the available subset of that,
+ */
+
+const mmap_region_t plat_qti_mmap[] = {
+ MAP_REGION_FLAT(QTI_DEVICE_BASE, QTI_DEVICE_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(QTI_AOP_CMD_DB_BASE, QTI_AOP_CMD_DB_SIZE,
+ MT_NS | MT_RO | MT_EXECUTE_NEVER),
+ {0}
+};
+
+CASSERT(ARRAY_SIZE(plat_qti_mmap) <= MAX_MMAP_REGIONS, assert_max_mmap_regions);
+
+
+bool qti_is_overlap_atf_rg(unsigned long long addr, size_t size)
+{
+ if (addr > addr + size
+ || (BL31_BASE < addr + size && BL31_LIMIT > addr)) {
+ return true;
+ }
+ return false;
+}
+
+/*
+ * unsigned int plat_qti_my_cluster_pos(void)
+ * definition to get the cluster index of the calling CPU.
+ * - In ARM v8 (MPIDR_EL1[24]=0)
+ * ClusterId = MPIDR_EL1[15:8]
+ * - In ARM v8.1 & Later version (MPIDR_EL1[24]=1)
+ * ClusterId = MPIDR_EL1[23:15]
+ */
+unsigned int plat_qti_my_cluster_pos(void)
+{
+ unsigned int mpidr, cluster_id;
+
+ mpidr = read_mpidr_el1();
+ if ((mpidr & MPIDR_MT_MASK) == 0) { /* MT not supported */
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ } else { /* MT supported */
+ cluster_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK;
+ }
+ assert(cluster_id < PLAT_CLUSTER_COUNT);
+ return cluster_id;
+}
+
+/*
+ * Set up the page tables for the generic and platform-specific memory regions.
+ * The extents of the generic memory regions are specified by the function
+ * arguments and consist of:
+ * - Trusted SRAM seen by the BL image;
+ * - Code section;
+ * - Read-only data section;
+ * - Coherent memory region, if applicable.
+ */
+void qti_setup_page_tables(
+ uintptr_t total_base,
+ size_t total_size,
+ uintptr_t code_start,
+ uintptr_t code_limit,
+ uintptr_t rodata_start,
+ uintptr_t rodata_limit
+ )
+{
+ /*
+ * Map the Trusted SRAM with appropriate memory attributes.
+ * Subsequent mappings will adjust the attributes for specific regions.
+ */
+ VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n",
+ (void *)total_base, (void *)(total_base + total_size));
+ mmap_add_region(total_base, total_base,
+ total_size, MT_MEMORY | MT_RW | MT_SECURE);
+
+ /* Re-map the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *)code_start, (void *)code_limit);
+ mmap_add_region(code_start, code_start,
+ code_limit - code_start, MT_CODE | MT_SECURE);
+
+ /* Re-map the read-only data section */
+ VERBOSE("Read-only data region: %p - %p\n",
+ (void *)rodata_start, (void *)rodata_limit);
+ mmap_add_region(rodata_start, rodata_start,
+ rodata_limit - rodata_start, MT_RO_DATA | MT_SECURE);
+
+ /* Now (re-)map the platform-specific memory regions */
+ mmap_add(plat_qti_mmap);
+
+ /* Create the page tables to reflect the above mappings */
+ init_xlat_tables();
+}
+
+static inline void qti_align_mem_region(uintptr_t addr, size_t size,
+ uintptr_t *aligned_addr,
+ size_t *aligned_size)
+{
+ *aligned_addr = round_down(addr, PAGE_SIZE);
+ *aligned_size = round_up(addr - *aligned_addr + size, PAGE_SIZE);
+}
+
+int qti_mmap_add_dynamic_region(uintptr_t base_pa, size_t size,
+ unsigned int attr)
+{
+ uintptr_t aligned_pa;
+ size_t aligned_size;
+
+ qti_align_mem_region(base_pa, size, &aligned_pa, &aligned_size);
+
+ if (qti_is_overlap_atf_rg(base_pa, size)) {
+ /* Memory shouldn't overlap with TF-A range. */
+ return -EPERM;
+ }
+
+ return mmap_add_dynamic_region(aligned_pa, aligned_pa, aligned_size,
+ attr);
+}
+
+int qti_mmap_remove_dynamic_region(uintptr_t base_va, size_t size)
+{
+ qti_align_mem_region(base_va, size, &base_va, &size);
+ return mmap_remove_dynamic_region(base_va, size);
+}
+
+/*
+ * This function returns soc version which mainly consist of below fields
+ *
+ * soc_version[30:24] = JEP-106 continuation code for the SiP
+ * soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
+ * soc_version[0:15] = Implementation defined SoC ID
+ */
+int32_t plat_get_soc_version(void)
+{
+ int i = 0;
+ /* Variant other than in mapped g_map_jtag_chipinfo_id variable will have
+ * default chipinfo id as 0xFFFF
+ */
+ uint32_t soc_version = (QTI_DEFAULT_CHIPINFO_ID & QTI_SOC_VERSION_MASK);
+ uint32_t jep106az_code = (JEDEC_QTI_BKID << QTI_SOC_CONTINUATION_SHIFT)
+ | (JEDEC_QTI_MFID << QTI_SOC_IDENTIFICATION_SHIFT);
+ uint32_t jtag_id = mmio_read_32(QTI_JTAG_ID_REG);
+ uint32_t jtag_id_val = (jtag_id >> QTI_JTAG_ID_SHIFT)
+ & QTI_SOC_VERSION_MASK;
+
+ for (i = 0; i < ARRAY_SIZE(g_map_jtag_chipinfo_id); i++) {
+ if (g_map_jtag_chipinfo_id[i].jtag_id == jtag_id_val)
+ soc_version = g_map_jtag_chipinfo_id[i].chipinfo_id
+ & QTI_SOC_VERSION_MASK;
+ }
+ return (int32_t)(jep106az_code | (soc_version));
+}
+
+/*
+ * This function returns soc revision in below format
+ *
+ * soc_revision[0:30] = SOC revision of specific SOC
+ */
+int32_t plat_get_soc_revision(void)
+{
+ return mmio_read_32(QTI_SOC_REVISION_REG) & QTI_SOC_REVISION_MASK;
+}
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC feature
+ * is availabile for the platform or not.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
diff --git a/plat/qti/common/src/qti_gic_v3.c b/plat/qti/common/src/qti_gic_v3.c
new file mode 100644
index 0000000..f00267a
--- /dev/null
+++ b/plat/qti/common/src/qti_gic_v3.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <drivers/arm/gicv3.h>
+
+#include <platform.h>
+#include <platform_def.h>
+#include <qti_plat.h>
+#include <qtiseclib_defs.h>
+#include <qtiseclib_defs_plat.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* Array of interrupts to be configured by the gic driver */
+static const interrupt_prop_t qti_interrupt_props[] = {
+ INTR_PROP_DESC(QTISECLIB_INT_ID_CPU_WAKEUP_SGI,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_RESET_SGI, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_SEC_WDOG_BARK, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_NON_SEC_WDOG_BITE,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_XPU_SEC, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_XPU_NON_SEC, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+#ifdef QTISECLIB_INT_ID_A1_NOC_ERROR
+ INTR_PROP_DESC(QTISECLIB_INT_ID_A1_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+#endif
+ INTR_PROP_DESC(QTISECLIB_INT_ID_A2_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_CONFIG_NOC_ERROR,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_DC_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_MEM_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_SYSTEM_NOC_ERROR,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(QTISECLIB_INT_ID_MMSS_NOC_ERROR,
+ GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+#ifdef QTISECLIB_INT_ID_LPASS_AGNOC_ERROR
+ INTR_PROP_DESC(QTISECLIB_INT_ID_LPASS_AGNOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_NSP_NOC_ERROR
+ INTR_PROP_DESC(QTISECLIB_INT_ID_NSP_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+ INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+#endif
+};
+
+const gicv3_driver_data_t qti_gic_data = {
+ .gicd_base = QTI_GICD_BASE,
+ .gicr_base = QTI_GICR_BASE,
+ .interrupt_props = qti_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(qti_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = plat_qti_core_pos_by_mpidr
+};
+
+void plat_qti_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+ gicv3_driver_init(&qti_gic_data);
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the GIC. Only invoked by BL31
+ *****************************************************************************/
+void plat_qti_gic_init(void)
+{
+ unsigned int i;
+
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+
+ /* Route secure spi interrupt to ANY. */
+ for (i = 0; i < ARRAY_SIZE(qti_interrupt_props); i++) {
+ unsigned int int_id = qti_interrupt_props[i].intr_num;
+
+ if (plat_ic_is_spi(int_id)) {
+ gicv3_set_spi_routing(int_id, GICV3_IRM_ANY, 0x0);
+ }
+ }
+}
+
+void gic_set_spi_routing(unsigned int id, unsigned int irm, u_register_t target)
+{
+ gicv3_set_spi_routing(id, irm, target);
+}
+
+/******************************************************************************
+ * ARM common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_qti_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_qti_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helper to initialize the per-CPU redistributor interface in GICv3
+ *****************************************************************************/
+void plat_qti_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * ARM common helpers to power GIC redistributor interface
+ *****************************************************************************/
+void plat_qti_gic_redistif_on(void)
+{
+ gicv3_rdistif_on(plat_my_core_pos());
+}
+
+void plat_qti_gic_redistif_off(void)
+{
+ gicv3_rdistif_off(plat_my_core_pos());
+}
diff --git a/plat/qti/common/src/qti_interrupt_svc.c b/plat/qti/common/src/qti_interrupt_svc.c
new file mode 100644
index 0000000..3017dc7
--- /dev/null
+++ b/plat/qti/common/src/qti_interrupt_svc.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <bl31/interrupt_mgmt.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/el3_runtime/context_mgmt.h>
+
+#include <platform.h>
+#include <qti_interrupt_svc.h>
+#include <qtiseclib_interface.h>
+
+#define QTI_INTR_INVALID_INT_NUM 0xFFFFFFFFU
+
+/*
+ * Top-level EL3 interrupt handler.
+ */
+static uint64_t qti_el3_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint32_t irq = QTI_INTR_INVALID_INT_NUM;
+
+ /*
+ * EL3 non-interruptible. Interrupt shouldn't occur when we are at
+ * EL3 / Secure.
+ */
+ assert(handle != cm_get_context(SECURE));
+
+ irq = plat_ic_acknowledge_interrupt();
+
+ qtiseclib_invoke_isr(irq, handle);
+
+ /* End of Interrupt. */
+ if (irq < 1022U) {
+ plat_ic_end_of_interrupt(irq);
+ }
+
+ return (uint64_t) handle;
+}
+
+int qti_interrupt_svc_init(void)
+{
+ int ret;
+ uint64_t flags = 0U;
+
+ /*
+ * Route EL3 interrupts to EL3 when in Non-secure.
+ * Note: EL3 won't have interrupt enable
+ * & we don't have S-EL1 support.
+ */
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ set_interrupt_rm_flag(flags, SECURE);
+
+ /* Register handler for EL3 interrupts */
+ ret = register_interrupt_type_handler(INTR_TYPE_EL3,
+ qti_el3_interrupt_handler, flags);
+ assert(ret == 0);
+
+ return ret;
+}
diff --git a/plat/qti/common/src/qti_pm.c b/plat/qti/common/src/qti_pm.c
new file mode 100644
index 0000000..5f1b7aa
--- /dev/null
+++ b/plat/qti/common/src/qti_pm.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <platform.h>
+#include <platform_def.h>
+#include <qti_cpu.h>
+#include <qti_plat.h>
+#include <qtiseclib_cb_interface.h>
+#include <qtiseclib_defs_plat.h>
+#include <qtiseclib_interface.h>
+
+#define QTI_LOCAL_PSTATE_WIDTH 4
+#define QTI_LOCAL_PSTATE_MASK ((1 << QTI_LOCAL_PSTATE_WIDTH) - 1)
+
+/* Make composite power state parameter till level 0 */
+#define qti_make_pwrstate_lvl0(lvl0_state, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
+
+/* Make composite power state parameter till level 1 */
+#define qti_make_pwrstate_lvl1(lvl1_state, lvl0_state, type) \
+ (((lvl1_state) << QTI_LOCAL_PSTATE_WIDTH) | \
+ qti_make_pwrstate_lvl0(lvl0_state, type))
+
+/* Make composite power state parameter till level 2 */
+#define qti_make_pwrstate_lvl2(lvl2_state, lvl1_state, lvl0_state, type) \
+ (((lvl2_state) << (QTI_LOCAL_PSTATE_WIDTH * 2)) | \
+ qti_make_pwrstate_lvl1(lvl1_state, lvl0_state, type))
+
+/* Make composite power state parameter till level 3 */
+#define qti_make_pwrstate_lvl3(lvl3_state, lvl2_state, lvl1_state, lvl0_state, type) \
+ (((lvl3_state) << (QTI_LOCAL_PSTATE_WIDTH * 3)) | \
+ qti_make_pwrstate_lvl2(lvl2_state, lvl1_state, lvl0_state, type))
+
+/* QTI_CORE_PWRDN_EN_MASK happens to be same across all CPUs */
+#define QTI_CORE_PWRDN_EN_MASK 1
+
+/* cpu power control happens to be same across all CPUs */
+_DEFINE_SYSREG_WRITE_FUNC(cpu_pwrctrl_val, S3_0_C15_C2_7)
+_DEFINE_SYSREG_READ_FUNC(cpu_pwrctrl_val, S3_0_C15_C2_7)
+
+const unsigned int qti_pm_idle_states[] = {
+ qti_make_pwrstate_lvl0(QTI_LOCAL_STATE_OFF,
+ PSTATE_TYPE_POWERDOWN),
+ qti_make_pwrstate_lvl0(QTI_LOCAL_STATE_DEEPOFF,
+ PSTATE_TYPE_POWERDOWN),
+ qti_make_pwrstate_lvl1(QTI_LOCAL_STATE_DEEPOFF,
+ QTI_LOCAL_STATE_DEEPOFF,
+ PSTATE_TYPE_POWERDOWN),
+ qti_make_pwrstate_lvl2(QTI_LOCAL_STATE_OFF,
+ QTI_LOCAL_STATE_DEEPOFF,
+ QTI_LOCAL_STATE_DEEPOFF,
+ PSTATE_TYPE_POWERDOWN),
+ qti_make_pwrstate_lvl3(QTI_LOCAL_STATE_OFF,
+ QTI_LOCAL_STATE_DEEPOFF,
+ QTI_LOCAL_STATE_DEEPOFF,
+ QTI_LOCAL_STATE_DEEPOFF,
+ PSTATE_TYPE_POWERDOWN),
+ 0,
+};
+
+/*******************************************************************************
+ * QTI standard platform handler called to check the validity of the power
+ * state parameter. The power state parameter has to be a composite power
+ * state.
+ ******************************************************************************/
+int qti_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ int i;
+
+ assert(req_state);
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
+ */
+ for (i = 0; !!qti_pm_idle_states[i]; i++) {
+ if (power_state == qti_pm_idle_states[i])
+ break;
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!qti_pm_idle_states[i])
+ return PSCI_E_INVALID_PARAMS;
+
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id &
+ QTI_LOCAL_PSTATE_MASK;
+ state_id >>= QTI_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * PLATFORM FUNCTIONS
+ ******************************************************************************/
+
+static void qti_set_cpupwrctlr_val(void)
+{
+ unsigned long val;
+
+ val = read_cpu_pwrctrl_val();
+ val |= QTI_CORE_PWRDN_EN_MASK;
+ write_cpu_pwrctrl_val(val);
+
+ isb();
+}
+
+/**
+ * CPU power on function - ideally we want a wrapper since this function is
+ * target specific. But to unblock teams.
+ */
+static int qti_cpu_power_on(u_register_t mpidr)
+{
+ int core_pos = plat_core_pos_by_mpidr(mpidr);
+
+ /* If not valid mpidr, return error */
+ if (core_pos < 0 || core_pos >= QTISECLIB_PLAT_CORE_COUNT) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ return qtiseclib_psci_node_power_on(mpidr);
+}
+
+static bool is_cpu_off(const psci_power_state_t *target_state)
+{
+ if ((target_state->pwr_domain_state[QTI_PWR_LVL0] ==
+ QTI_LOCAL_STATE_OFF) ||
+ (target_state->pwr_domain_state[QTI_PWR_LVL0] ==
+ QTI_LOCAL_STATE_DEEPOFF)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void qti_cpu_power_on_finish(const psci_power_state_t *target_state)
+{
+ const uint8_t *pwr_states =
+ (const uint8_t *)target_state->pwr_domain_state;
+ qtiseclib_psci_node_on_finish(pwr_states);
+
+ if (is_cpu_off(target_state)) {
+ plat_qti_gic_cpuif_enable();
+ }
+}
+
+static void qti_cpu_standby(plat_local_state_t cpu_state)
+{
+}
+
+static void qti_node_power_off(const psci_power_state_t *target_state)
+{
+ qtiseclib_psci_node_power_off((const uint8_t *)
+ target_state->pwr_domain_state);
+ if (is_cpu_off(target_state)) {
+ plat_qti_gic_cpuif_disable();
+ qti_set_cpupwrctlr_val();
+ }
+}
+
+static void qti_node_suspend(const psci_power_state_t *target_state)
+{
+ qtiseclib_psci_node_suspend((const uint8_t *)target_state->
+ pwr_domain_state);
+ if (is_cpu_off(target_state)) {
+ plat_qti_gic_cpuif_disable();
+ qti_set_cpupwrctlr_val();
+ }
+}
+
+static void qti_node_suspend_finish(const psci_power_state_t *target_state)
+{
+ const uint8_t *pwr_states =
+ (const uint8_t *)target_state->pwr_domain_state;
+ qtiseclib_psci_node_suspend_finish(pwr_states);
+ if (is_cpu_off(target_state)) {
+ plat_qti_gic_cpuif_enable();
+ }
+}
+
+__dead2 void qti_domain_power_down_wfi(const psci_power_state_t *target_state)
+{
+
+ /* For now just do WFI - add any target specific handling if needed */
+ psci_power_down_wfi();
+ /* We should never reach here */
+}
+
+static __dead2 void assert_ps_hold(void)
+{
+ mmio_write_32(QTI_PS_HOLD_REG, 0);
+ mdelay(1000);
+
+ /* Should be dead before reaching this. */
+ panic();
+}
+
+__dead2 void qti_system_off(void)
+{
+ qti_pmic_prepare_shutdown();
+ assert_ps_hold();
+}
+
+__dead2 void qti_system_reset(void)
+{
+ qti_pmic_prepare_reset();
+ assert_ps_hold();
+}
+
+void qti_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i = 0;
+ unsigned int state_id, power_state;
+ int size = ARRAY_SIZE(qti_pm_idle_states);
+
+ /*
+ * Find deepest state.
+ * The arm_pm_idle_states[] array has last element by default 0,
+ * so the real deepest state is second last element of that array.
+ */
+ power_state = qti_pm_idle_states[size - 2];
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] =
+ state_id & QTI_LOCAL_PSTATE_MASK;
+ state_id >>= QTI_LOCAL_PSTATE_WIDTH;
+ }
+}
+
+/*
+ * Structure containing platform specific PSCI operations. Common
+ * PSCI layer will use this.
+ */
+const plat_psci_ops_t plat_qti_psci_pm_ops = {
+ .pwr_domain_on = qti_cpu_power_on,
+ .pwr_domain_on_finish = qti_cpu_power_on_finish,
+ .cpu_standby = qti_cpu_standby,
+ .pwr_domain_off = qti_node_power_off,
+ .pwr_domain_suspend = qti_node_suspend,
+ .pwr_domain_suspend_finish = qti_node_suspend_finish,
+ .pwr_domain_pwr_down_wfi = qti_domain_power_down_wfi,
+ .system_off = qti_system_off,
+ .system_reset = qti_system_reset,
+ .get_node_hw_state = NULL,
+ .translate_power_state_by_mpidr = NULL,
+ .get_sys_suspend_power_state = qti_get_sys_suspend_power_state,
+ .validate_power_state = qti_validate_power_state,
+};
+
+/**
+ * The QTI Standard platform definition of platform porting API
+ * `plat_setup_psci_ops`.
+ */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ int err;
+
+ err = qtiseclib_psci_init((uintptr_t)bl31_warm_entrypoint);
+ if (err == PSCI_E_SUCCESS) {
+ *psci_ops = &plat_qti_psci_pm_ops;
+ }
+
+ return err;
+}
diff --git a/plat/qti/common/src/qti_rng.c b/plat/qti/common/src/qti_rng.c
new file mode 100644
index 0000000..f63f3b8
--- /dev/null
+++ b/plat/qti/common/src/qti_rng.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stddef.h>
+
+#include <lib/mmio.h>
+
+#include <qti_rng.h>
+#include <qti_rng_io.h>
+
+int qti_rng_get_data(uint8_t *out, uint32_t out_len)
+{
+ uint32_t tmp_rndm = 0;
+ uint32_t bytes_left = out_len;
+ int i = 0;
+
+ if (NULL == out || 0 == out_len) {
+ return -1;
+ }
+
+ /*
+ * RNG HW initialized at previous boot image.
+ * RNG clocks are expected to be ON.
+ */
+
+ do {
+ /* There is no data to read */
+ if ((mmio_read_32(SEC_PRNG_STATUS) &
+ SEC_PRNG_STATUS_DATA_AVAIL_BMSK) == 0) {
+ continue;
+ }
+
+ while ((tmp_rndm = mmio_read_32(SEC_PRNG_DATA_OUT)) == 0) {
+ ;
+ }
+
+ for (i = 0; i < 4; i++) {
+ *out = (uint8_t) (tmp_rndm >> (8 * i));
+
+ out++;
+ bytes_left--;
+
+ if (bytes_left == 0) {
+ break;
+ }
+ }
+
+ } while (bytes_left != 0);
+
+ return 0;
+}
diff --git a/plat/qti/common/src/qti_stack_protector.c b/plat/qti/common/src/qti_stack_protector.c
new file mode 100644
index 0000000..572830f
--- /dev/null
+++ b/plat/qti/common/src/qti_stack_protector.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform.h>
+#include <platform_def.h>
+#include <qti_rng.h>
+#include <qtiseclib_interface.h>
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ u_register_t random = 0x0;
+
+ /*
+ * get random data , the below API doesn't return random = 0 on success
+ */
+ qti_rng_get_data((uint8_t *) &random, sizeof(random));
+ assert(random != 0x0);
+
+ return random;
+}
diff --git a/plat/qti/common/src/qti_syscall.c b/plat/qti/common/src/qti_syscall.c
new file mode 100644
index 0000000..d8e5be9
--- /dev/null
+++ b/plat/qti/common/src/qti_syscall.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <context.h>
+#include <lib/coreboot.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <smccc_helpers.h>
+#include <tools_share/uuid.h>
+
+#include <qti_plat.h>
+#include <qti_secure_io_cfg.h>
+#include <qtiseclib_interface.h>
+
+/*
+ * SIP service - SMC function IDs for SiP Service queries
+ *
+ */
+#define QTI_SIP_SVC_CALL_COUNT_ID U(0x0200ff00)
+#define QTI_SIP_SVC_UID_ID U(0x0200ff01)
+/* 0x8200ff02 is reserved*/
+#define QTI_SIP_SVC_VERSION_ID U(0x0200ff03)
+#define QTI_SIP_SVC_AVAILABLE_ID U(0x02000601)
+/*
+ * Syscall's to allow Non Secure world accessing peripheral/IO memory
+ * those are secure/proteced BUT not required to be secure.
+ */
+#define QTI_SIP_SVC_SECURE_IO_READ_ID U(0x02000501)
+#define QTI_SIP_SVC_SECURE_IO_WRITE_ID U(0x02000502)
+
+/*
+ * Syscall's to assigns a list of intermediate PAs from a
+ * source Virtual Machine (VM) to a destination VM.
+ */
+#define QTI_SIP_SVC_MEM_ASSIGN_ID U(0x02000C16)
+
+#define QTI_SIP_SVC_SECURE_IO_READ_PARAM_ID U(0x1)
+#define QTI_SIP_SVC_SECURE_IO_WRITE_PARAM_ID U(0x2)
+#define QTI_SIP_SVC_MEM_ASSIGN_PARAM_ID U(0x1117)
+
+#define QTI_SIP_SVC_CALL_COUNT U(0x3)
+#define QTI_SIP_SVC_VERSION_MAJOR U(0x0)
+#define QTI_SIP_SVC_VERSION_MINOR U(0x0)
+
+#define QTI_VM_LAST U(44)
+#define SIZE4K U(0x1000)
+#define QTI_VM_MAX_LIST_SIZE U(0x20)
+
+#define FUNCID_OEN_NUM_MASK ((FUNCID_OEN_MASK << FUNCID_OEN_SHIFT)\
+ |(FUNCID_NUM_MASK << FUNCID_NUM_SHIFT))
+
+enum {
+ QTI_SIP_SUCCESS = 0,
+ QTI_SIP_NOT_SUPPORTED = -1,
+ QTI_SIP_PREEMPTED = -2,
+ QTI_SIP_INVALID_PARAM = -3,
+};
+
+/* QTI SiP Service UUID */
+DEFINE_SVC_UUID2(qti_sip_svc_uid,
+ 0x43864748, 0x217f, 0x41ad, 0xaa, 0x5a,
+ 0xba, 0xe7, 0x0f, 0xa5, 0x52, 0xaf);
+
+static bool qti_is_secure_io_access_allowed(u_register_t addr)
+{
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(qti_secure_io_allowed_regs); i++) {
+ if ((uintptr_t) addr == qti_secure_io_allowed_regs[i]) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool qti_check_syscall_availability(u_register_t smc_fid)
+{
+ switch (smc_fid) {
+ case QTI_SIP_SVC_CALL_COUNT_ID:
+ case QTI_SIP_SVC_UID_ID:
+ case QTI_SIP_SVC_VERSION_ID:
+ case QTI_SIP_SVC_AVAILABLE_ID:
+ case QTI_SIP_SVC_SECURE_IO_READ_ID:
+ case QTI_SIP_SVC_SECURE_IO_WRITE_ID:
+ case QTI_SIP_SVC_MEM_ASSIGN_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool qti_mem_assign_validate_param(memprot_info_t *mem_info,
+ u_register_t u_num_mappings,
+ uint32_t *source_vm_list,
+ u_register_t src_vm_list_cnt,
+ memprot_dst_vm_perm_info_t *dest_vm_list,
+ u_register_t dst_vm_list_cnt)
+{
+ int i;
+
+ if (!source_vm_list || !dest_vm_list || !mem_info
+ || (src_vm_list_cnt == 0)
+ || (src_vm_list_cnt >= QTI_VM_LAST) || (dst_vm_list_cnt == 0)
+ || (dst_vm_list_cnt >= QTI_VM_LAST) || (u_num_mappings == 0)
+ || u_num_mappings > QTI_VM_MAX_LIST_SIZE) {
+ ERROR("vm count is 0 or more then QTI_VM_LAST or empty list\n");
+ ERROR("source_vm_list %p dest_vm_list %p mem_info %p src_vm_list_cnt %u dst_vm_list_cnt %u u_num_mappings %u\n",
+ source_vm_list, dest_vm_list, mem_info,
+ (unsigned int)src_vm_list_cnt,
+ (unsigned int)dst_vm_list_cnt,
+ (unsigned int)u_num_mappings);
+ return false;
+ }
+ for (i = 0; i < u_num_mappings; i++) {
+ if ((mem_info[i].mem_addr & (SIZE4K - 1))
+ || (mem_info[i].mem_size == 0)
+ || (mem_info[i].mem_size & (SIZE4K - 1))) {
+ ERROR("mem_info passed buffer 0x%x or size 0x%x is not 4k aligned\n",
+ (unsigned int)mem_info[i].mem_addr,
+ (unsigned int)mem_info[i].mem_size);
+ return false;
+ }
+
+ if ((mem_info[i].mem_addr + mem_info[i].mem_size) <
+ mem_info[i].mem_addr) {
+ ERROR("overflow in mem_addr 0x%x add mem_size 0x%x\n",
+ (unsigned int)mem_info[i].mem_addr,
+ (unsigned int)mem_info[i].mem_size);
+ return false;
+ }
+ coreboot_memory_t mem_type = coreboot_get_memory_type(
+ mem_info[i].mem_addr,
+ mem_info[i].mem_size);
+ if (mem_type != CB_MEM_RAM && mem_type != CB_MEM_RESERVED) {
+ ERROR("memory region not in CB MEM RAM or RESERVED area: region start 0x%x size 0x%x\n",
+ (unsigned int)mem_info[i].mem_addr,
+ (unsigned int)mem_info[i].mem_size);
+ return false;
+ }
+ }
+ for (i = 0; i < src_vm_list_cnt; i++) {
+ if (source_vm_list[i] >= QTI_VM_LAST) {
+ ERROR("source_vm_list[%d] 0x%x is more then QTI_VM_LAST\n",
+ i, (unsigned int)source_vm_list[i]);
+ return false;
+ }
+ }
+ for (i = 0; i < dst_vm_list_cnt; i++) {
+ if (dest_vm_list[i].dst_vm >= QTI_VM_LAST) {
+ ERROR("dest_vm_list[%d] 0x%x is more then QTI_VM_LAST\n",
+ i, (unsigned int)dest_vm_list[i].dst_vm);
+ return false;
+ }
+ }
+ return true;
+}
+
+static uintptr_t qti_sip_mem_assign(void *handle, uint32_t smc_cc,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3, u_register_t x4)
+{
+ uintptr_t dyn_map_start = 0, dyn_map_end = 0;
+ size_t dyn_map_size = 0;
+ u_register_t x6, x7;
+ int ret = QTI_SIP_NOT_SUPPORTED;
+ u_register_t x5 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X5);
+
+ if (smc_cc == SMC_32) {
+ x5 = (uint32_t) x5;
+ }
+ /* Validate input arg count & retrieve arg3-6 from NS Buffer. */
+ if ((x1 != QTI_SIP_SVC_MEM_ASSIGN_PARAM_ID) || (x5 == 0x0)) {
+ ERROR("invalid mem_assign param id or no mapping info\n");
+ goto unmap_return;
+ }
+
+ /* Map NS Buffer. */
+ dyn_map_start = x5;
+ dyn_map_size =
+ (smc_cc ==
+ SMC_32) ? (sizeof(uint32_t) * 4) : (sizeof(uint64_t) * 4);
+ if (qti_mmap_add_dynamic_region(dyn_map_start, dyn_map_size,
+ (MT_NS | MT_RO_DATA)) != 0) {
+ ERROR("map failed for params NS Buffer %x %x\n",
+ (unsigned int)dyn_map_start, (unsigned int)dyn_map_size);
+ goto unmap_return;
+ }
+ /* Retrieve indirect args. */
+ if (smc_cc == SMC_32) {
+ x6 = *((uint32_t *) x5 + 1);
+ x7 = *((uint32_t *) x5 + 2);
+ x5 = *(uint32_t *) x5;
+ } else {
+ x6 = *((uint64_t *) x5 + 1);
+ x7 = *((uint64_t *) x5 + 2);
+ x5 = *(uint64_t *) x5;
+ }
+ /* Un-Map NS Buffer. */
+ if (qti_mmap_remove_dynamic_region(dyn_map_start, dyn_map_size) != 0) {
+ ERROR("unmap failed for params NS Buffer %x %x\n",
+ (unsigned int)dyn_map_start, (unsigned int)dyn_map_size);
+ goto unmap_return;
+ }
+
+ /*
+ * Map NS Buffers.
+ * arg0,2,4 points to buffers & arg1,3,5 hold sizes.
+ * MAP api's fail to map if it's already mapped. Let's
+ * find lowest start & highest end address, then map once.
+ */
+ dyn_map_start = MIN(x2, x4);
+ dyn_map_start = MIN(dyn_map_start, x6);
+ dyn_map_end = MAX((x2 + x3), (x4 + x5));
+ dyn_map_end = MAX(dyn_map_end, (x6 + x7));
+ dyn_map_size = dyn_map_end - dyn_map_start;
+
+ if (qti_mmap_add_dynamic_region(dyn_map_start, dyn_map_size,
+ (MT_NS | MT_RO_DATA)) != 0) {
+ ERROR("map failed for params NS Buffer2 %x %x\n",
+ (unsigned int)dyn_map_start, (unsigned int)dyn_map_size);
+ goto unmap_return;
+ }
+ memprot_info_t *mem_info_p = (memprot_info_t *) x2;
+ uint32_t u_num_mappings = x3 / sizeof(memprot_info_t);
+ uint32_t *source_vm_list_p = (uint32_t *) x4;
+ uint32_t src_vm_list_cnt = x5 / sizeof(uint32_t);
+ memprot_dst_vm_perm_info_t *dest_vm_list_p =
+ (memprot_dst_vm_perm_info_t *) x6;
+ uint32_t dst_vm_list_cnt =
+ x7 / sizeof(memprot_dst_vm_perm_info_t);
+ if (qti_mem_assign_validate_param(mem_info_p, u_num_mappings,
+ source_vm_list_p, src_vm_list_cnt,
+ dest_vm_list_p,
+ dst_vm_list_cnt) != true) {
+ ERROR("Param validation failed\n");
+ goto unmap_return;
+ }
+
+ memprot_info_t mem_info[QTI_VM_MAX_LIST_SIZE];
+ /* Populating the arguments */
+ for (int i = 0; i < u_num_mappings; i++) {
+ mem_info[i].mem_addr = mem_info_p[i].mem_addr;
+ mem_info[i].mem_size = mem_info_p[i].mem_size;
+ }
+
+ memprot_dst_vm_perm_info_t dest_vm_list[QTI_VM_LAST];
+
+ for (int i = 0; i < dst_vm_list_cnt; i++) {
+ dest_vm_list[i].dst_vm = dest_vm_list_p[i].dst_vm;
+ dest_vm_list[i].dst_vm_perm = dest_vm_list_p[i].dst_vm_perm;
+ dest_vm_list[i].ctx = dest_vm_list_p[i].ctx;
+ dest_vm_list[i].ctx_size = dest_vm_list_p[i].ctx_size;
+ }
+
+ uint32_t source_vm_list[QTI_VM_LAST];
+
+ for (int i = 0; i < src_vm_list_cnt; i++) {
+ source_vm_list[i] = source_vm_list_p[i];
+ }
+ /* Un-Map NS Buffers. */
+ if (qti_mmap_remove_dynamic_region(dyn_map_start,
+ dyn_map_size) != 0) {
+ ERROR("unmap failed for params NS Buffer %x %x\n",
+ (unsigned int)dyn_map_start, (unsigned int)dyn_map_size);
+ goto unmap_return;
+ }
+ /* Invoke API lib api. */
+ ret = qtiseclib_mem_assign(mem_info, u_num_mappings,
+ source_vm_list, src_vm_list_cnt,
+ dest_vm_list, dst_vm_list_cnt);
+
+ if (ret == 0) {
+ SMC_RET2(handle, QTI_SIP_SUCCESS, ret);
+ }
+unmap_return:
+ /* Un-Map NS Buffers if mapped */
+ if (dyn_map_start && dyn_map_size) {
+ qti_mmap_remove_dynamic_region(dyn_map_start, dyn_map_size);
+ }
+
+ SMC_RET2(handle, QTI_SIP_INVALID_PARAM, ret);
+}
+
+/*
+ * This function handles QTI specific syscalls. Currently only SiP calls are present.
+ * Both FAST & YIELD type call land here.
+ */
+static uintptr_t qti_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie, void *handle, u_register_t flags)
+{
+ uint32_t l_smc_fid = smc_fid & FUNCID_OEN_NUM_MASK;
+
+ if (GET_SMC_CC(smc_fid) == SMC_32) {
+ x1 = (uint32_t) x1;
+ x2 = (uint32_t) x2;
+ x3 = (uint32_t) x3;
+ x4 = (uint32_t) x4;
+ }
+
+ switch (l_smc_fid) {
+ case QTI_SIP_SVC_CALL_COUNT_ID:
+ {
+ SMC_RET1(handle, QTI_SIP_SVC_CALL_COUNT);
+ break;
+ }
+ case QTI_SIP_SVC_UID_ID:
+ {
+ /* Return UID to the caller */
+ SMC_UUID_RET(handle, qti_sip_svc_uid);
+ break;
+ }
+ case QTI_SIP_SVC_VERSION_ID:
+ {
+ /* Return the version of current implementation */
+ SMC_RET2(handle, QTI_SIP_SVC_VERSION_MAJOR,
+ QTI_SIP_SVC_VERSION_MINOR);
+ break;
+ }
+ case QTI_SIP_SVC_AVAILABLE_ID:
+ {
+ if (x1 != 1) {
+ SMC_RET1(handle, QTI_SIP_INVALID_PARAM);
+ }
+ if (qti_check_syscall_availability(x2) == true) {
+ SMC_RET2(handle, QTI_SIP_SUCCESS, 1);
+ } else {
+ SMC_RET2(handle, QTI_SIP_SUCCESS, 0);
+ }
+ break;
+ }
+ case QTI_SIP_SVC_SECURE_IO_READ_ID:
+ {
+ if ((x1 == QTI_SIP_SVC_SECURE_IO_READ_PARAM_ID) &&
+ qti_is_secure_io_access_allowed(x2)) {
+ SMC_RET2(handle, QTI_SIP_SUCCESS,
+ *((volatile uint32_t *)x2));
+ }
+ SMC_RET1(handle, QTI_SIP_INVALID_PARAM);
+ break;
+ }
+ case QTI_SIP_SVC_SECURE_IO_WRITE_ID:
+ {
+ if ((x1 == QTI_SIP_SVC_SECURE_IO_WRITE_PARAM_ID) &&
+ qti_is_secure_io_access_allowed(x2)) {
+ *((volatile uint32_t *)x2) = x3;
+ SMC_RET1(handle, QTI_SIP_SUCCESS);
+ }
+ SMC_RET1(handle, QTI_SIP_INVALID_PARAM);
+ break;
+ }
+ case QTI_SIP_SVC_MEM_ASSIGN_ID:
+ {
+ return qti_sip_mem_assign(handle, GET_SMC_CC(smc_fid),
+ x1, x2, x3, x4);
+ break;
+ }
+ default:
+ {
+ SMC_RET1(handle, QTI_SIP_NOT_SUPPORTED);
+ }
+ }
+ return (uintptr_t) handle;
+}
+
+/* Define a runtime service descriptor for both fast & yield SiP calls */
+DECLARE_RT_SVC(qti_sip_fast_svc, OEN_SIP_START,
+ OEN_SIP_END, SMC_TYPE_FAST, NULL, qti_sip_handler);
+
+DECLARE_RT_SVC(qti_sip_yield_svc, OEN_SIP_START,
+ OEN_SIP_END, SMC_TYPE_YIELD, NULL, qti_sip_handler);
diff --git a/plat/qti/common/src/qti_topology.c b/plat/qti/common/src/qti_topology.c
new file mode 100644
index 0000000..bf2e3f3
--- /dev/null
+++ b/plat/qti/common/src/qti_topology.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018,2020 The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+
+#include <platform_def.h>
+#include <qti_plat.h>
+
+/* The QTI power domain tree descriptor */
+const unsigned char qti_power_domain_tree_desc[] = {
+ /* One domain to represent PDC */
+ PLAT_PDC_COUNT,
+ /* One domain to represent RSC */
+ PLAT_RSC_COUNT,
+ /* There is one top-level FCM cluster */
+ PLAT_CLUSTER_COUNT,
+ /* No. of cores in the FCM cluster */
+ PLAT_CLUSTER0_CORE_COUNT
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return qti_power_domain_tree_desc;
+}
+
+/** Function: plat_core_pos_by_mpidr
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ */
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ int core_linear_index = plat_qti_core_pos_by_mpidr(mpidr);
+
+ if (core_linear_index < PLATFORM_CORE_COUNT) {
+ return core_linear_index;
+ } else {
+ return -1;
+ }
+}
diff --git a/plat/qti/common/src/spmi_arb.c b/plat/qti/common/src/spmi_arb.c
new file mode 100644
index 0000000..4213ed1
--- /dev/null
+++ b/plat/qti/common/src/spmi_arb.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2020, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <spmi_arb.h>
+
+#define REG_APID_MAP(apid) (0x0C440900U + sizeof(uint32_t) * apid)
+#define NUM_APID ((0x1100U - 0x900U) / sizeof(uint32_t))
+
+#define PPID_MASK (0xfffU << 8)
+
+#define REG_ARB_CMD(apid) (0x0C600000U + 0x10000U * apid)
+/* These are opcodes specific to this SPMI arbitrator, *not* SPMI commands. */
+#define OPC_EXT_WRITEL 0
+#define OPC_EXT_READL 1
+
+#define REG_ARB_STATUS(apid) (0x0C600008U + 0x10000U * apid)
+#define ARB_STATUS_DONE BIT(0)
+#define ARB_STATUS_FAILURE BIT(1)
+#define ARB_STATUS_DENIED BIT(2)
+#define ARB_STATUS_DROPPED BIT(3)
+
+/* Fake status to report driver errors. */
+#define ARB_FAKE_STATUS_TIMEOUT BIT(8)
+
+#define REG_ARB_RDATA0(apid) (0x0C600018U + 0x10000U * apid)
+#define REG_ARB_WDATA0(apid) (0x0C600010U + 0x10000U * apid)
+
+static int addr_to_apid(uint32_t addr)
+{
+ unsigned int i;
+
+ for (i = 0U; i < NUM_APID; i++) {
+ uint32_t reg = mmio_read_32(REG_APID_MAP(i));
+ if ((reg != 0U) && ((addr & PPID_MASK) == (reg & PPID_MASK))) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int wait_for_done(uint16_t apid)
+{
+ unsigned int timeout = 100;
+
+ while (timeout-- != 0U) {
+ uint32_t status = mmio_read_32(REG_ARB_STATUS(apid));
+ if ((status & ARB_STATUS_DONE) != 0U) {
+ if ((status & ARB_STATUS_FAILURE) != 0U ||
+ (status & ARB_STATUS_DENIED) != 0U ||
+ (status & ARB_STATUS_DROPPED) != 0U) {
+ return status & 0xff;
+ }
+ return 0;
+ }
+ mdelay(1);
+ }
+ ERROR("SPMI_ARB timeout!\n");
+ return ARB_FAKE_STATUS_TIMEOUT;
+}
+
+static void arb_command(uint16_t apid, uint8_t opcode, uint32_t addr,
+ uint8_t bytes)
+{
+ mmio_write_32(REG_ARB_CMD(apid), (uint32_t)opcode << 27 |
+ (addr & 0xff) << 4 | (bytes - 1));
+}
+
+int spmi_arb_read8(uint32_t addr)
+{
+ int apid = addr_to_apid(addr);
+
+ if (apid < 0) {
+ return apid;
+ }
+
+ arb_command(apid, OPC_EXT_READL, addr, 1);
+
+ int ret = wait_for_done(apid);
+ if (ret != 0) {
+ ERROR("SPMI_ARB read error [0x%x]: 0x%x\n", addr, ret);
+ return ret;
+ }
+
+ return mmio_read_32(REG_ARB_RDATA0(apid)) & 0xff;
+}
+
+int spmi_arb_write8(uint32_t addr, uint8_t data)
+{
+ int apid = addr_to_apid(addr);
+
+ if (apid < 0) {
+ return apid;
+ }
+
+ mmio_write_32(REG_ARB_WDATA0(apid), data);
+ arb_command(apid, OPC_EXT_WRITEL, addr, 1);
+
+ int ret = wait_for_done(apid);
+ if (ret != 0) {
+ ERROR("SPMI_ARB write error [0x%x] = 0x%x: 0x%x\n",
+ addr, data, ret);
+ }
+
+ return ret;
+}
diff --git a/plat/qti/msm8916/aarch64/msm8916_helpers.S b/plat/qti/msm8916/aarch64/msm8916_helpers.S
new file mode 100644
index 0000000..dad9968
--- /dev/null
+++ b/plat/qti/msm8916/aarch64/msm8916_helpers.S
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+#include <msm8916_mmap.h>
+
+#define APCS_TCM_START_ADDR 0x10
+#define APCS_TCM_REDIRECT_EN_0 BIT_32(0)
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_panic_handler
+ .globl plat_my_core_pos
+ .globl plat_get_my_entrypoint
+ .globl plat_reset_handler
+ .globl platform_mem_init
+ .globl msm8916_entry_point
+
+ /* -------------------------------------------------
+ * int plat_crash_console_init(void)
+ * Initialize the crash console.
+ * Out: x0 - 1 on success, 0 on error
+ * Clobber list : x0 - x4
+ * -------------------------------------------------
+ */
+func plat_crash_console_init
+ mov x1, #BLSP_UART2_BASE
+
+ /*
+ * If the non-secure world has been actively using the UART there might
+ * be still some characters left to be sent in the FIFO. In that case,
+ * resetting the transmitter too early might cause all output to become
+ * corrupted. To avoid that, try to flush (wait until FIFO empty) first.
+ */
+ mov x4, lr
+ bl console_uartdm_core_flush
+ mov lr, x4
+
+ mov x0, #1
+ b console_uartdm_core_init
+endfunc plat_crash_console_init
+
+ /* -------------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Print a character on the crash console.
+ * In : w0 - character to be printed
+ * Out: w0 - printed character on success
+ * Clobber list : x1, x2
+ * -------------------------------------------------
+ */
+func plat_crash_console_putc
+ mov x1, #BLSP_UART2_BASE
+ b console_uartdm_core_putc
+endfunc plat_crash_console_putc
+
+ /* -------------------------------------------------
+ * void plat_crash_console_flush(void)
+ * Force a write of all buffered data that has not
+ * been output.
+ * Clobber list : x1, x2
+ * -------------------------------------------------
+ */
+func plat_crash_console_flush
+ mov x1, #BLSP_UART2_BASE
+ b console_uartdm_core_flush
+endfunc plat_crash_console_flush
+
+ /* -------------------------------------------------
+ * void plat_panic_handler(void) __dead
+ * Called when an unrecoverable error occurs.
+ * -------------------------------------------------
+ */
+func plat_panic_handler
+ /* Try to shutdown/reset */
+ mov_imm x0, MPM_PS_HOLD
+ str wzr, [x0]
+1: b 1b
+endfunc plat_panic_handler
+
+ /* -------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * Out: x0 - index of the calling CPU
+ * -------------------------------------------------
+ */
+func plat_my_core_pos
+ /* There is just a single cluster so this is very simple */
+ mrs x0, mpidr_el1
+ and x0, x0, #MPIDR_CPU_MASK
+ ret
+endfunc plat_my_core_pos
+
+ /* -------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint(void)
+ * Distinguish cold and warm boot and return warm boot
+ * entry address if available.
+ * Out: x0 - warm boot entry point or 0 on cold boot
+ * -------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ ldr x0, msm8916_entry_point
+ ret
+endfunc plat_get_my_entrypoint
+
+ /* -------------------------------------------------
+ * void plat_reset_handler(void)
+ * Perform additional initialization after reset.
+ * Clobber list : x0 - x18, x30
+ * -------------------------------------------------
+ */
+func plat_reset_handler
+ /*
+ * Check if the CPU is running at the correct address.
+ * During cold boot the CPU enters here at the wrong address
+ * using the "boot remapper". (It remaps the BL31_BASE to
+ * the CPU reset address 0x0).
+ */
+ mov x0, #BL31_BASE
+ adr x1, bl31_entrypoint
+ cmp x0, x1
+ b.ne _remapped_cold_boot
+ /* Already running at correct address, just return directly */
+ ret
+
+_remapped_cold_boot:
+ /*
+ * The previous boot stage seems to use the L2 cache as TCM.
+ * Disable the TCM redirect before enabling caches to avoid
+ * strange crashes.
+ */
+ mov x2, #APCS_CFG
+ ldr w3, [x2, #APCS_TCM_START_ADDR]
+ and w3, w3, #~APCS_TCM_REDIRECT_EN_0
+ str w3, [x2, #APCS_TCM_START_ADDR]
+
+ /* Enter BL31 again at the real address */
+ br x0
+endfunc plat_reset_handler
+
+ /* -------------------------------------------------
+ * void platform_mem_init(void)
+ * Performs additional memory initialization early
+ * in the boot process.
+ * -------------------------------------------------
+ */
+func platform_mem_init
+ /* Nothing to do here, all memory is already initialized */
+ ret
+endfunc platform_mem_init
+
+ .data
+ .align 3
+
+ /* -------------------------------------------------
+ * Warm boot entry point for CPU. Set by PSCI code.
+ * -------------------------------------------------
+ */
+msm8916_entry_point:
+ .quad 0
diff --git a/plat/qti/msm8916/aarch64/uartdm_console.S b/plat/qti/msm8916/aarch64/uartdm_console.S
new file mode 100644
index 0000000..c69c193
--- /dev/null
+++ b/plat/qti/msm8916/aarch64/uartdm_console.S
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * Based on aarch64/skeleton_console.S:
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <console_macros.S>
+
+/* UART DM registers */
+#define UART_DM_DMEN 0x03c /* DMA / data packing */
+#define UART_DM_SR 0x0a4 /* status register */
+#define UART_DM_CR 0x0a8 /* command register */
+#define UART_DM_TF 0x100 /* transmit FIFO */
+
+#define UART_DM_DMEN_TX_SC BIT_32(4) /* TX single character mode */
+
+#define UART_DM_SR_TXRDY_BIT 2 /* TX FIFO has space */
+#define UART_DM_SR_TXEMT_BIT 3 /* TX FIFO is empty */
+
+#define UART_DM_CR_RESET_RX (U(0x01) << 4) /* reset receiver */
+#define UART_DM_CR_RESET_TX (U(0x02) << 4) /* reset transmitter */
+#define UART_DM_CR_TX_ENABLE BIT_32(2) /* enable transmitter */
+
+ .globl console_uartdm_register
+ .globl console_uartdm_core_init
+ .globl console_uartdm_putc
+ .globl console_uartdm_core_putc
+ .globl console_uartdm_flush
+ .globl console_uartdm_core_flush
+
+ /* -----------------------------------------------------------
+ * int console_uartdm_register(console_t *console,
+ * uintptr_t base_addr)
+ * Function to initialize and register the console. The caller
+ * needs to pass an empty console_t structure in which *MUST*
+ * be allocated in persistent memory (e.g. a global or static
+ * local variable, *NOT* on the stack).
+ * In : x0 - pointer to empty console_t structure
+ * x1 - base address
+ * Out: x0 - 1 on success, 0 on error
+ * Clobber list : x0 - x7
+ * -----------------------------------------------------------
+ */
+func console_uartdm_register
+ str x1, [x0, #CONSOLE_T_BASE]
+ mov x7, lr
+ bl console_uartdm_core_init
+ mov lr, x7
+
+ /* Register the new console */
+ finish_console_register uartdm putc=1, flush=1
+endfunc console_uartdm_register
+
+ /* -----------------------------------------------------------
+ * void console_uartdm_core_init(unused, uintptr_t base_addr)
+ * Function to initialize the console.
+ * In : x0 - unused
+ * x1 - base address
+ * Out: void
+ * Clobber list : x1, x2, x3
+ * -----------------------------------------------------------
+ */
+func console_uartdm_core_init
+ /* Reset receiver */
+ mov w3, #UART_DM_CR_RESET_RX
+ str w3, [x1, #UART_DM_CR]
+
+ /* Reset transmitter */
+ mov w3, #UART_DM_CR_RESET_TX
+ str w3, [x1, #UART_DM_CR]
+
+ /*
+ * Disable BAM/DMA modes but enable single-character mode for TX.
+ * The single character mode allows simplifying the putc implementation
+ * since characters can be written directly to the FIFO instead of
+ * having to initiate a new transfer and waiting for its completion.
+ */
+ mov w3, #UART_DM_DMEN_TX_SC
+ str w3, [x1, #UART_DM_DMEN]
+
+ /* Enable transmitter */
+ mov w3, #UART_DM_CR_TX_ENABLE
+ str w3, [x1, #UART_DM_CR]
+
+ ret
+endfunc console_uartdm_core_init
+
+ /* -----------------------------------------------------------
+ * int console_uartdm_putc(int c, console_t *console)
+ * Function to output a character over the console.
+ * In : w0 - character to be printed
+ * x1 - pointer to console_t struct
+ * Out: w0 - printed character on success, < 0 on error.
+ * Clobber list : x0, x1, x2
+ * -----------------------------------------------------------
+ */
+func console_uartdm_putc
+ ldr x1, [x1, #CONSOLE_T_BASE]
+ b console_uartdm_core_putc
+endfunc console_uartdm_putc
+
+ /* -----------------------------------------------------------
+ * int console_uartdm_core_putc(int c, uintptr_t base_addr)
+ * Function to output a character over the console.
+ * In : w0 - character to be printed
+ * x1 - base address
+ * Out: w0 - printed character on success, < 0 on error.
+ * Clobber list : x2
+ * -----------------------------------------------------------
+ */
+func console_uartdm_core_putc
+1: /* Loop until TX FIFO has space */
+ ldr w2, [x1, #UART_DM_SR]
+ tbz w2, #UART_DM_SR_TXRDY_BIT, 1b
+
+ /* Write character to FIFO */
+ str w0, [x1, #UART_DM_TF]
+ ret
+endfunc console_uartdm_core_putc
+
+ /* -----------------------------------------------------------
+ * void console_uartdm_flush(console_t *console)
+ * Function to force a write of all buffered data
+ * that has not been output.
+ * In : x0 - pointer to console_t struct
+ * Out: void
+ * Clobber list : x0, x1, x2, x3, x4, x5
+ * -----------------------------------------------------------
+ */
+func console_uartdm_flush
+ ldr x1, [x0, #CONSOLE_T_BASE]
+ b console_uartdm_core_flush
+endfunc console_uartdm_flush
+
+ /* -----------------------------------------------------------
+ * void console_uartdm_core_flush(unused, uintptr_t base_addr)
+ * Function to force a write of all buffered data
+ * that has not been output.
+ * In : x0 - unused
+ * x1 - base address
+ * Out: void
+ * Clobber list : x2
+ * -----------------------------------------------------------
+ */
+func console_uartdm_core_flush
+1: /* Loop until TX FIFO is empty */
+ ldr w2, [x1, #UART_DM_SR]
+ tbz w2, #UART_DM_SR_TXEMT_BIT, 1b
+ ret
+endfunc console_uartdm_core_flush
diff --git a/plat/qti/msm8916/include/msm8916_mmap.h b/plat/qti/msm8916/include/msm8916_mmap.h
new file mode 100644
index 0000000..406ae6b
--- /dev/null
+++ b/plat/qti/msm8916/include/msm8916_mmap.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MSM8916_MMAP_H
+#define MSM8916_MMAP_H
+
+#define PCNOC_BASE 0x00000000
+#define PCNOC_SIZE 0x8000000 /* 128 MiB */
+#define APCS_BASE 0x0b000000
+#define APCS_SIZE 0x800000 /* 8 MiB */
+
+#define MPM_BASE (PCNOC_BASE + 0x04a0000)
+#define MPM_PS_HOLD (MPM_BASE + 0xb000)
+
+#define TLMM_BASE (PCNOC_BASE + 0x1000000)
+#define TLMM_GPIO_CFG(n) (TLMM_BASE + ((n) * 0x1000))
+
+#define GCC_BASE (PCNOC_BASE + 0x1800000)
+
+#define APPS_SMMU_BASE (PCNOC_BASE + 0x1e00000)
+#define APPS_SMMU_QCOM (APPS_SMMU_BASE + 0xf0000)
+
+#define BLSP_UART1_BASE (PCNOC_BASE + 0x78af000)
+#define BLSP_UART2_BASE (PCNOC_BASE + 0x78b0000)
+
+#define APCS_QGIC2_BASE (APCS_BASE + 0x00000)
+#define APCS_QGIC2_GICD (APCS_QGIC2_BASE + 0x0000)
+#define APCS_QGIC2_GICC (APCS_QGIC2_BASE + 0x2000)
+#define APCS_BANKED_ACS (APCS_BASE + 0x08000)
+#define APCS_BANKED_SAW2 (APCS_BASE + 0x09000)
+#define APCS_CFG (APCS_BASE + 0x10000)
+#define APCS_GLB (APCS_BASE + 0x11000)
+#define APCS_L2_SAW2 (APCS_BASE + 0x12000)
+#define APCS_QTMR (APCS_BASE + 0x20000)
+#define APCS_ALIAS_ACS(cpu) (APCS_BASE + 0x88000 + ((cpu) * 0x10000))
+#define APCS_ALIAS_SAW2(cpu) (APCS_BASE + 0x89000 + ((cpu) * 0x10000))
+
+#endif /* MSM8916_MMAP_H */
diff --git a/plat/qti/msm8916/include/plat_macros.S b/plat/qti/msm8916/include/plat_macros.S
new file mode 100644
index 0000000..552add2
--- /dev/null
+++ b/plat/qti/msm8916/include/plat_macros.S
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+
+#include <msm8916_mmap.h>
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC registers whenever
+ * an unhandled exception is taken in BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x16, APCS_QGIC2_GICD
+ mov_imm x17, APCS_QGIC2_GICC
+ arm_print_gic_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/qti/msm8916/include/platform_def.h b/plat/qti/msm8916/include/platform_def.h
new file mode 100644
index 0000000..bfade70
--- /dev/null
+++ b/plat/qti/msm8916/include/platform_def.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat/common/common_def.h>
+
+/*
+ * There is at least 1 MiB available for BL31. However, at the moment the
+ * "msm8916_entry_point" variable in the data section is read through the
+ * 64 KiB region of the "boot remapper" after reset. For simplicity, limit
+ * the end of the data section (BL31_PROGBITS_LIMIT) to 64 KiB for now and
+ * the overall limit to 128 KiB. This could be increased if needed by placing
+ * the "msm8916_entry_point" variable explicitly in the first 64 KiB of BL31.
+ */
+#define BL31_LIMIT (BL31_BASE + 0x20000) /* 128 KiB */
+#define BL31_PROGBITS_LIMIT (BL31_BASE + 0x10000) /* 64 KiB */
+
+#define CACHE_WRITEBACK_GRANULE U(64)
+#define PLATFORM_STACK_SIZE U(0x1000)
+
+/* CPU topology: single cluster with 4 cores */
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
+ PLATFORM_MAX_CPUS_PER_CLUSTER)
+
+/* Power management */
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+#define PLAT_MAX_RET_STATE U(2)
+#define PLAT_MAX_OFF_STATE U(3)
+
+/* Translation tables */
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 4
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+/* Timer frequency */
+#define PLAT_SYSCNT_FREQ 19200000
+
+/*
+ * The Qualcomm QGIC2 implementation seems to have PIDR0-4 and PIDR4-7
+ * erroneously swapped for some reason. PIDR2 is actually at 0xFD8.
+ * Override the address in <drivers/arm/gicv2.h> to avoid a failing assert().
+ */
+#define GICD_PIDR2_GICV2 U(0xFD8)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/msm8916/include/uartdm_console.h b/plat/qti/msm8916/include/uartdm_console.h
new file mode 100644
index 0000000..0f09ba8
--- /dev/null
+++ b/plat/qti/msm8916/include/uartdm_console.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UARTDM_CONSOLE_H
+#define UARTDM_CONSOLE_H
+
+int console_uartdm_register(console_t *console, uintptr_t base_addr);
+
+#endif /* UARTDM_CONSOLE_H */
diff --git a/plat/qti/msm8916/msm8916_bl31_setup.c b/plat/qti/msm8916/msm8916_bl31_setup.c
new file mode 100644
index 0000000..638cd09
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_bl31_setup.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include "msm8916_gicv2.h"
+#include <msm8916_mmap.h>
+#include <platform_def.h>
+#include <uartdm_console.h>
+
+static const mmap_region_t msm8916_mmap[] = {
+ MAP_REGION_FLAT(PCNOC_BASE, PCNOC_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
+ MAP_REGION_FLAT(APCS_BASE, APCS_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
+ {},
+};
+
+static struct {
+ entry_point_info_t bl32;
+ entry_point_info_t bl33;
+} image_ep_info = {
+ /* BL32 entry point */
+ SET_STATIC_PARAM_HEAD(bl32, PARAM_EP, VERSION_1,
+ entry_point_info_t, SECURE),
+ .bl32.pc = BL32_BASE,
+
+ /* BL33 entry point */
+ SET_STATIC_PARAM_HEAD(bl33, PARAM_EP, VERSION_1,
+ entry_point_info_t, NON_SECURE),
+ .bl33.pc = PRELOADED_BL33_BASE,
+ .bl33.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS),
+};
+
+static console_t console;
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return PLAT_SYSCNT_FREQ;
+}
+
+#define CLK_ENABLE BIT_32(0)
+#define CLK_OFF BIT_32(31)
+
+#define GPIO_BLSP_UART2_TX 4
+#define GPIO_BLSP_UART2_RX 5
+#define GPIO_CFG_FUNC_BLSP_UART2 (U(0x2) << 2)
+#define GPIO_CFG_DRV_STRENGTH_16MA (U(0x7) << 6)
+
+#define GCC_BLSP1_AHB_CBCR (GCC_BASE + 0x01008)
+#define GCC_BLSP1_UART2_APPS_CBCR (GCC_BASE + 0x0302c)
+#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x45004)
+#define BLSP1_AHB_CLK_ENA BIT_32(10)
+
+/*
+ * The previous boot stage seems to disable most of the UART setup before exit
+ * so it must be enabled here again before the UART console can be used.
+ */
+static void msm8916_enable_blsp_uart2(void)
+{
+ /* Route GPIOs to BLSP UART2 */
+ mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_TX),
+ GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA);
+ mmio_write_32(TLMM_GPIO_CFG(GPIO_BLSP_UART2_RX),
+ GPIO_CFG_FUNC_BLSP_UART2 | GPIO_CFG_DRV_STRENGTH_16MA);
+
+ /* Enable AHB clock */
+ mmio_setbits_32(GCC_APCS_CLOCK_BRANCH_ENA_VOTE, BLSP1_AHB_CLK_ENA);
+ while (mmio_read_32(GCC_BLSP1_AHB_CBCR) & CLK_OFF)
+ ;
+
+ /* Enable BLSP UART2 clock */
+ mmio_setbits_32(GCC_BLSP1_UART2_APPS_CBCR, CLK_ENABLE);
+ while (mmio_read_32(GCC_BLSP1_UART2_APPS_CBCR) & CLK_OFF)
+ ;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ /* Initialize the debug console as early as possible */
+ msm8916_enable_blsp_uart2();
+ console_uartdm_register(&console, BLSP_UART2_BASE);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ mmap_add_region(BL31_BASE, BL31_BASE, BL31_END - BL31_BASE,
+ MT_RW_DATA | MT_SECURE);
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+ mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+ BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE);
+ mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER);
+
+ mmap_add(msm8916_mmap);
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+
+static void msm8916_configure_timer(void)
+{
+ /* Set timer frequency */
+ mmio_write_32(APCS_QTMR + CNTCTLBASE_CNTFRQ, plat_get_syscnt_freq2());
+
+ /* Make frame 0 available to non-secure world */
+ mmio_write_32(APCS_QTMR + CNTNSAR, BIT_32(CNTNSAR_NS_SHIFT(0)));
+ mmio_write_32(APCS_QTMR + CNTACR_BASE(0),
+ BIT_32(CNTACR_RPCT_SHIFT) | BIT_32(CNTACR_RVCT_SHIFT) |
+ BIT_32(CNTACR_RFRQ_SHIFT) | BIT_32(CNTACR_RVOFF_SHIFT) |
+ BIT_32(CNTACR_RWVT_SHIFT) | BIT_32(CNTACR_RWPT_SHIFT));
+}
+
+/*
+ * The APCS register regions always start with a SECURE register that should
+ * be cleared to 0 to only allow secure access. Since BL31 handles most of
+ * the CPU power management, most of them can be cleared to secure access only.
+ */
+#define APCS_GLB_SECURE_STS_NS BIT_32(0)
+#define APCS_GLB_SECURE_PWR_NS BIT_32(1)
+#define APCS_BOOT_START_ADDR_SEC (APCS_CFG + 0x04)
+#define REMAP_EN BIT_32(0)
+#define APCS_AA64NAA32_REG (APCS_CFG + 0x0c)
+
+static void msm8916_configure_cpu_pm(void)
+{
+ unsigned int cpu;
+
+ /* Disallow non-secure access to boot remapper / TCM registers */
+ mmio_write_32(APCS_CFG, 0);
+
+ /*
+ * Disallow non-secure access to power management registers.
+ * However, allow STS and PWR since those also seem to control access
+ * to CPU frequency related registers (e.g. APCS_CMD_RCGR). If these
+ * bits are not set, CPU frequency control fails in the non-secure world.
+ */
+ mmio_write_32(APCS_GLB, APCS_GLB_SECURE_STS_NS | APCS_GLB_SECURE_PWR_NS);
+
+ /* Disallow non-secure access to L2 SAW2 */
+ mmio_write_32(APCS_L2_SAW2, 0);
+
+ /* Disallow non-secure access to CPU ACS and SAW2 */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ mmio_write_32(APCS_ALIAS_ACS(cpu), 0);
+ mmio_write_32(APCS_ALIAS_SAW2(cpu), 0);
+ }
+
+ /* Make sure all further warm boots end up in BL31 and aarch64 state */
+ CASSERT((BL31_BASE & 0xffff) == 0, assert_bl31_base_64k_aligned);
+ mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL31_BASE | REMAP_EN);
+ mmio_write_32(APCS_AA64NAA32_REG, 1);
+}
+
+/*
+ * MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU,
+ * which allows routing context bank interrupts to one of 3 interrupt numbers
+ * ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number
+ * by default to avoid special setup on the non-secure side.
+ */
+#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038)
+#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c)
+#define SMMU_CFG_CLK_ENA BIT_32(12)
+#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000)
+#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff)
+
+static void msm8916_configure_smmu(void)
+{
+ /* Enable SMMU configuration clock to enable register access */
+ mmio_setbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
+ while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF)
+ ;
+
+ /* Route all context bank interrupts to non-secure interrupt */
+ mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL);
+
+ /* Disable configuration clock again */
+ mmio_clrbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
+}
+
+void bl31_platform_setup(void)
+{
+ INFO("BL31: Platform setup start\n");
+ generic_delay_timer_init();
+ msm8916_configure_timer();
+ msm8916_gicv2_init();
+ msm8916_configure_cpu_pm();
+ msm8916_configure_smmu();
+ INFO("BL31: Platform setup done\n");
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ switch (type) {
+ case SECURE:
+ return &image_ep_info.bl32;
+ case NON_SECURE:
+ return &image_ep_info.bl33;
+ default:
+ assert(sec_state_is_valid(type));
+ return NULL;
+ }
+}
diff --git a/plat/qti/msm8916/msm8916_cpu_boot.c b/plat/qti/msm8916/msm8916_cpu_boot.c
new file mode 100644
index 0000000..b3f51f6
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_cpu_boot.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <msm8916_mmap.h>
+#include "msm8916_pm.h"
+
+#define CPU_PWR_CTL 0x4
+#define APC_PWR_GATE_CTL 0x14
+
+#define CPU_PWR_CTL_CLAMP BIT_32(0)
+#define CPU_PWR_CTL_CORE_MEM_CLAMP BIT_32(1)
+#define CPU_PWR_CTL_L1_RST_DIS BIT_32(2)
+#define CPU_PWR_CTL_CORE_MEM_HS BIT_32(3)
+#define CPU_PWR_CTL_CORE_RST BIT_32(4)
+#define CPU_PWR_CTL_COREPOR_RST BIT_32(5)
+#define CPU_PWR_CTL_GATE_CLK BIT_32(6)
+#define CPU_PWR_CTL_CORE_PWRD_UP BIT_32(7)
+
+#define APC_PWR_GATE_CTL_GHDS_EN BIT_32(0)
+#define APC_PWR_GATE_CTL_GHDS_CNT(cnt) ((cnt) << 24)
+
+/* Boot a secondary CPU core for the first time. */
+void msm8916_cpu_boot(unsigned int core)
+{
+ uintptr_t acs = APCS_ALIAS_ACS(core);
+ uint32_t pwr_ctl;
+
+ pwr_ctl = CPU_PWR_CTL_CLAMP | CPU_PWR_CTL_CORE_MEM_CLAMP |
+ CPU_PWR_CTL_CORE_RST | CPU_PWR_CTL_COREPOR_RST;
+ mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl);
+ dsb();
+
+ mmio_write_32(acs + APC_PWR_GATE_CTL, APC_PWR_GATE_CTL_GHDS_EN |
+ APC_PWR_GATE_CTL_GHDS_CNT(16));
+ dsb();
+ udelay(2);
+
+ pwr_ctl &= ~CPU_PWR_CTL_CORE_MEM_CLAMP;
+ mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl);
+ dsb();
+
+ pwr_ctl |= CPU_PWR_CTL_CORE_MEM_HS;
+ mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl);
+ dsb();
+ udelay(2);
+
+ pwr_ctl &= ~CPU_PWR_CTL_CLAMP;
+ mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl);
+ dsb();
+ udelay(2);
+
+ pwr_ctl &= ~(CPU_PWR_CTL_CORE_RST | CPU_PWR_CTL_COREPOR_RST);
+ mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl);
+ dsb();
+
+ pwr_ctl |= CPU_PWR_CTL_CORE_PWRD_UP;
+ mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl);
+ dsb();
+}
diff --git a/plat/qti/msm8916/msm8916_gicv2.c b/plat/qti/msm8916/msm8916_gicv2.c
new file mode 100644
index 0000000..25a6628
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_gicv2.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+
+#include "msm8916_gicv2.h"
+#include <msm8916_mmap.h>
+
+#define IRQ_SEC_SGI_0 8
+#define IRQ_SEC_SGI_1 9
+#define IRQ_SEC_SGI_2 10
+#define IRQ_SEC_SGI_3 11
+#define IRQ_SEC_SGI_4 12
+#define IRQ_SEC_SGI_5 13
+#define IRQ_SEC_SGI_6 14
+#define IRQ_SEC_SGI_7 15
+
+#define IRQ_SEC_PHY_TIMER (16 + 2) /* PPI #2 */
+
+static const interrupt_prop_t msm8916_interrupt_props[] = {
+ INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+};
+
+static const gicv2_driver_data_t msm8916_gic_data = {
+ .gicd_base = APCS_QGIC2_GICD,
+ .gicc_base = APCS_QGIC2_GICC,
+ .interrupt_props = msm8916_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(msm8916_interrupt_props),
+};
+
+void msm8916_gicv2_init(void)
+{
+ gicv2_driver_init(&msm8916_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
diff --git a/plat/qti/msm8916/msm8916_gicv2.h b/plat/qti/msm8916/msm8916_gicv2.h
new file mode 100644
index 0000000..99db0d3
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_gicv2.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MSM8916_GICV2_H
+#define MSM8916_GICV2_H
+
+void msm8916_gicv2_init(void);
+
+#endif /* MSM8916_GICV2_H */
diff --git a/plat/qti/msm8916/msm8916_pm.c b/plat/qti/msm8916/msm8916_pm.c
new file mode 100644
index 0000000..6891e38
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_pm.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <msm8916_mmap.h>
+#include "msm8916_pm.h"
+
+static int msm8916_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ VERBOSE("PSCI: Booting CPU %d\n", core);
+ msm8916_cpu_boot(core);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void msm8916_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static void __dead2 msm8916_system_reset(void)
+{
+ mmio_write_32(MPM_PS_HOLD, 0);
+ mdelay(1000);
+
+ ERROR("PSCI: System reset failed\n");
+ panic();
+}
+
+static const plat_psci_ops_t msm8916_psci_ops = {
+ .pwr_domain_on = msm8916_pwr_domain_on,
+ .pwr_domain_on_finish = msm8916_pwr_domain_on_finish,
+ .system_off = msm8916_system_reset,
+ .system_reset = msm8916_system_reset,
+};
+
+/* Defined and used in msm8916_helpers.S */
+extern uintptr_t msm8916_entry_point;
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ msm8916_entry_point = sec_entrypoint;
+ *psci_ops = &msm8916_psci_ops;
+ return 0;
+}
diff --git a/plat/qti/msm8916/msm8916_pm.h b/plat/qti/msm8916/msm8916_pm.h
new file mode 100644
index 0000000..5473bfa
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_pm.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MSM8916_PM_H
+#define MSM8916_PM_H
+
+void msm8916_cpu_boot(unsigned int core);
+
+#endif /* MSM8916_PM_H */
diff --git a/plat/qti/msm8916/msm8916_topology.c b/plat/qti/msm8916/msm8916_topology.c
new file mode 100644
index 0000000..4d0ed8f
--- /dev/null
+++ b/plat/qti/msm8916/msm8916_topology.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+static const unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = {
+ PLATFORM_SYSTEM_COUNT,
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_MAX_CPUS_PER_CLUSTER,
+};
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+ MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
+ MPIDR_AFFLVL1_VAL(mpidr) > 0 ||
+ core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return core;
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return plat_power_domain_tree_desc;
+}
diff --git a/plat/qti/msm8916/platform.mk b/plat/qti/msm8916/platform.mk
new file mode 100644
index 0000000..e516cea
--- /dev/null
+++ b/plat/qti/msm8916/platform.mk
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include drivers/arm/gic/v2/gicv2.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS}
+
+PLAT_INCLUDES := -Iinclude/plat/arm/common/${ARCH} \
+ -Iplat/qti/msm8916/include
+
+BL31_SOURCES += ${GICV2_SOURCES} \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/${ARCH}/cortex_a53.S \
+ plat/common/plat_gicv2.c \
+ plat/common/plat_psci_common.c \
+ plat/qti/msm8916/msm8916_bl31_setup.c \
+ plat/qti/msm8916/msm8916_cpu_boot.c \
+ plat/qti/msm8916/msm8916_gicv2.c \
+ plat/qti/msm8916/msm8916_pm.c \
+ plat/qti/msm8916/msm8916_topology.c \
+ plat/qti/msm8916/${ARCH}/msm8916_helpers.S \
+ plat/qti/msm8916/${ARCH}/uartdm_console.S
+
+# Only BL31 is supported at the moment and is entered on a single CPU
+RESET_TO_BL31 := 1
+COLD_BOOT_SINGLE_CPU := 1
+
+# Build config flags
+# ------------------
+BL31_BASE ?= 0x86500000
+BL32_BASE ?= 0x86000000
+PRELOADED_BL33_BASE ?= 0x8f600000
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Single cluster
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
+
+# Disable features unsupported in ARMv8.0
+ENABLE_AMU := 0
+ENABLE_SPE_FOR_LOWER_ELS := 0
+ENABLE_SVE_FOR_NS := 0
+
+# MSM8916 uses ARM Cortex-A53 r0p0 so likely all the errata apply
+ERRATA_A53_819472 := 1
+ERRATA_A53_824069 := 1
+ERRATA_A53_826319 := 1
+ERRATA_A53_827319 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 0 # Workaround works only for >= r0p3
+ERRATA_A53_1530924 := 1
+
+$(eval $(call add_define,BL31_BASE))
+$(eval $(call add_define,BL32_BASE))
diff --git a/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h b/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h
new file mode 100644
index 0000000..deef41c
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTISECLIB_CB_INTERFACE_H
+#define QTISECLIB_CB_INTERFACE_H
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <qtiseclib_defs.h>
+
+/* Standard Library API's */
+void *qtiseclib_cb_memcpy(void *dst, const void *src, size_t len);
+int qtiseclib_cb_strcmp(const char *s1, const char *s2);
+void *qtiseclib_cb_memset(void *s, int c, size_t n);
+void *qtiseclib_cb_memmove(void *dest, const void *src, size_t n);
+
+#define QTISECLIB_CB_ERROR(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_ERROR, __VA_ARGS__)
+#define QTISECLIB_CB_NOTICE(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_NOTICE, __VA_ARGS__)
+#define QTISECLIB_CB_WARN(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_WARNING, __VA_ARGS__)
+#define QTISECLIB_CB_INFO(...) qtiseclib_cb_log(QTISECLIB_LOG_LEVEL_INFO, __VA_ARGS__)
+
+void qtiseclib_cb_log(unsigned int loglvl, const char *fmt, ...);
+
+void qtiseclib_cb_spin_lock(qtiseclib_cb_spinlock_t *lock);
+void qtiseclib_cb_spin_unlock(qtiseclib_cb_spinlock_t *lock);
+
+unsigned int qtiseclib_cb_plat_my_core_pos(void);
+int qtiseclib_cb_plat_core_pos_by_mpidr(u_register_t mpidr);
+unsigned int qtiseclib_cb_plat_my_cluster_pos(void);
+
+/* GIC platform wrappers */
+void qtiseclib_cb_gic_pcpu_init(void);
+void qtiseclib_cb_ic_raise_sgi(int sgi_num, u_register_t target);
+void qtiseclib_cb_set_spi_routing(unsigned int id, unsigned int irm,
+ u_register_t target);
+/* Crash reporting api's wrappers */
+void qtiseclib_cb_switch_console_to_crash_state(void);
+
+void qtiseclib_cb_udelay(uint32_t usec);
+
+void qtiseclib_cb_console_flush(void);
+
+#if QTI_SDI_BUILD
+int qtiseclib_cb_mmap_remove_dynamic_region(uintptr_t base_va, size_t size);
+int qtiseclib_cb_mmap_add_dynamic_region(unsigned long long base_pa,
+ size_t size,
+ qtiseclib_mmap_attr_t attr);
+
+void qtiseclib_cb_flush_dcache_all(void);
+void qtiseclib_cb_get_ns_ctx(qtiseclib_dbg_a64_ctxt_regs_type *ns_ctx);
+#endif
+
+#endif /* QTISECLIB_CB_INTERFACE_H */
diff --git a/plat/qti/qtiseclib/inc/qtiseclib_defs.h b/plat/qti/qtiseclib/inc/qtiseclib_defs.h
new file mode 100644
index 0000000..2afefe1
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/qtiseclib_defs.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTISECLIB_DEFS_H
+#define QTISECLIB_DEFS_H
+
+#include <stdint.h>
+
+#ifndef u_register_t
+typedef uintptr_t u_register_t;
+#endif
+
+/*
+ * Different Log Level supported in qtiseclib.
+ * TODO: Currently no filtering done on QTISECLIB logs.
+ */
+#define QTISECLIB_LOG_LEVEL_NONE 0
+#define QTISECLIB_LOG_LEVEL_ERROR 10
+#define QTISECLIB_LOG_LEVEL_NOTICE 20
+#define QTISECLIB_LOG_LEVEL_WARNING 30
+#define QTISECLIB_LOG_LEVEL_INFO 40
+#define QTISECLIB_LOG_LEVEL_VERBOSE 50
+
+#define QTI_GICV3_IRM_PE 0
+#define QTI_GICV3_IRM_ANY 1
+
+/* Common interrupt number/ID defs. */
+#define QTISECLIB_INT_ID_RESET_SGI (0xf)
+#define QTISECLIB_INT_ID_CPU_WAKEUP_SGI (0x8)
+
+#define QTISECLIB_INT_INVALID_INT_NUM (0xFFFFFFFFU)
+
+typedef struct qtiseclib_cb_spinlock {
+ volatile uint32_t lock;
+} qtiseclib_cb_spinlock_t;
+
+#if QTI_SDI_BUILD
+/* External CPU Dump Structure - 64 bit EL */
+typedef struct {
+ uint64_t x0;
+ uint64_t x1;
+ uint64_t x2;
+ uint64_t x3;
+ uint64_t x4;
+ uint64_t x5;
+ uint64_t x6;
+ uint64_t x7;
+ uint64_t x8;
+ uint64_t x9;
+ uint64_t x10;
+ uint64_t x11;
+ uint64_t x12;
+ uint64_t x13;
+ uint64_t x14;
+ uint64_t x15;
+ uint64_t x16;
+ uint64_t x17;
+ uint64_t x18;
+ uint64_t x19;
+ uint64_t x20;
+ uint64_t x21;
+ uint64_t x22;
+ uint64_t x23;
+ uint64_t x24;
+ uint64_t x25;
+ uint64_t x26;
+ uint64_t x27;
+ uint64_t x28;
+ uint64_t x29;
+ uint64_t x30;
+ uint64_t pc;
+ uint64_t currentEL;
+ uint64_t sp_el3;
+ uint64_t elr_el3;
+ uint64_t spsr_el3;
+ uint64_t sp_el2;
+ uint64_t elr_el2;
+ uint64_t spsr_el2;
+ uint64_t sp_el1;
+ uint64_t elr_el1;
+ uint64_t spsr_el1;
+ uint64_t sp_el0;
+ uint64_t __reserved1;
+ uint64_t __reserved2;
+ uint64_t __reserved3;
+ uint64_t __reserved4;
+ uint64_t __reserved5;
+ uint64_t __reserved6;
+ uint64_t __reserved7;
+ uint64_t __reserved8;
+} qtiseclib_dbg_a64_ctxt_regs_type;
+
+typedef enum qtiseclib_mmap_attr_s {
+ QTISECLIB_MAP_NS_RO_XN_DATA = 1,
+ QTISECLIB_MAP_RW_XN_NC_DATA = 2,
+ QTISECLIB_MAP_RW_XN_DATA = 3,
+} qtiseclib_mmap_attr_t;
+
+#endif /* QTI_SDI_BUILD */
+
+#endif /* QTISECLIB_DEFS_H */
diff --git a/plat/qti/qtiseclib/inc/qtiseclib_interface.h b/plat/qti/qtiseclib/inc/qtiseclib_interface.h
new file mode 100644
index 0000000..babed1b
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/qtiseclib_interface.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTISECLIB_INTERFACE_H
+#define QTISECLIB_INTERFACE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <qtiseclib_defs.h>
+
+typedef struct memprot_ipa_info_s {
+ uint64_t mem_addr;
+ uint64_t mem_size;
+} memprot_info_t;
+
+typedef struct memprot_dst_vm_perm_info_s {
+ uint32_t dst_vm;
+ uint32_t dst_vm_perm;
+ uint64_t ctx;
+ uint32_t ctx_size;
+} memprot_dst_vm_perm_info_t;
+
+/*
+ * QTISECLIB Published API's.
+ */
+
+/*
+ * Assembly API's
+ */
+
+/*
+ * CPUSS common reset handler for all CPU wake up (both cold & warm boot).
+ * Executes on all core. This API assume serialization across CPU
+ * already taken care before invoking.
+ *
+ * Clobbers: x0 - x17, x30
+ */
+void qtiseclib_cpuss_reset_asm(uint32_t bl31_cold_boot_state);
+
+/*
+ * Execute CPU (Kryo4 gold) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo4_gold_reset_asm(void);
+
+/*
+ * Execute CPU (Kryo46 gold) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo6_gold_reset_asm(void);
+
+/*
+ * Execute CPU (Kryo4 silver) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo4_silver_reset_asm(void);
+
+/*
+ * Execute CPU (Kryo6 silver) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo6_silver_reset_asm(void);
+
+/*
+ * C Api's
+ */
+void qtiseclib_bl31_platform_setup(void);
+void qtiseclib_invoke_isr(uint32_t irq, void *handle);
+void qtiseclib_panic(void);
+
+int qtiseclib_mem_assign(const memprot_info_t *mem_info,
+ uint32_t mem_info_list_cnt,
+ const uint32_t *source_vm_list,
+ uint32_t src_vm_list_cnt,
+ const memprot_dst_vm_perm_info_t *dest_vm_list,
+ uint32_t dst_vm_list_cnt);
+
+int qtiseclib_psci_init(uintptr_t warmboot_entry);
+int qtiseclib_psci_node_power_on(u_register_t mpidr);
+void qtiseclib_psci_node_on_finish(const uint8_t *states);
+void qtiseclib_psci_cpu_standby(uint8_t pwr_state);
+void qtiseclib_psci_node_power_off(const uint8_t *states);
+void qtiseclib_psci_node_suspend(const uint8_t *states);
+void qtiseclib_psci_node_suspend_finish(const uint8_t *states);
+void qtiseclib_disable_cluster_coherency(uint8_t state);
+
+#endif /* QTISECLIB_INTERFACE_H */
diff --git a/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h b/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h
new file mode 100644
index 0000000..3ecee20
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef QTISECLIB_DEFS_PLAT_H
+#define QTISECLIB_DEFS_PLAT_H
+
+#define QTISECLIB_PLAT_CLUSTER_COUNT 1
+#define QTISECLIB_PLAT_CORE_COUNT 8
+
+#define BL31_BASE 0x80b00000
+#define BL31_SIZE 0x00100000
+
+/* Chipset specific secure interrupt number/ID defs. */
+#define QTISECLIB_INT_ID_SEC_WDOG_BARK (0x204)
+#define QTISECLIB_INT_ID_NON_SEC_WDOG_BITE (0x21)
+
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC (0xE6)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC (0xE7)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC (0xE8)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC (0xE9)
+
+#define QTISECLIB_INT_ID_XPU_SEC (0xE3)
+#define QTISECLIB_INT_ID_XPU_NON_SEC (0xE4)
+
+#define QTISECLIB_INT_ID_A2_NOC_ERROR (0x194)
+#define QTISECLIB_INT_ID_CONFIG_NOC_ERROR (0xE2)
+#define QTISECLIB_INT_ID_DC_NOC_ERROR (0x122)
+#define QTISECLIB_INT_ID_MEM_NOC_ERROR (0x6C)
+#define QTISECLIB_INT_ID_SYSTEM_NOC_ERROR (0xC6)
+#define QTISECLIB_INT_ID_MMSS_NOC_ERROR (0xBA)
+
+#endif /* QTISECLIB_DEFS_PLAT_H */
diff --git a/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h b/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h
new file mode 100644
index 0000000..b3d309f
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __QTISECLIB_DEFS_PLAT_H__
+#define __QTISECLIB_DEFS_PLAT_H__
+
+#define QTISECLIB_PLAT_CLUSTER_COUNT 1
+#define QTISECLIB_PLAT_CORE_COUNT 8
+
+#define BL31_BASE 0xC0000000
+#define BL31_SIZE 0x00100000
+
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE 0x80860000
+#define QTI_AOP_CMD_DB_SIZE 0x00020000
+
+/* Chipset specific secure interrupt number/ID defs. */
+#define QTISECLIB_INT_ID_SEC_WDOG_BARK (0x204)
+#define QTISECLIB_INT_ID_NON_SEC_WDOG_BITE (0x21)
+
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC (0xE6)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC (0xE7)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC (0xE8)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC (0xE9)
+
+#define QTISECLIB_INT_ID_XPU_SEC (0xE3)
+#define QTISECLIB_INT_ID_XPU_NON_SEC (0xE4)
+
+//NOC INterrupt
+#define QTISECLIB_INT_ID_A1_NOC_ERROR (0xC9)
+#define QTISECLIB_INT_ID_A2_NOC_ERROR (0xEA)
+#define QTISECLIB_INT_ID_CONFIG_NOC_ERROR (0xE2)
+#define QTISECLIB_INT_ID_DC_NOC_ERROR (0x122)
+#define QTISECLIB_INT_ID_MEM_NOC_ERROR (0x6C)
+#define QTISECLIB_INT_ID_SYSTEM_NOC_ERROR (0xC8)
+#define QTISECLIB_INT_ID_MMSS_NOC_ERROR (0xBA)
+#define QTISECLIB_INT_ID_LPASS_AGNOC_ERROR (0x143)
+#define QTISECLIB_INT_ID_NSP_NOC_ERROR (0x1CE)
+
+#endif /* __QTISECLIB_DEFS_PLAT_H__ */
diff --git a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
new file mode 100644
index 0000000..c4cd259
--- /dev/null
+++ b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <context.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/delay_timer.h>
+#include <lib/coreboot.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/spinlock.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform.h>
+#include <qti_plat.h>
+#include <qtiseclib_cb_interface.h>
+
+void *qtiseclib_cb_memcpy(void *dst, const void *src, size_t len)
+{
+ return memcpy(dst, src, len);
+}
+
+int qtiseclib_cb_strcmp(const char *s1, const char *s2)
+{
+ return strcmp(s1, s2);
+}
+
+void *qtiseclib_cb_memset(void *s, int c, size_t n)
+{
+ return memset(s, c, n);
+}
+
+void *qtiseclib_cb_memmove(void *dest, const void *src, size_t n)
+{
+ return memmove(dest, src, n);
+}
+
+/* Printing logs below or equal LOG_LEVEL from QTISECLIB. */
+void qtiseclib_cb_log(unsigned int loglvl, const char *fmt, ...)
+{
+ if (loglvl <= LOG_LEVEL) {
+ va_list argp;
+ static spinlock_t qti_log_lock;
+ uint64_t uptime = read_cntpct_el0();
+
+ va_start(argp, fmt);
+
+ spin_lock(&qti_log_lock);
+ printf("QTISECLIB [%x%08x]",
+ (uint32_t) ((uptime >> 32) & 0xFFFFFFFF),
+ (uint32_t) (uptime & 0xFFFFFFFF));
+ vprintf(fmt, argp);
+ putchar('\n');
+ spin_unlock(&qti_log_lock);
+
+ va_end(argp);
+ }
+}
+
+void qtiseclib_cb_spin_lock(qtiseclib_cb_spinlock_t *lock)
+{
+ spin_lock((spinlock_t *) lock);
+}
+
+void qtiseclib_cb_spin_unlock(qtiseclib_cb_spinlock_t *lock)
+{
+ spin_unlock((spinlock_t *) lock);
+}
+
+unsigned int qtiseclib_cb_plat_my_core_pos(void)
+{
+ return plat_my_core_pos();
+}
+
+int qtiseclib_cb_plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+unsigned int qtiseclib_cb_plat_my_cluster_pos(void)
+{
+ return plat_qti_my_cluster_pos();
+}
+
+/* GIC platform functions */
+void qtiseclib_cb_gic_pcpu_init(void)
+{
+ plat_qti_gic_pcpu_init();
+}
+
+void qtiseclib_cb_ic_raise_sgi(int sgi_num, u_register_t target)
+{
+ plat_ic_raise_el3_sgi(sgi_num, target);
+}
+
+void qtiseclib_cb_set_spi_routing(unsigned int id, unsigned int irm,
+ u_register_t target)
+{
+ assert(QTI_GICV3_IRM_PE == GICV3_IRM_PE);
+ assert(QTI_GICV3_IRM_ANY == GICV3_IRM_ANY);
+ gic_set_spi_routing(id, irm, target);
+}
+
+/* Crash reporting api's wrappers */
+void qtiseclib_cb_switch_console_to_crash_state(void)
+{
+ console_switch_state(CONSOLE_FLAG_CRASH);
+}
+
+void qtiseclib_cb_udelay(uint32_t usec)
+{
+ udelay(usec);
+}
+
+void qtiseclib_cb_console_flush(void)
+{
+ return console_flush();
+}
+
+#if QTI_SDI_BUILD
+void qtiseclib_cb_get_ns_ctx(qtiseclib_dbg_a64_ctxt_regs_type *qti_ns_ctx)
+{
+ void *ctx;
+
+ ctx = cm_get_context(NON_SECURE);
+ if (ctx) {
+ /* nothing to be done w/o ns context */
+ return;
+ }
+
+ qti_ns_ctx->spsr_el3 =
+ read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3);
+ qti_ns_ctx->elr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_ELR_EL3);
+
+ qti_ns_ctx->spsr_el1 =
+ read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SPSR_EL1);
+ qti_ns_ctx->elr_el1 =
+ read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_ELR_EL1);
+ qti_ns_ctx->sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SP_EL1);
+
+ qti_ns_ctx->x0 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0);
+ qti_ns_ctx->x1 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1);
+ qti_ns_ctx->x2 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2);
+ qti_ns_ctx->x3 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3);
+ qti_ns_ctx->x4 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4);
+ qti_ns_ctx->x5 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5);
+ qti_ns_ctx->x6 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6);
+ qti_ns_ctx->x7 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7);
+ qti_ns_ctx->x8 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X8);
+ qti_ns_ctx->x9 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X9);
+ qti_ns_ctx->x10 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X10);
+ qti_ns_ctx->x11 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X11);
+ qti_ns_ctx->x12 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X12);
+ qti_ns_ctx->x13 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X13);
+ qti_ns_ctx->x14 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X14);
+ qti_ns_ctx->x15 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X15);
+ qti_ns_ctx->x16 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X16);
+ qti_ns_ctx->x17 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X17);
+ qti_ns_ctx->x18 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X18);
+ qti_ns_ctx->x19 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X19);
+ qti_ns_ctx->x20 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X20);
+ qti_ns_ctx->x21 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X21);
+ qti_ns_ctx->x22 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X22);
+ qti_ns_ctx->x23 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X23);
+ qti_ns_ctx->x24 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X24);
+ qti_ns_ctx->x25 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X25);
+ qti_ns_ctx->x26 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X26);
+ qti_ns_ctx->x27 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X27);
+ qti_ns_ctx->x28 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X28);
+ qti_ns_ctx->x29 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X29);
+ qti_ns_ctx->x30 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_LR);
+ qti_ns_ctx->sp_el0 =
+ read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0);
+}
+
+void qtiseclib_cb_flush_dcache_all(void)
+{
+ dcsw_op_all(DCCISW);
+}
+
+int qtiseclib_cb_mmap_add_dynamic_region(unsigned long long base_pa,
+ size_t size,
+ qtiseclib_mmap_attr_t attr)
+{
+ unsigned int l_attr = 0;
+
+ if (attr == QTISECLIB_MAP_NS_RO_XN_DATA) {
+ l_attr = MT_NS | MT_RO | MT_EXECUTE_NEVER;
+ } else if (attr == QTISECLIB_MAP_RW_XN_NC_DATA) {
+ l_attr = MT_RW | MT_NON_CACHEABLE | MT_EXECUTE_NEVER;
+ } else if (attr == QTISECLIB_MAP_RW_XN_DATA) {
+ l_attr = MT_RW | MT_EXECUTE_NEVER;
+ }
+ return qti_mmap_add_dynamic_region(base_pa, size, l_attr);
+}
+
+int qtiseclib_cb_mmap_remove_dynamic_region(uintptr_t base_va, size_t size)
+{
+ return qti_mmap_remove_dynamic_region(base_va, size);
+}
+#endif
+
diff --git a/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c b/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c
new file mode 100644
index 0000000..cdaa0a7
--- /dev/null
+++ b/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#include <qtiseclib_defs.h>
+#include <qtiseclib_interface.h>
+
+/*
+ * This file contains dummy implementation of QTISECLIB Published API's.
+ * which will be used to compile PLATFORM successfully when
+ * qtiseclib is not available
+ */
+
+/*
+ * CPUSS common reset handler for all CPU wake up (both cold & warm boot).
+ * Executes on all core. This API assume serialization across CPU
+ * already taken care before invoking.
+ *
+ * Clobbers: x0 - x17, x30
+ */
+void qtiseclib_cpuss_reset_asm(uint32_t bl31_cold_boot_state)
+{
+}
+
+/*
+ * Execute CPU (Kryo4 gold) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo4_gold_reset_asm(void)
+{
+}
+
+/*
+ * Execute CPU (Kryo4 silver) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo4_silver_reset_asm(void)
+{
+}
+
+/*
+ * Execute CPU (Kryo4 gold) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo6_gold_reset_asm(void)
+{
+}
+
+
+void qtiseclib_kryo6_silver_reset_asm(void)
+{
+}
+
+/*
+ * C Api's
+ */
+void qtiseclib_bl31_platform_setup(void)
+{
+ ERROR("Please use QTISECLIB_PATH while building TF-A\n");
+ ERROR("Please refer docs/plat/qti.rst for more details.\n");
+ panic();
+}
+
+void qtiseclib_invoke_isr(uint32_t irq, void *handle)
+{
+}
+
+void qtiseclib_panic(void)
+{
+}
+
+int
+qtiseclib_mem_assign(const memprot_info_t *mem_info,
+ uint32_t mem_info_list_cnt,
+ const uint32_t *source_vm_list,
+ uint32_t src_vm_list_cnt,
+ const memprot_dst_vm_perm_info_t *dest_vm_list,
+ uint32_t dst_vm_list_cnt)
+{
+ return 0;
+}
+
+int qtiseclib_psci_init(uintptr_t warmboot_entry)
+{
+ return 0;
+}
+
+int qtiseclib_psci_node_power_on(u_register_t mpidr)
+{
+ return 0;
+}
+
+void qtiseclib_psci_node_on_finish(const uint8_t *states)
+{
+}
+
+void qtiseclib_psci_cpu_standby(uint8_t pwr_state)
+{
+}
+
+void qtiseclib_psci_node_power_off(const uint8_t *states)
+{
+}
+
+void qtiseclib_psci_node_suspend(const uint8_t *states)
+{
+}
+
+void qtiseclib_psci_node_suspend_finish(const uint8_t *states)
+{
+}
+
+void qtiseclib_disable_cluster_coherency(uint8_t state)
+{
+}
+
diff --git a/plat/qti/sc7180/inc/platform_def.h b/plat/qti/sc7180/inc/platform_def.h
new file mode 100644
index 0000000..b69dfd9
--- /dev/null
+++ b/plat/qti/sc7180/inc/platform_def.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+/* Enable the dynamic translation tables library. */
+#define PLAT_XLAT_TABLES_DYNAMIC 1
+
+#include <common_def.h>
+
+#include <qti_board_def.h>
+#include <qtiseclib_defs_plat.h>
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*
+ * MPIDR_PRIMARY_CPU
+ * You just need to have the correct core_affinity_val i.e. [7:0]
+ * and cluster_affinity_val i.e. [15:8]
+ * the other bits will be ignored
+ */
+/*----------------------------------------------------------------------------*/
+#define MPIDR_PRIMARY_CPU 0x0000
+/*----------------------------------------------------------------------------*/
+
+#define QTI_PWR_LVL0 MPIDR_AFFLVL0
+#define QTI_PWR_LVL1 MPIDR_AFFLVL1
+#define QTI_PWR_LVL2 MPIDR_AFFLVL2
+#define QTI_PWR_LVL3 MPIDR_AFFLVL3
+
+/*
+ * Macros for local power states encoded by State-ID field
+ * within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define QTI_LOCAL_STATE_RUN 0
+/*
+ * Local power state for clock-gating. Valid only for CPU and not cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_STB 1
+/*
+ * Local power state for retention. Valid for CPU and cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_RET 2
+/*
+ * Local power state for OFF/power down. Valid for CPU, cluster, RSC and PDC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_OFF 3
+/*
+ * Local power state for DEEPOFF/power rail down. Valid for CPU, cluster and RSC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_DEEPOFF 4
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE QTI_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE QTI_LOCAL_STATE_DEEPOFF
+
+/******************************************************************************
+ * Required platform porting definitions common to all ARM standard platforms
+ *****************************************************************************/
+
+/*
+ * Platform specific page table and MMU setup constants.
+ */
+#define MAX_MMAP_REGIONS (PLAT_QTI_MMAP_ENTRIES)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 36)
+
+#define ARM_CACHE_WRITEBACK_SHIFT 6
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (1 << ARM_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * One cache line needed for bakery locks on ARM platforms
+ */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+/*----------------------------------------------------------------------------*/
+/* PSCI power domain topology definitions */
+/*----------------------------------------------------------------------------*/
+/* One domain each to represent RSC and PDC level */
+#define PLAT_PDC_COUNT 1
+#define PLAT_RSC_COUNT 1
+
+/* There is one top-level FCM cluster */
+#define PLAT_CLUSTER_COUNT 1
+
+/* No. of cores in the FCM cluster */
+#define PLAT_CLUSTER0_CORE_COUNT 8
+
+#define PLATFORM_CORE_COUNT (PLAT_CLUSTER0_CORE_COUNT)
+
+#define PLAT_NUM_PWR_DOMAINS (PLAT_PDC_COUNT +\
+ PLAT_RSC_COUNT +\
+ PLAT_CLUSTER_COUNT +\
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL 3
+
+/*****************************************************************************/
+/* Memory mapped Generic timer interfaces */
+/*****************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* GIC-600 constants */
+/*----------------------------------------------------------------------------*/
+#define BASE_GICD_BASE 0x17A00000
+#define BASE_GICR_BASE 0x17A60000
+#define BASE_GICC_BASE 0x0
+#define BASE_GICH_BASE 0x0
+#define BASE_GICV_BASE 0x0
+
+#define QTI_GICD_BASE BASE_GICD_BASE
+#define QTI_GICR_BASE BASE_GICR_BASE
+#define QTI_GICC_BASE BASE_GICC_BASE
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* UART related constants. */
+/*----------------------------------------------------------------------------*/
+/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */
+#define GENI4_CFG 0x0
+#define GENI4_IMAGE_REGS 0x100
+#define GENI4_DATA 0x600
+
+/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
+#define GENI_STATUS_REG (GENI4_CFG + 0x00000040)
+#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK (0x1)
+#define UART_TX_TRANS_LEN_REG (GENI4_IMAGE_REGS + 0x00000170)
+/* MASTER/TX ENGINE REGISTERS */
+#define GENI_M_CMD0_REG (GENI4_DATA + 0x00000000)
+/* FIFO, STATUS REGISTERS AND MASKS */
+#define GENI_TX_FIFOn_REG (GENI4_DATA + 0x00000100)
+
+#define GENI_M_CMD_TX (0x08000000)
+
+/*----------------------------------------------------------------------------*/
+/* Device address space for mapping. Excluding starting 4K */
+/*----------------------------------------------------------------------------*/
+#define QTI_DEVICE_BASE 0x1000
+#define QTI_DEVICE_SIZE (0x80000000 - QTI_DEVICE_BASE)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at DDR as per memory map. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/*----------------------------------------------------------------------------*/
+/* AOSS registers */
+/*----------------------------------------------------------------------------*/
+#define QTI_PS_HOLD_REG 0x0C264000
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE 0x80820000
+#define QTI_AOP_CMD_DB_SIZE 0x00020000
+/*----------------------------------------------------------------------------*/
+/* SOC hw version register */
+/*----------------------------------------------------------------------------*/
+#define QTI_SOC_VERSION_MASK U(0xFFFF)
+#define QTI_SOC_REVISION_REG 0x1FC8000
+#define QTI_SOC_REVISION_MASK U(0xFFFF)
+/*----------------------------------------------------------------------------*/
+/* LC PON register offsets */
+/*----------------------------------------------------------------------------*/
+#define PON_PS_HOLD_RESET_CTL 0x85a
+#define PON_PS_HOLD_RESET_CTL2 0x85b
+/*----------------------------------------------------------------------------*/
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/sc7180/inc/qti_map_chipinfo.h b/plat/qti/sc7180/inc/qti_map_chipinfo.h
new file mode 100644
index 0000000..4ab6191
--- /dev/null
+++ b/plat/qti/sc7180/inc/qti_map_chipinfo.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_MAP_CHIPINFO_H
+#define QTI_MAP_CHIPINFO_H
+
+#include <stdint.h>
+
+#include <qti_plat.h>
+
+#define QTI_JTAG_ID_REG 0x786130
+#define QTI_SOC_VERSION_MASK U(0xFFFF)
+#define QTI_SOC_REVISION_REG 0x1FC8000
+#define QTI_SOC_REVISION_MASK U(0xFFFF)
+#define QTI_JTAG_ID_SHIFT 12
+#define QTI_JTAG_ID_SC7180 U(0x012C)
+#define QTI_JTAG_ID_SC7180P U(0x0195)
+#define QTI_CHIPINFO_ID_SC7180 U(0x01A9)
+#define QTI_CHIPINFO_ID_SC7180P U(0x01EF)
+#define QTI_DEFAULT_CHIPINFO_ID U(0xFFFF)
+
+static const chip_id_info_t g_map_jtag_chipinfo_id[] = {
+ {QTI_JTAG_ID_SC7180, QTI_CHIPINFO_ID_SC7180},
+ {QTI_JTAG_ID_SC7180P, QTI_CHIPINFO_ID_SC7180P},
+};
+#endif /* QTI_MAP_CHIPINFO_H */
diff --git a/plat/qti/sc7180/inc/qti_rng_io.h b/plat/qti/sc7180/inc/qti_rng_io.h
new file mode 100644
index 0000000..f50234f
--- /dev/null
+++ b/plat/qti/sc7180/inc/qti_rng_io.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_RNG_IO_H
+#define QTI_RNG_IO_H
+
+#define SEC_PRNG_STATUS 0x00791004
+#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK 0x1
+#define SEC_PRNG_DATA_OUT 0x00791000
+
+
+#endif /* QTI_RNG_IO_H */
+
diff --git a/plat/qti/sc7180/inc/qti_secure_io_cfg.h b/plat/qti/sc7180/inc/qti_secure_io_cfg.h
new file mode 100644
index 0000000..3de636d
--- /dev/null
+++ b/plat/qti/sc7180/inc/qti_secure_io_cfg.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_SECURE_IO_CFG_H
+#define QTI_SECURE_IO_CFG_H
+
+#include <stdint.h>
+
+/*
+ * List of peripheral/IO memory areas that are protected from
+ * non-secure world but not required to be secure.
+ */
+
+#define APPS_SMMU_TBU_PWR_STATUS 0x15002204
+#define APPS_SMMU_CUSTOM_CFG 0x15002300
+#define APPS_SMMU_STATS_SYNC_INV_TBU_ACK 0x150025DC
+#define APPS_SMMU_SAFE_SEC_CFG 0x15002648
+#define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x15002670
+
+static const uintptr_t qti_secure_io_allowed_regs[] = {
+ APPS_SMMU_TBU_PWR_STATUS,
+ APPS_SMMU_CUSTOM_CFG,
+ APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
+ APPS_SMMU_SAFE_SEC_CFG,
+ APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR,
+};
+
+#endif /* QTI_SECURE_IO_CFG_H */
diff --git a/plat/qti/sc7180/platform.mk b/plat/qti/sc7180/platform.mk
new file mode 100644
index 0000000..41a08ca
--- /dev/null
+++ b/plat/qti/sc7180/platform.mk
@@ -0,0 +1,128 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Make for SC7180 QTI platform.
+
+QTI_PLAT_PATH := plat/qti
+CHIPSET := ${PLAT}
+
+# Turn On Separate code & data.
+SEPARATE_CODE_AND_RODATA := 1
+USE_COHERENT_MEM := 0
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
+HW_ASSISTED_COHERENCY := 1
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT := 0
+
+#Enable errata for cortex_a55 and cortex_a76
+ERRATA_A55_1530923 := 1
+ERRATA_A76_1165522 := 1
+
+# Enable PSCI v1.0 extended state ID format
+PSCI_EXTENDED_STATE_ID := 1
+ARM_RECOM_STATE_ID_ENC := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+RESET_TO_BL31 := 0
+
+MULTI_CONSOLE_API := 1
+
+QTI_SDI_BUILD := 0
+$(eval $(call assert_boolean,QTI_SDI_BUILD))
+$(eval $(call add_define,QTI_SDI_BUILD))
+
+#disable CTX_INCLUDE_AARCH32_REGS to support sc7180 gold cores
+override CTX_INCLUDE_AARCH32_REGS := 0
+WORKAROUND_CVE_2017_5715 := 0
+DYNAMIC_WORKAROUND_CVE_2018_3639 := 1
+# Enable stack protector.
+ENABLE_STACK_PROTECTOR := strong
+
+
+QTI_EXTERNAL_INCLUDES := -I${QTI_PLAT_PATH}/${CHIPSET}/inc \
+ -I${QTI_PLAT_PATH}/common/inc \
+ -I${QTI_PLAT_PATH}/common/inc/$(ARCH) \
+ -I${QTI_PLAT_PATH}/qtiseclib/inc \
+ -I${QTI_PLAT_PATH}/qtiseclib/inc/${CHIPSET} \
+
+QTI_BL31_SOURCES := $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_helpers.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo4_silver.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo4_gold.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_uart_console.S \
+ $(QTI_PLAT_PATH)/common/src/pm_ps_hold.c \
+ $(QTI_PLAT_PATH)/common/src/qti_stack_protector.c \
+ $(QTI_PLAT_PATH)/common/src/qti_common.c \
+ $(QTI_PLAT_PATH)/common/src/qti_bl31_setup.c \
+ $(QTI_PLAT_PATH)/common/src/qti_gic_v3.c \
+ $(QTI_PLAT_PATH)/common/src/qti_interrupt_svc.c \
+ $(QTI_PLAT_PATH)/common/src/qti_syscall.c \
+ $(QTI_PLAT_PATH)/common/src/qti_topology.c \
+ $(QTI_PLAT_PATH)/common/src/qti_pm.c \
+ $(QTI_PLAT_PATH)/common/src/qti_rng.c \
+ $(QTI_PLAT_PATH)/common/src/spmi_arb.c \
+ $(QTI_PLAT_PATH)/qtiseclib/src/qtiseclib_cb_interface.c \
+
+
+PLAT_INCLUDES := -Iinclude/plat/common/ \
+
+PLAT_INCLUDES += ${QTI_EXTERNAL_INCLUDES}
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/aarch64/crash_console_helpers.S \
+ common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+
+include lib/coreboot/coreboot.mk
+
+#PSCI Sources.
+PSCI_SOURCES := plat/common/plat_psci_common.c \
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+#Timer sources
+TIMER_SOURCES := drivers/delay_timer/generic_delay_timer.c \
+ drivers/delay_timer/delay_timer.c \
+
+#GIC sources.
+GIC_SOURCES := plat/common/plat_gicv3.c \
+ ${GICV3_SOURCES} \
+
+CPU_SOURCES := lib/cpus/aarch64/cortex_a76.S \
+ lib/cpus/aarch64/cortex_a55.S \
+
+BL31_SOURCES += ${QTI_BL31_SOURCES} \
+ ${PSCI_SOURCES} \
+ ${GIC_SOURCES} \
+ ${TIMER_SOURCES} \
+ ${CPU_SOURCES} \
+
+LIB_QTI_PATH := ${QTI_PLAT_PATH}/qtiseclib/lib/${CHIPSET}
+
+
+# Override this on the command line to point to the qtiseclib library which
+# will be available in coreboot.org
+QTISECLIB_PATH ?=
+
+ifeq ($(QTISECLIB_PATH),)
+# if No lib then use stub implementation for qtiseclib interface
+$(warning QTISECLIB_PATH is not provided while building, using stub implementation. \
+ Please refer docs/plat/qti.rst for more details \
+ THIS FIRMWARE WILL NOT BOOT!)
+BL31_SOURCES += plat/qti/qtiseclib/src/qtiseclib_interface_stub.c
+else
+# use library provided by QTISECLIB_PATH
+LDFLAGS += -L $(dir $(QTISECLIB_PATH))
+LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(QTISECLIB_PATH)))
+endif
+
diff --git a/plat/qti/sc7280/inc/platform_def.h b/plat/qti/sc7280/inc/platform_def.h
new file mode 100644
index 0000000..48b48ac
--- /dev/null
+++ b/plat/qti/sc7280/inc/platform_def.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+/* Enable the dynamic translation tables library. */
+#define PLAT_XLAT_TABLES_DYNAMIC 1
+
+#include <common_def.h>
+
+#include <qti_board_def.h>
+#include <qtiseclib_defs_plat.h>
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*
+ * MPIDR_PRIMARY_CPU
+ * You just need to have the correct core_affinity_val i.e. [7:0]
+ * and cluster_affinity_val i.e. [15:8]
+ * the other bits will be ignored
+ */
+/*----------------------------------------------------------------------------*/
+#define MPIDR_PRIMARY_CPU 0x0000
+/*----------------------------------------------------------------------------*/
+
+#define QTI_PWR_LVL0 MPIDR_AFFLVL0
+#define QTI_PWR_LVL1 MPIDR_AFFLVL1
+#define QTI_PWR_LVL2 MPIDR_AFFLVL2
+#define QTI_PWR_LVL3 MPIDR_AFFLVL3
+
+/*
+ * Macros for local power states encoded by State-ID field
+ * within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define QTI_LOCAL_STATE_RUN 0
+/*
+ * Local power state for clock-gating. Valid only for CPU and not cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_STB 1
+/*
+ * Local power state for retention. Valid for CPU and cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_RET 2
+/*
+ * Local power state for OFF/power down. Valid for CPU, cluster, RSC and PDC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_OFF 3
+/*
+ * Local power state for DEEPOFF/power rail down. Valid for CPU, cluster and RSC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_DEEPOFF 4
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE QTI_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE QTI_LOCAL_STATE_DEEPOFF
+
+/******************************************************************************
+ * Required platform porting definitions common to all ARM standard platforms
+ *****************************************************************************/
+
+/*
+ * Platform specific page table and MMU setup constants.
+ */
+#define MAX_MMAP_REGIONS (PLAT_QTI_MMAP_ENTRIES)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 36)
+
+#define ARM_CACHE_WRITEBACK_SHIFT 6
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE (1 << ARM_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * One cache line needed for bakery locks on ARM platforms
+ */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE)
+
+/*----------------------------------------------------------------------------*/
+/* PSCI power domain topology definitions */
+/*----------------------------------------------------------------------------*/
+/* One domain each to represent RSC and PDC level */
+#define PLAT_PDC_COUNT 1
+#define PLAT_RSC_COUNT 1
+
+/* There is one top-level FCM cluster */
+#define PLAT_CLUSTER_COUNT 1
+
+/* No. of cores in the FCM cluster */
+#define PLAT_CLUSTER0_CORE_COUNT 8
+
+#define PLATFORM_CORE_COUNT (PLAT_CLUSTER0_CORE_COUNT)
+
+#define PLAT_NUM_PWR_DOMAINS (PLAT_PDC_COUNT +\
+ PLAT_RSC_COUNT +\
+ PLAT_CLUSTER_COUNT +\
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL 3
+
+/*****************************************************************************/
+/* Memory mapped Generic timer interfaces */
+/*****************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* GIC-600 constants */
+/*----------------------------------------------------------------------------*/
+#define BASE_GICD_BASE 0x17A00000
+#define BASE_GICR_BASE 0x17A60000
+#define BASE_GICC_BASE 0x0
+#define BASE_GICH_BASE 0x0
+#define BASE_GICV_BASE 0x0
+
+#define QTI_GICD_BASE BASE_GICD_BASE
+#define QTI_GICR_BASE BASE_GICR_BASE
+#define QTI_GICC_BASE BASE_GICC_BASE
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* UART related constants. */
+/*----------------------------------------------------------------------------*/
+/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */
+#define GENI4_CFG 0x0
+#define GENI4_IMAGE_REGS 0x100
+#define GENI4_DATA 0x600
+
+/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
+#define GENI_STATUS_REG (GENI4_CFG + 0x00000040)
+#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK (0x1)
+#define UART_TX_TRANS_LEN_REG (GENI4_IMAGE_REGS + 0x00000170)
+/* MASTER/TX ENGINE REGISTERS */
+#define GENI_M_CMD0_REG (GENI4_DATA + 0x00000000)
+/* FIFO, STATUS REGISTERS AND MASKS */
+#define GENI_TX_FIFOn_REG (GENI4_DATA + 0x00000100)
+
+#define GENI_M_CMD_TX (0x08000000)
+
+/*----------------------------------------------------------------------------*/
+/* Device address space for mapping. Excluding starting 4K */
+/*----------------------------------------------------------------------------*/
+#define QTI_DEVICE_BASE 0x1000
+#define QTI_DEVICE_SIZE (0x80000000 - QTI_DEVICE_BASE)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at DDR as per memory map. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/*----------------------------------------------------------------------------*/
+/* AOSS registers */
+/*----------------------------------------------------------------------------*/
+#define QTI_PS_HOLD_REG 0x0C264000
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE 0x80860000
+#define QTI_AOP_CMD_DB_SIZE 0x00020000
+/*----------------------------------------------------------------------------*/
+/* SOC hw version register */
+/*----------------------------------------------------------------------------*/
+#define QTI_SOC_VERSION_MASK U(0xFFFF)
+#define QTI_SOC_REVISION_REG 0x1FC8000
+#define QTI_SOC_REVISION_MASK U(0xFFFF)
+/*----------------------------------------------------------------------------*/
+/* LC PON register offsets */
+/*----------------------------------------------------------------------------*/
+#define PON_PS_HOLD_RESET_CTL 0x852
+#define PON_PS_HOLD_RESET_CTL2 0x853
+/*----------------------------------------------------------------------------*/
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/sc7280/inc/qti_map_chipinfo.h b/plat/qti/sc7280/inc/qti_map_chipinfo.h
new file mode 100644
index 0000000..7303e20
--- /dev/null
+++ b/plat/qti/sc7280/inc/qti_map_chipinfo.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_MAP_CHIPINFO_H
+#define QTI_MAP_CHIPINFO_H
+
+#include <stdint.h>
+
+#include <qti_plat.h>
+
+#define QTI_JTAG_ID_REG 0x786130
+#define QTI_JTAG_ID_SHIFT 12
+#define QTI_JTAG_ID_SC7280 U(0x0193)
+#define QTI_JTAG_ID_SC7280P U(0x01EB)
+#define QTI_JTAG_ID_SC8270 U(0x01E3)
+#define QTI_JTAG_ID_SC8270P U(0x020A)
+#define QTI_JTAG_ID_SC7270P U(0x0215)
+#define QTI_CHIPINFO_ID_SC7280 U(0x01E7)
+#define QTI_CHIPINFO_ID_SC7280P U(0x0222)
+#define QTI_CHIPINFO_ID_SC8270 U(0x0229)
+#define QTI_CHIPINFO_ID_SC8270P U(0x0233)
+#define QTI_CHIPINFO_ID_SC7270P U(0x0237)
+#define QTI_DEFAULT_CHIPINFO_ID U(0xFFFF)
+
+static const chip_id_info_t g_map_jtag_chipinfo_id[] = {
+ {QTI_JTAG_ID_SC7280, QTI_CHIPINFO_ID_SC7280},
+ {QTI_JTAG_ID_SC7280P, QTI_CHIPINFO_ID_SC7280P},
+ {QTI_JTAG_ID_SC8270, QTI_CHIPINFO_ID_SC8270},
+ {QTI_JTAG_ID_SC8270P, QTI_CHIPINFO_ID_SC8270P},
+ {QTI_JTAG_ID_SC7270P, QTI_CHIPINFO_ID_SC7270P},
+};
+#endif /* QTI_MAP_CHIPINFO_H */
diff --git a/plat/qti/sc7280/inc/qti_rng_io.h b/plat/qti/sc7280/inc/qti_rng_io.h
new file mode 100644
index 0000000..0f41fd6
--- /dev/null
+++ b/plat/qti/sc7280/inc/qti_rng_io.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_RNG_IO_H
+#define QTI_RNG_IO_H
+
+#define SEC_PRNG_STATUS 0x10D1004
+#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK 0x1
+#define SEC_PRNG_DATA_OUT 0x10D1000
+
+
+#endif /* QTI_RNG_IO_H */
+
diff --git a/plat/qti/sc7280/inc/qti_secure_io_cfg.h b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
new file mode 100644
index 0000000..058c5b5
--- /dev/null
+++ b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_SECURE_IO_CFG_H
+#define QTI_SECURE_IO_CFG_H
+
+#include <stdint.h>
+
+/*
+ * List of peripheral/IO memory areas that are protected from
+ * non-secure world but not required to be secure.
+ */
+
+#define APPS_SMMU_TBU_PWR_STATUS 0x15002204
+#define APPS_SMMU_CUSTOM_CFG 0x15002300
+#define APPS_SMMU_STATS_SYNC_INV_TBU_ACK 0x150025DC
+#define APPS_SMMU_SAFE_SEC_CFG 0x15002648
+#define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR 0x15002670
+
+static const uintptr_t qti_secure_io_allowed_regs[] = {
+ APPS_SMMU_TBU_PWR_STATUS,
+ APPS_SMMU_CUSTOM_CFG,
+ APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
+ APPS_SMMU_SAFE_SEC_CFG,
+ APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR,
+};
+
+#endif /* QTI_SECURE_IO_CFG_H */
diff --git a/plat/qti/sc7280/platform.mk b/plat/qti/sc7280/platform.mk
new file mode 100644
index 0000000..df07bc4
--- /dev/null
+++ b/plat/qti/sc7280/platform.mk
@@ -0,0 +1,130 @@
+#
+# Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Make for SC7280 QTI platform.
+
+QTI_PLAT_PATH := plat/qti
+CHIPSET := ${PLAT}
+
+# Turn On Separate code & data.
+SEPARATE_CODE_AND_RODATA := 1
+USE_COHERENT_MEM := 0
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
+HW_ASSISTED_COHERENCY := 1
+
+#Enable errata configs for cortex_a78 and cortex_a55
+ERRATA_A55_1530923 := 1
+ERRATA_A78_1941498 := 1
+ERRATA_A78_1951500 := 1
+ERRATA_A78_2132060 := 1
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT := 0
+
+# Enable PSCI v1.0 extended state ID format
+PSCI_EXTENDED_STATE_ID := 1
+ARM_RECOM_STATE_ID_ENC := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+RESET_TO_BL31 := 0
+
+MULTI_CONSOLE_API := 1
+
+QTI_SDI_BUILD := 0
+$(eval $(call assert_boolean,QTI_SDI_BUILD))
+$(eval $(call add_define,QTI_SDI_BUILD))
+
+#disable CTX_INCLUDE_AARCH32_REGS to support sc7280 gold cores
+override CTX_INCLUDE_AARCH32_REGS := 0
+WORKAROUND_CVE_2017_5715 := 0
+DYNAMIC_WORKAROUND_CVE_2018_3639 := 1
+# Enable stack protector.
+ENABLE_STACK_PROTECTOR := strong
+
+
+QTI_EXTERNAL_INCLUDES := -I${QTI_PLAT_PATH}/${CHIPSET}/inc \
+ -I${QTI_PLAT_PATH}/common/inc \
+ -I${QTI_PLAT_PATH}/common/inc/$(ARCH) \
+ -I${QTI_PLAT_PATH}/qtiseclib/inc \
+ -I${QTI_PLAT_PATH}/qtiseclib/inc/${CHIPSET} \
+
+QTI_BL31_SOURCES := $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_helpers.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_silver.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_gold.S \
+ $(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_uart_console.S \
+ $(QTI_PLAT_PATH)/common/src/pm_ps_hold.c \
+ $(QTI_PLAT_PATH)/common/src/qti_stack_protector.c \
+ $(QTI_PLAT_PATH)/common/src/qti_common.c \
+ $(QTI_PLAT_PATH)/common/src/qti_bl31_setup.c \
+ $(QTI_PLAT_PATH)/common/src/qti_gic_v3.c \
+ $(QTI_PLAT_PATH)/common/src/qti_interrupt_svc.c \
+ $(QTI_PLAT_PATH)/common/src/qti_syscall.c \
+ $(QTI_PLAT_PATH)/common/src/qti_topology.c \
+ $(QTI_PLAT_PATH)/common/src/qti_pm.c \
+ $(QTI_PLAT_PATH)/common/src/qti_rng.c \
+ $(QTI_PLAT_PATH)/common/src/spmi_arb.c \
+ $(QTI_PLAT_PATH)/qtiseclib/src/qtiseclib_cb_interface.c \
+
+
+PLAT_INCLUDES := -Iinclude/plat/common/ \
+
+PLAT_INCLUDES += ${QTI_EXTERNAL_INCLUDES}
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \
+ plat/common/aarch64/crash_console_helpers.S \
+ common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+
+include lib/coreboot/coreboot.mk
+
+#PSCI Sources.
+PSCI_SOURCES := plat/common/plat_psci_common.c \
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+#Timer sources
+TIMER_SOURCES := drivers/delay_timer/generic_delay_timer.c \
+ drivers/delay_timer/delay_timer.c \
+
+#GIC sources.
+GIC_SOURCES := plat/common/plat_gicv3.c \
+ ${GICV3_SOURCES} \
+
+CPU_SOURCES := lib/cpus/aarch64/cortex_a78.S \
+ lib/cpus/aarch64/cortex_a55.S \
+
+BL31_SOURCES += ${QTI_BL31_SOURCES} \
+ ${PSCI_SOURCES} \
+ ${GIC_SOURCES} \
+ ${TIMER_SOURCES} \
+ ${CPU_SOURCES} \
+
+LIB_QTI_PATH := ${QTI_PLAT_PATH}/qtiseclib/lib/${CHIPSET}
+
+
+# Override this on the command line to point to the qtiseclib library which
+# will be available in coreboot.org
+QTISECLIB_PATH ?=
+
+ifeq ($(QTISECLIB_PATH),)
+# if No lib then use stub implementation for qtiseclib interface
+$(warning QTISECLIB_PATH is not provided while building, using stub implementation. \
+ Please refer docs/plat/qti.rst for more details \
+ THIS FIRMWARE WILL NOT BOOT!)
+BL31_SOURCES += plat/qti/qtiseclib/src/qtiseclib_interface_stub.c
+else
+# use library provided by QTISECLIB_PATH
+LDFLAGS += -L $(dir $(QTISECLIB_PATH))
+LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(QTISECLIB_PATH)))
+endif
+
diff --git a/plat/renesas/common/aarch64/plat_helpers.S b/plat/renesas/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..21c3bed
--- /dev/null
+++ b/plat/renesas/common/aarch64/plat_helpers.S
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <common/runtime_svc.h>
+#include <cortex_a57.h>
+#include <platform_def.h>
+
+#include "rcar_def.h"
+
+ .globl plat_get_my_entrypoint
+ .extern plat_set_my_stack
+ .globl platform_mem_init
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+ .globl plat_invalidate_icache
+ .globl plat_report_exception
+ .globl plat_secondary_reset
+ .globl plat_reset_handler
+ .globl plat_my_core_pos
+ .extern rcar_log_init
+
+ .extern console_rcar_init
+ .extern console_rcar_putc
+ .extern console_rcar_flush
+
+#if IMAGE_BL2
+ #define INT_ID_MASK (0x3ff)
+ .extern bl2_interrupt_error_type
+ .extern bl2_interrupt_error_id
+ .globl bl2_enter_bl31
+ .extern gicv2_acknowledge_interrupt
+ .extern rcar_swdt_exec
+#endif
+
+ /* -----------------------------------------------------
+ * void platform_get_core_pos (mpidr)
+ * -----------------------------------------------------
+ */
+func platform_get_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc platform_get_core_pos
+
+ /* -----------------------------------------------------
+ * void platform_my_core_pos
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b platform_get_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * void platform_get_my_entrypoint (unsigned int mpid);
+ *
+ * Main job of this routine is to distinguish between
+ * a cold and warm boot.
+ * On a cold boot the secondaries first wait for the
+ * platform to be initialized after which they are
+ * hotplugged in. The primary proceeds to perform the
+ * platform initialization.
+ * On a warm boot, each cpu jumps to the address in its
+ * mailbox.
+ *
+ * TODO: Not a good idea to save lr in a temp reg
+ * -----------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mrs x0, mpidr_el1
+ mov x9, x30 /* lr */
+
+#if defined(IMAGE_BL2)
+ /* always cold boot on bl2 */
+ mov x0, #0
+ ret x9
+#else
+ ldr x1, =BOOT_KIND_BASE
+ ldr x21, [x1]
+
+ /* Check the reset info */
+ and x1, x21, #0x000c
+ cmp x1, #0x0008
+ beq el3_panic
+ cmp x1, #0x000c
+ beq el3_panic
+
+ /* Check the boot kind */
+ and x1, x21, #0x0003
+ cmp x1, #0x0002
+ beq el3_panic
+ cmp x1, #0x0003
+ beq el3_panic
+
+ /* warm boot or cold boot */
+ and x1, x21, #1
+ cmp x1, #0
+ bne warm_reset
+
+ /* Cold boot */
+ mov x0, #0
+ b exit
+
+warm_reset:
+ /* --------------------------------------------------------------------
+ * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out
+ * of the caches after every update using normal memory so its safe to
+ * read it here with SO attributes
+ * ---------------------------------------------------------------------
+ */
+ ldr x10, =MBOX_BASE
+ bl platform_get_core_pos
+ lsl x0, x0, #CACHE_WRITEBACK_SHIFT
+ ldr x0, [x10, x0]
+ cbz x0, _panic
+exit:
+ ret x9
+_panic:
+ b do_panic
+#endif
+
+endfunc plat_get_my_entrypoint
+
+ /* ---------------------------------------------
+ * plat_secondary_reset
+ *
+ * ---------------------------------------------
+ */
+func plat_secondary_reset
+ mrs x0, sctlr_el3
+ bic x0, x0, #SCTLR_EE_BIT
+ msr sctlr_el3, x0
+ isb
+
+ mrs x0, cptr_el3
+ bic w0, w0, #TCPAC_BIT
+ bic w0, w0, #TTA_BIT
+ bic w0, w0, #TFP_BIT
+ msr cptr_el3, x0
+
+ mov_imm x0, PARAMS_BASE
+ mov_imm x2, BL31_BASE
+ ldr x3, =BOOT_KIND_BASE
+ mov x1, #0x1
+ str x1, [x3]
+ br x2 /* jump to BL31 */
+ nop
+ nop
+ nop
+endfunc plat_secondary_reset
+
+ /* ---------------------------------------------
+ * plat_enter_bl31
+ *
+ * ---------------------------------------------
+ */
+func bl2_enter_bl31
+ mov x20, x0
+ /*
+ * MMU needs to be disabled because both BL2 and BL31 execute
+ * in EL3, and therefore share the same address space.
+ * BL31 will initialize the address space according to its
+ * own requirement.
+ */
+#if RCAR_BL2_DCACHE == 1
+ /* Disable mmu and data cache */
+ bl disable_mmu_el3
+ /* Data cache clean and invalidate */
+ mov x0, #DCCISW
+ bl dcsw_op_all
+ /* TLB invalidate all, EL3 */
+ tlbi alle3
+#endif /* RCAR_BL2_DCACHE == 1 */
+ bl disable_mmu_icache_el3
+ /* Invalidate instruction cache */
+ ic iallu
+ dsb sy
+ isb
+ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+ msr elr_el3, x0
+ msr spsr_el3, x1
+ exception_return
+endfunc bl2_enter_bl31
+
+ /* -----------------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * Zero out the mailbox registers in the shared memory
+ * and set the rcar_boot_kind_flag.
+ * The mmu is turned off right now and only the primary can
+ * ever execute this code. Secondaries will read the
+ * mailboxes using SO accesses.
+ * -----------------------------------------------------
+ */
+func platform_mem_init
+#if !IMAGE_BL2
+ ldr x0, =MBOX_BASE
+ mov w1, #PLATFORM_CORE_COUNT
+loop:
+ str xzr, [x0], #CACHE_WRITEBACK_GRANULE
+ subs w1, w1, #1
+ b.gt loop
+#endif
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * void plat_report_exception(unsigned int type)
+ * Function to report an unhandled exception
+ * with platform-specific means.
+ * ---------------------------------------------
+ */
+func plat_report_exception
+ /* Switch to SP_EL0 */
+ msr spsel, #0
+#if IMAGE_BL2
+ mov w1, #FIQ_SP_EL0
+ cmp w0, w1
+ beq rep_exec_fiq_elx
+ b rep_exec_panic_type
+rep_exec_fiq_elx:
+ bl gicv2_acknowledge_interrupt
+ mov x2, #INT_ID_MASK
+ and x0, x0, x2
+ mov x1, #ARM_IRQ_SEC_WDT
+ cmp x0, x1
+ bne rep_exec_panic_id
+ mrs x0, ELR_EL3
+ b rcar_swdt_exec
+rep_exec_panic_type:
+ /* x0 is interrupt TYPE */
+ b bl2_interrupt_error_type
+rep_exec_panic_id:
+ /* x0 is interrupt ID */
+ b bl2_interrupt_error_id
+rep_exec_end:
+#endif
+ ret
+endfunc plat_report_exception
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize log area
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+#if IMAGE_BL2
+ mov x0, #0
+#else
+ mov x1, sp
+ mov_imm x2, RCAR_CRASH_STACK
+ mov sp, x2
+ str x1, [sp, #-16]!
+ str x30, [sp, #-16]!
+ bl console_rcar_init
+ ldr x30, [sp], #16
+ ldr x1, [sp], #16
+ mov sp, x1
+#endif
+ ret
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to store a character to log area
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov x1, sp
+ mov_imm x2, RCAR_CRASH_STACK
+ mov sp, x2
+ str x1, [sp, #-16]!
+ str x30, [sp, #-16]!
+ str x3, [sp, #-16]!
+ str x4, [sp, #-16]!
+ str x5, [sp, #-16]!
+ str x6, [sp, #-16]!
+ str x7, [sp, #-16]!
+ bl console_rcar_putc
+ ldr x7, [sp], #16
+ ldr x6, [sp], #16
+ ldr x5, [sp], #16
+ ldr x4, [sp], #16
+ ldr x3, [sp], #16
+ ldr x30, [sp], #16
+ ldr x1, [sp], #16
+ mov sp, x1
+ ret
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ b console_rcar_flush
+endfunc plat_crash_console_flush
+
+ /* --------------------------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Before adding code in this function, refer to the guidelines in
+ * docs/firmware-design.md to determine whether the code should reside
+ * within the FIRST_RESET_HANDLER_CALL block or not.
+ *
+ * For R-Car H3:
+ * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57
+ * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
+ * For R-Car M3/M3N:
+ * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57
+ * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
+ *
+ * --------------------------------------------------------------------
+ */
+func plat_reset_handler
+ /*
+ * On R-Car H3 : x2 := 0
+ * On R-Car M3/M3N: x2 := 1
+ */
+ /* read PRR */
+ ldr x0, =0xFFF00044
+ ldr w0, [x0]
+ ubfx w0, w0, 8, 8
+ /* H3? */
+ cmp w0, #0x4F
+ b.eq RCARH3
+ /* set R-Car M3/M3N */
+ mov x2, #1
+ b CHK_A5x
+RCARH3:
+ /* set R-Car H3 */
+ mov x2, #0
+ /* --------------------------------------------------------------------
+ * Determine whether this code is executed on a Cortex-A53 or on a
+ * Cortex-A57 core.
+ * --------------------------------------------------------------------
+ */
+CHK_A5x:
+ mrs x0, midr_el1
+ ubfx x1, x0, MIDR_PN_SHIFT, #12
+ cmp w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+ b.eq A57
+ ret
+A57:
+ /* Get data from CORTEX_A57_L2CTLR_EL1 */
+ mrs x0, CORTEX_A57_L2CTLR_EL1
+ /*
+ * On R-Car H3/M3/M3N
+ *
+ * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1
+ * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1
+ * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1
+ */
+ /* clear bit of L2 RAM */
+ /* ~(0x1e7) -> x1 */
+ mov x1, #0x1e7
+ neg x1, x1
+ /* clear bit of L2 RAM -> x0 */
+ and x0, x0, x1
+ /* L2 Tag RAM latency (3 cycles) */
+ orr x0, x0, #0x2 << 6
+ /* If M3/M3N then L2 RAM setup is 0 */
+ cbnz x2, M3_L2
+ /* L2 Data RAM setup (1 cycle) */
+ orr x0, x0, #0x1 << 5
+M3_L2:
+ /* L2 Data RAM latency (4 cycles) */
+ orr x0, x0, #0x3
+ /* Store data to L2CTLR_EL1 */
+ msr CORTEX_A57_L2CTLR_EL1, x0
+apply_l2_ram_latencies:
+ ret
+endfunc plat_reset_handler
+
+ /* ---------------------------------------------
+ * void plat_invalidate_icache(void)
+ * Instruction Cache Invalidate All to PoU
+ * ---------------------------------------------
+ */
+func plat_invalidate_icache
+ ic iallu
+
+ ret
+endfunc plat_invalidate_icache
diff --git a/plat/renesas/common/aarch64/platform_common.c b/plat/renesas/common/aarch64/platform_common.c
new file mode 100644
index 0000000..b0a88cb
--- /dev/null
+++ b/plat/renesas/common/aarch64/platform_common.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include "rcar_def.h"
+#include "rcar_private.h"
+#include "rcar_version.h"
+
+#if (IMAGE_BL2)
+extern void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *p);
+extern int32_t rcar_get_certificate(const int32_t name, uint32_t *cert);
+#endif
+
+const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN]
+ __attribute__ ((__section__("ro"))) = VERSION_OF_RENESAS;
+
+#define MAP_SHARED_RAM MAP_REGION_FLAT(RCAR_SHARED_MEM_BASE, \
+ RCAR_SHARED_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_FLASH0 MAP_REGION_FLAT(FLASH0_BASE, \
+ FLASH0_SIZE, \
+ MT_MEMORY | MT_RO | MT_SECURE)
+
+#define MAP_DRAM1_NS MAP_REGION_FLAT(DRAM1_NS_BASE, \
+ DRAM1_NS_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_DEVICE_RCAR MAP_REGION_FLAT(DEVICE_RCAR_BASE, \
+ DEVICE_RCAR_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE_RCAR2 MAP_REGION_FLAT(DEVICE_RCAR_BASE2, \
+ DEVICE_RCAR_SIZE2, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SRAM MAP_REGION_FLAT(DEVICE_SRAM_BASE, \
+ DEVICE_SRAM_SIZE, \
+ MT_MEMORY | MT_RO | MT_SECURE)
+
+#define MAP_SRAM_STACK MAP_REGION_FLAT(DEVICE_SRAM_STACK_BASE, \
+ DEVICE_SRAM_STACK_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_ATFW_CRASH MAP_REGION_FLAT(RCAR_BL31_CRASH_BASE, \
+ RCAR_BL31_CRASH_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_ATFW_LOG MAP_REGION_FLAT(RCAR_BL31_LOG_BASE, \
+ RCAR_BL31_LOG_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#if IMAGE_BL2
+#define MAP_DRAM0 MAP_REGION_FLAT(DRAM1_BASE, \
+ DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_REG0 MAP_REGION_FLAT(DEVICE_RCAR_BASE, \
+ DEVICE_RCAR_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_RAM0 MAP_REGION_FLAT(RCAR_SYSRAM_BASE, \
+ RCAR_SYSRAM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_REG1 MAP_REGION_FLAT(REG1_BASE, \
+ REG1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_ROM MAP_REGION_FLAT(ROM0_BASE, \
+ ROM0_SIZE, \
+ MT_MEMORY | MT_RO | MT_SECURE)
+
+#define MAP_REG2 MAP_REGION_FLAT(REG2_BASE, \
+ REG2_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DRAM1 MAP_REGION_FLAT(DRAM_40BIT_BASE, \
+ DRAM_40BIT_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
+#ifdef BL32_BASE
+#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_BASE, \
+ BL32_LIMIT - BL32_BASE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
+#if IMAGE_BL2
+static const mmap_region_t rcar_mmap[] = {
+ MAP_FLASH0, /* 0x08000000 - 0x0BFFFFFF RPC area */
+ MAP_DRAM0, /* 0x40000000 - 0xBFFFFFFF DRAM area(Legacy) */
+ MAP_REG0, /* 0xE6000000 - 0xE62FFFFF SoC register area */
+ MAP_RAM0, /* 0xE6300000 - 0xE6303FFF System RAM area */
+ MAP_REG1, /* 0xE6400000 - 0xEAFFFFFF SoC register area */
+ MAP_ROM, /* 0xEB100000 - 0xEB127FFF boot ROM area */
+ MAP_REG2, /* 0xEC000000 - 0xFFFFFFFF SoC register area */
+ MAP_DRAM1, /* 0x0400000000 - 0x07FFFFFFFF DRAM area(4GB over) */
+ {0}
+};
+#endif
+
+#if IMAGE_BL31
+static const mmap_region_t rcar_mmap[] = {
+ MAP_SHARED_RAM,
+ MAP_ATFW_CRASH,
+ MAP_ATFW_LOG,
+ MAP_DEVICE_RCAR,
+ MAP_DEVICE_RCAR2,
+ MAP_SRAM,
+ MAP_SRAM_STACK,
+ {0}
+};
+#endif
+
+#if IMAGE_BL32
+static const mmap_region_t rcar_mmap[] = {
+ MAP_DEVICE0,
+ MAP_DEVICE1,
+ {0}
+};
+#endif
+
+CASSERT(ARRAY_SIZE(rcar_mmap) + RCAR_BL_REGIONS
+ <= MAX_MMAP_REGIONS, assert_max_mmap_regions);
+
+/*
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ */
+#if USE_COHERENT_MEM
+void rcar_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_MEMORY | MT_RO | MT_SECURE);
+ mmap_add_region(coh_start, coh_start, coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ mmap_add(rcar_mmap);
+
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+#else
+void rcar_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_MEMORY | MT_RO | MT_SECURE);
+ mmap_add(rcar_mmap);
+
+ init_xlat_tables();
+ enable_mmu_el3(0);
+}
+#endif
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#if (IMAGE_BL2)
+ uint32_t cert, len;
+ uintptr_t dst;
+ int32_t ret;
+
+ ret = rcar_get_certificate(NON_TRUSTED_FW_CONTENT_CERT_ID, &cert);
+ if (ret) {
+ ERROR("%s : cert file load error", __func__);
+ return NS_IMAGE_OFFSET;
+ }
+
+ rcar_read_certificate((uint64_t) cert, &len, &dst);
+
+ return dst;
+#else
+ return NS_IMAGE_OFFSET;
+#endif
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int freq;
+
+ freq = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
+ if (freq == 0)
+ panic();
+
+ return freq;
+}
+
+void plat_rcar_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+static const interrupt_prop_t interrupt_props[] = {
+#if IMAGE_BL2
+ INTR_PROP_DESC(ARM_IRQ_SEC_WDT, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+#else
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
+ INTR_PROP_DESC(ARM_IRQ_SEC_RPC, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(ARM_IRQ_SEC_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(ARM_IRQ_SEC_TIMER_UP, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(ARM_IRQ_SEC_WDT, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(ARM_IRQ_SEC_CRYPT, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(ARM_IRQ_SEC_CRYPT_SecPKA, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+ INTR_PROP_DESC(ARM_IRQ_SEC_CRYPT_PubPKA, GIC_HIGHEST_SEC_PRIORITY,
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+#endif
+};
+
+static const gicv2_driver_data_t plat_gicv2_driver_data = {
+ .interrupt_props = interrupt_props,
+ .interrupt_props_num = (uint32_t) ARRAY_SIZE(interrupt_props),
+ .gicd_base = RCAR_GICD_BASE,
+ .gicc_base = RCAR_GICC_BASE,
+};
+
+void plat_rcar_gic_driver_init(void)
+{
+ gicv2_driver_init(&plat_gicv2_driver_data);
+}
diff --git a/plat/renesas/common/bl2_cpg_init.c b/plat/renesas/common/bl2_cpg_init.c
new file mode 100644
index 0000000..a545f71
--- /dev/null
+++ b/plat/renesas/common/bl2_cpg_init.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include "cpg_registers.h"
+#include "rcar_def.h"
+#include "rcar_private.h"
+
+static void bl2_secure_cpg_init(void);
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) || \
+ (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H)
+static void bl2_realtime_cpg_init_h3(void);
+static void bl2_system_cpg_init_h3(void);
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M)
+static void bl2_realtime_cpg_init_m3(void);
+static void bl2_system_cpg_init_m3(void);
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) || (RCAR_LSI == RZ_G2N)
+static void bl2_realtime_cpg_init_m3n(void);
+static void bl2_system_cpg_init_m3n(void);
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_V3M)
+static void bl2_realtime_cpg_init_v3m(void);
+static void bl2_system_cpg_init_v3m(void);
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E)
+static void bl2_realtime_cpg_init_e3(void);
+static void bl2_system_cpg_init_e3(void);
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_D3)
+static void bl2_system_cpg_init_d3(void);
+#endif
+
+typedef struct {
+ uintptr_t adr;
+ uint32_t val;
+} reg_setting_t;
+
+static void bl2_secure_cpg_init(void)
+{
+ uint32_t stop_cr2, reset_cr2;
+ uint32_t stop_cr4, reset_cr4;
+ uint32_t stop_cr5, reset_cr5;
+
+#if (RCAR_LSI == RCAR_D3)
+ reset_cr2 = 0x00000000U;
+ stop_cr2 = 0xFFFFFFFFU;
+#elif (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E)
+ reset_cr2 = 0x10000000U;
+ stop_cr2 = 0xEFFFFFFFU;
+#else
+ reset_cr2 = 0x14000000U;
+ stop_cr2 = 0xEBFFFFFFU;
+#endif
+
+#if (RCAR_LSI == RCAR_D3)
+ reset_cr4 = 0x00000000U;
+ stop_cr4 = 0xFFFFFFFFU;
+ reset_cr5 = 0x00000000U;
+ stop_cr5 = 0xFFFFFFFFU;
+#else
+ reset_cr4 = 0x80000003U;
+ stop_cr4 = 0x7FFFFFFFU;
+ reset_cr5 = 0x40000000U;
+ stop_cr5 = 0xBFFFFFFFU;
+#endif
+
+ /* Secure Module Stop Control Registers */
+ cpg_write(SCMSTPCR0, 0xFFFFFFFFU);
+ cpg_write(SCMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(SCMSTPCR2, stop_cr2);
+ cpg_write(SCMSTPCR3, 0xFFFFFFFFU);
+ cpg_write(SCMSTPCR4, stop_cr4);
+ cpg_write(SCMSTPCR5, stop_cr5);
+ cpg_write(SCMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(SCMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(SCMSTPCR8, 0xFFFFFFFFU);
+ cpg_write(SCMSTPCR9, 0xFFFDFFFFU);
+ cpg_write(SCMSTPCR10, 0xFFFFFFFFU);
+ cpg_write(SCMSTPCR11, 0xFFFFFFFFU);
+
+ /* Secure Software Reset Access Enable Control Registers */
+ cpg_write(SCSRSTECR0, 0x00000000U);
+ cpg_write(SCSRSTECR1, 0x00000000U);
+ cpg_write(SCSRSTECR2, reset_cr2);
+ cpg_write(SCSRSTECR3, 0x00000000U);
+ cpg_write(SCSRSTECR4, reset_cr4);
+ cpg_write(SCSRSTECR5, reset_cr5);
+ cpg_write(SCSRSTECR6, 0x00000000U);
+ cpg_write(SCSRSTECR7, 0x00000000U);
+ cpg_write(SCSRSTECR8, 0x00000000U);
+ cpg_write(SCSRSTECR9, 0x00020000U);
+ cpg_write(SCSRSTECR10, 0x00000000U);
+ cpg_write(SCSRSTECR11, 0x00000000U);
+}
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) || \
+ (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H)
+static void bl2_realtime_cpg_init_h3(void)
+{
+ uint32_t cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK;
+ uint32_t cr0, cr8;
+
+ cr0 = (cut == PRR_PRODUCT_10 || cut == PRR_PRODUCT_11) ?
+ 0x00200000U : 0x00210000U;
+ cr8 = (cut == PRR_PRODUCT_10 || cut == PRR_PRODUCT_11) ?
+ 0x01F1FFF4U : 0x01F1FFF7U;
+
+ cpg_write(RMSTPCR0, cr0);
+ cpg_write(RMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR2, 0x040E0FDCU);
+ cpg_write(RMSTPCR3, 0xFFFFFFDFU);
+ cpg_write(RMSTPCR4, 0x80000004U);
+ cpg_write(RMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(RMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR8, cr8);
+ cpg_write(RMSTPCR9, 0xFFFFFFFEU);
+ cpg_write(RMSTPCR10, 0xFFFEFFE0U);
+ cpg_write(RMSTPCR11, 0x000000B7U);
+}
+
+static void bl2_system_cpg_init_h3(void)
+{
+ /** System Module Stop Control Registers */
+ cpg_write(SMSTPCR0, 0x00210000U);
+ cpg_write(SMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR2, 0x040E2FDCU);
+ cpg_write(SMSTPCR3, 0xFFFFFBDFU);
+ cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
+ cpg_write(SMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(SMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR8, 0x01F1FFF5U);
+ cpg_write(SMSTPCR9, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR10, 0xFFFEFFE0U);
+ cpg_write(SMSTPCR11, 0x000000B7U);
+}
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M)
+static void bl2_realtime_cpg_init_m3(void)
+{
+ /* Realtime Module Stop Control Registers */
+ cpg_write(RMSTPCR0, 0x00200000U);
+ cpg_write(RMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR2, 0x040E0FDCU);
+ cpg_write(RMSTPCR3, 0xFFFFFFDFU);
+ cpg_write(RMSTPCR4, 0x80000004U);
+ cpg_write(RMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(RMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR8, 0x01F1FFF7U);
+ cpg_write(RMSTPCR9, 0xFFFFFFFEU);
+ cpg_write(RMSTPCR10, 0xFFFEFFE0U);
+ cpg_write(RMSTPCR11, 0x000000B7U);
+}
+
+static void bl2_system_cpg_init_m3(void)
+{
+ /* System Module Stop Control Registers */
+ cpg_write(SMSTPCR0, 0x00200000U);
+ cpg_write(SMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR2, 0x040E2FDCU);
+ cpg_write(SMSTPCR3, 0xFFFFFBDFU);
+ cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
+ cpg_write(SMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(SMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR8, 0x01F1FFF7U);
+ cpg_write(SMSTPCR9, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR10, 0xFFFEFFE0U);
+ cpg_write(SMSTPCR11, 0x000000B7U);
+}
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) || (RCAR_LSI == RZ_G2N)
+static void bl2_realtime_cpg_init_m3n(void)
+{
+ /* Realtime Module Stop Control Registers */
+ cpg_write(RMSTPCR0, 0x00210000U);
+ cpg_write(RMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR2, 0x040E0FDCU);
+ cpg_write(RMSTPCR3, 0xFFFFFFDFU);
+ cpg_write(RMSTPCR4, 0x80000004U);
+ cpg_write(RMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(RMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR8, 0x00F1FFF7U);
+ cpg_write(RMSTPCR9, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR10, 0xFFFFFFE0U);
+ cpg_write(RMSTPCR11, 0x000000B7U);
+}
+
+static void bl2_system_cpg_init_m3n(void)
+{
+ /* System Module Stop Control Registers */
+ cpg_write(SMSTPCR0, 0x00210000U);
+ cpg_write(SMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR2, 0x040E2FDCU);
+ cpg_write(SMSTPCR3, 0xFFFFFBDFU);
+ cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
+ cpg_write(SMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(SMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR8, 0x00F1FFF7U);
+ cpg_write(SMSTPCR9, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR10, 0xFFFFFFE0U);
+ cpg_write(SMSTPCR11, 0x000000B7U);
+}
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_V3M)
+static void bl2_realtime_cpg_init_v3m(void)
+{
+ /* Realtime Module Stop Control Registers */
+ cpg_write(RMSTPCR0, 0x00230000U);
+ cpg_write(RMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR2, 0x14062FD8U);
+ cpg_write(RMSTPCR3, 0xFFFFFFDFU);
+ cpg_write(RMSTPCR4, 0x80000184U);
+ cpg_write(RMSTPCR5, 0x83FFFFFFU);
+ cpg_write(RMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR8, 0x7FF3FFF4U);
+ cpg_write(RMSTPCR9, 0xFFFFFFFEU);
+}
+
+static void bl2_system_cpg_init_v3m(void)
+{
+ /* System Module Stop Control Registers */
+ cpg_write(SMSTPCR0, 0x00210000U);
+ cpg_write(SMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR2, 0x340E2FDCU);
+ cpg_write(SMSTPCR3, 0xFFFFFBDFU);
+ cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
+ cpg_write(SMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(SMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR8, 0x01F1FFF5U);
+ cpg_write(SMSTPCR9, 0xFFFFFFFEU);
+}
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E)
+static void bl2_realtime_cpg_init_e3(void)
+{
+ /* Realtime Module Stop Control Registers */
+ cpg_write(RMSTPCR0, 0x00210000U);
+ cpg_write(RMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR2, 0x000E0FDCU);
+ cpg_write(RMSTPCR3, 0xFFFFFFDFU);
+ cpg_write(RMSTPCR4, 0x80000004U);
+ cpg_write(RMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(RMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(RMSTPCR8, 0x00F1FFF7U);
+ cpg_write(RMSTPCR9, 0xFFFFFFDFU);
+ cpg_write(RMSTPCR10, 0xFFFFFFE8U);
+ cpg_write(RMSTPCR11, 0x000000B7U);
+}
+
+static void bl2_system_cpg_init_e3(void)
+{
+ /* System Module Stop Control Registers */
+ cpg_write(SMSTPCR0, 0x00210000U);
+ cpg_write(SMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR2, 0x000E2FDCU);
+ cpg_write(SMSTPCR3, 0xFFFFFBDFU);
+ cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
+ cpg_write(SMSTPCR5, 0xC3FFFFFFU);
+ cpg_write(SMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR8, 0x00F1FFF7U);
+ cpg_write(SMSTPCR9, 0xFFFFFFDFU);
+ cpg_write(SMSTPCR10, 0xFFFFFFE8U);
+ cpg_write(SMSTPCR11, 0x000000B7U);
+}
+#endif
+
+#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_D3)
+static void bl2_system_cpg_init_d3(void)
+{
+ /* System Module Stop Control Registers */
+ cpg_write(SMSTPCR0, 0x00010000U);
+ cpg_write(SMSTPCR1, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR2, 0x00060FDCU);
+ cpg_write(SMSTPCR3, 0xFFFFFBDFU);
+ cpg_write(SMSTPCR4, 0x00000080U | (mmio_read_32(SMSTPCR4) & 0x4));
+ cpg_write(SMSTPCR5, 0x83FFFFFFU);
+ cpg_write(SMSTPCR6, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR7, 0xFFFFFFFFU);
+ cpg_write(SMSTPCR8, 0x00F1FFF7U);
+ cpg_write(SMSTPCR9, 0xF3F5E016U);
+ cpg_write(SMSTPCR10, 0xFFFEFFE0U);
+ cpg_write(SMSTPCR11, 0x000000B7U);
+}
+#endif
+
+void bl2_cpg_init(void)
+{
+ uint32_t boot_cpu = mmio_read_32(RCAR_MODEMR) & MODEMR_BOOT_CPU_MASK;
+#if RCAR_LSI == RCAR_AUTO
+ uint32_t product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK;
+#endif
+ bl2_secure_cpg_init();
+
+ if (boot_cpu == MODEMR_BOOT_CPU_CA57 ||
+ boot_cpu == MODEMR_BOOT_CPU_CA53) {
+#if RCAR_LSI == RCAR_AUTO
+
+ switch (product) {
+ case PRR_PRODUCT_H3:
+ bl2_realtime_cpg_init_h3();
+ break;
+ case PRR_PRODUCT_M3:
+ bl2_realtime_cpg_init_m3();
+ break;
+ case PRR_PRODUCT_M3N:
+ bl2_realtime_cpg_init_m3n();
+ break;
+ case PRR_PRODUCT_V3M:
+ bl2_realtime_cpg_init_v3m();
+ break;
+ case PRR_PRODUCT_E3:
+ bl2_realtime_cpg_init_e3();
+ break;
+ case PRR_PRODUCT_D3:
+ /* no need */
+ break;
+ default:
+ panic();
+ break;
+ }
+#elif (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H)
+ bl2_realtime_cpg_init_h3();
+#elif (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M)
+ bl2_realtime_cpg_init_m3();
+#elif RCAR_LSI == RCAR_M3N || (RCAR_LSI == RZ_G2N)
+ bl2_realtime_cpg_init_m3n();
+#elif RCAR_LSI == RCAR_V3M
+ bl2_realtime_cpg_init_v3m();
+#elif RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2E
+ bl2_realtime_cpg_init_e3();
+#elif RCAR_LSI == RCAR_D3
+ /* no need */
+#else
+#error "Don't have CPG initialize routine(unknown)."
+#endif
+ }
+}
+
+void bl2_system_cpg_init(void)
+{
+#if RCAR_LSI == RCAR_AUTO
+ uint32_t product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK;
+
+ switch (product) {
+ case PRR_PRODUCT_H3:
+ bl2_system_cpg_init_h3();
+ break;
+ case PRR_PRODUCT_M3:
+ bl2_system_cpg_init_m3();
+ break;
+ case PRR_PRODUCT_M3N:
+ bl2_system_cpg_init_m3n();
+ break;
+ case PRR_PRODUCT_V3M:
+ bl2_system_cpg_init_v3m();
+ break;
+ case PRR_PRODUCT_E3:
+ bl2_system_cpg_init_e3();
+ break;
+ case PRR_PRODUCT_D3:
+ bl2_system_cpg_init_d3();
+ break;
+ default:
+ panic();
+ break;
+ }
+#elif (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) || (RCAR_LSI == RZ_G2H)
+ bl2_system_cpg_init_h3();
+#elif (RCAR_LSI == RCAR_M3) || (RCAR_LSI == RZ_G2M)
+ bl2_system_cpg_init_m3();
+#elif RCAR_LSI == RCAR_M3N || (RCAR_LSI == RZ_G2N)
+ bl2_system_cpg_init_m3n();
+#elif RCAR_LSI == RCAR_V3M
+ bl2_system_cpg_init_v3m();
+#elif RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2E
+ bl2_system_cpg_init_e3();
+#elif RCAR_LSI == RCAR_D3
+ bl2_system_cpg_init_d3();
+#else
+#error "Don't have CPG initialize routine(unknown)."
+#endif
+}
diff --git a/plat/renesas/common/bl2_interrupt_error.c b/plat/renesas/common/bl2_interrupt_error.c
new file mode 100644
index 0000000..d9a4b8e
--- /dev/null
+++ b/plat/renesas/common/bl2_interrupt_error.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+
+#include "rcar_def.h"
+
+#define SWDT_ERROR_ID (1024U)
+#define SWDT_ERROR_TYPE (16U)
+#define SWDT_CHAR_MAX (13U)
+
+extern void rcar_swdt_release(void);
+
+void bl2_interrupt_error_id(uint32_t int_id)
+{
+ ERROR("\n");
+ if (int_id >= SWDT_ERROR_ID) {
+ ERROR("Unhandled exception occurred.\n");
+ ERROR(" Exception type = FIQ_SP_EL0\n");
+ panic();
+ }
+
+ /* Clear the interrupt request */
+ gicv2_end_of_interrupt((uint32_t) int_id);
+ rcar_swdt_release();
+ ERROR("Unhandled exception occurred.\n");
+ ERROR(" Exception type = FIQ_SP_EL0\n");
+ ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3());
+ ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3());
+ ERROR(" ESR_EL3 = 0x%x\n", (uint32_t) read_esr_el3());
+ ERROR(" FAR_EL3 = 0x%x\n", (uint32_t) read_far_el3());
+ ERROR("\n");
+ panic();
+}
+
+void bl2_interrupt_error_type(uint32_t ex_type)
+{
+ const uint8_t interrupt_ex[SWDT_ERROR_TYPE][SWDT_CHAR_MAX] = {
+ "SYNC SP EL0",
+ "IRQ SP EL0",
+ "FIQ SP EL0",
+ "SERR SP EL0",
+ "SYNC SP ELx",
+ "IRQ SP ELx",
+ "FIQ SP ELx",
+ "SERR SP ELx",
+ "SYNC AARCH64",
+ "IRQ AARCH64",
+ "FIQ AARCH64",
+ "SERR AARCH64",
+ "SYNC AARCH32",
+ "IRQ AARCH32",
+ "FIQ AARCH32",
+ "SERR AARCH32"
+ };
+ char msg[128];
+
+ /* Clear the interrupt request */
+ if (ex_type >= SWDT_ERROR_TYPE) {
+ ERROR("\n");
+ ERROR("Unhandled exception occurred.\n");
+ ERROR(" Exception type = Unknown (%d)\n", ex_type);
+ goto loop;
+ }
+
+ rcar_swdt_release();
+ ERROR("\n");
+ ERROR("Unhandled exception occurred.\n");
+ snprintf(msg, sizeof(msg), " Exception type = %s\n",
+ &interrupt_ex[ex_type][0]);
+ ERROR("%s", msg);
+ switch (ex_type) {
+ case SYNC_EXCEPTION_SP_EL0:
+ ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3());
+ ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3());
+ ERROR(" ESR_EL3 = 0x%x\n", (uint32_t) read_esr_el3());
+ ERROR(" FAR_EL3 = 0x%x\n", (uint32_t) read_far_el3());
+ break;
+ case IRQ_SP_EL0:
+ ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3());
+ ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3());
+ ERROR(" IAR_EL3 = 0x%x\n", gicv2_acknowledge_interrupt());
+ break;
+ case FIQ_SP_EL0:
+ ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3());
+ ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3());
+ ERROR(" IAR_EL3 = 0x%x\n", gicv2_acknowledge_interrupt());
+ break;
+ case SERROR_SP_EL0:
+ ERROR(" SPSR_EL3 = 0x%x\n", (uint32_t) read_spsr_el3());
+ ERROR(" ELR_EL3 = 0x%x\n", (uint32_t) read_elr_el3());
+ ERROR(" ESR_EL3 = 0x%x\n", (uint32_t) read_esr_el3());
+ ERROR(" FAR_EL3 = 0x%x\n", (uint32_t) read_far_el3());
+ break;
+ default:
+ break;
+ }
+loop:
+ ERROR("\n");
+ panic();
+}
diff --git a/plat/renesas/common/bl2_plat_mem_params_desc.c b/plat/renesas/common/bl2_plat_mem_params_desc.c
new file mode 100644
index 0000000..bf2706d
--- /dev/null
+++ b/plat/renesas/common/bl2_plat_mem_params_desc.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/common/platform.h>
+
+#if (RCAR_BL33_EXECUTION_EL != 0) && (RCAR_BL33_EXECUTION_EL != 1)
+#error
+#endif
+
+#if (RCAR_BL33_EXECUTION_EL == 0)
+#define BL33_MODE MODE_EL1
+#else
+#define BL33_MODE MODE_EL2
+#endif
+
+extern uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)];
+
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t, SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.spsr = SPSR_64(MODE_EL3,
+ MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS),
+ .ep_info.pc = BL31_BASE,
+
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+ .image_info.image_base = BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+# ifdef BL32_BASE
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t, SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+ .ep_info.spsr = 0,
+ .ep_info.args.arg3 = (uintptr_t)fdt_blob,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, 0),
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+ .image_info.image_base = BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+#endif
+ {
+ .image_id = BL33_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+ entry_point_info_t, NON_SECURE | EXECUTABLE),
+ .ep_info.spsr = SPSR_64(BL33_MODE, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+ .ep_info.pc = BL33_BASE,
+#ifdef RCAR_BL33_ARG0
+ .ep_info.args.arg0 = RCAR_BL33_ARG0,
+#endif
+ .ep_info.args.arg1 = (uintptr_t)fdt_blob,
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+ image_info_t, 0),
+ .image_info.image_max_size =
+ (uint32_t) (DRAM_LIMIT - BL33_BASE),
+ .image_info.image_base = BL33_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/renesas/common/bl2_secure_setting.c b/plat/renesas/common/bl2_secure_setting.c
new file mode 100644
index 0000000..2f8b001
--- /dev/null
+++ b/plat/renesas/common/bl2_secure_setting.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "axi_registers.h"
+#include "lifec_registers.h"
+#include "micro_delay.h"
+
+static void lifec_security_setting(void);
+static void axi_security_setting(void);
+
+static const struct {
+ uint32_t reg;
+ uint32_t val;
+} lifec[] = {
+ /*
+ * LIFEC0 (SECURITY) settings
+ * Security attribute setting for master ports
+ * Bit 0: ARM realtime core (Cortex-R7) master port
+ * 0: Non-Secure
+ */
+ { SEC_SRC, 0x0000001EU },
+ /*
+ * Security attribute setting for slave ports 0 to 15
+ * {SEC_SEL0, 0xFFFFFFFFU},
+ * {SEC_SEL1, 0xFFFFFFFFU},
+ * {SEC_SEL2, 0xFFFFFFFFU},
+ * Bit19: AXI-Bus (Main Memory domain AXI) slave ports
+ * 0: registers accessed from secure resource only
+ * Bit 9: DBSC4 register access slave ports.
+ * 0: registers accessed from secure resource only.
+ */
+#if (LIFEC_DBSC_PROTECT_ENABLE == 1)
+ { SEC_SEL3, 0xFFF7FDFFU },
+#else /* LIFEC_DBSC_PROTECT_ENABLE == 1 */
+ { SEC_SEL3, 0xFFFFFFFFU },
+#endif /* LIFEC_DBSC_PROTECT_ENABLE == 1 */
+ /*
+ * {SEC_SEL4, 0xFFFFFFFFU},
+ * Bit 6: Boot ROM slave ports.
+ * 0: registers accessed from secure resource only
+ */
+ { SEC_SEL5, 0xFFFFFFBFU },
+ /*
+ * Bit13: SCEG PKA (secure APB) slave ports
+ * 0: registers accessed from secure resource only
+ * 1: Reserved[R-Car E3/D3]
+ * Bit12: SCEG PKA (public APB) slave ports
+ * 0: registers accessed from secure resource only
+ * 1: Reserved[R-Car E3/D3]
+ * Bit10: SCEG Secure Core slave ports
+ * 0: registers accessed from secure resource only
+ */
+#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3)
+ { SEC_SEL6, 0xFFFFFBFFU },
+#else /* (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) */
+ { SEC_SEL6, 0xFFFFCBFFU },
+#endif /* (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3) */
+ /*
+ * {SEC_SEL7, 0xFFFFFFFFU},
+ * {SEC_SEL8, 0xFFFFFFFFU},
+ * {SEC_SEL9, 0xFFFFFFFFU},
+ * {SEC_SEL10, 0xFFFFFFFFU},
+ * {SEC_SEL11, 0xFFFFFFFFU},
+ * {SEC_SEL12, 0xFFFFFFFFU},
+ * Bit22: RPC slave ports.
+ * 0: registers accessed from secure resource only.
+ */
+#if (RCAR_RPC_HYPERFLASH_LOCKED == 1)
+ { SEC_SEL13, 0xFFBFFFFFU },
+#endif /* (RCAR_RPC_HYPERFLASH_LOCKED == 1) */
+ /*
+ * Bit27: System Timer (SCMT) slave ports
+ * 0: registers accessed from secure resource only
+ * Bit26: System Watchdog Timer (SWDT) slave ports
+ * 0: registers accessed from secure resource only
+ */
+ { SEC_SEL14, 0xF3FFFFFFU },
+ /*
+ * Bit13: RST slave ports.
+ * 0: registers accessed from secure resource only
+ * Bit 7: Life Cycle 0 slave ports
+ * 0: registers accessed from secure resource only
+ */
+ { SEC_SEL15, 0xFFFFFF3FU },
+ /*
+ * Security group 0 attribute setting for master ports 0
+ * Security group 1 attribute setting for master ports 0
+ * {SEC_GRP0CR0, 0x00000000U},
+ * {SEC_GRP1CR0, 0x00000000U},
+ * Security group 0 attribute setting for master ports 1
+ * Security group 1 attribute setting for master ports 1
+ * {SEC_GRP0CR1, 0x00000000U},
+ * {SEC_GRP1CR1, 0x00000000U},
+ * Security group 0 attribute setting for master ports 2
+ * Security group 1 attribute setting for master ports 2
+ * Bit17: SCEG Secure Core master ports.
+ * SecurityGroup3
+ */
+ { SEC_GRP0CR2, 0x00020000U },
+ { SEC_GRP1CR2, 0x00020000U },
+ /*
+ * Security group 0 attribute setting for master ports 3
+ * Security group 1 attribute setting for master ports 3
+ * {SEC_GRP0CR3, 0x00000000U},
+ * {SEC_GRP1CR3, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 0
+ * Security group 1 attribute setting for slave ports 0
+ * {SEC_GRP0COND0, 0x00000000U},
+ * {SEC_GRP1COND0, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 1
+ * Security group 1 attribute setting for slave ports 1
+ * {SEC_GRP0COND1, 0x00000000U},
+ * {SEC_GRP1COND1, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 2
+ * Security group 1 attribute setting for slave ports 2
+ * {SEC_GRP0COND2, 0x00000000U},
+ * {SEC_GRP1COND2, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 3
+ * Security group 1 attribute setting for slave ports 3
+ * Bit19: AXI-Bus (Main Memory domain AXI) slave ports.
+ * SecurityGroup3
+ * Bit 9: DBSC4 register access slave ports.
+ * SecurityGroup3
+ */
+#if (LIFEC_DBSC_PROTECT_ENABLE == 1)
+ { SEC_GRP0COND3, 0x00080200U },
+ { SEC_GRP1COND3, 0x00080200U },
+#else /* (LIFEC_DBSC_PROTECT_ENABLE == 1) */
+ { SEC_GRP0COND3, 0x00000000U },
+ { SEC_GRP1COND3, 0x00000000U },
+#endif /* (LIFEC_DBSC_PROTECT_ENABLE == 1) */
+ /*
+ * Security group 0 attribute setting for slave ports 4
+ * Security group 1 attribute setting for slave ports 4
+ * {SEC_GRP0COND4, 0x00000000U},
+ * {SEC_GRP1COND4, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 5
+ * Security group 1 attribute setting for slave ports 5
+ * Bit 6: Boot ROM slave ports
+ * SecurityGroup3
+ */
+ { SEC_GRP0COND5, 0x00000040U },
+ { SEC_GRP1COND5, 0x00000040U },
+ /*
+ * Security group 0 attribute setting for slave ports 6
+ * Security group 1 attribute setting for slave ports 6
+ * Bit13: SCEG PKA (secure APB) slave ports
+ * SecurityGroup3
+ * Reserved[R-Car E3/D3]
+ * Bit12: SCEG PKA (public APB) slave ports
+ * SecurityGroup3
+ * Reserved[R-Car E3/D3]
+ * Bit10: SCEG Secure Core slave ports
+ * SecurityGroup3
+ */
+#if RCAR_LSI == RCAR_E3 || RCAR_LSI == RCAR_D3
+ { SEC_GRP0COND6, 0x00000400U },
+ { SEC_GRP1COND6, 0x00000400U },
+#else /* RCAR_LSI == RCAR_E3 */
+ { SEC_GRP0COND6, 0x00003400U },
+ { SEC_GRP1COND6, 0x00003400U },
+#endif /* RCAR_LSI == RCAR_E3 */
+ /*
+ * Security group 0 attribute setting for slave ports 7
+ * Security group 1 attribute setting for slave ports 7
+ * {SEC_GRP0COND7, 0x00000000U},
+ * {SEC_GRP1COND7, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 8
+ * Security group 1 attribute setting for slave ports 8
+ * {SEC_GRP0COND8, 0x00000000U},
+ * {SEC_GRP1COND8, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 9
+ * Security group 1 attribute setting for slave ports 9
+ * {SEC_GRP0COND9, 0x00000000U},
+ * {SEC_GRP1COND9, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 10
+ * Security group 1 attribute setting for slave ports 10
+ * {SEC_GRP0COND10, 0x00000000U},
+ * {SEC_GRP1COND10, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 11
+ * Security group 1 attribute setting for slave ports 11
+ * {SEC_GRP0COND11, 0x00000000U},
+ * {SEC_GRP1COND11, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 12
+ * Security group 1 attribute setting for slave ports 12
+ * {SEC_GRP0COND12, 0x00000000U},
+ * {SEC_GRP1COND12, 0x00000000U},
+ * Security group 0 attribute setting for slave ports 13
+ * Security group 1 attribute setting for slave ports 13
+ * Bit22: RPC slave ports.
+ * SecurityGroup3
+ */
+#if (RCAR_RPC_HYPERFLASH_LOCKED == 1)
+ { SEC_GRP0COND13, 0x00400000U },
+ { SEC_GRP1COND13, 0x00400000U },
+#endif /* (RCAR_RPC_HYPERFLASH_LOCKED == 1) */
+ /*
+ * Security group 0 attribute setting for slave ports 14
+ * Security group 1 attribute setting for slave ports 14
+ * Bit26: System Timer (SCMT) slave ports
+ * SecurityGroup3
+ * Bit27: System Watchdog Timer (SWDT) slave ports
+ * SecurityGroup3
+ */
+ { SEC_GRP0COND14, 0x0C000000U },
+ { SEC_GRP1COND14, 0x0C000000U },
+ /*
+ * Security group 0 attribute setting for slave ports 15
+ * Security group 1 attribute setting for slave ports 15
+ * Bit13: RST slave ports
+ * SecurityGroup3
+ * Bit 7: Life Cycle 0 slave ports
+ * SecurityGroup3
+ * Bit 6: TDBG slave ports
+ * SecurityGroup3
+ */
+ { SEC_GRP0COND15, 0x000000C0U },
+ { SEC_GRP1COND15, 0x000000C0U },
+ /*
+ * Security write protection attribute setting slave ports 0
+ * {SEC_READONLY0, 0x00000000U},
+ * Security write protection attribute setting slave ports 1
+ * {SEC_READONLY1, 0x00000000U},
+ * Security write protection attribute setting slave ports 2
+ * {SEC_READONLY2, 0x00000000U},
+ * Security write protection attribute setting slave ports 3
+ * {SEC_READONLY3, 0x00000000U},
+ * Security write protection attribute setting slave ports 4
+ * {SEC_READONLY4, 0x00000000U},
+ * Security write protection attribute setting slave ports 5
+ * {SEC_READONLY5, 0x00000000U},
+ * Security write protection attribute setting slave ports 6
+ * {SEC_READONLY6, 0x00000000U},
+ * Security write protection attribute setting slave ports 7
+ * {SEC_READONLY7, 0x00000000U},
+ * Security write protection attribute setting slave ports 8
+ * {SEC_READONLY8, 0x00000000U},
+ * Security write protection attribute setting slave ports 9
+ * {SEC_READONLY9, 0x00000000U},
+ * Security write protection attribute setting slave ports 10
+ * {SEC_READONLY10, 0x00000000U},
+ * Security write protection attribute setting slave ports 11
+ * {SEC_READONLY11, 0x00000000U},
+ * Security write protection attribute setting slave ports 12
+ * {SEC_READONLY12, 0x00000000U},
+ * Security write protection attribute setting slave ports 13
+ * {SEC_READONLY13, 0x00000000U},
+ * Security write protection attribute setting slave ports 14
+ * {SEC_READONLY14, 0x00000000U},
+ * Security write protection attribute setting slave ports 15
+ * {SEC_READONLY15, 0x00000000U}
+ */
+};
+
+/* AXI settings */
+static const struct {
+ uint32_t reg;
+ uint32_t val;
+} axi[] = {
+ /*
+ * DRAM protection
+ * AXI dram protected area division
+ */
+ {AXI_DPTDIVCR0, 0x0E0403F0U},
+ {AXI_DPTDIVCR1, 0x0E0407E0U},
+ {AXI_DPTDIVCR2, 0x0E080000U},
+ {AXI_DPTDIVCR3, 0x0E080000U},
+ {AXI_DPTDIVCR4, 0x0E080000U},
+ {AXI_DPTDIVCR5, 0x0E080000U},
+ {AXI_DPTDIVCR6, 0x0E080000U},
+ {AXI_DPTDIVCR7, 0x0E080000U},
+ {AXI_DPTDIVCR8, 0x0E080000U},
+ {AXI_DPTDIVCR9, 0x0E080000U},
+ {AXI_DPTDIVCR10, 0x0E080000U},
+ {AXI_DPTDIVCR11, 0x0E080000U},
+ {AXI_DPTDIVCR12, 0x0E080000U},
+ {AXI_DPTDIVCR13, 0x0E080000U},
+ {AXI_DPTDIVCR14, 0x0E080000U},
+ /* AXI dram protected area setting */
+ {AXI_DPTCR0, 0x0E000000U},
+ {AXI_DPTCR1, 0x0E000E0EU},
+ {AXI_DPTCR2, 0x0E000000U},
+ {AXI_DPTCR3, 0x0E000000U},
+ {AXI_DPTCR4, 0x0E000000U},
+ {AXI_DPTCR5, 0x0E000000U},
+ {AXI_DPTCR6, 0x0E000000U},
+ {AXI_DPTCR7, 0x0E000000U},
+ {AXI_DPTCR8, 0x0E000000U},
+ {AXI_DPTCR9, 0x0E000000U},
+ {AXI_DPTCR10, 0x0E000000U},
+ {AXI_DPTCR11, 0x0E000000U},
+ {AXI_DPTCR12, 0x0E000000U},
+ {AXI_DPTCR13, 0x0E000000U},
+ {AXI_DPTCR14, 0x0E000000U},
+ {AXI_DPTCR15, 0x0E000000U},
+ /*
+ * SRAM ptotection
+ * AXI sram protected area division
+ */
+ {AXI_SPTDIVCR0, 0x0E0E6304U},
+ {AXI_SPTDIVCR1, 0x0E0E6360U},
+ {AXI_SPTDIVCR2, 0x0E0E6360U},
+ {AXI_SPTDIVCR3, 0x0E0E6360U},
+ {AXI_SPTDIVCR4, 0x0E0E6360U},
+ {AXI_SPTDIVCR5, 0x0E0E6360U},
+ {AXI_SPTDIVCR6, 0x0E0E6360U},
+ {AXI_SPTDIVCR7, 0x0E0E6360U},
+ {AXI_SPTDIVCR8, 0x0E0E6360U},
+ {AXI_SPTDIVCR9, 0x0E0E6360U},
+ {AXI_SPTDIVCR10, 0x0E0E6360U},
+ {AXI_SPTDIVCR11, 0x0E0E6360U},
+ {AXI_SPTDIVCR12, 0x0E0E6360U},
+ {AXI_SPTDIVCR13, 0x0E0E6360U},
+ {AXI_SPTDIVCR14, 0x0E0E6360U},
+ /* AXI sram protected area setting */
+ {AXI_SPTCR0, 0x0E000E0EU},
+ {AXI_SPTCR1, 0x0E000000U},
+ {AXI_SPTCR2, 0x0E000000U},
+ {AXI_SPTCR3, 0x0E000000U},
+ {AXI_SPTCR4, 0x0E000000U},
+ {AXI_SPTCR5, 0x0E000000U},
+ {AXI_SPTCR6, 0x0E000000U},
+ {AXI_SPTCR7, 0x0E000000U},
+ {AXI_SPTCR8, 0x0E000000U},
+ {AXI_SPTCR9, 0x0E000000U},
+ {AXI_SPTCR10, 0x0E000000U},
+ {AXI_SPTCR11, 0x0E000000U},
+ {AXI_SPTCR12, 0x0E000000U},
+ {AXI_SPTCR13, 0x0E000000U},
+ {AXI_SPTCR14, 0x0E000000U},
+ {AXI_SPTCR15, 0x0E000000U}
+};
+
+static void lifec_security_setting(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < ARRAY_SIZE(lifec); i++)
+ mmio_write_32(lifec[i].reg, lifec[i].val);
+}
+
+/* SRAM/DRAM protection setting */
+static void axi_security_setting(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < ARRAY_SIZE(axi); i++)
+ mmio_write_32(axi[i].reg, axi[i].val);
+}
+
+void bl2_secure_setting(void)
+{
+ lifec_security_setting();
+ axi_security_setting();
+ rcar_micro_delay(10U);
+}
diff --git a/plat/renesas/common/bl31_plat_setup.c b/plat/renesas/common/bl31_plat_setup.c
new file mode 100644
index 0000000..60960d4
--- /dev/null
+++ b/plat/renesas/common/bl31_plat_setup.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "pwrc.h"
+#include "rcar_def.h"
+#include "rcar_private.h"
+#include "rcar_version.h"
+
+static const uint64_t BL31_RO_BASE = BL_CODE_BASE;
+static const uint64_t BL31_RO_LIMIT = BL_CODE_END;
+
+#if USE_COHERENT_MEM
+static const uint64_t BL31_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE;
+static const uint64_t BL31_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END;
+#endif /* USE_COHERENT_MEM */
+
+extern void plat_rcar_gic_driver_init(void);
+extern void plat_rcar_gic_init(void);
+
+u_register_t rcar_boot_mpidr;
+
+static int cci_map[] = {
+ CCI500_CLUSTER0_SL_IFACE_IX_FOR_M3,
+ CCI500_CLUSTER1_SL_IFACE_IX_FOR_M3
+};
+
+void plat_cci_init(void)
+{
+ uint32_t prd;
+
+ prd = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK);
+
+ if (PRR_PRODUCT_H3_CUT10 == prd || PRR_PRODUCT_H3_CUT11 == prd) {
+ cci_map[0U] = CCI500_CLUSTER0_SL_IFACE_IX;
+ cci_map[1U] = CCI500_CLUSTER1_SL_IFACE_IX;
+ }
+
+ cci_init(RCAR_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+}
+
+void plat_cci_enable(void)
+{
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+}
+
+void plat_cci_disable(void)
+{
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+}
+
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ bl2_to_bl31_params_mem_t *from_bl2 = (bl2_to_bl31_params_mem_t *)
+ PARAMS_BASE;
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ?
+ &from_bl2->bl33_ep_info : &from_bl2->bl32_ep_info;
+
+ return next_image_info->pc ? next_image_info : NULL;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ rcar_console_runtime_init();
+
+ NOTICE("BL3-1 : Rev.%s\n", version_of_renesas);
+
+#if RCAR_LSI != RCAR_D3
+ if (rcar_pwrc_get_cluster() == RCAR_CLUSTER_A53A57) {
+ plat_cci_init();
+ plat_cci_enable();
+ }
+#endif /* RCAR_LSI != RCAR_D3 */
+}
+
+void bl31_plat_arch_setup(void)
+{
+ rcar_configure_mmu_el3(BL31_BASE,
+ BL31_LIMIT - BL31_BASE,
+ BL31_RO_BASE, BL31_RO_LIMIT
+#if USE_COHERENT_MEM
+ , BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT
+#endif /* USE_COHERENT_MEM */
+ );
+ rcar_pwrc_code_copy_to_system_ram();
+}
+
+void bl31_platform_setup(void)
+{
+ plat_rcar_gic_driver_init();
+ plat_rcar_gic_init();
+
+ /* enable the system level generic timer */
+ mmio_write_32(RCAR_CNTC_BASE + CNTCR_OFF, CNTCR_FCREQ(U(0)) | CNTCR_EN);
+
+ rcar_pwrc_setup();
+#if 0
+ /*
+ * TODO: there is a broad number of rcar-gen3 SoC configurations; to
+ * support all of them, Renesas use the pwrc driver to discover what
+ * cores are on/off before announcing the topology.
+ * This code hasnt been ported yet
+ */
+
+ rcar_setup_topology();
+#endif
+
+ /*
+ * mask should match the kernel's MPIDR_HWID_BITMASK so the core can be
+ * identified during cpuhotplug (check the kernel's psci migrate set of
+ * functions
+ */
+ rcar_boot_mpidr = read_mpidr_el1() & 0x0000ffffU;
+ rcar_pwrc_all_disable_interrupt_wakeup();
+}
diff --git a/plat/renesas/common/common.mk b/plat/renesas/common/common.mk
new file mode 100644
index 0000000..ca61f0e
--- /dev/null
+++ b/plat/renesas/common/common.mk
@@ -0,0 +1,143 @@
+#
+# Copyright (c) 2018-2022, Renesas Electronics Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PROGRAMMABLE_RESET_ADDRESS := 0
+COLD_BOOT_SINGLE_CPU := 1
+ARM_CCI_PRODUCT_ID := 500
+TRUSTED_BOARD_BOOT := 1
+RESET_TO_BL31 := 1
+GENERATE_COT := 1
+BL2_AT_EL3 := 1
+ENABLE_SVE_FOR_NS := 0
+MULTI_CONSOLE_API := 1
+
+CRASH_REPORTING := 1
+HANDLE_EA_EL3_FIRST_NS := 1
+
+# This option gets enabled automatically if the TRUSTED_BOARD_BOOT
+# is set via root Makefile, but Renesas support Trusted-Boot without
+# Crypto module.
+override CRYPTO_SUPPORT := 0
+
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+ifeq (${SPD},none)
+ SPD_NONE:=1
+ $(eval $(call add_define,SPD_NONE))
+endif
+
+# LSI setting common define
+RCAR_H3:=0
+RCAR_M3:=1
+RCAR_M3N:=2
+RCAR_E3:=3
+RCAR_H3N:=4
+RCAR_D3:=5
+RCAR_V3M:=6
+RCAR_AUTO:=99
+RZ_G2M:=100
+RZ_G2H:=101
+RZ_G2N:=102
+RZ_G2E:=103
+$(eval $(call add_define,RCAR_H3))
+$(eval $(call add_define,RCAR_M3))
+$(eval $(call add_define,RCAR_M3N))
+$(eval $(call add_define,RCAR_E3))
+$(eval $(call add_define,RCAR_H3N))
+$(eval $(call add_define,RCAR_D3))
+$(eval $(call add_define,RCAR_V3M))
+$(eval $(call add_define,RCAR_AUTO))
+$(eval $(call add_define,RZ_G2M))
+$(eval $(call add_define,RZ_G2H))
+$(eval $(call add_define,RZ_G2N))
+$(eval $(call add_define,RZ_G2E))
+
+RCAR_CUT_10:=0
+RCAR_CUT_11:=1
+RCAR_CUT_13:=3
+RCAR_CUT_20:=10
+RCAR_CUT_30:=20
+$(eval $(call add_define,RCAR_CUT_10))
+$(eval $(call add_define,RCAR_CUT_11))
+$(eval $(call add_define,RCAR_CUT_13))
+$(eval $(call add_define,RCAR_CUT_20))
+$(eval $(call add_define,RCAR_CUT_30))
+
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
+
+# Enable workarounds for selected Cortex-A57 erratas.
+ERRATA_A57_859972 := 1
+ERRATA_A57_813419 := 1
+ERRATA_A57_1319537 := 1
+
+PLAT_INCLUDES := -Iplat/renesas/common/include/registers \
+ -Iplat/renesas/common/include \
+ -Iplat/renesas/common
+
+PLAT_BL_COMMON_SOURCES := drivers/renesas/common/iic_dvfs/iic_dvfs.c \
+ plat/renesas/common/rcar_common.c
+
+include drivers/arm/gic/v2/gicv2.mk
+RCAR_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c
+
+BL2_SOURCES += ${RCAR_GIC_SOURCES} \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ ${LIBFDT_SRCS} \
+ common/desc_image_load.c \
+ plat/renesas/common/aarch64/platform_common.c \
+ plat/renesas/common/aarch64/plat_helpers.S \
+ plat/renesas/common/bl2_interrupt_error.c \
+ plat/renesas/common/bl2_secure_setting.c \
+ plat/renesas/common/plat_storage.c \
+ plat/renesas/common/bl2_plat_mem_params_desc.c \
+ plat/renesas/common/plat_image_load.c \
+ plat/renesas/common/bl2_cpg_init.c \
+ drivers/renesas/common/console/rcar_printf.c \
+ drivers/renesas/common/scif/scif.S \
+ drivers/renesas/common/common.c \
+ drivers/renesas/common/io/io_emmcdrv.c \
+ drivers/renesas/common/io/io_memdrv.c \
+ drivers/renesas/common/io/io_rcar.c \
+ drivers/renesas/common/auth/auth_mod.c \
+ drivers/renesas/common/rpc/rpc_driver.c \
+ drivers/renesas/common/dma/dma_driver.c \
+ drivers/renesas/common/avs/avs_driver.c \
+ drivers/renesas/common/delay/micro_delay.c \
+ drivers/renesas/common/emmc/emmc_interrupt.c \
+ drivers/renesas/common/emmc/emmc_utility.c \
+ drivers/renesas/common/emmc/emmc_mount.c \
+ drivers/renesas/common/emmc/emmc_init.c \
+ drivers/renesas/common/emmc/emmc_read.c \
+ drivers/renesas/common/emmc/emmc_cmd.c \
+ drivers/renesas/common/watchdog/swdt.c \
+ drivers/renesas/common/rom/rom_api.c \
+ drivers/io/io_storage.c
+
+BL31_SOURCES += ${RCAR_GIC_SOURCES} \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a57.S \
+ plat/common/plat_psci_common.c \
+ plat/renesas/common/plat_topology.c \
+ plat/renesas/common/aarch64/plat_helpers.S \
+ plat/renesas/common/aarch64/platform_common.c \
+ plat/renesas/common/bl31_plat_setup.c \
+ plat/renesas/common/plat_pm.c \
+ drivers/renesas/common/console/rcar_console.S \
+ drivers/renesas/common/console/rcar_printf.c \
+ drivers/renesas/common/delay/micro_delay.c \
+ drivers/renesas/common/pwrc/call_sram.S \
+ drivers/renesas/common/pwrc/pwrc.c \
+ drivers/renesas/common/common.c \
+ drivers/arm/cci/cci.c
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
diff --git a/plat/renesas/common/include/plat.ld.S b/plat/renesas/common/include/plat.ld.S
new file mode 100644
index 0000000..7aef324
--- /dev/null
+++ b/plat/renesas/common/include/plat.ld.S
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef RCAR_PLAT_LD_S
+#define RCAR_PLAT_LD_S
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <platform_def.h>
+
+MEMORY {
+ SRAM (rwx): ORIGIN = BL31_SRAM_BASE, LENGTH = DEVICE_SRAM_SIZE
+ PRAM (r): ORIGIN = BL31_LIMIT - DEVICE_SRAM_SIZE, LENGTH = DEVICE_SRAM_SIZE
+}
+
+SECTIONS
+{
+ /* SRAM_COPY is in PRAM */
+ . = BL31_LIMIT - DEVICE_SRAM_SIZE;
+ __SRAM_COPY_START__ = .;
+
+ .system_ram : {
+ /* system ram start is in SRAM */
+ __system_ram_start__ = .;
+ *(.system_ram*)
+ *iic_dvfs.o(.rodata)
+ __system_ram_end__ = .;
+ } >SRAM AT>PRAM
+
+ ASSERT(__BL31_END__ <= BL31_LIMIT - DEVICE_SRAM_SIZE,
+ "BL31 image too large - writing on top of SRAM!")
+
+}
+
+#endif /* RCAR_PLAT_LD_S */
diff --git a/plat/renesas/common/include/plat_macros.S b/plat/renesas/common/include/plat_macros.S
new file mode 100644
index 0000000..927cd39
--- /dev/null
+++ b/plat/renesas/common/include/plat_macros.S
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+
+#include "rcar_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+ /* ---------------------------------------------
+ * The below macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL3-1.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_print_gic_regs
+ mov_imm x17, RCAR_GICC_BASE
+ mov_imm x16, RCAR_GICD_BASE
+print_gicc_regs:
+ /* gicc base address is now in x17 */
+ adr x6, gicc_regs /* Load the gicc reg list to x6 */
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+ adr x4, spacer
+ bl asm_print_str
+ ldr x4, [x7], #8
+ bl asm_print_hex
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+ .endm
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ------------------------------------------------
+ * The below macro prints out relevant interconnect
+ * registers whenever an unhandled exception is
+ * taken in BL3-1.
+ * Clobbers: x0 - x9, sp
+ * ------------------------------------------------
+ */
+ .macro plat_print_interconnect_regs
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (CCI500_BASE + SLAVE_IFACE3_OFFSET)
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (CCI500_BASE + SLAVE_IFACE4_OFFSET)
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ .endm
+
+ .macro plat_crash_print_regs
+ plat_print_gic_regs
+ plat_print_interconnect_regs
+ .endm
diff --git a/plat/renesas/common/include/platform_def.h b/plat/renesas/common/include/platform_def.h
new file mode 100644
index 0000000..ab071ec
--- /dev/null
+++ b/plat/renesas/common/include/platform_def.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#ifndef __ASSEMBLER__
+#include <stdlib.h>
+#endif
+
+#include <arch.h>
+
+#include "rcar_def.h"
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+ #define FIRMWARE_WELCOME_STR "Booting Rcar-gen3 Trusted Firmware\n"
+
+/* Size of cacheable stacks */
+#if IMAGE_BL1
+#if TRUSTED_BOARD_BOOT
+#define PLATFORM_STACK_SIZE U(0x1000)
+#else
+#define PLATFORM_STACK_SIZE U(0x440)
+#endif
+#elif IMAGE_BL2
+#if TRUSTED_BOARD_BOOT
+#define PLATFORM_STACK_SIZE U(0x1000)
+#else
+#define PLATFORM_STACK_SIZE U(0x400)
+#endif
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE U(0x800)
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE U(0x440)
+#endif
+
+#define BL332_IMAGE_ID (NS_BL2U_IMAGE_ID + 1)
+#define BL333_IMAGE_ID (NS_BL2U_IMAGE_ID + 2)
+#define BL334_IMAGE_ID (NS_BL2U_IMAGE_ID + 3)
+#define BL335_IMAGE_ID (NS_BL2U_IMAGE_ID + 4)
+#define BL336_IMAGE_ID (NS_BL2U_IMAGE_ID + 5)
+#define BL337_IMAGE_ID (NS_BL2U_IMAGE_ID + 6)
+#define BL338_IMAGE_ID (NS_BL2U_IMAGE_ID + 7)
+
+#define BL332_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 8)
+#define BL333_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 9)
+#define BL334_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 10)
+#define BL335_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 11)
+#define BL336_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 12)
+#define BL337_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 13)
+#define BL338_KEY_CERT_ID (NS_BL2U_IMAGE_ID + 14)
+
+#define BL332_CERT_ID (NS_BL2U_IMAGE_ID + 15)
+#define BL333_CERT_ID (NS_BL2U_IMAGE_ID + 16)
+#define BL334_CERT_ID (NS_BL2U_IMAGE_ID + 17)
+#define BL335_CERT_ID (NS_BL2U_IMAGE_ID + 18)
+#define BL336_CERT_ID (NS_BL2U_IMAGE_ID + 19)
+#define BL337_CERT_ID (NS_BL2U_IMAGE_ID + 20)
+#define BL338_CERT_ID (NS_BL2U_IMAGE_ID + 21)
+
+/* io drivers id */
+#define FLASH_DEV_ID U(0)
+#define EMMC_DEV_ID U(1)
+
+/*
+ * R-Car H3 Cortex-A57
+ * L1:I/48KB(16KBx3way) D/32KB(16KBx2way) L2:2MB(128KBx16way)
+ * Cortex-A53
+ * L1:I/32KB(16KBx2way) D/32KB(8KBx4way) L2:512KB(32KBx16way)
+ */
+#define PLATFORM_CACHE_LINE_SIZE 64
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(4)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \
+ PLATFORM_CLUSTER_COUNT + 1)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+/*
+ ******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define RCAR_SYSRAM_BASE U(0xE6300000)
+#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3)
+#define BL2_LIMIT U(0xE6320000)
+#else
+#define BL2_LIMIT U(0xE6360000)
+#endif
+
+#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3)
+#define BL2_BASE U(0xE6304000)
+#define BL2_IMAGE_LIMIT U(0xE6318000)
+#elif (RCAR_LSI == RCAR_V3M)
+#define BL2_BASE U(0xE6344000)
+#define BL2_IMAGE_LIMIT U(0xE636E800)
+#else
+#define BL2_BASE U(0xE6304000)
+#define BL2_IMAGE_LIMIT U(0xE632E800)
+#endif
+#define RCAR_SYSRAM_SIZE (BL2_BASE - RCAR_SYSRAM_BASE)
+
+/*
+ ******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************
+ * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL3-1 debug size plus a little space for growth.
+ */
+#define BL31_BASE (RCAR_TRUSTED_SRAM_BASE)
+#define BL31_LIMIT (RCAR_TRUSTED_SRAM_BASE + \
+ RCAR_TRUSTED_SRAM_SIZE)
+#define RCAR_BL31_LOG_BASE (0x44040000)
+#define RCAR_BL31_SDRAM_BTM (RCAR_BL31_LOG_BASE + 0x14000)
+#define RCAR_BL31_LOG_SIZE (RCAR_BL31_SDRAM_BTM - RCAR_BL31_LOG_BASE)
+#define BL31_SRAM_BASE (DEVICE_SRAM_BASE)
+#define BL31_SRAM_LIMIT (DEVICE_SRAM_BASE + DEVICE_SRAM_SIZE)
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#ifndef SPD_NONE
+#define BL32_BASE U(0x44100000)
+#define BL32_LIMIT (BL32_BASE + U(0x200000))
+#endif
+
+/*******************************************************************************
+ * BL33
+ ******************************************************************************/
+#define BL33_BASE DRAM1_NS_BASE
+#define BL33_COMP_SIZE U(0x200000)
+#define BL33_COMP_BASE (BL33_BASE - BL33_COMP_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#if IMAGE_BL1
+#define MAX_XLAT_TABLES U(2)
+#elif IMAGE_BL2
+#define MAX_XLAT_TABLES U(5)
+#elif IMAGE_BL31
+#define MAX_XLAT_TABLES U(4)
+#elif IMAGE_BL32
+#define MAX_XLAT_TABLES U(3)
+#endif
+
+#if IMAGE_BL2
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+#endif
+
+#define MAX_MMAP_REGIONS (RCAR_MMAP_ENTRIES + RCAR_BL_REGIONS)
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two mailboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT (6)
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*******************************************************************************
+ * Size of the per-cpu data in bytes that should be reserved in the generic
+ * per-cpu data structure for the RCAR port.
+ ******************************************************************************/
+#if !USE_COHERENT_MEM
+#define PLAT_PCPU_DATA_SIZE (2)
+#endif
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/renesas/common/include/rcar_def.h b/plat/renesas/common/include/rcar_def.h
new file mode 100644
index 0000000..2cd26ed
--- /dev/null
+++ b/plat/renesas/common/include/rcar_def.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RCAR_DEF_H
+#define RCAR_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+
+#define RCAR_PRIMARY_CPU 0x0
+#define RCAR_TRUSTED_SRAM_BASE 0x44000000
+#define RCAR_TRUSTED_SRAM_SIZE 0x0003E000
+#define RCAR_SHARED_MEM_BASE (RCAR_TRUSTED_SRAM_BASE + \
+ RCAR_TRUSTED_SRAM_SIZE)
+#define RCAR_SHARED_MEM_SIZE U(0x00001000)
+#define FLASH0_BASE U(0x08000000)
+#define FLASH0_SIZE U(0x04000000)
+#define FLASH_MEMORY_SIZE U(0x04000000) /* hyper flash */
+#define FLASH_TRANS_SIZE_UNIT U(0x00000100)
+#define DEVICE_RCAR_BASE U(0xE6000000)
+#define DEVICE_RCAR_SIZE U(0x00300000)
+#define DEVICE_RCAR_BASE2 U(0xE6360000)
+#define DEVICE_RCAR_SIZE2 U(0x19CA0000)
+#define DEVICE_SRAM_BASE U(0xE6300000)
+#define DEVICE_SRAM_SIZE U(0x00002000)
+#define DEVICE_SRAM_STACK_BASE (DEVICE_SRAM_BASE + DEVICE_SRAM_SIZE)
+#define DEVICE_SRAM_STACK_SIZE U(0x00001000)
+#define DRAM_LIMIT ULL(0x0000010000000000)
+#define DRAM1_BASE U(0x40000000)
+#define DRAM1_SIZE U(0x80000000)
+#define DRAM1_NS_BASE (DRAM1_BASE + U(0x10000000))
+#define DRAM1_NS_SIZE (DRAM1_SIZE - DRAM1_NS_BASE)
+#define DRAM_40BIT_BASE ULL(0x0400000000)
+#define DRAM_40BIT_SIZE ULL(0x0400000000)
+#define DRAM_PROTECTED_BASE ULL(0x43F00000)
+#define DRAM_40BIT_PROTECTED_BASE ULL(0x0403F00000)
+#define DRAM_PROTECTED_SIZE ULL(0x03F00000)
+#define RCAR_BL31_CRASH_BASE U(0x4403F000)
+#define RCAR_BL31_CRASH_SIZE U(0x00001000)
+/* Entrypoint mailboxes */
+#define MBOX_BASE RCAR_SHARED_MEM_BASE
+#define MBOX_SIZE 0x200
+/* Base address where parameters to BL31 are stored */
+#define PARAMS_BASE (MBOX_BASE + MBOX_SIZE)
+#define BOOT_KIND_BASE (RCAR_SHARED_MEM_BASE + \
+ RCAR_SHARED_MEM_SIZE - 0x100)
+/*
+ * The number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU
+ */
+#if USE_COHERENT_MEM
+#define RCAR_BL_REGIONS (3)
+#else
+#define RCAR_BL_REGIONS (2)
+#endif
+/*
+ * The RCAR_MAX_MMAP_REGIONS depends on the number of entries in rcar_mmap[]
+ * defined for each BL stage in rcar_common.c.
+ */
+#if IMAGE_BL2
+#define RCAR_MMAP_ENTRIES (9)
+#endif
+#if IMAGE_BL31
+#define RCAR_MMAP_ENTRIES (9)
+#endif
+#if IMAGE_BL2
+#define REG1_BASE U(0xE6400000)
+#define REG1_SIZE U(0x04C00000)
+#define ROM0_BASE U(0xEB100000)
+#define ROM0_SIZE U(0x00028000)
+#define REG2_BASE U(0xEC000000)
+#define REG2_SIZE U(0x14000000)
+#endif
+/* BL33 */
+#define NS_IMAGE_OFFSET (DRAM1_BASE + U(0x09000000))
+/* BL31 */
+#define RCAR_DEVICE_BASE DEVICE_RCAR_BASE
+#define RCAR_DEVICE_SIZE (0x1A000000)
+#define RCAR_LOG_RES_SIZE (64)
+#define RCAR_LOG_HEADER_SIZE (16)
+#define RCAR_LOG_OTHER_SIZE (RCAR_LOG_HEADER_SIZE + \
+ RCAR_LOG_RES_SIZE)
+#define RCAR_BL31_LOG_MAX (RCAR_BL31_LOG_SIZE - \
+ RCAR_LOG_OTHER_SIZE)
+#define RCAR_CRASH_STACK RCAR_BL31_CRASH_BASE
+#define AARCH64_SPACE_BASE ULL(0x00000000000)
+#define AARCH64_SPACE_SIZE ULL(0x10000000000)
+/* CCI related constants */
+#define CCI500_BASE U(0xF1200000)
+#define CCI500_CLUSTER0_SL_IFACE_IX (2)
+#define CCI500_CLUSTER1_SL_IFACE_IX (3)
+#define CCI500_CLUSTER0_SL_IFACE_IX_FOR_M3 (1)
+#define CCI500_CLUSTER1_SL_IFACE_IX_FOR_M3 (2)
+#define RCAR_CCI_BASE CCI500_BASE
+/* GIC */
+#define RCAR_GICD_BASE U(0xF1010000)
+#define RCAR_GICR_BASE U(0xF1010000)
+#define RCAR_GICC_BASE U(0xF1020000)
+#define RCAR_GICH_BASE U(0xF1040000)
+#define RCAR_GICV_BASE U(0xF1060000)
+#define ARM_IRQ_SEC_PHY_TIMER U(29)
+#define ARM_IRQ_SEC_SGI_0 U(8)
+#define ARM_IRQ_SEC_SGI_1 U(9)
+#define ARM_IRQ_SEC_SGI_2 U(10)
+#define ARM_IRQ_SEC_SGI_3 U(11)
+#define ARM_IRQ_SEC_SGI_4 U(12)
+#define ARM_IRQ_SEC_SGI_5 U(13)
+#define ARM_IRQ_SEC_SGI_6 U(14)
+#define ARM_IRQ_SEC_SGI_7 U(15)
+#define ARM_IRQ_SEC_RPC U(70)
+#define ARM_IRQ_SEC_TIMER U(166)
+#define ARM_IRQ_SEC_TIMER_UP U(171)
+#define ARM_IRQ_SEC_WDT U(173)
+#define ARM_IRQ_SEC_CRYPT U(102)
+#define ARM_IRQ_SEC_CRYPT_SecPKA U(97)
+#define ARM_IRQ_SEC_CRYPT_PubPKA U(98)
+/* Timer control */
+#define RCAR_CNTC_BASE U(0xE6080000)
+/* Reset */
+#define RCAR_MODEMR U(0xE6160060) /* Mode pin */
+#define RCAR_CA57RESCNT U(0xE6160040) /* Reset control A57 */
+#define RCAR_CA53RESCNT U(0xE6160044) /* Reset control A53 */
+#define RCAR_SRESCR U(0xE6160110) /* Soft Power On Reset */
+#define RCAR_CA53WUPCR U(0xE6151010) /* Wake-up control A53 */
+#define RCAR_CA57WUPCR U(0xE6152010) /* Wake-up control A57 */
+#define RCAR_CA53PSTR U(0xE6151040) /* Power status A53 */
+#define RCAR_CA57PSTR U(0xE6152040) /* Power status A57 */
+#define RCAR_CA53CPU0CR U(0xE6151100) /* CPU control A53 */
+#define RCAR_CA57CPU0CR U(0xE6152100) /* CPU control A57 */
+#define RCAR_CA53CPUCMCR U(0xE6151184) /* Common power A53 */
+#define RCAR_CA57CPUCMCR U(0xE6152184) /* Common power A57 */
+#define RCAR_WUPMSKCA57 U(0xE6180014) /* Wake-up mask A57 */
+#define RCAR_WUPMSKCA53 U(0xE6180018) /* Wake-up mask A53 */
+/* SYSC */
+#define RCAR_PWRSR3 U(0xE6180140) /* Power stat A53-SCU */
+#define RCAR_PWRSR5 U(0xE61801C0) /* Power stat A57-SCU */
+#define RCAR_SYSCIER U(0xE618000C) /* Interrupt enable */
+#define RCAR_SYSCIMR U(0xE6180010) /* Interrupt mask */
+#define RCAR_SYSCSR U(0xE6180000) /* SYSC status */
+#define RCAR_PWRONCR3 U(0xE618014C) /* Power resume A53-SCU */
+#define RCAR_PWRONCR5 U(0xE61801CC) /* Power resume A57-SCU */
+#define RCAR_PWROFFCR3 U(0xE6180144) /* Power shutoff A53-SCU */
+#define RCAR_PWROFFCR5 U(0xE61801C4) /* Power shutoff A57-SCU */
+#define RCAR_PWRER3 U(0xE6180154) /* shutoff/resume error */
+#define RCAR_PWRER5 U(0xE61801D4) /* shutoff/resume error */
+#define RCAR_SYSCISR U(0xE6180004) /* Interrupt status */
+#define RCAR_SYSCISCR U(0xE6180008) /* Interrupt stat clear */
+#define RCAR_SYSCEXTMASK U(0xE61802F8) /* External Request Mask */
+ /* H3/H3-N, M3 v3.0, M3-N, E3 */
+/* Product register */
+#define RCAR_PRR U(0xFFF00044)
+#define RCAR_M3_CUT_VER11 U(0x00000010) /* M3 Ver.1.1/Ver.1.2 */
+#define RCAR_D3_CUT_VER10 U(0x00000000) /* D3 Ver.1.0 */
+#define RCAR_D3_CUT_VER11 U(0x00000010) /* D3 Ver.1.1 */
+#define RCAR_MAJOR_MASK U(0x000000F0)
+#define RCAR_MINOR_MASK U(0x0000000F)
+#define PRR_PRODUCT_SHIFT U(8)
+#define RCAR_MAJOR_SHIFT U(4)
+#define RCAR_MINOR_SHIFT U(0)
+#define RCAR_MAJOR_OFFSET U(1)
+#define RCAR_M3_MINOR_OFFSET U(2)
+#define PRR_PRODUCT_H3_CUT10 (PRR_PRODUCT_H3 | U(0x00)) /* 1.0 */
+#define PRR_PRODUCT_H3_CUT11 (PRR_PRODUCT_H3 | U(0x01)) /* 1.1 */
+#define PRR_PRODUCT_H3_CUT20 (PRR_PRODUCT_H3 | U(0x10)) /* 2.0 */
+#define PRR_PRODUCT_M3_CUT10 (PRR_PRODUCT_M3 | U(0x00)) /* 1.0 */
+#define PRR_PRODUCT_M3_CUT11 (PRR_PRODUCT_M3 | U(0x10))
+#define PRR 0xFFF00044U
+#define PRR_PRODUCT_MASK 0x00007F00U
+#define PRR_CUT_MASK 0x000000FFU
+#define PRR_PRODUCT_H3 0x00004F00U /* R-Car H3 */
+#define PRR_PRODUCT_M3 0x00005200U /* R-Car M3-W */
+#define PRR_PRODUCT_V3M 0x00005400U /* R-Car V3M */
+#define PRR_PRODUCT_M3N 0x00005500U /* R-Car M3-N */
+#define PRR_PRODUCT_V3H 0x00005600U /* R-Car V3H */
+#define PRR_PRODUCT_E3 0x00005700U /* R-Car E3 */
+#define PRR_PRODUCT_D3 0x00005800U /* R-Car D3 */
+#define PRR_PRODUCT_10 0x00U /* Ver.1.0 */
+#define PRR_PRODUCT_11 0x01U /* Ver.1.1 */
+#define PRR_PRODUCT_20 0x10U /* Ver.2.0 */
+#define PRR_PRODUCT_21 0x11U /* Ver.2.1 */
+#define PRR_PRODUCT_30 0x20U /* Ver.3.0 */
+#define RCAR_CPU_MASK_CA57 U(0x80000000)
+#define RCAR_CPU_MASK_CA53 U(0x04000000)
+#define RCAR_CPU_HAVE_CA57 U(0x00000000)
+#define RCAR_CPU_HAVE_CA53 U(0x00000000)
+#define RCAR_SSCG_MASK U(0x1000) /* MD12 */
+#define RCAR_SSCG_ENABLE U(0x1000)
+/* MD pin information */
+#define MODEMR_BOOT_CPU_MASK U(0x000000C0)
+#define MODEMR_BOOT_CPU_CR7 U(0x000000C0)
+#define MODEMR_BOOT_CPU_CA57 U(0x00000000)
+#define MODEMR_BOOT_CPU_CA53 U(0x00000040)
+#define MODEMR_BOOT_DEV_MASK U(0x0000001E)
+#define MODEMR_BOOT_DEV_HYPERFLASH160 U(0x00000004)
+#define MODEMR_BOOT_DEV_HYPERFLASH80 U(0x00000006)
+#define MODEMR_BOOT_DEV_QSPI_FLASH40 U(0x00000008)
+#define MODEMR_BOOT_DEV_QSPI_FLASH80 U(0x0000000C)
+#define MODEMR_BOOT_DEV_EMMC_25X1 U(0x0000000A)
+#define MODEMR_BOOT_DEV_EMMC_50X8 U(0x0000001A)
+#define MODEMR_BOOT_PLL_MASK U(0x00006000)
+#define MODEMR_BOOT_PLL_SHIFT U(13)
+/* Memory mapped Generic timer interfaces */
+#define ARM_SYS_CNTCTL_BASE RCAR_CNTC_BASE
+/* MODEMR PLL masks and bitfield values */
+#define CHECK_MD13_MD14 U(0x6000)
+#define MD14_MD13_TYPE_0 U(0x0000) /* MD14=0 MD13=0 */
+#define MD14_MD13_TYPE_1 U(0x2000) /* MD14=0 MD13=1 */
+#define MD14_MD13_TYPE_2 U(0x4000) /* MD14=1 MD13=0 */
+#define MD14_MD13_TYPE_3 U(0x6000) /* MD14=1 MD13=1 */
+/* Frequency of EXTAL(Hz) */
+#define EXTAL_MD14_MD13_TYPE_0 U(8333300) /* MD14=0 MD13=0 */
+#define EXTAL_MD14_MD13_TYPE_1 U(10000000) /* MD14=0 MD13=1 */
+#define EXTAL_MD14_MD13_TYPE_2 U(12500000) /* MD14=1 MD13=0 */
+#define EXTAL_MD14_MD13_TYPE_3 U(16666600) /* MD14=1 MD13=1 */
+#define EXTAL_SALVATOR_XS U(8320000) /* Salvator-XS */
+#define EXTAL_EBISU U(24000000) /* Ebisu */
+#define EXTAL_DRAAK U(24000000) /* Draak */
+/* CPG write protect registers */
+#define CPGWPR_PASSWORD (0x5A5AFFFFU)
+#define CPGWPCR_PASSWORD (0xA5A50000U)
+/* CA5x Debug Resource control registers */
+#define CPG_CA57DBGRCR (CPG_BASE + 0x2180U)
+#define CPG_CA53DBGRCR (CPG_BASE + 0x1180U)
+#define DBGCPUPREN ((uint32_t)1U << 19U)
+#define CPG_PLL0CR (CPG_BASE + 0x00D8U)
+#define CPG_PLL2CR (CPG_BASE + 0x002CU)
+#define CPG_PLL4CR (CPG_BASE + 0x01F4U)
+#define CPG_CPGWPCR (CPG_BASE + 0x0904U)
+/* RST Registers */
+#define RST_BASE (0xE6160000U)
+#define RST_WDTRSTCR (RST_BASE + 0x0054U)
+#define RST_MODEMR (RST_BASE + 0x0060U)
+#define WDTRSTCR_PASSWORD (0xA55A0000U)
+#define WDTRSTCR_RWDT_RSTMSK ((uint32_t)1U << 0U)
+/* MFIS Registers */
+#define MFISWPCNTR_PASSWORD (0xACCE0000U)
+#define MFISWPCNTR (0xE6260900U)
+/* IPMMU registers */
+#define IPMMU_MM_BASE (0xE67B0000U)
+#define IPMMUMM_IMSCTLR (IPMMU_MM_BASE + 0x0500U)
+#define IPMMUMM_IMAUXCTLR (IPMMU_MM_BASE + 0x0504U)
+#define IPMMUMM_IMSCTLR_ENABLE (0xC0000000U)
+#define IPMMUMM_IMAUXCTLR_NMERGE40_BIT (0x01000000U)
+#define IMSCTLR_DISCACHE (0xE0000000U)
+#define IPMMU_VP0_BASE (0xFE990000U)
+#define IPMMUVP0_IMSCTLR (IPMMU_VP0_BASE + 0x0500U)
+#define IPMMU_VI0_BASE (0xFEBD0000U)
+#define IPMMUVI0_IMSCTLR (IPMMU_VI0_BASE + 0x0500U)
+#define IPMMU_VI1_BASE (0xFEBE0000U)
+#define IPMMUVI1_IMSCTLR (IPMMU_VI1_BASE + 0x0500U)
+#define IPMMU_PV0_BASE (0xFD800000U)
+#define IPMMUPV0_IMSCTLR (IPMMU_PV0_BASE + 0x0500U)
+#define IPMMU_PV1_BASE (0xFD950000U)
+#define IPMMUPV1_IMSCTLR (IPMMU_PV1_BASE + 0x0500U)
+#define IPMMU_PV2_BASE (0xFD960000U)
+#define IPMMUPV2_IMSCTLR (IPMMU_PV2_BASE + 0x0500U)
+#define IPMMU_PV3_BASE (0xFD970000U)
+#define IPMMUPV3_IMSCTLR (IPMMU_PV3_BASE + 0x0500U)
+#define IPMMU_HC_BASE (0xE6570000U)
+#define IPMMUHC_IMSCTLR (IPMMU_HC_BASE + 0x0500U)
+#define IPMMU_RT_BASE (0xFFC80000U)
+#define IPMMURT_IMSCTLR (IPMMU_RT_BASE + 0x0500U)
+#define IPMMU_MP_BASE (0xEC670000U)
+#define IPMMUMP_IMSCTLR (IPMMU_MP_BASE + 0x0500U)
+#define IPMMU_DS0_BASE (0xE6740000U)
+#define IPMMUDS0_IMSCTLR (IPMMU_DS0_BASE + 0x0500U)
+#define IPMMU_DS1_BASE (0xE7740000U)
+#define IPMMUDS1_IMSCTLR (IPMMU_DS1_BASE + 0x0500U)
+/* ARMREG registers */
+#define P_ARMREG_SEC_CTRL (0xE62711F0U)
+#define P_ARMREG_SEC_CTRL_PROT (0x00000001U)
+/* MIDR */
+#define MIDR_CA57 (0x0D07U << MIDR_PN_SHIFT)
+#define MIDR_CA53 (0x0D03U << MIDR_PN_SHIFT)
+/* for SuspendToRAM */
+#define GPIO_BASE (0xE6050000U)
+#define GPIO_INDT1 (GPIO_BASE + 0x100CU)
+#define GPIO_INDT3 (GPIO_BASE + 0x300CU)
+#define GPIO_INDT6 (GPIO_BASE + 0x540CU)
+#define GPIO_OUTDT1 (GPIO_BASE + 0x1008U)
+#define GPIO_OUTDT3 (GPIO_BASE + 0x3008U)
+#define GPIO_OUTDT6 (GPIO_BASE + 0x5408U)
+#define RCAR_COLD_BOOT (0x00U)
+#define RCAR_WARM_BOOT (0x01U)
+#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR
+#define KEEP10_MAGIC (0x55U)
+#endif
+/* lossy registers */
+#define LOSSY_PARAMS_BASE (0x47FD7000U)
+#define AXI_DCMPAREACRA0 (0xE6784100U)
+#define AXI_DCMPAREACRB0 (0xE6784104U)
+#define LOSSY_ENABLE (0x80000000U)
+#define LOSSY_DISABLE (0x00000000U)
+#define LOSSY_FMT_YUVPLANAR (0x00000000U)
+#define LOSSY_FMT_YUV422INTLV (0x20000000U)
+#define LOSSY_FMT_ARGB8888 (0x40000000U)
+#define LOSSY_ST_ADDR0 (0x54000000U)
+#define LOSSY_END_ADDR0 (0x57000000U)
+#define LOSSY_FMT0 LOSSY_FMT_YUVPLANAR
+#define LOSSY_ENA_DIS0 LOSSY_ENABLE
+#define LOSSY_ST_ADDR1 0x0U
+#define LOSSY_END_ADDR1 0x0U
+#define LOSSY_FMT1 LOSSY_FMT_ARGB8888
+#define LOSSY_ENA_DIS1 LOSSY_DISABLE
+#define LOSSY_ST_ADDR2 0x0U
+#define LOSSY_END_ADDR2 0x0U
+#define LOSSY_FMT2 LOSSY_FMT_YUV422INTLV
+#define LOSSY_ENA_DIS2 LOSSY_DISABLE
+
+#endif /* RCAR_DEF_H */
diff --git a/plat/renesas/common/include/rcar_private.h b/plat/renesas/common/include/rcar_private.h
new file mode 100644
index 0000000..36f4ca5
--- /dev/null
+++ b/plat/renesas/common/include/rcar_private.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RCAR_PRIVATE_H
+#define RCAR_PRIVATE_H
+
+#include <common/bl_common.h>
+#include <lib/bakery_lock.h>
+#include <lib/el3_runtime/cpu_data.h>
+
+#include <platform_def.h>
+
+typedef volatile struct mailbox {
+ unsigned long value __aligned(CACHE_WRITEBACK_GRANULE);
+} mailbox_t;
+
+/*
+ * This structure represents the superset of information that is passed to
+ * BL31 e.g. while passing control to it from BL2 which is bl31_params
+ * and bl31_plat_params and its elements
+ */
+typedef struct bl2_to_bl31_params_mem {
+ image_info_t bl32_image_info;
+ image_info_t bl33_image_info;
+ entry_point_info_t bl33_ep_info;
+ entry_point_info_t bl32_ep_info;
+} bl2_to_bl31_params_mem_t;
+
+#if USE_COHERENT_MEM
+#define RCAR_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(rcar_lock);
+#define rcar_lock_init() bakery_lock_init(&rcar_lock)
+#define rcar_lock_get() bakery_lock_get(&rcar_lock)
+#define rcar_lock_release() bakery_lock_release(&rcar_lock)
+#else
+/*
+ * Constants to specify how many bakery locks this platform implements. These
+ * are used if the platform chooses not to use coherent memory for bakery lock
+ * data structures.
+ */
+#define RCAR_MAX_BAKERIES 2
+#define RCAR_PWRC_BAKERY_ID 0
+
+/*
+ * Definition of structure which holds platform specific per-cpu data. Currently
+ * it holds only the bakery lock information for each cpu. Constants to
+ * specify how many bakeries this platform implements and bakery ids are
+ * specified in rcar_def.h
+ */
+typedef struct rcar_cpu_data {
+ bakery_info_t pcpu_bakery_info[RCAR_MAX_BAKERIES];
+} rcar_cpu_data_t;
+
+#define RCAR_CPU_DATA_LOCK_OFFSET \
+ __builtin_offsetof(rcar_cpu_data_t, pcpu_bakery_info)
+/*
+ * Helper macros for bakery lock api when using the above rcar_cpu_data_t for
+ * bakery lock data structures. It assumes that the bakery_info is at the
+ * beginning of the platform specific per-cpu data.
+ */
+#define rcar_lock_init(_lock_arg)
+
+#define rcar_lock_get(_lock_arg) \
+ bakery_lock_get(_lock_arg, \
+ CPU_DATA_PLAT_PCPU_OFFSET + RCAR_CPU_DATA_LOCK_OFFSET)
+
+#define rcar_lock_release(_lock_arg) \
+ bakery_lock_release(_lock_arg, \
+ CPU_DATA_PLAT_PCPU_OFFSET + RCAR_CPU_DATA_LOCK_OFFSET)
+/*
+ * Ensure that the size of the RCAR specific per-cpu data structure and the size
+ * of the memory allocated in generic per-cpu data for the platform are the same
+ */
+CASSERT(sizeof(rcar_cpu_data_t) == PLAT_PCPU_DATA_SIZE,
+ rcar_pcpu_data_size_mismatch);
+#endif
+/*
+ * Function and variable prototypes
+ */
+void rcar_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start, unsigned long ro_limit
+#if USE_COHERENT_MEM
+ , unsigned long coh_start, unsigned long coh_limit
+#endif
+ );
+
+void rcar_setup_topology(void);
+void rcar_cci_disable(void);
+void rcar_cci_enable(void);
+void rcar_cci_init(void);
+
+void plat_invalidate_icache(void);
+void plat_cci_disable(void);
+void plat_cci_enable(void);
+void plat_cci_init(void);
+
+void mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, uint32_t target_bit);
+void cpg_write(uintptr_t regadr, uint32_t regval);
+
+void rcar_console_boot_init(void);
+void rcar_console_boot_end(void);
+void rcar_console_runtime_init(void);
+void rcar_console_runtime_end(void);
+
+#endif /* RCAR_PRIVATE_H */
diff --git a/plat/renesas/common/include/rcar_version.h b/plat/renesas/common/include/rcar_version.h
new file mode 100644
index 0000000..5a0ca31
--- /dev/null
+++ b/plat/renesas/common/include/rcar_version.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RCAR_VERSION_H
+#define RCAR_VERSION_H
+
+#include <arch_helpers.h>
+
+#define VERSION_OF_RENESAS "3.0.3"
+#define VERSION_OF_RENESAS_MAXLEN 128
+
+extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN];
+
+#endif /* RCAR_VERSION_H */
diff --git a/plat/renesas/common/include/registers/axi_registers.h b/plat/renesas/common/include/registers/axi_registers.h
new file mode 100644
index 0000000..36cd58b
--- /dev/null
+++ b/plat/renesas/common/include/registers/axi_registers.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AXI_REGISTERS_H
+#define AXI_REGISTERS_H
+
+/* AXI registers */
+
+/* AXI base address */
+#define AXI_BASE (0xE6780000U)
+
+/* address split */
+
+/* AXI address split control 0 */
+#define AXI_ADSPLCR0 (AXI_BASE + 0x4008U)
+/* AXI address split control 1 */
+#define AXI_ADSPLCR1 (AXI_BASE + 0x400CU)
+/* AXI address split control 2 */
+#define AXI_ADSPLCR2 (AXI_BASE + 0x4010U)
+/* AXI address split control 3 */
+#define AXI_ADSPLCR3 (AXI_BASE + 0x4014U)
+
+/* functional safety */
+
+/* AXI functional safety control */
+#define AXI_FUSACR (AXI_BASE + 0x4020U)
+
+/* decompression */
+
+/* AXI decompression area configuration A0 */
+#define AXI_DCMPAREACRA0 (AXI_BASE + 0x4100U)
+/* AXI decompression area configuration B0 */
+#define AXI_DCMPAREACRB0 (AXI_BASE + 0x4104U)
+/* AXI decompression area configuration A1 */
+#define AXI_DCMPAREACRA1 (AXI_BASE + 0x4108U)
+/* AXI decompression area configuration B1 */
+#define AXI_DCMPAREACRB1 (AXI_BASE + 0x410CU)
+/* AXI decompression area configuration A2 */
+#define AXI_DCMPAREACRA2 (AXI_BASE + 0x4110U)
+/* AXI decompression area configuration B2 */
+#define AXI_DCMPAREACRB2 (AXI_BASE + 0x4114U)
+/* AXI decompression area configuration A3 */
+#define AXI_DCMPAREACRA3 (AXI_BASE + 0x4118U)
+/* AXI decompression area configuration B3 */
+#define AXI_DCMPAREACRB3 (AXI_BASE + 0x411CU)
+/* AXI decompression area configuration A4 */
+#define AXI_DCMPAREACRA4 (AXI_BASE + 0x4120U)
+/* AXI decompression area configuration B4 */
+#define AXI_DCMPAREACRB4 (AXI_BASE + 0x4124U)
+/* AXI decompression area configuration A5 */
+#define AXI_DCMPAREACRA5 (AXI_BASE + 0x4128U)
+/* AXI decompression area configuration B5 */
+#define AXI_DCMPAREACRB5 (AXI_BASE + 0x412CU)
+/* AXI decompression area configuration A6 */
+#define AXI_DCMPAREACRA6 (AXI_BASE + 0x4130U)
+/* AXI decompression area configuration B6 */
+#define AXI_DCMPAREACRB6 (AXI_BASE + 0x4134U)
+/* AXI decompression area configuration A7 */
+#define AXI_DCMPAREACRA7 (AXI_BASE + 0x4138U)
+/* AXI decompression area configuration B7 */
+#define AXI_DCMPAREACRB7 (AXI_BASE + 0x413CU)
+/* AXI decompression area configuration A8 */
+#define AXI_DCMPAREACRA8 (AXI_BASE + 0x4140U)
+/* AXI decompression area configuration B8 */
+#define AXI_DCMPAREACRB8 (AXI_BASE + 0x4144U)
+/* AXI decompression area configuration A9 */
+#define AXI_DCMPAREACRA9 (AXI_BASE + 0x4148U)
+/* AXI decompression area configuration B9 */
+#define AXI_DCMPAREACRB9 (AXI_BASE + 0x414CU)
+/* AXI decompression area configuration A10 */
+#define AXI_DCMPAREACRA10 (AXI_BASE + 0x4150U)
+/* AXI decompression area configuration B10 */
+#define AXI_DCMPAREACRB10 (AXI_BASE + 0x4154U)
+/* AXI decompression area configuration A11 */
+#define AXI_DCMPAREACRA11 (AXI_BASE + 0x4158U)
+/* AXI decompression area configuration B11 */
+#define AXI_DCMPAREACRB11 (AXI_BASE + 0x415CU)
+/* AXI decompression area configuration A12 */
+#define AXI_DCMPAREACRA12 (AXI_BASE + 0x4160U)
+/* AXI decompression area configuration B12 */
+#define AXI_DCMPAREACRB12 (AXI_BASE + 0x4164U)
+/* AXI decompression area configuration A13 */
+#define AXI_DCMPAREACRA13 (AXI_BASE + 0x4168U)
+/* AXI decompression area configuration B13 */
+#define AXI_DCMPAREACRB13 (AXI_BASE + 0x416CU)
+/* AXI decompression area configuration A14 */
+#define AXI_DCMPAREACRA14 (AXI_BASE + 0x4170U)
+/* AXI decompression area configuration B14 */
+#define AXI_DCMPAREACRB14 (AXI_BASE + 0x4174U)
+/* AXI decompression area configuration A15 */
+#define AXI_DCMPAREACRA15 (AXI_BASE + 0x4178U)
+/* AXI decompression area configuration B15 */
+#define AXI_DCMPAREACRB15 (AXI_BASE + 0x417CU)
+/* AXI decompression shadow area configuration */
+#define AXI_DCMPSHDWCR (AXI_BASE + 0x4280U)
+
+/* SDRAM protection */
+
+/* AXI dram protected area division 0 */
+#define AXI_DPTDIVCR0 (AXI_BASE + 0x4400U)
+/* AXI dram protected area division 1 */
+#define AXI_DPTDIVCR1 (AXI_BASE + 0x4404U)
+/* AXI dram protected area division 2 */
+#define AXI_DPTDIVCR2 (AXI_BASE + 0x4408U)
+/* AXI dram protected area division 3 */
+#define AXI_DPTDIVCR3 (AXI_BASE + 0x440CU)
+/* AXI dram protected area division 4 */
+#define AXI_DPTDIVCR4 (AXI_BASE + 0x4410U)
+/* AXI dram protected area division 5 */
+#define AXI_DPTDIVCR5 (AXI_BASE + 0x4414U)
+/* AXI dram protected area division 6 */
+#define AXI_DPTDIVCR6 (AXI_BASE + 0x4418U)
+/* AXI dram protected area division 7 */
+#define AXI_DPTDIVCR7 (AXI_BASE + 0x441CU)
+/* AXI dram protected area division 8 */
+#define AXI_DPTDIVCR8 (AXI_BASE + 0x4420U)
+/* AXI dram protected area division 9 */
+#define AXI_DPTDIVCR9 (AXI_BASE + 0x4424U)
+/* AXI dram protected area division 10 */
+#define AXI_DPTDIVCR10 (AXI_BASE + 0x4428U)
+/* AXI dram protected area division 11 */
+#define AXI_DPTDIVCR11 (AXI_BASE + 0x442CU)
+/* AXI dram protected area division 12 */
+#define AXI_DPTDIVCR12 (AXI_BASE + 0x4430U)
+/* AXI dram protected area division 13 */
+#define AXI_DPTDIVCR13 (AXI_BASE + 0x4434U)
+/* AXI dram protected area division 14 */
+#define AXI_DPTDIVCR14 (AXI_BASE + 0x4438U)
+
+/* AXI dram protected area setting 0 */
+#define AXI_DPTCR0 (AXI_BASE + 0x4440U)
+/* AXI dram protected area setting 1 */
+#define AXI_DPTCR1 (AXI_BASE + 0x4444U)
+/* AXI dram protected area setting 2 */
+#define AXI_DPTCR2 (AXI_BASE + 0x4448U)
+/* AXI dram protected area setting 3 */
+#define AXI_DPTCR3 (AXI_BASE + 0x444CU)
+/* AXI dram protected area setting 4 */
+#define AXI_DPTCR4 (AXI_BASE + 0x4450U)
+/* AXI dram protected area setting 5 */
+#define AXI_DPTCR5 (AXI_BASE + 0x4454U)
+/* AXI dram protected area setting 6 */
+#define AXI_DPTCR6 (AXI_BASE + 0x4458U)
+/* AXI dram protected area setting 7 */
+#define AXI_DPTCR7 (AXI_BASE + 0x445CU)
+/* AXI dram protected area setting 8 */
+#define AXI_DPTCR8 (AXI_BASE + 0x4460U)
+/* AXI dram protected area setting 9 */
+#define AXI_DPTCR9 (AXI_BASE + 0x4464U)
+/* AXI dram protected area setting 10 */
+#define AXI_DPTCR10 (AXI_BASE + 0x4468U)
+/* AXI dram protected area setting 11 */
+#define AXI_DPTCR11 (AXI_BASE + 0x446CU)
+/* AXI dram protected area setting 12 */
+#define AXI_DPTCR12 (AXI_BASE + 0x4470U)
+/* AXI dram protected area setting 13 */
+#define AXI_DPTCR13 (AXI_BASE + 0x4474U)
+/* AXI dram protected area setting 14 */
+#define AXI_DPTCR14 (AXI_BASE + 0x4478U)
+/* AXI dram protected area setting 15 */
+#define AXI_DPTCR15 (AXI_BASE + 0x447CU)
+
+/* SRAM protection */
+
+/* AXI sram protected area division 0 */
+#define AXI_SPTDIVCR0 (AXI_BASE + 0x4500U)
+/* AXI sram protected area division 1 */
+#define AXI_SPTDIVCR1 (AXI_BASE + 0x4504U)
+/* AXI sram protected area division 2 */
+#define AXI_SPTDIVCR2 (AXI_BASE + 0x4508U)
+/* AXI sram protected area division 3 */
+#define AXI_SPTDIVCR3 (AXI_BASE + 0x450CU)
+/* AXI sram protected area division 4 */
+#define AXI_SPTDIVCR4 (AXI_BASE + 0x4510U)
+/* AXI sram protected area division 5 */
+#define AXI_SPTDIVCR5 (AXI_BASE + 0x4514U)
+/* AXI sram protected area division 6 */
+#define AXI_SPTDIVCR6 (AXI_BASE + 0x4518U)
+/* AXI sram protected area division 7 */
+#define AXI_SPTDIVCR7 (AXI_BASE + 0x451CU)
+/* AXI sram protected area division 8 */
+#define AXI_SPTDIVCR8 (AXI_BASE + 0x4520U)
+/* AXI sram protected area division 9 */
+#define AXI_SPTDIVCR9 (AXI_BASE + 0x4524U)
+/* AXI sram protected area division 10 */
+#define AXI_SPTDIVCR10 (AXI_BASE + 0x4528U)
+/* AXI sram protected area division 11 */
+#define AXI_SPTDIVCR11 (AXI_BASE + 0x452CU)
+/* AXI sram protected area division 12 */
+#define AXI_SPTDIVCR12 (AXI_BASE + 0x4530U)
+/* AXI sram protected area division 13 */
+#define AXI_SPTDIVCR13 (AXI_BASE + 0x4534U)
+/* AXI sram protected area division 14 */
+#define AXI_SPTDIVCR14 (AXI_BASE + 0x4538U)
+
+/* AXI sram protected area setting 0 */
+#define AXI_SPTCR0 (AXI_BASE + 0x4540U)
+/* AXI sram protected area setting 1 */
+#define AXI_SPTCR1 (AXI_BASE + 0x4544U)
+/* AXI sram protected area setting 2 */
+#define AXI_SPTCR2 (AXI_BASE + 0x4548U)
+/* AXI sram protected area setting 3 */
+#define AXI_SPTCR3 (AXI_BASE + 0x454CU)
+/* AXI sram protected area setting 4 */
+#define AXI_SPTCR4 (AXI_BASE + 0x4550U)
+/* AXI sram protected area setting 5 */
+#define AXI_SPTCR5 (AXI_BASE + 0x4554U)
+/* AXI sram protected area setting 6 */
+#define AXI_SPTCR6 (AXI_BASE + 0x4558U)
+/* AXI sram protected area setting 7 */
+#define AXI_SPTCR7 (AXI_BASE + 0x455CU)
+/* AXI sram protected area setting 8 */
+#define AXI_SPTCR8 (AXI_BASE + 0x4560U)
+/* AXI sram protected area setting 9 */
+#define AXI_SPTCR9 (AXI_BASE + 0x4564U)
+/* AXI sram protected area setting 10 */
+#define AXI_SPTCR10 (AXI_BASE + 0x4568U)
+/* AXI sram protected area setting 11 */
+#define AXI_SPTCR11 (AXI_BASE + 0x456CU)
+/* AXI sram protected area setting 12 */
+#define AXI_SPTCR12 (AXI_BASE + 0x4570U)
+/* AXI sram protected area setting 13 */
+#define AXI_SPTCR13 (AXI_BASE + 0x4574U)
+/* AXI sram protected area setting 14 */
+#define AXI_SPTCR14 (AXI_BASE + 0x4578U)
+/* AXI sram protected area setting 15 */
+#define AXI_SPTCR15 (AXI_BASE + 0x457CU)
+
+/* EDC base address */
+#define EDC_BASE (0xFF840000U)
+
+/* EDC edc enable */
+#define EDC_EDCEN (EDC_BASE + 0x0010U)
+/* EDC edc status 0 */
+#define EDC_EDCST0 (EDC_BASE + 0x0020U)
+/* EDC edc status 1 */
+#define EDC_EDCST1 (EDC_BASE + 0x0024U)
+/* EDC edc interrupt enable 0 */
+#define EDC_EDCINTEN0 (EDC_BASE + 0x0040U)
+/* EDC edc interrupt enable 1 */
+#define EDC_EDCINTEN1 (EDC_BASE + 0x0044U)
+
+#endif /* AXI_REGISTERS_H */
diff --git a/plat/renesas/common/include/registers/cpg_registers.h b/plat/renesas/common/include/registers/cpg_registers.h
new file mode 100644
index 0000000..5d2bb9e
--- /dev/null
+++ b/plat/renesas/common/include/registers/cpg_registers.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CPG_REGISTERS_H
+#define CPG_REGISTERS_H
+
+/* CPG base address */
+#define CPG_BASE (0xE6150000U)
+
+/* CPG system module stop control 2 */
+#define CPG_SMSTPCR2 (CPG_BASE + 0x0138U)
+/* CPG software reset 2 */
+#define CPG_SRCR2 (CPG_BASE + 0x00B0U)
+/* CPG module stop status 2 */
+#define CPG_MSTPSR2 (CPG_BASE + 0x0040U)
+/* CPG module stop status 2 */
+#define CPG_MSTPSR3 (CPG_BASE + 0x0048U)
+/* CPG write protect */
+#define CPG_CPGWPR (CPG_BASE + 0x0900U)
+/* CPG write protect control */
+#define CPG_CPGWPCR (CPG_BASE + 0x0904U)
+/* CPG system module stop control 9 */
+#define CPG_SMSTPCR9 (CPG_BASE + 0x0994U)
+/* CPG module stop status 9 */
+#define CPG_MSTPSR9 (CPG_BASE + 0x09A4U)
+/* SDHI2 clock frequency control register */
+#define CPG_SD2CKCR (CPG_BASE + 0x0268U)
+/* SDHI3 clock frequency control register */
+#define CPG_SD3CKCR (CPG_BASE + 0x026CU)
+
+/* CPG (SECURITY) registers */
+
+/* Secure Module Stop Control Register 0 */
+#define SCMSTPCR0 (CPG_BASE + 0x0B20U)
+/* Secure Module Stop Control Register 1 */
+#define SCMSTPCR1 (CPG_BASE + 0x0B24U)
+/* Secure Module Stop Control Register 2 */
+#define SCMSTPCR2 (CPG_BASE + 0x0B28U)
+/* Secure Module Stop Control Register 3 */
+#define SCMSTPCR3 (CPG_BASE + 0x0B2CU)
+/* Secure Module Stop Control Register 4 */
+#define SCMSTPCR4 (CPG_BASE + 0x0B30U)
+/* Secure Module Stop Control Register 5 */
+#define SCMSTPCR5 (CPG_BASE + 0x0B34U)
+/* Secure Module Stop Control Register 6 */
+#define SCMSTPCR6 (CPG_BASE + 0x0B38U)
+/* Secure Module Stop Control Register 7 */
+#define SCMSTPCR7 (CPG_BASE + 0x0B3CU)
+/* Secure Module Stop Control Register 8 */
+#define SCMSTPCR8 (CPG_BASE + 0x0B40U)
+/* Secure Module Stop Control Register 9 */
+#define SCMSTPCR9 (CPG_BASE + 0x0B44U)
+/* Secure Module Stop Control Register 10 */
+#define SCMSTPCR10 (CPG_BASE + 0x0B48U)
+/* Secure Module Stop Control Register 11 */
+#define SCMSTPCR11 (CPG_BASE + 0x0B4CU)
+
+/* CPG (SECURITY) registers */
+
+/* Secure Software Reset Access Enable Control Register 0 */
+#define SCSRSTECR0 (CPG_BASE + 0x0B80U)
+/* Secure Software Reset Access Enable Control Register 1 */
+#define SCSRSTECR1 (CPG_BASE + 0x0B84U)
+/* Secure Software Reset Access Enable Control Register 2 */
+#define SCSRSTECR2 (CPG_BASE + 0x0B88U)
+/* Secure Software Reset Access Enable Control Register 3 */
+#define SCSRSTECR3 (CPG_BASE + 0x0B8CU)
+/* Secure Software Reset Access Enable Control Register 4 */
+#define SCSRSTECR4 (CPG_BASE + 0x0B90U)
+/* Secure Software Reset Access Enable Control Register 5 */
+#define SCSRSTECR5 (CPG_BASE + 0x0B94U)
+/* Secure Software Reset Access Enable Control Register 6 */
+#define SCSRSTECR6 (CPG_BASE + 0x0B98U)
+/* Secure Software Reset Access Enable Control Register 7 */
+#define SCSRSTECR7 (CPG_BASE + 0x0B9CU)
+/* Secure Software Reset Access Enable Control Register 8 */
+#define SCSRSTECR8 (CPG_BASE + 0x0BA0U)
+/* Secure Software Reset Access Enable Control Register 9 */
+#define SCSRSTECR9 (CPG_BASE + 0x0BA4U)
+/* Secure Software Reset Access Enable Control Register 10 */
+#define SCSRSTECR10 (CPG_BASE + 0x0BA8U)
+/* Secure Software Reset Access Enable Control Register 11 */
+#define SCSRSTECR11 (CPG_BASE + 0x0BACU)
+
+/* CPG (REALTIME) registers */
+
+/* Realtime Module Stop Control Register 0 */
+#define RMSTPCR0 (CPG_BASE + 0x0110U)
+/* Realtime Module Stop Control Register 1 */
+#define RMSTPCR1 (CPG_BASE + 0x0114U)
+/* Realtime Module Stop Control Register 2 */
+#define RMSTPCR2 (CPG_BASE + 0x0118U)
+/* Realtime Module Stop Control Register 3 */
+#define RMSTPCR3 (CPG_BASE + 0x011CU)
+/* Realtime Module Stop Control Register 4 */
+#define RMSTPCR4 (CPG_BASE + 0x0120U)
+/* Realtime Module Stop Control Register 5 */
+#define RMSTPCR5 (CPG_BASE + 0x0124U)
+/* Realtime Module Stop Control Register 6 */
+#define RMSTPCR6 (CPG_BASE + 0x0128U)
+/* Realtime Module Stop Control Register 7 */
+#define RMSTPCR7 (CPG_BASE + 0x012CU)
+/* Realtime Module Stop Control Register 8 */
+#define RMSTPCR8 (CPG_BASE + 0x0980U)
+/* Realtime Module Stop Control Register 9 */
+#define RMSTPCR9 (CPG_BASE + 0x0984U)
+/* Realtime Module Stop Control Register 10 */
+#define RMSTPCR10 (CPG_BASE + 0x0988U)
+/* Realtime Module Stop Control Register 11 */
+#define RMSTPCR11 (CPG_BASE + 0x098CU)
+
+/* CPG (SYSTEM) registers */
+
+/* System Module Stop Control Register 0 */
+#define SMSTPCR0 (CPG_BASE + 0x0130U)
+/* System Module Stop Control Register 1 */
+#define SMSTPCR1 (CPG_BASE + 0x0134U)
+/* System Module Stop Control Register 2 */
+#define SMSTPCR2 (CPG_BASE + 0x0138U)
+/* System Module Stop Control Register 3 */
+#define SMSTPCR3 (CPG_BASE + 0x013CU)
+/* System Module Stop Control Register 4 */
+#define SMSTPCR4 (CPG_BASE + 0x0140U)
+/* System Module Stop Control Register 5 */
+#define SMSTPCR5 (CPG_BASE + 0x0144U)
+/* System Module Stop Control Register 6 */
+#define SMSTPCR6 (CPG_BASE + 0x0148U)
+/* System Module Stop Control Register 7 */
+#define SMSTPCR7 (CPG_BASE + 0x014CU)
+/* System Module Stop Control Register 8 */
+#define SMSTPCR8 (CPG_BASE + 0x0990U)
+/* System Module Stop Control Register 9 */
+#define SMSTPCR9 (CPG_BASE + 0x0994U)
+/* System Module Stop Control Register 10 */
+#define SMSTPCR10 (CPG_BASE + 0x0998U)
+/* System Module Stop Control Register 11 */
+#define SMSTPCR11 (CPG_BASE + 0x099CU)
+
+#endif /* CPG_REGISTERS_H */
diff --git a/plat/renesas/common/include/registers/lifec_registers.h b/plat/renesas/common/include/registers/lifec_registers.h
new file mode 100644
index 0000000..5f49e52
--- /dev/null
+++ b/plat/renesas/common/include/registers/lifec_registers.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LIFEC_REGISTERS_H
+#define LIFEC_REGISTERS_H
+
+#define LIFEC_SEC_BASE (0xE6110000U)
+
+#define SEC_SRC (LIFEC_SEC_BASE + 0x0008U)
+#define SEC_SEL0 (LIFEC_SEC_BASE + 0x0030U)
+#define SEC_SEL1 (LIFEC_SEC_BASE + 0x0034U)
+#define SEC_SEL2 (LIFEC_SEC_BASE + 0x0038U)
+#define SEC_SEL3 (LIFEC_SEC_BASE + 0x003CU)
+#define SEC_SEL4 (LIFEC_SEC_BASE + 0x0058U)
+#define SEC_SEL5 (LIFEC_SEC_BASE + 0x005CU)
+#define SEC_SEL6 (LIFEC_SEC_BASE + 0x0060U)
+#define SEC_SEL7 (LIFEC_SEC_BASE + 0x0064U)
+#define SEC_SEL8 (LIFEC_SEC_BASE + 0x0068U)
+#define SEC_SEL9 (LIFEC_SEC_BASE + 0x006CU)
+#define SEC_SEL10 (LIFEC_SEC_BASE + 0x0070U)
+#define SEC_SEL11 (LIFEC_SEC_BASE + 0x0074U)
+#define SEC_SEL12 (LIFEC_SEC_BASE + 0x0078U)
+#define SEC_SEL13 (LIFEC_SEC_BASE + 0x007CU)
+#define SEC_SEL14 (LIFEC_SEC_BASE + 0x0080U)
+#define SEC_SEL15 (LIFEC_SEC_BASE + 0x0084U)
+#define SEC_GRP0CR0 (LIFEC_SEC_BASE + 0x0138U)
+#define SEC_GRP1CR0 (LIFEC_SEC_BASE + 0x013CU)
+#define SEC_GRP0CR1 (LIFEC_SEC_BASE + 0x0140U)
+#define SEC_GRP1CR1 (LIFEC_SEC_BASE + 0x0144U)
+#define SEC_GRP0CR2 (LIFEC_SEC_BASE + 0x0148U)
+#define SEC_GRP1CR2 (LIFEC_SEC_BASE + 0x014CU)
+#define SEC_GRP0CR3 (LIFEC_SEC_BASE + 0x0150U)
+#define SEC_GRP1CR3 (LIFEC_SEC_BASE + 0x0154U)
+#define SEC_GRP0COND0 (LIFEC_SEC_BASE + 0x0158U)
+#define SEC_GRP1COND0 (LIFEC_SEC_BASE + 0x015CU)
+#define SEC_GRP0COND1 (LIFEC_SEC_BASE + 0x0160U)
+#define SEC_GRP1COND1 (LIFEC_SEC_BASE + 0x0164U)
+#define SEC_GRP0COND2 (LIFEC_SEC_BASE + 0x0168U)
+#define SEC_GRP1COND2 (LIFEC_SEC_BASE + 0x016CU)
+#define SEC_GRP0COND3 (LIFEC_SEC_BASE + 0x0170U)
+#define SEC_GRP1COND3 (LIFEC_SEC_BASE + 0x0174U)
+#define SEC_GRP0COND4 (LIFEC_SEC_BASE + 0x0178U)
+#define SEC_GRP1COND4 (LIFEC_SEC_BASE + 0x017CU)
+#define SEC_GRP0COND5 (LIFEC_SEC_BASE + 0x0180U)
+#define SEC_GRP1COND5 (LIFEC_SEC_BASE + 0x0184U)
+#define SEC_GRP0COND6 (LIFEC_SEC_BASE + 0x0188U)
+#define SEC_GRP1COND6 (LIFEC_SEC_BASE + 0x018CU)
+#define SEC_GRP0COND7 (LIFEC_SEC_BASE + 0x0190U)
+#define SEC_GRP1COND7 (LIFEC_SEC_BASE + 0x0194U)
+#define SEC_GRP0COND8 (LIFEC_SEC_BASE + 0x0198U)
+#define SEC_GRP1COND8 (LIFEC_SEC_BASE + 0x019CU)
+#define SEC_GRP0COND9 (LIFEC_SEC_BASE + 0x01A0U)
+#define SEC_GRP1COND9 (LIFEC_SEC_BASE + 0x01A4U)
+#define SEC_GRP0COND10 (LIFEC_SEC_BASE + 0x01A8U)
+#define SEC_GRP1COND10 (LIFEC_SEC_BASE + 0x01ACU)
+#define SEC_GRP0COND11 (LIFEC_SEC_BASE + 0x01B0U)
+#define SEC_GRP1COND11 (LIFEC_SEC_BASE + 0x01B4U)
+#define SEC_GRP0COND12 (LIFEC_SEC_BASE + 0x01B8U)
+#define SEC_GRP1COND12 (LIFEC_SEC_BASE + 0x01BCU)
+#define SEC_GRP0COND13 (LIFEC_SEC_BASE + 0x01C0U)
+#define SEC_GRP1COND13 (LIFEC_SEC_BASE + 0x01C4U)
+#define SEC_GRP0COND14 (LIFEC_SEC_BASE + 0x01C8U)
+#define SEC_GRP1COND14 (LIFEC_SEC_BASE + 0x01CCU)
+#define SEC_GRP0COND15 (LIFEC_SEC_BASE + 0x01D0U)
+#define SEC_GRP1COND15 (LIFEC_SEC_BASE + 0x01D4U)
+#define SEC_READONLY0 (LIFEC_SEC_BASE + 0x01D8U)
+#define SEC_READONLY1 (LIFEC_SEC_BASE + 0x01DCU)
+#define SEC_READONLY2 (LIFEC_SEC_BASE + 0x01E0U)
+#define SEC_READONLY3 (LIFEC_SEC_BASE + 0x01E4U)
+#define SEC_READONLY4 (LIFEC_SEC_BASE + 0x01E8U)
+#define SEC_READONLY5 (LIFEC_SEC_BASE + 0x01ECU)
+#define SEC_READONLY6 (LIFEC_SEC_BASE + 0x01F0U)
+#define SEC_READONLY7 (LIFEC_SEC_BASE + 0x01F4U)
+#define SEC_READONLY8 (LIFEC_SEC_BASE + 0x01F8U)
+#define SEC_READONLY9 (LIFEC_SEC_BASE + 0x01FCU)
+#define SEC_READONLY10 (LIFEC_SEC_BASE + 0x0200U)
+#define SEC_READONLY11 (LIFEC_SEC_BASE + 0x0204U)
+#define SEC_READONLY12 (LIFEC_SEC_BASE + 0x0208U)
+#define SEC_READONLY13 (LIFEC_SEC_BASE + 0x020CU)
+#define SEC_READONLY14 (LIFEC_SEC_BASE + 0x0210U)
+#define SEC_READONLY15 (LIFEC_SEC_BASE + 0x0214U)
+
+#define LIFEC_SAFE_BASE (0xE6120000U)
+#define SAFE_GRP0CR0 (LIFEC_SAFE_BASE + 0x0138U)
+#define SAFE_GRP1CR0 (LIFEC_SAFE_BASE + 0x013CU)
+#define SAFE_GRP0CR1 (LIFEC_SAFE_BASE + 0x0140U)
+#define SAFE_GRP1CR1 (LIFEC_SAFE_BASE + 0x0144U)
+#define SAFE_GRP0CR2 (LIFEC_SAFE_BASE + 0x0148U)
+#define SAFE_GRP1CR2 (LIFEC_SAFE_BASE + 0x014CU)
+#define SAFE_GRP0CR3 (LIFEC_SAFE_BASE + 0x0150U)
+#define SAFE_GRP1CR3 (LIFEC_SAFE_BASE + 0x0154U)
+#define SAFE_GRP0COND0 (LIFEC_SAFE_BASE + 0x0158U)
+#define SAFE_GRP1COND0 (LIFEC_SAFE_BASE + 0x015CU)
+#define SAFE_GRP0COND1 (LIFEC_SAFE_BASE + 0x0160U)
+#define SAFE_GRP1COND1 (LIFEC_SAFE_BASE + 0x0164U)
+#define SAFE_GRP0COND2 (LIFEC_SAFE_BASE + 0x0168U)
+#define SAFE_GRP1COND2 (LIFEC_SAFE_BASE + 0x016CU)
+#define SAFE_GRP0COND3 (LIFEC_SAFE_BASE + 0x0170U)
+#define SAFE_GRP1COND3 (LIFEC_SAFE_BASE + 0x0174U)
+#define SAFE_GRP0COND4 (LIFEC_SAFE_BASE + 0x0178U)
+#define SAFE_GRP1COND4 (LIFEC_SAFE_BASE + 0x017CU)
+#define SAFE_GRP0COND5 (LIFEC_SAFE_BASE + 0x0180U)
+#define SAFE_GRP1COND5 (LIFEC_SAFE_BASE + 0x0184U)
+#define SAFE_GRP0COND6 (LIFEC_SAFE_BASE + 0x0188U)
+#define SAFE_GRP1COND6 (LIFEC_SAFE_BASE + 0x018CU)
+#define SAFE_GRP0COND7 (LIFEC_SAFE_BASE + 0x0190U)
+#define SAFE_GRP1COND7 (LIFEC_SAFE_BASE + 0x0194U)
+#define SAFE_GRP0COND8 (LIFEC_SAFE_BASE + 0x0198U)
+#define SAFE_GRP1COND8 (LIFEC_SAFE_BASE + 0x019CU)
+#define SAFE_GRP0COND9 (LIFEC_SAFE_BASE + 0x01A0U)
+#define SAFE_GRP1COND9 (LIFEC_SAFE_BASE + 0x01A4U)
+#define SAFE_GRP0COND10 (LIFEC_SAFE_BASE + 0x01A8U)
+#define SAFE_GRP1COND10 (LIFEC_SAFE_BASE + 0x01ACU)
+#define SAFE_GRP0COND11 (LIFEC_SAFE_BASE + 0x01B0U)
+#define SAFE_GRP1COND11 (LIFEC_SAFE_BASE + 0x01B4U)
+#define SAFE_GRP0COND12 (LIFEC_SAFE_BASE + 0x01B8U)
+#define SAFE_GRP1COND12 (LIFEC_SAFE_BASE + 0x01BCU)
+#define SAFE_GRP0COND13 (LIFEC_SAFE_BASE + 0x01C0U)
+#define SAFE_GRP1COND13 (LIFEC_SAFE_BASE + 0x01C4U)
+#define SAFE_GRP0COND14 (LIFEC_SAFE_BASE + 0x01C8U)
+#define SAFE_GRP1COND14 (LIFEC_SAFE_BASE + 0x01CCU)
+#define SAFE_GRP0COND15 (LIFEC_SAFE_BASE + 0x01D0U)
+#define SAFE_GRP1COND15 (LIFEC_SAFE_BASE + 0x01D4U)
+#define SAFE_READONLY0 (LIFEC_SAFE_BASE + 0x01D8U)
+#define SAFE_READONLY1 (LIFEC_SAFE_BASE + 0x01DCU)
+#define SAFE_READONLY2 (LIFEC_SAFE_BASE + 0x01E0U)
+#define SAFE_READONLY3 (LIFEC_SAFE_BASE + 0x01E4U)
+#define SAFE_READONLY4 (LIFEC_SAFE_BASE + 0x01E8U)
+#define SAFE_READONLY5 (LIFEC_SAFE_BASE + 0x01ECU)
+#define SAFE_READONLY6 (LIFEC_SAFE_BASE + 0x01F0U)
+#define SAFE_READONLY7 (LIFEC_SAFE_BASE + 0x01F4U)
+#define SAFE_READONLY8 (LIFEC_SAFE_BASE + 0x01F8U)
+#define SAFE_READONLY9 (LIFEC_SAFE_BASE + 0x01FCU)
+#define SAFE_READONLY10 (LIFEC_SAFE_BASE + 0x0200U)
+#define SAFE_READONLY11 (LIFEC_SAFE_BASE + 0x0204U)
+#define SAFE_READONLY12 (LIFEC_SAFE_BASE + 0x0208U)
+#define SAFE_READONLY13 (LIFEC_SAFE_BASE + 0x020CU)
+#define SAFE_READONLY14 (LIFEC_SAFE_BASE + 0x0210U)
+#define SAFE_READONLY15 (LIFEC_SAFE_BASE + 0x0214U)
+
+#endif /* LIFEC_REGISTERS_H */
diff --git a/plat/renesas/common/plat_image_load.c b/plat/renesas/common/plat_image_load.c
new file mode 100644
index 0000000..9d814a6
--- /dev/null
+++ b/plat/renesas/common/plat_image_load.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+extern void bl2_plat_flush_bl31_params(void);
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+#if IMAGE_BL2
+ bl2_plat_flush_bl31_params();
+#endif
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/renesas/common/plat_pm.c b/plat/renesas/common/plat_pm.c
new file mode 100644
index 0000000..9810596
--- /dev/null
+++ b/plat/renesas/common/plat_pm.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include "iic_dvfs.h"
+#include "platform_def.h"
+#include "pwrc.h"
+#include "rcar_def.h"
+#include "rcar_private.h"
+#if RCAR_GEN3_ULCB
+#include "ulcb_cpld.h"
+#endif /* RCAR_GEN3_ULCB */
+
+#define DVFS_SET_VID_0V (0x00)
+#define P_ALL_OFF (0x80)
+#define KEEPON_DDR1C (0x08)
+#define KEEPON_DDR0C (0x04)
+#define KEEPON_DDR1 (0x02)
+#define KEEPON_DDR0 (0x01)
+
+#define SYSTEM_PWR_STATE(s) ((s)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+#define CLUSTER_PWR_STATE(s) ((s)->pwr_domain_state[MPIDR_AFFLVL1])
+#define CORE_PWR_STATE(s) ((s)->pwr_domain_state[MPIDR_AFFLVL0])
+
+extern void rcar_pwrc_restore_generic_timer(uint64_t *stack);
+extern void plat_rcar_gic_driver_init(void);
+extern void plat_rcar_gic_init(void);
+
+static uintptr_t rcar_sec_entrypoint;
+
+static void rcar_program_mailbox(u_register_t mpidr, uintptr_t address)
+{
+ mailbox_t *rcar_mboxes = (mailbox_t *) MBOX_BASE;
+ uint64_t linear_id = plat_core_pos_by_mpidr(mpidr);
+ unsigned long range;
+
+ rcar_mboxes[linear_id].value = address;
+ range = (unsigned long)&rcar_mboxes[linear_id];
+
+ flush_dcache_range(range, sizeof(range));
+}
+
+static void rcar_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr_el3 = read_scr_el3();
+
+ write_scr_el3(scr_el3 | SCR_IRQ_BIT);
+ dsb();
+ wfi();
+ write_scr_el3(scr_el3);
+}
+
+static int rcar_pwr_domain_on(u_register_t mpidr)
+{
+ rcar_program_mailbox(mpidr, rcar_sec_entrypoint);
+ rcar_pwrc_cpuon(mpidr);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void rcar_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ uint32_t cluster_type = rcar_pwrc_get_cluster();
+ u_register_t mpidr = read_mpidr_el1();
+
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ if (cluster_type == RCAR_CLUSTER_A53A57)
+ plat_cci_enable();
+
+ rcar_program_mailbox(mpidr, 0);
+ rcar_pwrc_enable_interrupt_wakeup(mpidr);
+
+ gicv2_cpuif_enable();
+ gicv2_pcpu_distif_init();
+}
+
+static void rcar_pwr_domain_off(const psci_power_state_t *target_state)
+{
+#if RCAR_LSI != RCAR_D3
+ uint32_t cluster_type = rcar_pwrc_get_cluster();
+#endif
+ u_register_t mpidr = read_mpidr_el1();
+
+ rcar_pwrc_disable_interrupt_wakeup(mpidr);
+ gicv2_cpuif_disable();
+ rcar_pwrc_cpuoff(mpidr);
+
+#if RCAR_LSI != RCAR_D3
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ if (cluster_type == RCAR_CLUSTER_A53A57)
+ plat_cci_disable();
+
+ rcar_pwrc_clusteroff(mpidr);
+ }
+#endif
+}
+
+static void rcar_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint32_t cluster_type = rcar_pwrc_get_cluster();
+ u_register_t mpidr = read_mpidr_el1();
+
+ if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ rcar_program_mailbox(mpidr, rcar_sec_entrypoint);
+ rcar_pwrc_enable_interrupt_wakeup(mpidr);
+ gicv2_cpuif_disable();
+ rcar_pwrc_cpuoff(mpidr);
+
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ if (cluster_type == RCAR_CLUSTER_A53A57)
+ plat_cci_disable();
+
+ rcar_pwrc_clusteroff(mpidr);
+ }
+}
+
+static void rcar_pwr_domain_suspend_finish(const psci_power_state_t
+ *target_state)
+{
+ uint32_t cluster_type = rcar_pwrc_get_cluster();
+
+ if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ goto finish;
+
+ plat_rcar_gic_driver_init();
+ plat_rcar_gic_init();
+
+ if (cluster_type == RCAR_CLUSTER_A53A57)
+ plat_cci_init();
+
+ rcar_pwrc_restore_timer_state();
+ rcar_pwrc_setup();
+ rcar_pwrc_code_copy_to_system_ram();
+
+#if RCAR_SYSTEM_SUSPEND
+ rcar_pwrc_init_suspend_to_ram();
+#endif
+finish:
+ rcar_pwr_domain_on_finish(target_state);
+}
+
+static void __dead2 rcar_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
+{
+#if RCAR_SYSTEM_SUSPEND
+ if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ rcar_pwrc_suspend_to_ram();
+#endif
+ wfi();
+
+ ERROR("RCAR Power Down: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 rcar_system_off(void)
+{
+#if PMIC_ROHM_BD9571
+#if PMIC_LEVEL_MODE
+ if (rcar_iic_dvfs_send(PMIC, DVFS_SET_VID, DVFS_SET_VID_0V))
+ ERROR("BL3-1:Failed the SYSTEM-OFF.\n");
+#else
+ if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
+ ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
+#endif
+#else
+ u_register_t mpidr = read_mpidr_el1();
+ u_register_t cpu = mpidr & 0x0000ffffU;
+ int32_t rtn_on;
+
+ rtn_on = rcar_pwrc_cpu_on_check(mpidr);
+
+ if (cpu != rcar_boot_mpidr) {
+ panic();
+ }
+
+ if (rtn_on != 0) {
+ panic();
+ }
+
+ rcar_pwrc_cpuoff(mpidr);
+ rcar_pwrc_clusteroff(mpidr);
+
+#endif /* PMIC_ROHM_BD9571 */
+ wfi();
+ ERROR("RCAR System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 rcar_system_reset(void)
+{
+#if PMIC_ROHM_BD9571
+#if PMIC_LEVEL_MODE
+#if RCAR_SYSTEM_RESET_KEEPON_DDR
+ uint8_t mode;
+ int32_t error;
+
+ error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, KEEP10_MAGIC);
+ if (error) {
+ ERROR("Failed send KEEP10 magic ret=%d\n", error);
+ goto done;
+ }
+
+ error = rcar_iic_dvfs_receive(PMIC, BKUP_MODE_CNT, &mode);
+ if (error) {
+ ERROR("Failed receive BKUP_Mode_Cnt ret=%d\n", error);
+ goto done;
+ }
+
+ mode |= KEEPON_DDR1C | KEEPON_DDR0C | KEEPON_DDR1 | KEEPON_DDR0;
+ error = rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, mode);
+ if (error) {
+ ERROR("Failed send KEEPON_DDRx ret=%d\n", error);
+ goto done;
+ }
+
+ rcar_pwrc_set_suspend_to_ram();
+done:
+#else
+ if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
+ ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
+#endif
+#else
+#if (RCAR_GEN3_ULCB == 1)
+ rcar_cpld_reset_cpu();
+#endif
+#endif
+#else
+ rcar_pwrc_system_reset();
+#endif
+ wfi();
+
+ ERROR("RCAR System Reset: operation not handled.\n");
+ panic();
+}
+
+static int rcar_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ unsigned int pstate = psci_get_pstate_type(power_state);
+ uint32_t i;
+
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ } else {
+ for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ }
+
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+#if RCAR_SYSTEM_SUSPEND
+static void rcar_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ u_register_t mpidr = read_mpidr_el1() & 0x0000ffffU;
+ int i;
+
+ if (mpidr != rcar_boot_mpidr)
+ goto deny;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+
+ return;
+deny:
+ /* deny system suspend entry */
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSCI_LOCAL_STATE_RUN;
+ for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
+}
+#endif
+
+static const plat_psci_ops_t rcar_plat_psci_ops = {
+ .cpu_standby = rcar_cpu_standby,
+ .pwr_domain_on = rcar_pwr_domain_on,
+ .pwr_domain_off = rcar_pwr_domain_off,
+ .pwr_domain_suspend = rcar_pwr_domain_suspend,
+ .pwr_domain_on_finish = rcar_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = rcar_pwr_domain_suspend_finish,
+ .system_off = rcar_system_off,
+ .system_reset = rcar_system_reset,
+ .validate_power_state = rcar_validate_power_state,
+ .pwr_domain_pwr_down_wfi = rcar_pwr_domain_pwr_down_wfi,
+#if RCAR_SYSTEM_SUSPEND
+ .get_sys_suspend_power_state = rcar_get_sys_suspend_power_state,
+#endif
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &rcar_plat_psci_ops;
+ rcar_sec_entrypoint = sec_entrypoint;
+
+#if RCAR_SYSTEM_SUSPEND
+ rcar_pwrc_init_suspend_to_ram();
+#endif
+ return 0;
+}
+
diff --git a/plat/renesas/common/plat_storage.c b/plat/renesas/common/plat_storage.c
new file mode 100644
index 0000000..6524561
--- /dev/null
+++ b/plat/renesas/common/plat_storage.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/io/io_semihosting.h>
+
+#include "io_common.h"
+#include "io_memdrv.h"
+#include "io_emmcdrv.h"
+#include "io_private.h"
+#include "io_rcar.h"
+#include <platform_def.h>
+
+static uintptr_t emmcdrv_dev_handle;
+static uintptr_t memdrv_dev_handle;
+static uintptr_t rcar_dev_handle;
+
+static uintptr_t boot_io_drv_id;
+
+static const io_block_spec_t rcar_block_spec = {
+ .offset = FLASH0_BASE,
+ .length = FLASH0_SIZE
+};
+
+static const io_block_spec_t bl2_file_spec = {
+ .offset = BL2_IMAGE_ID,
+};
+
+static const io_block_spec_t bl31_file_spec = {
+ .offset = BL31_IMAGE_ID,
+};
+
+static const io_block_spec_t bl32_file_spec = {
+ .offset = BL32_IMAGE_ID,
+};
+
+static const io_block_spec_t bl33_file_spec = {
+ .offset = BL33_IMAGE_ID,
+};
+
+static const io_block_spec_t bl332_file_spec = {
+ .offset = BL332_IMAGE_ID,
+};
+
+static const io_block_spec_t bl333_file_spec = {
+ .offset = BL333_IMAGE_ID,
+};
+
+static const io_block_spec_t bl334_file_spec = {
+ .offset = BL334_IMAGE_ID,
+};
+
+static const io_block_spec_t bl335_file_spec = {
+ .offset = BL335_IMAGE_ID,
+};
+
+static const io_block_spec_t bl336_file_spec = {
+ .offset = BL336_IMAGE_ID,
+};
+
+static const io_block_spec_t bl337_file_spec = {
+ .offset = BL337_IMAGE_ID,
+};
+
+static const io_block_spec_t bl338_file_spec = {
+ .offset = BL338_IMAGE_ID,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_block_spec_t trusted_key_cert_file_spec = {
+ .offset = TRUSTED_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl31_key_cert_file_spec = {
+ .offset = SOC_FW_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl32_key_cert_file_spec = {
+ .offset = TRUSTED_OS_FW_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl33_key_cert_file_spec = {
+ .offset = NON_TRUSTED_FW_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl332_key_cert_file_spec = {
+ .offset = BL332_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl333_key_cert_file_spec = {
+ .offset = BL333_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl334_key_cert_file_spec = {
+ .offset = BL334_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl335_key_cert_file_spec = {
+ .offset = BL335_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl336_key_cert_file_spec = {
+ .offset = BL336_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl337_key_cert_file_spec = {
+ .offset = BL337_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl338_key_cert_file_spec = {
+ .offset = BL338_KEY_CERT_ID,
+};
+
+static const io_block_spec_t bl31_cert_file_spec = {
+ .offset = SOC_FW_CONTENT_CERT_ID,
+};
+
+static const io_block_spec_t bl32_cert_file_spec = {
+ .offset = TRUSTED_OS_FW_CONTENT_CERT_ID,
+};
+
+static const io_block_spec_t bl33_cert_file_spec = {
+ .offset = NON_TRUSTED_FW_CONTENT_CERT_ID,
+};
+
+static const io_block_spec_t bl332_cert_file_spec = {
+ .offset = BL332_CERT_ID,
+};
+
+static const io_block_spec_t bl333_cert_file_spec = {
+ .offset = BL333_CERT_ID,
+};
+
+static const io_block_spec_t bl334_cert_file_spec = {
+ .offset = BL334_CERT_ID,
+};
+
+static const io_block_spec_t bl335_cert_file_spec = {
+ .offset = BL335_CERT_ID,
+};
+
+static const io_block_spec_t bl336_cert_file_spec = {
+ .offset = BL336_CERT_ID,
+};
+
+static const io_block_spec_t bl337_cert_file_spec = {
+ .offset = BL337_CERT_ID,
+};
+
+static const io_block_spec_t bl338_cert_file_spec = {
+ .offset = BL338_CERT_ID,
+};
+#endif
+
+static int32_t open_emmcdrv(const uintptr_t spec);
+static int32_t open_memmap(const uintptr_t spec);
+static int32_t open_rcar(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int32_t (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &memdrv_dev_handle,
+ (uintptr_t) &rcar_block_spec,
+ &open_memmap},
+ [BL2_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl2_file_spec,
+ &open_rcar},
+ [BL31_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl31_file_spec,
+ &open_rcar},
+ [BL32_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl32_file_spec,
+ &open_rcar},
+ [BL33_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl33_file_spec,
+ &open_rcar},
+ [BL332_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl332_file_spec,
+ &open_rcar},
+ [BL333_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl333_file_spec,
+ &open_rcar},
+ [BL334_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl334_file_spec,
+ &open_rcar},
+ [BL335_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl335_file_spec,
+ &open_rcar},
+ [BL336_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl336_file_spec,
+ &open_rcar},
+ [BL337_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl337_file_spec,
+ &open_rcar},
+ [BL338_IMAGE_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl338_file_spec,
+ &open_rcar},
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &trusted_key_cert_file_spec,
+ &open_rcar},
+ [SOC_FW_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl31_key_cert_file_spec,
+ &open_rcar},
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl32_key_cert_file_spec,
+ &open_rcar},
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl33_key_cert_file_spec,
+ &open_rcar},
+ [BL332_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl332_key_cert_file_spec,
+ &open_rcar},
+ [BL333_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl333_key_cert_file_spec,
+ &open_rcar},
+ [BL334_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl334_key_cert_file_spec,
+ &open_rcar},
+ [BL335_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl335_key_cert_file_spec,
+ &open_rcar},
+ [BL336_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl336_key_cert_file_spec,
+ &open_rcar},
+ [BL337_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl337_key_cert_file_spec,
+ &open_rcar},
+ [BL338_KEY_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl338_key_cert_file_spec,
+ &open_rcar},
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl31_cert_file_spec,
+ &open_rcar},
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl32_cert_file_spec,
+ &open_rcar},
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl33_cert_file_spec,
+ &open_rcar},
+ [BL332_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl332_cert_file_spec,
+ &open_rcar},
+ [BL333_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl333_cert_file_spec,
+ &open_rcar},
+ [BL334_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl334_cert_file_spec,
+ &open_rcar},
+ [BL335_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl335_cert_file_spec,
+ &open_rcar},
+ [BL336_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl336_cert_file_spec,
+ &open_rcar},
+ [BL337_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl337_cert_file_spec,
+ &open_rcar},
+ [BL338_CERT_ID] = {
+ &rcar_dev_handle,
+ (uintptr_t) &bl338_cert_file_spec,
+ &open_rcar}, {
+#else
+ {
+#endif
+ 0, 0, 0}
+};
+
+static io_drv_spec_t io_drv_spec_memdrv = {
+ FLASH0_BASE,
+ FLASH0_SIZE,
+ 0,
+};
+
+static io_drv_spec_t io_drv_spec_emmcdrv = {
+ 0,
+ 0,
+ 0,
+};
+
+static struct plat_io_policy drv_policies[] __attribute__ ((section(".data"))) = {
+ /* FLASH_DEV_ID */
+ { &memdrv_dev_handle, (uintptr_t) &io_drv_spec_memdrv, &open_memmap, },
+ /* EMMC_DEV_ID */
+ { &emmcdrv_dev_handle, (uintptr_t) &io_drv_spec_emmcdrv, &open_emmcdrv, }
+};
+
+static int32_t open_rcar(const uintptr_t spec)
+{
+ return io_dev_init(rcar_dev_handle, boot_io_drv_id);
+}
+
+static int32_t open_memmap(const uintptr_t spec)
+{
+ uintptr_t handle;
+ int32_t result;
+
+ result = io_dev_init(memdrv_dev_handle, 0);
+ if (result != IO_SUCCESS)
+ return result;
+
+ result = io_open(memdrv_dev_handle, spec, &handle);
+ if (result == IO_SUCCESS)
+ io_close(handle);
+
+ return result;
+}
+
+static int32_t open_emmcdrv(const uintptr_t spec)
+{
+ return io_dev_init(emmcdrv_dev_handle, 0);
+}
+
+void rcar_io_setup(void)
+{
+ const io_dev_connector_t *memmap;
+ const io_dev_connector_t *rcar;
+
+ boot_io_drv_id = FLASH_DEV_ID;
+
+ rcar_register_io_dev(&rcar);
+ rcar_register_io_dev_memdrv(&memmap);
+ io_dev_open(rcar, 0, &rcar_dev_handle);
+ io_dev_open(memmap, 0, &memdrv_dev_handle);
+}
+
+void rcar_io_emmc_setup(void)
+{
+ const io_dev_connector_t *rcar;
+ const io_dev_connector_t *emmc;
+
+ boot_io_drv_id = EMMC_DEV_ID;
+
+ rcar_register_io_dev(&rcar);
+ rcar_register_io_dev_emmcdrv(&emmc);
+ io_dev_open(rcar, 0, &rcar_dev_handle);
+ io_dev_open(emmc, 0, &emmcdrv_dev_handle);
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ const struct plat_io_policy *policy;
+ int result;
+
+ policy = &policies[image_id];
+
+ result = policy->check(policy->image_spec);
+ if (result != IO_SUCCESS)
+ return result;
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ return IO_SUCCESS;
+}
+
+int32_t plat_get_drv_source(uint32_t io_drv_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ const struct plat_io_policy *policy;
+ int32_t result;
+
+ policy = &drv_policies[io_drv_id];
+
+ result = policy->check(policy->image_spec);
+ if (result != IO_SUCCESS)
+ return result;
+
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+
+ return IO_SUCCESS;
+}
diff --git a/plat/renesas/common/plat_topology.c b/plat/renesas/common/plat_topology.c
new file mode 100644
index 0000000..0d5880d
--- /dev/null
+++ b/plat/renesas/common/plat_topology.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <lib/psci/psci.h>
+
+static const unsigned char rcar_power_domain_tree_desc[] = {
+ 1,
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rcar_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
+ return -1;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT)
+ return -1;
+
+ if (cluster_id == 0 && cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT)
+ return -1;
+
+ if (cluster_id == 1 && cpu_id >= PLATFORM_CLUSTER1_CORE_COUNT)
+ return -1;
+
+ return (cpu_id + cluster_id * PLATFORM_CLUSTER0_CORE_COUNT);
+}
+
diff --git a/plat/renesas/common/rcar_common.c b/plat/renesas/common/rcar_common.c
new file mode 100644
index 0000000..df4c30c
--- /dev/null
+++ b/plat/renesas/common/rcar_common.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2019-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <drivers/console.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+
+#include <lib/mmio.h>
+#include <cpg_registers.h>
+
+#define MSTP318 (1 << 18)
+#define MSTP319 (1 << 19)
+#define PMSR 0x5c
+#define PMSR_L1FAEG (1U << 31)
+#define PMSR_PMEL1RX (1 << 23)
+#define PMCTLR 0x60
+#define PMSR_L1IATN (1U << 31)
+
+static int rcar_pcie_fixup(unsigned int controller)
+{
+ uint32_t rcar_pcie_base[] = { 0xfe011000, 0xee811000 };
+ uint32_t addr = rcar_pcie_base[controller];
+ uint32_t cpg, pmsr;
+ int ret = 0;
+
+ /* Test if PCIECx is enabled */
+ cpg = mmio_read_32(CPG_MSTPSR3);
+ if (cpg & (MSTP318 << !controller))
+ return ret;
+
+ pmsr = mmio_read_32(addr + PMSR);
+
+ if ((pmsr & PMSR_PMEL1RX) && ((pmsr & 0x70000) != 0x30000)) {
+ /* Fix applicable */
+ mmio_write_32(addr + PMCTLR, PMSR_L1IATN);
+ while (!(mmio_read_32(addr + PMSR) & PMSR_L1FAEG))
+ ;
+ mmio_write_32(addr + PMSR, PMSR_L1FAEG | PMSR_PMEL1RX);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/* RAS functions common to AArch64 ARM platforms */
+void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+ void *handle, uint64_t flags)
+{
+ unsigned int fixed = 0;
+
+ fixed |= rcar_pcie_fixup(0);
+ fixed |= rcar_pcie_fixup(1);
+
+ if (fixed)
+ return;
+
+ plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+}
+
+#include <drivers/renesas/rcar/console/console.h>
+
+static console_t rcar_boot_console;
+static console_t rcar_runtime_console;
+
+void rcar_console_boot_init(void)
+{
+ int ret;
+
+ ret = console_rcar_register(0, 0, 0, &rcar_boot_console);
+ if (!ret)
+ panic();
+
+ console_set_scope(&rcar_boot_console, CONSOLE_FLAG_BOOT);
+}
+
+void rcar_console_boot_end(void)
+{
+}
+
+void rcar_console_runtime_init(void)
+{
+ int ret;
+
+ ret = console_rcar_register(1, 0, 0, &rcar_runtime_console);
+ if (!ret)
+ panic();
+
+ console_set_scope(&rcar_boot_console, CONSOLE_FLAG_RUNTIME);
+}
+
+void rcar_console_runtime_end(void)
+{
+}
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
new file mode 100644
index 0000000..f85db8d
--- /dev/null
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -0,0 +1,1199 @@
+/*
+ * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/image_decompress.h>
+#include <drivers/console.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_storage.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/common/platform.h>
+#if RCAR_GEN3_BL33_GZIP == 1
+#include <tf_gunzip.h>
+#endif
+
+#include "avs_driver.h"
+#include "boot_init_dram.h"
+#include "cpg_registers.h"
+#include "board.h"
+#include "emmc_def.h"
+#include "emmc_hal.h"
+#include "emmc_std.h"
+
+#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR
+#include "iic_dvfs.h"
+#endif
+
+#include "io_common.h"
+#include "io_rcar.h"
+#include "qos_init.h"
+#include "rcar_def.h"
+#include "rcar_private.h"
+#include "rcar_version.h"
+#include "rom_api.h"
+
+#if RCAR_BL2_DCACHE == 1
+/*
+ * Following symbols are only used during plat_arch_setup() only
+ * when RCAR_BL2_DCACHE is enabled.
+ */
+static const uint64_t BL2_RO_BASE = BL_CODE_BASE;
+static const uint64_t BL2_RO_LIMIT = BL_CODE_END;
+
+#if USE_COHERENT_MEM
+static const uint64_t BL2_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE;
+static const uint64_t BL2_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END;
+#endif
+
+#endif
+
+extern void plat_rcar_gic_driver_init(void);
+extern void plat_rcar_gic_init(void);
+extern void bl2_enter_bl31(const struct entry_point_info *bl_ep_info);
+extern void bl2_system_cpg_init(void);
+extern void bl2_secure_setting(void);
+extern void bl2_cpg_init(void);
+extern void rcar_io_emmc_setup(void);
+extern void rcar_io_setup(void);
+extern void rcar_swdt_release(void);
+extern void rcar_swdt_init(void);
+extern void rcar_rpc_init(void);
+extern void rcar_pfc_init(void);
+extern void rcar_dma_init(void);
+
+static void bl2_init_generic_timer(void);
+
+/* R-Car Gen3 product check */
+#if (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N)
+#define TARGET_PRODUCT PRR_PRODUCT_H3
+#define TARGET_NAME "R-Car H3"
+#elif RCAR_LSI == RCAR_M3
+#define TARGET_PRODUCT PRR_PRODUCT_M3
+#define TARGET_NAME "R-Car M3"
+#elif RCAR_LSI == RCAR_M3N
+#define TARGET_PRODUCT PRR_PRODUCT_M3N
+#define TARGET_NAME "R-Car M3N"
+#elif RCAR_LSI == RCAR_V3M
+#define TARGET_PRODUCT PRR_PRODUCT_V3M
+#define TARGET_NAME "R-Car V3M"
+#elif RCAR_LSI == RCAR_E3
+#define TARGET_PRODUCT PRR_PRODUCT_E3
+#define TARGET_NAME "R-Car E3"
+#elif RCAR_LSI == RCAR_D3
+#define TARGET_PRODUCT PRR_PRODUCT_D3
+#define TARGET_NAME "R-Car D3"
+#elif RCAR_LSI == RCAR_AUTO
+#define TARGET_NAME "R-Car H3/M3/M3N/V3M"
+#endif
+
+#if (RCAR_LSI == RCAR_E3)
+#define GPIO_INDT (GPIO_INDT6)
+#define GPIO_BKUP_TRG_SHIFT ((uint32_t)1U<<13U)
+#else
+#define GPIO_INDT (GPIO_INDT1)
+#define GPIO_BKUP_TRG_SHIFT ((uint32_t)1U<<8U)
+#endif
+
+CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t) + 0x100)
+ < (RCAR_SHARED_MEM_BASE + RCAR_SHARED_MEM_SIZE),
+ assert_bl31_params_do_not_fit_in_shared_memory);
+
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/* FDT with DRAM configuration */
+uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)];
+static void *fdt = (void *)fdt_blob;
+
+static void unsigned_num_print(unsigned long long int unum, unsigned int radix,
+ char *string)
+{
+ /* Just need enough space to store 64 bit decimal integer */
+ char num_buf[20];
+ int i = 0;
+ unsigned int rem;
+
+ do {
+ rem = unum % radix;
+ if (rem < 0xa)
+ num_buf[i] = '0' + rem;
+ else
+ num_buf[i] = 'a' + (rem - 0xa);
+ i++;
+ unum /= radix;
+ } while (unum > 0U);
+
+ while (--i >= 0)
+ *string++ = num_buf[i];
+ *string = 0;
+}
+
+#if (RCAR_LOSSY_ENABLE == 1)
+typedef struct bl2_lossy_info {
+ uint32_t magic;
+ uint32_t a0;
+ uint32_t b0;
+} bl2_lossy_info_t;
+
+static void bl2_lossy_gen_fdt(uint32_t no, uint64_t start_addr,
+ uint64_t end_addr, uint32_t format,
+ uint32_t enable, int fcnlnode)
+{
+ const uint64_t fcnlsize = cpu_to_fdt64(end_addr - start_addr);
+ char nodename[40] = { 0 };
+ int ret, node;
+
+ /* Ignore undefined addresses */
+ if (start_addr == 0 && end_addr == 0)
+ return;
+
+ snprintf(nodename, sizeof(nodename), "lossy-decompression@");
+ unsigned_num_print(start_addr, 16, nodename + strlen(nodename));
+
+ node = ret = fdt_add_subnode(fdt, fcnlnode, nodename);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot create FCNL node (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_setprop_string(fdt, node, "compatible",
+ "renesas,lossy-decompression");
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL compat string (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_appendprop_string(fdt, node, "compatible",
+ "shared-dma-pool");
+ if (ret < 0) {
+ NOTICE("BL2: Cannot append FCNL compat string (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_setprop_u64(fdt, node, "reg", start_addr);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL reg prop (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_appendprop(fdt, node, "reg", &fcnlsize, sizeof(fcnlsize));
+ if (ret < 0) {
+ NOTICE("BL2: Cannot append FCNL reg size prop (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_setprop(fdt, node, "no-map", NULL, 0);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL no-map prop (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_setprop_u32(fdt, node, "renesas,formats", format);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL formats prop (ret=%i)\n", ret);
+ panic();
+ }
+}
+
+static void bl2_lossy_setting(uint32_t no, uint64_t start_addr,
+ uint64_t end_addr, uint32_t format,
+ uint32_t enable, int fcnlnode)
+{
+ bl2_lossy_info_t info;
+ uint32_t reg;
+
+ bl2_lossy_gen_fdt(no, start_addr, end_addr, format, enable, fcnlnode);
+
+ reg = format | (start_addr >> 20);
+ mmio_write_32(AXI_DCMPAREACRA0 + 0x8 * no, reg);
+ mmio_write_32(AXI_DCMPAREACRB0 + 0x8 * no, end_addr >> 20);
+ mmio_write_32(AXI_DCMPAREACRA0 + 0x8 * no, reg | enable);
+
+ info.magic = 0x12345678U;
+ info.a0 = mmio_read_32(AXI_DCMPAREACRA0 + 0x8 * no);
+ info.b0 = mmio_read_32(AXI_DCMPAREACRB0 + 0x8 * no);
+
+ mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no, info.magic);
+ mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x4, info.a0);
+ mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x8, info.b0);
+
+ NOTICE(" Entry %d: DCMPAREACRAx:0x%x DCMPAREACRBx:0x%x\n", no,
+ mmio_read_32(AXI_DCMPAREACRA0 + 0x8 * no),
+ mmio_read_32(AXI_DCMPAREACRB0 + 0x8 * no));
+}
+#endif
+
+void bl2_plat_flush_bl31_params(void)
+{
+ uint32_t product_cut, product, cut;
+ uint32_t boot_dev, boot_cpu;
+ uint32_t lcs, reg, val;
+
+ reg = mmio_read_32(RCAR_MODEMR);
+ boot_dev = reg & MODEMR_BOOT_DEV_MASK;
+
+ if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
+ boot_dev == MODEMR_BOOT_DEV_EMMC_50X8)
+ emmc_terminate();
+
+ if ((reg & MODEMR_BOOT_CPU_MASK) != MODEMR_BOOT_CPU_CR7)
+ bl2_secure_setting();
+
+ reg = mmio_read_32(RCAR_PRR);
+ product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK);
+ product = reg & PRR_PRODUCT_MASK;
+ cut = reg & PRR_CUT_MASK;
+
+ if (product == PRR_PRODUCT_M3 && PRR_PRODUCT_30 > cut)
+ goto tlb;
+
+ if (product == PRR_PRODUCT_H3 && PRR_PRODUCT_20 > cut)
+ goto tlb;
+
+ /* Disable MFIS write protection */
+ mmio_write_32(MFISWPCNTR, MFISWPCNTR_PASSWORD | 1);
+
+tlb:
+ reg = mmio_read_32(RCAR_MODEMR);
+ boot_cpu = reg & MODEMR_BOOT_CPU_MASK;
+ if (boot_cpu != MODEMR_BOOT_CPU_CA57 &&
+ boot_cpu != MODEMR_BOOT_CPU_CA53)
+ goto mmu;
+
+ if (product_cut == PRR_PRODUCT_H3_CUT20) {
+ mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUVI1_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV1_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV2_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV3_IMSCTLR, IMSCTLR_DISCACHE);
+ } else if (product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) ||
+ product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11)) {
+ mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE);
+ } else if ((product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) ||
+ (product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_11))) {
+ mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUVP0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE);
+ }
+
+ if (product_cut == (PRR_PRODUCT_H3_CUT20) ||
+ product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) ||
+ product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11) ||
+ product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) {
+ mmio_write_32(IPMMUHC_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMURT_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUMP_IMSCTLR, IMSCTLR_DISCACHE);
+
+ mmio_write_32(IPMMUDS0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUDS1_IMSCTLR, IMSCTLR_DISCACHE);
+ }
+
+mmu:
+ mmio_write_32(IPMMUMM_IMSCTLR, IPMMUMM_IMSCTLR_ENABLE);
+ mmio_write_32(IPMMUMM_IMAUXCTLR, IPMMUMM_IMAUXCTLR_NMERGE40_BIT);
+
+ val = rcar_rom_get_lcs(&lcs);
+ if (val) {
+ ERROR("BL2: Failed to get the LCS. (%d)\n", val);
+ panic();
+ }
+
+ if (lcs == LCS_SE)
+ mmio_clrbits_32(P_ARMREG_SEC_CTRL, P_ARMREG_SEC_CTRL_PROT);
+
+ rcar_swdt_release();
+ bl2_system_cpg_init();
+
+#if RCAR_BL2_DCACHE == 1
+ /* Disable data cache (clean and invalidate) */
+ disable_mmu_el3();
+#endif
+}
+
+static uint32_t is_ddr_backup_mode(void)
+{
+#if RCAR_SYSTEM_SUSPEND
+ static uint32_t reason = RCAR_COLD_BOOT;
+ static uint32_t once;
+
+#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR
+ uint8_t data;
+#endif
+ if (once)
+ return reason;
+
+ once = 1;
+ if ((mmio_read_32(GPIO_INDT) & GPIO_BKUP_TRG_SHIFT) == 0)
+ return reason;
+
+#if PMIC_ROHM_BD9571 && RCAR_SYSTEM_RESET_KEEPON_DDR
+ if (rcar_iic_dvfs_receive(PMIC, REG_KEEP10, &data)) {
+ ERROR("BL2: REG Keep10 READ ERROR.\n");
+ panic();
+ }
+
+ if (KEEP10_MAGIC != data)
+ reason = RCAR_WARM_BOOT;
+#else
+ reason = RCAR_WARM_BOOT;
+#endif
+ return reason;
+#else
+ return RCAR_COLD_BOOT;
+#endif
+}
+
+#if RCAR_GEN3_BL33_GZIP == 1
+void bl2_plat_preload_setup(void)
+{
+ image_decompress_init(BL33_COMP_BASE, BL33_COMP_SIZE, gunzip);
+}
+#endif
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ u_register_t *boot_kind = (void *) BOOT_KIND_BASE;
+ bl_mem_params_node_t *bl_mem_params;
+
+ bl_mem_params = get_bl_mem_params_node(image_id);
+
+#if RCAR_GEN3_BL33_GZIP == 1
+ if (image_id == BL33_IMAGE_ID) {
+ image_decompress_prepare(&bl_mem_params->image_info);
+ }
+#endif
+
+ if (image_id != BL31_IMAGE_ID)
+ return 0;
+
+ if (is_ddr_backup_mode() == RCAR_COLD_BOOT)
+ goto cold_boot;
+
+ *boot_kind = RCAR_WARM_BOOT;
+ flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind));
+
+ console_flush();
+ bl2_plat_flush_bl31_params();
+
+ /* will not return */
+ bl2_enter_bl31(&bl_mem_params->ep_info);
+
+cold_boot:
+ *boot_kind = RCAR_COLD_BOOT;
+ flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind));
+
+ return 0;
+}
+
+static uint64_t rcar_get_dest_addr_from_cert(uint32_t certid, uintptr_t *dest)
+{
+ uint32_t cert, len;
+ int ret;
+
+ ret = rcar_get_certificate(certid, &cert);
+ if (ret) {
+ ERROR("%s : cert file load error", __func__);
+ return 1;
+ }
+
+ rcar_read_certificate((uint64_t) cert, &len, dest);
+
+ return 0;
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ static bl2_to_bl31_params_mem_t *params;
+ bl_mem_params_node_t *bl_mem_params;
+ uintptr_t dest;
+ int ret;
+
+ if (!params) {
+ params = (bl2_to_bl31_params_mem_t *) PARAMS_BASE;
+ memset((void *)PARAMS_BASE, 0, sizeof(*params));
+ }
+
+ bl_mem_params = get_bl_mem_params_node(image_id);
+
+ switch (image_id) {
+ case BL31_IMAGE_ID:
+ ret = rcar_get_dest_addr_from_cert(SOC_FW_CONTENT_CERT_ID,
+ &dest);
+ if (!ret)
+ bl_mem_params->image_info.image_base = dest;
+ break;
+ case BL32_IMAGE_ID:
+ ret = rcar_get_dest_addr_from_cert(TRUSTED_OS_FW_CONTENT_CERT_ID,
+ &dest);
+ if (!ret)
+ bl_mem_params->image_info.image_base = dest;
+
+ memcpy(&params->bl32_ep_info, &bl_mem_params->ep_info,
+ sizeof(entry_point_info_t));
+ break;
+ case BL33_IMAGE_ID:
+#if RCAR_GEN3_BL33_GZIP == 1
+ if ((mmio_read_32(BL33_COMP_BASE) & 0xffff) == 0x8b1f) {
+ /* decompress gzip-compressed image */
+ ret = image_decompress(&bl_mem_params->image_info);
+ if (ret != 0) {
+ return ret;
+ }
+ } else {
+ /* plain image, copy it in place */
+ memcpy((void *)BL33_BASE, (void *)BL33_COMP_BASE,
+ bl_mem_params->image_info.image_size);
+ }
+#endif
+ memcpy(&params->bl33_ep_info, &bl_mem_params->ep_info,
+ sizeof(entry_point_info_t));
+ break;
+ }
+
+ return 0;
+}
+
+struct meminfo *bl2_plat_sec_mem_layout(void)
+{
+ return &bl2_tzram_layout;
+}
+
+static void bl2_populate_compatible_string(void *dt)
+{
+ uint32_t board_type;
+ uint32_t board_rev;
+ uint32_t reg;
+ int ret;
+
+ fdt_setprop_u32(dt, 0, "#address-cells", 2);
+ fdt_setprop_u32(dt, 0, "#size-cells", 2);
+
+ /* Populate compatible string */
+ rcar_get_board_type(&board_type, &board_rev);
+ switch (board_type) {
+ case BOARD_SALVATOR_X:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "renesas,salvator-x");
+ break;
+ case BOARD_SALVATOR_XS:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "renesas,salvator-xs");
+ break;
+ case BOARD_STARTER_KIT:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "renesas,m3ulcb");
+ break;
+ case BOARD_STARTER_KIT_PRE:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "renesas,h3ulcb");
+ break;
+ case BOARD_EAGLE:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "renesas,eagle");
+ break;
+ case BOARD_EBISU:
+ case BOARD_EBISU_4D:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "renesas,ebisu");
+ break;
+ case BOARD_DRAAK:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "renesas,draak");
+ break;
+ default:
+ NOTICE("BL2: Cannot set compatible string, board unsupported\n");
+ panic();
+ }
+
+ if (ret < 0) {
+ NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret);
+ panic();
+ }
+
+ reg = mmio_read_32(RCAR_PRR);
+ switch (reg & PRR_PRODUCT_MASK) {
+ case PRR_PRODUCT_H3:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a7795");
+ break;
+ case PRR_PRODUCT_M3:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a7796");
+ break;
+ case PRR_PRODUCT_M3N:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a77965");
+ break;
+ case PRR_PRODUCT_V3M:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a77970");
+ break;
+ case PRR_PRODUCT_E3:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a77990");
+ break;
+ case PRR_PRODUCT_D3:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a77995");
+ break;
+ default:
+ NOTICE("BL2: Cannot set compatible string, SoC unsupported\n");
+ panic();
+ }
+
+ if (ret < 0) {
+ NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret);
+ panic();
+ }
+}
+
+static void bl2_add_rpc_node(void)
+{
+#if (RCAR_RPC_HYPERFLASH_LOCKED == 0)
+ int ret, node;
+
+ node = ret = fdt_add_subnode(fdt, 0, "soc");
+ if (ret < 0) {
+ goto err;
+ }
+
+ node = ret = fdt_add_subnode(fdt, node, "spi@ee200000");
+ if (ret < 0) {
+ goto err;
+ }
+
+ ret = fdt_setprop_string(fdt, node, "status", "okay");
+ if (ret < 0) {
+ goto err;
+ }
+
+ return;
+err:
+ NOTICE("BL2: Cannot add RPC node to FDT (ret=%i)\n", ret);
+ panic();
+#endif
+}
+
+static void bl2_add_dram_entry(uint64_t start, uint64_t size)
+{
+ char nodename[32] = { 0 };
+ uint64_t fdtsize;
+ int ret, node;
+
+ fdtsize = cpu_to_fdt64(size);
+
+ snprintf(nodename, sizeof(nodename), "memory@");
+ unsigned_num_print(start, 16, nodename + strlen(nodename));
+ node = ret = fdt_add_subnode(fdt, 0, nodename);
+ if (ret < 0) {
+ goto err;
+ }
+
+ ret = fdt_setprop_string(fdt, node, "device_type", "memory");
+ if (ret < 0) {
+ goto err;
+ }
+
+ ret = fdt_setprop_u64(fdt, node, "reg", start);
+ if (ret < 0) {
+ goto err;
+ }
+
+ ret = fdt_appendprop(fdt, node, "reg", &fdtsize,
+ sizeof(fdtsize));
+ if (ret < 0) {
+ goto err;
+ }
+
+ return;
+err:
+ NOTICE("BL2: Cannot add memory node [%" PRIx64 " - %" PRIx64 "] to FDT (ret=%i)\n",
+ start, start + size - 1, ret);
+ panic();
+}
+
+static void bl2_advertise_dram_entries(uint64_t dram_config[8])
+{
+ uint64_t start, size, size32;
+ int chan;
+
+ for (chan = 0; chan < 4; chan++) {
+ start = dram_config[2 * chan];
+ size = dram_config[2 * chan + 1];
+ if (!size)
+ continue;
+
+ NOTICE("BL2: CH%d: %" PRIx64 " - %" PRIx64 ", %" PRId64 " %siB\n",
+ chan, start, start + size - 1,
+ (size >> 30) ? : size >> 20,
+ (size >> 30) ? "G" : "M");
+ }
+
+ /*
+ * We add the DT nodes in reverse order here. The fdt_add_subnode()
+ * adds the DT node before the first existing DT node, so we have
+ * to add them in reverse order to get nodes sorted by address in
+ * the resulting DT.
+ */
+ for (chan = 3; chan >= 0; chan--) {
+ start = dram_config[2 * chan];
+ size = dram_config[2 * chan + 1];
+ if (!size)
+ continue;
+
+ /*
+ * Channel 0 is mapped in 32bit space and the first
+ * 128 MiB are reserved and the maximum size is 2GiB.
+ */
+ if (chan == 0) {
+ /* Limit the 32bit entry to 2 GiB - 128 MiB */
+ size32 = size - 0x8000000U;
+ if (size32 >= 0x78000000U) {
+ size32 = 0x78000000U;
+ }
+
+ /* Emit 32bit entry, up to 2 GiB - 128 MiB long. */
+ bl2_add_dram_entry(0x48000000, size32);
+
+ /*
+ * If channel 0 is less than 2 GiB long, the
+ * entire memory fits into the 32bit space entry,
+ * so move on to the next channel.
+ */
+ if (size <= 0x80000000U) {
+ continue;
+ }
+
+ /*
+ * If channel 0 is more than 2 GiB long, emit
+ * another entry which covers the rest of the
+ * memory in channel 0, in the 64bit space.
+ *
+ * Start of this new entry is at 2 GiB offset
+ * from the beginning of the 64bit channel 0
+ * address, size is 2 GiB shorter than total
+ * size of the channel.
+ */
+ start += 0x80000000U;
+ size -= 0x80000000U;
+ }
+
+ bl2_add_dram_entry(start, size);
+ }
+}
+
+static void bl2_advertise_dram_size(uint32_t product)
+{
+ uint64_t dram_config[8] = {
+ [0] = 0x400000000ULL,
+ [2] = 0x500000000ULL,
+ [4] = 0x600000000ULL,
+ [6] = 0x700000000ULL,
+ };
+ uint32_t cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK;
+
+ switch (product) {
+ case PRR_PRODUCT_H3:
+#if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
+ /* 4GB(1GBx4) */
+ dram_config[1] = 0x40000000ULL;
+ dram_config[3] = 0x40000000ULL;
+ dram_config[5] = 0x40000000ULL;
+ dram_config[7] = 0x40000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && \
+ (RCAR_DRAM_CHANNEL == 5) && \
+ (RCAR_DRAM_SPLIT == 2)
+ /* 4GB(2GBx2 2ch split) */
+ dram_config[1] = 0x80000000ULL;
+ dram_config[3] = 0x80000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 15)
+ /* 8GB(2GBx4: default) */
+ dram_config[1] = 0x80000000ULL;
+ dram_config[3] = 0x80000000ULL;
+ dram_config[5] = 0x80000000ULL;
+ dram_config[7] = 0x80000000ULL;
+#endif /* RCAR_DRAM_LPDDR4_MEMCONF == 0 */
+ break;
+
+ case PRR_PRODUCT_M3:
+ if (cut < PRR_PRODUCT_30) {
+#if (RCAR_GEN3_ULCB == 1)
+ /* 2GB(1GBx2 2ch split) */
+ dram_config[1] = 0x40000000ULL;
+ dram_config[5] = 0x40000000ULL;
+#else
+ /* 4GB(2GBx2 2ch split) */
+ dram_config[1] = 0x80000000ULL;
+ dram_config[5] = 0x80000000ULL;
+#endif
+ } else {
+ /* 8GB(2GBx4 2ch split) */
+ dram_config[1] = 0x100000000ULL;
+ dram_config[5] = 0x100000000ULL;
+ }
+ break;
+
+ case PRR_PRODUCT_M3N:
+#if (RCAR_DRAM_LPDDR4_MEMCONF == 2)
+ /* 4GB(4GBx1) */
+ dram_config[1] = 0x100000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1)
+ /* 2GB(1GBx2) */
+ dram_config[1] = 0x80000000ULL;
+#endif
+ break;
+
+ case PRR_PRODUCT_V3M:
+ /* 1GB(512MBx2) */
+ dram_config[1] = 0x40000000ULL;
+ break;
+
+ case PRR_PRODUCT_E3:
+#if (RCAR_DRAM_DDR3L_MEMCONF == 0)
+ /* 1GB(512MBx2) */
+ dram_config[1] = 0x40000000ULL;
+#elif (RCAR_DRAM_DDR3L_MEMCONF == 1)
+ /* 2GB(512MBx4) */
+ dram_config[1] = 0x80000000ULL;
+#elif (RCAR_DRAM_DDR3L_MEMCONF == 2)
+ /* 4GB(1GBx4) */
+ dram_config[1] = 0x100000000ULL;
+#endif /* RCAR_DRAM_DDR3L_MEMCONF == 0 */
+ break;
+
+ case PRR_PRODUCT_D3:
+ /* 512MB */
+ dram_config[1] = 0x20000000ULL;
+ break;
+ }
+
+ bl2_advertise_dram_entries(dram_config);
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ uint32_t reg, midr, lcs, boot_dev, boot_cpu, sscg, type, rev;
+ uint32_t product, product_cut, major, minor;
+ int32_t ret;
+ const char *str;
+ const char *unknown = "unknown";
+ const char *cpu_ca57 = "CA57";
+ const char *cpu_ca53 = "CA53";
+ const char *product_m3n = "M3N";
+ const char *product_h3 = "H3";
+ const char *product_m3 = "M3";
+ const char *product_e3 = "E3";
+ const char *product_d3 = "D3";
+ const char *product_v3m = "V3M";
+ const char *lcs_secure = "SE";
+ const char *lcs_cm = "CM";
+ const char *lcs_dm = "DM";
+ const char *lcs_sd = "SD";
+ const char *lcs_fa = "FA";
+ const char *sscg_off = "PLL1 nonSSCG Clock select";
+ const char *sscg_on = "PLL1 SSCG Clock select";
+ const char *boot_hyper80 = "HyperFlash(80MHz)";
+ const char *boot_qspi40 = "QSPI Flash(40MHz)";
+ const char *boot_qspi80 = "QSPI Flash(80MHz)";
+ const char *boot_emmc25x1 = "eMMC(25MHz x1)";
+ const char *boot_emmc50x8 = "eMMC(50MHz x8)";
+#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RCAR_D3)
+ const char *boot_hyper160 = "HyperFlash(150MHz)";
+#else
+ const char *boot_hyper160 = "HyperFlash(160MHz)";
+#endif
+#if (RCAR_LOSSY_ENABLE == 1)
+ int fcnlnode;
+#endif
+
+ bl2_init_generic_timer();
+
+ reg = mmio_read_32(RCAR_MODEMR);
+ boot_dev = reg & MODEMR_BOOT_DEV_MASK;
+ boot_cpu = reg & MODEMR_BOOT_CPU_MASK;
+
+ bl2_cpg_init();
+
+ if (boot_cpu == MODEMR_BOOT_CPU_CA57 ||
+ boot_cpu == MODEMR_BOOT_CPU_CA53) {
+ rcar_pfc_init();
+ rcar_console_boot_init();
+ }
+
+ plat_rcar_gic_driver_init();
+ plat_rcar_gic_init();
+ rcar_swdt_init();
+
+ /* FIQ interrupts are taken to EL3 */
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+
+ write_daifclr(DAIF_FIQ_BIT);
+
+ reg = read_midr();
+ midr = reg & (MIDR_PN_MASK << MIDR_PN_SHIFT);
+ switch (midr) {
+ case MIDR_CA57:
+ str = cpu_ca57;
+ break;
+ case MIDR_CA53:
+ str = cpu_ca53;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+
+ NOTICE("BL2: R-Car Gen3 Initial Program Loader(%s) Rev.%s\n", str,
+ version_of_renesas);
+
+ reg = mmio_read_32(RCAR_PRR);
+ product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK);
+ product = reg & PRR_PRODUCT_MASK;
+
+ switch (product) {
+ case PRR_PRODUCT_H3:
+ str = product_h3;
+ break;
+ case PRR_PRODUCT_M3:
+ str = product_m3;
+ break;
+ case PRR_PRODUCT_M3N:
+ str = product_m3n;
+ break;
+ case PRR_PRODUCT_V3M:
+ str = product_v3m;
+ break;
+ case PRR_PRODUCT_E3:
+ str = product_e3;
+ break;
+ case PRR_PRODUCT_D3:
+ str = product_d3;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+
+ if ((PRR_PRODUCT_M3 == product) &&
+ (PRR_PRODUCT_20 == (reg & RCAR_MAJOR_MASK))) {
+ if (RCAR_M3_CUT_VER11 == (reg & PRR_CUT_MASK)) {
+ /* M3 Ver.1.1 or Ver.1.2 */
+ NOTICE("BL2: PRR is R-Car %s Ver.1.1 / Ver.1.2\n",
+ str);
+ } else {
+ NOTICE("BL2: PRR is R-Car %s Ver.1.%d\n",
+ str,
+ (reg & RCAR_MINOR_MASK) + RCAR_M3_MINOR_OFFSET);
+ }
+ } else if (product == PRR_PRODUCT_D3) {
+ if (RCAR_D3_CUT_VER10 == (reg & PRR_CUT_MASK)) {
+ NOTICE("BL2: PRR is R-Car %s Ver.1.0\n", str);
+ } else if (RCAR_D3_CUT_VER11 == (reg & PRR_CUT_MASK)) {
+ NOTICE("BL2: PRR is R-Car %s Ver.1.1\n", str);
+ } else {
+ NOTICE("BL2: PRR is R-Car %s Ver.X.X\n", str);
+ }
+ } else {
+ major = (reg & RCAR_MAJOR_MASK) >> RCAR_MAJOR_SHIFT;
+ major = major + RCAR_MAJOR_OFFSET;
+ minor = reg & RCAR_MINOR_MASK;
+ NOTICE("BL2: PRR is R-Car %s Ver.%d.%d\n", str, major, minor);
+ }
+
+ if (PRR_PRODUCT_E3 == product || PRR_PRODUCT_D3 == product) {
+ reg = mmio_read_32(RCAR_MODEMR);
+ sscg = reg & RCAR_SSCG_MASK;
+ str = sscg == RCAR_SSCG_ENABLE ? sscg_on : sscg_off;
+ NOTICE("BL2: %s\n", str);
+ }
+
+ rcar_get_board_type(&type, &rev);
+
+ switch (type) {
+ case BOARD_SALVATOR_X:
+ case BOARD_KRIEK:
+ case BOARD_STARTER_KIT:
+ case BOARD_SALVATOR_XS:
+ case BOARD_EBISU:
+ case BOARD_STARTER_KIT_PRE:
+ case BOARD_EBISU_4D:
+ case BOARD_DRAAK:
+ case BOARD_EAGLE:
+ break;
+ default:
+ type = BOARD_UNKNOWN;
+ break;
+ }
+
+ if (type == BOARD_UNKNOWN || rev == BOARD_REV_UNKNOWN)
+ NOTICE("BL2: Board is %s Rev.---\n", GET_BOARD_NAME(type));
+ else {
+ NOTICE("BL2: Board is %s Rev.%d.%d\n",
+ GET_BOARD_NAME(type),
+ GET_BOARD_MAJOR(rev), GET_BOARD_MINOR(rev));
+ }
+
+#if RCAR_LSI != RCAR_AUTO
+ if (product != TARGET_PRODUCT) {
+ ERROR("BL2: IPL was been built for the %s.\n", TARGET_NAME);
+ ERROR("BL2: Please write the correct IPL to flash memory.\n");
+ panic();
+ }
+#endif
+ rcar_avs_init();
+ rcar_avs_setting();
+
+ switch (boot_dev) {
+ case MODEMR_BOOT_DEV_HYPERFLASH160:
+ str = boot_hyper160;
+ break;
+ case MODEMR_BOOT_DEV_HYPERFLASH80:
+ str = boot_hyper80;
+ break;
+ case MODEMR_BOOT_DEV_QSPI_FLASH40:
+ str = boot_qspi40;
+ break;
+ case MODEMR_BOOT_DEV_QSPI_FLASH80:
+ str = boot_qspi80;
+ break;
+ case MODEMR_BOOT_DEV_EMMC_25X1:
+#if RCAR_LSI == RCAR_D3
+ ERROR("BL2: Failed to Initialize. eMMC is not supported.\n");
+ panic();
+#endif
+ str = boot_emmc25x1;
+ break;
+ case MODEMR_BOOT_DEV_EMMC_50X8:
+ str = boot_emmc50x8;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+ NOTICE("BL2: Boot device is %s\n", str);
+
+ rcar_avs_setting();
+ reg = rcar_rom_get_lcs(&lcs);
+ if (reg) {
+ str = unknown;
+ goto lcm_state;
+ }
+
+ switch (lcs) {
+ case LCS_CM:
+ str = lcs_cm;
+ break;
+ case LCS_DM:
+ str = lcs_dm;
+ break;
+ case LCS_SD:
+ str = lcs_sd;
+ break;
+ case LCS_SE:
+ str = lcs_secure;
+ break;
+ case LCS_FA:
+ str = lcs_fa;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+
+lcm_state:
+ NOTICE("BL2: LCM state is %s\n", str);
+
+ rcar_avs_end();
+ is_ddr_backup_mode();
+
+ bl2_tzram_layout.total_base = BL31_BASE;
+ bl2_tzram_layout.total_size = BL31_LIMIT - BL31_BASE;
+
+ if (boot_cpu == MODEMR_BOOT_CPU_CA57 ||
+ boot_cpu == MODEMR_BOOT_CPU_CA53) {
+ ret = rcar_dram_init();
+ if (ret) {
+ NOTICE("BL2: Failed to DRAM initialize (%d).\n", ret);
+ panic();
+ }
+ rcar_qos_init();
+ }
+
+ /* Set up FDT */
+ ret = fdt_create_empty_tree(fdt, sizeof(fdt_blob));
+ if (ret) {
+ NOTICE("BL2: Cannot allocate FDT for U-Boot (ret=%i)\n", ret);
+ panic();
+ }
+
+ /* Add platform compatible string */
+ bl2_populate_compatible_string(fdt);
+
+ /* Enable RPC if unlocked */
+ bl2_add_rpc_node();
+
+ /* Print DRAM layout */
+ bl2_advertise_dram_size(product);
+
+ if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
+ boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) {
+ if (rcar_emmc_init() != EMMC_SUCCESS) {
+ NOTICE("BL2: Failed to eMMC driver initialize.\n");
+ panic();
+ }
+ rcar_emmc_memcard_power(EMMC_POWER_ON);
+ if (rcar_emmc_mount() != EMMC_SUCCESS) {
+ NOTICE("BL2: Failed to eMMC mount operation.\n");
+ panic();
+ }
+ } else {
+ rcar_rpc_init();
+ rcar_dma_init();
+ }
+
+ reg = mmio_read_32(RST_WDTRSTCR);
+ reg &= ~WDTRSTCR_RWDT_RSTMSK;
+ reg |= WDTRSTCR_PASSWORD;
+ mmio_write_32(RST_WDTRSTCR, reg);
+
+ mmio_write_32(CPG_CPGWPR, CPGWPR_PASSWORD);
+ mmio_write_32(CPG_CPGWPCR, CPGWPCR_PASSWORD);
+
+ reg = mmio_read_32(RCAR_PRR);
+ if ((reg & RCAR_CPU_MASK_CA57) == RCAR_CPU_HAVE_CA57)
+ mmio_write_32(CPG_CA57DBGRCR,
+ DBGCPUPREN | mmio_read_32(CPG_CA57DBGRCR));
+
+ if ((reg & RCAR_CPU_MASK_CA53) == RCAR_CPU_HAVE_CA53)
+ mmio_write_32(CPG_CA53DBGRCR,
+ DBGCPUPREN | mmio_read_32(CPG_CA53DBGRCR));
+
+ if (product_cut == PRR_PRODUCT_H3_CUT10) {
+ reg = mmio_read_32(CPG_PLL2CR);
+ reg &= ~((uint32_t) 1 << 5);
+ mmio_write_32(CPG_PLL2CR, reg);
+
+ reg = mmio_read_32(CPG_PLL4CR);
+ reg &= ~((uint32_t) 1 << 5);
+ mmio_write_32(CPG_PLL4CR, reg);
+
+ reg = mmio_read_32(CPG_PLL0CR);
+ reg &= ~((uint32_t) 1 << 12);
+ mmio_write_32(CPG_PLL0CR, reg);
+ }
+#if (RCAR_LOSSY_ENABLE == 1)
+ NOTICE("BL2: Lossy Decomp areas\n");
+
+ fcnlnode = fdt_add_subnode(fdt, 0, "reserved-memory");
+ if (fcnlnode < 0) {
+ NOTICE("BL2: Cannot create reserved mem node (ret=%i)\n",
+ fcnlnode);
+ panic();
+ }
+
+ bl2_lossy_setting(0, LOSSY_ST_ADDR0, LOSSY_END_ADDR0,
+ LOSSY_FMT0, LOSSY_ENA_DIS0, fcnlnode);
+ bl2_lossy_setting(1, LOSSY_ST_ADDR1, LOSSY_END_ADDR1,
+ LOSSY_FMT1, LOSSY_ENA_DIS1, fcnlnode);
+ bl2_lossy_setting(2, LOSSY_ST_ADDR2, LOSSY_END_ADDR2,
+ LOSSY_FMT2, LOSSY_ENA_DIS2, fcnlnode);
+#endif
+
+ fdt_pack(fdt);
+ NOTICE("BL2: FDT at %p\n", fdt);
+
+ if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
+ boot_dev == MODEMR_BOOT_DEV_EMMC_50X8)
+ rcar_io_emmc_setup();
+ else
+ rcar_io_setup();
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+#if RCAR_BL2_DCACHE == 1
+ NOTICE("BL2: D-Cache enable\n");
+ rcar_configure_mmu_el3(BL2_BASE,
+ BL2_END - BL2_BASE,
+ BL2_RO_BASE, BL2_RO_LIMIT
+#if USE_COHERENT_MEM
+ , BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT
+#endif
+ );
+#endif
+}
+
+void bl2_platform_setup(void)
+{
+
+}
+
+static void bl2_init_generic_timer(void)
+{
+/* FIXME: V3M 16.666 MHz ? */
+#if RCAR_LSI == RCAR_D3
+ uint32_t reg_cntfid = EXTAL_DRAAK;
+#elif RCAR_LSI == RCAR_E3
+ uint32_t reg_cntfid = EXTAL_EBISU;
+#else /* RCAR_LSI == RCAR_E3 */
+ uint32_t reg;
+ uint32_t reg_cntfid;
+ uint32_t modemr;
+ uint32_t modemr_pll;
+ uint32_t board_type;
+ uint32_t board_rev;
+ uint32_t pll_table[] = {
+ EXTAL_MD14_MD13_TYPE_0, /* MD14/MD13 : 0b00 */
+ EXTAL_MD14_MD13_TYPE_1, /* MD14/MD13 : 0b01 */
+ EXTAL_MD14_MD13_TYPE_2, /* MD14/MD13 : 0b10 */
+ EXTAL_MD14_MD13_TYPE_3 /* MD14/MD13 : 0b11 */
+ };
+
+ modemr = mmio_read_32(RCAR_MODEMR);
+ modemr_pll = (modemr & MODEMR_BOOT_PLL_MASK);
+
+ /* Set frequency data in CNTFID0 */
+ reg_cntfid = pll_table[modemr_pll >> MODEMR_BOOT_PLL_SHIFT];
+ reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK);
+ switch (modemr_pll) {
+ case MD14_MD13_TYPE_0:
+ rcar_get_board_type(&board_type, &board_rev);
+ if (BOARD_SALVATOR_XS == board_type) {
+ reg_cntfid = EXTAL_SALVATOR_XS;
+ }
+ break;
+ case MD14_MD13_TYPE_3:
+ if (PRR_PRODUCT_H3_CUT10 == reg) {
+ reg_cntfid = reg_cntfid >> 1U;
+ }
+ break;
+ default:
+ /* none */
+ break;
+ }
+#endif /* RCAR_LSI == RCAR_E3 */
+ /* Update memory mapped and register based freqency */
+ write_cntfrq_el0((u_register_t )reg_cntfid);
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + (uintptr_t)CNTFID_OFF, reg_cntfid);
+ /* Enable counter */
+ mmio_setbits_32(RCAR_CNTC_BASE + (uintptr_t)CNTCR_OFF,
+ (uint32_t)CNTCR_EN);
+}
diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk
new file mode 100644
index 0000000..670d499
--- /dev/null
+++ b/plat/renesas/rcar/platform.mk
@@ -0,0 +1,371 @@
+#
+# Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/renesas/common/common.mk
+
+ifndef LSI
+ $(error "Error: Unknown LSI. Please use LSI=<LSI name> to specify the LSI")
+else
+ ifeq (${LSI},AUTO)
+ RCAR_LSI:=${RCAR_AUTO}
+ else ifeq (${LSI},H3)
+ RCAR_LSI:=${RCAR_H3}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else ifeq (${LSI_CUT},11)
+ RCAR_LSI_CUT:=1
+ else ifeq (${LSI_CUT},20)
+ RCAR_LSI_CUT:=10
+ else ifeq (${LSI_CUT},30)
+ RCAR_LSI_CUT:=20
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},H3N)
+ RCAR_LSI:=${RCAR_H3N}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},30)
+ RCAR_LSI_CUT:=20
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},M3)
+ RCAR_LSI:=${RCAR_M3}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else ifeq (${LSI_CUT},11)
+ RCAR_LSI_CUT:=1
+ else ifeq (${LSI_CUT},13)
+ RCAR_LSI_CUT:=3
+ else ifeq (${LSI_CUT},30)
+ RCAR_LSI_CUT:=20
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},M3N)
+ RCAR_LSI:=${RCAR_M3N}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else ifeq (${LSI_CUT},11)
+ RCAR_LSI_CUT:=1
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},E3)
+ RCAR_LSI:=${RCAR_E3}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else ifeq (${LSI_CUT},11)
+ RCAR_LSI_CUT:=1
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},D3)
+ RCAR_LSI:=${RCAR_D3}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},V3M)
+ RCAR_LSI:=${RCAR_V3M}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ endif
+ ifeq (${LSI_CUT},20)
+ RCAR_LSI_CUT:=10
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else
+ $(error "Error: ${LSI} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI))
+endif
+
+# lock RPC HYPERFLASH access by default
+# unlock to repogram the ATF firmware from u-boot
+ifndef RCAR_RPC_HYPERFLASH_LOCKED
+RCAR_RPC_HYPERFLASH_LOCKED := 1
+endif
+$(eval $(call add_define,RCAR_RPC_HYPERFLASH_LOCKED))
+
+# Process RCAR_SECURE_BOOT flag
+ifndef RCAR_SECURE_BOOT
+RCAR_SECURE_BOOT := 1
+endif
+$(eval $(call add_define,RCAR_SECURE_BOOT))
+
+# Process RCAR_QOS_TYPE flag
+ifndef RCAR_QOS_TYPE
+RCAR_QOS_TYPE := 0
+endif
+$(eval $(call add_define,RCAR_QOS_TYPE))
+
+# Process RCAR_DRAM_SPLIT flag
+ifndef RCAR_DRAM_SPLIT
+RCAR_DRAM_SPLIT := 0
+endif
+$(eval $(call add_define,RCAR_DRAM_SPLIT))
+
+# Process RCAR_BL33_EXECUTION_EL flag
+ifndef RCAR_BL33_EXECUTION_EL
+RCAR_BL33_EXECUTION_EL := 0
+endif
+$(eval $(call add_define,RCAR_BL33_EXECUTION_EL))
+
+# Process RCAR_AVS_SETTING_ENABLE flag
+ifeq (${RCAR_AVS_SETTING_ENABLE},0)
+AVS_SETTING_ENABLE := 0
+else
+AVS_SETTING_ENABLE := 1
+endif
+$(eval $(call add_define,AVS_SETTING_ENABLE))
+
+# Process RCAR_LOSSY_ENABLE flag
+ifndef RCAR_LOSSY_ENABLE
+RCAR_LOSSY_ENABLE := 0
+endif
+$(eval $(call add_define,RCAR_LOSSY_ENABLE))
+
+# Process LIFEC_DBSC_PROTECT_ENABLE flag
+ifndef LIFEC_DBSC_PROTECT_ENABLE
+LIFEC_DBSC_PROTECT_ENABLE := 1
+endif
+$(eval $(call add_define,LIFEC_DBSC_PROTECT_ENABLE))
+
+# Process PMIC_ROHM_BD9571 flag
+ifndef PMIC_ROHM_BD9571
+PMIC_ROHM_BD9571 := 1
+endif
+$(eval $(call add_define,PMIC_ROHM_BD9571))
+
+# Process PMIC_LEVEL_MODE flag
+ifndef PMIC_LEVEL_MODE
+PMIC_LEVEL_MODE := 1
+endif
+$(eval $(call add_define,PMIC_LEVEL_MODE))
+
+# Process RCAR_GEN3_ULCB flag
+ifndef RCAR_GEN3_ULCB
+RCAR_GEN3_ULCB := 0
+endif
+ifeq (${RCAR_GEN3_ULCB},1)
+ BOARD_DEFAULT := 0x10
+ $(eval $(call add_define,BOARD_DEFAULT))
+endif
+$(eval $(call add_define,RCAR_GEN3_ULCB))
+
+# Process RCAR_REF_INT flag
+ifndef RCAR_REF_INT
+RCAR_REF_INT :=0
+endif
+$(eval $(call add_define,RCAR_REF_INT))
+
+# Process RCAR_REWT_TRAINING flag
+ifndef RCAR_REWT_TRAINING
+RCAR_REWT_TRAINING := 1
+endif
+$(eval $(call add_define,RCAR_REWT_TRAINING))
+
+# Process RCAR_SYSTEM_SUSPEND flag
+ifndef RCAR_SYSTEM_SUSPEND
+RCAR_SYSTEM_SUSPEND := 1
+endif
+$(eval $(call add_define,RCAR_SYSTEM_SUSPEND))
+
+# SYSTEM_SUSPEND requires power control of PMIC etc.
+# When executing SYSTEM_SUSPEND other than Salvator-X, Salvator-XS and Ebisu,
+# processing equivalent to that implemented in PMIC_ROHM_BD9571 is necessary.
+ifeq (${RCAR_SYSTEM_SUSPEND},1)
+ ifeq (${PMIC_ROHM_BD9571},0)
+ $(error "Error: When you want RCAR_SYSTEM_SUSPEND to be enable, please also set PMIC_ROHM_BD9571 to enable.")
+ endif
+endif
+
+# Process RCAR_DRAM_LPDDR4_MEMCONF flag
+ifndef RCAR_DRAM_LPDDR4_MEMCONF
+RCAR_DRAM_LPDDR4_MEMCONF :=1
+endif
+$(eval $(call add_define,RCAR_DRAM_LPDDR4_MEMCONF))
+
+# Process RCAR_DRAM_MEMRANK flag
+ifndef RCAR_DRAM_MEMRANK
+RCAR_DRAM_MEMRANK :=0
+endif
+$(eval $(call add_define,RCAR_DRAM_MEMRANK))
+
+# Process RCAR_DRAM_DDR3L_MEMCONF flag
+ifndef RCAR_DRAM_DDR3L_MEMCONF
+RCAR_DRAM_DDR3L_MEMCONF :=1
+endif
+$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMCONF))
+
+# Process RCAR_DRAM_DDR3L_MEMDUAL flag
+ifndef RCAR_DRAM_DDR3L_MEMDUAL
+RCAR_DRAM_DDR3L_MEMDUAL :=1
+endif
+$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMDUAL))
+
+# Process RCAR_BL33_ARG0 flag
+ifdef RCAR_BL33_ARG0
+$(eval $(call add_define,RCAR_BL33_ARG0))
+endif
+
+#Process RCAR_BL2_DCACHE flag
+ifndef RCAR_BL2_DCACHE
+RCAR_BL2_DCACHE := 0
+endif
+$(eval $(call add_define,RCAR_BL2_DCACHE))
+
+# Process RCAR_DRAM_CHANNEL flag
+ifndef RCAR_DRAM_CHANNEL
+RCAR_DRAM_CHANNEL :=15
+endif
+$(eval $(call add_define,RCAR_DRAM_CHANNEL))
+
+#Process RCAR_SYSTEM_RESET_KEEPON_DDR flag
+ifndef RCAR_SYSTEM_RESET_KEEPON_DDR
+RCAR_SYSTEM_RESET_KEEPON_DDR := 0
+endif
+$(eval $(call add_define,RCAR_SYSTEM_RESET_KEEPON_DDR))
+
+ifndef RCAR_GEN3_BL33_GZIP
+RCAR_GEN3_BL33_GZIP := 0
+endif
+$(eval $(call add_define,RCAR_GEN3_BL33_GZIP))
+
+# RCAR_SYSTEM_RESET_KEEPON_DDR requires power control of PMIC etc.
+# When executing SYSTEM_SUSPEND other than Salvator-X, Salvator-XS and Ebisu,
+# processing equivalent to that implemented in PMIC_ROHM_BD9571 is necessary.
+# Also, it is necessary to enable RCAR_SYSTEM_SUSPEND.
+ifeq (${RCAR_SYSTEM_RESET_KEEPON_DDR},1)
+ ifeq (${PMIC_ROHM_BD9571},0)
+ $(error "Error: When you want RCAR_SYSTEM_RESET_KEEPON_DDR to be enable, please also set PMIC_ROHM_BD9571 to enable.")
+ endif
+ ifeq (${RCAR_SYSTEM_SUSPEND},0)
+ $(error "Error: When you want RCAR_SYSTEM_RESET_KEEPON_DDR to be enable, please also set RCAR_SYSTEM_SUSPEND to enable.")
+ endif
+endif
+
+include drivers/renesas/common/ddr/ddr.mk
+include drivers/renesas/rcar/qos/qos.mk
+include drivers/renesas/rcar/pfc/pfc.mk
+include lib/libfdt/libfdt.mk
+
+PLAT_INCLUDES += -Idrivers/renesas/common/ddr \
+ -Idrivers/renesas/rcar/qos \
+ -Idrivers/renesas/rcar/board \
+ -Idrivers/renesas/rcar/cpld/ \
+ -Idrivers/renesas/common \
+ -Idrivers/renesas/common/iic_dvfs \
+ -Idrivers/renesas/common/avs \
+ -Idrivers/renesas/common/delay \
+ -Idrivers/renesas/common/rom \
+ -Idrivers/renesas/common/scif \
+ -Idrivers/renesas/common/emmc \
+ -Idrivers/renesas/common/pwrc \
+ -Idrivers/renesas/common/io
+
+BL2_SOURCES += plat/renesas/rcar/bl2_plat_setup.c \
+ drivers/renesas/rcar/board/board.c
+
+ifeq (${RCAR_GEN3_BL33_GZIP},1)
+include lib/zlib/zlib.mk
+
+BL2_SOURCES += common/image_decompress.c \
+ $(ZLIB_SOURCES)
+endif
+
+ifeq (${RCAR_GEN3_ULCB},1)
+BL31_SOURCES += drivers/renesas/rcar/cpld/ulcb_cpld.c
+endif
+
+# build the layout images for the bootrom and the necessary srecords
+rcar: rcar_layout_tool rcar_srecord
+distclean realclean clean: clean_layout_tool clean_srecord
+
+# layout images
+LAYOUT_TOOLPATH ?= tools/renesas/rcar_layout_create
+
+clean_layout_tool:
+ @echo "clean layout tool"
+ ${Q}${MAKE} -C ${LAYOUT_TOOLPATH} clean
+
+.PHONY: rcar_layout_tool
+rcar_layout_tool:
+ @echo "generating layout srecs"
+ ${Q}${MAKE} CPPFLAGS="-D=AARCH64" --no-print-directory -C ${LAYOUT_TOOLPATH}
+
+# srecords
+SREC_PATH = ${BUILD_PLAT}
+BL2_ELF_SRC = ${SREC_PATH}/bl2/bl2.elf
+BL31_ELF_SRC = ${SREC_PATH}/bl31/bl31.elf
+
+clean_srecord:
+ @echo "clean bl2 and bl31 srecs"
+ rm -f ${SREC_PATH}/bl2.srec ${SREC_PATH}/bl31.srec
+
+.PHONY: rcar_srecord
+rcar_srecord: $(BL2_ELF_SRC) $(BL31_ELF_SRC)
+ @echo "generating srec: ${SREC_PATH}/bl2.srec"
+ $(Q)$(OC) -O srec --srec-forceS3 ${BL2_ELF_SRC} ${SREC_PATH}/bl2.srec
+ @echo "generating srec: ${SREC_PATH}/bl31.srec"
+ $(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec
+
diff --git a/plat/renesas/rzg/bl2_plat_setup.c b/plat/renesas/rzg/bl2_plat_setup.c
new file mode 100644
index 0000000..e9dbd20
--- /dev/null
+++ b/plat/renesas/rzg/bl2_plat_setup.c
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/console.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_storage.h>
+#include <libfdt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <platform_def.h>
+#include <plat/common/platform.h>
+
+#include "avs_driver.h"
+#include "board.h"
+#include "boot_init_dram.h"
+#include "cpg_registers.h"
+#include "emmc_def.h"
+#include "emmc_hal.h"
+#include "emmc_std.h"
+#include "io_common.h"
+#include "io_rcar.h"
+#include "qos_init.h"
+#include "rcar_def.h"
+#include "rcar_private.h"
+#include "rcar_version.h"
+#include "rom_api.h"
+
+#define MAX_DRAM_CHANNELS 4
+/*
+ * DDR ch0 has a shadow area mapped in 32bit address space.
+ * Physical address 0x4_0000_0000 - 0x4_7fff_ffff in 64bit space
+ * is mapped to 0x4000_0000 - 0xbfff_ffff in 32bit space.
+ */
+#define MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE 0x80000000ULL
+
+#if RCAR_BL2_DCACHE == 1
+/*
+ * Following symbols are only used during plat_arch_setup() only
+ * when RCAR_BL2_DCACHE is enabled.
+ */
+static const uint64_t BL2_RO_BASE = BL_CODE_BASE;
+static const uint64_t BL2_RO_LIMIT = BL_CODE_END;
+
+#if USE_COHERENT_MEM
+static const uint64_t BL2_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE;
+static const uint64_t BL2_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END;
+#endif /* USE_COHERENT_MEM */
+
+#endif /* RCAR_BL2_DCACHE */
+
+extern void plat_rcar_gic_driver_init(void);
+extern void plat_rcar_gic_init(void);
+extern void bl2_enter_bl31(const struct entry_point_info *bl_ep_info);
+extern void bl2_system_cpg_init(void);
+extern void bl2_secure_setting(void);
+extern void bl2_cpg_init(void);
+extern void rcar_io_emmc_setup(void);
+extern void rcar_io_setup(void);
+extern void rcar_swdt_release(void);
+extern void rcar_swdt_init(void);
+extern void rcar_rpc_init(void);
+extern void rcar_dma_init(void);
+extern void rzg_pfc_init(void);
+
+static void bl2_init_generic_timer(void);
+
+/* RZ/G2 product check */
+#if RCAR_LSI == RZ_G2M
+#define TARGET_PRODUCT PRR_PRODUCT_M3
+#define TARGET_NAME "RZ/G2M"
+#elif RCAR_LSI == RZ_G2H
+#define TARGET_PRODUCT PRR_PRODUCT_H3
+#define TARGET_NAME "RZ/G2H"
+#elif RCAR_LSI == RZ_G2N
+#define TARGET_PRODUCT PRR_PRODUCT_M3N
+#define TARGET_NAME "RZ/G2N"
+#elif RCAR_LSI == RZ_G2E
+#define TARGET_PRODUCT PRR_PRODUCT_E3
+#define TARGET_NAME "RZ/G2E"
+#elif RCAR_LSI == RCAR_AUTO
+#define TARGET_NAME "RZ/G2M"
+#endif /* RCAR_LSI == RZ_G2M */
+
+#if (RCAR_LSI == RZ_G2E)
+#define GPIO_INDT (GPIO_INDT6)
+#define GPIO_BKUP_TRG_SHIFT ((uint32_t)1U << 13U)
+#else
+#define GPIO_INDT (GPIO_INDT1)
+#define GPIO_BKUP_TRG_SHIFT (1U << 8U)
+#endif /* RCAR_LSI == RZ_G2E */
+
+CASSERT((PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t) + 0x100)
+ < (RCAR_SHARED_MEM_BASE + RCAR_SHARED_MEM_SIZE),
+ assert_bl31_params_do_not_fit_in_shared_memory);
+
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/* FDT with DRAM configuration */
+uint64_t fdt_blob[PAGE_SIZE_4KB / sizeof(uint64_t)];
+static void *fdt = (void *)fdt_blob;
+
+static void unsigned_num_print(uint64_t unum, unsigned int radix, char *string)
+{
+ /* Just need enough space to store 64 bit decimal integer */
+ char num_buf[20];
+ int i = 0;
+ unsigned int rem;
+
+ do {
+ rem = unum % radix;
+ if (rem < 0xaU) {
+ num_buf[i] = '0' + rem;
+ } else {
+ num_buf[i] = 'a' + (rem - 0xaU);
+ }
+ i++;
+ unum /= radix;
+ } while (unum > 0U);
+
+ while (--i >= 0) {
+ *string++ = num_buf[i];
+ }
+ *string = 0;
+}
+
+#if RCAR_LOSSY_ENABLE == 1
+typedef struct bl2_lossy_info {
+ uint32_t magic;
+ uint32_t a0;
+ uint32_t b0;
+} bl2_lossy_info_t;
+
+static void bl2_lossy_gen_fdt(uint32_t no, uint64_t start_addr,
+ uint64_t end_addr, uint32_t format,
+ uint32_t enable, int fcnlnode)
+{
+ const uint64_t fcnlsize = cpu_to_fdt64(end_addr - start_addr);
+ char nodename[40] = { 0 };
+ int ret, node;
+
+ /* Ignore undefined addresses */
+ if (start_addr == 0UL && end_addr == 0UL) {
+ return;
+ }
+
+ snprintf(nodename, sizeof(nodename), "lossy-decompression@");
+ unsigned_num_print(start_addr, 16, nodename + strlen(nodename));
+
+ node = ret = fdt_add_subnode(fdt, fcnlnode, nodename);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot create FCNL node (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_setprop_string(fdt, node, "compatible",
+ "renesas,lossy-decompression");
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL compat string %s (ret=%i)\n",
+ "renesas,lossy-decompression", ret);
+ panic();
+ }
+
+ ret = fdt_appendprop_string(fdt, node, "compatible",
+ "shared-dma-pool");
+ if (ret < 0) {
+ NOTICE("BL2: Cannot append FCNL compat string %s (ret=%i)\n",
+ "shared-dma-pool", ret);
+ panic();
+ }
+
+ ret = fdt_setprop_u64(fdt, node, "reg", start_addr);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL reg prop (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_appendprop(fdt, node, "reg", &fcnlsize, sizeof(fcnlsize));
+ if (ret < 0) {
+ NOTICE("BL2: Cannot append FCNL reg size prop (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_setprop(fdt, node, "no-map", NULL, 0);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL no-map prop (ret=%i)\n", ret);
+ panic();
+ }
+
+ ret = fdt_setprop_u32(fdt, node, "renesas,formats", format);
+ if (ret < 0) {
+ NOTICE("BL2: Cannot add FCNL formats prop (ret=%i)\n", ret);
+ panic();
+ }
+}
+
+static void bl2_lossy_setting(uint32_t no, uint64_t start_addr,
+ uint64_t end_addr, uint32_t format,
+ uint32_t enable, int fcnlnode)
+{
+ bl2_lossy_info_t info;
+ uint32_t reg;
+
+ bl2_lossy_gen_fdt(no, start_addr, end_addr, format, enable, fcnlnode);
+
+ reg = format | (start_addr >> 20);
+ mmio_write_32(AXI_DCMPAREACRA0 + 0x8U * no, reg);
+ mmio_write_32(AXI_DCMPAREACRB0 + 0x8U * no, end_addr >> 20);
+ mmio_write_32(AXI_DCMPAREACRA0 + 0x8U * no, reg | enable);
+
+ info.magic = 0x12345678U;
+ info.a0 = mmio_read_32(AXI_DCMPAREACRA0 + 0x8U * no);
+ info.b0 = mmio_read_32(AXI_DCMPAREACRB0 + 0x8U * no);
+
+ mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no, info.magic);
+ mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x4U, info.a0);
+ mmio_write_32(LOSSY_PARAMS_BASE + sizeof(info) * no + 0x8U, info.b0);
+
+ NOTICE(" Entry %d: DCMPAREACRAx:0x%x DCMPAREACRBx:0x%x\n", no,
+ mmio_read_32(AXI_DCMPAREACRA0 + 0x8U * no),
+ mmio_read_32(AXI_DCMPAREACRB0 + 0x8U * no));
+}
+#endif /* RCAR_LOSSY_ENABLE == 1 */
+
+void bl2_plat_flush_bl31_params(void)
+{
+ uint32_t product_cut, product, cut;
+ uint32_t boot_dev, boot_cpu;
+ uint32_t reg;
+
+ reg = mmio_read_32(RCAR_MODEMR);
+ boot_dev = reg & MODEMR_BOOT_DEV_MASK;
+
+ if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
+ boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) {
+ emmc_terminate();
+ }
+
+ if ((reg & MODEMR_BOOT_CPU_MASK) != MODEMR_BOOT_CPU_CR7) {
+ bl2_secure_setting();
+ }
+
+ reg = mmio_read_32(RCAR_PRR);
+ product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK);
+ product = reg & PRR_PRODUCT_MASK;
+ cut = reg & PRR_CUT_MASK;
+
+ if (!((product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) ||
+ (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20))) {
+ /* Disable MFIS write protection */
+ mmio_write_32(MFISWPCNTR, MFISWPCNTR_PASSWORD | 1U);
+ }
+
+ reg = mmio_read_32(RCAR_MODEMR);
+ boot_cpu = reg & MODEMR_BOOT_CPU_MASK;
+ if (boot_cpu == MODEMR_BOOT_CPU_CA57 ||
+ boot_cpu == MODEMR_BOOT_CPU_CA53) {
+ if (product_cut == PRR_PRODUCT_H3_CUT20) {
+ mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUVI1_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV1_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV2_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV3_IMSCTLR, IMSCTLR_DISCACHE);
+ } else if (product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) ||
+ product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11)) {
+ mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE);
+ } else if ((product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) ||
+ (product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_11))) {
+ mmio_write_32(IPMMUVI0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUVP0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUPV0_IMSCTLR, IMSCTLR_DISCACHE);
+ }
+
+ if (product_cut == (PRR_PRODUCT_H3_CUT20) ||
+ product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_10) ||
+ product_cut == (PRR_PRODUCT_M3N | PRR_PRODUCT_11) ||
+ product_cut == (PRR_PRODUCT_E3 | PRR_PRODUCT_10)) {
+ mmio_write_32(IPMMUHC_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMURT_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUMP_IMSCTLR, IMSCTLR_DISCACHE);
+
+ mmio_write_32(IPMMUDS0_IMSCTLR, IMSCTLR_DISCACHE);
+ mmio_write_32(IPMMUDS1_IMSCTLR, IMSCTLR_DISCACHE);
+ }
+ }
+
+ mmio_write_32(IPMMUMM_IMSCTLR, IPMMUMM_IMSCTLR_ENABLE);
+ mmio_write_32(IPMMUMM_IMAUXCTLR, IPMMUMM_IMAUXCTLR_NMERGE40_BIT);
+
+ rcar_swdt_release();
+ bl2_system_cpg_init();
+
+#if RCAR_BL2_DCACHE == 1
+ /* Disable data cache (clean and invalidate) */
+ disable_mmu_el3();
+#endif /* RCAR_BL2_DCACHE == 1 */
+}
+
+static uint32_t is_ddr_backup_mode(void)
+{
+#if RCAR_SYSTEM_SUSPEND
+ static uint32_t reason = RCAR_COLD_BOOT;
+ static uint32_t once;
+
+ if (once != 0U) {
+ return reason;
+ }
+
+ once = 1;
+ if ((mmio_read_32(GPIO_INDT) & GPIO_BKUP_TRG_SHIFT) == 0U) {
+ return reason;
+ }
+
+ reason = RCAR_WARM_BOOT;
+ return reason;
+#else /* RCAR_SYSTEM_SUSPEND */
+ return RCAR_COLD_BOOT;
+#endif /* RCAR_SYSTEM_SUSPEND */
+}
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ u_register_t *boot_kind = (void *)BOOT_KIND_BASE;
+ bl_mem_params_node_t *bl_mem_params;
+
+ if (image_id != BL31_IMAGE_ID) {
+ return 0;
+ }
+
+ bl_mem_params = get_bl_mem_params_node(image_id);
+
+ if (is_ddr_backup_mode() != RCAR_COLD_BOOT) {
+ *boot_kind = RCAR_WARM_BOOT;
+ flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind));
+
+ console_flush();
+ bl2_plat_flush_bl31_params();
+
+ /* will not return */
+ bl2_enter_bl31(&bl_mem_params->ep_info);
+ }
+
+ *boot_kind = RCAR_COLD_BOOT;
+ flush_dcache_range(BOOT_KIND_BASE, sizeof(*boot_kind));
+
+ return 0;
+}
+
+static uint64_t rzg_get_dest_addr_from_cert(uint32_t certid, uintptr_t *dest)
+{
+ uint32_t cert, len;
+ int err;
+
+ err = rcar_get_certificate(certid, &cert);
+ if (err != 0) {
+ ERROR("%s : cert file load error", __func__);
+ return 1U;
+ }
+
+ rcar_read_certificate((uint64_t)cert, &len, dest);
+
+ return 0U;
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ static bl2_to_bl31_params_mem_t *params;
+ bl_mem_params_node_t *bl_mem_params;
+ uintptr_t dest;
+ uint64_t ret;
+
+ if (params == NULL) {
+ params = (bl2_to_bl31_params_mem_t *)PARAMS_BASE;
+ memset((void *)PARAMS_BASE, 0, sizeof(*params));
+ }
+
+ bl_mem_params = get_bl_mem_params_node(image_id);
+
+ switch (image_id) {
+ case BL31_IMAGE_ID:
+ ret = rzg_get_dest_addr_from_cert(SOC_FW_CONTENT_CERT_ID,
+ &dest);
+ if (ret == 0U) {
+ bl_mem_params->image_info.image_base = dest;
+ }
+ break;
+ case BL32_IMAGE_ID:
+ ret = rzg_get_dest_addr_from_cert(TRUSTED_OS_FW_CONTENT_CERT_ID,
+ &dest);
+ if (ret == 0U) {
+ bl_mem_params->image_info.image_base = dest;
+ }
+
+ memcpy(&params->bl32_ep_info, &bl_mem_params->ep_info,
+ sizeof(entry_point_info_t));
+ break;
+ case BL33_IMAGE_ID:
+ memcpy(&params->bl33_ep_info, &bl_mem_params->ep_info,
+ sizeof(entry_point_info_t));
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+struct meminfo *bl2_plat_sec_mem_layout(void)
+{
+ return &bl2_tzram_layout;
+}
+
+static void bl2_populate_compatible_string(void *dt)
+{
+ uint32_t board_type;
+ uint32_t board_rev;
+ uint32_t reg;
+ int ret;
+
+ fdt_setprop_u32(dt, 0, "#address-cells", 2);
+ fdt_setprop_u32(dt, 0, "#size-cells", 2);
+
+ /* Populate compatible string */
+ rzg_get_board_type(&board_type, &board_rev);
+ switch (board_type) {
+ case BOARD_HIHOPE_RZ_G2M:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "hoperun,hihope-rzg2m");
+ break;
+ case BOARD_HIHOPE_RZ_G2H:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "hoperun,hihope-rzg2h");
+ break;
+ case BOARD_HIHOPE_RZ_G2N:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "hoperun,hihope-rzg2n");
+ break;
+ case BOARD_EK874_RZ_G2E:
+ ret = fdt_setprop_string(dt, 0, "compatible",
+ "si-linux,cat874");
+ break;
+ default:
+ NOTICE("BL2: Cannot set compatible string, board unsupported\n");
+ panic();
+ break;
+ }
+
+ if (ret < 0) {
+ NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret);
+ panic();
+ }
+
+ reg = mmio_read_32(RCAR_PRR);
+ switch (reg & PRR_PRODUCT_MASK) {
+ case PRR_PRODUCT_M3:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a774a1");
+ break;
+ case PRR_PRODUCT_H3:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a774e1");
+ break;
+ case PRR_PRODUCT_M3N:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a774b1");
+ break;
+ case PRR_PRODUCT_E3:
+ ret = fdt_appendprop_string(dt, 0, "compatible",
+ "renesas,r8a774c0");
+ break;
+ default:
+ NOTICE("BL2: Cannot set compatible string, SoC unsupported\n");
+ panic();
+ break;
+ }
+
+ if (ret < 0) {
+ NOTICE("BL2: Cannot set compatible string (ret=%i)\n", ret);
+ panic();
+ }
+}
+
+static int bl2_add_memory_node(uint64_t start, uint64_t size)
+{
+ char nodename[32] = { 0 };
+ uint64_t fdtsize;
+ int ret, node;
+
+ fdtsize = cpu_to_fdt64(size);
+
+ snprintf(nodename, sizeof(nodename), "memory@");
+ unsigned_num_print(start, 16, nodename + strlen(nodename));
+ node = ret = fdt_add_subnode(fdt, 0, nodename);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = fdt_setprop_string(fdt, node, "device_type", "memory");
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = fdt_setprop_u64(fdt, node, "reg", start);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return fdt_appendprop(fdt, node, "reg", &fdtsize, sizeof(fdtsize));
+}
+
+static void bl2_advertise_dram_entries(uint64_t dram_config[8])
+{
+ uint64_t start, size;
+ int ret, chan;
+
+ for (chan = 0; chan < MAX_DRAM_CHANNELS; chan++) {
+ start = dram_config[2 * chan];
+ size = dram_config[2 * chan + 1];
+ if (size == 0U) {
+ continue;
+ }
+
+ NOTICE("BL2: CH%d: %" PRIx64 " - %" PRIx64 ", %" PRId64 " %siB\n",
+ chan, start, start + size - 1U,
+ (size >> 30) ? : size >> 20,
+ (size >> 30) ? "G" : "M");
+ }
+
+ /*
+ * We add the DT nodes in reverse order here. The fdt_add_subnode()
+ * adds the DT node before the first existing DT node, so we have
+ * to add them in reverse order to get nodes sorted by address in
+ * the resulting DT.
+ */
+ for (chan = MAX_DRAM_CHANNELS - 1; chan >= 0; chan--) {
+ start = dram_config[2 * chan];
+ size = dram_config[2 * chan + 1];
+ if (size == 0U) {
+ continue;
+ }
+
+ /*
+ * Channel 0 is mapped in 32bit space and the first
+ * 128 MiB are reserved
+ */
+ if (chan == 0) {
+ /*
+ * Maximum DDR size in Channel 0 for 32 bit space is 2GB, Add DT node
+ * for remaining region in 64 bit address space
+ */
+ if (size > MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE) {
+ start = dram_config[chan] + MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE;
+ size -= MAX_DRAM_SIZE_CH0_32BIT_ADDR_SPACE;
+ ret = bl2_add_memory_node(start, size);
+ if (ret < 0) {
+ goto err;
+ }
+ }
+ start = 0x48000000U;
+ size -= 0x8000000U;
+ }
+
+ ret = bl2_add_memory_node(start, size);
+ if (ret < 0) {
+ goto err;
+ }
+ }
+
+ return;
+err:
+ NOTICE("BL2: Cannot add memory node to FDT (ret=%i)\n", ret);
+ panic();
+}
+
+static void bl2_advertise_dram_size(uint32_t product)
+{
+ uint64_t dram_config[8] = {
+ [0] = 0x400000000ULL,
+ [2] = 0x500000000ULL,
+ [4] = 0x600000000ULL,
+ [6] = 0x700000000ULL,
+ };
+
+ switch (product) {
+ case PRR_PRODUCT_M3:
+ /* 4GB(2GBx2 2ch split) */
+ dram_config[1] = 0x80000000ULL;
+ dram_config[5] = 0x80000000ULL;
+ break;
+ case PRR_PRODUCT_H3:
+#if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
+ /* 4GB(1GBx4) */
+ dram_config[1] = 0x40000000ULL;
+ dram_config[3] = 0x40000000ULL;
+ dram_config[5] = 0x40000000ULL;
+ dram_config[7] = 0x40000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 5) && \
+ (RCAR_DRAM_SPLIT == 2)
+ /* 4GB(2GBx2 2ch split) */
+ dram_config[1] = 0x80000000ULL;
+ dram_config[3] = 0x80000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1) && (RCAR_DRAM_CHANNEL == 15)
+ /* 8GB(2GBx4: default) */
+ dram_config[1] = 0x80000000ULL;
+ dram_config[3] = 0x80000000ULL;
+ dram_config[5] = 0x80000000ULL;
+ dram_config[7] = 0x80000000ULL;
+#endif /* RCAR_DRAM_LPDDR4_MEMCONF == 0 */
+ break;
+ case PRR_PRODUCT_M3N:
+ /* 4GB(4GBx1) */
+ dram_config[1] = 0x100000000ULL;
+ break;
+ case PRR_PRODUCT_E3:
+#if (RCAR_DRAM_DDR3L_MEMCONF == 0)
+ /* 1GB(512MBx2) */
+ dram_config[1] = 0x40000000ULL;
+#elif (RCAR_DRAM_DDR3L_MEMCONF == 1)
+ /* 2GB(512MBx4) */
+ dram_config[1] = 0x80000000ULL;
+#elif (RCAR_DRAM_DDR3L_MEMCONF == 2)
+ /* 4GB(1GBx4) */
+ dram_config[1] = 0x100000000ULL;
+#endif /* RCAR_DRAM_DDR3L_MEMCONF == 0 */
+ break;
+ default:
+ NOTICE("BL2: Detected invalid DRAM entries\n");
+ break;
+ }
+
+ bl2_advertise_dram_entries(dram_config);
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
+ u_register_t arg3, u_register_t arg4)
+{
+ uint32_t reg, midr, boot_dev, boot_cpu, type, rev;
+ uint32_t product, product_cut, major, minor;
+ int32_t ret;
+ const char *str;
+ const char *unknown = "unknown";
+ const char *cpu_ca57 = "CA57";
+ const char *cpu_ca53 = "CA53";
+ const char *product_g2e = "G2E";
+ const char *product_g2h = "G2H";
+ const char *product_g2m = "G2M";
+ const char *product_g2n = "G2N";
+ const char *boot_hyper80 = "HyperFlash(80MHz)";
+ const char *boot_qspi40 = "QSPI Flash(40MHz)";
+ const char *boot_qspi80 = "QSPI Flash(80MHz)";
+ const char *boot_emmc25x1 = "eMMC(25MHz x1)";
+ const char *boot_emmc50x8 = "eMMC(50MHz x8)";
+#if (RCAR_LSI == RZ_G2E)
+ uint32_t sscg;
+ const char *sscg_on = "PLL1 SSCG Clock select";
+ const char *sscg_off = "PLL1 nonSSCG Clock select";
+ const char *boot_hyper160 = "HyperFlash(150MHz)";
+#else
+ const char *boot_hyper160 = "HyperFlash(160MHz)";
+#endif /* RCAR_LSI == RZ_G2E */
+#if RZG_LCS_STATE_DETECTION_ENABLE
+ uint32_t lcs;
+ const char *lcs_secure = "SE";
+ const char *lcs_cm = "CM";
+ const char *lcs_dm = "DM";
+ const char *lcs_sd = "SD";
+ const char *lcs_fa = "FA";
+#endif /* RZG_LCS_STATE_DETECTION_ENABLE */
+
+#if (RCAR_LOSSY_ENABLE == 1)
+ int fcnlnode;
+#endif /* (RCAR_LOSSY_ENABLE == 1) */
+
+ bl2_init_generic_timer();
+
+ reg = mmio_read_32(RCAR_MODEMR);
+ boot_dev = reg & MODEMR_BOOT_DEV_MASK;
+ boot_cpu = reg & MODEMR_BOOT_CPU_MASK;
+
+ bl2_cpg_init();
+
+ if (boot_cpu == MODEMR_BOOT_CPU_CA57 ||
+ boot_cpu == MODEMR_BOOT_CPU_CA53) {
+ rzg_pfc_init();
+ rcar_console_boot_init();
+ }
+
+ plat_rcar_gic_driver_init();
+ plat_rcar_gic_init();
+ rcar_swdt_init();
+
+ /* FIQ interrupts are taken to EL3 */
+ write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
+
+ write_daifclr(DAIF_FIQ_BIT);
+
+ reg = read_midr();
+ midr = reg & (MIDR_PN_MASK << MIDR_PN_SHIFT);
+ switch (midr) {
+ case MIDR_CA57:
+ str = cpu_ca57;
+ break;
+ case MIDR_CA53:
+ str = cpu_ca53;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+
+ NOTICE("BL2: RZ/G2 Initial Program Loader(%s) Rev.%s\n", str,
+ version_of_renesas);
+
+ reg = mmio_read_32(RCAR_PRR);
+ product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK);
+ product = reg & PRR_PRODUCT_MASK;
+
+ switch (product) {
+ case PRR_PRODUCT_M3:
+ str = product_g2m;
+ break;
+ case PRR_PRODUCT_H3:
+ str = product_g2h;
+ break;
+ case PRR_PRODUCT_M3N:
+ str = product_g2n;
+ break;
+ case PRR_PRODUCT_E3:
+ str = product_g2e;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+
+ if ((product == PRR_PRODUCT_M3) &&
+ ((reg & RCAR_MAJOR_MASK) == PRR_PRODUCT_20)) {
+ if ((reg & PRR_CUT_MASK) == RCAR_M3_CUT_VER11) {
+ /* M3 Ver.1.1 or Ver.1.2 */
+ NOTICE("BL2: PRR is RZ/%s Ver.1.1 / Ver.1.2\n", str);
+ } else {
+ NOTICE("BL2: PRR is RZ/%s Ver.1.%d\n", str,
+ (reg & RCAR_MINOR_MASK) + RCAR_M3_MINOR_OFFSET);
+ }
+ } else {
+ major = (reg & RCAR_MAJOR_MASK) >> RCAR_MAJOR_SHIFT;
+ major = major + RCAR_MAJOR_OFFSET;
+ minor = reg & RCAR_MINOR_MASK;
+ NOTICE("BL2: PRR is RZ/%s Ver.%d.%d\n", str, major, minor);
+ }
+
+#if (RCAR_LSI == RZ_G2E)
+ if (product == PRR_PRODUCT_E3) {
+ reg = mmio_read_32(RCAR_MODEMR);
+ sscg = reg & RCAR_SSCG_MASK;
+ str = sscg == RCAR_SSCG_ENABLE ? sscg_on : sscg_off;
+ NOTICE("BL2: %s\n", str);
+ }
+#endif /* RCAR_LSI == RZ_G2E */
+
+ rzg_get_board_type(&type, &rev);
+
+ switch (type) {
+ case BOARD_HIHOPE_RZ_G2M:
+ case BOARD_HIHOPE_RZ_G2H:
+ case BOARD_HIHOPE_RZ_G2N:
+ case BOARD_EK874_RZ_G2E:
+ break;
+ default:
+ type = BOARD_UNKNOWN;
+ break;
+ }
+
+ if (type == BOARD_UNKNOWN || rev == BOARD_REV_UNKNOWN) {
+ NOTICE("BL2: Board is %s Rev.---\n", GET_BOARD_NAME(type));
+ } else {
+ NOTICE("BL2: Board is %s Rev.%d.%d\n",
+ GET_BOARD_NAME(type),
+ GET_BOARD_MAJOR(rev), GET_BOARD_MINOR(rev));
+ }
+
+#if RCAR_LSI != RCAR_AUTO
+ if (product != TARGET_PRODUCT) {
+ ERROR("BL2: IPL was been built for the %s.\n", TARGET_NAME);
+ ERROR("BL2: Please write the correct IPL to flash memory.\n");
+ panic();
+ }
+#endif /* RCAR_LSI != RCAR_AUTO */
+ rcar_avs_init();
+ rcar_avs_setting();
+
+ switch (boot_dev) {
+ case MODEMR_BOOT_DEV_HYPERFLASH160:
+ str = boot_hyper160;
+ break;
+ case MODEMR_BOOT_DEV_HYPERFLASH80:
+ str = boot_hyper80;
+ break;
+ case MODEMR_BOOT_DEV_QSPI_FLASH40:
+ str = boot_qspi40;
+ break;
+ case MODEMR_BOOT_DEV_QSPI_FLASH80:
+ str = boot_qspi80;
+ break;
+ case MODEMR_BOOT_DEV_EMMC_25X1:
+ str = boot_emmc25x1;
+ break;
+ case MODEMR_BOOT_DEV_EMMC_50X8:
+ str = boot_emmc50x8;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+ NOTICE("BL2: Boot device is %s\n", str);
+
+ rcar_avs_setting();
+
+#if RZG_LCS_STATE_DETECTION_ENABLE
+ reg = rcar_rom_get_lcs(&lcs);
+ if (reg != 0U) {
+ str = unknown;
+ goto lcm_state;
+ }
+
+ switch (lcs) {
+ case LCS_CM:
+ str = lcs_cm;
+ break;
+ case LCS_DM:
+ str = lcs_dm;
+ break;
+ case LCS_SD:
+ str = lcs_sd;
+ break;
+ case LCS_SE:
+ str = lcs_secure;
+ break;
+ case LCS_FA:
+ str = lcs_fa;
+ break;
+ default:
+ str = unknown;
+ break;
+ }
+
+lcm_state:
+ NOTICE("BL2: LCM state is %s\n", str);
+#endif /* RZG_LCS_STATE_DETECTION_ENABLE */
+
+ rcar_avs_end();
+ is_ddr_backup_mode();
+
+ bl2_tzram_layout.total_base = BL31_BASE;
+ bl2_tzram_layout.total_size = BL31_LIMIT - BL31_BASE;
+
+ if (boot_cpu == MODEMR_BOOT_CPU_CA57 ||
+ boot_cpu == MODEMR_BOOT_CPU_CA53) {
+ ret = rcar_dram_init();
+ if (ret != 0) {
+ NOTICE("BL2: Failed to DRAM initialize (%d).\n", ret);
+ panic();
+ }
+ rzg_qos_init();
+ }
+
+ /* Set up FDT */
+ ret = fdt_create_empty_tree(fdt, sizeof(fdt_blob));
+ if (ret != 0) {
+ NOTICE("BL2: Cannot allocate FDT for U-Boot (ret=%i)\n", ret);
+ panic();
+ }
+
+ /* Add platform compatible string */
+ bl2_populate_compatible_string(fdt);
+
+ /* Print DRAM layout */
+ bl2_advertise_dram_size(product);
+
+ if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
+ boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) {
+ if (rcar_emmc_init() != EMMC_SUCCESS) {
+ NOTICE("BL2: Failed to eMMC driver initialize.\n");
+ panic();
+ }
+ rcar_emmc_memcard_power(EMMC_POWER_ON);
+ if (rcar_emmc_mount() != EMMC_SUCCESS) {
+ NOTICE("BL2: Failed to eMMC mount operation.\n");
+ panic();
+ }
+ } else {
+ rcar_rpc_init();
+ rcar_dma_init();
+ }
+
+ reg = mmio_read_32(RST_WDTRSTCR);
+ reg &= ~WDTRSTCR_RWDT_RSTMSK;
+ reg |= WDTRSTCR_PASSWORD;
+ mmio_write_32(RST_WDTRSTCR, reg);
+
+ mmio_write_32(CPG_CPGWPR, CPGWPR_PASSWORD);
+ mmio_write_32(CPG_CPGWPCR, CPGWPCR_PASSWORD);
+
+ reg = mmio_read_32(RCAR_PRR);
+ if ((reg & RCAR_CPU_MASK_CA57) == RCAR_CPU_HAVE_CA57) {
+ mmio_write_32(CPG_CA57DBGRCR,
+ DBGCPUPREN | mmio_read_32(CPG_CA57DBGRCR));
+ }
+
+ if ((reg & RCAR_CPU_MASK_CA53) == RCAR_CPU_HAVE_CA53) {
+ mmio_write_32(CPG_CA53DBGRCR,
+ DBGCPUPREN | mmio_read_32(CPG_CA53DBGRCR));
+ }
+
+ if (product_cut == PRR_PRODUCT_H3_CUT10) {
+ reg = mmio_read_32(CPG_PLL2CR);
+ reg &= ~((uint32_t)1 << 5);
+ mmio_write_32(CPG_PLL2CR, reg);
+
+ reg = mmio_read_32(CPG_PLL4CR);
+ reg &= ~((uint32_t)1 << 5);
+ mmio_write_32(CPG_PLL4CR, reg);
+
+ reg = mmio_read_32(CPG_PLL0CR);
+ reg &= ~((uint32_t)1 << 12);
+ mmio_write_32(CPG_PLL0CR, reg);
+ }
+#if (RCAR_LOSSY_ENABLE == 1)
+ NOTICE("BL2: Lossy Decomp areas\n");
+
+ fcnlnode = fdt_add_subnode(fdt, 0, "reserved-memory");
+ if (fcnlnode < 0) {
+ NOTICE("BL2: Cannot create reserved mem node (ret=%i)\n",
+ fcnlnode);
+ panic();
+ }
+
+ bl2_lossy_setting(0, LOSSY_ST_ADDR0, LOSSY_END_ADDR0,
+ LOSSY_FMT0, LOSSY_ENA_DIS0, fcnlnode);
+ bl2_lossy_setting(1, LOSSY_ST_ADDR1, LOSSY_END_ADDR1,
+ LOSSY_FMT1, LOSSY_ENA_DIS1, fcnlnode);
+ bl2_lossy_setting(2, LOSSY_ST_ADDR2, LOSSY_END_ADDR2,
+ LOSSY_FMT2, LOSSY_ENA_DIS2, fcnlnode);
+#endif /* RCAR_LOSSY_ENABLE */
+
+ fdt_pack(fdt);
+ NOTICE("BL2: FDT at %p\n", fdt);
+
+ if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
+ boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) {
+ rcar_io_emmc_setup();
+ } else {
+ rcar_io_setup();
+ }
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+#if RCAR_BL2_DCACHE == 1
+ NOTICE("BL2: D-Cache enable\n");
+ rcar_configure_mmu_el3(BL2_BASE,
+ BL2_END - BL2_BASE,
+ BL2_RO_BASE, BL2_RO_LIMIT
+#if USE_COHERENT_MEM
+ , BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT
+#endif /* USE_COHERENT_MEM */
+ );
+#endif /* RCAR_BL2_DCACHE == 1 */
+}
+
+void bl2_platform_setup(void)
+{
+ /*
+ * Place holder for performing any platform initialization specific
+ * to BL2.
+ */
+}
+
+static void bl2_init_generic_timer(void)
+{
+#if RCAR_LSI == RZ_G2E
+ uint32_t reg_cntfid = EXTAL_EBISU;
+#else
+ uint32_t reg_cntfid;
+ uint32_t modemr;
+ uint32_t modemr_pll;
+ uint32_t pll_table[] = {
+ EXTAL_MD14_MD13_TYPE_0, /* MD14/MD13 : 0b00 */
+ EXTAL_MD14_MD13_TYPE_1, /* MD14/MD13 : 0b01 */
+ EXTAL_MD14_MD13_TYPE_2, /* MD14/MD13 : 0b10 */
+ EXTAL_MD14_MD13_TYPE_3 /* MD14/MD13 : 0b11 */
+ };
+
+ modemr = mmio_read_32(RCAR_MODEMR);
+ modemr_pll = (modemr & MODEMR_BOOT_PLL_MASK);
+
+ /* Set frequency data in CNTFID0 */
+ reg_cntfid = pll_table[modemr_pll >> MODEMR_BOOT_PLL_SHIFT];
+#endif /* RCAR_LSI == RZ_G2E */
+
+ /* Update memory mapped and register based frequency */
+ write_cntfrq_el0((u_register_t)reg_cntfid);
+ mmio_write_32(ARM_SYS_CNTCTL_BASE + (uintptr_t)CNTFID_OFF, reg_cntfid);
+ /* Enable counter */
+ mmio_setbits_32(RCAR_CNTC_BASE + (uintptr_t)CNTCR_OFF,
+ (uint32_t)CNTCR_EN);
+}
diff --git a/plat/renesas/rzg/platform.mk b/plat/renesas/rzg/platform.mk
new file mode 100644
index 0000000..f37d7d0
--- /dev/null
+++ b/plat/renesas/rzg/platform.mk
@@ -0,0 +1,274 @@
+#
+# Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/renesas/common/common.mk
+
+ifndef LSI
+ $(error "Error: Unknown LSI. Please use LSI=<LSI name> to specify the LSI")
+else
+ ifeq (${LSI},AUTO)
+ RCAR_LSI:=${RCAR_AUTO}
+ else ifeq (${LSI},G2M)
+ RCAR_LSI:=${RZ_G2M}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else ifeq (${LSI_CUT},11)
+ RCAR_LSI_CUT:=1
+ else ifeq (${LSI_CUT},13)
+ RCAR_LSI_CUT:=3
+ else ifeq (${LSI_CUT},30)
+ RCAR_LSI_CUT:=20
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},G2H)
+ RCAR_LSI:=${RZ_G2H}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},30)
+ RCAR_LSI_CUT:=20
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},G2N)
+ RCAR_LSI:=${RZ_G2N}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else ifeq (${LSI_CUT},11)
+ RCAR_LSI_CUT:=1
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else ifeq (${LSI},G2E)
+ RCAR_LSI:=${RZ_G2E}
+ ifndef LSI_CUT
+ # enable compatible function.
+ RCAR_LSI_CUT_COMPAT := 1
+ $(eval $(call add_define,RCAR_LSI_CUT_COMPAT))
+ else
+ # disable compatible function.
+ ifeq (${LSI_CUT},10)
+ RCAR_LSI_CUT:=0
+ else ifeq (${LSI_CUT},11)
+ RCAR_LSI_CUT:=1
+ else
+ $(error "Error: ${LSI_CUT} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI_CUT))
+ endif
+ else
+ $(error "Error: ${LSI} is not supported.")
+ endif
+ $(eval $(call add_define,RCAR_LSI))
+endif
+
+# Process RZG_LCS_STATE_DETECTION_ENABLE flag
+# Enable to get LCS state information
+ifndef RZG_LCS_STATE_DETECTION_ENABLE
+RZG_LCS_STATE_DETECTION_ENABLE := 0
+endif
+$(eval $(call add_define,RZG_LCS_STATE_DETECTION_ENABLE))
+
+# Process RCAR_SECURE_BOOT flag
+ifndef RCAR_SECURE_BOOT
+RCAR_SECURE_BOOT := 0
+endif
+$(eval $(call add_define,RCAR_SECURE_BOOT))
+
+# LCS state of RZ/G2 Chip is all CM.
+# However certain chips(RZ/G2M and RZ/G2E) have incorrect factory Fuse settings
+# which results in getting incorrect LCS states
+# if need to enable RCAR_SECURE_BOOT, make sure the chip has proper factory Fuse settings.
+ifeq (${RCAR_SECURE_BOOT},1)
+ ifeq (${RZG_LCS_STATE_DETECTION_ENABLE},0)
+ $(error "Error: Please check the chip has proper factory Fuse settings and set RZG_LCS_STATE_DETECTION_ENABLE to enable.")
+ endif
+endif
+
+# lock RPC HYPERFLASH access by default
+# unlock to repogram the ATF firmware from u-boot
+ifndef RCAR_RPC_HYPERFLASH_LOCKED
+RCAR_RPC_HYPERFLASH_LOCKED := 1
+endif
+$(eval $(call add_define,RCAR_RPC_HYPERFLASH_LOCKED))
+
+# Process RCAR_QOS_TYPE flag
+ifndef RCAR_QOS_TYPE
+RCAR_QOS_TYPE := 0
+endif
+$(eval $(call add_define,RCAR_QOS_TYPE))
+
+# Process RCAR_DRAM_SPLIT flag
+ifndef RCAR_DRAM_SPLIT
+RCAR_DRAM_SPLIT := 0
+endif
+$(eval $(call add_define,RCAR_DRAM_SPLIT))
+
+# Process RCAR_BL33_EXECUTION_EL flag
+ifndef RCAR_BL33_EXECUTION_EL
+RCAR_BL33_EXECUTION_EL := 0
+endif
+$(eval $(call add_define,RCAR_BL33_EXECUTION_EL))
+
+# Process RCAR_AVS_SETTING_ENABLE flag
+ifndef AVS_SETTING_ENABLE
+AVS_SETTING_ENABLE := 0
+endif
+$(eval $(call add_define,AVS_SETTING_ENABLE))
+
+# Process RCAR_LOSSY_ENABLE flag
+ifndef RCAR_LOSSY_ENABLE
+RCAR_LOSSY_ENABLE := 0
+endif
+$(eval $(call add_define,RCAR_LOSSY_ENABLE))
+
+# Process LIFEC_DBSC_PROTECT_ENABLE flag
+ifndef LIFEC_DBSC_PROTECT_ENABLE
+LIFEC_DBSC_PROTECT_ENABLE := 1
+endif
+$(eval $(call add_define,LIFEC_DBSC_PROTECT_ENABLE))
+
+# Process RCAR_GEN3_ULCB flag
+ifndef RCAR_GEN3_ULCB
+RCAR_GEN3_ULCB := 0
+endif
+
+# Process RCAR_REF_INT flag
+ifndef RCAR_REF_INT
+RCAR_REF_INT :=0
+endif
+$(eval $(call add_define,RCAR_REF_INT))
+
+# Process RCAR_REWT_TRAINING flag
+ifndef RCAR_REWT_TRAINING
+RCAR_REWT_TRAINING := 1
+endif
+$(eval $(call add_define,RCAR_REWT_TRAINING))
+
+# Process RCAR_SYSTEM_SUSPEND flag
+ifndef RCAR_SYSTEM_SUSPEND
+RCAR_SYSTEM_SUSPEND := 0
+endif
+$(eval $(call add_define,RCAR_SYSTEM_SUSPEND))
+
+# Process RCAR_DRAM_LPDDR4_MEMCONF flag
+ifndef RCAR_DRAM_LPDDR4_MEMCONF
+RCAR_DRAM_LPDDR4_MEMCONF :=1
+endif
+$(eval $(call add_define,RCAR_DRAM_LPDDR4_MEMCONF))
+
+# Process RCAR_DRAM_DDR3L_MEMCONF flag
+ifndef RCAR_DRAM_DDR3L_MEMCONF
+RCAR_DRAM_DDR3L_MEMCONF :=1
+endif
+$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMCONF))
+
+# Process RCAR_DRAM_DDR3L_MEMDUAL flag
+ifndef RCAR_DRAM_DDR3L_MEMDUAL
+RCAR_DRAM_DDR3L_MEMDUAL :=1
+endif
+$(eval $(call add_define,RCAR_DRAM_DDR3L_MEMDUAL))
+
+# Process RCAR_BL33_ARG0 flag
+ifdef RCAR_BL33_ARG0
+$(eval $(call add_define,RCAR_BL33_ARG0))
+endif
+
+#Process RCAR_BL2_DCACHE flag
+ifndef RCAR_BL2_DCACHE
+RCAR_BL2_DCACHE := 0
+endif
+$(eval $(call add_define,RCAR_BL2_DCACHE))
+
+# Process RCAR_DRAM_CHANNEL flag
+ifndef RCAR_DRAM_CHANNEL
+RCAR_DRAM_CHANNEL :=15
+endif
+$(eval $(call add_define,RCAR_DRAM_CHANNEL))
+
+#Process RCAR_SYSTEM_RESET_KEEPON_DDR flag
+ifndef RCAR_SYSTEM_RESET_KEEPON_DDR
+RCAR_SYSTEM_RESET_KEEPON_DDR := 0
+endif
+$(eval $(call add_define,RCAR_SYSTEM_RESET_KEEPON_DDR))
+
+RZG_SOC :=1
+$(eval $(call add_define,RZG_SOC))
+
+include drivers/renesas/common/ddr/ddr.mk
+include drivers/renesas/rzg/qos/qos.mk
+include drivers/renesas/rzg/pfc/pfc.mk
+include lib/libfdt/libfdt.mk
+
+PLAT_INCLUDES += -Idrivers/renesas/common/ddr \
+ -Idrivers/renesas/rzg/qos \
+ -Idrivers/renesas/rzg/board \
+ -Idrivers/renesas/common \
+ -Idrivers/renesas/common/iic_dvfs \
+ -Idrivers/renesas/common/avs \
+ -Idrivers/renesas/common/delay \
+ -Idrivers/renesas/common/rom \
+ -Idrivers/renesas/common/scif \
+ -Idrivers/renesas/common/emmc \
+ -Idrivers/renesas/common/pwrc \
+ -Idrivers/renesas/common/io
+
+BL2_SOURCES += plat/renesas/rzg/bl2_plat_setup.c \
+ drivers/renesas/rzg/board/board.c
+
+# build the layout images for the bootrom and the necessary srecords
+rzg: rzg_layout_create rzg_srecord
+distclean realclean clean: clean_layout_tool clean_srecord
+
+# layout images
+LAYOUT_TOOLPATH ?= tools/renesas/rzg_layout_create
+
+clean_layout_tool:
+ @echo "clean layout tool"
+ ${Q}${MAKE} -C ${LAYOUT_TOOLPATH} clean
+
+.PHONY: rzg_layout_create
+rzg_layout_create:
+ @echo "generating layout srecs"
+ ${Q}${MAKE} CPPFLAGS="-D=AARCH64" --no-print-directory -C ${LAYOUT_TOOLPATH}
+
+# srecords
+SREC_PATH = ${BUILD_PLAT}
+BL2_ELF_SRC = ${SREC_PATH}/bl2/bl2.elf
+BL31_ELF_SRC = ${SREC_PATH}/bl31/bl31.elf
+
+clean_srecord:
+ @echo "clean bl2 and bl31 srecs"
+ rm -f ${SREC_PATH}/bl2.srec ${SREC_PATH}/bl31.srec
+
+.PHONY: rzg_srecord
+rzg_srecord: $(BL2_ELF_SRC) $(BL31_ELF_SRC)
+ @echo "generating srec: ${SREC_PATH}/bl2.srec"
+ $(Q)$(OC) -O srec --srec-forceS3 ${BL2_ELF_SRC} ${SREC_PATH}/bl2.srec
+ @echo "generating srec: ${SREC_PATH}/bl31.srec"
+ $(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec
diff --git a/plat/rockchip/common/aarch32/plat_helpers.S b/plat/rockchip/common/aarch32/plat_helpers.S
new file mode 100644
index 0000000..475c297
--- /dev/null
+++ b/plat/rockchip/common/aarch32/plat_helpers.S
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a12.h>
+#include <plat_private.h>
+#include <plat_pmu_macros.S>
+
+ .globl cpuson_entry_point
+ .globl cpuson_flags
+ .globl platform_cpu_warmboot
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_report_exception
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+ .globl plat_panic_handler
+
+ /*
+ * void plat_reset_handler(void);
+ *
+ * Determine the SOC type and call the appropriate reset
+ * handler.
+ *
+ */
+func plat_reset_handler
+ bx lr
+endfunc plat_reset_handler
+
+func plat_my_core_pos
+ ldcopr r0, MPIDR
+ and r1, r0, #MPIDR_CPU_MASK
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+ and r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
+#else
+ and r0, r0, #MPIDR_CLUSTER_MASK
+#endif
+ add r0, r1, r0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
+ bx lr
+endfunc plat_my_core_pos
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* rk3288 does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+ ldcopr r0, MPIDR
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+ ldr r1, =(PLAT_RK_MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+#else
+ ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+#endif
+ and r0, r1
+ cmp r0, #PLAT_RK_PRIMARY_CPU
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+endfunc plat_is_my_cpu_primary
+
+ /* --------------------------------------------------------------------
+ * void plat_panic_handler(void)
+ * Call system reset function on panic. Set up an emergency stack so we
+ * can run C functions (it only needs to last for a few calls until we
+ * reboot anyway).
+ * --------------------------------------------------------------------
+ */
+func plat_panic_handler
+ bl plat_set_my_stack
+ b rockchip_soc_soft_reset
+endfunc plat_panic_handler
+
+ /* --------------------------------------------------------------------
+ * void platform_cpu_warmboot (void);
+ * cpus online or resume entrypoint
+ * --------------------------------------------------------------------
+ */
+func platform_cpu_warmboot _align=16
+ push { r4 - r7, lr }
+ ldcopr r0, MPIDR
+ and r5, r0, #MPIDR_CPU_MASK
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+ and r6, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
+#else
+ and r6, r0, #MPIDR_CLUSTER_MASK
+#endif
+ mov r0, r6
+
+ func_rockchip_clst_warmboot
+ /* --------------------------------------------------------------------
+ * big cluster id is 1
+ * big cores id is from 0-3, little cores id 4-7
+ * --------------------------------------------------------------------
+ */
+ add r7, r5, r6, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
+ /* --------------------------------------------------------------------
+ * get per cpuup flag
+ * --------------------------------------------------------------------
+ */
+ ldr r4, =cpuson_flags
+ add r4, r4, r7, lsl #2
+ ldr r1, [r4]
+ /* --------------------------------------------------------------------
+ * check cpuon reason
+ * --------------------------------------------------------------------
+ */
+ cmp r1, #PMU_CPU_AUTO_PWRDN
+ beq boot_entry
+ cmp r1, #PMU_CPU_HOTPLUG
+ beq boot_entry
+ /* --------------------------------------------------------------------
+ * If the boot core cpuson_flags or cpuson_entry_point is not
+ * expection. force the core into wfe.
+ * --------------------------------------------------------------------
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+boot_entry:
+ mov r1, #0
+ str r1, [r4]
+ /* --------------------------------------------------------------------
+ * get per cpuup boot addr
+ * --------------------------------------------------------------------
+ */
+ ldr r5, =cpuson_entry_point
+ ldr r2, [r5, r7, lsl #2] /* ehem. #3 */
+ pop { r4 - r7, lr }
+
+ bx r2
+endfunc platform_cpu_warmboot
+
+ /* --------------------------------------------------------------------
+ * Per-CPU Secure entry point - resume or power up
+ * --------------------------------------------------------------------
+ */
+ .section tzfw_coherent_mem, "a"
+ .align 3
+cpuson_entry_point:
+ .rept PLATFORM_CORE_COUNT
+ .quad 0
+ .endr
+cpuson_flags:
+ .rept PLATFORM_CORE_COUNT
+ .word 0
+ .endr
+rockchip_clst_warmboot_data
diff --git a/plat/rockchip/common/aarch32/platform_common.c b/plat/rockchip/common/aarch32/platform_common.c
new file mode 100644
index 0000000..9030951
--- /dev/null
+++ b/plat/rockchip/common/aarch32/platform_common.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include <plat_private.h>
+
+void plat_configure_mmu_svc_mon(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long ro_start,
+ unsigned long ro_limit,
+ unsigned long coh_start,
+ unsigned long coh_limit)
+{
+ mmap_add_region(total_base, total_base, total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+ mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+ MT_MEMORY | MT_RO | MT_SECURE);
+ mmap_add_region(coh_start, coh_start, coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ mmap_add(plat_rk_mmap);
+ rockchip_plat_mmu_svc_mon();
+ init_xlat_tables();
+ enable_mmu_svc_mon(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+/*
+ * generic pm code does cci handling, but rockchip arm32 platforms
+ * have ever only 1 cluster, so nothing to do.
+ */
+void plat_cci_init(void)
+{
+}
+
+void plat_cci_enable(void)
+{
+}
+
+void plat_cci_disable(void)
+{
+}
diff --git a/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S b/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S
new file mode 100644
index 0000000..a05ae54
--- /dev/null
+++ b/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl pmu_cpuson_entrypoint
+ .macro pmusram_entry_func _name
+ .section .pmusram.entry, "ax"
+ .type \_name, %function
+ .cfi_startproc
+ \_name:
+ .endm
+
+pmusram_entry_func pmu_cpuson_entrypoint
+
+#if PSRAM_CHECK_WAKEUP_CPU
+check_wake_cpus:
+ ldcopr r0, MPIDR
+ and r1, r0, #MPIDR_CPU_MASK
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+ and r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
+#else
+ and r0, r0, #MPIDR_CLUSTER_MASK
+#endif
+ orr r0, r0, r1
+
+ /* primary_cpu */
+ ldr r1, boot_mpidr
+ cmp r0, r1
+ beq sys_wakeup
+
+ /*
+ * If the core is not the primary cpu,
+ * force the core into wfe.
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+sys_wakeup:
+#endif
+
+#if PSRAM_DO_DDR_RESUME
+ddr_resume:
+ ldr r2, =__bl32_sram_stack_end
+ mov sp, r2
+ bl dmc_resume
+#endif
+ bl sram_restore
+sys_resume:
+ bl sp_min_warm_entrypoint
+endfunc pmu_cpuson_entrypoint
diff --git a/plat/rockchip/common/aarch64/plat_helpers.S b/plat/rockchip/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..4af052b
--- /dev/null
+++ b/plat/rockchip/common/aarch64/plat_helpers.S
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a53.h>
+#include <cortex_a72.h>
+#include <plat_private.h>
+#include <plat_pmu_macros.S>
+
+ .globl cpuson_entry_point
+ .globl cpuson_flags
+ .globl platform_cpu_warmboot
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_report_exception
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+ .globl plat_panic_handler
+
+ /*
+ * void plat_reset_handler(void);
+ *
+ * Determine the SOC type and call the appropriate reset
+ * handler.
+ *
+ */
+func plat_reset_handler
+ mrs x0, midr_el1
+ ubfx x0, x0, MIDR_PN_SHIFT, #12
+ cmp w0, #((CORTEX_A72_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+ b.eq handler_a72
+ b handler_end
+handler_a72:
+ /*
+ * This handler does the following:
+ * Set the L2 Data RAM latency for Cortex-A72.
+ * Set the L2 Tag RAM latency to for Cortex-A72.
+ */
+ mov x0, #((5 << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
+ (0x1 << 5))
+ msr CORTEX_A72_L2CTLR_EL1, x0
+ isb
+handler_end:
+ ret
+endfunc plat_reset_handler
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
+ ret
+endfunc plat_my_core_pos
+
+ /* --------------------------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * --------------------------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ /* rk3368 does not do cold boot for secondary CPU */
+cb_panic:
+ b cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #PLAT_RK_PRIMARY_CPU
+ cset x0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* --------------------------------------------------------------------
+ * void plat_panic_handler(void)
+ * Call system reset function on panic. Set up an emergency stack so we
+ * can run C functions (it only needs to last for a few calls until we
+ * reboot anyway).
+ * --------------------------------------------------------------------
+ */
+func plat_panic_handler
+ msr spsel, #0
+ bl plat_set_my_stack
+ b rockchip_soc_soft_reset
+endfunc plat_panic_handler
+
+ /* --------------------------------------------------------------------
+ * void platform_cpu_warmboot (void);
+ * cpus online or resume enterpoint
+ * --------------------------------------------------------------------
+ */
+func platform_cpu_warmboot _align=16
+ mrs x0, MPIDR_EL1
+ and x19, x0, #MPIDR_CPU_MASK
+ and x20, x0, #MPIDR_CLUSTER_MASK
+ mov x0, x20
+ func_rockchip_clst_warmboot
+ /* --------------------------------------------------------------------
+ * big cluster id is 1
+ * big cores id is from 0-3, little cores id 4-7
+ * --------------------------------------------------------------------
+ */
+ add x21, x19, x20, lsr #PLAT_RK_CLST_TO_CPUID_SHIFT
+ /* --------------------------------------------------------------------
+ * get per cpuup flag
+ * --------------------------------------------------------------------
+ */
+ adr x4, cpuson_flags
+ add x4, x4, x21, lsl #2
+ ldr w1, [x4]
+ /* --------------------------------------------------------------------
+ * check cpuon reason
+ * --------------------------------------------------------------------
+ */
+ cmp w1, PMU_CPU_AUTO_PWRDN
+ b.eq boot_entry
+ cmp w1, PMU_CPU_HOTPLUG
+ b.eq boot_entry
+ /* --------------------------------------------------------------------
+ * If the boot core cpuson_flags or cpuson_entry_point is not
+ * expection. force the core into wfe.
+ * --------------------------------------------------------------------
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+boot_entry:
+ str wzr, [x4]
+ /* --------------------------------------------------------------------
+ * get per cpuup boot addr
+ * --------------------------------------------------------------------
+ */
+ adr x5, cpuson_entry_point
+ ldr x2, [x5, x21, lsl #3]
+ br x2
+endfunc platform_cpu_warmboot
+
+ /* --------------------------------------------------------------------
+ * Per-CPU Secure entry point - resume or power up
+ * --------------------------------------------------------------------
+ */
+ .section tzfw_coherent_mem, "a"
+ .align 3
+cpuson_entry_point:
+ .rept PLATFORM_CORE_COUNT
+ .quad 0
+ .endr
+cpuson_flags:
+ .rept PLATFORM_CORE_COUNT
+ .word 0
+ .endr
+rockchip_clst_warmboot_data
diff --git a/plat/rockchip/common/aarch64/platform_common.c b/plat/rockchip/common/aarch64/platform_common.c
new file mode 100644
index 0000000..81e8520
--- /dev/null
+++ b/plat/rockchip/common/aarch64/platform_common.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/cci.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include <plat_private.h>
+
+#ifdef PLAT_RK_CCI_BASE
+static const int cci_map[] = {
+ PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX,
+ PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX
+};
+#endif
+
+/******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+#define DEFINE_CONFIGURE_MMU_EL(_el) \
+ void plat_configure_mmu_el ## _el(unsigned long total_base, \
+ unsigned long total_size, \
+ unsigned long ro_start, \
+ unsigned long ro_limit, \
+ unsigned long coh_start, \
+ unsigned long coh_limit) \
+ { \
+ mmap_add_region(total_base, total_base, \
+ total_size, \
+ MT_MEMORY | MT_RW | MT_SECURE); \
+ mmap_add_region(ro_start, ro_start, \
+ ro_limit - ro_start, \
+ MT_MEMORY | MT_RO | MT_SECURE); \
+ mmap_add_region(coh_start, coh_start, \
+ coh_limit - coh_start, \
+ MT_DEVICE | MT_RW | MT_SECURE); \
+ mmap_add(plat_rk_mmap); \
+ rockchip_plat_mmu_el##_el(); \
+ init_xlat_tables(); \
+ \
+ enable_mmu_el ## _el(0); \
+ }
+
+/* Define EL3 variants of the function initialising the MMU */
+DEFINE_CONFIGURE_MMU_EL(3)
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+void plat_cci_init(void)
+{
+#ifdef PLAT_RK_CCI_BASE
+ /* Initialize CCI driver */
+ cci_init(PLAT_RK_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
+#endif
+}
+
+void plat_cci_enable(void)
+{
+ /*
+ * Enable CCI coherency for this cluster.
+ * No need for locks as no other cpu is active at the moment.
+ */
+#ifdef PLAT_RK_CCI_BASE
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+#endif
+}
+
+void plat_cci_disable(void)
+{
+#ifdef PLAT_RK_CCI_BASE
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
+#endif
+}
diff --git a/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S b/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S
new file mode 100644
index 0000000..d91ee0e
--- /dev/null
+++ b/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl pmu_cpuson_entrypoint
+ .macro pmusram_entry_func _name
+ .section .pmusram.entry, "ax"
+ .type \_name, %function
+ .cfi_startproc
+ \_name:
+ .endm
+
+pmusram_entry_func pmu_cpuson_entrypoint
+
+#if PSRAM_CHECK_WAKEUP_CPU
+check_wake_cpus:
+ mrs x0, MPIDR_EL1
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ orr x0, x0, x1
+
+ /* primary_cpu */
+ ldr w1, boot_mpidr
+ cmp w0, w1
+ b.eq sys_wakeup
+
+ /*
+ * If the core is not the primary cpu,
+ * force the core into wfe.
+ */
+wfe_loop:
+ wfe
+ b wfe_loop
+sys_wakeup:
+#endif
+
+#if PSRAM_DO_DDR_RESUME
+ddr_resume:
+ ldr x2, =__bl31_sram_stack_end
+ mov sp, x2
+ bl dmc_resume
+#endif
+ bl sram_restore
+sys_resume:
+ bl bl31_warm_entrypoint
+endfunc pmu_cpuson_entrypoint
diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c
new file mode 100644
index 0000000..98ef415
--- /dev/null
+++ b/plat/rockchip/common/bl31_plat_setup.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <plat_private.h>
+#include <plat/common/platform.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
+ assert(next_image_info->h.type == PARAM_EP);
+
+ /* None of the images on this platform can have 0x0 as the entrypoint */
+ if (next_image_info->pc)
+ return next_image_info;
+ else
+ return NULL;
+}
+
+#pragma weak params_early_setup
+void params_early_setup(u_register_t plat_param_from_bl2)
+{
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ * BL2 has flushed this information to memory, so we are guaranteed to pick up
+ * good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ params_early_setup(arg1);
+
+ if (rockchip_get_uart_base() != 0)
+ console_16550_register(rockchip_get_uart_base(),
+ rockchip_get_uart_clock(),
+ rockchip_get_uart_baudrate(), &console);
+
+ VERBOSE("bl31_setup\n");
+
+ bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+ generic_delay_timer_init();
+ plat_rockchip_soc_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_rockchip_gic_driver_init();
+ plat_rockchip_gic_init();
+ plat_rockchip_pmu_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+ plat_cci_init();
+ plat_cci_enable();
+ plat_configure_mmu_el3(BL_CODE_BASE,
+ BL_COHERENT_RAM_END - BL_CODE_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
diff --git a/plat/rockchip/common/drivers/parameter/ddr_parameter.c b/plat/rockchip/common/drivers/parameter/ddr_parameter.c
new file mode 100644
index 0000000..e89fe1e
--- /dev/null
+++ b/plat/rockchip/common/drivers/parameter/ddr_parameter.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <plat_private.h>
+#include <soc.h>
+
+#include "ddr_parameter.h"
+
+/*
+ * The miniloader delivers the parameters about ddr usage info from address
+ * 0x02000000 and the data format is defined as below figure. It tells ATF the
+ * areas of ddr that are used by platform, we treat them as non-secure regions
+ * by default. Then we should parse the other part regions and configurate them
+ * as secure regions to avoid illegal access.
+ *
+ * [ddr usage info data format]
+ * 0x02000000
+ * -----------------------------------------------------------------------------
+ * | <name> | <size> | <description> |
+ * -----------------------------------------------------------------------------
+ * | count | 4byte | the array numbers of the |
+ * | | | 'addr_array' and 'size_array' |
+ * -----------------------------------------------------------------------------
+ * | reserved | 4byte | just for 'addr_array' 8byte aligned |
+ * -----------------------------------------------------------------------------
+ * | addr_array[count] | per 8byte | memory region base address |
+ * -----------------------------------------------------------------------------
+ * | size_array[count] | per 8byte | memory region size (byte) |
+ * -----------------------------------------------------------------------------
+ */
+
+/*
+ * function: read parameters info(ns-regions) and try to parse s-regions info
+ *
+ * @addr: head address to the ddr usage struct from miniloader
+ * @max_mb: the max ddr capacity(MB) that the platform support
+ */
+struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb)
+{
+ uint64_t base, top;
+ uint32_t i, addr_offset, size_offset;
+ struct param_ddr_usage p;
+
+ memset(&p, 0, sizeof(p));
+
+ /* read how many blocks of ns-regions, read from offset: 0x0 */
+ p.ns_nr = mmio_read_32(addr + REGION_NR_OFFSET);
+ if ((p.ns_nr > DDR_REGION_NR_MAX) || (p.ns_nr == 0)) {
+ ERROR("over or zero region, nr=%d, max=%d\n",
+ p.ns_nr, DDR_REGION_NR_MAX);
+ return p;
+ }
+
+ /* whole ddr regions boundary, it will be used when parse s-regions */
+ p.boundary = max_mb;
+
+ /* calculate ns-region base addr and size offset */
+ addr_offset = REGION_ADDR_OFFSET;
+ size_offset = REGION_ADDR_OFFSET + p.ns_nr * REGION_DATA_PER_BYTES;
+
+ /* read all ns-regions base and top address */
+ for (i = 0; i < p.ns_nr; i++) {
+ base = mmio_read_64(addr + addr_offset);
+ top = base + mmio_read_64(addr + size_offset);
+ /*
+ * translate byte to MB and store info,
+ * Miniloader will promise every ns-region is MB aligned.
+ */
+ p.ns_base[i] = RG_SIZE_MB(base);
+ p.ns_top[i] = RG_SIZE_MB(top);
+
+ addr_offset += REGION_DATA_PER_BYTES;
+ size_offset += REGION_DATA_PER_BYTES;
+ }
+
+ /*
+ * a s-region's base starts from previous ns-region's top, and a
+ * s-region's top ends with next ns-region's base. maybe like this:
+ *
+ * case1: ns-regison start from 0MB
+ * -----------------------------------------------
+ * | ns0 | S0 | ns1 | S1 | ns2 |
+ * 0----------------------------------------------- max_mb
+ *
+ *
+ * case2: ns-regison not start from 0MB
+ * -----------------------------------------------
+ * | S0 | ns0 | ns1 | ns2 | S1 |
+ * 0----------------------------------------------- max_mb
+ */
+
+ /* like above case2 figure, ns-region is not start from 0MB */
+ if (p.ns_base[0] != 0) {
+ p.s_base[p.s_nr] = 0;
+ p.s_top[p.s_nr] = p.ns_base[0];
+ p.s_nr++;
+ }
+
+ /*
+ * notice: if ns-regions not start from 0MB, p.s_nr = 1 now, otherwise 0
+ */
+ for (i = 0; i < p.ns_nr; i++) {
+ /*
+ * if current ns-regions top covers boundary,
+ * that means s-regions are all parsed yet, so finsh.
+ */
+ if (p.ns_top[i] == p.boundary)
+ goto out;
+
+ /* s-region's base starts from previous ns-region's top */
+ p.s_base[p.s_nr] = p.ns_top[i];
+
+ /* s-region's top ends with next ns-region's base */
+ if (i + 1 < p.ns_nr)
+ p.s_top[p.s_nr] = p.ns_base[i + 1];
+ else
+ p.s_top[p.s_nr] = p.boundary;
+ p.s_nr++;
+ }
+out:
+ return p;
+}
diff --git a/plat/rockchip/common/drivers/parameter/ddr_parameter.h b/plat/rockchip/common/drivers/parameter/ddr_parameter.h
new file mode 100644
index 0000000..25c93a1
--- /dev/null
+++ b/plat/rockchip/common/drivers/parameter/ddr_parameter.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DDR_PARAMETER_H
+#define DDR_PARAMETER_H
+
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <plat_private.h>
+#include <soc.h>
+
+#define DDR_REGION_NR_MAX 10
+#define REGION_NR_OFFSET 0
+#define REGION_ADDR_OFFSET 8
+#define REGION_DATA_PER_BYTES 8
+#define RG_SIZE_MB(byte) ((byte) >> 20)
+
+/* unit: MB */
+struct param_ddr_usage {
+ uint64_t boundary;
+
+ uint32_t ns_nr;
+ uint64_t ns_base[DDR_REGION_NR_MAX];
+ uint64_t ns_top[DDR_REGION_NR_MAX];
+
+ uint32_t s_nr;
+ uint64_t s_base[DDR_REGION_NR_MAX + 1];
+ uint64_t s_top[DDR_REGION_NR_MAX + 1];
+};
+
+struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb);
+
+#endif /* DDR_PARAMETER_H */
diff --git a/plat/rockchip/common/drivers/pmu/pmu_com.h b/plat/rockchip/common/drivers/pmu/pmu_com.h
new file mode 100644
index 0000000..5359f73
--- /dev/null
+++ b/plat/rockchip/common/drivers/pmu/pmu_com.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_COM_H
+#define PMU_COM_H
+
+#ifndef CHECK_CPU_WFIE_BASE
+#define CHECK_CPU_WFIE_BASE (PMU_BASE + PMU_CORE_PWR_ST)
+#endif
+/*
+ * Use this macro to instantiate lock before it is used in below
+ * rockchip_pd_lock_xxx() macros
+ */
+DECLARE_BAKERY_LOCK(rockchip_pd_lock);
+
+/*
+ * These are wrapper macros to the powe domain Bakery Lock API.
+ */
+#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock)
+#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock)
+#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock)
+
+/*****************************************************************************
+ * power domain on or off
+ *****************************************************************************/
+enum pmu_pd_state {
+ pmu_pd_on = 0,
+ pmu_pd_off = 1
+};
+
+#pragma weak plat_ic_get_pending_interrupt_id
+#pragma weak pmu_power_domain_ctr
+#pragma weak check_cpu_wfie
+
+static inline uint32_t pmu_power_domain_st(uint32_t pd)
+{
+ uint32_t pwrdn_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd);
+
+ if (pwrdn_st)
+ return pmu_pd_off;
+ else
+ return pmu_pd_on;
+}
+
+static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
+{
+ uint32_t val;
+ uint32_t loop = 0;
+ int ret = 0;
+
+ rockchip_pd_lock_get();
+
+ val = mmio_read_32(PMU_BASE + PMU_PWRDN_CON);
+ if (pd_state == pmu_pd_off)
+ val |= BIT(pd);
+ else
+ val &= ~BIT(pd);
+
+ mmio_write_32(PMU_BASE + PMU_PWRDN_CON, val);
+ dsb();
+
+ while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if (pmu_power_domain_st(pd) != pd_state) {
+ WARN("%s: %d, %d, error!\n", __func__, pd, pd_state);
+ ret = -EINVAL;
+ }
+
+ rockchip_pd_lock_rls();
+
+ return ret;
+}
+
+static int check_cpu_wfie(uint32_t cpu_id, uint32_t wfie_msk)
+{
+ uint32_t cluster_id, loop = 0;
+
+ if (cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) {
+ cluster_id = 1;
+ cpu_id -= PLATFORM_CLUSTER0_CORE_COUNT;
+ } else {
+ cluster_id = 0;
+ }
+
+ /*
+ * wfe/wfi tracking not possible, hopefully the host
+ * was sucessful in enabling wfe/wfi.
+ * We'll give a bit of additional time, like the kernel does.
+ */
+ if ((cluster_id && clstb_cpu_wfe < 0) ||
+ (!cluster_id && clstl_cpu_wfe < 0)) {
+ mdelay(1);
+ return 0;
+ }
+
+ if (cluster_id)
+ wfie_msk <<= (clstb_cpu_wfe + cpu_id);
+ else
+ wfie_msk <<= (clstl_cpu_wfe + cpu_id);
+
+ while (!(mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) &&
+ (loop < CHK_CPU_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if ((mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) == 0) {
+ WARN("%s: %d, %d, %d, error!\n", __func__,
+ cluster_id, cpu_id, wfie_msk);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#endif /* PMU_COM_H */
diff --git a/plat/rockchip/common/include/plat_macros.S b/plat/rockchip/common/include/plat_macros.S
new file mode 100644
index 0000000..691beeb
--- /dev/null
+++ b/plat/rockchip/common/include/plat_macros.S
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ROCKCHIP_PLAT_MACROS_S
+#define ROCKCHIP_PLAT_MACROS_S
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+ .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
+ " Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+ .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+ /* ---------------------------------------------
+ * The below utility macro prints out relevant GIC
+ * and CCI registers whenever an unhandled
+ * exception is taken in BL31.
+ * Expects: GICD base in x26, GICC base in x27
+ * Clobbers: x0 - x10, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+
+ mov_imm x26, PLAT_RK_GICD_BASE
+ mov_imm x27, PLAT_RK_GICC_BASE
+
+ /* Check for GICv3 system register access */
+ mrs x7, id_aa64pfr0_el1
+ ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x7, #1
+ b.ne print_gicv2
+
+ /* Check for SRE enable */
+ mrs x8, ICC_SRE_EL3
+ tst x8, #ICC_SRE_SRE_BIT
+ b.eq print_gicv2
+
+ /* Load the icc reg list to x6 */
+ adr x6, icc_regs
+ /* Load the icc regs to gp regs used by str_in_crash_buf_print */
+ mrs x8, ICC_HPPIR0_EL1
+ mrs x9, ICC_HPPIR1_EL1
+ mrs x10, ICC_CTLR_EL3
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ b print_gic_common
+
+print_gicv2:
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x27, #GICC_HPPIR]
+ ldr w9, [x27, #GICC_AHPPIR]
+ ldr w10, [x27, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+print_gic_common:
+ /* Print the GICD_ISPENDR regs */
+ add x7, x26, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x26
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+
+#if PLATFORM_CLUSTER_COUNT > 1
+ adr x6, cci_iface_regs
+ /* Store in x7 the base address of the first interface */
+ mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX))
+ ldr w8, [x7, #SNOOP_CTRL_REG]
+ /* Store in x7 the base address of the second interface */
+ mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
+ PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX))
+ ldr w9, [x7, #SNOOP_CTRL_REG]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+#endif
+ .endm
+
+#endif /* ROCKCHIP_PLAT_MACROS_S */
diff --git a/plat/rockchip/common/include/plat_params.h b/plat/rockchip/common/include/plat_params.h
new file mode 100644
index 0000000..95b850f
--- /dev/null
+++ b/plat/rockchip/common/include/plat_params.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PARAMS_H
+#define PLAT_PARAMS_H
+
+#include <stdint.h>
+
+#include <export/plat/rockchip/common/plat_params_exp.h>
+
+#endif /* PLAT_PARAMS_H */
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
new file mode 100644
index 0000000..990d106
--- /dev/null
+++ b/plat/rockchip/common/include/plat_private.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#include <lib/psci/psci.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <lib/mmio.h>
+#include <plat_params.h>
+
+#define __sramdata __attribute__((section(".sram.data")))
+#define __sramconst __attribute__((section(".sram.rodata")))
+#define __sramfunc __attribute__((section(".sram.text")))
+
+#define __pmusramdata __attribute__((section(".pmusram.data")))
+#define __pmusramconst __attribute__((section(".pmusram.rodata")))
+#define __pmusramfunc __attribute__((section(".pmusram.text")))
+
+extern uint32_t __bl31_sram_text_start, __bl31_sram_text_end;
+extern uint32_t __bl31_sram_data_start, __bl31_sram_data_end;
+extern uint32_t __bl31_sram_stack_start, __bl31_sram_stack_end;
+extern uint32_t __bl31_sram_text_real_end, __bl31_sram_data_real_end;
+extern uint32_t __sram_incbin_start, __sram_incbin_end;
+extern uint32_t __sram_incbin_real_end;
+
+/******************************************************************************
+ * The register have write-mask bits, it is mean, if you want to set the bits,
+ * you needs set the write-mask bits at the same time,
+ * The write-mask bits is in high 16-bits.
+ * The fllowing macro definition helps access write-mask bits reg efficient!
+ ******************************************************************************/
+#define REG_MSK_SHIFT 16
+
+#ifndef WMSK_BIT
+#define WMSK_BIT(nr) BIT((nr) + REG_MSK_SHIFT)
+#endif
+
+/* set one bit with write mask */
+#ifndef BIT_WITH_WMSK
+#define BIT_WITH_WMSK(nr) (BIT(nr) | WMSK_BIT(nr))
+#endif
+
+#ifndef BITS_SHIFT
+#define BITS_SHIFT(bits, shift) (bits << (shift))
+#endif
+
+#ifndef BITS_WITH_WMASK
+#define BITS_WITH_WMASK(bits, msk, shift)\
+ (BITS_SHIFT(bits, shift) | BITS_SHIFT(msk, (shift + REG_MSK_SHIFT)))
+#endif
+
+/******************************************************************************
+ * Function and variable prototypes
+ *****************************************************************************/
+#ifdef __aarch64__
+void plat_configure_mmu_el3(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+
+void rockchip_plat_mmu_el3(void);
+#else
+void plat_configure_mmu_svc_mon(unsigned long total_base,
+ unsigned long total_size,
+ unsigned long,
+ unsigned long,
+ unsigned long,
+ unsigned long);
+
+void rockchip_plat_mmu_svc_mon(void);
+#endif
+
+void plat_cci_init(void);
+void plat_cci_enable(void);
+void plat_cci_disable(void);
+
+void plat_delay_timer_init(void);
+
+void params_early_setup(u_register_t plat_params_from_bl2);
+
+void plat_rockchip_gic_driver_init(void);
+void plat_rockchip_gic_init(void);
+void plat_rockchip_gic_cpuif_enable(void);
+void plat_rockchip_gic_cpuif_disable(void);
+void plat_rockchip_gic_pcpu_init(void);
+
+void plat_rockchip_pmu_init(void);
+void plat_rockchip_soc_init(void);
+uintptr_t plat_get_sec_entrypoint(void);
+
+void platform_cpu_warmboot(void);
+
+struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void);
+struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void);
+struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count);
+struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void);
+void plat_rockchip_gpio_init(void);
+void plat_rockchip_save_gpio(void);
+void plat_rockchip_restore_gpio(void);
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint);
+int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
+ plat_local_state_t lvl_state);
+int rockchip_soc_cores_pwr_dm_off(void);
+int rockchip_soc_sys_pwr_dm_suspend(void);
+int rockchip_soc_cores_pwr_dm_suspend(void);
+int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl,
+ plat_local_state_t lvl_state);
+int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl,
+ plat_local_state_t lvl_state);
+int rockchip_soc_cores_pwr_dm_on_finish(void);
+int rockchip_soc_sys_pwr_dm_resume(void);
+
+int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl,
+ plat_local_state_t lvl_state);
+int rockchip_soc_cores_pwr_dm_resume(void);
+void __dead2 rockchip_soc_soft_reset(void);
+void __dead2 rockchip_soc_system_off(void);
+void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(
+ const psci_power_state_t *target_state);
+void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void);
+
+extern const unsigned char rockchip_power_domain_tree_desc[];
+
+extern void *pmu_cpuson_entrypoint;
+extern u_register_t cpuson_entry_point[PLATFORM_CORE_COUNT];
+extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT];
+
+extern const mmap_region_t plat_rk_mmap[];
+
+uint32_t rockchip_get_uart_base(void);
+uint32_t rockchip_get_uart_baudrate(void);
+uint32_t rockchip_get_uart_clock(void);
+
+#endif /* __ASSEMBLER__ */
+
+/******************************************************************************
+ * cpu up status
+ * The bits of macro value is not more than 12 bits for cmp instruction!
+ ******************************************************************************/
+#define PMU_CPU_HOTPLUG 0xf00
+#define PMU_CPU_AUTO_PWRDN 0xf0
+#define PMU_CLST_RET 0xa5
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/rockchip/common/include/rockchip_sip_svc.h b/plat/rockchip/common/include/rockchip_sip_svc.h
new file mode 100644
index 0000000..340d653
--- /dev/null
+++ b/plat/rockchip/common/include/rockchip_sip_svc.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ROCKCHIP_SIP_SVC_H
+#define ROCKCHIP_SIP_SVC_H
+
+/* SMC function IDs for SiP Service queries */
+#define SIP_SVC_CALL_COUNT 0x8200ff00
+#define SIP_SVC_UID 0x8200ff01
+#define SIP_SVC_VERSION 0x8200ff03
+
+/* rockchip SiP Service Calls version numbers */
+#define RK_SIP_SVC_VERSION_MAJOR 0x0
+#define RK_SIP_SVC_VERSION_MINOR 0x1
+
+/* Number of ROCKCHIP SiP Calls implemented */
+#define RK_COMMON_SIP_NUM_CALLS 0x3
+
+enum {
+ RK_SIP_E_SUCCESS = 0,
+ RK_SIP_E_INVALID_PARAM = -1
+};
+
+#endif /* ROCKCHIP_SIP_SVC_H */
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
new file mode 100644
index 0000000..68054ad
--- /dev/null
+++ b/plat/rockchip/common/params_setup.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+#include <lib/bl_aux_params/bl_aux_params.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/gpio.h>
+#include <libfdt.h>
+#include <lib/coreboot.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <plat_params.h>
+#include <plat_private.h>
+
+static struct bl_aux_gpio_info rst_gpio = { .index = UINT_MAX } ;
+static struct bl_aux_gpio_info poweroff_gpio = { .index = UINT_MAX };
+static struct bl_aux_gpio_info suspend_gpio[10];
+uint32_t suspend_gpio_cnt;
+static struct bl_aux_rk_apio_info suspend_apio;
+
+#if COREBOOT
+static int dt_process_fdt(u_register_t param_from_bl2)
+{
+ return -ENODEV;
+}
+#else
+static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
+static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
+static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK;
+#define FDT_BUFFER_SIZE 0x20000
+static uint64_t fdt_buffer[FDT_BUFFER_SIZE / 8];
+
+void *plat_get_fdt(void)
+{
+ return &fdt_buffer[0];
+}
+
+static void plat_rockchip_dt_process_fdt_uart(void *fdt)
+{
+ const char *path_name = "/chosen";
+ const char *prop_name = "stdout-path";
+ int node_offset;
+ int stdout_path_len;
+ const char *stdout_path;
+ const char *separator;
+ const char *baud_start;
+ char serial_char;
+ int serial_no;
+ uint32_t uart_base;
+ uint32_t baud;
+
+ node_offset = fdt_path_offset(fdt, path_name);
+ if (node_offset < 0)
+ return;
+
+ stdout_path = fdt_getprop(fdt, node_offset, prop_name,
+ &stdout_path_len);
+ if (stdout_path == NULL)
+ return;
+
+ /*
+ * We expect something like:
+ * "serial0:baudrate"
+ */
+ if (strncmp("serial", stdout_path, 6) != 0)
+ return;
+
+ serial_char = stdout_path[6];
+ serial_no = serial_char - '0';
+
+ switch (serial_no) {
+ case 0:
+ uart_base = UART0_BASE;
+ break;
+ case 1:
+ uart_base = UART1_BASE;
+ break;
+ case 2:
+ uart_base = UART2_BASE;
+ break;
+#ifdef UART3_BASE
+ case 3:
+ uart_base = UART3_BASE;
+ break;
+#endif
+#ifdef UART4_BASE
+ case 4:
+ uart_base = UART4_BASE;
+ break;
+#endif
+#ifdef UART5_BASE
+ case 5:
+ uart_base = UART5_BASE;
+ break;
+#endif
+ default:
+ return;
+ }
+
+ rk_uart_base = uart_base;
+
+ separator = strchr(stdout_path, ':');
+ if (!separator)
+ return;
+
+ baud = 0;
+ baud_start = separator + 1;
+ while (*baud_start != '\0') {
+ /*
+ * uart binding is <baud>{<parity>{<bits>{...}}}
+ * So the baudrate either is the whole string, or
+ * we end in the parity characters.
+ */
+ if (*baud_start == 'n' || *baud_start == 'o' ||
+ *baud_start == 'e')
+ break;
+
+ baud = baud * 10 + (*baud_start - '0');
+ baud_start++;
+ }
+
+ rk_uart_baudrate = baud;
+}
+
+static int dt_process_fdt(u_register_t param_from_bl2)
+{
+ void *fdt = plat_get_fdt();
+ int ret;
+
+ ret = fdt_open_into((void *)param_from_bl2, fdt, FDT_BUFFER_SIZE);
+ if (ret < 0)
+ return ret;
+
+ plat_rockchip_dt_process_fdt_uart(fdt);
+
+ return 0;
+}
+#endif
+
+uint32_t rockchip_get_uart_base(void)
+{
+#if COREBOOT
+ return coreboot_serial.baseaddr;
+#else
+ return rk_uart_base;
+#endif
+}
+
+uint32_t rockchip_get_uart_baudrate(void)
+{
+#if COREBOOT
+ return coreboot_serial.baud;
+#else
+ return rk_uart_baudrate;
+#endif
+}
+
+uint32_t rockchip_get_uart_clock(void)
+{
+#if COREBOOT
+ return coreboot_serial.input_hertz;
+#else
+ return rk_uart_clock;
+#endif
+}
+
+struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void)
+{
+ if (rst_gpio.index == UINT_MAX)
+ return NULL;
+
+ return &rst_gpio;
+}
+
+struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void)
+{
+ if (poweroff_gpio.index == UINT_MAX)
+ return NULL;
+
+ return &poweroff_gpio;
+}
+
+struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count)
+{
+ *count = suspend_gpio_cnt;
+
+ return &suspend_gpio[0];
+}
+
+struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void)
+{
+ return &suspend_apio;
+}
+
+static bool rk_aux_param_handler(struct bl_aux_param_header *param)
+{
+ /* Store platform parameters for later processing if needed. */
+ switch (param->type) {
+ case BL_AUX_PARAM_RK_RESET_GPIO:
+ rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
+ return true;
+ case BL_AUX_PARAM_RK_POWEROFF_GPIO:
+ poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
+ return true;
+ case BL_AUX_PARAM_RK_SUSPEND_GPIO:
+ if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) {
+ ERROR("Exceeded the supported suspend GPIO number.\n");
+ return true;
+ }
+ suspend_gpio[suspend_gpio_cnt++] =
+ ((struct bl_aux_param_gpio *)param)->gpio;
+ return true;
+ case BL_AUX_PARAM_RK_SUSPEND_APIO:
+ suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio;
+ return true;
+ }
+
+ return false;
+}
+
+void params_early_setup(u_register_t plat_param_from_bl2)
+{
+ int ret;
+
+ /*
+ * Test if this is a FDT passed as a platform-specific parameter
+ * block.
+ */
+ ret = dt_process_fdt(plat_param_from_bl2);
+ if (!ret) {
+ return;
+ } else if (ret != -FDT_ERR_BADMAGIC) {
+ /*
+ * If we found an FDT but couldn't parse it (e.g. corrupt, not
+ * enough space), return and don't attempt to parse the param
+ * as something else, since we know that will also fail. All
+ * we're doing is setting up UART, this doesn't need to be
+ * fatal.
+ */
+ WARN("%s: found FDT but could not parse: error %d\n",
+ __func__, ret);
+ return;
+ }
+
+ bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler);
+}
diff --git a/plat/rockchip/common/plat_pm.c b/plat/rockchip/common/plat_pm.c
new file mode 100644
index 0000000..6926887
--- /dev/null
+++ b/plat/rockchip/common/plat_pm.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/psci/psci.h>
+
+#include <plat_private.h>
+
+/* Macros to read the rk power domain state */
+#define RK_CORE_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define RK_CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define RK_SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+static uintptr_t rockchip_sec_entrypoint;
+
+#pragma weak rockchip_soc_cores_pwr_dm_on
+#pragma weak rockchip_soc_hlvl_pwr_dm_off
+#pragma weak rockchip_soc_cores_pwr_dm_off
+#pragma weak rockchip_soc_sys_pwr_dm_suspend
+#pragma weak rockchip_soc_cores_pwr_dm_suspend
+#pragma weak rockchip_soc_hlvl_pwr_dm_suspend
+#pragma weak rockchip_soc_hlvl_pwr_dm_on_finish
+#pragma weak rockchip_soc_cores_pwr_dm_on_finish
+#pragma weak rockchip_soc_sys_pwr_dm_resume
+#pragma weak rockchip_soc_hlvl_pwr_dm_resume
+#pragma weak rockchip_soc_cores_pwr_dm_resume
+#pragma weak rockchip_soc_soft_reset
+#pragma weak rockchip_soc_system_off
+#pragma weak rockchip_soc_sys_pd_pwr_dn_wfi
+#pragma weak rockchip_soc_cores_pd_pwr_dn_wfi
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
+ plat_local_state_t lvl_state)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_cores_pwr_dm_off(void)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_cores_pwr_dm_suspend(void)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl,
+ plat_local_state_t lvl_state)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl,
+ plat_local_state_t lvl_state)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl,
+ plat_local_state_t lvl_state)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+int rockchip_soc_cores_pwr_dm_resume(void)
+{
+ return PSCI_E_NOT_SUPPORTED;
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ while (1)
+ ;
+}
+
+void __dead2 rockchip_soc_system_off(void)
+{
+ while (1)
+ ;
+}
+
+void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(
+ const psci_power_state_t *target_state)
+{
+ psci_power_down_wfi();
+}
+
+void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
+{
+ psci_power_down_wfi();
+}
+
+/*******************************************************************************
+ * Rockchip standard platform handler called to check the validity of the power
+ * state parameter.
+ ******************************************************************************/
+int rockchip_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+ int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+ int i;
+
+ assert(req_state);
+
+ if (pwr_lvl > PLAT_MAX_PWR_LVL)
+ return PSCI_E_INVALID_PARAMS;
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ /*
+ * It's probably to enter standby only on power level 0
+ * ignore any other power level.
+ */
+ if (pwr_lvl != MPIDR_AFFLVL0)
+ return PSCI_E_INVALID_PARAMS;
+
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] =
+ PLAT_MAX_RET_STATE;
+ } else {
+ for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
+ req_state->pwr_domain_state[i] =
+ PLAT_MAX_OFF_STATE;
+
+ for (i = (pwr_lvl + 1); i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] =
+ PLAT_MAX_RET_STATE;
+ }
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
+ return PSCI_E_SUCCESS;
+}
+
+void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ int i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+}
+
+/*******************************************************************************
+ * RockChip handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+void rockchip_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr;
+
+ assert(cpu_state == PLAT_MAX_RET_STATE);
+
+ scr = read_scr_el3();
+ /* Enable PhysicalIRQ bit for NS world to wake the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT);
+ isb();
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR to the original value, synchronisation of scr_el3 is
+ * done by eret while el3_exit to save some execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+int rockchip_pwr_domain_on(u_register_t mpidr)
+{
+ return rockchip_soc_cores_pwr_dm_on(mpidr, rockchip_sec_entrypoint);
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void rockchip_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint32_t lvl;
+ plat_local_state_t lvl_state;
+ int ret;
+
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ plat_rockchip_gic_cpuif_disable();
+
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_cci_disable();
+
+ rockchip_soc_cores_pwr_dm_off();
+
+ for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
+ lvl_state = target_state->pwr_domain_state[lvl];
+ ret = rockchip_soc_hlvl_pwr_dm_off(lvl, lvl_state);
+ if (ret == PSCI_E_NOT_SUPPORTED)
+ break;
+ }
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint32_t lvl;
+ plat_local_state_t lvl_state;
+ int ret;
+
+ if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_rockchip_gic_cpuif_disable();
+
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ rockchip_soc_sys_pwr_dm_suspend();
+ else
+ rockchip_soc_cores_pwr_dm_suspend();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ plat_cci_disable();
+
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ return;
+
+ for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
+ lvl_state = target_state->pwr_domain_state[lvl];
+ ret = rockchip_soc_hlvl_pwr_dm_suspend(lvl, lvl_state);
+ if (ret == PSCI_E_NOT_SUPPORTED)
+ break;
+ }
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+void rockchip_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ uint32_t lvl;
+ plat_local_state_t lvl_state;
+ int ret;
+
+ assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
+ lvl_state = target_state->pwr_domain_state[lvl];
+ ret = rockchip_soc_hlvl_pwr_dm_on_finish(lvl, lvl_state);
+ if (ret == PSCI_E_NOT_SUPPORTED)
+ break;
+ }
+
+ rockchip_soc_cores_pwr_dm_on_finish();
+
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ }
+
+ /* Enable the gic cpu interface */
+ plat_rockchip_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_rockchip_gic_cpuif_enable();
+}
+
+/*******************************************************************************
+ * RockChip handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+void rockchip_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ uint32_t lvl;
+ plat_local_state_t lvl_state;
+ int ret;
+
+ /* Nothing to be done on waking up from retention from CPU level */
+ if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ rockchip_soc_sys_pwr_dm_resume();
+ goto comm_finish;
+ }
+
+ for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
+ lvl_state = target_state->pwr_domain_state[lvl];
+ ret = rockchip_soc_hlvl_pwr_dm_resume(lvl, lvl_state);
+ if (ret == PSCI_E_NOT_SUPPORTED)
+ break;
+ }
+
+ rockchip_soc_cores_pwr_dm_resume();
+
+ /*
+ * Program the gic per-cpu distributor or re-distributor interface.
+ * For sys power domain operation, resuming of the gic needs to operate
+ * in rockchip_soc_sys_pwr_dm_resume(), according to the sys power mode
+ * implements.
+ */
+ plat_rockchip_gic_cpuif_enable();
+
+comm_finish:
+ /* Perform the common cluster specific operations */
+ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ /* Enable coherency if this cluster was off */
+ plat_cci_enable();
+ }
+}
+
+/*******************************************************************************
+ * RockChip handlers to reboot the system
+ ******************************************************************************/
+static void __dead2 rockchip_system_reset(void)
+{
+ rockchip_soc_soft_reset();
+}
+
+/*******************************************************************************
+ * RockChip handlers to power off the system
+ ******************************************************************************/
+static void __dead2 rockchip_system_poweroff(void)
+{
+ rockchip_soc_system_off();
+}
+
+static void __dead2 rockchip_pd_pwr_down_wfi(
+ const psci_power_state_t *target_state)
+{
+ if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ rockchip_soc_sys_pd_pwr_dn_wfi();
+ else
+ rockchip_soc_cores_pd_pwr_dn_wfi(target_state);
+}
+
+/*******************************************************************************
+ * Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip
+ * standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+const plat_psci_ops_t plat_rockchip_psci_pm_ops = {
+ .cpu_standby = rockchip_cpu_standby,
+ .pwr_domain_on = rockchip_pwr_domain_on,
+ .pwr_domain_off = rockchip_pwr_domain_off,
+ .pwr_domain_suspend = rockchip_pwr_domain_suspend,
+ .pwr_domain_on_finish = rockchip_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = rockchip_pd_pwr_down_wfi,
+ .system_reset = rockchip_system_reset,
+ .system_off = rockchip_system_poweroff,
+ .validate_power_state = rockchip_validate_power_state,
+ .get_sys_suspend_power_state = rockchip_get_sys_suspend_power_state
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ *psci_ops = &plat_rockchip_psci_pm_ops;
+ rockchip_sec_entrypoint = sec_entrypoint;
+ return 0;
+}
+
+uintptr_t plat_get_sec_entrypoint(void)
+{
+ assert(rockchip_sec_entrypoint);
+ return rockchip_sec_entrypoint;
+}
diff --git a/plat/rockchip/common/plat_topology.c b/plat/rockchip/common/plat_topology.c
new file mode 100644
index 0000000..4987eeb
--- /dev/null
+++ b/plat/rockchip/common/plat_topology.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <lib/psci/psci.h>
+
+#include <plat_private.h>
+
+/*******************************************************************************
+ * This function returns the RockChip default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return rockchip_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ cpu_id = mpidr & MPIDR_AFFLVL_MASK;
+#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
+ cluster_id = mpidr & PLAT_RK_MPIDR_CLUSTER_MASK;
+#else
+ cluster_id = mpidr & MPIDR_CLUSTER_MASK;
+#endif
+
+ cpu_id += (cluster_id >> PLAT_RK_CLST_TO_CPUID_SHIFT);
+
+ if (cpu_id >= PLATFORM_CORE_COUNT)
+ return -1;
+
+ return cpu_id;
+}
diff --git a/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S
new file mode 100644
index 0000000..6cea2ea
--- /dev/null
+++ b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <cpus_on_fixed_addr.h>
+
+ .globl sys_sleep_flag_sram
+ .globl pmu_cpuson_entrypoint
+
+ .macro pmusram_entry_func _name
+ .section .pmusram.entry, "ax"
+ .type \_name, %function
+ .cfi_startproc
+ \_name:
+ .endm
+
+pmusram_entry_func pmu_cpuson_entrypoint
+ adr x5, sys_sleep_flag_sram
+ ldr w2, [x5, #PSRAM_DT_PM_FLAG]
+
+ tbz w2, #PM_WARM_BOOT_SHT, sys_resume_sp
+ ldr x1, =platform_cpu_warmboot
+ br x1
+sys_resume_sp:
+ adr x5, sys_sleep_flag_sram
+ ldr x1, [x5, #PSRAM_DT_SP]
+ mov sp, x1
+ddr_resume:
+ ldr x1, [x5, #PSRAM_DT_DDR_FUNC]
+ cmp x1, #0
+ b.eq sys_resume
+ blr x1
+sys_resume:
+ ldr x1, =bl31_warm_entrypoint
+ br x1
+endfunc pmu_cpuson_entrypoint
+
+ .section .pmusram.data, "a"
+ .align 3
+sys_sleep_flag_sram:
+ .rept PSRAM_DT_SIZE_WORDS
+ .word 0
+ .endr
diff --git a/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h
new file mode 100644
index 0000000..bcd2a7c
--- /dev/null
+++ b/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CPU_ON_FIXED_ADDR_H__
+#define __CPU_ON_FIXED_ADDR_H__
+
+/*****************************************************************************
+ * define data offset in struct psram_data
+ *****************************************************************************/
+#define PSRAM_DT_SP 0x0
+#define PSRAM_DT_DDR_FUNC 0x8
+#define PSRAM_DT_DDR_DATA 0x10
+#define PSRAM_DT_DDRFLAG 0x18
+#define PSRAM_DT_MPIDR 0x1c
+#define PSRAM_DT_PM_FLAG 0x20
+#define PSRAM_DT_END 0x24
+
+/* reserve 4 byte */
+#define PSRAM_DT_END_RES4 (PSRAM_DT_END + 4)
+
+#define PSRAM_DT_SIZE_WORDS (PSRAM_DT_END_RES4 / 4)
+
+#define PM_WARM_BOOT_SHT 0
+#define PM_WARM_BOOT_BIT (1 << PM_WARM_BOOT_SHT)
+
+#ifndef __ASSEMBLER__
+
+struct psram_data_t {
+ uint64_t sp;
+ uint64_t ddr_func;
+ uint64_t ddr_data;
+ uint32_t ddr_flag;
+ uint32_t boot_mpidr;
+ uint32_t pm_flag;
+};
+
+CASSERT(__builtin_offsetof(struct psram_data_t, sp) == PSRAM_DT_SP,
+ assert_psram_dt_sp_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_func) == PSRAM_DT_DDR_FUNC,
+ assert_psram_dt_ddr_func_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_data) == PSRAM_DT_DDR_DATA,
+ assert_psram_dt_ddr_data_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, ddr_flag) == PSRAM_DT_DDRFLAG,
+ assert_psram_dt_ddr_flag_offset_mistmatch);
+CASSERT(__builtin_offsetof(struct psram_data_t, boot_mpidr) == PSRAM_DT_MPIDR,
+ assert_psram_dt_mpidr_offset_mistmatch);
+
+extern struct psram_data_t sys_sleep_flag_sram;
+
+#endif /* __ASSEMBLER__ */
+
+#endif
diff --git a/plat/rockchip/common/rockchip_gicv2.c b/plat/rockchip/common/rockchip_gicv2.c
new file mode 100644
index 0000000..8db2b30
--- /dev/null
+++ b/plat/rockchip/common/rockchip_gicv2.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/utils.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv2 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_rockchip_gic_driver_init
+#pragma weak plat_rockchip_gic_init
+#pragma weak plat_rockchip_gic_cpuif_enable
+#pragma weak plat_rockchip_gic_cpuif_disable
+#pragma weak plat_rockchip_gic_pcpu_init
+
+/******************************************************************************
+ * List of interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t g0_interrupt_props[] = {
+ PLAT_RK_GICV2_G0_IRQS
+};
+
+/*
+ * Ideally `rockchip_gic_data` structure definition should be a `const` but it
+ * is kept as modifiable for overwriting with different GICD and GICC base when
+ * running on FVP with VE memory map.
+ */
+gicv2_driver_data_t rockchip_gic_data = {
+ .gicd_base = PLAT_RK_GICD_BASE,
+ .gicc_base = PLAT_RK_GICC_BASE,
+ .interrupt_props = g0_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props),
+};
+
+/******************************************************************************
+ * RockChip common helper to initialize the GICv2 only driver.
+ *****************************************************************************/
+void plat_rockchip_gic_driver_init(void)
+{
+ gicv2_driver_init(&rockchip_gic_data);
+}
+
+void plat_rockchip_gic_init(void)
+{
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * RockChip common helper to enable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_enable(void)
+{
+ gicv2_cpuif_enable();
+}
+
+/******************************************************************************
+ * RockChip common helper to disable the GICv2 CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_disable(void)
+{
+ gicv2_cpuif_disable();
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the per cpu distributor interface
+ * in GICv2
+ *****************************************************************************/
+void plat_rockchip_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+}
diff --git a/plat/rockchip/common/rockchip_gicv3.c b/plat/rockchip/common/rockchip_gicv3.c
new file mode 100644
index 0000000..edae2ef
--- /dev/null
+++ b/plat/rockchip/common/rockchip_gicv3.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_rockchip_gic_driver_init
+#pragma weak plat_rockchip_gic_init
+#pragma weak plat_rockchip_gic_cpuif_enable
+#pragma weak plat_rockchip_gic_cpuif_disable
+#pragma weak plat_rockchip_gic_pcpu_init
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t g01s_interrupt_props[] = {
+ PLAT_RK_GICV3_G0_IRQS,
+ PLAT_RK_GICV3_G1S_IRQS
+};
+
+static unsigned int plat_rockchip_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+const gicv3_driver_data_t rockchip_gic_data = {
+ .gicd_base = PLAT_RK_GICD_BASE,
+ .gicr_base = PLAT_RK_GICR_BASE,
+ .interrupt_props = g01s_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(g01s_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = plat_rockchip_mpidr_to_core_pos,
+};
+
+void plat_rockchip_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#ifdef IMAGE_BL31
+ gicv3_driver_init(&rockchip_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the GIC. Only invoked
+ * by BL31
+ *****************************************************************************/
+void plat_rockchip_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_rockchip_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * RockChip common helper to initialize the per-cpu redistributor interface
+ * in GICv3
+ *****************************************************************************/
+void plat_rockchip_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/rockchip/common/rockchip_sip_svc.c b/plat/rockchip/common/rockchip_sip_svc.c
new file mode 100644
index 0000000..27ef042
--- /dev/null
+++ b/plat/rockchip/common/rockchip_sip_svc.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <tools_share/uuid.h>
+
+#include <plat_sip_calls.h>
+#include <rockchip_sip_svc.h>
+
+/* Rockchip SiP Service UUID */
+DEFINE_SVC_UUID2(rk_sip_svc_uid,
+ 0xe2c76fe8, 0x3e31, 0xe611, 0xb7, 0x0d,
+ 0x8f, 0x88, 0xee, 0x74, 0x7b, 0x72);
+
+#pragma weak rockchip_plat_sip_handler
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
+
+/*
+ * This function is responsible for handling all SiP calls from the NS world
+ */
+uintptr_t sip_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ uint32_t ns;
+
+ /* Determine which security state this SMC originated from */
+ ns = is_caller_non_secure(flags);
+ if (!ns)
+ SMC_RET1(handle, SMC_UNK);
+
+ switch (smc_fid) {
+ case SIP_SVC_CALL_COUNT:
+ /* Return the number of Rockchip SiP Service Calls. */
+ SMC_RET1(handle,
+ RK_COMMON_SIP_NUM_CALLS + RK_PLAT_SIP_NUM_CALLS);
+
+ case SIP_SVC_UID:
+ /* Return UID to the caller */
+ SMC_UUID_RET(handle, rk_sip_svc_uid);
+
+ case SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ SMC_RET2(handle, RK_SIP_SVC_VERSION_MAJOR,
+ RK_SIP_SVC_VERSION_MINOR);
+
+ default:
+ return rockchip_plat_sip_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ }
+}
+
+/* Define a runtime service descriptor for fast SMC calls */
+DECLARE_RT_SVC(
+ rockchip_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ NULL,
+ sip_smc_handler
+);
diff --git a/plat/rockchip/common/rockchip_stack_protector.c b/plat/rockchip/common/rockchip_stack_protector.c
new file mode 100644
index 0000000..1898977
--- /dev/null
+++ b/plat/rockchip/common/rockchip_stack_protector.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * Ideally, a random number should be returned instead of the
+ * combination of a timer's value and a compile-time constant.
+ * As the virt platform does not have any random number generator,
+ * this is better than nothing but not necessarily really secure.
+ */
+ return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
+
diff --git a/plat/rockchip/common/sp_min_plat_setup.c b/plat/rockchip/common/sp_min_plat_setup.c
new file mode 100644
index 0000000..0237b16
--- /dev/null
+++ b/plat/rockchip/common/sp_min_plat_setup.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <plat_private.h>
+#include <plat/common/platform.h>
+
+static entry_point_info_t bl33_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type.
+ * A NULL pointer is returned if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = &bl33_ep_info;
+
+ if (next_image_info->pc == 0U) {
+ return NULL;
+ }
+
+ return next_image_info;
+}
+
+#pragma weak params_early_setup
+void params_early_setup(u_register_t plat_param_from_bl2)
+{
+}
+
+unsigned int plat_is_my_cpu_primary(void);
+
+/*******************************************************************************
+ * Perform any BL32 specific platform actions.
+ ******************************************************************************/
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ static console_t console;
+
+ params_early_setup(arg1);
+
+ if (rockchip_get_uart_base() != 0)
+ console_16550_register(rockchip_get_uart_base(),
+ rockchip_get_uart_clock(),
+ rockchip_get_uart_baudrate(), &console);
+
+ VERBOSE("sp_min_setup\n");
+
+ bl31_params_parse_helper(arg0, NULL, &bl33_ep_info);
+}
+
+/*******************************************************************************
+ * Perform any sp_min platform setup code
+ ******************************************************************************/
+void sp_min_platform_setup(void)
+{
+ generic_delay_timer_init();
+ plat_rockchip_soc_init();
+
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_rockchip_gic_driver_init();
+ plat_rockchip_gic_init();
+ plat_rockchip_pmu_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void sp_min_plat_arch_setup(void)
+{
+ plat_cci_init();
+ plat_cci_enable();
+
+ plat_configure_mmu_svc_mon(BL_CODE_BASE,
+ BL_COHERENT_RAM_END - BL_CODE_BASE,
+ BL_CODE_BASE,
+ BL_CODE_END,
+ BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END);
+}
+
+void sp_min_plat_fiq_handler(uint32_t id)
+{
+ VERBOSE("[sp_min] interrupt #%d\n", id);
+}
diff --git a/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..a757621
--- /dev/null
+++ b/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+.globl clst_warmboot_data
+
+.macro func_rockchip_clst_warmboot
+.endm
+
+.macro rockchip_clst_warmboot_data
+clst_warmboot_data:
+ .rept PLATFORM_CLUSTER_COUNT
+ .word 0
+ .endr
+.endm
diff --git a/plat/rockchip/px30/drivers/pmu/pmu.c b/plat/rockchip/px30/drivers/pmu/pmu.c
new file mode 100644
index 0000000..5f4e64f
--- /dev/null
+++ b/plat/rockchip/px30/drivers/pmu/pmu.c
@@ -0,0 +1,1071 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <cpus_on_fixed_addr.h>
+#include <plat_private.h>
+#include <pmu.h>
+#include <px30_def.h>
+#include <secure.h>
+#include <soc.h>
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock)
+#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock)
+#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock)
+
+static struct psram_data_t *psram_boot_cfg =
+ (struct psram_data_t *)&sys_sleep_flag_sram;
+
+/*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg,
+ * it is core_pwr_pd mode
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode
+ * so we need core_pm_cfg_info to distinguish which method be used now.
+ */
+
+static uint32_t cores_pd_cfg_info[PLATFORM_CORE_COUNT]
+#if USE_COHERENT_MEM
+__attribute__ ((section("tzfw_coherent_mem")))
+#endif
+;
+
+struct px30_sleep_ddr_data {
+ uint32_t clk_sel0;
+ uint32_t cru_mode_save;
+ uint32_t cru_pmu_mode_save;
+ uint32_t ddrc_hwlpctl;
+ uint32_t ddrc_pwrctrl;
+ uint32_t ddrgrf_con0;
+ uint32_t ddrgrf_con1;
+ uint32_t ddrstdby_con0;
+ uint32_t gpio0b_iomux;
+ uint32_t gpio0c_iomux;
+ uint32_t pmu_pwrmd_core_l;
+ uint32_t pmu_pwrmd_core_h;
+ uint32_t pmu_pwrmd_cmm_l;
+ uint32_t pmu_pwrmd_cmm_h;
+ uint32_t pmu_wkup_cfg2_l;
+ uint32_t pmu_cru_clksel_con0;
+ uint32_t pmugrf_soc_con0;
+ uint32_t pmusgrf_soc_con0;
+ uint32_t pmic_slp_iomux;
+ uint32_t pgrf_pvtm_con[2];
+ uint32_t cru_clk_gate[CRU_CLKGATES_CON_CNT];
+ uint32_t cru_pmu_clk_gate[CRU_PMU_CLKGATE_CON_CNT];
+ uint32_t cru_plls_con_save[END_PLL_ID][PLL_CON_CNT];
+ uint32_t cpu_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t gpu_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp_128m_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp_rd_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp_wr_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp_m1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vip_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t rga_rd_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t rga_wr_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vop_m0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vop_m1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vpu_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vpu_r128_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t dcf_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t dmac_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t crypto_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t gmac_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t emmc_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t nand_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t sdio_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t sfc_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t sdmmc_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t usb_host_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t usb_otg_qos[CPU_AXI_QOS_NUM_REGS];
+};
+
+static struct px30_sleep_ddr_data ddr_data
+#if USE_COHERENT_MEM
+__attribute__ ((section("tzfw_coherent_mem")))
+#endif
+;
+
+static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id)
+{
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ return cores_pd_cfg_info[cpu_id];
+}
+
+static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value)
+{
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ cores_pd_cfg_info[cpu_id] = value;
+#if !USE_COHERENT_MEM
+ flush_dcache_range((uintptr_t)&cores_pd_cfg_info[cpu_id],
+ sizeof(uint32_t));
+#endif
+}
+
+static inline uint32_t pmu_power_domain_st(uint32_t pd)
+{
+ return mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd) ?
+ pmu_pd_off :
+ pmu_pd_on;
+}
+
+static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
+{
+ uint32_t loop = 0;
+ int ret = 0;
+
+ rockchip_pd_lock_get();
+
+ mmio_write_32(PMU_BASE + PMU_PWRDN_CON,
+ BITS_WITH_WMASK(pd_state, 0x1, pd));
+ dsb();
+
+ while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if (pmu_power_domain_st(pd) != pd_state) {
+ WARN("%s: %d, %d, error!\n", __func__, pd, pd_state);
+ ret = -EINVAL;
+ }
+
+ rockchip_pd_lock_rls();
+
+ return ret;
+}
+
+static inline uint32_t pmu_bus_idle_st(uint32_t bus)
+{
+ return !!((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus)) &&
+ (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus + 16)));
+}
+
+static void pmu_bus_idle_req(uint32_t bus, uint32_t state)
+{
+ uint32_t wait_cnt = 0;
+
+ mmio_write_32(PMU_BASE + PMU_BUS_IDLE_REQ,
+ BITS_WITH_WMASK(state, 0x1, bus));
+
+ while (pmu_bus_idle_st(bus) != state &&
+ wait_cnt < BUS_IDLE_LOOP) {
+ udelay(1);
+ wait_cnt++;
+ }
+
+ if (pmu_bus_idle_st(bus) != state)
+ WARN("%s:idle_st=0x%x, bus_id=%d\n",
+ __func__, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST), bus);
+}
+
+static void qos_save(void)
+{
+ /* scu powerdomain will power off, so cpu qos should be saved */
+ SAVE_QOS(ddr_data.cpu_qos, CPU);
+
+ if (pmu_power_domain_st(PD_GPU) == pmu_pd_on)
+ SAVE_QOS(ddr_data.gpu_qos, GPU);
+ if (pmu_power_domain_st(PD_VI) == pmu_pd_on) {
+ SAVE_QOS(ddr_data.isp_128m_qos, ISP_128M);
+ SAVE_QOS(ddr_data.isp_rd_qos, ISP_RD);
+ SAVE_QOS(ddr_data.isp_wr_qos, ISP_WR);
+ SAVE_QOS(ddr_data.isp_m1_qos, ISP_M1);
+ SAVE_QOS(ddr_data.vip_qos, VIP);
+ }
+ if (pmu_power_domain_st(PD_VO) == pmu_pd_on) {
+ SAVE_QOS(ddr_data.rga_rd_qos, RGA_RD);
+ SAVE_QOS(ddr_data.rga_wr_qos, RGA_WR);
+ SAVE_QOS(ddr_data.vop_m0_qos, VOP_M0);
+ SAVE_QOS(ddr_data.vop_m1_qos, VOP_M1);
+ }
+ if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) {
+ SAVE_QOS(ddr_data.vpu_qos, VPU);
+ SAVE_QOS(ddr_data.vpu_r128_qos, VPU_R128);
+ }
+ if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) {
+ SAVE_QOS(ddr_data.emmc_qos, EMMC);
+ SAVE_QOS(ddr_data.nand_qos, NAND);
+ SAVE_QOS(ddr_data.sdio_qos, SDIO);
+ SAVE_QOS(ddr_data.sfc_qos, SFC);
+ }
+ if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on)
+ SAVE_QOS(ddr_data.gmac_qos, GMAC);
+ if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on)
+ SAVE_QOS(ddr_data.crypto_qos, CRYPTO);
+ if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on)
+ SAVE_QOS(ddr_data.sdmmc_qos, SDMMC);
+ if (pmu_power_domain_st(PD_USB) == pmu_pd_on) {
+ SAVE_QOS(ddr_data.usb_host_qos, USB_HOST);
+ SAVE_QOS(ddr_data.usb_otg_qos, USB_OTG);
+ }
+}
+
+static void qos_restore(void)
+{
+ RESTORE_QOS(ddr_data.cpu_qos, CPU);
+
+ if (pmu_power_domain_st(PD_GPU) == pmu_pd_on)
+ RESTORE_QOS(ddr_data.gpu_qos, GPU);
+ if (pmu_power_domain_st(PD_VI) == pmu_pd_on) {
+ RESTORE_QOS(ddr_data.isp_128m_qos, ISP_128M);
+ RESTORE_QOS(ddr_data.isp_rd_qos, ISP_RD);
+ RESTORE_QOS(ddr_data.isp_wr_qos, ISP_WR);
+ RESTORE_QOS(ddr_data.isp_m1_qos, ISP_M1);
+ RESTORE_QOS(ddr_data.vip_qos, VIP);
+ }
+ if (pmu_power_domain_st(PD_VO) == pmu_pd_on) {
+ RESTORE_QOS(ddr_data.rga_rd_qos, RGA_RD);
+ RESTORE_QOS(ddr_data.rga_wr_qos, RGA_WR);
+ RESTORE_QOS(ddr_data.vop_m0_qos, VOP_M0);
+ RESTORE_QOS(ddr_data.vop_m1_qos, VOP_M1);
+ }
+ if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) {
+ RESTORE_QOS(ddr_data.vpu_qos, VPU);
+ RESTORE_QOS(ddr_data.vpu_r128_qos, VPU_R128);
+ }
+ if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) {
+ RESTORE_QOS(ddr_data.emmc_qos, EMMC);
+ RESTORE_QOS(ddr_data.nand_qos, NAND);
+ RESTORE_QOS(ddr_data.sdio_qos, SDIO);
+ RESTORE_QOS(ddr_data.sfc_qos, SFC);
+ }
+ if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on)
+ RESTORE_QOS(ddr_data.gmac_qos, GMAC);
+ if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on)
+ RESTORE_QOS(ddr_data.crypto_qos, CRYPTO);
+ if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on)
+ RESTORE_QOS(ddr_data.sdmmc_qos, SDMMC);
+ if (pmu_power_domain_st(PD_USB) == pmu_pd_on) {
+ RESTORE_QOS(ddr_data.usb_host_qos, USB_HOST);
+ RESTORE_QOS(ddr_data.usb_otg_qos, USB_OTG);
+ }
+}
+
+static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state)
+{
+ uint32_t state;
+
+ if (pmu_power_domain_st(pd_id) == pd_state)
+ goto out;
+
+ if (pd_state == pmu_pd_on)
+ pmu_power_domain_ctr(pd_id, pd_state);
+
+ state = (pd_state == pmu_pd_off) ? bus_idle : bus_active;
+
+ switch (pd_id) {
+ case PD_GPU:
+ pmu_bus_idle_req(BUS_ID_GPU, state);
+ break;
+ case PD_VI:
+ pmu_bus_idle_req(BUS_ID_VI, state);
+ break;
+ case PD_VO:
+ pmu_bus_idle_req(BUS_ID_VO, state);
+ break;
+ case PD_VPU:
+ pmu_bus_idle_req(BUS_ID_VPU, state);
+ break;
+ case PD_MMC_NAND:
+ pmu_bus_idle_req(BUS_ID_MMC, state);
+ break;
+ case PD_GMAC:
+ pmu_bus_idle_req(BUS_ID_GMAC, state);
+ break;
+ case PD_CRYPTO:
+ pmu_bus_idle_req(BUS_ID_CRYPTO, state);
+ break;
+ case PD_SDCARD:
+ pmu_bus_idle_req(BUS_ID_SDCARD, state);
+ break;
+ case PD_USB:
+ pmu_bus_idle_req(BUS_ID_USB, state);
+ break;
+ default:
+ break;
+ }
+
+ if (pd_state == pmu_pd_off)
+ pmu_power_domain_ctr(pd_id, pd_state);
+
+out:
+ return 0;
+}
+
+static uint32_t pmu_powerdomain_state;
+
+static void pmu_power_domains_suspend(void)
+{
+ uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT];
+
+ clk_gate_con_save(clkgt_save);
+ clk_gate_con_disable();
+ qos_save();
+
+ pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST);
+ pmu_set_power_domain(PD_GPU, pmu_pd_off);
+ pmu_set_power_domain(PD_VI, pmu_pd_off);
+ pmu_set_power_domain(PD_VO, pmu_pd_off);
+ pmu_set_power_domain(PD_VPU, pmu_pd_off);
+ pmu_set_power_domain(PD_MMC_NAND, pmu_pd_off);
+ pmu_set_power_domain(PD_GMAC, pmu_pd_off);
+ pmu_set_power_domain(PD_CRYPTO, pmu_pd_off);
+ pmu_set_power_domain(PD_SDCARD, pmu_pd_off);
+ pmu_set_power_domain(PD_USB, pmu_pd_off);
+
+ clk_gate_con_restore(clkgt_save);
+}
+
+static void pmu_power_domains_resume(void)
+{
+ uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT];
+
+ clk_gate_con_save(clkgt_save);
+ clk_gate_con_disable();
+
+ if (!(pmu_powerdomain_state & BIT(PD_USB)))
+ pmu_set_power_domain(PD_USB, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_SDCARD)))
+ pmu_set_power_domain(PD_SDCARD, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_CRYPTO)))
+ pmu_set_power_domain(PD_CRYPTO, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_GMAC)))
+ pmu_set_power_domain(PD_GMAC, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_MMC_NAND)))
+ pmu_set_power_domain(PD_MMC_NAND, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_VPU)))
+ pmu_set_power_domain(PD_VPU, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_VO)))
+ pmu_set_power_domain(PD_VO, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_VI)))
+ pmu_set_power_domain(PD_VI, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_GPU)))
+ pmu_set_power_domain(PD_GPU, pmu_pd_on);
+
+ qos_restore();
+ clk_gate_con_restore(clkgt_save);
+}
+
+static int check_cpu_wfie(uint32_t cpu)
+{
+ uint32_t loop = 0, wfie_msk = CKECK_WFEI_MSK << cpu;
+
+ while (!(mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) &&
+ (loop < WFEI_CHECK_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if ((mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) == 0) {
+ WARN("%s: %d, %d, error!\n", __func__, cpu, wfie_msk);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ uint32_t cpu_pd, apm_value, cfg_info, loop = 0;
+
+ cpu_pd = PD_CPU0 + cpu_id;
+ cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id);
+
+ if (cfg_info == core_pwr_pd) {
+ /* disable apm cfg */
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ WITH_16BITS_WMSK(CORES_PM_DISABLE));
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ WITH_16BITS_WMSK(CORES_PM_DISABLE));
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ }
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
+ } else {
+ /* wait cpu down */
+ while (pmu_power_domain_st(cpu_pd) == pmu_pd_on && loop < 100) {
+ udelay(2);
+ loop++;
+ }
+
+ /* return error if can't wait cpu down */
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ WARN("%s:can't wait cpu down\n", __func__);
+ return -EINVAL;
+ }
+
+ /* power up cpu in power down state */
+ apm_value = BIT(core_pm_sft_wakeup_en);
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ WITH_16BITS_WMSK(apm_value));
+ }
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
+{
+ uint32_t cpu_pd, apm_value;
+
+ cpu_pd = PD_CPU0 + cpu_id;
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
+ return 0;
+
+ if (pd_cfg == core_pwr_pd) {
+ if (check_cpu_wfie(cpu_id))
+ return -EINVAL;
+ /* disable apm cfg */
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ WITH_16BITS_WMSK(CORES_PM_DISABLE));
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ } else {
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+ apm_value = BIT(core_pm_en) | BIT(core_pm_dis_int);
+ if (pd_cfg == core_pwr_wfi_int)
+ apm_value |= BIT(core_pm_int_wakeup_en);
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ WITH_16BITS_WMSK(apm_value));
+ }
+
+ return 0;
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu;
+
+ boot_cpu = plat_my_core_pos();
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ if (cpu == boot_cpu)
+ continue;
+ cpus_power_domain_off(cpu, core_pwr_pd);
+ }
+}
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr,
+ uint64_t entrypoint)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpu_id] = entrypoint;
+ dsb();
+
+ cpus_power_domain_on(cpu_id);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ WITH_16BITS_WMSK(CORES_PM_DISABLE));
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_off(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
+ cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint();
+ dsb();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_resume(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ /* Disable core_pm */
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ WITH_16BITS_WMSK(CORES_PM_DISABLE));
+
+ return PSCI_E_SUCCESS;
+}
+
+#define CLK_MSK_GATING(msk, con) \
+ mmio_write_32(CRU_BASE + (con), ((msk) << 16) | 0xffff)
+#define CLK_MSK_UNGATING(msk, con) \
+ mmio_write_32(CRU_BASE + (con), ((~(msk)) << 16) | 0xffff)
+
+static uint32_t clk_ungt_msk[CRU_CLKGATES_CON_CNT] = {
+ 0xe0ff, 0xffff, 0x0000, 0x0000,
+ 0x0000, 0x0380, 0x0000, 0x0000,
+ 0x07c0, 0x0000, 0x0000, 0x000f,
+ 0x0061, 0x1f02, 0x0440, 0x1801,
+ 0x004b, 0x0000
+};
+
+static uint32_t clk_pmu_ungt_msk[CRU_PMU_CLKGATE_CON_CNT] = {
+ 0xf1ff, 0x0310
+};
+
+void clk_gate_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) {
+ ddr_data.cru_clk_gate[i] =
+ mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i));
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
+ WITH_16BITS_WMSK(~clk_ungt_msk[i]));
+ }
+
+ for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) {
+ ddr_data.cru_pmu_clk_gate[i] =
+ mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i));
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i),
+ WITH_16BITS_WMSK(~clk_pmu_ungt_msk[i]));
+ }
+}
+
+void clk_gate_resume(void)
+{
+ int i;
+
+ for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i),
+ WITH_16BITS_WMSK(ddr_data.cru_pmu_clk_gate[i]));
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
+ WITH_16BITS_WMSK(ddr_data.cru_clk_gate[i]));
+}
+
+static void pvtm_32k_config(void)
+{
+ uint32_t pvtm_freq_khz, pvtm_div;
+
+ ddr_data.pmu_cru_clksel_con0 =
+ mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0));
+
+ ddr_data.pgrf_pvtm_con[0] =
+ mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON0);
+ ddr_data.pgrf_pvtm_con[1] =
+ mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON1);
+
+ mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
+ BITS_WITH_WMASK(0, 0x3, pgrf_pvtm_st));
+ dsb();
+ mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
+ BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_en));
+ dsb();
+ mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, PVTM_CALC_CNT);
+ dsb();
+
+ mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
+ BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_st));
+
+ /* pmugrf_pvtm_st0 will be clear after PVTM start,
+ * which will cost about 6 cycles of pvtm at least.
+ * So we wait 30 cycles of pvtm for security.
+ */
+ while (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) < 30)
+ ;
+
+ dsb();
+ while (!(mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST0) & 0x1))
+ ;
+
+ pvtm_freq_khz =
+ (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) * 24000 +
+ PVTM_CALC_CNT / 2) / PVTM_CALC_CNT;
+ pvtm_div = (pvtm_freq_khz + 16) / 32;
+
+ /* pvtm_div = div_factor << 2 + 1,
+ * so div_factor = (pvtm_div - 1) >> 2.
+ * But the operation ">> 2" will clear the low bit of pvtm_div,
+ * so we don't have to do "- 1" for compasation
+ */
+ pvtm_div = pvtm_div >> 2;
+ if (pvtm_div > 0x3f)
+ pvtm_div = 0x3f;
+
+ mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
+ BITS_WITH_WMASK(pvtm_div, 0x3f, pgrf_pvtm_div));
+
+ /* select pvtm as 32k source */
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0),
+ BITS_WITH_WMASK(1, 0x3U, 14));
+}
+
+static void pvtm_32k_config_restore(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0),
+ ddr_data.pmu_cru_clksel_con0 | BITS_WMSK(0x3U, 14));
+
+ mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
+ WITH_16BITS_WMSK(ddr_data.pgrf_pvtm_con[0]));
+ mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1,
+ ddr_data.pgrf_pvtm_con[1]);
+}
+
+static void ddr_sleep_config(void)
+{
+ /* disable ddr pd, sr */
+ ddr_data.ddrc_pwrctrl = mmio_read_32(DDR_UPCTL_BASE + 0x30);
+ mmio_write_32(DDR_UPCTL_BASE + 0x30, BITS_WITH_WMASK(0x0, 0x3, 0));
+
+ /* disable ddr auto gt */
+ ddr_data.ddrgrf_con1 = mmio_read_32(DDRGRF_BASE + 0x4);
+ mmio_write_32(DDRGRF_BASE + 0x4, BITS_WITH_WMASK(0x0, 0x1f, 0));
+
+ /* disable ddr standby */
+ ddr_data.ddrstdby_con0 = mmio_read_32(DDR_STDBY_BASE + 0x0);
+ mmio_write_32(DDR_STDBY_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 0));
+ while ((mmio_read_32(DDR_UPCTL_BASE + 0x4) & 0x7) != 1)
+ ;
+
+ /* ddr pmu ctrl */
+ ddr_data.ddrgrf_con0 = mmio_read_32(DDRGRF_BASE + 0x0);
+ mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 5));
+ dsb();
+ mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x1, 0x1, 4));
+
+ /* ddr ret sel */
+ ddr_data.pmugrf_soc_con0 =
+ mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(0));
+ mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0),
+ BITS_WITH_WMASK(0x0, 0x1, 12));
+}
+
+static void ddr_sleep_config_restore(void)
+{
+ /* restore ddr ret sel */
+ mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0),
+ ddr_data.pmugrf_soc_con0 | BITS_WMSK(0x1, 12));
+
+ /* restore ddr pmu ctrl */
+ mmio_write_32(DDRGRF_BASE + 0x0,
+ ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 4));
+ dsb();
+ mmio_write_32(DDRGRF_BASE + 0x0,
+ ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 5));
+
+ /* restore ddr standby */
+ mmio_write_32(DDR_STDBY_BASE + 0x0,
+ ddr_data.ddrstdby_con0 | BITS_WMSK(0x1, 0));
+
+ /* restore ddr auto gt */
+ mmio_write_32(DDRGRF_BASE + 0x4,
+ ddr_data.ddrgrf_con1 | BITS_WMSK(0x1f, 0));
+
+ /* restore ddr pd, sr */
+ mmio_write_32(DDR_UPCTL_BASE + 0x30,
+ ddr_data.ddrc_pwrctrl | BITS_WMSK(0x3, 0));
+}
+
+static void pmu_sleep_config(void)
+{
+ uint32_t pwrmd_core_lo, pwrmd_core_hi, pwrmd_com_lo, pwrmd_com_hi;
+ uint32_t pmu_wkup_cfg2_lo;
+ uint32_t clk_freq_khz;
+
+ /* save pmic_sleep iomux gpio0_a4 */
+ ddr_data.pmic_slp_iomux = mmio_read_32(PMUGRF_BASE + GPIO0A_IOMUX);
+
+ ddr_data.pmu_pwrmd_core_l =
+ mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_LO);
+ ddr_data.pmu_pwrmd_core_h =
+ mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_HI);
+ ddr_data.pmu_pwrmd_cmm_l =
+ mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO);
+ ddr_data.pmu_pwrmd_cmm_h =
+ mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI);
+ ddr_data.pmu_wkup_cfg2_l = mmio_read_32(PMU_BASE + PMU_WKUP_CFG2_LO);
+
+ pwrmd_core_lo = BIT(pmu_global_int_dis) |
+ BIT(pmu_core_src_gt) |
+ BIT(pmu_cpu0_pd) |
+ BIT(pmu_clr_core) |
+ BIT(pmu_scu_pd) |
+ BIT(pmu_l2_idle) |
+ BIT(pmu_l2_flush) |
+ BIT(pmu_clr_bus2main) |
+ BIT(pmu_clr_peri2msch);
+
+ pwrmd_core_hi = BIT(pmu_dpll_pd_en) |
+ BIT(pmu_apll_pd_en) |
+ BIT(pmu_cpll_pd_en) |
+ BIT(pmu_gpll_pd_en) |
+ BIT(pmu_npll_pd_en);
+
+ pwrmd_com_lo = BIT(pmu_mode_en) |
+ BIT(pmu_pll_pd) |
+ BIT(pmu_pmu_use_if) |
+ BIT(pmu_alive_use_if) |
+ BIT(pmu_osc_dis) |
+ BIT(pmu_sref_enter) |
+ BIT(pmu_ddrc_gt) |
+ BIT(pmu_clr_pmu) |
+ BIT(pmu_clr_peri_pmu);
+
+ pwrmd_com_hi = BIT(pmu_clr_bus) |
+ BIT(pmu_clr_msch) |
+ BIT(pmu_wakeup_begin_cfg);
+
+ pmu_wkup_cfg2_lo = BIT(pmu_cluster_wkup_en) |
+ BIT(pmu_gpio_wkup_en) |
+ BIT(pmu_timer_wkup_en);
+
+ /* set pmic_sleep iomux gpio0_a4 */
+ mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX,
+ BITS_WITH_WMASK(1, 0x3, 8));
+
+ clk_freq_khz = 32;
+
+ mmio_write_32(PMU_BASE + PMU_OSC_CNT_LO,
+ WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff));
+ mmio_write_32(PMU_BASE + PMU_OSC_CNT_HI,
+ WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16));
+
+ mmio_write_32(PMU_BASE + PMU_STABLE_CNT_LO,
+ WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff));
+ mmio_write_32(PMU_BASE + PMU_STABLE_CNT_HI,
+ WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16));
+
+ mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_LO,
+ WITH_16BITS_WMSK(clk_freq_khz * 2 & 0xffff));
+ mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_HI,
+ WITH_16BITS_WMSK(clk_freq_khz * 2 >> 16));
+
+ /* Pmu's clk has switched to 24M back When pmu FSM counts
+ * the follow counters, so we should use 24M to calculate
+ * these counters.
+ */
+ mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_LO,
+ WITH_16BITS_WMSK(24000 * 2 & 0xffff));
+ mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_HI,
+ WITH_16BITS_WMSK(24000 * 2 >> 16));
+
+ mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_LO,
+ WITH_16BITS_WMSK(24000 * 2 & 0xffff));
+ mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_HI,
+ WITH_16BITS_WMSK(24000 * 2 >> 16));
+
+ mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_LO,
+ WITH_16BITS_WMSK(24000 * 5 & 0xffff));
+ mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_HI,
+ WITH_16BITS_WMSK(24000 * 5 >> 16));
+
+ mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_LO,
+ WITH_16BITS_WMSK(24000 * 2 & 0xffff));
+ mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_HI,
+ WITH_16BITS_WMSK(24000 * 2 >> 16));
+
+ /* Config pmu power mode and pmu wakeup source */
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO,
+ WITH_16BITS_WMSK(pwrmd_core_lo));
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI,
+ WITH_16BITS_WMSK(pwrmd_core_hi));
+
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO,
+ WITH_16BITS_WMSK(pwrmd_com_lo));
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI,
+ WITH_16BITS_WMSK(pwrmd_com_hi));
+
+ mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO,
+ WITH_16BITS_WMSK(pmu_wkup_cfg2_lo));
+}
+
+static void pmu_sleep_restore(void)
+{
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO,
+ WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_l));
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI,
+ WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_h));
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO,
+ WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_l));
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI,
+ WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_h));
+ mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO,
+ WITH_16BITS_WMSK(ddr_data.pmu_wkup_cfg2_l));
+
+ /* restore pmic_sleep iomux */
+ mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX,
+ WITH_16BITS_WMSK(ddr_data.pmic_slp_iomux));
+}
+
+static void soc_sleep_config(void)
+{
+ ddr_data.gpio0c_iomux = mmio_read_32(PMUGRF_BASE + GPIO0C_IOMUX);
+
+ pmu_sleep_config();
+
+ ddr_sleep_config();
+
+ pvtm_32k_config();
+}
+
+static void soc_sleep_restore(void)
+{
+ secure_timer_init();
+
+ pvtm_32k_config_restore();
+
+ ddr_sleep_config_restore();
+
+ pmu_sleep_restore();
+
+ mmio_write_32(PMUGRF_BASE + GPIO0C_IOMUX,
+ WITH_16BITS_WMSK(ddr_data.gpio0c_iomux));
+}
+
+static inline void pm_pll_wait_lock(uint32_t pll_base, uint32_t pll_id)
+{
+ uint32_t delay = PLL_LOCKED_TIMEOUT;
+
+ while (delay > 0) {
+ if (mmio_read_32(pll_base + PLL_CON(1)) &
+ PLL_LOCK_MSK)
+ break;
+ delay--;
+ }
+
+ if (delay == 0)
+ ERROR("Can't wait pll:%d lock\n", pll_id);
+}
+
+static inline void pll_pwr_ctr(uint32_t pll_base, uint32_t pll_id, uint32_t pd)
+{
+ mmio_write_32(pll_base + PLL_CON(1),
+ BITS_WITH_WMASK(1, 1U, 15));
+ if (pd)
+ mmio_write_32(pll_base + PLL_CON(1),
+ BITS_WITH_WMASK(1, 1, 14));
+ else
+ mmio_write_32(pll_base + PLL_CON(1),
+ BITS_WITH_WMASK(0, 1, 14));
+}
+
+static inline void pll_set_mode(uint32_t pll_id, uint32_t mode)
+{
+ uint32_t val = BITS_WITH_WMASK(mode, 0x3, PLL_MODE_SHIFT(pll_id));
+
+ if (pll_id != GPLL_ID)
+ mmio_write_32(CRU_BASE + CRU_MODE, val);
+ else
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_MODE,
+ BITS_WITH_WMASK(mode, 0x3, 0));
+}
+
+static inline void pll_suspend(uint32_t pll_id)
+{
+ int i;
+ uint32_t pll_base;
+
+ if (pll_id != GPLL_ID)
+ pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0);
+ else
+ pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0);
+
+ /* save pll con */
+ for (i = 0; i < PLL_CON_CNT; i++)
+ ddr_data.cru_plls_con_save[pll_id][i] =
+ mmio_read_32(pll_base + PLL_CON(i));
+
+ /* slow mode */
+ pll_set_mode(pll_id, SLOW_MODE);
+}
+
+static inline void pll_resume(uint32_t pll_id)
+{
+ uint32_t mode, pll_base;
+
+ if (pll_id != GPLL_ID) {
+ pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0);
+ mode = (ddr_data.cru_mode_save >> PLL_MODE_SHIFT(pll_id)) & 0x3;
+ } else {
+ pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0);
+ mode = ddr_data.cru_pmu_mode_save & 0x3;
+ }
+
+ /* if pll locked before suspend, we should wait atfer resume */
+ if (ddr_data.cru_plls_con_save[pll_id][1] & PLL_LOCK_MSK)
+ pm_pll_wait_lock(pll_base, pll_id);
+
+ pll_set_mode(pll_id, mode);
+}
+
+static void pm_plls_suspend(void)
+{
+ ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_MODE);
+ ddr_data.cru_pmu_mode_save = mmio_read_32(PMUCRU_BASE + CRU_PMU_MODE);
+ ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(0));
+
+ pll_suspend(GPLL_ID);
+ pll_suspend(NPLL_ID);
+ pll_suspend(CPLL_ID);
+ pll_suspend(APLL_ID);
+
+ /* core */
+ mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
+ BITS_WITH_WMASK(0, 0xf, 0));
+
+ /* pclk_dbg */
+ mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
+ BITS_WITH_WMASK(0, 0xf, 8));
+}
+
+static void pm_plls_resume(void)
+{
+ /* pclk_dbg */
+ mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
+ ddr_data.clk_sel0 | BITS_WMSK(0xf, 8));
+
+ /* core */
+ mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
+ ddr_data.clk_sel0 | BITS_WMSK(0xf, 0));
+
+ pll_resume(APLL_ID);
+ pll_resume(CPLL_ID);
+ pll_resume(NPLL_ID);
+ pll_resume(GPLL_ID);
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ pmu_power_domains_suspend();
+
+ clk_gate_suspend();
+
+ soc_sleep_config();
+
+ pm_plls_suspend();
+
+ psram_boot_cfg->pm_flag &= ~PM_WARM_BOOT_BIT;
+
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ psram_boot_cfg->pm_flag |= PM_WARM_BOOT_BIT;
+
+ pm_plls_resume();
+
+ soc_sleep_restore();
+
+ clk_gate_resume();
+
+ pmu_power_domains_resume();
+
+ plat_rockchip_gic_cpuif_enable();
+
+ return 0;
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ pll_set_mode(GPLL_ID, SLOW_MODE);
+ pll_set_mode(CPLL_ID, SLOW_MODE);
+ pll_set_mode(NPLL_ID, SLOW_MODE);
+ pll_set_mode(APLL_ID, SLOW_MODE);
+ dsb();
+
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE);
+ dsb();
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to execute valid codes.
+ */
+ psci_power_down_wfi();
+}
+
+void __dead2 rockchip_soc_system_off(void)
+{
+ uint32_t val;
+
+ /* set pmic_sleep pin(gpio0_a4) to gpio mode */
+ mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, BITS_WITH_WMASK(0, 0x3, 8));
+
+ /* config output */
+ val = mmio_read_32(GPIO0_BASE + SWPORTA_DDR);
+ val |= BIT(4);
+ mmio_write_32(GPIO0_BASE + SWPORTA_DDR, val);
+
+ /* config output high level */
+ val = mmio_read_32(GPIO0_BASE);
+ val |= BIT(4);
+ mmio_write_32(GPIO0_BASE, val);
+ dsb();
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to execute valid codes.
+ */
+ psci_power_down_wfi();
+}
+
+void rockchip_plat_mmu_el3(void)
+{
+ /* TODO: support the el3 for px30 SoCs */
+}
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ rockchip_pd_lock_init();
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ psram_boot_cfg->ddr_func = (uint64_t)0;
+ psram_boot_cfg->ddr_data = (uint64_t)0;
+ psram_boot_cfg->sp = PSRAM_SP_TOP;
+ psram_boot_cfg->ddr_flag = 0x0;
+ psram_boot_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
+ psram_boot_cfg->pm_flag = PM_WARM_BOOT_BIT;
+
+ nonboot_cpus_off();
+
+ /* Remap pmu_sram's base address to boot address */
+ mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0),
+ BITS_WITH_WMASK(1, 0x1, 13));
+
+ INFO("%s: pd status %x\n",
+ __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/px30/drivers/pmu/pmu.h b/plat/rockchip/px30/drivers/pmu/pmu.h
new file mode 100644
index 0000000..416d1c1
--- /dev/null
+++ b/plat/rockchip/px30/drivers/pmu/pmu.h
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PMU_H__
+#define __PMU_H__
+
+/* Needed aligned 16 bytes for sp stack top */
+#define PSRAM_SP_TOP ((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf)
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WKUP_CFG0_LO 0x00
+#define PMU_WKUP_CFG0_HI 0x04
+#define PMU_WKUP_CFG1_LO 0x08
+#define PMU_WKUP_CFG1_HI 0x0c
+#define PMU_WKUP_CFG2_LO 0x10
+
+#define PMU_PWRDN_CON 0x18
+#define PMU_PWRDN_ST 0x20
+
+#define PMU_PWRMODE_CORE_LO 0x24
+#define PMU_PWRMODE_CORE_HI 0x28
+#define PMU_PWRMODE_COMMON_CON_LO 0x2c
+#define PMU_PWRMODE_COMMON_CON_HI 0x30
+
+#define PMU_SFT_CON 0x34
+#define PMU_INT_ST 0x44
+#define PMU_BUS_IDLE_REQ 0x64
+#define PMU_BUS_IDLE_ST 0x6c
+
+#define PMU_OSC_CNT_LO 0x74
+#define PMU_OSC_CNT_HI 0x78
+#define PMU_PLLLOCK_CNT_LO 0x7c
+#define PMU_PLLLOCK_CNT_HI 0x80
+#define PMU_PLLRST_CNT_LO 0x84
+#define PMU_PLLRST_CNT_HI 0x88
+#define PMU_STABLE_CNT_LO 0x8c
+#define PMU_STABLE_CNT_HI 0x90
+#define PMU_WAKEUP_RST_CLR_LO 0x9c
+#define PMU_WAKEUP_RST_CLR_HI 0xa0
+
+#define PMU_DDR_SREF_ST 0xa4
+
+#define PMU_SYS_REG0_LO 0xa8
+#define PMU_SYS_REG0_HI 0xac
+#define PMU_SYS_REG1_LO 0xb0
+#define PMU_SYS_REG1_HI 0xb4
+#define PMU_SYS_REG2_LO 0xb8
+#define PMU_SYS_REG2_HI 0xbc
+#define PMU_SYS_REG3_LO 0xc0
+#define PMU_SYS_REG3_HI 0xc4
+
+#define PMU_SCU_PWRDN_CNT_LO 0xc8
+#define PMU_SCU_PWRDN_CNT_HI 0xcc
+#define PMU_SCU_PWRUP_CNT_LO 0xd0
+#define PMU_SCU_PWRUP_CNT_HI 0xd4
+
+#define PMU_TIMEOUT_CNT_LO 0xd8
+#define PMU_TIMEOUT_CNT_HI 0xdc
+
+#define PMU_CPUAPM_CON(cpu) (0xe0 + (cpu) * 0x4)
+
+#define CORES_PM_DISABLE 0x0
+#define CLST_CPUS_MSK 0xf
+
+#define PD_CTR_LOOP 500
+#define PD_CHECK_LOOP 500
+#define WFEI_CHECK_LOOP 500
+#define BUS_IDLE_LOOP 1000
+
+enum pmu_wkup_cfg2 {
+ pmu_cluster_wkup_en = 0,
+ pmu_gpio_wkup_en = 2,
+ pmu_sdio_wkup_en = 3,
+ pmu_sdmmc_wkup_en = 4,
+ pmu_uart0_wkup_en = 5,
+ pmu_timer_wkup_en = 6,
+ pmu_usbdev_wkup_en = 7,
+ pmu_sft_wkup_en = 8,
+ pmu_timeout_wkup_en = 10,
+};
+
+enum pmu_powermode_core_lo {
+ pmu_global_int_dis = 0,
+ pmu_core_src_gt = 1,
+ pmu_cpu0_pd = 3,
+ pmu_clr_core = 5,
+ pmu_scu_pd = 6,
+ pmu_l2_idle = 8,
+ pmu_l2_flush = 9,
+ pmu_clr_bus2main = 10,
+ pmu_clr_peri2msch = 11,
+};
+
+enum pmu_powermode_core_hi {
+ pmu_apll_pd_en = 3,
+ pmu_dpll_pd_en = 4,
+ pmu_cpll_pd_en = 5,
+ pmu_gpll_pd_en = 6,
+ pmu_npll_pd_en = 7,
+};
+
+enum pmu_powermode_common_lo {
+ pmu_mode_en = 0,
+ pmu_ddr_pd_en = 1,
+ pmu_wkup_rst = 3,
+ pmu_pll_pd = 4,
+ pmu_pmu_use_if = 6,
+ pmu_alive_use_if = 7,
+ pmu_osc_dis = 8,
+ pmu_input_clamp = 9,
+ pmu_sref_enter = 10,
+ pmu_ddrc_gt = 11,
+ pmu_ddrio_ret = 12,
+ pmu_ddrio_ret_deq = 13,
+ pmu_clr_pmu = 14,
+ pmu_clr_peri_pmu = 15,
+};
+
+enum pmu_powermode_common_hi {
+ pmu_clr_bus = 0,
+ pmu_clr_mmc = 1,
+ pmu_clr_msch = 2,
+ pmu_clr_nandc = 3,
+ pmu_clr_gmac = 4,
+ pmu_clr_vo = 5,
+ pmu_clr_vi = 6,
+ pmu_clr_gpu = 7,
+ pmu_clr_usb = 8,
+ pmu_clr_vpu = 9,
+ pmu_clr_crypto = 10,
+ pmu_wakeup_begin_cfg = 11,
+ pmu_peri_clk_src_gt = 12,
+ pmu_bus_clk_src_gt = 13,
+};
+
+enum pmu_pd_id {
+ PD_CPU0 = 0,
+ PD_CPU1 = 1,
+ PD_CPU2 = 2,
+ PD_CPU3 = 3,
+ PD_SCU = 4,
+ PD_USB = 5,
+ PD_DDR = 6,
+ PD_SDCARD = 8,
+ PD_CRYPTO = 9,
+ PD_GMAC = 10,
+ PD_MMC_NAND = 11,
+ PD_VPU = 12,
+ PD_VO = 13,
+ PD_VI = 14,
+ PD_GPU = 15,
+ PD_END = 16,
+};
+
+enum pmu_bus_id {
+ BUS_ID_BUS = 0,
+ BUS_ID_BUS2MAIN = 1,
+ BUS_ID_GPU = 2,
+ BUS_ID_CORE = 3,
+ BUS_ID_CRYPTO = 4,
+ BUS_ID_MMC = 5,
+ BUS_ID_GMAC = 6,
+ BUS_ID_VO = 7,
+ BUS_ID_VI = 8,
+ BUS_ID_SDCARD = 9,
+ BUS_ID_USB = 10,
+ BUS_ID_MSCH = 11,
+ BUS_ID_PERI = 12,
+ BUS_ID_PMU = 13,
+ BUS_ID_VPU = 14,
+ BUS_ID_PERI2MSCH = 15,
+};
+
+enum pmu_pd_state {
+ pmu_pd_on = 0,
+ pmu_pd_off = 1
+};
+
+enum pmu_bus_state {
+ bus_active = 0,
+ bus_idle = 1,
+};
+
+enum cores_pm_ctr_mode {
+ core_pwr_pd = 0,
+ core_pwr_wfi = 1,
+ core_pwr_wfi_int = 2
+};
+
+enum pmu_cores_pm_by_wfi {
+ core_pm_en = 0,
+ core_pm_int_wakeup_en,
+ core_pm_dis_int,
+ core_pm_sft_wakeup_en
+};
+
+/*****************************************************************************
+ * pmu_sgrf
+ *****************************************************************************/
+#define PMUSGRF_SOC_CON(i) ((i) * 0x4)
+
+/*****************************************************************************
+ * pmu_grf
+ *****************************************************************************/
+#define GPIO0A_IOMUX 0x0
+#define GPIO0B_IOMUX 0x4
+#define GPIO0C_IOMUX 0x8
+#define GPIO0A_PULL 0x10
+
+#define GPIO0L_SMT 0x38
+#define GPIO0H_SMT 0x3c
+
+#define PMUGRF_SOC_CON(i) (0x100 + (i) * 4)
+
+#define PMUGRF_PVTM_CON0 0x180
+#define PMUGRF_PVTM_CON1 0x184
+#define PMUGRF_PVTM_ST0 0x190
+#define PMUGRF_PVTM_ST1 0x194
+
+#define PVTM_CALC_CNT 0x200
+
+#define PMUGRF_OS_REG(n) (0x200 + (n) * 4)
+
+#define GPIO0A6_IOMUX_MSK (0x3 << 12)
+#define GPIO0A6_IOMUX_GPIO (0x0 << 12)
+#define GPIO0A6_IOMUX_RSTOUT (0x1 << 12)
+#define GPIO0A6_IOMUX_SHTDN (0x2 << 12)
+
+enum px30_pmugrf_pvtm_con0 {
+ pgrf_pvtm_st = 0,
+ pgrf_pvtm_en = 1,
+ pgrf_pvtm_div = 2,
+};
+
+/*****************************************************************************
+ * pmu_cru
+ *****************************************************************************/
+#define CRU_PMU_MODE 0x20
+#define CRU_PMU_CLKSEL_CON 0x40
+#define CRU_PMU_CLKSELS_CON(i) (CRU_PMU_CLKSEL_CON + (i) * 4)
+#define CRU_PMU_CLKSEL_CON_CNT 5
+#define CRU_PMU_CLKGATE_CON 0x80
+#define CRU_PMU_CLKGATES_CON(i) (CRU_PMU_CLKGATE_CON + (i) * 4)
+#define CRU_PMU_CLKGATE_CON_CNT 2
+#define CRU_PMU_ATCS_CON 0xc0
+#define CRU_PMU_ATCSS_CON(i) (CRU_PMU_ATCS_CON + (i) * 4)
+#define CRU_PMU_ATCS_CON_CNT 2
+
+/*****************************************************************************
+ * pmusgrf
+ *****************************************************************************/
+#define PMUSGRF_RSTOUT_EN (0x7 << 10)
+#define PMUSGRF_RSTOUT_FST 10
+#define PMUSGRF_RSTOUT_TSADC 11
+#define PMUSGRF_RSTOUT_WDT 12
+
+#define PMUGRF_SOC_CON2_US_WMSK (0x1fff << 16)
+#define PMUGRF_SOC_CON2_MAX_341US 0x1fff
+#define PMUGRF_SOC_CON2_200US 0x12c0
+
+#define PMUGRF_FAILSAFE_SHTDN_TSADC BIT(0)
+#define PMUGRF_FAILSAFE_SHTDN_WDT BIT(1)
+
+/*****************************************************************************
+ * QOS
+ *****************************************************************************/
+#define CPU_AXI_QOS_ID_COREID 0x00
+#define CPU_AXI_QOS_REVISIONID 0x04
+#define CPU_AXI_QOS_PRIORITY 0x08
+#define CPU_AXI_QOS_MODE 0x0c
+#define CPU_AXI_QOS_BANDWIDTH 0x10
+#define CPU_AXI_QOS_SATURATION 0x14
+#define CPU_AXI_QOS_EXTCONTROL 0x18
+#define CPU_AXI_QOS_NUM_REGS 0x07
+
+#define CPU_AXI_CPU_QOS_BASE 0xff508000
+#define CPU_AXI_GPU_QOS_BASE 0xff520000
+#define CPU_AXI_ISP_128M_QOS_BASE 0xff548000
+#define CPU_AXI_ISP_RD_QOS_BASE 0xff548080
+#define CPU_AXI_ISP_WR_QOS_BASE 0xff548100
+#define CPU_AXI_ISP_M1_QOS_BASE 0xff548180
+#define CPU_AXI_VIP_QOS_BASE 0xff548200
+#define CPU_AXI_RGA_RD_QOS_BASE 0xff550000
+#define CPU_AXI_RGA_WR_QOS_BASE 0xff550080
+#define CPU_AXI_VOP_M0_QOS_BASE 0xff550100
+#define CPU_AXI_VOP_M1_QOS_BASE 0xff550180
+#define CPU_AXI_VPU_QOS_BASE 0xff558000
+#define CPU_AXI_VPU_R128_QOS_BASE 0xff558080
+#define CPU_AXI_DCF_QOS_BASE 0xff500000
+#define CPU_AXI_DMAC_QOS_BASE 0xff500080
+#define CPU_AXI_CRYPTO_QOS_BASE 0xff510000
+#define CPU_AXI_GMAC_QOS_BASE 0xff518000
+#define CPU_AXI_EMMC_QOS_BASE 0xff538000
+#define CPU_AXI_NAND_QOS_BASE 0xff538080
+#define CPU_AXI_SDIO_QOS_BASE 0xff538100
+#define CPU_AXI_SFC_QOS_BASE 0xff538180
+#define CPU_AXI_SDMMC_QOS_BASE 0xff52c000
+#define CPU_AXI_USB_HOST_QOS_BASE 0xff540000
+#define CPU_AXI_USB_OTG_QOS_BASE 0xff540080
+
+#define PX30_CPU_AXI_SAVE_QOS(array, base) do { \
+ array[0] = mmio_read_32(base + CPU_AXI_QOS_ID_COREID); \
+ array[1] = mmio_read_32(base + CPU_AXI_QOS_REVISIONID); \
+ array[2] = mmio_read_32(base + CPU_AXI_QOS_PRIORITY); \
+ array[3] = mmio_read_32(base + CPU_AXI_QOS_MODE); \
+ array[4] = mmio_read_32(base + CPU_AXI_QOS_BANDWIDTH); \
+ array[5] = mmio_read_32(base + CPU_AXI_QOS_SATURATION); \
+ array[6] = mmio_read_32(base + CPU_AXI_QOS_EXTCONTROL); \
+} while (0)
+
+#define PX30_CPU_AXI_RESTORE_QOS(array, base) do { \
+ mmio_write_32(base + CPU_AXI_QOS_ID_COREID, array[0]); \
+ mmio_write_32(base + CPU_AXI_QOS_REVISIONID, array[1]); \
+ mmio_write_32(base + CPU_AXI_QOS_PRIORITY, array[2]); \
+ mmio_write_32(base + CPU_AXI_QOS_MODE, array[3]); \
+ mmio_write_32(base + CPU_AXI_QOS_BANDWIDTH, array[4]); \
+ mmio_write_32(base + CPU_AXI_QOS_SATURATION, array[5]); \
+ mmio_write_32(base + CPU_AXI_QOS_EXTCONTROL, array[6]); \
+} while (0)
+
+#define SAVE_QOS(array, NAME) \
+ PX30_CPU_AXI_SAVE_QOS(array, CPU_AXI_##NAME##_QOS_BASE)
+#define RESTORE_QOS(array, NAME) \
+ PX30_CPU_AXI_RESTORE_QOS(array, CPU_AXI_##NAME##_QOS_BASE)
+
+#endif /* __PMU_H__ */
diff --git a/plat/rockchip/px30/drivers/secure/secure.c b/plat/rockchip/px30/drivers/secure/secure.c
new file mode 100644
index 0000000..144f945
--- /dev/null
+++ b/plat/rockchip/px30/drivers/secure/secure.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <ddr_parameter.h>
+#include <plat_private.h>
+#include <secure.h>
+#include <px30_def.h>
+
+/**
+ * There are 8 regions for DDR security control
+ * @rgn - the DDR regions 0 ~ 7 which are can be configured.
+ * @st - start address to set as secure
+ * @sz - length of area to set as secure
+ * The internal unit is megabytes, so memory areas need to be aligned
+ * to megabyte borders.
+ */
+static void secure_ddr_region(uint32_t rgn,
+ uintptr_t st, size_t sz)
+{
+ uintptr_t ed = st + sz;
+ uintptr_t st_mb, ed_mb;
+ uint32_t val;
+
+ assert(rgn <= 7);
+ assert(st < ed);
+
+ /* check aligned 1MB */
+ assert(st % SIZE_M(1) == 0);
+ assert(ed % SIZE_M(1) == 0);
+
+ st_mb = st / SIZE_M(1);
+ ed_mb = ed / SIZE_M(1);
+
+ /* map top and base */
+ mmio_write_32(FIREWALL_DDR_BASE +
+ FIREWALL_DDR_FW_DDR_RGN(rgn),
+ RG_MAP_SECURE(ed_mb, st_mb));
+
+ /* enable secure */
+ val = mmio_read_32(FIREWALL_DDR_BASE + FIREWALL_DDR_FW_DDR_CON_REG);
+ val |= BIT(rgn);
+ mmio_write_32(FIREWALL_DDR_BASE +
+ FIREWALL_DDR_FW_DDR_CON_REG, val);
+}
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG,
+ TIMER_DIS);
+
+ mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOAD_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOAD_COUNT1, 0xffffffff);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG,
+ TIMER_EN | TIMER_FMODE);
+}
+
+void sgrf_init(void)
+{
+#ifdef PLAT_RK_SECURE_DDR_MINILOADER
+ uint32_t i;
+ struct param_ddr_usage usg;
+
+ /* general secure regions */
+ usg = ddr_region_usage_parse(DDR_PARAM_BASE,
+ PLAT_MAX_DDR_CAPACITY_MB);
+
+ /* region-0 for TF-A, region-1 for optional OP-TEE */
+ assert(usg.s_nr < 7);
+
+ for (i = 0; i < usg.s_nr; i++)
+ secure_ddr_region(7 - i, usg.s_top[i], usg.s_base[i]);
+#endif
+
+ /* secure the trustzone ram */
+ secure_ddr_region(0, TZRAM_BASE, TZRAM_SIZE);
+
+ /* set all slave ip into no-secure, except stimer */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4), SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(8), 0x00030000);
+
+ /* set master crypto to no-secure, dcf to secure */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), 0x000f0003);
+
+ /* set DMAC into no-secure */
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(0), DMA_IRQ_BOOT_NS);
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(1), DMA_PERI_CH_NS_15_0);
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(2), DMA_PERI_CH_NS_19_16);
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(3), DMA_MANAGER_BOOT_NS);
+
+ /* soft reset dma before use */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), DMA_SOFTRST_REQ);
+ udelay(5);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), DMA_SOFTRST_RLS);
+}
diff --git a/plat/rockchip/px30/drivers/secure/secure.h b/plat/rockchip/px30/drivers/secure/secure.h
new file mode 100644
index 0000000..498027d
--- /dev/null
+++ b/plat/rockchip/px30/drivers/secure/secure.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SECURE_H
+#define SECURE_H
+
+/***************************************************************************
+ * SGRF
+ ***************************************************************************/
+#define SGRF_SOC_CON(i) ((i) * 0x4)
+#define SGRF_DMAC_CON(i) (0x30 + (i) * 0x4)
+
+#define SGRF_MST_S_ALL_NS 0xffffffff
+#define SGRF_SLV_S_ALL_NS 0xffff0000
+#define DMA_IRQ_BOOT_NS 0xffffffff
+#define DMA_PERI_CH_NS_15_0 0xffffffff
+#define DMA_PERI_CH_NS_19_16 0x000f000f
+#define DMA_MANAGER_BOOT_NS 0x00010001
+#define DMA_SOFTRST_REQ BITS_WITH_WMASK(1, 0x1, 12)
+#define DMA_SOFTRST_RLS BITS_WITH_WMASK(0, 0x1, 12)
+
+/***************************************************************************
+ * DDR FIREWALL
+ ***************************************************************************/
+#define FIREWALL_DDR_FW_DDR_RGN(i) ((i) * 0x4)
+#define FIREWALL_DDR_FW_DDR_MST(i) (0x20 + (i) * 0x4)
+#define FIREWALL_DDR_FW_DDR_CON_REG 0x40
+#define FIREWALL_DDR_FW_DDR_RGN_NUM 8
+#define FIREWALL_DDR_FW_DDR_MST_NUM 6
+
+#define PLAT_MAX_DDR_CAPACITY_MB 4096
+#define RG_MAP_SECURE(top, base) ((((top) - 1) << 16) | (base))
+
+/**************************************************
+ * secure timer
+ **************************************************/
+
+/* chanal0~5 */
+#define STIMER_CHN_BASE(n) (STIME_BASE + 0x20 * (n))
+
+#define TIMER_LOAD_COUNT0 0x0
+#define TIMER_LOAD_COUNT1 0x4
+
+#define TIMER_CUR_VALUE0 0x8
+#define TIMER_CUR_VALUE1 0xc
+
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INTSTATUS 0x18
+
+#define TIMER_DIS 0x0
+#define TIMER_EN 0x1
+
+#define TIMER_FMODE (0x0 << 1)
+#define TIMER_RMODE (0x1 << 1)
+
+#define TIMER_LOAD_COUNT0_MSK (0xffffffff)
+#define TIMER_LOAD_COUNT1_MSK (0xffffffff00000000)
+
+void secure_timer_init(void);
+void sgrf_init(void);
+
+#endif /* SECURE_H */
diff --git a/plat/rockchip/px30/drivers/soc/soc.c b/plat/rockchip/px30/drivers/soc/soc.c
new file mode 100644
index 0000000..200563d
--- /dev/null
+++ b/plat/rockchip/px30/drivers/soc/soc.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+#include <pmu.h>
+#include <px30_def.h>
+#include <secure.h>
+#include <soc.h>
+#include <rockchip_sip_svc.h>
+
+/* Aggregate of all devices in the first GB */
+#define PX30_DEV_RNG0_BASE 0xff000000
+#define PX30_DEV_RNG0_SIZE 0x00ff0000
+
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(PX30_DEV_RNG0_BASE, PX30_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SHARE_MEM_BASE, SHARE_MEM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PARAM_BASE, DDR_PARAM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+void clk_gate_con_save(uint32_t *clkgt_save)
+{
+ uint32_t i, j;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ clkgt_save[i] =
+ mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i));
+ j = i;
+ for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++, j++)
+ clkgt_save[j] =
+ mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i));
+}
+
+void clk_gate_con_restore(uint32_t *clkgt_save)
+{
+ uint32_t i, j;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
+ WITH_16BITS_WMSK(clkgt_save[i]));
+
+ j = i;
+ for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i),
+ WITH_16BITS_WMSK(clkgt_save[j]));
+}
+
+void clk_gate_con_disable(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
+ 0xffff0000);
+
+ for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i),
+ 0xffff0000);
+}
+
+static void soc_reset_config_all(void)
+{
+ uint32_t tmp;
+
+ /* tsadc and wdt can trigger a first rst */
+ tmp = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON);
+ tmp |= CRU_GLB_RST_TSADC_FST | CRU_GLB_RST_WDT_FST;
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, tmp);
+ return;
+ tmp = mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(3));
+ tmp &= ~(PMUGRF_FAILSAFE_SHTDN_TSADC | PMUGRF_FAILSAFE_SHTDN_WDT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(3), tmp);
+
+ /* wdt pin rst eable */
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(2),
+ BIT_WITH_WMSK(GRF_SOC_CON2_NSWDT_RST_EN));
+}
+
+void px30_soc_reset_config(void)
+{
+ uint32_t tmp;
+
+ /* enable soc ip rst hold time cfg */
+ tmp = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON);
+ tmp |= BIT(CRU_GLB_RST_TSADC_EXT) | BIT(CRU_GLB_RST_WDT_EXT);
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, tmp);
+ /* soc ip rst hold time, 24m */
+ tmp = mmio_read_32(CRU_BASE + CRU_GLB_CNT_TH);
+ tmp &= ~CRU_GLB_CNT_RST_MSK;
+ tmp |= (CRU_GLB_CNT_RST_1MS / 2);
+ mmio_write_32(CRU_BASE + CRU_GLB_CNT_TH, tmp);
+
+ mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0),
+ BIT_WITH_WMSK(PMUSGRF_RSTOUT_FST) |
+ BIT_WITH_WMSK(PMUSGRF_RSTOUT_TSADC) |
+ BIT_WITH_WMSK(PMUSGRF_RSTOUT_WDT));
+
+ /* rst_out pulse time */
+ mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(2),
+ PMUGRF_SOC_CON2_MAX_341US | PMUGRF_SOC_CON2_US_WMSK);
+
+ soc_reset_config_all();
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ sgrf_init();
+}
diff --git a/plat/rockchip/px30/drivers/soc/soc.h b/plat/rockchip/px30/drivers/soc/soc.h
new file mode 100644
index 0000000..648d18b
--- /dev/null
+++ b/plat/rockchip/px30/drivers/soc/soc.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SOC_H__
+#define __SOC_H__
+
+#include <plat_private.h>
+
+#ifndef BITS_WMSK
+#define BITS_WMSK(msk, shift) ((msk) << (shift + REG_MSK_SHIFT))
+#endif
+
+enum plls_id {
+ APLL_ID = 0,
+ DPLL_ID,
+ CPLL_ID,
+ NPLL_ID,
+ GPLL_ID,
+ END_PLL_ID,
+};
+
+enum pll_mode {
+ SLOW_MODE,
+ NORM_MODE,
+ DEEP_SLOW_MODE,
+};
+
+/***************************************************************************
+ * GRF
+ ***************************************************************************/
+#define GRF_SOC_CON(i) (0x0400 + (i) * 4)
+#define GRF_PD_VO_CON0 0x0434
+#define GRF_SOC_STATUS0 0x0480
+#define GRF_CPU_STATUS0 0x0520
+#define GRF_CPU_STATUS1 0x0524
+#define GRF_SOC_NOC_CON0 0x0530
+#define GRF_SOC_NOC_CON1 0x0534
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+#define GRF_SOC_CON2_NSWDT_RST_EN 12
+
+/***************************************************************************
+ * cru
+ ***************************************************************************/
+#define CRU_MODE 0xa0
+#define CRU_MISC 0xa4
+#define CRU_GLB_CNT_TH 0xb0
+#define CRU_GLB_RST_ST 0xb4
+#define CRU_GLB_SRST_FST 0xb8
+#define CRU_GLB_SRST_SND 0xbc
+#define CRU_GLB_RST_CON 0xc0
+
+#define CRU_CLKSEL_CON 0x100
+#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + (i) * 4)
+#define CRU_CLKSEL_CON_CNT 60
+
+#define CRU_CLKGATE_CON 0x200
+#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + (i) * 4)
+#define CRU_CLKGATES_CON_CNT 18
+
+#define CRU_SOFTRST_CON 0x300
+#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4))
+#define CRU_SOFTRSTS_CON_CNT 12
+
+#define CRU_AUTOCS_CON0(id) (0x400 + (id) * 8)
+#define CRU_AUTOCS_CON1(id) (0x404 + (id) * 8)
+
+#define CRU_CONS_GATEID(i) (16 * (i))
+#define GATE_ID(reg, bit) ((reg) * 16 + (bit))
+
+#define CRU_GLB_SRST_FST_VALUE 0xfdb9
+#define CRU_GLB_SRST_SND_VALUE 0xeca8
+
+#define CRU_GLB_RST_TSADC_EXT 6
+#define CRU_GLB_RST_WDT_EXT 7
+
+#define CRU_GLB_CNT_RST_MSK 0xffff
+#define CRU_GLB_CNT_RST_1MS 0x5DC0
+
+#define CRU_GLB_RST_TSADC_FST BIT(0)
+#define CRU_GLB_RST_WDT_FST BIT(1)
+
+/***************************************************************************
+ * pll
+ ***************************************************************************/
+#define CRU_PLL_CONS(id, i) ((id) * 0x20 + (i) * 4)
+#define PLL_CON(i) ((i) * 4)
+#define PLL_CON_CNT 5
+#define PLL_LOCK_MSK BIT(10)
+#define PLL_MODE_SHIFT(id) ((id) == CPLL_ID ? \
+ 2 : \
+ ((id) == DPLL_ID ? 4 : 2 * (id)))
+#define PLL_MODE_MSK(id) (0x3 << PLL_MODE_SHIFT(id))
+
+#define PLL_LOCKED_TIMEOUT 600000U
+
+/***************************************************************************
+ * GPIO
+ ***************************************************************************/
+#define SWPORTA_DR 0x00
+#define SWPORTA_DDR 0x04
+#define GPIO_INTEN 0x30
+#define GPIO_INT_STATUS 0x40
+#define GPIO_NUMS 4
+
+void clk_gate_con_save(uint32_t *clkgt_save);
+void clk_gate_con_restore(uint32_t *clkgt_save);
+void clk_gate_con_disable(void);
+
+void px30_soc_reset_config(void);
+
+#endif /* __SOC_H__ */
diff --git a/plat/rockchip/px30/include/plat.ld.S b/plat/rockchip/px30/include/plat.ld.S
new file mode 100644
index 0000000..44cca0d
--- /dev/null
+++ b/plat/rockchip/px30/include/plat.ld.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __ROCKCHIP_PLAT_LD_S__
+#define __ROCKCHIP_PLAT_LD_S__
+
+MEMORY {
+ PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
+}
+
+SECTIONS
+{
+ . = PMUSRAM_BASE;
+
+ /*
+ * pmu_cpuson_entrypoint request address
+ * align 64K when resume, so put it in the
+ * start of pmusram
+ */
+ .pmusram : {
+ ASSERT(. == ALIGN(64 * 1024),
+ ".pmusram.entry request 64K aligned.");
+ KEEP(*(.pmusram.entry))
+
+ __bl31_pmusram_text_start = .;
+ *(.pmusram.text)
+ *(.pmusram.rodata)
+ __bl31_pmusram_text_end = .;
+ __bl31_pmusram_data_start = .;
+ *(.pmusram.data)
+ __bl31_pmusram_data_end = .;
+ } >PMUSRAM
+}
+
+#endif /* __ROCKCHIP_PLAT_LD_S__ */
diff --git a/plat/rockchip/px30/include/plat_sip_calls.h b/plat/rockchip/px30/include/plat_sip_calls.h
new file mode 100644
index 0000000..7b6a6a8
--- /dev/null
+++ b/plat/rockchip/px30/include/plat_sip_calls.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_SIP_CALLS_H__
+#define __PLAT_SIP_CALLS_H__
+
+#define RK_PLAT_SIP_NUM_CALLS 0
+
+#endif /* __PLAT_SIP_CALLS_H__ */
diff --git a/plat/rockchip/px30/include/platform_def.h b/plat/rockchip/px30/include/platform_def.h
new file mode 100644
index 0000000..a11f84f
--- /dev/null
+++ b/plat/rockchip/px30/include/platform_def.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <px30_def.h>
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+#define PLAT_RK_CLST_TO_CPUID_SHIFT 8
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF text, ro, rw, Size: 1MB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x100000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x40000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+#define ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 27
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE PX30_GICD_BASE
+#define PLAT_RK_GICC_BASE PX30_GICC_BASE
+
+#define PLAT_RK_UART_BASE PX30_UART_BASE
+#define PLAT_RK_UART_CLOCK PX30_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE PX30_BAUDRATE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rockchip/px30/plat_sip_calls.c b/plat/rockchip/px30/plat_sip_calls.c
new file mode 100644
index 0000000..a4b8e55
--- /dev/null
+++ b/plat/rockchip/px30/plat_sip_calls.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <plat_sip_calls.h>
+#include <rockchip_sip_svc.h>
+
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/rockchip/px30/platform.mk b/plat/rockchip/px30/platform.mk
new file mode 100644
index 0000000..d14ffc4
--- /dev/null
+++ b/plat/rockchip/px30/platform.mk
@@ -0,0 +1,73 @@
+#
+#Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+#
+#SPDX-License-Identifier: BSD-3-Clause
+#
+
+include drivers/arm/gic/v2/gicv2.mk
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+DISABLE_BIN_GENERATION := 1
+
+PLAT_INCLUDES := -Idrivers/arm/gic/common/ \
+ -Idrivers/arm/gic/v2/ \
+ -Iinclude/plat/common/ \
+ -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/drivers/parameter/ \
+ -I${RK_PLAT_COMMON}/pmusram \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/secure/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/include/
+
+RK_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ ${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES := lib/bl_aux_params/bl_aux_params.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ plat/common/plat_psci_common.c
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ common/desc_image_load.c \
+ drivers/arm/cci/cci.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/cortex_a35.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/params_setup.c \
+ ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/secure/secure.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
+ ${RK_PLAT_SOC}/plat_sip_calls.c
+
+ifdef PLAT_RK_SECURE_DDR_MINILOADER
+BL31_SOURCES += ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c
+endif
+
+ENABLE_PLAT_COMPAT := 0
+MULTI_CONSOLE_API := 1
+
+include lib/libfdt/libfdt.mk
+
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))
+$(eval $(call add_define,PLAT_WARMBOOT_ADDR_NOT_ALIGN))
diff --git a/plat/rockchip/px30/px30_def.h b/plat/rockchip/px30/px30_def.h
new file mode 100644
index 0000000..efe789e
--- /dev/null
+++ b/plat/rockchip/px30/px30_def.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PX30_DEF_H__
+#define __PX30_DEF_H__
+
+#define MAJOR_VERSION (1)
+#define MINOR_VERSION (0)
+
+#define SIZE_K(n) ((n) * 1024)
+#define SIZE_M(n) ((n) * 1024 * 1024)
+
+#define WITH_16BITS_WMSK(bits) (0xffff0000 | (bits))
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define PMU_BASE 0xff000000
+#define PMU_SIZE SIZE_K(64)
+
+#define PMUGRF_BASE 0xff010000
+#define PMUGRF_SIZE SIZE_K(64)
+
+#define PMUSRAM_BASE 0xff020000
+#define PMUSRAM_SIZE SIZE_K(64)
+#define PMUSRAM_RSIZE SIZE_K(8)
+
+#define UART0_BASE 0xff030000
+#define UART0_SIZE SIZE_K(64)
+
+#define GPIO0_BASE 0xff040000
+#define GPIO0_SIZE SIZE_K(64)
+
+#define PMUSGRF_BASE 0xff050000
+#define PMUSGRF_SIZE SIZE_K(64)
+
+#define INTSRAM_BASE 0xff0e0000
+#define INTSRAM_SIZE SIZE_K(64)
+
+#define SGRF_BASE 0xff11c000
+#define SGRF_SIZE SIZE_K(16)
+
+#define GIC400_BASE 0xff130000
+#define GIC400_SIZE SIZE_K(64)
+
+#define GRF_BASE 0xff140000
+#define GRF_SIZE SIZE_K(64)
+
+#define UART1_BASE 0xff158000
+#define UART1_SIZE SIZE_K(64)
+
+#define UART2_BASE 0xff160000
+#define UART2_SIZE SIZE_K(64)
+
+#define UART3_BASE 0xff168000
+#define UART3_SIZE SIZE_K(64)
+
+#define UART5_BASE 0xff178000
+#define UART5_SIZE SIZE_K(64)
+
+#define I2C0_BASE 0xff180000
+#define I2C0_SIZE SIZE_K(64)
+
+#define PWM0_BASE 0xff200000
+#define PWM0_SIZE SIZE_K(32)
+
+#define PWM1_BASE 0xff208000
+#define PWM1_SIZE SIZE_K(32)
+
+#define NTIME_BASE 0xff210000
+#define NTIME_SIZE SIZE_K(64)
+
+#define STIME_BASE 0xff220000
+#define STIME_SIZE SIZE_K(64)
+
+#define DCF_BASE 0xff230000
+#define DCF_SIZE SIZE_K(64)
+
+#define GPIO1_BASE 0xff250000
+#define GPIO1_SIZE SIZE_K(64)
+
+#define GPIO2_BASE 0xff260000
+#define GPIO2_SIZE SIZE_K(64)
+
+#define GPIO3_BASE 0xff270000
+#define GPIO3_SIZE SIZE_K(64)
+
+#define DDR_PHY_BASE 0xff2a0000
+#define DDR_PHY_SIZE SIZE_K(64)
+
+#define CRU_BASE 0xff2b0000
+#define CRU_SIZE SIZE_K(32)
+
+#define CRU_BOOST_BASE 0xff2b8000
+#define CRU_BOOST_SIZE SIZE_K(16)
+
+#define PMUCRU_BASE 0xff2bc000
+#define PMUCRU_SIZE SIZE_K(16)
+
+#define VOP_BASE 0xff460000
+#define VOP_SIZE SIZE_K(16)
+
+#define SERVER_MSCH_BASE 0xff530000
+#define SERVER_MSCH_SIZE SIZE_K(64)
+
+#define FIREWALL_DDR_BASE 0xff534000
+#define FIREWALL_DDR_SIZE SIZE_K(16)
+
+#define DDR_UPCTL_BASE 0xff600000
+#define DDR_UPCTL_SIZE SIZE_K(64)
+
+#define DDR_MNTR_BASE 0xff610000
+#define DDR_MNTR_SIZE SIZE_K(64)
+
+#define DDR_STDBY_BASE 0xff620000
+#define DDR_STDBY_SIZE SIZE_K(64)
+
+#define DDRGRF_BASE 0xff630000
+#define DDRGRF_SIZE SIZE_K(32)
+
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define PX30_UART_BASE UART2_BASE
+#define PX30_BAUDRATE 1500000
+#define PX30_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+#define SYS_COUNTER_FREQ_IN_MHZ 24
+
+/******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define PX30_GICD_BASE (GIC400_BASE + 0x1000)
+#define PX30_GICC_BASE (GIC400_BASE + 0x2000)
+#define PX30_GICR_BASE 0 /* no GICR in GIC-400 */
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER 29
+
+#define RK_IRQ_SEC_SGI_0 8
+#define RK_IRQ_SEC_SGI_1 9
+#define RK_IRQ_SEC_SGI_2 10
+#define RK_IRQ_SEC_SGI_3 11
+#define RK_IRQ_SEC_SGI_4 12
+#define RK_IRQ_SEC_SGI_5 13
+#define RK_IRQ_SEC_SGI_6 14
+#define RK_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 0 interrupts.
+ */
+#define PLAT_RK_GICV2_G0_IRQS \
+ INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/
+#define SHARE_MEM_PAGE_NUM 15
+#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4)
+
+#define DDR_PARAM_BASE 0x02000000
+#define DDR_PARAM_SIZE SIZE_K(4)
+
+#endif /* __PLAT_DEF_H__ */
diff --git a/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..2003749
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+.macro func_rockchip_clst_warmboot
+ /* Nothing to do for rk3288 */
+.endm
+
+.macro rockchip_clst_warmboot_data
+ /* Nothing to do for rk3288 */
+.endm
diff --git a/plat/rockchip/rk3288/drivers/pmu/pmu.c b/plat/rockchip/rk3288/drivers/pmu/pmu.c
new file mode 100644
index 0000000..d6d7098
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/pmu/pmu.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include <pmu.h>
+#include <pmu_com.h>
+#include <rk3288_def.h>
+#include <secure.h>
+#include <soc.h>
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+
+static uint32_t cpu_warm_boot_addr;
+
+static uint32_t store_pmu_pwrmode_con;
+static uint32_t store_sgrf_soc_con0;
+static uint32_t store_sgrf_cpu_con0;
+
+/* These enum are variants of low power mode */
+enum {
+ ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
+ ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
+};
+
+static inline int rk3288_pmu_bus_idle(uint32_t req, uint32_t idle)
+{
+ uint32_t mask = BIT(req);
+ uint32_t idle_mask = 0;
+ uint32_t idle_target = 0;
+ uint32_t val;
+ uint32_t wait_cnt = 0;
+
+ switch (req) {
+ case bus_ide_req_gpu:
+ idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu);
+ idle_target = (idle << pmu_idle_ack_gpu) |
+ (idle << pmu_idle_gpu);
+ break;
+ case bus_ide_req_core:
+ idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core);
+ idle_target = (idle << pmu_idle_ack_core) |
+ (idle << pmu_idle_core);
+ break;
+ case bus_ide_req_cpup:
+ idle_mask = BIT(pmu_idle_ack_cpup) | BIT(pmu_idle_cpup);
+ idle_target = (idle << pmu_idle_ack_cpup) |
+ (idle << pmu_idle_cpup);
+ break;
+ case bus_ide_req_bus:
+ idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus);
+ idle_target = (idle << pmu_idle_ack_bus) |
+ (idle << pmu_idle_bus);
+ break;
+ case bus_ide_req_dma:
+ idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma);
+ idle_target = (idle << pmu_idle_ack_dma) |
+ (idle << pmu_idle_dma);
+ break;
+ case bus_ide_req_peri:
+ idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri);
+ idle_target = (idle << pmu_idle_ack_peri) |
+ (idle << pmu_idle_peri);
+ break;
+ case bus_ide_req_video:
+ idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video);
+ idle_target = (idle << pmu_idle_ack_video) |
+ (idle << pmu_idle_video);
+ break;
+ case bus_ide_req_hevc:
+ idle_mask = BIT(pmu_idle_ack_hevc) | BIT(pmu_idle_hevc);
+ idle_target = (idle << pmu_idle_ack_hevc) |
+ (idle << pmu_idle_hevc);
+ break;
+ case bus_ide_req_vio:
+ idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio);
+ idle_target = (pmu_idle_ack_vio) |
+ (idle << pmu_idle_vio);
+ break;
+ case bus_ide_req_alive:
+ idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive);
+ idle_target = (idle << pmu_idle_ack_alive) |
+ (idle << pmu_idle_alive);
+ break;
+ default:
+ ERROR("%s: Unsupported the idle request\n", __func__);
+ break;
+ }
+
+ val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ);
+ if (idle)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val);
+
+ while ((mmio_read_32(PMU_BASE +
+ PMU_BUS_IDE_ST) & idle_mask) != idle_target) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ WARN("%s:st=%x(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST),
+ idle_mask);
+ }
+
+ return 0;
+}
+
+static bool rk3288_sleep_disable_osc(void)
+{
+ static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
+ GRF_UOC2_CON0 };
+ uint32_t reg, i;
+
+ /*
+ * if any usb phy is still on(GRF_SIDDQ==0), that means we need the
+ * function of usb wakeup, so do not switch to 32khz, since the usb phy
+ * clk does not connect to 32khz osc
+ */
+ for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
+ reg = mmio_read_32(GRF_BASE + reg_offset[i]);
+ if (!(reg & GRF_SIDDQ))
+ return false;
+ }
+
+ return true;
+}
+
+static void pmu_set_sleep_mode(int level)
+{
+ uint32_t mode_set, mode_set1;
+ bool osc_disable = rk3288_sleep_disable_osc();
+
+ mode_set = BIT(pmu_mode_glb_int_dis) | BIT(pmu_mode_l2_flush_en) |
+ BIT(pmu_mode_sref0_enter) | BIT(pmu_mode_sref1_enter) |
+ BIT(pmu_mode_ddrc0_gt) | BIT(pmu_mode_ddrc1_gt) |
+ BIT(pmu_mode_en) | BIT(pmu_mode_chip_pd) |
+ BIT(pmu_mode_scu_pd);
+
+ mode_set1 = BIT(pmu_mode_clr_core) | BIT(pmu_mode_clr_cpup);
+
+ if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
+ /* arm off, logic deep sleep */
+ mode_set |= BIT(pmu_mode_bus_pd) | BIT(pmu_mode_pmu_use_lf) |
+ BIT(pmu_mode_ddrio1_ret) |
+ BIT(pmu_mode_ddrio0_ret) |
+ BIT(pmu_mode_pmu_alive_use_lf) |
+ BIT(pmu_mode_pll_pd);
+
+ if (osc_disable)
+ mode_set |= BIT(pmu_mode_osc_dis);
+
+ mode_set1 |= BIT(pmu_mode_clr_alive) | BIT(pmu_mode_clr_bus) |
+ BIT(pmu_mode_clr_peri) | BIT(pmu_mode_clr_dma);
+
+ mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
+ pmu_armint_wakeup_en);
+
+ /*
+ * In deep suspend we use PMU_PMU_USE_LF to let the rk3288
+ * switch its main clock supply to the alternative 32kHz
+ * source. Therefore set 30ms on a 32kHz clock for pmic
+ * stabilization. Similar 30ms on 24MHz for the other
+ * mode below.
+ */
+ mmio_write_32(PMU_BASE + PMU_STABL_CNT, 32 * 30);
+
+ /* only wait for stabilization, if we turned the osc off */
+ mmio_write_32(PMU_BASE + PMU_OSC_CNT,
+ osc_disable ? 32 * 30 : 0);
+ } else {
+ /*
+ * arm off, logic normal
+ * if pmu_clk_core_src_gate_en is not set,
+ * wakeup will be error
+ */
+ mode_set |= BIT(pmu_mode_core_src_gt);
+
+ mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
+ BIT(pmu_armint_wakeup_en) |
+ BIT(pmu_gpioint_wakeup_en));
+
+ /* 30ms on a 24MHz clock for pmic stabilization */
+ mmio_write_32(PMU_BASE + PMU_STABL_CNT, 24000 * 30);
+
+ /* oscillator is still running, so no need to wait */
+ mmio_write_32(PMU_BASE + PMU_OSC_CNT, 0);
+ }
+
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, mode_set);
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CON1, mode_set1);
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ uint32_t cpu_pd;
+
+ cpu_pd = PD_CPU0 + cpu_id;
+
+ /* if the core has been on, power it off first */
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ /* put core in reset - some sort of A12/A17 bug */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
+ BIT(cpu_id) | (BIT(cpu_id) << 16));
+
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ }
+
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
+
+ /* pull core out of reset */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), BIT(cpu_id) << 16);
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id)
+{
+ uint32_t cpu_pd = PD_CPU0 + cpu_id;
+
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
+ return 0;
+
+ if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
+ return -EINVAL;
+
+ /* put core in reset - some sort of A12/A17 bug */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
+ BIT(cpu_id) | (BIT(cpu_id) << 16));
+
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+
+ return 0;
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu;
+
+ boot_cpu = plat_my_core_pos();
+ boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr());
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ if (cpu == boot_cpu)
+ continue;
+
+ cpus_power_domain_off(cpu);
+ }
+}
+
+void sram_save(void)
+{
+ /* TODO: support the sdram save for rk3288 SoCs*/
+}
+
+void sram_restore(void)
+{
+ /* TODO: support the sdram restore for rk3288 SoCs */
+}
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpu_id] = entrypoint;
+ dsb();
+
+ cpus_power_domain_on(cpu_id);
+
+ /*
+ * We communicate with the bootrom to active the cpus other
+ * than cpu0, after a blob of initialize code, they will
+ * stay at wfe state, once they are actived, they will check
+ * the mailbox:
+ * sram_base_addr + 4: 0xdeadbeaf
+ * sram_base_addr + 8: start address for pc
+ * The cpu0 need to wait the other cpus other than cpu0 entering
+ * the wfe state.The wait time is affected by many aspects.
+ * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
+ */
+ mdelay(1); /* ensure the cpus other than cpu0 to startup */
+
+ /* tell the bootrom mailbox where to start from */
+ mmio_write_32(SRAM_BASE + 8, cpu_warm_boot_addr);
+ mmio_write_32(SRAM_BASE + 4, 0xDEADBEAF);
+ dsb();
+ sev();
+
+ return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, store_pmu_pwrmode_con);
+ mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0),
+ store_sgrf_cpu_con0 | SGRF_DAPDEVICE_MSK);
+
+ /* disable fastboot mode */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0),
+ store_sgrf_soc_con0 | SGRF_FAST_BOOT_DIS);
+
+ secure_watchdog_ungate();
+ clk_gate_con_restore();
+ clk_sel_con_restore();
+ clk_plls_resume();
+
+ secure_gic_init();
+ plat_rockchip_gic_init();
+
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ nonboot_cpus_off();
+
+ store_sgrf_cpu_con0 = mmio_read_32(SGRF_BASE + SGRF_CPU_CON(0));
+ store_sgrf_soc_con0 = mmio_read_32(SGRF_BASE + SGRF_SOC_CON(0));
+ store_pmu_pwrmode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON);
+
+ /* save clk-gates and ungate all for suspend */
+ clk_gate_con_save();
+ clk_gate_con_disable();
+ clk_sel_con_save();
+
+ pmu_set_sleep_mode(ROCKCHIP_ARM_OFF_LOGIC_NORMAL);
+
+ clk_plls_suspend();
+ secure_watchdog_gate();
+
+ /*
+ * The dapswjdp can not auto reset before resume, that cause it may
+ * access some illegal address during resume. Let's disable it before
+ * suspend, and the MASKROM will enable it back.
+ */
+ mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), SGRF_DAPDEVICE_MSK);
+
+ /*
+ * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR
+ */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_FAST_BOOT_ENA);
+
+ /* boot-address of resuming system is from this register value */
+ mmio_write_32(SGRF_BASE + SGRF_FAST_BOOT_ADDR,
+ (uint32_t)&pmu_cpuson_entrypoint);
+
+ /* flush all caches - otherwise we might loose the resume address */
+ dcsw_op_all(DC_OP_CISW);
+
+ return 0;
+}
+
+void rockchip_plat_mmu_svc_mon(void)
+{
+}
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ cpu_warm_boot_addr = (uint32_t)platform_cpu_warmboot;
+
+ /* on boot all power-domains are on */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = pmu_pd_on;
+
+ nonboot_cpus_off();
+}
diff --git a/plat/rockchip/rk3288/drivers/pmu/pmu.h b/plat/rockchip/rk3288/drivers/pmu/pmu.h
new file mode 100644
index 0000000..06d5528
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/pmu/pmu.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_H
+#define PMU_H
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE 0x80
+#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WAKEUP_CFG0 0x0
+#define PMU_WAKEUP_CFG1 0x4
+#define PMU_PWRDN_CON 0x8
+#define PMU_PWRDN_ST 0xc
+
+#define PMU_PWRMODE_CON 0x18
+#define PMU_BUS_IDE_REQ 0x10
+#define PMU_BUS_IDE_ST 0x14
+
+#define PMU_OSC_CNT 0x20
+#define PMU_PLL_CNT 0x24
+#define PMU_STABL_CNT 0x28
+#define PMU_DDRIO0_PWR_CNT 0x2c
+#define PMU_DDRIO1_PWR_CNT 0x30
+#define PMU_WKUPRST_CNT 0x44
+#define PMU_SFT_CON 0x48
+#define PMU_PWRMODE_CON1 0x90
+
+enum pmu_pdid {
+ PD_CPU0 = 0,
+ PD_CPU1,
+ PD_CPU2,
+ PD_CPU3,
+ PD_BUS = 5,
+ PD_PERI,
+ PD_VIO,
+ PD_VIDEO,
+ PD_GPU,
+ PD_SCU = 11,
+ PD_HEVC = 14,
+ PD_END
+};
+
+enum pmu_bus_ide {
+ bus_ide_req_bus = 0,
+ bus_ide_req_peri,
+ bus_ide_req_gpu,
+ bus_ide_req_video,
+ bus_ide_req_vio,
+ bus_ide_req_core,
+ bus_ide_req_alive,
+ bus_ide_req_dma,
+ bus_ide_req_cpup,
+ bus_ide_req_hevc,
+ bus_ide_req_end
+};
+
+enum pmu_pwrmode {
+ pmu_mode_en = 0,
+ pmu_mode_core_src_gt,
+ pmu_mode_glb_int_dis,
+ pmu_mode_l2_flush_en,
+ pmu_mode_bus_pd,
+ pmu_mode_cpu0_pd,
+ pmu_mode_scu_pd,
+ pmu_mode_pll_pd = 7,
+ pmu_mode_chip_pd,
+ pmu_mode_pwr_off_comb,
+ pmu_mode_pmu_alive_use_lf,
+ pmu_mode_pmu_use_lf,
+ pmu_mode_osc_dis = 12,
+ pmu_mode_input_clamp,
+ pmu_mode_wkup_rst,
+ pmu_mode_sref0_enter,
+ pmu_mode_sref1_enter,
+ pmu_mode_ddrio0_ret,
+ pmu_mode_ddrio1_ret,
+ pmu_mode_ddrc0_gt,
+ pmu_mode_ddrc1_gt,
+ pmu_mode_ddrio0_ret_deq,
+ pmu_mode_ddrio1_ret_deq,
+};
+
+enum pmu_pwrmode1 {
+ pmu_mode_clr_bus = 0,
+ pmu_mode_clr_core,
+ pmu_mode_clr_cpup,
+ pmu_mode_clr_alive,
+ pmu_mode_clr_dma,
+ pmu_mode_clr_peri,
+ pmu_mode_clr_gpu,
+ pmu_mode_clr_video,
+ pmu_mode_clr_hevc,
+ pmu_mode_clr_vio
+};
+
+enum pmu_sft_con {
+ pmu_sft_ddrio0_ret_cfg = 6,
+ pmu_sft_ddrio1_ret_cfg = 9,
+ pmu_sft_l2flsh = 15,
+};
+
+enum pmu_wakeup_cfg1 {
+ pmu_armint_wakeup_en = 0,
+ pmu_gpio_wakeup_negedge,
+ pmu_sdmmc0_wakeup_en,
+ pmu_gpioint_wakeup_en,
+};
+
+enum pmu_bus_idle_st {
+ pmu_idle_bus = 0,
+ pmu_idle_peri,
+ pmu_idle_gpu,
+ pmu_idle_video,
+ pmu_idle_vio,
+ pmu_idle_core,
+ pmu_idle_alive,
+ pmu_idle_dma,
+ pmu_idle_cpup,
+ pmu_idle_hevc,
+ pmu_idle_ack_bus = 16,
+ pmu_idle_ack_peri,
+ pmu_idle_ack_gpu,
+ pmu_idle_ack_video,
+ pmu_idle_ack_vio,
+ pmu_idle_ack_core,
+ pmu_idle_ack_alive,
+ pmu_idle_ack_dma,
+ pmu_idle_ack_cpup,
+ pmu_idle_ack_hevc,
+};
+
+#define CHECK_CPU_WFIE_BASE (0)
+
+#define clstl_cpu_wfe -1
+#define clstb_cpu_wfe -1
+#define CKECK_WFEI_MSK 0
+
+
+#define PD_CTR_LOOP 500
+#define CHK_CPU_LOOP 500
+
+#define MAX_WAIT_CONUT 1000
+
+#endif /* PMU_H */
diff --git a/plat/rockchip/rk3288/drivers/secure/secure.c b/plat/rockchip/rk3288/drivers/secure/secure.c
new file mode 100644
index 0000000..25e1cca
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/secure/secure.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <plat_private.h>
+#include <secure.h>
+#include <soc.h>
+
+static void sgrf_ddr_rgn_global_bypass(uint32_t bypass)
+{
+ if (bypass)
+ /* set bypass (non-secure regions) for whole ddr regions */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21),
+ SGRF_DDR_RGN_BYPS);
+ else
+ /* cancel bypass for whole ddr regions */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21),
+ SGRF_DDR_RGN_NO_BYPS);
+}
+
+/**
+ * There are 8 + 1 regions for DDR secure control:
+ * DDR_RGN_0 ~ DDR_RGN_7: Per DDR_RGNs grain size is 1MB
+ * DDR_RGN_X - the memories of exclude DDR_RGN_0 ~ DDR_RGN_7
+ *
+ * SGRF_SOC_CON6 - start address of RGN_0 + control
+ * SGRF_SOC_CON7 - end address of RGN_0
+ * ...
+ * SGRF_SOC_CON20 - start address of the RGN_7 + control
+ * SGRF_SOC_CON21 - end address of the RGN_7 + RGN_X control
+ *
+ * @rgn - the DDR regions 0 ~ 7 which are can be configured.
+ * @st - start address to set as secure
+ * @sz - length of area to set as secure
+ * The @st_mb and @ed_mb indicate the start and end addresses for which to set
+ * the security, and the unit is megabyte. When the st_mb == 0, ed_mb == 0, the
+ * address range 0x0 ~ 0xfffff is secure.
+ *
+ * For example, if we would like to set the range [0, 32MB) is security via
+ * DDR_RGN0, then rgn == 0, st_mb == 0, ed_mb == 31.
+ */
+static void sgrf_ddr_rgn_config(uint32_t rgn, uintptr_t st, size_t sz)
+{
+ uintptr_t ed = st + sz;
+ uintptr_t st_mb, ed_mb;
+
+ assert(rgn <= 7);
+ assert(st < ed);
+
+ /* check aligned 1MB */
+ assert(st % SIZE_M(1) == 0);
+ assert(ed % SIZE_M(1) == 0);
+
+ st_mb = st / SIZE_M(1);
+ ed_mb = ed / SIZE_M(1);
+
+ /* set ddr region addr start */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)),
+ BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_ADDR_WMSK, 0));
+
+ /* set ddr region addr end */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2) + 1),
+ BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_ADDR_WMSK, 0));
+
+ /* select region security */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)),
+ SGRF_DDR_RGN_SECURE_SEL);
+
+ /* enable region security */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)),
+ SGRF_DDR_RGN_SECURE_EN);
+}
+
+void secure_watchdog_gate(void)
+{
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_GATE);
+}
+
+void secure_watchdog_ungate(void)
+{
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_UNGATE);
+}
+
+__pmusramfunc void sram_secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0);
+
+ mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void secure_gic_init(void)
+{
+ /* (re-)enable non-secure access to the gic*/
+ mmio_write_32(CORE_AXI_BUS_BASE + CORE_AXI_SECURITY0,
+ AXI_SECURITY0_GIC);
+}
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0);
+
+ mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void secure_sgrf_init(void)
+{
+ /*
+ * We use the first sram part to talk to the bootrom,
+ * so make it secure.
+ */
+ mmio_write_32(TZPC_BASE + TZPC_R0SIZE, TZPC_SRAM_SECURE_4K(1));
+
+ secure_gic_init();
+
+ /* set all master ip to non-secure */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), SGRF_SOC_CON2_MST_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), SGRF_SOC_CON3_MST_NS);
+
+ /* setting all configurable ip into non-secure */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4),
+ SGRF_SOC_CON4_SECURE_WMSK /*TODO:|SGRF_STIMER_SECURE*/);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON5_SECURE_WMSK);
+
+ /* secure dma to non-secure */
+ mmio_write_32(TZPC_BASE + TZPC_DECPROT1SET, 0xff);
+ mmio_write_32(TZPC_BASE + TZPC_DECPROT2SET, 0xff);
+ mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), 0x3800);
+ dsb();
+
+ /* rst dma1 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1),
+ RST_DMA1_MSK | (RST_DMA1_MSK << 16));
+ /* rst dma2 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4),
+ RST_DMA2_MSK | (RST_DMA2_MSK << 16));
+
+ dsb();
+
+ /* release dma1 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16));
+ /* release dma2 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16));
+}
+
+void secure_sgrf_ddr_rgn_init(void)
+{
+ sgrf_ddr_rgn_config(0, TZRAM_BASE, TZRAM_SIZE);
+ sgrf_ddr_rgn_global_bypass(0);
+}
diff --git a/plat/rockchip/rk3288/drivers/secure/secure.h b/plat/rockchip/rk3288/drivers/secure/secure.h
new file mode 100644
index 0000000..6c0b2b7
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/secure/secure.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SECURE_H
+#define SECURE_H
+
+/******************************************************************************
+ * TZPC TrustZone controller
+ ******************************************************************************/
+
+#define TZPC_R0SIZE 0x0
+#define TZPC_SRAM_SECURE_4K(n) ((n) > 0x200 ? 0x200 : (n))
+#define TZPC_DECPROT1STAT 0x80c
+#define TZPC_DECPROT1SET 0x810
+#define TZPC_DECPROT1CLR 0x814
+#define TZPC_DECPROT2STAT 0x818
+#define TZPC_DECPROT2SET 0x818
+#define TZPC_DECPROT2CLR 0x820
+
+/**************************************************
+ * sgrf reg, offset
+ **************************************************/
+/*
+ * soc_con0-5 start at 0x0, soc_con6-... start art 0x50
+ * adjusted for the 5 lower registers
+ */
+#define SGRF_SOC_CON(n) ((((n) < 6) ? 0x0 : 0x38) + (n) * 4)
+#define SGRF_BUSDMAC_CON(n) (0x20 + (n) * 4)
+#define SGRF_CPU_CON(n) (0x40 + (n) * 4)
+#define SGRF_SOC_STATUS(n) (0x100 + (n) * 4)
+#define SGRF_FAST_BOOT_ADDR 0x120
+
+/* SGRF_SOC_CON0 */
+#define SGRF_FAST_BOOT_ENA BIT_WITH_WMSK(8)
+#define SGRF_FAST_BOOT_DIS WMSK_BIT(8)
+#define SGRF_PCLK_WDT_GATE BIT_WITH_WMSK(6)
+#define SGRF_PCLK_WDT_UNGATE WMSK_BIT(6)
+#define SGRF_PCLK_STIMER_GATE BIT_WITH_WMSK(4)
+
+#define SGRF_SOC_CON2_MST_NS 0xffe0ffe0
+#define SGRF_SOC_CON3_MST_NS 0x003f003f
+
+/* SGRF_SOC_CON4 */
+#define SGRF_SOC_CON4_SECURE_WMSK 0xffff0000
+#define SGRF_DDRC1_SECURE BIT_WITH_WMSK(12)
+#define SGRF_DDRC0_SECURE BIT_WITH_WMSK(11)
+#define SGRF_PMUSRAM_SECURE BIT_WITH_WMSK(8)
+#define SGRF_WDT_SECURE BIT_WITH_WMSK(7)
+#define SGRF_STIMER_SECURE BIT_WITH_WMSK(6)
+
+/* SGRF_SOC_CON5 */
+#define SGRF_SLV_SEC_BYPS BIT_WITH_WMSK(15)
+#define SGRF_SLV_SEC_NO_BYPS WMSK_BIT(15)
+#define SGRF_SOC_CON5_SECURE_WMSK 0x00ff0000
+
+/* ddr regions in SGRF_SOC_CON6 and following */
+#define SGRF_DDR_RGN_SECURE_SEL BIT_WITH_WMSK(15)
+#define SGRF_DDR_RGN_SECURE_EN BIT_WITH_WMSK(14)
+#define SGRF_DDR_RGN_ADDR_WMSK 0x0fff
+
+/* SGRF_SOC_CON21 */
+/* All security of the DDR RGNs are bypassed */
+#define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(15)
+#define SGRF_DDR_RGN_NO_BYPS WMSK_BIT(15)
+
+/* SGRF_CPU_CON0 */
+#define SGRF_DAPDEVICE_ENA BIT_WITH_WMSK(0)
+#define SGRF_DAPDEVICE_MSK WMSK_BIT(0)
+
+/*****************************************************************************
+ * core-axi
+ *****************************************************************************/
+#define CORE_AXI_SECURITY0 0x08
+#define AXI_SECURITY0_GIC BIT(0)
+
+/*****************************************************************************
+ * secure timer
+ *****************************************************************************/
+#define TIMER_LOAD_COUNT0 0x00
+#define TIMER_LOAD_COUNT1 0x04
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INTSTATUS 0x18
+
+#define TIMER_EN 0x1
+
+#define STIMER1_BASE (STIME_BASE + 0x20)
+
+/* export secure operating APIs */
+void secure_watchdog_gate(void);
+void secure_watchdog_ungate(void);
+void secure_gic_init(void);
+void secure_timer_init(void);
+void secure_sgrf_init(void);
+void secure_sgrf_ddr_rgn_init(void);
+__pmusramfunc void sram_secure_timer_init(void);
+
+#endif /* SECURE_H */
diff --git a/plat/rockchip/rk3288/drivers/soc/soc.c b/plat/rockchip/rk3288/drivers/soc/soc.c
new file mode 100644
index 0000000..36f410b
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/soc/soc.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <plat_private.h>
+#include <rk3288_def.h>
+#include <soc.h>
+#include <secure.h>
+
+/* sleep data for pll suspend */
+static struct deepsleep_data_s slp_data;
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(TZPC_BASE, TZPC_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SRAM_BASE, SRAM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART0_BASE, UART0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART1_BASE, UART1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART2_BASE, UART2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART3_BASE, UART3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART4_BASE, UART4_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GRF_BASE, GRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PCTL0_BASE, DDR_PCTL0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PHY0_BASE, DDR_PHY0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PCTL1_BASE, DDR_PCTL1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PHY1_BASE, DDR_PHY1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CORE_AXI_BUS_BASE, CORE_AXI_BUS_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ secure_sgrf_init();
+ /*
+ * We cannot enable ddr security at this point, as the kernel
+ * seems to have an issue with it even living in the same 128MB
+ * memory block. Only when moving the kernel to the second
+ * 128MB block does it not conflict, but then we'd loose this
+ * memory area for use. Late maybe enable
+ * secure_sgrf_ddr_rgn_init();
+ */
+}
+
+void regs_update_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift)
+{
+ uint32_t tmp, orig;
+
+ orig = mmio_read_32(addr);
+
+ tmp = orig & ~(mask << shift);
+ tmp |= (val & mask) << shift;
+
+ if (tmp != orig)
+ mmio_write_32(addr, tmp);
+ dsb();
+}
+
+static void pll_save(uint32_t pll_id)
+{
+ uint32_t *pll = slp_data.pll_con[pll_id];
+
+ pll[0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0));
+ pll[1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1));
+ pll[2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2));
+ pll[3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3));
+}
+
+void clk_plls_suspend(void)
+{
+ pll_save(NPLL_ID);
+ pll_save(CPLL_ID);
+ pll_save(GPLL_ID);
+ pll_save(APLL_ID);
+ slp_data.pll_mode = mmio_read_32(CRU_BASE + PLL_MODE_CON);
+
+ /*
+ * Switch PLLs other than DPLL (for SDRAM) to slow mode to
+ * avoid crashes on resume. The Mask ROM on the system will
+ * put APLL, CPLL, and GPLL into slow mode at resume time
+ * anyway (which is why we restore them), but we might not
+ * even make it to the Mask ROM if this isn't done at suspend
+ * time.
+ *
+ * NOTE: only APLL truly matters here, but we'll do them all.
+ */
+ mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000);
+}
+
+void clk_plls_resume(void)
+{
+ /* restore pll-modes */
+ mmio_write_32(CRU_BASE + PLL_MODE_CON,
+ slp_data.pll_mode | REG_SOC_WMSK);
+}
+
+void clk_gate_con_save(void)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ slp_data.cru_gate_con[i] =
+ mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i));
+}
+
+void clk_gate_con_disable(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), REG_SOC_WMSK);
+}
+
+void clk_gate_con_restore(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
+ REG_SOC_WMSK | slp_data.cru_gate_con[i]);
+}
+
+void clk_sel_con_save(void)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < CRU_CLKSELS_CON_CNT; i++)
+ slp_data.cru_sel_con[i] =
+ mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(i));
+}
+
+void clk_sel_con_restore(void)
+{
+ uint32_t i, val;
+
+ for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) {
+ /* fractional dividers don't have write-masks */
+ if ((i >= 7 && i <= 9) ||
+ (i >= 17 && i <= 20) ||
+ (i == 23) || (i == 41))
+ val = slp_data.cru_sel_con[i];
+ else
+ val = slp_data.cru_sel_con[i] | REG_SOC_WMSK;
+
+ mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(i), val);
+ }
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ uint32_t temp_val;
+
+ /*
+ * Switch PLLs other than DPLL (for SDRAM) to slow mode to
+ * avoid crashes on resume. The Mask ROM on the system will
+ * put APLL, CPLL, and GPLL into slow mode at resume time
+ * anyway (which is why we restore them), but we might not
+ * even make it to the Mask ROM if this isn't done at suspend
+ * time.
+ *
+ * NOTE: only APLL truly matters here, but we'll do them all.
+ */
+ mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000);
+
+ temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON);
+ temp_val &= ~PMU_RST_MASK;
+ temp_val |= PMU_RST_BY_SECOND_SFT;
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
diff --git a/plat/rockchip/rk3288/drivers/soc/soc.h b/plat/rockchip/rk3288/drivers/soc/soc.h
new file mode 100644
index 0000000..b96c4dc
--- /dev/null
+++ b/plat/rockchip/rk3288/drivers/soc/soc.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+enum plls_id {
+ APLL_ID = 0,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ NPLL_ID,
+ END_PLL_ID,
+};
+
+
+#define CYCL_24M_CNT_US(us) (24 * (us))
+#define CYCL_24M_CNT_MS(ms) ((ms) * CYCL_24M_CNT_US(1000))
+
+/*****************************************************************************
+ * grf regs
+ *****************************************************************************/
+#define GRF_UOC0_CON0 0x320
+#define GRF_UOC1_CON0 0x334
+#define GRF_UOC2_CON0 0x348
+#define GRF_SIDDQ BIT(13)
+
+/*****************************************************************************
+ * cru reg, offset
+ *****************************************************************************/
+#define CRU_SOFTRST_CON 0x1b8
+#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4))
+#define CRU_SOFTRSTS_CON_CNT 11
+
+#define RST_DMA1_MSK 0x4
+#define RST_DMA2_MSK 0x1
+
+#define CRU_CLKSEL_CON 0x60
+#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4))
+#define CRU_CLKSELS_CON_CNT 42
+
+#define CRU_CLKGATE_CON 0x160
+#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4))
+#define CRU_CLKGATES_CON_CNT 18
+
+#define CRU_GLB_SRST_FST 0x1b0
+#define CRU_GLB_SRST_SND 0x1b4
+#define CRU_GLB_RST_CON 0x1f0
+
+#define CRU_CONS_GATEID(i) (16 * (i))
+#define GATE_ID(reg, bit) (((reg) * 16) + (bit))
+
+#define PMU_RST_MASK 0x3
+#define PMU_RST_BY_FIRST_SFT (0 << 2)
+#define PMU_RST_BY_SECOND_SFT (1 << 2)
+#define PMU_RST_NOT_BY_SFT (2 << 2)
+
+/***************************************************************************
+ * pll
+ ***************************************************************************/
+#define PLL_CON_COUNT 4
+#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
+#define PLL_PWR_DN_MSK BIT(1)
+#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1)
+#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1)
+#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1)
+#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1)
+#define PLL_BYPASS_MSK BIT(0)
+#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16)
+#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1)
+#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1)
+
+#define PLL_MODE_CON 0x50
+
+struct deepsleep_data_s {
+ uint32_t pll_con[END_PLL_ID][PLL_CON_COUNT];
+ uint32_t pll_mode;
+ uint32_t cru_sel_con[CRU_CLKSELS_CON_CNT];
+ uint32_t cru_gate_con[CRU_CLKGATES_CON_CNT];
+};
+
+#define REG_W_MSK(bits_shift, msk) \
+ ((msk) << ((bits_shift) + 16))
+#define REG_VAL_CLRBITS(val, bits_shift, msk) \
+ ((val) & (~((msk) << bits_shift)))
+#define REG_SET_BITS(bits, bits_shift, msk) \
+ (((bits) & (msk)) << (bits_shift))
+#define REG_WMSK_BITS(bits, bits_shift, msk) \
+ (REG_W_MSK(bits_shift, msk) | \
+ REG_SET_BITS(bits, bits_shift, msk))
+#define REG_SOC_WMSK 0xffff0000
+
+#define regs_update_bit_set(addr, shift) \
+ regs_update_bits((addr), 0x1, 0x1, (shift))
+#define regs_update_bit_clr(addr, shift) \
+ regs_update_bits((addr), 0x0, 0x1, (shift))
+
+void regs_update_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift);
+void clk_plls_suspend(void);
+void clk_plls_resume(void);
+void clk_gate_con_save(void);
+void clk_gate_con_disable(void);
+void clk_gate_con_restore(void);
+void clk_sel_con_save(void);
+void clk_sel_con_restore(void);
+#endif /* SOC_H */
diff --git a/plat/rockchip/rk3288/include/plat_sip_calls.h b/plat/rockchip/rk3288/include/plat_sip_calls.h
new file mode 100644
index 0000000..66c4868
--- /dev/null
+++ b/plat/rockchip/rk3288/include/plat_sip_calls.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+#define RK_PLAT_SIP_NUM_CALLS 0
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/rockchip/rk3288/include/plat_sp_min.ld.S b/plat/rockchip/rk3288/include/plat_sp_min.ld.S
new file mode 100644
index 0000000..2878437
--- /dev/null
+++ b/plat/rockchip/rk3288/include/plat_sp_min.ld.S
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ROCKCHIP_PLAT_LD_S
+#define ROCKCHIP_PLAT_LD_S
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+MEMORY {
+ SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE
+ PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
+}
+
+SECTIONS
+{
+ . = SRAM_BASE;
+ ASSERT(. == ALIGN(PAGE_SIZE),
+ "SRAM_BASE address is not aligned on a page boundary.")
+
+ .text_sram : ALIGN(PAGE_SIZE) {
+ __bl32_sram_text_start = .;
+ *(.sram.text)
+ *(.sram.rodata)
+ __bl32_sram_text_real_end = .;
+ . = ALIGN(PAGE_SIZE);
+ __bl32_sram_text_end = .;
+ } >SRAM
+ ASSERT((__bl32_sram_text_real_end - __bl32_sram_text_start) <=
+ SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit")
+
+ .data_sram : ALIGN(PAGE_SIZE) {
+ __bl32_sram_data_start = .;
+ *(.sram.data)
+ __bl32_sram_data_real_end = .;
+ . = ALIGN(PAGE_SIZE);
+ __bl32_sram_data_end = .;
+ } >SRAM
+ ASSERT((__bl32_sram_data_real_end - __bl32_sram_data_start) <=
+ SRAM_DATA_LIMIT, ".data_sram has exceeded its limit")
+
+ .stack_sram : ALIGN(PAGE_SIZE) {
+ __bl32_sram_stack_start = .;
+ . += PAGE_SIZE;
+ __bl32_sram_stack_end = .;
+ } >SRAM
+
+ . = PMUSRAM_BASE;
+
+ /*
+ * pmu_cpuson_entrypoint request address
+ * align 64K when resume, so put it in the
+ * start of pmusram
+ */
+ .pmusram : {
+ ASSERT(. == ALIGN(64 * 1024),
+ ".pmusram.entry request 64K aligned.");
+ *(.pmusram.entry)
+
+ __bl32_pmusram_text_start = .;
+ *(.pmusram.text)
+ *(.pmusram.rodata)
+ __bl32_pmusram_text_end = .;
+
+ __bl32_pmusram_data_start = .;
+ *(.pmusram.data)
+ __bl32_pmusram_data_end = .;
+ } >PMUSRAM
+}
+
+#endif /* ROCKCHIP_PLAT_LD_S */
diff --git a/plat/rockchip/rk3288/include/platform_def.h b/plat/rockchip/rk3288/include/platform_def.h
new file mode 100644
index 0000000..85ec3fb
--- /dev/null
+++ b/plat/rockchip/rk3288/include/platform_def.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include <bl32_param.h>
+#include <rk3288_def.h>
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf32-littlearm"
+#define PLATFORM_LINKER_ARCH arm
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL1)
+#define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x800
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_RK_CLST_TO_CPUID_SHIFT 6
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE U(1)
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE U(2)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 18
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE RK3288_GICD_BASE
+#define PLAT_RK_GICC_BASE RK3288_GICC_BASE
+
+#define PLAT_RK_UART_BASE UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3288_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3288_BAUDRATE
+
+/* ClusterId is always 0x5 on rk3288, filter it */
+#define PLAT_RK_MPIDR_CLUSTER_MASK 0
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define PSRAM_DO_DDR_RESUME 0
+#define PSRAM_CHECK_WAKEUP_CPU 0
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rockchip/rk3288/include/shared/bl32_param.h b/plat/rockchip/rk3288/include/shared/bl32_param.h
new file mode 100644
index 0000000..ffdb2f3
--- /dev/null
+++ b/plat/rockchip/rk3288/include/shared/bl32_param.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL32_PARAM_H
+#define BL32_PARAM_H
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF text, ro, rw, Size: 1MB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x100000)
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL32 at the top of the Trusted RAM
+ */
+#define BL32_BASE (TZRAM_BASE + 0x40000)
+#define BL32_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+#endif /* BL32_PARAM_H */
diff --git a/plat/rockchip/rk3288/plat_sip_calls.c b/plat/rockchip/rk3288/plat_sip_calls.c
new file mode 100644
index 0000000..5918d58
--- /dev/null
+++ b/plat/rockchip/rk3288/plat_sip_calls.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <plat_sip_calls.h>
+#include <rockchip_sip_svc.h>
+
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/rockchip/rk3288/platform.mk b/plat/rockchip/rk3288/platform.mk
new file mode 100644
index 0000000..b8dd195
--- /dev/null
+++ b/plat/rockchip/rk3288/platform.mk
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include drivers/arm/gic/v2/gicv2.mk
+
+ARM_CORTEX_A12 := yes
+ARM_ARCH_MAJOR := 7
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+DISABLE_BIN_GENERATION := 1
+
+PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/aarch32/ \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/secure/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/include/ \
+ -I${RK_PLAT_SOC}/include/shared/ \
+
+RK_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ ${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+ plat/common/aarch32/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/aarch32/xlat_tables.c
+
+BL32_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/ti/uart/aarch32/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/aarch32/cortex_a12.S \
+ ${RK_PLAT_COMMON}/aarch32/plat_helpers.S \
+ ${RK_PLAT_COMMON}/params_setup.c \
+ ${RK_PLAT_COMMON}/aarch32/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch32/platform_common.c \
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
+ ${RK_PLAT_SOC}/plat_sip_calls.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/secure/secure.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
+
+MULTI_CONSOLE_API := 1
+
+include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
+
+$(eval $(call add_define,PLAT_SP_MIN_EXTRA_LD_SCRIPT))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+WORKAROUND_CVE_2017_5715 := 0
diff --git a/plat/rockchip/rk3288/rk3288_def.h b/plat/rockchip/rk3288/rk3288_def.h
new file mode 100644
index 0000000..7bff865
--- /dev/null
+++ b/plat/rockchip/rk3288/rk3288_def.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK3288_DEF_H
+#define RK3288_DEF_H
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define SIZE_K(n) ((n) * 1024)
+#define SIZE_M(n) ((n) * 1024 * 1024)
+
+#define SRAM_TEXT_LIMIT (4 * 1024)
+#define SRAM_DATA_LIMIT (4 * 1024)
+
+#define DDR_PCTL0_BASE 0xff610000
+#define DDR_PCTL0_SIZE SIZE_K(64)
+
+#define DDR_PHY0_BASE 0xff620000
+#define DDR_PHY0_SIZE SIZE_K(64)
+
+#define DDR_PCTL1_BASE 0xff630000
+#define DDR_PCTL1_SIZE SIZE_K(64)
+
+#define DDR_PHY1_BASE 0xff640000
+#define DDR_PHY1_SIZE SIZE_K(64)
+
+#define UART0_BASE 0xff180000
+#define UART0_SIZE SIZE_K(64)
+
+#define UART1_BASE 0xff190000
+#define UART1_SIZE SIZE_K(64)
+
+#define UART2_BASE 0xff690000
+#define UART2_SIZE SIZE_K(64)
+
+#define UART3_BASE 0xff1b0000
+#define UART3_SIZE SIZE_K(64)
+
+#define UART4_BASE 0xff1c0000
+#define UART4_SIZE SIZE_K(64)
+
+/* 96k instead of 64k? */
+#define SRAM_BASE 0xff700000
+#define SRAM_SIZE SIZE_K(64)
+
+#define PMUSRAM_BASE 0xff720000
+#define PMUSRAM_SIZE SIZE_K(4)
+#define PMUSRAM_RSIZE SIZE_K(4)
+
+#define PMU_BASE 0xff730000
+#define PMU_SIZE SIZE_K(64)
+
+#define SGRF_BASE 0xff740000
+#define SGRF_SIZE SIZE_K(64)
+
+#define CRU_BASE 0xff760000
+#define CRU_SIZE SIZE_K(64)
+
+#define GRF_BASE 0xff770000
+#define GRF_SIZE SIZE_K(64)
+
+/* timer 6+7 can be set as secure in SGRF */
+#define STIME_BASE 0xff810000
+#define STIME_SIZE SIZE_K(64)
+
+#define SERVICE_BUS_BASE 0xffac0000
+#define SERVICE_BUS_SIZE SIZE_K(64)
+
+#define TZPC_BASE 0xffb00000
+#define TZPC_SIZE SIZE_K(64)
+
+#define GIC400_BASE 0xffc00000
+#define GIC400_SIZE SIZE_K(64)
+
+#define CORE_AXI_BUS_BASE 0xffd00000
+#define CORE_AXI_BUS_SIZE SIZE_M(1)
+
+#define COLD_BOOT_BASE 0xffff0000
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3288_BAUDRATE 115200
+#define RK3288_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+
+/******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define RK3288_GICD_BASE (GIC400_BASE + 0x1000)
+#define RK3288_GICC_BASE (GIC400_BASE + 0x2000)
+#define RK3288_GICR_BASE 0 /* no GICR in GIC-400 */
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER 29
+
+/* what are these, and are they present on rk3288? */
+#define RK_IRQ_SEC_SGI_0 8
+#define RK_IRQ_SEC_SGI_1 9
+#define RK_IRQ_SEC_SGI_2 10
+#define RK_IRQ_SEC_SGI_3 11
+#define RK_IRQ_SEC_SGI_4 12
+#define RK_IRQ_SEC_SGI_5 13
+#define RK_IRQ_SEC_SGI_6 14
+#define RK_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 0 interrupts.
+ */
+#define PLAT_RK_GICV2_G0_IRQS \
+ INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+#endif /* RK3288_DEF_H */
diff --git a/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk b/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk
new file mode 100644
index 0000000..befdca3
--- /dev/null
+++ b/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \
+ plat/rockchip/common/sp_min_plat_setup.c
diff --git a/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..cd604d2
--- /dev/null
+++ b/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+.globl clst_warmboot_data
+
+.macro func_rockchip_clst_warmboot
+.endm
+
+.macro rockchip_clst_warmboot_data
+clst_warmboot_data:
+ .rept PLATFORM_CLUSTER_COUNT
+ .word 0
+ .endr
+.endm
diff --git a/plat/rockchip/rk3328/drivers/pmu/pmu.c b/plat/rockchip/rk3328/drivers/pmu/pmu.c
new file mode 100644
index 0000000..a17fef9
--- /dev/null
+++ b/plat/rockchip/rk3328/drivers/pmu/pmu.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include <pmu.h>
+#include <pmu_com.h>
+#include <rk3328_def.h>
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+
+static struct rk3328_sleep_ddr_data ddr_data;
+static __sramdata struct rk3328_sleep_sram_data sram_data;
+
+static uint32_t cpu_warm_boot_addr;
+
+#pragma weak rk3328_pmic_suspend
+#pragma weak rk3328_pmic_resume
+
+static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id)
+{
+ uint32_t pd_reg, apm_reg;
+
+ pd_reg = mmio_read_32(PMU_BASE + PMU_PWRDN_CON) & BIT(cpu_id);
+ apm_reg = mmio_read_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id)) &
+ BIT(core_pm_en);
+
+ if (pd_reg && !apm_reg)
+ return core_pwr_pd;
+ else if (!pd_reg && apm_reg)
+ return core_pwr_wfi;
+
+ ERROR("%s: 0x%x, 0x%x\n", __func__, pd_reg, apm_reg);
+ while (1)
+ ;
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ uint32_t cpu_pd, cfg_info;
+
+ cpu_pd = PD_CPU0 + cpu_id;
+ cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id);
+
+ if (cfg_info == core_pwr_pd) {
+ /* disable apm cfg */
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ CORES_PM_DISABLE);
+
+ /* if the cores have be on, power off it firstly */
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ CORES_PM_DISABLE);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ }
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
+ } else {
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id);
+ return -EINVAL;
+ }
+
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ BIT(core_pm_sft_wakeup_en));
+ }
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
+{
+ uint32_t cpu_pd, core_pm_value;
+
+ cpu_pd = PD_CPU0 + cpu_id;
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
+ return 0;
+
+ if (pd_cfg == core_pwr_pd) {
+ if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
+ return -EINVAL;
+ /* disable apm cfg */
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ CORES_PM_DISABLE);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ } else {
+ core_pm_value = BIT(core_pm_en) | BIT(core_pm_dis_int);
+ if (pd_cfg == core_pwr_wfi_int)
+ core_pm_value |= BIT(core_pm_int_wakeup_en);
+
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
+ core_pm_value);
+ }
+
+ return 0;
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu;
+
+ /* turn off noboot cpus */
+ boot_cpu = plat_my_core_pos();
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ if (cpu == boot_cpu)
+ continue;
+ cpus_power_domain_off(cpu, core_pwr_pd);
+ }
+}
+
+void sram_save(void)
+{
+ /* TODO: support the sdram save for rk3328 SoCs*/
+}
+
+void sram_restore(void)
+{
+ /* TODO: support the sdram restore for rk3328 SoCs */
+}
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpu_id] = entrypoint;
+ dsb();
+
+ cpus_power_domain_on(cpu_id);
+
+ return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_off(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi);
+
+ return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
+ cpuson_entry_point[cpu_id] = (uintptr_t)plat_get_sec_entrypoint();
+ dsb();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
+
+ return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), CORES_PM_DISABLE);
+
+ return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_resume(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), CORES_PM_DISABLE);
+
+ return 0;
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(CPLL_ID));
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(GPLL_ID));
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(NPLL_ID));
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(APLL_ID));
+ dsb();
+
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE);
+ dsb();
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
+
+/*
+ * For PMIC RK805, its sleep pin is connect with gpio2_d2 from rk3328.
+ * If the PMIC is configed for responding the sleep pin to power off it,
+ * once the pin is output high, it will get the pmic power off.
+ */
+void __dead2 rockchip_soc_system_off(void)
+{
+ uint32_t val;
+
+ /* gpio config */
+ val = mmio_read_32(GRF_BASE + GRF_GPIO2D_IOMUX);
+ val &= ~GPIO2_D2_GPIO_MODE;
+ mmio_write_32(GRF_BASE + GRF_GPIO2D_IOMUX, val);
+
+ /* config output */
+ val = mmio_read_32(GPIO2_BASE + SWPORTA_DDR);
+ val |= GPIO2_D2;
+ mmio_write_32(GPIO2_BASE + SWPORTA_DDR, val);
+
+ /* config output high level */
+ val = mmio_read_32(GPIO2_BASE);
+ val |= GPIO2_D2;
+ mmio_write_32(GPIO2_BASE, val);
+ dsb();
+
+ while (1)
+ ;
+}
+
+static uint32_t clk_ungt_msk[CRU_CLKGATE_NUMS] = {
+ 0x187f, 0x0000, 0x010c, 0x0000, 0x0200,
+ 0x0010, 0x0000, 0x0017, 0x001f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0003, 0x0000,
+ 0xf001, 0x27c0, 0x04D9, 0x03ff, 0x0000,
+ 0x0000, 0x0000, 0x0010, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0003, 0x0008
+};
+
+static void clks_gating_suspend(uint32_t *ungt_msk)
+{
+ int i;
+
+ for (i = 0; i < CRU_CLKGATE_NUMS; i++) {
+ ddr_data.clk_ungt_save[i] =
+ mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(i));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i),
+ ((~ungt_msk[i]) << 16) | 0xffff);
+ }
+}
+
+static void clks_gating_resume(void)
+{
+ int i;
+
+ for (i = 0; i < CRU_CLKGATE_NUMS; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i),
+ ddr_data.clk_ungt_save[i] | 0xffff0000);
+}
+
+static inline void pm_pll_wait_lock(uint32_t pll_id)
+{
+ uint32_t delay = PLL_LOCKED_TIMEOUT;
+
+ while (delay > 0) {
+ if (mmio_read_32(CRU_BASE + PLL_CONS(pll_id, 1)) &
+ PLL_IS_LOCKED)
+ break;
+ delay--;
+ }
+ if (delay == 0)
+ ERROR("lock-pll: %d\n", pll_id);
+}
+
+static inline void pll_pwr_dwn(uint32_t pll_id, uint32_t pd)
+{
+ mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1),
+ BITS_WITH_WMASK(1U, 1U, 15));
+ if (pd)
+ mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1),
+ BITS_WITH_WMASK(1, 1, 14));
+ else
+ mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1),
+ BITS_WITH_WMASK(0, 1, 14));
+}
+
+static __sramfunc void dpll_suspend(void)
+{
+ int i;
+
+ /* slow mode */
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(DPLL_ID));
+
+ /* save pll con */
+ for (i = 0; i < CRU_PLL_CON_NUMS; i++)
+ sram_data.dpll_con_save[i] =
+ mmio_read_32(CRU_BASE + PLL_CONS(DPLL_ID, i));
+ mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1),
+ BITS_WITH_WMASK(1U, 1U, 15));
+ mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1),
+ BITS_WITH_WMASK(1, 1, 14));
+}
+
+static __sramfunc void dpll_resume(void)
+{
+ uint32_t delay = PLL_LOCKED_TIMEOUT;
+
+ mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1),
+ BITS_WITH_WMASK(1U, 1U, 15));
+ mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1),
+ BITS_WITH_WMASK(0, 1, 14));
+ mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1),
+ sram_data.dpll_con_save[1] | 0xc0000000);
+
+ dsb();
+
+ while (delay > 0) {
+ if (mmio_read_32(CRU_BASE + PLL_CONS(DPLL_ID, 1)) &
+ PLL_IS_LOCKED)
+ break;
+ delay--;
+ }
+ if (delay == 0)
+ while (1)
+ ;
+
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE,
+ PLL_NORM_MODE(DPLL_ID));
+}
+
+static inline void pll_suspend(uint32_t pll_id)
+{
+ int i;
+
+ /* slow mode */
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(pll_id));
+
+ /* save pll con */
+ for (i = 0; i < CRU_PLL_CON_NUMS; i++)
+ ddr_data.cru_plls_con_save[pll_id][i] =
+ mmio_read_32(CRU_BASE + PLL_CONS(pll_id, i));
+
+ /* powerdown pll */
+ pll_pwr_dwn(pll_id, pmu_pd_off);
+}
+
+static inline void pll_resume(uint32_t pll_id)
+{
+ mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1),
+ ddr_data.cru_plls_con_save[pll_id][1] | 0xc0000000);
+
+ pm_pll_wait_lock(pll_id);
+
+ if (PLL_IS_NORM_MODE(ddr_data.cru_mode_save, pll_id))
+ mmio_write_32(CRU_BASE + CRU_CRU_MODE,
+ PLL_NORM_MODE(pll_id));
+}
+
+static void pm_plls_suspend(void)
+{
+ ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_CRU_MODE);
+ ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(0));
+ ddr_data.clk_sel1 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(1));
+ ddr_data.clk_sel18 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(18));
+ ddr_data.clk_sel20 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(20));
+ ddr_data.clk_sel24 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(24));
+ ddr_data.clk_sel38 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(38));
+ pll_suspend(NPLL_ID);
+ pll_suspend(CPLL_ID);
+ pll_suspend(GPLL_ID);
+ pll_suspend(APLL_ID);
+
+ /* core */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(0),
+ BITS_WITH_WMASK(0, 0x1f, 0));
+
+ /* pclk_dbg */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(0, 0xf, 0));
+
+ /* crypto */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(20),
+ BITS_WITH_WMASK(0, 0x1f, 0));
+
+ /* pwm0 */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(24),
+ BITS_WITH_WMASK(0, 0x7f, 8));
+
+ /* uart2 from 24M */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(18),
+ BITS_WITH_WMASK(2, 0x3, 8));
+
+ /* clk_rtc32k */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(38),
+ BITS_WITH_WMASK(767, 0x3fff, 0) |
+ BITS_WITH_WMASK(2U, 0x3u, 14));
+}
+
+static void pm_plls_resume(void)
+{
+ /* clk_rtc32k */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(38),
+ ddr_data.clk_sel38 |
+ BITS_WMSK(0x3fff, 0) |
+ BITS_WMSK(0x3u, 14));
+
+ /* uart2 */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(18),
+ ddr_data.clk_sel18 | BITS_WMSK(0x3, 8));
+
+ /* pwm0 */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(24),
+ ddr_data.clk_sel24 | BITS_WMSK(0x7f, 8));
+
+ /* crypto */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(20),
+ ddr_data.clk_sel20 | BITS_WMSK(0x1f, 0));
+
+ /* pclk_dbg */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(1),
+ ddr_data.clk_sel1 | BITS_WMSK(0xf, 0));
+
+ /* core */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(0),
+ ddr_data.clk_sel0 | BITS_WMSK(0x1f, 0));
+
+ pll_pwr_dwn(APLL_ID, pmu_pd_on);
+ pll_pwr_dwn(GPLL_ID, pmu_pd_on);
+ pll_pwr_dwn(CPLL_ID, pmu_pd_on);
+ pll_pwr_dwn(NPLL_ID, pmu_pd_on);
+
+ pll_resume(APLL_ID);
+ pll_resume(GPLL_ID);
+ pll_resume(CPLL_ID);
+ pll_resume(NPLL_ID);
+}
+
+#define ARCH_TIMER_TICKS_PER_US (SYS_COUNTER_FREQ_IN_TICKS / 1000000)
+
+static __sramfunc void sram_udelay(uint32_t us)
+{
+ uint64_t pct_orig, pct_now;
+ uint64_t to_wait = ARCH_TIMER_TICKS_PER_US * us;
+
+ isb();
+ pct_orig = read_cntpct_el0();
+
+ do {
+ isb();
+ pct_now = read_cntpct_el0();
+ } while ((pct_now - pct_orig) <= to_wait);
+}
+
+/*
+ * For PMIC RK805, its sleep pin is connect with gpio2_d2 from rk3328.
+ * If the PMIC is configed for responding the sleep pin
+ * to get it into sleep mode,
+ * once the pin is output high, it will get the pmic into sleep mode.
+ */
+__sramfunc void rk3328_pmic_suspend(void)
+{
+ sram_data.pmic_sleep_save = mmio_read_32(GRF_BASE + PMIC_SLEEP_REG);
+ sram_data.pmic_sleep_gpio_save[1] = mmio_read_32(GPIO2_BASE + 4);
+ sram_data.pmic_sleep_gpio_save[0] = mmio_read_32(GPIO2_BASE);
+ mmio_write_32(GRF_BASE + PMIC_SLEEP_REG, BITS_WITH_WMASK(0, 0x3, 4));
+ mmio_write_32(GPIO2_BASE + 4,
+ sram_data.pmic_sleep_gpio_save[1] | BIT(26));
+ mmio_write_32(GPIO2_BASE,
+ sram_data.pmic_sleep_gpio_save[0] | BIT(26));
+}
+
+__sramfunc void rk3328_pmic_resume(void)
+{
+ mmio_write_32(GPIO2_BASE, sram_data.pmic_sleep_gpio_save[0]);
+ mmio_write_32(GPIO2_BASE + 4, sram_data.pmic_sleep_gpio_save[1]);
+ mmio_write_32(GRF_BASE + PMIC_SLEEP_REG,
+ sram_data.pmic_sleep_save | BITS_WMSK(0xffffu, 0));
+ /* Resuming volt need a lot of time */
+ sram_udelay(100);
+}
+
+static __sramfunc void ddr_suspend(void)
+{
+ sram_data.pd_sr_idle_save = mmio_read_32(DDR_UPCTL_BASE +
+ DDR_PCTL2_PWRCTL);
+ sram_data.pd_sr_idle_save &= SELFREF_EN;
+
+ mmio_clrbits_32(DDR_UPCTL_BASE + DDR_PCTL2_PWRCTL, SELFREF_EN);
+ sram_data.ddr_grf_con0 = mmio_read_32(DDR_GRF_BASE +
+ DDRGRF_SOC_CON(0));
+ mmio_write_32(DDR_GRF_BASE, BIT_WITH_WMSK(14) | WMSK_BIT(15));
+
+ /*
+ * Override csysreq from ddrc and
+ * send valid csysreq signal to PMU,
+ * csysreq is controlled by ddrc only
+ */
+
+ /* in self-refresh */
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(0));
+ while ((mmio_read_32(DDR_GRF_BASE + DDRGRF_SOC_STATUS(1)) &
+ (0x03 << 12)) != (0x02 << 12))
+ ;
+ /* ddr retention */
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(2));
+
+ /* ddr gating */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(0),
+ BITS_WITH_WMASK(0x7, 0x7, 4));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(7),
+ BITS_WITH_WMASK(1, 1, 4));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18),
+ BITS_WITH_WMASK(0x1ff, 0x1ff, 1));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(27),
+ BITS_WITH_WMASK(0x3, 0x3, 0));
+
+ dpll_suspend();
+}
+
+__sramfunc void dmc_restore(void)
+{
+ dpll_resume();
+
+ /* ddr gating */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(0),
+ BITS_WITH_WMASK(0, 0x7, 4));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(7),
+ BITS_WITH_WMASK(0, 1, 4));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18),
+ BITS_WITH_WMASK(0, 0x1ff, 1));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(27),
+ BITS_WITH_WMASK(0, 0x3, 0));
+
+ /* ddr de_retention */
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(2));
+ /* exit self-refresh */
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(0));
+ while ((mmio_read_32(DDR_GRF_BASE + DDRGRF_SOC_STATUS(1)) &
+ (0x03 << 12)) != (0x00 << 12))
+ ;
+
+ mmio_write_32(DDR_GRF_BASE, sram_data.ddr_grf_con0 | 0xc0000000);
+ if (sram_data.pd_sr_idle_save)
+ mmio_setbits_32(DDR_UPCTL_BASE + DDR_PCTL2_PWRCTL,
+ SELFREF_EN);
+}
+
+static __sramfunc void sram_dbg_uart_suspend(void)
+{
+ sram_data.uart2_ier = mmio_read_32(UART2_BASE + UART_IER);
+ mmio_write_32(UART2_BASE + UART_IER, UART_INT_DISABLE);
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(16), 0x20002000);
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(2), 0x00040004);
+}
+
+__sramfunc void sram_dbg_uart_resume(void)
+{
+ /* restore uart clk and reset fifo */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(16), 0x20000000);
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(2), 0x00040000);
+ mmio_write_32(UART2_BASE + UART_FCR, UART_FIFO_RESET);
+ mmio_write_32(UART2_BASE + UART_IER, sram_data.uart2_ier);
+}
+
+static __sramfunc void sram_soc_enter_lp(void)
+{
+ uint32_t apm_value;
+
+ apm_value = BIT(core_pm_en) |
+ BIT(core_pm_dis_int) |
+ BIT(core_pm_int_wakeup_en);
+ mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(PD_CPU0), apm_value);
+
+ dsb();
+ isb();
+err_loop:
+ wfi();
+ /*
+ *Soc will enter low power mode and
+ *do not return to here.
+ */
+ goto err_loop;
+}
+
+__sramfunc void sram_suspend(void)
+{
+ /* disable mmu and icache */
+ disable_mmu_icache_el3();
+ tlbialle3();
+ dsbsy();
+ isb();
+
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ ((uintptr_t)&pmu_cpuson_entrypoint >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ /* ddr self-refresh and gating phy */
+ ddr_suspend();
+
+ rk3328_pmic_suspend();
+
+ sram_dbg_uart_suspend();
+
+ sram_soc_enter_lp();
+}
+
+void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
+{
+ sram_suspend();
+
+ /* should never reach here */
+ psci_power_down_wfi();
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ clks_gating_suspend(clk_ungt_msk);
+
+ pm_plls_suspend();
+
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ pm_plls_resume();
+
+ clks_gating_resume();
+
+ plat_rockchip_gic_cpuif_enable();
+
+ return 0;
+}
+
+void rockchip_plat_mmu_el3(void)
+{
+ /* TODO: support the el3 for rk3328 SoCs */
+}
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot;
+
+ /* the warm booting address of cpus */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ nonboot_cpus_off();
+
+ INFO("%s: pd status 0x%x\n",
+ __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/rk3328/drivers/pmu/pmu.h b/plat/rockchip/rk3328/drivers/pmu/pmu.h
new file mode 100644
index 0000000..dfb8912
--- /dev/null
+++ b/plat/rockchip/rk3328/drivers/pmu/pmu.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_H
+#define PMU_H
+
+#include <soc.h>
+
+struct rk3328_sleep_ddr_data {
+ uint32_t pmu_debug_enable;
+ uint32_t debug_iomux_save;
+ uint32_t pmic_sleep_save;
+ uint32_t pmu_wakeup_conf0;
+ uint32_t pmu_pwrmd_com;
+ uint32_t cru_mode_save;
+ uint32_t clk_sel0, clk_sel1, clk_sel18,
+ clk_sel20, clk_sel24, clk_sel38;
+ uint32_t clk_ungt_save[CRU_CLKGATE_NUMS];
+ uint32_t cru_plls_con_save[MAX_PLL][CRU_PLL_CON_NUMS];
+};
+
+struct rk3328_sleep_sram_data {
+ uint32_t pmic_sleep_save;
+ uint32_t pmic_sleep_gpio_save[2];
+ uint32_t ddr_grf_con0;
+ uint32_t dpll_con_save[CRU_PLL_CON_NUMS];
+ uint32_t pd_sr_idle_save;
+ uint32_t uart2_ier;
+};
+
+/*****************************************************************************
+ * The ways of cores power domain contorlling
+ *****************************************************************************/
+enum cores_pm_ctr_mode {
+ core_pwr_pd = 0,
+ core_pwr_wfi = 1,
+ core_pwr_wfi_int = 2
+};
+
+enum pmu_cores_pm_by_wfi {
+ core_pm_en = 0,
+ core_pm_int_wakeup_en,
+ core_pm_dis_int,
+ core_pm_sft_wakeup_en
+};
+
+extern void *pmu_cpuson_entrypoint_start;
+extern void *pmu_cpuson_entrypoint_end;
+
+#define CORES_PM_DISABLE 0x0
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WAKEUP_CFG0 0x00
+#define PMU_PWRDN_CON 0x0c
+#define PMU_PWRDN_ST 0x10
+#define PMU_PWRMD_COM 0x18
+#define PMU_SFT_CON 0x1c
+#define PMU_INT_CON 0x20
+#define PMU_INT_ST 0x24
+#define PMU_POWER_ST 0x44
+#define PMU_CPUAPM_CON(n) (0x80 + (n) * 4)
+#define PMU_SYS_REG(n) (0xa0 + (n) * 4)
+
+#define CHECK_CPU_WFIE_BASE (GRF_BASE + GRF_CPU_STATUS(1))
+
+enum pmu_core_pwrst_shift {
+ clst_cpu_wfe = 0,
+ clst_cpu_wfi = 4,
+};
+
+#define clstl_cpu_wfe (clst_cpu_wfe)
+#define clstb_cpu_wfe (clst_cpu_wfe)
+
+enum pmu_pd_id {
+ PD_CPU0 = 0,
+ PD_CPU1,
+ PD_CPU2,
+ PD_CPU3,
+};
+
+enum pmu_power_mode_common {
+ pmu_mode_en = 0,
+ sref_enter_en,
+ global_int_disable_cfg,
+ cpu0_pd_en,
+ wait_wakeup_begin_cfg = 4,
+ l2_flush_en,
+ l2_idle_en,
+ ddrio_ret_de_req,
+ ddrio_ret_en = 8,
+};
+
+enum pmu_sft_con {
+ upctl_c_sysreq_cfg = 0,
+ l2flushreq_req,
+ ddr_io_ret_cfg,
+ pmu_sft_ret_cfg,
+};
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+#define PD_CTR_LOOP 500
+#define CHK_CPU_LOOP 500
+#define MAX_WAIT_CONUT 1000
+
+#define WAKEUP_INT_CLUSTER_EN 0x1
+#define PMIC_SLEEP_REG 0x34
+
+#define PLL_IS_NORM_MODE(mode, pll_id) \
+ ((mode & (PLL_NORM_MODE(pll_id)) & 0xffff) != 0)
+
+#define CTLR_ENABLE_G1_BIT BIT(1)
+#define UART_FIFO_EMPTY BIT(6)
+
+#define UART_IER 0x04
+#define UART_FCR 0x08
+#define UART_LSR 0x14
+
+#define UART_INT_DISABLE 0x00
+#define UART_FIFO_RESET 0x07
+
+#endif /* PMU_H */
diff --git a/plat/rockchip/rk3328/drivers/soc/soc.c b/plat/rockchip/rk3328/drivers/soc/soc.c
new file mode 100644
index 0000000..306308f
--- /dev/null
+++ b/plat/rockchip/rk3328/drivers/soc/soc.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <ddr_parameter.h>
+#include <plat_private.h>
+#include <rk3328_def.h>
+#include <soc.h>
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(UART0_BASE, UART0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART1_BASE, UART1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART2_BASE, UART2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GPIO0_BASE, GPIO0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GPIO1_BASE, GPIO1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GPIO2_BASE, GPIO2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GPIO3_BASE, GPIO3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GRF_BASE, GRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(FIREWALL_CFG_BASE, FIREWALL_CFG_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SHARE_MEM_BASE, SHARE_MEM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_GRF_BASE, DDR_GRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_UPCTL_BASE, DDR_UPCTL_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PWM_BASE, PWM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PARAM_BASE, DDR_PARAM_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(EFUSE8_BASE, EFUSE8_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(EFUSE32_BASE, EFUSE32_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PHY_BASE, DDR_PHY_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SERVER_MSCH_BASE, SERVER_MSCH_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_MONITOR_BASE, DDR_MONITOR_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(VOP_BASE, VOP_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOADE_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER_CHN_BASE(1) + TIMER_LOADE_COUNT1, 0xffffffff);
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER_CHN_BASE(1) + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void sgrf_init(void)
+{
+#ifdef PLAT_RK_SECURE_DDR_MINILOADER
+ uint32_t i, val;
+ struct param_ddr_usage usg;
+
+ /* general secure regions */
+ usg = ddr_region_usage_parse(DDR_PARAM_BASE,
+ PLAT_MAX_DDR_CAPACITY_MB);
+ for (i = 0; i < usg.s_nr; i++) {
+ /* enable secure */
+ val = mmio_read_32(FIREWALL_DDR_BASE +
+ FIREWALL_DDR_FW_DDR_CON_REG);
+ val |= BIT(7 - i);
+ mmio_write_32(FIREWALL_DDR_BASE +
+ FIREWALL_DDR_FW_DDR_CON_REG, val);
+ /* map top and base */
+ mmio_write_32(FIREWALL_DDR_BASE +
+ FIREWALL_DDR_FW_DDR_RGN(7 - i),
+ RG_MAP_SECURE(usg.s_top[i], usg.s_base[i]));
+ }
+#endif
+
+ /* set ddr rgn0_top and rga0_top as 0 */
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_FW_DDR_RGN(0), 0x0);
+
+ /* set all slave ip into no-secure, except stimer */
+ mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(0),
+ SGRF_SLV_S_ALL_NS);
+ mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(1),
+ SGRF_SLV_S_ALL_NS);
+ mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(2),
+ SGRF_SLV_S_ALL_NS | STIMER_S);
+ mmio_write_32(FIREWALL_CFG_BASE + FIREWALL_CFG_FW_SYS_CON(3),
+ SGRF_SLV_S_ALL_NS);
+
+ /* set all master ip into no-secure */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), 0xf0000000);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), SGRF_MST_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4), SGRF_MST_S_ALL_NS);
+
+ /* set DMAC into no-secure */
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(3), DMA_IRQ_BOOT_NS);
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(4), DMA_PERI_CH_NS_15_0);
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(5), DMA_PERI_CH_NS_19_16);
+ mmio_write_32(SGRF_BASE + SGRF_DMAC_CON(5), DMA_MANAGER_BOOT_NS);
+
+ /* soft reset dma before use */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(3), DMA_SOFTRST_REQ);
+ udelay(5);
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(3), DMA_SOFTRST_RLS);
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ sgrf_init();
+
+ NOTICE("BL31:Rockchip release version: v%d.%d\n",
+ MAJOR_VERSION, MINOR_VERSION);
+}
diff --git a/plat/rockchip/rk3328/drivers/soc/soc.h b/plat/rockchip/rk3328/drivers/soc/soc.h
new file mode 100644
index 0000000..e8cbc09
--- /dev/null
+++ b/plat/rockchip/rk3328/drivers/soc/soc.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+/******************************* stimer ***************************************/
+#define TIMER_LOADE_COUNT0 0x00
+#define TIMER_LOADE_COUNT1 0x04
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INTSTATUS 0x18
+#define TIMER_EN 0x1
+
+/**************************** read/write **************************************/
+#ifndef BITS_WMSK
+#define BITS_WMSK(msk, shift) ((msk) << (shift + REG_MSK_SHIFT))
+#endif
+
+/**************************** cru *********************************************/
+enum plls_id {
+ APLL_ID = 0,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ REVERVE,
+ NPLL_ID,
+ MAX_PLL,
+};
+
+#define CRU_CRU_MODE 0x0080
+#define CRU_CRU_MISC 0x0084
+#define CRU_GLB_SRST_FST 0x009c
+#define CRU_GLB_SRST_FST_VALUE 0xfdb9
+#define PLL_CONS(id, i) (0x020 * (id) + ((i) * 4))
+#define CRU_CLKSEL_CON(i) (0x100 + ((i) * 4))
+#define CRU_CLKSEL_NUMS 53
+#define CRU_CLKGATE_CON(i) (0x200 + ((i) * 4))
+#define CRU_CLKGATE_NUMS 29
+#define CRU_SOFTRSTS_CON(n) (0x300 + ((n) * 4))
+#define CRU_SOFTRSTS_NUMS 12
+#define CRU_PLL_CON_NUMS 5
+
+/* PLLn_CON1 */
+#define PLL_IS_LOCKED BIT(10)
+/* PLLn_CON0 */
+#define PLL_BYPASS BITS_WITH_WMASK(1, 0x1, 15)
+#define PLL_NO_BYPASS BITS_WITH_WMASK(0, 0x1, 15)
+/* CRU_MODE */
+#define PLL_SLOW_MODE(id) ((id) == NPLL_ID) ? \
+ BITS_WITH_WMASK(0, 0x1, 1) : \
+ BITS_WITH_WMASK(0, 0x1, ((id) * 4))
+#define PLL_NORM_MODE(id) ((id) == NPLL_ID) ? \
+ BITS_WITH_WMASK(1, 0x1, 1) : \
+ BITS_WITH_WMASK(1, 0x1, ((id) * 4))
+
+#define CRU_GATEID_CONS(ID) (0x200 + (ID / 16) * 4)
+#define CRU_CONS_GATEID(i) (16 * (i))
+#define GATE_ID(reg, bit) ((reg * 16) + bit)
+
+#define PLL_LOCKED_TIMEOUT 600000U
+
+#define STIMER_CHN_BASE(n) (STIME_BASE + 0x20 * (n))
+/************************** config regs ***************************************/
+#define FIREWALL_CFG_FW_SYS_CON(n) (0x000 + (n) * 4)
+#define FIREWALL_DDR_FW_DDR_RGN(n) (0x000 + (n) * 4)
+#define FIREWALL_DDR_FW_DDR_MST(n) (0x020 + (n) * 4)
+#define FIREWALL_DDR_FW_DDR_CON_REG (0x040)
+#define GRF_SOC_CON(n) (0x400 + (n) * 4)
+#define GRF_SOC_STATUS(n) (0x480 + (n) * 4)
+#define GRF_CPU_STATUS(n) (0x520 + (n) * 4)
+#define GRF_OS_REG(n) (0x5c8 + (n) * 4)
+#define DDRGRF_SOC_CON(n) (0x000 + (n) * 4)
+#define DDRGRF_SOC_STATUS(n) (0x100 + (n) * 4)
+#define SGRF_SOC_CON(n) (0x000 + (n) * 4)
+#define SGRF_DMAC_CON(n) (0x100 + (n) * 4)
+#define SGRF_HDCP_KEY_CON(n) (0x280 + (n) * 4)
+
+#define DDR_PCTL2_PWRCTL 0x30
+/************************** regs func *****************************************/
+#define STIMER_S BIT(23)
+#define SGRF_SLV_S_ALL_NS 0x0
+#define SGRF_MST_S_ALL_NS 0xffffffff
+#define DMA_IRQ_BOOT_NS 0xffffffff
+#define DMA_MANAGER_BOOT_NS 0x80008000
+#define DMA_PERI_CH_NS_15_0 0xffffffff
+#define DMA_PERI_CH_NS_19_16 0x000f000f
+#define DMA_SOFTRST_REQ 0x01000100
+#define DMA_SOFTRST_RLS 0x01000000
+
+#define SELFREF_EN BIT(0)
+/************************** cpu ***********************************************/
+#define CPU_BOOT_ADDR_WMASK 0xffff0000
+#define CPU_BOOT_ADDR_ALIGN 16
+
+/************************** ddr secure region *********************************/
+#define PLAT_MAX_DDR_CAPACITY_MB 4096
+#define RG_MAP_SECURE(top, base) ((((top) - 1) << 16) | (base))
+
+/************************** gpio2_d2 ******************************************/
+#define SWPORTA_DR 0x00
+#define SWPORTA_DDR 0x04
+#define GPIO2_D2 BIT(26)
+#define GPIO2_D2_GPIO_MODE 0x30
+#define GRF_GPIO2D_IOMUX 0x34
+
+#endif /* SOC_H */
diff --git a/plat/rockchip/rk3328/include/plat.ld.S b/plat/rockchip/rk3328/include/plat.ld.S
new file mode 100644
index 0000000..e9bb3a2
--- /dev/null
+++ b/plat/rockchip/rk3328/include/plat.ld.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ROCKCHIP_PLAT_LD_S
+#define ROCKCHIP_PLAT_LD_S
+
+MEMORY {
+ PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
+}
+
+SECTIONS
+{
+ . = PMUSRAM_BASE;
+
+ /*
+ * pmu_cpuson_entrypoint request address
+ * align 64K when resume, so put it in the
+ * start of pmusram
+ */
+ .text_pmusram : {
+ ASSERT(. == ALIGN(64 * 1024),
+ ".pmusram.entry request 64K aligned.");
+ *(.pmusram.entry)
+ __bl31_pmusram_text_start = .;
+ *(.pmusram.text)
+ *(.pmusram.rodata)
+ __bl31_pmusram_text_end = .;
+ __bl31_pmusram_data_start = .;
+ *(.pmusram.data)
+ __bl31_pmusram_data_end = .;
+
+ } >PMUSRAM
+}
+
+#endif /* ROCKCHIP_PLAT_LD_S */
diff --git a/plat/rockchip/rk3328/include/platform_def.h b/plat/rockchip/rk3328/include/platform_def.h
new file mode 100644
index 0000000..6579756
--- /dev/null
+++ b/plat/rockchip/rk3328/include/platform_def.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <plat/common/common_def.h>
+
+#include <rk3328_def.h>
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL1)
+#define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x800
+#elif defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+#define PLAT_RK_CLST_TO_CPUID_SHIFT 6
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE U(1)
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE U(2)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF text, ro, rw, Size: 1MB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x100000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x40000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 9
+#define MAX_MMAP_REGIONS 33
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE RK3328_GICD_BASE
+#define PLAT_RK_GICC_BASE RK3328_GICC_BASE
+
+#define PLAT_RK_UART_BASE UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3328_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3328_BAUDRATE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define PSRAM_DO_DDR_RESUME 0
+#define PSRAM_CHECK_WAKEUP_CPU 0
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
new file mode 100644
index 0000000..5b4766d
--- /dev/null
+++ b/plat/rockchip/rk3328/platform.mk
@@ -0,0 +1,75 @@
+#
+# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include drivers/arm/gic/v2/gicv2.mk
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+DISABLE_BIN_GENERATION := 1
+
+PLAT_INCLUDES := -Idrivers/arm/gic/common/ \
+ -Idrivers/arm/gic/v2/ \
+ -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/aarch64/ \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_COMMON}/drivers/parameter/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/include/
+
+RK_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ ${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/params_setup.c \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c
+
+ifdef PLAT_RK_SECURE_DDR_MINILOADER
+BL31_SOURCES += ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c
+endif
+
+include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
+
+# Enable workarounds for selected Cortex-A53 errata
+ERRATA_A53_855873 := 1
+
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+WORKAROUND_CVE_2017_5715 := 0
diff --git a/plat/rockchip/rk3328/rk3328_def.h b/plat/rockchip/rk3328/rk3328_def.h
new file mode 100644
index 0000000..60055e8
--- /dev/null
+++ b/plat/rockchip/rk3328/rk3328_def.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK3328_DEF_H
+#define RK3328_DEF_H
+
+#define MAJOR_VERSION (1)
+#define MINOR_VERSION (2)
+
+#define SIZE_K(n) ((n) * 1024)
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define UART0_BASE 0xff110000
+#define UART0_SIZE SIZE_K(64)
+
+#define UART1_BASE 0xff120000
+#define UART1_SIZE SIZE_K(64)
+
+#define UART2_BASE 0xff130000
+#define UART2_SIZE SIZE_K(64)
+
+#define PMU_BASE 0xff140000
+#define PMU_SIZE SIZE_K(64)
+
+#define SGRF_BASE 0xff0d0000
+#define SGRF_SIZE SIZE_K(64)
+
+#define CRU_BASE 0xff440000
+#define CRU_SIZE SIZE_K(64)
+
+#define GRF_BASE 0xff100000
+#define GRF_SIZE SIZE_K(64)
+
+#define GPIO0_BASE 0xff210000
+#define GPIO0_SIZE SIZE_K(32)
+
+#define GPIO1_BASE 0xff220000
+#define GPIO1_SIZE SIZE_K(32)
+
+#define GPIO2_BASE 0xff230000
+#define GPIO2_SIZE SIZE_K(64)
+
+#define GPIO3_BASE 0xff240000
+#define GPIO3_SIZE SIZE_K(64)
+
+#define STIME_BASE 0xff1d0000
+#define STIME_SIZE SIZE_K(64)
+
+#define INTMEM_BASE 0xff090000
+#define INTMEM_SIZE SIZE_K(32)
+
+#define SRAM_LDS_BASE (INTMEM_BASE + SIZE_K(4))
+#define SRAM_LDS_SIZE (INTMEM_SIZE - SIZE_K(4))
+
+#define PMUSRAM_BASE INTMEM_BASE
+#define PMUSRAM_SIZE SIZE_K(4)
+#define PMUSRAM_RSIZE SIZE_K(4)
+
+#define VOP_BASE 0xff370000
+#define VOP_SIZE SIZE_K(16)
+
+#define DDR_PHY_BASE 0xff400000
+#define DDR_PHY_SIZE SIZE_K(4)
+
+#define SERVER_MSCH_BASE 0xff720000
+#define SERVER_MSCH_SIZE SIZE_K(4)
+
+#define DDR_UPCTL_BASE 0xff780000
+#define DDR_UPCTL_SIZE SIZE_K(12)
+
+#define DDR_MONITOR_BASE 0xff790000
+#define DDR_MONITOR_SIZE SIZE_K(4)
+
+#define FIREWALL_DDR_BASE 0xff7c0000
+#define FIREWALL_DDR_SIZE SIZE_K(64)
+
+#define FIREWALL_CFG_BASE 0xff7d0000
+#define FIREWALL_CFG_SIZE SIZE_K(64)
+
+#define GIC400_BASE 0xff810000
+#define GIC400_SIZE SIZE_K(64)
+
+#define DDR_GRF_BASE 0xff798000
+#define DDR_GRF_SIZE SIZE_K(16)
+
+#define PWM_BASE 0xff1b0000
+#define PWM_SIZE SIZE_K(64)
+
+#define DDR_PARAM_BASE 0x02000000
+#define DDR_PARAM_SIZE SIZE_K(4)
+
+#define EFUSE8_BASE 0xff260000
+#define EFUSE8_SIZE SIZE_K(4)
+
+#define EFUSE32_BASE 0xff0b0000
+#define EFUSE32_SIZE SIZE_K(4)
+
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3328_BAUDRATE 1500000
+#define RK3328_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000U
+#define SYS_COUNTER_FREQ_IN_MHZ 24
+
+/******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define RK3328_GICD_BASE (GIC400_BASE + 0x1000)
+#define RK3328_GICC_BASE (GIC400_BASE + 0x2000)
+#define RK3328_GICR_BASE 0 /* no GICR in GIC-400 */
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER 29
+
+#define RK_IRQ_SEC_SGI_0 8
+#define RK_IRQ_SEC_SGI_1 9
+#define RK_IRQ_SEC_SGI_2 10
+#define RK_IRQ_SEC_SGI_3 11
+#define RK_IRQ_SEC_SGI_4 12
+#define RK_IRQ_SEC_SGI_5 13
+#define RK_IRQ_SEC_SGI_6 14
+#define RK_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 0 interrupts.
+ */
+#define PLAT_RK_GICV2_G0_IRQS \
+ INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/
+#define SHARE_MEM_PAGE_NUM 15
+#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4)
+
+#endif /* RK3328_DEF_H */
diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c
new file mode 100644
index 0000000..fa98eb3
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <ddr_rk3368.h>
+#include <pmu.h>
+#include <rk3368_def.h>
+#include <soc.h>
+
+/* GRF_SOC_STATUS0 */
+#define DPLL_LOCK (0x1 << 2)
+
+/* GRF_DDRC0_CON0 */
+#define GRF_DDR_16BIT_EN (((0x1 << 3) << 16) | (0x1 << 3))
+#define GRF_DDR_32BIT_EN (((0x1 << 3) << 16) | (0x0 << 3))
+#define GRF_MOBILE_DDR_EN (((0x1 << 4) << 16) | (0x1 << 4))
+#define GRF_MOBILE_DDR_DISB (((0x1 << 4) << 16) | (0x0 << 4))
+#define GRF_DDR3_EN (((0x1 << 2) << 16) | (0x1 << 2))
+#define GRF_LPDDR2_3_EN (((0x1 << 2) << 16) | (0x0 << 2))
+
+/* PMUGRF_SOC_CON0 */
+#define ddrphy_bufferen_io_en(n) ((0x1 << (9 + 16)) | (n << 9))
+#define ddrphy_bufferen_core_en(n) ((0x1 << (8 + 16)) | (n << 8))
+
+struct PCTRL_TIMING_TAG {
+ uint32_t ddrfreq;
+ uint32_t TOGCNT1U;
+ uint32_t TINIT;
+ uint32_t TRSTH;
+ uint32_t TOGCNT100N;
+ uint32_t TREFI;
+ uint32_t TMRD;
+ uint32_t TRFC;
+ uint32_t TRP;
+ uint32_t TRTW;
+ uint32_t TAL;
+ uint32_t TCL;
+ uint32_t TCWL;
+ uint32_t TRAS;
+ uint32_t TRC;
+ uint32_t TRCD;
+ uint32_t TRRD;
+ uint32_t TRTP;
+ uint32_t TWR;
+ uint32_t TWTR;
+ uint32_t TEXSR;
+ uint32_t TXP;
+ uint32_t TXPDLL;
+ uint32_t TZQCS;
+ uint32_t TZQCSI;
+ uint32_t TDQS;
+ uint32_t TCKSRE;
+ uint32_t TCKSRX;
+ uint32_t TCKE;
+ uint32_t TMOD;
+ uint32_t TRSTL;
+ uint32_t TZQCL;
+ uint32_t TMRR;
+ uint32_t TCKESR;
+ uint32_t TDPD;
+ uint32_t TREFI_MEM_DDR3;
+};
+
+struct MSCH_SAVE_REG_TAG {
+ uint32_t ddrconf;
+ uint32_t ddrtiming;
+ uint32_t ddrmode;
+ uint32_t readlatency;
+ uint32_t activate;
+ uint32_t devtodev;
+};
+
+/* ddr suspend need save reg */
+struct PCTL_SAVE_REG_TAG {
+ uint32_t SCFG;
+ uint32_t CMDTSTATEN;
+ uint32_t MCFG1;
+ uint32_t MCFG;
+ uint32_t PPCFG;
+ struct PCTRL_TIMING_TAG pctl_timing;
+ /* DFI Control Registers */
+ uint32_t DFITCTRLDELAY;
+ uint32_t DFIODTCFG;
+ uint32_t DFIODTCFG1;
+ uint32_t DFIODTRANKMAP;
+ /* DFI Write Data Registers */
+ uint32_t DFITPHYWRDATA;
+ uint32_t DFITPHYWRLAT;
+ uint32_t DFITPHYWRDATALAT;
+ /* DFI Read Data Registers */
+ uint32_t DFITRDDATAEN;
+ uint32_t DFITPHYRDLAT;
+ /* DFI Update Registers */
+ uint32_t DFITPHYUPDTYPE0;
+ uint32_t DFITPHYUPDTYPE1;
+ uint32_t DFITPHYUPDTYPE2;
+ uint32_t DFITPHYUPDTYPE3;
+ uint32_t DFITCTRLUPDMIN;
+ uint32_t DFITCTRLUPDMAX;
+ uint32_t DFITCTRLUPDDLY;
+ uint32_t DFIUPDCFG;
+ uint32_t DFITREFMSKI;
+ uint32_t DFITCTRLUPDI;
+ /* DFI Status Registers */
+ uint32_t DFISTCFG0;
+ uint32_t DFISTCFG1;
+ uint32_t DFITDRAMCLKEN;
+ uint32_t DFITDRAMCLKDIS;
+ uint32_t DFISTCFG2;
+ /* DFI Low Power Register */
+ uint32_t DFILPCFG0;
+};
+
+struct DDRPHY_SAVE_REG_TAG {
+ uint32_t PHY_REG0;
+ uint32_t PHY_REG1;
+ uint32_t PHY_REGB;
+ uint32_t PHY_REGC;
+ uint32_t PHY_REG11;
+ uint32_t PHY_REG13;
+ uint32_t PHY_REG14;
+ uint32_t PHY_REG16;
+ uint32_t PHY_REG20;
+ uint32_t PHY_REG21;
+ uint32_t PHY_REG26;
+ uint32_t PHY_REG27;
+ uint32_t PHY_REG28;
+ uint32_t PHY_REG30;
+ uint32_t PHY_REG31;
+ uint32_t PHY_REG36;
+ uint32_t PHY_REG37;
+ uint32_t PHY_REG38;
+ uint32_t PHY_REG40;
+ uint32_t PHY_REG41;
+ uint32_t PHY_REG46;
+ uint32_t PHY_REG47;
+ uint32_t PHY_REG48;
+ uint32_t PHY_REG50;
+ uint32_t PHY_REG51;
+ uint32_t PHY_REG56;
+ uint32_t PHY_REG57;
+ uint32_t PHY_REG58;
+ uint32_t PHY_REGDLL;
+ uint32_t PHY_REGEC;
+ uint32_t PHY_REGED;
+ uint32_t PHY_REGEE;
+ uint32_t PHY_REGEF;
+ uint32_t PHY_REGFB;
+ uint32_t PHY_REGFC;
+ uint32_t PHY_REGFD;
+ uint32_t PHY_REGFE;
+};
+
+struct BACKUP_REG_TAG {
+ uint32_t tag;
+ uint32_t pctladdr;
+ struct PCTL_SAVE_REG_TAG pctl;
+ uint32_t phyaddr;
+ struct DDRPHY_SAVE_REG_TAG phy;
+ uint32_t nocaddr;
+ struct MSCH_SAVE_REG_TAG noc;
+ uint32_t pllselect;
+ uint32_t phypllockaddr;
+ uint32_t phyplllockmask;
+ uint32_t phyplllockval;
+ uint32_t pllpdstat;
+ uint32_t dpllmodeaddr;
+ uint32_t dpllslowmode;
+ uint32_t dpllnormalmode;
+ uint32_t dpllresetaddr;
+ uint32_t dpllreset;
+ uint32_t dplldereset;
+ uint32_t dpllconaddr;
+ uint32_t dpllcon[4];
+ uint32_t dplllockaddr;
+ uint32_t dplllockmask;
+ uint32_t dplllockval;
+ uint32_t ddrpllsrcdivaddr;
+ uint32_t ddrpllsrcdiv;
+ uint32_t retendisaddr;
+ uint32_t retendisval;
+ uint32_t grfregaddr;
+ uint32_t grfddrcreg;
+ uint32_t crupctlphysoftrstaddr;
+ uint32_t cruresetpctlphy;
+ uint32_t cruderesetphy;
+ uint32_t cruderesetpctlphy;
+ uint32_t physoftrstaddr;
+ uint32_t endtag;
+};
+
+static uint32_t ddr_get_phy_pll_freq(void)
+{
+ uint32_t ret = 0;
+ uint32_t fb_div, pre_div;
+
+ fb_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC);
+ fb_div |= (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED) & 0x1) << 8;
+
+ pre_div = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) & 0xff;
+ ret = 2 * 24 * fb_div / (4 * pre_div);
+
+ return ret;
+}
+
+static void ddr_copy(uint32_t *pdest, uint32_t *psrc, uint32_t words)
+{
+ uint32_t i;
+
+ for (i = 0; i < words; i++)
+ pdest[i] = psrc[i];
+}
+
+static void ddr_get_dpll_cfg(uint32_t *p)
+{
+ uint32_t nmhz, NO, NF, NR;
+
+ nmhz = ddr_get_phy_pll_freq();
+ if (nmhz <= 150)
+ NO = 6;
+ else if (nmhz <= 250)
+ NO = 4;
+ else if (nmhz <= 500)
+ NO = 2;
+ else
+ NO = 1;
+
+ NR = 1;
+ NF = 2 * nmhz * NR * NO / 24;
+
+ p[0] = SET_NR(NR) | SET_NO(NO);
+ p[1] = SET_NF(NF);
+ p[2] = SET_NB(NF / 2);
+}
+
+void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr)
+{
+ struct BACKUP_REG_TAG *p_ddr_reg = (struct BACKUP_REG_TAG *)base_addr;
+ struct PCTL_SAVE_REG_TAG *pctl_tim = &p_ddr_reg->pctl;
+
+ p_ddr_reg->tag = 0x56313031;
+ p_ddr_reg->pctladdr = DDR_PCTL_BASE;
+ p_ddr_reg->phyaddr = DDR_PHY_BASE;
+ p_ddr_reg->nocaddr = SERVICE_BUS_BASE;
+
+ /* PCTLR */
+ ddr_copy((uint32_t *)&pctl_tim->pctl_timing.TOGCNT1U,
+ (uint32_t *)(DDR_PCTL_BASE + DDR_PCTL_TOGCNT1U), 35);
+ pctl_tim->pctl_timing.TREFI |= DDR_UPD_REF_ENABLE;
+ pctl_tim->SCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_SCFG);
+ pctl_tim->CMDTSTATEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_CMDTSTATEN);
+ pctl_tim->MCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG1);
+ pctl_tim->MCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_MCFG);
+ pctl_tim->PPCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_PPCFG);
+ pctl_tim->pctl_timing.ddrfreq = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_TOGCNT1U * 2);
+ pctl_tim->DFITCTRLDELAY = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLDELAY);
+ pctl_tim->DFIODTCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIODTCFG);
+ pctl_tim->DFIODTCFG1 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFIODTCFG1);
+ pctl_tim->DFIODTRANKMAP = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFIODTRANKMAP);
+ pctl_tim->DFITPHYWRDATA = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRDATA);
+ pctl_tim->DFITPHYWRLAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRLAT);
+ pctl_tim->DFITPHYWRDATALAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYWRDATALAT);
+ pctl_tim->DFITRDDATAEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITRDDATAEN);
+ pctl_tim->DFITPHYRDLAT = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYRDLAT);
+ pctl_tim->DFITPHYUPDTYPE0 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE0);
+ pctl_tim->DFITPHYUPDTYPE1 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE1);
+ pctl_tim->DFITPHYUPDTYPE2 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE2);
+ pctl_tim->DFITPHYUPDTYPE3 = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITPHYUPDTYPE3);
+ pctl_tim->DFITCTRLUPDMIN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDMIN);
+ pctl_tim->DFITCTRLUPDMAX = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDMAX);
+ pctl_tim->DFITCTRLUPDDLY = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDDLY);
+
+ pctl_tim->DFIUPDCFG = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFIUPDCFG);
+ pctl_tim->DFITREFMSKI = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITREFMSKI);
+ pctl_tim->DFITCTRLUPDI = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITCTRLUPDI);
+ pctl_tim->DFISTCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG0);
+ pctl_tim->DFISTCFG1 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG1);
+ pctl_tim->DFITDRAMCLKEN = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITDRAMCLKEN);
+ pctl_tim->DFITDRAMCLKDIS = mmio_read_32(DDR_PCTL_BASE +
+ DDR_PCTL_DFITDRAMCLKDIS);
+ pctl_tim->DFISTCFG2 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFISTCFG2);
+ pctl_tim->DFILPCFG0 = mmio_read_32(DDR_PCTL_BASE + DDR_PCTL_DFILPCFG0);
+
+ /* PHY */
+ p_ddr_reg->phy.PHY_REG0 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG0);
+ p_ddr_reg->phy.PHY_REG1 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG1);
+ p_ddr_reg->phy.PHY_REGB = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGB);
+ p_ddr_reg->phy.PHY_REGC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGC);
+ p_ddr_reg->phy.PHY_REG11 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG11);
+ p_ddr_reg->phy.PHY_REG13 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG13);
+ p_ddr_reg->phy.PHY_REG14 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG14);
+ p_ddr_reg->phy.PHY_REG16 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG16);
+ p_ddr_reg->phy.PHY_REG20 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG20);
+ p_ddr_reg->phy.PHY_REG21 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG21);
+ p_ddr_reg->phy.PHY_REG26 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG26);
+ p_ddr_reg->phy.PHY_REG27 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG27);
+ p_ddr_reg->phy.PHY_REG28 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG28);
+ p_ddr_reg->phy.PHY_REG30 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG30);
+ p_ddr_reg->phy.PHY_REG31 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG31);
+ p_ddr_reg->phy.PHY_REG36 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG36);
+ p_ddr_reg->phy.PHY_REG37 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG37);
+ p_ddr_reg->phy.PHY_REG38 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG38);
+ p_ddr_reg->phy.PHY_REG40 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG40);
+ p_ddr_reg->phy.PHY_REG41 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG41);
+ p_ddr_reg->phy.PHY_REG46 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG46);
+ p_ddr_reg->phy.PHY_REG47 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG47);
+ p_ddr_reg->phy.PHY_REG48 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG48);
+ p_ddr_reg->phy.PHY_REG50 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG50);
+ p_ddr_reg->phy.PHY_REG51 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG51);
+ p_ddr_reg->phy.PHY_REG56 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG56);
+ p_ddr_reg->phy.PHY_REG57 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG57);
+ p_ddr_reg->phy.PHY_REG58 = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG58);
+ p_ddr_reg->phy.PHY_REGDLL = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGDLL);
+ p_ddr_reg->phy.PHY_REGEC = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEC);
+ p_ddr_reg->phy.PHY_REGED = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGED);
+ p_ddr_reg->phy.PHY_REGEE = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE);
+ p_ddr_reg->phy.PHY_REGEF = 0;
+
+ if (mmio_read_32(DDR_PHY_BASE + DDR_PHY_REG2) & 0x2) {
+ p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG2C);
+ p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG3C);
+ p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG4C);
+ p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REG5C);
+ } else {
+ p_ddr_reg->phy.PHY_REGFB = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFB);
+ p_ddr_reg->phy.PHY_REGFC = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFC);
+ p_ddr_reg->phy.PHY_REGFD = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFD);
+ p_ddr_reg->phy.PHY_REGFE = mmio_read_32(DDR_PHY_BASE +
+ DDR_PHY_REGFE);
+ }
+
+ /* NOC */
+ p_ddr_reg->noc.ddrconf = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRCONF);
+ p_ddr_reg->noc.ddrtiming = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_DDRTIMING);
+ p_ddr_reg->noc.ddrmode = mmio_read_32(SERVICE_BUS_BASE + MSCH_DDRMODE);
+ p_ddr_reg->noc.readlatency = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_READLATENCY);
+ p_ddr_reg->noc.activate = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_ACTIVATE);
+ p_ddr_reg->noc.devtodev = mmio_read_32(SERVICE_BUS_BASE +
+ MSCH_DEVTODEV);
+
+ p_ddr_reg->pllselect = mmio_read_32(DDR_PHY_BASE + DDR_PHY_REGEE) * 0x1;
+ p_ddr_reg->phypllockaddr = GRF_BASE + GRF_SOC_STATUS0;
+ p_ddr_reg->phyplllockmask = GRF_DDRPHY_LOCK;
+ p_ddr_reg->phyplllockval = 0;
+
+ /* PLLPD */
+ p_ddr_reg->pllpdstat = pllpdstat;
+ /* DPLL */
+ p_ddr_reg->dpllmodeaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3);
+ /* slow mode and power on */
+ p_ddr_reg->dpllslowmode = DPLL_WORK_SLOW_MODE | DPLL_POWER_DOWN;
+ p_ddr_reg->dpllnormalmode = DPLL_WORK_NORMAL_MODE;
+ p_ddr_reg->dpllresetaddr = CRU_BASE + PLL_CONS(DPLL_ID, 3);
+ p_ddr_reg->dpllreset = DPLL_RESET_CONTROL_NORMAL;
+ p_ddr_reg->dplldereset = DPLL_RESET_CONTROL_RESET;
+ p_ddr_reg->dpllconaddr = CRU_BASE + PLL_CONS(DPLL_ID, 0);
+
+ if (p_ddr_reg->pllselect == 0) {
+ p_ddr_reg->dpllcon[0] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 0))
+ & 0xffff) |
+ (0xFFFFu << 16);
+ p_ddr_reg->dpllcon[1] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 1))
+ & 0xffff);
+ p_ddr_reg->dpllcon[2] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 2))
+ & 0xffff);
+ p_ddr_reg->dpllcon[3] = (mmio_read_32(CRU_BASE +
+ PLL_CONS(DPLL_ID, 3))
+ & 0xffff) |
+ (0xFFFFu << 16);
+ } else {
+ ddr_get_dpll_cfg(&p_ddr_reg->dpllcon[0]);
+ }
+
+ p_ddr_reg->pllselect = 0;
+ p_ddr_reg->dplllockaddr = CRU_BASE + PLL_CONS(DPLL_ID, 1);
+ p_ddr_reg->dplllockmask = DPLL_STATUS_LOCK;
+ p_ddr_reg->dplllockval = DPLL_STATUS_LOCK;
+
+ /* SET_DDR_PLL_SRC */
+ p_ddr_reg->ddrpllsrcdivaddr = CRU_BASE + CRU_CLKSELS_CON(13);
+ p_ddr_reg->ddrpllsrcdiv = (mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(13))
+ & DDR_PLL_SRC_MASK)
+ | (DDR_PLL_SRC_MASK << 16);
+ p_ddr_reg->retendisaddr = PMU_BASE + PMU_PWRMD_COM;
+ p_ddr_reg->retendisval = PD_PERI_PWRDN_ENABLE;
+ p_ddr_reg->grfregaddr = GRF_BASE + GRF_DDRC0_CON0;
+ p_ddr_reg->grfddrcreg = (mmio_read_32(GRF_BASE + GRF_DDRC0_CON0) &
+ DDR_PLL_SRC_MASK) |
+ (DDR_PLL_SRC_MASK << 16);
+
+ /* pctl phy soft reset */
+ p_ddr_reg->crupctlphysoftrstaddr = CRU_BASE + CRU_SOFTRSTS_CON(10);
+ p_ddr_reg->cruresetpctlphy = DDRCTRL0_PSRSTN_REQ(1) |
+ DDRCTRL0_SRSTN_REQ(1) |
+ DDRPHY0_PSRSTN_REQ(1) |
+ DDRPHY0_SRSTN_REQ(1);
+ p_ddr_reg->cruderesetphy = DDRCTRL0_PSRSTN_REQ(1) |
+ DDRCTRL0_SRSTN_REQ(1) |
+ DDRPHY0_PSRSTN_REQ(0) |
+ DDRPHY0_SRSTN_REQ(0);
+
+ p_ddr_reg->cruderesetpctlphy = DDRCTRL0_PSRSTN_REQ(0) |
+ DDRCTRL0_SRSTN_REQ(0) |
+ DDRPHY0_PSRSTN_REQ(0) |
+ DDRPHY0_SRSTN_REQ(0);
+
+ p_ddr_reg->physoftrstaddr = DDR_PHY_BASE + DDR_PHY_REG0;
+
+ p_ddr_reg->endtag = 0xFFFFFFFF;
+}
+
+/*
+ * "rk3368_ddr_reg_resume_V1.05.bin" is an executable bin which is generated
+ * by ARM DS5 for resuming ddr controller. If the soc wakes up from system
+ * suspend, ddr needs to be resumed and the resuming code needs to be run in
+ * sram. But there is not a way to pointing the resuming code to the PMUSRAM
+ * when linking .o files of bl31, so we use the
+ * "rk3368_ddr_reg_resume_V1.05.bin" whose code is position-independent and
+ * it can be loaded anywhere and run.
+ */
+static __aligned(4) unsigned int ddr_reg_resume[] = {
+ #include "rk3368_ddr_reg_resume_V1.05.bin"
+};
+
+uint32_t ddr_get_resume_code_size(void)
+{
+ return sizeof(ddr_reg_resume);
+}
+
+uint32_t ddr_get_resume_data_size(void)
+{
+ return sizeof(struct BACKUP_REG_TAG);
+}
+
+uint32_t *ddr_get_resume_code_base(void)
+{
+ return (unsigned int *)ddr_reg_resume;
+}
diff --git a/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h
new file mode 100644
index 0000000..6663bcb
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DDR_RK3368_H
+#define DDR_RK3368_H
+
+#define DDR_PCTL_SCFG 0x0
+#define DDR_PCTL_SCTL 0x4
+#define DDR_PCTL_STAT 0x8
+#define DDR_PCTL_INTRSTAT 0xc
+
+#define DDR_PCTL_MCMD 0x40
+#define DDR_PCTL_POWCTL 0x44
+#define DDR_PCTL_POWSTAT 0x48
+#define DDR_PCTL_CMDTSTAT 0x4c
+#define DDR_PCTL_CMDTSTATEN 0x50
+#define DDR_PCTL_MRRCFG0 0x60
+#define DDR_PCTL_MRRSTAT0 0x64
+#define DDR_PCTL_MRRSTAT1 0x68
+#define DDR_PCTL_MCFG1 0x7c
+#define DDR_PCTL_MCFG 0x80
+#define DDR_PCTL_PPCFG 0x84
+#define DDR_PCTL_MSTAT 0x88
+#define DDR_PCTL_LPDDR2ZQCFG 0x8c
+#define DDR_PCTL_DTUPDES 0x94
+#define DDR_PCTL_DTUNA 0x98
+#define DDR_PCTL_DTUNE 0x9c
+#define DDR_PCTL_DTUPRD0 0xa0
+#define DDR_PCTL_DTUPRD1 0xa4
+#define DDR_PCTL_DTUPRD2 0xa8
+#define DDR_PCTL_DTUPRD3 0xac
+#define DDR_PCTL_DTUAWDT 0xb0
+#define DDR_PCTL_TOGCNT1U 0xc0
+#define DDR_PCTL_TINIT 0xc4
+#define DDR_PCTL_TRSTH 0xc8
+#define DDR_PCTL_TOGCNT100N 0xcc
+#define DDR_PCTL_TREFI 0xd0
+#define DDR_PCTL_TMRD 0xd4
+#define DDR_PCTL_TRFC 0xd8
+#define DDR_PCTL_TRP 0xdc
+#define DDR_PCTL_TRTW 0xe0
+#define DDR_PCTL_TAL 0xe4
+#define DDR_PCTL_TCL 0xe8
+#define DDR_PCTL_TCWL 0xec
+#define DDR_PCTL_TRAS 0xf0
+#define DDR_PCTL_TRC 0xf4
+#define DDR_PCTL_TRCD 0xf8
+#define DDR_PCTL_TRRD 0xfc
+#define DDR_PCTL_TRTP 0x100
+#define DDR_PCTL_TWR 0x104
+#define DDR_PCTL_TWTR 0x108
+#define DDR_PCTL_TEXSR 0x10c
+#define DDR_PCTL_TXP 0x110
+#define DDR_PCTL_TXPDLL 0x114
+#define DDR_PCTL_TZQCS 0x118
+#define DDR_PCTL_TZQCSI 0x11c
+#define DDR_PCTL_TDQS 0x120
+#define DDR_PCTL_TCKSRE 0x124
+#define DDR_PCTL_TCKSRX 0x128
+#define DDR_PCTL_TCKE 0x12c
+#define DDR_PCTL_TMOD 0x130
+#define DDR_PCTL_TRSTL 0x134
+#define DDR_PCTL_TZQCL 0x138
+#define DDR_PCTL_TMRR 0x13c
+#define DDR_PCTL_TCKESR 0x140
+#define DDR_PCTL_TDPD 0x144
+#define DDR_PCTL_TREFI_MEM_DDR3 0x148
+#define DDR_PCTL_ECCCFG 0x180
+#define DDR_PCTL_ECCTST 0x184
+#define DDR_PCTL_ECCCLR 0x188
+#define DDR_PCTL_ECCLOG 0x18c
+#define DDR_PCTL_DTUWACTL 0x200
+#define DDR_PCTL_DTURACTL 0x204
+#define DDR_PCTL_DTUCFG 0x208
+#define DDR_PCTL_DTUECTL 0x20c
+#define DDR_PCTL_DTUWD0 0x210
+#define DDR_PCTL_DTUWD1 0x214
+#define DDR_PCTL_DTUWD2 0x218
+#define DDR_PCTL_DTUWD3 0x21c
+#define DDR_PCTL_DTUWDM 0x220
+#define DDR_PCTL_DTURD0 0x224
+#define DDR_PCTL_DTURD1 0x228
+#define DDR_PCTL_DTURD2 0x22c
+#define DDR_PCTL_DTURD3 0x230
+#define DDR_PCTL_DTULFSRWD 0x234
+#define DDR_PCTL_DTULFSRRD 0x238
+#define DDR_PCTL_DTUEAF 0x23c
+#define DDR_PCTL_DFITCTRLDELAY 0x240
+#define DDR_PCTL_DFIODTCFG 0x244
+#define DDR_PCTL_DFIODTCFG1 0x248
+#define DDR_PCTL_DFIODTRANKMAP 0x24c
+#define DDR_PCTL_DFITPHYWRDATA 0x250
+#define DDR_PCTL_DFITPHYWRLAT 0x254
+#define DDR_PCTL_DFITPHYWRDATALAT 0x258
+#define DDR_PCTL_DFITRDDATAEN 0x260
+#define DDR_PCTL_DFITPHYRDLAT 0x264
+#define DDR_PCTL_DFITPHYUPDTYPE0 0x270
+#define DDR_PCTL_DFITPHYUPDTYPE1 0x274
+#define DDR_PCTL_DFITPHYUPDTYPE2 0x278
+#define DDR_PCTL_DFITPHYUPDTYPE3 0x27c
+#define DDR_PCTL_DFITCTRLUPDMIN 0x280
+#define DDR_PCTL_DFITCTRLUPDMAX 0x284
+#define DDR_PCTL_DFITCTRLUPDDLY 0x288
+#define DDR_PCTL_DFIUPDCFG 0x290
+#define DDR_PCTL_DFITREFMSKI 0x294
+#define DDR_PCTL_DFITCTRLUPDI 0x298
+#define DDR_PCTL_DFITRCFG0 0x2ac
+#define DDR_PCTL_DFITRSTAT0 0x2b0
+#define DDR_PCTL_DFITRWRLVLEN 0x2b4
+#define DDR_PCTL_DFITRRDLVLEN 0x2b8
+#define DDR_PCTL_DFITRRDLVLGATEEN 0x2bc
+#define DDR_PCTL_DFISTSTAT0 0x2c0
+#define DDR_PCTL_DFISTCFG0 0x2c4
+#define DDR_PCTL_DFISTCFG1 0x2c8
+#define DDR_PCTL_DFITDRAMCLKEN 0x2d0
+#define DDR_PCTL_DFITDRAMCLKDIS 0x2d4
+#define DDR_PCTL_DFISTCFG2 0x2d8
+#define DDR_PCTL_DFISTPARCLR 0x2dc
+#define DDR_PCTL_DFISTPARLOG 0x2e0
+#define DDR_PCTL_DFILPCFG0 0x2f0
+#define DDR_PCTL_DFITRWRLVLRESP0 0x300
+#define DDR_PCTL_DFITRWRLVLRESP1 0x304
+#define DDR_PCTL_DFITRWRLVLRESP2 0x308
+#define DDR_PCTL_DFITRRDLVLRESP0 0x30c
+#define DDR_PCTL_DFITRRDLVLRESP1 0x310
+#define DDR_PCTL_DFITRRDLVLRESP2 0x314
+#define DDR_PCTL_DFITRWRLVLDELAY0 0x318
+#define DDR_PCTL_DFITRWRLVLDELAY1 0x31c
+#define DDR_PCTL_DFITRWRLVLDELAY2 0x320
+#define DDR_PCTL_DFITRRDLVLDELAY0 0x324
+#define DDR_PCTL_DFITRRDLVLDELAY1 0x328
+#define DDR_PCTL_DFITRRDLVLDELAY2 0x32c
+#define DDR_PCTL_DFITRRDLVLGATEDELAY0 0x330
+#define DDR_PCTL_DFITRRDLVLGATEDELAY1 0x334
+#define DDR_PCTL_DFITRRDLVLGATEDELAY2 0x338
+#define DDR_PCTL_DFITRCMD 0x33c
+#define DDR_PCTL_IPVR 0x3f8
+#define DDR_PCTL_IPTR 0x3fc
+
+/* DDR PHY REG */
+#define DDR_PHY_REG0 0x0
+#define DDR_PHY_REG1 0x4
+#define DDR_PHY_REG2 0x8
+#define DDR_PHY_REG3 0xc
+#define DDR_PHY_REG4 0x10
+#define DDR_PHY_REG5 0x14
+#define DDR_PHY_REG6 0x18
+#define DDR_PHY_REGB 0x2c
+#define DDR_PHY_REGC 0x30
+#define DDR_PHY_REG11 0x44
+#define DDR_PHY_REG12 0x48
+#define DDR_PHY_REG13 0x4c
+#define DDR_PHY_REG14 0x50
+#define DDR_PHY_REG16 0x58
+#define DDR_PHY_REG20 0x80
+#define DDR_PHY_REG21 0x84
+#define DDR_PHY_REG26 0x98
+#define DDR_PHY_REG27 0x9c
+#define DDR_PHY_REG28 0xa0
+#define DDR_PHY_REG2C 0xb0
+#define DDR_PHY_REG30 0xc0
+#define DDR_PHY_REG31 0xc4
+#define DDR_PHY_REG36 0xd8
+#define DDR_PHY_REG37 0xdc
+#define DDR_PHY_REG38 0xe0
+#define DDR_PHY_REG3C 0xf0
+#define DDR_PHY_REG40 0x100
+#define DDR_PHY_REG41 0x104
+#define DDR_PHY_REG46 0x118
+#define DDR_PHY_REG47 0x11c
+#define DDR_PHY_REG48 0x120
+#define DDR_PHY_REG4C 0x130
+#define DDR_PHY_REG50 0x140
+#define DDR_PHY_REG51 0x144
+#define DDR_PHY_REG56 0x158
+#define DDR_PHY_REG57 0x15c
+#define DDR_PHY_REG58 0x160
+#define DDR_PHY_REG5C 0x170
+#define DDR_PHY_REGDLL 0x290
+#define DDR_PHY_REGEC 0x3b0
+#define DDR_PHY_REGED 0x3b4
+#define DDR_PHY_REGEE 0x3b8
+#define DDR_PHY_REGEF 0x3bc
+#define DDR_PHY_REGF0 0x3c0
+#define DDR_PHY_REGF1 0x3c4
+#define DDR_PHY_REGF2 0x3c8
+#define DDR_PHY_REGFA 0x3e8
+#define DDR_PHY_REGFB 0x3ec
+#define DDR_PHY_REGFC 0x3f0
+#define DDR_PHY_REGFD 0x3f4
+#define DDR_PHY_REGFE 0x3f8
+#define DDR_PHY_REGFF 0x3fc
+
+/* MSCH REG define */
+#define MSCH_COREID 0x0
+#define MSCH_DDRCONF 0x8
+#define MSCH_DDRTIMING 0xc
+#define MSCH_DDRMODE 0x10
+#define MSCH_READLATENCY 0x14
+#define MSCH_ACTIVATE 0x38
+#define MSCH_DEVTODEV 0x3c
+
+#define SET_NR(n) ((0x3f << (8 + 16)) | ((n - 1) << 8))
+#define SET_NO(n) ((0xf << (0 + 16)) | ((n - 1) << 0))
+#define SET_NF(n) ((n - 1) & 0x1fff)
+#define SET_NB(n) ((n - 1) & 0xfff)
+#define PLLMODE(n) ((0x3 << (8 + 16)) | (n << 8))
+
+/* GRF REG define */
+#define GRF_SOC_STATUS0 0x480
+#define GRF_DDRPHY_LOCK (0x1 << 15)
+#define GRF_DDRC0_CON0 0x600
+
+/* CRU softreset ddr pctl, phy */
+#define DDRMSCH0_SRSTN_REQ(n) (((0x1 << 10) << 16) | (n << 10))
+#define DDRCTRL0_PSRSTN_REQ(n) (((0x1 << 3) << 16) | (n << 3))
+#define DDRCTRL0_SRSTN_REQ(n) (((0x1 << 2) << 16) | (n << 2))
+#define DDRPHY0_PSRSTN_REQ(n) (((0x1 << 1) << 16) | (n << 1))
+#define DDRPHY0_SRSTN_REQ(n) (((0x1 << 0) << 16) | (n << 0))
+
+/* CRU_DPLL_CON2 */
+#define DPLL_STATUS_LOCK (1U << 31)
+
+/* CRU_DPLL_CON3 */
+#define DPLL_POWER_DOWN ((0x1 << (1 + 16)) | (0 << 1))
+#define DPLL_WORK_NORMAL_MODE ((0x3 << (8 + 16)) | (0 << 8))
+#define DPLL_WORK_SLOW_MODE ((0x3 << (8 + 16)) | (1 << 8))
+#define DPLL_RESET_CONTROL_NORMAL ((0x1 << (5 + 16)) | (0x0 << 5))
+#define DPLL_RESET_CONTROL_RESET ((0x1 << (5 + 16)) | (0x1 << 5))
+
+/* PMU_PWRDN_CON */
+#define PD_PERI_PWRDN_ENABLE (1 << 13)
+
+#define DDR_PLL_SRC_MASK 0x13
+
+/* DDR_PCTL_TREFI */
+#define DDR_UPD_REF_ENABLE (0X1u << 31)
+
+uint32_t ddr_get_resume_code_size(void);
+uint32_t ddr_get_resume_data_size(void);
+uint32_t *ddr_get_resume_code_base(void);
+void ddr_reg_save(uint32_t pllpdstat, uint64_t base_addr);
+
+#endif /* DDR_RK3368_H */
diff --git a/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..399f61c
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+.macro func_rockchip_clst_warmboot
+ /* Nothing to do for rk3368 */
+.endm
+
+.macro rockchip_clst_warmboot_data
+ /* Nothing to do for rk3368 */
+.endm
diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.c b/plat/rockchip/rk3368/drivers/pmu/pmu.c
new file mode 100644
index 0000000..e277a18
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/pmu/pmu.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <ddr_rk3368.h>
+#include <plat_private.h>
+#include <pmu.h>
+#include <pmu_com.h>
+#include <rk3368_def.h>
+#include <soc.h>
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+
+static uint32_t cpu_warm_boot_addr;
+
+void rk3368_flash_l2_b(void)
+{
+ uint32_t wait_cnt = 0;
+
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b);
+ dsb();
+
+ while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)
+ & BIT(clst_b_l2_flsh_done))) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ WARN("%s:reg %x,wait\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST));
+ }
+
+ regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_l2flsh_clst_b);
+}
+
+static inline int rk3368_pmu_bus_idle(uint32_t req, uint32_t idle)
+{
+ uint32_t mask = BIT(req);
+ uint32_t idle_mask = 0;
+ uint32_t idle_target = 0;
+ uint32_t val;
+ uint32_t wait_cnt = 0;
+
+ switch (req) {
+ case bus_ide_req_clst_l:
+ idle_mask = BIT(pmu_idle_ack_cluster_l);
+ idle_target = (idle << pmu_idle_ack_cluster_l);
+ break;
+
+ case bus_ide_req_clst_b:
+ idle_mask = BIT(pmu_idle_ack_cluster_b);
+ idle_target = (idle << pmu_idle_ack_cluster_b);
+ break;
+
+ case bus_ide_req_cxcs:
+ idle_mask = BIT(pmu_idle_ack_cxcs);
+ idle_target = ((!idle) << pmu_idle_ack_cxcs);
+ break;
+
+ case bus_ide_req_cci400:
+ idle_mask = BIT(pmu_idle_ack_cci400);
+ idle_target = ((!idle) << pmu_idle_ack_cci400);
+ break;
+
+ case bus_ide_req_gpu:
+ idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu);
+ idle_target = (idle << pmu_idle_ack_gpu) |
+ (idle << pmu_idle_gpu);
+ break;
+
+ case bus_ide_req_core:
+ idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core);
+ idle_target = (idle << pmu_idle_ack_core) |
+ (idle << pmu_idle_core);
+ break;
+
+ case bus_ide_req_bus:
+ idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus);
+ idle_target = (idle << pmu_idle_ack_bus) |
+ (idle << pmu_idle_bus);
+ break;
+ case bus_ide_req_dma:
+ idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma);
+ idle_target = (idle << pmu_idle_ack_dma) |
+ (idle << pmu_idle_dma);
+ break;
+
+ case bus_ide_req_peri:
+ idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri);
+ idle_target = (idle << pmu_idle_ack_peri) |
+ (idle << pmu_idle_peri);
+ break;
+
+ case bus_ide_req_video:
+ idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video);
+ idle_target = (idle << pmu_idle_ack_video) |
+ (idle << pmu_idle_video);
+ break;
+
+ case bus_ide_req_vio:
+ idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio);
+ idle_target = (pmu_idle_ack_vio) |
+ (idle << pmu_idle_vio);
+ break;
+
+ case bus_ide_req_alive:
+ idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive);
+ idle_target = (idle << pmu_idle_ack_alive) |
+ (idle << pmu_idle_alive);
+ break;
+
+ case bus_ide_req_pmu:
+ idle_mask = BIT(pmu_idle_ack_pmu) | BIT(pmu_idle_pmu);
+ idle_target = (idle << pmu_idle_ack_pmu) |
+ (idle << pmu_idle_pmu);
+ break;
+
+ case bus_ide_req_msch:
+ idle_mask = BIT(pmu_idle_ack_msch) | BIT(pmu_idle_msch);
+ idle_target = (idle << pmu_idle_ack_msch) |
+ (idle << pmu_idle_msch);
+ break;
+
+ case bus_ide_req_cci:
+ idle_mask = BIT(pmu_idle_ack_cci) | BIT(pmu_idle_cci);
+ idle_target = (idle << pmu_idle_ack_cci) |
+ (idle << pmu_idle_cci);
+ break;
+
+ default:
+ ERROR("%s: Unsupported the idle request\n", __func__);
+ break;
+ }
+
+ val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ);
+ if (idle)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val);
+
+ while ((mmio_read_32(PMU_BASE +
+ PMU_BUS_IDE_ST) & idle_mask) != idle_target) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ WARN("%s:st=%x(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST),
+ idle_mask);
+ }
+
+ return 0;
+}
+
+void pmu_scu_b_pwrup(void)
+{
+ regs_updata_bit_clr(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b);
+ rk3368_pmu_bus_idle(bus_ide_req_clst_b, 0);
+}
+
+static void pmu_scu_b_pwrdn(void)
+{
+ uint32_t wait_cnt = 0;
+
+ if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) &
+ PM_PWRDM_CPUSB_MSK) != PM_PWRDM_CPUSB_MSK) {
+ ERROR("%s: not all cpus is off\n", __func__);
+ return;
+ }
+
+ rk3368_flash_l2_b();
+
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_acinactm_clst_b);
+
+ while (!(mmio_read_32(PMU_BASE +
+ PMU_CORE_PWR_ST) & BIT(clst_b_l2_wfi))) {
+ wait_cnt++;
+ if (!(wait_cnt % MAX_WAIT_CONUT))
+ ERROR("%s:wait cluster-b l2(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST));
+ }
+ rk3368_pmu_bus_idle(bus_ide_req_clst_b, 1);
+}
+
+static void pmu_sleep_mode_config(void)
+{
+ uint32_t pwrmd_core, pwrmd_com;
+
+ pwrmd_core = BIT(pmu_mdcr_cpu0_pd) |
+ BIT(pmu_mdcr_scu_l_pd) |
+ BIT(pmu_mdcr_l2_flush) |
+ BIT(pmu_mdcr_l2_idle) |
+ BIT(pmu_mdcr_clr_clst_l) |
+ BIT(pmu_mdcr_clr_core) |
+ BIT(pmu_mdcr_clr_cci) |
+ BIT(pmu_mdcr_core_pd);
+
+ pwrmd_com = BIT(pmu_mode_en) |
+ BIT(pmu_mode_sref_enter) |
+ BIT(pmu_mode_pwr_off);
+
+ regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_l_wkup_en);
+ regs_updata_bit_set(PMU_BASE + PMU_WKUP_CFG2, pmu_cluster_b_wkup_en);
+ regs_updata_bit_clr(PMU_BASE + PMU_WKUP_CFG2, pmu_gpio_wkup_en);
+
+ mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(2));
+ mmio_write_32(PMU_BASE + PMU_PLLRST_CNT, CYCL_24M_CNT_US(100));
+ mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_24M_CNT_MS(2));
+ mmio_write_32(PMU_BASE + PMU_PWRMD_CORE, pwrmd_core);
+ mmio_write_32(PMU_BASE + PMU_PWRMD_COM, pwrmd_com);
+ dsb();
+}
+
+static void pmu_set_sleep_mode(void)
+{
+ pmu_sleep_mode_config();
+ soc_sleep_config();
+ regs_updata_bit_set(PMU_BASE + PMU_PWRMD_CORE, pmu_mdcr_global_int_dis);
+ regs_updata_bit_set(PMU_BASE + PMU_SFT_CON, pmu_sft_glbl_int_dis_b);
+ pmu_scu_b_pwrdn();
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ ((uintptr_t)&pmu_cpuson_entrypoint >>
+ CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2),
+ ((uintptr_t)&pmu_cpuson_entrypoint >>
+ CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK);
+}
+
+static int cpus_id_power_domain(uint32_t cluster,
+ uint32_t cpu,
+ uint32_t pd_state,
+ uint32_t wfie_msk)
+{
+ uint32_t pd;
+ uint64_t mpidr;
+
+ if (cluster)
+ pd = PD_CPUB0 + cpu;
+ else
+ pd = PD_CPUL0 + cpu;
+
+ if (pmu_power_domain_st(pd) == pd_state)
+ return 0;
+
+ if (pd_state == pmu_pd_off) {
+ mpidr = (cluster << MPIDR_AFF1_SHIFT) | cpu;
+ if (check_cpu_wfie(mpidr, wfie_msk))
+ return -EINVAL;
+ }
+
+ return pmu_power_domain_ctr(pd, pd_state);
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, boot_cluster, cpu;
+
+ boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
+ boot_cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CLUSTER0_CORE_COUNT; cpu++) {
+ if (!boot_cluster && (cpu == boot_cpu))
+ continue;
+ cpus_id_power_domain(0, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+ }
+
+ for (cpu = 0; cpu < PLATFORM_CLUSTER1_CORE_COUNT; cpu++) {
+ if (boot_cluster && (cpu == boot_cpu))
+ continue;
+ cpus_id_power_domain(1, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+ }
+}
+
+void sram_save(void)
+{
+ /* TODO: support the sdram save for rk3368 SoCs*/
+}
+
+void sram_restore(void)
+{
+ /* TODO: support the sdram restore for rk3368 SoCs */
+}
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu, cluster;
+ uint32_t cpuon_id;
+
+ cpu = MPIDR_AFFLVL0_VAL(mpidr);
+ cluster = MPIDR_AFFLVL1_VAL(mpidr);
+
+ /* Make sure the cpu is off,Before power up the cpu! */
+ cpus_id_power_domain(cluster, cpu, pmu_pd_off, CKECK_WFEI_MSK);
+
+ cpuon_id = (cluster * PLATFORM_CLUSTER0_CORE_COUNT) + cpu;
+ assert(cpuon_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpuon_id] == 0);
+ cpuson_flags[cpuon_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpuon_id] = entrypoint;
+
+ /* Switch boot addr to pmusram */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster),
+ (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ dsb();
+
+ cpus_id_power_domain(cluster, cpu, pmu_pd_on, CKECK_WFEI_MSK);
+
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1 + cluster),
+ (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2),
+ (COLD_BOOT_BASE >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ pm_plls_resume();
+ pmu_scu_b_pwrup();
+
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ nonboot_cpus_off();
+ pmu_set_sleep_mode();
+
+ return 0;
+}
+
+void rockchip_plat_mmu_el3(void)
+{
+ /* TODO: support the el3 for rk3368 SoCs */
+}
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ /* register requires 32bits mode, switch it to 32 bits */
+ cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot;
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ nonboot_cpus_off();
+ INFO("%s(%d): pd status %x\n", __func__, __LINE__,
+ mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/rk3368/drivers/pmu/pmu.h b/plat/rockchip/rk3368/drivers/pmu/pmu.h
new file mode 100644
index 0000000..b4d4807
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/pmu/pmu.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_H
+#define PMU_H
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE 0x80
+#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WKUP_CFG0 0x0
+#define PMU_WKUP_CFG1 0x4
+#define PMU_WKUP_CFG2 0x8
+#define PMU_TIMEOUT_CNT 0x7c
+#define PMU_PWRDN_CON 0xc
+#define PMU_PWRDN_ST 0x10
+#define PMU_CORE_PWR_ST 0x38
+
+#define PMU_PWRMD_CORE 0x14
+#define PMU_PWRMD_COM 0x18
+#define PMU_SFT_CON 0x1c
+#define PMU_BUS_IDE_REQ 0x3c
+#define PMU_BUS_IDE_ST 0x40
+#define PMU_OSC_CNT 0x48
+#define PMU_PLLLOCK_CNT 0x4c
+#define PMU_PLLRST_CNT 0x50
+#define PMU_STABLE_CNT 0x54
+#define PMU_DDRIO_PWR_CNT 0x58
+#define PMU_WKUPRST_CNT 0x5c
+
+enum pmu_powermode_core {
+ pmu_mdcr_global_int_dis = 0,
+ pmu_mdcr_core_src_gt,
+ pmu_mdcr_clr_cci,
+ pmu_mdcr_cpu0_pd,
+ pmu_mdcr_clr_clst_l = 4,
+ pmu_mdcr_clr_core,
+ pmu_mdcr_scu_l_pd,
+ pmu_mdcr_core_pd,
+ pmu_mdcr_l2_idle = 8,
+ pmu_mdcr_l2_flush
+};
+
+/*
+ * the shift of bits for cores status
+ */
+enum pmu_core_pwrst_shift {
+ clstl_cpu_wfe = 2,
+ clstl_cpu_wfi = 6,
+ clstb_cpu_wfe = 12,
+ clstb_cpu_wfi = 16
+};
+
+enum pmu_pdid {
+ PD_CPUL0 = 0,
+ PD_CPUL1,
+ PD_CPUL2,
+ PD_CPUL3,
+ PD_SCUL,
+ PD_CPUB0 = 5,
+ PD_CPUB1,
+ PD_CPUB2,
+ PD_CPUB3,
+ PD_SCUB = 9,
+ PD_PERI = 13,
+ PD_VIDEO,
+ PD_VIO,
+ PD_GPU0,
+ PD_GPU1,
+ PD_END
+};
+
+enum pmu_bus_ide {
+ bus_ide_req_clst_l = 0,
+ bus_ide_req_clst_b,
+ bus_ide_req_gpu,
+ bus_ide_req_core,
+ bus_ide_req_bus = 4,
+ bus_ide_req_dma,
+ bus_ide_req_peri,
+ bus_ide_req_video,
+ bus_ide_req_vio = 8,
+ bus_ide_req_res0,
+ bus_ide_req_cxcs,
+ bus_ide_req_alive,
+ bus_ide_req_pmu = 12,
+ bus_ide_req_msch,
+ bus_ide_req_cci,
+ bus_ide_req_cci400 = 15,
+ bus_ide_req_end
+};
+
+enum pmu_powermode_common {
+ pmu_mode_en = 0,
+ pmu_mode_res0,
+ pmu_mode_bus_pd,
+ pmu_mode_wkup_rst,
+ pmu_mode_pll_pd = 4,
+ pmu_mode_pwr_off,
+ pmu_mode_pmu_use_if,
+ pmu_mode_pmu_alive_use_if,
+ pmu_mode_osc_dis = 8,
+ pmu_mode_input_clamp,
+ pmu_mode_sref_enter,
+ pmu_mode_ddrc_gt,
+ pmu_mode_ddrio_ret = 12,
+ pmu_mode_ddrio_ret_deq,
+ pmu_mode_clr_pmu,
+ pmu_mode_clr_alive,
+ pmu_mode_clr_bus = 16,
+ pmu_mode_clr_dma,
+ pmu_mode_clr_msch,
+ pmu_mode_clr_peri,
+ pmu_mode_clr_video = 20,
+ pmu_mode_clr_vio,
+ pmu_mode_clr_gpu,
+ pmu_mode_clr_mcu,
+ pmu_mode_clr_cxcs = 24,
+ pmu_mode_clr_cci400,
+ pmu_mode_res1,
+ pmu_mode_res2,
+ pmu_mode_res3 = 28,
+ pmu_mode_mclst
+};
+
+enum pmu_core_power_st {
+ clst_l_cpu_wfe = 2,
+ clst_l_cpu_wfi = 6,
+ clst_b_l2_flsh_done = 10,
+ clst_b_l2_wfi = 11,
+ clst_b_cpu_wfe = 12,
+ clst_b_cpu_wfi = 16,
+ mcu_sleeping = 20,
+};
+
+enum pmu_sft_con {
+ pmu_sft_acinactm_clst_b = 5,
+ pmu_sft_l2flsh_clst_b,
+ pmu_sft_glbl_int_dis_b = 9,
+ pmu_sft_ddrio_ret_cfg = 11,
+};
+
+enum pmu_wkup_cfg2 {
+ pmu_cluster_l_wkup_en = 0,
+ pmu_cluster_b_wkup_en,
+ pmu_gpio_wkup_en,
+ pmu_sdio_wkup_en,
+ pmu_sdmmc_wkup_en,
+ pmu_sim_wkup_en,
+ pmu_timer_wkup_en,
+ pmu_usbdev_wkup_en,
+ pmu_sft_wkup_en,
+ pmu_wdt_mcu_wkup_en,
+ pmu_timeout_wkup_en,
+};
+
+enum pmu_bus_idle_st {
+ pmu_idle_ack_cluster_l = 0,
+ pmu_idle_ack_cluster_b,
+ pmu_idle_ack_gpu,
+ pmu_idle_ack_core,
+ pmu_idle_ack_bus,
+ pmu_idle_ack_dma,
+ pmu_idle_ack_peri,
+ pmu_idle_ack_video,
+ pmu_idle_ack_vio,
+ pmu_idle_ack_cci = 10,
+ pmu_idle_ack_msch,
+ pmu_idle_ack_alive,
+ pmu_idle_ack_pmu,
+ pmu_idle_ack_cxcs,
+ pmu_idle_ack_cci400,
+ pmu_inactive_cluster_l,
+ pmu_inactive_cluster_b,
+ pmu_idle_gpu,
+ pmu_idle_core,
+ pmu_idle_bus,
+ pmu_idle_dma,
+ pmu_idle_peri,
+ pmu_idle_video,
+ pmu_idle_vio,
+ pmu_idle_cci = 26,
+ pmu_idle_msch,
+ pmu_idle_alive,
+ pmu_idle_pmu,
+ pmu_active_cxcs,
+ pmu_active_cci,
+};
+
+#define PM_PWRDM_CPUSB_MSK (0xf << 5)
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+#define PD_CTR_LOOP 500
+#define CHK_CPU_LOOP 500
+
+#define MAX_WAIT_CONUT 1000
+
+#endif /* PMU_H */
diff --git a/plat/rockchip/rk3368/drivers/soc/soc.c b/plat/rockchip/rk3368/drivers/soc/soc.c
new file mode 100644
index 0000000..7d51bb8
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/soc/soc.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+
+#include <plat_private.h>
+#include <rk3368_def.h>
+#include <soc.h>
+
+static uint32_t plls_con[END_PLL_ID][4];
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(CCI400_BASE, CCI400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(STIME_BASE, STIME_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMU_BASE, PMU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART0_BASE, UART0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART1_BASE, UART1_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART2_BASE, UART2_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART3_BASE, UART3_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(UART4_BASE, UART4_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRU_BASE, CRU_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PCTL_BASE, DDR_PCTL_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_PHY_BASE, DDR_PHY_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(GRF_BASE, GRF_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SISE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_BASE + TIMER_LOADE_COUNT1, 0xffffffff);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN);
+}
+
+void sgrf_init(void)
+{
+ /* setting all configurable ip into no-secure */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), SGRF_SOC_CON7_BITS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7), SGRF_SOC_CON_NS);
+
+ /* secure dma to no sesure */
+ mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(0), SGRF_BUSDMAC_CON0_NS);
+ mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), SGRF_BUSDMAC_CON1_NS);
+ dsb();
+
+ /* rst dma1 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1),
+ RST_DMA1_MSK | (RST_DMA1_MSK << 16));
+ /* rst dma2 */
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4),
+ RST_DMA2_MSK | (RST_DMA2_MSK << 16));
+
+ dsb();
+
+ /* release dma1 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16));
+ /* release dma2 rst*/
+ mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16));
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ sgrf_init();
+}
+
+void regs_updata_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift)
+{
+ uint32_t tmp, orig;
+
+ orig = mmio_read_32(addr);
+
+ tmp = orig & ~(mask << shift);
+ tmp |= (val & mask) << shift;
+
+ if (tmp != orig)
+ mmio_write_32(addr, tmp);
+ dsb();
+}
+
+static void plls_suspend(uint32_t pll_id)
+{
+ plls_con[pll_id][0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0));
+ plls_con[pll_id][1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1));
+ plls_con[pll_id][2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2));
+ plls_con[pll_id][3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3));
+
+ mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((pll_id), 3), PLL_BYPASS);
+}
+
+static void pm_plls_suspend(void)
+{
+ plls_suspend(NPLL_ID);
+ plls_suspend(CPLL_ID);
+ plls_suspend(GPLL_ID);
+ plls_suspend(ABPLL_ID);
+ plls_suspend(ALPLL_ID);
+}
+
+static inline void plls_resume(void)
+{
+ mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3),
+ plls_con[ABPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3),
+ plls_con[ALPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3),
+ plls_con[GPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3),
+ plls_con[CPLL_ID][3] | PLL_BYPASS_W_MSK);
+ mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3),
+ plls_con[NPLL_ID][3] | PLL_BYPASS_W_MSK);
+}
+
+void soc_sleep_config(void)
+{
+ int i = 0;
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000);
+ pm_plls_suspend();
+
+ for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 0xffff0000);
+}
+
+void pm_plls_resume(void)
+{
+ plls_resume();
+
+ mmio_write_32(CRU_BASE + PLL_CONS(ABPLL_ID, 3),
+ plls_con[ABPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(ALPLL_ID, 3),
+ plls_con[ALPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(GPLL_ID, 3),
+ plls_con[GPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(CPLL_ID, 3),
+ plls_con[CPLL_ID][3] | PLLS_MODE_WMASK);
+ mmio_write_32(CRU_BASE + PLL_CONS(NPLL_ID, 3),
+ plls_con[NPLL_ID][3] | PLLS_MODE_WMASK);
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ uint32_t temp_val;
+
+ mmio_write_32(CRU_BASE + PLL_CONS((GPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((CPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((NPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((ABPLL_ID), 3), PLL_SLOW_BITS);
+ mmio_write_32(CRU_BASE + PLL_CONS((ALPLL_ID), 3), PLL_SLOW_BITS);
+
+ temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON) |
+ PMU_RST_BY_SECOND_SFT;
+
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val);
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
diff --git a/plat/rockchip/rk3368/drivers/soc/soc.h b/plat/rockchip/rk3368/drivers/soc/soc.h
new file mode 100644
index 0000000..6c7a01b
--- /dev/null
+++ b/plat/rockchip/rk3368/drivers/soc/soc.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+enum plls_id {
+ ABPLL_ID = 0,
+ ALPLL_ID,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ NPLL_ID,
+ END_PLL_ID,
+};
+
+/*****************************************************************************
+ * secure timer
+ *****************************************************************************/
+#define TIMER_LOADE_COUNT0 0x00
+#define TIMER_LOADE_COUNT1 0x04
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INTSTATUS 0x18
+
+#define TIMER_EN 0x1
+
+#define STIMER1_BASE (STIME_BASE + 0x20)
+
+#define CYCL_24M_CNT_US(us) (24 * us)
+#define CYCL_24M_CNT_MS(ms) (ms * CYCL_24M_CNT_US(1000))
+
+/*****************************************************************************
+ * sgrf reg, offset
+ *****************************************************************************/
+#define SGRF_SOC_CON(n) (0x0 + (n) * 4)
+#define SGRF_BUSDMAC_CON(n) (0x100 + (n) * 4)
+
+#define SGRF_SOC_CON_NS 0xffff0000
+
+/*****************************************************************************
+ * con6[2]pmusram is security.
+ * con6[6]stimer is security.
+ *****************************************************************************/
+#define PMUSRAM_S_SHIFT 2
+#define PMUSRAM_S 1
+#define STIMER_S_SHIFT 6
+#define STIMER_S 1
+#define SGRF_SOC_CON7_BITS ((0xffffu << 16) | \
+ (PMUSRAM_S << PMUSRAM_S_SHIFT) | \
+ (STIMER_S << STIMER_S_SHIFT))
+
+#define SGRF_BUSDMAC_CON0_NS 0xfffcfff8
+#define SGRF_BUSDMAC_CON1_NS 0xffff0fff
+
+/*
+ * sgrf_soc_con1~2, mask and offset
+ */
+#define CPU_BOOT_ADDR_WMASK 0xffff0000
+#define CPU_BOOT_ADDR_ALIGN 16
+
+/*****************************************************************************
+ * cru reg, offset
+ *****************************************************************************/
+#define CRU_SOFTRST_CON 0x300
+#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4))
+#define CRU_SOFTRSTS_CON_CNT 15
+
+#define SOFTRST_DMA1 0x40004
+#define SOFTRST_DMA2 0x10001
+
+#define RST_DMA1_MSK 0x4
+#define RST_DMA2_MSK 0x0
+
+#define CRU_CLKSEL_CON 0x100
+#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4))
+#define CRU_CLKSEL_CON_CNT 56
+
+#define CRU_CLKGATE_CON 0x200
+#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4))
+#define CRU_CLKGATES_CON_CNT 25
+
+#define CRU_GLB_SRST_FST 0x280
+#define CRU_GLB_SRST_SND 0x284
+#define CRU_GLB_RST_CON 0x388
+
+#define CRU_CONS_GATEID(i) (16 * (i))
+#define GATE_ID(reg, bit) ((reg * 16) + bit)
+
+#define PMU_RST_BY_SECOND_SFT (BIT(1) << 2)
+#define PMU_RST_NOT_BY_SFT (BIT(1) << 2)
+
+/***************************************************************************
+ * pll
+ ***************************************************************************/
+#define PLL_PWR_DN_MSK (0x1 << 1)
+#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1)
+#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1)
+#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1)
+#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1)
+#define PLL_BYPASS_MSK (0x1 << 0)
+#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16)
+#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1)
+#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1)
+#define PLL_MODE_SHIFT 8
+#define PLL_MODE_MSK 0x3
+#define PLLS_MODE_WMASK (PLL_MODE_MSK << (16 + PLL_MODE_SHIFT))
+#define PLL_SLOW 0x0
+#define PLL_NORM 0x1
+#define PLL_DEEP 0x2
+#define PLL_SLOW_BITS REG_WMSK_BITS(PLL_SLOW, 8, 0x3)
+#define PLL_NORM_BITS REG_WMSK_BITS(PLL_NORM, 8, 0x3)
+#define PLL_DEEP_BITS REG_WMSK_BITS(PLL_DEEP, 8, 0x3)
+
+#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4))
+
+#define REG_W_MSK(bits_shift, msk) \
+ ((msk) << ((bits_shift) + 16))
+#define REG_VAL_CLRBITS(val, bits_shift, msk) \
+ (val & (~(msk << bits_shift)))
+#define REG_SET_BITS(bits, bits_shift, msk) \
+ (((bits) & (msk)) << (bits_shift))
+#define REG_WMSK_BITS(bits, bits_shift, msk) \
+ (REG_W_MSK(bits_shift, msk) | \
+ REG_SET_BITS(bits, bits_shift, msk))
+
+#define regs_updata_bit_set(addr, shift) \
+ regs_updata_bits((addr), 0x1, 0x1, (shift))
+#define regs_updata_bit_clr(addr, shift) \
+ regs_updata_bits((addr), 0x0, 0x1, (shift))
+
+void regs_updata_bits(uintptr_t addr, uint32_t val,
+ uint32_t mask, uint32_t shift);
+void soc_sleep_config(void);
+void pm_plls_resume(void);
+
+#endif /* SOC_H */
diff --git a/plat/rockchip/rk3368/include/plat.ld.S b/plat/rockchip/rk3368/include/plat.ld.S
new file mode 100644
index 0000000..e9bb3a2
--- /dev/null
+++ b/plat/rockchip/rk3368/include/plat.ld.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ROCKCHIP_PLAT_LD_S
+#define ROCKCHIP_PLAT_LD_S
+
+MEMORY {
+ PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
+}
+
+SECTIONS
+{
+ . = PMUSRAM_BASE;
+
+ /*
+ * pmu_cpuson_entrypoint request address
+ * align 64K when resume, so put it in the
+ * start of pmusram
+ */
+ .text_pmusram : {
+ ASSERT(. == ALIGN(64 * 1024),
+ ".pmusram.entry request 64K aligned.");
+ *(.pmusram.entry)
+ __bl31_pmusram_text_start = .;
+ *(.pmusram.text)
+ *(.pmusram.rodata)
+ __bl31_pmusram_text_end = .;
+ __bl31_pmusram_data_start = .;
+ *(.pmusram.data)
+ __bl31_pmusram_data_end = .;
+
+ } >PMUSRAM
+}
+
+#endif /* ROCKCHIP_PLAT_LD_S */
diff --git a/plat/rockchip/rk3368/include/plat_sip_calls.h b/plat/rockchip/rk3368/include/plat_sip_calls.h
new file mode 100644
index 0000000..66c4868
--- /dev/null
+++ b/plat/rockchip/rk3368/include/plat_sip_calls.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+#define RK_PLAT_SIP_NUM_CALLS 0
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/rockchip/rk3368/include/platform_def.h b/plat/rockchip/rk3368/include/platform_def.h
new file mode 100644
index 0000000..519a025
--- /dev/null
+++ b/plat/rockchip/rk3368/include/platform_def.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include <rk3368_def.h>
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL1)
+#define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x800
+#elif defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(4)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_RK_CLST_TO_CPUID_SHIFT 6
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE U(1)
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE U(2)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF text, ro, rw, Size: 1MB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x100000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x40000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 20
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE RK3368_GICD_BASE
+#define PLAT_RK_GICC_BASE RK3368_GICC_BASE
+
+#define PLAT_RK_UART_BASE UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3368_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3368_BAUDRATE
+
+#define PLAT_RK_CCI_BASE CCI400_BASE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define PSRAM_DO_DDR_RESUME 0
+#define PSRAM_CHECK_WAKEUP_CPU 0
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rockchip/rk3368/plat_sip_calls.c b/plat/rockchip/rk3368/plat_sip_calls.c
new file mode 100644
index 0000000..5918d58
--- /dev/null
+++ b/plat/rockchip/rk3368/plat_sip_calls.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <plat_sip_calls.h>
+#include <rockchip_sip_svc.h>
+
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+}
diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk
new file mode 100644
index 0000000..e6c62de
--- /dev/null
+++ b/plat/rockchip/rk3368/platform.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include drivers/arm/gic/v2/gicv2.mk
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+DISABLE_BIN_GENERATION := 1
+
+PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/aarch64/ \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/drivers/ddr/ \
+ -I${RK_PLAT_SOC}/include/
+
+RK_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ ${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/params_setup.c \
+ ${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
+ ${RK_PLAT_SOC}/plat_sip_calls.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
+ ${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \
+
+include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
+
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+WORKAROUND_CVE_2017_5715 := 0
diff --git a/plat/rockchip/rk3368/rk3368_def.h b/plat/rockchip/rk3368/rk3368_def.h
new file mode 100644
index 0000000..4b0fbab
--- /dev/null
+++ b/plat/rockchip/rk3368/rk3368_def.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK3368_DEF_H
+#define RK3368_DEF_H
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define CCI400_BASE 0xffb90000
+#define CCI400_SIZE 0x10000
+
+#define GIC400_BASE 0xffb70000
+#define GIC400_SIZE 0x10000
+
+#define STIME_BASE 0xff830000
+#define STIME_SIZE 0x10000
+
+#define CRU_BASE 0xff760000
+#define CRU_SIZE 0x10000
+
+#define GRF_BASE 0xff770000
+#define GRF_SIZE 0x10000
+
+#define SGRF_BASE 0xff740000
+#define SGRF_SIZE 0x10000
+
+#define PMU_BASE 0xff730000
+#define PMU_GRF_BASE 0xff738000
+#define PMU_SIZE 0x10000
+
+#define RK_INTMEM_BASE 0xff8c0000
+#define RK_INTMEM_SIZE 0x10000
+
+#define UART0_BASE 0xff180000
+#define UART0_SIZE 0x10000
+
+#define UART1_BASE 0xff190000
+#define UART1_SIZE 0x10000
+
+#define UART2_BASE 0xff690000
+#define UART2_SIZE 0x10000
+
+#define UART3_BASE 0xff1b0000
+#define UART3_SIZE 0x10000
+
+#define UART4_BASE 0xff1c0000
+#define UART4_SIZE 0x10000
+
+#define CRU_BASE 0xff760000
+
+#define PMUSRAM_BASE 0xff720000
+#define PMUSRAM_SIZE 0x10000
+#define PMUSRAM_RSIZE 0x1000
+
+#define DDR_PCTL_BASE 0xff610000
+#define DDR_PCTL_SIZE 0x10000
+
+#define DDR_PHY_BASE 0xff620000
+#define DDR_PHY_SIZE 0x10000
+
+#define SERVICE_BUS_BASE 0xffac0000
+#define SERVICE_BUS_SISE 0x50000
+
+#define COLD_BOOT_BASE 0xffff0000
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3368_BAUDRATE 115200
+#define RK3368_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+
+/******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define RK3368_GICD_BASE (GIC400_BASE + 0x1000)
+#define RK3368_GICC_BASE (GIC400_BASE + 0x2000)
+#define RK3368_GICR_BASE 0 /* no GICR in GIC-400 */
+
+/*****************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 3
+#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 4
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER 29
+
+#define RK_IRQ_SEC_SGI_0 8
+#define RK_IRQ_SEC_SGI_1 9
+#define RK_IRQ_SEC_SGI_2 10
+#define RK_IRQ_SEC_SGI_3 11
+#define RK_IRQ_SEC_SGI_4 12
+#define RK_IRQ_SEC_SGI_5 13
+#define RK_IRQ_SEC_SGI_6 14
+#define RK_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 0 interrupts.
+ */
+#define PLAT_RK_GICV2_G0_IRQS \
+ INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+#endif /* RK3368_DEF_H */
diff --git a/plat/rockchip/rk3399/drivers/dp/cdn_dp.c b/plat/rockchip/rk3399/drivers/dp/cdn_dp.c
new file mode 100644
index 0000000..a8773f4
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dp/cdn_dp.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <cdefs.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lib/smccc.h>
+
+#include <cdn_dp.h>
+
+__asm__(
+ ".pushsection .text.hdcp_handler, \"ax\", %progbits\n"
+ ".global hdcp_handler\n"
+ ".balign 4\n"
+ "hdcp_handler:\n"
+ ".incbin \"" HDCPFW "\"\n"
+ ".type hdcp_handler, %function\n"
+ ".size hdcp_handler, .- hdcp_handler\n"
+ ".popsection\n"
+);
+
+static uint64_t *hdcp_key_pdata;
+static struct cdn_dp_hdcp_key_1x key;
+
+int hdcp_handler(struct cdn_dp_hdcp_key_1x *key);
+
+uint64_t dp_hdcp_ctrl(uint64_t type)
+{
+ switch (type) {
+ case HDCP_KEY_DATA_START_TRANSFER:
+ memset(&key, 0x00, sizeof(key));
+ hdcp_key_pdata = (uint64_t *)&key;
+ return 0;
+ case HDCP_KEY_DATA_START_DECRYPT:
+ if (hdcp_key_pdata == (uint64_t *)(&key + 1))
+ return hdcp_handler(&key);
+ else
+ return PSCI_E_INVALID_PARAMS;
+ assert(0); /* Unreachable */
+ default:
+ return SMC_UNK;
+ }
+}
+
+uint64_t dp_hdcp_store_key(uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ uint64_t x5,
+ uint64_t x6)
+{
+ if (hdcp_key_pdata < (uint64_t *)&key ||
+ hdcp_key_pdata + 6 > (uint64_t *)(&key + 1))
+ return PSCI_E_INVALID_PARAMS;
+
+ hdcp_key_pdata[0] = x1;
+ hdcp_key_pdata[1] = x2;
+ hdcp_key_pdata[2] = x3;
+ hdcp_key_pdata[3] = x4;
+ hdcp_key_pdata[4] = x5;
+ hdcp_key_pdata[5] = x6;
+ hdcp_key_pdata += 6;
+
+ return 0;
+}
diff --git a/plat/rockchip/rk3399/drivers/dp/cdn_dp.h b/plat/rockchip/rk3399/drivers/dp/cdn_dp.h
new file mode 100644
index 0000000..c5cbae2
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dp/cdn_dp.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CDN_DP_H
+#define CDN_DP_H
+
+#include <plat_private.h>
+
+enum {
+ CDN_DP_HDCP_1X_KSV_LEN = 5,
+ CDN_DP_HDCP_KSV_LEN = 8,
+ CDN_DP_HDCP_RESERVED_LEN = 10,
+ CDN_DP_HDCP_UID_LEN = 16,
+ CDN_DP_HDCP_SHA_LEN = 20,
+ CDN_DP_HDCP_DPK_LEN = 280,
+ CDN_DP_HDCP_1X_KEYS_LEN = 285,
+ CDN_DP_HDCP_KEY_LEN = 326,
+};
+
+struct cdn_dp_hdcp_key_1x {
+ uint8_t ksv[CDN_DP_HDCP_KSV_LEN];
+ uint8_t device_key[CDN_DP_HDCP_DPK_LEN];
+ uint8_t sha1[CDN_DP_HDCP_SHA_LEN];
+ uint8_t uid[CDN_DP_HDCP_UID_LEN];
+ uint16_t seed;
+ uint8_t reserved[CDN_DP_HDCP_RESERVED_LEN];
+};
+
+#define HDCP_KEY_DATA_START_TRANSFER 0
+#define HDCP_KEY_DATA_START_DECRYPT 1
+#define HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE (6 * 64) / 8
+
+/* Checks the cdn_dp_hdcp_key_1x must be aligned on 6 x 64-bit word boundary */
+CASSERT(sizeof(struct cdn_dp_hdcp_key_1x) % HDCP_KEY_1X_STORE_DATA_ALIGN_SIZE, \
+ assert_hdcp_key_1x_store_data_align_size_mismatch);
+
+uint64_t dp_hdcp_ctrl(uint64_t type);
+
+uint64_t dp_hdcp_store_key(uint64_t x1,
+ uint64_t x2,
+ uint64_t x3,
+ uint64_t x4,
+ uint64_t x5,
+ uint64_t x6);
+
+#endif /* CDN_DP_H */
diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c
new file mode 100644
index 0000000..816372b
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/dfs.c
@@ -0,0 +1,2114 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <m0_ctl.h>
+#include <plat_private.h>
+#include "dfs.h"
+#include "dram.h"
+#include "dram_spec_timing.h"
+#include "pmu.h"
+#include "soc.h"
+#include "string.h"
+
+#define ENPER_CS_TRAINING_FREQ (666)
+#define TDFI_LAT_THRESHOLD_FREQ (928)
+#define PHY_DLL_BYPASS_FREQ (260)
+
+static const struct pll_div dpll_rates_table[] = {
+
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2 */
+ {.mhz = 928, .refdiv = 1, .fbdiv = 116, .postdiv1 = 3, .postdiv2 = 1},
+ {.mhz = 800, .refdiv = 1, .fbdiv = 100, .postdiv1 = 3, .postdiv2 = 1},
+ {.mhz = 732, .refdiv = 1, .fbdiv = 61, .postdiv1 = 2, .postdiv2 = 1},
+ {.mhz = 666, .refdiv = 1, .fbdiv = 111, .postdiv1 = 4, .postdiv2 = 1},
+ {.mhz = 600, .refdiv = 1, .fbdiv = 50, .postdiv1 = 2, .postdiv2 = 1},
+ {.mhz = 528, .refdiv = 1, .fbdiv = 66, .postdiv1 = 3, .postdiv2 = 1},
+ {.mhz = 400, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 1},
+ {.mhz = 300, .refdiv = 1, .fbdiv = 50, .postdiv1 = 4, .postdiv2 = 1},
+ {.mhz = 200, .refdiv = 1, .fbdiv = 50, .postdiv1 = 3, .postdiv2 = 2},
+};
+
+struct rk3399_dram_status {
+ uint32_t current_index;
+ uint32_t index_freq[2];
+ uint32_t boot_freq;
+ uint32_t low_power_stat;
+ struct timing_related_config timing_config;
+ struct drv_odt_lp_config drv_odt_lp_cfg;
+};
+
+struct rk3399_saved_status {
+ uint32_t freq;
+ uint32_t low_power_stat;
+ uint32_t odt;
+};
+
+static struct rk3399_dram_status rk3399_dram_status;
+static struct rk3399_saved_status rk3399_suspend_status;
+static uint32_t wrdqs_delay_val[2][2][4];
+static uint32_t rddqs_delay_ps;
+
+static struct rk3399_sdram_default_config ddr3_default_config = {
+ .bl = 8,
+ .ap = 0,
+ .burst_ref_cnt = 1,
+ .zqcsi = 0
+};
+
+static struct rk3399_sdram_default_config lpddr3_default_config = {
+ .bl = 8,
+ .ap = 0,
+ .burst_ref_cnt = 1,
+ .zqcsi = 0
+};
+
+static struct rk3399_sdram_default_config lpddr4_default_config = {
+ .bl = 16,
+ .ap = 0,
+ .caodt = 240,
+ .burst_ref_cnt = 1,
+ .zqcsi = 0
+};
+
+static uint32_t get_cs_die_capability(struct rk3399_sdram_params *ram_config,
+ uint8_t channel, uint8_t cs)
+{
+ struct rk3399_sdram_channel *ch = &ram_config->ch[channel];
+ uint32_t bandwidth;
+ uint32_t die_bandwidth;
+ uint32_t die;
+ uint32_t cs_cap;
+ uint32_t row;
+
+ row = cs == 0 ? ch->cs0_row : ch->cs1_row;
+ bandwidth = 8 * (1 << ch->bw);
+ die_bandwidth = 8 * (1 << ch->dbw);
+ die = bandwidth / die_bandwidth;
+ cs_cap = (1 << (row + ((1 << ch->bk) / 4 + 1) + ch->col +
+ (bandwidth / 16)));
+ if (ch->row_3_4)
+ cs_cap = cs_cap * 3 / 4;
+
+ return (cs_cap / die);
+}
+
+static void get_dram_drv_odt_val(uint32_t dram_type,
+ struct drv_odt_lp_config *drv_config)
+{
+ uint32_t tmp;
+ uint32_t mr1_val, mr3_val, mr11_val;
+
+ switch (dram_type) {
+ case DDR3:
+ mr1_val = (mmio_read_32(CTL_REG(0, 133)) >> 16) & 0xffff;
+ tmp = ((mr1_val >> 1) & 1) | ((mr1_val >> 4) & 1);
+ if (tmp)
+ drv_config->dram_side_drv = 34;
+ else
+ drv_config->dram_side_drv = 40;
+ tmp = ((mr1_val >> 2) & 1) | ((mr1_val >> 5) & 1) |
+ ((mr1_val >> 7) & 1);
+ if (tmp == 0)
+ drv_config->dram_side_dq_odt = 0;
+ else if (tmp == 1)
+ drv_config->dram_side_dq_odt = 60;
+ else if (tmp == 3)
+ drv_config->dram_side_dq_odt = 40;
+ else
+ drv_config->dram_side_dq_odt = 120;
+ break;
+ case LPDDR3:
+ mr3_val = mmio_read_32(CTL_REG(0, 138)) & 0xf;
+ mr11_val = (mmio_read_32(CTL_REG(0, 139)) >> 24) & 0x3;
+ if (mr3_val == 0xb)
+ drv_config->dram_side_drv = 3448;
+ else if (mr3_val == 0xa)
+ drv_config->dram_side_drv = 4048;
+ else if (mr3_val == 0x9)
+ drv_config->dram_side_drv = 3440;
+ else if (mr3_val == 0x4)
+ drv_config->dram_side_drv = 60;
+ else if (mr3_val == 0x3)
+ drv_config->dram_side_drv = 48;
+ else if (mr3_val == 0x2)
+ drv_config->dram_side_drv = 40;
+ else
+ drv_config->dram_side_drv = 34;
+
+ if (mr11_val == 1)
+ drv_config->dram_side_dq_odt = 60;
+ else if (mr11_val == 2)
+ drv_config->dram_side_dq_odt = 120;
+ else if (mr11_val == 0)
+ drv_config->dram_side_dq_odt = 0;
+ else
+ drv_config->dram_side_dq_odt = 240;
+ break;
+ case LPDDR4:
+ default:
+ mr3_val = (mmio_read_32(CTL_REG(0, 138)) >> 3) & 0x7;
+ mr11_val = (mmio_read_32(CTL_REG(0, 139)) >> 24) & 0xff;
+
+ if ((mr3_val == 0) || (mr3_val == 7))
+ drv_config->dram_side_drv = 40;
+ else
+ drv_config->dram_side_drv = 240 / mr3_val;
+
+ tmp = mr11_val & 0x7;
+ if ((tmp == 7) || (tmp == 0))
+ drv_config->dram_side_dq_odt = 0;
+ else
+ drv_config->dram_side_dq_odt = 240 / tmp;
+
+ tmp = (mr11_val >> 4) & 0x7;
+ if ((tmp == 7) || (tmp == 0))
+ drv_config->dram_side_ca_odt = 0;
+ else
+ drv_config->dram_side_ca_odt = 240 / tmp;
+ break;
+ }
+}
+
+static void sdram_timing_cfg_init(struct timing_related_config *ptiming_config,
+ struct rk3399_sdram_params *sdram_params,
+ struct drv_odt_lp_config *drv_config)
+{
+ uint32_t i, j;
+
+ for (i = 0; i < sdram_params->num_channels; i++) {
+ ptiming_config->dram_info[i].speed_rate = DDR3_DEFAULT;
+ ptiming_config->dram_info[i].cs_cnt = sdram_params->ch[i].rank;
+ for (j = 0; j < sdram_params->ch[i].rank; j++) {
+ ptiming_config->dram_info[i].per_die_capability[j] =
+ get_cs_die_capability(sdram_params, i, j);
+ }
+ }
+ ptiming_config->dram_type = sdram_params->dramtype;
+ ptiming_config->ch_cnt = sdram_params->num_channels;
+ switch (sdram_params->dramtype) {
+ case DDR3:
+ ptiming_config->bl = ddr3_default_config.bl;
+ ptiming_config->ap = ddr3_default_config.ap;
+ break;
+ case LPDDR3:
+ ptiming_config->bl = lpddr3_default_config.bl;
+ ptiming_config->ap = lpddr3_default_config.ap;
+ break;
+ case LPDDR4:
+ ptiming_config->bl = lpddr4_default_config.bl;
+ ptiming_config->ap = lpddr4_default_config.ap;
+ ptiming_config->rdbi = 0;
+ ptiming_config->wdbi = 0;
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+ ptiming_config->dramds = drv_config->dram_side_drv;
+ ptiming_config->dramodt = drv_config->dram_side_dq_odt;
+ ptiming_config->caodt = drv_config->dram_side_ca_odt;
+ ptiming_config->odt = (mmio_read_32(PHY_REG(0, 5)) >> 16) & 0x1;
+}
+
+struct lat_adj_pair {
+ uint32_t cl;
+ uint32_t rdlat_adj;
+ uint32_t cwl;
+ uint32_t wrlat_adj;
+};
+
+const struct lat_adj_pair ddr3_lat_adj[] = {
+ {6, 5, 5, 4},
+ {8, 7, 6, 5},
+ {10, 9, 7, 6},
+ {11, 9, 8, 7},
+ {13, 0xb, 9, 8},
+ {14, 0xb, 0xa, 9}
+};
+
+const struct lat_adj_pair lpddr3_lat_adj[] = {
+ {3, 2, 1, 0},
+ {6, 5, 3, 2},
+ {8, 7, 4, 3},
+ {9, 8, 5, 4},
+ {10, 9, 6, 5},
+ {11, 9, 6, 5},
+ {12, 0xa, 6, 5},
+ {14, 0xc, 8, 7},
+ {16, 0xd, 8, 7}
+};
+
+const struct lat_adj_pair lpddr4_lat_adj[] = {
+ {6, 5, 4, 2},
+ {10, 9, 6, 4},
+ {14, 0xc, 8, 6},
+ {20, 0x11, 0xa, 8},
+ {24, 0x15, 0xc, 0xa},
+ {28, 0x18, 0xe, 0xc},
+ {32, 0x1b, 0x10, 0xe},
+ {36, 0x1e, 0x12, 0x10}
+};
+
+static uint32_t get_rdlat_adj(uint32_t dram_type, uint32_t cl)
+{
+ const struct lat_adj_pair *p;
+ uint32_t cnt;
+ uint32_t i;
+
+ if (dram_type == DDR3) {
+ p = ddr3_lat_adj;
+ cnt = ARRAY_SIZE(ddr3_lat_adj);
+ } else if (dram_type == LPDDR3) {
+ p = lpddr3_lat_adj;
+ cnt = ARRAY_SIZE(lpddr3_lat_adj);
+ } else {
+ p = lpddr4_lat_adj;
+ cnt = ARRAY_SIZE(lpddr4_lat_adj);
+ }
+
+ for (i = 0; i < cnt; i++) {
+ if (cl == p[i].cl)
+ return p[i].rdlat_adj;
+ }
+ /* fail */
+ return 0xff;
+}
+
+static uint32_t get_wrlat_adj(uint32_t dram_type, uint32_t cwl)
+{
+ const struct lat_adj_pair *p;
+ uint32_t cnt;
+ uint32_t i;
+
+ if (dram_type == DDR3) {
+ p = ddr3_lat_adj;
+ cnt = ARRAY_SIZE(ddr3_lat_adj);
+ } else if (dram_type == LPDDR3) {
+ p = lpddr3_lat_adj;
+ cnt = ARRAY_SIZE(lpddr3_lat_adj);
+ } else {
+ p = lpddr4_lat_adj;
+ cnt = ARRAY_SIZE(lpddr4_lat_adj);
+ }
+
+ for (i = 0; i < cnt; i++) {
+ if (cwl == p[i].cwl)
+ return p[i].wrlat_adj;
+ }
+ /* fail */
+ return 0xff;
+}
+
+#define PI_REGS_DIMM_SUPPORT (0)
+#define PI_ADD_LATENCY (0)
+#define PI_DOUBLEFREEK (1)
+
+#define PI_PAD_DELAY_PS_VALUE (1000)
+#define PI_IE_ENABLE_VALUE (3000)
+#define PI_TSEL_ENABLE_VALUE (700)
+
+static uint32_t get_pi_rdlat_adj(struct dram_timing_t *pdram_timing)
+{
+ /*[DLLSUBTYPE2] == "STD_DENALI_HS" */
+ uint32_t rdlat, delay_adder, ie_enable, hs_offset, tsel_adder,
+ extra_adder, tsel_enable;
+
+ ie_enable = PI_IE_ENABLE_VALUE;
+ tsel_enable = PI_TSEL_ENABLE_VALUE;
+
+ rdlat = pdram_timing->cl + PI_ADD_LATENCY;
+ delay_adder = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ delay_adder++;
+ hs_offset = 0;
+ tsel_adder = 0;
+ extra_adder = 0;
+ /* rdlat = rdlat - (PREAMBLE_SUPPORT & 0x1); */
+ tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz);
+ if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0)
+ tsel_adder++;
+ delay_adder = delay_adder - 1;
+ if (tsel_adder > delay_adder)
+ extra_adder = tsel_adder - delay_adder;
+ else
+ extra_adder = 0;
+ if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK)
+ hs_offset = 2;
+ else
+ hs_offset = 1;
+
+ if (delay_adder > (rdlat - 1 - hs_offset)) {
+ rdlat = rdlat - tsel_adder;
+ } else {
+ if ((rdlat - delay_adder) < 2)
+ rdlat = 2;
+ else
+ rdlat = rdlat - delay_adder - extra_adder;
+ }
+
+ return rdlat;
+}
+
+static uint32_t get_pi_wrlat(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ uint32_t tmp;
+
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = pdram_timing->cl;
+ if (tmp >= 14)
+ tmp = 8;
+ else if (tmp >= 10)
+ tmp = 6;
+ else if (tmp == 9)
+ tmp = 5;
+ else if (tmp == 8)
+ tmp = 4;
+ else if (tmp == 6)
+ tmp = 3;
+ else
+ tmp = 1;
+ } else {
+ tmp = 1;
+ }
+
+ return tmp;
+}
+
+static uint32_t get_pi_wrlat_adj(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ return get_pi_wrlat(pdram_timing, timing_config) + PI_ADD_LATENCY - 1;
+}
+
+static uint32_t get_pi_tdfi_phy_rdlat(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ /* [DLLSUBTYPE2] == "STD_DENALI_HS" */
+ uint32_t cas_lat, delay_adder, ie_enable, hs_offset, ie_delay_adder;
+ uint32_t mem_delay_ps, round_trip_ps;
+ uint32_t phy_internal_delay, lpddr_adder, dfi_adder, rdlat_delay;
+
+ ie_enable = PI_IE_ENABLE_VALUE;
+
+ delay_adder = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ delay_adder++;
+ delay_adder = delay_adder - 1;
+ if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK)
+ hs_offset = 2;
+ else
+ hs_offset = 1;
+
+ cas_lat = pdram_timing->cl + PI_ADD_LATENCY;
+
+ if (delay_adder > (cas_lat - 1 - hs_offset)) {
+ ie_delay_adder = 0;
+ } else {
+ ie_delay_adder = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ ie_delay_adder++;
+ }
+
+ if (timing_config->dram_type == DDR3) {
+ mem_delay_ps = 0;
+ } else if (timing_config->dram_type == LPDDR4) {
+ mem_delay_ps = 3600;
+ } else if (timing_config->dram_type == LPDDR3) {
+ mem_delay_ps = 5500;
+ } else {
+ NOTICE("get_pi_tdfi_phy_rdlat:dramtype unsupport\n");
+ return 0;
+ }
+ round_trip_ps = 1100 + 500 + mem_delay_ps + 500 + 600;
+ delay_adder = round_trip_ps / (1000000 / pdram_timing->mhz);
+ if ((round_trip_ps % (1000000 / pdram_timing->mhz)) != 0)
+ delay_adder++;
+
+ phy_internal_delay = 5 + 2 + 4;
+ lpddr_adder = mem_delay_ps / (1000000 / pdram_timing->mhz);
+ if ((mem_delay_ps % (1000000 / pdram_timing->mhz)) != 0)
+ lpddr_adder++;
+ dfi_adder = 0;
+ phy_internal_delay = phy_internal_delay + 2;
+ rdlat_delay = delay_adder + phy_internal_delay +
+ ie_delay_adder + lpddr_adder + dfi_adder;
+
+ rdlat_delay = rdlat_delay + 2;
+ return rdlat_delay;
+}
+
+static uint32_t get_pi_todtoff_min(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ uint32_t tmp, todtoff_min_ps;
+
+ if (timing_config->dram_type == LPDDR3)
+ todtoff_min_ps = 2500;
+ else if (timing_config->dram_type == LPDDR4)
+ todtoff_min_ps = 1500;
+ else
+ todtoff_min_ps = 0;
+ /* todtoff_min */
+ tmp = todtoff_min_ps / (1000000 / pdram_timing->mhz);
+ if ((todtoff_min_ps % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ return tmp;
+}
+
+static uint32_t get_pi_todtoff_max(struct dram_timing_t *pdram_timing,
+ struct timing_related_config *timing_config)
+{
+ uint32_t tmp, todtoff_max_ps;
+
+ if ((timing_config->dram_type == LPDDR4)
+ || (timing_config->dram_type == LPDDR3))
+ todtoff_max_ps = 3500;
+ else
+ todtoff_max_ps = 0;
+
+ /* todtoff_max */
+ tmp = todtoff_max_ps / (1000000 / pdram_timing->mhz);
+ if ((todtoff_max_ps % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ return tmp;
+}
+
+static void gen_rk3399_ctl_params_f0(struct timing_related_config
+ *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t i;
+ uint32_t tmp, tmp1;
+
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+ if (timing_config->dram_type == DDR3) {
+ tmp = ((700000 + 10) * timing_config->freq +
+ 999) / 1000;
+ tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) +
+ pdram_timing->tmod + pdram_timing->tzqinit;
+ mmio_write_32(CTL_REG(i, 5), tmp);
+
+ mmio_clrsetbits_32(CTL_REG(i, 22), 0xffff,
+ pdram_timing->tdllk);
+
+ mmio_write_32(CTL_REG(i, 32),
+ (pdram_timing->tmod << 8) |
+ pdram_timing->tmrd);
+
+ mmio_clrsetbits_32(CTL_REG(i, 59), 0xffffu << 16,
+ (pdram_timing->txsr -
+ pdram_timing->trcd) << 16);
+ } else if (timing_config->dram_type == LPDDR4) {
+ mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1 +
+ pdram_timing->tinit3);
+ mmio_write_32(CTL_REG(i, 32),
+ (pdram_timing->tmrd << 8) |
+ pdram_timing->tmrd);
+ mmio_clrsetbits_32(CTL_REG(i, 59), 0xffffu << 16,
+ pdram_timing->txsr << 16);
+ } else {
+ mmio_write_32(CTL_REG(i, 5), pdram_timing->tinit1);
+ mmio_write_32(CTL_REG(i, 7), pdram_timing->tinit4);
+ mmio_write_32(CTL_REG(i, 32),
+ (pdram_timing->tmrd << 8) |
+ pdram_timing->tmrd);
+ mmio_clrsetbits_32(CTL_REG(i, 59), 0xffffu << 16,
+ pdram_timing->txsr << 16);
+ }
+ mmio_write_32(CTL_REG(i, 6), pdram_timing->tinit3);
+ mmio_write_32(CTL_REG(i, 8), pdram_timing->tinit5);
+ mmio_clrsetbits_32(CTL_REG(i, 23), (0x7f << 16),
+ ((pdram_timing->cl * 2) << 16));
+ mmio_clrsetbits_32(CTL_REG(i, 23), (0x1f << 24),
+ (pdram_timing->cwl << 24));
+ mmio_clrsetbits_32(CTL_REG(i, 24), 0x3f, pdram_timing->al);
+ mmio_clrsetbits_32(CTL_REG(i, 26), 0xffffu << 16,
+ (pdram_timing->trc << 24) |
+ (pdram_timing->trrd << 16));
+ mmio_write_32(CTL_REG(i, 27),
+ (pdram_timing->tfaw << 24) |
+ (pdram_timing->trppb << 16) |
+ (pdram_timing->twtr << 8) |
+ pdram_timing->tras_min);
+
+ mmio_clrsetbits_32(CTL_REG(i, 31), 0xffu << 24,
+ max(4, pdram_timing->trtp) << 24);
+ mmio_write_32(CTL_REG(i, 33), (pdram_timing->tcke << 24) |
+ pdram_timing->tras_max);
+ mmio_clrsetbits_32(CTL_REG(i, 34), 0xff,
+ max(1, pdram_timing->tckesr));
+ mmio_clrsetbits_32(CTL_REG(i, 39),
+ (0x3f << 16) | (0xff << 8),
+ (pdram_timing->twr << 16) |
+ (pdram_timing->trcd << 8));
+ mmio_clrsetbits_32(CTL_REG(i, 42), 0x1f << 16,
+ pdram_timing->tmrz << 16);
+ tmp = pdram_timing->tdal ? pdram_timing->tdal :
+ (pdram_timing->twr + pdram_timing->trp);
+ mmio_clrsetbits_32(CTL_REG(i, 44), 0xff, tmp);
+ mmio_clrsetbits_32(CTL_REG(i, 45), 0xff, pdram_timing->trp);
+ mmio_write_32(CTL_REG(i, 48),
+ ((pdram_timing->trefi - 8) << 16) |
+ pdram_timing->trfc);
+ mmio_clrsetbits_32(CTL_REG(i, 52), 0xffff, pdram_timing->txp);
+ mmio_clrsetbits_32(CTL_REG(i, 53), 0xffffu << 16,
+ pdram_timing->txpdll << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 55), 0xf << 24,
+ pdram_timing->tcscke << 24);
+ mmio_clrsetbits_32(CTL_REG(i, 55), 0xff, pdram_timing->tmrri);
+ mmio_write_32(CTL_REG(i, 56),
+ (pdram_timing->tzqcke << 24) |
+ (pdram_timing->tmrwckel << 16) |
+ (pdram_timing->tckehcs << 8) |
+ pdram_timing->tckelcs);
+ mmio_clrsetbits_32(CTL_REG(i, 60), 0xffff, pdram_timing->txsnr);
+ mmio_clrsetbits_32(CTL_REG(i, 62), 0xffffu << 16,
+ (pdram_timing->tckehcmd << 24) |
+ (pdram_timing->tckelcmd << 16));
+ mmio_write_32(CTL_REG(i, 63),
+ (pdram_timing->tckelpd << 24) |
+ (pdram_timing->tescke << 16) |
+ (pdram_timing->tsr << 8) |
+ pdram_timing->tckckel);
+ mmio_clrsetbits_32(CTL_REG(i, 64), 0xfff,
+ (pdram_timing->tcmdcke << 8) |
+ pdram_timing->tcsckeh);
+ mmio_clrsetbits_32(CTL_REG(i, 92), 0xffff << 8,
+ (pdram_timing->tcksrx << 16) |
+ (pdram_timing->tcksre << 8));
+ mmio_clrsetbits_32(CTL_REG(i, 108), 0x1 << 24,
+ (timing_config->dllbp << 24));
+ mmio_clrsetbits_32(CTL_REG(i, 122), 0x3ff << 16,
+ (pdram_timing->tvrcg_enable << 16));
+ mmio_write_32(CTL_REG(i, 123), (pdram_timing->tfc_long << 16) |
+ pdram_timing->tvrcg_disable);
+ mmio_write_32(CTL_REG(i, 124),
+ (pdram_timing->tvref_long << 16) |
+ (pdram_timing->tckfspx << 8) |
+ pdram_timing->tckfspe);
+ mmio_write_32(CTL_REG(i, 133), (pdram_timing->mr[1] << 16) |
+ pdram_timing->mr[0]);
+ mmio_clrsetbits_32(CTL_REG(i, 134), 0xffff,
+ pdram_timing->mr[2]);
+ mmio_clrsetbits_32(CTL_REG(i, 138), 0xffff,
+ pdram_timing->mr[3]);
+ mmio_clrsetbits_32(CTL_REG(i, 139), 0xffu << 24,
+ pdram_timing->mr11 << 24);
+ mmio_write_32(CTL_REG(i, 147),
+ (pdram_timing->mr[1] << 16) |
+ pdram_timing->mr[0]);
+ mmio_clrsetbits_32(CTL_REG(i, 148), 0xffff,
+ pdram_timing->mr[2]);
+ mmio_clrsetbits_32(CTL_REG(i, 152), 0xffff,
+ pdram_timing->mr[3]);
+ mmio_clrsetbits_32(CTL_REG(i, 153), 0xffu << 24,
+ pdram_timing->mr11 << 24);
+ if (timing_config->dram_type == LPDDR4) {
+ mmio_clrsetbits_32(CTL_REG(i, 140), 0xffffu << 16,
+ pdram_timing->mr12 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 142), 0xffffu << 16,
+ pdram_timing->mr14 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 145), 0xffffu << 16,
+ pdram_timing->mr22 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 154), 0xffffu << 16,
+ pdram_timing->mr12 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 156), 0xffffu << 16,
+ pdram_timing->mr14 << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 159), 0xffffu << 16,
+ pdram_timing->mr22 << 16);
+ }
+ mmio_clrsetbits_32(CTL_REG(i, 179), 0xfff << 8,
+ pdram_timing->tzqinit << 8);
+ mmio_write_32(CTL_REG(i, 180), (pdram_timing->tzqcs << 16) |
+ (pdram_timing->tzqinit / 2));
+ mmio_write_32(CTL_REG(i, 181), (pdram_timing->tzqlat << 16) |
+ pdram_timing->tzqcal);
+ mmio_clrsetbits_32(CTL_REG(i, 212), 0xff << 8,
+ pdram_timing->todton << 8);
+
+ if (timing_config->odt) {
+ mmio_setbits_32(CTL_REG(i, 213), 1 << 16);
+ if (timing_config->freq < 400)
+ tmp = 4 << 24;
+ else
+ tmp = 8 << 24;
+ } else {
+ mmio_clrbits_32(CTL_REG(i, 213), 1 << 16);
+ tmp = 2 << 24;
+ }
+
+ mmio_clrsetbits_32(CTL_REG(i, 216), 0x1f << 24, tmp);
+ mmio_clrsetbits_32(CTL_REG(i, 221), (0x3 << 16) | (0xf << 8),
+ (pdram_timing->tdqsck << 16) |
+ (pdram_timing->tdqsck_max << 8));
+ tmp =
+ (get_wrlat_adj(timing_config->dram_type, pdram_timing->cwl)
+ << 8) | get_rdlat_adj(timing_config->dram_type,
+ pdram_timing->cl);
+ mmio_clrsetbits_32(CTL_REG(i, 284), 0xffff, tmp);
+ mmio_clrsetbits_32(CTL_REG(i, 82), 0xffffu << 16,
+ (4 * pdram_timing->trefi) << 16);
+
+ mmio_clrsetbits_32(CTL_REG(i, 83), 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = 0;
+ }
+ mmio_clrsetbits_32(CTL_REG(i, 214), 0x3f << 16,
+ (tmp & 0x3f) << 16);
+
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl+TDQSCK_MIN -1 */
+ tmp = pdram_timing->cl +
+ get_pi_todtoff_min(pdram_timing, timing_config) - 1;
+ /* todtoff_max */
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ }
+ mmio_clrsetbits_32(CTL_REG(i, 215), 0x3f << 8,
+ (tmp & 0x3f) << 8);
+
+ mmio_clrsetbits_32(CTL_REG(i, 275), 0xff << 16,
+ (get_pi_tdfi_phy_rdlat(pdram_timing,
+ timing_config) &
+ 0xff) << 16);
+
+ mmio_clrsetbits_32(CTL_REG(i, 277), 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ mmio_clrsetbits_32(CTL_REG(i, 282), 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ mmio_write_32(CTL_REG(i, 283), 20 * pdram_timing->trefi);
+
+ /* CTL_308 TDFI_CALVL_CAPTURE_F0:RW:16:10 */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ mmio_clrsetbits_32(CTL_REG(i, 308), 0x3ff << 16, tmp << 16);
+
+ /* CTL_308 TDFI_CALVL_CC_F0:RW:0:10 */
+ tmp = tmp + 18;
+ mmio_clrsetbits_32(CTL_REG(i, 308), 0x3ff, tmp);
+
+ /* CTL_314 TDFI_WRCSLAT_F0:RW:8:8 */
+ tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config);
+ if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) {
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ } else {
+ tmp = tmp1 - 2;
+ }
+ mmio_clrsetbits_32(CTL_REG(i, 314), 0xff << 8, tmp << 8);
+
+ /* CTL_314 TDFI_RDCSLAT_F0:RW:0:8 */
+ if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) &&
+ (pdram_timing->cl >= 5))
+ tmp = pdram_timing->cl - 5;
+ else
+ tmp = pdram_timing->cl - 2;
+ mmio_clrsetbits_32(CTL_REG(i, 314), 0xff, tmp);
+ }
+}
+
+static void gen_rk3399_ctl_params_f1(struct timing_related_config
+ *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t i;
+ uint32_t tmp, tmp1;
+
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+ if (timing_config->dram_type == DDR3) {
+ tmp =
+ ((700000 + 10) * timing_config->freq + 999) / 1000;
+ tmp += pdram_timing->txsnr + (pdram_timing->tmrd * 3) +
+ pdram_timing->tmod + pdram_timing->tzqinit;
+ mmio_write_32(CTL_REG(i, 9), tmp);
+ mmio_clrsetbits_32(CTL_REG(i, 22), 0xffffu << 16,
+ pdram_timing->tdllk << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00,
+ (pdram_timing->tmod << 24) |
+ (pdram_timing->tmrd << 16) |
+ (pdram_timing->trtp << 8));
+ mmio_clrsetbits_32(CTL_REG(i, 60), 0xffffu << 16,
+ (pdram_timing->txsr -
+ pdram_timing->trcd) << 16);
+ } else if (timing_config->dram_type == LPDDR4) {
+ mmio_write_32(CTL_REG(i, 9), pdram_timing->tinit1 +
+ pdram_timing->tinit3);
+ mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00,
+ (pdram_timing->tmrd << 24) |
+ (pdram_timing->tmrd << 16) |
+ (pdram_timing->trtp << 8));
+ mmio_clrsetbits_32(CTL_REG(i, 60), 0xffffu << 16,
+ pdram_timing->txsr << 16);
+ } else {
+ mmio_write_32(CTL_REG(i, 9), pdram_timing->tinit1);
+ mmio_write_32(CTL_REG(i, 11), pdram_timing->tinit4);
+ mmio_clrsetbits_32(CTL_REG(i, 34), 0xffffff00,
+ (pdram_timing->tmrd << 24) |
+ (pdram_timing->tmrd << 16) |
+ (pdram_timing->trtp << 8));
+ mmio_clrsetbits_32(CTL_REG(i, 60), 0xffffu << 16,
+ pdram_timing->txsr << 16);
+ }
+ mmio_write_32(CTL_REG(i, 10), pdram_timing->tinit3);
+ mmio_write_32(CTL_REG(i, 12), pdram_timing->tinit5);
+ mmio_clrsetbits_32(CTL_REG(i, 24), (0x7f << 8),
+ ((pdram_timing->cl * 2) << 8));
+ mmio_clrsetbits_32(CTL_REG(i, 24), (0x1f << 16),
+ (pdram_timing->cwl << 16));
+ mmio_clrsetbits_32(CTL_REG(i, 24), 0x3f << 24,
+ pdram_timing->al << 24);
+ mmio_clrsetbits_32(CTL_REG(i, 28), 0xffffff00,
+ (pdram_timing->tras_min << 24) |
+ (pdram_timing->trc << 16) |
+ (pdram_timing->trrd << 8));
+ mmio_clrsetbits_32(CTL_REG(i, 29), 0xffffff,
+ (pdram_timing->tfaw << 16) |
+ (pdram_timing->trppb << 8) |
+ pdram_timing->twtr);
+ mmio_write_32(CTL_REG(i, 35), (pdram_timing->tcke << 24) |
+ pdram_timing->tras_max);
+ mmio_clrsetbits_32(CTL_REG(i, 36), 0xff,
+ max(1, pdram_timing->tckesr));
+ mmio_clrsetbits_32(CTL_REG(i, 39), (0xffu << 24),
+ (pdram_timing->trcd << 24));
+ mmio_clrsetbits_32(CTL_REG(i, 40), 0x3f, pdram_timing->twr);
+ mmio_clrsetbits_32(CTL_REG(i, 42), 0x1f << 24,
+ pdram_timing->tmrz << 24);
+ tmp = pdram_timing->tdal ? pdram_timing->tdal :
+ (pdram_timing->twr + pdram_timing->trp);
+ mmio_clrsetbits_32(CTL_REG(i, 44), 0xff << 8, tmp << 8);
+ mmio_clrsetbits_32(CTL_REG(i, 45), 0xff << 8,
+ pdram_timing->trp << 8);
+ mmio_write_32(CTL_REG(i, 49),
+ ((pdram_timing->trefi - 8) << 16) |
+ pdram_timing->trfc);
+ mmio_clrsetbits_32(CTL_REG(i, 52), 0xffffu << 16,
+ pdram_timing->txp << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 54), 0xffff,
+ pdram_timing->txpdll);
+ mmio_clrsetbits_32(CTL_REG(i, 55), 0xff << 8,
+ pdram_timing->tmrri << 8);
+ mmio_write_32(CTL_REG(i, 57), (pdram_timing->tmrwckel << 24) |
+ (pdram_timing->tckehcs << 16) |
+ (pdram_timing->tckelcs << 8) |
+ pdram_timing->tcscke);
+ mmio_clrsetbits_32(CTL_REG(i, 58), 0xf, pdram_timing->tzqcke);
+ mmio_clrsetbits_32(CTL_REG(i, 61), 0xffff, pdram_timing->txsnr);
+ mmio_clrsetbits_32(CTL_REG(i, 64), 0xffffu << 16,
+ (pdram_timing->tckehcmd << 24) |
+ (pdram_timing->tckelcmd << 16));
+ mmio_write_32(CTL_REG(i, 65), (pdram_timing->tckelpd << 24) |
+ (pdram_timing->tescke << 16) |
+ (pdram_timing->tsr << 8) |
+ pdram_timing->tckckel);
+ mmio_clrsetbits_32(CTL_REG(i, 66), 0xfff,
+ (pdram_timing->tcmdcke << 8) |
+ pdram_timing->tcsckeh);
+ mmio_clrsetbits_32(CTL_REG(i, 92), (0xffu << 24),
+ (pdram_timing->tcksre << 24));
+ mmio_clrsetbits_32(CTL_REG(i, 93), 0xff,
+ pdram_timing->tcksrx);
+ mmio_clrsetbits_32(CTL_REG(i, 108), (0x1 << 25),
+ (timing_config->dllbp << 25));
+ mmio_write_32(CTL_REG(i, 125),
+ (pdram_timing->tvrcg_disable << 16) |
+ pdram_timing->tvrcg_enable);
+ mmio_write_32(CTL_REG(i, 126), (pdram_timing->tckfspx << 24) |
+ (pdram_timing->tckfspe << 16) |
+ pdram_timing->tfc_long);
+ mmio_clrsetbits_32(CTL_REG(i, 127), 0xffff,
+ pdram_timing->tvref_long);
+ mmio_clrsetbits_32(CTL_REG(i, 134), 0xffffu << 16,
+ pdram_timing->mr[0] << 16);
+ mmio_write_32(CTL_REG(i, 135), (pdram_timing->mr[2] << 16) |
+ pdram_timing->mr[1]);
+ mmio_clrsetbits_32(CTL_REG(i, 138), 0xffffu << 16,
+ pdram_timing->mr[3] << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 140), 0xff, pdram_timing->mr11);
+ mmio_clrsetbits_32(CTL_REG(i, 148), 0xffffu << 16,
+ pdram_timing->mr[0] << 16);
+ mmio_write_32(CTL_REG(i, 149), (pdram_timing->mr[2] << 16) |
+ pdram_timing->mr[1]);
+ mmio_clrsetbits_32(CTL_REG(i, 152), 0xffffu << 16,
+ pdram_timing->mr[3] << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 154), 0xff, pdram_timing->mr11);
+ if (timing_config->dram_type == LPDDR4) {
+ mmio_clrsetbits_32(CTL_REG(i, 141), 0xffff,
+ pdram_timing->mr12);
+ mmio_clrsetbits_32(CTL_REG(i, 143), 0xffff,
+ pdram_timing->mr14);
+ mmio_clrsetbits_32(CTL_REG(i, 146), 0xffff,
+ pdram_timing->mr22);
+ mmio_clrsetbits_32(CTL_REG(i, 155), 0xffff,
+ pdram_timing->mr12);
+ mmio_clrsetbits_32(CTL_REG(i, 157), 0xffff,
+ pdram_timing->mr14);
+ mmio_clrsetbits_32(CTL_REG(i, 160), 0xffff,
+ pdram_timing->mr22);
+ }
+ mmio_write_32(CTL_REG(i, 182),
+ ((pdram_timing->tzqinit / 2) << 16) |
+ pdram_timing->tzqinit);
+ mmio_write_32(CTL_REG(i, 183), (pdram_timing->tzqcal << 16) |
+ pdram_timing->tzqcs);
+ mmio_clrsetbits_32(CTL_REG(i, 184), 0x3f, pdram_timing->tzqlat);
+ mmio_clrsetbits_32(CTL_REG(i, 188), 0xfff,
+ pdram_timing->tzqreset);
+ mmio_clrsetbits_32(CTL_REG(i, 212), 0xff << 16,
+ pdram_timing->todton << 16);
+
+ if (timing_config->odt) {
+ mmio_setbits_32(CTL_REG(i, 213), (1 << 24));
+ if (timing_config->freq < 400)
+ tmp = 4 << 24;
+ else
+ tmp = 8 << 24;
+ } else {
+ mmio_clrbits_32(CTL_REG(i, 213), (1 << 24));
+ tmp = 2 << 24;
+ }
+ mmio_clrsetbits_32(CTL_REG(i, 217), 0x1f << 24, tmp);
+ mmio_clrsetbits_32(CTL_REG(i, 221), 0xf << 24,
+ (pdram_timing->tdqsck_max << 24));
+ mmio_clrsetbits_32(CTL_REG(i, 222), 0x3, pdram_timing->tdqsck);
+ mmio_clrsetbits_32(CTL_REG(i, 291), 0xffff,
+ (get_wrlat_adj(timing_config->dram_type,
+ pdram_timing->cwl) << 8) |
+ get_rdlat_adj(timing_config->dram_type,
+ pdram_timing->cl));
+
+ mmio_clrsetbits_32(CTL_REG(i, 84), 0xffff,
+ (4 * pdram_timing->trefi) & 0xffff);
+
+ mmio_clrsetbits_32(CTL_REG(i, 84), 0xffffu << 16,
+ ((2 * pdram_timing->trefi) & 0xffff) << 16);
+
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = 0;
+ }
+ mmio_clrsetbits_32(CTL_REG(i, 214), 0x3f << 24,
+ (tmp & 0x3f) << 24);
+
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl + TDQSCK_MIN - 1 */
+ tmp = pdram_timing->cl +
+ get_pi_todtoff_min(pdram_timing, timing_config);
+ tmp--;
+ /* todtoff_max */
+ tmp1 = get_pi_todtoff_max(pdram_timing, timing_config);
+ tmp = (tmp > tmp1) ? (tmp - tmp1) : 0;
+ } else {
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ }
+ mmio_clrsetbits_32(CTL_REG(i, 215), 0x3f << 16,
+ (tmp & 0x3f) << 16);
+
+ mmio_clrsetbits_32(CTL_REG(i, 275), 0xffu << 24,
+ (get_pi_tdfi_phy_rdlat(pdram_timing,
+ timing_config) &
+ 0xff) << 24);
+
+ mmio_clrsetbits_32(CTL_REG(i, 284), 0xffffu << 16,
+ ((2 * pdram_timing->trefi) & 0xffff) << 16);
+
+ mmio_clrsetbits_32(CTL_REG(i, 289), 0xffff,
+ (2 * pdram_timing->trefi) & 0xffff);
+
+ mmio_write_32(CTL_REG(i, 290), 20 * pdram_timing->trefi);
+
+ /* CTL_309 TDFI_CALVL_CAPTURE_F1:RW:16:10 */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ mmio_clrsetbits_32(CTL_REG(i, 309), 0x3ff << 16, tmp << 16);
+
+ /* CTL_309 TDFI_CALVL_CC_F1:RW:0:10 */
+ tmp = tmp + 18;
+ mmio_clrsetbits_32(CTL_REG(i, 309), 0x3ff, tmp);
+
+ /* CTL_314 TDFI_WRCSLAT_F1:RW:24:8 */
+ tmp1 = get_pi_wrlat_adj(pdram_timing, timing_config);
+ if (timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) {
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ } else {
+ tmp = tmp1 - 2;
+ }
+
+ mmio_clrsetbits_32(CTL_REG(i, 314), 0xffu << 24, tmp << 24);
+
+ /* CTL_314 TDFI_RDCSLAT_F1:RW:16:8 */
+ if ((timing_config->freq <= TDFI_LAT_THRESHOLD_FREQ) &&
+ (pdram_timing->cl >= 5))
+ tmp = pdram_timing->cl - 5;
+ else
+ tmp = pdram_timing->cl - 2;
+ mmio_clrsetbits_32(CTL_REG(i, 314), 0xff << 16, tmp << 16);
+ }
+}
+
+static void gen_rk3399_enable_training(uint32_t ch_cnt, uint32_t nmhz)
+{
+ uint32_t i, tmp;
+
+ if (nmhz <= PHY_DLL_BYPASS_FREQ)
+ tmp = 0;
+ else
+ tmp = 1;
+
+ for (i = 0; i < ch_cnt; i++) {
+ mmio_clrsetbits_32(CTL_REG(i, 305), 1 << 16, tmp << 16);
+ mmio_clrsetbits_32(CTL_REG(i, 71), 1, tmp);
+ mmio_clrsetbits_32(CTL_REG(i, 70), 1 << 8, 1 << 8);
+ }
+}
+
+static void gen_rk3399_disable_training(uint32_t ch_cnt)
+{
+ uint32_t i;
+
+ for (i = 0; i < ch_cnt; i++) {
+ mmio_clrbits_32(CTL_REG(i, 305), 1 << 16);
+ mmio_clrbits_32(CTL_REG(i, 71), 1);
+ mmio_clrbits_32(CTL_REG(i, 70), 1 << 8);
+ }
+}
+
+static void gen_rk3399_ctl_params(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing,
+ uint32_t fn)
+{
+ if (fn == 0)
+ gen_rk3399_ctl_params_f0(timing_config, pdram_timing);
+ else
+ gen_rk3399_ctl_params_f1(timing_config, pdram_timing);
+}
+
+static void gen_rk3399_pi_params_f0(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t tmp, tmp1, tmp2;
+ uint32_t i;
+
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+ /* PI_02 PI_TDFI_PHYMSTR_MAX_F0:RW:0:32 */
+ tmp = 4 * pdram_timing->trefi;
+ mmio_write_32(PI_REG(i, 2), tmp);
+ /* PI_03 PI_TDFI_PHYMSTR_RESP_F0:RW:0:16 */
+ tmp = 2 * pdram_timing->trefi;
+ mmio_clrsetbits_32(PI_REG(i, 3), 0xffff, tmp);
+ /* PI_07 PI_TDFI_PHYUPD_RESP_F0:RW:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 7), 0xffffu << 16, tmp << 16);
+
+ /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F0:RW:0:8 */
+ if (timing_config->dram_type == LPDDR4)
+ tmp = 2;
+ else
+ tmp = 0;
+ tmp = (pdram_timing->bl / 2) + 4 +
+ (get_pi_rdlat_adj(pdram_timing) - 2) + tmp +
+ get_pi_tdfi_phy_rdlat(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 42), 0xff, tmp);
+ /* PI_43 PI_WRLAT_F0:RW:0:5 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 43), 0x1f, tmp);
+ }
+ /* PI_43 PI_ADDITIVE_LAT_F0:RW:8:6 */
+ mmio_clrsetbits_32(PI_REG(i, 43), 0x3f << 8,
+ PI_ADD_LATENCY << 8);
+
+ /* PI_43 PI_CASLAT_LIN_F0:RW:16:7 */
+ mmio_clrsetbits_32(PI_REG(i, 43), 0x7f << 16,
+ (pdram_timing->cl * 2) << 16);
+ /* PI_46 PI_TREF_F0:RW:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 46), 0xffffu << 16,
+ pdram_timing->trefi << 16);
+ /* PI_46 PI_TRFC_F0:RW:0:10 */
+ mmio_clrsetbits_32(PI_REG(i, 46), 0x3ff, pdram_timing->trfc);
+ /* PI_66 PI_TODTL_2CMD_F0:RW:24:8 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_todtoff_max(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 66), 0xffu << 24,
+ tmp << 24);
+ }
+ /* PI_72 PI_WR_TO_ODTH_F0:RW:16:6 */
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp1 = get_pi_wrlat(pdram_timing, timing_config);
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3) {
+ tmp = 0;
+ }
+ mmio_clrsetbits_32(PI_REG(i, 72), 0x3f << 16, tmp << 16);
+ /* PI_73 PI_RD_TO_ODTH_F0:RW:8:6 */
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl + TDQSCK_MIN - 1 */
+ tmp1 = pdram_timing->cl;
+ tmp1 += get_pi_todtoff_min(pdram_timing, timing_config);
+ tmp1--;
+ /* todtoff_max */
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3) {
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+ }
+ mmio_clrsetbits_32(PI_REG(i, 73), 0x3f << 8, tmp << 8);
+ /* PI_89 PI_RDLAT_ADJ_F0:RW:16:8 */
+ tmp = get_pi_rdlat_adj(pdram_timing);
+ mmio_clrsetbits_32(PI_REG(i, 89), 0xff << 16, tmp << 16);
+ /* PI_90 PI_WRLAT_ADJ_F0:RW:16:8 */
+ tmp = get_pi_wrlat_adj(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 90), 0xff << 16, tmp << 16);
+ /* PI_91 PI_TDFI_WRCSLAT_F0:RW:16:8 */
+ tmp1 = tmp;
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ mmio_clrsetbits_32(PI_REG(i, 91), 0xff << 16, tmp << 16);
+ /* PI_95 PI_TDFI_CALVL_CAPTURE_F0:RW:16:10 */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ mmio_clrsetbits_32(PI_REG(i, 95), 0x3ff << 16, tmp << 16);
+ /* PI_95 PI_TDFI_CALVL_CC_F0:RW:0:10 */
+ mmio_clrsetbits_32(PI_REG(i, 95), 0x3ff, tmp + 18);
+ /* PI_102 PI_TMRZ_F0:RW:8:5 */
+ mmio_clrsetbits_32(PI_REG(i, 102), 0x1f << 8,
+ pdram_timing->tmrz << 8);
+ /* PI_111 PI_TDFI_CALVL_STROBE_F0:RW:8:4 */
+ tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz);
+ if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ /* pi_tdfi_calvl_strobe=tds_train+5 */
+ tmp = tmp1 + 5;
+ mmio_clrsetbits_32(PI_REG(i, 111), 0xf << 8, tmp << 8);
+ /* PI_116 PI_TCKEHDQS_F0:RW:16:6 */
+ tmp = 10000 / (1000000 / pdram_timing->mhz);
+ if ((10000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ if (pdram_timing->mhz <= 100)
+ tmp = tmp + 1;
+ else
+ tmp = tmp + 8;
+ mmio_clrsetbits_32(PI_REG(i, 116), 0x3f << 16, tmp << 16);
+ /* PI_125 PI_MR1_DATA_F0_0:RW+:8:16 */
+ mmio_clrsetbits_32(PI_REG(i, 125), 0xffff << 8,
+ pdram_timing->mr[1] << 8);
+ /* PI_133 PI_MR1_DATA_F0_1:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 133), 0xffff, pdram_timing->mr[1]);
+ /* PI_140 PI_MR1_DATA_F0_2:RW+:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 140), 0xffffu << 16,
+ pdram_timing->mr[1] << 16);
+ /* PI_148 PI_MR1_DATA_F0_3:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 148), 0xffff, pdram_timing->mr[1]);
+ /* PI_126 PI_MR2_DATA_F0_0:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 126), 0xffff, pdram_timing->mr[2]);
+ /* PI_133 PI_MR2_DATA_F0_1:RW+:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 133), 0xffffu << 16,
+ pdram_timing->mr[2] << 16);
+ /* PI_141 PI_MR2_DATA_F0_2:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 141), 0xffff, pdram_timing->mr[2]);
+ /* PI_148 PI_MR2_DATA_F0_3:RW+:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 148), 0xffffu << 16,
+ pdram_timing->mr[2] << 16);
+ /* PI_156 PI_TFC_F0:RW:0:10 */
+ mmio_clrsetbits_32(PI_REG(i, 156), 0x3ff,
+ pdram_timing->tfc_long);
+ /* PI_158 PI_TWR_F0:RW:24:6 */
+ mmio_clrsetbits_32(PI_REG(i, 158), 0x3f << 24,
+ pdram_timing->twr << 24);
+ /* PI_158 PI_TWTR_F0:RW:16:6 */
+ mmio_clrsetbits_32(PI_REG(i, 158), 0x3f << 16,
+ pdram_timing->twtr << 16);
+ /* PI_158 PI_TRCD_F0:RW:8:8 */
+ mmio_clrsetbits_32(PI_REG(i, 158), 0xff << 8,
+ pdram_timing->trcd << 8);
+ /* PI_158 PI_TRP_F0:RW:0:8 */
+ mmio_clrsetbits_32(PI_REG(i, 158), 0xff, pdram_timing->trp);
+ /* PI_157 PI_TRTP_F0:RW:24:8 */
+ mmio_clrsetbits_32(PI_REG(i, 157), 0xffu << 24,
+ pdram_timing->trtp << 24);
+ /* PI_159 PI_TRAS_MIN_F0:RW:24:8 */
+ mmio_clrsetbits_32(PI_REG(i, 159), 0xffu << 24,
+ pdram_timing->tras_min << 24);
+ /* PI_159 PI_TRAS_MAX_F0:RW:0:17 */
+ tmp = pdram_timing->tras_max * 99 / 100;
+ mmio_clrsetbits_32(PI_REG(i, 159), 0x1ffff, tmp);
+ /* PI_160 PI_TMRD_F0:RW:16:6 */
+ mmio_clrsetbits_32(PI_REG(i, 160), 0x3f << 16,
+ pdram_timing->tmrd << 16);
+ /*PI_160 PI_TDQSCK_MAX_F0:RW:0:4 */
+ mmio_clrsetbits_32(PI_REG(i, 160), 0xf,
+ pdram_timing->tdqsck_max);
+ /* PI_187 PI_TDFI_CTRLUPD_MAX_F0:RW:8:16 */
+ mmio_clrsetbits_32(PI_REG(i, 187), 0xffff << 8,
+ (2 * pdram_timing->trefi) << 8);
+ /* PI_188 PI_TDFI_CTRLUPD_INTERVAL_F0:RW:0:32 */
+ mmio_clrsetbits_32(PI_REG(i, 188), 0xffffffff,
+ 20 * pdram_timing->trefi);
+ }
+}
+
+static void gen_rk3399_pi_params_f1(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t tmp, tmp1, tmp2;
+ uint32_t i;
+
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+ /* PI_04 PI_TDFI_PHYMSTR_MAX_F1:RW:0:32 */
+ tmp = 4 * pdram_timing->trefi;
+ mmio_write_32(PI_REG(i, 4), tmp);
+ /* PI_05 PI_TDFI_PHYMSTR_RESP_F1:RW:0:16 */
+ tmp = 2 * pdram_timing->trefi;
+ mmio_clrsetbits_32(PI_REG(i, 5), 0xffff, tmp);
+ /* PI_12 PI_TDFI_PHYUPD_RESP_F1:RW:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 12), 0xffff, tmp);
+
+ /* PI_42 PI_TDELAY_RDWR_2_BUS_IDLE_F1:RW:8:8 */
+ if (timing_config->dram_type == LPDDR4)
+ tmp = 2;
+ else
+ tmp = 0;
+ tmp = (pdram_timing->bl / 2) + 4 +
+ (get_pi_rdlat_adj(pdram_timing) - 2) + tmp +
+ get_pi_tdfi_phy_rdlat(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 42), 0xff << 8, tmp << 8);
+ /* PI_43 PI_WRLAT_F1:RW:24:5 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_wrlat(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 43), 0x1f << 24,
+ tmp << 24);
+ }
+ /* PI_44 PI_ADDITIVE_LAT_F1:RW:0:6 */
+ mmio_clrsetbits_32(PI_REG(i, 44), 0x3f, PI_ADD_LATENCY);
+ /* PI_44 PI_CASLAT_LIN_F1:RW:8:7:=0x18 */
+ mmio_clrsetbits_32(PI_REG(i, 44), 0x7f << 8,
+ (pdram_timing->cl * 2) << 8);
+ /* PI_47 PI_TREF_F1:RW:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 47), 0xffffu << 16,
+ pdram_timing->trefi << 16);
+ /* PI_47 PI_TRFC_F1:RW:0:10 */
+ mmio_clrsetbits_32(PI_REG(i, 47), 0x3ff, pdram_timing->trfc);
+ /* PI_67 PI_TODTL_2CMD_F1:RW:8:8 */
+ if (timing_config->dram_type == LPDDR3) {
+ tmp = get_pi_todtoff_max(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 67), 0xff << 8, tmp << 8);
+ }
+ /* PI_72 PI_WR_TO_ODTH_F1:RW:24:6 */
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ tmp1 = get_pi_wrlat(pdram_timing, timing_config);
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3) {
+ tmp = 0;
+ }
+ mmio_clrsetbits_32(PI_REG(i, 72), 0x3f << 24, tmp << 24);
+ /* PI_73 PI_RD_TO_ODTH_F1:RW:16:6 */
+ if ((timing_config->dram_type == LPDDR3) ||
+ (timing_config->dram_type == LPDDR4)) {
+ /* min_rl_preamble = cl + TDQSCK_MIN - 1 */
+ tmp1 = pdram_timing->cl +
+ get_pi_todtoff_min(pdram_timing, timing_config);
+ tmp1--;
+ /* todtoff_max */
+ tmp2 = get_pi_todtoff_max(pdram_timing, timing_config);
+ if (tmp1 > tmp2)
+ tmp = tmp1 - tmp2;
+ else
+ tmp = 0;
+ } else if (timing_config->dram_type == DDR3)
+ tmp = pdram_timing->cl - pdram_timing->cwl;
+
+ mmio_clrsetbits_32(PI_REG(i, 73), 0x3f << 16, tmp << 16);
+ /*P I_89 PI_RDLAT_ADJ_F1:RW:24:8 */
+ tmp = get_pi_rdlat_adj(pdram_timing);
+ mmio_clrsetbits_32(PI_REG(i, 89), 0xffu << 24, tmp << 24);
+ /* PI_90 PI_WRLAT_ADJ_F1:RW:24:8 */
+ tmp = get_pi_wrlat_adj(pdram_timing, timing_config);
+ mmio_clrsetbits_32(PI_REG(i, 90), 0xffu << 24, tmp << 24);
+ /* PI_91 PI_TDFI_WRCSLAT_F1:RW:24:8 */
+ tmp1 = tmp;
+ if (tmp1 == 0)
+ tmp = 0;
+ else if (tmp1 < 5)
+ tmp = tmp1 - 1;
+ else
+ tmp = tmp1 - 5;
+ mmio_clrsetbits_32(PI_REG(i, 91), 0xffu << 24, tmp << 24);
+ /*PI_96 PI_TDFI_CALVL_CAPTURE_F1:RW:16:10 */
+ /* tadr=20ns */
+ tmp1 = 20000 / (1000000 / pdram_timing->mhz) + 1;
+ if ((20000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ tmp = (tmp1 >> 1) + (tmp1 % 2) + 5;
+ mmio_clrsetbits_32(PI_REG(i, 96), 0x3ff << 16, tmp << 16);
+ /* PI_96 PI_TDFI_CALVL_CC_F1:RW:0:10 */
+ tmp = tmp + 18;
+ mmio_clrsetbits_32(PI_REG(i, 96), 0x3ff, tmp);
+ /*PI_103 PI_TMRZ_F1:RW:0:5 */
+ mmio_clrsetbits_32(PI_REG(i, 103), 0x1f, pdram_timing->tmrz);
+ /*PI_111 PI_TDFI_CALVL_STROBE_F1:RW:16:4 */
+ /* tds_train=ceil(2/ns) */
+ tmp1 = 2 * 1000 / (1000000 / pdram_timing->mhz);
+ if ((2 * 1000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp1++;
+ /* pi_tdfi_calvl_strobe=tds_train+5 */
+ tmp = tmp1 + 5;
+ mmio_clrsetbits_32(PI_REG(i, 111), 0xf << 16,
+ tmp << 16);
+ /* PI_116 PI_TCKEHDQS_F1:RW:24:6 */
+ tmp = 10000 / (1000000 / pdram_timing->mhz);
+ if ((10000 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ if (pdram_timing->mhz <= 100)
+ tmp = tmp + 1;
+ else
+ tmp = tmp + 8;
+ mmio_clrsetbits_32(PI_REG(i, 116), 0x3f << 24,
+ tmp << 24);
+ /* PI_128 PI_MR1_DATA_F1_0:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 128), 0xffff, pdram_timing->mr[1]);
+ /* PI_135 PI_MR1_DATA_F1_1:RW+:8:16 */
+ mmio_clrsetbits_32(PI_REG(i, 135), 0xffff << 8,
+ pdram_timing->mr[1] << 8);
+ /* PI_143 PI_MR1_DATA_F1_2:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 143), 0xffff, pdram_timing->mr[1]);
+ /* PI_150 PI_MR1_DATA_F1_3:RW+:8:16 */
+ mmio_clrsetbits_32(PI_REG(i, 150), 0xffff << 8,
+ pdram_timing->mr[1] << 8);
+ /* PI_128 PI_MR2_DATA_F1_0:RW+:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 128), 0xffffu << 16,
+ pdram_timing->mr[2] << 16);
+ /* PI_136 PI_MR2_DATA_F1_1:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 136), 0xffff, pdram_timing->mr[2]);
+ /* PI_143 PI_MR2_DATA_F1_2:RW+:16:16 */
+ mmio_clrsetbits_32(PI_REG(i, 143), 0xffffu << 16,
+ pdram_timing->mr[2] << 16);
+ /* PI_151 PI_MR2_DATA_F1_3:RW+:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 151), 0xffff, pdram_timing->mr[2]);
+ /* PI_156 PI_TFC_F1:RW:16:10 */
+ mmio_clrsetbits_32(PI_REG(i, 156), 0x3ff << 16,
+ pdram_timing->tfc_long << 16);
+ /* PI_162 PI_TWR_F1:RW:8:6 */
+ mmio_clrsetbits_32(PI_REG(i, 162), 0x3f << 8,
+ pdram_timing->twr << 8);
+ /* PI_162 PI_TWTR_F1:RW:0:6 */
+ mmio_clrsetbits_32(PI_REG(i, 162), 0x3f, pdram_timing->twtr);
+ /* PI_161 PI_TRCD_F1:RW:24:8 */
+ mmio_clrsetbits_32(PI_REG(i, 161), 0xffu << 24,
+ pdram_timing->trcd << 24);
+ /* PI_161 PI_TRP_F1:RW:16:8 */
+ mmio_clrsetbits_32(PI_REG(i, 161), 0xff << 16,
+ pdram_timing->trp << 16);
+ /* PI_161 PI_TRTP_F1:RW:8:8 */
+ mmio_clrsetbits_32(PI_REG(i, 161), 0xff << 8,
+ pdram_timing->trtp << 8);
+ /* PI_163 PI_TRAS_MIN_F1:RW:24:8 */
+ mmio_clrsetbits_32(PI_REG(i, 163), 0xffu << 24,
+ pdram_timing->tras_min << 24);
+ /* PI_163 PI_TRAS_MAX_F1:RW:0:17 */
+ mmio_clrsetbits_32(PI_REG(i, 163), 0x1ffff,
+ pdram_timing->tras_max * 99 / 100);
+ /* PI_164 PI_TMRD_F1:RW:16:6 */
+ mmio_clrsetbits_32(PI_REG(i, 164), 0x3f << 16,
+ pdram_timing->tmrd << 16);
+ /* PI_164 PI_TDQSCK_MAX_F1:RW:0:4 */
+ mmio_clrsetbits_32(PI_REG(i, 164), 0xf,
+ pdram_timing->tdqsck_max);
+ /* PI_189 PI_TDFI_CTRLUPD_MAX_F1:RW:0:16 */
+ mmio_clrsetbits_32(PI_REG(i, 189), 0xffff,
+ 2 * pdram_timing->trefi);
+ /* PI_190 PI_TDFI_CTRLUPD_INTERVAL_F1:RW:0:32 */
+ mmio_clrsetbits_32(PI_REG(i, 190), 0xffffffff,
+ 20 * pdram_timing->trefi);
+ }
+}
+
+static void gen_rk3399_pi_params(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing,
+ uint32_t fn)
+{
+ if (fn == 0)
+ gen_rk3399_pi_params_f0(timing_config, pdram_timing);
+ else
+ gen_rk3399_pi_params_f1(timing_config, pdram_timing);
+}
+
+static void gen_rk3399_set_odt(uint32_t odt_en)
+{
+ uint32_t drv_odt_val;
+ uint32_t i;
+
+ for (i = 0; i < rk3399_dram_status.timing_config.ch_cnt; i++) {
+ drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 16;
+ mmio_clrsetbits_32(PHY_REG(i, 5), 0x7 << 16, drv_odt_val);
+ mmio_clrsetbits_32(PHY_REG(i, 133), 0x7 << 16, drv_odt_val);
+ mmio_clrsetbits_32(PHY_REG(i, 261), 0x7 << 16, drv_odt_val);
+ mmio_clrsetbits_32(PHY_REG(i, 389), 0x7 << 16, drv_odt_val);
+ drv_odt_val = (odt_en | (0 << 1) | (0 << 2)) << 24;
+ mmio_clrsetbits_32(PHY_REG(i, 6), 0x7 << 24, drv_odt_val);
+ mmio_clrsetbits_32(PHY_REG(i, 134), 0x7 << 24, drv_odt_val);
+ mmio_clrsetbits_32(PHY_REG(i, 262), 0x7 << 24, drv_odt_val);
+ mmio_clrsetbits_32(PHY_REG(i, 390), 0x7 << 24, drv_odt_val);
+ }
+}
+
+static void gen_rk3399_phy_dll_bypass(uint32_t mhz, uint32_t ch,
+ uint32_t index, uint32_t dram_type)
+{
+ uint32_t sw_master_mode = 0;
+ uint32_t rddqs_gate_delay, rddqs_latency, total_delay;
+ uint32_t i;
+
+ if (dram_type == DDR3)
+ total_delay = PI_PAD_DELAY_PS_VALUE;
+ else if (dram_type == LPDDR3)
+ total_delay = PI_PAD_DELAY_PS_VALUE + 2500;
+ else
+ total_delay = PI_PAD_DELAY_PS_VALUE + 1500;
+ /* total_delay + 0.55tck */
+ total_delay += (55 * 10000)/mhz;
+ rddqs_latency = total_delay * mhz / 1000000;
+ total_delay -= rddqs_latency * 1000000 / mhz;
+ rddqs_gate_delay = total_delay * 0x200 * mhz / 1000000;
+ if (mhz <= PHY_DLL_BYPASS_FREQ) {
+ sw_master_mode = 0xc;
+ mmio_setbits_32(PHY_REG(ch, 514), 1);
+ mmio_setbits_32(PHY_REG(ch, 642), 1);
+ mmio_setbits_32(PHY_REG(ch, 770), 1);
+
+ /* setting bypass mode slave delay */
+ for (i = 0; i < 4; i++) {
+ /* wr dq delay = -180deg + (0x60 / 4) * 20ps */
+ mmio_clrsetbits_32(PHY_REG(ch, 1 + 128 * i), 0x7ff << 8,
+ 0x4a0 << 8);
+ /* rd dqs/dq delay = (0x60 / 4) * 20ps */
+ mmio_clrsetbits_32(PHY_REG(ch, 11 + 128 * i), 0x3ff,
+ 0xa0);
+ /* rd rddqs_gate delay */
+ mmio_clrsetbits_32(PHY_REG(ch, 2 + 128 * i), 0x3ff,
+ rddqs_gate_delay);
+ mmio_clrsetbits_32(PHY_REG(ch, 78 + 128 * i), 0xf,
+ rddqs_latency);
+ }
+ for (i = 0; i < 3; i++)
+ /* adr delay */
+ mmio_clrsetbits_32(PHY_REG(ch, 513 + 128 * i),
+ 0x7ff << 16, 0x80 << 16);
+
+ if ((mmio_read_32(PHY_REG(ch, 86)) & 0xc00) == 0) {
+ /*
+ * old status is normal mode,
+ * and saving the wrdqs slave delay
+ */
+ for (i = 0; i < 4; i++) {
+ /* save and clear wr dqs slave delay */
+ wrdqs_delay_val[ch][index][i] = 0x3ff &
+ (mmio_read_32(PHY_REG(ch, 63 + i * 128))
+ >> 16);
+ mmio_clrsetbits_32(PHY_REG(ch, 63 + i * 128),
+ 0x03ff << 16, 0 << 16);
+ /*
+ * in normal mode the cmd may delay 1cycle by
+ * wrlvl and in bypass mode making dqs also
+ * delay 1cycle.
+ */
+ mmio_clrsetbits_32(PHY_REG(ch, 78 + i * 128),
+ 0x07 << 8, 0x1 << 8);
+ }
+ }
+ } else if (mmio_read_32(PHY_REG(ch, 86)) & 0xc00) {
+ /* old status is bypass mode and restore wrlvl resume */
+ for (i = 0; i < 4; i++) {
+ mmio_clrsetbits_32(PHY_REG(ch, 63 + i * 128),
+ 0x03ff << 16,
+ (wrdqs_delay_val[ch][index][i] &
+ 0x3ff) << 16);
+ /* resume phy_write_path_lat_add */
+ mmio_clrbits_32(PHY_REG(ch, 78 + i * 128), 0x07 << 8);
+ }
+ }
+
+ /* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
+ mmio_clrsetbits_32(PHY_REG(ch, 86), 0xf << 8, sw_master_mode << 8);
+ mmio_clrsetbits_32(PHY_REG(ch, 214), 0xf << 8, sw_master_mode << 8);
+ mmio_clrsetbits_32(PHY_REG(ch, 342), 0xf << 8, sw_master_mode << 8);
+ mmio_clrsetbits_32(PHY_REG(ch, 470), 0xf << 8, sw_master_mode << 8);
+
+ /* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
+ mmio_clrsetbits_32(PHY_REG(ch, 547), 0xf << 16, sw_master_mode << 16);
+ mmio_clrsetbits_32(PHY_REG(ch, 675), 0xf << 16, sw_master_mode << 16);
+ mmio_clrsetbits_32(PHY_REG(ch, 803), 0xf << 16, sw_master_mode << 16);
+}
+
+static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
+ struct drv_odt_lp_config *drv_config,
+ struct dram_timing_t *pdram_timing,
+ uint32_t fn)
+{
+ uint32_t tmp, i, div, j;
+ uint32_t mem_delay_ps, pad_delay_ps, total_delay_ps, delay_frac_ps;
+ uint32_t trpre_min_ps, gate_delay_ps, gate_delay_frac_ps;
+ uint32_t ie_enable, tsel_enable, cas_lat, rddata_en_ie_dly, tsel_adder;
+ uint32_t extra_adder, delta, hs_offset;
+
+ for (i = 0; i < timing_config->ch_cnt; i++) {
+
+ pad_delay_ps = PI_PAD_DELAY_PS_VALUE;
+ ie_enable = PI_IE_ENABLE_VALUE;
+ tsel_enable = PI_TSEL_ENABLE_VALUE;
+
+ mmio_clrsetbits_32(PHY_REG(i, 896), (0x3 << 8) | 1, fn << 8);
+
+ /* PHY_LOW_FREQ_SEL */
+ /* DENALI_PHY_913 1bit offset_0 */
+ if (timing_config->freq > 400)
+ mmio_clrbits_32(PHY_REG(i, 913), 1);
+ else
+ mmio_setbits_32(PHY_REG(i, 913), 1);
+
+ /* PHY_RPTR_UPDATE_x */
+ /* DENALI_PHY_87/215/343/471 4bit offset_16 */
+ tmp = 2500 / (1000000 / pdram_timing->mhz) + 3;
+ if ((2500 % (1000000 / pdram_timing->mhz)) != 0)
+ tmp++;
+ mmio_clrsetbits_32(PHY_REG(i, 87), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 215), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 343), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 471), 0xf << 16, tmp << 16);
+
+ /* PHY_PLL_CTRL */
+ /* DENALI_PHY_911 13bits offset_0 */
+ /* PHY_LP4_BOOT_PLL_CTRL */
+ /* DENALI_PHY_919 13bits offset_0 */
+ tmp = (1 << 12) | (2 << 7) | (1 << 1);
+ mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff, tmp);
+ mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff, tmp);
+
+ /* PHY_PLL_CTRL_CA */
+ /* DENALI_PHY_911 13bits offset_16 */
+ /* PHY_LP4_BOOT_PLL_CTRL_CA */
+ /* DENALI_PHY_919 13bits offset_16 */
+ tmp = (2 << 7) | (1 << 5) | (1 << 1);
+ mmio_clrsetbits_32(PHY_REG(i, 911), 0x1fff << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 919), 0x1fff << 16, tmp << 16);
+
+ /* PHY_TCKSRE_WAIT */
+ /* DENALI_PHY_922 4bits offset_24 */
+ if (pdram_timing->mhz <= 400)
+ tmp = 1;
+ else if (pdram_timing->mhz <= 800)
+ tmp = 3;
+ else if (pdram_timing->mhz <= 1000)
+ tmp = 4;
+ else
+ tmp = 5;
+ mmio_clrsetbits_32(PHY_REG(i, 922), 0xf << 24, tmp << 24);
+ /* PHY_CAL_CLK_SELECT_0:RW8:3 */
+ div = pdram_timing->mhz / (2 * 20);
+ for (j = 2, tmp = 1; j <= 128; j <<= 1, tmp++) {
+ if (div < j)
+ break;
+ }
+ mmio_clrsetbits_32(PHY_REG(i, 947), 0x7 << 8, tmp << 8);
+
+ if (timing_config->dram_type == DDR3) {
+ mem_delay_ps = 0;
+ trpre_min_ps = 1000;
+ } else if (timing_config->dram_type == LPDDR4) {
+ mem_delay_ps = 1500;
+ trpre_min_ps = 900;
+ } else if (timing_config->dram_type == LPDDR3) {
+ mem_delay_ps = 2500;
+ trpre_min_ps = 900;
+ } else {
+ ERROR("gen_rk3399_phy_params:dramtype unsupport\n");
+ return;
+ }
+ total_delay_ps = mem_delay_ps + pad_delay_ps;
+ delay_frac_ps = 1000 * total_delay_ps /
+ (1000000 / pdram_timing->mhz);
+ gate_delay_ps = delay_frac_ps + 1000 - (trpre_min_ps / 2);
+ gate_delay_frac_ps = gate_delay_ps % 1000;
+ tmp = gate_delay_frac_ps * 0x200 / 1000;
+ /* PHY_RDDQS_GATE_SLAVE_DELAY */
+ /* DENALI_PHY_77/205/333/461 10bits offset_16 */
+ mmio_clrsetbits_32(PHY_REG(i, 77), 0x2ff << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 205), 0x2ff << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 333), 0x2ff << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 461), 0x2ff << 16, tmp << 16);
+
+ tmp = gate_delay_ps / 1000;
+ /* PHY_LP4_BOOT_RDDQS_LATENCY_ADJUST */
+ /* DENALI_PHY_10/138/266/394 4bit offset_0 */
+ mmio_clrsetbits_32(PHY_REG(i, 10), 0xf, tmp);
+ mmio_clrsetbits_32(PHY_REG(i, 138), 0xf, tmp);
+ mmio_clrsetbits_32(PHY_REG(i, 266), 0xf, tmp);
+ mmio_clrsetbits_32(PHY_REG(i, 394), 0xf, tmp);
+ /* PHY_GTLVL_LAT_ADJ_START */
+ /* DENALI_PHY_80/208/336/464 4bits offset_16 */
+ tmp = rddqs_delay_ps / (1000000 / pdram_timing->mhz) + 2;
+ mmio_clrsetbits_32(PHY_REG(i, 80), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 208), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 336), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 464), 0xf << 16, tmp << 16);
+
+ cas_lat = pdram_timing->cl + PI_ADD_LATENCY;
+ rddata_en_ie_dly = ie_enable / (1000000 / pdram_timing->mhz);
+ if ((ie_enable % (1000000 / pdram_timing->mhz)) != 0)
+ rddata_en_ie_dly++;
+ rddata_en_ie_dly = rddata_en_ie_dly - 1;
+ tsel_adder = tsel_enable / (1000000 / pdram_timing->mhz);
+ if ((tsel_enable % (1000000 / pdram_timing->mhz)) != 0)
+ tsel_adder++;
+ if (rddata_en_ie_dly > tsel_adder)
+ extra_adder = rddata_en_ie_dly - tsel_adder;
+ else
+ extra_adder = 0;
+ delta = cas_lat - rddata_en_ie_dly;
+ if (PI_REGS_DIMM_SUPPORT && PI_DOUBLEFREEK)
+ hs_offset = 2;
+ else
+ hs_offset = 1;
+ if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset))
+ tmp = 0;
+ else if ((delta == 2) || (delta == 1))
+ tmp = rddata_en_ie_dly - 0 - extra_adder;
+ else
+ tmp = extra_adder;
+ /* PHY_LP4_BOOT_RDDATA_EN_TSEL_DLY */
+ /* DENALI_PHY_9/137/265/393 4bit offset_16 */
+ mmio_clrsetbits_32(PHY_REG(i, 9), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 137), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 265), 0xf << 16, tmp << 16);
+ mmio_clrsetbits_32(PHY_REG(i, 393), 0xf << 16, tmp << 16);
+ /* PHY_RDDATA_EN_TSEL_DLY */
+ /* DENALI_PHY_86/214/342/470 4bit offset_0 */
+ mmio_clrsetbits_32(PHY_REG(i, 86), 0xf, tmp);
+ mmio_clrsetbits_32(PHY_REG(i, 214), 0xf, tmp);
+ mmio_clrsetbits_32(PHY_REG(i, 342), 0xf, tmp);
+ mmio_clrsetbits_32(PHY_REG(i, 470), 0xf, tmp);
+
+ if (tsel_adder > rddata_en_ie_dly)
+ extra_adder = tsel_adder - rddata_en_ie_dly;
+ else
+ extra_adder = 0;
+ if (rddata_en_ie_dly > (cas_lat - 1 - hs_offset))
+ tmp = tsel_adder;
+ else
+ tmp = rddata_en_ie_dly - 0 + extra_adder;
+ /* PHY_LP4_BOOT_RDDATA_EN_DLY */
+ /* DENALI_PHY_9/137/265/393 4bit offset_8 */
+ mmio_clrsetbits_32(PHY_REG(i, 9), 0xf << 8, tmp << 8);
+ mmio_clrsetbits_32(PHY_REG(i, 137), 0xf << 8, tmp << 8);
+ mmio_clrsetbits_32(PHY_REG(i, 265), 0xf << 8, tmp << 8);
+ mmio_clrsetbits_32(PHY_REG(i, 393), 0xf << 8, tmp << 8);
+ /* PHY_RDDATA_EN_DLY */
+ /* DENALI_PHY_85/213/341/469 4bit offset_24 */
+ mmio_clrsetbits_32(PHY_REG(i, 85), 0xf << 24, tmp << 24);
+ mmio_clrsetbits_32(PHY_REG(i, 213), 0xf << 24, tmp << 24);
+ mmio_clrsetbits_32(PHY_REG(i, 341), 0xf << 24, tmp << 24);
+ mmio_clrsetbits_32(PHY_REG(i, 469), 0xf << 24, tmp << 24);
+
+ if (pdram_timing->mhz <= ENPER_CS_TRAINING_FREQ) {
+ /*
+ * Note:Per-CS Training is not compatible at speeds
+ * under 533 MHz. If the PHY is running at a speed
+ * less than 533MHz, all phy_per_cs_training_en_X
+ * parameters must be cleared to 0.
+ */
+
+ /*DENALI_PHY_84/212/340/468 1bit offset_16 */
+ mmio_clrbits_32(PHY_REG(i, 84), 0x1 << 16);
+ mmio_clrbits_32(PHY_REG(i, 212), 0x1 << 16);
+ mmio_clrbits_32(PHY_REG(i, 340), 0x1 << 16);
+ mmio_clrbits_32(PHY_REG(i, 468), 0x1 << 16);
+ } else {
+ mmio_setbits_32(PHY_REG(i, 84), 0x1 << 16);
+ mmio_setbits_32(PHY_REG(i, 212), 0x1 << 16);
+ mmio_setbits_32(PHY_REG(i, 340), 0x1 << 16);
+ mmio_setbits_32(PHY_REG(i, 468), 0x1 << 16);
+ }
+ gen_rk3399_phy_dll_bypass(pdram_timing->mhz, i, fn,
+ timing_config->dram_type);
+ }
+}
+
+static int to_get_clk_index(unsigned int mhz)
+{
+ int pll_cnt, i;
+
+ pll_cnt = ARRAY_SIZE(dpll_rates_table);
+
+ /* Assumming rate_table is in descending order */
+ for (i = 0; i < pll_cnt; i++) {
+ if (mhz >= dpll_rates_table[i].mhz)
+ break;
+ }
+
+ /* if mhz lower than lowest frequency in table, use lowest frequency */
+ if (i == pll_cnt)
+ i = pll_cnt - 1;
+
+ return i;
+}
+
+uint32_t ddr_get_rate(void)
+{
+ uint32_t refdiv, postdiv1, fbdiv, postdiv2;
+
+ refdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) & 0x3f;
+ fbdiv = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 0)) & 0xfff;
+ postdiv1 =
+ (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 8) & 0x7;
+ postdiv2 =
+ (mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, 1)) >> 12) & 0x7;
+
+ return (24 / refdiv * fbdiv / postdiv1 / postdiv2) * 1000 * 1000;
+}
+
+/*
+ * return: bit12: channel 1, external self-refresh
+ * bit11: channel 1, stdby_mode
+ * bit10: channel 1, self-refresh with controller and memory clock gate
+ * bit9: channel 1, self-refresh
+ * bit8: channel 1, power-down
+ *
+ * bit4: channel 1, external self-refresh
+ * bit3: channel 0, stdby_mode
+ * bit2: channel 0, self-refresh with controller and memory clock gate
+ * bit1: channel 0, self-refresh
+ * bit0: channel 0, power-down
+ */
+uint32_t exit_low_power(void)
+{
+ uint32_t low_power = 0;
+ uint32_t channel_mask;
+ uint32_t tmp, i;
+
+ channel_mask = (mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) &
+ 0x3;
+ for (i = 0; i < 2; i++) {
+ if (!(channel_mask & (1 << i)))
+ continue;
+
+ /* exit stdby mode */
+ mmio_write_32(CIC_BASE + CIC_CTRL1,
+ (1 << (i + 16)) | (0 << i));
+ /* exit external self-refresh */
+ tmp = i ? 12 : 8;
+ low_power |= ((mmio_read_32(PMU_BASE + PMU_SFT_CON) >> tmp) &
+ 0x1) << (4 + 8 * i);
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 1 << tmp);
+ while (!(mmio_read_32(PMU_BASE + PMU_DDR_SREF_ST) & (1 << i)))
+ ;
+ /* exit auto low-power */
+ mmio_clrbits_32(CTL_REG(i, 101), 0x7);
+ /* lp_cmd to exit */
+ if (((mmio_read_32(CTL_REG(i, 100)) >> 24) & 0x7f) !=
+ 0x40) {
+ while (mmio_read_32(CTL_REG(i, 200)) & 0x1)
+ ;
+ mmio_clrsetbits_32(CTL_REG(i, 93), 0xffu << 24,
+ 0x69 << 24);
+ while (((mmio_read_32(CTL_REG(i, 100)) >> 24) & 0x7f) !=
+ 0x40)
+ ;
+ }
+ }
+ return low_power;
+}
+
+void resume_low_power(uint32_t low_power)
+{
+ uint32_t channel_mask;
+ uint32_t tmp, i, val;
+
+ channel_mask = (mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2)) >> 28) &
+ 0x3;
+ for (i = 0; i < 2; i++) {
+ if (!(channel_mask & (1 << i)))
+ continue;
+
+ /* resume external self-refresh */
+ tmp = i ? 12 : 8;
+ val = (low_power >> (4 + 8 * i)) & 0x1;
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, val << tmp);
+ /* resume auto low-power */
+ val = (low_power >> (8 * i)) & 0x7;
+ mmio_setbits_32(CTL_REG(i, 101), val);
+ /* resume stdby mode */
+ val = (low_power >> (3 + 8 * i)) & 0x1;
+ mmio_write_32(CIC_BASE + CIC_CTRL1,
+ (1 << (i + 16)) | (val << i));
+ }
+}
+
+static void dram_low_power_config(void)
+{
+ uint32_t tmp, i;
+ uint32_t ch_cnt = rk3399_dram_status.timing_config.ch_cnt;
+ uint32_t dram_type = rk3399_dram_status.timing_config.dram_type;
+
+ if (dram_type == DDR3)
+ tmp = (2 << 16) | (0x7 << 8);
+ else
+ tmp = (3 << 16) | (0x7 << 8);
+
+ for (i = 0; i < ch_cnt; i++)
+ mmio_clrsetbits_32(CTL_REG(i, 101), 0x70f0f, tmp);
+
+ /* standby idle */
+ mmio_write_32(CIC_BASE + CIC_CG_WAIT_TH, 0x640008);
+
+ if (ch_cnt == 2) {
+ mmio_write_32(GRF_BASE + GRF_DDRC1_CON1,
+ (((0x1<<4) | (0x1<<5) | (0x1<<6) |
+ (0x1<<7)) << 16) |
+ ((0x1<<4) | (0x0<<5) | (0x1<<6) | (0x1<<7)));
+ mmio_write_32(CIC_BASE + CIC_CTRL1, 0x002a0028);
+ }
+
+ mmio_write_32(GRF_BASE + GRF_DDRC0_CON1,
+ (((0x1<<4) | (0x1<<5) | (0x1<<6) | (0x1<<7)) << 16) |
+ ((0x1<<4) | (0x0<<5) | (0x1<<6) | (0x1<<7)));
+ mmio_write_32(CIC_BASE + CIC_CTRL1, 0x00150014);
+}
+
+void dram_dfs_init(void)
+{
+ uint32_t trefi0, trefi1, boot_freq;
+ uint32_t rddqs_adjust, rddqs_slave;
+
+ /* get sdram config for os reg */
+ get_dram_drv_odt_val(sdram_config.dramtype,
+ &rk3399_dram_status.drv_odt_lp_cfg);
+ sdram_timing_cfg_init(&rk3399_dram_status.timing_config,
+ &sdram_config,
+ &rk3399_dram_status.drv_odt_lp_cfg);
+
+ trefi0 = ((mmio_read_32(CTL_REG(0, 48)) >> 16) & 0xffff) + 8;
+ trefi1 = ((mmio_read_32(CTL_REG(0, 49)) >> 16) & 0xffff) + 8;
+
+ rk3399_dram_status.index_freq[0] = trefi0 * 10 / 39;
+ rk3399_dram_status.index_freq[1] = trefi1 * 10 / 39;
+ rk3399_dram_status.current_index =
+ (mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3;
+ if (rk3399_dram_status.timing_config.dram_type == DDR3) {
+ rk3399_dram_status.index_freq[0] /= 2;
+ rk3399_dram_status.index_freq[1] /= 2;
+ }
+ boot_freq =
+ rk3399_dram_status.index_freq[rk3399_dram_status.current_index];
+ boot_freq = dpll_rates_table[to_get_clk_index(boot_freq)].mhz;
+ rk3399_dram_status.boot_freq = boot_freq;
+ rk3399_dram_status.index_freq[rk3399_dram_status.current_index] =
+ boot_freq;
+ rk3399_dram_status.index_freq[(rk3399_dram_status.current_index + 1) &
+ 0x1] = 0;
+ rk3399_dram_status.low_power_stat = 0;
+ /*
+ * following register decide if NOC stall the access request
+ * or return error when NOC being idled. when doing ddr frequency
+ * scaling in M0 or DCF, we need to make sure noc stall the access
+ * request, if return error cpu may data abort when ddr frequency
+ * changing. it don't need to set this register every times,
+ * so we init this register in function dram_dfs_init().
+ */
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(0), 0xffffffff);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(1), 0xffffffff);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(2), 0xffffffff);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 0xffffffff);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 0x70007000);
+
+ /* Disable multicast */
+ mmio_clrbits_32(PHY_REG(0, 896), 1);
+ mmio_clrbits_32(PHY_REG(1, 896), 1);
+ dram_low_power_config();
+
+ /*
+ * If boot_freq isn't in the bypass mode, it can get the
+ * rddqs_delay_ps from the result of gate training
+ */
+ if (((mmio_read_32(PHY_REG(0, 86)) >> 8) & 0xf) != 0xc) {
+
+ /*
+ * Select PHY's frequency set to current_index
+ * index for get the result of gate Training
+ * from registers
+ */
+ mmio_clrsetbits_32(PHY_REG(0, 896), 0x3 << 8,
+ rk3399_dram_status.current_index << 8);
+ rddqs_slave = (mmio_read_32(PHY_REG(0, 77)) >> 16) & 0x3ff;
+ rddqs_slave = rddqs_slave * 1000000 / boot_freq / 512;
+
+ rddqs_adjust = mmio_read_32(PHY_REG(0, 78)) & 0xf;
+ rddqs_adjust = rddqs_adjust * 1000000 / boot_freq;
+ rddqs_delay_ps = rddqs_slave + rddqs_adjust -
+ (1000000 / boot_freq / 2);
+ } else {
+ rddqs_delay_ps = 3500;
+ }
+}
+
+/*
+ * arg0: bit0-7: sr_idle; bit8-15:sr_mc_gate_idle; bit16-31: standby idle
+ * arg1: bit0-11: pd_idle; bit 16-27: srpd_lite_idle
+ * arg2: bit0: if odt en
+ */
+uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2)
+{
+ struct drv_odt_lp_config *lp_cfg = &rk3399_dram_status.drv_odt_lp_cfg;
+ uint32_t *low_power = &rk3399_dram_status.low_power_stat;
+ uint32_t dram_type, ch_count, pd_tmp, sr_tmp, i;
+
+ dram_type = rk3399_dram_status.timing_config.dram_type;
+ ch_count = rk3399_dram_status.timing_config.ch_cnt;
+
+ lp_cfg->sr_idle = arg0 & 0xff;
+ lp_cfg->sr_mc_gate_idle = (arg0 >> 8) & 0xff;
+ lp_cfg->standby_idle = (arg0 >> 16) & 0xffff;
+ lp_cfg->pd_idle = arg1 & 0xfff;
+ lp_cfg->srpd_lite_idle = (arg1 >> 16) & 0xfff;
+
+ rk3399_dram_status.timing_config.odt = arg2 & 0x1;
+
+ exit_low_power();
+
+ *low_power = 0;
+
+ /* pd_idle en */
+ if (lp_cfg->pd_idle)
+ *low_power |= ((1 << 0) | (1 << 8));
+ /* sr_idle en srpd_lite_idle */
+ if (lp_cfg->sr_idle | lp_cfg->srpd_lite_idle)
+ *low_power |= ((1 << 1) | (1 << 9));
+ /* sr_mc_gate_idle */
+ if (lp_cfg->sr_mc_gate_idle)
+ *low_power |= ((1 << 2) | (1 << 10));
+ /* standbyidle */
+ if (lp_cfg->standby_idle) {
+ if (rk3399_dram_status.timing_config.ch_cnt == 2)
+ *low_power |= ((1 << 3) | (1 << 11));
+ else
+ *low_power |= (1 << 3);
+ }
+
+ pd_tmp = arg1;
+ if (dram_type != LPDDR4)
+ pd_tmp = arg1 & 0xfff;
+ sr_tmp = arg0 & 0xffff;
+ for (i = 0; i < ch_count; i++) {
+ mmio_write_32(CTL_REG(i, 102), pd_tmp);
+ mmio_clrsetbits_32(CTL_REG(i, 103), 0xffff, sr_tmp);
+ }
+ mmio_write_32(CIC_BASE + CIC_IDLE_TH, (arg0 >> 16) & 0xffff);
+
+ return 0;
+}
+
+static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index)
+{
+ mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv));
+ mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1,
+ POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) |
+ REFDIV(pll_div.refdiv));
+
+ mmio_write_32(M0_PARAM_ADDR + PARAM_DRAM_FREQ, pll_div.mhz);
+
+ mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4);
+ dmbst();
+ m0_configure_execute_addr(M0_BINCODE_BASE);
+}
+
+static uint32_t prepare_ddr_timing(uint32_t mhz)
+{
+ uint32_t index;
+ struct dram_timing_t dram_timing;
+
+ rk3399_dram_status.timing_config.freq = mhz;
+
+ if (mhz < 300)
+ rk3399_dram_status.timing_config.dllbp = 1;
+ else
+ rk3399_dram_status.timing_config.dllbp = 0;
+
+ if (rk3399_dram_status.timing_config.odt == 1)
+ gen_rk3399_set_odt(1);
+
+ index = (rk3399_dram_status.current_index + 1) & 0x1;
+
+ /*
+ * checking if having available gate traiing timing for
+ * target freq.
+ */
+ dram_get_parameter(&rk3399_dram_status.timing_config, &dram_timing);
+ gen_rk3399_ctl_params(&rk3399_dram_status.timing_config,
+ &dram_timing, index);
+ gen_rk3399_pi_params(&rk3399_dram_status.timing_config,
+ &dram_timing, index);
+ gen_rk3399_phy_params(&rk3399_dram_status.timing_config,
+ &rk3399_dram_status.drv_odt_lp_cfg,
+ &dram_timing, index);
+ rk3399_dram_status.index_freq[index] = mhz;
+
+ return index;
+}
+
+uint32_t ddr_set_rate(uint32_t hz)
+{
+ uint32_t low_power, index, ddr_index;
+ uint32_t mhz = hz / (1000 * 1000);
+
+ if (mhz ==
+ rk3399_dram_status.index_freq[rk3399_dram_status.current_index])
+ return mhz;
+
+ index = to_get_clk_index(mhz);
+ mhz = dpll_rates_table[index].mhz;
+
+ ddr_index = prepare_ddr_timing(mhz);
+ gen_rk3399_enable_training(rk3399_dram_status.timing_config.ch_cnt,
+ mhz);
+ if (ddr_index > 1)
+ goto out;
+
+ /*
+ * Make sure the clock is enabled. The M0 clocks should be on all of the
+ * time during S0.
+ */
+ m0_configure_ddr(dpll_rates_table[index], ddr_index);
+ m0_start();
+ m0_wait_done();
+ m0_stop();
+
+ if (rk3399_dram_status.timing_config.odt == 0)
+ gen_rk3399_set_odt(0);
+
+ rk3399_dram_status.current_index = ddr_index;
+ low_power = rk3399_dram_status.low_power_stat;
+ resume_low_power(low_power);
+out:
+ gen_rk3399_disable_training(rk3399_dram_status.timing_config.ch_cnt);
+ return mhz;
+}
+
+uint32_t ddr_round_rate(uint32_t hz)
+{
+ int index;
+ uint32_t mhz = hz / (1000 * 1000);
+
+ index = to_get_clk_index(mhz);
+
+ return dpll_rates_table[index].mhz * 1000 * 1000;
+}
+
+void ddr_prepare_for_sys_suspend(void)
+{
+ uint32_t mhz =
+ rk3399_dram_status.index_freq[rk3399_dram_status.current_index];
+
+ /*
+ * If we're not currently at the boot (assumed highest) frequency, we
+ * need to change frequencies to configure out current index.
+ */
+ rk3399_suspend_status.freq = mhz;
+ exit_low_power();
+ rk3399_suspend_status.low_power_stat =
+ rk3399_dram_status.low_power_stat;
+ rk3399_suspend_status.odt = rk3399_dram_status.timing_config.odt;
+ rk3399_dram_status.low_power_stat = 0;
+ rk3399_dram_status.timing_config.odt = 1;
+ if (mhz != rk3399_dram_status.boot_freq)
+ ddr_set_rate(rk3399_dram_status.boot_freq * 1000 * 1000);
+
+ /*
+ * This will configure the other index to be the same frequency as the
+ * current one. We retrain both indices on resume, so both have to be
+ * setup for the same frequency.
+ */
+ prepare_ddr_timing(rk3399_dram_status.boot_freq);
+}
+
+void ddr_prepare_for_sys_resume(void)
+{
+ /* Disable multicast */
+ mmio_clrbits_32(PHY_REG(0, 896), 1);
+ mmio_clrbits_32(PHY_REG(1, 896), 1);
+
+ /* The suspend code changes the current index, so reset it now. */
+ rk3399_dram_status.current_index =
+ (mmio_read_32(CTL_REG(0, 111)) >> 16) & 0x3;
+ rk3399_dram_status.low_power_stat =
+ rk3399_suspend_status.low_power_stat;
+ rk3399_dram_status.timing_config.odt = rk3399_suspend_status.odt;
+
+ /*
+ * Set the saved frequency from suspend if it's different than the
+ * current frequency.
+ */
+ if (rk3399_suspend_status.freq !=
+ rk3399_dram_status.index_freq[rk3399_dram_status.current_index]) {
+ ddr_set_rate(rk3399_suspend_status.freq * 1000 * 1000);
+ return;
+ }
+
+ gen_rk3399_set_odt(rk3399_dram_status.timing_config.odt);
+ resume_low_power(rk3399_dram_status.low_power_stat);
+}
diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.h b/plat/rockchip/rk3399/drivers/dram/dfs.h
new file mode 100644
index 0000000..172b2a7
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/dfs.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DFS_H
+#define DFS_H
+
+#include <stdint.h>
+
+struct rk3399_sdram_default_config {
+ unsigned char bl;
+ /* 1:auto precharge, 0:never auto precharge */
+ unsigned char ap;
+ /* dram driver strength */
+ unsigned char dramds;
+ /* dram ODT, if odt=0, this parameter invalid */
+ unsigned char dramodt;
+ /* ca ODT, if odt=0, this parameter invalid
+ * only used by LPDDR4
+ */
+ unsigned char caodt;
+ unsigned char burst_ref_cnt;
+ /* zqcs period, unit(s) */
+ unsigned char zqcsi;
+};
+
+struct drv_odt_lp_config {
+ uint32_t pd_idle;
+ uint32_t sr_idle;
+ uint32_t sr_mc_gate_idle;
+ uint32_t srpd_lite_idle;
+ uint32_t standby_idle;
+ uint32_t odt_en;
+
+ uint32_t dram_side_drv;
+ uint32_t dram_side_dq_odt;
+ uint32_t dram_side_ca_odt;
+};
+
+uint32_t ddr_set_rate(uint32_t hz);
+uint32_t ddr_round_rate(uint32_t hz);
+uint32_t ddr_get_rate(void);
+uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2);
+void dram_dfs_init(void);
+void ddr_prepare_for_sys_suspend(void);
+void ddr_prepare_for_sys_resume(void);
+
+#endif /* DFS_H */
diff --git a/plat/rockchip/rk3399/drivers/dram/dram.c b/plat/rockchip/rk3399/drivers/dram/dram.c
new file mode 100644
index 0000000..42b6294
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/dram.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dram.h>
+#include <plat_private.h>
+#include <rk3399_def.h>
+#include <secure.h>
+#include <soc.h>
+
+__pmusramdata struct rk3399_sdram_params sdram_config;
+
+void dram_init(void)
+{
+ uint32_t os_reg2_val, i;
+
+ os_reg2_val = mmio_read_32(PMUGRF_BASE + PMUGRF_OSREG(2));
+ sdram_config.dramtype = SYS_REG_DEC_DDRTYPE(os_reg2_val);
+ sdram_config.num_channels = SYS_REG_DEC_NUM_CH(os_reg2_val);
+ sdram_config.stride = (mmio_read_32(SGRF_BASE + SGRF_SOC_CON3_7(4)) >>
+ 10) & 0x1f;
+
+ for (i = 0; i < 2; i++) {
+ struct rk3399_sdram_channel *ch = &sdram_config.ch[i];
+ struct rk3399_msch_timings *noc = &ch->noc_timings;
+
+ if (!(SYS_REG_DEC_CHINFO(os_reg2_val, i)))
+ continue;
+
+ ch->rank = SYS_REG_DEC_RANK(os_reg2_val, i);
+ ch->col = SYS_REG_DEC_COL(os_reg2_val, i);
+ ch->bk = SYS_REG_DEC_BK(os_reg2_val, i);
+ ch->bw = SYS_REG_DEC_BW(os_reg2_val, i);
+ ch->dbw = SYS_REG_DEC_DBW(os_reg2_val, i);
+ ch->row_3_4 = SYS_REG_DEC_ROW_3_4(os_reg2_val, i);
+ ch->cs0_row = SYS_REG_DEC_CS0_ROW(os_reg2_val, i);
+ ch->cs1_row = SYS_REG_DEC_CS1_ROW(os_reg2_val, i);
+ ch->ddrconfig = mmio_read_32(MSCH_BASE(i) + MSCH_DEVICECONF);
+
+ noc->ddrtiminga0.d32 = mmio_read_32(MSCH_BASE(i) +
+ MSCH_DDRTIMINGA0);
+ noc->ddrtimingb0.d32 = mmio_read_32(MSCH_BASE(i) +
+ MSCH_DDRTIMINGB0);
+ noc->ddrtimingc0.d32 = mmio_read_32(MSCH_BASE(i) +
+ MSCH_DDRTIMINGC0);
+ noc->devtodev0.d32 = mmio_read_32(MSCH_BASE(i) +
+ MSCH_DEVTODEV0);
+ noc->ddrmode.d32 = mmio_read_32(MSCH_BASE(i) + MSCH_DDRMODE);
+ noc->agingx0 = mmio_read_32(MSCH_BASE(i) + MSCH_AGINGX0);
+ }
+}
diff --git a/plat/rockchip/rk3399/drivers/dram/dram.h b/plat/rockchip/rk3399/drivers/dram/dram.h
new file mode 100644
index 0000000..5572b16
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/dram.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DRAM_H
+#define DRAM_H
+
+#include <stdint.h>
+
+#include <dram_regs.h>
+#include <plat_private.h>
+
+enum {
+ DDR3 = 3,
+ LPDDR2 = 5,
+ LPDDR3 = 6,
+ LPDDR4 = 7,
+ UNUSED = 0xff
+};
+
+struct rk3399_ddr_pctl_regs {
+ uint32_t denali_ctl[CTL_REG_NUM];
+};
+
+struct rk3399_ddr_publ_regs {
+ /*
+ * PHY registers from 0 to 90 for slice1.
+ * These are used to restore slice1-4 on resume.
+ */
+ uint32_t phy0[91];
+ /*
+ * PHY registers from 512 to 895.
+ * Only registers 0-37 of each 128 register range are used.
+ */
+ uint32_t phy512[3][38];
+ uint32_t phy896[63];
+};
+
+struct rk3399_ddr_pi_regs {
+ uint32_t denali_pi[PI_REG_NUM];
+};
+union noc_ddrtiminga0 {
+ uint32_t d32;
+ struct {
+ unsigned acttoact : 6;
+ unsigned reserved0 : 2;
+ unsigned rdtomiss : 6;
+ unsigned reserved1 : 2;
+ unsigned wrtomiss : 6;
+ unsigned reserved2 : 2;
+ unsigned readlatency : 8;
+ } b;
+};
+
+union noc_ddrtimingb0 {
+ uint32_t d32;
+ struct {
+ unsigned rdtowr : 5;
+ unsigned reserved0 : 3;
+ unsigned wrtord : 5;
+ unsigned reserved1 : 3;
+ unsigned rrd : 4;
+ unsigned reserved2 : 4;
+ unsigned faw : 6;
+ unsigned reserved3 : 2;
+ } b;
+};
+
+union noc_ddrtimingc0 {
+ uint32_t d32;
+ struct {
+ unsigned burstpenalty : 4;
+ unsigned reserved0 : 4;
+ unsigned wrtomwr : 6;
+ unsigned reserved1 : 18;
+ } b;
+};
+
+union noc_devtodev0 {
+ uint32_t d32;
+ struct {
+ unsigned busrdtord : 3;
+ unsigned reserved0 : 1;
+ unsigned busrdtowr : 3;
+ unsigned reserved1 : 1;
+ unsigned buswrtord : 3;
+ unsigned reserved2 : 1;
+ unsigned buswrtowr : 3;
+ unsigned reserved3 : 17;
+ } b;
+};
+
+union noc_ddrmode {
+ uint32_t d32;
+ struct {
+ unsigned autoprecharge : 1;
+ unsigned bypassfiltering : 1;
+ unsigned fawbank : 1;
+ unsigned burstsize : 2;
+ unsigned mwrsize : 2;
+ unsigned reserved2 : 1;
+ unsigned forceorder : 8;
+ unsigned forceorderstate : 8;
+ unsigned reserved3 : 8;
+ } b;
+};
+
+struct rk3399_msch_timings {
+ union noc_ddrtiminga0 ddrtiminga0;
+ union noc_ddrtimingb0 ddrtimingb0;
+ union noc_ddrtimingc0 ddrtimingc0;
+ union noc_devtodev0 devtodev0;
+ union noc_ddrmode ddrmode;
+ uint32_t agingx0;
+};
+
+struct rk3399_sdram_channel {
+ unsigned char rank;
+ /* col = 0, means this channel is invalid */
+ unsigned char col;
+ /* 3:8bank, 2:4bank */
+ unsigned char bk;
+ /* channel buswidth, 2:32bit, 1:16bit, 0:8bit */
+ unsigned char bw;
+ /* die buswidth, 2:32bit, 1:16bit, 0:8bit */
+ unsigned char dbw;
+ /* row_3_4 = 1: 6Gb or 12Gb die
+ * row_3_4 = 0: normal die, power of 2
+ */
+ unsigned char row_3_4;
+ unsigned char cs0_row;
+ unsigned char cs1_row;
+ uint32_t ddrconfig;
+ struct rk3399_msch_timings noc_timings;
+};
+
+struct rk3399_sdram_params {
+ struct rk3399_sdram_channel ch[2];
+ uint32_t ddr_freq;
+ unsigned char dramtype;
+ unsigned char num_channels;
+ unsigned char stride;
+ unsigned char odt;
+ struct rk3399_ddr_pctl_regs pctl_regs;
+ struct rk3399_ddr_pi_regs pi_regs;
+ struct rk3399_ddr_publ_regs phy_regs;
+ uint32_t rx_cal_dqs[2][4];
+};
+
+extern struct rk3399_sdram_params sdram_config;
+
+void dram_init(void);
+
+#endif /* DRAM_H */
diff --git a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c
new file mode 100644
index 0000000..3cdb7a2
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c
@@ -0,0 +1,1324 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <lib/utils.h>
+
+#include <dram.h>
+
+#include "dram_spec_timing.h"
+
+static const uint8_t ddr3_cl_cwl[][7] = {
+ /*
+ * speed 0~330 331 ~ 400 401 ~ 533 534~666 667~800 801~933 934~1066
+ * tCK>3 2.5~3 1.875~2.5 1.5~1.875 1.25~1.5 1.07~1.25 0.938~1.07
+ * cl<<4, cwl cl<<4, cwl cl<<4, cwl
+ */
+ /* DDR3_800D (5-5-5) */
+ {((5 << 4) | 5), ((5 << 4) | 5), 0, 0, 0, 0, 0},
+ /* DDR3_800E (6-6-6) */
+ {((5 << 4) | 5), ((6 << 4) | 5), 0, 0, 0, 0, 0},
+ /* DDR3_1066E (6-6-6) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), 0, 0, 0, 0},
+ /* DDR3_1066F (7-7-7) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), 0, 0, 0, 0},
+ /* DDR3_1066G (8-8-8) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), 0, 0, 0, 0},
+ /* DDR3_1333F (7-7-7) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1333G (8-8-8) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((8 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1333H (9-9-9) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((9 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1333J (10-10-10) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ 0, 0, 0},
+ /* DDR3_1600G (8-8-8) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7),
+ ((8 << 4) | 8), 0, 0},
+ /* DDR3_1600H (9-9-9) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7),
+ ((9 << 4) | 8), 0, 0},
+ /* DDR3_1600J (10-10-10) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((10 << 4) | 8), 0, 0},
+ /* DDR3_1600K (11-11-11) */
+ {((5 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ ((11 << 4) | 8), 0, 0},
+ /* DDR3_1866J (10-10-10) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7),
+ ((9 << 4) | 8), ((11 << 4) | 9), 0},
+ /* DDR3_1866K (11-11-11) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((8 << 4) | 7),
+ ((10 << 4) | 8), ((11 << 4) | 9), 0},
+ /* DDR3_1866L (12-12-12) */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((11 << 4) | 8), ((12 << 4) | 9), 0},
+ /* DDR3_1866M (13-13-13) */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ ((11 << 4) | 8), ((13 << 4) | 9), 0},
+ /* DDR3_2133K (11-11-11) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((7 << 4) | 7),
+ ((9 << 4) | 8), ((10 << 4) | 9), ((11 << 4) | 10)},
+ /* DDR3_2133L (12-12-12) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((6 << 4) | 6), ((8 << 4) | 7),
+ ((9 << 4) | 8), ((11 << 4) | 9), ((12 << 4) | 10)},
+ /* DDR3_2133M (13-13-13) */
+ {((5 << 4) | 5), ((5 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((10 << 4) | 8), ((12 << 4) | 9), ((13 << 4) | 10)},
+ /* DDR3_2133N (14-14-14) */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((7 << 4) | 6), ((9 << 4) | 7),
+ ((11 << 4) | 8), ((13 << 4) | 9), ((14 << 4) | 10)},
+ /* DDR3_DEFAULT */
+ {((6 << 4) | 5), ((6 << 4) | 5), ((8 << 4) | 6), ((10 << 4) | 7),
+ ((11 << 4) | 8), ((13 << 4) | 9), ((14 << 4) | 10)}
+};
+
+static const uint16_t ddr3_trc_tfaw[] = {
+ /* tRC tFAW */
+ ((50 << 8) | 50), /* DDR3_800D (5-5-5) */
+ ((53 << 8) | 50), /* DDR3_800E (6-6-6) */
+
+ ((49 << 8) | 50), /* DDR3_1066E (6-6-6) */
+ ((51 << 8) | 50), /* DDR3_1066F (7-7-7) */
+ ((53 << 8) | 50), /* DDR3_1066G (8-8-8) */
+
+ ((47 << 8) | 45), /* DDR3_1333F (7-7-7) */
+ ((48 << 8) | 45), /* DDR3_1333G (8-8-8) */
+ ((50 << 8) | 45), /* DDR3_1333H (9-9-9) */
+ ((51 << 8) | 45), /* DDR3_1333J (10-10-10) */
+
+ ((45 << 8) | 40), /* DDR3_1600G (8-8-8) */
+ ((47 << 8) | 40), /* DDR3_1600H (9-9-9)*/
+ ((48 << 8) | 40), /* DDR3_1600J (10-10-10) */
+ ((49 << 8) | 40), /* DDR3_1600K (11-11-11) */
+
+ ((45 << 8) | 35), /* DDR3_1866J (10-10-10) */
+ ((46 << 8) | 35), /* DDR3_1866K (11-11-11) */
+ ((47 << 8) | 35), /* DDR3_1866L (12-12-12) */
+ ((48 << 8) | 35), /* DDR3_1866M (13-13-13) */
+
+ ((44 << 8) | 35), /* DDR3_2133K (11-11-11) */
+ ((45 << 8) | 35), /* DDR3_2133L (12-12-12) */
+ ((46 << 8) | 35), /* DDR3_2133M (13-13-13) */
+ ((47 << 8) | 35), /* DDR3_2133N (14-14-14) */
+
+ ((53 << 8) | 50) /* DDR3_DEFAULT */
+};
+
+static uint32_t get_max_speed_rate(struct timing_related_config *timing_config)
+{
+ if (timing_config->ch_cnt > 1)
+ return max(timing_config->dram_info[0].speed_rate,
+ timing_config->dram_info[1].speed_rate);
+ else
+ return timing_config->dram_info[0].speed_rate;
+}
+
+static uint32_t
+get_max_die_capability(struct timing_related_config *timing_config)
+{
+ uint32_t die_cap = 0;
+ uint32_t cs, ch;
+
+ for (ch = 0; ch < timing_config->ch_cnt; ch++) {
+ for (cs = 0; cs < timing_config->dram_info[ch].cs_cnt; cs++) {
+ die_cap = max(die_cap,
+ timing_config->
+ dram_info[ch].per_die_capability[cs]);
+ }
+ }
+ return die_cap;
+}
+
+/* tRSTL, 100ns */
+#define DDR3_TRSTL (100)
+/* trsth, 500us */
+#define DDR3_TRSTH (500000)
+/* trefi, 7.8us */
+#define DDR3_TREFI_7_8_US (7800)
+/* tWR, 15ns */
+#define DDR3_TWR (15)
+/* tRTP, max(4 tCK,7.5ns) */
+#define DDR3_TRTP (7)
+/* tRRD = max(4nCK, 10ns) */
+#define DDR3_TRRD (10)
+/* tCK */
+#define DDR3_TCCD (4)
+/*tWTR, max(4 tCK,7.5ns)*/
+#define DDR3_TWTR (7)
+/* tCK */
+#define DDR3_TRTW (0)
+/* tRAS, 37.5ns(400MHz) 37.5ns(533MHz) */
+#define DDR3_TRAS (37)
+/* ns */
+#define DDR3_TRFC_512MBIT (90)
+/* ns */
+#define DDR3_TRFC_1GBIT (110)
+/* ns */
+#define DDR3_TRFC_2GBIT (160)
+/* ns */
+#define DDR3_TRFC_4GBIT (300)
+/* ns */
+#define DDR3_TRFC_8GBIT (350)
+
+/*pd and sr*/
+#define DDR3_TXP (7) /* tXP, max(3 tCK, 7.5ns)( < 933MHz) */
+#define DDR3_TXPDLL (24) /* tXPDLL, max(10 tCK, 24ns) */
+#define DDR3_TDLLK (512) /* tXSR, tDLLK=512 tCK */
+#define DDR3_TCKE_400MHZ (7) /* tCKE, max(3 tCK,7.5ns)(400MHz) */
+#define DDR3_TCKE_533MHZ (6) /* tCKE, max(3 tCK,5.625ns)(533MHz) */
+#define DDR3_TCKSRE (10) /* tCKSRX, max(5 tCK, 10ns) */
+
+/*mode register timing*/
+#define DDR3_TMOD (15) /* tMOD, max(12 tCK,15ns) */
+#define DDR3_TMRD (4) /* tMRD, 4 tCK */
+
+/* ZQ */
+#define DDR3_TZQINIT (640) /* tZQinit, max(512 tCK, 640ns) */
+#define DDR3_TZQCS (80) /* tZQCS, max(64 tCK, 80ns) */
+#define DDR3_TZQOPER (320) /* tZQoper, max(256 tCK, 320ns) */
+
+/* Write leveling */
+#define DDR3_TWLMRD (40) /* tCK */
+#define DDR3_TWLO (9) /* max 7.5ns */
+#define DDR3_TWLDQSEN (25) /* tCK */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all ddr3
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void ddr3_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_speed_bin = get_max_speed_rate(timing_config);
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp;
+
+ zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+ if (nmhz <= 330)
+ tmp = 0;
+ else if (nmhz <= 400)
+ tmp = 1;
+ else if (nmhz <= 533)
+ tmp = 2;
+ else if (nmhz <= 666)
+ tmp = 3;
+ else if (nmhz <= 800)
+ tmp = 4;
+ else if (nmhz <= 933)
+ tmp = 5;
+ else
+ tmp = 6;
+
+ /* when dll bypss cl = cwl = 6 */
+ if (nmhz < 300) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 6;
+ } else {
+ pdram_timing->cl = (ddr3_cl_cwl[ddr_speed_bin][tmp] >> 4) & 0xf;
+ pdram_timing->cwl = ddr3_cl_cwl[ddr_speed_bin][tmp] & 0xf;
+ }
+
+ switch (timing_config->dramds) {
+ case 40:
+ tmp = DDR3_DS_40;
+ break;
+ case 34:
+ default:
+ tmp = DDR3_DS_34;
+ break;
+ }
+
+ if (timing_config->odt)
+ switch (timing_config->dramodt) {
+ case 60:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_60;
+ break;
+ case 40:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_40;
+ break;
+ case 120:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_120;
+ break;
+ case 0:
+ default:
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS;
+ break;
+ }
+ else
+ pdram_timing->mr[1] = tmp | DDR3_RTT_NOM_DIS;
+
+ pdram_timing->mr[2] = DDR3_MR2_CWL(pdram_timing->cwl);
+ pdram_timing->mr[3] = 0;
+
+ pdram_timing->trstl = ((DDR3_TRSTL * nmhz + 999) / 1000);
+ pdram_timing->trsth = ((DDR3_TRSTH * nmhz + 999) / 1000);
+ /* tREFI, average periodic refresh interval, 7.8us */
+ pdram_timing->trefi = ((DDR3_TREFI_7_8_US * nmhz + 999) / 1000);
+ /* base timing */
+ pdram_timing->trcd = pdram_timing->cl;
+ pdram_timing->trp = pdram_timing->cl;
+ pdram_timing->trppb = pdram_timing->cl;
+ tmp = ((DDR3_TWR * nmhz + 999) / 1000);
+ pdram_timing->twr = tmp;
+ pdram_timing->tdal = tmp + pdram_timing->trp;
+ if (tmp < 9) {
+ tmp = tmp - 4;
+ } else {
+ tmp += (tmp & 0x1) ? 1 : 0;
+ tmp = tmp >> 1;
+ }
+ if (pdram_timing->bl == 4)
+ pdram_timing->mr[0] = DDR3_BC4
+ | DDR3_CL(pdram_timing->cl)
+ | DDR3_WR(tmp);
+ else
+ pdram_timing->mr[0] = DDR3_BL8
+ | DDR3_CL(pdram_timing->cl)
+ | DDR3_WR(tmp);
+ tmp = ((DDR3_TRTP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->trtp = max(4, tmp);
+ pdram_timing->trc =
+ (((ddr3_trc_tfaw[ddr_speed_bin] >> 8) * nmhz + 999) / 1000);
+ tmp = ((DDR3_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(4, tmp);
+ pdram_timing->tccd = DDR3_TCCD;
+ tmp = ((DDR3_TWTR * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->twtr = max(4, tmp);
+ pdram_timing->trtw = DDR3_TRTW;
+ pdram_timing->tras_max = 9 * pdram_timing->trefi;
+ pdram_timing->tras_min = ((DDR3_TRAS * nmhz + (nmhz >> 1) + 999)
+ / 1000);
+ pdram_timing->tfaw =
+ (((ddr3_trc_tfaw[ddr_speed_bin] & 0x0ff) * nmhz + 999)
+ / 1000);
+ /* tRFC, 90ns(512Mb),110ns(1Gb),160ns(2Gb),300ns(4Gb),350ns(8Gb) */
+ if (ddr_capability_per_die <= 0x4000000)
+ tmp = DDR3_TRFC_512MBIT;
+ else if (ddr_capability_per_die <= 0x8000000)
+ tmp = DDR3_TRFC_1GBIT;
+ else if (ddr_capability_per_die <= 0x10000000)
+ tmp = DDR3_TRFC_2GBIT;
+ else if (ddr_capability_per_die <= 0x20000000)
+ tmp = DDR3_TRFC_4GBIT;
+ else
+ tmp = DDR3_TRFC_8GBIT;
+ pdram_timing->trfc = (tmp * nmhz + 999) / 1000;
+ pdram_timing->txsnr = max(5, (((tmp + 10) * nmhz + 999) / 1000));
+ pdram_timing->tdqsck_max = 0;
+ /*pd and sr*/
+ pdram_timing->txsr = DDR3_TDLLK;
+ tmp = ((DDR3_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(3, tmp);
+ tmp = ((DDR3_TXPDLL * nmhz + 999) / 1000);
+ pdram_timing->txpdll = max(10, tmp);
+ pdram_timing->tdllk = DDR3_TDLLK;
+ if (nmhz >= 533)
+ tmp = ((DDR3_TCKE_533MHZ * nmhz + 999) / 1000);
+ else
+ tmp = ((DDR3_TCKE_400MHZ * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tcke = max(3, tmp);
+ pdram_timing->tckesr = (pdram_timing->tcke + 1);
+ tmp = ((DDR3_TCKSRE * nmhz + 999) / 1000);
+ pdram_timing->tcksre = max(5, tmp);
+ pdram_timing->tcksrx = max(5, tmp);
+ /*mode register timing*/
+ tmp = ((DDR3_TMOD * nmhz + 999) / 1000);
+ pdram_timing->tmod = max(12, tmp);
+ pdram_timing->tmrd = DDR3_TMRD;
+ pdram_timing->tmrr = 0;
+ /*ODT*/
+ pdram_timing->todton = pdram_timing->cwl - 2;
+ /*ZQ*/
+ tmp = ((DDR3_TZQINIT * nmhz + 999) / 1000);
+ pdram_timing->tzqinit = max(512, tmp);
+ tmp = ((DDR3_TZQCS * nmhz + 999) / 1000);
+ pdram_timing->tzqcs = max(64, tmp);
+ tmp = ((DDR3_TZQOPER * nmhz + 999) / 1000);
+ pdram_timing->tzqoper = max(256, tmp);
+ /* write leveling */
+ pdram_timing->twlmrd = DDR3_TWLMRD;
+ pdram_timing->twldqsen = DDR3_TWLDQSEN;
+ pdram_timing->twlo = ((DDR3_TWLO * nmhz + (nmhz >> 1) + 999) / 1000);
+}
+
+#define LPDDR2_TINIT1 (100) /* ns */
+#define LPDDR2_TINIT2 (5) /* tCK */
+#define LPDDR2_TINIT3 (200000) /* 200us */
+#define LPDDR2_TINIT4 (1000) /* 1us */
+#define LPDDR2_TINIT5 (10000) /* 10us */
+#define LPDDR2_TRSTL (0) /* tCK */
+#define LPDDR2_TRSTH (500000) /* 500us */
+#define LPDDR2_TREFI_3_9_US (3900) /* 3.9us */
+#define LPDDR2_TREFI_7_8_US (7800) /* 7.8us */
+
+/* base timing */
+#define LPDDR2_TRCD (24) /* tRCD,15ns(Fast)18ns(Typ)24ns(Slow) */
+#define LPDDR2_TRP_PB (18) /* tRPpb,15ns(Fast)18ns(Typ)24ns(Slow) */
+#define LPDDR2_TRP_AB_8_BANK (21) /* tRPab,18ns(Fast)21ns(Typ)27ns(Slow) */
+#define LPDDR2_TWR (15) /* tWR, max(3tCK,15ns) */
+#define LPDDR2_TRTP (7) /* tRTP, max(2tCK, 7.5ns) */
+#define LPDDR2_TRRD (10) /* tRRD, max(2tCK,10ns) */
+#define LPDDR2_TCCD (2) /* tCK */
+#define LPDDR2_TWTR_GREAT_200MHZ (7) /* ns */
+#define LPDDR2_TWTR_LITTLE_200MHZ (10) /* ns */
+#define LPDDR2_TRTW (0) /* tCK */
+#define LPDDR2_TRAS_MAX (70000) /* 70us */
+#define LPDDR2_TRAS (42) /* tRAS, max(3tCK,42ns) */
+#define LPDDR2_TFAW_GREAT_200MHZ (50) /* max(8tCK,50ns) */
+#define LPDDR2_TFAW_LITTLE_200MHZ (60) /* max(8tCK,60ns) */
+#define LPDDR2_TRFC_8GBIT (210) /* ns */
+#define LPDDR2_TRFC_4GBIT (130) /* ns */
+#define LPDDR2_TDQSCK_MIN (2) /* tDQSCKmin, 2.5ns */
+#define LPDDR2_TDQSCK_MAX (5) /* tDQSCKmax, 5.5ns */
+
+/*pd and sr*/
+#define LPDDR2_TXP (7) /* tXP, max(2tCK,7.5ns) */
+#define LPDDR2_TXPDLL (0)
+#define LPDDR2_TDLLK (0) /* tCK */
+#define LPDDR2_TCKE (3) /* tCK */
+#define LPDDR2_TCKESR (15) /* tCKESR, max(3tCK,15ns) */
+#define LPDDR2_TCKSRE (1) /* tCK */
+#define LPDDR2_TCKSRX (2) /* tCK */
+
+/*mode register timing*/
+#define LPDDR2_TMOD (0)
+#define LPDDR2_TMRD (5) /* tMRD, (=tMRW), 5 tCK */
+#define LPDDR2_TMRR (2) /* tCK */
+
+/*ZQ*/
+#define LPDDR2_TZQINIT (1000) /* ns */
+#define LPDDR2_TZQCS (90) /* tZQCS, max(6tCK,90ns) */
+#define LPDDR2_TZQCL (360) /* tZQCL, max(6tCK,360ns) */
+#define LPDDR2_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all lpddr2
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void lpddr2_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp, twr_tmp, bl_tmp;
+
+ zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+
+ /* 1066 933 800 667 533 400 333
+ * RL, 8 7 6 5 4 3 3
+ * WL, 4 4 3 2 2 1 1
+ */
+ if (nmhz <= 266) {
+ pdram_timing->cl = 4;
+ pdram_timing->cwl = 2;
+ pdram_timing->mr[2] = LPDDR2_RL4_WL2;
+ } else if (nmhz <= 333) {
+ pdram_timing->cl = 5;
+ pdram_timing->cwl = 2;
+ pdram_timing->mr[2] = LPDDR2_RL5_WL2;
+ } else if (nmhz <= 400) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 3;
+ pdram_timing->mr[2] = LPDDR2_RL6_WL3;
+ } else if (nmhz <= 466) {
+ pdram_timing->cl = 7;
+ pdram_timing->cwl = 4;
+ pdram_timing->mr[2] = LPDDR2_RL7_WL4;
+ } else {
+ pdram_timing->cl = 8;
+ pdram_timing->cwl = 4;
+ pdram_timing->mr[2] = LPDDR2_RL8_WL4;
+ }
+ switch (timing_config->dramds) {
+ case 120:
+ pdram_timing->mr[3] = LPDDR2_DS_120;
+ break;
+ case 80:
+ pdram_timing->mr[3] = LPDDR2_DS_80;
+ break;
+ case 60:
+ pdram_timing->mr[3] = LPDDR2_DS_60;
+ break;
+ case 48:
+ pdram_timing->mr[3] = LPDDR2_DS_48;
+ break;
+ case 40:
+ pdram_timing->mr[3] = LPDDR2_DS_40;
+ break;
+ case 34:
+ default:
+ pdram_timing->mr[3] = LPDDR2_DS_34;
+ break;
+ }
+ pdram_timing->mr[0] = 0;
+
+ pdram_timing->tinit1 = (LPDDR2_TINIT1 * nmhz + 999) / 1000;
+ pdram_timing->tinit2 = LPDDR2_TINIT2;
+ pdram_timing->tinit3 = (LPDDR2_TINIT3 * nmhz + 999) / 1000;
+ pdram_timing->tinit4 = (LPDDR2_TINIT4 * nmhz + 999) / 1000;
+ pdram_timing->tinit5 = (LPDDR2_TINIT5 * nmhz + 999) / 1000;
+ pdram_timing->trstl = LPDDR2_TRSTL;
+ pdram_timing->trsth = (LPDDR2_TRSTH * nmhz + 999) / 1000;
+ /*
+ * tREFI, average periodic refresh interval,
+ * 15.6us(<256Mb) 7.8us(256Mb-1Gb) 3.9us(2Gb-8Gb)
+ */
+ if (ddr_capability_per_die >= 0x10000000)
+ pdram_timing->trefi = (LPDDR2_TREFI_3_9_US * nmhz + 999)
+ / 1000;
+ else
+ pdram_timing->trefi = (LPDDR2_TREFI_7_8_US * nmhz + 999)
+ / 1000;
+ /* base timing */
+ tmp = ((LPDDR2_TRCD * nmhz + 999) / 1000);
+ pdram_timing->trcd = max(3, tmp);
+ /*
+ * tRPpb, max(3tCK, 15ns(Fast) 18ns(Typ) 24ns(Slow),
+ */
+ trppb_tmp = ((LPDDR2_TRP_PB * nmhz + 999) / 1000);
+ trppb_tmp = max(3, trppb_tmp);
+ pdram_timing->trppb = trppb_tmp;
+ /*
+ * tRPab, max(3tCK, 4-bank:15ns(Fast) 18ns(Typ) 24ns(Slow),
+ * 8-bank:18ns(Fast) 21ns(Typ) 27ns(Slow))
+ */
+ trp_tmp = ((LPDDR2_TRP_AB_8_BANK * nmhz + 999) / 1000);
+ trp_tmp = max(3, trp_tmp);
+ pdram_timing->trp = trp_tmp;
+ twr_tmp = ((LPDDR2_TWR * nmhz + 999) / 1000);
+ twr_tmp = max(3, twr_tmp);
+ pdram_timing->twr = twr_tmp;
+ bl_tmp = (pdram_timing->bl == 16) ? LPDDR2_BL16 :
+ ((pdram_timing->bl == 8) ? LPDDR2_BL8 : LPDDR2_BL4);
+ pdram_timing->mr[1] = bl_tmp | LPDDR2_N_WR(twr_tmp);
+ tmp = ((LPDDR2_TRTP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->trtp = max(2, tmp);
+ tras_tmp = ((LPDDR2_TRAS * nmhz + 999) / 1000);
+ tras_tmp = max(3, tras_tmp);
+ pdram_timing->tras_min = tras_tmp;
+ pdram_timing->tras_max = ((LPDDR2_TRAS_MAX * nmhz + 999) / 1000);
+ pdram_timing->trc = (tras_tmp + trp_tmp);
+ tmp = ((LPDDR2_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(2, tmp);
+ pdram_timing->tccd = LPDDR2_TCCD;
+ /* tWTR, max(2tCK, 7.5ns(533-266MHz) 10ns(200-166MHz)) */
+ if (nmhz > 200)
+ tmp = ((LPDDR2_TWTR_GREAT_200MHZ * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ else
+ tmp = ((LPDDR2_TWTR_LITTLE_200MHZ * nmhz + 999) / 1000);
+ pdram_timing->twtr = max(2, tmp);
+ pdram_timing->trtw = LPDDR2_TRTW;
+ if (nmhz <= 200)
+ pdram_timing->tfaw = (LPDDR2_TFAW_LITTLE_200MHZ * nmhz + 999)
+ / 1000;
+ else
+ pdram_timing->tfaw = (LPDDR2_TFAW_GREAT_200MHZ * nmhz + 999)
+ / 1000;
+ /* tRFC, 90ns(<=512Mb) 130ns(1Gb-4Gb) 210ns(8Gb) */
+ if (ddr_capability_per_die >= 0x40000000) {
+ pdram_timing->trfc =
+ (LPDDR2_TRFC_8GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR2_TRFC_8GBIT + 10) * nmhz + 999) / 1000);
+ } else {
+ pdram_timing->trfc =
+ (LPDDR2_TRFC_4GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR2_TRFC_4GBIT + 10) * nmhz + 999) / 1000);
+ }
+ if (tmp < 2)
+ tmp = 2;
+ pdram_timing->txsr = tmp;
+ pdram_timing->txsnr = tmp;
+ /* tdqsck use rounded down */
+ pdram_timing->tdqsck = ((LPDDR2_TDQSCK_MIN * nmhz + (nmhz >> 1))
+ / 1000);
+ pdram_timing->tdqsck_max =
+ ((LPDDR2_TDQSCK_MAX * nmhz + (nmhz >> 1) + 999)
+ / 1000);
+ /* pd and sr */
+ tmp = ((LPDDR2_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(2, tmp);
+ pdram_timing->txpdll = LPDDR2_TXPDLL;
+ pdram_timing->tdllk = LPDDR2_TDLLK;
+ pdram_timing->tcke = LPDDR2_TCKE;
+ tmp = ((LPDDR2_TCKESR * nmhz + 999) / 1000);
+ pdram_timing->tckesr = max(3, tmp);
+ pdram_timing->tcksre = LPDDR2_TCKSRE;
+ pdram_timing->tcksrx = LPDDR2_TCKSRX;
+ /* mode register timing */
+ pdram_timing->tmod = LPDDR2_TMOD;
+ pdram_timing->tmrd = LPDDR2_TMRD;
+ pdram_timing->tmrr = LPDDR2_TMRR;
+ /* ZQ */
+ pdram_timing->tzqinit = (LPDDR2_TZQINIT * nmhz + 999) / 1000;
+ tmp = ((LPDDR2_TZQCS * nmhz + 999) / 1000);
+ pdram_timing->tzqcs = max(6, tmp);
+ tmp = ((LPDDR2_TZQCL * nmhz + 999) / 1000);
+ pdram_timing->tzqoper = max(6, tmp);
+ tmp = ((LPDDR2_TZQRESET * nmhz + 999) / 1000);
+ pdram_timing->tzqreset = max(3, tmp);
+}
+
+#define LPDDR3_TINIT1 (100) /* ns */
+#define LPDDR3_TINIT2 (5) /* tCK */
+#define LPDDR3_TINIT3 (200000) /* 200us */
+#define LPDDR3_TINIT4 (1000) /* 1us */
+#define LPDDR3_TINIT5 (10000) /* 10us */
+#define LPDDR3_TRSTL (0)
+#define LPDDR3_TRSTH (0) /* 500us */
+#define LPDDR3_TREFI_3_9_US (3900) /* 3.9us */
+
+/* base timging */
+#define LPDDR3_TRCD (18) /* tRCD,15ns(Fast)18ns(Typ)24ns(Slow) */
+#define LPDDR3_TRP_PB (18) /* tRPpb, 15ns(Fast) 18ns(Typ) 24ns(Slow) */
+#define LPDDR3_TRP_AB (21) /* tRPab, 18ns(Fast) 21ns(Typ) 27ns(Slow) */
+#define LPDDR3_TWR (15) /* tWR, max(4tCK,15ns) */
+#define LPDDR3_TRTP (7) /* tRTP, max(4tCK, 7.5ns) */
+#define LPDDR3_TRRD (10) /* tRRD, max(2tCK,10ns) */
+#define LPDDR3_TCCD (4) /* tCK */
+#define LPDDR3_TWTR (7) /* tWTR, max(4tCK, 7.5ns) */
+#define LPDDR3_TRTW (0) /* tCK register min valid value */
+#define LPDDR3_TRAS_MAX (70000) /* 70us */
+#define LPDDR3_TRAS (42) /* tRAS, max(3tCK,42ns) */
+#define LPDDR3_TFAW (50) /* tFAW,max(8tCK, 50ns) */
+#define LPDDR3_TRFC_8GBIT (210) /* tRFC, 130ns(4Gb) 210ns(>4Gb) */
+#define LPDDR3_TRFC_4GBIT (130) /* ns */
+#define LPDDR3_TDQSCK_MIN (2) /* tDQSCKmin,2.5ns */
+#define LPDDR3_TDQSCK_MAX (5) /* tDQSCKmax,5.5ns */
+
+/* pd and sr */
+#define LPDDR3_TXP (7) /* tXP, max(3tCK,7.5ns) */
+#define LPDDR3_TXPDLL (0)
+#define LPDDR3_TCKE (7) /* tCKE, (max 7.5ns,3 tCK) */
+#define LPDDR3_TCKESR (15) /* tCKESR, max(3tCK,15ns) */
+#define LPDDR3_TCKSRE (2) /* tCKSRE=tCPDED, 2 tCK */
+#define LPDDR3_TCKSRX (2) /* tCKSRX, 2 tCK */
+
+/* mode register timing */
+#define LPDDR3_TMOD (0)
+#define LPDDR3_TMRD (14) /* tMRD, (=tMRW), max(14ns, 10 tCK) */
+#define LPDDR3_TMRR (4) /* tMRR, 4 tCK */
+#define LPDDR3_TMRRI LPDDR3_TRCD
+
+/* ODT */
+#define LPDDR3_TODTON (3) /* 3.5ns */
+
+/* ZQ */
+#define LPDDR3_TZQINIT (1000) /* 1us */
+#define LPDDR3_TZQCS (90) /* tZQCS, 90ns */
+#define LPDDR3_TZQCL (360) /* 360ns */
+#define LPDDR3_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */
+/* write leveling */
+#define LPDDR3_TWLMRD (40) /* ns */
+#define LPDDR3_TWLO (20) /* ns */
+#define LPDDR3_TWLDQSEN (25) /* ns */
+/* CA training */
+#define LPDDR3_TCACKEL (10) /* tCK */
+#define LPDDR3_TCAENT (10) /* tCK */
+#define LPDDR3_TCAMRD (20) /* tCK */
+#define LPDDR3_TCACKEH (10) /* tCK */
+#define LPDDR3_TCAEXT (10) /* tCK */
+#define LPDDR3_TADR (20) /* ns */
+#define LPDDR3_TMRZ (3) /* ns */
+
+/* FSP */
+#define LPDDR3_TFC_LONG (250) /* ns */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all lpddr3
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void lpddr3_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp, twr_tmp, bl_tmp;
+
+ zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+
+ /*
+ * Only support Write Latency Set A here
+ * 1066 933 800 733 667 600 533 400 166
+ * RL, 16 14 12 11 10 9 8 6 3
+ * WL, 8 8 6 6 6 5 4 3 1
+ */
+ if (nmhz <= 400) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 3;
+ pdram_timing->mr[2] = LPDDR3_RL6_WL3;
+ } else if (nmhz <= 533) {
+ pdram_timing->cl = 8;
+ pdram_timing->cwl = 4;
+ pdram_timing->mr[2] = LPDDR3_RL8_WL4;
+ } else if (nmhz <= 600) {
+ pdram_timing->cl = 9;
+ pdram_timing->cwl = 5;
+ pdram_timing->mr[2] = LPDDR3_RL9_WL5;
+ } else if (nmhz <= 667) {
+ pdram_timing->cl = 10;
+ pdram_timing->cwl = 6;
+ pdram_timing->mr[2] = LPDDR3_RL10_WL6;
+ } else if (nmhz <= 733) {
+ pdram_timing->cl = 11;
+ pdram_timing->cwl = 6;
+ pdram_timing->mr[2] = LPDDR3_RL11_WL6;
+ } else if (nmhz <= 800) {
+ pdram_timing->cl = 12;
+ pdram_timing->cwl = 6;
+ pdram_timing->mr[2] = LPDDR3_RL12_WL6;
+ } else if (nmhz <= 933) {
+ pdram_timing->cl = 14;
+ pdram_timing->cwl = 8;
+ pdram_timing->mr[2] = LPDDR3_RL14_WL8;
+ } else {
+ pdram_timing->cl = 16;
+ pdram_timing->cwl = 8;
+ pdram_timing->mr[2] = LPDDR3_RL16_WL8;
+ }
+ switch (timing_config->dramds) {
+ case 80:
+ pdram_timing->mr[3] = LPDDR3_DS_80;
+ break;
+ case 60:
+ pdram_timing->mr[3] = LPDDR3_DS_60;
+ break;
+ case 48:
+ pdram_timing->mr[3] = LPDDR3_DS_48;
+ break;
+ case 40:
+ pdram_timing->mr[3] = LPDDR3_DS_40;
+ break;
+ case 3440:
+ pdram_timing->mr[3] = LPDDR3_DS_34D_40U;
+ break;
+ case 4048:
+ pdram_timing->mr[3] = LPDDR3_DS_40D_48U;
+ break;
+ case 3448:
+ pdram_timing->mr[3] = LPDDR3_DS_34D_48U;
+ break;
+ case 34:
+ default:
+ pdram_timing->mr[3] = LPDDR3_DS_34;
+ break;
+ }
+ pdram_timing->mr[0] = 0;
+ if (timing_config->odt)
+ switch (timing_config->dramodt) {
+ case 60:
+ pdram_timing->mr11 = LPDDR3_ODT_60;
+ break;
+ case 120:
+ pdram_timing->mr11 = LPDDR3_ODT_120;
+ break;
+ case 240:
+ default:
+ pdram_timing->mr11 = LPDDR3_ODT_240;
+ break;
+ }
+ else
+ pdram_timing->mr11 = LPDDR3_ODT_DIS;
+
+ pdram_timing->tinit1 = (LPDDR3_TINIT1 * nmhz + 999) / 1000;
+ pdram_timing->tinit2 = LPDDR3_TINIT2;
+ pdram_timing->tinit3 = (LPDDR3_TINIT3 * nmhz + 999) / 1000;
+ pdram_timing->tinit4 = (LPDDR3_TINIT4 * nmhz + 999) / 1000;
+ pdram_timing->tinit5 = (LPDDR3_TINIT5 * nmhz + 999) / 1000;
+ pdram_timing->trstl = LPDDR3_TRSTL;
+ pdram_timing->trsth = (LPDDR3_TRSTH * nmhz + 999) / 1000;
+ /* tREFI, average periodic refresh interval, 3.9us(4Gb-16Gb) */
+ pdram_timing->trefi = (LPDDR3_TREFI_3_9_US * nmhz + 999) / 1000;
+ /* base timing */
+ tmp = ((LPDDR3_TRCD * nmhz + 999) / 1000);
+ pdram_timing->trcd = max(3, tmp);
+ trppb_tmp = ((LPDDR3_TRP_PB * nmhz + 999) / 1000);
+ trppb_tmp = max(3, trppb_tmp);
+ pdram_timing->trppb = trppb_tmp;
+ trp_tmp = ((LPDDR3_TRP_AB * nmhz + 999) / 1000);
+ trp_tmp = max(3, trp_tmp);
+ pdram_timing->trp = trp_tmp;
+ twr_tmp = ((LPDDR3_TWR * nmhz + 999) / 1000);
+ twr_tmp = max(4, twr_tmp);
+ pdram_timing->twr = twr_tmp;
+ if (twr_tmp <= 6)
+ twr_tmp = 6;
+ else if (twr_tmp <= 8)
+ twr_tmp = 8;
+ else if (twr_tmp <= 12)
+ twr_tmp = twr_tmp;
+ else if (twr_tmp <= 14)
+ twr_tmp = 14;
+ else
+ twr_tmp = 16;
+ if (twr_tmp > 9)
+ pdram_timing->mr[2] |= (1 << 4); /*enable nWR > 9*/
+ twr_tmp = (twr_tmp > 9) ? (twr_tmp - 10) : (twr_tmp - 2);
+ bl_tmp = LPDDR3_BL8;
+ pdram_timing->mr[1] = bl_tmp | LPDDR3_N_WR(twr_tmp);
+ tmp = ((LPDDR3_TRTP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->trtp = max(4, tmp);
+ tras_tmp = ((LPDDR3_TRAS * nmhz + 999) / 1000);
+ tras_tmp = max(3, tras_tmp);
+ pdram_timing->tras_min = tras_tmp;
+ pdram_timing->trc = (tras_tmp + trp_tmp);
+ tmp = ((LPDDR3_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(2, tmp);
+ pdram_timing->tccd = LPDDR3_TCCD;
+ tmp = ((LPDDR3_TWTR * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->twtr = max(4, tmp);
+ pdram_timing->trtw = ((LPDDR3_TRTW * nmhz + 999) / 1000);
+ pdram_timing->tras_max = ((LPDDR3_TRAS_MAX * nmhz + 999) / 1000);
+ tmp = (LPDDR3_TFAW * nmhz + 999) / 1000;
+ pdram_timing->tfaw = max(8, tmp);
+ if (ddr_capability_per_die > 0x20000000) {
+ pdram_timing->trfc =
+ (LPDDR3_TRFC_8GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR3_TRFC_8GBIT + 10) * nmhz + 999) / 1000);
+ } else {
+ pdram_timing->trfc =
+ (LPDDR3_TRFC_4GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR3_TRFC_4GBIT + 10) * nmhz + 999) / 1000);
+ }
+ pdram_timing->txsr = max(2, tmp);
+ pdram_timing->txsnr = max(2, tmp);
+ /* tdqsck use rounded down */
+ pdram_timing->tdqsck =
+ ((LPDDR3_TDQSCK_MIN * nmhz + (nmhz >> 1))
+ / 1000);
+ pdram_timing->tdqsck_max =
+ ((LPDDR3_TDQSCK_MAX * nmhz + (nmhz >> 1) + 999)
+ / 1000);
+ /*pd and sr*/
+ tmp = ((LPDDR3_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(3, tmp);
+ pdram_timing->txpdll = LPDDR3_TXPDLL;
+ tmp = ((LPDDR3_TCKE * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tcke = max(3, tmp);
+ tmp = ((LPDDR3_TCKESR * nmhz + 999) / 1000);
+ pdram_timing->tckesr = max(3, tmp);
+ pdram_timing->tcksre = LPDDR3_TCKSRE;
+ pdram_timing->tcksrx = LPDDR3_TCKSRX;
+ /*mode register timing*/
+ pdram_timing->tmod = LPDDR3_TMOD;
+ tmp = ((LPDDR3_TMRD * nmhz + 999) / 1000);
+ pdram_timing->tmrd = max(10, tmp);
+ pdram_timing->tmrr = LPDDR3_TMRR;
+ tmp = ((LPDDR3_TRCD * nmhz + 999) / 1000);
+ pdram_timing->tmrri = max(3, tmp);
+ /* ODT */
+ pdram_timing->todton = (LPDDR3_TODTON * nmhz + (nmhz >> 1) + 999)
+ / 1000;
+ /* ZQ */
+ pdram_timing->tzqinit = (LPDDR3_TZQINIT * nmhz + 999) / 1000;
+ pdram_timing->tzqcs =
+ ((LPDDR3_TZQCS * nmhz + 999) / 1000);
+ pdram_timing->tzqoper =
+ ((LPDDR3_TZQCL * nmhz + 999) / 1000);
+ tmp = ((LPDDR3_TZQRESET * nmhz + 999) / 1000);
+ pdram_timing->tzqreset = max(3, tmp);
+ /* write leveling */
+ pdram_timing->twlmrd = (LPDDR3_TWLMRD * nmhz + 999) / 1000;
+ pdram_timing->twlo = (LPDDR3_TWLO * nmhz + 999) / 1000;
+ pdram_timing->twldqsen = (LPDDR3_TWLDQSEN * nmhz + 999) / 1000;
+ /* CA training */
+ pdram_timing->tcackel = LPDDR3_TCACKEL;
+ pdram_timing->tcaent = LPDDR3_TCAENT;
+ pdram_timing->tcamrd = LPDDR3_TCAMRD;
+ pdram_timing->tcackeh = LPDDR3_TCACKEH;
+ pdram_timing->tcaext = LPDDR3_TCAEXT;
+ pdram_timing->tadr = (LPDDR3_TADR * nmhz + 999) / 1000;
+ pdram_timing->tmrz = (LPDDR3_TMRZ * nmhz + 999) / 1000;
+ pdram_timing->tcacd = pdram_timing->tadr + 2;
+
+ /* FSP */
+ pdram_timing->tfc_long = (LPDDR3_TFC_LONG * nmhz + 999) / 1000;
+}
+
+#define LPDDR4_TINIT1 (200000) /* 200us */
+#define LPDDR4_TINIT2 (10) /* 10ns */
+#define LPDDR4_TINIT3 (2000000) /* 2ms */
+#define LPDDR4_TINIT4 (5) /* tCK */
+#define LPDDR4_TINIT5 (2000) /* 2us */
+#define LPDDR4_TRSTL LPDDR4_TINIT1
+#define LPDDR4_TRSTH LPDDR4_TINIT3
+#define LPDDR4_TREFI_3_9_US (3900) /* 3.9us */
+
+/* base timging */
+#define LPDDR4_TRCD (18) /* tRCD, max(18ns,4tCK) */
+#define LPDDR4_TRP_PB (18) /* tRPpb, max(18ns, 4tCK) */
+#define LPDDR4_TRP_AB (21) /* tRPab, max(21ns, 4tCK) */
+#define LPDDR4_TRRD (10) /* tRRD, max(4tCK,10ns) */
+#define LPDDR4_TCCD_BL16 (8) /* tCK */
+#define LPDDR4_TCCD_BL32 (16) /* tCK */
+#define LPDDR4_TWTR (10) /* tWTR, max(8tCK, 10ns) */
+#define LPDDR4_TRTW (0) /* tCK register min valid value */
+#define LPDDR4_TRAS_MAX (70000) /* 70us */
+#define LPDDR4_TRAS (42) /* tRAS, max(3tCK,42ns) */
+#define LPDDR4_TFAW (40) /* tFAW,min 40ns) */
+#define LPDDR4_TRFC_12GBIT (280) /* tRFC, 280ns(>=12Gb) */
+#define LPDDR4_TRFC_6GBIT (180) /* 6Gb/8Gb 180ns */
+#define LPDDR4_TRFC_4GBIT (130) /* 4Gb 130ns */
+#define LPDDR4_TDQSCK_MIN (1) /* tDQSCKmin,1.5ns */
+#define LPDDR4_TDQSCK_MAX (3) /* tDQSCKmax,3.5ns */
+#define LPDDR4_TPPD (4) /* tCK */
+
+/* pd and sr */
+#define LPDDR4_TXP (7) /* tXP, max(5tCK,7.5ns) */
+#define LPDDR4_TCKE (7) /* tCKE, max(7.5ns,4 tCK) */
+#define LPDDR4_TESCKE (1) /* tESCKE, max(1.75ns, 3tCK) */
+#define LPDDR4_TSR (15) /* tSR, max(15ns, 3tCK) */
+#define LPDDR4_TCMDCKE (1) /* max(1.75ns, 3tCK) */
+#define LPDDR4_TCSCKE (1) /* 1.75ns */
+#define LPDDR4_TCKELCS (5) /* max(5ns, 5tCK) */
+#define LPDDR4_TCSCKEH (1) /* 1.75ns */
+#define LPDDR4_TCKEHCS (7) /* max(7.5ns, 5tCK) */
+#define LPDDR4_TMRWCKEL (14) /* max(14ns, 10tCK) */
+#define LPDDR4_TCKELCMD (7) /* max(7.5ns, 3tCK) */
+#define LPDDR4_TCKEHCMD (7) /* max(7.5ns, 3tCK) */
+#define LPDDR4_TCKELPD (7) /* max(7.5ns, 3tCK) */
+#define LPDDR4_TCKCKEL (7) /* max(7.5ns, 3tCK) */
+
+/* mode register timing */
+#define LPDDR4_TMRD (14) /* tMRD, (=tMRW), max(14ns, 10 tCK) */
+#define LPDDR4_TMRR (8) /* tMRR, 8 tCK */
+
+/* ODT */
+#define LPDDR4_TODTON (3) /* 3.5ns */
+
+/* ZQ */
+#define LPDDR4_TZQCAL (1000) /* 1us */
+#define LPDDR4_TZQLAT (30) /* tZQLAT, max(30ns,8tCK) */
+#define LPDDR4_TZQRESET (50) /* ZQreset, max(3tCK,50ns) */
+#define LPDDR4_TZQCKE (1) /* tZQCKE, max(1.75ns, 3tCK) */
+
+/* write leveling */
+#define LPDDR4_TWLMRD (40) /* tCK */
+#define LPDDR4_TWLO (20) /* ns */
+#define LPDDR4_TWLDQSEN (20) /* tCK */
+
+/* CA training */
+#define LPDDR4_TCAENT (250) /* ns */
+#define LPDDR4_TADR (20) /* ns */
+#define LPDDR4_TMRZ (1) /* 1.5ns */
+#define LPDDR4_TVREF_LONG (250) /* ns */
+#define LPDDR4_TVREF_SHORT (100) /* ns */
+
+/* VRCG */
+#define LPDDR4_TVRCG_ENABLE (200) /* ns */
+#define LPDDR4_TVRCG_DISABLE (100) /* ns */
+
+/* FSP */
+#define LPDDR4_TFC_LONG (250) /* ns */
+#define LPDDR4_TCKFSPE (7) /* max(7.5ns, 4tCK) */
+#define LPDDR4_TCKFSPX (7) /* max(7.5ns, 4tCK) */
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate all lpddr4
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ */
+static void lpddr4_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ uint32_t nmhz = timing_config->freq;
+ uint32_t ddr_capability_per_die = get_max_die_capability(timing_config);
+ uint32_t tmp, trp_tmp, trppb_tmp, tras_tmp;
+
+ zeromem((void *)pdram_timing, sizeof(struct dram_timing_t));
+ pdram_timing->mhz = nmhz;
+ pdram_timing->al = 0;
+ pdram_timing->bl = timing_config->bl;
+
+ /*
+ * Only support Write Latency Set A here
+ * 2133 1866 1600 1333 1066 800 533 266
+ * RL, 36 32 28 24 20 14 10 6
+ * WL, 18 16 14 12 10 8 6 4
+ * nWR, 40 34 30 24 20 16 10 6
+ * nRTP,16 14 12 10 8 8 8 8
+ */
+ tmp = (timing_config->bl == 32) ? 1 : 0;
+
+ /*
+ * we always use WR preamble = 2tCK
+ * RD preamble = Static
+ */
+ tmp |= (1 << 2);
+ if (nmhz <= 266) {
+ pdram_timing->cl = 6;
+ pdram_timing->cwl = 4;
+ pdram_timing->twr = 6;
+ pdram_timing->trtp = 8;
+ pdram_timing->mr[2] = LPDDR4_RL6_NRTP8 | LPDDR4_A_WL4;
+ } else if (nmhz <= 533) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 12;
+ pdram_timing->mr[2] = LPDDR4_RL12_NRTP8 | LPDDR4_A_WL6;
+ } else {
+ pdram_timing->cl = 10;
+ pdram_timing->mr[2] = LPDDR4_RL10_NRTP8 | LPDDR4_A_WL6;
+ }
+ pdram_timing->cwl = 6;
+ pdram_timing->twr = 10;
+ pdram_timing->trtp = 8;
+ tmp |= (1 << 4);
+ } else if (nmhz <= 800) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 16;
+ pdram_timing->mr[2] = LPDDR4_RL16_NRTP8 | LPDDR4_A_WL8;
+ } else {
+ pdram_timing->cl = 14;
+ pdram_timing->mr[2] = LPDDR4_RL14_NRTP8 | LPDDR4_A_WL8;
+ }
+ pdram_timing->cwl = 8;
+ pdram_timing->twr = 16;
+ pdram_timing->trtp = 8;
+ tmp |= (2 << 4);
+ } else if (nmhz <= 1066) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 22;
+ pdram_timing->mr[2] = LPDDR4_RL22_NRTP8 | LPDDR4_A_WL10;
+ } else {
+ pdram_timing->cl = 20;
+ pdram_timing->mr[2] = LPDDR4_RL20_NRTP8 | LPDDR4_A_WL10;
+ }
+ pdram_timing->cwl = 10;
+ pdram_timing->twr = 20;
+ pdram_timing->trtp = 8;
+ tmp |= (3 << 4);
+ } else if (nmhz <= 1333) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 28;
+ pdram_timing->mr[2] = LPDDR4_RL28_NRTP10 |
+ LPDDR4_A_WL12;
+ } else {
+ pdram_timing->cl = 24;
+ pdram_timing->mr[2] = LPDDR4_RL24_NRTP10 |
+ LPDDR4_A_WL12;
+ }
+ pdram_timing->cwl = 12;
+ pdram_timing->twr = 24;
+ pdram_timing->trtp = 10;
+ tmp |= (4 << 4);
+ } else if (nmhz <= 1600) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 32;
+ pdram_timing->mr[2] = LPDDR4_RL32_NRTP12 |
+ LPDDR4_A_WL14;
+ } else {
+ pdram_timing->cl = 28;
+ pdram_timing->mr[2] = LPDDR4_RL28_NRTP12 |
+ LPDDR4_A_WL14;
+ }
+ pdram_timing->cwl = 14;
+ pdram_timing->twr = 30;
+ pdram_timing->trtp = 12;
+ tmp |= (5 << 4);
+ } else if (nmhz <= 1866) {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 36;
+ pdram_timing->mr[2] = LPDDR4_RL36_NRTP14 |
+ LPDDR4_A_WL16;
+ } else {
+ pdram_timing->cl = 32;
+ pdram_timing->mr[2] = LPDDR4_RL32_NRTP14 |
+ LPDDR4_A_WL16;
+ }
+ pdram_timing->cwl = 16;
+ pdram_timing->twr = 34;
+ pdram_timing->trtp = 14;
+ tmp |= (6 << 4);
+ } else {
+ if (timing_config->rdbi) {
+ pdram_timing->cl = 40;
+ pdram_timing->mr[2] = LPDDR4_RL40_NRTP16 |
+ LPDDR4_A_WL18;
+ } else {
+ pdram_timing->cl = 36;
+ pdram_timing->mr[2] = LPDDR4_RL36_NRTP16 |
+ LPDDR4_A_WL18;
+ }
+ pdram_timing->cwl = 18;
+ pdram_timing->twr = 40;
+ pdram_timing->trtp = 16;
+ tmp |= (7 << 4);
+ }
+ pdram_timing->mr[1] = tmp;
+ tmp = (timing_config->rdbi ? LPDDR4_DBI_RD_EN : 0) |
+ (timing_config->wdbi ? LPDDR4_DBI_WR_EN : 0);
+ switch (timing_config->dramds) {
+ case 240:
+ pdram_timing->mr[3] = LPDDR4_PDDS_240 | tmp;
+ break;
+ case 120:
+ pdram_timing->mr[3] = LPDDR4_PDDS_120 | tmp;
+ break;
+ case 80:
+ pdram_timing->mr[3] = LPDDR4_PDDS_80 | tmp;
+ break;
+ case 60:
+ pdram_timing->mr[3] = LPDDR4_PDDS_60 | tmp;
+ break;
+ case 48:
+ pdram_timing->mr[3] = LPDDR4_PDDS_48 | tmp;
+ break;
+ case 40:
+ default:
+ pdram_timing->mr[3] = LPDDR4_PDDS_40 | tmp;
+ break;
+ }
+ pdram_timing->mr[0] = 0;
+ if (timing_config->odt) {
+ switch (timing_config->dramodt) {
+ case 240:
+ tmp = LPDDR4_DQODT_240;
+ break;
+ case 120:
+ tmp = LPDDR4_DQODT_120;
+ break;
+ case 80:
+ tmp = LPDDR4_DQODT_80;
+ break;
+ case 60:
+ tmp = LPDDR4_DQODT_60;
+ break;
+ case 48:
+ tmp = LPDDR4_DQODT_48;
+ break;
+ case 40:
+ default:
+ tmp = LPDDR4_DQODT_40;
+ break;
+ }
+
+ switch (timing_config->caodt) {
+ case 240:
+ pdram_timing->mr11 = LPDDR4_CAODT_240 | tmp;
+ break;
+ case 120:
+ pdram_timing->mr11 = LPDDR4_CAODT_120 | tmp;
+ break;
+ case 80:
+ pdram_timing->mr11 = LPDDR4_CAODT_80 | tmp;
+ break;
+ case 60:
+ pdram_timing->mr11 = LPDDR4_CAODT_60 | tmp;
+ break;
+ case 48:
+ pdram_timing->mr11 = LPDDR4_CAODT_48 | tmp;
+ break;
+ case 40:
+ default:
+ pdram_timing->mr11 = LPDDR4_CAODT_40 | tmp;
+ break;
+ }
+ } else {
+ pdram_timing->mr11 = LPDDR4_CAODT_DIS | tmp;
+ }
+
+ pdram_timing->tinit1 = (LPDDR4_TINIT1 * nmhz + 999) / 1000;
+ pdram_timing->tinit2 = (LPDDR4_TINIT2 * nmhz + 999) / 1000;
+ pdram_timing->tinit3 = (LPDDR4_TINIT3 * nmhz + 999) / 1000;
+ pdram_timing->tinit4 = (LPDDR4_TINIT4 * nmhz + 999) / 1000;
+ pdram_timing->tinit5 = (LPDDR4_TINIT5 * nmhz + 999) / 1000;
+ pdram_timing->trstl = (LPDDR4_TRSTL * nmhz + 999) / 1000;
+ pdram_timing->trsth = (LPDDR4_TRSTH * nmhz + 999) / 1000;
+ /* tREFI, average periodic refresh interval, 3.9us(4Gb-16Gb) */
+ pdram_timing->trefi = (LPDDR4_TREFI_3_9_US * nmhz + 999) / 1000;
+ /* base timing */
+ tmp = ((LPDDR4_TRCD * nmhz + 999) / 1000);
+ pdram_timing->trcd = max(4, tmp);
+ trppb_tmp = ((LPDDR4_TRP_PB * nmhz + 999) / 1000);
+ trppb_tmp = max(4, trppb_tmp);
+ pdram_timing->trppb = trppb_tmp;
+ trp_tmp = ((LPDDR4_TRP_AB * nmhz + 999) / 1000);
+ trp_tmp = max(4, trp_tmp);
+ pdram_timing->trp = trp_tmp;
+ tras_tmp = ((LPDDR4_TRAS * nmhz + 999) / 1000);
+ tras_tmp = max(3, tras_tmp);
+ pdram_timing->tras_min = tras_tmp;
+ pdram_timing->trc = (tras_tmp + trp_tmp);
+ tmp = ((LPDDR4_TRRD * nmhz + 999) / 1000);
+ pdram_timing->trrd = max(4, tmp);
+ if (timing_config->bl == 32)
+ pdram_timing->tccd = LPDDR4_TCCD_BL16;
+ else
+ pdram_timing->tccd = LPDDR4_TCCD_BL32;
+ pdram_timing->tccdmw = 4 * pdram_timing->tccd;
+ tmp = ((LPDDR4_TWTR * nmhz + 999) / 1000);
+ pdram_timing->twtr = max(8, tmp);
+ pdram_timing->trtw = ((LPDDR4_TRTW * nmhz + 999) / 1000);
+ pdram_timing->tras_max = ((LPDDR4_TRAS_MAX * nmhz + 999) / 1000);
+ pdram_timing->tfaw = (LPDDR4_TFAW * nmhz + 999) / 1000;
+ if (ddr_capability_per_die > 0x60000000) {
+ /* >= 12Gb */
+ pdram_timing->trfc =
+ (LPDDR4_TRFC_12GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR4_TRFC_12GBIT + 7) * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ } else if (ddr_capability_per_die > 0x30000000) {
+ pdram_timing->trfc =
+ (LPDDR4_TRFC_6GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR4_TRFC_6GBIT + 7) * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ } else {
+ pdram_timing->trfc =
+ (LPDDR4_TRFC_4GBIT * nmhz + 999) / 1000;
+ tmp = (((LPDDR4_TRFC_4GBIT + 7) * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ }
+ pdram_timing->txsr = max(2, tmp);
+ pdram_timing->txsnr = max(2, tmp);
+ /* tdqsck use rounded down */
+ pdram_timing->tdqsck = ((LPDDR4_TDQSCK_MIN * nmhz +
+ (nmhz >> 1)) / 1000);
+ pdram_timing->tdqsck_max = ((LPDDR4_TDQSCK_MAX * nmhz +
+ (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tppd = LPDDR4_TPPD;
+ /* pd and sr */
+ tmp = ((LPDDR4_TXP * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->txp = max(5, tmp);
+ tmp = ((LPDDR4_TCKE * nmhz + (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tcke = max(4, tmp);
+ tmp = ((LPDDR4_TESCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ pdram_timing->tescke = max(3, tmp);
+ tmp = ((LPDDR4_TSR * nmhz + 999) / 1000);
+ pdram_timing->tsr = max(3, tmp);
+ tmp = ((LPDDR4_TCMDCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ pdram_timing->tcmdcke = max(3, tmp);
+ pdram_timing->tcscke = ((LPDDR4_TCSCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ tmp = ((LPDDR4_TCKELCS * nmhz + 999) / 1000);
+ pdram_timing->tckelcs = max(5, tmp);
+ pdram_timing->tcsckeh = ((LPDDR4_TCSCKEH * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ tmp = ((LPDDR4_TCKEHCS * nmhz +
+ (nmhz >> 1) + 999) / 1000);
+ pdram_timing->tckehcs = max(5, tmp);
+ tmp = ((LPDDR4_TMRWCKEL * nmhz + 999) / 1000);
+ pdram_timing->tmrwckel = max(10, tmp);
+ tmp = ((LPDDR4_TCKELCMD * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckelcmd = max(3, tmp);
+ tmp = ((LPDDR4_TCKEHCMD * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckehcmd = max(3, tmp);
+ tmp = ((LPDDR4_TCKELPD * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckelpd = max(3, tmp);
+ tmp = ((LPDDR4_TCKCKEL * nmhz + (nmhz >> 1) +
+ 999) / 1000);
+ pdram_timing->tckckel = max(3, tmp);
+ /* mode register timing */
+ tmp = ((LPDDR4_TMRD * nmhz + 999) / 1000);
+ pdram_timing->tmrd = max(10, tmp);
+ pdram_timing->tmrr = LPDDR4_TMRR;
+ pdram_timing->tmrri = pdram_timing->trcd + 3;
+ /* ODT */
+ pdram_timing->todton = (LPDDR4_TODTON * nmhz + (nmhz >> 1) + 999)
+ / 1000;
+ /* ZQ */
+ pdram_timing->tzqcal = (LPDDR4_TZQCAL * nmhz + 999) / 1000;
+ tmp = ((LPDDR4_TZQLAT * nmhz + 999) / 1000);
+ pdram_timing->tzqlat = max(8, tmp);
+ tmp = ((LPDDR4_TZQRESET * nmhz + 999) / 1000);
+ pdram_timing->tzqreset = max(3, tmp);
+ tmp = ((LPDDR4_TZQCKE * nmhz +
+ ((nmhz * 3) / 4) +
+ 999) / 1000);
+ pdram_timing->tzqcke = max(3, tmp);
+ /* write leveling */
+ pdram_timing->twlmrd = LPDDR4_TWLMRD;
+ pdram_timing->twlo = (LPDDR4_TWLO * nmhz + 999) / 1000;
+ pdram_timing->twldqsen = LPDDR4_TWLDQSEN;
+ /* CA training */
+ pdram_timing->tcaent = (LPDDR4_TCAENT * nmhz + 999) / 1000;
+ pdram_timing->tadr = (LPDDR4_TADR * nmhz + 999) / 1000;
+ pdram_timing->tmrz = (LPDDR4_TMRZ * nmhz + (nmhz >> 1) + 999) / 1000;
+ pdram_timing->tvref_long = (LPDDR4_TVREF_LONG * nmhz + 999) / 1000;
+ pdram_timing->tvref_short = (LPDDR4_TVREF_SHORT * nmhz + 999) / 1000;
+ /* VRCG */
+ pdram_timing->tvrcg_enable = (LPDDR4_TVRCG_ENABLE * nmhz +
+ 999) / 1000;
+ pdram_timing->tvrcg_disable = (LPDDR4_TVRCG_DISABLE * nmhz +
+ 999) / 1000;
+ /* FSP */
+ pdram_timing->tfc_long = (LPDDR4_TFC_LONG * nmhz + 999) / 1000;
+ tmp = (LPDDR4_TCKFSPE * nmhz + (nmhz >> 1) + 999) / 1000;
+ pdram_timing->tckfspe = max(4, tmp);
+ tmp = (LPDDR4_TCKFSPX * nmhz + (nmhz >> 1) + 999) / 1000;
+ pdram_timing->tckfspx = max(4, tmp);
+}
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate correspond "dram_type"
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ * NOTE: MR ODT is set, need to disable by controller
+ */
+void dram_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing)
+{
+ switch (timing_config->dram_type) {
+ case DDR3:
+ ddr3_get_parameter(timing_config, pdram_timing);
+ break;
+ case LPDDR2:
+ lpddr2_get_parameter(timing_config, pdram_timing);
+ break;
+ case LPDDR3:
+ lpddr3_get_parameter(timing_config, pdram_timing);
+ break;
+ case LPDDR4:
+ lpddr4_get_parameter(timing_config, pdram_timing);
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+}
diff --git a/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h
new file mode 100644
index 0000000..9cda22c
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DRAM_SPEC_TIMING_H
+#define DRAM_SPEC_TIMING_H
+
+#include <stdint.h>
+
+enum ddr3_speed_rate {
+ /* 5-5-5 */
+ DDR3_800D = 0,
+ /* 6-6-6 */
+ DDR3_800E = 1,
+ /* 6-6-6 */
+ DDR3_1066E = 2,
+ /* 7-7-7 */
+ DDR3_1066F = 3,
+ /* 8-8-8 */
+ DDR3_1066G = 4,
+ /* 7-7-7 */
+ DDR3_1333F = 5,
+ /* 8-8-8 */
+ DDR3_1333G = 6,
+ /* 9-9-9 */
+ DDR3_1333H = 7,
+ /* 10-10-10 */
+ DDR3_1333J = 8,
+ /* 8-8-8 */
+ DDR3_1600G = 9,
+ /* 9-9-9 */
+ DDR3_1600H = 10,
+ /* 10-10-10 */
+ DDR3_1600J = 11,
+ /* 11-11-11 */
+ DDR3_1600K = 12,
+ /* 10-10-10 */
+ DDR3_1866J = 13,
+ /* 11-11-11 */
+ DDR3_1866K = 14,
+ /* 12-12-12 */
+ DDR3_1866L = 15,
+ /* 13-13-13 */
+ DDR3_1866M = 16,
+ /* 11-11-11 */
+ DDR3_2133K = 17,
+ /* 12-12-12 */
+ DDR3_2133L = 18,
+ /* 13-13-13 */
+ DDR3_2133M = 19,
+ /* 14-14-14 */
+ DDR3_2133N = 20,
+ DDR3_DEFAULT = 21,
+};
+
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#define range(mi, val, ma) (((ma) > (val)) ? (max(mi, val)) : (ma))
+
+struct dram_timing_t {
+ /* unit MHz */
+ uint32_t mhz;
+ /* some timing unit is us */
+ uint32_t tinit1;
+ uint32_t tinit2;
+ uint32_t tinit3;
+ uint32_t tinit4;
+ uint32_t tinit5;
+ /* reset low, DDR3:200us */
+ uint32_t trstl;
+ /* reset high to CKE high, DDR3:500us */
+ uint32_t trsth;
+ uint32_t trefi;
+ /* base */
+ uint32_t trcd;
+ /* trp per bank */
+ uint32_t trppb;
+ /* trp all bank */
+ uint32_t trp;
+ uint32_t twr;
+ uint32_t tdal;
+ uint32_t trtp;
+ uint32_t trc;
+ uint32_t trrd;
+ uint32_t tccd;
+ uint32_t twtr;
+ uint32_t trtw;
+ uint32_t tras_max;
+ uint32_t tras_min;
+ uint32_t tfaw;
+ uint32_t trfc;
+ uint32_t tdqsck;
+ uint32_t tdqsck_max;
+ /* pd or sr */
+ uint32_t txsr;
+ uint32_t txsnr;
+ uint32_t txp;
+ uint32_t txpdll;
+ uint32_t tdllk;
+ uint32_t tcke;
+ uint32_t tckesr;
+ uint32_t tcksre;
+ uint32_t tcksrx;
+ uint32_t tdpd;
+ /* mode regiter timing */
+ uint32_t tmod;
+ uint32_t tmrd;
+ uint32_t tmrr;
+ uint32_t tmrri;
+ /* ODT */
+ uint32_t todton;
+ /* ZQ */
+ uint32_t tzqinit;
+ uint32_t tzqcs;
+ uint32_t tzqoper;
+ uint32_t tzqreset;
+ /* Write Leveling */
+ uint32_t twlmrd;
+ uint32_t twlo;
+ uint32_t twldqsen;
+ /* CA Training */
+ uint32_t tcackel;
+ uint32_t tcaent;
+ uint32_t tcamrd;
+ uint32_t tcackeh;
+ uint32_t tcaext;
+ uint32_t tadr;
+ uint32_t tmrz;
+ uint32_t tcacd;
+ /* mode register */
+ uint32_t mr[4];
+ uint32_t mr11;
+ /* lpddr4 spec */
+ uint32_t mr12;
+ uint32_t mr13;
+ uint32_t mr14;
+ uint32_t mr16;
+ uint32_t mr17;
+ uint32_t mr20;
+ uint32_t mr22;
+ uint32_t tccdmw;
+ uint32_t tppd;
+ uint32_t tescke;
+ uint32_t tsr;
+ uint32_t tcmdcke;
+ uint32_t tcscke;
+ uint32_t tckelcs;
+ uint32_t tcsckeh;
+ uint32_t tckehcs;
+ uint32_t tmrwckel;
+ uint32_t tzqcal;
+ uint32_t tzqlat;
+ uint32_t tzqcke;
+ uint32_t tvref_long;
+ uint32_t tvref_short;
+ uint32_t tvrcg_enable;
+ uint32_t tvrcg_disable;
+ uint32_t tfc_long;
+ uint32_t tckfspe;
+ uint32_t tckfspx;
+ uint32_t tckehcmd;
+ uint32_t tckelcmd;
+ uint32_t tckelpd;
+ uint32_t tckckel;
+ /* other */
+ uint32_t al;
+ uint32_t cl;
+ uint32_t cwl;
+ uint32_t bl;
+};
+
+struct dram_info_t {
+ /* speed_rate only used when DDR3 */
+ enum ddr3_speed_rate speed_rate;
+ /* 1: use CS0, 2: use CS0 and CS1 */
+ uint32_t cs_cnt;
+ /* give the max per-die capability on each rank/cs */
+ uint32_t per_die_capability[2];
+};
+
+struct timing_related_config {
+ struct dram_info_t dram_info[2];
+ uint32_t dram_type;
+ /* MHz */
+ uint32_t freq;
+ uint32_t ch_cnt;
+ uint32_t bl;
+ /* 1:auto precharge, 0:never auto precharge */
+ uint32_t ap;
+ /*
+ * 1:dll bypass, 0:dll normal
+ * dram and controller dll bypass at the same time
+ */
+ uint32_t dllbp;
+ /* 1:odt enable, 0:odt disable */
+ uint32_t odt;
+ /* 1:enable, 0:disabe */
+ uint32_t rdbi;
+ uint32_t wdbi;
+ /* dram driver strength */
+ uint32_t dramds;
+ /* dram ODT, if odt=0, this parameter invalid */
+ uint32_t dramodt;
+ /*
+ * ca ODT, if odt=0, this parameter invalid
+ * it only used by LPDDR4
+ */
+ uint32_t caodt;
+};
+
+/* mr0 for ddr3 */
+#define DDR3_BL8 (0)
+#define DDR3_BC4_8 (1)
+#define DDR3_BC4 (2)
+#define DDR3_CL(n) (((((n) - 4) & 0x7) << 4)\
+ | ((((n) - 4) & 0x8) >> 1))
+#define DDR3_WR(n) (((n) & 0x7) << 9)
+#define DDR3_DLL_RESET (1 << 8)
+#define DDR3_DLL_DERESET (0 << 8)
+
+/* mr1 for ddr3 */
+#define DDR3_DLL_ENABLE (0)
+#define DDR3_DLL_DISABLE (1)
+#define DDR3_MR1_AL(n) (((n) & 0x3) << 3)
+
+#define DDR3_DS_40 (0)
+#define DDR3_DS_34 (1 << 1)
+#define DDR3_RTT_NOM_DIS (0)
+#define DDR3_RTT_NOM_60 (1 << 2)
+#define DDR3_RTT_NOM_120 (1 << 6)
+#define DDR3_RTT_NOM_40 ((1 << 2) | (1 << 6))
+#define DDR3_TDQS (1 << 11)
+
+/* mr2 for ddr3 */
+#define DDR3_MR2_CWL(n) ((((n) - 5) & 0x7) << 3)
+#define DDR3_RTT_WR_DIS (0)
+#define DDR3_RTT_WR_60 (1 << 9)
+#define DDR3_RTT_WR_120 (2 << 9)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete, 1:DAI still in progress
+ */
+#define LPDDR2_DAI (0x1)
+/* 0:S2 or S4 SDRAM, 1:NVM */
+#define LPDDR2_DI (0x1 << 1)
+/* 0:DNV not supported, 1:DNV supported */
+#define LPDDR2_DNVI (0x1 << 2)
+#define LPDDR2_RZQI (0x3 << 3)
+
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+
+/* MR1 (Device Feature) */
+#define LPDDR2_BL4 (0x2)
+#define LPDDR2_BL8 (0x3)
+#define LPDDR2_BL16 (0x4)
+#define LPDDR2_N_WR(n) (((n) - 2) << 5)
+
+/* MR2 (Device Feature 2) */
+#define LPDDR2_RL3_WL1 (0x1)
+#define LPDDR2_RL4_WL2 (0x2)
+#define LPDDR2_RL5_WL2 (0x3)
+#define LPDDR2_RL6_WL3 (0x4)
+#define LPDDR2_RL7_WL4 (0x5)
+#define LPDDR2_RL8_WL4 (0x6)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR2_DS_34 (0x1)
+#define LPDDR2_DS_40 (0x2)
+#define LPDDR2_DS_48 (0x3)
+#define LPDDR2_DS_60 (0x4)
+#define LPDDR2_DS_80 (0x6)
+/* optional */
+#define LPDDR2_DS_120 (0x7)
+
+/* MR4 (Device Temperature) */
+#define LPDDR2_TREF_MASK (0x7)
+#define LPDDR2_4_TREF (0x1)
+#define LPDDR2_2_TREF (0x2)
+#define LPDDR2_1_TREF (0x3)
+#define LPDDR2_025_TREF (0x5)
+#define LPDDR2_025_TREF_DERATE (0x6)
+
+#define LPDDR2_TUF (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR2_S4 (0x0)
+#define LPDDR2_S2 (0x1)
+#define LPDDR2_N (0x2)
+/* Unit:MB */
+#define LPDDR2_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR2_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR2_ZQINIT (0xff)
+#define LPDDR2_ZQCL (0xab)
+#define LPDDR2_ZQCS (0x56)
+#define LPDDR2_ZQRESET (0xc3)
+
+/* MR16 (PASR Bank Mask), S2 SDRAM Only */
+#define LPDDR2_PASR_FULL (0x0)
+#define LPDDR2_PASR_1_2 (0x1)
+#define LPDDR2_PASR_1_4 (0x2)
+#define LPDDR2_PASR_1_8 (0x3)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete,
+ * 1:DAI still in progress
+ */
+#define LPDDR3_DAI (0x1)
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+#define LPDDR3_RZQI (0x3 << 3)
+/*
+ * 0:DRAM does not support WL(Set B),
+ * 1:DRAM support WL(Set B)
+ */
+#define LPDDR3_WL_SUPOT (1 << 6)
+/*
+ * 0:DRAM does not support RL=3,nWR=3,WL=1;
+ * 1:DRAM supports RL=3,nWR=3,WL=1 for frequencies <=166
+ */
+#define LPDDR3_RL3_SUPOT (1 << 7)
+
+/* MR1 (Device Feature) */
+#define LPDDR3_BL8 (0x3)
+#define LPDDR3_N_WR(n) ((n) << 5)
+
+/* MR2 (Device Feature 2), WL Set A,default */
+/* <=166MHz,optional*/
+#define LPDDR3_RL3_WL1 (0x1)
+/* <=400MHz*/
+#define LPDDR3_RL6_WL3 (0x4)
+/* <=533MHz*/
+#define LPDDR3_RL8_WL4 (0x6)
+/* <=600MHz*/
+#define LPDDR3_RL9_WL5 (0x7)
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL6 (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL6 (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL6 (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL8 (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL8 (0xe)
+
+/* WL Set B, optional */
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL8 (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL9 (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL9 (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL11 (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL13 (0xe)
+
+/* 1:enable nWR programming > 9(default)*/
+#define LPDDR3_N_WRE (1 << 4)
+/* 1:Select WL Set B*/
+#define LPDDR3_WL_S (1 << 6)
+/* 1:enable*/
+#define LPDDR3_WR_LEVEL (1 << 7)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR3_DS_34 (0x1)
+#define LPDDR3_DS_40 (0x2)
+#define LPDDR3_DS_48 (0x3)
+#define LPDDR3_DS_60 (0x4)
+#define LPDDR3_DS_80 (0x6)
+#define LPDDR3_DS_34D_40U (0x9)
+#define LPDDR3_DS_40D_48U (0xa)
+#define LPDDR3_DS_34D_48U (0xb)
+
+/* MR4 (Device Temperature) */
+#define LPDDR3_TREF_MASK (0x7)
+/* SDRAM Low temperature operating limit exceeded */
+#define LPDDR3_LT_EXED (0x0)
+#define LPDDR3_4_TREF (0x1)
+#define LPDDR3_2_TREF (0x2)
+#define LPDDR3_1_TREF (0x3)
+#define LPDDR3_05_TREF (0x4)
+#define LPDDR3_025_TREF (0x5)
+#define LPDDR3_025_TREF_DERATE (0x6)
+/* SDRAM High temperature operating limit exceeded */
+#define LPDDR3_HT_EXED (0x7)
+
+/* 1:value has changed since last read of MR4 */
+#define LPDDR3_TUF (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR3_S8 (0x3)
+#define LPDDR3_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR3_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR3_ZQINIT (0xff)
+#define LPDDR3_ZQCL (0xab)
+#define LPDDR3_ZQCS (0x56)
+#define LPDDR3_ZQRESET (0xc3)
+
+/* MR11 (ODT Control) */
+#define LPDDR3_ODT_60 (1)
+#define LPDDR3_ODT_120 (2)
+#define LPDDR3_ODT_240 (3)
+#define LPDDR3_ODT_DIS (0)
+
+/* MR2 (Device Feature 2) */
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL6_NRTP8 (0x0)
+#define LPDDR4_RL10_NRTP8 (0x1)
+#define LPDDR4_RL14_NRTP8 (0x2)
+#define LPDDR4_RL20_NRTP8 (0x3)
+#define LPDDR4_RL24_NRTP10 (0x4)
+#define LPDDR4_RL28_NRTP12 (0x5)
+#define LPDDR4_RL32_NRTP14 (0x6)
+#define LPDDR4_RL36_NRTP16 (0x7)
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL12_NRTP8 (0x1)
+#define LPDDR4_RL16_NRTP8 (0x2)
+#define LPDDR4_RL22_NRTP8 (0x3)
+#define LPDDR4_RL28_NRTP10 (0x4)
+#define LPDDR4_RL32_NRTP12 (0x5)
+#define LPDDR4_RL36_NRTP14 (0x6)
+#define LPDDR4_RL40_NRTP16 (0x7)
+/* WL Set A,default */
+#define LPDDR4_A_WL4 (0x0)
+#define LPDDR4_A_WL6 (0x1)
+#define LPDDR4_A_WL8 (0x2)
+#define LPDDR4_A_WL10 (0x3)
+#define LPDDR4_A_WL12 (0x4)
+#define LPDDR4_A_WL14 (0x5)
+#define LPDDR4_A_WL16 (0x6)
+#define LPDDR4_A_WL18 (0x7)
+/* WL Set B, optional */
+#define LPDDR4_B_WL4 (0x0 << 3)
+#define LPDDR4_B_WL8 (0x1 << 3)
+#define LPDDR4_B_WL12 (0x2 << 3)
+#define LPDDR4_B_WL18 (0x3 << 3)
+#define LPDDR4_B_WL22 (0x4 << 3)
+#define LPDDR4_B_WL26 (0x5 << 3)
+#define LPDDR4_B_WL30 (0x6 << 3)
+#define LPDDR4_B_WL34 (0x7 << 3)
+/* 1:Select WL Set B*/
+#define LPDDR4_WL_B (1 << 6)
+/* 1:enable*/
+#define LPDDR4_WR_LEVEL (1 << 7)
+
+/* MR3 */
+#define LPDDR4_VDDQ_2_5 (0)
+#define LPDDR4_VDDQ_3 (1)
+#define LPDDR4_WRPST_0_5_TCK (0 << 1)
+#define LPDDR4_WRPST_1_5_TCK (1 << 1)
+#define LPDDR4_PPR_EN (1 << 2)
+/* PDDS */
+#define LPDDR4_PDDS_240 (0x1 << 3)
+#define LPDDR4_PDDS_120 (0x2 << 3)
+#define LPDDR4_PDDS_80 (0x3 << 3)
+#define LPDDR4_PDDS_60 (0x4 << 3)
+#define LPDDR4_PDDS_48 (0x5 << 3)
+#define LPDDR4_PDDS_40 (0x6 << 3)
+#define LPDDR4_DBI_RD_EN (1 << 6)
+#define LPDDR4_DBI_WR_EN (1 << 7)
+
+/* MR11 (ODT Control) */
+#define LPDDR4_DQODT_240 (1)
+#define LPDDR4_DQODT_120 (2)
+#define LPDDR4_DQODT_80 (3)
+#define LPDDR4_DQODT_60 (4)
+#define LPDDR4_DQODT_48 (5)
+#define LPDDR4_DQODT_40 (6)
+#define LPDDR4_DQODT_DIS (0)
+#define LPDDR4_CAODT_240 (1 << 4)
+#define LPDDR4_CAODT_120 (2 << 4)
+#define LPDDR4_CAODT_80 (3 << 4)
+#define LPDDR4_CAODT_60 (4 << 4)
+#define LPDDR4_CAODT_48 (5 << 4)
+#define LPDDR4_CAODT_40 (6 << 4)
+#define LPDDR4_CAODT_DIS (0 << 4)
+
+/*
+ * Description: depend on input parameter "timing_config",
+ * and calculate correspond "dram_type"
+ * spec timing to "pdram_timing"
+ * parameters:
+ * input: timing_config
+ * output: pdram_timing
+ * NOTE: MR ODT is set, need to disable by controller
+ */
+void dram_get_parameter(struct timing_related_config *timing_config,
+ struct dram_timing_t *pdram_timing);
+
+#endif /* DRAM_SPEC_TIMING_H */
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c
new file mode 100644
index 0000000..a8b1c32
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+
+#include <dram.h>
+#include <plat_private.h>
+#include <pmu.h>
+#include <pmu_bits.h>
+#include <pmu_regs.h>
+#include <rk3399_def.h>
+#include <secure.h>
+#include <soc.h>
+#include <suspend.h>
+
+#define PMUGRF_OS_REG0 0x300
+#define PMUGRF_OS_REG1 0x304
+#define PMUGRF_OS_REG2 0x308
+#define PMUGRF_OS_REG3 0x30c
+
+#define CRU_SFTRST_DDR_CTRL(ch, n) ((0x1 << (8 + 16 + (ch) * 4)) | \
+ ((n) << (8 + (ch) * 4)))
+#define CRU_SFTRST_DDR_PHY(ch, n) ((0x1 << (9 + 16 + (ch) * 4)) | \
+ ((n) << (9 + (ch) * 4)))
+
+#define FBDIV_ENC(n) ((n) << 16)
+#define FBDIV_DEC(n) (((n) >> 16) & 0xfff)
+#define POSTDIV2_ENC(n) ((n) << 12)
+#define POSTDIV2_DEC(n) (((n) >> 12) & 0x7)
+#define POSTDIV1_ENC(n) ((n) << 8)
+#define POSTDIV1_DEC(n) (((n) >> 8) & 0x7)
+#define REFDIV_ENC(n) (n)
+#define REFDIV_DEC(n) ((n) & 0x3f)
+
+/* PMU CRU */
+#define PMUCRU_RSTNHOLD_CON0 0x120
+#define PMUCRU_RSTNHOLD_CON1 0x124
+
+#define PRESET_GPIO0_HOLD(n) (((n) << 7) | WMSK_BIT(7))
+#define PRESET_GPIO1_HOLD(n) (((n) << 8) | WMSK_BIT(8))
+
+#define SYS_COUNTER_FREQ_IN_MHZ (SYS_COUNTER_FREQ_IN_TICKS / 1000000)
+
+__pmusramdata uint32_t dpll_data[PLL_CON_COUNT];
+__pmusramdata uint32_t cru_clksel_con6;
+__pmusramdata uint8_t pmu_enable_watchdog0;
+
+/*
+ * Copy @num registers from @src to @dst
+ */
+static __pmusramfunc void sram_regcpy(uintptr_t dst, uintptr_t src,
+ uint32_t num)
+{
+ while (num--) {
+ mmio_write_32(dst, mmio_read_32(src));
+ dst += sizeof(uint32_t);
+ src += sizeof(uint32_t);
+ }
+}
+
+/*
+ * Copy @num registers from @src to @dst
+ * This is intentionally a copy of the sram_regcpy function. PMUSRAM functions
+ * cannot be called from code running in DRAM.
+ */
+static void dram_regcpy(uintptr_t dst, uintptr_t src, uint32_t num)
+{
+ while (num--) {
+ mmio_write_32(dst, mmio_read_32(src));
+ dst += sizeof(uint32_t);
+ src += sizeof(uint32_t);
+ }
+}
+
+static __pmusramfunc uint32_t sram_get_timer_value(void)
+{
+ /*
+ * Generic delay timer implementation expects the timer to be a down
+ * counter. We apply bitwise NOT operator to the tick values returned
+ * by read_cntpct_el0() to simulate the down counter.
+ */
+ return (uint32_t)(~read_cntpct_el0());
+}
+
+static __pmusramfunc void sram_udelay(uint32_t usec)
+{
+ uint32_t start, cnt, delta, total_ticks;
+
+ /* counter is decreasing */
+ start = sram_get_timer_value();
+ total_ticks = usec * SYS_COUNTER_FREQ_IN_MHZ;
+ do {
+ cnt = sram_get_timer_value();
+ if (cnt > start) {
+ delta = UINT32_MAX - cnt;
+ delta += start;
+ } else
+ delta = start - cnt;
+ } while (delta <= total_ticks);
+}
+
+static __pmusramfunc void configure_sgrf(void)
+{
+ /*
+ * SGRF_DDR_RGN_DPLL_CLK and SGRF_DDR_RGN_RTC_CLK:
+ * IC ECO bug, need to set this register.
+ *
+ * SGRF_DDR_RGN_BYPS:
+ * After the PD_CENTER suspend/resume, the DDR region
+ * related registers in the SGRF will be reset, we
+ * need to re-initialize them.
+ */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16),
+ SGRF_DDR_RGN_DPLL_CLK |
+ SGRF_DDR_RGN_RTC_CLK |
+ SGRF_DDR_RGN_BYPS);
+}
+
+static __pmusramfunc void rkclk_ddr_reset(uint32_t channel, uint32_t ctl,
+ uint32_t phy)
+{
+ channel &= 0x1;
+ ctl &= 0x1;
+ phy &= 0x1;
+ mmio_write_32(CRU_BASE + CRU_SOFTRST_CON(4),
+ CRU_SFTRST_DDR_CTRL(channel, ctl) |
+ CRU_SFTRST_DDR_PHY(channel, phy));
+}
+
+static __pmusramfunc void phy_pctrl_reset(uint32_t ch)
+{
+ rkclk_ddr_reset(ch, 1, 1);
+ sram_udelay(10);
+ rkclk_ddr_reset(ch, 1, 0);
+ sram_udelay(10);
+ rkclk_ddr_reset(ch, 0, 0);
+ sram_udelay(10);
+}
+
+static __pmusramfunc void set_cs_training_index(uint32_t ch, uint32_t rank)
+{
+ uint32_t byte;
+
+ /* PHY_8/136/264/392 phy_per_cs_training_index_X 1bit offset_24 */
+ for (byte = 0; byte < 4; byte++)
+ mmio_clrsetbits_32(PHY_REG(ch, 8 + (128 * byte)), 0x1 << 24,
+ rank << 24);
+}
+
+static __pmusramfunc void select_per_cs_training_index(uint32_t ch,
+ uint32_t rank)
+{
+ /* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */
+ if ((mmio_read_32(PHY_REG(ch, 84)) >> 16) & 1)
+ set_cs_training_index(ch, rank);
+}
+
+static __pmusramfunc void override_write_leveling_value(uint32_t ch)
+{
+ uint32_t byte;
+
+ for (byte = 0; byte < 4; byte++) {
+ /*
+ * PHY_8/136/264/392
+ * phy_per_cs_training_multicast_en_X 1bit offset_16
+ */
+ mmio_clrsetbits_32(PHY_REG(ch, 8 + (128 * byte)), 0x1 << 16,
+ 1 << 16);
+ mmio_clrsetbits_32(PHY_REG(ch, 63 + (128 * byte)),
+ 0xffffu << 16,
+ 0x200 << 16);
+ }
+
+ /* CTL_200 ctrlupd_req 1bit offset_8 */
+ mmio_clrsetbits_32(CTL_REG(ch, 200), 0x1 << 8, 0x1 << 8);
+}
+
+static __pmusramfunc int data_training(uint32_t ch,
+ struct rk3399_sdram_params *sdram_params,
+ uint32_t training_flag)
+{
+ uint32_t obs_0, obs_1, obs_2, obs_3, obs_err = 0;
+ uint32_t rank = sdram_params->ch[ch].rank;
+ uint32_t rank_mask;
+ uint32_t i, tmp;
+
+ if (sdram_params->dramtype == LPDDR4)
+ rank_mask = (rank == 1) ? 0x5 : 0xf;
+ else
+ rank_mask = (rank == 1) ? 0x1 : 0x3;
+
+ /* PHY_927 PHY_PAD_DQS_DRIVE RPULL offset_22 */
+ mmio_setbits_32(PHY_REG(ch, 927), (1 << 22));
+
+ if (training_flag == PI_FULL_TRAINING) {
+ if (sdram_params->dramtype == LPDDR4) {
+ training_flag = PI_WRITE_LEVELING |
+ PI_READ_GATE_TRAINING |
+ PI_READ_LEVELING |
+ PI_WDQ_LEVELING;
+ } else if (sdram_params->dramtype == LPDDR3) {
+ training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |
+ PI_READ_GATE_TRAINING;
+ } else if (sdram_params->dramtype == DDR3) {
+ training_flag = PI_WRITE_LEVELING |
+ PI_READ_GATE_TRAINING |
+ PI_READ_LEVELING;
+ }
+ }
+
+ /* ca training(LPDDR4,LPDDR3 support) */
+ if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING) {
+ for (i = 0; i < 4; i++) {
+ if (!(rank_mask & (1 << i)))
+ continue;
+
+ select_per_cs_training_index(ch, i);
+ /* PI_100 PI_CALVL_EN:RW:8:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 100), 0x3 << 8, 0x2 << 8);
+
+ /* PI_92 PI_CALVL_REQ:WR:16:1,PI_CALVL_CS:RW:24:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 92),
+ (0x1 << 16) | (0x3 << 24),
+ (0x1 << 16) | (i << 24));
+ while (1) {
+ /* PI_174 PI_INT_STATUS:RD:8:18 */
+ tmp = mmio_read_32(PI_REG(ch, 174)) >> 8;
+
+ /*
+ * check status obs
+ * PHY_532/660/788 phy_adr_calvl_obs1_:0:32
+ */
+ obs_0 = mmio_read_32(PHY_REG(ch, 532));
+ obs_1 = mmio_read_32(PHY_REG(ch, 660));
+ obs_2 = mmio_read_32(PHY_REG(ch, 788));
+ if (((obs_0 >> 30) & 0x3) ||
+ ((obs_1 >> 30) & 0x3) ||
+ ((obs_2 >> 30) & 0x3))
+ obs_err = 1;
+ if ((((tmp >> 11) & 0x1) == 0x1) &&
+ (((tmp >> 13) & 0x1) == 0x1) &&
+ (((tmp >> 5) & 0x1) == 0x0) &&
+ (obs_err == 0))
+ break;
+ else if ((((tmp >> 5) & 0x1) == 0x1) ||
+ (obs_err == 1))
+ return -1;
+ }
+ /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+ mmio_write_32(PI_REG(ch, 175), 0x00003f7c);
+ }
+ mmio_clrbits_32(PI_REG(ch, 100), 0x3 << 8);
+ }
+
+ /* write leveling(LPDDR4,LPDDR3,DDR3 support) */
+ if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING) {
+ for (i = 0; i < rank; i++) {
+ select_per_cs_training_index(ch, i);
+ /* PI_60 PI_WRLVL_EN:RW:8:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 60), 0x3 << 8, 0x2 << 8);
+ /* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 59),
+ (0x1 << 8) | (0x3 << 16),
+ (0x1 << 8) | (i << 16));
+
+ while (1) {
+ /* PI_174 PI_INT_STATUS:RD:8:18 */
+ tmp = mmio_read_32(PI_REG(ch, 174)) >> 8;
+
+ /*
+ * check status obs, if error maybe can not
+ * get leveling done PHY_40/168/296/424
+ * phy_wrlvl_status_obs_X:0:13
+ */
+ obs_0 = mmio_read_32(PHY_REG(ch, 40));
+ obs_1 = mmio_read_32(PHY_REG(ch, 168));
+ obs_2 = mmio_read_32(PHY_REG(ch, 296));
+ obs_3 = mmio_read_32(PHY_REG(ch, 424));
+ if (((obs_0 >> 12) & 0x1) ||
+ ((obs_1 >> 12) & 0x1) ||
+ ((obs_2 >> 12) & 0x1) ||
+ ((obs_3 >> 12) & 0x1))
+ obs_err = 1;
+ if ((((tmp >> 10) & 0x1) == 0x1) &&
+ (((tmp >> 13) & 0x1) == 0x1) &&
+ (((tmp >> 4) & 0x1) == 0x0) &&
+ (obs_err == 0))
+ break;
+ else if ((((tmp >> 4) & 0x1) == 0x1) ||
+ (obs_err == 1))
+ return -1;
+ }
+
+ /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+ mmio_write_32(PI_REG(ch, 175), 0x00003f7c);
+ }
+ override_write_leveling_value(ch);
+ mmio_clrbits_32(PI_REG(ch, 60), 0x3 << 8);
+ }
+
+ /* read gate training(LPDDR4,LPDDR3,DDR3 support) */
+ if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING) {
+ for (i = 0; i < rank; i++) {
+ select_per_cs_training_index(ch, i);
+ /* PI_80 PI_RDLVL_GATE_EN:RW:24:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 80), 0x3 << 24,
+ 0x2 << 24);
+ /*
+ * PI_74 PI_RDLVL_GATE_REQ:WR:16:1
+ * PI_RDLVL_CS:RW:24:2
+ */
+ mmio_clrsetbits_32(PI_REG(ch, 74),
+ (0x1 << 16) | (0x3 << 24),
+ (0x1 << 16) | (i << 24));
+
+ while (1) {
+ /* PI_174 PI_INT_STATUS:RD:8:18 */
+ tmp = mmio_read_32(PI_REG(ch, 174)) >> 8;
+
+ /*
+ * check status obs
+ * PHY_43/171/299/427
+ * PHY_GTLVL_STATUS_OBS_x:16:8
+ */
+ obs_0 = mmio_read_32(PHY_REG(ch, 43));
+ obs_1 = mmio_read_32(PHY_REG(ch, 171));
+ obs_2 = mmio_read_32(PHY_REG(ch, 299));
+ obs_3 = mmio_read_32(PHY_REG(ch, 427));
+ if (((obs_0 >> (16 + 6)) & 0x3) ||
+ ((obs_1 >> (16 + 6)) & 0x3) ||
+ ((obs_2 >> (16 + 6)) & 0x3) ||
+ ((obs_3 >> (16 + 6)) & 0x3))
+ obs_err = 1;
+ if ((((tmp >> 9) & 0x1) == 0x1) &&
+ (((tmp >> 13) & 0x1) == 0x1) &&
+ (((tmp >> 3) & 0x1) == 0x0) &&
+ (obs_err == 0))
+ break;
+ else if ((((tmp >> 3) & 0x1) == 0x1) ||
+ (obs_err == 1))
+ return -1;
+ }
+ /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+ mmio_write_32(PI_REG(ch, 175), 0x00003f7c);
+ }
+ mmio_clrbits_32(PI_REG(ch, 80), 0x3 << 24);
+ }
+
+ /* read leveling(LPDDR4,LPDDR3,DDR3 support) */
+ if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING) {
+ for (i = 0; i < rank; i++) {
+ select_per_cs_training_index(ch, i);
+ /* PI_80 PI_RDLVL_EN:RW:16:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 80), 0x3 << 16,
+ 0x2 << 16);
+ /* PI_74 PI_RDLVL_REQ:WR:8:1,PI_RDLVL_CS:RW:24:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 74),
+ (0x1 << 8) | (0x3 << 24),
+ (0x1 << 8) | (i << 24));
+ while (1) {
+ /* PI_174 PI_INT_STATUS:RD:8:18 */
+ tmp = mmio_read_32(PI_REG(ch, 174)) >> 8;
+
+ /*
+ * make sure status obs not report error bit
+ * PHY_46/174/302/430
+ * phy_rdlvl_status_obs_X:16:8
+ */
+ if ((((tmp >> 8) & 0x1) == 0x1) &&
+ (((tmp >> 13) & 0x1) == 0x1) &&
+ (((tmp >> 2) & 0x1) == 0x0))
+ break;
+ else if (((tmp >> 2) & 0x1) == 0x1)
+ return -1;
+ }
+ /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+ mmio_write_32(PI_REG(ch, 175), 0x00003f7c);
+ }
+ mmio_clrbits_32(PI_REG(ch, 80), 0x3 << 16);
+ }
+
+ /* wdq leveling(LPDDR4 support) */
+ if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING) {
+ for (i = 0; i < 4; i++) {
+ if (!(rank_mask & (1 << i)))
+ continue;
+
+ select_per_cs_training_index(ch, i);
+ /*
+ * disable PI_WDQLVL_VREF_EN before wdq leveling?
+ * PI_181 PI_WDQLVL_VREF_EN:RW:8:1
+ */
+ mmio_clrbits_32(PI_REG(ch, 181), 0x1 << 8);
+ /* PI_124 PI_WDQLVL_EN:RW:16:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 124), 0x3 << 16,
+ 0x2 << 16);
+ /* PI_121 PI_WDQLVL_REQ:WR:8:1,PI_WDQLVL_CS:RW:16:2 */
+ mmio_clrsetbits_32(PI_REG(ch, 121),
+ (0x1 << 8) | (0x3 << 16),
+ (0x1 << 8) | (i << 16));
+ while (1) {
+ /* PI_174 PI_INT_STATUS:RD:8:18 */
+ tmp = mmio_read_32(PI_REG(ch, 174)) >> 8;
+ if ((((tmp >> 12) & 0x1) == 0x1) &&
+ (((tmp >> 13) & 0x1) == 0x1) &&
+ (((tmp >> 6) & 0x1) == 0x0))
+ break;
+ else if (((tmp >> 6) & 0x1) == 0x1)
+ return -1;
+ }
+ /* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
+ mmio_write_32(PI_REG(ch, 175), 0x00003f7c);
+ }
+ mmio_clrbits_32(PI_REG(ch, 124), 0x3 << 16);
+ }
+
+ /* PHY_927 PHY_PAD_DQS_DRIVE RPULL offset_22 */
+ mmio_clrbits_32(PHY_REG(ch, 927), (1 << 22));
+
+ return 0;
+}
+
+static __pmusramfunc void set_ddrconfig(
+ struct rk3399_sdram_params *sdram_params,
+ unsigned char channel, uint32_t ddrconfig)
+{
+ /* only need to set ddrconfig */
+ struct rk3399_sdram_channel *ch = &sdram_params->ch[channel];
+ unsigned int cs0_cap = 0;
+ unsigned int cs1_cap = 0;
+
+ cs0_cap = (1 << (ch->cs0_row + ch->col + ch->bk + ch->bw - 20));
+ if (ch->rank > 1)
+ cs1_cap = cs0_cap >> (ch->cs0_row - ch->cs1_row);
+ if (ch->row_3_4) {
+ cs0_cap = cs0_cap * 3 / 4;
+ cs1_cap = cs1_cap * 3 / 4;
+ }
+
+ mmio_write_32(MSCH_BASE(channel) + MSCH_DEVICECONF,
+ ddrconfig | (ddrconfig << 6));
+ mmio_write_32(MSCH_BASE(channel) + MSCH_DEVICESIZE,
+ ((cs0_cap / 32) & 0xff) | (((cs1_cap / 32) & 0xff) << 8));
+}
+
+static __pmusramfunc void dram_all_config(
+ struct rk3399_sdram_params *sdram_params)
+{
+ unsigned int i;
+
+ for (i = 0; i < 2; i++) {
+ struct rk3399_sdram_channel *info = &sdram_params->ch[i];
+ struct rk3399_msch_timings *noc = &info->noc_timings;
+
+ if (sdram_params->ch[i].col == 0)
+ continue;
+
+ mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGA0,
+ noc->ddrtiminga0.d32);
+ mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGB0,
+ noc->ddrtimingb0.d32);
+ mmio_write_32(MSCH_BASE(i) + MSCH_DDRTIMINGC0,
+ noc->ddrtimingc0.d32);
+ mmio_write_32(MSCH_BASE(i) + MSCH_DEVTODEV0,
+ noc->devtodev0.d32);
+ mmio_write_32(MSCH_BASE(i) + MSCH_DDRMODE, noc->ddrmode.d32);
+
+ /* rank 1 memory clock disable (dfi_dram_clk_disable = 1) */
+ if (sdram_params->ch[i].rank == 1)
+ mmio_setbits_32(CTL_REG(i, 276), 1 << 17);
+ }
+
+ DDR_STRIDE(sdram_params->stride);
+
+ /* reboot hold register set */
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS |
+ PRESET_GPIO0_HOLD(1) |
+ PRESET_GPIO1_HOLD(1));
+ mmio_clrsetbits_32(CRU_BASE + CRU_GLB_RST_CON, 0x3, 0x3);
+}
+
+static __pmusramfunc void pctl_cfg(uint32_t ch,
+ struct rk3399_sdram_params *sdram_params)
+{
+ const uint32_t *params_ctl = sdram_params->pctl_regs.denali_ctl;
+ const uint32_t *params_pi = sdram_params->pi_regs.denali_pi;
+ const struct rk3399_ddr_publ_regs *phy_regs = &sdram_params->phy_regs;
+ uint32_t tmp, tmp1, tmp2, i;
+
+ /*
+ * Workaround controller bug:
+ * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
+ */
+ sram_regcpy(CTL_REG(ch, 1), (uintptr_t)&params_ctl[1],
+ CTL_REG_NUM - 1);
+ mmio_write_32(CTL_REG(ch, 0), params_ctl[0]);
+ sram_regcpy(PI_REG(ch, 0), (uintptr_t)&params_pi[0],
+ PI_REG_NUM);
+
+ sram_regcpy(PHY_REG(ch, 910), (uintptr_t)&phy_regs->phy896[910 - 896],
+ 3);
+
+ mmio_clrsetbits_32(CTL_REG(ch, 68), PWRUP_SREFRESH_EXIT,
+ PWRUP_SREFRESH_EXIT);
+
+ /* PHY_DLL_RST_EN */
+ mmio_clrsetbits_32(PHY_REG(ch, 957), 0x3 << 24, 1 << 24);
+ dmbst();
+
+ mmio_setbits_32(PI_REG(ch, 0), START);
+ mmio_setbits_32(CTL_REG(ch, 0), START);
+
+ /* wait lock */
+ while (1) {
+ tmp = mmio_read_32(PHY_REG(ch, 920));
+ tmp1 = mmio_read_32(PHY_REG(ch, 921));
+ tmp2 = mmio_read_32(PHY_REG(ch, 922));
+ if ((((tmp >> 16) & 0x1) == 0x1) &&
+ (((tmp1 >> 16) & 0x1) == 0x1) &&
+ (((tmp1 >> 0) & 0x1) == 0x1) &&
+ (((tmp2 >> 0) & 0x1) == 0x1))
+ break;
+ /* if PLL bypass,don't need wait lock */
+ if (mmio_read_32(PHY_REG(ch, 911)) & 0x1)
+ break;
+ }
+
+ sram_regcpy(PHY_REG(ch, 896), (uintptr_t)&phy_regs->phy896[0], 63);
+
+ for (i = 0; i < 4; i++)
+ sram_regcpy(PHY_REG(ch, 128 * i),
+ (uintptr_t)&phy_regs->phy0[0], 91);
+
+ for (i = 0; i < 3; i++)
+ sram_regcpy(PHY_REG(ch, 512 + 128 * i),
+ (uintptr_t)&phy_regs->phy512[i][0], 38);
+}
+
+static __pmusramfunc int dram_switch_to_next_index(
+ struct rk3399_sdram_params *sdram_params)
+{
+ uint32_t ch, ch_count;
+ uint32_t fn = ((mmio_read_32(CTL_REG(0, 111)) >> 16) + 1) & 0x1;
+
+ mmio_write_32(CIC_BASE + CIC_CTRL0,
+ (((0x3 << 4) | (1 << 2) | 1) << 16) |
+ (fn << 4) | (1 << 2) | 1);
+ while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2)))
+ ;
+
+ mmio_write_32(CIC_BASE + CIC_CTRL0, 0x20002);
+ while (!(mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 0)))
+ ;
+
+ ch_count = sdram_params->num_channels;
+
+ /* LPDDR4 f2 cann't do training, all training will fail */
+ for (ch = 0; ch < ch_count; ch++) {
+ /*
+ * Without this disabled for LPDDR4 we end up writing 0's
+ * in place of real data in an interesting pattern.
+ */
+ if (sdram_params->dramtype != LPDDR4) {
+ mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
+ fn << 8);
+ }
+
+ /* data_training failed */
+ if (data_training(ch, sdram_params, PI_FULL_TRAINING))
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Needs to be done for both channels at once in case of a shared reset signal
+ * between channels.
+ */
+static __pmusramfunc int pctl_start(uint32_t channel_mask,
+ struct rk3399_sdram_params *sdram_params)
+{
+ uint32_t count;
+ uint32_t byte;
+
+ mmio_setbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT);
+ mmio_setbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT);
+
+ /* need de-access IO retention before controller START */
+ if (channel_mask & (1 << 0))
+ mmio_setbits_32(PMU_BASE + PMU_PWRMODE_CON, (1 << 19));
+ if (channel_mask & (1 << 1))
+ mmio_setbits_32(PMU_BASE + PMU_PWRMODE_CON, (1 << 23));
+
+ /* PHY_DLL_RST_EN */
+ if (channel_mask & (1 << 0))
+ mmio_clrsetbits_32(PHY_REG(0, 957), 0x3 << 24,
+ 0x2 << 24);
+ if (channel_mask & (1 << 1))
+ mmio_clrsetbits_32(PHY_REG(1, 957), 0x3 << 24,
+ 0x2 << 24);
+
+ /* check ERROR bit */
+ if (channel_mask & (1 << 0)) {
+ count = 0;
+ while (!(mmio_read_32(CTL_REG(0, 203)) & (1 << 3))) {
+ /* CKE is low, loop 10ms */
+ if (count > 100)
+ return -1;
+
+ sram_udelay(100);
+ count++;
+ }
+
+ mmio_clrbits_32(CTL_REG(0, 68), PWRUP_SREFRESH_EXIT);
+
+ /* Restore the PHY_RX_CAL_DQS value */
+ for (byte = 0; byte < 4; byte++)
+ mmio_clrsetbits_32(PHY_REG(0, 57 + 128 * byte),
+ 0xfff << 16,
+ sdram_params->rx_cal_dqs[0][byte]);
+ }
+ if (channel_mask & (1 << 1)) {
+ count = 0;
+ while (!(mmio_read_32(CTL_REG(1, 203)) & (1 << 3))) {
+ /* CKE is low, loop 10ms */
+ if (count > 100)
+ return -1;
+
+ sram_udelay(100);
+ count++;
+ }
+
+ mmio_clrbits_32(CTL_REG(1, 68), PWRUP_SREFRESH_EXIT);
+
+ /* Restore the PHY_RX_CAL_DQS value */
+ for (byte = 0; byte < 4; byte++)
+ mmio_clrsetbits_32(PHY_REG(1, 57 + 128 * byte),
+ 0xfff << 16,
+ sdram_params->rx_cal_dqs[1][byte]);
+ }
+
+ return 0;
+}
+
+__pmusramfunc static void pmusram_restore_pll(int pll_id, uint32_t *src)
+{
+ mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
+
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
+
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
+
+ while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
+ (1U << 31)) == 0x0)
+ ;
+}
+
+__pmusramfunc static void pmusram_enable_watchdog(void)
+{
+ /* Make the watchdog use the first global reset. */
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, 1 << 1);
+
+ /*
+ * This gives the system ~8 seconds before reset. The pclk for the
+ * watchdog is 4MHz on reset. The value of 0x9 in WDT_TORR means that
+ * the watchdog will wait for 0x1ffffff cycles before resetting.
+ */
+ mmio_write_32(WDT0_BASE + 4, 0x9);
+
+ /* Enable the watchdog */
+ mmio_setbits_32(WDT0_BASE, 0x1);
+
+ /* Magic reset the watchdog timer value for WDT_CRR. */
+ mmio_write_32(WDT0_BASE + 0xc, 0x76);
+
+ secure_watchdog_ungate();
+
+ /* The watchdog is in PD_ALIVE, so deidle it. */
+ mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, PMU_CLR_ALIVE);
+}
+
+void dmc_suspend(void)
+{
+ struct rk3399_sdram_params *sdram_params = &sdram_config;
+ struct rk3399_ddr_publ_regs *phy_regs;
+ uint32_t *params_ctl;
+ uint32_t *params_pi;
+ uint32_t refdiv, postdiv2, postdiv1, fbdiv;
+ uint32_t ch, byte, i;
+
+ phy_regs = &sdram_params->phy_regs;
+ params_ctl = sdram_params->pctl_regs.denali_ctl;
+ params_pi = sdram_params->pi_regs.denali_pi;
+
+ /* save dpll register and ddr clock register value to pmusram */
+ cru_clksel_con6 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON6);
+ for (i = 0; i < PLL_CON_COUNT; i++)
+ dpll_data[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(DPLL_ID, i));
+
+ fbdiv = dpll_data[0] & 0xfff;
+ postdiv2 = POSTDIV2_DEC(dpll_data[1]);
+ postdiv1 = POSTDIV1_DEC(dpll_data[1]);
+ refdiv = REFDIV_DEC(dpll_data[1]);
+
+ sdram_params->ddr_freq = ((fbdiv * 24) /
+ (refdiv * postdiv1 * postdiv2)) * MHz;
+
+ INFO("sdram_params->ddr_freq = %d\n", sdram_params->ddr_freq);
+ sdram_params->odt = (((mmio_read_32(PHY_REG(0, 5)) >> 16) &
+ 0x7) != 0) ? 1 : 0;
+
+ /* copy the registers CTL PI and PHY */
+ dram_regcpy((uintptr_t)&params_ctl[0], CTL_REG(0, 0), CTL_REG_NUM);
+
+ /* mask DENALI_CTL_00_DATA.START, only copy here, will trigger later */
+ params_ctl[0] &= ~(0x1 << 0);
+
+ dram_regcpy((uintptr_t)&params_pi[0], PI_REG(0, 0),
+ PI_REG_NUM);
+
+ /* mask DENALI_PI_00_DATA.START, only copy here, will trigger later*/
+ params_pi[0] &= ~(0x1 << 0);
+
+ dram_regcpy((uintptr_t)&phy_regs->phy0[0],
+ PHY_REG(0, 0), 91);
+
+ for (i = 0; i < 3; i++)
+ dram_regcpy((uintptr_t)&phy_regs->phy512[i][0],
+ PHY_REG(0, 512 + 128 * i), 38);
+
+ dram_regcpy((uintptr_t)&phy_regs->phy896[0], PHY_REG(0, 896), 63);
+
+ for (ch = 0; ch < sdram_params->num_channels; ch++) {
+ for (byte = 0; byte < 4; byte++)
+ sdram_params->rx_cal_dqs[ch][byte] = (0xfff << 16) &
+ mmio_read_32(PHY_REG(ch, 57 + byte * 128));
+ }
+
+ /* set DENALI_PHY_957_DATA.PHY_DLL_RST_EN = 0x1 */
+ phy_regs->phy896[957 - 896] &= ~(0x3 << 24);
+ phy_regs->phy896[957 - 896] |= 1 << 24;
+ phy_regs->phy896[0] |= 1;
+ phy_regs->phy896[0] &= ~(0x3 << 8);
+}
+
+__pmusramfunc void phy_dll_bypass_set(uint32_t ch, uint32_t freq)
+{
+ if (freq <= (125 * 1000 * 1000)) {
+ /* Set master mode to SW for slices*/
+ mmio_setbits_32(PHY_REG(ch, 86), 3 << 10);
+ mmio_setbits_32(PHY_REG(ch, 214), 3 << 10);
+ mmio_setbits_32(PHY_REG(ch, 342), 3 << 10);
+ mmio_setbits_32(PHY_REG(ch, 470), 3 << 10);
+ /* Set master mode to SW for address slices*/
+ mmio_setbits_32(PHY_REG(ch, 547), 3 << 18);
+ mmio_setbits_32(PHY_REG(ch, 675), 3 << 18);
+ mmio_setbits_32(PHY_REG(ch, 803), 3 << 18);
+ } else {
+ /* Clear SW master mode for slices*/
+ mmio_clrbits_32(PHY_REG(ch, 86), 3 << 10);
+ mmio_clrbits_32(PHY_REG(ch, 214), 3 << 10);
+ mmio_clrbits_32(PHY_REG(ch, 342), 3 << 10);
+ mmio_clrbits_32(PHY_REG(ch, 470), 3 << 10);
+ /* Clear SW master mode for address slices*/
+ mmio_clrbits_32(PHY_REG(ch, 547), 3 << 18);
+ mmio_clrbits_32(PHY_REG(ch, 675), 3 << 18);
+ mmio_clrbits_32(PHY_REG(ch, 803), 3 << 18);
+ }
+}
+
+__pmusramfunc void dmc_resume(void)
+{
+ struct rk3399_sdram_params *sdram_params = &sdram_config;
+ uint32_t channel_mask = 0;
+ uint32_t channel;
+
+ /*
+ * We can't turn off the watchdog, so if we have not turned it on before
+ * we should not turn it on here.
+ */
+ if ((pmu_enable_watchdog0 & 0x1) == 0x1) {
+ pmusram_enable_watchdog();
+ }
+ pmu_sgrf_rst_hld_release();
+ restore_pmu_rsthold();
+ sram_secure_timer_init();
+
+ /*
+ * we switch ddr clock to abpll when suspend,
+ * we set back to dpll here
+ */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON6,
+ cru_clksel_con6 | REG_SOC_WMSK);
+ pmusram_restore_pll(DPLL_ID, dpll_data);
+
+ configure_sgrf();
+
+retry:
+ for (channel = 0; channel < sdram_params->num_channels; channel++) {
+ phy_pctrl_reset(channel);
+ /*
+ * Without this, LPDDR4 will write 0's in place of real data
+ * in a strange pattern.
+ */
+ if (sdram_params->dramtype == LPDDR4) {
+ phy_dll_bypass_set(channel, sdram_params->ddr_freq);
+ }
+ pctl_cfg(channel, sdram_params);
+ }
+
+ for (channel = 0; channel < 2; channel++) {
+ if (sdram_params->ch[channel].col)
+ channel_mask |= 1 << channel;
+ }
+
+ if (pctl_start(channel_mask, sdram_params) < 0)
+ goto retry;
+
+ for (channel = 0; channel < sdram_params->num_channels; channel++) {
+ /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
+ if (sdram_params->dramtype == LPDDR3)
+ sram_udelay(10);
+
+ /*
+ * Training here will always fail for LPDDR4, so skip it
+ * If traning fail, retry to do it again.
+ */
+ if (sdram_params->dramtype != LPDDR4 &&
+ data_training(channel, sdram_params, PI_FULL_TRAINING))
+ goto retry;
+
+ set_ddrconfig(sdram_params, channel,
+ sdram_params->ch[channel].ddrconfig);
+ }
+
+ dram_all_config(sdram_params);
+
+ /* Switch to index 1 and prepare for DDR frequency switch. */
+ dram_switch_to_next_index(sdram_params);
+}
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.h b/plat/rockchip/rk3399/drivers/dram/suspend.h
new file mode 100644
index 0000000..1389944
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUSPEND_H
+#define SUSPEND_H
+
+#include <stdint.h>
+#include <dram.h>
+
+#define KHz (1000)
+#define MHz (1000 * KHz)
+#define GHz (1000 * MHz)
+
+#define PI_CA_TRAINING (1 << 0)
+#define PI_WRITE_LEVELING (1 << 1)
+#define PI_READ_GATE_TRAINING (1 << 2)
+#define PI_READ_LEVELING (1 << 3)
+#define PI_WDQ_LEVELING (1 << 4)
+#define PI_FULL_TRAINING (0xff)
+
+void dmc_suspend(void);
+__pmusramfunc void dmc_resume(void);
+extern __pmusramdata uint8_t pmu_enable_watchdog0;
+
+#endif /* SUSPEND_H */
diff --git a/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
new file mode 100644
index 0000000..724968f
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/gpio.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include <soc.h>
+
+struct gpio_save {
+ uint32_t swporta_dr;
+ uint32_t swporta_ddr;
+ uint32_t inten;
+ uint32_t intmask;
+ uint32_t inttype_level;
+ uint32_t int_polarity;
+ uint32_t debounce;
+ uint32_t ls_sync;
+} store_gpio[3];
+
+static uint32_t store_grf_gpio[(GRF_GPIO2D_HE - GRF_GPIO2A_IOMUX) / 4 + 1];
+
+#define SWPORTA_DR 0x00
+#define SWPORTA_DDR 0x04
+#define INTEN 0x30
+#define INTMASK 0x34
+#define INTTYPE_LEVEL 0x38
+#define INT_POLARITY 0x3c
+#define DEBOUNCE 0x48
+#define LS_SYNC 0x60
+
+#define EXT_PORTA 0x50
+#define PMU_GPIO_PORT0 0
+#define PMU_GPIO_PORT1 1
+#define GPIO_PORT2 2
+#define GPIO_PORT3 3
+#define GPIO_PORT4 4
+
+#define PMU_GRF_GPIO0A_P 0x40
+#define GRF_GPIO2A_P 0xe040
+#define GPIO_P_MASK 0x03
+
+#define GET_GPIO_PORT(pin) (pin / 32)
+#define GET_GPIO_NUM(pin) (pin % 32)
+#define GET_GPIO_BANK(pin) ((pin % 32) / 8)
+#define GET_GPIO_ID(pin) ((pin % 32) % 8)
+
+enum {
+ ENC_ZDZU,
+ ENC_ZUDR,
+ ENC_ZUDZ,
+ NUM_ENC
+};
+
+static const struct port_info {
+ uint32_t clkgate_reg;
+ uint32_t pull_base;
+ uint32_t port_base;
+ /*
+ * Selects the pull mode encoding per bank,
+ * first index for pull_type_{hw2sw,sw2hw}
+ */
+ uint8_t pull_enc[4];
+ uint8_t clkgate_bit;
+ uint8_t max_bank;
+} port_info[] = {
+ {
+ .clkgate_reg = PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
+ .pull_base = PMUGRF_BASE + PMUGRF_GPIO0A_P,
+ .port_base = GPIO0_BASE,
+ .pull_enc = {ENC_ZDZU, ENC_ZDZU},
+ .clkgate_bit = PCLK_GPIO0_GATE_SHIFT,
+ .max_bank = 1,
+ }, {
+ .clkgate_reg = PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
+ .pull_base = PMUGRF_BASE + PMUGRF_GPIO1A_P,
+ .port_base = GPIO1_BASE,
+ .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR},
+ .clkgate_bit = PCLK_GPIO1_GATE_SHIFT,
+ .max_bank = 3,
+ }, {
+ .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31),
+ .pull_base = GRF_BASE + GRF_GPIO2A_P,
+ .port_base = GPIO2_BASE,
+ .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZDZU, ENC_ZDZU},
+ .clkgate_bit = PCLK_GPIO2_GATE_SHIFT,
+ .max_bank = 3,
+ }, {
+ .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31),
+ .pull_base = GRF_BASE + GRF_GPIO3A_P,
+ .port_base = GPIO3_BASE,
+ .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR},
+ .clkgate_bit = PCLK_GPIO3_GATE_SHIFT,
+ .max_bank = 3,
+ }, {
+ .clkgate_reg = CRU_BASE + CRU_CLKGATE_CON(31),
+ .pull_base = GRF_BASE + GRF_GPIO4A_P,
+ .port_base = GPIO4_BASE,
+ .pull_enc = {ENC_ZUDR, ENC_ZUDR, ENC_ZUDR, ENC_ZUDR},
+ .clkgate_bit = PCLK_GPIO4_GATE_SHIFT,
+ .max_bank = 3,
+ }
+};
+
+/*
+ * Mappings between TF-A constants and hardware encodings:
+ * there are 3 different encoding schemes that may differ between
+ * banks of the same port: the corresponding value of the pull_enc array
+ * in port_info is used as the first index
+ */
+static const uint8_t pull_type_hw2sw[NUM_ENC][4] = {
+ [ENC_ZDZU] = {GPIO_PULL_NONE, GPIO_PULL_DOWN, GPIO_PULL_NONE, GPIO_PULL_UP},
+ [ENC_ZUDR] = {GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN, GPIO_PULL_REPEATER},
+ [ENC_ZUDZ] = {GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN, GPIO_PULL_NONE}
+};
+static const uint8_t pull_type_sw2hw[NUM_ENC][4] = {
+ [ENC_ZDZU] = {
+ [GPIO_PULL_NONE] = 0,
+ [GPIO_PULL_DOWN] = 1,
+ [GPIO_PULL_UP] = 3,
+ [GPIO_PULL_REPEATER] = -1
+ },
+ [ENC_ZUDR] = {
+ [GPIO_PULL_NONE] = 0,
+ [GPIO_PULL_DOWN] = 2,
+ [GPIO_PULL_UP] = 1,
+ [GPIO_PULL_REPEATER] = 3
+ },
+ [ENC_ZUDZ] = {
+ [GPIO_PULL_NONE] = 0,
+ [GPIO_PULL_DOWN] = 2,
+ [GPIO_PULL_UP] = 1,
+ [GPIO_PULL_REPEATER] = -1
+ }
+};
+
+/* Return old clock state, enables clock, in order to do GPIO access */
+static int gpio_get_clock(uint32_t gpio_number)
+{
+ uint32_t port = GET_GPIO_PORT(gpio_number);
+ assert(port < 5U);
+
+ const struct port_info *info = &port_info[port];
+
+ if ((mmio_read_32(info->clkgate_reg) & (1U << info->clkgate_bit)) == 0U) {
+ return 0;
+ }
+ mmio_write_32(
+ info->clkgate_reg,
+ BITS_WITH_WMASK(0, 1, info->clkgate_bit)
+ );
+ return 1;
+}
+
+/* Restore old state of gpio clock, assuming it is running now */
+void gpio_put_clock(uint32_t gpio_number, uint32_t clock_state)
+{
+ if (clock_state == 0) {
+ return;
+ }
+ uint32_t port = GET_GPIO_PORT(gpio_number);
+ const struct port_info *info = &port_info[port];
+
+ mmio_write_32(info->clkgate_reg, BITS_WITH_WMASK(1, 1, info->clkgate_bit));
+}
+
+static int get_pull(int gpio)
+{
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t bank = GET_GPIO_BANK(gpio);
+ uint32_t id = GET_GPIO_ID(gpio);
+ uint32_t val, clock_state;
+
+ assert(port < 5U);
+ const struct port_info *info = &port_info[port];
+
+ assert(bank <= info->max_bank);
+
+ clock_state = gpio_get_clock(gpio);
+ val = (mmio_read_32(info->pull_base + 4 * bank) >> (id * 2)) & GPIO_P_MASK;
+ gpio_put_clock(gpio, clock_state);
+
+ return pull_type_hw2sw[info->pull_enc[bank]][val];
+}
+
+static void set_pull(int gpio, int pull)
+{
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t bank = GET_GPIO_BANK(gpio);
+ uint32_t id = GET_GPIO_ID(gpio);
+ uint32_t clock_state;
+
+ assert(port < 5U);
+ const struct port_info *info = &port_info[port];
+
+ assert(bank <= info->max_bank);
+
+ uint8_t val = pull_type_sw2hw[info->pull_enc[bank]][pull];
+
+ assert(val != (uint8_t)-1);
+
+ clock_state = gpio_get_clock(gpio);
+ mmio_write_32(
+ info->pull_base + 4 * bank,
+ BITS_WITH_WMASK(val, GPIO_P_MASK, id * 2)
+ );
+ gpio_put_clock(gpio, clock_state);
+}
+
+static void set_direction(int gpio, int direction)
+{
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ uint32_t clock_state;
+
+ assert((port < 5) && (num < 32));
+
+ clock_state = gpio_get_clock(gpio);
+
+ /*
+ * in gpio.h
+ * #define GPIO_DIR_OUT 0
+ * #define GPIO_DIR_IN 1
+ * but rk3399 gpio direction 1: output, 0: input
+ * so need to revert direction value
+ */
+ mmio_setbits_32(
+ port_info[port].port_base + SWPORTA_DDR,
+ ((direction == 0) ? 1 : 0) << num
+ );
+ gpio_put_clock(gpio, clock_state);
+}
+
+static int get_direction(int gpio)
+{
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ int direction, clock_state;
+
+ assert((port < 5U) && (num < 32U));
+
+ clock_state = gpio_get_clock(gpio);
+
+ /*
+ * in gpio.h
+ * #define GPIO_DIR_OUT 0
+ * #define GPIO_DIR_IN 1
+ * but rk3399 gpio direction 1: output, 0: input
+ * so need to revert direction value
+ */
+ direction = (((mmio_read_32(
+ port_info[port].port_base + SWPORTA_DDR
+ ) >> num) & 1U) == 0) ? 1 : 0;
+ gpio_put_clock(gpio, clock_state);
+
+ return direction;
+}
+
+static int get_value(int gpio)
+{
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ int value, clock_state;
+
+ assert((port < 5) && (num < 32));
+
+ clock_state = gpio_get_clock(gpio);
+ value = (mmio_read_32(port_info[port].port_base + EXT_PORTA) >> num) &
+ 0x1U;
+ gpio_put_clock(gpio, clock_state);
+
+ return value;
+}
+
+static void set_value(int gpio, int value)
+{
+ uint32_t port = GET_GPIO_PORT(gpio);
+ uint32_t num = GET_GPIO_NUM(gpio);
+ uint32_t clock_state;
+
+ assert((port < 5U) && (num < 32U));
+
+ clock_state = gpio_get_clock(gpio);
+ mmio_clrsetbits_32(
+ port_info[port].port_base + SWPORTA_DR,
+ 1 << num,
+ ((value == 0) ? 0 : 1) << num
+ );
+ gpio_put_clock(gpio, clock_state);
+}
+
+void plat_rockchip_save_gpio(void)
+{
+ unsigned int i;
+ uint32_t cru_gate_save;
+
+ cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
+
+ /*
+ * when shutdown logic, we need to save gpio2 ~ gpio4 register,
+ * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
+ * and we do not care gpio0 and gpio1 clock gate, since we never
+ * gating them
+ */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+ /*
+ * since gpio0, gpio1 are pmugpio, they will keep ther value
+ * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
+ * register value
+ */
+ for (i = 2; i < 5; i++) {
+ uint32_t base = port_info[i].port_base;
+
+ store_gpio[i - 2] = (struct gpio_save) {
+ .swporta_dr = mmio_read_32(base + SWPORTA_DR),
+ .swporta_ddr = mmio_read_32(base + SWPORTA_DDR),
+ .inten = mmio_read_32(base + INTEN),
+ .intmask = mmio_read_32(base + INTMASK),
+ .inttype_level = mmio_read_32(base + INTTYPE_LEVEL),
+ .int_polarity = mmio_read_32(base + INT_POLARITY),
+ .debounce = mmio_read_32(base + DEBOUNCE),
+ .ls_sync = mmio_read_32(base + LS_SYNC),
+ };
+ }
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ cru_gate_save | REG_SOC_WMSK);
+
+ /*
+ * gpio0, gpio1 in pmuiomux, they will keep ther value
+ * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
+ * iomux register value
+ */
+ for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
+ store_grf_gpio[i] =
+ mmio_read_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4);
+}
+
+void plat_rockchip_restore_gpio(void)
+{
+ int i;
+ uint32_t cru_gate_save;
+
+ for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4,
+ REG_SOC_WMSK | store_grf_gpio[i]);
+
+ cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
+
+ /*
+ * when shutdown logic, we need to save gpio2 ~ gpio4 register,
+ * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
+ * and we do not care gpio0 and gpio1 clock gate, since we never
+ * gating them
+ */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+ for (i = 2; i < 5; i++) {
+ uint32_t base = port_info[i].port_base;
+ const struct gpio_save *save = &store_gpio[i - 2];
+
+ mmio_write_32(base + SWPORTA_DR, save->swporta_dr);
+ mmio_write_32(base + SWPORTA_DDR, save->swporta_ddr);
+ mmio_write_32(base + INTEN, save->inten);
+ mmio_write_32(base + INTMASK, save->intmask);
+ mmio_write_32(base + INTTYPE_LEVEL, save->inttype_level),
+ mmio_write_32(base + INT_POLARITY, save->int_polarity);
+ mmio_write_32(base + DEBOUNCE, save->debounce);
+ mmio_write_32(base + LS_SYNC, save->ls_sync);
+ }
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ cru_gate_save | REG_SOC_WMSK);
+}
+
+const gpio_ops_t rk3399_gpio_ops = {
+ .get_direction = get_direction,
+ .set_direction = set_direction,
+ .get_value = get_value,
+ .set_value = set_value,
+ .set_pull = set_pull,
+ .get_pull = get_pull,
+};
+
+void plat_rockchip_gpio_init(void)
+{
+ gpio_init(&rk3399_gpio_ops);
+}
diff --git a/plat/rockchip/rk3399/drivers/m0/Makefile b/plat/rockchip/rk3399/drivers/m0/Makefile
new file mode 100644
index 0000000..79e09f0
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/Makefile
@@ -0,0 +1,125 @@
+#
+# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Cross Compile
+M0_CROSS_COMPILE ?= arm-none-eabi-
+
+# Build architecture
+ARCH := cortex-m0
+
+# Build platform
+PLAT_M0 ?= rk3399m0
+PLAT_M0_PMU ?= rk3399m0pmu
+
+ifeq (${V},0)
+ Q=@
+else
+ Q=
+endif
+export Q
+
+.SUFFIXES:
+
+INCLUDES += -Iinclude/ \
+ -I../../include/shared/
+
+# NOTE: Add C source files here
+C_SOURCES_COMMON := src/startup.c
+C_SOURCES := src/dram.c \
+ src/stopwatch.c
+C_SOURCES_PMU := src/suspend.c
+
+# Flags definition
+COMMON_FLAGS := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft
+CFLAGS := -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-common
+ASFLAGS := -Wa,--gdwarf-2
+LDFLAGS := -Wl,--gc-sections -Wl,--build-id=none
+
+# Cross tool
+CC := ${M0_CROSS_COMPILE}gcc
+CPP := ${M0_CROSS_COMPILE}cpp
+AR := ${M0_CROSS_COMPILE}ar
+OC := ${M0_CROSS_COMPILE}objcopy
+OD := ${M0_CROSS_COMPILE}objdump
+NM := ${M0_CROSS_COMPILE}nm
+
+# NOTE: The line continuation '\' is required in the next define otherwise we
+# end up with a line-feed characer at the end of the last c filename.
+# Also bare this issue in mind if extending the list of supported filetypes.
+define SOURCES_TO_OBJS
+ $(notdir $(patsubst %.c,%.o,$(filter %.c,$(1)))) \
+ $(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
+endef
+
+SOURCES_COMMON := $(C_SOURCES_COMMON)
+SOURCES := $(C_SOURCES)
+SOURCES_PMU := $(C_SOURCES_PMU)
+OBJS_COMMON := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_COMMON)))
+OBJS := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES)))
+OBJS_PMU := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_PMU)))
+LINKERFILE := $(BUILD)/$(PLAT_M0).ld
+MAPFILE := $(BUILD)/$(PLAT_M0).map
+MAPFILE_PMU := $(BUILD)/$(PLAT_M0_PMU).map
+ELF := $(BUILD)/$(PLAT_M0).elf
+ELF_PMU := $(BUILD)/$(PLAT_M0_PMU).elf
+BIN := $(BUILD)/$(PLAT_M0).bin
+BIN_PMU := $(BUILD)/$(PLAT_M0_PMU).bin
+LINKERFILE_SRC := src/$(PLAT_M0).ld.S
+
+# Function definition related compilation
+define MAKE_C
+$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
+-include $(patsubst %.o,%.d,$(OBJ))
+
+$(OBJ) : $(2)
+ @echo " CC $$<"
+ $$(Q)$$(CC) $$(COMMON_FLAGS) $$(CFLAGS) $$(INCLUDES) -MMD -MT $$@ -c $$< -o $$@
+endef
+
+define MAKE_S
+$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
+
+$(OBJ) : $(2)
+ @echo " AS $$<"
+ $$(Q)$$(CC) -x assembler-with-cpp $$(COMMON_FLAGS) $$(ASFLAGS) -c $$< -o $$@
+endef
+
+define MAKE_OBJS
+ $(eval C_OBJS := $(filter %.c,$(2)))
+ $(eval REMAIN := $(filter-out %.c,$(2)))
+ $(eval $(foreach obj,$(C_OBJS),$(call MAKE_C,$(1),$(obj),$(3))))
+
+ $(eval S_OBJS := $(filter %.S,$(REMAIN)))
+ $(eval REMAIN := $(filter-out %.S,$(REMAIN)))
+ $(eval $(foreach obj,$(S_OBJS),$(call MAKE_S,$(1),$(obj),$(3))))
+
+ $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN)))
+endef
+
+.PHONY: all
+all: $(BIN) $(BIN_PMU)
+
+.DEFAULT_GOAL := all
+
+$(LINKERFILE): $(LINKERFILE_SRC)
+ $(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF $@.d -MT $@ -o $@ $<
+-include $(LINKERFILE).d
+
+$(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE)
+ @echo " LD $@"
+ $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
+
+%.bin : %.elf
+ @echo " BIN $@"
+ $(Q)$(OC) -O binary $< $@
+
+$(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE)
+ @echo " LD $@"
+ $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
+
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1)))
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1)))
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_PMU),$(1)))
diff --git a/plat/rockchip/rk3399/drivers/m0/include/addressmap.h b/plat/rockchip/rk3399/drivers/m0/include/addressmap.h
new file mode 100644
index 0000000..d431437
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/include/addressmap.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ADDRESSMAP_H
+#define ADDRESSMAP_H
+
+#include <addressmap_shared.h>
+
+/* Registers base address for M0 */
+#define MMIO_BASE 0x40000000
+
+#endif /* ADDRESSMAP_H */
diff --git a/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h
new file mode 100644
index 0000000..2e90694
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK3399_MCU_H
+#define RK3399_MCU_H
+
+#include <addressmap.h>
+
+typedef unsigned int uint32_t;
+
+#define mmio_read_32(c) ({unsigned int __v = \
+ (*(volatile unsigned int *)(c)); __v; })
+#define mmio_write_32(c, v) ((*(volatile unsigned int *)(c)) = (v))
+
+#define mmio_clrbits_32(addr, clear) \
+ mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)))
+#define mmio_setbits_32(addr, set) \
+ mmio_write_32(addr, (mmio_read_32(addr)) | (set))
+#define mmio_clrsetbits_32(addr, clear, set) \
+ mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)) | (set))
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+void stopwatch_init_usecs_expire(unsigned int usecs);
+int stopwatch_expired(void);
+void stopwatch_reset(void);
+
+#endif /* RK3399_MCU_H */
diff --git a/plat/rockchip/rk3399/drivers/m0/src/dram.c b/plat/rockchip/rk3399/drivers/m0/src/dram.c
new file mode 100644
index 0000000..84e8884
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/src/dram.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dram_regs.h>
+#include <m0_param.h>
+#include <pmu_bits.h>
+#include <pmu_regs.h>
+#include "misc_regs.h"
+#include "rk3399_mcu.h"
+
+static uint32_t gatedis_con0;
+
+static void idle_port(void)
+{
+ gatedis_con0 = mmio_read_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0);
+ mmio_write_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0, 0x3fffffff);
+
+ mmio_setbits_32(PMU_BASE + PMU_BUS_IDLE_REQ,
+ (1 << PMU_IDLE_REQ_MSCH0) | (1 << PMU_IDLE_REQ_MSCH1));
+ while ((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) &
+ ((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0))) !=
+ ((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0)))
+ continue;
+}
+
+static void deidle_port(void)
+{
+ mmio_clrbits_32(PMU_BASE + PMU_BUS_IDLE_REQ,
+ (1 << PMU_IDLE_REQ_MSCH0) | (1 << PMU_IDLE_REQ_MSCH1));
+ while (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) &
+ ((1 << PMU_IDLE_ST_MSCH1) | (1 << PMU_IDLE_ST_MSCH0)))
+ continue;
+
+ /* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
+ mmio_write_32(PMUCRU_BASE + PMU_CRU_GATEDIS_CON0, gatedis_con0);
+}
+
+static void ddr_set_pll(void)
+{
+ mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_SLOW_MODE));
+
+ mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_POWER_DOWN(1));
+ mmio_write_32(CRU_BASE + CRU_DPLL_CON0,
+ mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON0));
+ mmio_write_32(CRU_BASE + CRU_DPLL_CON1,
+ mmio_read_32(PARAM_ADDR + PARAM_DPLL_CON1));
+ mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_POWER_DOWN(0));
+
+ while ((mmio_read_32(CRU_BASE + CRU_DPLL_CON2) & (1u << 31)) == 0)
+ continue;
+
+ mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE));
+}
+
+__attribute__((noreturn)) void m0_main(void)
+{
+ mmio_setbits_32(PHY_REG(0, 927), (1 << 22));
+ mmio_setbits_32(PHY_REG(1, 927), (1 << 22));
+ idle_port();
+
+ mmio_write_32(CIC_BASE + CIC_CTRL0,
+ (((0x3 << 4) | (1 << 2) | 1) << 16) |
+ (1 << 2) | 1 |
+ mmio_read_32(PARAM_ADDR + PARAM_FREQ_SELECT));
+ while ((mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 2)) == 0)
+ continue;
+
+ ddr_set_pll();
+ mmio_write_32(CIC_BASE + CIC_CTRL0, 0x20002);
+ while ((mmio_read_32(CIC_BASE + CIC_STATUS0) & (1 << 0)) == 0)
+ continue;
+
+ deidle_port();
+ mmio_clrbits_32(PHY_REG(0, 927), (1 << 22));
+ mmio_clrbits_32(PHY_REG(1, 927), (1 << 22));
+
+ mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
+
+ for (;;)
+ __asm__ volatile ("wfi");
+}
diff --git a/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S b/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S
new file mode 100644
index 0000000..bfe054e
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <m0_param.h>
+
+OUTPUT_FORMAT("elf32-littlearm")
+
+SECTIONS {
+ .m0_bin 0 : {
+ KEEP(*(.isr_vector))
+ ASSERT(. == 0xc0, "ISR vector has the wrong size.");
+ ASSERT(. == PARAM_ADDR, "M0 params should go right behind ISR table.");
+ . += PARAM_M0_SIZE;
+ *(.text*)
+ *(.rodata*)
+ *(.data*)
+ *(.bss*)
+ . = ALIGN(8);
+ *(.co_stack*)
+ }
+
+ /DISCARD/ : { *(.comment) *(.note*) }
+}
diff --git a/plat/rockchip/rk3399/drivers/m0/src/startup.c b/plat/rockchip/rk3399/drivers/m0/src/startup.c
new file mode 100644
index 0000000..dfd8af2
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/src/startup.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "rk3399_mcu.h"
+
+/* Stack configuration */
+#define STACK_SIZE 0x00000040
+__attribute__ ((section(".co_stack")))
+unsigned long pstack[STACK_SIZE];
+
+/* Macro definition */
+#define WEAK __attribute__ ((weak))
+
+/* System exception vector handler */
+__attribute__ ((used))
+void WEAK reset_handler(void);
+void WEAK nmi_handler(void);
+void WEAK hardware_fault_handler(void);
+void WEAK svc_handler(void);
+void WEAK pend_sv_handler(void);
+void WEAK systick_handler(void);
+
+extern int m0_main(void);
+
+/* Function prototypes */
+static void default_reset_handler(void);
+static void default_handler(void);
+
+/*
+ * The minimal vector table for a Cortex M3. Note that the proper constructs
+ * must be placed on this to ensure that it ends up at physical address
+ * 0x00000000.
+ */
+__attribute__ ((used, section(".isr_vector")))
+void (* const g_pfnVectors[])(void) = {
+ /* core Exceptions */
+ (void *)&pstack[STACK_SIZE], /* the initial stack pointer */
+ reset_handler,
+ nmi_handler,
+ hardware_fault_handler,
+ 0, 0, 0, 0, 0, 0, 0,
+ svc_handler,
+ 0, 0,
+ pend_sv_handler,
+ systick_handler,
+
+ /* external exceptions */
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+/**
+ * This is the code that gets called when the processor first
+ * starts execution following a reset event. Only the absolutely
+ * necessary set is performed, after which the application
+ * supplied m0_main() routine is called.
+ */
+static void default_reset_handler(void)
+{
+ /* call the application's entry point */
+ m0_main();
+}
+
+/**
+ * Provide weak aliases for each Exception handler to the Default_Handler.
+ * As they are weak aliases, any function with the same name will override
+ * this definition.
+ */
+#pragma weak reset_handler = default_reset_handler
+#pragma weak nmi_handler = default_handler
+#pragma weak hardware_fault_handler = default_handler
+#pragma weak svc_handler = default_handler
+#pragma weak pend_sv_handler = default_handler
+#pragma weak systick_handler = default_handler
+
+/**
+ * This is the code that gets called when the processor receives
+ * an unexpected interrupt. This simply enters an infinite loop,
+ * preserving the system state for examination by a debugger.
+ */
+static void default_handler(void)
+{
+ /* go into an infinite loop. */
+ while (1)
+ ;
+}
diff --git a/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c b/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c
new file mode 100644
index 0000000..5af8caa
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <m0_param.h>
+#include "rk3399_mcu.h"
+
+/* use 24MHz SysTick */
+#define US_TO_CYCLE(US) (US * 24)
+
+#define SYST_CST 0xe000e010
+/* enable counter */
+#define ENABLE (1 << 0)
+/* count down to 0 does not cause SysTick exception to pend */
+#define TICKINT (1 << 1)
+/* core clock used for SysTick */
+#define CLKSOURCE (1 << 2)
+
+#define COUNTFLAG (1 << 16)
+#define SYST_RVR 0xe000e014
+#define MAX_VALUE 0xffffff
+#define MAX_USECS (MAX_VALUE / US_TO_CYCLE(1))
+#define SYST_CVR 0xe000e018
+#define SYST_CALIB 0xe000e01c
+
+unsigned int remaining_usecs;
+
+static inline void stopwatch_set_usecs(void)
+{
+ unsigned int cycle;
+ unsigned int usecs = MIN(MAX_USECS, remaining_usecs);
+
+ remaining_usecs -= usecs;
+ cycle = US_TO_CYCLE(usecs);
+ mmio_write_32(SYST_RVR, cycle);
+ mmio_write_32(SYST_CVR, 0);
+
+ mmio_write_32(SYST_CST, ENABLE | TICKINT | CLKSOURCE);
+}
+
+void stopwatch_init_usecs_expire(unsigned int usecs)
+{
+ /*
+ * Enter an inifite loop if the stopwatch is in use. This will allow the
+ * state to be analyzed with a debugger.
+ */
+ if (mmio_read_32(SYST_CST) & ENABLE)
+ while (1)
+ ;
+
+ remaining_usecs = usecs;
+ stopwatch_set_usecs();
+}
+
+int stopwatch_expired(void)
+{
+ int val = mmio_read_32(SYST_CST);
+ if ((val & COUNTFLAG) || !(val & ENABLE)) {
+ if (!remaining_usecs)
+ return 1;
+
+ stopwatch_set_usecs();
+ }
+
+ return 0;
+}
+
+void stopwatch_reset(void)
+{
+ mmio_clrbits_32(SYST_CST, ENABLE);
+ remaining_usecs = 0;
+}
diff --git a/plat/rockchip/rk3399/drivers/m0/src/suspend.c b/plat/rockchip/rk3399/drivers/m0/src/suspend.c
new file mode 100644
index 0000000..9ad2fa2
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/m0/src/suspend.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <pmu_regs.h>
+#include "rk3399_mcu.h"
+
+#define M0_SCR 0xe000ed10 /* System Control Register (SCR) */
+
+#define SCR_SLEEPDEEP_SHIFT (1 << 2)
+
+__attribute__((noreturn)) void m0_main(void)
+{
+ unsigned int status_value;
+
+ /*
+ * PMU sometimes doesn't clear power mode bit as it's supposed to due
+ * to a hardware bug. Make the M0 clear it manually to be sure,
+ * otherwise interrupts some cases with concurrent wake interrupts
+ * we stay asleep forever.
+ */
+ while (1) {
+ status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+ if (status_value) {
+ mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
+ break;
+ }
+ }
+
+ /*
+ * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
+ * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
+ * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
+ * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
+ * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
+ * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
+ * that glitch will affect SOC, and mess up SOC status, so we
+ * addressmap_shared software clamp between ST_INPUT_CLAMP and
+ * ST_WAKEUP_RESET_CLR to avoid this happen.
+ */
+ while (1) {
+ status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+ if (status_value >= 17) {
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+ break;
+ }
+
+ }
+
+ while (1) {
+ status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+ if (status_value >= 26) {
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+ break;
+ }
+ }
+
+ for (;;)
+ __asm__ volatile ("wfi");
+}
diff --git a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c
new file mode 100644
index 0000000..cad76ac
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <m0_ctl.h>
+#include <plat_private.h>
+#include <rk3399_def.h>
+#include <secure.h>
+#include <soc.h>
+
+void m0_init(void)
+{
+ /* secure config for M0 */
+ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7));
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12));
+
+ /* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
+ mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02);
+
+ /*
+ * To switch the parent to xin24M and div == 1,
+ *
+ * We need to close most of the PLLs and clocks except the OSC 24MHz
+ * durning suspend, and this should be enough to supplies the ddrfreq,
+ * For the simple handle, we just keep the fixed 24MHz to supply the
+ * suspend and ddrfreq directly.
+ */
+ mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0,
+ BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8));
+
+ mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5));
+}
+
+void m0_configure_execute_addr(uintptr_t addr)
+{
+ /* set the execute address for M0 */
+ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
+ BITS_WITH_WMASK((addr >> 12) & 0xffff,
+ 0xffffu, 0));
+ mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
+ BITS_WITH_WMASK((addr >> 28) & 0xf,
+ 0xfu, 0));
+}
+
+void m0_start(void)
+{
+ /* enable clocks for M0 */
+ mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
+ BITS_WITH_WMASK(0x0, 0xf, 0));
+
+ /* clean the PARAM_M0_DONE flag, mean that M0 will start working */
+ mmio_write_32(M0_PARAM_ADDR + PARAM_M0_DONE, 0);
+ dmbst();
+
+ mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
+ BITS_WITH_WMASK(0x0, 0x4, 0));
+
+ udelay(5);
+ /* start M0 */
+ mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
+ BITS_WITH_WMASK(0x0, 0x20, 0));
+ dmbst();
+}
+
+void m0_stop(void)
+{
+ /* stop M0 */
+ mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
+ BITS_WITH_WMASK(0x24, 0x24, 0));
+
+ /* disable clocks for M0 */
+ mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
+ BITS_WITH_WMASK(0xf, 0xf, 0));
+}
+
+void m0_wait_done(void)
+{
+ do {
+ /*
+ * Don't starve the M0 for access to SRAM, so delay before
+ * reading the PARAM_M0_DONE value again.
+ */
+ udelay(5);
+ dsb();
+ } while (mmio_read_32(M0_PARAM_ADDR + PARAM_M0_DONE) != M0_DONE_FLAG);
+
+ /*
+ * Let the M0 settle into WFI before we leave. This is so we don't reset
+ * the M0 in a bad spot which can cause problems with the M0.
+ */
+ udelay(10);
+ dsb();
+}
diff --git a/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h
new file mode 100644
index 0000000..7542e22
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef M0_CTL_H
+#define M0_CTL_H
+
+#include <m0_param.h>
+
+#define M0_BINCODE_BASE ((uintptr_t)rk3399m0_bin)
+#define M0_PARAM_ADDR (M0_BINCODE_BASE + PARAM_ADDR)
+#define M0PMU_BINCODE_BASE ((uintptr_t)rk3399m0pmu_bin)
+
+/* pmu_fw.c */
+extern char rk3399m0_bin[];
+extern char rk3399m0_bin_end[];
+
+extern char rk3399m0pmu_bin[];
+extern char rk3399m0pmu_bin_end[];
+
+extern void m0_init(void);
+extern void m0_start(void);
+extern void m0_stop(void);
+extern void m0_wait_done(void);
+extern void m0_configure_execute_addr(uintptr_t addr);
+
+#endif /* M0_CTL_H */
diff --git a/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..546c09a
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <pmu_regs.h>
+
+ .globl clst_warmboot_data
+
+ .macro sram_func _name
+ .cfi_sections .debug_frame
+ .section .sram.text, "ax"
+ .type \_name, %function
+ .cfi_startproc
+ \_name:
+ .endm
+
+#define CRU_CLKSEL_CON6 0x118
+
+#define DDRCTL0_C_SYSREQ_CFG 0x0100
+#define DDRCTL1_C_SYSREQ_CFG 0x1000
+
+#define DDRC0_SREF_DONE_EXT 0x01
+#define DDRC1_SREF_DONE_EXT 0x04
+
+#define PLL_MODE_SHIFT (0x8)
+#define PLL_NORMAL_MODE ((0x3 << (PLL_MODE_SHIFT + 16)) | \
+ (0x1 << PLL_MODE_SHIFT))
+#define MPIDR_CLST_L_BITS 0x0
+ /*
+ * For different socs, if we want to speed up warmboot,
+ * we need to config some regs here.
+ * If scu was suspend, we must resume related clk
+ * from slow (24M) mode to normal mode first.
+ * X0: MPIDR_EL1 & MPIDR_CLUSTER_MASK
+ */
+.macro func_rockchip_clst_warmboot
+ adr x4, clst_warmboot_data
+ lsr x5, x0, #6
+ ldr w3, [x4, x5]
+ str wzr, [x4, x5]
+ cmp w3, #PMU_CLST_RET
+ b.ne clst_warmboot_end
+ ldr w6, =(PLL_NORMAL_MODE)
+ /*
+ * core_l offset is CRU_BASE + 0xc,
+ * core_b offset is CRU_BASE + 0x2c
+ */
+ ldr x7, =(CRU_BASE + 0xc)
+ lsr x2, x0, #3
+ str w6, [x7, x2]
+clst_warmboot_end:
+.endm
+
+.macro rockchip_clst_warmboot_data
+clst_warmboot_data:
+ .rept PLATFORM_CLUSTER_COUNT
+ .word 0
+ .endr
+.endm
+
+ /* -----------------------------------------------
+ * void sram_func_set_ddrctl_pll(uint32_t pll_src)
+ * Function to switch the PLL source for ddrctrl
+ * In: x0 - The PLL of the clk_ddrc clock source
+ * out: None
+ * Clobber list : x0 - x3, x5, x8 - x10
+ * -----------------------------------------------
+ */
+
+ .globl sram_func_set_ddrctl_pll
+
+sram_func sram_func_set_ddrctl_pll
+ /* backup parameter */
+ mov x8, x0
+
+ /* disable the MMU at EL3 */
+ mrs x9, sctlr_el3
+ bic x10, x9, #(SCTLR_M_BIT)
+ msr sctlr_el3, x10
+ isb
+ dsb sy
+
+ /* enable ddrctl0_1 idle request */
+ mov x5, PMU_BASE
+ ldr w0, [x5, #PMU_SFT_CON]
+ orr w0, w0, #DDRCTL0_C_SYSREQ_CFG
+ orr w0, w0, #DDRCTL1_C_SYSREQ_CFG
+ str w0, [x5, #PMU_SFT_CON]
+
+check_ddrc0_1_sref_enter:
+ ldr w1, [x5, #PMU_DDR_SREF_ST]
+ and w2, w1, #DDRC0_SREF_DONE_EXT
+ and w3, w1, #DDRC1_SREF_DONE_EXT
+ orr w2, w2, w3
+ cmp w2, #(DDRC0_SREF_DONE_EXT | DDRC1_SREF_DONE_EXT)
+ b.eq check_ddrc0_1_sref_enter
+
+ /*
+ * select a PLL for ddrctrl:
+ * x0 = 0: ALPLL
+ * x0 = 1: ABPLL
+ * x0 = 2: DPLL
+ * x0 = 3: GPLLL
+ */
+ mov x5, CRU_BASE
+ lsl w0, w8, #4
+ orr w0, w0, #0x00300000
+ str w0, [x5, #CRU_CLKSEL_CON6]
+
+ /* disable ddrctl0_1 idle request */
+ mov x5, PMU_BASE
+ ldr w0, [x5, #PMU_SFT_CON]
+ bic w0, w0, #DDRCTL0_C_SYSREQ_CFG
+ bic w0, w0, #DDRCTL1_C_SYSREQ_CFG
+ str w0, [x5, #PMU_SFT_CON]
+
+check_ddrc0_1_sref_exit:
+ ldr w1, [x5, #PMU_DDR_SREF_ST]
+ and w2, w1, #DDRC0_SREF_DONE_EXT
+ and w3, w1, #DDRC1_SREF_DONE_EXT
+ orr w2, w2, w3
+ cmp w2, #0x0
+ b.eq check_ddrc0_1_sref_exit
+
+ /* reenable the MMU at EL3 */
+ msr sctlr_el3, x9
+ isb
+ dsb sy
+
+ ret
+endfunc sram_func_set_ddrctl_pll
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
new file mode 100644
index 0000000..3084c4f
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -0,0 +1,1626 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/delay_timer.h>
+#include <drivers/gpio.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <dfs.h>
+#include <m0_ctl.h>
+#include <plat_params.h>
+#include <plat_private.h>
+#include <pmu.h>
+#include <pmu_com.h>
+#include <pwm.h>
+#include <rk3399_def.h>
+#include <secure.h>
+#include <soc.h>
+#include <suspend.h>
+
+DEFINE_BAKERY_LOCK(rockchip_pd_lock);
+
+static uint32_t cpu_warm_boot_addr;
+static char store_sram[SRAM_BIN_LIMIT + SRAM_TEXT_LIMIT + SRAM_DATA_LIMIT];
+static uint32_t store_cru[CRU_SDIO0_CON1 / 4 + 1];
+static uint32_t store_usbphy0[7];
+static uint32_t store_usbphy1[7];
+static uint32_t store_grf_io_vsel;
+static uint32_t store_grf_soc_con0;
+static uint32_t store_grf_soc_con1;
+static uint32_t store_grf_soc_con2;
+static uint32_t store_grf_soc_con3;
+static uint32_t store_grf_soc_con4;
+static uint32_t store_grf_soc_con7;
+static uint32_t store_grf_ddrc_con[4];
+static uint32_t store_wdt0[2];
+static uint32_t store_wdt1[2];
+static gicv3_dist_ctx_t dist_ctx;
+static gicv3_redist_ctx_t rdist_ctx;
+
+/*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg,
+ * it is core_pwr_pd mode
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode
+ * so we need core_pm_cfg_info to distinguish which method be used now.
+ */
+
+static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT]
+#if USE_COHERENT_MEM
+__attribute__ ((section("tzfw_coherent_mem")))
+#endif
+;/* coheront */
+
+static void pmu_bus_idle_req(uint32_t bus, uint32_t state)
+{
+ uint32_t bus_id = BIT(bus);
+ uint32_t bus_req;
+ uint32_t wait_cnt = 0;
+ uint32_t bus_state, bus_ack;
+
+ if (state)
+ bus_req = BIT(bus);
+ else
+ bus_req = 0;
+
+ mmio_clrsetbits_32(PMU_BASE + PMU_BUS_IDLE_REQ, bus_id, bus_req);
+
+ do {
+ bus_state = mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & bus_id;
+ bus_ack = mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK) & bus_id;
+ if (bus_state == bus_req && bus_ack == bus_req)
+ break;
+
+ wait_cnt++;
+ udelay(1);
+ } while (wait_cnt < MAX_WAIT_COUNT);
+
+ if (bus_state != bus_req || bus_ack != bus_req) {
+ INFO("%s:st=%x(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST),
+ bus_state);
+ INFO("%s:st=%x(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK),
+ bus_ack);
+ }
+}
+
+struct pmu_slpdata_s pmu_slpdata;
+
+static void qos_restore(void)
+{
+ if (pmu_power_domain_st(PD_GPU) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.gpu_qos, GPU);
+ if (pmu_power_domain_st(PD_ISP0) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.isp0_m0_qos, ISP0_M0);
+ RESTORE_QOS(pmu_slpdata.isp0_m1_qos, ISP0_M1);
+ }
+ if (pmu_power_domain_st(PD_ISP1) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.isp1_m0_qos, ISP1_M0);
+ RESTORE_QOS(pmu_slpdata.isp1_m1_qos, ISP1_M1);
+ }
+ if (pmu_power_domain_st(PD_VO) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.vop_big_r, VOP_BIG_R);
+ RESTORE_QOS(pmu_slpdata.vop_big_w, VOP_BIG_W);
+ RESTORE_QOS(pmu_slpdata.vop_little, VOP_LITTLE);
+ }
+ if (pmu_power_domain_st(PD_HDCP) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.hdcp_qos, HDCP);
+ if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.gmac_qos, GMAC);
+ if (pmu_power_domain_st(PD_CCI) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.cci_m0_qos, CCI_M0);
+ RESTORE_QOS(pmu_slpdata.cci_m1_qos, CCI_M1);
+ }
+ if (pmu_power_domain_st(PD_SD) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.sdmmc_qos, SDMMC);
+ if (pmu_power_domain_st(PD_EMMC) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.emmc_qos, EMMC);
+ if (pmu_power_domain_st(PD_SDIOAUDIO) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.sdio_qos, SDIO);
+ if (pmu_power_domain_st(PD_GIC) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.gic_qos, GIC);
+ if (pmu_power_domain_st(PD_RGA) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.rga_r_qos, RGA_R);
+ RESTORE_QOS(pmu_slpdata.rga_w_qos, RGA_W);
+ }
+ if (pmu_power_domain_st(PD_IEP) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.iep_qos, IEP);
+ if (pmu_power_domain_st(PD_USB3) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.usb_otg0_qos, USB_OTG0);
+ RESTORE_QOS(pmu_slpdata.usb_otg1_qos, USB_OTG1);
+ }
+ if (pmu_power_domain_st(PD_PERIHP) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.usb_host0_qos, USB_HOST0);
+ RESTORE_QOS(pmu_slpdata.usb_host1_qos, USB_HOST1);
+ RESTORE_QOS(pmu_slpdata.perihp_nsp_qos, PERIHP_NSP);
+ }
+ if (pmu_power_domain_st(PD_PERILP) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.dmac0_qos, DMAC0);
+ RESTORE_QOS(pmu_slpdata.dmac1_qos, DMAC1);
+ RESTORE_QOS(pmu_slpdata.dcf_qos, DCF);
+ RESTORE_QOS(pmu_slpdata.crypto0_qos, CRYPTO0);
+ RESTORE_QOS(pmu_slpdata.crypto1_qos, CRYPTO1);
+ RESTORE_QOS(pmu_slpdata.perilp_nsp_qos, PERILP_NSP);
+ RESTORE_QOS(pmu_slpdata.perilpslv_nsp_qos, PERILPSLV_NSP);
+ RESTORE_QOS(pmu_slpdata.peri_cm1_qos, PERI_CM1);
+ }
+ if (pmu_power_domain_st(PD_VDU) == pmu_pd_on)
+ RESTORE_QOS(pmu_slpdata.video_m0_qos, VIDEO_M0);
+ if (pmu_power_domain_st(PD_VCODEC) == pmu_pd_on) {
+ RESTORE_QOS(pmu_slpdata.video_m1_r_qos, VIDEO_M1_R);
+ RESTORE_QOS(pmu_slpdata.video_m1_w_qos, VIDEO_M1_W);
+ }
+}
+
+static void qos_save(void)
+{
+ if (pmu_power_domain_st(PD_GPU) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.gpu_qos, GPU);
+ if (pmu_power_domain_st(PD_ISP0) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.isp0_m0_qos, ISP0_M0);
+ SAVE_QOS(pmu_slpdata.isp0_m1_qos, ISP0_M1);
+ }
+ if (pmu_power_domain_st(PD_ISP1) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.isp1_m0_qos, ISP1_M0);
+ SAVE_QOS(pmu_slpdata.isp1_m1_qos, ISP1_M1);
+ }
+ if (pmu_power_domain_st(PD_VO) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.vop_big_r, VOP_BIG_R);
+ SAVE_QOS(pmu_slpdata.vop_big_w, VOP_BIG_W);
+ SAVE_QOS(pmu_slpdata.vop_little, VOP_LITTLE);
+ }
+ if (pmu_power_domain_st(PD_HDCP) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.hdcp_qos, HDCP);
+ if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.gmac_qos, GMAC);
+ if (pmu_power_domain_st(PD_CCI) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.cci_m0_qos, CCI_M0);
+ SAVE_QOS(pmu_slpdata.cci_m1_qos, CCI_M1);
+ }
+ if (pmu_power_domain_st(PD_SD) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.sdmmc_qos, SDMMC);
+ if (pmu_power_domain_st(PD_EMMC) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.emmc_qos, EMMC);
+ if (pmu_power_domain_st(PD_SDIOAUDIO) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.sdio_qos, SDIO);
+ if (pmu_power_domain_st(PD_GIC) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.gic_qos, GIC);
+ if (pmu_power_domain_st(PD_RGA) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.rga_r_qos, RGA_R);
+ SAVE_QOS(pmu_slpdata.rga_w_qos, RGA_W);
+ }
+ if (pmu_power_domain_st(PD_IEP) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.iep_qos, IEP);
+ if (pmu_power_domain_st(PD_USB3) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.usb_otg0_qos, USB_OTG0);
+ SAVE_QOS(pmu_slpdata.usb_otg1_qos, USB_OTG1);
+ }
+ if (pmu_power_domain_st(PD_PERIHP) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.usb_host0_qos, USB_HOST0);
+ SAVE_QOS(pmu_slpdata.usb_host1_qos, USB_HOST1);
+ SAVE_QOS(pmu_slpdata.perihp_nsp_qos, PERIHP_NSP);
+ }
+ if (pmu_power_domain_st(PD_PERILP) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.dmac0_qos, DMAC0);
+ SAVE_QOS(pmu_slpdata.dmac1_qos, DMAC1);
+ SAVE_QOS(pmu_slpdata.dcf_qos, DCF);
+ SAVE_QOS(pmu_slpdata.crypto0_qos, CRYPTO0);
+ SAVE_QOS(pmu_slpdata.crypto1_qos, CRYPTO1);
+ SAVE_QOS(pmu_slpdata.perilp_nsp_qos, PERILP_NSP);
+ SAVE_QOS(pmu_slpdata.perilpslv_nsp_qos, PERILPSLV_NSP);
+ SAVE_QOS(pmu_slpdata.peri_cm1_qos, PERI_CM1);
+ }
+ if (pmu_power_domain_st(PD_VDU) == pmu_pd_on)
+ SAVE_QOS(pmu_slpdata.video_m0_qos, VIDEO_M0);
+ if (pmu_power_domain_st(PD_VCODEC) == pmu_pd_on) {
+ SAVE_QOS(pmu_slpdata.video_m1_r_qos, VIDEO_M1_R);
+ SAVE_QOS(pmu_slpdata.video_m1_w_qos, VIDEO_M1_W);
+ }
+}
+
+static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state)
+{
+ uint32_t state;
+
+ if (pmu_power_domain_st(pd_id) == pd_state)
+ goto out;
+
+ if (pd_state == pmu_pd_on)
+ pmu_power_domain_ctr(pd_id, pd_state);
+
+ state = (pd_state == pmu_pd_off) ? BUS_IDLE : BUS_ACTIVE;
+
+ switch (pd_id) {
+ case PD_GPU:
+ pmu_bus_idle_req(BUS_ID_GPU, state);
+ break;
+ case PD_VIO:
+ pmu_bus_idle_req(BUS_ID_VIO, state);
+ break;
+ case PD_ISP0:
+ pmu_bus_idle_req(BUS_ID_ISP0, state);
+ break;
+ case PD_ISP1:
+ pmu_bus_idle_req(BUS_ID_ISP1, state);
+ break;
+ case PD_VO:
+ pmu_bus_idle_req(BUS_ID_VOPB, state);
+ pmu_bus_idle_req(BUS_ID_VOPL, state);
+ break;
+ case PD_HDCP:
+ pmu_bus_idle_req(BUS_ID_HDCP, state);
+ break;
+ case PD_TCPD0:
+ break;
+ case PD_TCPD1:
+ break;
+ case PD_GMAC:
+ pmu_bus_idle_req(BUS_ID_GMAC, state);
+ break;
+ case PD_CCI:
+ pmu_bus_idle_req(BUS_ID_CCIM0, state);
+ pmu_bus_idle_req(BUS_ID_CCIM1, state);
+ break;
+ case PD_SD:
+ pmu_bus_idle_req(BUS_ID_SD, state);
+ break;
+ case PD_EMMC:
+ pmu_bus_idle_req(BUS_ID_EMMC, state);
+ break;
+ case PD_EDP:
+ pmu_bus_idle_req(BUS_ID_EDP, state);
+ break;
+ case PD_SDIOAUDIO:
+ pmu_bus_idle_req(BUS_ID_SDIOAUDIO, state);
+ break;
+ case PD_GIC:
+ pmu_bus_idle_req(BUS_ID_GIC, state);
+ break;
+ case PD_RGA:
+ pmu_bus_idle_req(BUS_ID_RGA, state);
+ break;
+ case PD_VCODEC:
+ pmu_bus_idle_req(BUS_ID_VCODEC, state);
+ break;
+ case PD_VDU:
+ pmu_bus_idle_req(BUS_ID_VDU, state);
+ break;
+ case PD_IEP:
+ pmu_bus_idle_req(BUS_ID_IEP, state);
+ break;
+ case PD_USB3:
+ pmu_bus_idle_req(BUS_ID_USB3, state);
+ break;
+ case PD_PERIHP:
+ pmu_bus_idle_req(BUS_ID_PERIHP, state);
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ if (pd_state == pmu_pd_off)
+ pmu_power_domain_ctr(pd_id, pd_state);
+
+out:
+ return 0;
+}
+
+static uint32_t pmu_powerdomain_state;
+
+static void pmu_power_domains_suspend(void)
+{
+ clk_gate_con_save();
+ clk_gate_con_disable();
+ qos_save();
+ pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST);
+ pmu_set_power_domain(PD_GPU, pmu_pd_off);
+ pmu_set_power_domain(PD_TCPD0, pmu_pd_off);
+ pmu_set_power_domain(PD_TCPD1, pmu_pd_off);
+ pmu_set_power_domain(PD_VO, pmu_pd_off);
+ pmu_set_power_domain(PD_ISP0, pmu_pd_off);
+ pmu_set_power_domain(PD_ISP1, pmu_pd_off);
+ pmu_set_power_domain(PD_HDCP, pmu_pd_off);
+ pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_off);
+ pmu_set_power_domain(PD_GMAC, pmu_pd_off);
+ pmu_set_power_domain(PD_EDP, pmu_pd_off);
+ pmu_set_power_domain(PD_IEP, pmu_pd_off);
+ pmu_set_power_domain(PD_RGA, pmu_pd_off);
+ pmu_set_power_domain(PD_VCODEC, pmu_pd_off);
+ pmu_set_power_domain(PD_VDU, pmu_pd_off);
+ pmu_set_power_domain(PD_USB3, pmu_pd_off);
+ pmu_set_power_domain(PD_EMMC, pmu_pd_off);
+ pmu_set_power_domain(PD_VIO, pmu_pd_off);
+ pmu_set_power_domain(PD_SD, pmu_pd_off);
+ pmu_set_power_domain(PD_PERIHP, pmu_pd_off);
+ clk_gate_con_restore();
+}
+
+static void pmu_power_domains_resume(void)
+{
+ clk_gate_con_save();
+ clk_gate_con_disable();
+ if (!(pmu_powerdomain_state & BIT(PD_VDU)))
+ pmu_set_power_domain(PD_VDU, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_VCODEC)))
+ pmu_set_power_domain(PD_VCODEC, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_RGA)))
+ pmu_set_power_domain(PD_RGA, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_IEP)))
+ pmu_set_power_domain(PD_IEP, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_EDP)))
+ pmu_set_power_domain(PD_EDP, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_GMAC)))
+ pmu_set_power_domain(PD_GMAC, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_SDIOAUDIO)))
+ pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_HDCP)))
+ pmu_set_power_domain(PD_HDCP, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_ISP1)))
+ pmu_set_power_domain(PD_ISP1, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_ISP0)))
+ pmu_set_power_domain(PD_ISP0, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_VO)))
+ pmu_set_power_domain(PD_VO, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_TCPD1)))
+ pmu_set_power_domain(PD_TCPD1, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_TCPD0)))
+ pmu_set_power_domain(PD_TCPD0, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_GPU)))
+ pmu_set_power_domain(PD_GPU, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_USB3)))
+ pmu_set_power_domain(PD_USB3, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_EMMC)))
+ pmu_set_power_domain(PD_EMMC, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_VIO)))
+ pmu_set_power_domain(PD_VIO, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_SD)))
+ pmu_set_power_domain(PD_SD, pmu_pd_on);
+ if (!(pmu_powerdomain_state & BIT(PD_PERIHP)))
+ pmu_set_power_domain(PD_PERIHP, pmu_pd_on);
+ qos_restore();
+ clk_gate_con_restore();
+}
+
+void pmu_power_domains_on(void)
+{
+ clk_gate_con_disable();
+ pmu_set_power_domain(PD_VDU, pmu_pd_on);
+ pmu_set_power_domain(PD_VCODEC, pmu_pd_on);
+ pmu_set_power_domain(PD_RGA, pmu_pd_on);
+ pmu_set_power_domain(PD_IEP, pmu_pd_on);
+ pmu_set_power_domain(PD_EDP, pmu_pd_on);
+ pmu_set_power_domain(PD_GMAC, pmu_pd_on);
+ pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_on);
+ pmu_set_power_domain(PD_HDCP, pmu_pd_on);
+ pmu_set_power_domain(PD_ISP1, pmu_pd_on);
+ pmu_set_power_domain(PD_ISP0, pmu_pd_on);
+ pmu_set_power_domain(PD_VO, pmu_pd_on);
+ pmu_set_power_domain(PD_TCPD1, pmu_pd_on);
+ pmu_set_power_domain(PD_TCPD0, pmu_pd_on);
+ pmu_set_power_domain(PD_GPU, pmu_pd_on);
+}
+
+void rk3399_flush_l2_b(void)
+{
+ uint32_t wait_cnt = 0;
+
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B));
+ dsb();
+
+ /*
+ * The Big cluster flush L2 cache took ~4ms by default, give 10ms for
+ * the enough margin.
+ */
+ while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) &
+ BIT(L2_FLUSHDONE_CLUSTER_B))) {
+ wait_cnt++;
+ udelay(10);
+ if (wait_cnt == 10000 / 10)
+ WARN("L2 cache flush on suspend took longer than 10ms\n");
+ }
+
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B));
+}
+
+static void pmu_scu_b_pwrdn(void)
+{
+ uint32_t wait_cnt = 0;
+
+ if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) &
+ (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) !=
+ (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) {
+ ERROR("%s: not all cpus is off\n", __func__);
+ return;
+ }
+
+ rk3399_flush_l2_b();
+
+ mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG));
+
+ while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) &
+ BIT(STANDBY_BY_WFIL2_CLUSTER_B))) {
+ wait_cnt++;
+ udelay(1);
+ if (wait_cnt >= MAX_WAIT_COUNT)
+ ERROR("%s:wait cluster-b l2(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST));
+ }
+}
+
+static void pmu_scu_b_pwrup(void)
+{
+ mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG));
+}
+
+static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id)
+{
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ return core_pm_cfg_info[cpu_id];
+}
+
+static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value)
+{
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ core_pm_cfg_info[cpu_id] = value;
+#if !USE_COHERENT_MEM
+ flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id],
+ sizeof(uint32_t));
+#endif
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ uint32_t cfg_info;
+ uint32_t cpu_pd = PD_CPUL0 + cpu_id;
+ /*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically.
+ */
+
+ cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id);
+
+ if (cfg_info == core_pwr_pd) {
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ CORES_PM_DISABLE);
+ /* if the cores have be on, power off it firstly */
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ }
+
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
+ } else {
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
+ WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id);
+ return -EINVAL;
+ }
+
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ BIT(core_pm_sft_wakeup_en));
+ dsb();
+ }
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
+{
+ uint32_t cpu_pd;
+ uint32_t core_pm_value;
+
+ cpu_pd = PD_CPUL0 + cpu_id;
+ if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
+ return 0;
+
+ if (pd_cfg == core_pwr_pd) {
+ if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
+ return -EINVAL;
+
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ CORES_PM_DISABLE);
+
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+ pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
+ } else {
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+
+ core_pm_value = BIT(core_pm_en);
+ if (pd_cfg == core_pwr_wfi_int)
+ core_pm_value |= BIT(core_pm_int_wakeup_en);
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ core_pm_value);
+ dsb();
+ }
+
+ return 0;
+}
+
+static inline void clst_pwr_domain_suspend(plat_local_state_t lvl_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ uint32_t pll_id, clst_st_msk, clst_st_chk_msk, pmu_st;
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+
+ if (lvl_state == PLAT_MAX_OFF_STATE) {
+ if (cpu_id < PLATFORM_CLUSTER0_CORE_COUNT) {
+ pll_id = ALPLL_ID;
+ clst_st_msk = CLST_L_CPUS_MSK;
+ } else {
+ pll_id = ABPLL_ID;
+ clst_st_msk = CLST_B_CPUS_MSK <<
+ PLATFORM_CLUSTER0_CORE_COUNT;
+ }
+
+ clst_st_chk_msk = clst_st_msk & ~(BIT(cpu_id));
+
+ pmu_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST);
+
+ pmu_st &= clst_st_msk;
+
+ if (pmu_st == clst_st_chk_msk) {
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3),
+ PLL_SLOW_MODE);
+
+ clst_warmboot_data[pll_id] = PMU_CLST_RET;
+
+ pmu_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST);
+ pmu_st &= clst_st_msk;
+ if (pmu_st == clst_st_chk_msk)
+ return;
+ /*
+ * it is mean that others cpu is up again,
+ * we must resume the cfg at once.
+ */
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3),
+ PLL_NOMAL_MODE);
+ clst_warmboot_data[pll_id] = 0;
+ }
+ }
+}
+
+static int clst_pwr_domain_resume(plat_local_state_t lvl_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ uint32_t pll_id, pll_st;
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+
+ if (lvl_state == PLAT_MAX_OFF_STATE) {
+ if (cpu_id < PLATFORM_CLUSTER0_CORE_COUNT)
+ pll_id = ALPLL_ID;
+ else
+ pll_id = ABPLL_ID;
+
+ pll_st = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 3)) >>
+ PLL_MODE_SHIFT;
+
+ if (pll_st != NORMAL_MODE) {
+ WARN("%s: clst (%d) is in error mode (%d)\n",
+ __func__, pll_id, pll_st);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu;
+
+ boot_cpu = plat_my_core_pos();
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ if (cpu == boot_cpu)
+ continue;
+ cpus_power_domain_off(cpu, core_pwr_pd);
+ }
+}
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpu_id] = entrypoint;
+ dsb();
+
+ cpus_power_domain_on(cpu_id);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_off(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
+ plat_local_state_t lvl_state)
+{
+ if (lvl == MPIDR_AFFLVL1) {
+ clst_pwr_domain_suspend(lvl_state);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
+ cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint();
+ dsb();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl, plat_local_state_t lvl_state)
+{
+ if (lvl == MPIDR_AFFLVL1) {
+ clst_pwr_domain_suspend(lvl_state);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id),
+ CORES_PM_DISABLE);
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl,
+ plat_local_state_t lvl_state)
+{
+ if (lvl == MPIDR_AFFLVL1) {
+ clst_pwr_domain_resume(lvl_state);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_resume(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ /* Disable core_pm */
+ mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl, plat_local_state_t lvl_state)
+{
+ if (lvl == MPIDR_AFFLVL1) {
+ clst_pwr_domain_resume(lvl_state);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/**
+ * init_pmu_counts - Init timing counts in the PMU register area
+ *
+ * At various points when we power up or down parts of the system we need
+ * a delay to wait for power / clocks to become stable. The PMU has counters
+ * to help software do the delay properly. Basically, it works like this:
+ * - Software sets up counter values
+ * - When software turns on something in the PMU, the counter kicks off
+ * - The hardware sets a bit automatically when the counter has finished and
+ * software knows that the initialization is done.
+ *
+ * It's software's job to setup these counters. The hardware power on default
+ * for these settings is conservative, setting everything to 0x5dc0
+ * (750 ms in 32 kHz counts or 1 ms in 24 MHz counts).
+ *
+ * Note that some of these counters are only really used at suspend/resume
+ * time (for instance, that's the only time we turn off/on the oscillator) and
+ * others are used during normal runtime (like turning on/off a CPU or GPU) but
+ * it doesn't hurt to init everything at boot.
+ *
+ * Also note that these counters can run off the 32 kHz clock or the 24 MHz
+ * clock. While the 24 MHz clock can give us more precision, it's not always
+ * available (like when we turn the oscillator off at sleep time). The
+ * pmu_use_lf (lf: low freq) is available in power mode. Current understanding
+ * is that counts work like this:
+ * IF (pmu_use_lf == 0) || (power_mode_en == 0)
+ * use the 24M OSC for counts
+ * ELSE
+ * use the 32K OSC for counts
+ *
+ * Notes:
+ * - There is a separate bit for the PMU called PMU_24M_EN_CFG. At the moment
+ * we always keep that 0. This apparently choose between using the PLL as
+ * the source for the PMU vs. the 24M clock. If we ever set it to 1 we
+ * should consider how it affects these counts (if at all).
+ * - The power_mode_en is documented to auto-clear automatically when we leave
+ * "power mode". That's why most clocks are on 24M. Only timings used when
+ * in "power mode" are 32k.
+ * - In some cases the kernel may override these counts.
+ *
+ * The PMU_STABLE_CNT / PMU_OSC_CNT / PMU_PLLLOCK_CNT are important CNTs
+ * in power mode, we need to ensure that they are available.
+ */
+static void init_pmu_counts(void)
+{
+ /* COUNTS FOR INSIDE POWER MODE */
+
+ /*
+ * From limited testing, need PMU stable >= 2ms, but go overkill
+ * and choose 30 ms to match testing on past SoCs. Also let
+ * OSC have 30 ms for stabilization.
+ */
+ mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_32K_CNT_MS(30));
+ mmio_write_32(PMU_BASE + PMU_OSC_CNT, CYCL_32K_CNT_MS(30));
+
+ /* Unclear what these should be; try 3 ms */
+ mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_CNT, CYCL_32K_CNT_MS(3));
+
+ /* Unclear what this should be, but set the default explicitly */
+ mmio_write_32(PMU_BASE + PMU_TIMEOUT_CNT, 0x5dc0);
+
+ /* COUNTS FOR OUTSIDE POWER MODE */
+
+ /* Put something sorta conservative here until we know better */
+ mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(3));
+ mmio_write_32(PMU_BASE + PMU_DDRIO_PWRON_CNT, CYCL_24M_CNT_MS(1));
+ mmio_write_32(PMU_BASE + PMU_CENTER_PWRDN_CNT, CYCL_24M_CNT_MS(1));
+ mmio_write_32(PMU_BASE + PMU_CENTER_PWRUP_CNT, CYCL_24M_CNT_MS(1));
+
+ /*
+ * when we enable PMU_CLR_PERILP, it will shut down the SRAM, but
+ * M0 code run in SRAM, and we need it to check whether cpu enter
+ * FSM status, so we must wait M0 finish their code and enter WFI,
+ * then we can shutdown SRAM, according FSM order:
+ * ST_NORMAL->..->ST_SCU_L_PWRDN->..->ST_CENTER_PWRDN->ST_PERILP_PWRDN
+ * we can add delay when shutdown ST_SCU_L_PWRDN to guarantee M0 get
+ * the FSM status and enter WFI, then enable PMU_CLR_PERILP.
+ */
+ mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_MS(5));
+ mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_US(1));
+
+ /*
+ * Set CPU/GPU to 1 us.
+ *
+ * NOTE: Even though ATF doesn't configure the GPU we'll still setup
+ * counts here. After all ATF controls all these other bits and also
+ * chooses which clock these counters use.
+ */
+ mmio_write_32(PMU_BASE + PMU_SCU_B_PWRDN_CNT, CYCL_24M_CNT_US(1));
+ mmio_write_32(PMU_BASE + PMU_SCU_B_PWRUP_CNT, CYCL_24M_CNT_US(1));
+ mmio_write_32(PMU_BASE + PMU_GPU_PWRDN_CNT, CYCL_24M_CNT_US(1));
+ mmio_write_32(PMU_BASE + PMU_GPU_PWRUP_CNT, CYCL_24M_CNT_US(1));
+}
+
+static uint32_t clk_ddrc_save;
+
+static void sys_slp_config(void)
+{
+ uint32_t slp_mode_cfg = 0;
+
+ /* keep enabling clk_ddrc_bpll_src_en gate for DDRC */
+ clk_ddrc_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(3));
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), WMSK_BIT(1));
+
+ prepare_abpll_for_ddrctrl();
+ sram_func_set_ddrctl_pll(ABPLL_ID);
+
+ mmio_write_32(GRF_BASE + GRF_SOC_CON4, CCI_FORCE_WAKEUP);
+ mmio_write_32(PMU_BASE + PMU_CCI500_CON,
+ BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) |
+ BIT_WITH_WMSK(PMU_CLR_QREQ_CCI500_HW) |
+ BIT_WITH_WMSK(PMU_QGATING_CCI500_CFG));
+
+ mmio_write_32(PMU_BASE + PMU_ADB400_CON,
+ BIT_WITH_WMSK(PMU_CLR_CORE_L_HW) |
+ BIT_WITH_WMSK(PMU_CLR_CORE_L_2GIC_HW) |
+ BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW));
+
+ slp_mode_cfg = BIT(PMU_PWR_MODE_EN) |
+ BIT(PMU_WKUP_RST_EN) |
+ BIT(PMU_INPUT_CLAMP_EN) |
+ BIT(PMU_POWER_OFF_REQ_CFG) |
+ BIT(PMU_CPU0_PD_EN) |
+ BIT(PMU_L2_FLUSH_EN) |
+ BIT(PMU_L2_IDLE_EN) |
+ BIT(PMU_SCU_PD_EN) |
+ BIT(PMU_CCI_PD_EN) |
+ BIT(PMU_CLK_CORE_SRC_GATE_EN) |
+ BIT(PMU_ALIVE_USE_LF) |
+ BIT(PMU_SREF0_ENTER_EN) |
+ BIT(PMU_SREF1_ENTER_EN) |
+ BIT(PMU_DDRC0_GATING_EN) |
+ BIT(PMU_DDRC1_GATING_EN) |
+ BIT(PMU_DDRIO0_RET_EN) |
+ BIT(PMU_DDRIO0_RET_DE_REQ) |
+ BIT(PMU_DDRIO1_RET_EN) |
+ BIT(PMU_DDRIO1_RET_DE_REQ) |
+ BIT(PMU_CENTER_PD_EN) |
+ BIT(PMU_PERILP_PD_EN) |
+ BIT(PMU_CLK_PERILP_SRC_GATE_EN) |
+ BIT(PMU_PLL_PD_EN) |
+ BIT(PMU_CLK_CENTER_SRC_GATE_EN) |
+ BIT(PMU_OSC_DIS) |
+ BIT(PMU_PMU_USE_LF);
+
+ mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, BIT(PMU_GPIO_WKUP_EN));
+ mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg);
+
+ mmio_write_32(PMU_BASE + PMU_PLL_CON, PLL_PD_HW);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON0, EXTERNAL_32K);
+ mmio_write_32(PMUGRF_BASE, IOMUX_CLK_32K); /* 32k iomux */
+}
+
+static void set_hw_idle(uint32_t hw_idle)
+{
+ mmio_setbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle);
+}
+
+static void clr_hw_idle(uint32_t hw_idle)
+{
+ mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle);
+}
+
+static uint32_t iomux_status[12];
+static uint32_t pull_mode_status[12];
+static uint32_t gpio_direction[3];
+static uint32_t gpio_2_4_clk_gate;
+
+static void suspend_apio(void)
+{
+ struct bl_aux_rk_apio_info *suspend_apio;
+ int i;
+
+ suspend_apio = plat_get_rockchip_suspend_apio();
+
+ if (!suspend_apio)
+ return;
+
+ /* save gpio2 ~ gpio4 iomux and pull mode */
+ for (i = 0; i < 12; i++) {
+ iomux_status[i] = mmio_read_32(GRF_BASE +
+ GRF_GPIO2A_IOMUX + i * 4);
+ pull_mode_status[i] = mmio_read_32(GRF_BASE +
+ GRF_GPIO2A_P + i * 4);
+ }
+
+ /* store gpio2 ~ gpio4 clock gate state */
+ gpio_2_4_clk_gate = (mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)) >>
+ PCLK_GPIO2_GATE_SHIFT) & 0x07;
+
+ /* enable gpio2 ~ gpio4 clock gate */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
+
+ /* save gpio2 ~ gpio4 direction */
+ gpio_direction[0] = mmio_read_32(GPIO2_BASE + 0x04);
+ gpio_direction[1] = mmio_read_32(GPIO3_BASE + 0x04);
+ gpio_direction[2] = mmio_read_32(GPIO4_BASE + 0x04);
+
+ /* apio1 charge gpio3a0 ~ gpio3c7 */
+ if (suspend_apio->apio1) {
+
+ /* set gpio3a0 ~ gpio3c7 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO3A_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO3B_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO3C_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio3a0 ~ gpio3c7 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO3A_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO3B_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO3C_P, REG_SOC_WMSK | 0);
+
+ /* set gpio3a0 ~ gpio3c7 to input */
+ mmio_clrbits_32(GPIO3_BASE + 0x04, 0x00ffffff);
+ }
+
+ /* apio2 charge gpio2a0 ~ gpio2b4 */
+ if (suspend_apio->apio2) {
+
+ /* set gpio2a0 ~ gpio2b4 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO2B_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio2a0 ~ gpio2b4 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO2B_P, REG_SOC_WMSK | 0);
+
+ /* set gpio2a0 ~ gpio2b4 to input */
+ mmio_clrbits_32(GPIO2_BASE + 0x04, 0x00001fff);
+ }
+
+ /* apio3 charge gpio2c0 ~ gpio2d4*/
+ if (suspend_apio->apio3) {
+
+ /* set gpio2a0 ~ gpio2b4 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO2C_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO2D_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio2c0 ~ gpio2d4 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO2C_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO2D_P, REG_SOC_WMSK | 0);
+
+ /* set gpio2c0 ~ gpio2d4 to input */
+ mmio_clrbits_32(GPIO2_BASE + 0x04, 0x1fff0000);
+ }
+
+ /* apio4 charge gpio4c0 ~ gpio4c7, gpio4d0 ~ gpio4d6 */
+ if (suspend_apio->apio4) {
+
+ /* set gpio4c0 ~ gpio4d6 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO4D_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio4c0 ~ gpio4d6 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO4D_P, REG_SOC_WMSK | 0);
+
+ /* set gpio4c0 ~ gpio4d6 to input */
+ mmio_clrbits_32(GPIO4_BASE + 0x04, 0x7fff0000);
+ }
+
+ /* apio5 charge gpio3d0 ~ gpio3d7, gpio4a0 ~ gpio4a7*/
+ if (suspend_apio->apio5) {
+ /* set gpio3d0 ~ gpio4a7 iomux to gpio */
+ mmio_write_32(GRF_BASE + GRF_GPIO3D_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+ mmio_write_32(GRF_BASE + GRF_GPIO4A_IOMUX,
+ REG_SOC_WMSK | GRF_IOMUX_GPIO);
+
+ /* set gpio3d0 ~ gpio4a7 pull mode to pull none */
+ mmio_write_32(GRF_BASE + GRF_GPIO3D_P, REG_SOC_WMSK | 0);
+ mmio_write_32(GRF_BASE + GRF_GPIO4A_P, REG_SOC_WMSK | 0);
+
+ /* set gpio4c0 ~ gpio4d6 to input */
+ mmio_clrbits_32(GPIO3_BASE + 0x04, 0xff000000);
+ mmio_clrbits_32(GPIO4_BASE + 0x04, 0x000000ff);
+ }
+}
+
+static void resume_apio(void)
+{
+ struct bl_aux_rk_apio_info *suspend_apio;
+ int i;
+
+ suspend_apio = plat_get_rockchip_suspend_apio();
+
+ if (!suspend_apio)
+ return;
+
+ for (i = 0; i < 12; i++) {
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_P + i * 4,
+ REG_SOC_WMSK | pull_mode_status[i]);
+ mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4,
+ REG_SOC_WMSK | iomux_status[i]);
+ }
+
+ /* set gpio2 ~ gpio4 direction back to store value */
+ mmio_write_32(GPIO2_BASE + 0x04, gpio_direction[0]);
+ mmio_write_32(GPIO3_BASE + 0x04, gpio_direction[1]);
+ mmio_write_32(GPIO4_BASE + 0x04, gpio_direction[2]);
+
+ /* set gpio2 ~ gpio4 clock gate back to store value */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
+ BITS_WITH_WMASK(gpio_2_4_clk_gate, 0x07,
+ PCLK_GPIO2_GATE_SHIFT));
+}
+
+static void suspend_gpio(void)
+{
+ struct bl_aux_gpio_info *suspend_gpio;
+ uint32_t count;
+ int i;
+
+ suspend_gpio = plat_get_rockchip_suspend_gpio(&count);
+
+ for (i = 0; i < count; i++) {
+ gpio_set_value(suspend_gpio[i].index, suspend_gpio[i].polarity);
+ gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT);
+ udelay(1);
+ }
+}
+
+static void resume_gpio(void)
+{
+ struct bl_aux_gpio_info *suspend_gpio;
+ uint32_t count;
+ int i;
+
+ suspend_gpio = plat_get_rockchip_suspend_gpio(&count);
+
+ for (i = count - 1; i >= 0; i--) {
+ gpio_set_value(suspend_gpio[i].index,
+ !suspend_gpio[i].polarity);
+ gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT);
+ udelay(1);
+ }
+}
+
+void sram_save(void)
+{
+ size_t text_size = (char *)&__bl31_sram_text_real_end -
+ (char *)&__bl31_sram_text_start;
+ size_t data_size = (char *)&__bl31_sram_data_real_end -
+ (char *)&__bl31_sram_data_start;
+ size_t incbin_size = (char *)&__sram_incbin_real_end -
+ (char *)&__sram_incbin_start;
+
+ memcpy(&store_sram[0], &__bl31_sram_text_start, text_size);
+ memcpy(&store_sram[text_size], &__bl31_sram_data_start, data_size);
+ memcpy(&store_sram[text_size + data_size], &__sram_incbin_start,
+ incbin_size);
+}
+
+void sram_restore(void)
+{
+ size_t text_size = (char *)&__bl31_sram_text_real_end -
+ (char *)&__bl31_sram_text_start;
+ size_t data_size = (char *)&__bl31_sram_data_real_end -
+ (char *)&__bl31_sram_data_start;
+ size_t incbin_size = (char *)&__sram_incbin_real_end -
+ (char *)&__sram_incbin_start;
+
+ memcpy(&__bl31_sram_text_start, &store_sram[0], text_size);
+ memcpy(&__bl31_sram_data_start, &store_sram[text_size], data_size);
+ memcpy(&__sram_incbin_start, &store_sram[text_size + data_size],
+ incbin_size);
+}
+
+struct uart_debug {
+ uint32_t uart_dll;
+ uint32_t uart_dlh;
+ uint32_t uart_ier;
+ uint32_t uart_fcr;
+ uint32_t uart_mcr;
+ uint32_t uart_lcr;
+};
+
+#define UART_DLL 0x00
+#define UART_DLH 0x04
+#define UART_IER 0x04
+#define UART_FCR 0x08
+#define UART_LCR 0x0c
+#define UART_MCR 0x10
+#define UARTSRR 0x88
+
+#define UART_RESET BIT(0)
+#define UARTFCR_FIFOEN BIT(0)
+#define RCVR_FIFO_RESET BIT(1)
+#define XMIT_FIFO_RESET BIT(2)
+#define DIAGNOSTIC_MODE BIT(4)
+#define UARTLCR_DLAB BIT(7)
+
+static struct uart_debug uart_save;
+
+void suspend_uart(void)
+{
+ uint32_t uart_base = rockchip_get_uart_base();
+
+ if (uart_base == 0)
+ return;
+
+ uart_save.uart_lcr = mmio_read_32(uart_base + UART_LCR);
+ uart_save.uart_ier = mmio_read_32(uart_base + UART_IER);
+ uart_save.uart_mcr = mmio_read_32(uart_base + UART_MCR);
+ mmio_write_32(uart_base + UART_LCR,
+ uart_save.uart_lcr | UARTLCR_DLAB);
+ uart_save.uart_dll = mmio_read_32(uart_base + UART_DLL);
+ uart_save.uart_dlh = mmio_read_32(uart_base + UART_DLH);
+ mmio_write_32(uart_base + UART_LCR, uart_save.uart_lcr);
+}
+
+void resume_uart(void)
+{
+ uint32_t uart_base = rockchip_get_uart_base();
+ uint32_t uart_lcr;
+
+ if (uart_base == 0)
+ return;
+
+ mmio_write_32(uart_base + UARTSRR,
+ XMIT_FIFO_RESET | RCVR_FIFO_RESET | UART_RESET);
+
+ uart_lcr = mmio_read_32(uart_base + UART_LCR);
+ mmio_write_32(uart_base + UART_MCR, DIAGNOSTIC_MODE);
+ mmio_write_32(uart_base + UART_LCR, uart_lcr | UARTLCR_DLAB);
+ mmio_write_32(uart_base + UART_DLL, uart_save.uart_dll);
+ mmio_write_32(uart_base + UART_DLH, uart_save.uart_dlh);
+ mmio_write_32(uart_base + UART_LCR, uart_save.uart_lcr);
+ mmio_write_32(uart_base + UART_IER, uart_save.uart_ier);
+ mmio_write_32(uart_base + UART_FCR, UARTFCR_FIFOEN);
+ mmio_write_32(uart_base + UART_MCR, uart_save.uart_mcr);
+}
+
+void save_usbphy(void)
+{
+ store_usbphy0[0] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL0);
+ store_usbphy0[1] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL2);
+ store_usbphy0[2] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL3);
+ store_usbphy0[3] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL12);
+ store_usbphy0[4] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL13);
+ store_usbphy0[5] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL15);
+ store_usbphy0[6] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL16);
+
+ store_usbphy1[0] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL0);
+ store_usbphy1[1] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL2);
+ store_usbphy1[2] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL3);
+ store_usbphy1[3] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL12);
+ store_usbphy1[4] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL13);
+ store_usbphy1[5] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL15);
+ store_usbphy1[6] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL16);
+}
+
+void restore_usbphy(void)
+{
+ mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL0,
+ REG_SOC_WMSK | store_usbphy0[0]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL2,
+ REG_SOC_WMSK | store_usbphy0[1]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL3,
+ REG_SOC_WMSK | store_usbphy0[2]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL12,
+ REG_SOC_WMSK | store_usbphy0[3]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL13,
+ REG_SOC_WMSK | store_usbphy0[4]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL15,
+ REG_SOC_WMSK | store_usbphy0[5]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL16,
+ REG_SOC_WMSK | store_usbphy0[6]);
+
+ mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL0,
+ REG_SOC_WMSK | store_usbphy1[0]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL2,
+ REG_SOC_WMSK | store_usbphy1[1]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL3,
+ REG_SOC_WMSK | store_usbphy1[2]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL12,
+ REG_SOC_WMSK | store_usbphy1[3]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL13,
+ REG_SOC_WMSK | store_usbphy1[4]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL15,
+ REG_SOC_WMSK | store_usbphy1[5]);
+ mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL16,
+ REG_SOC_WMSK | store_usbphy1[6]);
+}
+
+void grf_register_save(void)
+{
+ int i;
+
+ store_grf_soc_con0 = mmio_read_32(GRF_BASE + GRF_SOC_CON(0));
+ store_grf_soc_con1 = mmio_read_32(GRF_BASE + GRF_SOC_CON(1));
+ store_grf_soc_con2 = mmio_read_32(GRF_BASE + GRF_SOC_CON(2));
+ store_grf_soc_con3 = mmio_read_32(GRF_BASE + GRF_SOC_CON(3));
+ store_grf_soc_con4 = mmio_read_32(GRF_BASE + GRF_SOC_CON(4));
+ store_grf_soc_con7 = mmio_read_32(GRF_BASE + GRF_SOC_CON(7));
+
+ for (i = 0; i < 4; i++)
+ store_grf_ddrc_con[i] =
+ mmio_read_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4);
+
+ store_grf_io_vsel = mmio_read_32(GRF_BASE + GRF_IO_VSEL);
+}
+
+void grf_register_restore(void)
+{
+ int i;
+
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(0),
+ REG_SOC_WMSK | store_grf_soc_con0);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(1),
+ REG_SOC_WMSK | store_grf_soc_con1);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(2),
+ REG_SOC_WMSK | store_grf_soc_con2);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(3),
+ REG_SOC_WMSK | store_grf_soc_con3);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(4),
+ REG_SOC_WMSK | store_grf_soc_con4);
+ mmio_write_32(GRF_BASE + GRF_SOC_CON(7),
+ REG_SOC_WMSK | store_grf_soc_con7);
+
+ for (i = 0; i < 4; i++)
+ mmio_write_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4,
+ REG_SOC_WMSK | store_grf_ddrc_con[i]);
+
+ mmio_write_32(GRF_BASE + GRF_IO_VSEL, REG_SOC_WMSK | store_grf_io_vsel);
+}
+
+void cru_register_save(void)
+{
+ int i;
+
+ for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4)
+ store_cru[i / 4] = mmio_read_32(CRU_BASE + i);
+}
+
+void cru_register_restore(void)
+{
+ int i;
+
+ for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) {
+
+ /*
+ * since DPLL, CRU_CLKSEL_CON6 have been restore in
+ * dmc_resume, ABPLL will resote later, so skip them
+ */
+ if ((i == CRU_CLKSEL_CON6) ||
+ (i >= CRU_PLL_CON(ABPLL_ID, 0) &&
+ i <= CRU_PLL_CON(DPLL_ID, 5)))
+ continue;
+
+ if ((i == CRU_PLL_CON(ALPLL_ID, 2)) ||
+ (i == CRU_PLL_CON(CPLL_ID, 2)) ||
+ (i == CRU_PLL_CON(GPLL_ID, 2)) ||
+ (i == CRU_PLL_CON(NPLL_ID, 2)) ||
+ (i == CRU_PLL_CON(VPLL_ID, 2)))
+ mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
+ /*
+ * CRU_GLB_CNT_TH and CRU_CLKSEL_CON97~CRU_CLKSEL_CON107
+ * not need do high 16bit mask
+ */
+ else if ((i > 0x27c && i < 0x2b0) || (i == 0x508))
+ mmio_write_32(CRU_BASE + i, store_cru[i / 4]);
+ else
+ mmio_write_32(CRU_BASE + i,
+ REG_SOC_WMSK | store_cru[i / 4]);
+ }
+}
+
+void wdt_register_save(void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ store_wdt0[i] = mmio_read_32(WDT0_BASE + i * 4);
+ store_wdt1[i] = mmio_read_32(WDT1_BASE + i * 4);
+ }
+ pmu_enable_watchdog0 = (uint8_t) store_wdt0[0] & 0x1;
+}
+
+void wdt_register_restore(void)
+{
+ int i;
+
+ for (i = 1; i >= 0; i--) {
+ mmio_write_32(WDT0_BASE + i * 4, store_wdt0[i]);
+ mmio_write_32(WDT1_BASE + i * 4, store_wdt1[i]);
+ }
+
+ /* write 0x76 to cnt_restart to keep watchdog alive */
+ mmio_write_32(WDT0_BASE + 0x0c, 0x76);
+ mmio_write_32(WDT1_BASE + 0x0c, 0x76);
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ uint32_t wait_cnt = 0;
+ uint32_t status = 0;
+
+ ddr_prepare_for_sys_suspend();
+ dmc_suspend();
+ pmu_scu_b_pwrdn();
+
+ gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+ gicv3_distif_save(&dist_ctx);
+
+ /* need to save usbphy before shutdown PERIHP PD */
+ save_usbphy();
+
+ pmu_power_domains_suspend();
+ set_hw_idle(BIT(PMU_CLR_CENTER1) |
+ BIT(PMU_CLR_ALIVE) |
+ BIT(PMU_CLR_MSCH0) |
+ BIT(PMU_CLR_MSCH1) |
+ BIT(PMU_CLR_CCIM0) |
+ BIT(PMU_CLR_CCIM1) |
+ BIT(PMU_CLR_CENTER) |
+ BIT(PMU_CLR_PERILP) |
+ BIT(PMU_CLR_PERILPM0) |
+ BIT(PMU_CLR_GIC));
+ set_pmu_rsthold();
+ sys_slp_config();
+
+ m0_configure_execute_addr(M0PMU_BINCODE_BASE);
+ m0_start();
+
+ pmu_sgrf_rst_hld();
+
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ ((uintptr_t)&pmu_cpuson_entrypoint >>
+ CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK);
+
+ mmio_write_32(PMU_BASE + PMU_ADB400_CON,
+ BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) |
+ BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) |
+ BIT_WITH_WMSK(PMU_PWRDWN_REQ_GIC2_CORE_B_SW));
+ dsb();
+ status = BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST) |
+ BIT(PMU_PWRDWN_REQ_CORE_B_SW_ST) |
+ BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST);
+ while ((mmio_read_32(PMU_BASE +
+ PMU_ADB400_ST) & status) != status) {
+ wait_cnt++;
+ if (wait_cnt >= MAX_WAIT_COUNT) {
+ ERROR("%s:wait cluster-b l2(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_ADB400_ST));
+ panic();
+ }
+ udelay(1);
+ }
+ mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN));
+
+ wdt_register_save();
+ secure_watchdog_gate();
+
+ /*
+ * Disabling PLLs/PWM/DVFS is approaching WFI which is
+ * the last steps in suspend.
+ */
+ disable_dvfs_plls();
+ disable_pwms();
+ disable_nodvfs_plls();
+
+ suspend_apio();
+ suspend_gpio();
+ suspend_uart();
+ grf_register_save();
+ cru_register_save();
+ sram_save();
+ plat_rockchip_save_gpio();
+
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ uint32_t wait_cnt = 0;
+ uint32_t status = 0;
+
+ plat_rockchip_restore_gpio();
+ cru_register_restore();
+ grf_register_restore();
+ wdt_register_restore();
+ resume_uart();
+ resume_apio();
+ resume_gpio();
+ enable_nodvfs_plls();
+ enable_pwms();
+ /* PWM regulators take time to come up; give 300us to be safe. */
+ udelay(300);
+ enable_dvfs_plls();
+
+ secure_sgrf_init();
+ secure_sgrf_ddr_rgn_init();
+
+ /* restore clk_ddrc_bpll_src_en gate */
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3),
+ BITS_WITH_WMASK(clk_ddrc_save, 0xff, 0));
+
+ /*
+ * The wakeup status is not cleared by itself, we need to clear it
+ * manually. Otherwise we will alway query some interrupt next time.
+ *
+ * NOTE: If the kernel needs to query this, we might want to stash it
+ * somewhere.
+ */
+ mmio_write_32(PMU_BASE + PMU_WAKEUP_STATUS, 0xffffffff);
+ mmio_write_32(PMU_BASE + PMU_WKUP_CFG4, 0x00);
+
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+
+ mmio_write_32(PMU_BASE + PMU_CCI500_CON,
+ WMSK_BIT(PMU_CLR_PREQ_CCI500_HW) |
+ WMSK_BIT(PMU_CLR_QREQ_CCI500_HW) |
+ WMSK_BIT(PMU_QGATING_CCI500_CFG));
+ dsb();
+ mmio_clrbits_32(PMU_BASE + PMU_PWRDN_CON,
+ BIT(PMU_SCU_B_PWRDWN_EN));
+
+ mmio_write_32(PMU_BASE + PMU_ADB400_CON,
+ WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) |
+ WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_SW) |
+ WMSK_BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW) |
+ WMSK_BIT(PMU_CLR_CORE_L_HW) |
+ WMSK_BIT(PMU_CLR_CORE_L_2GIC_HW) |
+ WMSK_BIT(PMU_CLR_GIC2_CORE_L_HW));
+
+ status = BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST) |
+ BIT(PMU_PWRDWN_REQ_CORE_B_SW_ST) |
+ BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST);
+
+ while ((mmio_read_32(PMU_BASE +
+ PMU_ADB400_ST) & status)) {
+ wait_cnt++;
+ if (wait_cnt >= MAX_WAIT_COUNT) {
+ ERROR("%s:wait cluster-b l2(%x)\n", __func__,
+ mmio_read_32(PMU_BASE + PMU_ADB400_ST));
+ panic();
+ }
+ udelay(1);
+ }
+
+ pmu_scu_b_pwrup();
+ pmu_power_domains_resume();
+
+ restore_abpll();
+ clr_hw_idle(BIT(PMU_CLR_CENTER1) |
+ BIT(PMU_CLR_ALIVE) |
+ BIT(PMU_CLR_MSCH0) |
+ BIT(PMU_CLR_MSCH1) |
+ BIT(PMU_CLR_CCIM0) |
+ BIT(PMU_CLR_CCIM1) |
+ BIT(PMU_CLR_CENTER) |
+ BIT(PMU_CLR_PERILP) |
+ BIT(PMU_CLR_PERILPM0) |
+ BIT(PMU_CLR_GIC));
+
+ gicv3_distif_init_restore(&dist_ctx);
+ gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+ plat_rockchip_gic_cpuif_enable();
+ m0_stop();
+
+ restore_usbphy();
+
+ ddr_prepare_for_sys_resume();
+
+ return 0;
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ struct bl_aux_gpio_info *rst_gpio;
+
+ rst_gpio = plat_get_rockchip_gpio_reset();
+
+ if (rst_gpio) {
+ gpio_set_direction(rst_gpio->index, GPIO_DIR_OUT);
+ gpio_set_value(rst_gpio->index, rst_gpio->polarity);
+ } else {
+ soc_global_soft_reset();
+ }
+
+ while (1)
+ ;
+}
+
+void __dead2 rockchip_soc_system_off(void)
+{
+ struct bl_aux_gpio_info *poweroff_gpio;
+
+ poweroff_gpio = plat_get_rockchip_gpio_poweroff();
+
+ if (poweroff_gpio) {
+ /*
+ * if use tsadc over temp pin(GPIO1A6) as shutdown gpio,
+ * need to set this pin iomux back to gpio function
+ */
+ if (poweroff_gpio->index == TSADC_INT_PIN) {
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX,
+ GPIO1A6_IOMUX);
+ }
+ gpio_set_direction(poweroff_gpio->index, GPIO_DIR_OUT);
+ gpio_set_value(poweroff_gpio->index, poweroff_gpio->polarity);
+ } else {
+ WARN("Do nothing when system off\n");
+ }
+
+ while (1)
+ ;
+}
+
+void rockchip_plat_mmu_el3(void)
+{
+ size_t sram_size;
+
+ /* sram.text size */
+ sram_size = (char *)&__bl31_sram_text_end -
+ (char *)&__bl31_sram_text_start;
+ mmap_add_region((unsigned long)&__bl31_sram_text_start,
+ (unsigned long)&__bl31_sram_text_start,
+ sram_size, MT_MEMORY | MT_RO | MT_SECURE);
+
+ /* sram.data size */
+ sram_size = (char *)&__bl31_sram_data_end -
+ (char *)&__bl31_sram_data_start;
+ mmap_add_region((unsigned long)&__bl31_sram_data_start,
+ (unsigned long)&__bl31_sram_data_start,
+ sram_size, MT_MEMORY | MT_RW | MT_SECURE);
+
+ sram_size = (char *)&__bl31_sram_stack_end -
+ (char *)&__bl31_sram_stack_start;
+ mmap_add_region((unsigned long)&__bl31_sram_stack_start,
+ (unsigned long)&__bl31_sram_stack_start,
+ sram_size, MT_MEMORY | MT_RW | MT_SECURE);
+
+ sram_size = (char *)&__sram_incbin_end - (char *)&__sram_incbin_start;
+ mmap_add_region((unsigned long)&__sram_incbin_start,
+ (unsigned long)&__sram_incbin_start,
+ sram_size, MT_NON_CACHEABLE | MT_RW | MT_SECURE);
+}
+
+void plat_rockchip_pmu_init(void)
+{
+ uint32_t cpu;
+
+ rockchip_pd_lock_init();
+
+ /* register requires 32bits mode, switch it to 32 bits */
+ cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot;
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ for (cpu = 0; cpu < PLATFORM_CLUSTER_COUNT; cpu++)
+ clst_warmboot_data[cpu] = 0;
+
+ /* config cpu's warm boot address */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1),
+ (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) |
+ CPU_BOOT_ADDR_WMASK);
+ mmio_write_32(PMU_BASE + PMU_NOC_AUTO_ENA, NOC_AUTO_ENABLE);
+
+ /*
+ * Enable Schmitt trigger for better 32 kHz input signal, which is
+ * important for suspend/resume reliability among other things.
+ */
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_SMT, GPIO0A0_SMT_ENABLE);
+
+ init_pmu_counts();
+
+ nonboot_cpus_off();
+
+ INFO("%s(%d): pd status %x\n", __func__, __LINE__,
+ mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
+}
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.h b/plat/rockchip/rk3399/drivers/pmu/pmu.h
new file mode 100644
index 0000000..bb7de50
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_H
+#define PMU_H
+
+#include <pmu_bits.h>
+#include <pmu_regs.h>
+#include <soc.h>
+
+/* Allocate sp reginon in pmusram */
+#define PSRAM_SP_SIZE 0x80
+#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE)
+
+/*****************************************************************************
+ * Common define for per soc pmu.h
+ *****************************************************************************/
+/* The ways of cores power domain contorlling */
+enum cores_pm_ctr_mode {
+ core_pwr_pd = 0,
+ core_pwr_wfi = 1,
+ core_pwr_wfi_int = 2
+};
+
+/*****************************************************************************
+ * pmu con,reg
+ *****************************************************************************/
+#define PMU_WKUP_CFG(n) ((n) * 4)
+
+#define PMU_CORE_PM_CON(cpu) (0xc0 + (cpu * 4))
+
+/* the shift of bits for cores status */
+enum pmu_core_pwrst_shift {
+ clstl_cpu_wfe = 2,
+ clstl_cpu_wfi = 6,
+ clstb_cpu_wfe = 12,
+ clstb_cpu_wfi = 16
+};
+
+#define CKECK_WFE_MSK 0x1
+#define CKECK_WFI_MSK 0x10
+#define CKECK_WFEI_MSK 0x11
+
+/* Specific features required */
+#define AP_PWROFF 0x0a
+
+#define GPIO0A0_SMT_ENABLE BITS_WITH_WMASK(1, 3, 0)
+#define GPIO1A6_IOMUX BITS_WITH_WMASK(0, 3, 12)
+
+#define TSADC_INT_PIN 38
+#define CORES_PM_DISABLE 0x0
+
+#define PD_CTR_LOOP 10000
+#define CHK_CPU_LOOP 500
+#define MAX_WAIT_COUNT 1000
+
+#define GRF_SOC_CON4 0x0e210
+
+#define PMUGRF_GPIO0A_SMT 0x0120
+#define PMUGRF_SOC_CON0 0x0180
+
+#define CCI_FORCE_WAKEUP WMSK_BIT(8)
+#define EXTERNAL_32K WMSK_BIT(0)
+
+#define PLL_PD_HW 0xff
+#define IOMUX_CLK_32K 0x00030002
+#define NOC_AUTO_ENABLE 0x3fffffff
+
+#define SAVE_QOS(array, NAME) \
+ RK3399_CPU_AXI_SAVE_QOS(array, CPU_AXI_##NAME##_QOS_BASE)
+#define RESTORE_QOS(array, NAME) \
+ RK3399_CPU_AXI_RESTORE_QOS(array, CPU_AXI_##NAME##_QOS_BASE)
+
+#define RK3399_CPU_AXI_SAVE_QOS(array, base) do { \
+ array[0] = mmio_read_32(base + CPU_AXI_QOS_ID_COREID); \
+ array[1] = mmio_read_32(base + CPU_AXI_QOS_REVISIONID); \
+ array[2] = mmio_read_32(base + CPU_AXI_QOS_PRIORITY); \
+ array[3] = mmio_read_32(base + CPU_AXI_QOS_MODE); \
+ array[4] = mmio_read_32(base + CPU_AXI_QOS_BANDWIDTH); \
+ array[5] = mmio_read_32(base + CPU_AXI_QOS_SATURATION); \
+ array[6] = mmio_read_32(base + CPU_AXI_QOS_EXTCONTROL); \
+} while (0)
+
+#define RK3399_CPU_AXI_RESTORE_QOS(array, base) do { \
+ mmio_write_32(base + CPU_AXI_QOS_ID_COREID, array[0]); \
+ mmio_write_32(base + CPU_AXI_QOS_REVISIONID, array[1]); \
+ mmio_write_32(base + CPU_AXI_QOS_PRIORITY, array[2]); \
+ mmio_write_32(base + CPU_AXI_QOS_MODE, array[3]); \
+ mmio_write_32(base + CPU_AXI_QOS_BANDWIDTH, array[4]); \
+ mmio_write_32(base + CPU_AXI_QOS_SATURATION, array[5]); \
+ mmio_write_32(base + CPU_AXI_QOS_EXTCONTROL, array[6]); \
+} while (0)
+
+struct pmu_slpdata_s {
+ uint32_t cci_m0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t cci_m1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t dmac0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t dmac1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t dcf_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t crypto0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t crypto1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t pmu_cm0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t peri_cm1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t gic_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t sdmmc_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t gmac_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t emmc_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t usb_otg0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t usb_otg1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t usb_host0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t usb_host1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t gpu_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t video_m0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t video_m1_r_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t video_m1_w_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t rga_r_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t rga_w_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vop_big_r[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vop_big_w[CPU_AXI_QOS_NUM_REGS];
+ uint32_t vop_little[CPU_AXI_QOS_NUM_REGS];
+ uint32_t iep_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp1_m0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp1_m1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp0_m0_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t isp0_m1_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t hdcp_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t perihp_nsp_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t perilp_nsp_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t perilpslv_nsp_qos[CPU_AXI_QOS_NUM_REGS];
+ uint32_t sdio_qos[CPU_AXI_QOS_NUM_REGS];
+};
+
+extern uint32_t clst_warmboot_data[PLATFORM_CLUSTER_COUNT];
+
+extern void sram_func_set_ddrctl_pll(uint32_t pll_src);
+void pmu_power_domains_on(void);
+
+#endif /* PMU_H */
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c b/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c
new file mode 100644
index 0000000..25596b1
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* convoluted way to make sure that the define is pasted just the right way */
+#define INCBIN(file, sym, sec) \
+ __asm__( \
+ ".section " sec "\n" \
+ ".global " sym "\n" \
+ ".type " sym ", %object\n" \
+ ".align 4\n" \
+ sym ":\n" \
+ ".incbin \"" file "\"\n" \
+ ".size " sym ", .-" sym "\n" \
+ ".global " sym "_end\n" \
+ sym "_end:\n" \
+ )
+
+INCBIN(RK3399M0FW, "rk3399m0_bin", ".sram.incbin");
+INCBIN(RK3399M0PMUFW, "rk3399m0pmu_bin", ".pmusram.incbin");
diff --git a/plat/rockchip/rk3399/drivers/pwm/pwm.c b/plat/rockchip/rk3399/drivers/pwm/pwm.c
new file mode 100644
index 0000000..11c1565
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pwm/pwm.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_private.h>
+#include <pmu.h>
+#include <pwm.h>
+#include <soc.h>
+
+#define PWM0_IOMUX_PWM_EN (1 << 0)
+#define PWM1_IOMUX_PWM_EN (1 << 1)
+#define PWM2_IOMUX_PWM_EN (1 << 2)
+#define PWM3_IOMUX_PWM_EN (1 << 3)
+
+struct pwm_data_s {
+ uint32_t iomux_bitmask;
+ uint32_t enable_bitmask;
+};
+
+static struct pwm_data_s pwm_data;
+
+/*
+ * Disable the PWMs.
+ */
+void disable_pwms(void)
+{
+ uint32_t i, val;
+
+ pwm_data.iomux_bitmask = 0;
+
+ /* Save PWMs pinmux and change PWMs pinmux to GPIOs */
+ val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
+ if (((val >> GRF_GPIO4C2_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C2_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM0_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C2_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+
+ val = mmio_read_32(GRF_BASE + GRF_GPIO4C_IOMUX);
+ if (((val >> GRF_GPIO4C6_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == GRF_GPIO4C6_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM1_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C6_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+
+ val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX);
+ if (((val >> PMUGRF_GPIO1C3_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO1C3_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM2_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO1C3_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
+ }
+
+ val = mmio_read_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX);
+ if (((val >> PMUGRF_GPIO0A6_IOMUX_SHIFT) &
+ GRF_IOMUX_2BIT_MASK) == PMUGRF_GPIO0A6_IOMUX_PWM) {
+ pwm_data.iomux_bitmask |= PWM3_IOMUX_PWM_EN;
+ val = BITS_WITH_WMASK(GRF_IOMUX_GPIO, GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO0A6_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
+ }
+
+ /* Disable the pwm channel */
+ pwm_data.enable_bitmask = 0;
+ for (i = 0; i < 4; i++) {
+ val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
+ if ((val & PWM_ENABLE) != PWM_ENABLE)
+ continue;
+ pwm_data.enable_bitmask |= (1 << i);
+ mmio_write_32(PWM_BASE + PWM_CTRL(i), val & ~PWM_ENABLE);
+ }
+}
+
+/*
+ * Enable the PWMs.
+ */
+void enable_pwms(void)
+{
+ uint32_t i, val;
+
+ for (i = 0; i < 4; i++) {
+ val = mmio_read_32(PWM_BASE + PWM_CTRL(i));
+ if (!(pwm_data.enable_bitmask & (1 << i)))
+ continue;
+ mmio_write_32(PWM_BASE + PWM_CTRL(i), val | PWM_ENABLE);
+ }
+
+ /* Restore all IOMUXes */
+ if (pwm_data.iomux_bitmask & PWM3_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(PMUGRF_GPIO0A6_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO0A6_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_IOMUX, val);
+ }
+
+ if (pwm_data.iomux_bitmask & PWM2_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(PMUGRF_GPIO1C3_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ PMUGRF_GPIO1C3_IOMUX_SHIFT);
+ mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1C_IOMUX, val);
+ }
+
+ if (pwm_data.iomux_bitmask & PWM1_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(GRF_GPIO4C6_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C6_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+
+ if (pwm_data.iomux_bitmask & PWM0_IOMUX_PWM_EN) {
+ val = BITS_WITH_WMASK(GRF_GPIO4C2_IOMUX_PWM,
+ GRF_IOMUX_2BIT_MASK,
+ GRF_GPIO4C2_IOMUX_SHIFT);
+ mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, val);
+ }
+}
diff --git a/plat/rockchip/rk3399/drivers/pwm/pwm.h b/plat/rockchip/rk3399/drivers/pwm/pwm.h
new file mode 100644
index 0000000..d665392
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/pwm/pwm.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PWM_H
+#define PWM_H
+
+void disable_pwms(void);
+void enable_pwms(void);
+
+#endif /* PWM_H */
diff --git a/plat/rockchip/rk3399/drivers/secure/secure.c b/plat/rockchip/rk3399/drivers/secure/secure.c
new file mode 100644
index 0000000..13c83ca
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/secure/secure.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include <plat_private.h>
+#include <secure.h>
+#include <soc.h>
+
+static void sgrf_ddr_rgn_global_bypass(uint32_t bypass)
+{
+ if (bypass)
+ /* set bypass (non-secure regions) for whole ddr regions */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16),
+ SGRF_DDR_RGN_BYPS);
+ else
+ /* cancel bypass for whole ddr regions */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16),
+ SGRF_DDR_RGN_NO_BYPS);
+}
+
+/**
+ * There are 8 + 1 regions for DDR secure control:
+ * DDR_RGN_0 ~ DDR_RGN_7: Per DDR_RGNs grain size is 1MB
+ * DDR_RGN_X - the memories of exclude DDR_RGN_0 ~ DDR_RGN_7
+ *
+ * DDR_RGN_0 - start address of the RGN0
+ * DDR_RGN_8 - end address of the RGN0
+ * DDR_RGN_1 - start address of the RGN1
+ * DDR_RGN_9 - end address of the RGN1
+ * ...
+ * DDR_RGN_7 - start address of the RGN7
+ * DDR_RGN_15 - end address of the RGN7
+ * DDR_RGN_16 - bit 0 ~ 7 is bitmap for RGN0~7 secure,0: disable, 1: enable
+ * bit 8 is setting for RGNx, the rest of the memory and region
+ * which excludes RGN0~7, 0: disable, 1: enable
+ * bit 9, the global secure configuration via bypass, 0: disable
+ * bypass, 1: enable bypass
+ *
+ * @rgn - the DDR regions 0 ~ 7 which are can be configured.
+ * @st - start address to set as secure
+ * @sz - length of area to set as secure
+ * The @st_mb and @ed_mb indicate the start and end addresses for which to set
+ * the security, and the unit is megabyte. When the st_mb == 0, ed_mb == 0, the
+ * address range 0x0 ~ 0xfffff is secure.
+ *
+ * For example, if we would like to set the range [0, 32MB) is security via
+ * DDR_RGN0, then rgn == 0, st_mb == 0, ed_mb == 31.
+ */
+static void sgrf_ddr_rgn_config(uint32_t rgn,
+ uintptr_t st, size_t sz)
+{
+ uintptr_t ed = st + sz;
+ uintptr_t st_mb, ed_mb;
+
+ assert(rgn <= 7);
+ assert(st < ed);
+
+ /* check aligned 1MB */
+ assert(st % SIZE_M(1) == 0);
+ assert(ed % SIZE_M(1) == 0);
+
+ st_mb = st / SIZE_M(1);
+ ed_mb = ed / SIZE_M(1);
+
+ /* set ddr region addr start */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(rgn),
+ BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_0_16_WMSK, 0));
+
+ /* set ddr region addr end */
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(rgn + 8),
+ BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_0_16_WMSK, 0));
+
+ mmio_write_32(SGRF_BASE + SGRF_DDRRGN_CON0_16(16),
+ BIT_WITH_WMSK(rgn));
+}
+
+void secure_watchdog_gate(void)
+{
+ /**
+ * Disable CA53 and CM0 wdt pclk
+ * BIT[8]: ca53 wdt pclk, 0: enable 1: disable
+ * BIT[10]: cm0 wdt pclk, 0: enable 1: disable
+ */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3),
+ BIT_WITH_WMSK(PCLK_WDT_CA53_GATE_SHIFT) |
+ BIT_WITH_WMSK(PCLK_WDT_CM0_GATE_SHIFT));
+}
+
+__pmusramfunc void secure_watchdog_ungate(void)
+{
+ /**
+ * Enable CA53 and CM0 wdt pclk
+ * BIT[8]: ca53 wdt pclk, 0: enable 1: disable
+ * BIT[10]: cm0 wdt pclk, 0: enable 1: disable
+ */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3),
+ WMSK_BIT(PCLK_WDT_CA53_GATE_SHIFT) |
+ WMSK_BIT(PCLK_WDT_CM0_GATE_SHIFT));
+}
+
+__pmusramfunc void sram_secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT1, 0xffffffff);
+
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
+ TIMER_EN | TIMER_FMODE);
+}
+
+void secure_timer_init(void)
+{
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_END_COUNT1, 0xffffffff);
+
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_INIT_COUNT0, 0x0);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
+ TIMER_EN | TIMER_FMODE);
+}
+
+void secure_sgrf_init(void)
+{
+ /* security config for master */
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5),
+ REG_SOC_WMSK | SGRF_SOC_ALLMST_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6),
+ REG_SOC_WMSK | SGRF_SOC_ALLMST_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SOC_CON(7),
+ REG_SOC_WMSK | SGRF_SOC_ALLMST_NS);
+
+ /* security config for slave */
+ mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(0),
+ SGRF_PMU_SLV_S_CFGED |
+ SGRF_PMU_SLV_CRYPTO1_NS);
+ mmio_write_32(SGRF_BASE + SGRF_PMU_SLV_CON0_1(1),
+ SGRF_SLV_S_WMSK | SGRF_PMUSRAM_S);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(0),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(1),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(2),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(3),
+ SGRF_SLV_S_WMSK | SGRF_SLV_S_ALL_NS);
+ mmio_write_32(SGRF_BASE + SGRF_SLV_SECURE_CON0_4(4),
+ SGRF_SLV_S_WMSK | SGRF_INTSRAM_S);
+}
+
+void secure_sgrf_ddr_rgn_init(void)
+{
+ sgrf_ddr_rgn_config(0, TZRAM_BASE, TZRAM_SIZE);
+ sgrf_ddr_rgn_global_bypass(0);
+}
diff --git a/plat/rockchip/rk3399/drivers/secure/secure.h b/plat/rockchip/rk3399/drivers/secure/secure.h
new file mode 100644
index 0000000..e31c999
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/secure/secure.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SECURE_H
+#define SECURE_H
+
+/**************************************************
+ * sgrf reg, offset
+ **************************************************/
+#define SGRF_SOC_CON0_1(n) (0xc000 + (n) * 4)
+#define SGRF_SOC_CON3_7(n) (0xe00c + ((n) - 3) * 4)
+#define SGRF_SOC_CON8_15(n) (0x8020 + ((n) - 8) * 4)
+#define SGRF_SOC_CON(n) (n < 3 ? SGRF_SOC_CON0_1(n) :\
+ (n < 8 ? SGRF_SOC_CON3_7(n) :\
+ SGRF_SOC_CON8_15(n)))
+
+#define SGRF_PMU_SLV_CON0_1(n) (0xc240 + ((n) - 0) * 4)
+#define SGRF_SLV_SECURE_CON0_4(n) (0xe3c0 + ((n) - 0) * 4)
+#define SGRF_DDRRGN_CON0_16(n) ((n) * 4)
+#define SGRF_DDRRGN_CON20_34(n) (0x50 + ((n) - 20) * 4)
+
+/* All of master in ns */
+#define SGRF_SOC_ALLMST_NS 0xffff
+
+/* security config for slave */
+#define SGRF_SLV_S_WMSK 0xffff0000
+#define SGRF_SLV_S_ALL_NS 0x0
+
+/* security config pmu slave ip */
+/* All of slaves is ns */
+#define SGRF_PMU_SLV_S_NS BIT_WITH_WMSK(0)
+/* slaves secure attr is configed */
+#define SGRF_PMU_SLV_S_CFGED WMSK_BIT(0)
+#define SGRF_PMU_SLV_CRYPTO1_NS WMSK_BIT(1)
+
+#define SGRF_PMUSRAM_S BIT(8)
+
+#define SGRF_INTSRAM_S BIT(13)
+
+/* ddr region */
+#define SGRF_DDR_RGN_0_16_WMSK 0x0fff /* DDR RGN 0~16 size mask */
+
+#define SGRF_DDR_RGN_DPLL_CLK BIT_WITH_WMSK(15) /* DDR PLL output clock */
+#define SGRF_DDR_RGN_RTC_CLK BIT_WITH_WMSK(14) /* 32K clock for DDR PLL */
+
+/* All security of the DDR RGNs are bypass */
+#define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(9)
+/* All security of the DDR RGNs are not bypass */
+#define SGRF_DDR_RGN_NO_BYPS WMSK_BIT(9)
+
+/* The MST access the ddr rgn n with secure attribution */
+#define SGRF_L_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n))
+/* bits[16:8]*/
+#define SGRF_H_MST_S_DDR_RGN(n) BIT_WITH_WMSK((n) + 8)
+
+#define SGRF_PMU_CON0 0x0c100
+#define SGRF_PMU_CON(n) (SGRF_PMU_CON0 + (n) * 4)
+
+/**************************************************
+ * secure timer
+ **************************************************/
+/* chanal0~5 */
+#define STIMER0_CHN_BASE(n) (STIME_BASE + 0x20 * (n))
+/* chanal6~11 */
+#define STIMER1_CHN_BASE(n) (STIME_BASE + 0x8000 + 0x20 * (n))
+
+ /* low 32 bits */
+#define TIMER_END_COUNT0 0x00
+ /* high 32 bits */
+#define TIMER_END_COUNT1 0x04
+
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0C
+
+ /* low 32 bits */
+#define TIMER_INIT_COUNT0 0x10
+ /* high 32 bits */
+#define TIMER_INIT_COUNT1 0x14
+
+#define TIMER_INTSTATUS 0x18
+#define TIMER_CONTROL_REG 0x1c
+
+#define TIMER_EN 0x1
+
+#define TIMER_FMODE (0x0 << 1)
+#define TIMER_RMODE (0x1 << 1)
+
+/**************************************************
+ * secure WDT
+ **************************************************/
+#define PCLK_WDT_CA53_GATE_SHIFT 8
+#define PCLK_WDT_CM0_GATE_SHIFT 10
+
+/* export secure operating APIs */
+void secure_watchdog_gate(void);
+__pmusramfunc void secure_watchdog_ungate(void);
+void secure_timer_init(void);
+void secure_sgrf_init(void);
+void secure_sgrf_ddr_rgn_init(void);
+__pmusramfunc void sram_secure_timer_init(void);
+
+#endif /* SECURE_H */
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c
new file mode 100644
index 0000000..98b5ad6
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/soc/soc.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#include <dfs.h>
+#include <dram.h>
+#include <m0_ctl.h>
+#include <plat_private.h>
+#include <pmu.h>
+#include <rk3399_def.h>
+#include <secure.h>
+#include <soc.h>
+
+/* Table of regions to map using the MMU. */
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(DEV_RNG0_BASE, DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+/* sleep data for pll suspend */
+static struct deepsleep_data_s slp_data;
+
+/* sleep data that needs to be accessed from pmusram */
+__pmusramdata struct pmu_sleep_data pmu_slp_data;
+
+static void set_pll_slow_mode(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_SLOW_MODE);
+ else
+ mmio_write_32((CRU_BASE +
+ CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
+}
+
+static void set_pll_normal_mode(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3), PLL_NOMAL_MODE);
+ else
+ mmio_write_32(CRU_BASE +
+ CRU_PLL_CON(pll_id, 3), PLL_NOMAL_MODE);
+}
+
+static void set_pll_bypass(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE +
+ PMUCRU_PPLL_CON(3), PLL_BYPASS_MODE);
+ else
+ mmio_write_32(CRU_BASE +
+ CRU_PLL_CON(pll_id, 3), PLL_BYPASS_MODE);
+}
+
+static void _pll_suspend(uint32_t pll_id)
+{
+ set_pll_slow_mode(pll_id);
+ set_pll_bypass(pll_id);
+}
+
+/**
+ * disable_dvfs_plls - To suspend the specific PLLs
+ *
+ * When we close the center logic, the DPLL will be closed,
+ * so we need to keep the ABPLL and switch to it to supply
+ * clock for DDR during suspend, then we should not close
+ * the ABPLL and exclude ABPLL_ID.
+ */
+void disable_dvfs_plls(void)
+{
+ _pll_suspend(CPLL_ID);
+ _pll_suspend(NPLL_ID);
+ _pll_suspend(VPLL_ID);
+ _pll_suspend(GPLL_ID);
+ _pll_suspend(ALPLL_ID);
+}
+
+/**
+ * disable_nodvfs_plls - To suspend the PPLL
+ */
+void disable_nodvfs_plls(void)
+{
+ _pll_suspend(PPLL_ID);
+}
+
+/**
+ * restore_pll - Copy PLL settings from memory to a PLL.
+ *
+ * This will copy PLL settings from an array in memory to the memory mapped
+ * registers for a PLL.
+ *
+ * Note that: above the PLL exclude PPLL.
+ *
+ * pll_id: One of the values from enum plls_id
+ * src: Pointer to the array of values to restore from
+ */
+static void restore_pll(int pll_id, uint32_t *src)
+{
+ /* Nice to have PLL off while configuring */
+ mmio_write_32((CRU_BASE + CRU_PLL_CON(pll_id, 3)), PLL_SLOW_MODE);
+
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 0), src[0] | REG_SOC_WMSK);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 1), src[1] | REG_SOC_WMSK);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 2), src[2]);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 4), src[4] | REG_SOC_WMSK);
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 5), src[5] | REG_SOC_WMSK);
+
+ /* Do PLL_CON3 since that will enable things */
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), src[3] | REG_SOC_WMSK);
+
+ /* Wait for PLL lock done */
+ while ((mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 2)) &
+ 0x80000000) == 0x0)
+ ;
+}
+
+/**
+ * save_pll - Copy PLL settings a PLL to memory
+ *
+ * This will copy PLL settings from the memory mapped registers for a PLL to
+ * an array in memory.
+ *
+ * Note that: above the PLL exclude PPLL.
+ *
+ * pll_id: One of the values from enum plls_id
+ * src: Pointer to the array of values to save to.
+ */
+static void save_pll(uint32_t *dst, int pll_id)
+{
+ int i;
+
+ for (i = 0; i < PLL_CON_COUNT; i++)
+ dst[i] = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, i));
+}
+
+/**
+ * prepare_abpll_for_ddrctrl - Copy DPLL settings to ABPLL
+ *
+ * This will copy DPLL settings from the memory mapped registers for a PLL to
+ * an array in memory.
+ */
+void prepare_abpll_for_ddrctrl(void)
+{
+ save_pll(slp_data.plls_con[ABPLL_ID], ABPLL_ID);
+ save_pll(slp_data.plls_con[DPLL_ID], DPLL_ID);
+
+ restore_pll(ABPLL_ID, slp_data.plls_con[DPLL_ID]);
+}
+
+void restore_abpll(void)
+{
+ restore_pll(ABPLL_ID, slp_data.plls_con[ABPLL_ID]);
+}
+
+void clk_gate_con_save(void)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < PMUCRU_GATE_COUNT; i++)
+ slp_data.pmucru_gate_con[i] =
+ mmio_read_32(PMUCRU_BASE + PMUCRU_GATE_CON(i));
+
+ for (i = 0; i < CRU_GATE_COUNT; i++)
+ slp_data.cru_gate_con[i] =
+ mmio_read_32(CRU_BASE + CRU_GATE_CON(i));
+}
+
+void clk_gate_con_disable(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < PMUCRU_GATE_COUNT; i++)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i), REG_SOC_WMSK);
+
+ for (i = 0; i < CRU_GATE_COUNT; i++)
+ mmio_write_32(CRU_BASE + CRU_GATE_CON(i), REG_SOC_WMSK);
+}
+
+void clk_gate_con_restore(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < PMUCRU_GATE_COUNT; i++)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_GATE_CON(i),
+ REG_SOC_WMSK | slp_data.pmucru_gate_con[i]);
+
+ for (i = 0; i < CRU_GATE_COUNT; i++)
+ mmio_write_32(CRU_BASE + CRU_GATE_CON(i),
+ REG_SOC_WMSK | slp_data.cru_gate_con[i]);
+}
+
+static void set_plls_nobypass(uint32_t pll_id)
+{
+ if (pll_id == PPLL_ID)
+ mmio_write_32(PMUCRU_BASE + PMUCRU_PPLL_CON(3),
+ PLL_NO_BYPASS_MODE);
+ else
+ mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3),
+ PLL_NO_BYPASS_MODE);
+}
+
+static void _pll_resume(uint32_t pll_id)
+{
+ set_plls_nobypass(pll_id);
+ set_pll_normal_mode(pll_id);
+}
+
+void set_pmu_rsthold(void)
+{
+ uint32_t rstnhold_cofig0;
+ uint32_t rstnhold_cofig1;
+
+ pmu_slp_data.pmucru_rstnhold_con0 = mmio_read_32(PMUCRU_BASE +
+ PMUCRU_RSTNHOLD_CON0);
+ pmu_slp_data.pmucru_rstnhold_con1 = mmio_read_32(PMUCRU_BASE +
+ PMUCRU_RSTNHOLD_CON1);
+ rstnhold_cofig0 = BIT_WITH_WMSK(PRESETN_NOC_PMU_HOLD) |
+ BIT_WITH_WMSK(PRESETN_INTMEM_PMU_HOLD) |
+ BIT_WITH_WMSK(HRESETN_CM0S_PMU_HOLD) |
+ BIT_WITH_WMSK(HRESETN_CM0S_NOC_PMU_HOLD) |
+ BIT_WITH_WMSK(DRESETN_CM0S_PMU_HOLD) |
+ BIT_WITH_WMSK(POESETN_CM0S_PMU_HOLD) |
+ BIT_WITH_WMSK(PRESETN_TIMER_PMU_0_1_HOLD) |
+ BIT_WITH_WMSK(RESETN_TIMER_PMU_0_HOLD) |
+ BIT_WITH_WMSK(RESETN_TIMER_PMU_1_HOLD) |
+ BIT_WITH_WMSK(PRESETN_UART_M0_PMU_HOLD) |
+ BIT_WITH_WMSK(RESETN_UART_M0_PMU_HOLD) |
+ BIT_WITH_WMSK(PRESETN_WDT_PMU_HOLD);
+ rstnhold_cofig1 = BIT_WITH_WMSK(PRESETN_RKPWM_PMU_HOLD) |
+ BIT_WITH_WMSK(PRESETN_PMUGRF_HOLD) |
+ BIT_WITH_WMSK(PRESETN_SGRF_HOLD) |
+ BIT_WITH_WMSK(PRESETN_GPIO0_HOLD) |
+ BIT_WITH_WMSK(PRESETN_GPIO1_HOLD) |
+ BIT_WITH_WMSK(PRESETN_CRU_PMU_HOLD) |
+ BIT_WITH_WMSK(PRESETN_PVTM_PMU_HOLD);
+
+ mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0, rstnhold_cofig0);
+ mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1, rstnhold_cofig1);
+}
+
+void pmu_sgrf_rst_hld(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_HOLD);
+}
+
+/*
+ * When system reset in running state, we want the cpus to be reboot
+ * from maskrom (system reboot),
+ * the pmusgrf reset-hold bits needs to be released.
+ * When system wake up from system deep suspend, some soc will be reset
+ * when waked up,
+ * we want the bootcpu to be reboot from pmusram,
+ * the pmusgrf reset-hold bits needs to be held.
+ */
+__pmusramfunc void pmu_sgrf_rst_hld_release(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS);
+}
+
+__pmusramfunc void restore_pmu_rsthold(void)
+{
+ mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON0,
+ pmu_slp_data.pmucru_rstnhold_con0 | REG_SOC_WMSK);
+ mmio_write_32(PMUCRU_BASE + PMUCRU_RSTNHOLD_CON1,
+ pmu_slp_data.pmucru_rstnhold_con1 | REG_SOC_WMSK);
+}
+
+/**
+ * enable_dvfs_plls - To resume the specific PLLs
+ *
+ * Please see the comment at the disable_dvfs_plls()
+ * we don't suspend the ABPLL, so don't need resume
+ * it too.
+ */
+void enable_dvfs_plls(void)
+{
+ _pll_resume(ALPLL_ID);
+ _pll_resume(GPLL_ID);
+ _pll_resume(VPLL_ID);
+ _pll_resume(NPLL_ID);
+ _pll_resume(CPLL_ID);
+}
+
+/**
+ * enable_nodvfs_plls - To resume the PPLL
+ */
+void enable_nodvfs_plls(void)
+{
+ _pll_resume(PPLL_ID);
+}
+
+void soc_global_soft_reset_init(void)
+{
+ mmio_write_32(PMUCRU_BASE + CRU_PMU_RSTHOLD_CON(1),
+ CRU_PMU_SGRF_RST_RLS);
+
+ mmio_clrbits_32(CRU_BASE + CRU_GLB_RST_CON,
+ CRU_PMU_WDTRST_MSK | CRU_PMU_FIRST_SFTRST_MSK);
+}
+
+void __dead2 soc_global_soft_reset(void)
+{
+ pmu_power_domains_on();
+ set_pll_slow_mode(VPLL_ID);
+ set_pll_slow_mode(NPLL_ID);
+ set_pll_slow_mode(GPLL_ID);
+ set_pll_slow_mode(CPLL_ID);
+ set_pll_slow_mode(PPLL_ID);
+ set_pll_slow_mode(ABPLL_ID);
+ set_pll_slow_mode(ALPLL_ID);
+
+ dsb();
+
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to excute valid codes.
+ */
+ while (1)
+ ;
+}
+
+void plat_rockchip_soc_init(void)
+{
+ secure_timer_init();
+ secure_sgrf_init();
+ secure_sgrf_ddr_rgn_init();
+ soc_global_soft_reset_init();
+ plat_rockchip_gpio_init();
+ m0_init();
+ dram_init();
+ dram_dfs_init();
+}
diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h
new file mode 100644
index 0000000..8daa5bb
--- /dev/null
+++ b/plat/rockchip/rk3399/drivers/soc/soc.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define SOC_H
+
+#include <lib/utils.h>
+
+#define GLB_SRST_FST_CFG_VAL 0xfdb9
+#define GLB_SRST_SND_CFG_VAL 0xeca8
+
+#define PMUCRU_PPLL_CON(n) ((n) * 4)
+#define CRU_PLL_CON(pll_id, n) ((pll_id) * 0x20 + (n) * 4)
+#define PLL_MODE_MSK 0x03
+#define PLL_MODE_SHIFT 0x08
+#define PLL_BYPASS_MSK 0x01
+#define PLL_BYPASS_SHIFT 0x01
+#define PLL_PWRDN_MSK 0x01
+#define PLL_PWRDN_SHIFT 0x0
+#define PLL_BYPASS BIT(1)
+#define PLL_PWRDN BIT(0)
+
+#define NO_PLL_BYPASS (0x00)
+#define NO_PLL_PWRDN (0x00)
+
+#define FBDIV(n) ((0xfff << 16) | n)
+#define POSTDIV2(n) ((0x7 << (12 + 16)) | (n << 12))
+#define POSTDIV1(n) ((0x7 << (8 + 16)) | (n << 8))
+#define REFDIV(n) ((0x3F << 16) | n)
+#define PLL_LOCK(n) ((n >> 31) & 0x1)
+
+#define PLL_SLOW_MODE BITS_WITH_WMASK(SLOW_MODE,\
+ PLL_MODE_MSK, PLL_MODE_SHIFT)
+
+#define PLL_NOMAL_MODE BITS_WITH_WMASK(NORMAL_MODE,\
+ PLL_MODE_MSK, PLL_MODE_SHIFT)
+
+#define PLL_BYPASS_MODE BIT_WITH_WMSK(PLL_BYPASS_SHIFT)
+#define PLL_NO_BYPASS_MODE WMSK_BIT(PLL_BYPASS_SHIFT)
+
+#define PLL_CON_COUNT 0x06
+#define CRU_CLKSEL_COUNT 108
+#define CRU_CLKSEL_CON(n) (0x100 + (n) * 4)
+
+#define PMUCRU_CLKSEL_CONUT 0x06
+#define PMUCRU_CLKSEL_OFFSET 0x080
+#define REG_SIZE 0x04
+#define REG_SOC_WMSK 0xffff0000
+#define CLK_GATE_MASK 0x01
+
+#define PMUCRU_GATE_COUNT 0x03
+#define CRU_GATE_COUNT 0x23
+#define PMUCRU_GATE_CON(n) (0x100 + (n) * 4)
+#define CRU_GATE_CON(n) (0x300 + (n) * 4)
+
+#define PMUCRU_RSTNHOLD_CON0 0x120
+enum {
+ PRESETN_NOC_PMU_HOLD = 1,
+ PRESETN_INTMEM_PMU_HOLD,
+ HRESETN_CM0S_PMU_HOLD,
+ HRESETN_CM0S_NOC_PMU_HOLD,
+ DRESETN_CM0S_PMU_HOLD,
+ POESETN_CM0S_PMU_HOLD,
+ PRESETN_SPI3_HOLD,
+ RESETN_SPI3_HOLD,
+ PRESETN_TIMER_PMU_0_1_HOLD,
+ RESETN_TIMER_PMU_0_HOLD,
+ RESETN_TIMER_PMU_1_HOLD,
+ PRESETN_UART_M0_PMU_HOLD,
+ RESETN_UART_M0_PMU_HOLD,
+ PRESETN_WDT_PMU_HOLD
+};
+
+#define PMUCRU_RSTNHOLD_CON1 0x124
+enum {
+ PRESETN_I2C0_HOLD,
+ PRESETN_I2C4_HOLD,
+ PRESETN_I2C8_HOLD,
+ PRESETN_MAILBOX_PMU_HOLD,
+ PRESETN_RKPWM_PMU_HOLD,
+ PRESETN_PMUGRF_HOLD,
+ PRESETN_SGRF_HOLD,
+ PRESETN_GPIO0_HOLD,
+ PRESETN_GPIO1_HOLD,
+ PRESETN_CRU_PMU_HOLD,
+ PRESETN_INTR_ARB_HOLD,
+ PRESETN_PVTM_PMU_HOLD,
+ RESETN_I2C0_HOLD,
+ RESETN_I2C4_HOLD,
+ RESETN_I2C8_HOLD
+};
+
+enum plls_id {
+ ALPLL_ID = 0,
+ ABPLL_ID,
+ DPLL_ID,
+ CPLL_ID,
+ GPLL_ID,
+ NPLL_ID,
+ VPLL_ID,
+ PPLL_ID,
+ END_PLL_ID,
+};
+
+#define CLST_L_CPUS_MSK (0xf)
+#define CLST_B_CPUS_MSK (0x3)
+
+enum pll_work_mode {
+ SLOW_MODE = 0x00,
+ NORMAL_MODE = 0x01,
+ DEEP_SLOW_MODE = 0x02,
+};
+
+enum glb_sft_reset {
+ PMU_RST_BY_FIRST_SFT,
+ PMU_RST_BY_SECOND_SFT = BIT(2),
+ PMU_RST_NOT_BY_SFT = BIT(3),
+};
+
+struct pll_div {
+ uint32_t mhz;
+ uint32_t refdiv;
+ uint32_t fbdiv;
+ uint32_t postdiv1;
+ uint32_t postdiv2;
+ uint32_t frac;
+ uint32_t freq;
+};
+
+struct deepsleep_data_s {
+ uint32_t plls_con[END_PLL_ID][PLL_CON_COUNT];
+ uint32_t cru_gate_con[CRU_GATE_COUNT];
+ uint32_t pmucru_gate_con[PMUCRU_GATE_COUNT];
+};
+
+struct pmu_sleep_data {
+ uint32_t pmucru_rstnhold_con0;
+ uint32_t pmucru_rstnhold_con1;
+};
+
+/**************************************************
+ * pmugrf reg, offset
+ **************************************************/
+#define PMUGRF_OSREG(n) (0x300 + (n) * 4)
+#define PMUGRF_GPIO0A_P 0x040
+#define PMUGRF_GPIO1A_P 0x050
+
+/**************************************************
+ * DCF reg, offset
+ **************************************************/
+#define DCF_DCF_CTRL 0x0
+#define DCF_DCF_ADDR 0x8
+#define DCF_DCF_ISR 0xc
+#define DCF_DCF_TOSET 0x14
+#define DCF_DCF_TOCMD 0x18
+#define DCF_DCF_CMD_CFG 0x1c
+
+/* DCF_DCF_ISR */
+#define DCF_TIMEOUT (1 << 2)
+#define DCF_ERR (1 << 1)
+#define DCF_DONE (1 << 0)
+
+/* DCF_DCF_CTRL */
+#define DCF_VOP_HW_EN (1 << 2)
+#define DCF_STOP (1 << 1)
+#define DCF_START (1 << 0)
+
+#define CYCL_24M_CNT_US(us) (24 * us)
+#define CYCL_24M_CNT_MS(ms) (ms * CYCL_24M_CNT_US(1000))
+#define CYCL_32K_CNT_MS(ms) (ms * 32)
+
+/**************************************************
+ * cru reg, offset
+ **************************************************/
+#define CRU_SOFTRST_CON(n) (0x400 + (n) * 4)
+
+#define CRU_DMAC0_RST BIT_WITH_WMSK(3)
+ /* reset release*/
+#define CRU_DMAC0_RST_RLS WMSK_BIT(3)
+
+#define CRU_DMAC1_RST BIT_WITH_WMSK(4)
+ /* reset release*/
+#define CRU_DMAC1_RST_RLS WMSK_BIT(4)
+
+#define CRU_GLB_RST_CON 0x0510
+#define CRU_GLB_SRST_FST 0x0500
+#define CRU_GLB_SRST_SND 0x0504
+
+#define CRU_CLKGATE_CON(n) (0x300 + n * 4)
+#define PCLK_GPIO2_GATE_SHIFT 3
+#define PCLK_GPIO3_GATE_SHIFT 4
+#define PCLK_GPIO4_GATE_SHIFT 5
+
+/**************************************************
+ * pmu cru reg, offset
+ **************************************************/
+#define CRU_PMU_RSTHOLD_CON(n) (0x120 + n * 4)
+/* reset hold*/
+#define CRU_PMU_SGRF_RST_HOLD BIT_WITH_WMSK(6)
+/* reset hold release*/
+#define CRU_PMU_SGRF_RST_RLS WMSK_BIT(6)
+
+#define CRU_PMU_WDTRST_MSK (0x1 << 4)
+#define CRU_PMU_WDTRST_EN 0x0
+
+#define CRU_PMU_FIRST_SFTRST_MSK (0x3 << 2)
+#define CRU_PMU_FIRST_SFTRST_EN 0x0
+
+#define CRU_PMU_CLKGATE_CON(n) (0x100 + n * 4)
+#define PCLK_GPIO0_GATE_SHIFT 3
+#define PCLK_GPIO1_GATE_SHIFT 4
+
+#define CPU_BOOT_ADDR_WMASK 0xffff0000
+#define CPU_BOOT_ADDR_ALIGN 16
+
+#define GRF_IOMUX_2BIT_MASK 0x3
+#define GRF_IOMUX_GPIO 0x0
+
+#define GRF_GPIO4C2_IOMUX_SHIFT 4
+#define GRF_GPIO4C2_IOMUX_PWM 0x1
+#define GRF_GPIO4C6_IOMUX_SHIFT 12
+#define GRF_GPIO4C6_IOMUX_PWM 0x1
+
+#define PWM_CNT(n) (0x0000 + 0x10 * (n))
+#define PWM_PERIOD_HPR(n) (0x0004 + 0x10 * (n))
+#define PWM_DUTY_LPR(n) (0x0008 + 0x10 * (n))
+#define PWM_CTRL(n) (0x000c + 0x10 * (n))
+
+#define PWM_DISABLE (0 << 0)
+#define PWM_ENABLE (1 << 0)
+
+/* grf reg offset */
+#define GRF_USBPHY0_CTRL0 0x4480
+#define GRF_USBPHY0_CTRL2 0x4488
+#define GRF_USBPHY0_CTRL3 0x448c
+#define GRF_USBPHY0_CTRL12 0x44b0
+#define GRF_USBPHY0_CTRL13 0x44b4
+#define GRF_USBPHY0_CTRL15 0x44bc
+#define GRF_USBPHY0_CTRL16 0x44c0
+
+#define GRF_USBPHY1_CTRL0 0x4500
+#define GRF_USBPHY1_CTRL2 0x4508
+#define GRF_USBPHY1_CTRL3 0x450c
+#define GRF_USBPHY1_CTRL12 0x4530
+#define GRF_USBPHY1_CTRL13 0x4534
+#define GRF_USBPHY1_CTRL15 0x453c
+#define GRF_USBPHY1_CTRL16 0x4540
+
+#define GRF_GPIO2A_IOMUX 0xe000
+#define GRF_GPIO2A_P 0xe040
+#define GRF_GPIO3A_P 0xe050
+#define GRF_GPIO4A_P 0xe060
+#define GRF_GPIO2D_HE 0xe18c
+#define GRF_DDRC0_CON0 0xe380
+#define GRF_DDRC0_CON1 0xe384
+#define GRF_DDRC1_CON0 0xe388
+#define GRF_DDRC1_CON1 0xe38c
+#define GRF_SOC_CON_BASE 0xe200
+#define GRF_SOC_CON(n) (GRF_SOC_CON_BASE + (n) * 4)
+#define GRF_IO_VSEL 0xe640
+
+#define CRU_CLKSEL_CON0 0x0100
+#define CRU_CLKSEL_CON6 0x0118
+#define CRU_SDIO0_CON1 0x058c
+#define PMUCRU_CLKSEL_CON0 0x0080
+#define PMUCRU_CLKGATE_CON2 0x0108
+#define PMUCRU_SOFTRST_CON0 0x0110
+#define PMUCRU_GATEDIS_CON0 0x0130
+#define PMUCRU_SOFTRST_CON(n) (PMUCRU_SOFTRST_CON0 + (n) * 4)
+
+/* export related and operating SoC APIs */
+void __dead2 soc_global_soft_reset(void);
+void disable_dvfs_plls(void);
+void disable_nodvfs_plls(void);
+void enable_dvfs_plls(void);
+void enable_nodvfs_plls(void);
+void prepare_abpll_for_ddrctrl(void);
+void restore_abpll(void);
+void clk_gate_con_save(void);
+void clk_gate_con_disable(void);
+void clk_gate_con_restore(void);
+void set_pmu_rsthold(void);
+void pmu_sgrf_rst_hld(void);
+__pmusramfunc void pmu_sgrf_rst_hld_release(void);
+__pmusramfunc void restore_pmu_rsthold(void);
+#endif /* SOC_H */
diff --git a/plat/rockchip/rk3399/include/addressmap.h b/plat/rockchip/rk3399/include/addressmap.h
new file mode 100644
index 0000000..dc1c703
--- /dev/null
+++ b/plat/rockchip/rk3399/include/addressmap.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ADDRESSMAP_H
+#define ADDRESSMAP_H
+
+#include <addressmap_shared.h>
+
+/* Registers base address */
+#define MMIO_BASE 0xF8000000
+
+/* Aggregate of all devices in the first GB */
+#define DEV_RNG0_BASE MMIO_BASE
+#define DEV_RNG0_SIZE SIZE_M(125)
+
+#endif /* ADDRESSMAP_H */
diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S
new file mode 100644
index 0000000..cfa912f
--- /dev/null
+++ b/plat/rockchip/rk3399/include/plat.ld.S
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ROCKCHIP_PLAT_LD_S
+#define ROCKCHIP_PLAT_LD_S
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+MEMORY {
+ SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE
+ PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
+}
+
+SECTIONS
+{
+ . = SRAM_BASE;
+ ASSERT(. == ALIGN(PAGE_SIZE),
+ "SRAM_BASE address is not aligned on a page boundary.")
+
+ /*
+ * The SRAM space allocation for RK3399
+ * ----------------
+ * | m0 code bin
+ * ----------------
+ * | sram text
+ * ----------------
+ * | sram data
+ * ----------------
+ */
+ .incbin_sram : ALIGN(PAGE_SIZE) {
+ __sram_incbin_start = .;
+ *(.sram.incbin)
+ __sram_incbin_real_end = .;
+ . = ALIGN(PAGE_SIZE);
+ __sram_incbin_end = .;
+ } >SRAM
+ ASSERT((__sram_incbin_real_end - __sram_incbin_start) <=
+ SRAM_BIN_LIMIT, ".incbin_sram has exceeded its limit")
+
+ .text_sram : ALIGN(PAGE_SIZE) {
+ __bl31_sram_text_start = .;
+ *(.sram.text)
+ *(.sram.rodata)
+ __bl31_sram_text_real_end = .;
+ . = ALIGN(PAGE_SIZE);
+ __bl31_sram_text_end = .;
+ } >SRAM
+ ASSERT((__bl31_sram_text_real_end - __bl31_sram_text_start) <=
+ SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit")
+
+ .data_sram : ALIGN(PAGE_SIZE) {
+ __bl31_sram_data_start = .;
+ *(.sram.data)
+ __bl31_sram_data_real_end = .;
+ . = ALIGN(PAGE_SIZE);
+ __bl31_sram_data_end = .;
+ } >SRAM
+ ASSERT((__bl31_sram_data_real_end - __bl31_sram_data_start) <=
+ SRAM_DATA_LIMIT, ".data_sram has exceeded its limit")
+
+ .stack_sram : ALIGN(PAGE_SIZE) {
+ __bl31_sram_stack_start = .;
+ . += PAGE_SIZE;
+ __bl31_sram_stack_end = .;
+ } >SRAM
+
+ . = PMUSRAM_BASE;
+
+ /*
+ * pmu_cpuson_entrypoint request address
+ * align 64K when resume, so put it in the
+ * start of pmusram
+ */
+ .pmusram : {
+ ASSERT(. == ALIGN(64 * 1024),
+ ".pmusram.entry request 64K aligned.");
+ *(.pmusram.entry)
+
+ __bl31_pmusram_text_start = .;
+ *(.pmusram.text)
+ *(.pmusram.rodata)
+ __bl31_pmusram_text_end = .;
+
+ /* M0 start address request 4K align */
+ . = ALIGN(4096);
+ __pmusram_incbin_start = .;
+ *(.pmusram.incbin)
+ __pmusram_incbin_end = .;
+
+ __bl31_pmusram_data_start = .;
+ *(.pmusram.data)
+ __bl31_pmusram_data_end = .;
+ } >PMUSRAM
+}
+
+#endif /* ROCKCHIP_PLAT_LD_S */
diff --git a/plat/rockchip/rk3399/include/plat_sip_calls.h b/plat/rockchip/rk3399/include/plat_sip_calls.h
new file mode 100644
index 0000000..66c4868
--- /dev/null
+++ b/plat/rockchip/rk3399/include/plat_sip_calls.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SIP_CALLS_H
+#define PLAT_SIP_CALLS_H
+
+#define RK_PLAT_SIP_NUM_CALLS 0
+
+#endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/rockchip/rk3399/include/platform_def.h b/plat/rockchip/rk3399/include/platform_def.h
new file mode 100644
index 0000000..78269b6
--- /dev/null
+++ b/plat/rockchip/rk3399/include/platform_def.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include <bl31_param.h>
+#include <rk3399_def.h>
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL1)
+#define PLATFORM_STACK_SIZE 0x440
+#elif defined(IMAGE_BL2)
+#define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE 0x800
+#elif defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLATFORM_SYSTEM_COUNT U(1)
+#define PLATFORM_CLUSTER_COUNT U(2)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(2)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_RK_CLST_TO_CPUID_SHIFT 6
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE U(1)
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE U(2)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 20
+#define MAX_MMAP_REGIONS 25
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE BASE_GICD_BASE
+#define PLAT_RK_GICR_BASE BASE_GICR_BASE
+#define PLAT_RK_GICC_BASE 0
+
+#define PLAT_RK_UART_BASE UART2_BASE
+#define PLAT_RK_UART_CLOCK RK3399_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK3399_BAUDRATE
+
+#define PLAT_RK_CCI_BASE CCI500_BASE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+
+#define PSRAM_DO_DDR_RESUME 1
+#define PSRAM_CHECK_WAKEUP_CPU 0
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rockchip/rk3399/include/shared/addressmap_shared.h b/plat/rockchip/rk3399/include/shared/addressmap_shared.h
new file mode 100644
index 0000000..84a31b2
--- /dev/null
+++ b/plat/rockchip/rk3399/include/shared/addressmap_shared.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ADDRESSMAP_SHARED_H
+#define ADDRESSMAP_SHARED_H
+
+#define SIZE_K(n) ((n) * 1024)
+#define SIZE_M(n) ((n) * 1024 * 1024)
+#define SRAM_TEXT_LIMIT (4 * 1024)
+#define SRAM_DATA_LIMIT (4 * 1024)
+#define SRAM_BIN_LIMIT (4 * 1024)
+
+/*
+ * The parts of the shared defined registers address with AP and M0,
+ * let's note and mark the previous defines like this:
+ */
+#define GIC500_BASE (MMIO_BASE + 0x06E00000)
+#define UART0_BASE (MMIO_BASE + 0x07180000)
+#define UART1_BASE (MMIO_BASE + 0x07190000)
+#define UART2_BASE (MMIO_BASE + 0x071A0000)
+#define UART3_BASE (MMIO_BASE + 0x071B0000)
+
+#define PMU_BASE (MMIO_BASE + 0x07310000)
+#define PMUGRF_BASE (MMIO_BASE + 0x07320000)
+#define SGRF_BASE (MMIO_BASE + 0x07330000)
+#define PMUSRAM_BASE (MMIO_BASE + 0x073B0000)
+#define PWM_BASE (MMIO_BASE + 0x07420000)
+
+#define CIC_BASE (MMIO_BASE + 0x07620000)
+#define PD_BUS0_BASE (MMIO_BASE + 0x07650000)
+#define DCF_BASE (MMIO_BASE + 0x076A0000)
+#define GPIO0_BASE (MMIO_BASE + 0x07720000)
+#define GPIO1_BASE (MMIO_BASE + 0x07730000)
+#define PMUCRU_BASE (MMIO_BASE + 0x07750000)
+#define CRU_BASE (MMIO_BASE + 0x07760000)
+#define GRF_BASE (MMIO_BASE + 0x07770000)
+#define GPIO2_BASE (MMIO_BASE + 0x07780000)
+#define GPIO3_BASE (MMIO_BASE + 0x07788000)
+#define GPIO4_BASE (MMIO_BASE + 0x07790000)
+#define WDT1_BASE (MMIO_BASE + 0x07840000)
+#define WDT0_BASE (MMIO_BASE + 0x07848000)
+#define TIMER_BASE (MMIO_BASE + 0x07850000)
+#define STIME_BASE (MMIO_BASE + 0x07860000)
+#define SRAM_BASE (MMIO_BASE + 0x078C0000)
+#define SERVICE_NOC_0_BASE (MMIO_BASE + 0x07A50000)
+#define DDRC0_BASE (MMIO_BASE + 0x07A80000)
+#define SERVICE_NOC_1_BASE (MMIO_BASE + 0x07A84000)
+#define DDRC1_BASE (MMIO_BASE + 0x07A88000)
+#define SERVICE_NOC_2_BASE (MMIO_BASE + 0x07A8C000)
+#define SERVICE_NOC_3_BASE (MMIO_BASE + 0x07A90000)
+#define CCI500_BASE (MMIO_BASE + 0x07B00000)
+#define COLD_BOOT_BASE (MMIO_BASE + 0x07FF0000)
+
+/* Registers size */
+#define GIC500_SIZE SIZE_M(2)
+#define UART0_SIZE SIZE_K(64)
+#define UART1_SIZE SIZE_K(64)
+#define UART2_SIZE SIZE_K(64)
+#define UART3_SIZE SIZE_K(64)
+#define PMU_SIZE SIZE_K(64)
+#define PMUGRF_SIZE SIZE_K(64)
+#define SGRF_SIZE SIZE_K(64)
+#define PMUSRAM_SIZE SIZE_K(64)
+#define PMUSRAM_RSIZE SIZE_K(8)
+#define PWM_SIZE SIZE_K(64)
+#define CIC_SIZE SIZE_K(4)
+#define DCF_SIZE SIZE_K(4)
+#define GPIO0_SIZE SIZE_K(64)
+#define GPIO1_SIZE SIZE_K(64)
+#define PMUCRU_SIZE SIZE_K(64)
+#define CRU_SIZE SIZE_K(64)
+#define GRF_SIZE SIZE_K(64)
+#define GPIO2_SIZE SIZE_K(32)
+#define GPIO3_SIZE SIZE_K(32)
+#define GPIO4_SIZE SIZE_K(32)
+#define STIME_SIZE SIZE_K(64)
+#define SRAM_SIZE SIZE_K(192)
+#define SERVICE_NOC_0_SIZE SIZE_K(192)
+#define DDRC0_SIZE SIZE_K(32)
+#define SERVICE_NOC_1_SIZE SIZE_K(16)
+#define DDRC1_SIZE SIZE_K(32)
+#define SERVICE_NOC_2_SIZE SIZE_K(16)
+#define SERVICE_NOC_3_SIZE SIZE_K(448)
+#define CCI500_SIZE SIZE_M(1)
+#define PD_BUS0_SIZE SIZE_K(448)
+
+/* DDR Registers address */
+#define CTL_BASE(ch) (DDRC0_BASE + (ch) * 0x8000)
+#define CTL_REG(ch, n) (CTL_BASE(ch) + (n) * 0x4)
+
+#define PI_OFFSET 0x800
+#define PI_BASE(ch) (CTL_BASE(ch) + PI_OFFSET)
+#define PI_REG(ch, n) (PI_BASE(ch) + (n) * 0x4)
+
+#define PHY_OFFSET 0x2000
+#define PHY_BASE(ch) (CTL_BASE(ch) + PHY_OFFSET)
+#define PHY_REG(ch, n) (PHY_BASE(ch) + (n) * 0x4)
+
+#define MSCH_BASE(ch) (SERVICE_NOC_1_BASE + (ch) * 0x8000)
+
+#endif /* ADDRESSMAP_SHARED_H */
diff --git a/plat/rockchip/rk3399/include/shared/bl31_param.h b/plat/rockchip/rk3399/include/shared/bl31_param.h
new file mode 100644
index 0000000..6e7e8ba
--- /dev/null
+++ b/plat/rockchip/rk3399/include/shared/bl31_param.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL31_PARAM_H
+#define BL31_PARAM_H
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF text, ro, rw, Size: 1MB */
+#define TZRAM_BASE (0x0)
+#define TZRAM_SIZE (0x100000)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x40000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+#endif /* BL31_PARAM_H */
diff --git a/plat/rockchip/rk3399/include/shared/dram_regs.h b/plat/rockchip/rk3399/include/shared/dram_regs.h
new file mode 100644
index 0000000..4d4ebf6
--- /dev/null
+++ b/plat/rockchip/rk3399/include/shared/dram_regs.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DRAM_REGS_H
+#define DRAM_REGS_H
+
+#define CTL_REG_NUM 332
+#define PHY_REG_NUM 959
+#define PI_REG_NUM 200
+
+#define MSCH_ID_COREID 0x0
+#define MSCH_ID_REVISIONID 0x4
+#define MSCH_DEVICECONF 0x8
+#define MSCH_DEVICESIZE 0xc
+#define MSCH_DDRTIMINGA0 0x10
+#define MSCH_DDRTIMINGB0 0x14
+#define MSCH_DDRTIMINGC0 0x18
+#define MSCH_DEVTODEV0 0x1c
+#define MSCH_DDRMODE 0x110
+#define MSCH_AGINGX0 0x1000
+
+#define CIC_CTRL0 0x0
+#define CIC_CTRL1 0x4
+#define CIC_IDLE_TH 0x8
+#define CIC_CG_WAIT_TH 0xc
+#define CIC_STATUS0 0x10
+#define CIC_STATUS1 0x14
+#define CIC_CTRL2 0x18
+#define CIC_CTRL3 0x1c
+#define CIC_CTRL4 0x20
+
+/* DENALI_CTL_00 */
+#define START 1
+
+/* DENALI_CTL_68 */
+#define PWRUP_SREFRESH_EXIT (1 << 16)
+
+/* DENALI_CTL_274 */
+#define MEM_RST_VALID 1
+
+#define PHY_DRV_ODT_Hi_Z 0x0
+#define PHY_DRV_ODT_240 0x1
+#define PHY_DRV_ODT_120 0x8
+#define PHY_DRV_ODT_80 0x9
+#define PHY_DRV_ODT_60 0xc
+#define PHY_DRV_ODT_48 0xd
+#define PHY_DRV_ODT_40 0xe
+#define PHY_DRV_ODT_34_3 0xf
+
+/*
+ * sys_reg bitfield struct
+ * [31] row_3_4_ch1
+ * [30] row_3_4_ch0
+ * [29:28] chinfo
+ * [27] rank_ch1
+ * [26:25] col_ch1
+ * [24] bk_ch1
+ * [23:22] cs0_row_ch1
+ * [21:20] cs1_row_ch1
+ * [19:18] bw_ch1
+ * [17:16] dbw_ch1;
+ * [15:13] ddrtype
+ * [12] channelnum
+ * [11] rank_ch0
+ * [10:9] col_ch0
+ * [8] bk_ch0
+ * [7:6] cs0_row_ch0
+ * [5:4] cs1_row_ch0
+ * [3:2] bw_ch0
+ * [1:0] dbw_ch0
+ */
+#define SYS_REG_ENC_ROW_3_4(n, ch) ((n) << (30 + (ch)))
+#define SYS_REG_DEC_ROW_3_4(n, ch) (((n) >> (30 + (ch))) & 0x1)
+#define SYS_REG_ENC_CHINFO(ch) (1 << (28 + (ch)))
+#define SYS_REG_DEC_CHINFO(n, ch) (((n) >> (28 + (ch))) & 0x1)
+#define SYS_REG_ENC_DDRTYPE(n) ((n) << 13)
+#define SYS_REG_DEC_DDRTYPE(n) (((n) >> 13) & 0x7)
+#define SYS_REG_ENC_NUM_CH(n) (((n) - 1) << 12)
+#define SYS_REG_DEC_NUM_CH(n) (1 + (((n) >> 12) & 0x1))
+#define SYS_REG_ENC_RANK(n, ch) (((n) - 1) << (11 + (ch) * 16))
+#define SYS_REG_DEC_RANK(n, ch) (1 + (((n) >> (11 + (ch) * 16)) & 0x1))
+#define SYS_REG_ENC_COL(n, ch) (((n) - 9) << (9 + (ch) * 16))
+#define SYS_REG_DEC_COL(n, ch) (9 + (((n) >> (9 + (ch) * 16)) & 0x3))
+#define SYS_REG_ENC_BK(n, ch) (((n) == 3 ? 0 : 1) << (8 + (ch) * 16))
+#define SYS_REG_DEC_BK(n, ch) (3 - (((n) >> (8 + (ch) * 16)) & 0x1))
+#define SYS_REG_ENC_CS0_ROW(n, ch) (((n) - 13) << (6 + (ch) * 16))
+#define SYS_REG_DEC_CS0_ROW(n, ch) (13 + (((n) >> (6 + (ch) * 16)) & 0x3))
+#define SYS_REG_ENC_CS1_ROW(n, ch) (((n) - 13) << (4 + (ch) * 16))
+#define SYS_REG_DEC_CS1_ROW(n, ch) (13 + (((n) >> (4 + (ch) * 16)) & 0x3))
+#define SYS_REG_ENC_BW(n, ch) ((2 >> (n)) << (2 + (ch) * 16))
+#define SYS_REG_DEC_BW(n, ch) (2 >> (((n) >> (2 + (ch) * 16)) & 0x3))
+#define SYS_REG_ENC_DBW(n, ch) ((2 >> (n)) << (0 + (ch) * 16))
+#define SYS_REG_DEC_DBW(n, ch) (2 >> (((n) >> (0 + (ch) * 16)) & 0x3))
+#define DDR_STRIDE(n) mmio_write_32(SGRF_BASE + SGRF_SOC_CON3_7(4), \
+ (0x1f<<(10+16))|((n)<<10))
+
+#endif /* DRAM_REGS_H */
diff --git a/plat/rockchip/rk3399/include/shared/m0_param.h b/plat/rockchip/rk3399/include/shared/m0_param.h
new file mode 100644
index 0000000..a5311c9
--- /dev/null
+++ b/plat/rockchip/rk3399/include/shared/m0_param.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef M0_PARAM_H
+#define M0_PARAM_H
+
+#define PARAM_ADDR 0xc0
+
+#define PARAM_M0_FUNC 0x00
+#define PARAM_DRAM_FREQ 0x04
+#define PARAM_DPLL_CON0 0x08
+#define PARAM_DPLL_CON1 0x0c
+#define PARAM_DPLL_CON2 0x10
+#define PARAM_DPLL_CON3 0x14
+#define PARAM_DPLL_CON4 0x18
+#define PARAM_DPLL_CON5 0x1c
+#define PARAM_FREQ_SELECT 0x20
+#define PARAM_M0_DONE 0x24
+#define PARAM_M0_SIZE 0x28
+#define M0_DONE_FLAG 0xf59ec39a
+
+#endif /* M0_PARAM_H */
diff --git a/plat/rockchip/rk3399/include/shared/misc_regs.h b/plat/rockchip/rk3399/include/shared/misc_regs.h
new file mode 100644
index 0000000..0160453
--- /dev/null
+++ b/plat/rockchip/rk3399/include/shared/misc_regs.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MISC_REGS_H
+#define MISC_REGS_H
+
+/* CRU */
+#define CRU_DPLL_CON0 0x40
+#define CRU_DPLL_CON1 0x44
+#define CRU_DPLL_CON2 0x48
+#define CRU_DPLL_CON3 0x4c
+#define CRU_DPLL_CON4 0x50
+#define CRU_DPLL_CON5 0x54
+
+/* CRU_PLL_CON3 */
+#define PLL_SLOW_MODE 0
+#define PLL_NORMAL_MODE 1
+#define PLL_MODE(n) ((0x3 << (8 + 16)) | ((n) << 8))
+#define PLL_POWER_DOWN(n) ((0x1 << (0 + 16)) | ((n) << 0))
+
+/* PMU CRU */
+#define PMU_CRU_GATEDIS_CON0 0x130
+
+#endif /* MISC_REGS_H */
diff --git a/plat/rockchip/rk3399/include/shared/pmu_bits.h b/plat/rockchip/rk3399/include/shared/pmu_bits.h
new file mode 100644
index 0000000..2968d5b
--- /dev/null
+++ b/plat/rockchip/rk3399/include/shared/pmu_bits.h
@@ -0,0 +1,697 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_BITS_H
+#define PMU_BITS_H
+
+enum pmu_powerdomain_id {
+ PD_CPUL0 = 0,
+ PD_CPUL1,
+ PD_CPUL2,
+ PD_CPUL3,
+ PD_CPUB0,
+ PD_CPUB1,
+ PD_SCUL,
+ PD_SCUB,
+ PD_TCPD0,
+ PD_TCPD1,
+ PD_CCI,
+ PD_PERILP,
+ PD_PERIHP,
+ PD_CENTER,
+ PD_VIO,
+ PD_GPU,
+ PD_VCODEC,
+ PD_VDU,
+ PD_RGA,
+ PD_IEP,
+ PD_VO,
+ PD_ISP0 = 22,
+ PD_ISP1,
+ PD_HDCP,
+ PD_GMAC,
+ PD_EMMC,
+ PD_USB3,
+ PD_EDP,
+ PD_GIC,
+ PD_SD,
+ PD_SDIOAUDIO,
+ PD_END
+};
+
+enum powerdomain_state {
+ PMU_POWER_ON = 0,
+ PMU_POWER_OFF,
+};
+
+enum pmu_bus_id {
+ BUS_ID_GPU = 0,
+ BUS_ID_PERILP,
+ BUS_ID_PERIHP,
+ BUS_ID_VCODEC,
+ BUS_ID_VDU,
+ BUS_ID_RGA,
+ BUS_ID_IEP,
+ BUS_ID_VOPB,
+ BUS_ID_VOPL,
+ BUS_ID_ISP0,
+ BUS_ID_ISP1,
+ BUS_ID_HDCP,
+ BUS_ID_USB3,
+ BUS_ID_PERILPM0,
+ BUS_ID_CENTER,
+ BUS_ID_CCIM0,
+ BUS_ID_CCIM1,
+ BUS_ID_VIO,
+ BUS_ID_MSCH0,
+ BUS_ID_MSCH1,
+ BUS_ID_ALIVE,
+ BUS_ID_PMU,
+ BUS_ID_EDP,
+ BUS_ID_GMAC,
+ BUS_ID_EMMC,
+ BUS_ID_CENTER1,
+ BUS_ID_PMUM0,
+ BUS_ID_GIC,
+ BUS_ID_SD,
+ BUS_ID_SDIOAUDIO,
+};
+
+enum pmu_bus_state {
+ BUS_ACTIVE,
+ BUS_IDLE,
+};
+
+/* pmu_cpuapm bit */
+enum pmu_cores_pm_by_wfi {
+ core_pm_en = 0,
+ core_pm_int_wakeup_en,
+ core_pm_resv,
+ core_pm_sft_wakeup_en
+};
+
+enum pmu_wkup_cfg0 {
+ PMU_GPIO0A_POSE_WKUP_EN = 0,
+ PMU_GPIO0B_POSE_WKUP_EN = 8,
+ PMU_GPIO0C_POSE_WKUP_EN = 16,
+ PMU_GPIO0D_POSE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg1 {
+ PMU_GPIO0A_NEGEDGE_WKUP_EN = 0,
+ PMU_GPIO0B_NEGEDGE_WKUP_EN = 7,
+ PMU_GPIO0C_NEGEDGE_WKUP_EN = 16,
+ PMU_GPIO0D_NEGEDGE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg2 {
+ PMU_GPIO1A_POSE_WKUP_EN = 0,
+ PMU_GPIO1B_POSE_WKUP_EN = 7,
+ PMU_GPIO1C_POSE_WKUP_EN = 16,
+ PMU_GPIO1D_POSE_WKUP_EN = 24,
+};
+
+enum pmu_wkup_cfg3 {
+ PMU_GPIO1A_NEGEDGE_WKUP_EN = 0,
+ PMU_GPIO1B_NEGEDGE_WKUP_EN = 7,
+ PMU_GPIO1C_NEGEDGE_WKUP_EN = 16,
+ PMU_GPIO1D_NEGEDGE_WKUP_EN = 24,
+};
+
+/* pmu_wkup_cfg4 */
+enum pmu_wkup_cfg4 {
+ PMU_CLUSTER_L_WKUP_EN = 0,
+ PMU_CLUSTER_B_WKUP_EN,
+ PMU_GPIO_WKUP_EN,
+ PMU_SDIO_WKUP_EN,
+
+ PMU_SDMMC_WKUP_EN,
+ PMU_TIMER_WKUP_EN = 6,
+ PMU_USBDEV_WKUP_EN,
+
+ PMU_SFT_WKUP_EN,
+ PMU_M0_WDT_WKUP_EN,
+ PMU_TIMEOUT_WKUP_EN,
+ PMU_PWM_WKUP_EN,
+
+ PMU_PCIE_WKUP_EN = 13,
+};
+
+enum pmu_pwrdn_con {
+ PMU_A53_L0_PWRDWN_EN = 0,
+ PMU_A53_L1_PWRDWN_EN,
+ PMU_A53_L2_PWRDWN_EN,
+ PMU_A53_L3_PWRDWN_EN,
+
+ PMU_A72_B0_PWRDWN_EN,
+ PMU_A72_B1_PWRDWN_EN,
+ PMU_SCU_L_PWRDWN_EN,
+ PMU_SCU_B_PWRDWN_EN,
+
+ PMU_TCPD0_PWRDWN_EN,
+ PMU_TCPD1_PWRDWN_EN,
+ PMU_CCI_PWRDWN_EN,
+ PMU_PERILP_PWRDWN_EN,
+
+ PMU_PERIHP_PWRDWN_EN,
+ PMU_CENTER_PWRDWN_EN,
+ PMU_VIO_PWRDWN_EN,
+ PMU_GPU_PWRDWN_EN,
+
+ PMU_VCODEC_PWRDWN_EN,
+ PMU_VDU_PWRDWN_EN,
+ PMU_RGA_PWRDWN_EN,
+ PMU_IEP_PWRDWN_EN,
+
+ PMU_VO_PWRDWN_EN,
+ PMU_ISP0_PWRDWN_EN = 22,
+ PMU_ISP1_PWRDWN_EN,
+
+ PMU_HDCP_PWRDWN_EN,
+ PMU_GMAC_PWRDWN_EN,
+ PMU_EMMC_PWRDWN_EN,
+ PMU_USB3_PWRDWN_EN,
+
+ PMU_EDP_PWRDWN_EN,
+ PMU_GIC_PWRDWN_EN,
+ PMU_SD_PWRDWN_EN,
+ PMU_SDIOAUDIO_PWRDWN_EN,
+};
+
+enum pmu_pwrdn_st {
+ PMU_A53_L0_PWRDWN_ST = 0,
+ PMU_A53_L1_PWRDWN_ST,
+ PMU_A53_L2_PWRDWN_ST,
+ PMU_A53_L3_PWRDWN_ST,
+
+ PMU_A72_B0_PWRDWN_ST,
+ PMU_A72_B1_PWRDWN_ST,
+ PMU_SCU_L_PWRDWN_ST,
+ PMU_SCU_B_PWRDWN_ST,
+
+ PMU_TCPD0_PWRDWN_ST,
+ PMU_TCPD1_PWRDWN_ST,
+ PMU_CCI_PWRDWN_ST,
+ PMU_PERILP_PWRDWN_ST,
+
+ PMU_PERIHP_PWRDWN_ST,
+ PMU_CENTER_PWRDWN_ST,
+ PMU_VIO_PWRDWN_ST,
+ PMU_GPU_PWRDWN_ST,
+
+ PMU_VCODEC_PWRDWN_ST,
+ PMU_VDU_PWRDWN_ST,
+ PMU_RGA_PWRDWN_ST,
+ PMU_IEP_PWRDWN_ST,
+
+ PMU_VO_PWRDWN_ST,
+ PMU_ISP0_PWRDWN_ST = 22,
+ PMU_ISP1_PWRDWN_ST,
+
+ PMU_HDCP_PWRDWN_ST,
+ PMU_GMAC_PWRDWN_ST,
+ PMU_EMMC_PWRDWN_ST,
+ PMU_USB3_PWRDWN_ST,
+
+ PMU_EDP_PWRDWN_ST,
+ PMU_GIC_PWRDWN_ST,
+ PMU_SD_PWRDWN_ST,
+ PMU_SDIOAUDIO_PWRDWN_ST,
+
+};
+
+enum pmu_pll_con {
+ PMU_PLL_PD_CFG = 0,
+ PMU_SFT_PLL_PD = 8,
+};
+
+enum pmu_pwermode_con {
+ PMU_PWR_MODE_EN = 0,
+ PMU_WKUP_RST_EN,
+ PMU_INPUT_CLAMP_EN,
+ PMU_OSC_DIS,
+
+ PMU_ALIVE_USE_LF,
+ PMU_PMU_USE_LF,
+ PMU_POWER_OFF_REQ_CFG,
+ PMU_CHIP_PD_EN,
+
+ PMU_PLL_PD_EN,
+ PMU_CPU0_PD_EN,
+ PMU_L2_FLUSH_EN,
+ PMU_L2_IDLE_EN,
+
+ PMU_SCU_PD_EN,
+ PMU_CCI_PD_EN,
+ PMU_PERILP_PD_EN,
+ PMU_CENTER_PD_EN,
+
+ PMU_SREF0_ENTER_EN,
+ PMU_DDRC0_GATING_EN,
+ PMU_DDRIO0_RET_EN,
+ PMU_DDRIO0_RET_DE_REQ,
+
+ PMU_SREF1_ENTER_EN,
+ PMU_DDRC1_GATING_EN,
+ PMU_DDRIO1_RET_EN,
+ PMU_DDRIO1_RET_DE_REQ,
+
+ PMU_CLK_CENTER_SRC_GATE_EN = 26,
+ PMU_CLK_PERILP_SRC_GATE_EN,
+
+ PMU_CLK_CORE_SRC_GATE_EN,
+ PMU_DDRIO_RET_HW_DE_REQ,
+ PMU_SLP_OUTPUT_CFG,
+ PMU_MAIN_CLUSTER,
+};
+
+enum pmu_sft_con {
+ PMU_WKUP_SFT = 0,
+ PMU_INPUT_CLAMP_CFG,
+ PMU_OSC_DIS_CFG,
+ PMU_PMU_LF_EN_CFG,
+
+ PMU_ALIVE_LF_EN_CFG,
+ PMU_24M_EN_CFG,
+ PMU_DBG_PWRUP_L0_CFG,
+ PMU_WKUP_SFT_M0,
+
+ PMU_DDRCTL0_C_SYSREQ_CFG,
+ PMU_DDR0_IO_RET_CFG,
+
+ PMU_DDRCTL1_C_SYSREQ_CFG = 12,
+ PMU_DDR1_IO_RET_CFG,
+ DBG_PWRUP_B0_CFG = 15,
+
+ DBG_NOPWERDWN_L0_EN,
+ DBG_NOPWERDWN_L1_EN,
+ DBG_NOPWERDWN_L2_EN,
+ DBG_NOPWERDWN_L3_EN,
+
+ DBG_PWRUP_REQ_L_EN = 20,
+ CLUSTER_L_CLK_SRC_GATING_CFG,
+ L2_FLUSH_REQ_CLUSTER_L,
+ ACINACTM_CLUSTER_L_CFG,
+
+ DBG_NO_PWERDWN_B0_EN,
+ DBG_NO_PWERDWN_B1_EN,
+
+ DBG_PWRUP_REQ_B_EN = 28,
+ CLUSTER_B_CLK_SRC_GATING_CFG,
+ L2_FLUSH_REQ_CLUSTER_B,
+ ACINACTM_CLUSTER_B_CFG,
+};
+
+enum pmu_int_con {
+ PMU_PMU_INT_EN = 0,
+ PMU_PWRMD_WKUP_INT_EN,
+ PMU_WKUP_GPIO0_NEG_INT_EN,
+ PMU_WKUP_GPIO0_POS_INT_EN,
+ PMU_WKUP_GPIO1_NEG_INT_EN,
+ PMU_WKUP_GPIO1_POS_INT_EN,
+};
+
+enum pmu_int_st {
+ PMU_PWRMD_WKUP_INT_ST = 1,
+ PMU_WKUP_GPIO0_NEG_INT_ST,
+ PMU_WKUP_GPIO0_POS_INT_ST,
+ PMU_WKUP_GPIO1_NEG_INT_ST,
+ PMU_WKUP_GPIO1_POS_INT_ST,
+};
+
+enum pmu_gpio0_pos_int_con {
+ PMU_GPIO0A_POS_INT_EN = 0,
+ PMU_GPIO0B_POS_INT_EN = 8,
+ PMU_GPIO0C_POS_INT_EN = 16,
+ PMU_GPIO0D_POS_INT_EN = 24,
+};
+
+enum pmu_gpio0_neg_int_con {
+ PMU_GPIO0A_NEG_INT_EN = 0,
+ PMU_GPIO0B_NEG_INT_EN = 8,
+ PMU_GPIO0C_NEG_INT_EN = 16,
+ PMU_GPIO0D_NEG_INT_EN = 24,
+};
+
+enum pmu_gpio1_pos_int_con {
+ PMU_GPIO1A_POS_INT_EN = 0,
+ PMU_GPIO1B_POS_INT_EN = 8,
+ PMU_GPIO1C_POS_INT_EN = 16,
+ PMU_GPIO1D_POS_INT_EN = 24,
+};
+
+enum pmu_gpio1_neg_int_con {
+ PMU_GPIO1A_NEG_INT_EN = 0,
+ PMU_GPIO1B_NEG_INT_EN = 8,
+ PMU_GPIO1C_NEG_INT_EN = 16,
+ PMU_GPIO1D_NEG_INT_EN = 24,
+};
+
+enum pmu_gpio0_pos_int_st {
+ PMU_GPIO0A_POS_INT_ST = 0,
+ PMU_GPIO0B_POS_INT_ST = 8,
+ PMU_GPIO0C_POS_INT_ST = 16,
+ PMU_GPIO0D_POS_INT_ST = 24,
+};
+
+enum pmu_gpio0_neg_int_st {
+ PMU_GPIO0A_NEG_INT_ST = 0,
+ PMU_GPIO0B_NEG_INT_ST = 8,
+ PMU_GPIO0C_NEG_INT_ST = 16,
+ PMU_GPIO0D_NEG_INT_ST = 24,
+};
+
+enum pmu_gpio1_pos_int_st {
+ PMU_GPIO1A_POS_INT_ST = 0,
+ PMU_GPIO1B_POS_INT_ST = 8,
+ PMU_GPIO1C_POS_INT_ST = 16,
+ PMU_GPIO1D_POS_INT_ST = 24,
+};
+
+enum pmu_gpio1_neg_int_st {
+ PMU_GPIO1A_NEG_INT_ST = 0,
+ PMU_GPIO1B_NEG_INT_ST = 8,
+ PMU_GPIO1C_NEG_INT_ST = 16,
+ PMU_GPIO1D_NEG_INT_ST = 24,
+};
+
+/* pmu power down configure register 0x0050 */
+enum pmu_pwrdn_inten {
+ PMU_A53_L0_PWR_SWITCH_INT_EN = 0,
+ PMU_A53_L1_PWR_SWITCH_INT_EN,
+ PMU_A53_L2_PWR_SWITCH_INT_EN,
+ PMU_A53_L3_PWR_SWITCH_INT_EN,
+
+ PMU_A72_B0_PWR_SWITCH_INT_EN,
+ PMU_A72_B1_PWR_SWITCH_INT_EN,
+ PMU_SCU_L_PWR_SWITCH_INT_EN,
+ PMU_SCU_B_PWR_SWITCH_INT_EN,
+
+ PMU_TCPD0_PWR_SWITCH_INT_EN,
+ PMU_TCPD1_PWR_SWITCH_INT_EN,
+ PMU_CCI_PWR_SWITCH_INT_EN,
+ PMU_PERILP_PWR_SWITCH_INT_EN,
+
+ PMU_PERIHP_PWR_SWITCH_INT_EN,
+ PMU_CENTER_PWR_SWITCH_INT_EN,
+ PMU_VIO_PWR_SWITCH_INT_EN,
+ PMU_GPU_PWR_SWITCH_INT_EN,
+
+ PMU_VCODEC_PWR_SWITCH_INT_EN,
+ PMU_VDU_PWR_SWITCH_INT_EN,
+ PMU_RGA_PWR_SWITCH_INT_EN,
+ PMU_IEP_PWR_SWITCH_INT_EN,
+
+ PMU_VO_PWR_SWITCH_INT_EN,
+ PMU_ISP0_PWR_SWITCH_INT_EN = 22,
+ PMU_ISP1_PWR_SWITCH_INT_EN,
+
+ PMU_HDCP_PWR_SWITCH_INT_EN,
+ PMU_GMAC_PWR_SWITCH_INT_EN,
+ PMU_EMMC_PWR_SWITCH_INT_EN,
+ PMU_USB3_PWR_SWITCH_INT_EN,
+
+ PMU_EDP_PWR_SWITCH_INT_EN,
+ PMU_GIC_PWR_SWITCH_INT_EN,
+ PMU_SD_PWR_SWITCH_INT_EN,
+ PMU_SDIOAUDIO_PWR_SWITCH_INT_EN,
+};
+
+enum pmu_wkup_status {
+ PMU_WKUP_BY_CLSTER_L_INT = 0,
+ PMU_WKUP_BY_CLSTER_b_INT,
+ PMU_WKUP_BY_GPIO_INT,
+ PMU_WKUP_BY_SDIO_DET,
+
+ PMU_WKUP_BY_SDMMC_DET,
+ PMU_WKUP_BY_TIMER = 6,
+ PMU_WKUP_BY_USBDEV_DET,
+
+ PMU_WKUP_BY_M0_SFT,
+ PMU_WKUP_BY_M0_WDT_INT,
+ PMU_WKUP_BY_TIMEOUT,
+ PMU_WKUP_BY_PWM,
+
+ PMU_WKUP_BY_PCIE = 13,
+};
+
+enum pmu_bus_clr {
+ PMU_CLR_GPU = 0,
+ PMU_CLR_PERILP,
+ PMU_CLR_PERIHP,
+ PMU_CLR_VCODEC,
+
+ PMU_CLR_VDU,
+ PMU_CLR_RGA,
+ PMU_CLR_IEP,
+ PMU_CLR_VOPB,
+
+ PMU_CLR_VOPL,
+ PMU_CLR_ISP0,
+ PMU_CLR_ISP1,
+ PMU_CLR_HDCP,
+
+ PMU_CLR_USB3,
+ PMU_CLR_PERILPM0,
+ PMU_CLR_CENTER,
+ PMU_CLR_CCIM1,
+
+ PMU_CLR_CCIM0,
+ PMU_CLR_VIO,
+ PMU_CLR_MSCH0,
+ PMU_CLR_MSCH1,
+
+ PMU_CLR_ALIVE,
+ PMU_CLR_PMU,
+ PMU_CLR_EDP,
+ PMU_CLR_GMAC,
+
+ PMU_CLR_EMMC,
+ PMU_CLR_CENTER1,
+ PMU_CLR_PMUM0,
+ PMU_CLR_GIC,
+
+ PMU_CLR_SD,
+ PMU_CLR_SDIOAUDIO,
+};
+
+/* PMU bus idle request register */
+enum pmu_bus_idle_req {
+ PMU_IDLE_REQ_GPU = 0,
+ PMU_IDLE_REQ_PERILP,
+ PMU_IDLE_REQ_PERIHP,
+ PMU_IDLE_REQ_VCODEC,
+
+ PMU_IDLE_REQ_VDU,
+ PMU_IDLE_REQ_RGA,
+ PMU_IDLE_REQ_IEP,
+ PMU_IDLE_REQ_VOPB,
+
+ PMU_IDLE_REQ_VOPL,
+ PMU_IDLE_REQ_ISP0,
+ PMU_IDLE_REQ_ISP1,
+ PMU_IDLE_REQ_HDCP,
+
+ PMU_IDLE_REQ_USB3,
+ PMU_IDLE_REQ_PERILPM0,
+ PMU_IDLE_REQ_CENTER,
+ PMU_IDLE_REQ_CCIM0,
+
+ PMU_IDLE_REQ_CCIM1,
+ PMU_IDLE_REQ_VIO,
+ PMU_IDLE_REQ_MSCH0,
+ PMU_IDLE_REQ_MSCH1,
+
+ PMU_IDLE_REQ_ALIVE,
+ PMU_IDLE_REQ_PMU,
+ PMU_IDLE_REQ_EDP,
+ PMU_IDLE_REQ_GMAC,
+
+ PMU_IDLE_REQ_EMMC,
+ PMU_IDLE_REQ_CENTER1,
+ PMU_IDLE_REQ_PMUM0,
+ PMU_IDLE_REQ_GIC,
+
+ PMU_IDLE_REQ_SD,
+ PMU_IDLE_REQ_SDIOAUDIO,
+};
+
+/* pmu bus idle status register */
+enum pmu_bus_idle_st {
+ PMU_IDLE_ST_GPU = 0,
+ PMU_IDLE_ST_PERILP,
+ PMU_IDLE_ST_PERIHP,
+ PMU_IDLE_ST_VCODEC,
+
+ PMU_IDLE_ST_VDU,
+ PMU_IDLE_ST_RGA,
+ PMU_IDLE_ST_IEP,
+ PMU_IDLE_ST_VOPB,
+
+ PMU_IDLE_ST_VOPL,
+ PMU_IDLE_ST_ISP0,
+ PMU_IDLE_ST_ISP1,
+ PMU_IDLE_ST_HDCP,
+
+ PMU_IDLE_ST_USB3,
+ PMU_IDLE_ST_PERILPM0,
+ PMU_IDLE_ST_CENTER,
+ PMU_IDLE_ST_CCIM0,
+
+ PMU_IDLE_ST_CCIM1,
+ PMU_IDLE_ST_VIO,
+ PMU_IDLE_ST_MSCH0,
+ PMU_IDLE_ST_MSCH1,
+
+ PMU_IDLE_ST_ALIVE,
+ PMU_IDLE_ST_PMU,
+ PMU_IDLE_ST_EDP,
+ PMU_IDLE_ST_GMAC,
+
+ PMU_IDLE_ST_EMMC,
+ PMU_IDLE_ST_CENTER1,
+ PMU_IDLE_ST_PMUM0,
+ PMU_IDLE_ST_GIC,
+
+ PMU_IDLE_ST_SD,
+ PMU_IDLE_ST_SDIOAUDIO,
+};
+
+enum pmu_bus_idle_ack {
+ PMU_IDLE_ACK_GPU = 0,
+ PMU_IDLE_ACK_PERILP,
+ PMU_IDLE_ACK_PERIHP,
+ PMU_IDLE_ACK_VCODEC,
+
+ PMU_IDLE_ACK_VDU,
+ PMU_IDLE_ACK_RGA,
+ PMU_IDLE_ACK_IEP,
+ PMU_IDLE_ACK_VOPB,
+
+ PMU_IDLE_ACK_VOPL,
+ PMU_IDLE_ACK_ISP0,
+ PMU_IDLE_ACK_ISP1,
+ PMU_IDLE_ACK_HDCP,
+
+ PMU_IDLE_ACK_USB3,
+ PMU_IDLE_ACK_PERILPM0,
+ PMU_IDLE_ACK_CENTER,
+ PMU_IDLE_ACK_CCIM0,
+
+ PMU_IDLE_ACK_CCIM1,
+ PMU_IDLE_ACK_VIO,
+ PMU_IDLE_ACK_MSCH0,
+ PMU_IDLE_ACK_MSCH1,
+
+ PMU_IDLE_ACK_ALIVE,
+ PMU_IDLE_ACK_PMU,
+ PMU_IDLE_ACK_EDP,
+ PMU_IDLE_ACK_GMAC,
+
+ PMU_IDLE_ACK_EMMC,
+ PMU_IDLE_ACK_CENTER1,
+ PMU_IDLE_ACK_PMUM0,
+ PMU_IDLE_ACK_GIC,
+
+ PMU_IDLE_ACK_SD,
+ PMU_IDLE_ACK_SDIOAUDIO,
+};
+
+enum pmu_cci500_con {
+ PMU_PREQ_CCI500_CFG_SW = 0,
+ PMU_CLR_PREQ_CCI500_HW,
+ PMU_PSTATE_CCI500_0,
+ PMU_PSTATE_CCI500_1,
+
+ PMU_PSTATE_CCI500_2,
+ PMU_QREQ_CCI500_CFG_SW,
+ PMU_CLR_QREQ_CCI500_HW,
+ PMU_QGATING_CCI500_CFG,
+
+ PMU_PREQ_CCI500_CFG_SW_WMSK = 16,
+ PMU_CLR_PREQ_CCI500_HW_WMSK,
+ PMU_PSTATE_CCI500_0_WMSK,
+ PMU_PSTATE_CCI500_1_WMSK,
+
+ PMU_PSTATE_CCI500_2_WMSK,
+ PMU_QREQ_CCI500_CFG_SW_WMSK,
+ PMU_CLR_QREQ_CCI500_HW_WMSK,
+ PMU_QGATING_CCI500_CFG_WMSK,
+};
+
+enum pmu_adb400_con {
+ PMU_PWRDWN_REQ_CXCS_SW = 0,
+ PMU_PWRDWN_REQ_CORE_L_SW,
+ PMU_PWRDWN_REQ_CORE_L_2GIC_SW,
+ PMU_PWRDWN_REQ_GIC2_CORE_L_SW,
+
+ PMU_PWRDWN_REQ_CORE_B_SW,
+ PMU_PWRDWN_REQ_CORE_B_2GIC_SW,
+ PMU_PWRDWN_REQ_GIC2_CORE_B_SW,
+
+ PMU_CLR_CXCS_HW = 8,
+ PMU_CLR_CORE_L_HW,
+ PMU_CLR_CORE_L_2GIC_HW,
+ PMU_CLR_GIC2_CORE_L_HW,
+
+ PMU_CLR_CORE_B_HW,
+ PMU_CLR_CORE_B_2GIC_HW,
+ PMU_CLR_GIC2_CORE_B_HW,
+
+ PMU_PWRDWN_REQ_CXCS_SW_WMSK = 16,
+ PMU_PWRDWN_REQ_CORE_L_SW_WMSK,
+ PMU_PWRDWN_REQ_CORE_L_2GIC_SW_WMSK,
+ PMU_PWRDWN_REQ_GIC2_CORE_L_SW_WMSK,
+
+ PMU_PWRDWN_REQ_CORE_B_SW_WMSK,
+ PMU_PWRDWN_REQ_CORE_B_2GIC_SW_WMSK,
+ PMU_PWRDWN_REQ_GIC2_CORE_B_SW_WMSK,
+
+ PMU_CLR_CXCS_HW_WMSK = 24,
+ PMU_CLR_CORE_L_HW_WMSK,
+ PMU_CLR_CORE_L_2GIC_HW_WMSK,
+ PMU_CLR_GIC2_CORE_L_HW_WMSK,
+
+ PMU_CLR_CORE_B_HW_WMSK,
+ PMU_CLR_CORE_B_2GIC_HW_WMSK,
+ PMU_CLR_GIC2_CORE_B_HW_WMSK,
+};
+
+enum pmu_adb400_st {
+ PMU_PWRDWN_REQ_CXCS_SW_ST = 0,
+ PMU_PWRDWN_REQ_CORE_L_SW_ST,
+ PMU_PWRDWN_REQ_CORE_L_2GIC_SW_ST,
+ PMU_PWRDWN_REQ_GIC2_CORE_L_SW_ST,
+
+ PMU_PWRDWN_REQ_CORE_B_SW_ST,
+ PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST,
+ PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST,
+
+ PMU_CLR_CXCS_HW_ST = 8,
+ PMU_CLR_CORE_L_HW_ST,
+ PMU_CLR_CORE_L_2GIC_HW_ST,
+ PMU_CLR_GIC2_CORE_L_HW_ST,
+
+ PMU_CLR_CORE_B_HW_ST,
+ PMU_CLR_CORE_B_2GIC_HW_ST,
+ PMU_CLR_GIC2_CORE_B_HW_ST,
+};
+
+enum pmu_pwrdn_con1 {
+ PMU_VD_SCU_L_PWRDN_EN = 0,
+ PMU_VD_SCU_B_PWRDN_EN,
+ PMU_VD_CENTER_PWRDN_EN,
+};
+
+enum pmu_core_pwr_st {
+ L2_FLUSHDONE_CLUSTER_L = 0,
+ STANDBY_BY_WFIL2_CLUSTER_L,
+
+ L2_FLUSHDONE_CLUSTER_B = 10,
+ STANDBY_BY_WFIL2_CLUSTER_B,
+};
+
+#endif /* PMU_BITS_H */
diff --git a/plat/rockchip/rk3399/include/shared/pmu_regs.h b/plat/rockchip/rk3399/include/shared/pmu_regs.h
new file mode 100644
index 0000000..43e785e
--- /dev/null
+++ b/plat/rockchip/rk3399/include/shared/pmu_regs.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PMU_REGS_H
+#define PMU_REGS_H
+
+#define PMU_WKUP_CFG0 0x00
+#define PMU_WKUP_CFG1 0x04
+#define PMU_WKUP_CFG2 0x08
+#define PMU_WKUP_CFG3 0x0c
+#define PMU_WKUP_CFG4 0x10
+#define PMU_PWRDN_CON 0x14
+#define PMU_PWRDN_ST 0x18
+#define PMU_PLL_CON 0x1c
+#define PMU_PWRMODE_CON 0x20
+#define PMU_SFT_CON 0x24
+#define PMU_INT_CON 0x28
+#define PMU_INT_ST 0x2c
+#define PMU_GPIO0_POS_INT_CON 0x30
+#define PMU_GPIO0_NEG_INT_CON 0x34
+#define PMU_GPIO1_POS_INT_CON 0x38
+#define PMU_GPIO1_NEG_INT_CON 0x3c
+#define PMU_GPIO0_POS_INT_ST 0x40
+#define PMU_GPIO0_NEG_INT_ST 0x44
+#define PMU_GPIO1_POS_INT_ST 0x48
+#define PMU_GPIO1_NEG_INT_ST 0x4c
+#define PMU_PWRDN_INTEN 0x50
+#define PMU_PWRDN_STATUS 0x54
+#define PMU_WAKEUP_STATUS 0x58
+#define PMU_BUS_CLR 0x5c
+#define PMU_BUS_IDLE_REQ 0x60
+#define PMU_BUS_IDLE_ST 0x64
+#define PMU_BUS_IDLE_ACK 0x68
+#define PMU_CCI500_CON 0x6c
+#define PMU_ADB400_CON 0x70
+#define PMU_ADB400_ST 0x74
+#define PMU_POWER_ST 0x78
+#define PMU_CORE_PWR_ST 0x7c
+#define PMU_OSC_CNT 0x80
+#define PMU_PLLLOCK_CNT 0x84
+#define PMU_PLLRST_CNT 0x88
+#define PMU_STABLE_CNT 0x8c
+#define PMU_DDRIO_PWRON_CNT 0x90
+#define PMU_WAKEUP_RST_CLR_CNT 0x94
+#define PMU_DDR_SREF_ST 0x98
+#define PMU_SCU_L_PWRDN_CNT 0x9c
+#define PMU_SCU_L_PWRUP_CNT 0xa0
+#define PMU_SCU_B_PWRDN_CNT 0xa4
+#define PMU_SCU_B_PWRUP_CNT 0xa8
+#define PMU_GPU_PWRDN_CNT 0xac
+#define PMU_GPU_PWRUP_CNT 0xb0
+#define PMU_CENTER_PWRDN_CNT 0xb4
+#define PMU_CENTER_PWRUP_CNT 0xb8
+#define PMU_TIMEOUT_CNT 0xbc
+#define PMU_CPU0APM_CON 0xc0
+#define PMU_CPU1APM_CON 0xc4
+#define PMU_CPU2APM_CON 0xc8
+#define PMU_CPU3APM_CON 0xcc
+#define PMU_CPU0BPM_CON 0xd0
+#define PMU_CPU1BPM_CON 0xd4
+#define PMU_NOC_AUTO_ENA 0xd8
+#define PMU_PWRDN_CON1 0xdc
+
+#define PMUGRF_GPIO0A_IOMUX 0x00
+#define PMUGRF_GPIO1A_IOMUX 0x10
+#define PMUGRF_GPIO1C_IOMUX 0x18
+
+#define PMUGRF_GPIO0A6_IOMUX_SHIFT 12
+#define PMUGRF_GPIO0A6_IOMUX_PWM 0x1
+#define PMUGRF_GPIO1C3_IOMUX_SHIFT 6
+#define PMUGRF_GPIO1C3_IOMUX_PWM 0x1
+
+#define CPU_AXI_QOS_ID_COREID 0x00
+#define CPU_AXI_QOS_REVISIONID 0x04
+#define CPU_AXI_QOS_PRIORITY 0x08
+#define CPU_AXI_QOS_MODE 0x0c
+#define CPU_AXI_QOS_BANDWIDTH 0x10
+#define CPU_AXI_QOS_SATURATION 0x14
+#define CPU_AXI_QOS_EXTCONTROL 0x18
+#define CPU_AXI_QOS_NUM_REGS 0x07
+
+#define CPU_AXI_CCI_M0_QOS_BASE 0xffa50000
+#define CPU_AXI_CCI_M1_QOS_BASE 0xffad8000
+#define CPU_AXI_DMAC0_QOS_BASE 0xffa64200
+#define CPU_AXI_DMAC1_QOS_BASE 0xffa64280
+#define CPU_AXI_DCF_QOS_BASE 0xffa64180
+#define CPU_AXI_CRYPTO0_QOS_BASE 0xffa64100
+#define CPU_AXI_CRYPTO1_QOS_BASE 0xffa64080
+#define CPU_AXI_PMU_CM0_QOS_BASE 0xffa68000
+#define CPU_AXI_PERI_CM1_QOS_BASE 0xffa64300
+#define CPU_AXI_GIC_QOS_BASE 0xffa78000
+#define CPU_AXI_SDIO_QOS_BASE 0xffa76000
+#define CPU_AXI_SDMMC_QOS_BASE 0xffa74000
+#define CPU_AXI_EMMC_QOS_BASE 0xffa58000
+#define CPU_AXI_GMAC_QOS_BASE 0xffa5c000
+#define CPU_AXI_USB_OTG0_QOS_BASE 0xffa70000
+#define CPU_AXI_USB_OTG1_QOS_BASE 0xffa70080
+#define CPU_AXI_USB_HOST0_QOS_BASE 0xffa60100
+#define CPU_AXI_USB_HOST1_QOS_BASE 0xffa60180
+#define CPU_AXI_GPU_QOS_BASE 0xffae0000
+#define CPU_AXI_VIDEO_M0_QOS_BASE 0xffab8000
+#define CPU_AXI_VIDEO_M1_R_QOS_BASE 0xffac0000
+#define CPU_AXI_VIDEO_M1_W_QOS_BASE 0xffac0080
+#define CPU_AXI_RGA_R_QOS_BASE 0xffab0000
+#define CPU_AXI_RGA_W_QOS_BASE 0xffab0080
+#define CPU_AXI_IEP_QOS_BASE 0xffa98000
+#define CPU_AXI_VOP_BIG_R_QOS_BASE 0xffac8000
+#define CPU_AXI_VOP_BIG_W_QOS_BASE 0xffac8080
+#define CPU_AXI_VOP_LITTLE_QOS_BASE 0xffad0000
+#define CPU_AXI_ISP0_M0_QOS_BASE 0xffaa0000
+#define CPU_AXI_ISP0_M1_QOS_BASE 0xffaa0080
+#define CPU_AXI_ISP1_M0_QOS_BASE 0xffaa8000
+#define CPU_AXI_ISP1_M1_QOS_BASE 0xffaa8080
+#define CPU_AXI_HDCP_QOS_BASE 0xffa90000
+#define CPU_AXI_PERIHP_NSP_QOS_BASE 0xffad8080
+#define CPU_AXI_PERILP_NSP_QOS_BASE 0xffad8180
+#define CPU_AXI_PERILPSLV_NSP_QOS_BASE 0xffad8100
+
+#define GRF_GPIO2A_IOMUX 0xe000
+#define GRF_GPIO2B_IOMUX 0xe004
+#define GRF_GPIO2C_IOMUX 0xe008
+#define GRF_GPIO2D_IOMUX 0xe00c
+#define GRF_GPIO3A_IOMUX 0xe010
+#define GRF_GPIO3B_IOMUX 0xe014
+#define GRF_GPIO3C_IOMUX 0xe018
+#define GRF_GPIO3D_IOMUX 0xe01c
+#define GRF_GPIO4A_IOMUX 0xe020
+#define GRF_GPIO4B_IOMUX 0xe024
+#define GRF_GPIO4C_IOMUX 0xe028
+#define GRF_GPIO4D_IOMUX 0xe02c
+
+#define GRF_GPIO2A_P 0xe040
+#define GRF_GPIO2B_P 0xe044
+#define GRF_GPIO2C_P 0xe048
+#define GRF_GPIO2D_P 0xe04C
+#define GRF_GPIO3A_P 0xe050
+#define GRF_GPIO3B_P 0xe054
+#define GRF_GPIO3C_P 0xe058
+#define GRF_GPIO3D_P 0xe05C
+#define GRF_GPIO4A_P 0xe060
+#define GRF_GPIO4B_P 0xe064
+#define GRF_GPIO4C_P 0xe068
+#define GRF_GPIO4D_P 0xe06C
+
+#endif /* PMU_REGS_H */
diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c
new file mode 100644
index 0000000..ce8476c
--- /dev/null
+++ b/plat/rockchip/rk3399/plat_sip_calls.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+
+#include <cdn_dp.h>
+#include <dfs.h>
+#include <plat_sip_calls.h>
+#include <rockchip_sip_svc.h>
+
+#define RK_SIP_DDR_CFG 0x82000008
+#define DRAM_INIT 0x00
+#define DRAM_SET_RATE 0x01
+#define DRAM_ROUND_RATE 0x02
+#define DRAM_SET_AT_SR 0x03
+#define DRAM_GET_BW 0x04
+#define DRAM_GET_RATE 0x05
+#define DRAM_CLR_IRQ 0x06
+#define DRAM_SET_PARAM 0x07
+#define DRAM_SET_ODT_PD 0x08
+
+#define RK_SIP_HDCP_CONTROL 0x82000009
+#define RK_SIP_HDCP_KEY_DATA64 0xC200000A
+
+uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1,
+ uint64_t id, uint64_t arg2)
+{
+ switch (id) {
+ case DRAM_SET_RATE:
+ return ddr_set_rate((uint32_t)arg0);
+ case DRAM_ROUND_RATE:
+ return ddr_round_rate((uint32_t)arg0);
+ case DRAM_GET_RATE:
+ return ddr_get_rate();
+ case DRAM_SET_ODT_PD:
+ dram_set_odt_pd(arg0, arg1, arg2);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+#ifdef PLAT_RK_DP_HDCP
+ uint64_t x5, x6;
+#endif
+
+ switch (smc_fid) {
+ case RK_SIP_DDR_CFG:
+ SMC_RET1(handle, ddr_smc_handler(x1, x2, x3, x4));
+#ifdef PLAT_RK_DP_HDCP
+ case RK_SIP_HDCP_CONTROL:
+ SMC_RET1(handle, dp_hdcp_ctrl(x1));
+ case RK_SIP_HDCP_KEY_DATA64:
+ x5 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X5);
+ x6 = read_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X6);
+ SMC_RET1(handle, dp_hdcp_store_key(x1, x2, x3, x4, x5, x6));
+#endif
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
new file mode 100644
index 0000000..aba67c2
--- /dev/null
+++ b/plat/rockchip/rk3399/platform.mk
@@ -0,0 +1,113 @@
+#
+# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+DISABLE_BIN_GENERATION := 1
+
+PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/aarch64/ \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/pwm/ \
+ -I${RK_PLAT_SOC}/drivers/secure/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/drivers/dram/ \
+ -I${RK_PLAT_SOC}/drivers/dp/ \
+ -I${RK_PLAT_SOC}/include/ \
+ -I${RK_PLAT_SOC}/include/shared/ \
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+RK_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ ${RK_PLAT}/common/rockchip_gicv3.c
+
+PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+ lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/gpio/gpio.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/params_setup.c \
+ ${RK_PLAT_COMMON}/aarch64/pmu_sram_cpus_on.S \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
+ ${RK_PLAT_SOC}/plat_sip_calls.c \
+ ${RK_PLAT_SOC}/drivers/gpio/rk3399_gpio.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c \
+ ${RK_PLAT_SOC}/drivers/pmu/m0_ctl.c \
+ ${RK_PLAT_SOC}/drivers/pwm/pwm.c \
+ ${RK_PLAT_SOC}/drivers/secure/secure.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
+ ${RK_PLAT_SOC}/drivers/dram/dfs.c \
+ ${RK_PLAT_SOC}/drivers/dram/dram.c \
+ ${RK_PLAT_SOC}/drivers/dram/dram_spec_timing.c \
+ ${RK_PLAT_SOC}/drivers/dram/suspend.c
+
+include lib/coreboot/coreboot.mk
+include lib/libfdt/libfdt.mk
+
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_855873 := 1
+
+# M0 source build
+PLAT_M0 := ${PLAT}m0
+BUILD_M0 := ${BUILD_PLAT}/m0
+
+RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin
+$(eval $(call add_define_val,RK3399M0FW,\"$(RK3399M0FW)\"))
+
+RK3399M0PMUFW=${BUILD_M0}/${PLAT_M0}pmu.bin
+$(eval $(call add_define_val,RK3399M0PMUFW,\"$(RK3399M0PMUFW)\"))
+
+ifdef PLAT_RK_DP_HDCP
+BL31_SOURCES += ${RK_PLAT_SOC}/drivers/dp/cdn_dp.c
+
+HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin
+$(eval $(call add_define_val,HDCPFW,\"$(HDCPFW)\"))
+
+${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW)
+${RK_PLAT_SOC}/drivers/dp/cdn_dp.c: $(HDCPFW)
+endif
+
+# CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin
+export CCACHE_EXTRAFILES
+${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW)
+${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW)
+
+$(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},${BUILD_PLAT}))
+.PHONY: $(RK3399M0FW)
+$(RK3399M0FW): | ${BUILD_M0}
+ $(MAKE) -C ${RK_PLAT_SOC}/drivers/m0 BUILD=$(abspath ${BUILD_PLAT}/m0)
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
diff --git a/plat/rockchip/rk3399/rk3399_def.h b/plat/rockchip/rk3399/rk3399_def.h
new file mode 100644
index 0000000..ba83242
--- /dev/null
+++ b/plat/rockchip/rk3399/rk3399_def.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK3399_DEF_H
+#define RK3399_DEF_H
+
+#include <addressmap.h>
+
+#define RK3399_PRIMARY_CPU 0x0
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK3399_BAUDRATE 115200
+#define RK3399_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+
+/* Base rockchip_platform compatible GIC memory map */
+#define BASE_GICD_BASE (GIC500_BASE)
+#define BASE_GICR_BASE (GIC500_BASE + SIZE_M(1))
+
+/*****************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 0
+#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 1
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_RK_GICV3_G1S_IRQS \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ INTR_GROUP1S, GIC_INTR_CFG_LEVEL)
+
+#define PLAT_RK_GICV3_G0_IRQS \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+#endif /* RK3399_DEF_H */
diff --git a/plat/rpi/common/aarch64/plat_helpers.S b/plat/rpi/common/aarch64/plat_helpers.S
new file mode 100644
index 0000000..f045e21
--- /dev/null
+++ b/plat/rpi/common/aarch64/plat_helpers.S
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2015-2020, 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 <platform_def.h>
+#include <cortex_a72.h>
+
+ .globl plat_crash_console_flush
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl platform_mem_init
+ .globl plat_get_my_entrypoint
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_reset_handler
+ .globl plat_rpi3_calc_core_pos
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_rpi_get_model
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ *
+ * This function uses the plat_rpi3_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_rpi3_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
+ *
+ * CorePos = (ClusterId * 4) + CoreId
+ * -----------------------------------------------------
+ */
+func plat_rpi3_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc plat_rpi3_calc_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ mrs x0, mpidr_el1
+ and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ cmp x0, #RPI_PRIMARY_CPU
+ cset w0, eq
+ ret
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * void plat_wait_for_warm_boot (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a CPU to be put into holding pen to wait
+ * for a warm boot request.
+ * The function will never return.
+ * -----------------------------------------------------
+ */
+func plat_wait_for_warm_boot
+ /*
+ * Calculate address of our hold entry.
+ * As the function will never return, there is no need to save LR.
+ */
+ bl plat_my_core_pos
+ lsl x0, x0, #3
+ mov_imm x2, PLAT_RPI3_TM_HOLD_BASE
+ add x0, x0, x2
+ /*
+ * This code runs way before requesting the warmboot of this core,
+ * so it is possible to clear the mailbox before getting a request
+ * to boot.
+ */
+ mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
+ str x1,[x0]
+
+ /* Wait until we have a go */
+poll_mailbox:
+ wfe
+ ldr x1, [x0]
+ cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO
+ bne poll_mailbox
+
+ /* Jump to the provided entrypoint */
+ mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT
+ ldr x1, [x0]
+ br x1
+endfunc plat_wait_for_warm_boot
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ b plat_wait_for_warm_boot
+endfunc plat_secondary_cold_boot_setup
+
+ /* ---------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and a warm
+ * boot.
+ *
+ * This functions returns:
+ * - 0 for a cold boot.
+ * - Any other value for a warm boot.
+ * ---------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mov x1, x30
+ bl plat_is_my_cpu_primary
+ /*
+ * Secondaries always cold boot.
+ */
+ cbz w0, 1f
+ /*
+ * Primaries warm boot if they are requested
+ * to power off.
+ */
+ mov_imm x0, PLAT_RPI3_TM_HOLD_BASE
+ ldr x0, [x0]
+ cmp x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF
+ adr x0, plat_wait_for_warm_boot
+ csel x0, x0, xzr, eq
+ ret x1
+1: mov x0, #0
+ ret x1
+endfunc plat_get_my_entrypoint
+
+ /* ---------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * No need to carry out any memory initialization.
+ * ---------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x3
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_RPI_MINI_UART_BASE
+ mov x1, xzr
+ mov x2, xzr
+ b console_16550_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_RPI_MINI_UART_BASE
+ b console_16550_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, PLAT_RPI_MINI_UART_BASE
+ b console_16550_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * int plat_rpi_get_model()
+ * Macro to determine whether we are running on
+ * a Raspberry Pi 3 or 4. Just checks the MIDR for
+ * being either a Cortex-A72 or a Cortex-A53.
+ * Out : return 4 if RPi4, 3 otherwise.
+ * Clobber list : x0
+ * ---------------------------------------------
+ */
+ .macro _plat_rpi_get_model
+ mrs x0, midr_el1
+ and x0, x0, #0xf0 /* Isolate low byte of part number */
+ cmp w0, #0x80 /* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */
+ mov w0, #3
+ csinc w0, w0, w0, ne
+ .endm
+
+ func plat_rpi_get_model
+ _plat_rpi_get_model
+ ret
+ endfunc plat_rpi_get_model
+
+ /* ---------------------------------------------
+ * void plat_reset_handler(void);
+ * ---------------------------------------------
+ */
+func plat_reset_handler
+ /* L2 cache setup only needed on RPi4 */
+ _plat_rpi_get_model
+ cmp w0, #4
+ b.ne 1f
+
+ /* ------------------------------------------------
+ * Set L2 read/write cache latency:
+ * - L2 Data RAM latency: 3 cycles (0b010)
+ * - L2 Data RAM setup: 1 cycle (bit 5)
+ * ------------------------------------------------
+ */
+ mrs x0, CORTEX_A72_L2CTLR_EL1
+ mov x1, #0x22
+ orr x0, x0, x1
+ msr CORTEX_A72_L2CTLR_EL1, x0
+ isb
+
+1:
+ ret
+endfunc plat_reset_handler
diff --git a/plat/rpi/common/include/rpi_shared.h b/plat/rpi/common/include/rpi_shared.h
new file mode 100644
index 0000000..ddf239e
--- /dev/null
+++ b/plat/rpi/common/include/rpi_shared.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPI_SHARED_H
+#define RPI_SHARED_H
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+/* Utility functions */
+void rpi3_console_init(void);
+void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
+ uintptr_t code_start, uintptr_t code_limit,
+ uintptr_t rodata_start, uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ , uintptr_t coh_start, uintptr_t coh_limit
+#endif
+ );
+
+/* Optional functions required in the Raspberry Pi 3 port */
+unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
+
+/* BL2 utility functions */
+uint32_t rpi3_get_spsr_for_bl32_entry(void);
+uint32_t rpi3_get_spsr_for_bl33_entry(void);
+
+/* IO storage utility functions */
+void plat_rpi3_io_setup(void);
+
+/* VideoCore firmware commands */
+int rpi3_vc_hardware_get_board_revision(uint32_t *revision);
+
+int plat_rpi_get_model(void);
+
+#endif /* RPI3_PRIVATE_H */
diff --git a/plat/rpi/common/rpi3_common.c b/plat/rpi/common/rpi3_common.c
new file mode 100644
index 0000000..ef88bf1
--- /dev/null
+++ b/plat/rpi/common/rpi3_common.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <bl31/interrupt_mgmt.h>
+#include <drivers/console.h>
+#include <drivers/rpi3/gpio/rpi3_gpio.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <drivers/arm/pl011.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <rpi_hw.h>
+#include <rpi_shared.h>
+
+#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
+ DEVICE0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#ifdef SHARED_RAM_BASE
+#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \
+ SHARED_RAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+#ifdef RPI3_PRELOADED_DTB_BASE
+#define MAP_NS_DTB MAP_REGION_FLAT(RPI3_PRELOADED_DTB_BASE, 0x10000, \
+ MT_MEMORY | MT_RW | MT_NS)
+#endif
+
+#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_FIP MAP_REGION_FLAT(PLAT_RPI3_FIP_BASE, \
+ PLAT_RPI3_FIP_MAX_SIZE, \
+ MT_MEMORY | MT_RO | MT_NS)
+
+#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+
+#ifdef SPD_opteed
+#define MAP_OPTEE_PAGEABLE MAP_REGION_FLAT( \
+ RPI3_OPTEE_PAGEABLE_LOAD_BASE, \
+ RPI3_OPTEE_PAGEABLE_LOAD_SIZE, \
+ MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
+/*
+ * Table of regions for various BL stages to map using the MMU.
+ */
+#ifdef IMAGE_BL1
+static const mmap_region_t plat_rpi3_mmap[] = {
+#ifdef MAP_SHARED_RAM
+ MAP_SHARED_RAM,
+#endif
+ MAP_DEVICE0,
+ MAP_FIP,
+#ifdef SPD_opteed
+ MAP_OPTEE_PAGEABLE,
+#endif
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL2
+static const mmap_region_t plat_rpi3_mmap[] = {
+#ifdef MAP_SHARED_RAM
+ MAP_SHARED_RAM,
+#endif
+ MAP_DEVICE0,
+ MAP_FIP,
+ MAP_NS_DRAM0,
+#ifdef BL32_BASE
+ MAP_BL32_MEM,
+#endif
+ {0}
+};
+#endif
+
+#ifdef IMAGE_BL31
+static const mmap_region_t plat_rpi3_mmap[] = {
+#ifdef MAP_SHARED_RAM
+ MAP_SHARED_RAM,
+#endif
+ MAP_DEVICE0,
+#ifdef RPI3_PRELOADED_DTB_BASE
+ MAP_NS_DTB,
+#endif
+#ifdef BL32_BASE
+ MAP_BL32_MEM,
+#endif
+ {0}
+};
+#endif
+
+/*******************************************************************************
+ * Function that sets up the console
+ ******************************************************************************/
+static console_t rpi3_console;
+
+
+static bool rpi3_use_mini_uart(void)
+{
+ return rpi3_gpio_get_select(14) == RPI3_GPIO_FUNC_ALT5;
+}
+
+void rpi3_console_init(void)
+{
+ int console_scope = CONSOLE_FLAG_BOOT;
+ int rc;
+
+ if (RPI3_RUNTIME_UART != -1)
+ console_scope |= CONSOLE_FLAG_RUNTIME;
+
+ rpi3_gpio_init();
+
+ if (rpi3_use_mini_uart())
+ rc = console_16550_register(PLAT_RPI_MINI_UART_BASE,
+ 0,
+ PLAT_RPI_UART_BAUDRATE,
+ &rpi3_console);
+ else
+ rc = console_pl011_register(PLAT_RPI_PL011_UART_BASE,
+ PLAT_RPI_PL011_UART_CLOCK,
+ PLAT_RPI_UART_BAUDRATE,
+ &rpi3_console);
+
+ if (rc == 0) {
+ /*
+ * The crash console doesn't use the multi console API, it uses
+ * the core console functions directly. It is safe to call panic
+ * and let it print debug information.
+ */
+ panic();
+ }
+
+ console_set_scope(&rpi3_console, console_scope);
+}
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
+ uintptr_t code_start, uintptr_t code_limit,
+ uintptr_t rodata_start, uintptr_t rodata_limit
+#if USE_COHERENT_MEM
+ , uintptr_t coh_start, uintptr_t coh_limit
+#endif
+ )
+{
+ /*
+ * Map the Trusted SRAM with appropriate memory attributes.
+ * Subsequent mappings will adjust the attributes for specific regions.
+ */
+ VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n",
+ (void *) total_base, (void *) (total_base + total_size));
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ /* Re-map the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *) code_start, (void *) code_limit);
+ mmap_add_region(code_start, code_start,
+ code_limit - code_start,
+ MT_CODE | MT_SECURE);
+
+ /* Re-map the read-only data section */
+ VERBOSE("Read-only data region: %p - %p\n",
+ (void *) rodata_start, (void *) rodata_limit);
+ mmap_add_region(rodata_start, rodata_start,
+ rodata_limit - rodata_start,
+ MT_RO_DATA | MT_SECURE);
+
+#if USE_COHERENT_MEM
+ /* Re-map the coherent memory region */
+ VERBOSE("Coherent region: %p - %p\n",
+ (void *) coh_start, (void *) coh_limit);
+ mmap_add_region(coh_start, coh_start,
+ coh_limit - coh_start,
+ MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+
+ mmap_add(plat_rpi3_mmap);
+
+ init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t rpi3_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t rpi3_get_spsr_for_bl33_entry(void)
+{
+#if RPI3_BL33_IN_AARCH32
+ INFO("BL33 will boot in Non-secure AArch32 Hypervisor mode\n");
+ return SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS);
+#else
+ return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+#endif
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+uint32_t plat_ic_get_pending_interrupt_type(void)
+{
+ ERROR("rpi3: Interrupt routed to EL3.\n");
+ return INTR_TYPE_INVAL;
+}
+
+uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state)
+{
+ assert((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_EL3) ||
+ (type == INTR_TYPE_NS));
+
+ assert(sec_state_is_valid(security_state));
+
+ /* Non-secure interrupts are signalled on the IRQ line always. */
+ if (type == INTR_TYPE_NS)
+ return __builtin_ctz(SCR_IRQ_BIT);
+
+ /* Secure interrupts are signalled on the FIQ line always. */
+ return __builtin_ctz(SCR_FIQ_BIT);
+}
diff --git a/plat/rpi/common/rpi3_image_load.c b/plat/rpi/common/rpi3_image_load.c
new file mode 100644
index 0000000..5394c6f
--- /dev/null
+++ b/plat/rpi/common/rpi3_image_load.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/rpi/common/rpi3_io_storage.c b/plat/rpi/common/rpi3_io_storage.c
new file mode 100644
index 0000000..49c6a76
--- /dev/null
+++ b/plat/rpi/common/rpi3_io_storage.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <tools_share/firmware_image_package.h>
+
+/* Semihosting filenames */
+#define BL2_IMAGE_NAME "bl2.bin"
+#define BL31_IMAGE_NAME "bl31.bin"
+#define BL32_IMAGE_NAME "bl32.bin"
+#define BL33_IMAGE_NAME "bl33.bin"
+
+#if TRUSTED_BOARD_BOOT
+#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt"
+#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
+#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt"
+#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt"
+#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt"
+#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt"
+#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt"
+#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+ .offset = PLAT_RPI3_FIP_BASE,
+ .length = PLAT_RPI3_FIP_MAX_SIZE
+};
+
+static const io_uuid_spec_t bl2_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+static int open_fip(const uintptr_t spec);
+static int open_memmap(const uintptr_t spec);
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ int (*check)(const uintptr_t spec);
+};
+
+/* By default, load images from the FIP */
+static const struct plat_io_policy policies[] = {
+ [FIP_IMAGE_ID] = {
+ &memmap_dev_handle,
+ (uintptr_t)&fip_block_spec,
+ open_memmap
+ },
+ [BL2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl2_uuid_spec,
+ open_fip
+ },
+ [BL31_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl31_uuid_spec,
+ open_fip
+ },
+ [BL32_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA1_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra1_uuid_spec,
+ open_fip
+ },
+ [BL32_EXTRA2_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl32_extra2_uuid_spec,
+ open_fip
+ },
+ [BL33_IMAGE_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&bl33_uuid_spec,
+ open_fip
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tb_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ open_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
+ open_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ open_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ open_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static int open_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ /* See if a Firmware Image Package is available */
+ result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+ if (result == 0) {
+ result = io_open(fip_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using FIP\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+static int open_memmap(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+ if (result == 0) {
+ result = io_open(memmap_dev_handle, spec, &local_image_handle);
+ if (result == 0) {
+ VERBOSE("Using Memmap\n");
+ io_close(local_image_handle);
+ }
+ }
+ return result;
+}
+
+void plat_rpi3_io_setup(void)
+{
+ int io_result;
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to devices and cache the handles */
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &memmap_dev_handle);
+ assert(io_result == 0);
+
+ /* Ignore improbable errors in release builds */
+ (void)io_result;
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int result;
+ const struct plat_io_policy *policy;
+
+ assert(image_id < ARRAY_SIZE(policies));
+
+ policy = &policies[image_id];
+ result = policy->check(policy->image_spec);
+ if (result == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ }
+
+ return result;
+}
diff --git a/plat/rpi/common/rpi3_pm.c b/plat/rpi/common/rpi3_pm.c
new file mode 100644
index 0000000..d98ac66
--- /dev/null
+++ b/plat/rpi/common/rpi3_pm.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <rpi_hw.h>
+
+#ifdef RPI_HAVE_GIC
+#include <drivers/arm/gicv2.h>
+#endif
+
+/* Make composite power state parameter till power level 0 */
+#if PSCI_EXTENDED_STATE_ID
+
+#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+
+#else
+
+#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
+ (((lvl0_state) << PSTATE_ID_SHIFT) | \
+ ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+ ((type) << PSTATE_TYPE_SHIFT))
+
+#endif /* PSCI_EXTENDED_STATE_ID */
+
+#define rpi3_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
+ (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \
+ rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
+
+/*
+ * The table storing the valid idle power states. Ensure that the
+ * array entries are populated in ascending order of state-id to
+ * enable us to use binary search during power state validation.
+ * The table must be terminated by a NULL entry.
+ */
+static const unsigned int rpi3_pm_idle_states[] = {
+ /* State-id - 0x01 */
+ rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET,
+ MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+ /* State-id - 0x02 */
+ rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+ /* State-id - 0x22 */
+ rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF,
+ MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+ 0,
+};
+
+/*******************************************************************************
+ * Platform handler called to check the validity of the power state
+ * parameter. The power state parameter has to be a composite power state.
+ ******************************************************************************/
+static int rpi3_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ unsigned int state_id;
+ int i;
+
+ assert(req_state != 0);
+
+ /*
+ * Currently we are using a linear search for finding the matching
+ * entry in the idle power state array. This can be made a binary
+ * search if the number of entries justify the additional complexity.
+ */
+ for (i = 0; rpi3_pm_idle_states[i] != 0; i++) {
+ if (power_state == rpi3_pm_idle_states[i]) {
+ break;
+ }
+ }
+
+ /* Return error if entry not found in the idle state array */
+ if (!rpi3_pm_idle_states[i]) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ i = 0;
+ state_id = psci_get_pstate_id(power_state);
+
+ /* Parse the State ID and populate the state info parameter */
+ while (state_id) {
+ req_state->pwr_domain_state[i++] = state_id &
+ PLAT_LOCAL_PSTATE_MASK;
+ state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Platform handler called when a CPU is about to enter standby.
+ ******************************************************************************/
+static void rpi3_cpu_standby(plat_local_state_t cpu_state)
+{
+ assert(cpu_state == PLAT_LOCAL_STATE_RET);
+
+ /*
+ * Enter standby state.
+ * dsb is good practice before using wfi to enter low power states
+ */
+ dsb();
+ wfi();
+}
+
+static void rpi3_pwr_domain_off(const psci_power_state_t *target_state)
+{
+#ifdef RPI_HAVE_GIC
+ gicv2_cpuif_disable();
+#endif
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ ******************************************************************************/
+static int rpi3_pwr_domain_on(u_register_t mpidr)
+{
+ int rc = PSCI_E_SUCCESS;
+ unsigned int pos = plat_core_pos_by_mpidr(mpidr);
+ uintptr_t hold_base = PLAT_RPI3_TM_HOLD_BASE;
+
+ assert(pos < PLATFORM_CORE_COUNT);
+
+ hold_base += pos * PLAT_RPI3_TM_HOLD_ENTRY_SIZE;
+
+ mmio_write_64(hold_base, PLAT_RPI3_TM_HOLD_STATE_GO);
+ /* No cache maintenance here, hold_base is mapped as device memory. */
+
+ /* Make sure that the write has completed */
+ dsb();
+ isb();
+
+ sev();
+
+ return rc;
+}
+
+/*******************************************************************************
+ * Platform handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ ******************************************************************************/
+static void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+ PLAT_LOCAL_STATE_OFF);
+
+#ifdef RPI_HAVE_GIC
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+#endif
+}
+
+static void __dead2 rpi3_pwr_down_wfi(
+ const psci_power_state_t *target_state)
+{
+ uintptr_t hold_base = PLAT_RPI3_TM_HOLD_BASE;
+ unsigned int pos = plat_my_core_pos();
+
+ if (pos == 0) {
+ /*
+ * The secondaries will always be in a wait
+ * for warm boot on reset, but the BSP needs
+ * to be able to distinguish between waiting
+ * for warm boot (e.g. after psci_off, waiting
+ * for psci_on) and a cold boot.
+ */
+ mmio_write_64(hold_base, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF);
+ /* No cache maintenance here, we run with caches off already. */
+ dsb();
+ isb();
+ }
+
+ write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT);
+
+ while (1) {
+ wfi();
+ }
+}
+
+/*******************************************************************************
+ * Platform handlers for system reset and system off.
+ ******************************************************************************/
+
+/* 10 ticks (Watchdog timer = Timer clock / 16) */
+#define RESET_TIMEOUT U(10)
+
+static void __dead2 rpi3_watchdog_reset(void)
+{
+ uint32_t rstc;
+
+ console_flush();
+
+ dsbsy();
+ isb();
+
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_WDOG_OFFSET,
+ RPI3_PM_PASSWORD | RESET_TIMEOUT);
+
+ rstc = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET);
+ rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
+ rstc |= RPI3_PM_PASSWORD | RPI3_PM_RSTC_WRCFG_FULL_RESET;
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET, rstc);
+
+ for (;;) {
+ wfi();
+ }
+}
+
+static void __dead2 rpi3_system_reset(void)
+{
+ INFO("rpi3: PSCI_SYSTEM_RESET: Invoking watchdog reset\n");
+
+ rpi3_watchdog_reset();
+}
+
+static void __dead2 rpi3_system_off(void)
+{
+ uint32_t rsts;
+
+ INFO("rpi3: PSCI_SYSTEM_OFF: Invoking watchdog reset\n");
+
+ /*
+ * This function doesn't actually make the Raspberry Pi turn itself off,
+ * the hardware doesn't allow it. It simply reboots it and the RSTS
+ * value tells the bootcode.bin firmware not to continue the regular
+ * bootflow and to stay in a low power mode.
+ */
+
+ rsts = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET);
+ rsts |= RPI3_PM_PASSWORD | RPI3_PM_RSTS_WRCFG_HALT;
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET, rsts);
+
+ rpi3_watchdog_reset();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t plat_rpi3_psci_pm_ops = {
+ .cpu_standby = rpi3_cpu_standby,
+ .pwr_domain_off = rpi3_pwr_domain_off,
+ .pwr_domain_on = rpi3_pwr_domain_on,
+ .pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
+ .pwr_domain_pwr_down_wfi = rpi3_pwr_down_wfi,
+ .system_off = rpi3_system_off,
+ .system_reset = rpi3_system_reset,
+ .validate_power_state = rpi3_validate_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ uintptr_t *entrypoint = (void *) PLAT_RPI3_TM_ENTRYPOINT;
+
+ *entrypoint = sec_entrypoint;
+ *psci_ops = &plat_rpi3_psci_pm_ops;
+
+ return 0;
+}
diff --git a/plat/rpi/common/rpi3_rotpk.S b/plat/rpi/common/rpi3_rotpk.S
new file mode 100644
index 0000000..1c17b21
--- /dev/null
+++ b/plat/rpi/common/rpi3_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global rpi3_rotpk_hash
+ .global rpi3_rotpk_hash_end
+rpi3_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+rpi3_rotpk_hash_end:
diff --git a/plat/rpi/common/rpi3_stack_protector.c b/plat/rpi/common/rpi3_stack_protector.c
new file mode 100644
index 0000000..aae5fac
--- /dev/null
+++ b/plat/rpi/common/rpi3_stack_protector.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#include <drivers/rpi3/rng/rpi3_rng.h>
+
+/* Get 128 bits of entropy and fuse the values together to form the canary. */
+#define TRNG_NBYTES 16U
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ size_t i;
+ u_register_t buf[TRNG_NBYTES / sizeof(u_register_t)];
+ u_register_t ret = 0U;
+
+ rpi3_rng_read(buf, sizeof(buf));
+
+ for (i = 0U; i < ARRAY_SIZE(buf); i++)
+ ret ^= buf[i];
+
+ return ret;
+}
diff --git a/plat/rpi/common/rpi3_topology.c b/plat/rpi/common/rpi3_topology.c
new file mode 100644
index 0000000..3747287
--- /dev/null
+++ b/plat/rpi/common/rpi3_topology.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+
+#include <rpi_shared.h>
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the ARM default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+ if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
+ return -1;
+ }
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+ return -1;
+ }
+
+ return plat_rpi3_calc_core_pos(mpidr);
+}
diff --git a/plat/rpi/common/rpi3_trusted_boot.c b/plat/rpi/common/rpi3_trusted_boot.c
new file mode 100644
index 0000000..f6c669f
--- /dev/null
+++ b/plat/rpi/common/rpi3_trusted_boot.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char rpi3_rotpk_hash[], rpi3_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = rpi3_rotpk_hash;
+ *key_len = rpi3_rotpk_hash_end - rpi3_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
new file mode 100644
index 0000000..715aec4
--- /dev/null
+++ b/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+
+ /* Fill BL31 related information */
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+#if DEBUG
+ .ep_info.args.arg1 = RPI3_BL31_PLAT_PARAM_VAL,
+#endif
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+# ifdef BL32_BASE
+ .next_handoff_image_id = BL32_IMAGE_ID,
+# else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
+ },
+
+# ifdef BL32_BASE
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 1 related information.
+ * A typical use for extra1 image is with OP-TEE where it is the pager
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /*
+ * Fill BL32 external 2 related information.
+ * A typical use for extra2 image is with OP-TEE where it is the paged
+ * image.
+ */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+ .image_info.image_base = RPI3_OPTEE_PAGEABLE_LOAD_BASE,
+ .image_info.image_max_size = RPI3_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+# endif /* BL32_BASE */
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+# ifdef PRELOADED_BL33_BASE
+ .ep_info.pc = PRELOADED_BL33_BASE,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+# else
+ .ep_info.pc = PLAT_RPI3_NS_IMAGE_OFFSET,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_RPI3_NS_IMAGE_OFFSET,
+ .image_info.image_max_size = PLAT_RPI3_NS_IMAGE_MAX_SIZE,
+# endif /* PRELOADED_BL33_BASE */
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/rpi/rpi3/include/plat_macros.S b/plat/rpi/rpi3/include/plat_macros.S
new file mode 100644
index 0000000..c0c3967
--- /dev/null
+++ b/plat/rpi/rpi3/include/plat_macros.S
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/rpi/rpi3/include/platform_def.h b/plat/rpi/rpi3/include/platform_def.h
new file mode 100644
index 0000000..f44d1f5
--- /dev/null
+++ b/plat/rpi/rpi3/include/platform_def.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "rpi_hw.h"
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE ULL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define RPI_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", and
+ * secure DRAM. Note that this is all actually DRAM with different names,
+ * there is no Secure RAM in the Raspberry Pi 3.
+ */
+#if RPI3_USE_UEFI_MAP
+#define SEC_ROM_BASE ULL(0x00000000)
+#define SEC_ROM_SIZE ULL(0x00010000)
+
+/* FIP placed after ROM to append it to BL1 with very little padding. */
+#define PLAT_RPI3_FIP_BASE ULL(0x00020000)
+#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x00010000)
+
+/* Reserve 2M of secure SRAM and DRAM, starting at 2M */
+#define SEC_SRAM_BASE ULL(0x00200000)
+#define SEC_SRAM_SIZE ULL(0x00100000)
+
+#define SEC_DRAM0_BASE ULL(0x00300000)
+#define SEC_DRAM0_SIZE ULL(0x00100000)
+
+/* Windows on ARM requires some RAM at 4M */
+#define NS_DRAM0_BASE ULL(0x00400000)
+#define NS_DRAM0_SIZE ULL(0x00C00000)
+#else
+#define SEC_ROM_BASE ULL(0x00000000)
+#define SEC_ROM_SIZE ULL(0x00020000)
+
+/* FIP placed after ROM to append it to BL1 with very little padding. */
+#define PLAT_RPI3_FIP_BASE ULL(0x00020000)
+#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001E0000)
+
+/* We have 16M of memory reserved starting at 256M */
+#define SEC_SRAM_BASE ULL(0x10000000)
+#define SEC_SRAM_SIZE ULL(0x00100000)
+
+#define SEC_DRAM0_BASE ULL(0x10100000)
+#define SEC_DRAM0_SIZE ULL(0x00F00000)
+/* End of reserved memory */
+
+#define NS_DRAM0_BASE ULL(0x11000000)
+#define NS_DRAM0_SIZE ULL(0x01000000)
+#endif /* RPI3_USE_UEFI_MAP */
+
+/*
+ * BL33 entrypoint.
+ */
+#define PLAT_RPI3_NS_IMAGE_OFFSET NS_DRAM0_BASE
+#define PLAT_RPI3_NS_IMAGE_MAX_SIZE NS_DRAM0_SIZE
+
+/*
+ * I/O registers.
+ */
+#define DEVICE0_BASE RPI_IO_BASE
+#define DEVICE0_SIZE RPI_IO_SIZE
+
+/*
+ * Arm TF lives in SRAM, partition it here
+ */
+#define SHARED_RAM_BASE SEC_SRAM_BASE
+#define SHARED_RAM_SIZE ULL(0x00001000)
+
+#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE)
+#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE)
+
+/*
+ * Mailbox to control the secondary cores.All secondary cores are held in a wait
+ * loop in cold boot. To release them perform the following steps (plus any
+ * additional barriers that may be needed):
+ *
+ * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT;
+ * *entrypoint = ADDRESS_TO_JUMP_TO;
+ *
+ * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+ * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO;
+ *
+ * sev();
+ */
+#define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE
+
+/* The secure entry point to be used on warm reset by all CPUs. */
+#define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE
+#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8)
+
+/* Hold entries for each CPU. */
+#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \
+ PLAT_RPI3_TM_ENTRYPOINT_SIZE)
+#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8)
+#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \
+ PLAT_RPI3_TM_HOLD_SIZE)
+
+#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0)
+#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1)
+#define PLAT_RPI3_TM_HOLD_STATE_BSP_OFF ULL(2)
+
+/*
+ * BL1 specific defines.
+ *
+ * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
+ * addresses.
+ *
+ * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using
+ * the current BL1 RW debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL1_RW_SIZE ULL(0x12000)
+
+#define BL1_RO_BASE SEC_ROM_BASE
+#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
+#define BL1_RW_BASE (BL1_RW_LIMIT - PLAT_MAX_BL1_RW_SIZE)
+#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+
+/*
+ * BL2 specific defines.
+ *
+ * Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define PLAT_MAX_BL2_SIZE ULL(0x2C000)
+
+#define BL2_BASE (BL2_LIMIT - PLAT_MAX_BL2_SIZE)
+#define BL2_LIMIT BL31_BASE
+
+/*
+ * BL31 specific defines.
+ *
+ * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL31_SIZE ULL(0x20000)
+
+#define BL31_BASE (BL31_LIMIT - PLAT_MAX_BL31_SIZE)
+#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
+#define BL31_PROGBITS_LIMIT BL1_RW_BASE
+
+/*
+ * BL32 specific defines.
+ *
+ * BL32 can execute from Secure SRAM or Secure DRAM.
+ */
+#define BL32_SRAM_BASE BL_RAM_BASE
+#define BL32_SRAM_LIMIT BL31_BASE
+#define BL32_DRAM_BASE SEC_DRAM0_BASE
+#define BL32_DRAM_LIMIT (SEC_DRAM0_BASE + SEC_DRAM0_SIZE)
+
+#ifdef SPD_opteed
+/* Load pageable part of OP-TEE at end of allocated DRAM space for BL32 */
+#define RPI3_OPTEE_PAGEABLE_LOAD_SIZE 0x080000 /* 512KB */
+#define RPI3_OPTEE_PAGEABLE_LOAD_BASE (BL32_DRAM_LIMIT - \
+ RPI3_OPTEE_PAGEABLE_LOAD_SIZE)
+#endif
+
+#define SEC_SRAM_ID 0
+#define SEC_DRAM_ID 1
+
+#if RPI3_BL32_RAM_LOCATION_ID == SEC_SRAM_ID
+# define BL32_MEM_BASE BL_RAM_BASE
+# define BL32_MEM_SIZE BL_RAM_SIZE
+# define BL32_BASE BL32_SRAM_BASE
+# define BL32_LIMIT BL32_SRAM_LIMIT
+#elif RPI3_BL32_RAM_LOCATION_ID == SEC_DRAM_ID
+# define BL32_MEM_BASE SEC_DRAM0_BASE
+# define BL32_MEM_SIZE SEC_DRAM0_SIZE
+# define BL32_BASE BL32_DRAM_BASE
+# define BL32_LIMIT BL32_DRAM_LIMIT
+#else
+# error "Unsupported RPI3_BL32_RAM_LOCATION_ID value"
+#endif
+#define BL32_SIZE (BL32_LIMIT - BL32_BASE)
+
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
+
+/*
+ * Other memory-related defines.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 4
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+#define MAX_IO_BLOCK_DEVICES U(1)
+
+/*
+ * Serial-related constants.
+ */
+#define PLAT_RPI_MINI_UART_BASE RPI3_MINI_UART_BASE
+#define PLAT_RPI_PL011_UART_BASE RPI3_PL011_UART_BASE
+#define PLAT_RPI_PL011_UART_CLOCK RPI3_PL011_UART_CLOCK
+#define PLAT_RPI_UART_BAUDRATE ULL(115200)
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS ULL(19200000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rpi/rpi3/include/rpi_hw.h b/plat/rpi/rpi3/include/rpi_hw.h
new file mode 100644
index 0000000..2aecab3
--- /dev/null
+++ b/plat/rpi/rpi3/include/rpi_hw.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPI_HW_H
+#define RPI_HW_H
+
+#include <lib/utils_def.h>
+
+/*
+ * Peripherals
+ */
+
+#define RPI_IO_BASE ULL(0x3F000000)
+#define RPI_IO_SIZE ULL(0x01000000)
+
+/*
+ * ARM <-> VideoCore mailboxes
+ */
+#define RPI3_MBOX_OFFSET ULL(0x0000B880)
+#define RPI3_MBOX_BASE (RPI_IO_BASE + RPI3_MBOX_OFFSET)
+/* VideoCore -> ARM */
+#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
+#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
+#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
+#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
+#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
+/* ARM -> VideoCore */
+#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
+#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
+#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
+#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
+#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
+/* Mailbox status constants */
+#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */
+#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */
+
+/*
+ * Power management, reset controller, watchdog.
+ */
+#define RPI3_IO_PM_OFFSET ULL(0x00100000)
+#define RPI3_PM_BASE (RPI_IO_BASE + RPI3_IO_PM_OFFSET)
+/* Registers on top of RPI3_PM_BASE. */
+#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
+#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
+#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
+/* Watchdog constants */
+#define RPI3_PM_PASSWORD U(0x5A000000)
+#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
+#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
+/*
+ * The RSTS register is used by the VideoCore firmware when booting the
+ * Raspberry Pi to know which partition to boot from. The partition value is
+ * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
+ * to indicate halt.
+ */
+#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
+
+/*
+ * Hardware random number generator.
+ */
+#define RPI3_IO_RNG_OFFSET ULL(0x00104000)
+#define RPI3_RNG_BASE (RPI_IO_BASE + RPI3_IO_RNG_OFFSET)
+#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
+#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
+#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
+#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
+/* Enable/disable RNG */
+#define RPI3_RNG_CTRL_ENABLE U(0x1)
+#define RPI3_RNG_CTRL_DISABLE U(0x0)
+/* Number of currently available words */
+#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
+#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
+/* Value to mask interrupts caused by the RNG */
+#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
+
+/*
+ * Serial ports:
+ * 'Mini UART' in the BCM docucmentation is the 8250 compatible UART.
+ * There is also a PL011 UART, multiplexed to the same pins.
+ */
+#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
+#define RPI3_MINI_UART_BASE (RPI_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
+#define RPI3_IO_PL011_UART_OFFSET ULL(0x00201000)
+#define RPI3_PL011_UART_BASE (RPI_IO_BASE + RPI3_IO_PL011_UART_OFFSET)
+#define RPI3_PL011_UART_CLOCK ULL(48000000)
+
+/*
+ * GPIO controller
+ */
+#define RPI3_IO_GPIO_OFFSET ULL(0x00200000)
+#define RPI3_GPIO_BASE (RPI_IO_BASE + RPI3_IO_GPIO_OFFSET)
+
+/*
+ * SDHost controller
+ */
+#define RPI3_IO_SDHOST_OFFSET ULL(0x00202000)
+#define RPI3_SDHOST_BASE (RPI_IO_BASE + RPI3_IO_SDHOST_OFFSET)
+
+/*
+ * Local interrupt controller
+ */
+#define RPI3_INTC_BASE_ADDRESS ULL(0x40000000)
+/* Registers on top of RPI3_INTC_BASE_ADDRESS */
+#define RPI3_INTC_CONTROL_OFFSET ULL(0x00000000)
+#define RPI3_INTC_PRESCALER_OFFSET ULL(0x00000008)
+#define RPI3_INTC_MBOX_CONTROL_OFFSET ULL(0x00000050)
+#define RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ ULL(0x00000080)
+#define RPI3_INTC_PENDING_FIQ_OFFSET ULL(0x00000070)
+#define RPI3_INTC_PENDING_FIQ_MBOX3 ULL(0x00000080)
+
+#endif /* RPI_HW_H */
diff --git a/plat/rpi/rpi3/platform.mk b/plat/rpi/rpi3/platform.mk
new file mode 100644
index 0000000..53c97e2
--- /dev/null
+++ b/plat/rpi/rpi3/platform.mk
@@ -0,0 +1,221 @@
+#
+# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/libfdt/libfdt.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Iplat/rpi/common/include \
+ -Iplat/rpi/rpi3/include
+
+PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \
+ drivers/arm/pl011/aarch64/pl011_console.S \
+ drivers/gpio/gpio.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/rpi3/gpio/rpi3_gpio.c \
+ plat/rpi/common/aarch64/plat_helpers.S \
+ plat/rpi/common/rpi3_common.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+BL1_SOURCES += drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/aarch64/platform_mp_stack.S \
+ plat/rpi/rpi3/rpi3_bl1_setup.c \
+ plat/rpi/common/rpi3_io_storage.c \
+ drivers/rpi3/mailbox/rpi3_mbox.c \
+ plat/rpi/rpi3/rpi_mbox_board.c
+
+BL2_SOURCES += common/desc_image_load.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/io/io_block.c \
+ drivers/mmc/mmc.c \
+ drivers/rpi3/sdhost/rpi3_sdhost.c \
+ plat/common/aarch64/platform_mp_stack.S \
+ plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \
+ plat/rpi/rpi3/rpi3_bl2_setup.c \
+ plat/rpi/common/rpi3_image_load.c \
+ plat/rpi/common/rpi3_io_storage.c
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ plat/rpi/rpi3/rpi3_bl31_setup.c \
+ plat/rpi/common/rpi3_pm.c \
+ plat/rpi/common/rpi3_topology.c \
+ ${LIBFDT_SRCS}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a53
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a53
+endif
+
+# Platform Makefile target
+# ------------------------
+
+RPI3_BL1_PAD_BIN := ${BUILD_PLAT}/bl1_pad.bin
+RPI3_ARMSTUB8_BIN := ${BUILD_PLAT}/armstub8.bin
+
+# Add new default target when compiling this platform
+all: armstub
+
+# This target concatenates BL1 and the FIP so that the base addresses match the
+# ones defined in the memory map
+armstub: bl1 fip
+ @echo " CAT $@"
+ ${Q}cp ${BUILD_PLAT}/bl1.bin ${RPI3_BL1_PAD_BIN}
+ ${Q}truncate --size=131072 ${RPI3_BL1_PAD_BIN}
+ ${Q}cat ${RPI3_BL1_PAD_BIN} ${BUILD_PLAT}/fip.bin > ${RPI3_ARMSTUB8_BIN}
+ @${ECHO_BLANK_LINE}
+ @echo "Built $@ successfully"
+ @${ECHO_BLANK_LINE}
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_826319 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+WORKAROUND_CVE_2017_5715 := 0
+
+# Disable stack protector by default
+ENABLE_STACK_PROTECTOR := 0
+
+# Reset to BL31 isn't supported
+RESET_TO_BL31 := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Platform build flags
+# --------------------
+
+# BL33 images are in AArch64 by default
+RPI3_BL33_IN_AARCH32 := 0
+
+# Assume that BL33 isn't the Linux kernel by default
+RPI3_DIRECT_LINUX_BOOT := 0
+
+# UART to use at runtime. -1 means the runtime UART is disabled.
+# Any other value means the default UART will be used.
+RPI3_RUNTIME_UART := -1
+
+# Use normal memory mapping for ROM, FIP, SRAM and DRAM
+RPI3_USE_UEFI_MAP := 0
+
+# BL32 location
+RPI3_BL32_RAM_LOCATION := tdram
+ifeq (${RPI3_BL32_RAM_LOCATION}, tsram)
+ RPI3_BL32_RAM_LOCATION_ID = SEC_SRAM_ID
+else ifeq (${RPI3_BL32_RAM_LOCATION}, tdram)
+ RPI3_BL32_RAM_LOCATION_ID = SEC_DRAM_ID
+else
+ $(error "Unsupported RPI3_BL32_RAM_LOCATION value")
+endif
+
+# Process platform flags
+# ----------------------
+
+$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID))
+$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
+$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT))
+ifdef RPI3_PRELOADED_DTB_BASE
+$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE))
+endif
+$(eval $(call add_define,RPI3_RUNTIME_UART))
+$(eval $(call add_define,RPI3_USE_UEFI_MAP))
+
+# Verify build config
+# -------------------
+#
+ifneq (${RPI3_DIRECT_LINUX_BOOT}, 0)
+ ifndef RPI3_PRELOADED_DTB_BASE
+ $(error Error: RPI3_PRELOADED_DTB_BASE needed if RPI3_DIRECT_LINUX_BOOT=1)
+ endif
+endif
+
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: rpi3 needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on rpi3)
+endif
+
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+PLAT_BL_COMMON_SOURCES += drivers/rpi3/rng/rpi3_rng.c \
+ plat/rpi/common/rpi3_stack_protector.c
+endif
+
+ifeq (${SPD},opteed)
+BL2_SOURCES += \
+ lib/optee/optee_utils.c
+endif
+
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+ include drivers/auth/mbedtls/mbedtls_crypto.mk
+ include drivers/auth/mbedtls/mbedtls_x509.mk
+
+ AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c
+
+ BL1_SOURCES += ${AUTH_SOURCES} \
+ bl1/tbbr/tbbr_img_desc.c \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/rpi/common/rpi3_trusted_boot.c \
+ plat/rpi/common/rpi3_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl1.c
+
+ BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/rpi/common/rpi3_trusted_boot.c \
+ plat/rpi/common/rpi3_rotpk.S \
+ drivers/auth/tbbr/tbbr_cot_bl2.c
+
+ ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+ $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+
+ $(BUILD_PLAT)/bl1/rpi3_rotpk.o: $(ROTPK_HASH)
+ $(BUILD_PLAT)/bl2/rpi3_rotpk.o: $(ROTPK_HASH)
+
+ certificates: $(ROT_KEY)
+
+ $(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
+
+ $(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
diff --git a/plat/rpi/rpi3/rpi3_bl1_setup.c b/plat/rpi/rpi3/rpi3_bl1_setup.c
new file mode 100644
index 0000000..3ac30e0
--- /dev/null
+++ b/plat/rpi/rpi3/rpi3_bl1_setup.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+#include <rpi_shared.h>
+
+/* Data structure which holds the extents of the trusted SRAM for BL1 */
+static meminfo_t bl1_tzram_layout;
+
+meminfo_t *bl1_plat_sec_mem_layout(void)
+{
+ return &bl1_tzram_layout;
+}
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+ /* use the 19.2 MHz clock for the architected timer */
+ mmio_write_32(RPI3_INTC_BASE_ADDRESS + RPI3_INTC_CONTROL_OFFSET, 0);
+ mmio_write_32(RPI3_INTC_BASE_ADDRESS + RPI3_INTC_PRESCALER_OFFSET,
+ 0x80000000);
+
+ /* Initialize the console to provide early debug support */
+ rpi3_console_init();
+
+ /* Allow BL1 to see the whole Trusted RAM */
+ bl1_tzram_layout.total_base = BL_RAM_BASE;
+ bl1_tzram_layout.total_size = BL_RAM_SIZE;
+}
+
+/******************************************************************************
+ * Perform the very early platform specific architecture setup. This only
+ * does basic initialization. Later architectural setup (bl1_arch_setup())
+ * does not do anything platform specific.
+ *****************************************************************************/
+void bl1_plat_arch_setup(void)
+{
+ rpi3_setup_page_tables(bl1_tzram_layout.total_base,
+ bl1_tzram_layout.total_size,
+ BL_CODE_BASE, BL1_CODE_END,
+ BL1_RO_DATA_BASE, BL1_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el3(0);
+}
+
+void bl1_platform_setup(void)
+{
+ uint32_t __unused rev;
+ int __unused rc;
+
+ rc = rpi3_vc_hardware_get_board_revision(&rev);
+
+ if (rc == 0) {
+ const char __unused *model, __unused *info;
+
+ switch (rev) {
+ case 0xA02082:
+ model = "Raspberry Pi 3 Model B";
+ info = "(1GB, Sony, UK)";
+ break;
+ case 0xA22082:
+ model = "Raspberry Pi 3 Model B";
+ info = "(1GB, Embest, China)";
+ break;
+ case 0xA020D3:
+ model = "Raspberry Pi 3 Model B+";
+ info = "(1GB, Sony, UK)";
+ break;
+ default:
+ model = "Unknown";
+ info = "(Unknown)";
+ ERROR("rpi3: Unknown board revision 0x%08x\n", rev);
+ break;
+ }
+
+ NOTICE("rpi3: Detected: %s %s [0x%08x]\n", model, info, rev);
+ } else {
+ ERROR("rpi3: Unable to detect board revision\n");
+ }
+
+ /* Initialise the IO layer and register platform IO devices */
+ plat_rpi3_io_setup();
+}
diff --git a/plat/rpi/rpi3/rpi3_bl2_setup.c b/plat/rpi/rpi3/rpi3_bl2_setup.c
new file mode 100644
index 0000000..db71817
--- /dev/null
+++ b/plat/rpi/rpi3/rpi3_bl2_setup.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <lib/optee_utils.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/rpi3/gpio/rpi3_gpio.h>
+#include <drivers/rpi3/sdhost/rpi3_sdhost.h>
+
+#include <rpi_shared.h>
+
+/* Data structure which holds the extents of the trusted SRAM for BL2 */
+static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
+
+/* Data structure which holds the MMC info */
+static struct mmc_device_info mmc_info;
+
+static void rpi3_sdhost_setup(void)
+{
+ struct rpi3_sdhost_params params;
+
+ memset(&params, 0, sizeof(struct rpi3_sdhost_params));
+ params.reg_base = RPI3_SDHOST_BASE;
+ params.bus_width = MMC_BUS_WIDTH_1;
+ params.clk_rate = 50000000;
+ mmc_info.mmc_dev_type = MMC_IS_SD_HC;
+ rpi3_sdhost_init(&params, &mmc_info);
+}
+
+/*******************************************************************************
+ * BL1 has passed the extents of the trusted SRAM that should be visible to BL2
+ * in x0. This memory layout is sitting at the base of the free trusted SRAM.
+ * Copy it to a safe location before its reclaimed by later BL2 functionality.
+ ******************************************************************************/
+
+void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ meminfo_t *mem_layout = (meminfo_t *) arg1;
+
+ /* Initialize the console to provide early debug support */
+ rpi3_console_init();
+
+ /* Enable arch timer */
+ generic_delay_timer_init();
+
+ /* Setup GPIO driver */
+ rpi3_gpio_init();
+
+ /* Setup the BL2 memory layout */
+ bl2_tzram_layout = *mem_layout;
+
+ /* Setup SDHost driver */
+ rpi3_sdhost_setup();
+
+ plat_rpi3_io_setup();
+}
+
+void bl2_platform_setup(void)
+{
+ /*
+ * This is where a TrustZone address space controller and other
+ * security related peripherals would be configured.
+ */
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here.
+ ******************************************************************************/
+void bl2_plat_arch_setup(void)
+{
+ rpi3_setup_page_tables(bl2_tzram_layout.total_base,
+ bl2_tzram_layout.total_size,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el1(0);
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+#ifdef SPD_opteed
+ bl_mem_params_node_t *pager_mem_params = NULL;
+ bl_mem_params_node_t *paged_mem_params = NULL;
+#endif
+
+ assert(bl_mem_params != NULL);
+
+ switch (image_id) {
+ case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ assert(paged_mem_params);
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ &paged_mem_params->image_info);
+ if (err != 0)
+ WARN("OPTEE header parse error.\n");
+#endif
+ bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
+ break;
+
+ case BL33_IMAGE_ID:
+ /* BL33 expects to receive the primary CPU MPID (through r0) */
+ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
+ bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
+
+ /* Shutting down the SDHost driver to let BL33 drives SDHost.*/
+ rpi3_sdhost_stop();
+ break;
+
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
+}
diff --git a/plat/rpi/rpi3/rpi3_bl31_setup.c b/plat/rpi/rpi3/rpi3_bl31_setup.c
new file mode 100644
index 0000000..5915753
--- /dev/null
+++ b/plat/rpi/rpi3/rpi3_bl31_setup.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/common/platform.h>
+
+#include <rpi_shared.h>
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type) != 0);
+
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+/*******************************************************************************
+ * Return entrypoint of BL33.
+ ******************************************************************************/
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ return PLAT_RPI3_NS_IMAGE_OFFSET;
+#endif
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+
+{
+ /* Initialize the console to provide early debug support */
+ rpi3_console_init();
+
+ /*
+ * In debug builds, a special value is passed in 'arg1' to verify
+ * platform parameters from BL2 to BL31. Not used in release builds.
+ */
+ assert(arg1 == RPI3_BL31_PLAT_PARAM_VAL);
+
+ /* Check that params passed from BL2 are not NULL. */
+ bl_params_t *params_from_bl2 = (bl_params_t *) arg0;
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 and BL32 (if present), entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID) {
+ bl32_image_ep_info = *bl_params->ep_info;
+ }
+
+ if (bl_params->image_id == BL33_IMAGE_ID) {
+ bl33_image_ep_info = *bl_params->ep_info;
+ }
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0) {
+ panic();
+ }
+
+#if RPI3_DIRECT_LINUX_BOOT
+# if RPI3_BL33_IN_AARCH32
+ /*
+ * According to the file ``Documentation/arm/Booting`` of the Linux
+ * kernel tree, Linux expects:
+ * r0 = 0
+ * r1 = machine type number, optional in DT-only platforms (~0 if so)
+ * r2 = Physical address of the device tree blob
+ */
+ VERBOSE("rpi3: Preparing to boot 32-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = 0U;
+ bl33_image_ep_info.args.arg1 = ~0U;
+ bl33_image_ep_info.args.arg2 = (u_register_t) RPI3_PRELOADED_DTB_BASE;
+# else
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ */
+ VERBOSE("rpi3: Preparing to boot 64-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = (u_register_t) RPI3_PRELOADED_DTB_BASE;
+ bl33_image_ep_info.args.arg1 = 0ULL;
+ bl33_image_ep_info.args.arg2 = 0ULL;
+ bl33_image_ep_info.args.arg3 = 0ULL;
+# endif /* RPI3_BL33_IN_AARCH32 */
+#endif /* RPI3_DIRECT_LINUX_BOOT */
+}
+
+void bl31_plat_arch_setup(void)
+{
+ rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el3(0);
+}
+
+#ifdef RPI3_PRELOADED_DTB_BASE
+/*
+ * Add information to the device tree (if any) about the reserved DRAM used by
+ * the Trusted Firmware.
+ */
+static void rpi3_dtb_add_mem_rsv(void)
+{
+ int i, regions, rc;
+ uint64_t addr, size;
+ void *dtb = (void *)RPI3_PRELOADED_DTB_BASE;
+
+ INFO("rpi3: Checking DTB...\n");
+
+ /* Return if no device tree is detected */
+ if (fdt_check_header(dtb) != 0)
+ return;
+
+ regions = fdt_num_mem_rsv(dtb);
+
+ VERBOSE("rpi3: Found %d mem reserve region(s)\n", regions);
+
+ /* We expect to find one reserved region that we can modify */
+ if (regions < 1)
+ return;
+
+ /*
+ * Look for the region that corresponds to the default boot firmware. It
+ * starts at address 0, and it is not needed when the default firmware
+ * is replaced by this port of the Trusted Firmware.
+ */
+ for (i = 0; i < regions; i++) {
+ if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0)
+ continue;
+
+ if (addr != 0x0)
+ continue;
+
+ VERBOSE("rpi3: Firmware mem reserve region found\n");
+
+ rc = fdt_del_mem_rsv(dtb, i);
+ if (rc != 0) {
+ INFO("rpi3: Can't remove mem reserve region (%d)\n", rc);
+ }
+
+ break;
+ }
+
+ if (i == regions) {
+ VERBOSE("rpi3: Firmware mem reserve region not found\n");
+ }
+
+ /*
+ * Reserve all SRAM. As said in the documentation, this isn't actually
+ * secure memory, so it is needed to tell BL33 that this is a reserved
+ * memory region. It doesn't guarantee it won't use it, though.
+ */
+ rc = fdt_add_mem_rsv(dtb, SEC_SRAM_BASE, SEC_SRAM_SIZE);
+ if (rc != 0) {
+ WARN("rpi3: Can't add mem reserve region (%d)\n", rc);
+ }
+
+ INFO("rpi3: Reserved 0x%llx - 0x%llx in DTB\n", SEC_SRAM_BASE,
+ SEC_SRAM_BASE + SEC_SRAM_SIZE);
+}
+#endif
+
+void bl31_platform_setup(void)
+{
+#ifdef RPI3_PRELOADED_DTB_BASE
+ /* Only modify a DTB if we know where to look for it */
+ rpi3_dtb_add_mem_rsv();
+#endif
+}
diff --git a/plat/rpi/rpi3/rpi_mbox_board.c b/plat/rpi/rpi3/rpi_mbox_board.c
new file mode 100644
index 0000000..e7c1e2b
--- /dev/null
+++ b/plat/rpi/rpi3/rpi_mbox_board.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+
+#include <drivers/rpi3/mailbox/rpi3_mbox.h>
+
+#define RPI3_MBOX_BUFFER_SIZE U(256)
+static uint8_t __aligned(16) rpi3_mbox_buffer[RPI3_MBOX_BUFFER_SIZE];
+
+/*******************************************************************************
+ * Request board revision. Returns the revision and 0 on success, -1 on error.
+ ******************************************************************************/
+int rpi3_vc_hardware_get_board_revision(uint32_t *revision)
+{
+ uint32_t tag_request_size = sizeof(uint32_t);
+ rpi3_mbox_request_t *req = (rpi3_mbox_request_t *) rpi3_mbox_buffer;
+
+ assert(revision != NULL);
+
+ VERBOSE("rpi3: mbox: Sending request at %p\n", (void *)req);
+
+ req->size = sizeof(rpi3_mbox_buffer);
+ req->code = RPI3_MBOX_PROCESS_REQUEST;
+
+ req->tags[0] = RPI3_TAG_HARDWARE_GET_BOARD_REVISION;
+ req->tags[1] = tag_request_size; /* Space available for the response */
+ req->tags[2] = RPI3_TAG_REQUEST;
+ req->tags[3] = 0; /* Placeholder for the response */
+
+ req->tags[4] = RPI3_TAG_END;
+
+ rpi3_vc_mailbox_request_send(req, RPI3_MBOX_BUFFER_SIZE);
+
+ if (req->code != RPI3_MBOX_REQUEST_SUCCESSFUL) {
+ ERROR("rpi3: mbox: Code = 0x%08x\n", req->code);
+ return -1;
+ }
+
+ if (req->tags[2] != (RPI3_TAG_IS_RESPONSE | tag_request_size)) {
+ ERROR("rpi3: mbox: get board revision failed (0x%08x)\n",
+ req->tags[2]);
+ return -1;
+ }
+
+ *revision = req->tags[3];
+
+ return 0;
+}
diff --git a/plat/rpi/rpi4/aarch64/armstub8_header.S b/plat/rpi/rpi4/aarch64/armstub8_header.S
new file mode 100644
index 0000000..246358d
--- /dev/null
+++ b/plat/rpi/rpi4/aarch64/armstub8_header.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * armstub8.bin header to let the GPU firmware recognise this code.
+ * It will then write the load address of the kernel image and the DT
+ * after the header magic in RAM, so we can read those addresses at runtime.
+ */
+
+.text
+ b armstub8_end
+
+.global stub_magic
+.global dtb_ptr32
+.global kernel_entry32
+
+.org 0xf0
+armstub8:
+stub_magic:
+ .word 0x5afe570b
+stub_version:
+ .word 0
+dtb_ptr32:
+ .word 0x0
+kernel_entry32:
+ .word 0x0
+
+/*
+ * Technically an offset of 0x100 would suffice, but the follow-up code
+ * (bl31_entrypoint.S at BL31_BASE) needs to be page aligned, so pad here
+ * till the end of the first 4K page.
+ */
+.org 0x1000
+armstub8_end:
diff --git a/plat/rpi/rpi4/include/plat.ld.S b/plat/rpi/rpi4/include/plat.ld.S
new file mode 100644
index 0000000..9262fad
--- /dev/null
+++ b/plat/rpi/rpi4/include/plat.ld.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Stub linker script to provide the armstub8.bin header before the actual
+ * code. If the GPU firmware finds a magic value at offset 240 in
+ * armstub8.bin, it will put the DTB and kernel load address in subsequent
+ * words. We can then read those values to find the proper NS entry point
+ * and find our DTB more flexibly.
+ */
+
+MEMORY {
+ PRERAM (rwx): ORIGIN = 0, LENGTH = 4096
+}
+
+SECTIONS
+{
+ .armstub8 . : {
+ *armstub8_header.o(.text*)
+ KEEP(*(.armstub8))
+ } >PRERAM
+}
diff --git a/plat/rpi/rpi4/include/plat_macros.S b/plat/rpi/rpi4/include/plat_macros.S
new file mode 100644
index 0000000..6007d03
--- /dev/null
+++ b/plat/rpi/rpi4/include/plat_macros.S
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/rpi/rpi4/include/platform_def.h b/plat/rpi/rpi4/include/platform_def.h
new file mode 100644
index 0000000..6787ebf
--- /dev/null
+++ b/plat/rpi/rpi4/include/platform_def.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "rpi_hw.h"
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE ULL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define RPI_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * I/O registers.
+ */
+#define DEVICE0_BASE RPI_IO_BASE
+#define DEVICE0_SIZE RPI_IO_SIZE
+
+/*
+ * Mailbox to control the secondary cores. All secondary cores are held in a
+ * wait loop in cold boot. To release them perform the following steps (plus
+ * any additional barriers that may be needed):
+ *
+ * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT;
+ * *entrypoint = ADDRESS_TO_JUMP_TO;
+ *
+ * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+ * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO;
+ *
+ * sev();
+ */
+/* The secure entry point to be used on warm reset by all CPUs. */
+#define PLAT_RPI3_TM_ENTRYPOINT 0x100
+#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8)
+
+/* Hold entries for each CPU. */
+#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \
+ PLAT_RPI3_TM_ENTRYPOINT_SIZE)
+#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8)
+#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \
+ PLAT_RPI3_TM_HOLD_SIZE)
+
+#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0)
+#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1)
+#define PLAT_RPI3_TM_HOLD_STATE_BSP_OFF ULL(2)
+
+/*
+ * BL31 specific defines.
+ *
+ * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL31_SIZE ULL(0x80000)
+
+#define BL31_BASE ULL(0x1000)
+#define BL31_LIMIT ULL(0x80000)
+#define BL31_PROGBITS_LIMIT ULL(0x80000)
+
+#define SEC_SRAM_ID 0
+#define SEC_DRAM_ID 1
+
+/*
+ * Other memory-related defines.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 4
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+#define MAX_IO_BLOCK_DEVICES U(1)
+
+/*
+ * Serial-related constants.
+ */
+#define PLAT_RPI_MINI_UART_BASE RPI4_MINI_UART_BASE
+#define PLAT_RPI_PL011_UART_BASE RPI4_PL011_UART_BASE
+#define PLAT_RPI_PL011_UART_CLOCK RPI4_PL011_UART_CLOCK
+#define PLAT_RPI_UART_BAUDRATE ULL(115200)
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS ULL(54000000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rpi/rpi4/include/rpi_hw.h b/plat/rpi/rpi4/include/rpi_hw.h
new file mode 100644
index 0000000..0430d46
--- /dev/null
+++ b/plat/rpi/rpi4/include/rpi_hw.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPI_HW_H
+#define RPI_HW_H
+
+#include <lib/utils_def.h>
+
+/*
+ * Peripherals
+ */
+
+#define RPI_IO_BASE ULL(0xFC000000)
+#define RPI_IO_SIZE ULL(0x04000000)
+
+#define RPI_LEGACY_BASE (ULL(0x02000000) + RPI_IO_BASE)
+
+/*
+ * ARM <-> VideoCore mailboxes
+ */
+#define RPI3_MBOX_OFFSET ULL(0x0000B880)
+#define RPI3_MBOX_BASE (RPI_LEGACY_BASE + RPI3_MBOX_OFFSET)
+/* VideoCore -> ARM */
+#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
+#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
+#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
+#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
+#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
+/* ARM -> VideoCore */
+#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
+#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
+#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
+#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
+#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
+/* Mailbox status constants */
+#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */
+#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */
+
+/*
+ * Power management, reset controller, watchdog.
+ */
+#define RPI3_IO_PM_OFFSET ULL(0x00100000)
+#define RPI3_PM_BASE (RPI_LEGACY_BASE + RPI3_IO_PM_OFFSET)
+/* Registers on top of RPI3_PM_BASE. */
+#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
+#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
+#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
+/* Watchdog constants */
+#define RPI3_PM_PASSWORD U(0x5A000000)
+#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
+#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
+/*
+ * The RSTS register is used by the VideoCore firmware when booting the
+ * Raspberry Pi to know which partition to boot from. The partition value is
+ * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
+ * to indicate halt.
+ */
+#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
+
+/*
+ * Hardware random number generator.
+ */
+#define RPI3_IO_RNG_OFFSET ULL(0x00104000)
+#define RPI3_RNG_BASE (RPI_LEGACY_BASE + RPI3_IO_RNG_OFFSET)
+#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
+#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
+#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
+#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
+/* Enable/disable RNG */
+#define RPI3_RNG_CTRL_ENABLE U(0x1)
+#define RPI3_RNG_CTRL_DISABLE U(0x0)
+/* Number of currently available words */
+#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
+#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
+/* Value to mask interrupts caused by the RNG */
+#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
+
+/*
+ * Serial ports:
+ * 'Mini UART' in the BCM docucmentation is the 8250 compatible UART.
+ * There is also a PL011 UART, multiplexed to the same pins.
+ */
+#define RPI4_IO_MINI_UART_OFFSET ULL(0x00215040)
+#define RPI4_MINI_UART_BASE (RPI_LEGACY_BASE + RPI4_IO_MINI_UART_OFFSET)
+#define RPI4_IO_PL011_UART_OFFSET ULL(0x00201000)
+#define RPI4_PL011_UART_BASE (RPI_LEGACY_BASE + RPI4_IO_PL011_UART_OFFSET)
+#define RPI4_PL011_UART_CLOCK ULL(48000000)
+
+/*
+ * GPIO controller
+ */
+#define RPI3_IO_GPIO_OFFSET ULL(0x00200000)
+#define RPI3_GPIO_BASE (RPI_LEGACY_BASE + RPI3_IO_GPIO_OFFSET)
+
+/*
+ * SDHost controller
+ */
+#define RPI3_IO_SDHOST_OFFSET ULL(0x00202000)
+#define RPI3_SDHOST_BASE (RPI_LEGACY_BASE + RPI3_IO_SDHOST_OFFSET)
+
+/*
+ * GIC interrupt controller
+ */
+#define RPI_HAVE_GIC
+#define RPI4_GIC_GICD_BASE ULL(0xff841000)
+#define RPI4_GIC_GICC_BASE ULL(0xff842000)
+
+#define RPI4_LOCAL_CONTROL_BASE_ADDRESS ULL(0xff800000)
+#define RPI4_LOCAL_CONTROL_PRESCALER ULL(0xff800008)
+
+#endif /* RPI_HW_H */
diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk
new file mode 100644
index 0000000..528eb1d
--- /dev/null
+++ b/plat/rpi/rpi4/platform.mk
@@ -0,0 +1,116 @@
+#
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/libfdt/libfdt.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+include drivers/arm/gic/v2/gicv2.mk
+
+PLAT_INCLUDES := -Iplat/rpi/common/include \
+ -Iplat/rpi/rpi4/include
+
+PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \
+ drivers/arm/pl011/aarch64/pl011_console.S \
+ plat/rpi/common/rpi3_common.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \
+ plat/rpi/common/aarch64/plat_helpers.S \
+ plat/rpi/rpi4/aarch64/armstub8_header.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/gpio/gpio.c \
+ drivers/rpi3/gpio/rpi3_gpio.c \
+ plat/common/plat_gicv2.c \
+ plat/rpi/rpi4/rpi4_bl31_setup.c \
+ plat/rpi/common/rpi3_pm.c \
+ plat/common/plat_psci_common.c \
+ plat/rpi/common/rpi3_topology.c \
+ common/fdt_fixup.c \
+ ${LIBFDT_SRCS} \
+ ${GICV2_SOURCES}
+
+# For now we only support BL31, using the kernel loaded by the GPU firmware.
+RESET_TO_BL31 := 1
+
+# All CPUs enter armstub8.bin.
+COLD_BOOT_SINGLE_CPU := 0
+
+# Tune compiler for Cortex-A72
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a72
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a72
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a72
+endif
+
+# Add support for platform supplied linker script for BL31 build
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+# Enable all errata workarounds for Cortex-A72
+ERRATA_A72_859971 := 1
+
+WORKAROUND_CVE_2017_5715 := 1
+
+# Add new default target when compiling this platform
+all: bl31
+
+# Build config flags
+# ------------------
+
+# Disable stack protector by default
+ENABLE_STACK_PROTECTOR := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Use Coherent memory
+USE_COHERENT_MEM := 1
+
+# Platform build flags
+# --------------------
+
+# There is not much else than a Linux kernel to load at the moment.
+RPI3_DIRECT_LINUX_BOOT := 1
+
+# BL33 images are in AArch64 by default
+RPI3_BL33_IN_AARCH32 := 0
+
+# UART to use at runtime. -1 means the runtime UART is disabled.
+# Any other value means the default UART will be used.
+RPI3_RUNTIME_UART := 0
+
+# Use normal memory mapping for ROM, FIP, SRAM and DRAM
+RPI3_USE_UEFI_MAP := 0
+
+# SMCCC PCI support (should be enabled for ACPI builds)
+SMC_PCI_SUPPORT := 0
+
+# Process platform flags
+# ----------------------
+
+$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
+$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT))
+ifdef RPI3_PRELOADED_DTB_BASE
+$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE))
+endif
+$(eval $(call add_define,RPI3_RUNTIME_UART))
+$(eval $(call add_define,RPI3_USE_UEFI_MAP))
+$(eval $(call add_define,SMC_PCI_SUPPORT))
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on rpi4)
+endif
+
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+PLAT_BL_COMMON_SOURCES += drivers/rpi3/rng/rpi3_rng.c \
+ plat/rpi/common/rpi3_stack_protector.c
+endif
+
+ifeq ($(SMC_PCI_SUPPORT), 1)
+BL31_SOURCES += plat/rpi/rpi4/rpi4_pci_svc.c
+endif
+
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
new file mode 100644
index 0000000..2fb4d3d
--- /dev/null
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+
+#include <drivers/arm/gicv2.h>
+
+#include <rpi_shared.h>
+
+/*
+ * Fields at the beginning of armstub8.bin.
+ * While building the BL31 image, we put the stub magic into the binary.
+ * The GPU firmware detects this at boot time, clears that field as a
+ * confirmation and puts the kernel and DT address in the following words.
+ */
+extern uint32_t stub_magic;
+extern uint32_t dtb_ptr32;
+extern uint32_t kernel_entry32;
+
+static const gicv2_driver_data_t rpi4_gic_data = {
+ .gicd_base = RPI4_GIC_GICD_BASE,
+ .gicc_base = RPI4_GIC_GICC_BASE,
+};
+
+/*
+ * To be filled by the code below. At the moment BL32 is not supported.
+ * In the future these might be passed down from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type) != 0);
+
+ next_image_info = (type == NON_SECURE)
+ ? &bl33_image_ep_info : &bl32_image_ep_info;
+
+ /* None of the images can have 0x0 as the entrypoint. */
+ if (next_image_info->pc) {
+ return next_image_info;
+ } else {
+ return NULL;
+ }
+}
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+ return PRELOADED_BL33_BASE;
+#else
+ /* Cleared by the GPU if kernel address is valid. */
+ if (stub_magic == 0)
+ return kernel_entry32;
+
+ WARN("Stub magic failure, using default kernel address 0x80000\n");
+ return 0x80000;
+#endif
+}
+
+static uintptr_t rpi4_get_dtb_address(void)
+{
+#ifdef RPI3_PRELOADED_DTB_BASE
+ return RPI3_PRELOADED_DTB_BASE;
+#else
+ /* Cleared by the GPU if DTB address is valid. */
+ if (stub_magic == 0)
+ return dtb_ptr32;
+
+ WARN("Stub magic failure, DTB address unknown\n");
+ return 0;
+#endif
+}
+
+static void ldelay(register_t delay)
+{
+ __asm__ volatile (
+ "1:\tcbz %0, 2f\n\t"
+ "sub %0, %0, #1\n\t"
+ "b 1b\n"
+ "2:"
+ : "=&r" (delay) : "0" (delay)
+ );
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+
+{
+ /*
+ * LOCAL_CONTROL:
+ * Bit 9 clear: Increment by 1 (vs. 2).
+ * Bit 8 clear: Timer source is 19.2MHz crystal (vs. APB).
+ */
+ mmio_write_32(RPI4_LOCAL_CONTROL_BASE_ADDRESS, 0);
+
+ /* LOCAL_PRESCALER; divide-by (0x80000000 / register_val) == 1 */
+ mmio_write_32(RPI4_LOCAL_CONTROL_PRESCALER, 0x80000000);
+
+ /* Early GPU firmware revisions need a little break here. */
+ ldelay(100000);
+
+ /* Initialize the console to provide early debug support. */
+ rpi3_console_init();
+
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#if RPI3_DIRECT_LINUX_BOOT
+# if RPI3_BL33_IN_AARCH32
+ /*
+ * According to the file ``Documentation/arm/Booting`` of the Linux
+ * kernel tree, Linux expects:
+ * r0 = 0
+ * r1 = machine type number, optional in DT-only platforms (~0 if so)
+ * r2 = Physical address of the device tree blob
+ */
+ VERBOSE("rpi4: Preparing to boot 32-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = 0U;
+ bl33_image_ep_info.args.arg1 = ~0U;
+ bl33_image_ep_info.args.arg2 = rpi4_get_dtb_address();
+# else
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ */
+ VERBOSE("rpi4: Preparing to boot 64-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = rpi4_get_dtb_address();
+ bl33_image_ep_info.args.arg1 = 0ULL;
+ bl33_image_ep_info.args.arg2 = 0ULL;
+ bl33_image_ep_info.args.arg3 = 0ULL;
+# endif /* RPI3_BL33_IN_AARCH32 */
+#endif /* RPI3_DIRECT_LINUX_BOOT */
+}
+
+void bl31_plat_arch_setup(void)
+{
+ /*
+ * Is the dtb_ptr32 pointer valid? If yes, map the DTB region.
+ * We map the 2MB region the DTB start address lives in, plus
+ * the next 2MB, to have enough room for expansion.
+ */
+ if (stub_magic == 0) {
+ unsigned long long dtb_region = dtb_ptr32;
+
+ dtb_region &= ~0x1fffff; /* Align to 2 MB. */
+ mmap_add_region(dtb_region, dtb_region, 4U << 20,
+ MT_MEMORY | MT_RW | MT_NS);
+ }
+ /*
+ * Add the first page of memory, which holds the stub magic,
+ * the kernel and the DT address.
+ * This also holds the secondary CPU's entrypoints and mailboxes.
+ */
+ mmap_add_region(0, 0, 4096, MT_NON_CACHEABLE | MT_RW | MT_SECURE);
+
+ rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE,
+ BL_CODE_BASE, BL_CODE_END,
+ BL_RO_DATA_BASE, BL_RO_DATA_END
+#if USE_COHERENT_MEM
+ , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
+#endif
+ );
+
+ enable_mmu_el3(0);
+}
+
+/*
+ * Remove the FDT /memreserve/ entry that covers the region at the very
+ * beginning of memory (if that exists). This is where the secondaries
+ * originally spin, but we pull them out there.
+ * Having overlapping /reserved-memory and /memreserve/ regions confuses
+ * the Linux kernel, so we need to get rid of this one.
+ */
+static void remove_spintable_memreserve(void *dtb)
+{
+ uint64_t addr, size;
+ int regions = fdt_num_mem_rsv(dtb);
+ int i;
+
+ for (i = 0; i < regions; i++) {
+ if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) {
+ return;
+ }
+ if (size == 0U) {
+ return;
+ }
+ /* We only look for the region at the beginning of DRAM. */
+ if (addr != 0U) {
+ continue;
+ }
+ /*
+ * Currently the region in the existing DTs is exactly 4K
+ * in size. Should this value ever change, there is probably
+ * a reason for that, so inform the user about this.
+ */
+ if (size == 4096U) {
+ fdt_del_mem_rsv(dtb, i);
+ return;
+ }
+ WARN("Keeping unknown /memreserve/ region at 0, size: %" PRId64 "\n",
+ size);
+ }
+}
+
+static void rpi4_prepare_dtb(void)
+{
+ void *dtb = (void *)rpi4_get_dtb_address();
+ uint32_t gic_int_prop[3];
+ int ret, offs;
+
+ /* Return if no device tree is detected */
+ if (fdt_check_header(dtb) != 0)
+ return;
+
+ ret = fdt_open_into(dtb, dtb, 0x100000);
+ if (ret < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
+ return;
+ }
+
+ if (dt_add_psci_node(dtb)) {
+ ERROR("Failed to add PSCI Device Tree node\n");
+ return;
+ }
+
+ if (dt_add_psci_cpu_enable_methods(dtb)) {
+ ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
+ return;
+ }
+
+ /*
+ * Remove the original reserved region (used for the spintable), and
+ * replace it with a region describing the whole of Trusted Firmware.
+ */
+ remove_spintable_memreserve(dtb);
+ if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000))
+ WARN("Failed to add reserved memory nodes to DT.\n");
+
+ offs = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-400");
+ gic_int_prop[0] = cpu_to_fdt32(1); // PPI
+ gic_int_prop[1] = cpu_to_fdt32(9); // PPI #9
+ gic_int_prop[2] = cpu_to_fdt32(0x0f04); // all cores, level high
+ fdt_setprop(dtb, offs, "interrupts", gic_int_prop, 12);
+
+ offs = fdt_path_offset(dtb, "/chosen");
+ fdt_setprop_string(dtb, offs, "stdout-path", "serial0");
+
+ ret = fdt_pack(dtb);
+ if (ret < 0)
+ ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
+
+ clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
+ INFO("Changed device tree to advertise PSCI.\n");
+}
+
+void bl31_platform_setup(void)
+{
+ rpi4_prepare_dtb();
+
+ /* Configure the interrupt controller */
+ gicv2_driver_init(&rpi4_gic_data);
+ gicv2_distif_init();
+ gicv2_pcpu_distif_init();
+ gicv2_cpuif_enable();
+}
diff --git a/plat/rpi/rpi4/rpi4_pci_svc.c b/plat/rpi/rpi4/rpi4_pci_svc.c
new file mode 100644
index 0000000..7d1ca5c
--- /dev/null
+++ b/plat/rpi/rpi4/rpi4_pci_svc.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * The RPi4 has a single nonstandard PCI config region. It is broken into two
+ * pieces, the root port config registers and a window to a single device's
+ * config space which can move between devices. There isn't (yet) an
+ * authoritative public document on this since the available BCM2711 reference
+ * notes that there is a PCIe root port in the memory map but doesn't describe
+ * it. Given that it's not ECAM compliant yet reasonably simple, it makes for
+ * an excellent example of the PCI SMCCC interface.
+ *
+ * The PCI SMCCC interface is described in DEN0115 availabe from:
+ * https://developer.arm.com/documentation/den0115/latest
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/pmf/pmf.h>
+#include <lib/runtime_instr.h>
+#include <services/pci_svc.h>
+#include <services/sdei.h>
+#include <services/std_svc.h>
+#include <smccc_helpers.h>
+
+#include <lib/mmio.h>
+
+static spinlock_t pci_lock;
+
+#define PCIE_REG_BASE U(RPI_IO_BASE + 0x01500000)
+#define PCIE_MISC_PCIE_STATUS 0x4068
+#define PCIE_EXT_CFG_INDEX 0x9000
+/* A small window pointing at the ECAM of the device selected by CFG_INDEX */
+#define PCIE_EXT_CFG_DATA 0x8000
+#define INVALID_PCI_ADDR 0xFFFFFFFF
+
+#define PCIE_EXT_BUS_SHIFT 20
+#define PCIE_EXT_DEV_SHIFT 15
+#define PCIE_EXT_FUN_SHIFT 12
+
+
+static uint64_t pci_segment_lib_get_base(uint32_t address, uint32_t offset)
+{
+ uint64_t base;
+ uint32_t bus, dev, fun;
+ uint32_t status;
+
+ base = PCIE_REG_BASE;
+
+ offset &= PCI_OFFSET_MASK; /* Pick off the 4k register offset */
+
+ /* The root port is at the base of the PCIe register space */
+ if (address != 0U) {
+ /*
+ * The current device must be at CFG_DATA, a 4K window mapped,
+ * via CFG_INDEX, to the device we are accessing. At the same
+ * time we must avoid accesses to certain areas of the cfg
+ * space via CFG_DATA. Detect those accesses and report that
+ * the address is invalid.
+ */
+ base += PCIE_EXT_CFG_DATA;
+ bus = PCI_ADDR_BUS(address);
+ dev = PCI_ADDR_DEV(address);
+ fun = PCI_ADDR_FUN(address);
+ address = (bus << PCIE_EXT_BUS_SHIFT) |
+ (dev << PCIE_EXT_DEV_SHIFT) |
+ (fun << PCIE_EXT_FUN_SHIFT);
+
+ /* Allow only dev = 0 on root port and bus 1 */
+ if ((bus < 2U) && (dev > 0U)) {
+ return INVALID_PCI_ADDR;
+ }
+
+ /* Assure link up before reading bus 1 */
+ status = mmio_read_32(PCIE_REG_BASE + PCIE_MISC_PCIE_STATUS);
+ if ((status & 0x30) != 0x30) {
+ return INVALID_PCI_ADDR;
+ }
+
+ /* Adjust which device the CFG_DATA window is pointing at */
+ mmio_write_32(PCIE_REG_BASE + PCIE_EXT_CFG_INDEX, address);
+ }
+ return base + offset;
+}
+
+/**
+ * pci_read_config() - Performs a config space read at addr
+ * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
+ * @off: register offset of function described by @addr to read
+ * @sz: size of read (8,16,32) bits.
+ * @val: returned zero extended value read from config space
+ *
+ * sz bits of PCI config space is read at addr:offset, and the value
+ * is returned in val. Invalid segment/offset values return failure.
+ * Reads to valid functions that don't exist return INVALID_PCI_ADDR
+ * as is specified by PCI for requests that aren't completed by EPs.
+ * The boilerplate in pci_svc.c tends to do basic segment, off
+ * and sz validation. This routine should avoid duplicating those
+ * checks.
+ *
+ * This function maps directly to the PCI_READ function in DEN0115
+ * where detailed requirements may be found.
+ *
+ * Return: SMC_PCI_CALL_SUCCESS with val set
+ * SMC_PCI_CALL_INVAL_PARAM, on parameter error
+ */
+uint32_t pci_read_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t *val)
+{
+ uint32_t ret = SMC_PCI_CALL_SUCCESS;
+ uint64_t base;
+
+ spin_lock(&pci_lock);
+ base = pci_segment_lib_get_base(addr, off);
+
+ if (base == INVALID_PCI_ADDR) {
+ *val = base;
+ } else {
+ switch (sz) {
+ case SMC_PCI_SZ_8BIT:
+ *val = mmio_read_8(base);
+ break;
+ case SMC_PCI_SZ_16BIT:
+ *val = mmio_read_16(base);
+ break;
+ case SMC_PCI_SZ_32BIT:
+ *val = mmio_read_32(base);
+ break;
+ default: /* should be unreachable */
+ *val = 0;
+ ret = SMC_PCI_CALL_INVAL_PARAM;
+ }
+ }
+ spin_unlock(&pci_lock);
+ return ret;
+}
+
+/**
+ * pci_write_config() - Performs a config space write at addr
+ * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
+ * @off: register offset of function described by @addr to write
+ * @sz: size of write (8,16,32) bits.
+ * @val: value to be written
+ *
+ * sz bits of PCI config space is written at addr:offset. Invalid
+ * segment/BDF values return failure. Writes to valid functions
+ * without valid EPs are ignored, as is specified by PCI.
+ * The boilerplate in pci_svc.c tends to do basic segment, off
+ * and sz validation, so it shouldn't need to be repeated here.
+ *
+ * This function maps directly to the PCI_WRITE function in DEN0115
+ * where detailed requirements may be found.
+ *
+ * Return: SMC_PCI_CALL_SUCCESS
+ * SMC_PCI_CALL_INVAL_PARAM, on parameter error
+ */
+uint32_t pci_write_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t val)
+{
+ uint32_t ret = SMC_PCI_CALL_SUCCESS;
+ uint64_t base;
+
+ spin_lock(&pci_lock);
+ base = pci_segment_lib_get_base(addr, off);
+
+ if (base != INVALID_PCI_ADDR) {
+ switch (sz) {
+ case SMC_PCI_SZ_8BIT:
+ mmio_write_8(base, val);
+ break;
+ case SMC_PCI_SZ_16BIT:
+ mmio_write_16(base, val);
+ break;
+ case SMC_PCI_SZ_32BIT:
+ mmio_write_32(base, val);
+ break;
+ default: /* should be unreachable */
+ ret = SMC_PCI_CALL_INVAL_PARAM;
+ }
+ }
+ spin_unlock(&pci_lock);
+ return ret;
+}
+
+/**
+ * pci_get_bus_for_seg() - returns the start->end bus range for a segment
+ * @seg: segment being queried
+ * @bus_range: returned bus begin + (end << 8)
+ * @nseg: returns next segment in this machine or 0 for end
+ *
+ * pci_get_bus_for_seg is called to check if a given segment is
+ * valid on this machine. If it is valid, then its bus ranges are
+ * returned along with the next valid segment on the machine. If
+ * this is the last segment, then nseg must be 0.
+ *
+ * This function maps directly to the PCI_GET_SEG_INFO function
+ * in DEN0115 where detailed requirements may be found.
+ *
+ * Return: SMC_PCI_CALL_SUCCESS, and appropriate bus_range and nseg
+ * SMC_PCI_CALL_NOT_IMPL, if the segment is invalid
+ */
+uint32_t pci_get_bus_for_seg(uint32_t seg, uint32_t *bus_range, uint32_t *nseg)
+{
+ uint32_t ret = SMC_PCI_CALL_SUCCESS;
+ *nseg = 0U; /* only a single segment */
+ if (seg == 0U) {
+ *bus_range = 0xFF00; /* start 0, end 255 */
+ } else {
+ *bus_range = 0U;
+ ret = SMC_PCI_CALL_NOT_IMPL;
+ }
+ return ret;
+}
diff --git a/plat/socionext/synquacer/drivers/mhu/sq_mhu.c b/plat/socionext/synquacer/drivers/mhu/sq_mhu.c
new file mode 100644
index 0000000..925ed97
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/mhu/sq_mhu.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include <sq_common.h>
+#include "sq_mhu.h"
+
+/* SCP MHU secure channel registers */
+#define SCP_INTR_S_STAT 0x200
+#define SCP_INTR_S_SET 0x208
+#define SCP_INTR_S_CLEAR 0x210
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT 0x300
+#define CPU_INTR_S_SET 0x308
+#define CPU_INTR_S_CLEAR 0x310
+
+DEFINE_BAKERY_LOCK(sq_lock);
+
+/*
+ * Slot 31 is reserved because the MHU hardware uses this register bit to
+ * indicate a non-secure access attempt. The total number of available slots is
+ * therefore 31 [30:0].
+ */
+#define MHU_MAX_SLOT_ID 30
+
+void mhu_secure_message_start(unsigned int slot_id)
+{
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+
+ bakery_lock_get(&sq_lock);
+
+ /* Make sure any previous command has finished */
+ while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
+ (1 << slot_id))
+ ;
+}
+
+void mhu_secure_message_send(unsigned int slot_id)
+{
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+ assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
+ (1 << slot_id)));
+
+ /* Send command to SCP */
+ mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
+}
+
+uint32_t mhu_secure_message_wait(void)
+{
+ uint32_t response;
+
+ /* Wait for response from SCP */
+ while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT)))
+ ;
+
+ return response;
+}
+
+void mhu_secure_message_end(unsigned int slot_id)
+{
+ assert(slot_id <= MHU_MAX_SLOT_ID);
+
+ /*
+ * Clear any response we got by writing one in the relevant slot bit to
+ * the CLEAR register
+ */
+ mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
+
+ bakery_lock_release(&sq_lock);
+}
+
+void mhu_secure_init(void)
+{
+ bakery_lock_init(&sq_lock);
+
+ /*
+ * The STAT register resets to zero. Ensure it is in the expected state,
+ * as a stale or garbage value would make us think it's a message we've
+ * already sent.
+ */
+ assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0);
+}
+
+void plat_sq_pwrc_setup(void)
+{
+ mhu_secure_init();
+}
diff --git a/plat/socionext/synquacer/drivers/mhu/sq_mhu.h b/plat/socionext/synquacer/drivers/mhu/sq_mhu.h
new file mode 100644
index 0000000..f6b5cc3
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/mhu/sq_mhu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SQ_MHU_H
+#define SQ_MHU_H
+
+#include <stdint.h>
+
+void mhu_secure_message_start(unsigned int slot_id);
+void mhu_secure_message_send(unsigned int slot_id);
+uint32_t mhu_secure_message_wait(void);
+void mhu_secure_message_end(unsigned int slot_id);
+
+void mhu_secure_init(void);
+
+#endif /* SQ_MHU_H */
diff --git a/plat/socionext/synquacer/drivers/scp/sq_scmi.c b/plat/socionext/synquacer/drivers/scp/sq_scmi.c
new file mode 100644
index 0000000..0e99256
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scp/sq_scmi.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/css_scp.h>
+#include <drivers/arm/css/scmi.h>
+#include <plat/arm/css/common/css_pm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include <scmi_sq.h>
+#include <sq_common.h>
+
+/*
+ * This file implements the SCP helper functions using SCMI protocol.
+ */
+
+DEFINE_BAKERY_LOCK(sq_scmi_lock);
+#define SQ_SCMI_LOCK_GET_INSTANCE (&sq_scmi_lock)
+
+#define SQ_SCMI_PAYLOAD_BASE PLAT_SQ_SCP_COM_SHARED_MEM_BASE
+#define MHU_CPU_INTR_S_SET_OFFSET 0x308
+
+const uint32_t sq_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
+};
+
+static scmi_channel_plat_info_t sq_scmi_plat_info = {
+ .scmi_mbx_mem = SQ_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_SQ_MHU_BASE + MHU_CPU_INTR_S_SET_OFFSET,
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhu_ring_doorbell,
+};
+
+/*
+ * SCMI power state parameter bit field encoding for SynQuacer platform.
+ *
+ * 31 20 19 16 15 12 11 8 7 4 3 0
+ * +-------------------------------------------------------------+
+ * | SBZ | Max level | Level 3 | Level 2 | Level 1 | Level 0 |
+ * | | | state | state | state | state |
+ * +-------------------------------------------------------------+
+ *
+ * `Max level` encodes the highest level that has a valid power state
+ * encoded in the power state.
+ */
+#define SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT 16
+#define SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH 4
+#define SCMI_PWR_STATE_MAX_PWR_LVL_MASK \
+ ((1 << SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH) - 1)
+#define SCMI_SET_PWR_STATE_MAX_PWR_LVL(_power_state, _max_level) \
+ (_power_state) |= ((_max_level) & SCMI_PWR_STATE_MAX_PWR_LVL_MASK)\
+ << SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT
+#define SCMI_GET_PWR_STATE_MAX_PWR_LVL(_power_state) \
+ (((_power_state) >> SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT) \
+ & SCMI_PWR_STATE_MAX_PWR_LVL_MASK)
+
+#define SCMI_PWR_STATE_LVL_WIDTH 4
+#define SCMI_PWR_STATE_LVL_MASK \
+ ((1 << SCMI_PWR_STATE_LVL_WIDTH) - 1)
+#define SCMI_SET_PWR_STATE_LVL(_power_state, _level, _level_state) \
+ (_power_state) |= ((_level_state) & SCMI_PWR_STATE_LVL_MASK) \
+ << (SCMI_PWR_STATE_LVL_WIDTH * (_level))
+#define SCMI_GET_PWR_STATE_LVL(_power_state, _level) \
+ (((_power_state) >> (SCMI_PWR_STATE_LVL_WIDTH * (_level))) & \
+ SCMI_PWR_STATE_LVL_MASK)
+
+/*
+ * The SCMI power state enumeration for a power domain level
+ */
+typedef enum {
+ scmi_power_state_off = 0,
+ scmi_power_state_on = 1,
+ scmi_power_state_sleep = 2,
+} scmi_power_state_t;
+
+/*
+ * The global handle for invoking the SCMI driver APIs after the driver
+ * has been initialized.
+ */
+static void *sq_scmi_handle;
+
+/* The SCMI channel global object */
+static scmi_channel_t channel;
+
+/*
+ * Helper function to turn off a CPU power domain and
+ * its parent power domains if applicable.
+ */
+void sq_scmi_off(const struct psci_power_state *target_state)
+{
+ int lvl = 0, ret;
+ uint32_t scmi_pwr_state = 0;
+
+ /* At-least the CPU level should be specified to be OFF */
+ assert(target_state->pwr_domain_state[SQ_PWR_LVL0] ==
+ SQ_LOCAL_STATE_OFF);
+
+ for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
+ if (target_state->pwr_domain_state[lvl] == SQ_LOCAL_STATE_RUN)
+ break;
+
+ assert(target_state->pwr_domain_state[lvl] ==
+ SQ_LOCAL_STATE_OFF);
+ SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl,
+ scmi_power_state_off);
+ }
+
+ SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
+
+ ret = scmi_pwr_state_set(sq_scmi_handle,
+ sq_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()],
+ scmi_pwr_state);
+
+ if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
+ ERROR("SCMI set power state command return 0x%x unexpected\n",
+ ret);
+ panic();
+ }
+}
+
+/*
+ * Helper function to turn ON a CPU power domain and
+ *its parent power domains if applicable.
+ */
+void sq_scmi_on(u_register_t mpidr)
+{
+ int lvl = 0, ret, core_pos;
+ uint32_t scmi_pwr_state = 0;
+
+ for (; lvl <= PLAT_MAX_PWR_LVL; lvl++)
+ SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl,
+ scmi_power_state_on);
+
+ SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
+
+ core_pos = plat_core_pos_by_mpidr(mpidr);
+ assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
+
+ ret = scmi_pwr_state_set(sq_scmi_handle,
+ sq_core_pos_to_scmi_dmn_id_map[core_pos],
+ scmi_pwr_state);
+
+ if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
+ ERROR("SCMI set power state command return 0x%x unexpected\n",
+ ret);
+ panic();
+ }
+}
+
+void __dead2 sq_scmi_system_off(int state)
+{
+ int ret;
+
+ /*
+ * Disable GIC CPU interface to prevent pending interrupt from waking
+ * up the AP from WFI.
+ */
+ sq_gic_cpuif_disable();
+
+ /*
+ * Issue SCMI command. First issue a graceful
+ * request and if that fails force the request.
+ */
+ ret = scmi_sys_pwr_state_set(sq_scmi_handle,
+ SCMI_SYS_PWR_FORCEFUL_REQ,
+ state);
+
+ if (ret != SCMI_E_SUCCESS) {
+ ERROR("SCMI system power state set 0x%x returns unexpected 0x%x\n",
+ state, ret);
+ panic();
+ }
+ wfi();
+ ERROR("SCMI set power state: operation not handled.\n");
+ panic();
+}
+
+/*
+ * Helper function to reset the system via SCMI.
+ */
+void __dead2 sq_scmi_sys_shutdown(void)
+{
+ sq_scmi_system_off(SCMI_SYS_PWR_SHUTDOWN);
+}
+
+void __dead2 sq_scmi_sys_reboot(void)
+{
+ sq_scmi_system_off(SCMI_SYS_PWR_COLD_RESET);
+}
+
+static int scmi_ap_core_init(scmi_channel_t *ch)
+{
+#if PROGRAMMABLE_RESET_ADDRESS
+ uint32_t version;
+ int ret;
+
+ ret = scmi_proto_version(ch, SCMI_AP_CORE_PROTO_ID, &version);
+ if (ret != SCMI_E_SUCCESS) {
+ WARN("SCMI AP core protocol version message failed\n");
+ return -1;
+ }
+
+ if (!is_scmi_version_compatible(SCMI_AP_CORE_PROTO_VER, version)) {
+ WARN("SCMI AP core protocol version 0x%x incompatible with driver version 0x%x\n",
+ version, SCMI_AP_CORE_PROTO_VER);
+ return -1;
+ }
+ INFO("SCMI AP core protocol version 0x%x detected\n", version);
+#endif
+ return 0;
+}
+
+void __init plat_sq_pwrc_setup(void)
+{
+ channel.info = &sq_scmi_plat_info;
+ channel.lock = SQ_SCMI_LOCK_GET_INSTANCE;
+ sq_scmi_handle = scmi_init(&channel);
+ if (sq_scmi_handle == NULL) {
+ ERROR("SCMI Initialization failed\n");
+ panic();
+ }
+ if (scmi_ap_core_init(&channel) < 0) {
+ ERROR("SCMI AP core protocol initialization failed\n");
+ panic();
+ }
+}
+
+uint32_t sq_scmi_get_draminfo(struct draminfo *info)
+{
+ scmi_get_draminfo(sq_scmi_handle, info);
+
+ return 0;
+}
diff --git a/plat/socionext/synquacer/drivers/scp/sq_scp.c b/plat/socionext/synquacer/drivers/scp/sq_scp.c
new file mode 100644
index 0000000..e494022
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scp/sq_scp.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <sq_common.h>
+#include "sq_scpi.h"
+
+/*
+ * Helper function to get dram information from SCP.
+ */
+uint32_t sq_scp_get_draminfo(struct draminfo *info)
+{
+#if SQ_USE_SCMI_DRIVER
+ sq_scmi_get_draminfo(info);
+#else
+ scpi_get_draminfo(info);
+#endif
+ return 0;
+}
diff --git a/plat/socionext/synquacer/drivers/scpi/sq_scpi.c b/plat/socionext/synquacer/drivers/scpi/sq_scpi.c
new file mode 100644
index 0000000..0cb75a0
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scpi/sq_scpi.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <sq_common.h>
+
+#include "sq_mhu.h"
+#include "sq_scpi.h"
+
+#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_SQ_SCP_COM_SHARED_MEM_BASE
+#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SQ_SCP_COM_SHARED_MEM_BASE \
+ + 0x100)
+
+#define SCPI_CMD_HEADER_AP_TO_SCP \
+ ((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
+#define SCPI_CMD_PAYLOAD_AP_TO_SCP \
+ ((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
+
+/* ID of the MHU slot used for the SCPI protocol */
+#define SCPI_MHU_SLOT_ID 0
+
+static void scpi_secure_message_start(void)
+{
+ mhu_secure_message_start(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_send(size_t payload_size)
+{
+ /*
+ * Ensure that any write to the SCPI payload area is seen by SCP before
+ * we write to the MHU register. If these 2 writes were reordered by
+ * the CPU then SCP would read stale payload data
+ */
+ dmbst();
+
+ mhu_secure_message_send(SCPI_MHU_SLOT_ID);
+}
+
+static void scpi_secure_message_receive(scpi_cmd_t *cmd)
+{
+ uint32_t mhu_status;
+
+ assert(cmd != NULL);
+
+ mhu_status = mhu_secure_message_wait();
+
+ /* Expect an SCPI message, reject any other protocol */
+ if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
+ ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
+ mhu_status);
+ panic();
+ }
+
+ /*
+ * Ensure that any read to the SCPI payload area is done after reading
+ * the MHU register. If these 2 reads were reordered then the CPU would
+ * read invalid payload data
+ */
+ dmbld();
+
+ memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
+}
+
+static void scpi_secure_message_end(void)
+{
+ mhu_secure_message_end(SCPI_MHU_SLOT_ID);
+}
+
+int scpi_wait_ready(void)
+{
+ scpi_cmd_t scpi_cmd;
+ scpi_status_t status = SCP_OK;
+
+ VERBOSE("Waiting for SCP_READY command...\n");
+
+ /* Get a message from the SCP */
+ scpi_secure_message_start();
+ scpi_secure_message_receive(&scpi_cmd);
+ scpi_secure_message_end();
+
+ /* We are expecting 'SCP Ready', produce correct error if it's not */
+ if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
+ ERROR("Unexpected SCP command: expected command #%u,"
+ "got command #%u\n", SCPI_CMD_SCP_READY, scpi_cmd.id);
+ status = SCP_E_SUPPORT;
+ } else if (scpi_cmd.size != 0) {
+ ERROR("SCP_READY command has incorrect size: expected 0,"
+ "got %u\n", scpi_cmd.size);
+ status = SCP_E_SIZE;
+ }
+
+ VERBOSE("Sending response for SCP_READY command\n");
+
+ /*
+ * Send our response back to SCP.
+ * We are using the same SCPI header, just update the status field.
+ */
+ scpi_cmd.status = status;
+ scpi_secure_message_start();
+ memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd));
+ scpi_secure_message_send(0);
+ scpi_secure_message_end();
+
+ return status == SCP_OK ? 0 : -1;
+}
+
+void scpi_set_sq_power_state(unsigned int mpidr, scpi_power_state_t cpu_state,
+ scpi_power_state_t cluster_state, scpi_power_state_t sq_state)
+{
+ scpi_cmd_t *cmd;
+ uint32_t state = 0;
+ uint32_t *payload_addr;
+
+ state |= mpidr & 0x0f; /* CPU ID */
+ state |= (mpidr & 0xf00) >> 4; /* Cluster ID */
+ state |= cpu_state << 8;
+ state |= cluster_state << 12;
+ state |= sq_state << 16;
+
+ scpi_secure_message_start();
+
+ /* Populate the command header */
+ cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+ cmd->id = SCPI_CMD_SET_POWER_STATE;
+ cmd->set = SCPI_SET_NORMAL;
+ cmd->sender = 0;
+ cmd->size = sizeof(state);
+ /* Populate the command payload */
+ payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+ *payload_addr = state;
+ scpi_secure_message_send(sizeof(state));
+
+ /*
+ * SCP does not reply to this command in order to avoid MHU interrupts
+ * from the sender, which could interfere with its power state request.
+ */
+ scpi_secure_message_end();
+}
+
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
+{
+ scpi_cmd_t *cmd;
+ uint8_t *payload_addr;
+ scpi_cmd_t response;
+
+ scpi_secure_message_start();
+
+ /* Populate the command header */
+ cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+ cmd->id = SCPI_CMD_SYS_POWER_STATE;
+ cmd->set = 0;
+ cmd->sender = 0;
+ cmd->size = sizeof(*payload_addr);
+ /* Populate the command payload */
+ payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
+ *payload_addr = system_state & 0xff;
+ scpi_secure_message_send(sizeof(*payload_addr));
+
+ scpi_secure_message_receive(&response);
+
+ scpi_secure_message_end();
+
+ return response.status;
+}
+
+uint32_t scpi_get_draminfo(struct draminfo *info)
+{
+ scpi_cmd_t *cmd;
+ struct {
+ scpi_cmd_t cmd;
+ struct draminfo info;
+ } response;
+ uint32_t mhu_status;
+
+ scpi_secure_message_start();
+
+ /* Populate the command header */
+ cmd = SCPI_CMD_HEADER_AP_TO_SCP;
+ cmd->id = SCPI_CMD_GET_DRAMINFO;
+ cmd->set = SCPI_SET_EXTENDED;
+ cmd->sender = 0;
+ cmd->size = 0;
+
+ scpi_secure_message_send(0);
+
+ mhu_status = mhu_secure_message_wait();
+
+ /* Expect an SCPI message, reject any other protocol */
+ if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
+ ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
+ mhu_status);
+ panic();
+ }
+
+ /*
+ * Ensure that any read to the SCPI payload area is done after reading
+ * the MHU register. If these 2 reads were reordered then the CPU would
+ * read invalid payload data
+ */
+ dmbld();
+
+ memcpy(&response, (void *)SCPI_SHARED_MEM_SCP_TO_AP, sizeof(response));
+
+ scpi_secure_message_end();
+
+ if (response.cmd.status == SCP_OK)
+ *info = response.info;
+
+ return response.cmd.status;
+}
diff --git a/plat/socionext/synquacer/drivers/scpi/sq_scpi.h b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h
new file mode 100644
index 0000000..eb6ce5c
--- /dev/null
+++ b/plat/socionext/synquacer/drivers/scpi/sq_scpi.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SQ_SCPI_H
+#define SQ_SCPI_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * An SCPI command consists of a header and a payload.
+ * The following structure describes the header. It is 64-bit long.
+ */
+typedef struct {
+ /* Command ID */
+ uint32_t id : 7;
+ /* Set ID. Identifies whether this is a standard or extended command. */
+ uint32_t set : 1;
+ /* Sender ID to match a reply. The value is sender specific. */
+ uint32_t sender : 8;
+ /* Size of the payload in bytes (0 - 511) */
+ uint32_t size : 9;
+ uint32_t reserved : 7;
+ /*
+ * Status indicating the success of a command.
+ * See the enum below.
+ */
+ uint32_t status;
+} scpi_cmd_t;
+
+typedef enum {
+ SCPI_SET_NORMAL = 0, /* Normal SCPI commands */
+ SCPI_SET_EXTENDED /* Extended SCPI commands */
+} scpi_set_t;
+
+enum {
+ SCP_OK = 0, /* Success */
+ SCP_E_PARAM, /* Invalid parameter(s) */
+ SCP_E_ALIGN, /* Invalid alignment */
+ SCP_E_SIZE, /* Invalid size */
+ SCP_E_HANDLER, /* Invalid handler or callback */
+ SCP_E_ACCESS, /* Invalid access or permission denied */
+ SCP_E_RANGE, /* Value out of range */
+ SCP_E_TIMEOUT, /* Time out has ocurred */
+ SCP_E_NOMEM, /* Invalid memory area or pointer */
+ SCP_E_PWRSTATE, /* Invalid power state */
+ SCP_E_SUPPORT, /* Feature not supported or disabled */
+ SCPI_E_DEVICE, /* Device error */
+ SCPI_E_BUSY, /* Device is busy */
+};
+
+typedef uint32_t scpi_status_t;
+
+typedef enum {
+ SCPI_CMD_SCP_READY = 0x01,
+ SCPI_CMD_SET_POWER_STATE = 0x03,
+ SCPI_CMD_SYS_POWER_STATE = 0x05
+} scpi_command_t;
+
+typedef enum {
+ scpi_power_on = 0,
+ scpi_power_retention = 1,
+ scpi_power_off = 3,
+} scpi_power_state_t;
+
+typedef enum {
+ scpi_system_shutdown = 0,
+ scpi_system_reboot = 1,
+ scpi_system_reset = 2
+} scpi_system_state_t;
+
+extern int scpi_wait_ready(void);
+extern void scpi_set_sq_power_state(unsigned int mpidr,
+ scpi_power_state_t cpu_state,
+ scpi_power_state_t cluster_state,
+ scpi_power_state_t css_state);
+uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
+uint32_t scpi_get_draminfo(struct draminfo *info);
+
+#endif /* SQ_SCPI_H */
diff --git a/plat/socionext/synquacer/include/plat.ld.S b/plat/socionext/synquacer/include/plat.ld.S
new file mode 100644
index 0000000..af7a172
--- /dev/null
+++ b/plat/socionext/synquacer/include/plat.ld.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SYNQUACER_PLAT_LD_S__
+#define SYNQUACER_PLAT_LD_S__
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+#define SPM_SHIM_EXCEPTIONS_VMA SP_DRAM
+
+MEMORY {
+ SP_DRAM (rw): ORIGIN = PLAT_SQ_SP_PRIV_BASE, LENGTH = PLAT_SQ_SP_PRIV_SIZE
+}
+
+SECTIONS
+{
+ /*
+ * Put the page tables in secure DRAM so that the PTW can make cacheable
+ * accesses, as the core SPM code expects. (The SRAM on SynQuacer does
+ * not support inner shareable WBWA mappings so it is mapped normal
+ * non-cacheable)
+ */
+ sp_xlat_table (NOLOAD) : ALIGN(PAGE_SIZE) {
+ *(sp_xlat_table)
+ } >SP_DRAM
+}
+
+#endif /* SYNQUACER_PLAT_LD_S__ */
diff --git a/plat/socionext/synquacer/include/plat_macros.S b/plat/socionext/synquacer/include/plat_macros.S
new file mode 100644
index 0000000..932b21d
--- /dev/null
+++ b/plat/socionext/synquacer/include/plat_macros.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+/*
+ * Print CCN registers
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h
new file mode 100644
index 0000000..d6bfe42
--- /dev/null
+++ b/plat/socionext/synquacer/include/platform_def.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+/* CPU topology */
+#define PLAT_MAX_CORES_PER_CLUSTER U(2)
+#define PLAT_CLUSTER_COUNT U(12)
+#define PLATFORM_CORE_COUNT (PLAT_CLUSTER_COUNT * \
+ PLAT_MAX_CORES_PER_CLUSTER)
+
+/* Macros to read the SQ power domain state */
+#define SQ_PWR_LVL0 MPIDR_AFFLVL0
+#define SQ_PWR_LVL1 MPIDR_AFFLVL1
+#define SQ_PWR_LVL2 MPIDR_AFFLVL2
+
+#define SQ_CORE_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL0]
+#define SQ_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL1]
+#define SQ_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\
+ (state)->pwr_domain_state[SQ_PWR_LVL2] : 0)
+
+#define PLAT_MAX_PWR_LVL U(1)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+#define SQ_LOCAL_STATE_RUN 0
+#define SQ_LOCAL_STATE_RET 1
+#define SQ_LOCAL_STATE_OFF 2
+
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 8
+#define MAX_MMAP_REGIONS 8
+
+#if TRUSTED_BOARD_BOOT
+#define PLATFORM_STACK_SIZE 0x1000
+#else
+#define PLATFORM_STACK_SIZE 0x400
+#endif
+
+#if !RESET_TO_BL31
+
+/* A mailbox page will be mapped from BL2 and BL31 */
+#define BL2_MAILBOX_BASE 0x0403f000
+#define BL2_MAILBOX_SIZE 0x1000
+
+#define PLAT_SQ_BOOTIDX_BASE 0x08510000
+#define PLAT_SQ_MAX_BOOT_INDEX 2
+
+#define MAX_IO_HANDLES 2
+#define MAX_IO_DEVICES 2
+#define MAX_IO_BLOCK_DEVICES U(1)
+
+#define BL2_BASE 0x04000000
+#define BL2_SIZE (256 * 1024)
+#define BL2_LIMIT (BL2_BASE + BL2_SIZE)
+
+/* If BL2 is enabled, the BL31 is loaded on secure DRAM */
+#define BL31_BASE 0xfbe00000
+#define BL31_SIZE 0x00100000
+#else
+
+#define BL31_BASE 0x04000000
+#define BL31_SIZE 0x00080000
+#endif
+
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+#define BL32_BASE 0xfc000000
+#define BL32_SIZE 0x03c00000
+#define BL32_LIMIT (BL32_BASE + BL32_SIZE)
+
+/* Alternative BL33 */
+#define PLAT_SQ_BL33_BASE 0xe0000000
+#define PLAT_SQ_BL33_SIZE 0x00200000
+
+/* FWU FIP IO base */
+#define PLAT_SQ_FIP_IOBASE 0x08600000
+#define PLAT_SQ_FIP_MAXSIZE 0x00400000
+
+#define PLAT_SQ_CCN_BASE 0x32000000
+#define PLAT_SQ_CLUSTER_TO_CCN_ID_MAP \
+ 0, /* Cluster 0 */ \
+ 18, /* Cluster 1 */ \
+ 11, /* Cluster 2 */ \
+ 29, /* Cluster 3 */ \
+ 35, /* Cluster 4 */ \
+ 17, /* Cluster 5 */ \
+ 12, /* Cluster 6 */ \
+ 30, /* Cluster 7 */ \
+ 14, /* Cluster 8 */ \
+ 32, /* Cluster 9 */ \
+ 15, /* Cluster 10 */ \
+ 33 /* Cluster 11 */
+
+/* UART related constants */
+#define PLAT_SQ_BOOT_UART_BASE 0x2A400000
+#define PLAT_SQ_BOOT_UART_CLK_IN_HZ 62500000
+#define SQ_CONSOLE_BAUDRATE 115200
+
+#define SQ_SYS_CNTCTL_BASE 0x2a430000
+
+#define SQ_SYS_TIMCTL_BASE 0x2a810000
+#define PLAT_SQ_NSTIMER_FRAME_ID 0
+#define SQ_SYS_CNT_BASE_NS 0x2a830000
+
+#define DRAMINFO_BASE 0x2E00FFC0
+
+#define PLAT_SQ_MHU_BASE 0x45000000
+
+#define PLAT_SQ_SCP_COM_SHARED_MEM_BASE 0x45400000
+#define SCPI_CMD_GET_DRAMINFO 0x1
+
+#define SQ_BOOT_CFG_ADDR 0x45410000
+#define PLAT_SQ_PRIMARY_CPU_SHIFT 8
+#define PLAT_SQ_PRIMARY_CPU_BIT_WIDTH 6
+
+#define PLAT_SQ_GICD_BASE 0x30000000
+#define PLAT_SQ_GICR_BASE 0x30400000
+
+#define PLAT_SQ_GPIO_BASE 0x51000000
+
+#define PLAT_SPM_BUF_BASE (BL32_LIMIT - 32 * PLAT_SPM_BUF_SIZE)
+#define PLAT_SPM_BUF_SIZE ULL(0x10000)
+#define PLAT_SPM_SPM_BUF_EL0_MMAP MAP_REGION2(PLAT_SPM_BUF_BASE, \
+ PLAT_SPM_BUF_BASE, \
+ PLAT_SPM_BUF_SIZE, \
+ MT_RO_DATA | MT_SECURE | \
+ MT_USER, PAGE_SIZE)
+
+#define PLAT_SP_IMAGE_NS_BUF_BASE BL32_LIMIT
+#define PLAT_SP_IMAGE_NS_BUF_SIZE ULL(0x200000)
+#define PLAT_SP_IMAGE_NS_BUF_MMAP MAP_REGION2(PLAT_SP_IMAGE_NS_BUF_BASE, \
+ PLAT_SP_IMAGE_NS_BUF_BASE, \
+ PLAT_SP_IMAGE_NS_BUF_SIZE, \
+ MT_RW_DATA | MT_NS | \
+ MT_USER, PAGE_SIZE)
+
+#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x10000)
+#define PLAT_SP_IMAGE_STACK_SIZE (32 * PLAT_SP_IMAGE_STACK_PCPU_SIZE)
+#define PLAT_SP_IMAGE_STACK_BASE (PLAT_SQ_SP_HEAP_BASE + PLAT_SQ_SP_HEAP_SIZE)
+
+#define PLAT_SQ_SP_IMAGE_SIZE ULL(0x200000)
+#define PLAT_SQ_SP_IMAGE_MMAP MAP_REGION2(BL32_BASE, BL32_BASE, \
+ PLAT_SQ_SP_IMAGE_SIZE, \
+ MT_CODE | MT_SECURE | \
+ MT_USER, PAGE_SIZE)
+
+#define PLAT_SQ_SP_HEAP_BASE (BL32_BASE + PLAT_SQ_SP_IMAGE_SIZE)
+#define PLAT_SQ_SP_HEAP_SIZE ULL(0x800000)
+
+#define PLAT_SQ_SP_IMAGE_RW_MMAP MAP_REGION2(PLAT_SQ_SP_HEAP_BASE, \
+ PLAT_SQ_SP_HEAP_BASE, \
+ (PLAT_SQ_SP_HEAP_SIZE + \
+ PLAT_SP_IMAGE_STACK_SIZE), \
+ MT_RW_DATA | MT_SECURE | \
+ MT_USER, PAGE_SIZE)
+
+#define PLAT_SQ_SP_PRIV_BASE (PLAT_SP_IMAGE_STACK_BASE + \
+ PLAT_SP_IMAGE_STACK_SIZE)
+#define PLAT_SQ_SP_PRIV_SIZE ULL(0x40000)
+
+#define PLAT_SP_PRI 0x20
+#define PLAT_PRI_BITS 2
+#define PLAT_SPM_COOKIE_0 ULL(0)
+#define PLAT_SPM_COOKIE_1 ULL(0)
+
+/* Total number of memory regions with distinct properties */
+#define PLAT_SP_IMAGE_NUM_MEM_REGIONS 6
+
+#define PLAT_SP_IMAGE_MMAP_REGIONS 30
+#define PLAT_SP_IMAGE_MAX_XLAT_TABLES 20
+#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "sp_xlat_table"
+#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME "sp_xlat_table"
+
+#define PLAT_SQ_UART1_BASE PLAT_SQ_BOOT_UART_BASE
+#define PLAT_SQ_UART1_SIZE ULL(0x1000)
+#define PLAT_SQ_UART1_MMAP MAP_REGION_FLAT(PLAT_SQ_UART1_BASE, \
+ PLAT_SQ_UART1_SIZE, \
+ MT_DEVICE | MT_RW | \
+ MT_NS | MT_PRIVILEGED)
+
+#define PLAT_SQ_PERIPH_BASE 0x50000000
+#define PLAT_SQ_PERIPH_SIZE ULL(0x8000000)
+#define PLAT_SQ_PERIPH_MMAP MAP_REGION_FLAT(PLAT_SQ_PERIPH_BASE, \
+ PLAT_SQ_PERIPH_SIZE, \
+ MT_DEVICE | MT_RW | \
+ MT_NS | MT_USER)
+
+#define PLAT_SQ_FLASH_BASE 0x08000000
+#define PLAT_SQ_FLASH_SIZE ULL(0x8000000)
+#define PLAT_SQ_FLASH_MMAP MAP_REGION_FLAT(PLAT_SQ_FLASH_BASE, \
+ PLAT_SQ_FLASH_SIZE, \
+ MT_DEVICE | MT_RW | \
+ MT_NS | MT_USER)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/socionext/synquacer/include/sq_common.h b/plat/socionext/synquacer/include/sq_common.h
new file mode 100644
index 0000000..eef0e1f
--- /dev/null
+++ b/plat/socionext/synquacer/include/sq_common.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SQ_COMMON_H
+#define SQ_COMMON_H
+
+#include <stdint.h>
+
+#include <lib/psci/psci.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+struct draminfo {
+ uint32_t num_regions;
+ uint32_t reserved;
+ uint64_t base1;
+ uint64_t size1;
+ uint64_t base2;
+ uint64_t size2;
+ uint64_t base3;
+ uint64_t size3;
+};
+
+uint32_t sq_scp_get_draminfo(struct draminfo *info);
+
+void plat_sq_pwrc_setup(void);
+
+void plat_sq_interconnect_init(void);
+void plat_sq_interconnect_enter_coherency(void);
+void plat_sq_interconnect_exit_coherency(void);
+
+unsigned int sq_calc_core_pos(u_register_t mpidr);
+
+void sq_gic_driver_init(void);
+void sq_gic_init(void);
+void sq_gic_cpuif_enable(void);
+void sq_gic_cpuif_disable(void);
+void sq_gic_pcpu_init(void);
+
+int sq_io_setup(void);
+struct image_info *sq_get_image_info(unsigned int image_id);
+void sq_mmap_setup(uintptr_t total_base, size_t total_size,
+ const struct mmap_region *mmap);
+
+/* SCMI API for power management by SCP */
+void sq_scmi_off(const struct psci_power_state *target_state);
+void sq_scmi_on(u_register_t mpidr);
+void __dead2 sq_scmi_sys_shutdown(void);
+void __dead2 sq_scmi_sys_reboot(void);
+void __dead2 sq_scmi_system_off(int state);
+/* SCMI API for vendor specific protocol */
+uint32_t sq_scmi_get_draminfo(struct draminfo *info);
+
+#endif /* SQ_COMMON_H */
diff --git a/plat/socionext/synquacer/platform.mk b/plat/socionext/synquacer/platform.mk
new file mode 100644
index 0000000..b76ae88
--- /dev/null
+++ b/plat/socionext/synquacer/platform.mk
@@ -0,0 +1,117 @@
+#
+# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+override PROGRAMMABLE_RESET_ADDRESS := 1
+override USE_COHERENT_MEM := 1
+override SEPARATE_CODE_AND_RODATA := 1
+override ENABLE_SVE_FOR_NS := 0
+# Enable workarounds for selected Cortex-A53 erratas.
+ERRATA_A53_855873 := 1
+
+ifeq (${RESET_TO_BL31}, 1)
+override RESET_TO_BL31 := 1
+override TRUSTED_BOARD_BOOT := 0
+SQ_USE_SCMI_DRIVER ?= 0
+else
+override RESET_TO_BL31 := 0
+override BL2_AT_EL3 := 1
+SQ_USE_SCMI_DRIVER := 1
+BL2_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+endif
+
+# Libraries
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_PATH := plat/socionext/synquacer
+PLAT_INCLUDES := -I$(PLAT_PATH)/include \
+ -I$(PLAT_PATH)/drivers/scpi \
+ -I$(PLAT_PATH)/drivers/mhu \
+ -Idrivers/arm/css/scmi \
+ -Idrivers/arm/css/scmi/vendor
+
+PLAT_BL_COMMON_SOURCES += $(PLAT_PATH)/sq_helpers.S \
+ drivers/arm/pl011/aarch64/pl011_console.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ $(PLAT_PATH)/sq_xlat_setup.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+ifneq (${RESET_TO_BL31}, 1)
+BL2_SOURCES += common/desc_image_load.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ $(PLAT_PATH)/sq_bl2_setup.c \
+ $(PLAT_PATH)/sq_image_desc.c \
+ $(PLAT_PATH)/sq_io_storage.c
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+BL2_SOURCES += drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl2.c \
+ plat/common/tbbr/plat_tbbr.c \
+ $(PLAT_PATH)/sq_rotpk.S \
+ $(PLAT_PATH)/sq_tbbr.c
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/sq_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+
+endif # TRUSTED_BOARD_BOOT
+endif
+
+BL31_SOURCES += drivers/arm/ccn/ccn.c \
+ ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ $(PLAT_PATH)/sq_bl31_setup.c \
+ $(PLAT_PATH)/sq_ccn.c \
+ $(PLAT_PATH)/sq_topology.c \
+ $(PLAT_PATH)/sq_psci.c \
+ $(PLAT_PATH)/sq_gicv3.c \
+ $(PLAT_PATH)/drivers/scp/sq_scp.c
+
+ifeq (${SQ_USE_SCMI_DRIVER},0)
+BL31_SOURCES += $(PLAT_PATH)/drivers/scpi/sq_scpi.c \
+ $(PLAT_PATH)/drivers/mhu/sq_mhu.c
+else
+BL31_SOURCES += $(PLAT_PATH)/drivers/scp/sq_scmi.c \
+ drivers/arm/css/scmi/scmi_common.c \
+ drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \
+ drivers/arm/css/scmi/scmi_sys_pwr_proto.c \
+ drivers/arm/css/scmi/vendor/scmi_sq.c \
+ drivers/arm/css/mhu/css_mhu_doorbell.c
+endif
+
+ifeq (${SPM_MM},1)
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+BL31_SOURCES += $(PLAT_PATH)/sq_spm.c
+endif
+
+ifeq (${SQ_USE_SCMI_DRIVER},1)
+$(eval $(call add_define,SQ_USE_SCMI_DRIVER))
+endif
diff --git a/plat/socionext/synquacer/sq_bl2_setup.c b/plat/socionext/synquacer/sq_bl2_setup.c
new file mode 100644
index 0000000..a98d912
--- /dev/null
+++ b/plat/socionext/synquacer/sq_bl2_setup.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/image_decompress.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/io/io_storage.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+#include <sq_common.h>
+
+static console_t console;
+
+void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
+ u_register_t x2, u_register_t x3)
+{
+ /* Initialize the console to provide early debug support */
+ (void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
+ PLAT_SQ_BOOT_UART_CLK_IN_HZ,
+ SQ_CONSOLE_BAUDRATE, &console);
+ console_set_scope(&console, CONSOLE_FLAG_BOOT);
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ int ret;
+
+ sq_mmap_setup(BL2_BASE, BL2_SIZE, NULL);
+
+ ret = sq_io_setup();
+ if (ret) {
+ ERROR("failed to setup io devices\n");
+ plat_error_handler(ret);
+ }
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
+
+void bl2_plat_preload_setup(void)
+{
+}
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ struct image_info *image_info;
+
+ image_info = sq_get_image_info(image_id);
+
+ return mmap_add_dynamic_region(image_info->image_base,
+ image_info->image_base,
+ image_info->image_max_size,
+ MT_MEMORY | MT_RW | MT_NS);
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ return 0;
+}
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
new file mode 100644
index 0000000..967437b
--- /dev/null
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <lib/mmio.h>
+#include <sq_common.h>
+
+static console_t console;
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_START__, SPM_SHIM_EXCEPTIONS_START);
+IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_END__, SPM_SHIM_EXCEPTIONS_END);
+IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_LMA__, SPM_SHIM_EXCEPTIONS_LMA);
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ unsigned int counter_base_frequency;
+
+ /* Read the frequency from Frequency modes table */
+ counter_base_frequency = mmio_read_32(SQ_SYS_CNTCTL_BASE + CNTFID_OFF);
+
+ /* The first entry of the frequency modes table must not be 0 */
+ if (counter_base_frequency == 0)
+ panic();
+
+ return counter_base_frequency;
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ assert(sec_state_is_valid(type));
+ return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info;
+}
+
+#if !RESET_TO_BL31
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ void *from_bl2 = (void *) arg0;
+ bl_params_node_t *bl_params = ((bl_params_t *) from_bl2)->head;
+
+ /* Initialize the console to provide early debug support */
+ (void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
+ PLAT_SQ_BOOT_UART_CLK_IN_HZ,
+ SQ_CONSOLE_BAUDRATE, &console);
+
+ console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+
+ /* Initialize power controller before setting up topology */
+ plat_sq_pwrc_setup();
+
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+}
+
+#else
+/*******************************************************************************
+ * Gets SPSR for BL32 entry
+ ******************************************************************************/
+uint32_t sq_get_spsr_for_bl32_entry(void)
+{
+ /*
+ * The Secure Payload Dispatcher service is responsible for
+ * setting the SPSR prior to entry into the BL32 image.
+ */
+ return 0;
+}
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+uint32_t sq_get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ /* Initialize the console to provide early debug support */
+ (void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
+ PLAT_SQ_BOOT_UART_CLK_IN_HZ,
+ SQ_CONSOLE_BAUDRATE, &console);
+
+ console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(arg0 == 0U);
+ assert(arg1 == 0U);
+
+ /* Initialize power controller before setting up topology */
+ plat_sq_pwrc_setup();
+
+#ifdef SPD_opteed
+ struct draminfo di = {0};
+
+ sq_scp_get_draminfo(&di);
+
+ /*
+ * Check if OP-TEE has been loaded in Secure RAM allocated
+ * from DRAM1 region
+ */
+ if ((di.base1 + di.size1) <= BL32_BASE) {
+ NOTICE("OP-TEE has been loaded by SCP firmware\n");
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = sq_get_spsr_for_bl32_entry();
+ } else {
+ NOTICE("OP-TEE has not been loaded by SCP firmware\n");
+ }
+#endif /* SPD_opteed */
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info,
+ PARAM_EP,
+ VERSION_1,
+ 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
+ bl33_image_ep_info.spsr = sq_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+#endif
+
+static void sq_configure_sys_timer(void)
+{
+ unsigned int reg_val;
+ unsigned int freq_val = plat_get_syscnt_freq2();
+
+ reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
+ reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
+ reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
+ mmio_write_32(SQ_SYS_TIMCTL_BASE +
+ CNTACR_BASE(PLAT_SQ_NSTIMER_FRAME_ID), reg_val);
+
+ reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_SQ_NSTIMER_FRAME_ID));
+ mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
+
+ /* Initialize CNTFRQ register in CNTCTLBase frame */
+ mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val);
+
+ /*
+ * Initialize CNTFRQ register in Non-secure CNTBase frame.
+ * This is required for SynQuacer, because it does not
+ * follow ARM ARM in that the value updated in CNTFRQ is not
+ * reflected in CNTBASEN_CNTFRQ. Hence update the value manually.
+ */
+ mmio_write_32(SQ_SYS_CNT_BASE_NS + CNTBASEN_CNTFRQ, freq_val);
+}
+
+void bl31_platform_setup(void)
+{
+ /* Initialize the CCN interconnect */
+ plat_sq_interconnect_init();
+ plat_sq_interconnect_enter_coherency();
+
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ sq_gic_driver_init();
+ sq_gic_init();
+
+ /* Enable and initialize the System level generic timer */
+ mmio_write_32(SQ_SYS_CNTCTL_BASE + CNTCR_OFF,
+ CNTCR_FCREQ(0U) | CNTCR_EN);
+
+ /* Allow access to the System counter timer module */
+ sq_configure_sys_timer();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ struct draminfo *di = (struct draminfo *)(unsigned long)DRAMINFO_BASE;
+
+ sq_scp_get_draminfo(di);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ static const mmap_region_t secure_partition_mmap[] = {
+#if SPM_MM
+ MAP_REGION_FLAT(PLAT_SPM_BUF_BASE,
+ PLAT_SPM_BUF_SIZE,
+ MT_RW_DATA | MT_SECURE),
+ MAP_REGION_FLAT(PLAT_SQ_SP_PRIV_BASE,
+ PLAT_SQ_SP_PRIV_SIZE,
+ MT_RW_DATA | MT_SECURE),
+#endif
+#if !RESET_TO_BL31
+ MAP_REGION_FLAT(BL2_MAILBOX_BASE,
+ BL2_MAILBOX_SIZE,
+ MT_RW | MT_SECURE),
+#endif
+ {0},
+ };
+
+ sq_mmap_setup(BL31_BASE, BL31_SIZE, secure_partition_mmap);
+ enable_mmu_el3(XLAT_TABLE_NC);
+
+#if SPM_MM
+ memcpy((void *)SPM_SHIM_EXCEPTIONS_START,
+ (void *)SPM_SHIM_EXCEPTIONS_LMA,
+ (uintptr_t)SPM_SHIM_EXCEPTIONS_END -
+ (uintptr_t)SPM_SHIM_EXCEPTIONS_START);
+#endif
+}
+
+void bl31_plat_enable_mmu(uint32_t flags)
+{
+ enable_mmu_el3(flags | XLAT_TABLE_NC);
+}
diff --git a/plat/socionext/synquacer/sq_ccn.c b/plat/socionext/synquacer/sq_ccn.c
new file mode 100644
index 0000000..fa6ea87
--- /dev/null
+++ b/plat/socionext/synquacer/sq_ccn.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <drivers/arm/ccn.h>
+
+static const unsigned char master_to_rn_id_map[] = {
+ PLAT_SQ_CLUSTER_TO_CCN_ID_MAP
+};
+
+static const ccn_desc_t sq_ccn_desc = {
+ .periphbase = PLAT_SQ_CCN_BASE,
+ .num_masters = ARRAY_SIZE(master_to_rn_id_map),
+ .master_to_rn_id_map = master_to_rn_id_map
+};
+
+/******************************************************************************
+ * Helper function to initialize SQ CCN driver.
+ *****************************************************************************/
+void plat_sq_interconnect_init(void)
+{
+ ccn_init(&sq_ccn_desc);
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_sq_interconnect_enter_coherency(void)
+{
+ ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_sq_interconnect_exit_coherency(void)
+{
+ ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
diff --git a/plat/socionext/synquacer/sq_gicv3.c b/plat/socionext/synquacer/sq_gicv3.c
new file mode 100644
index 0000000..05318e3
--- /dev/null
+++ b/plat/socionext/synquacer/sq_gicv3.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <plat/common/platform.h>
+
+#include "sq_common.h"
+
+static uintptr_t sq_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t sq_interrupt_props[] = {
+ /* G0 interrupts */
+
+ /* SGI0 */
+ INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ /* SGI6 */
+ INTR_PROP_DESC(14, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+
+ /* G1S interrupts */
+
+ /* Timer */
+ INTR_PROP_DESC(29, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_LEVEL),
+ /* SGI1 */
+ INTR_PROP_DESC(9, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI2 */
+ INTR_PROP_DESC(10, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI3 */
+ INTR_PROP_DESC(11, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI4 */
+ INTR_PROP_DESC(12, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI5 */
+ INTR_PROP_DESC(13, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI7 */
+ INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE)
+};
+
+static unsigned int sq_mpidr_to_core_pos(u_register_t mpidr)
+{
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+static const struct gicv3_driver_data sq_gic_driver_data = {
+ .gicd_base = PLAT_SQ_GICD_BASE,
+ .gicr_base = PLAT_SQ_GICR_BASE,
+ .interrupt_props = sq_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(sq_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = sq_rdistif_base_addrs,
+ .mpidr_to_core_pos = sq_mpidr_to_core_pos,
+};
+
+void sq_gic_driver_init(void)
+{
+ gicv3_driver_init(&sq_gic_driver_data);
+}
+
+void sq_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void sq_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void sq_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void sq_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/socionext/synquacer/sq_helpers.S b/plat/socionext/synquacer/sq_helpers.S
new file mode 100644
index 0000000..5f9eab4
--- /dev/null
+++ b/plat/socionext/synquacer/sq_helpers.S
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2018-2022, 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 <platform_def.h>
+
+ .global sq_calc_core_pos
+ .global plat_my_core_pos
+ .global platform_mem_init
+ .global plat_is_my_cpu_primary
+ .global plat_secondary_cold_boot_setup
+ .global plat_crash_console_init
+ .global plat_crash_console_putc
+ .global plat_crash_console_flush
+
+/*
+ * unsigned int sq_calc_core_pos(u_register_t mpidr)
+ * core_pos = (cluster_id * max_cpus_per_cluster) + core_id
+ */
+func sq_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, lsr #7
+ ret
+endfunc sq_calc_core_pos
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b sq_calc_core_pos
+endfunc plat_my_core_pos
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+/*
+ * Secondary CPUs are placed in a holding pen, waiting for their mailbox
+ * to be populated. Note that all CPUs share the same mailbox ; therefore,
+ * populating it will release all CPUs from their holding pen. If
+ * finer-grained control is needed then this should be handled in the
+ * code that secondary CPUs jump to.
+ */
+func plat_secondary_cold_boot_setup
+#if !RESET_TO_BL31
+ mov_imm x0, BL2_MAILBOX_BASE
+ ldr x0, [x0]
+#else
+ ldr x0, sq_sec_entrypoint
+#endif
+
+ /* Wait until the mailbox gets populated */
+poll_mailbox:
+ cbz x0, 1f
+ br x0
+1:
+ wfe
+ b poll_mailbox
+endfunc plat_secondary_cold_boot_setup
+
+/*
+ * Find out whether the current cpu is the primary
+ * cpu (applicable only after a cold boot)
+ */
+func plat_is_my_cpu_primary
+ mov x9, x30
+ bl plat_my_core_pos
+ ldr x1, =SQ_BOOT_CFG_ADDR
+ ldr x1, [x1]
+ ubfx x1, x1, #PLAT_SQ_PRIMARY_CPU_SHIFT, \
+ #PLAT_SQ_PRIMARY_CPU_BIT_WIDTH
+ cmp x0, x1
+ cset w0, eq
+ ret x9
+endfunc plat_is_my_cpu_primary
+
+/*
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ */
+func plat_crash_console_init
+ mov_imm x0, PLAT_SQ_BOOT_UART_BASE
+ mov_imm x1, PLAT_SQ_BOOT_UART_CLK_IN_HZ
+ mov_imm x2, SQ_CONSOLE_BAUDRATE
+ b console_pl011_core_init
+endfunc plat_crash_console_init
+
+/*
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_SQ_BOOT_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+/*
+ * void plat_crash_console_flush(int c)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ */
+func plat_crash_console_flush
+ mov_imm x0, PLAT_SQ_BOOT_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/socionext/synquacer/sq_image_desc.c b/plat/socionext/synquacer/sq_image_desc.c
new file mode 100644
index 0000000..5fe125b
--- /dev/null
+++ b/plat/socionext/synquacer/sq_image_desc.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch.h>
+#include <common/desc_image_load.h>
+
+#include <platform_def.h>
+
+static struct bl_mem_params_node sq_image_descs[] = {
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL31_BASE,
+ .image_info.image_max_size = BL31_SIZE,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = BL31_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ .next_handoff_image_id = BL32_IMAGE_ID,
+ },
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = BL32_BASE,
+ .image_info.image_max_size = BL32_SIZE,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE),
+ .ep_info.pc = BL32_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+ {
+ .image_id = BL33_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = PLAT_SQ_BL33_BASE,
+ .image_info.image_max_size = PLAT_SQ_BL33_SIZE,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+ .ep_info.pc = PLAT_SQ_BL33_BASE,
+ .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+};
+REGISTER_BL_IMAGE_DESCS(sq_image_descs)
+
+struct image_info *sq_get_image_info(unsigned int image_id)
+{
+ struct bl_mem_params_node *desc;
+
+ desc = get_bl_mem_params_node(image_id);
+ assert(desc);
+ return &desc->image_info;
+}
diff --git a/plat/socionext/synquacer/sq_io_storage.c b/plat/socionext/synquacer/sq_io_storage.c
new file mode 100644
index 0000000..ea83dad
--- /dev/null
+++ b/plat/socionext/synquacer/sq_io_storage.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <sq_common.h>
+
+static const io_dev_connector_t *sq_fip_dev_con;
+static uintptr_t sq_fip_dev_handle;
+
+static const io_dev_connector_t *sq_backend_dev_con;
+static uintptr_t sq_backend_dev_handle;
+
+static io_block_spec_t sq_fip_spec = {
+ .offset = PLAT_SQ_FIP_IOBASE, /* FIP Image is at 5MB offset on memory-mapped NOR flash */
+ .length = PLAT_SQ_FIP_MAXSIZE, /* Expected maximum FIP image size */
+};
+
+static const io_uuid_spec_t sq_bl2_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t sq_bl31_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t sq_bl32_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t sq_bl33_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t sq_tb_fw_cert_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t sq_trusted_key_cert_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t sq_soc_fw_key_cert_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t sq_tos_fw_key_cert_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t sq_nt_fw_key_cert_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t sq_soc_fw_cert_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t sq_tos_fw_cert_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t sq_nt_fw_cert_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+struct sq_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ uintptr_t init_params;
+};
+
+static const struct sq_io_policy sq_io_policies[] = {
+ [FIP_IMAGE_ID] = {
+ .dev_handle = &sq_backend_dev_handle,
+ .image_spec = (uintptr_t)&sq_fip_spec,
+ },
+ [BL2_IMAGE_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_bl2_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [BL31_IMAGE_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_bl31_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [BL32_IMAGE_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_bl32_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [BL33_IMAGE_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_bl33_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_tb_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_trusted_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_soc_fw_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_tos_fw_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_nt_fw_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_soc_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_tos_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ .dev_handle = &sq_fip_dev_handle,
+ .image_spec = (uintptr_t)&sq_nt_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+#endif
+};
+
+static int sq_update_fip_spec(void)
+{
+ uint32_t boot_index;
+ int ret;
+
+ ret = mmap_add_dynamic_region(PLAT_SQ_BOOTIDX_BASE, PLAT_SQ_BOOTIDX_BASE,
+ PAGE_SIZE, MT_RO_DATA | MT_SECURE);
+ if (ret) {
+ return ret;
+ }
+
+ boot_index = mmio_read_32(PLAT_SQ_BOOTIDX_BASE);
+ if (boot_index < PLAT_SQ_MAX_BOOT_INDEX) {
+ sq_fip_spec.offset += PLAT_SQ_FIP_MAXSIZE * boot_index;
+ INFO("FWU Enabled: boot_index %d\n", boot_index);
+ } else {
+ WARN("FWU Disabled: wrong boot_index value. Fallback to index 0.\n");
+ }
+
+ mmap_remove_dynamic_region(PLAT_SQ_BOOTIDX_BASE, PAGE_SIZE);
+ return 0;
+}
+
+static int sq_io_memmap_setup(void)
+{
+ int ret;
+
+ ret = sq_update_fip_spec();
+ if (ret) {
+ return ret;
+ }
+
+ ret = mmap_add_dynamic_region(sq_fip_spec.offset, sq_fip_spec.offset,
+ sq_fip_spec.length, MT_RO_DATA | MT_SECURE);
+ if (ret) {
+ return ret;
+ }
+
+ ret = register_io_dev_memmap(&sq_backend_dev_con);
+ if (ret) {
+ return ret;
+ }
+
+ return io_dev_open(sq_backend_dev_con, 0, &sq_backend_dev_handle);
+}
+
+static int sq_io_fip_setup(void)
+{
+ int ret;
+
+ ret = register_io_dev_fip(&sq_fip_dev_con);
+ if (ret) {
+ return ret;
+ }
+
+ return io_dev_open(sq_fip_dev_con, 0, &sq_fip_dev_handle);
+}
+
+int sq_io_setup(void)
+{
+ int ret;
+
+ ret = sq_io_memmap_setup();
+ if (ret) {
+ return ret;
+ }
+
+ ret = sq_io_fip_setup();
+ if (ret) {
+ return ret;
+ }
+
+ return 0;
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ uintptr_t init_params;
+
+ assert(image_id < ARRAY_SIZE(sq_io_policies));
+
+ *dev_handle = *sq_io_policies[image_id].dev_handle;
+ *image_spec = sq_io_policies[image_id].image_spec;
+ init_params = sq_io_policies[image_id].init_params;
+
+ return io_dev_init(*dev_handle, init_params);
+}
diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c
new file mode 100644
index 0000000..017516f
--- /dev/null
+++ b/plat/socionext/synquacer/sq_psci.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/cassert.h>
+#include <lib/psci/psci.h>
+
+#include <sq_common.h>
+#include "sq_scpi.h"
+
+uintptr_t sq_sec_entrypoint;
+
+int sq_pwr_domain_on(u_register_t mpidr)
+{
+#if SQ_USE_SCMI_DRIVER
+ sq_scmi_on(mpidr);
+#else
+ /*
+ * SCP takes care of powering up parent power domains so we
+ * only need to care about level 0
+ */
+ scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on,
+ scpi_power_on);
+#endif
+
+ return PSCI_E_SUCCESS;
+}
+
+static void sq_pwr_domain_on_finisher_common(
+ const psci_power_state_t *target_state)
+{
+ assert(SQ_CORE_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF);
+
+ /*
+ * Perform the common cluster specific operations i.e enable coherency
+ * if this cluster was off.
+ */
+ if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
+ plat_sq_interconnect_enter_coherency();
+}
+
+void sq_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* Assert that the system power domain need not be initialized */
+ assert(SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_RUN);
+
+ sq_pwr_domain_on_finisher_common(target_state);
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ sq_gic_pcpu_init();
+
+ /* Enable the gic cpu interface */
+ sq_gic_cpuif_enable();
+}
+
+#if !SQ_USE_SCMI_DRIVER
+static void sq_power_down_common(const psci_power_state_t *target_state)
+{
+ uint32_t cluster_state = scpi_power_on;
+ uint32_t system_state = scpi_power_on;
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ sq_gic_cpuif_disable();
+
+ /* Check if power down at system power domain level is requested */
+ if (SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
+ system_state = scpi_power_retention;
+
+ /* Cluster is to be turned off, so disable coherency */
+ if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
+ plat_sq_interconnect_exit_coherency();
+ cluster_state = scpi_power_off;
+ }
+
+ /*
+ * Ask the SCP to power down the appropriate components depending upon
+ * their state.
+ */
+ scpi_set_sq_power_state(read_mpidr_el1(),
+ scpi_power_off,
+ cluster_state,
+ system_state);
+}
+#endif
+
+void sq_pwr_domain_off(const psci_power_state_t *target_state)
+{
+#if SQ_USE_SCMI_DRIVER
+ /* Prevent interrupts from spuriously waking up this cpu */
+ sq_gic_cpuif_disable();
+
+ /* Cluster is to be turned off, so disable coherency */
+ if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
+ plat_sq_interconnect_exit_coherency();
+ }
+
+ sq_scmi_off(target_state);
+#else
+ sq_power_down_common(target_state);
+#endif
+}
+
+void __dead2 sq_system_off(void)
+{
+#if SQ_USE_SCMI_DRIVER
+ sq_scmi_sys_shutdown();
+#else
+ volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE;
+
+ /* set PD[9] high to power off the system */
+ gpio[5] |= 0x2; /* set output */
+ gpio[1] |= 0x2; /* set high */
+ dmbst();
+
+ generic_delay_timer_init();
+
+ mdelay(1);
+
+ while (1) {
+ gpio[1] &= ~0x2; /* set low */
+ dmbst();
+
+ mdelay(1);
+
+ gpio[1] |= 0x2; /* set high */
+ dmbst();
+
+ mdelay(100);
+ }
+
+ wfi();
+ ERROR("SQ System Off: operation not handled.\n");
+ panic();
+#endif
+}
+
+void __dead2 sq_system_reset(void)
+{
+#if SQ_USE_SCMI_DRIVER
+ sq_scmi_sys_reboot();
+#else
+ uint32_t response;
+
+ /* Send the system reset request to the SCP */
+ response = scpi_sys_power_state(scpi_system_reboot);
+
+ if (response != SCP_OK) {
+ ERROR("SQ System Reset: SCP error %u.\n", response);
+ panic();
+ }
+ wfi();
+ ERROR("SQ System Reset: operation not handled.\n");
+ panic();
+#endif
+}
+
+void sq_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr;
+
+ assert(cpu_state == SQ_LOCAL_STATE_RET);
+
+ scr = read_scr_el3();
+ /* Enable PhysicalIRQ bit for NS world to wake the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT);
+ isb();
+ dsb();
+ wfi();
+
+ /*
+ * Restore SCR to the original value, synchronisation of scr_el3 is
+ * done by eret while el3_exit to save some execution cycles.
+ */
+ write_scr_el3(scr);
+}
+
+const plat_psci_ops_t sq_psci_ops = {
+ .pwr_domain_on = sq_pwr_domain_on,
+ .pwr_domain_off = sq_pwr_domain_off,
+ .pwr_domain_on_finish = sq_pwr_domain_on_finish,
+ .cpu_standby = sq_cpu_standby,
+ .system_off = sq_system_off,
+ .system_reset = sq_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+#if !RESET_TO_BL31
+ uintptr_t *sq_sec_ep = (uintptr_t *)BL2_MAILBOX_BASE;
+
+ *sq_sec_ep = sec_entrypoint;
+ flush_dcache_range((uint64_t)sq_sec_ep,
+ sizeof(*sq_sec_ep));
+#else
+ sq_sec_entrypoint = sec_entrypoint;
+ flush_dcache_range((uint64_t)&sq_sec_entrypoint,
+ sizeof(sq_sec_entrypoint));
+#endif
+
+ *psci_ops = &sq_psci_ops;
+
+ return 0;
+}
diff --git a/plat/socionext/synquacer/sq_rotpk.S b/plat/socionext/synquacer/sq_rotpk.S
new file mode 100644
index 0000000..61227ed
--- /dev/null
+++ b/plat/socionext/synquacer/sq_rotpk.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global sq_rotpk_hash
+ .global sq_rotpk_hash_end
+ .section .rodata.sq_rotpk_hash, "a"
+sq_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+sq_rotpk_hash_end:
diff --git a/plat/socionext/synquacer/sq_spm.c b/plat/socionext/synquacer/sq_spm.c
new file mode 100644
index 0000000..7bea111
--- /dev/null
+++ b/plat/socionext/synquacer/sq_spm.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <bl31/ehf.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <services/spm_mm_partition.h>
+
+static const mmap_region_t plat_arm_secure_partition_mmap[] = {
+ PLAT_SQ_FLASH_MMAP,
+ PLAT_SQ_UART1_MMAP,
+ PLAT_SQ_PERIPH_MMAP,
+ PLAT_SQ_SP_IMAGE_MMAP,
+ PLAT_SP_IMAGE_NS_BUF_MMAP,
+ PLAT_SQ_SP_IMAGE_RW_MMAP,
+ PLAT_SPM_SPM_BUF_EL0_MMAP,
+ {0}
+};
+
+/*
+ * Boot information passed to a secure partition during initialisation. Linear
+ * indices in MP information will be filled at runtime.
+ */
+static spm_mm_mp_info_t sp_mp_info[] = {
+ {0x80000000, 0}, {0x80000001, 0}, {0x80000100, 0}, {0x80000101, 0},
+ {0x80000200, 0}, {0x80000201, 0}, {0x80000300, 0}, {0x80000301, 0},
+ {0x80000400, 0}, {0x80000401, 0}, {0x80000500, 0}, {0x80000501, 0},
+ {0x80000600, 0}, {0x80000601, 0}, {0x80000700, 0}, {0x80000701, 0},
+ {0x80000800, 0}, {0x80000801, 0}, {0x80000900, 0}, {0x80000901, 0},
+ {0x80000a00, 0}, {0x80000a01, 0}, {0x80000b00, 0}, {0x80000b01, 0},
+};
+
+const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
+ .h.type = PARAM_SP_IMAGE_BOOT_INFO,
+ .h.version = VERSION_1,
+ .h.size = sizeof(spm_mm_boot_info_t),
+ .h.attr = 0,
+ .sp_mem_base = BL32_BASE,
+ .sp_mem_limit = BL32_LIMIT,
+ .sp_image_base = BL32_BASE,
+ .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
+ .sp_heap_base = PLAT_SQ_SP_HEAP_BASE,
+ .sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
+ .sp_shared_buf_base = PLAT_SPM_BUF_BASE,
+ .sp_image_size = PLAT_SQ_SP_IMAGE_SIZE,
+ .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+ .sp_heap_size = PLAT_SQ_SP_HEAP_SIZE,
+ .sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
+ .sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
+ .num_sp_mem_regions = PLAT_SP_IMAGE_NUM_MEM_REGIONS,
+ .num_cpus = PLATFORM_CORE_COUNT,
+ .mp_info = sp_mp_info,
+};
+
+const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
+{
+ return plat_arm_secure_partition_mmap;
+}
+
+const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
+ void *cookie)
+{
+ return &plat_arm_secure_partition_boot_info;
+}
+
+static ehf_pri_desc_t sq_exceptions[] = {
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
+};
+EHF_REGISTER_PRIORITIES(sq_exceptions, ARRAY_SIZE(sq_exceptions), PLAT_PRI_BITS);
diff --git a/plat/socionext/synquacer/sq_tbbr.c b/plat/socionext/synquacer/sq_tbbr.c
new file mode 100644
index 0000000..e9fa18c
--- /dev/null
+++ b/plat/socionext/synquacer/sq_tbbr.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char sq_rotpk_hash[], sq_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = sq_rotpk_hash;
+ *key_len = sq_rotpk_hash_end - sq_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ /*
+ * No support for non-volatile counter. Update the ROT key to protect
+ * the system against rollback.
+ */
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 0;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/socionext/synquacer/sq_topology.c b/plat/socionext/synquacer/sq_topology.c
new file mode 100644
index 0000000..359997a
--- /dev/null
+++ b/plat/socionext/synquacer/sq_topology.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+
+#include <sq_common.h>
+
+unsigned char sq_pd_tree_desc[PLAT_CLUSTER_COUNT + 1];
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ if (cluster_id >= PLAT_CLUSTER_COUNT)
+ return -1;
+
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+ if (cpu_id >= PLAT_MAX_CORES_PER_CLUSTER)
+ return -1;
+
+ return sq_calc_core_pos(mpidr);
+}
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ int i;
+
+ sq_pd_tree_desc[0] = PLAT_CLUSTER_COUNT;
+
+ for (i = 0; i < PLAT_CLUSTER_COUNT; i++)
+ sq_pd_tree_desc[i + 1] = PLAT_MAX_CORES_PER_CLUSTER;
+
+ return sq_pd_tree_desc;
+}
diff --git a/plat/socionext/synquacer/sq_xlat_setup.c b/plat/socionext/synquacer/sq_xlat_setup.c
new file mode 100644
index 0000000..5d1669d
--- /dev/null
+++ b/plat/socionext/synquacer/sq_xlat_setup.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#define SQ_REG_REGION_BASE 0x20000000ULL
+#define SQ_REG_REGION_SIZE 0x60000000ULL
+
+void sq_mmap_setup(uintptr_t total_base, size_t total_size,
+ const struct mmap_region *mmap)
+{
+ VERBOSE("Trusted RAM seen by this BL image: %p - %p\n",
+ (void *)total_base, (void *)(total_base + total_size));
+ mmap_add_region(total_base, total_base,
+ total_size,
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE);
+
+ /* remap the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *)BL_CODE_BASE, (void *)BL_CODE_END);
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE,
+ MT_NON_CACHEABLE | MT_RO | MT_SECURE);
+
+ /* Re-map the read-only data section */
+ VERBOSE("Read-only data region: %p - %p\n",
+ (void *)BL_RO_DATA_BASE, (void *)BL_RO_DATA_END);
+ mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
+ round_up(BL_RO_DATA_END, PAGE_SIZE) - BL_RO_DATA_BASE,
+ (MT_NON_CACHEABLE | MT_RO | MT_EXECUTE_NEVER |
+ MT_SECURE));
+
+ /* remap the coherent memory region */
+ VERBOSE("Coherent region: %p - %p\n",
+ (void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END);
+ mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+
+ /* register region */
+ mmap_add_region(SQ_REG_REGION_BASE, SQ_REG_REGION_BASE,
+ SQ_REG_REGION_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+
+ /* additional regions if needed */
+ if (mmap)
+ mmap_add(mmap);
+
+ init_xlat_tables();
+}
diff --git a/plat/socionext/uniphier/include/plat_macros.S b/plat/socionext/uniphier/include/plat_macros.S
new file mode 100644
index 0000000..d6d2579
--- /dev/null
+++ b/plat/socionext/uniphier/include/plat_macros.S
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/socionext/uniphier/include/platform_def.h b/plat/socionext/uniphier/include/platform_def.h
new file mode 100644
index 0000000..b23386d
--- /dev/null
+++ b/plat/socionext/uniphier/include/platform_def.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_STACK_SIZE 0x1000
+
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << (CACHE_WRITEBACK_SHIFT))
+
+/* topology */
+#define UNIPHIER_MAX_CPUS_PER_CLUSTER U(4)
+#define UNIPHIER_CLUSTER_COUNT U(2)
+
+#define PLATFORM_CORE_COUNT \
+ ((UNIPHIER_MAX_CPUS_PER_CLUSTER) * (UNIPHIER_CLUSTER_COUNT))
+
+#define PLAT_MAX_PWR_LVL U(1)
+
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define UNIPHIER_BL2_OFFSET UL(0x00000000)
+#define UNIPHIER_BL2_MAX_SIZE UL(0x00080000)
+
+/* 0x00080000-0x01000000: reserved for DSP */
+
+#define UNIPHIER_BL31_OFFSET UL(0x01000000)
+#define UNIPHIER_BL31_MAX_SIZE UL(0x00080000)
+
+#define UNIPHIER_BL32_OFFSET UL(0x01080000)
+#define UNIPHIER_BL32_MAX_SIZE UL(0x00100000)
+
+/*
+ * The link addresses are determined by UNIPHIER_MEM_BASE + offset.
+ * When ENABLE_PIE is set, all the TF images can be loaded anywhere, so
+ * UNIPHIER_MEM_BASE is arbitrary.
+ *
+ * When ENABLE_PIE is unset, UNIPHIER_MEM_BASE should be chosen so that
+ * BL2_BASE matches to the physical address where BL2 is loaded, that is,
+ * UNIPHIER_MEM_BASE should be the base address of the DRAM region.
+ */
+#define UNIPHIER_MEM_BASE UL(0x00000000)
+
+#define BL2_BASE (UNIPHIER_MEM_BASE + UNIPHIER_BL2_OFFSET)
+#define BL2_LIMIT (BL2_BASE + UNIPHIER_BL2_MAX_SIZE)
+
+#define BL31_BASE (UNIPHIER_MEM_BASE + UNIPHIER_BL31_OFFSET)
+#define BL31_LIMIT (BL31_BASE + UNIPHIER_BL31_MAX_SIZE)
+
+#define BL32_BASE (UNIPHIER_MEM_BASE + UNIPHIER_BL32_OFFSET)
+#define BL32_LIMIT (BL32_BASE + UNIPHIER_BL32_MAX_SIZE)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+
+#define MAX_XLAT_TABLES 9
+#define MAX_MMAP_REGIONS 13
+
+#define MAX_IO_HANDLES 2
+#define MAX_IO_DEVICES 2
+#define MAX_IO_BLOCK_DEVICES U(1)
+
+#define TSP_SEC_MEM_BASE (BL32_BASE)
+#define TSP_SEC_MEM_SIZE ((BL32_LIMIT) - (BL32_BASE))
+#define TSP_IRQ_SEC_PHY_TIMER 29
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
new file mode 100644
index 0000000..378497a
--- /dev/null
+++ b/plat/socionext/uniphier/platform.mk
@@ -0,0 +1,140 @@
+#
+# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+override BL2_AT_EL3 := 1
+override COLD_BOOT_SINGLE_CPU := 1
+override PROGRAMMABLE_RESET_ADDRESS := 1
+override USE_COHERENT_MEM := 1
+override ENABLE_SVE_FOR_NS := 0
+
+# Disabling ENABLE_PIE saves memory footprint a lot, but you need to adjust
+# UNIPHIER_MEM_BASE so that all TF images are loaded at their link addresses.
+override ENABLE_PIE := 1
+
+ALLOW_RO_XLAT_TABLES := 1
+
+ifeq ($(ALLOW_RO_XLAT_TABLES),1)
+BL31_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
+BL32_CPPFLAGS += -DPLAT_RO_XLAT_TABLES
+endif
+
+# The dynamic xlat table is only used in BL2
+BL2_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
+
+# Cortex-A53 revision r0p4-51rel0
+# needed for LD20, unneeded for LD11, PXs3 (no ACE)
+ERRATA_A53_855873 := 1
+
+FIP_ALIGN := 512
+
+ifeq ($(NEED_BL32),yes)
+$(eval $(call add_define,UNIPHIER_LOAD_BL32))
+endif
+
+# Libraries
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_PATH := plat/socionext/uniphier
+PLAT_INCLUDES := -I$(PLAT_PATH)/include
+
+# common sources for BL2, BL31 (and BL32 if SPD=tspd)
+PLAT_BL_COMMON_SOURCES += plat/common/aarch64/crash_console_helpers.S \
+ $(PLAT_PATH)/uniphier_console.S \
+ $(PLAT_PATH)/uniphier_console_setup.c \
+ $(PLAT_PATH)/uniphier_helpers.S \
+ $(PLAT_PATH)/uniphier_soc_info.c \
+ $(PLAT_PATH)/uniphier_xlat_setup.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+BL2_SOURCES += common/desc_image_load.c \
+ drivers/io/io_block.c \
+ drivers/io/io_fip.c \
+ drivers/io/io_memmap.c \
+ drivers/io/io_storage.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ $(PLAT_PATH)/uniphier_bl2_setup.c \
+ $(PLAT_PATH)/uniphier_boot_device.c \
+ $(PLAT_PATH)/uniphier_emmc.c \
+ $(PLAT_PATH)/uniphier_image_desc.c \
+ $(PLAT_PATH)/uniphier_io_storage.c \
+ $(PLAT_PATH)/uniphier_nand.c \
+ $(PLAT_PATH)/uniphier_scp.c \
+ $(PLAT_PATH)/uniphier_usb.c
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+BL31_SOURCES += drivers/arm/cci/cci.c \
+ ${GICV3_SOURCES} \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ plat/common/plat_gicv3.c \
+ plat/common/plat_psci_common.c \
+ $(PLAT_PATH)/uniphier_bl31_setup.c \
+ $(PLAT_PATH)/uniphier_boot_device.c \
+ $(PLAT_PATH)/uniphier_cci.c \
+ $(PLAT_PATH)/uniphier_gicv3.c \
+ $(PLAT_PATH)/uniphier_psci.c \
+ $(PLAT_PATH)/uniphier_scp.c \
+ $(PLAT_PATH)/uniphier_smp.S \
+ $(PLAT_PATH)/uniphier_syscnt.c \
+ $(PLAT_PATH)/uniphier_topology.c
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+BL2_SOURCES += drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot_common.c \
+ drivers/auth/tbbr/tbbr_cot_bl2.c \
+ plat/common/tbbr/plat_tbbr.c \
+ $(PLAT_PATH)/uniphier_rotpk.S \
+ $(PLAT_PATH)/uniphier_tbbr.c
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/uniphier_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ ${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
+
+endif
+
+ifeq (${FIP_GZIP},1)
+
+include lib/zlib/zlib.mk
+
+BL2_SOURCES += common/image_decompress.c \
+ $(ZLIB_SOURCES)
+
+$(eval $(call add_define,UNIPHIER_DECOMPRESS_GZIP))
+
+# compress all images loaded by BL2
+SCP_BL2_PRE_TOOL_FILTER := GZIP
+BL31_PRE_TOOL_FILTER := GZIP
+BL32_PRE_TOOL_FILTER := GZIP
+BL33_PRE_TOOL_FILTER := GZIP
+
+endif
+
+.PHONY: bl2_gzip
+bl2_gzip: $(BUILD_PLAT)/bl2.bin.gz
+%.gz: %
+ @echo " GZIP $@"
+ $(Q)gzip -n -f -9 $< --stdout > $@
diff --git a/plat/socionext/uniphier/tsp/tsp-uniphier.mk b/plat/socionext/uniphier/tsp/tsp-uniphier.mk
new file mode 100644
index 0000000..54d4f51
--- /dev/null
+++ b/plat/socionext/uniphier/tsp/tsp-uniphier.mk
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_SOURCES += plat/common/plat_gicv3.c \
+ plat/common/aarch64/platform_mp_stack.S \
+ $(PLAT_PATH)/tsp/uniphier_tsp_setup.c
diff --git a/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
new file mode 100644
index 0000000..4bbb259
--- /dev/null
+++ b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <plat/common/platform.h>
+
+#include "../uniphier.h"
+
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
+
+void tsp_early_platform_setup(void)
+{
+ uniphier_soc = uniphier_get_soc_id();
+ if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+ plat_error_handler(-ENOTSUP);
+
+ uniphier_console_setup(uniphier_soc);
+}
+
+void tsp_platform_setup(void)
+{
+}
+
+void tsp_plat_arch_setup(void)
+{
+ uniphier_mmap_setup(uniphier_soc);
+}
diff --git a/plat/socionext/uniphier/uniphier.h b/plat/socionext/uniphier/uniphier.h
new file mode 100644
index 0000000..ee520ad
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UNIPHIER_H
+#define UNIPHIER_H
+
+#include <stdint.h>
+#include <string.h>
+
+unsigned int uniphier_get_soc_type(void);
+unsigned int uniphier_get_soc_model(void);
+unsigned int uniphier_get_soc_revision(void);
+unsigned int uniphier_get_soc_id(void);
+
+#define UNIPHIER_SOC_LD11 0
+#define UNIPHIER_SOC_LD20 1
+#define UNIPHIER_SOC_PXS3 2
+#define UNIPHIER_SOC_UNKNOWN 0xffffffff
+
+unsigned int uniphier_get_boot_device(unsigned int soc);
+
+#define UNIPHIER_BOOT_DEVICE_EMMC 0
+#define UNIPHIER_BOOT_DEVICE_NAND 1
+#define UNIPHIER_BOOT_DEVICE_NOR 2
+#define UNIPHIER_BOOT_DEVICE_SD 3
+#define UNIPHIER_BOOT_DEVICE_USB 4
+#define UNIPHIER_BOOT_DEVICE_RSV 0xffffffff
+
+unsigned int uniphier_get_boot_master(unsigned int soc);
+
+#define UNIPHIER_BOOT_MASTER_THIS 0
+#define UNIPHIER_BOOT_MASTER_SCP 1
+#define UNIPHIER_BOOT_MASTER_EXT 2
+
+void uniphier_console_setup(unsigned int soc);
+
+struct io_block_dev_spec;
+int uniphier_emmc_init(unsigned int soc,
+ struct io_block_dev_spec **block_dev_spec);
+int uniphier_nand_init(unsigned int soc,
+ struct io_block_dev_spec **block_dev_spec);
+int uniphier_usb_init(unsigned int soc,
+ struct io_block_dev_spec **block_dev_spec);
+
+int uniphier_io_setup(unsigned int soc, uintptr_t mem_base);
+
+void uniphier_init_image_descs(uintptr_t mem_base);
+struct image_info;
+struct image_info *uniphier_get_image_info(unsigned int image_id);
+
+int uniphier_scp_is_running(void);
+void uniphier_scp_start(uint32_t scp_base);
+void uniphier_scp_open_com(void);
+void uniphier_scp_system_off(void);
+void uniphier_scp_system_reset(void);
+
+void uniphier_mmap_setup(unsigned int soc);
+
+void uniphier_cci_init(unsigned int soc);
+void uniphier_cci_enable(void);
+void uniphier_cci_disable(void);
+
+void uniphier_gic_driver_init(unsigned int soc);
+void uniphier_gic_init(void);
+void uniphier_gic_cpuif_enable(void);
+void uniphier_gic_cpuif_disable(void);
+void uniphier_gic_pcpu_init(void);
+
+void uniphier_psci_init(unsigned int soc);
+
+unsigned int uniphier_calc_core_pos(u_register_t mpidr);
+
+#endif /* UNIPHIER_H */
diff --git a/plat/socionext/uniphier/uniphier_bl2_setup.c b/plat/socionext/uniphier/uniphier_bl2_setup.c
new file mode 100644
index 0000000..4524610
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_bl2_setup.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/image_decompress.h>
+#include <drivers/io/io_storage.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+#ifdef UNIPHIER_DECOMPRESS_GZIP
+#include <tf_gunzip.h>
+#endif
+
+#include "uniphier.h"
+
+#define UNIPHIER_IMAGE_BUF_OFFSET 0x03800000UL
+#define UNIPHIER_IMAGE_BUF_SIZE 0x00800000UL
+
+static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE;
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
+static int uniphier_bl2_kick_scp;
+
+void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
+ u_register_t x2, u_register_t x3)
+{
+ uniphier_soc = uniphier_get_soc_id();
+ if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+ plat_error_handler(-ENOTSUP);
+
+ uniphier_console_setup(uniphier_soc);
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+ int skip_scp = 0;
+ int ret;
+
+ uniphier_mmap_setup(uniphier_soc);
+
+ /* add relocation offset (run-time-address - link-address) */
+ uniphier_mem_base += BL_CODE_BASE - BL2_BASE;
+
+ ret = uniphier_io_setup(uniphier_soc, uniphier_mem_base);
+ if (ret) {
+ ERROR("failed to setup io devices\n");
+ plat_error_handler(ret);
+ }
+
+ switch (uniphier_get_boot_master(uniphier_soc)) {
+ case UNIPHIER_BOOT_MASTER_THIS:
+ INFO("Booting from this SoC\n");
+ skip_scp = 1;
+ break;
+ case UNIPHIER_BOOT_MASTER_SCP:
+ INFO("Booting from on-chip SCP\n");
+ if (uniphier_scp_is_running()) {
+ INFO("SCP is already running. SCP_BL2 load will be skipped.\n");
+ skip_scp = 1;
+ }
+
+ /*
+ * SCP must be kicked every time even if it is already running
+ * because it polls this event after the reboot of the backend.
+ */
+ uniphier_bl2_kick_scp = 1;
+ break;
+ case UNIPHIER_BOOT_MASTER_EXT:
+ INFO("Booting from external SCP\n");
+ skip_scp = 1;
+ break;
+ default:
+ plat_error_handler(-ENOTSUP);
+ break;
+ }
+
+ if (skip_scp) {
+ struct image_info *image_info;
+
+ image_info = uniphier_get_image_info(SCP_BL2_IMAGE_ID);
+ image_info->h.attr |= IMAGE_ATTRIB_SKIP_LOADING;
+ }
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+bl_params_t *plat_get_next_bl_params(void)
+{
+ return get_next_bl_params_from_mem_params_desc();
+}
+
+void bl2_plat_preload_setup(void)
+{
+#ifdef UNIPHIER_DECOMPRESS_GZIP
+ uintptr_t buf_base = uniphier_mem_base + UNIPHIER_IMAGE_BUF_OFFSET;
+ int ret;
+
+ ret = mmap_add_dynamic_region(buf_base, buf_base,
+ UNIPHIER_IMAGE_BUF_SIZE,
+ MT_MEMORY | MT_RW | MT_NS);
+ if (ret)
+ plat_error_handler(ret);
+
+ image_decompress_init(buf_base, UNIPHIER_IMAGE_BUF_SIZE, gunzip);
+#endif
+
+ uniphier_init_image_descs(uniphier_mem_base);
+}
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ struct image_info *image_info;
+ int ret;
+
+ image_info = uniphier_get_image_info(image_id);
+
+ ret = mmap_add_dynamic_region(image_info->image_base,
+ image_info->image_base,
+ image_info->image_max_size,
+ MT_MEMORY | MT_RW | MT_NS);
+ if (ret)
+ return ret;
+
+#ifdef UNIPHIER_DECOMPRESS_GZIP
+ image_decompress_prepare(image_info);
+#endif
+ return 0;
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ struct image_info *image_info = uniphier_get_image_info(image_id);
+#ifdef UNIPHIER_DECOMPRESS_GZIP
+ int ret;
+
+ if (!(image_info->h.attr & IMAGE_ATTRIB_SKIP_LOADING)) {
+ ret = image_decompress(uniphier_get_image_info(image_id));
+ if (ret)
+ return ret;
+ }
+#endif
+
+ if (image_id == SCP_BL2_IMAGE_ID && uniphier_bl2_kick_scp)
+ uniphier_scp_start(image_info->image_base);
+
+ return 0;
+}
diff --git a/plat/socionext/uniphier/uniphier_bl31_setup.c b/plat/socionext/uniphier/uniphier_bl31_setup.c
new file mode 100644
index 0000000..c2baebd
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_bl31_setup.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "uniphier.h"
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ assert(sec_state_is_valid(type));
+ return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info;
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ void *from_bl2;
+
+ from_bl2 = (void *)arg0;
+
+ bl_params_node_t *bl_params = ((bl_params_t *)from_bl2)->head;
+
+ uniphier_soc = uniphier_get_soc_id();
+ if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+ plat_error_handler(-ENOTSUP);
+
+ uniphier_console_setup(uniphier_soc);
+
+ while (bl_params) {
+ if (bl_params->image_id == BL32_IMAGE_ID)
+ bl32_image_ep_info = *bl_params->ep_info;
+
+ if (bl_params->image_id == BL33_IMAGE_ID)
+ bl33_image_ep_info = *bl_params->ep_info;
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (bl33_image_ep_info.pc == 0)
+ panic();
+}
+
+static const uintptr_t uniphier_cntctl_base[] = {
+ [UNIPHIER_SOC_LD11] = 0x60e00000,
+ [UNIPHIER_SOC_LD20] = 0x60e00000,
+ [UNIPHIER_SOC_PXS3] = 0x60e00000,
+};
+
+void bl31_platform_setup(void)
+{
+ uintptr_t cntctl_base;
+
+ uniphier_cci_init(uniphier_soc);
+ uniphier_cci_enable();
+
+ /* Initialize the GIC driver, cpu and distributor interfaces */
+ uniphier_gic_driver_init(uniphier_soc);
+ uniphier_gic_init();
+
+ assert(uniphier_soc < ARRAY_SIZE(uniphier_cntctl_base));
+ cntctl_base = uniphier_cntctl_base[uniphier_soc];
+
+ /* Enable and initialize the System level generic timer */
+ mmio_write_32(cntctl_base + CNTCR_OFF, CNTCR_FCREQ(0U) | CNTCR_EN);
+
+ uniphier_psci_init(uniphier_soc);
+}
+
+void bl31_plat_arch_setup(void)
+{
+ uniphier_mmap_setup(uniphier_soc);
+}
diff --git a/plat/socionext/uniphier/uniphier_boot_device.c b/plat/socionext/uniphier/uniphier_boot_device.c
new file mode 100644
index 0000000..36a9908
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_boot_device.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_PINMON0 0x0
+#define UNIPHIER_PINMON2 0x8
+
+static const uintptr_t uniphier_pinmon_base[] = {
+ [UNIPHIER_SOC_LD11] = 0x5f900100,
+ [UNIPHIER_SOC_LD20] = 0x5f900100,
+ [UNIPHIER_SOC_PXS3] = 0x5f900100,
+};
+
+static bool uniphier_ld11_is_usb_boot(uint32_t pinmon)
+{
+ return !!(~pinmon & 0x00000080);
+}
+
+static bool uniphier_ld20_is_usb_boot(uint32_t pinmon)
+{
+ return !!(~pinmon & 0x00000780);
+}
+
+static bool uniphier_pxs3_is_usb_boot(uint32_t pinmon)
+{
+ uintptr_t pinmon_base = uniphier_pinmon_base[UNIPHIER_SOC_PXS3];
+ uint32_t pinmon2 = mmio_read_32(pinmon_base + UNIPHIER_PINMON2);
+
+ return !!(pinmon2 & BIT(31));
+}
+
+static const unsigned int uniphier_ld11_boot_device_table[] = {
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_NOR,
+};
+
+static unsigned int uniphier_ld11_get_boot_device(uint32_t pinmon)
+{
+ unsigned int boot_sel = (pinmon >> 1) & 0x1f;
+
+ assert(boot_sel < ARRAY_SIZE(uniphier_ld11_boot_device_table));
+
+ return uniphier_ld11_boot_device_table[boot_sel];
+}
+
+static const unsigned int uniphier_pxs3_boot_device_table[] = {
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_EMMC,
+ UNIPHIER_BOOT_DEVICE_NAND,
+ UNIPHIER_BOOT_DEVICE_NAND,
+};
+
+static unsigned int uniphier_pxs3_get_boot_device(uint32_t pinmon)
+{
+ unsigned int boot_sel = (pinmon >> 1) & 0xf;
+
+ assert(boot_sel < ARRAY_SIZE(uniphier_pxs3_boot_device_table));
+
+ return uniphier_pxs3_boot_device_table[boot_sel];
+}
+
+struct uniphier_boot_device_info {
+ bool have_boot_swap;
+ bool (*is_sd_boot)(uint32_t pinmon);
+ bool (*is_usb_boot)(uint32_t pinmon);
+ unsigned int (*get_boot_device)(uint32_t pinmon);
+};
+
+static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
+ [UNIPHIER_SOC_LD11] = {
+ .have_boot_swap = true,
+ .is_usb_boot = uniphier_ld11_is_usb_boot,
+ .get_boot_device = uniphier_ld11_get_boot_device,
+ },
+ [UNIPHIER_SOC_LD20] = {
+ .have_boot_swap = true,
+ .is_usb_boot = uniphier_ld20_is_usb_boot,
+ .get_boot_device = uniphier_ld11_get_boot_device,
+ },
+ [UNIPHIER_SOC_PXS3] = {
+ .have_boot_swap = true,
+ .is_usb_boot = uniphier_pxs3_is_usb_boot,
+ .get_boot_device = uniphier_pxs3_get_boot_device,
+ },
+};
+
+unsigned int uniphier_get_boot_device(unsigned int soc)
+{
+ const struct uniphier_boot_device_info *info;
+ uintptr_t pinmon_base;
+ uint32_t pinmon;
+
+ assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
+ info = &uniphier_boot_device_info[soc];
+
+ assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
+ pinmon_base = uniphier_pinmon_base[soc];
+
+ pinmon = mmio_read_32(pinmon_base + UNIPHIER_PINMON0);
+
+ if (info->have_boot_swap && !(pinmon & BIT(29)))
+ return UNIPHIER_BOOT_DEVICE_NOR;
+
+ if (info->is_sd_boot && info->is_sd_boot(pinmon))
+ return UNIPHIER_BOOT_DEVICE_SD;
+
+ if (info->is_usb_boot && info->is_usb_boot(pinmon))
+ return UNIPHIER_BOOT_DEVICE_USB;
+
+ return info->get_boot_device(pinmon);
+}
+
+static const bool uniphier_have_onchip_scp[] = {
+ [UNIPHIER_SOC_LD11] = true,
+ [UNIPHIER_SOC_LD20] = true,
+ [UNIPHIER_SOC_PXS3] = false,
+};
+
+unsigned int uniphier_get_boot_master(unsigned int soc)
+{
+ assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp));
+
+ if (uniphier_have_onchip_scp[soc]) {
+ uintptr_t pinmon_base;
+
+ assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
+ pinmon_base = uniphier_pinmon_base[soc];
+
+ if (mmio_read_32(pinmon_base + UNIPHIER_PINMON0) & BIT(27))
+ return UNIPHIER_BOOT_MASTER_THIS;
+ else
+ return UNIPHIER_BOOT_MASTER_SCP;
+ } else {
+ return UNIPHIER_BOOT_MASTER_EXT;
+ }
+}
diff --git a/plat/socionext/uniphier/uniphier_cci.c b/plat/socionext/uniphier/uniphier_cci.c
new file mode 100644
index 0000000..3ca1768
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_cci.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <arch_helpers.h>
+#include <drivers/arm/cci.h>
+#include <lib/utils_def.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_CCI500_BASE 0x5FD00000
+
+static const int uniphier_cci_map[] = {1, 0};
+
+static void __uniphier_cci_init(void)
+{
+ cci_init(UNIPHIER_CCI500_BASE, uniphier_cci_map,
+ ARRAY_SIZE(uniphier_cci_map));
+}
+
+static void __uniphier_cci_enable(void)
+{
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+static void __uniphier_cci_disable(void)
+{
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
+}
+
+struct uniphier_cci_ops {
+ void (*init)(void);
+ void (*enable)(void);
+ void (*disable)(void);
+};
+
+static const struct uniphier_cci_ops uniphier_cci_ops_table[] = {
+ [UNIPHIER_SOC_LD11] = {
+ .init = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ },
+ [UNIPHIER_SOC_LD20] = {
+ .init = __uniphier_cci_init,
+ .enable = __uniphier_cci_enable,
+ .disable = __uniphier_cci_disable,
+ },
+ [UNIPHIER_SOC_PXS3] = {
+ .init = NULL,
+ .enable = NULL,
+ .disable = NULL,
+ },
+};
+
+static struct uniphier_cci_ops uniphier_cci_ops;
+
+void uniphier_cci_init(unsigned int soc)
+{
+ uniphier_cci_ops = uniphier_cci_ops_table[soc];
+ flush_dcache_range((uint64_t)&uniphier_cci_ops,
+ sizeof(uniphier_cci_ops));
+
+ if (uniphier_cci_ops.init)
+ uniphier_cci_ops.init();
+}
+
+void uniphier_cci_enable(void)
+{
+ if (uniphier_cci_ops.enable)
+ uniphier_cci_ops.enable();
+}
+
+void uniphier_cci_disable(void)
+{
+ if (uniphier_cci_ops.disable)
+ uniphier_cci_ops.disable();
+}
diff --git a/plat/socionext/uniphier/uniphier_console.S b/plat/socionext/uniphier/uniphier_console.S
new file mode 100644
index 0000000..48927f4
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_console.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <drivers/console.h>
+
+#include "uniphier_console.h"
+
+/*
+ * In: w0 - character to be printed
+ * x1 - pointer to console structure
+ * Out: return the character written (always succeeds)
+ * Clobber: x2
+ */
+ .globl uniphier_console_putc
+func uniphier_console_putc
+ ldr x1, [x1, #CONSOLE_T_BASE]
+
+ /* Wait until the transmitter FIFO gets empty */
+0: ldr w2, [x1, #UNIPHIER_UART_LSR]
+ tbz w2, #UNIPHIER_UART_LSR_THRE_BIT, 0b
+
+ str w0, [x1, #UNIPHIER_UART_TX]
+
+ ret
+endfunc uniphier_console_putc
+
+/*
+ * In: x0 - pointer to console structure
+ * Out: return the character read, or ERROR_NO_PENDING_CHAR if no character
+ is available
+ * Clobber: x1
+ */
+ .globl uniphier_console_getc
+func uniphier_console_getc
+ ldr x0, [x0, #CONSOLE_T_BASE]
+
+ ldr w1, [x0, #UNIPHIER_UART_LSR]
+ tbz w1, #UNIPHIER_UART_LSR_DR_BIT, 0f
+
+ ldr w0, [x0, #UNIPHIER_UART_RX]
+ ret
+
+0: mov w0, #ERROR_NO_PENDING_CHAR
+ ret
+endfunc uniphier_console_getc
+
+/*
+ * In: x0 - pointer to console structure
+ * Out: return 0 (always succeeds)
+ * Clobber: x1
+ */
+ .global uniphier_console_flush
+func uniphier_console_flush
+ ldr x0, [x0, #CONSOLE_T_BASE]
+
+ /* wait until the transmitter gets empty */
+0: ldr w1, [x0, #UNIPHIER_UART_LSR]
+ tbz w1, #UNIPHIER_UART_LSR_TEMT_BIT, 0b
+
+ ret
+endfunc uniphier_console_flush
diff --git a/plat/socionext/uniphier/uniphier_console.h b/plat/socionext/uniphier/uniphier_console.h
new file mode 100644
index 0000000..e35fc88
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_console.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UNIPHIER_CONSOLE_H
+#define UNIPHIER_CONSOLE_H
+
+#define UNIPHIER_UART_RX 0x00 /* In: Receive buffer */
+#define UNIPHIER_UART_TX 0x00 /* Out: Transmit buffer */
+
+#define UNIPHIER_UART_FCR 0x0c /* Char/FIFO Control Register */
+#define UNIPHIER_UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
+
+#define UNIPHIER_UART_LCR_MCR 0x10 /* Line/Modem Control Register */
+#define UNIPHIER_UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
+#define UNIPHIER_UART_LSR 0x14 /* Line Status Register */
+#define UNIPHIER_UART_LSR_TEMT 0x40 /* Transmitter empty */
+#define UNIPHIER_UART_LSR_TEMT_BIT 6 /* Transmitter empty */
+#define UNIPHIER_UART_LSR_THRE_BIT 5 /* Transmit-hold-register empty */
+#define UNIPHIER_UART_LSR_DR_BIT 0 /* Receiver data ready */
+#define UNIPHIER_UART_DLR 0x24 /* Divisor Latch Register */
+
+#endif /* UNIPHIER_CONSOLE_H */
diff --git a/plat/socionext/uniphier/uniphier_console_setup.c b/plat/socionext/uniphier/uniphier_console_setup.c
new file mode 100644
index 0000000..9fda26e
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_console_setup.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019-2020, Socionext Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/console.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "uniphier.h"
+#include "uniphier_console.h"
+
+#define UNIPHIER_UART_OFFSET 0x100
+#define UNIPHIER_UART_NR_PORTS 4
+
+/* These callbacks are implemented in assembly to use crash_console_helpers.S */
+int uniphier_console_putc(int character, struct console *console);
+int uniphier_console_getc(struct console *console);
+void uniphier_console_flush(struct console *console);
+
+static console_t uniphier_console = {
+ .flags = CONSOLE_FLAG_BOOT |
+#if DEBUG
+ CONSOLE_FLAG_RUNTIME |
+#endif
+ CONSOLE_FLAG_CRASH |
+ CONSOLE_FLAG_TRANSLATE_CRLF,
+ .putc = uniphier_console_putc,
+ .getc = uniphier_console_getc,
+ .flush = uniphier_console_flush,
+};
+
+static const uintptr_t uniphier_uart_base[] = {
+ [UNIPHIER_SOC_LD11] = 0x54006800,
+ [UNIPHIER_SOC_LD20] = 0x54006800,
+ [UNIPHIER_SOC_PXS3] = 0x54006800,
+};
+
+/*
+ * There are 4 UART ports available on this platform. By default, we want to
+ * use the same one as used in the previous firmware stage.
+ */
+static uintptr_t uniphier_console_get_base(unsigned int soc)
+{
+ uintptr_t base, end;
+ uint32_t div;
+
+ assert(soc < ARRAY_SIZE(uniphier_uart_base));
+ base = uniphier_uart_base[soc];
+ end = base + UNIPHIER_UART_OFFSET * UNIPHIER_UART_NR_PORTS;
+
+ while (base < end) {
+ div = mmio_read_32(base + UNIPHIER_UART_DLR);
+ if (div)
+ return base;
+ base += UNIPHIER_UART_OFFSET;
+ }
+
+ return 0;
+}
+
+static void uniphier_console_init(uintptr_t base)
+{
+ mmio_write_32(base + UNIPHIER_UART_FCR, UNIPHIER_UART_FCR_ENABLE_FIFO);
+ mmio_write_32(base + UNIPHIER_UART_LCR_MCR,
+ UNIPHIER_UART_LCR_WLEN8 << 8);
+}
+
+void uniphier_console_setup(unsigned int soc)
+{
+ uintptr_t base;
+
+ base = uniphier_console_get_base(soc);
+ if (!base)
+ plat_error_handler(-EINVAL);
+
+ uniphier_console.base = base;
+ console_register(&uniphier_console);
+
+ /*
+ * The hardware might be still printing characters queued up in the
+ * previous firmware stage. Make sure the transmitter is empty before
+ * any initialization. Otherwise, the console might get corrupted.
+ */
+ console_flush();
+
+ uniphier_console_init(base);
+}
diff --git a/plat/socionext/uniphier/uniphier_emmc.c b/plat/socionext/uniphier/uniphier_emmc.c
new file mode 100644
index 0000000..b3d23cb
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_emmc.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <drivers/io/io_block.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "uniphier.h"
+
+#define MMC_CMD_SWITCH 6
+#define MMC_CMD_SELECT_CARD 7
+#define MMC_CMD_SEND_CSD 9
+#define MMC_CMD_READ_MULTIPLE_BLOCK 18
+
+#define EXT_CSD_PART_CONF 179 /* R/W */
+
+#define MMC_RSP_PRESENT BIT(0)
+#define MMC_RSP_136 BIT(1) /* 136 bit response */
+#define MMC_RSP_CRC BIT(2) /* expect valid crc */
+#define MMC_RSP_BUSY BIT(3) /* card may send busy */
+#define MMC_RSP_OPCODE BIT(4) /* response contains opcode */
+
+#define MMC_RSP_NONE (0)
+#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R1b (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | \
+ MMC_RSP_BUSY)
+#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
+#define MMC_RSP_R3 (MMC_RSP_PRESENT)
+#define MMC_RSP_R4 (MMC_RSP_PRESENT)
+#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+
+#define SDHCI_DMA_ADDRESS 0x00
+#define SDHCI_BLOCK_SIZE 0x04
+#define SDHCI_MAKE_BLKSZ(dma, blksz) ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF))
+#define SDHCI_BLOCK_COUNT 0x06
+#define SDHCI_ARGUMENT 0x08
+#define SDHCI_TRANSFER_MODE 0x0C
+#define SDHCI_TRNS_DMA BIT(0)
+#define SDHCI_TRNS_BLK_CNT_EN BIT(1)
+#define SDHCI_TRNS_ACMD12 BIT(2)
+#define SDHCI_TRNS_READ BIT(4)
+#define SDHCI_TRNS_MULTI BIT(5)
+#define SDHCI_COMMAND 0x0E
+#define SDHCI_CMD_RESP_MASK 0x03
+#define SDHCI_CMD_CRC 0x08
+#define SDHCI_CMD_INDEX 0x10
+#define SDHCI_CMD_DATA 0x20
+#define SDHCI_CMD_ABORTCMD 0xC0
+#define SDHCI_CMD_RESP_NONE 0x00
+#define SDHCI_CMD_RESP_LONG 0x01
+#define SDHCI_CMD_RESP_SHORT 0x02
+#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
+#define SDHCI_MAKE_CMD(c, f) ((((c) & 0xff) << 8) | ((f) & 0xff))
+#define SDHCI_RESPONSE 0x10
+#define SDHCI_HOST_CONTROL 0x28
+#define SDHCI_CTRL_DMA_MASK 0x18
+#define SDHCI_CTRL_SDMA 0x00
+#define SDHCI_BLOCK_GAP_CONTROL 0x2A
+#define SDHCI_SOFTWARE_RESET 0x2F
+#define SDHCI_RESET_CMD 0x02
+#define SDHCI_RESET_DATA 0x04
+#define SDHCI_INT_STATUS 0x30
+#define SDHCI_INT_RESPONSE BIT(0)
+#define SDHCI_INT_DATA_END BIT(1)
+#define SDHCI_INT_DMA_END BIT(3)
+#define SDHCI_INT_ERROR BIT(15)
+#define SDHCI_SIGNAL_ENABLE 0x38
+
+/* RCA assigned by Boot ROM */
+#define UNIPHIER_EMMC_RCA 0x1000
+
+struct uniphier_mmc_cmd {
+ unsigned int cmdidx;
+ unsigned int resp_type;
+ unsigned int cmdarg;
+ unsigned int is_data;
+};
+
+struct uniphier_emmc_host {
+ uintptr_t base;
+ bool is_block_addressing;
+};
+
+static struct uniphier_emmc_host uniphier_emmc_host;
+
+static int uniphier_emmc_send_cmd(uintptr_t host_base,
+ struct uniphier_mmc_cmd *cmd)
+{
+ uint32_t mode = 0;
+ uint32_t end_bit;
+ uint32_t stat, flags, dma_addr;
+
+ mmio_write_32(host_base + SDHCI_INT_STATUS, -1);
+ mmio_write_32(host_base + SDHCI_SIGNAL_ENABLE, 0);
+ mmio_write_32(host_base + SDHCI_ARGUMENT, cmd->cmdarg);
+
+ if (cmd->is_data)
+ mode = SDHCI_TRNS_DMA | SDHCI_TRNS_BLK_CNT_EN |
+ SDHCI_TRNS_ACMD12 | SDHCI_TRNS_READ |
+ SDHCI_TRNS_MULTI;
+
+ mmio_write_16(host_base + SDHCI_TRANSFER_MODE, mode);
+
+ if (!(cmd->resp_type & MMC_RSP_PRESENT))
+ flags = SDHCI_CMD_RESP_NONE;
+ else if (cmd->resp_type & MMC_RSP_136)
+ flags = SDHCI_CMD_RESP_LONG;
+ else if (cmd->resp_type & MMC_RSP_BUSY)
+ flags = SDHCI_CMD_RESP_SHORT_BUSY;
+ else
+ flags = SDHCI_CMD_RESP_SHORT;
+
+ if (cmd->resp_type & MMC_RSP_CRC)
+ flags |= SDHCI_CMD_CRC;
+ if (cmd->resp_type & MMC_RSP_OPCODE)
+ flags |= SDHCI_CMD_INDEX;
+ if (cmd->is_data)
+ flags |= SDHCI_CMD_DATA;
+
+ if (cmd->resp_type & MMC_RSP_BUSY || cmd->is_data)
+ end_bit = SDHCI_INT_DATA_END;
+ else
+ end_bit = SDHCI_INT_RESPONSE;
+
+ mmio_write_16(host_base + SDHCI_COMMAND,
+ SDHCI_MAKE_CMD(cmd->cmdidx, flags));
+
+ do {
+ stat = mmio_read_32(host_base + SDHCI_INT_STATUS);
+ if (stat & SDHCI_INT_ERROR)
+ return -EIO;
+
+ if (stat & SDHCI_INT_DMA_END) {
+ mmio_write_32(host_base + SDHCI_INT_STATUS, stat);
+ dma_addr = mmio_read_32(host_base + SDHCI_DMA_ADDRESS);
+ mmio_write_32(host_base + SDHCI_DMA_ADDRESS, dma_addr);
+ }
+ } while (!(stat & end_bit));
+
+ return 0;
+}
+
+static int uniphier_emmc_switch_part(uintptr_t host_base, int part_num)
+{
+ struct uniphier_mmc_cmd cmd = {0};
+
+ cmd.cmdidx = MMC_CMD_SWITCH;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = (EXT_CSD_PART_CONF << 16) | (part_num << 8) | (3 << 24);
+
+ return uniphier_emmc_send_cmd(host_base, &cmd);
+}
+
+static int uniphier_emmc_check_device_size(uintptr_t host_base,
+ bool *is_block_addressing)
+{
+ struct uniphier_mmc_cmd cmd = {0};
+ uint32_t csd40, csd72; /* CSD[71:40], CSD[103:72] */
+ int ret;
+
+ cmd.cmdidx = MMC_CMD_SEND_CSD;
+ cmd.resp_type = MMC_RSP_R2;
+ cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
+
+ ret = uniphier_emmc_send_cmd(host_base, &cmd);
+ if (ret)
+ return ret;
+
+ csd40 = mmio_read_32(host_base + SDHCI_RESPONSE + 4);
+ csd72 = mmio_read_32(host_base + SDHCI_RESPONSE + 8);
+
+ /* C_SIZE == 0xfff && C_SIZE_MULT == 0x7 ? */
+ *is_block_addressing = !(~csd40 & 0xffc00380) && !(~csd72 & 0x3);
+
+ return 0;
+}
+
+static int uniphier_emmc_load_image(uintptr_t host_base,
+ uint32_t dev_addr,
+ unsigned long load_addr,
+ uint32_t block_cnt)
+{
+ struct uniphier_mmc_cmd cmd = {0};
+ uint8_t tmp;
+
+ assert((load_addr >> 32) == 0);
+
+ mmio_write_32(host_base + SDHCI_DMA_ADDRESS, load_addr);
+ mmio_write_16(host_base + SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(7, 512));
+ mmio_write_16(host_base + SDHCI_BLOCK_COUNT, block_cnt);
+
+ tmp = mmio_read_8(host_base + SDHCI_HOST_CONTROL);
+ tmp &= ~SDHCI_CTRL_DMA_MASK;
+ tmp |= SDHCI_CTRL_SDMA;
+ mmio_write_8(host_base + SDHCI_HOST_CONTROL, tmp);
+
+ tmp = mmio_read_8(host_base + SDHCI_BLOCK_GAP_CONTROL);
+ tmp &= ~1; /* clear Stop At Block Gap Request */
+ mmio_write_8(host_base + SDHCI_BLOCK_GAP_CONTROL, tmp);
+
+ cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.cmdarg = dev_addr;
+ cmd.is_data = 1;
+
+ return uniphier_emmc_send_cmd(host_base, &cmd);
+}
+
+static size_t uniphier_emmc_read(int lba, uintptr_t buf, size_t size)
+{
+ int ret;
+
+ inv_dcache_range(buf, size);
+
+ if (!uniphier_emmc_host.is_block_addressing)
+ lba *= 512;
+
+ ret = uniphier_emmc_load_image(uniphier_emmc_host.base,
+ lba, buf, size / 512);
+
+ inv_dcache_range(buf, size);
+
+ return ret ? 0 : size;
+}
+
+static struct io_block_dev_spec uniphier_emmc_dev_spec = {
+ .ops = {
+ .read = uniphier_emmc_read,
+ },
+ .block_size = 512,
+};
+
+static int uniphier_emmc_hw_init(struct uniphier_emmc_host *host)
+{
+ struct uniphier_mmc_cmd cmd = {0};
+ uintptr_t host_base = uniphier_emmc_host.base;
+ int ret;
+
+ /*
+ * deselect card before SEND_CSD command.
+ * Do not check the return code. It fails, but it is OK.
+ */
+ cmd.cmdidx = MMC_CMD_SELECT_CARD;
+ cmd.resp_type = MMC_RSP_R1;
+
+ uniphier_emmc_send_cmd(host_base, &cmd); /* CMD7 (arg=0) */
+
+ /* reset CMD Line */
+ mmio_write_8(host_base + SDHCI_SOFTWARE_RESET,
+ SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ while (mmio_read_8(host_base + SDHCI_SOFTWARE_RESET))
+ ;
+
+ ret = uniphier_emmc_check_device_size(host_base,
+ &uniphier_emmc_host.is_block_addressing);
+ if (ret)
+ return ret;
+
+ cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
+
+ /* select card again */
+ ret = uniphier_emmc_send_cmd(host_base, &cmd);
+ if (ret)
+ return ret;
+
+ /* switch to Boot Partition 1 */
+ ret = uniphier_emmc_switch_part(host_base, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const uintptr_t uniphier_emmc_base[] = {
+ [UNIPHIER_SOC_LD11] = 0x5a000200,
+ [UNIPHIER_SOC_LD20] = 0x5a000200,
+ [UNIPHIER_SOC_PXS3] = 0x5a000200,
+};
+
+int uniphier_emmc_init(unsigned int soc,
+ struct io_block_dev_spec **block_dev_spec)
+{
+ int ret;
+
+ assert(soc < ARRAY_SIZE(uniphier_emmc_base));
+ uniphier_emmc_host.base = uniphier_emmc_base[soc];
+ if (uniphier_emmc_host.base == 0UL)
+ return -ENOTSUP;
+
+ ret = uniphier_emmc_hw_init(&uniphier_emmc_host);
+ if (ret)
+ return ret;
+
+ *block_dev_spec = &uniphier_emmc_dev_spec;
+
+ return 0;
+}
diff --git a/plat/socionext/uniphier/uniphier_gicv3.c b/plat/socionext/uniphier/uniphier_gicv3.c
new file mode 100644
index 0000000..266efe7
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_gicv3.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <drivers/arm/gicv3.h>
+#include <common/interrupt_props.h>
+#include <plat/common/platform.h>
+
+#include "uniphier.h"
+
+static uintptr_t uniphier_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t uniphier_interrupt_props[] = {
+ /* G0 interrupts */
+
+ /* SGI0 */
+ INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+ /* SGI6 */
+ INTR_PROP_DESC(14, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
+ GIC_INTR_CFG_EDGE),
+
+ /* G1S interrupts */
+
+ /* Timer */
+ INTR_PROP_DESC(29, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_LEVEL),
+ /* SGI1 */
+ INTR_PROP_DESC(9, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI2 */
+ INTR_PROP_DESC(10, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI3 */
+ INTR_PROP_DESC(11, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI4 */
+ INTR_PROP_DESC(12, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI5 */
+ INTR_PROP_DESC(13, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE),
+ /* SGI7 */
+ INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
+ GIC_INTR_CFG_EDGE)
+};
+
+static unsigned int uniphier_mpidr_to_core_pos(u_register_t mpidr)
+{
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+static const struct gicv3_driver_data uniphier_gic_driver_data[] = {
+ [UNIPHIER_SOC_LD11] = {
+ .gicd_base = 0x5fe00000,
+ .gicr_base = 0x5fe40000,
+ .interrupt_props = uniphier_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(uniphier_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = uniphier_rdistif_base_addrs,
+ .mpidr_to_core_pos = uniphier_mpidr_to_core_pos,
+ },
+ [UNIPHIER_SOC_LD20] = {
+ .gicd_base = 0x5fe00000,
+ .gicr_base = 0x5fe80000,
+ .interrupt_props = uniphier_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(uniphier_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = uniphier_rdistif_base_addrs,
+ .mpidr_to_core_pos = uniphier_mpidr_to_core_pos,
+ },
+ [UNIPHIER_SOC_PXS3] = {
+ .gicd_base = 0x5fe00000,
+ .gicr_base = 0x5fe80000,
+ .interrupt_props = uniphier_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(uniphier_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = uniphier_rdistif_base_addrs,
+ .mpidr_to_core_pos = uniphier_mpidr_to_core_pos,
+ },
+};
+
+void uniphier_gic_driver_init(unsigned int soc)
+{
+ assert(soc < ARRAY_SIZE(uniphier_gic_driver_data));
+
+ gicv3_driver_init(&uniphier_gic_driver_data[soc]);
+}
+
+void uniphier_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void uniphier_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void uniphier_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void uniphier_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/socionext/uniphier/uniphier_helpers.S b/plat/socionext/uniphier/uniphier_helpers.S
new file mode 100644
index 0000000..105cf9e
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_helpers.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .global uniphier_calc_core_pos
+ .global plat_my_core_pos
+ .globl platform_mem_init
+
+/*
+ * unsigned int uniphier_calc_core_pos(u_register_t mpidr)
+ * core_pos = (cluster_id * max_cpus_per_cluster) + core_id
+ */
+func uniphier_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ lsr x0, x0, #MPIDR_AFFINITY_BITS
+ mov x2, #UNIPHIER_MAX_CPUS_PER_CLUSTER
+ madd x0, x0, x2, x1
+ ret
+endfunc uniphier_calc_core_pos
+
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b uniphier_calc_core_pos
+endfunc plat_my_core_pos
+
+func platform_mem_init
+ ret
+endfunc platform_mem_init
diff --git a/plat/socionext/uniphier/uniphier_image_desc.c b/plat/socionext/uniphier/uniphier_image_desc.c
new file mode 100644
index 0000000..dd62d1e
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_image_desc.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <common/desc_image_load.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_BL33_OFFSET 0x04000000UL
+#define UNIPHIER_BL33_MAX_SIZE 0x00800000UL
+
+#define UNIPHIER_SCP_OFFSET 0x04800000UL
+#define UNIPHIER_SCP_MAX_SIZE 0x00020000UL
+
+static struct bl_mem_params_node uniphier_image_descs[] = {
+ {
+ .image_id = SCP_BL2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = UNIPHIER_SCP_OFFSET,
+ .image_info.image_max_size = UNIPHIER_SCP_MAX_SIZE,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | NON_EXECUTABLE),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+ {
+ .image_id = BL31_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = UNIPHIER_BL31_OFFSET,
+ .image_info.image_max_size = UNIPHIER_BL31_MAX_SIZE,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+ .ep_info.pc = UNIPHIER_BL31_OFFSET,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+#ifdef UNIPHIER_LOAD_BL32
+ .next_handoff_image_id = BL32_IMAGE_ID,
+#else
+ .next_handoff_image_id = BL33_IMAGE_ID,
+#endif
+ },
+#ifdef UNIPHIER_LOAD_BL32
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = UNIPHIER_BL32_OFFSET,
+ .image_info.image_max_size = UNIPHIER_BL32_MAX_SIZE,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE),
+ .ep_info.pc = UNIPHIER_BL32_OFFSET,
+ .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+#endif
+ {
+ .image_id = BL33_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t, 0),
+ .image_info.image_base = UNIPHIER_BL33_OFFSET,
+ .image_info.image_max_size = UNIPHIER_BL33_MAX_SIZE,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+ .ep_info.pc = UNIPHIER_BL33_OFFSET,
+ .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+};
+REGISTER_BL_IMAGE_DESCS(uniphier_image_descs)
+
+/*
+ * image_info.image_base and ep_info.pc are the offset from the memory base.
+ * When ENABLE_PIE is set, we never know the real memory base at link-time.
+ * Fix-up the addresses by adding the run-time detected base.
+ */
+void uniphier_init_image_descs(uintptr_t mem_base)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(uniphier_image_descs); i++) {
+ uniphier_image_descs[i].image_info.image_base += mem_base;
+ uniphier_image_descs[i].ep_info.pc += mem_base;
+ }
+}
+
+struct image_info *uniphier_get_image_info(unsigned int image_id)
+{
+ struct bl_mem_params_node *desc;
+
+ desc = get_bl_mem_params_node(image_id);
+ assert(desc);
+ return &desc->image_info;
+}
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
new file mode 100644
index 0000000..92e15b0
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_ROM_REGION_BASE 0x00000000ULL
+#define UNIPHIER_ROM_REGION_SIZE 0x04000000ULL
+
+#define UNIPHIER_OCM_REGION_SIZE 0x00040000ULL
+
+#define UNIPHIER_BLOCK_BUF_OFFSET 0x03000000UL
+#define UNIPHIER_BLOCK_BUF_SIZE 0x00800000UL
+
+static const io_dev_connector_t *uniphier_fip_dev_con;
+static uintptr_t uniphier_fip_dev_handle;
+
+static const io_dev_connector_t *uniphier_backend_dev_con;
+static uintptr_t uniphier_backend_dev_handle;
+
+static io_block_spec_t uniphier_fip_spec = {
+ /* .offset will be set by the io_setup func */
+ .length = 0x00200000,
+};
+
+static const io_uuid_spec_t uniphier_bl2_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
+};
+
+static const io_uuid_spec_t uniphier_scp_spec = {
+ .uuid = UUID_SCP_FIRMWARE_SCP_BL2,
+};
+
+static const io_uuid_spec_t uniphier_bl31_spec = {
+ .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t uniphier_bl32_spec = {
+ .uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t uniphier_bl33_spec = {
+ .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t uniphier_tb_fw_cert_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t uniphier_trusted_key_cert_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t uniphier_scp_fw_key_cert_spec = {
+ .uuid = UUID_SCP_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t uniphier_soc_fw_key_cert_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t uniphier_tos_fw_key_cert_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t uniphier_nt_fw_key_cert_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t uniphier_scp_fw_cert_spec = {
+ .uuid = UUID_SCP_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t uniphier_soc_fw_cert_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t uniphier_tos_fw_cert_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t uniphier_nt_fw_cert_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+struct uniphier_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ uintptr_t init_params;
+};
+
+static const struct uniphier_io_policy uniphier_io_policies[] = {
+ [FIP_IMAGE_ID] = {
+ .dev_handle = &uniphier_backend_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_fip_spec,
+ },
+ [BL2_IMAGE_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_bl2_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [SCP_BL2_IMAGE_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_scp_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [BL31_IMAGE_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_bl31_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [BL32_IMAGE_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_bl32_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [BL33_IMAGE_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_bl33_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_tb_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [TRUSTED_KEY_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_trusted_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [SCP_FW_KEY_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_scp_fw_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_soc_fw_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_tos_fw_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_nt_fw_key_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [SCP_FW_CONTENT_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_scp_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_soc_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_tos_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ .dev_handle = &uniphier_fip_dev_handle,
+ .image_spec = (uintptr_t)&uniphier_nt_fw_cert_spec,
+ .init_params = FIP_IMAGE_ID,
+ },
+#endif
+};
+
+static int uniphier_io_block_setup(size_t fip_offset,
+ struct io_block_dev_spec *block_dev_spec,
+ size_t buffer_offset)
+{
+ int ret;
+
+ uniphier_fip_spec.offset = fip_offset;
+
+ block_dev_spec->buffer.offset = buffer_offset;
+ block_dev_spec->buffer.length = UNIPHIER_BLOCK_BUF_SIZE;
+
+ ret = mmap_add_dynamic_region(block_dev_spec->buffer.offset,
+ block_dev_spec->buffer.offset,
+ block_dev_spec->buffer.length,
+ MT_MEMORY | MT_RW | MT_NS);
+ if (ret)
+ return ret;
+
+ ret = register_io_dev_block(&uniphier_backend_dev_con);
+ if (ret)
+ return ret;
+
+ return io_dev_open(uniphier_backend_dev_con, (uintptr_t)block_dev_spec,
+ &uniphier_backend_dev_handle);
+}
+
+static int uniphier_io_memmap_setup(size_t fip_offset)
+{
+ int ret;
+
+ uniphier_fip_spec.offset = fip_offset;
+
+ ret = mmap_add_dynamic_region(fip_offset, fip_offset,
+ uniphier_fip_spec.length,
+ MT_RO_DATA | MT_SECURE);
+ if (ret)
+ return ret;
+
+ ret = register_io_dev_memmap(&uniphier_backend_dev_con);
+ if (ret)
+ return ret;
+
+ return io_dev_open(uniphier_backend_dev_con, 0,
+ &uniphier_backend_dev_handle);
+}
+
+static int uniphier_io_fip_setup(void)
+{
+ int ret;
+
+ ret = register_io_dev_fip(&uniphier_fip_dev_con);
+ if (ret)
+ return ret;
+
+ return io_dev_open(uniphier_fip_dev_con, 0, &uniphier_fip_dev_handle);
+}
+
+static int uniphier_io_emmc_setup(unsigned int soc, size_t buffer_offset)
+{
+ struct io_block_dev_spec *block_dev_spec;
+ int ret;
+
+ ret = uniphier_emmc_init(soc, &block_dev_spec);
+ if (ret)
+ return ret;
+
+ return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset);
+}
+
+static int uniphier_io_nand_setup(unsigned int soc, size_t buffer_offset)
+{
+ struct io_block_dev_spec *block_dev_spec;
+ int ret;
+
+ ret = uniphier_nand_init(soc, &block_dev_spec);
+ if (ret)
+ return ret;
+
+ return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset);
+}
+
+static int uniphier_io_nor_setup(unsigned int soc_id, size_t buffer_offset)
+{
+ return uniphier_io_memmap_setup(0x70000);
+}
+
+static const uintptr_t uniphier_ocm_base[] = {
+ [UNIPHIER_SOC_LD11] = 0x30000000,
+ [UNIPHIER_SOC_LD20] = 0x30000000,
+ [UNIPHIER_SOC_PXS3] = 0x30000000,
+};
+
+static int uniphier_io_rom_api_setup(unsigned int soc)
+{
+ uintptr_t ocm_base;
+ int ret;
+
+ assert(soc < ARRAY_SIZE(uniphier_ocm_base));
+ ocm_base = uniphier_ocm_base[soc];
+
+ ret = mmap_add_dynamic_region(UNIPHIER_ROM_REGION_BASE,
+ UNIPHIER_ROM_REGION_BASE,
+ UNIPHIER_ROM_REGION_SIZE,
+ MT_CODE | MT_SECURE);
+ if (ret)
+ return ret;
+
+ /*
+ * on-chip SRAM region: should be DEVICE attribute because the USB
+ * load functions provided by the ROM use this memory region as a work
+ * area, but do not cater to cache coherency.
+ */
+ ret = mmap_add_dynamic_region(ocm_base, ocm_base,
+ UNIPHIER_OCM_REGION_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int uniphier_io_usb_setup(unsigned int soc, size_t buffer_offset)
+{
+ struct io_block_dev_spec *block_dev_spec;
+ int ret;
+
+ /* use ROM API for loading images from USB storage */
+ ret = uniphier_io_rom_api_setup(soc);
+ if (ret)
+ return ret;
+
+ ret = uniphier_usb_init(soc, &block_dev_spec);
+ if (ret)
+ return ret;
+
+ return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset);
+}
+
+static int (* const uniphier_io_setup_table[])(unsigned int, size_t) = {
+ [UNIPHIER_BOOT_DEVICE_EMMC] = uniphier_io_emmc_setup,
+ [UNIPHIER_BOOT_DEVICE_NAND] = uniphier_io_nand_setup,
+ [UNIPHIER_BOOT_DEVICE_NOR] = uniphier_io_nor_setup,
+ [UNIPHIER_BOOT_DEVICE_USB] = uniphier_io_usb_setup,
+};
+
+int uniphier_io_setup(unsigned int soc_id, uintptr_t mem_base)
+{
+ int (*io_setup)(unsigned int soc_id, size_t buffer_offset);
+ unsigned int boot_dev;
+ int ret;
+
+ boot_dev = uniphier_get_boot_device(soc_id);
+ if (boot_dev == UNIPHIER_BOOT_DEVICE_RSV)
+ return -EINVAL;
+
+ io_setup = uniphier_io_setup_table[boot_dev];
+ ret = io_setup(soc_id, mem_base + UNIPHIER_BLOCK_BUF_OFFSET);
+ if (ret)
+ return ret;
+
+ ret = uniphier_io_fip_setup();
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ uintptr_t init_params;
+
+ assert(image_id < ARRAY_SIZE(uniphier_io_policies));
+
+ *dev_handle = *uniphier_io_policies[image_id].dev_handle;
+ *image_spec = uniphier_io_policies[image_id].image_spec;
+ init_params = uniphier_io_policies[image_id].init_params;
+
+ return io_dev_init(*dev_handle, init_params);
+}
diff --git a/plat/socionext/uniphier/uniphier_nand.c b/plat/socionext/uniphier/uniphier_nand.c
new file mode 100644
index 0000000..71cb96c
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_nand.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/io/io_block.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "uniphier.h"
+
+#define NAND_CMD_READ0 0
+#define NAND_CMD_READSTART 0x30
+
+#define DENALI_ECC_ENABLE 0x0e0
+#define DENALI_PAGES_PER_BLOCK 0x150
+#define DENALI_DEVICE_MAIN_AREA_SIZE 0x170
+#define DENALI_DEVICE_SPARE_AREA_SIZE 0x180
+#define DENALI_TWO_ROW_ADDR_CYCLES 0x190
+#define DENALI_INTR_STATUS0 0x410
+#define DENALI_INTR_ECC_UNCOR_ERR BIT(1)
+#define DENALI_INTR_DMA_CMD_COMP BIT(2)
+#define DENALI_INTR_INT_ACT BIT(12)
+
+#define DENALI_DMA_ENABLE 0x700
+
+#define DENALI_HOST_ADDR 0x00
+#define DENALI_HOST_DATA 0x10
+
+#define DENALI_MAP01 (1 << 26)
+#define DENALI_MAP10 (2 << 26)
+#define DENALI_MAP11 (3 << 26)
+
+#define DENALI_MAP11_CMD ((DENALI_MAP11) | 0)
+#define DENALI_MAP11_ADDR ((DENALI_MAP11) | 1)
+#define DENALI_MAP11_DATA ((DENALI_MAP11) | 2)
+
+#define DENALI_ACCESS_DEFAULT_AREA 0x42
+
+#define UNIPHIER_NAND_BBT_UNKNOWN 0xff
+
+struct uniphier_nand {
+ uintptr_t host_base;
+ uintptr_t reg_base;
+ int pages_per_block;
+ int page_size;
+ int two_row_addr_cycles;
+ uint8_t bbt[16];
+};
+
+struct uniphier_nand uniphier_nand;
+
+static void uniphier_nand_host_write(struct uniphier_nand *nand,
+ uint32_t addr, uint32_t data)
+{
+ mmio_write_32(nand->host_base + DENALI_HOST_ADDR, addr);
+ mmio_write_32(nand->host_base + DENALI_HOST_DATA, data);
+}
+
+static uint32_t uniphier_nand_host_read(struct uniphier_nand *nand,
+ uint32_t addr)
+{
+ mmio_write_32(nand->host_base + DENALI_HOST_ADDR, addr);
+ return mmio_read_32(nand->host_base + DENALI_HOST_DATA);
+}
+
+static int uniphier_nand_block_isbad(struct uniphier_nand *nand, int block)
+{
+ int page = nand->pages_per_block * block;
+ int column = nand->page_size;
+ uint8_t bbm;
+ uint32_t status;
+ int is_bad;
+
+ /* use cache if available */
+ if (block < ARRAY_SIZE(nand->bbt) &&
+ nand->bbt[block] != UNIPHIER_NAND_BBT_UNKNOWN)
+ return nand->bbt[block];
+
+ mmio_write_32(nand->reg_base + DENALI_ECC_ENABLE, 0);
+
+ mmio_write_32(nand->reg_base + DENALI_INTR_STATUS0, -1);
+
+ uniphier_nand_host_write(nand, DENALI_MAP11_CMD, NAND_CMD_READ0);
+ uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, column & 0xff);
+ uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, (column >> 8) & 0xff);
+ uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, page & 0xff);
+ uniphier_nand_host_write(nand, DENALI_MAP11_ADDR, (page >> 8) & 0xff);
+ if (!nand->two_row_addr_cycles)
+ uniphier_nand_host_write(nand, DENALI_MAP11_ADDR,
+ (page >> 16) & 0xff);
+ uniphier_nand_host_write(nand, DENALI_MAP11_CMD, NAND_CMD_READSTART);
+
+ do {
+ status = mmio_read_32(nand->reg_base + DENALI_INTR_STATUS0);
+ } while (!(status & DENALI_INTR_INT_ACT));
+
+ bbm = uniphier_nand_host_read(nand, DENALI_MAP11_DATA);
+
+ is_bad = bbm != 0xff;
+
+ /* if possible, save the result for future re-use */
+ if (block < ARRAY_SIZE(nand->bbt))
+ nand->bbt[block] = is_bad;
+
+ if (is_bad)
+ WARN("found bad block at %d. skip.\n", block);
+
+ return is_bad;
+}
+
+static int uniphier_nand_read_pages(struct uniphier_nand *nand, uintptr_t buf,
+ int page_start, int page_count)
+{
+ uint32_t status;
+
+ mmio_write_32(nand->reg_base + DENALI_ECC_ENABLE, 1);
+ mmio_write_32(nand->reg_base + DENALI_DMA_ENABLE, 1);
+
+ mmio_write_32(nand->reg_base + DENALI_INTR_STATUS0, -1);
+
+ /* use Data DMA (64bit) */
+ mmio_write_32(nand->host_base + DENALI_HOST_ADDR,
+ DENALI_MAP10 | page_start);
+
+ /*
+ * 1. setup transfer type, interrupt when complete,
+ * burst len = 64 bytes, the number of pages
+ */
+ mmio_write_32(nand->host_base + DENALI_HOST_DATA,
+ 0x01002000 | (64 << 16) | page_count);
+
+ /* 2. set memory low address */
+ mmio_write_32(nand->host_base + DENALI_HOST_DATA, buf);
+
+ /* 3. set memory high address */
+ mmio_write_32(nand->host_base + DENALI_HOST_DATA, buf >> 32);
+
+ do {
+ status = mmio_read_32(nand->reg_base + DENALI_INTR_STATUS0);
+ } while (!(status & DENALI_INTR_DMA_CMD_COMP));
+
+ mmio_write_32(nand->reg_base + DENALI_DMA_ENABLE, 0);
+
+ if (status & DENALI_INTR_ECC_UNCOR_ERR) {
+ ERROR("uncorrectable error in page range %d-%d",
+ page_start, page_start + page_count - 1);
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
+static size_t __uniphier_nand_read(struct uniphier_nand *nand, int lba,
+ uintptr_t buf, size_t size)
+{
+ int pages_per_block = nand->pages_per_block;
+ int page_size = nand->page_size;
+ int blocks_to_skip = lba / pages_per_block;
+ int pages_to_read = div_round_up(size, page_size);
+ int page = lba % pages_per_block;
+ int block = 0;
+ uintptr_t p = buf;
+ int page_count, ret;
+
+ while (blocks_to_skip) {
+ ret = uniphier_nand_block_isbad(nand, block);
+ if (ret < 0)
+ goto out;
+
+ if (!ret)
+ blocks_to_skip--;
+
+ block++;
+ }
+
+ while (pages_to_read) {
+ ret = uniphier_nand_block_isbad(nand, block);
+ if (ret < 0)
+ goto out;
+
+ if (ret) {
+ block++;
+ continue;
+ }
+
+ page_count = MIN(pages_per_block - page, pages_to_read);
+
+ ret = uniphier_nand_read_pages(nand, p,
+ block * pages_per_block + page,
+ page_count);
+ if (ret)
+ goto out;
+
+ block++;
+ page = 0;
+ p += page_size * page_count;
+ pages_to_read -= page_count;
+ }
+
+out:
+ /* number of read bytes */
+ return MIN(size, p - buf);
+}
+
+static size_t uniphier_nand_read(int lba, uintptr_t buf, size_t size)
+{
+ size_t count;
+
+ inv_dcache_range(buf, size);
+
+ count = __uniphier_nand_read(&uniphier_nand, lba, buf, size);
+
+ inv_dcache_range(buf, size);
+
+ return count;
+}
+
+static struct io_block_dev_spec uniphier_nand_dev_spec = {
+ .ops = {
+ .read = uniphier_nand_read,
+ },
+ /* fill .block_size at run-time */
+};
+
+static int uniphier_nand_hw_init(struct uniphier_nand *nand)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(nand->bbt); i++)
+ nand->bbt[i] = UNIPHIER_NAND_BBT_UNKNOWN;
+
+ nand->reg_base = nand->host_base + 0x100000;
+
+ nand->pages_per_block =
+ mmio_read_32(nand->reg_base + DENALI_PAGES_PER_BLOCK);
+
+ nand->page_size =
+ mmio_read_32(nand->reg_base + DENALI_DEVICE_MAIN_AREA_SIZE);
+
+ if (mmio_read_32(nand->reg_base + DENALI_TWO_ROW_ADDR_CYCLES) & BIT(0))
+ nand->two_row_addr_cycles = 1;
+
+ uniphier_nand_host_write(nand, DENALI_MAP10,
+ DENALI_ACCESS_DEFAULT_AREA);
+
+ return 0;
+}
+
+static const uintptr_t uniphier_nand_base[] = {
+ [UNIPHIER_SOC_LD11] = 0x68000000,
+ [UNIPHIER_SOC_LD20] = 0x68000000,
+ [UNIPHIER_SOC_PXS3] = 0x68000000,
+};
+
+int uniphier_nand_init(unsigned int soc,
+ struct io_block_dev_spec **block_dev_spec)
+{
+ int ret;
+
+ assert(soc < ARRAY_SIZE(uniphier_nand_base));
+ uniphier_nand.host_base = uniphier_nand_base[soc];
+ if (!uniphier_nand.host_base)
+ return -ENOTSUP;
+
+ ret = uniphier_nand_hw_init(&uniphier_nand);
+ if (ret)
+ return ret;
+
+ uniphier_nand_dev_spec.block_size = uniphier_nand.page_size;
+
+ *block_dev_spec = &uniphier_nand_dev_spec;
+
+ return 0;
+}
diff --git a/plat/socionext/uniphier/uniphier_psci.c b/plat/socionext/uniphier/uniphier_psci.c
new file mode 100644
index 0000000..a371705
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_psci.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_ROM_RSV0 0x0
+
+#define UNIPHIER_SLFRSTSEL 0x10
+#define UNIPHIER_SLFRSTSEL_MASK GENMASK(1, 0)
+#define UNIPHIER_SLFRSTCTL 0x14
+#define UNIPHIER_SLFRSTCTL_RST BIT(0)
+
+#define MPIDR_AFFINITY_INVALID ((u_register_t)-1)
+
+static uintptr_t uniphier_rom_rsv_base;
+static uintptr_t uniphier_slfrst_base;
+
+uintptr_t uniphier_sec_entrypoint;
+
+void uniphier_warmboot_entrypoint(void);
+void __dead2 uniphier_fake_pwr_down(void);
+u_register_t uniphier_holding_pen_release;
+static int uniphier_psci_scp_mode;
+
+static int uniphier_psci_pwr_domain_on(u_register_t mpidr)
+{
+ uniphier_holding_pen_release = mpidr;
+ flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
+ sizeof(uniphier_holding_pen_release));
+
+ mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0,
+ (uint64_t)&uniphier_warmboot_entrypoint);
+ sev();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uniphier_gic_cpuif_disable();
+}
+
+static void uniphier_psci_pwr_domain_on_finish(
+ const psci_power_state_t *target_state)
+{
+ uniphier_gic_pcpu_init();
+ uniphier_gic_cpuif_enable();
+
+ uniphier_cci_enable();
+}
+
+static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi(
+ const psci_power_state_t *target_state)
+{
+ /*
+ * The Boot ROM cannot distinguish warm and cold resets.
+ * Instead of the CPU reset, fake it.
+ */
+ uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID;
+ flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
+ sizeof(uniphier_holding_pen_release));
+
+ uniphier_fake_pwr_down();
+}
+
+static void uniphier_self_system_reset(void)
+{
+ mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL,
+ UNIPHIER_SLFRSTSEL_MASK);
+ mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL,
+ UNIPHIER_SLFRSTCTL_RST);
+}
+
+static void __dead2 uniphier_psci_system_off(void)
+{
+ if (uniphier_psci_scp_mode) {
+ uniphier_scp_system_off();
+ } else {
+ NOTICE("SCP is disabled; can't shutdown the system.\n");
+ NOTICE("Resetting the system instead.\n");
+ uniphier_self_system_reset();
+ }
+
+ wfi();
+ ERROR("UniPhier System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 uniphier_psci_system_reset(void)
+{
+ if (uniphier_psci_scp_mode)
+ uniphier_scp_system_reset();
+ else
+ uniphier_self_system_reset();
+
+ wfi();
+ ERROR("UniPhier System Reset: operation not handled.\n");
+ panic();
+}
+
+static const struct plat_psci_ops uniphier_psci_ops = {
+ .pwr_domain_on = uniphier_psci_pwr_domain_on,
+ .pwr_domain_off = uniphier_psci_pwr_domain_off,
+ .pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish,
+ .pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi,
+ .system_off = uniphier_psci_system_off,
+ .system_reset = uniphier_psci_system_reset,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ uniphier_sec_entrypoint = sec_entrypoint;
+ flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
+ sizeof(uniphier_sec_entrypoint));
+
+ *psci_ops = &uniphier_psci_ops;
+
+ return 0;
+}
+
+struct uniphier_psci_ctrl_base {
+ uintptr_t rom_rsv_base;
+ uintptr_t slfrst_base;
+};
+
+static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = {
+ [UNIPHIER_SOC_LD11] = {
+ .rom_rsv_base = 0x59801200,
+ .slfrst_base = 0x61843000,
+ },
+ [UNIPHIER_SOC_LD20] = {
+ .rom_rsv_base = 0x59801200,
+ .slfrst_base = 0x61843000,
+ },
+ [UNIPHIER_SOC_PXS3] = {
+ .rom_rsv_base = 0x59801200,
+ .slfrst_base = 0x61843000,
+ },
+};
+
+void uniphier_psci_init(unsigned int soc)
+{
+ assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base));
+ uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base;
+ uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base;
+
+ if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) {
+ uniphier_psci_scp_mode = uniphier_scp_is_running();
+ flush_dcache_range((uint64_t)&uniphier_psci_scp_mode,
+ sizeof(uniphier_psci_scp_mode));
+
+ if (uniphier_psci_scp_mode)
+ uniphier_scp_open_com();
+ }
+}
diff --git a/plat/socionext/uniphier/uniphier_rotpk.S b/plat/socionext/uniphier/uniphier_rotpk.S
new file mode 100644
index 0000000..21c44b6
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_rotpk.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global uniphier_rotpk_hash
+ .global uniphier_rotpk_hash_end
+ .section .rodata.uniphier_rotpk_hash, "a"
+uniphier_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+uniphier_rotpk_hash_end:
diff --git a/plat/socionext/uniphier/uniphier_scp.c b/plat/socionext/uniphier/uniphier_scp.c
new file mode 100644
index 0000000..8a12d5d
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_scp.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_ROM_RSV3 0x5980120c
+
+#define UNIPHIER_STMBE2COM 0x5f800030
+#define UNIPHIER_STMTOBEIRQ 0x5f800060
+#define UNIPHIER_BETOSTMIRQ0PT 0x5f800070
+#define UNIPHIER_BEIRQCLRPT 0x5f800072
+
+#define UNIPHIER_SCP_READY_MAGIC 0x0000b6a5
+
+#define UNIPHIER_SCP_PACKET_START 0xA0
+#define UNIPHIER_SCP_PACKET_END 0xA5
+#define UNIPHIER_SCP_PACKET_ESC 0xA6
+#define UNIPHIER_SCP_IS_CTRL_CODE(c) (0xA0 <= (c) && (c) <= 0xA6)
+
+int uniphier_scp_is_running(void)
+{
+ return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC;
+}
+
+void uniphier_scp_start(uint32_t scp_base)
+{
+ uint32_t tmp;
+
+ mmio_write_32(UNIPHIER_STMBE2COM + 4, scp_base);
+ mmio_write_32(UNIPHIER_STMBE2COM, UNIPHIER_SCP_READY_MAGIC);
+
+ do {
+ tmp = mmio_read_32(UNIPHIER_ROM_RSV3);
+ } while (!(tmp & BIT(8)));
+
+ mmio_write_32(UNIPHIER_ROM_RSV3, tmp | BIT(9));
+}
+
+static void uniphier_scp_send_packet(const uint8_t *packet, int packet_len)
+{
+ uintptr_t reg = UNIPHIER_STMBE2COM;
+ uint32_t word;
+ int len, i;
+
+ while (packet_len) {
+ len = MIN(packet_len, 4);
+ word = 0;
+
+ for (i = 0; i < len; i++)
+ word |= *packet++ << (8 * i);
+
+ mmio_write_32(reg, word);
+ reg += 4;
+ packet_len -= len;
+ }
+
+ mmio_write_8(UNIPHIER_BETOSTMIRQ0PT, 0x55);
+
+ while (!(mmio_read_32(UNIPHIER_STMTOBEIRQ) & BIT(1)))
+ ;
+ mmio_write_8(UNIPHIER_BEIRQCLRPT, BIT(1) | BIT(0));
+}
+
+static void uniphier_scp_send_cmd(const uint8_t *cmd, int cmd_len)
+{
+ uint8_t packet[32]; /* long enough */
+ uint8_t *p = packet;
+ uint8_t c;
+ int i;
+
+ *p++ = UNIPHIER_SCP_PACKET_START;
+ *p++ = cmd_len;
+
+ for (i = 0; i < cmd_len; i++) {
+ c = *cmd++;
+ if (UNIPHIER_SCP_IS_CTRL_CODE(c)) {
+ *p++ = UNIPHIER_SCP_PACKET_ESC;
+ *p++ = c ^ BIT(7);
+ } else {
+ *p++ = c;
+ }
+ }
+
+ *p++ = UNIPHIER_SCP_PACKET_END;
+
+ uniphier_scp_send_packet(packet, p - packet);
+}
+
+#define UNIPHIER_SCP_CMD(name, ...) \
+static const uint8_t __uniphier_scp_##name##_cmd[] = { \
+ __VA_ARGS__ \
+}; \
+void uniphier_scp_##name(void) \
+{ \
+ uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd, \
+ ARRAY_SIZE(__uniphier_scp_##name##_cmd)); \
+}
+
+UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05)
+UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01)
+UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00)
diff --git a/plat/socionext/uniphier/uniphier_smp.S b/plat/socionext/uniphier/uniphier_smp.S
new file mode 100644
index 0000000..d6cb9ff
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_smp.S
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+ .globl uniphier_warmboot_entrypoint
+ .globl uniphier_fake_pwr_down
+
+func uniphier_warmboot_entrypoint
+ mrs x0, mpidr_el1
+ mov_imm x1, MPIDR_AFFINITY_MASK
+ and x0, x0, x1
+ b 1f
+0: wfe
+1: ldr x1, uniphier_holding_pen_release
+ cmp x1, x0
+ b.ne 0b
+ ldr x0, uniphier_sec_entrypoint
+ br x0
+endfunc uniphier_warmboot_entrypoint
+
+func uniphier_fake_pwr_down
+ bl disable_mmu_icache_el3
+ b uniphier_warmboot_entrypoint
+endfunc uniphier_fake_pwr_down
diff --git a/plat/socionext/uniphier/uniphier_soc_info.c b/plat/socionext/uniphier/uniphier_soc_info.c
new file mode 100644
index 0000000..0e7a2d1
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_soc_info.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <lib/mmio.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_REVISION 0x5f800000UL
+#define UNIPHIER_REVISION_NEW 0x1f800000UL
+
+static unsigned int uniphier_get_revision_field(unsigned int mask,
+ unsigned int shift)
+{
+ uintptr_t reg;
+
+ if (BL_CODE_BASE >= 0x80000000UL)
+ reg = UNIPHIER_REVISION;
+ else
+ reg = UNIPHIER_REVISION_NEW;
+
+ return (mmio_read_32(reg) >> shift) & mask;
+}
+
+unsigned int uniphier_get_soc_type(void)
+{
+ return uniphier_get_revision_field(0xff, 16);
+}
+
+unsigned int uniphier_get_soc_model(void)
+{
+ return uniphier_get_revision_field(0x07, 8);
+}
+
+unsigned int uniphier_get_soc_revision(void)
+{
+ return uniphier_get_revision_field(0x1f, 0);
+}
+
+unsigned int uniphier_get_soc_id(void)
+{
+ uint32_t type = uniphier_get_soc_type();
+
+ switch (type) {
+ case 0x31:
+ return UNIPHIER_SOC_LD11;
+ case 0x32:
+ return UNIPHIER_SOC_LD20;
+ case 0x35:
+ return UNIPHIER_SOC_PXS3;
+ default:
+ return UNIPHIER_SOC_UNKNOWN;
+ }
+}
diff --git a/plat/socionext/uniphier/uniphier_syscnt.c b/plat/socionext/uniphier/uniphier_syscnt.c
new file mode 100644
index 0000000..1937843
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_syscnt.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return 50000000;
+}
diff --git a/plat/socionext/uniphier/uniphier_tbbr.c b/plat/socionext/uniphier/uniphier_tbbr.c
new file mode 100644
index 0000000..e31ca03
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_tbbr.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char uniphier_rotpk_hash[], uniphier_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = uniphier_rotpk_hash;
+ *key_len = uniphier_rotpk_hash_end - uniphier_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ /*
+ * No support for non-volatile counter. Update the ROT key to protect
+ * the system against rollback.
+ */
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 0;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/socionext/uniphier/uniphier_topology.c b/plat/socionext/uniphier/uniphier_topology.c
new file mode 100644
index 0000000..c106c98
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_topology.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <plat/common/platform.h>
+
+#include "uniphier.h"
+
+static unsigned char uniphier_power_domain_tree_desc[UNIPHIER_CLUSTER_COUNT + 1];
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ int i;
+
+ uniphier_power_domain_tree_desc[0] = UNIPHIER_CLUSTER_COUNT;
+
+ for (i = 0; i < UNIPHIER_CLUSTER_COUNT; i++)
+ uniphier_power_domain_tree_desc[i + 1] =
+ UNIPHIER_MAX_CPUS_PER_CLUSTER;
+
+ return uniphier_power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+
+ cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ if (cluster_id >= UNIPHIER_CLUSTER_COUNT)
+ return -1;
+
+ cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+ if (cpu_id >= UNIPHIER_MAX_CPUS_PER_CLUSTER)
+ return -1;
+
+ return uniphier_calc_core_pos(mpidr);
+}
diff --git a/plat/socionext/uniphier/uniphier_usb.c b/plat/socionext/uniphier/uniphier_usb.c
new file mode 100644
index 0000000..7469ad1
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_usb.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <drivers/io/io_block.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include "uniphier.h"
+
+#define UNIPHIER_LD11_USB_DESC_BASE 0x30010000
+#define UNIPHIER_LD20_USB_DESC_BASE 0x30014000
+#define UNIPHIER_PXS3_USB_DESC_BASE 0x30014000
+
+#define UNIPHIER_SRB_OCM_CONT 0x61200000
+
+struct uniphier_ld11_trans_op {
+ uint8_t __pad[48];
+};
+
+struct uniphier_ld11_op {
+ uint8_t __pad[56];
+ struct uniphier_ld11_trans_op *trans_op;
+ void *__pad2;
+ void *dev_desc;
+};
+
+struct uniphier_ld20_trans_op {
+ uint8_t __pad[40];
+};
+
+struct uniphier_ld20_op {
+ uint8_t __pad[192];
+ struct uniphier_ld20_trans_op *trans_op;
+ void *__pad2;
+ void *dev_desc;
+};
+
+struct uniphier_pxs3_op {
+ uint8_t __pad[184];
+ struct uniphier_ld20_trans_op *trans_op;
+ void *__pad2;
+ void *dev_desc;
+};
+
+static int (*__uniphier_usb_read)(int lba, uintptr_t buf, size_t size);
+
+static void uniphier_ld11_usb_init(void)
+{
+ struct uniphier_ld11_op *op = (void *)UNIPHIER_LD11_USB_DESC_BASE;
+
+ op->trans_op = (void *)(op + 1);
+
+ op->dev_desc = op->trans_op + 1;
+}
+
+static int uniphier_ld11_usb_read(int lba, uintptr_t buf, size_t size)
+{
+ static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
+ unsigned int size, uintptr_t buf);
+ uintptr_t func_addr;
+
+ func_addr = uniphier_get_soc_revision() == 1 ? 0x3880 : 0x3958;
+ rom_usb_read = (__typeof(rom_usb_read))func_addr;
+
+ return rom_usb_read(UNIPHIER_LD11_USB_DESC_BASE, lba, size, buf);
+}
+
+static void uniphier_ld20_usb_init(void)
+{
+ struct uniphier_ld20_op *op = (void *)UNIPHIER_LD20_USB_DESC_BASE;
+
+ op->trans_op = (void *)(op + 1);
+
+ op->dev_desc = op->trans_op + 1;
+}
+
+static int uniphier_ld20_usb_read(int lba, uintptr_t buf, size_t size)
+{
+ static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
+ unsigned int size, uintptr_t buf);
+ int ret;
+
+ rom_usb_read = (__typeof(rom_usb_read))0x37f0;
+
+ mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0x1ff);
+
+ /* ROM-API - return 1 on success, 0 on error */
+ ret = rom_usb_read(UNIPHIER_LD20_USB_DESC_BASE, lba, size, buf);
+
+ mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0);
+
+ return ret ? 0 : -1;
+}
+
+static void uniphier_pxs3_usb_init(void)
+{
+ struct uniphier_pxs3_op *op = (void *)UNIPHIER_PXS3_USB_DESC_BASE;
+
+ op->trans_op = (void *)(op + 1);
+
+ op->dev_desc = op->trans_op + 1;
+}
+
+static int uniphier_pxs3_usb_read(int lba, uintptr_t buf, size_t size)
+{
+ static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
+ unsigned int size, uintptr_t buf);
+ int ret;
+
+ rom_usb_read = (__typeof(rom_usb_read))0x39e8;
+
+ /* ROM-API - return 1 on success, 0 on error */
+ ret = rom_usb_read(UNIPHIER_PXS3_USB_DESC_BASE, lba, size, buf);
+
+ return ret ? 0 : -1;
+}
+
+struct uniphier_usb_rom_param {
+ void (*init)(void);
+ int (*read)(int lba, uintptr_t buf, size_t size);
+};
+
+static const struct uniphier_usb_rom_param uniphier_usb_rom_params[] = {
+ [UNIPHIER_SOC_LD11] = {
+ .init = uniphier_ld11_usb_init,
+ .read = uniphier_ld11_usb_read,
+ },
+ [UNIPHIER_SOC_LD20] = {
+ .init = uniphier_ld20_usb_init,
+ .read = uniphier_ld20_usb_read,
+ },
+ [UNIPHIER_SOC_PXS3] = {
+ .init = uniphier_pxs3_usb_init,
+ .read = uniphier_pxs3_usb_read,
+ },
+};
+
+static size_t uniphier_usb_read(int lba, uintptr_t buf, size_t size)
+{
+ int ret;
+
+ inv_dcache_range(buf, size);
+
+ ret = __uniphier_usb_read(lba, buf, size);
+
+ inv_dcache_range(buf, size);
+
+ return ret ? 0 : size;
+}
+
+static struct io_block_dev_spec uniphier_usb_dev_spec = {
+ .ops = {
+ .read = uniphier_usb_read,
+ },
+ .block_size = 512,
+};
+
+int uniphier_usb_init(unsigned int soc,
+ struct io_block_dev_spec **block_dev_spec)
+{
+ const struct uniphier_usb_rom_param *param;
+
+ assert(soc < ARRAY_SIZE(uniphier_usb_rom_params));
+ param = &uniphier_usb_rom_params[soc];
+
+ if (param->init)
+ param->init();
+
+ __uniphier_usb_read = param->read;
+
+ *block_dev_spec = &uniphier_usb_dev_spec;
+
+ return 0;
+}
diff --git a/plat/socionext/uniphier/uniphier_xlat_setup.c b/plat/socionext/uniphier/uniphier_xlat_setup.c
new file mode 100644
index 0000000..5043f4b
--- /dev/null
+++ b/plat/socionext/uniphier/uniphier_xlat_setup.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include "uniphier.h"
+
+struct uniphier_reg_region {
+ uintptr_t base;
+ size_t size;
+};
+
+static const struct uniphier_reg_region uniphier_reg_region[] = {
+ [UNIPHIER_SOC_LD11] = {
+ .base = 0x50000000UL,
+ .size = 0x20000000UL,
+ },
+ [UNIPHIER_SOC_LD20] = {
+ .base = 0x50000000UL,
+ .size = 0x20000000UL,
+ },
+ [UNIPHIER_SOC_PXS3] = {
+ .base = 0x50000000UL,
+ .size = 0x20000000UL,
+ },
+};
+
+void uniphier_mmap_setup(unsigned int soc)
+{
+ VERBOSE("Trusted RAM seen by this BL image: %p - %p\n",
+ (void *)BL_CODE_BASE, (void *)BL_END);
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ round_up(BL_END, PAGE_SIZE) - BL_CODE_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE);
+
+ /* remap the code section */
+ VERBOSE("Code region: %p - %p\n",
+ (void *)BL_CODE_BASE, (void *)BL_CODE_END);
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+
+ /* remap the coherent memory region */
+ VERBOSE("Coherent region: %p - %p\n",
+ (void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END);
+ mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE);
+
+ /* register region */
+ assert(soc < ARRAY_SIZE(uniphier_reg_region));
+ mmap_add_region(uniphier_reg_region[soc].base,
+ uniphier_reg_region[soc].base,
+ uniphier_reg_region[soc].size,
+ MT_DEVICE | MT_RW | MT_SECURE);
+
+ init_xlat_tables();
+
+ enable_mmu(0);
+
+#if PLAT_RO_XLAT_TABLES
+ {
+ int ret;
+
+ ret = xlat_make_tables_readonly();
+ if (ret) {
+ ERROR("Failed to make translation tables read-only.");
+ plat_error_handler(ret);
+ }
+ }
+#endif
+}
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
new file mode 100644
index 0000000..b271ed6
--- /dev/null
+++ b/plat/st/common/bl2_io_storage.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/fwu/fwu.h>
+#include <drivers/fwu/fwu_metadata.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_encrypted.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_mtd.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/efi.h>
+#include <drivers/partition/partition.h>
+#include <drivers/raw_nand.h>
+#include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
+#include <drivers/st/io_mmc.h>
+#include <drivers/st/stm32_fmc2_nand.h>
+#include <drivers/st/stm32_qspi.h>
+#include <drivers/st/stm32_sdmmc2.h>
+#include <drivers/usb_device.h>
+#include <lib/fconf/fconf.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32cubeprogrammer.h>
+#include <stm32mp_efi.h>
+#include <stm32mp_fconf_getter.h>
+#include <stm32mp_io_storage.h>
+#include <usb_dfu.h>
+
+/* IO devices */
+uintptr_t fip_dev_handle;
+uintptr_t storage_dev_handle;
+
+static const io_dev_connector_t *fip_dev_con;
+
+#ifndef DECRYPTION_SUPPORT_none
+static const io_dev_connector_t *enc_dev_con;
+uintptr_t enc_dev_handle;
+#endif
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static struct mmc_device_info mmc_info;
+
+static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
+
+static io_block_dev_spec_t mmc_block_dev_spec = {
+ /* It's used as temp buffer in block driver */
+ .buffer = {
+ .offset = (size_t)&block_buffer,
+ .length = MMC_BLOCK_SIZE,
+ },
+ .ops = {
+ .read = mmc_read_blocks,
+ .write = NULL,
+ },
+ .block_size = MMC_BLOCK_SIZE,
+};
+
+static const io_dev_connector_t *mmc_dev_con;
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static io_mtd_dev_spec_t spi_nor_dev_spec = {
+ .ops = {
+ .init = spi_nor_init,
+ .read = spi_nor_read,
+ },
+};
+#endif
+
+#if STM32MP_RAW_NAND
+static io_mtd_dev_spec_t nand_dev_spec = {
+ .ops = {
+ .init = nand_raw_init,
+ .read = nand_read,
+ .seek = nand_seek_bb
+ },
+};
+
+static const io_dev_connector_t *nand_dev_con;
+#endif
+
+#if STM32MP_SPI_NAND
+static io_mtd_dev_spec_t spi_nand_dev_spec = {
+ .ops = {
+ .init = spi_nand_init,
+ .read = nand_read,
+ .seek = nand_seek_bb
+ },
+};
+#endif
+
+#if STM32MP_SPI_NAND || STM32MP_SPI_NOR
+static const io_dev_connector_t *spi_dev_con;
+#endif
+
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
+static const io_dev_connector_t *memmap_dev_con;
+#endif
+
+io_block_spec_t image_block_spec = {
+ .offset = 0U,
+ .length = 0U,
+};
+
+int open_fip(const uintptr_t spec)
+{
+ return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+}
+
+#ifndef DECRYPTION_SUPPORT_none
+int open_enc_fip(const uintptr_t spec)
+{
+ int result;
+ uintptr_t local_image_handle;
+
+ result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
+ if (result != 0) {
+ return result;
+ }
+
+ result = io_open(enc_dev_handle, spec, &local_image_handle);
+ if (result != 0) {
+ return result;
+ }
+
+ VERBOSE("Using encrypted FIP\n");
+ io_close(local_image_handle);
+
+ return 0;
+}
+#endif
+
+int open_storage(const uintptr_t spec)
+{
+ return io_dev_init(storage_dev_handle, 0);
+}
+
+#if STM32MP_EMMC_BOOT
+static uint32_t get_boot_part_fip_header(void)
+{
+ io_block_spec_t emmc_boot_fip_block_spec = {
+ .offset = STM32MP_EMMC_BOOT_FIP_OFFSET,
+ .length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
+ };
+ uint32_t magic = 0U;
+ int io_result;
+ size_t bytes_read;
+ uintptr_t fip_hdr_handle;
+
+ io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_fip_block_spec,
+ &fip_hdr_handle);
+ assert(io_result == 0);
+
+ io_result = io_read(fip_hdr_handle, (uintptr_t)&magic, sizeof(magic),
+ &bytes_read);
+ if ((io_result != 0) || (bytes_read != sizeof(magic))) {
+ panic();
+ }
+
+ io_close(fip_hdr_handle);
+
+ VERBOSE("%s: eMMC boot magic at offset 256K: %08x\n",
+ __func__, magic);
+
+ return magic;
+}
+#endif
+
+static void print_boot_device(boot_api_context_t *boot_context)
+{
+ switch (boot_context->boot_interface_selected) {
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+ INFO("Using SDMMC\n");
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+ INFO("Using EMMC\n");
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+ INFO("Using QSPI NOR\n");
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+ INFO("Using FMC NAND\n");
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+ INFO("Using SPI NAND\n");
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+ INFO("Using UART\n");
+ break;
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+ INFO("Using USB\n");
+ break;
+ default:
+ ERROR("Boot interface %u not found\n",
+ boot_context->boot_interface_selected);
+ panic();
+ break;
+ }
+
+ if (boot_context->boot_interface_instance != 0U) {
+ INFO(" Instance %d\n", boot_context->boot_interface_instance);
+ }
+}
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static void boot_mmc(enum mmc_device_type mmc_dev_type,
+ uint16_t boot_interface_instance)
+{
+ int io_result __unused;
+ struct stm32_sdmmc2_params params;
+
+ zeromem(&params, sizeof(struct stm32_sdmmc2_params));
+
+ mmc_info.mmc_dev_type = mmc_dev_type;
+
+ switch (boot_interface_instance) {
+ case 1:
+ params.reg_base = STM32MP_SDMMC1_BASE;
+ break;
+ case 2:
+ params.reg_base = STM32MP_SDMMC2_BASE;
+ break;
+ case 3:
+ params.reg_base = STM32MP_SDMMC3_BASE;
+ break;
+ default:
+ WARN("SDMMC instance not found, using default\n");
+ if (mmc_dev_type == MMC_IS_SD) {
+ params.reg_base = STM32MP_SDMMC1_BASE;
+ } else {
+ params.reg_base = STM32MP_SDMMC2_BASE;
+ }
+ break;
+ }
+
+ if (mmc_dev_type != MMC_IS_EMMC) {
+ params.flags = MMC_FLAG_SD_CMD6;
+ }
+
+ params.device_info = &mmc_info;
+ if (stm32_sdmmc2_mmc_init(&params) != 0) {
+ ERROR("SDMMC%u init failed\n", boot_interface_instance);
+ panic();
+ }
+
+ /* Open MMC as a block device to read FIP */
+ io_result = register_io_dev_block(&mmc_dev_con);
+ if (io_result != 0) {
+ panic();
+ }
+
+ io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
+ &storage_dev_handle);
+ assert(io_result == 0);
+
+#if STM32MP_EMMC_BOOT
+ if (mmc_dev_type == MMC_IS_EMMC) {
+ io_result = mmc_part_switch_current_boot();
+ assert(io_result == 0);
+
+ if (get_boot_part_fip_header() != TOC_HEADER_NAME) {
+ WARN("%s: Can't find FIP header on eMMC boot partition. Trying GPT\n",
+ __func__);
+ io_result = mmc_part_switch_user();
+ assert(io_result == 0);
+ return;
+ }
+
+ VERBOSE("%s: FIP header found on eMMC boot partition\n",
+ __func__);
+ image_block_spec.offset = STM32MP_EMMC_BOOT_FIP_OFFSET;
+ image_block_spec.length = mmc_boot_part_size() - STM32MP_EMMC_BOOT_FIP_OFFSET;
+ }
+#endif
+}
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static void boot_spi_nor(boot_api_context_t *boot_context)
+{
+ int io_result __unused;
+
+ io_result = stm32_qspi_init();
+ assert(io_result == 0);
+
+ io_result = register_io_dev_mtd(&spi_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to device */
+ io_result = io_dev_open(spi_dev_con,
+ (uintptr_t)&spi_nor_dev_spec,
+ &storage_dev_handle);
+ assert(io_result == 0);
+}
+#endif /* STM32MP_SPI_NOR */
+
+#if STM32MP_RAW_NAND
+static void boot_fmc2_nand(boot_api_context_t *boot_context)
+{
+ int io_result __unused;
+
+ io_result = stm32_fmc2_init();
+ assert(io_result == 0);
+
+ /* Register the IO device on this platform */
+ io_result = register_io_dev_mtd(&nand_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to device */
+ io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
+ &storage_dev_handle);
+ assert(io_result == 0);
+}
+#endif /* STM32MP_RAW_NAND */
+
+#if STM32MP_SPI_NAND
+static void boot_spi_nand(boot_api_context_t *boot_context)
+{
+ int io_result __unused;
+
+ io_result = stm32_qspi_init();
+ assert(io_result == 0);
+
+ io_result = register_io_dev_mtd(&spi_dev_con);
+ assert(io_result == 0);
+
+ /* Open connections to device */
+ io_result = io_dev_open(spi_dev_con,
+ (uintptr_t)&spi_nand_dev_spec,
+ &storage_dev_handle);
+ assert(io_result == 0);
+}
+#endif /* STM32MP_SPI_NAND */
+
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
+static void mmap_io_setup(void)
+{
+ int io_result __unused;
+
+ io_result = register_io_dev_memmap(&memmap_dev_con);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+ &storage_dev_handle);
+ assert(io_result == 0);
+}
+
+#if STM32MP_UART_PROGRAMMER
+static void stm32cubeprogrammer_uart(void)
+{
+ int ret __unused;
+ boot_api_context_t *boot_context =
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+ uintptr_t uart_base;
+
+ uart_base = get_uart_address(boot_context->boot_interface_instance);
+ ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
+ assert(ret == 0);
+}
+#endif
+
+#if STM32MP_USB_PROGRAMMER
+static void stm32cubeprogrammer_usb(void)
+{
+ int ret __unused;
+ struct usb_handle *pdev;
+
+ /* Init USB on platform */
+ pdev = usb_dfu_plat_init();
+
+ ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
+ assert(ret == 0);
+}
+#endif
+#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
+
+
+void stm32mp_io_setup(void)
+{
+ int io_result __unused;
+ boot_api_context_t *boot_context =
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+
+ print_boot_device(boot_context);
+
+ if ((boot_context->boot_partition_used_toboot == 1U) ||
+ (boot_context->boot_partition_used_toboot == 2U)) {
+ INFO("Boot used partition fsbl%u\n",
+ boot_context->boot_partition_used_toboot);
+ }
+
+ io_result = register_io_dev_fip(&fip_dev_con);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+ &fip_dev_handle);
+
+#ifndef DECRYPTION_SUPPORT_none
+ io_result = register_io_dev_enc(&enc_dev_con);
+ assert(io_result == 0);
+
+ io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
+ &enc_dev_handle);
+ assert(io_result == 0);
+#endif
+
+ switch (boot_context->boot_interface_selected) {
+#if STM32MP_SDMMC
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+ dmbsy();
+ boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
+ break;
+#endif
+#if STM32MP_EMMC
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+ dmbsy();
+ boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
+ break;
+#endif
+#if STM32MP_SPI_NOR
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+ dmbsy();
+ boot_spi_nor(boot_context);
+ break;
+#endif
+#if STM32MP_RAW_NAND
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+ dmbsy();
+ boot_fmc2_nand(boot_context);
+ break;
+#endif
+#if STM32MP_SPI_NAND
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+ dmbsy();
+ boot_spi_nand(boot_context);
+ break;
+#endif
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
+#if STM32MP_UART_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+#endif
+#if STM32MP_USB_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+#endif
+ dmbsy();
+ mmap_io_setup();
+ break;
+#endif
+
+ default:
+ ERROR("Boot interface %d not supported\n",
+ boot_context->boot_interface_selected);
+ panic();
+ break;
+ }
+}
+
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+ static bool gpt_init_done __unused;
+ uint16_t boot_itf = stm32mp_get_boot_itf_selected();
+
+ switch (boot_itf) {
+#if STM32MP_SDMMC || STM32MP_EMMC
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+#if STM32MP_EMMC_BOOT
+ if (image_block_spec.offset == STM32MP_EMMC_BOOT_FIP_OFFSET) {
+ break;
+ }
+#endif
+ /* fallthrough */
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+ if (!gpt_init_done) {
+/*
+ * With FWU Multi Bank feature enabled, the selection of
+ * the image to boot will be done by fwu_init calling the
+ * platform hook, plat_fwu_set_images_source.
+ */
+#if !PSA_FWU_SUPPORT
+ const partition_entry_t *entry;
+ const struct efi_guid img_type_guid = STM32MP_FIP_GUID;
+ uuid_t img_type_uuid;
+
+ guidcpy(&img_type_uuid, &img_type_guid);
+ partition_init(GPT_IMAGE_ID);
+ entry = get_partition_entry_by_type(&img_type_uuid);
+ if (entry == NULL) {
+ entry = get_partition_entry(FIP_IMAGE_NAME);
+ if (entry == NULL) {
+ ERROR("Could NOT find the %s partition!\n",
+ FIP_IMAGE_NAME);
+
+ return -ENOENT;
+ }
+ }
+
+ image_block_spec.offset = entry->start;
+ image_block_spec.length = entry->length;
+#endif
+ gpt_init_done = true;
+ } else {
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ assert(bl_mem_params != NULL);
+
+ mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
+ mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
+ }
+
+ break;
+#endif
+
+#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
+#if STM32MP_RAW_NAND
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+#endif
+#if STM32MP_SPI_NAND
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+#endif
+ image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
+ break;
+#endif
+
+#if STM32MP_SPI_NOR
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+ image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
+ break;
+#endif
+
+#if STM32MP_UART_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+ if (image_id == FW_CONFIG_ID) {
+ stm32cubeprogrammer_uart();
+ /* FIP loaded at DWL address */
+ image_block_spec.offset = DWL_BUFFER_BASE;
+ image_block_spec.length = DWL_BUFFER_SIZE;
+ }
+ break;
+#endif
+#if STM32MP_USB_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+ if (image_id == FW_CONFIG_ID) {
+ stm32cubeprogrammer_usb();
+ /* FIP loaded at DWL address */
+ image_block_spec.offset = DWL_BUFFER_BASE;
+ image_block_spec.length = DWL_BUFFER_SIZE;
+ }
+ break;
+#endif
+
+ default:
+ ERROR("FIP Not found\n");
+ panic();
+ }
+
+ return 0;
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+ uintptr_t *image_spec)
+{
+ int rc;
+ const struct plat_io_policy *policy;
+
+ policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
+ rc = policy->check(policy->image_spec);
+ if (rc == 0) {
+ *image_spec = policy->image_spec;
+ *dev_handle = *(policy->dev_handle);
+ }
+
+ return rc;
+}
+
+#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
+/*
+ * In each boot in non-trial mode, we set the BKP register to
+ * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
+ *
+ * As long as the update agent didn't update the "accepted" field in metadata
+ * (i.e. we are in trial mode), we select the new active_index.
+ * To avoid infinite boot loop at trial boot we decrement a BKP register.
+ * If this counter is 0:
+ * - an unexpected TAMPER event raised (that resets the BKP registers to 0)
+ * - a power-off occurs before the update agent was able to update the
+ * "accepted' field
+ * - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode.
+ * we select the previous_active_index.
+ */
+#define INVALID_BOOT_IDX 0xFFFFFFFF
+
+uint32_t plat_fwu_get_boot_idx(void)
+{
+ /*
+ * Select boot index and update boot counter only once per boot
+ * even if this function is called several times.
+ */
+ static uint32_t boot_idx = INVALID_BOOT_IDX;
+ const struct fwu_metadata *data;
+
+ data = fwu_get_metadata();
+
+ if (boot_idx == INVALID_BOOT_IDX) {
+ boot_idx = data->active_index;
+ if (fwu_is_trial_run_state()) {
+ if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) {
+ WARN("Trial FWU fails %u times\n",
+ FWU_MAX_TRIAL_REBOOT);
+ boot_idx = data->previous_active_index;
+ }
+ } else {
+ stm32_set_max_fwu_trial_boot_cnt();
+ }
+ }
+
+ return boot_idx;
+}
+
+static void *stm32_get_image_spec(const uuid_t *img_type_uuid)
+{
+ unsigned int i;
+
+ for (i = 0U; i < MAX_NUMBER_IDS; i++) {
+ if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 0) {
+ return (void *)policies[i].image_spec;
+ }
+ }
+
+ return NULL;
+}
+
+void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
+{
+ unsigned int i;
+ uint32_t boot_idx;
+ const partition_entry_t *entry;
+ const uuid_t *img_type_uuid, *img_uuid;
+ io_block_spec_t *image_spec;
+
+ boot_idx = plat_fwu_get_boot_idx();
+ assert(boot_idx < NR_OF_FW_BANKS);
+
+ for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
+ img_type_uuid = &metadata->img_entry[i].img_type_uuid;
+ image_spec = stm32_get_image_spec(img_type_uuid);
+ if (image_spec == NULL) {
+ ERROR("Unable to get image spec for the image in the metadata\n");
+ panic();
+ }
+
+ img_uuid =
+ &metadata->img_entry[i].img_props[boot_idx].img_uuid;
+
+ entry = get_partition_entry_by_uuid(img_uuid);
+ if (entry == NULL) {
+ ERROR("Unable to find the partition with the uuid mentioned in metadata\n");
+ panic();
+ }
+
+ image_spec->offset = entry->start;
+ image_spec->length = entry->length;
+ }
+}
+
+static int plat_set_image_source(unsigned int image_id,
+ uintptr_t *handle,
+ uintptr_t *image_spec,
+ const char *part_name)
+{
+ struct plat_io_policy *policy;
+ io_block_spec_t *spec;
+ const partition_entry_t *entry = get_partition_entry(part_name);
+
+ if (entry == NULL) {
+ ERROR("Unable to find the %s partition\n", part_name);
+ return -ENOENT;
+ }
+
+ policy = &policies[image_id];
+
+ spec = (io_block_spec_t *)policy->image_spec;
+ spec->offset = entry->start;
+ spec->length = entry->length;
+
+ *image_spec = policy->image_spec;
+ *handle = *policy->dev_handle;
+
+ return 0;
+}
+
+int plat_fwu_set_metadata_image_source(unsigned int image_id,
+ uintptr_t *handle,
+ uintptr_t *image_spec)
+{
+ char *part_name;
+
+ assert((image_id == FWU_METADATA_IMAGE_ID) ||
+ (image_id == BKUP_FWU_METADATA_IMAGE_ID));
+
+ partition_init(GPT_IMAGE_ID);
+
+ if (image_id == FWU_METADATA_IMAGE_ID) {
+ part_name = METADATA_PART_1;
+ } else {
+ part_name = METADATA_PART_2;
+ }
+
+ return plat_set_image_source(image_id, handle, image_spec,
+ part_name);
+}
+#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
diff --git a/plat/st/common/include/stm32cubeprogrammer.h b/plat/st/common/include/stm32cubeprogrammer.h
new file mode 100644
index 0000000..0f5a64d
--- /dev/null
+++ b/plat/st/common/include/stm32cubeprogrammer.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32CUBEPROGRAMMER_H
+#define STM32CUBEPROGRAMMER_H
+
+#include <stdint.h>
+
+#include <usb_dfu.h>
+
+/* Phase definition */
+#define PHASE_FLASHLAYOUT 0U
+#define PHASE_SSBL 3U
+#define PHASE_CMD 0xF1U
+#define PHASE_RESET 0xFFU
+
+/* Functions provided by plat */
+uint8_t usb_dfu_get_phase(uint8_t alt);
+
+int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle,
+ uintptr_t ssbl_base,
+ size_t ssbl_len);
+
+int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len);
+
+#endif /* STM32CUBEPROGRAMMER_H */
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
new file mode 100644
index 0000000..a5316b6
--- /dev/null
+++ b/plat/st/common/include/stm32mp_common.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_COMMON_H
+#define STM32MP_COMMON_H
+
+#include <stdbool.h>
+
+#include <platform_def.h>
+
+#define JEDEC_ST_BKID U(0x0)
+#define JEDEC_ST_MFID U(0x20)
+
+/* Functions to save and get boot context address given by ROM code */
+void stm32mp_save_boot_ctx_address(uintptr_t address);
+uintptr_t stm32mp_get_boot_ctx_address(void);
+uint16_t stm32mp_get_boot_itf_selected(void);
+
+bool stm32mp_is_single_core(void);
+bool stm32mp_is_closed_device(void);
+bool stm32mp_is_auth_supported(void);
+
+/* Return the base address of the DDR controller */
+uintptr_t stm32mp_ddrctrl_base(void);
+
+/* Return the base address of the DDR PHY */
+uintptr_t stm32mp_ddrphyc_base(void);
+
+/* Return the base address of the PWR peripheral */
+uintptr_t stm32mp_pwr_base(void);
+
+/* Return the base address of the RCC peripheral */
+uintptr_t stm32mp_rcc_base(void);
+
+/* Check MMU status to allow spinlock use */
+bool stm32mp_lock_available(void);
+
+int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx,
+ uint32_t *otp_len);
+int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val);
+int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val);
+
+/* Get IWDG platform instance ID from peripheral IO memory base address */
+uint32_t stm32_iwdg_get_instance(uintptr_t base);
+
+/* Return bitflag mask for expected IWDG configuration from OTP content */
+uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst);
+
+#if defined(IMAGE_BL2)
+/* Update OTP shadow registers with IWDG configuration from device tree */
+uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags);
+#endif
+
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+/* Get the UART address from its instance number */
+uintptr_t get_uart_address(uint32_t instance_nb);
+#endif
+
+/* Setup the UART console */
+int stm32mp_uart_console_setup(void);
+
+#if STM32MP_EARLY_CONSOLE
+void stm32mp_setup_early_console(void);
+#else
+static inline void stm32mp_setup_early_console(void)
+{
+}
+#endif
+
+/*
+ * Platform util functions for the GPIO driver
+ * @bank: Target GPIO bank ID as per DT bindings
+ *
+ * Platform shall implement these functions to provide to stm32_gpio
+ * driver the resource reference for a target GPIO bank. That are
+ * memory mapped interface base address, interface offset (see below)
+ * and clock identifier.
+ *
+ * stm32_get_gpio_bank_offset() returns a bank offset that is used to
+ * check DT configuration matches platform implementation of the banks
+ * description.
+ */
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank);
+unsigned long stm32_get_gpio_bank_clock(unsigned int bank);
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank);
+bool stm32_gpio_is_secure_at_reset(unsigned int bank);
+
+/* Return node offset for target GPIO bank ID @bank or a FDT error code */
+int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank);
+
+/* Get the chip revision */
+uint32_t stm32mp_get_chip_version(void);
+/* Get the chip device ID */
+uint32_t stm32mp_get_chip_dev_id(void);
+
+/* Get SOC name */
+#define STM32_SOC_NAME_SIZE 20
+void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE]);
+
+/* Print CPU information */
+void stm32mp_print_cpuinfo(void);
+
+/* Print board information */
+void stm32mp_print_boardinfo(void);
+
+/* Initialise the IO layer and register platform IO devices */
+void stm32mp_io_setup(void);
+
+/* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */
+int stm32mp_map_ddr_non_cacheable(void);
+int stm32mp_unmap_ddr(void);
+
+/* Functions to save and get boot peripheral info */
+void stm32_save_boot_interface(uint32_t interface, uint32_t instance);
+void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance);
+
+/* Functions to save and get boot authentication status and partition used */
+void stm32_save_boot_auth(uint32_t auth_status, uint32_t boot_partition);
+
+#if PSA_FWU_SUPPORT
+void stm32mp1_fwu_set_boot_idx(void);
+uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void);
+void stm32_set_max_fwu_trial_boot_cnt(void);
+#endif /* PSA_FWU_SUPPORT */
+
+#endif /* STM32MP_COMMON_H */
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
new file mode 100644
index 0000000..b7bf1d0
--- /dev/null
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020-2022, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_DT_H
+#define STM32MP_DT_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define DT_DISABLED U(0)
+#define DT_NON_SECURE U(1)
+#define DT_SECURE U(2)
+#define DT_SHARED (DT_NON_SECURE | DT_SECURE)
+
+struct dt_node_info {
+ uint32_t base;
+ int32_t clock;
+ int32_t reset;
+ uint32_t status;
+};
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+int dt_open_and_check(uintptr_t dt_addr);
+int fdt_get_address(void **fdt_addr);
+bool fdt_check_node(int node);
+uint8_t fdt_get_status(int node);
+int dt_set_stdout_pinctrl(void);
+void dt_fill_device_info(struct dt_node_info *info, int node);
+int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
+int dt_get_stdout_uart_info(struct dt_node_info *info);
+int dt_match_instance_by_compatible(const char *compatible, uintptr_t address);
+uint32_t dt_get_ddr_size(void);
+uint32_t dt_get_pwr_vdd_voltage(void);
+struct rdev *dt_get_vdd_regulator(void);
+struct rdev *dt_get_cpu_regulator(void);
+const char *dt_get_board_model(void);
+int dt_find_otp_name(const char *name, uint32_t *otp, uint32_t *otp_len);
+int fdt_get_gpio_bank_pin_count(unsigned int bank);
+
+#endif /* STM32MP_DT_H */
diff --git a/plat/st/common/include/stm32mp_efi.h b/plat/st/common/include/stm32mp_efi.h
new file mode 100644
index 0000000..490560f
--- /dev/null
+++ b/plat/st/common/include/stm32mp_efi.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#ifndef STM32MP_EFI_H
+#define STM32MP_EFI_H
+
+#include <drivers/partition/efi.h>
+
+#define STM32MP_FIP_GUID \
+ EFI_GUID(0x19d5df83, 0x11b0, 0x457b, \
+ 0xbe, 0x2c, 0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5)
+
+#endif /* STM32MP_EFI_H */
diff --git a/plat/st/common/include/stm32mp_fconf_getter.h b/plat/st/common/include/stm32mp_fconf_getter.h
new file mode 100644
index 0000000..18884ae
--- /dev/null
+++ b/plat/st/common/include/stm32mp_fconf_getter.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_FCONF_GETTER
+#define STM32MP_FCONF_GETTER
+
+#include <assert.h>
+
+#include <lib/fconf/fconf.h>
+#include <tools_share/uuid.h>
+
+/* IO policies */
+#define stm32mp__io_policies_getter(id) __extension__ ({ \
+ assert((id) < MAX_NUMBER_IDS); \
+ &policies[id]; \
+})
+
+struct plat_io_policy {
+ uintptr_t *dev_handle;
+ uintptr_t image_spec;
+ struct efi_guid img_type_guid;
+ int (*check)(const uintptr_t spec);
+};
+
+extern struct plat_io_policy policies[];
+int fconf_populate_stm32mp_io_policies(uintptr_t config);
+
+#endif /* STM32MP_FCONF_GETTER */
diff --git a/plat/st/common/include/stm32mp_io_storage.h b/plat/st/common/include/stm32mp_io_storage.h
new file mode 100644
index 0000000..3c04c47
--- /dev/null
+++ b/plat/st/common/include/stm32mp_io_storage.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef STM32MP_IO_STORAGE_H
+#define STM32MP_IO_STORAGE_H
+
+#include <stdint.h>
+
+#include <drivers/io/io_storage.h>
+
+/* IO devices handle */
+extern uintptr_t storage_dev_handle;
+extern uintptr_t fip_dev_handle;
+extern uintptr_t enc_dev_handle;
+
+extern io_block_spec_t image_block_spec;
+
+/* Function declarations */
+int open_fip(const uintptr_t spec);
+#ifndef DECRYPTION_SUPPORT_none
+int open_enc_fip(const uintptr_t spec);
+#endif
+int open_storage(const uintptr_t spec);
+
+#endif /* STM32MP_IO_STORAGE_H */
diff --git a/plat/st/common/include/stm32mp_shared_resources.h b/plat/st/common/include/stm32mp_shared_resources.h
new file mode 100644
index 0000000..13f4b13
--- /dev/null
+++ b/plat/st/common/include/stm32mp_shared_resources.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_SHARED_RESOURCES_H
+#define STM32MP_SHARED_RESOURCES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef STM32MP_SHARED_RESOURCES
+enum stm32mp_shres;
+
+/* Return true if @clock_id is shared by secure and non-secure worlds */
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id);
+
+/* Return true if and only if @reset_id relates to a non-secure peripheral */
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
+
+/* Register a shared resource assigned to the secure world */
+void stm32mp_register_secure_periph(enum stm32mp_shres id);
+
+/* Register a shared resource assigned to the non-secure world */
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id);
+
+/* Register a peripheral as secure or non-secure based on IO base address */
+void stm32mp_register_secure_periph_iomem(uintptr_t base);
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base);
+
+/* Register a GPIO as secure or non-secure based on its bank and pin numbers */
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin);
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin);
+
+/* Consolidate peripheral states and lock against new peripheral registering */
+void stm32mp_lock_periph_registering(void);
+#else
+static inline void stm32mp_register_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline void stm32mp_register_secure_gpio(unsigned int bank __unused,
+ unsigned int pin __unused)
+{
+}
+
+static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused,
+ unsigned int pin __unused)
+{
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+#endif /* STM32MP_SHARED_RESOURCES_H */
diff --git a/plat/st/common/include/usb_dfu.h b/plat/st/common/include/usb_dfu.h
new file mode 100644
index 0000000..f7d4245
--- /dev/null
+++ b/plat/st/common/include/usb_dfu.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef USB_DFU_H
+#define USB_DFU_H
+
+#include <stdint.h>
+
+#include <drivers/usb_device.h>
+
+#define DFU_DESCRIPTOR_TYPE 0x21U
+
+/* Max DFU Packet Size = 1024 bytes */
+#define USBD_DFU_XFER_SIZE 1024U
+
+#define TRANSFER_SIZE_BYTES(size) \
+ ((uint8_t)((size) & 0xFF)), /* XFERSIZEB0 */\
+ ((uint8_t)((size) >> 8)) /* XFERSIZEB1 */
+
+/*
+ * helper for descriptor of DFU interface 0 Alternate setting n
+ * with iInterface = index of string descriptor, assumed Nth user string
+ */
+#define USBD_DFU_IF_DESC(n) 0x09U, /* Interface Descriptor size */\
+ USB_DESC_TYPE_INTERFACE, /* descriptor type */\
+ 0x00U, /* Number of Interface */\
+ (n), /* Alternate setting */\
+ 0x00U, /* bNumEndpoints*/\
+ 0xFEU, /* Application Specific Class Code */\
+ 0x01U, /* Device Firmware Upgrade Code */\
+ 0x02U, /* DFU mode protocol */ \
+ USBD_IDX_USER0_STR + (n) /* iInterface */
+
+/* DFU1.1 Standard */
+#define USB_DFU_VERSION 0x0110U
+#define USB_DFU_ITF_SIZ 9U
+#define USB_DFU_DESC_SIZ(itf) (USB_DFU_ITF_SIZ * ((itf) + 2U))
+
+/*
+ * bmAttribute value for DFU:
+ * bitCanDnload = 1(bit 0)
+ * bitCanUpload = 1(bit 1)
+ * bitManifestationTolerant = 1 (bit 2)
+ * bitWillDetach = 1(bit 3)
+ * Reserved (bit4-6)
+ * bitAcceleratedST = 0(bit 7)
+ */
+#define DFU_BM_ATTRIBUTE 0x0FU
+
+#define DFU_STATUS_SIZE 6U
+
+/* Callback for media access */
+struct usb_dfu_media {
+ int (*upload)(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+ void *user_data);
+ int (*download)(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+ void *user_data);
+ int (*manifestation)(uint8_t alt, void *user_data);
+};
+
+/* Internal DFU handle */
+struct usb_dfu_handle {
+ uint8_t status[DFU_STATUS_SIZE];
+ uint8_t dev_state;
+ uint8_t dev_status;
+ uint8_t alt_setting;
+ const struct usb_dfu_media *callback;
+};
+
+void usb_dfu_register(struct usb_handle *pdev, struct usb_dfu_handle *phandle);
+
+int usb_dfu_loop(struct usb_handle *pdev, const struct usb_dfu_media *pmedia);
+
+/* Function provided by plat */
+struct usb_handle *usb_dfu_plat_init(void);
+
+#endif /* USB_DFU_H */
diff --git a/plat/st/common/stm32cubeprogrammer_uart.c b/plat/st/common/stm32cubeprogrammer_uart.c
new file mode 100644
index 0000000..d004dcf
--- /dev/null
+++ b/plat/st/common/stm32cubeprogrammer_uart.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <endian.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32_uart.h>
+#include <drivers/st/stm32_uart_regs.h>
+#include <lib/mmio.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32cubeprogrammer.h>
+
+/* USART bootloader protocol version V4.0 */
+#define USART_BL_VERSION 0x40U
+
+/* Command definition */
+#define GET_CMD_COMMAND 0x00U
+#define GET_VER_COMMAND 0x01U
+#define GET_ID_COMMAND 0x02U
+#define PHASE_COMMAND 0x03U
+#define READ_PART_COMMAND 0x12U
+#define START_COMMAND 0x21U
+#define DOWNLOAD_COMMAND 0x31U
+
+/* Answer defines */
+#define INIT_BYTE 0x7FU
+#define ACK_BYTE 0x79U
+#define NACK_BYTE 0x1FU
+#define ABORT 0x5FU
+
+#define UNDEFINED_DOWN_ADDR U(0xFFFFFFFF)
+#define PROGRAMMER_TIMEOUT_US 20000U
+
+static const uint8_t command_tab[] = {
+ GET_CMD_COMMAND,
+ GET_VER_COMMAND,
+ GET_ID_COMMAND,
+ PHASE_COMMAND,
+ START_COMMAND,
+ DOWNLOAD_COMMAND
+};
+
+/* STM32CubeProgrammer over UART handle */
+struct stm32prog_uart_handle_s {
+ struct stm32_uart_handle_s uart;
+ uint32_t packet;
+ uint8_t *addr;
+ uint32_t len;
+ uint8_t phase;
+ /* Error msg buffer: max 255 in UART protocol, reduced in TF-A */
+ uint8_t error[64];
+} handle;
+
+/* Trace and handle unrecoverable UART protocol error */
+#define STM32PROG_ERROR(...) \
+ { \
+ ERROR(__VA_ARGS__); \
+ if (handle.phase != PHASE_RESET) { \
+ snprintf((char *)&handle.error, sizeof(handle.error), __VA_ARGS__); \
+ handle.phase = PHASE_RESET; \
+ handle.addr = (uint8_t *)UNDEFINED_DOWN_ADDR; \
+ handle.len = 0U; \
+ handle.packet = 0U; \
+ } \
+ }
+
+static int uart_write(const uint8_t *addr, uint16_t size)
+{
+ while (size != 0U) {
+ if (stm32_uart_putc(&handle.uart, *addr) != 0) {
+ return -EIO;
+ }
+ size--;
+ addr++;
+ }
+
+ return 0;
+}
+
+static int uart_write_8(uint8_t byte)
+{
+ return stm32_uart_putc(&handle.uart, byte);
+}
+
+static int uart_write_32(uint32_t value)
+{
+ return uart_write((uint8_t *)&value, 4U);
+}
+
+static int uart_read_8(uint8_t *byte)
+{
+ int ret;
+ uint64_t timeout_ref = timeout_init_us(PROGRAMMER_TIMEOUT_US);
+
+ do {
+ ret = stm32_uart_getc(&handle.uart);
+ if (ret == -EAGAIN) {
+ if (timeout_elapsed(timeout_ref)) {
+ return -ETIMEDOUT;
+ }
+ } else if (ret < 0) {
+ return ret;
+ }
+ } while (ret == -EAGAIN);
+
+ *byte = (uint8_t)ret;
+
+ return 0;
+}
+
+static int uart_send_result(uint8_t byte)
+{
+ int ret;
+
+ /* Always flush fifo before to send result = read all pending data */
+ do {
+ ret = stm32_uart_getc(&handle.uart);
+ } while (ret >= 0);
+
+ return uart_write_8(byte);
+}
+
+static bool is_valid_header(fip_toc_header_t *header)
+{
+ return (header->name == TOC_HEADER_NAME) &&
+ (header->serial_number != 0U);
+}
+
+static int uart_receive_command(uint8_t *command)
+{
+ uint8_t byte = 0U;
+ uint8_t xor = 0U;
+ unsigned int count;
+ bool found = false;
+ int ret;
+
+ /* Repeat read until something is received */
+ do {
+ stm32_iwdg_refresh();
+ ret = uart_read_8(&byte);
+ } while (ret == -ETIMEDOUT);
+
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Handle reconnection request */
+ if (byte == INIT_BYTE) {
+ *command = byte;
+ return 0;
+ }
+
+ for (count = 0U; count < ARRAY_SIZE(command_tab); count++) {
+ if (command_tab[count] == byte) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ VERBOSE("UART: Command unknown (byte=0x%x)\n", byte);
+ return -EPROTO;
+ }
+
+ ret = uart_read_8(&xor);
+ if (ret != 0) {
+ return ret;
+ }
+ if ((byte ^ xor) != 0xFF) {
+ VERBOSE("UART: Command XOR check fail (byte=0x%x, xor=0x%x)\n",
+ byte, xor);
+ return -EPROTO;
+ }
+
+ *command = byte;
+
+ return 0;
+}
+
+static int get_cmd_command(void)
+{
+ const uint8_t msg[2] = {
+ sizeof(command_tab), /* Length of data - 1 */
+ USART_BL_VERSION
+ };
+ int ret;
+
+ ret = uart_write(msg, sizeof(msg));
+ if (ret != 0) {
+ return ret;
+ }
+
+ return uart_write(command_tab, sizeof(command_tab));
+}
+
+static int get_version_command(void)
+{
+ return uart_write_8(STM32_TF_VERSION);
+}
+
+static int get_id_command(void)
+{
+ uint8_t msg[3] = {
+ sizeof(msg) - 1 /* Length of data - 1 */
+ };
+ uint32_t chip_id = stm32mp_get_chip_dev_id();
+
+ be16enc(&msg[1], chip_id);
+
+ return uart_write(msg, sizeof(msg));
+}
+
+static int uart_send_phase(uint32_t address)
+{
+ int ret;
+ uint8_t msg_size = 5U; /* Length of data - 1 */
+ uint8_t error_size = 0U;
+
+ /* Additional information only for RESET phase */
+ if (handle.phase == PHASE_RESET) {
+ error_size = strnlen((char *)&handle.error, sizeof(handle.error));
+ }
+ ret = uart_write_8(msg_size + error_size);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Send the ID of next partition */
+ ret = uart_write_8(handle.phase);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Destination address */
+ ret = uart_write_32(address);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = uart_write_8(error_size);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Additional information: message error */
+ if (error_size > 0U) {
+ ret = uart_write(handle.error, error_size);
+ }
+
+ return ret;
+}
+
+static int uart_download_part(void)
+{
+ uint8_t operation = 0U;
+ uint8_t xor;
+ uint8_t byte = 0U;
+ uint32_t packet_number = 0U;
+ uint32_t packet_size = 0U;
+ uint32_t i = 0U;
+ int ret;
+
+ /* Get operation number */
+ ret = uart_read_8(&operation);
+ if (ret != 0) {
+ return ret;
+ }
+
+ xor = operation;
+
+ /* Get packet number */
+ for (i = 3U; i != 0U; i--) {
+ ret = uart_read_8(&byte);
+ if (ret != 0) {
+ return ret;
+ }
+
+ xor ^= byte;
+ packet_number = (packet_number << 8) | byte;
+ }
+
+ if (packet_number != handle.packet) {
+ WARN("UART: Bad packet number receive: %u, expected %u\n",
+ packet_number, handle.packet);
+ return -EPROTO;
+ }
+
+ /* Checksum */
+ ret = uart_read_8(&byte);
+ if (ret != 0) {
+ return ret;
+ }
+ if (xor != byte) {
+ VERBOSE("UART: Download Command checksum xor: %x, received %x\n",
+ xor, byte);
+ return -EPROTO;
+ }
+
+ ret = uart_send_result(ACK_BYTE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = uart_read_8(&byte);
+ if (ret != 0) {
+ return ret;
+ }
+ xor = byte;
+ packet_size = byte + 1U;
+ if (handle.len < packet_size) {
+ STM32PROG_ERROR("Download overflow at %p\n", handle.addr + packet_size);
+ return 0;
+ }
+
+ for (i = 0U; i < packet_size; i++) {
+ ret = uart_read_8(&byte);
+ if (ret != 0) {
+ return ret;
+ }
+
+ *(handle.addr + i) = byte;
+ xor ^= byte;
+ }
+
+ /* Checksum */
+ ret = uart_read_8(&byte) != 0;
+ if (ret != 0) {
+ return ret;
+ }
+ if (xor != byte) {
+ VERBOSE("UART: Download Data checksum xor: %x, received %x\n",
+ xor, byte);
+ return -EPROTO;
+ }
+
+ /* Packet treated */
+ handle.packet++;
+ handle.addr += packet_size;
+ handle.len -= packet_size;
+
+ return 0;
+}
+
+static int uart_start_cmd(uintptr_t buffer)
+{
+ uint8_t byte = 0U;
+ uint8_t xor = 0U;
+ uint32_t i;
+ uint32_t start_address = 0U;
+ int ret;
+
+ /* Get address */
+ for (i = 4U; i != 0U; i--) {
+ ret = uart_read_8(&byte);
+ if (ret != 0U) {
+ return ret;
+ }
+
+ xor ^= byte;
+ start_address = (start_address << 8) | byte;
+ }
+
+ /* Checksum */
+ ret = uart_read_8(&byte);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (xor != byte) {
+ VERBOSE("UART: Start Command checksum xor: %x, received %x\n",
+ xor, byte);
+ return -EPROTO;
+ }
+
+ if (start_address != UNDEFINED_DOWN_ADDR) {
+ STM32PROG_ERROR("Invalid start at %x, for phase %u\n",
+ start_address, handle.phase);
+ return 0;
+ }
+
+ if (!is_valid_header((fip_toc_header_t *)buffer)) {
+ STM32PROG_ERROR("FIP Header check failed %lx, for phase %u\n",
+ buffer, handle.phase);
+ return -EIO;
+ }
+ VERBOSE("FIP header looks OK.\n");
+
+ return 0;
+}
+
+static int uart_read(uint8_t id, uintptr_t buffer, size_t length)
+{
+ bool start_done = false;
+ int ret;
+ uint8_t command = 0U;
+
+ handle.phase = id;
+ handle.packet = 0U;
+ handle.addr = (uint8_t *)buffer;
+ handle.len = length;
+
+ INFO("UART: read phase %u at 0x%lx size 0x%x\n",
+ id, buffer, length);
+ while (!start_done) {
+ ret = uart_receive_command(&command);
+ if (ret != 0) {
+ /* Delay to wait STM32CubeProgrammer end of transmission */
+ mdelay(3);
+
+ ret = uart_send_result(NACK_BYTE);
+ if (ret != 0U) {
+ return ret;
+ }
+
+ continue;
+ }
+
+ uart_send_result(ACK_BYTE);
+
+ switch (command) {
+ case INIT_BYTE:
+ INFO("UART: Connected\n");
+ /* Nothing to do */
+ continue;
+
+ case GET_CMD_COMMAND:
+ ret = get_cmd_command();
+ break;
+
+ case GET_VER_COMMAND:
+ ret = get_version_command();
+ break;
+
+ case GET_ID_COMMAND:
+ ret = get_id_command();
+ break;
+
+ case PHASE_COMMAND:
+ ret = uart_send_phase((uint32_t)buffer);
+ if ((ret == 0) && (handle.phase == PHASE_RESET)) {
+ start_done = true;
+ INFO("UART: Reset\n");
+ }
+ break;
+
+ case DOWNLOAD_COMMAND:
+ ret = uart_download_part();
+ break;
+
+ case START_COMMAND:
+ ret = uart_start_cmd(buffer);
+ if ((ret == 0) && (handle.phase == id)) {
+ INFO("UART: Start phase %u\n", handle.phase);
+ start_done = true;
+ }
+ break;
+
+ default:
+ WARN("UART: Unknown command\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret == 0) {
+ ret = uart_send_result(ACK_BYTE);
+ } else {
+ ret = uart_send_result(NACK_BYTE);
+ }
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/* Init UART: 115200, 8bit 1stop parity even and enable FIFO mode */
+const struct stm32_uart_init_s init = {
+ .baud_rate = STM32MP_UART_BAUDRATE,
+ .word_length = STM32_UART_WORDLENGTH_9B,
+ .stop_bits = STM32_UART_STOPBITS_1,
+ .parity = STM32_UART_PARITY_EVEN,
+ .hw_flow_control = STM32_UART_HWCONTROL_NONE,
+ .mode = STM32_UART_MODE_TX_RX,
+ .fifo_mode = STM32_UART_FIFOMODE_EN,
+};
+
+int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len)
+{
+ int ret;
+
+ if (stm32_uart_init(&handle.uart, instance, &init) != 0) {
+ return -EIO;
+ }
+
+ /*
+ * The following NACK_BYTE is written because STM32CubeProgrammer has
+ * already sent its command before TF-A has reached this point, and
+ * because FIFO was not configured by BootROM.
+ * The byte in the UART_RX register is then the checksum and not the
+ * command. NACK_BYTE has to be written, so that the programmer will
+ * re-send the good command.
+ */
+ ret = uart_send_result(NACK_BYTE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return uart_read(PHASE_SSBL, base, len);
+}
diff --git a/plat/st/common/stm32cubeprogrammer_usb.c b/plat/st/common/stm32cubeprogrammer_usb.c
new file mode 100644
index 0000000..75e8038
--- /dev/null
+++ b/plat/st/common/stm32cubeprogrammer_usb.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <tools_share/firmware_image_package.h>
+
+#include <stm32cubeprogrammer.h>
+#include <usb_dfu.h>
+
+/* Undefined download address */
+#define UNDEFINED_DOWN_ADDR 0xFFFFFFFF
+
+struct dfu_state {
+ uint8_t phase;
+ uintptr_t base;
+ size_t len;
+ uintptr_t address;
+ /* working buffer */
+ uint8_t buffer[UCHAR_MAX];
+};
+
+static struct dfu_state dfu_state;
+
+/* minimal size of Get Pḧase = offset for additionnl information */
+#define GET_PHASE_LEN 9
+
+#define DFU_ERROR(...) \
+ { \
+ ERROR(__VA_ARGS__); \
+ if (dfu->phase != PHASE_RESET) { \
+ snprintf((char *)&dfu->buffer[GET_PHASE_LEN], \
+ sizeof(dfu->buffer) - GET_PHASE_LEN, \
+ __VA_ARGS__); \
+ dfu->phase = PHASE_RESET; \
+ dfu->address = UNDEFINED_DOWN_ADDR; \
+ dfu->len = 0; \
+ } \
+ }
+
+static bool is_valid_header(fip_toc_header_t *header)
+{
+ if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0U)) {
+ return true;
+ }
+
+ return false;
+}
+
+static int dfu_callback_upload(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+ void *user_data)
+{
+ int result = 0;
+ uint32_t length = 0;
+ struct dfu_state *dfu = (struct dfu_state *)user_data;
+
+ switch (usb_dfu_get_phase(alt)) {
+ case PHASE_CMD:
+ /* Get Pḧase */
+ dfu->buffer[0] = dfu->phase;
+ dfu->buffer[1] = (uint8_t)(dfu->address);
+ dfu->buffer[2] = (uint8_t)(dfu->address >> 8);
+ dfu->buffer[3] = (uint8_t)(dfu->address >> 16);
+ dfu->buffer[4] = (uint8_t)(dfu->address >> 24);
+ dfu->buffer[5] = 0x00;
+ dfu->buffer[6] = 0x00;
+ dfu->buffer[7] = 0x00;
+ dfu->buffer[8] = 0x00;
+ length = GET_PHASE_LEN;
+ if (dfu->phase == PHASE_FLASHLAYOUT &&
+ dfu->address == UNDEFINED_DOWN_ADDR) {
+ INFO("Send detach request\n");
+ dfu->buffer[length++] = 0x01;
+ }
+ if (dfu->phase == PHASE_RESET) {
+ /* error information is added by DFU_ERROR macro */
+ length += strnlen((char *)&dfu->buffer[GET_PHASE_LEN],
+ sizeof(dfu->buffer) - GET_PHASE_LEN)
+ - 1;
+ }
+ break;
+
+ default:
+ DFU_ERROR("phase ID :%i, alternate %i for phase %i\n",
+ dfu->phase, alt, usb_dfu_get_phase(alt));
+ result = -EIO;
+ break;
+ }
+
+ if (result == 0) {
+ *len = length;
+ *buffer = (uintptr_t)dfu->buffer;
+ }
+
+ return result;
+}
+
+static int dfu_callback_download(uint8_t alt, uintptr_t *buffer, uint32_t *len,
+ void *user_data)
+{
+ struct dfu_state *dfu = (struct dfu_state *)user_data;
+
+ if ((dfu->phase != usb_dfu_get_phase(alt)) ||
+ (dfu->address == UNDEFINED_DOWN_ADDR)) {
+ DFU_ERROR("phase ID :%i, alternate %i, address %x\n",
+ dfu->phase, alt, (uint32_t)dfu->address);
+ return -EIO;
+ }
+
+ VERBOSE("Download %d %lx %x\n", alt, dfu->address, *len);
+ *buffer = dfu->address;
+ dfu->address += *len;
+
+ if (dfu->address - dfu->base > dfu->len) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int dfu_callback_manifestation(uint8_t alt, void *user_data)
+{
+ struct dfu_state *dfu = (struct dfu_state *)user_data;
+
+ if (dfu->phase != usb_dfu_get_phase(alt)) {
+ ERROR("Manifestation phase ID :%i, alternate %i, address %lx\n",
+ dfu->phase, alt, dfu->address);
+ return -EIO;
+ }
+
+ INFO("phase ID :%i, Manifestation %d at %lx\n",
+ dfu->phase, alt, dfu->address);
+
+ switch (dfu->phase) {
+ case PHASE_SSBL:
+ if (!is_valid_header((fip_toc_header_t *)dfu->base)) {
+ DFU_ERROR("FIP Header check failed for phase %d\n", alt);
+ return -EIO;
+ }
+ VERBOSE("FIP header looks OK.\n");
+
+ /* Configure End with request detach */
+ dfu->phase = PHASE_FLASHLAYOUT;
+ dfu->address = UNDEFINED_DOWN_ADDR;
+ dfu->len = 0;
+ break;
+ default:
+ DFU_ERROR("Unknown phase\n");
+ }
+
+ return 0;
+}
+
+/* Open a connection to the USB device */
+static const struct usb_dfu_media usb_dfu_fops = {
+ .upload = dfu_callback_upload,
+ .download = dfu_callback_download,
+ .manifestation = dfu_callback_manifestation,
+};
+
+int stm32cubeprog_usb_load(struct usb_handle *usb_core_handle,
+ uintptr_t base,
+ size_t len)
+{
+ int ret;
+
+ usb_core_handle->user_data = (void *)&dfu_state;
+
+ INFO("DFU USB START...\n");
+ ret = usb_core_start(usb_core_handle);
+ if (ret != USBD_OK) {
+ return -EIO;
+ }
+
+ dfu_state.phase = PHASE_SSBL;
+ dfu_state.address = base;
+ dfu_state.base = base;
+ dfu_state.len = len;
+
+ ret = usb_dfu_loop(usb_core_handle, &usb_dfu_fops);
+ if (ret != USBD_OK) {
+ return -EIO;
+ }
+
+ INFO("DFU USB STOP...\n");
+ ret = usb_core_stop(usb_core_handle);
+ if (ret != USBD_OK) {
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
new file mode 100644
index 0000000..bb56bac
--- /dev/null
+++ b/plat/st/common/stm32mp_common.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_console.h>
+#include <drivers/st/stm32mp_clkfunc.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
+
+#include <platform_def.h>
+
+#define HEADER_VERSION_MAJOR_MASK GENMASK(23, 16)
+#define RESET_TIMEOUT_US_1MS 1000U
+
+static console_t console;
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+ return BL33_BASE;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ return read_cntfrq_el0();
+}
+
+static uintptr_t boot_ctx_address;
+static uint16_t boot_itf_selected;
+
+void stm32mp_save_boot_ctx_address(uintptr_t address)
+{
+ boot_api_context_t *boot_context = (boot_api_context_t *)address;
+
+ boot_ctx_address = address;
+ boot_itf_selected = boot_context->boot_interface_selected;
+}
+
+uintptr_t stm32mp_get_boot_ctx_address(void)
+{
+ return boot_ctx_address;
+}
+
+uint16_t stm32mp_get_boot_itf_selected(void)
+{
+ return boot_itf_selected;
+}
+
+uintptr_t stm32mp_ddrctrl_base(void)
+{
+ return DDRCTRL_BASE;
+}
+
+uintptr_t stm32mp_ddrphyc_base(void)
+{
+ return DDRPHYC_BASE;
+}
+
+uintptr_t stm32mp_pwr_base(void)
+{
+ return PWR_BASE;
+}
+
+uintptr_t stm32mp_rcc_base(void)
+{
+ return RCC_BASE;
+}
+
+bool stm32mp_lock_available(void)
+{
+ const uint32_t c_m_bits = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* The spinlocks are used only when MMU and data cache are enabled */
+ return (read_sctlr() & c_m_bits) == c_m_bits;
+}
+
+int stm32mp_map_ddr_non_cacheable(void)
+{
+ return mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
+ STM32MP_DDR_MAX_SIZE,
+ MT_NON_CACHEABLE | MT_RW | MT_SECURE);
+}
+
+int stm32mp_unmap_ddr(void)
+{
+ return mmap_remove_dynamic_region(STM32MP_DDR_BASE,
+ STM32MP_DDR_MAX_SIZE);
+}
+
+int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx,
+ uint32_t *otp_len)
+{
+ assert(otp_name != NULL);
+ assert(otp_idx != NULL);
+
+ return dt_find_otp_name(otp_name, otp_idx, otp_len);
+}
+
+int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val)
+{
+ uint32_t otp_idx;
+
+ assert(otp_name != NULL);
+ assert(otp_val != NULL);
+
+ if (stm32_get_otp_index(otp_name, &otp_idx, NULL) != 0) {
+ return -1;
+ }
+
+ if (stm32_get_otp_value_from_idx(otp_idx, otp_val) != 0) {
+ ERROR("BSEC: %s Read Error\n", otp_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val)
+{
+ uint32_t ret = BSEC_NOT_SUPPORTED;
+
+ assert(otp_val != NULL);
+
+#if defined(IMAGE_BL2)
+ ret = bsec_shadow_read_otp(otp_val, otp_idx);
+#elif defined(IMAGE_BL32)
+ ret = bsec_read_otp(otp_val, otp_idx);
+#else
+#error "Not supported"
+#endif
+ if (ret != BSEC_OK) {
+ ERROR("BSEC: idx=%u Read Error\n", otp_idx);
+ return -1;
+ }
+
+ return 0;
+}
+
+#if defined(IMAGE_BL2)
+static void reset_uart(uint32_t reset)
+{
+ int ret;
+
+ ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS);
+ if (ret != 0) {
+ panic();
+ }
+
+ udelay(2);
+
+ ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS);
+ if (ret != 0) {
+ panic();
+ }
+
+ mdelay(1);
+}
+#endif
+
+static void set_console(uintptr_t base, uint32_t clk_rate)
+{
+ unsigned int console_flags;
+
+ if (console_stm32_register(base, clk_rate,
+ (uint32_t)STM32MP_UART_BAUDRATE, &console) == 0) {
+ panic();
+ }
+
+ console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH |
+ CONSOLE_FLAG_TRANSLATE_CRLF;
+#if !defined(IMAGE_BL2) && defined(DEBUG)
+ console_flags |= CONSOLE_FLAG_RUNTIME;
+#endif
+
+ console_set_scope(&console, console_flags);
+}
+
+int stm32mp_uart_console_setup(void)
+{
+ struct dt_node_info dt_uart_info;
+ uint32_t clk_rate = 0U;
+ int result;
+ uint32_t boot_itf __unused;
+ uint32_t boot_instance __unused;
+
+ result = dt_get_stdout_uart_info(&dt_uart_info);
+
+ if ((result <= 0) ||
+ (dt_uart_info.status == DT_DISABLED)) {
+ return -ENODEV;
+ }
+
+#if defined(IMAGE_BL2)
+ if ((dt_uart_info.clock < 0) ||
+ (dt_uart_info.reset < 0)) {
+ return -ENODEV;
+ }
+#endif
+
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+ stm32_get_boot_interface(&boot_itf, &boot_instance);
+
+ if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) &&
+ (get_uart_address(boot_instance) == dt_uart_info.base)) {
+ return -EACCES;
+ }
+#endif
+
+#if defined(IMAGE_BL2)
+ if (dt_set_stdout_pinctrl() != 0) {
+ return -ENODEV;
+ }
+
+ clk_enable((unsigned long)dt_uart_info.clock);
+
+ reset_uart((uint32_t)dt_uart_info.reset);
+
+ clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock);
+#endif
+
+ set_console(dt_uart_info.base, clk_rate);
+
+ return 0;
+}
+
+#if STM32MP_EARLY_CONSOLE
+void stm32mp_setup_early_console(void)
+{
+#if defined(IMAGE_BL2) || STM32MP_RECONFIGURE_CONSOLE
+ plat_crash_console_init();
+#endif
+ set_console(STM32MP_DEBUG_USART_BASE, STM32MP_DEBUG_USART_CLK_FRQ);
+ NOTICE("Early console setup\n");
+}
+#endif /* STM32MP_EARLY_CONSOLE */
+
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ * feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+ switch (fid) {
+ case SMCCC_ARCH_SOC_ID:
+ return SMC_ARCH_CALL_SUCCESS;
+ default:
+ return SMC_ARCH_CALL_NOT_SUPPORTED;
+ }
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+ uint32_t chip_id = stm32mp_get_chip_dev_id();
+ uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_ST_BKID, JEDEC_ST_MFID);
+
+ return (int32_t)(manfid | (chip_id & SOC_ID_IMPL_DEF_MASK));
+}
+
+/* Get SOC revision */
+int32_t plat_get_soc_revision(void)
+{
+ return (int32_t)(stm32mp_get_chip_version() & SOC_ID_REV_MASK);
+}
diff --git a/plat/st/common/stm32mp_crypto_lib.c b/plat/st/common/stm32mp_crypto_lib.c
new file mode 100644
index 0000000..d644242
--- /dev/null
+++ b/plat/st/common/stm32mp_crypto_lib.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <endian.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32_hash.h>
+#include <drivers/st/stm32_pka.h>
+#include <drivers/st/stm32_rng.h>
+#include <drivers/st/stm32_saes.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <mbedtls/asn1.h>
+#include <mbedtls/md.h>
+#include <mbedtls/oid.h>
+#include <mbedtls/platform.h>
+#include <mbedtls/x509.h>
+#include <plat/common/platform.h>
+#include <tools_share/firmware_encrypted.h>
+
+#include <platform_def.h>
+
+#define CRYPTO_HASH_MAX_SIZE 32U
+#define CRYPTO_SIGN_MAX_SIZE 64U
+#define CRYPTO_PUBKEY_MAX_SIZE 64U
+#define CRYPTO_MAX_TAG_SIZE 16U
+
+/* brainpoolP256t1 OID is not defined in mbedTLS */
+#define OID_EC_GRP_BP256T1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x08"
+
+#if STM32MP_CRYPTO_ROM_LIB
+struct stm32mp_auth_ops {
+ uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
+ uint8_t *signature, uint32_t ecc_algo);
+};
+
+static struct stm32mp_auth_ops auth_ops;
+#endif
+
+static void crypto_lib_init(void)
+{
+ boot_api_context_t *boot_context __maybe_unused;
+ int ret;
+
+ NOTICE("TRUSTED_BOARD_BOOT support enabled\n");
+
+ ret = stm32_hash_register();
+ if (ret != 0) {
+ ERROR("HASH init (%d)\n", ret);
+ panic();
+ }
+
+ if (stm32mp_is_closed_device() || stm32mp_is_auth_supported()) {
+#if STM32MP_CRYPTO_ROM_LIB
+ boot_context = (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+ auth_ops.verify_signature = boot_context->bootrom_ecdsa_verify_signature;
+#else
+ /* Use hardware peripherals */
+ if (stm32_rng_init() != 0) {
+ panic();
+ }
+
+ if (stm32_saes_driver_init() != 0) {
+ panic();
+ }
+
+ if (stm32_pka_init() != 0) {
+ panic();
+ }
+#endif
+ }
+}
+
+int get_plain_pk_from_asn1(void *pk_ptr, unsigned int pk_len, void **plain_pk,
+ unsigned int *len, int *pk_alg)
+{
+ int ret;
+ mbedtls_pk_context mbedtls_pk = {0};
+ unsigned char *p, *end;
+ mbedtls_asn1_buf alg_params = {0};
+ mbedtls_asn1_buf alg_oid = {0};
+
+ *plain_pk = NULL;
+ *len = 0U;
+
+ /* Parse the public key */
+ mbedtls_pk_init(&mbedtls_pk);
+ p = (unsigned char *)pk_ptr;
+ end = (unsigned char *)(p + pk_len);
+
+ ret = mbedtls_asn1_get_tag(&p, end, len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (ret != 0) {
+ return -EINVAL;
+ }
+
+ end = p + *len;
+ ret = mbedtls_asn1_get_alg(&p, end, &alg_oid, &alg_params);
+ if (ret != 0) {
+ VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
+ return -EINVAL;
+ }
+
+ if (pk_alg != NULL) {
+ if ((strlen(MBEDTLS_OID_EC_GRP_SECP256R1) == alg_params.len) &&
+ (memcmp(MBEDTLS_OID_EC_GRP_SECP256R1, alg_params.p, alg_params.len) == 0)) {
+ *pk_alg = BOOT_API_ECDSA_ALGO_TYPE_P256NIST;
+ } else if ((strlen(OID_EC_GRP_BP256T1) == alg_params.len) &&
+ (memcmp(OID_EC_GRP_BP256T1, alg_params.p, alg_params.len) == 0)) {
+ *pk_alg = BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256;
+ } else {
+ ERROR("%s: Algorithm is not supported\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ ret = mbedtls_asn1_get_bitstring_null(&p, end, len);
+ if (ret != 0) {
+ VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
+ return -EINVAL;
+ }
+
+ /* We remove the ident (0x04) first byte. */
+ if ((*len < 1U) || (p[0] != MBEDTLS_ASN1_OCTET_STRING)) {
+ VERBOSE("%s: not expected len or tag\n", __func__);
+ return -EINVAL;
+ }
+
+ *len = *len - 1U;
+ *plain_pk = p + 1U;
+
+ return 0;
+}
+
+#if STM32MP_CRYPTO_ROM_LIB
+uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
+ uint8_t *signature, uint32_t ecc_algo)
+{
+ int ret;
+
+ ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
+ STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE);
+ if (ret != 0) {
+ VERBOSE("%s: mmap_add_dynamic_region (%d)\n", __func__, ret);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ ret = auth_ops.verify_signature(hash_in, pubkey_in, signature, ecc_algo);
+
+ if (ret != BOOT_API_RETURN_OK) {
+ VERBOSE("%s: auth_ops.verify_sign (%d)\n", __func__, ret);
+ ret = CRYPTO_ERR_SIGNATURE;
+ } else {
+ ret = 0;
+ }
+
+ mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED);
+
+ return ret;
+}
+
+int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+ void **hashed_pk_ptr, unsigned int *hashed_pk_len)
+{
+ return get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, hashed_pk_ptr, hashed_pk_len, NULL);
+}
+#else /* STM32MP_CRYPTO_ROM_LIB*/
+static uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
+ uint8_t *signature, uint32_t ecc_algo)
+{
+ int ret = -1;
+ enum stm32_pka_ecdsa_curve_id cid;
+
+ switch (ecc_algo) {
+ case BOOT_API_ECDSA_ALGO_TYPE_P256NIST:
+#if PKA_USE_NIST_P256
+ cid = PKA_NIST_P256;
+ ret = 0;
+#else
+ WARN("%s nist_p256 requested but not included\n", __func__);
+#endif
+ break;
+ case BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256:
+#if PKA_USE_BRAINPOOL_P256T1
+ cid = PKA_BRAINPOOL_P256T1;
+ ret = 0;
+#else
+ WARN("%s brainpool_p256t1 requested but not included\n", __func__);
+#endif
+ break;
+ default:
+ WARN("%s unexpected ecc_algo(%u)\n", __func__, ecc_algo);
+ break;
+ }
+
+ if (ret < 0) {
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ ret = stm32_pka_ecdsa_verif(hash_in,
+ BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES,
+ signature, BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
+ signature + BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
+ BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
+ pubkey_in, BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
+ pubkey_in + BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
+ BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U, cid);
+ if (ret < 0) {
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ return 0;
+}
+
+int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+ void **hashed_pk_ptr, unsigned int *hashed_pk_len)
+{
+ static uint8_t st_pk[CRYPTO_PUBKEY_MAX_SIZE + sizeof(uint32_t)];
+ int ret;
+ void *plain_pk;
+ unsigned int len;
+ int curve_id;
+ uint32_t cid;
+
+ ret = get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, &plain_pk, &len, &curve_id);
+ if ((ret != 0) || (len > CRYPTO_PUBKEY_MAX_SIZE)) {
+ return -EINVAL;
+ }
+
+ cid = curve_id; /* we want value of curve_id (1 or 2) in a uint32_t */
+
+ memcpy(st_pk, &cid, sizeof(cid));
+ memcpy(st_pk + sizeof(cid), plain_pk, len);
+
+ *hashed_pk_ptr = st_pk;
+ *hashed_pk_len = len + sizeof(cid);
+
+ return 0;
+}
+#endif /* STM32MP_CRYPTO_ROM_LIB */
+
+static int get_plain_digest_from_asn1(void *digest_ptr, unsigned int digest_len,
+ uint8_t **out, size_t *out_len, mbedtls_md_type_t *md_alg)
+{
+ int ret;
+ mbedtls_asn1_buf hash_oid, params;
+ size_t len;
+ unsigned char *p, *end;
+
+ *out = NULL;
+ *out_len = 0U;
+
+ /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
+ p = (unsigned char *)digest_ptr;
+ end = p + digest_len;
+ ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Get the hash algorithm */
+ ret = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = mbedtls_oid_get_md_alg(&hash_oid, md_alg);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Length of hash must match the algorithm's size */
+ if (len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) {
+ return -1;
+ }
+
+ *out = p;
+ *out_len = len;
+
+ return 0;
+}
+
+static int crypto_verify_signature(void *data_ptr, unsigned int data_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *sig_alg, unsigned int sig_alg_len,
+ void *pk_ptr, unsigned int pk_len)
+{
+ uint8_t image_hash[CRYPTO_HASH_MAX_SIZE] = {0};
+ uint8_t sig[CRYPTO_SIGN_MAX_SIZE];
+ uint8_t my_pk[CRYPTO_PUBKEY_MAX_SIZE];
+ int ret;
+ size_t len;
+ mbedtls_asn1_sequence seq;
+ mbedtls_asn1_sequence *cur;
+ unsigned char *p, *end;
+ int curve_id;
+ mbedtls_asn1_buf sig_oid, sig_params;
+ mbedtls_md_type_t md_alg;
+ mbedtls_pk_type_t pk_alg;
+ size_t bignum_len = sizeof(sig) / 2U;
+ unsigned int seq_num = 0U;
+
+ if (!stm32mp_is_closed_device() && !stm32mp_is_auth_supported()) {
+ return CRYPTO_SUCCESS;
+ }
+
+ /* Get pointers to signature OID and parameters */
+ p = (unsigned char *)sig_alg;
+ end = (unsigned char *)(p + sig_alg_len);
+ ret = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
+ if (ret != 0) {
+ VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* Get the actual signature algorithm (MD + PK) */
+ ret = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
+ if (ret != 0) {
+ VERBOSE("%s: mbedtls_oid_get_sig_alg (%d)\n", __func__, ret);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ if ((md_alg != MBEDTLS_MD_SHA256) || (pk_alg != MBEDTLS_PK_ECDSA)) {
+ VERBOSE("%s: md_alg=%u pk_alg=%u\n", __func__, md_alg, pk_alg);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ ret = get_plain_pk_from_asn1(pk_ptr, pk_len, &pk_ptr, &pk_len, &curve_id);
+ if (ret != 0) {
+ VERBOSE("%s: get_plain_pk_from_asn1 (%d)\n", __func__, ret);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* We expect a known pk_len */
+ if (pk_len != sizeof(my_pk)) {
+ VERBOSE("%s: pk_len=%u sizeof(my_pk)=%zu)\n", __func__, pk_len, sizeof(my_pk));
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* Need to copy as auth_ops.verify_signature
+ * expects aligned public key.
+ */
+ memcpy(my_pk, pk_ptr, sizeof(my_pk));
+
+ /* Get the signature (bitstring) */
+ p = (unsigned char *)sig_ptr;
+ end = (unsigned char *)(p + sig_len);
+ ret = mbedtls_asn1_get_bitstring_null(&p, end, &len);
+ if (ret != 0) {
+ VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* Get r and s from sequence */
+ ret = mbedtls_asn1_get_sequence_of(&p, end, &seq, MBEDTLS_ASN1_INTEGER);
+ if (ret != 0) {
+ VERBOSE("%s: mbedtls_asn1_get_sequence_of (%d)\n", __func__, ret);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /* We expect only 2 integers (r and s) from the sequence */
+ if (seq.next->next != NULL) {
+ cur = seq.next;
+ mbedtls_asn1_sequence *next;
+
+ VERBOSE("%s: nb seq != 2\n", __func__);
+ /* Free all the sequences */
+ while (cur != NULL) {
+ next = cur->next;
+ mbedtls_free(cur);
+ cur = next;
+ }
+
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ /*
+ * ECDSA signatures are composed of a tuple (R,S) where R and S are between 0 and n.
+ * This means that the R and S can have a maximum of 32 each, but can also be smaller.
+ * Also seen the integer sequence may (sometime) start with 0x00 as MSB, but we can only
+ * manage exactly 2*32 bytes, we remove this higher byte if there are not 00,
+ * we will fail either.
+ */
+ cur = &seq;
+ memset(sig, 0U, sizeof(sig));
+
+ while (cur != NULL) {
+ size_t skip = 0U;
+ size_t seek = seq_num * bignum_len;
+
+ if (cur->buf.len > bignum_len) {
+ /* Remove extra 0x00 bytes */
+ skip = cur->buf.len - bignum_len;
+ } else if (cur->buf.len < bignum_len) {
+ /* Add padding to match HW required size */
+ seek += (bignum_len % cur->buf.len);
+ }
+
+ if (seek + cur->buf.len > sizeof(sig) + skip) {
+ panic();
+ }
+
+ memcpy(sig + seek, cur->buf.p + skip, cur->buf.len - skip);
+ cur = cur->next;
+ seq_num++;
+ }
+
+ /* Need to free allocated 'next' in mbedtls_asn1_get_sequence_of */
+ mbedtls_free(seq.next);
+
+ /* Compute hash for the data covered by the signature */
+ stm32_hash_init(HASH_SHA256);
+
+ ret = stm32_hash_final_update((uint8_t *)data_ptr, data_len, image_hash);
+ if (ret != 0) {
+ VERBOSE("%s: stm32_hash_final_update (%d)\n", __func__, ret);
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ return verify_signature(image_hash, my_pk, sig, curve_id);
+}
+
+static int crypto_verify_hash(void *data_ptr, unsigned int data_len,
+ void *digest_info_ptr,
+ unsigned int digest_info_len)
+{
+ int ret;
+ uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+ unsigned char *p;
+ mbedtls_md_type_t md_alg;
+ size_t len;
+
+ /* we receive an asn1 encapsulated digest, we flatten it */
+ ret = get_plain_digest_from_asn1(digest_info_ptr,
+ digest_info_len, &p, &len,
+ &md_alg);
+ if ((ret != 0) || (md_alg != MBEDTLS_MD_SHA256) || (len != sizeof(calc_hash))) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ digest_info_ptr = p;
+ digest_info_len = len;
+
+ stm32_hash_init(HASH_SHA256);
+
+ ret = stm32_hash_final_update(data_ptr, data_len, calc_hash);
+ if (ret != 0) {
+ VERBOSE("%s: hash failed\n", __func__);
+ return CRYPTO_ERR_HASH;
+ }
+
+ ret = memcmp(calc_hash, digest_info_ptr, digest_info_len);
+ if (ret != 0) {
+ VERBOSE("%s: not expected digest\n", __func__);
+ ret = CRYPTO_ERR_HASH;
+ }
+
+ return ret;
+}
+
+#if !defined(DECRYPTION_SUPPORT_none)
+static int derive_key(uint8_t *key, size_t *key_len, size_t len,
+ unsigned int *flags, const uint8_t *img_id, size_t img_id_len)
+{
+ size_t i, j;
+
+ assert(*key_len >= 32U);
+
+ /*
+ * Not a real derivation yet
+ *
+ * But we expect a 32 bytes key, and OTP is only 16 bytes
+ * => duplicate.
+ */
+ for (i = 0U, j = len; j < 32U;
+ i += sizeof(uint32_t), j += sizeof(uint32_t)) {
+ memcpy(key + j, key + i, sizeof(uint32_t));
+ }
+
+ *key_len = 32U;
+ /* Variable 'key' store a real key */
+ *flags = 0U;
+
+ return 0;
+}
+
+int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
+ size_t *key_len, unsigned int *flags,
+ const uint8_t *img_id, size_t img_id_len)
+{
+ uint32_t otp_idx;
+ uint32_t otp_len;
+ size_t read_len;
+ size_t i;
+
+ if (fw_enc_status == FW_ENC_WITH_BSSK) {
+ return -EINVAL;
+ }
+
+ if (stm32_get_otp_index(ENCKEY_OTP, &otp_idx, &otp_len) != 0) {
+ VERBOSE("%s: get %s index error\n", __func__, ENCKEY_OTP);
+ return -EINVAL;
+ }
+
+ if (otp_len > (*key_len * CHAR_BIT)) {
+ VERBOSE("%s: length Error otp_len=%u key_len=%u\n", __func__,
+ otp_len, *key_len * CHAR_BIT);
+ return -EINVAL;
+ }
+
+ read_len = otp_len / CHAR_BIT;
+ assert(read_len % sizeof(uint32_t) == 0);
+
+ for (i = 0U; i < read_len / sizeof(uint32_t); i++) {
+ uint32_t tmp;
+ uint32_t otp_val;
+
+ if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) {
+ zeromem(key, *key_len);
+ VERBOSE("%s: unable to read from otp\n", __func__);
+ return -EINVAL;
+ }
+
+ tmp = bswap32(otp_val);
+ memcpy(key + i * sizeof(uint32_t), &tmp, sizeof(tmp));
+ }
+
+ /* Now we have the OTP values in key till read_len */
+
+ if (derive_key(key, key_len, read_len, flags, img_id,
+ img_id_len) != 0) {
+ zeromem(key, *key_len);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum stm32_saes_key_selection select_key(unsigned int key_flags)
+{
+ if ((key_flags & ENC_KEY_IS_IDENTIFIER) != 0U) {
+ panic();
+ }
+
+ /* Use the provided key buffer */
+ return STM32_SAES_KEY_SOFT;
+}
+
+static int stm32_decrypt_aes_gcm(void *data, size_t data_len,
+ const void *key, unsigned int key_len,
+ unsigned int key_flags,
+ const void *iv, unsigned int iv_len,
+ const void *tag, unsigned int tag_len)
+{
+ int ret;
+ struct stm32_saes_context ctx;
+ unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
+ enum stm32_saes_key_selection key_mode;
+ unsigned int diff = 0U;
+ unsigned int i;
+
+ key_mode = select_key(key_flags);
+
+ ret = stm32_saes_init(&ctx, true, STM32_SAES_MODE_GCM, key_mode, key,
+ key_len, iv, iv_len);
+ if (ret != 0) {
+ return CRYPTO_ERR_INIT;
+ }
+
+ ret = stm32_saes_update_assodata(&ctx, true, NULL, 0U);
+ if (ret != 0) {
+ return CRYPTO_ERR_DECRYPTION;
+ }
+
+ ret = stm32_saes_update_load(&ctx, true, data, data, data_len);
+ if (ret != 0) {
+ return CRYPTO_ERR_DECRYPTION;
+ }
+
+ ret = stm32_saes_final(&ctx, tag_buf, sizeof(tag_buf));
+ if (ret != 0) {
+ return CRYPTO_ERR_DECRYPTION;
+ }
+
+ /* Check tag in "constant-time" */
+ for (i = 0U; i < tag_len; i++) {
+ diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
+ }
+
+ if (diff != 0U) {
+ return CRYPTO_ERR_DECRYPTION;
+ }
+
+ return CRYPTO_SUCCESS;
+}
+
+/*
+ * Authenticated decryption of an image
+ *
+ */
+static int crypto_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, size_t len,
+ const void *key, unsigned int key_len, unsigned int key_flags,
+ const void *iv, unsigned int iv_len, const void *tag,
+ unsigned int tag_len)
+{
+ int rc = -1;
+ uint32_t real_iv[4];
+
+ switch (dec_algo) {
+ case CRYPTO_GCM_DECRYPT:
+ /*
+ * GCM expect a Nonce
+ * The AES IV is the nonce (a uint32_t[3])
+ * then a counter (a uint32_t big endian)
+ * The counter starts at 2.
+ */
+ memcpy(real_iv, iv, iv_len);
+ real_iv[3] = htobe32(0x2U);
+
+ rc = stm32_decrypt_aes_gcm(data_ptr, len, key, key_len, key_flags,
+ real_iv, sizeof(real_iv), tag, tag_len);
+ break;
+ default:
+ rc = CRYPTO_ERR_DECRYPTION;
+ break;
+ }
+
+ if (rc != 0) {
+ return rc;
+ }
+
+ return CRYPTO_SUCCESS;
+}
+
+REGISTER_CRYPTO_LIB("stm32_crypto_lib",
+ crypto_lib_init,
+ crypto_verify_signature,
+ crypto_verify_hash,
+ crypto_auth_decrypt);
+
+#else /* No decryption support */
+REGISTER_CRYPTO_LIB("stm32_crypto_lib",
+ crypto_lib_init,
+ crypto_verify_signature,
+ crypto_verify_hash,
+ NULL);
+
+#endif
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
new file mode 100644
index 0000000..c9efeb5
--- /dev/null
+++ b/plat/st/common/stm32mp_dt.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/st/regulator.h>
+#include <drivers/st/stm32_gpio.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+#include <stm32mp_dt.h>
+
+static void *fdt;
+
+/*******************************************************************************
+ * This function checks device tree file with its header.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_open_and_check(uintptr_t dt_addr)
+{
+ int ret;
+
+ ret = fdt_check_header((void *)dt_addr);
+ if (ret == 0) {
+ fdt = (void *)dt_addr;
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+ * This function gets the address of the DT.
+ * If DT is OK, fdt_addr is filled with DT address.
+ * Returns 1 if success, 0 otherwise.
+ ******************************************************************************/
+int fdt_get_address(void **fdt_addr)
+{
+ if (fdt == NULL) {
+ return 0;
+ }
+
+ *fdt_addr = fdt;
+
+ return 1;
+}
+
+/*******************************************************************************
+ * This function check the presence of a node (generic use of fdt library).
+ * Returns true if present, else return false.
+ ******************************************************************************/
+bool fdt_check_node(int node)
+{
+ int len;
+ const char *cchar;
+
+ cchar = fdt_get_name(fdt, node, &len);
+
+ return (cchar != NULL) && (len >= 0);
+}
+
+/*******************************************************************************
+ * This function return global node status (generic use of fdt library).
+ ******************************************************************************/
+uint8_t fdt_get_status(int node)
+{
+ uint8_t status = DT_DISABLED;
+ const char *cchar;
+
+ cchar = fdt_getprop(fdt, node, "status", NULL);
+ if ((cchar == NULL) ||
+ (strncmp(cchar, "okay", strlen("okay")) == 0)) {
+ status |= DT_NON_SECURE;
+ }
+
+ cchar = fdt_getprop(fdt, node, "secure-status", NULL);
+ if (cchar == NULL) {
+ if (status == DT_NON_SECURE) {
+ status |= DT_SECURE;
+ }
+ } else if (strncmp(cchar, "okay", strlen("okay")) == 0) {
+ status |= DT_SECURE;
+ }
+
+ return status;
+}
+
+#if ENABLE_ASSERTIONS
+/*******************************************************************************
+ * This function returns the address cells from the node parent.
+ * Returns:
+ * - #address-cells value if success.
+ * - invalid value if error.
+ * - a default value if undefined #address-cells property as per libfdt
+ * implementation.
+ ******************************************************************************/
+static int fdt_get_node_parent_address_cells(int node)
+{
+ int parent;
+
+ parent = fdt_parent_offset(fdt, node);
+ if (parent < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return fdt_address_cells(fdt, parent);
+}
+#endif
+
+/*******************************************************************************
+ * This function gets the stdout pin configuration information from the DT.
+ * And then calls the sub-function to treat it and set GPIO registers.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_set_stdout_pinctrl(void)
+{
+ int node;
+
+ node = fdt_get_stdout_node_offset(fdt);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return dt_set_pinctrl_config(node);
+}
+
+/*******************************************************************************
+ * This function fills the generic information from a given node.
+ ******************************************************************************/
+void dt_fill_device_info(struct dt_node_info *info, int node)
+{
+ const fdt32_t *cuint;
+
+ assert(fdt_get_node_parent_address_cells(node) == 1);
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint != NULL) {
+ info->base = fdt32_to_cpu(*cuint);
+ } else {
+ info->base = 0;
+ }
+
+ cuint = fdt_getprop(fdt, node, "clocks", NULL);
+ if (cuint != NULL) {
+ cuint++;
+ info->clock = (int)fdt32_to_cpu(*cuint);
+ } else {
+ info->clock = -1;
+ }
+
+ cuint = fdt_getprop(fdt, node, "resets", NULL);
+ if (cuint != NULL) {
+ cuint++;
+ info->reset = (int)fdt32_to_cpu(*cuint);
+ } else {
+ info->reset = -1;
+ }
+
+ info->status = fdt_get_status(node);
+}
+
+/*******************************************************************************
+ * This function retrieve the generic information from DT.
+ * Returns node on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
+{
+ int node;
+
+ node = fdt_node_offset_by_compatible(fdt, offset, compat);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ dt_fill_device_info(info, node);
+
+ return node;
+}
+
+/*******************************************************************************
+ * This function gets the UART instance info of stdout from the DT.
+ * Returns node on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int dt_get_stdout_uart_info(struct dt_node_info *info)
+{
+ int node;
+
+ node = fdt_get_stdout_node_offset(fdt);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ dt_fill_device_info(info, node);
+
+ return node;
+}
+
+/*******************************************************************************
+ * This function returns the node offset matching compatible string in the DT,
+ * and also matching the reg property with the given address.
+ * Returns value on success, and error value on failure.
+ ******************************************************************************/
+int dt_match_instance_by_compatible(const char *compatible, uintptr_t address)
+{
+ int node;
+
+ fdt_for_each_compatible_node(fdt, node, compatible) {
+ const fdt32_t *cuint;
+
+ assert(fdt_get_node_parent_address_cells(node) == 1);
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ continue;
+ }
+
+ if ((uintptr_t)fdt32_to_cpu(*cuint) == address) {
+ return node;
+ }
+ }
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+/*******************************************************************************
+ * This function gets DDR size information from the DT.
+ * Returns value in bytes on success, and 0 on failure.
+ ******************************************************************************/
+uint32_t dt_get_ddr_size(void)
+{
+ static uint32_t size;
+ int node;
+
+ if (size != 0U) {
+ return size;
+ }
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+ if (node < 0) {
+ INFO("%s: Cannot read DDR node in DT\n", __func__);
+ return 0;
+ }
+
+ size = fdt_read_uint32_default(fdt, node, "st,mem-size", 0U);
+
+ flush_dcache_range((uintptr_t)&size, sizeof(uint32_t));
+
+ return size;
+}
+
+/*******************************************************************************
+ * This function gets PWR VDD regulator voltage information from the DT.
+ * Returns value in microvolts on success, and 0 on failure.
+ ******************************************************************************/
+uint32_t dt_get_pwr_vdd_voltage(void)
+{
+ struct rdev *regul = dt_get_vdd_regulator();
+ uint16_t min;
+
+ if (regul == NULL) {
+ return 0;
+ }
+
+ regulator_get_range(regul, &min, NULL);
+
+ return (uint32_t)min * 1000U;
+}
+
+/*******************************************************************************
+ * This function retrieves VDD supply regulator from DT.
+ * Returns an rdev taken from supply node, NULL otherwise.
+ ******************************************************************************/
+struct rdev *dt_get_vdd_regulator(void)
+{
+ int node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
+
+ if (node < 0) {
+ return NULL;
+ }
+
+ return regulator_get_by_supply_name(fdt, node, "vdd");
+}
+
+/*******************************************************************************
+ * This function retrieves CPU supply regulator from DT.
+ * Returns an rdev taken from supply node, NULL otherwise.
+ ******************************************************************************/
+struct rdev *dt_get_cpu_regulator(void)
+{
+ int node = fdt_path_offset(fdt, "/cpus/cpu@0");
+
+ if (node < 0) {
+ return NULL;
+ }
+
+ return regulator_get_by_supply_name(fdt, node, "cpu");
+}
+
+/*******************************************************************************
+ * This function retrieves board model from DT
+ * Returns string taken from model node, NULL otherwise
+ ******************************************************************************/
+const char *dt_get_board_model(void)
+{
+ int node = fdt_path_offset(fdt, "/");
+
+ if (node < 0) {
+ return NULL;
+ }
+
+ return (const char *)fdt_getprop(fdt, node, "model", NULL);
+}
+
+/*******************************************************************************
+ * dt_find_otp_name: get OTP ID and length in DT.
+ * name: sub-node name to look up.
+ * otp: pointer to read OTP number or NULL.
+ * otp_len: pointer to read OTP length in bits or NULL.
+ * return value: 0 if no error, an FDT error value otherwise.
+ ******************************************************************************/
+int dt_find_otp_name(const char *name, uint32_t *otp, uint32_t *otp_len)
+{
+ int node;
+ int len;
+ const fdt32_t *cuint;
+
+ if ((name == NULL) || (otp == NULL)) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_BSEC_COMPAT);
+ if (node < 0) {
+ return node;
+ }
+
+ node = fdt_subnode_offset(fdt, node, name);
+ if (node < 0) {
+ ERROR("nvmem node %s not found\n", name);
+ return node;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", &len);
+ if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) {
+ ERROR("Malformed nvmem node %s: ignored\n", name);
+ return -FDT_ERR_BADVALUE;
+ }
+
+ if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) {
+ ERROR("Misaligned nvmem %s element: ignored\n", name);
+ return -FDT_ERR_BADVALUE;
+ }
+
+ if (otp != NULL) {
+ *otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
+ }
+
+ if (otp_len != NULL) {
+ cuint++;
+ *otp_len = fdt32_to_cpu(*cuint) * CHAR_BIT;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function gets the pin count for a GPIO bank based from the FDT.
+ * It also checks node consistency.
+ ******************************************************************************/
+int fdt_get_gpio_bank_pin_count(unsigned int bank)
+{
+ int pinctrl_node;
+ int node;
+ uint32_t bank_offset;
+
+ pinctrl_node = stm32_get_gpio_bank_pinctrl_node(fdt, bank);
+ if (pinctrl_node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ bank_offset = stm32_get_gpio_bank_offset(bank);
+
+ fdt_for_each_subnode(node, fdt, pinctrl_node) {
+ const fdt32_t *cuint;
+ int pin_count;
+ int len;
+ int i;
+
+ if (fdt_getprop(fdt, node, "gpio-controller", NULL) == NULL) {
+ continue;
+ }
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ continue;
+ }
+
+ if (fdt32_to_cpu(*cuint) != bank_offset) {
+ continue;
+ }
+
+ if (fdt_get_status(node) == DT_DISABLED) {
+ return 0;
+ }
+
+ /* Parse gpio-ranges with its 4 parameters */
+ cuint = fdt_getprop(fdt, node, "gpio-ranges", &len);
+ len /= sizeof(*cuint);
+ if ((len % 4) != 0) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ /* Get the last defined gpio line (offset + nb of pins) */
+ pin_count = fdt32_to_cpu(*(cuint + 1)) + fdt32_to_cpu(*(cuint + 3));
+ for (i = 0; i < len / 4; i++) {
+ pin_count = MAX(pin_count, (int)(fdt32_to_cpu(*(cuint + 1)) +
+ fdt32_to_cpu(*(cuint + 3))));
+ cuint += 4;
+ }
+
+ return pin_count;
+ }
+
+ return 0;
+}
diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c
new file mode 100644
index 0000000..0b6cc78
--- /dev/null
+++ b/plat/st/common/stm32mp_fconf_io.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_efi.h>
+#include <stm32mp_fconf_getter.h>
+#include <stm32mp_io_storage.h>
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static io_block_spec_t gpt_block_spec = {
+ .offset = 0U,
+ .length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+#endif
+
+#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
+io_block_spec_t metadata_block_spec = {
+ .offset = 0, /* To be filled at runtime */
+ .length = 0, /* To be filled at runtime */
+};
+#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
+
+/* By default, STM32 platforms load images from the FIP */
+struct plat_io_policy policies[MAX_NUMBER_IDS] = {
+ [FIP_IMAGE_ID] = {
+ .dev_handle = &storage_dev_handle,
+ .image_spec = (uintptr_t)&image_block_spec,
+ .img_type_guid = STM32MP_FIP_GUID,
+ .check = open_storage
+ },
+#ifndef DECRYPTION_SUPPORT_none
+ [ENC_IMAGE_ID] = {
+ .dev_handle = &fip_dev_handle,
+ .image_spec = (uintptr_t)NULL,
+ .img_type_guid = NULL_GUID,
+ .check = open_fip
+ },
+#endif
+#if STM32MP_SDMMC || STM32MP_EMMC
+ [GPT_IMAGE_ID] = {
+ .dev_handle = &storage_dev_handle,
+ .image_spec = (uintptr_t)&gpt_block_spec,
+ .img_type_guid = NULL_GUID,
+ .check = open_storage
+ },
+#endif
+#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
+ [FWU_METADATA_IMAGE_ID] = {
+ .dev_handle = &storage_dev_handle,
+ .image_spec = (uintptr_t)&metadata_block_spec,
+ .img_type_guid = NULL_GUID,
+ .check = open_storage
+ },
+ [BKUP_FWU_METADATA_IMAGE_ID] = {
+ .dev_handle = &storage_dev_handle,
+ .image_spec = (uintptr_t)&metadata_block_spec,
+ .img_type_guid = NULL_GUID,
+ .check = open_storage
+ },
+#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
+};
+
+#define DEFAULT_UUID_NUMBER U(7)
+
+#if TRUSTED_BOARD_BOOT
+#define TBBR_UUID_NUMBER U(6)
+#else
+#define TBBR_UUID_NUMBER U(0)
+#endif
+
+#define FCONF_ST_IO_UUID_NUMBER (DEFAULT_UUID_NUMBER + \
+ TBBR_UUID_NUMBER)
+
+static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER];
+static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids);
+
+struct policies_load_info {
+ unsigned int image_id;
+ const char *name;
+};
+
+/* image id to property name table */
+static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = {
+ {FW_CONFIG_ID, "fw_cfg_uuid"},
+ {BL32_IMAGE_ID, "bl32_uuid"},
+ {BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"},
+ {BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"},
+ {BL33_IMAGE_ID, "bl33_uuid"},
+ {HW_CONFIG_ID, "hw_cfg_uuid"},
+ {TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
+#if TRUSTED_BOARD_BOOT
+ {STM32MP_CONFIG_CERT_ID, "stm32mp_cfg_cert_uuid"},
+ {TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"},
+ {TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"},
+ {NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"},
+ {TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
+ {NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+int fconf_populate_stm32mp_io_policies(uintptr_t config)
+{
+ int node;
+ unsigned int i;
+
+ /* As libfdt uses void *, we can't avoid this cast */
+ const void *dtb = (void *)config;
+
+ /* Assert the node offset point to "st,io-fip-handle" compatible property */
+ const char *compatible_str = "st,io-fip-handle";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+ return node;
+ }
+
+ /* Locate the uuid cells and read the value for all the load info uuid */
+ for (i = 0U; i < FCONF_ST_IO_UUID_NUMBER; i++) {
+ union uuid_helper_t uuid_helper;
+ io_uuid_spec_t *uuid_ptr;
+ int err;
+
+ uuid_ptr = pool_alloc(&fconf_stm32mp_uuids_pool);
+ err = fdtw_read_uuid(dtb, node, load_info[i].name, 16,
+ (uint8_t *)&uuid_helper);
+ if (err < 0) {
+ WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
+ return err;
+ }
+
+ VERBOSE("FCONF: stm32mp-io_policies.%s cell found with value = "
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+ load_info[i].name,
+ uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1],
+ uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3],
+ uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1],
+ uuid_helper.uuid_struct.time_hi_and_version[0],
+ uuid_helper.uuid_struct.time_hi_and_version[1],
+ uuid_helper.uuid_struct.clock_seq_hi_and_reserved,
+ uuid_helper.uuid_struct.clock_seq_low,
+ uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1],
+ uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3],
+ uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5]);
+
+ uuid_ptr->uuid = uuid_helper.uuid_struct;
+ policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
+ switch (load_info[i].image_id) {
+#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none)
+ case BL32_IMAGE_ID:
+ case BL32_EXTRA1_IMAGE_ID:
+ case BL32_EXTRA2_IMAGE_ID:
+ policies[load_info[i].image_id].dev_handle = &enc_dev_handle;
+ policies[load_info[i].image_id].check = open_enc_fip;
+ break;
+#endif
+ default:
+ policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
+ policies[load_info[i].image_id].check = open_fip;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(TB_FW, stm32mp_io, fconf_populate_stm32mp_io_policies);
diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c
new file mode 100644
index 0000000..051d6fc
--- /dev/null
+++ b/plat/st/common/stm32mp_trusted_boot.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <endian.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <common/debug.h>
+#include <common/tbbr/cot_def.h>
+#include <drivers/st/stm32_hash.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <boot_api.h>
+#include <platform_def.h>
+
+#define HEADER_AND_EXT_TOTAL_SIZE 512
+
+static uint8_t der_sha256_header[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+static uint8_t root_pk_hash[HASH_DER_LEN];
+
+static int copy_hash_from_otp(const char *otp_name, uint8_t *hash, size_t len)
+{
+ uint32_t otp_idx;
+ uint32_t otp_len;
+ size_t i;
+ bool valid = false;
+
+ assert(len % sizeof(uint32_t) == 0);
+
+ if (stm32_get_otp_index(otp_name, &otp_idx, &otp_len) != 0) {
+ VERBOSE("%s: get %s index error\n", __func__, otp_name);
+ return -EINVAL;
+ }
+ if (otp_len != (len * CHAR_BIT)) {
+ VERBOSE("%s: length Error\n", __func__);
+ return -EINVAL;
+ }
+
+ for (i = 0U; i < len / sizeof(uint32_t); i++) {
+ uint32_t tmp;
+ uint32_t otp_val;
+ uint32_t first;
+
+ if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) {
+ VERBOSE("%s: unable to read from otp\n", __func__);
+ return -EINVAL;
+ }
+
+ tmp = bswap32(otp_val);
+ memcpy(hash + i * sizeof(uint32_t), &tmp, sizeof(tmp));
+
+ if (i == 0U) {
+ first = tmp;
+ }
+
+ /*
+ * Check if key hash values in OTP are 0 or 0xFFFFFFFFF
+ * programmed : Invalid Key
+ */
+ if (!stm32mp_is_closed_device() && !valid) {
+ if ((tmp != 0U) && (tmp != 0xFFFFFFFFU) && (tmp != first)) {
+ valid = true;
+ }
+ }
+ }
+
+ if (!stm32mp_is_closed_device() && !valid) {
+ return 0;
+ }
+
+ return len;
+}
+
+#if STM32_HEADER_VERSION_MAJOR == 1
+static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len)
+{
+ if (cookie != NULL) {
+ return -EINVAL;
+ }
+
+ return copy_hash_from_otp(PKH_OTP, hash, len);
+}
+#else
+static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len)
+{
+ int ret;
+ uint32_t pk_idx = 0U;
+ uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+ uint8_t otp_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+ boot_api_image_header_t *hdr = (boot_api_image_header_t *)(SRAM3_BASE + SRAM3_SIZE -
+ HEADER_AND_EXT_TOTAL_SIZE);
+ boot_extension_header_t *ext_header = (boot_extension_header_t *)hdr->ext_header;
+ boot_ext_header_params_authentication_t *param;
+
+ if (cookie != NULL) {
+ return -EINVAL;
+ }
+
+ if (hdr->header_version != BOOT_API_HEADER_VERSION) {
+ VERBOSE("%s: unexpected header_version\n", __func__);
+ return -EINVAL;
+ }
+
+ param = (boot_ext_header_params_authentication_t *)ext_header->params;
+
+ pk_idx = param->pk_idx;
+
+ stm32_hash_init(HASH_SHA256);
+ ret = stm32_hash_final_update((uint8_t *)param->pk_hashes,
+ param->nb_pk * sizeof(boot_api_sha256_t), calc_hash);
+ if (ret != 0) {
+ VERBOSE("%s: hash failed\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = copy_hash_from_otp(PKH_OTP, otp_hash, len);
+ if (ret < 0) {
+ return -EINVAL;
+ }
+
+ if (ret != 0) {
+ ret = memcmp(calc_hash, otp_hash, sizeof(calc_hash));
+ if (ret != 0) {
+ VERBOSE("%s: not expected digest\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = sizeof(otp_hash);
+ }
+
+ memcpy(hash, param->pk_hashes[pk_idx], sizeof(otp_hash));
+
+ return ret;
+}
+#endif
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ size_t start_copy_idx = 0U;
+ int res;
+
+ memcpy(root_pk_hash, der_sha256_header, sizeof(der_sha256_header));
+ start_copy_idx = sizeof(der_sha256_header);
+
+ res = get_rotpk_hash(cookie, root_pk_hash + start_copy_idx,
+ BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES);
+ if (res < 0) {
+ return -EINVAL;
+ }
+
+ *key_len = HASH_DER_LEN;
+ *key_ptr = &root_pk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ if ((res == 0) && !stm32mp_is_closed_device()) {
+ *flags |= ROTPK_NOT_DEPLOYED;
+ }
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = mmio_read_32(TAMP_BASE + TAMP_COUNTR);
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ while (mmio_read_32(TAMP_BASE + TAMP_COUNTR) != nv_ctr) {
+ mmio_write_32(TAMP_BASE + TAMP_COUNTR, 1U);
+ }
+
+ return 0;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+#if STM32MP_USE_EXTERNAL_HEAP
+ /* Retrieve the already allocated heap's info from DTB */
+ *heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr);
+ *heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size);
+
+ /* We expect heap already statically mapped */
+
+ return 0;
+#else
+ return get_mbedtls_heap_helper(heap_addr, heap_size);
+#endif
+}
diff --git a/plat/st/common/usb_dfu.c b/plat/st/common/usb_dfu.c
new file mode 100644
index 0000000..8bb0994
--- /dev/null
+++ b/plat/st/common/usb_dfu.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+
+#include <platform_def.h>
+#include <usb_dfu.h>
+
+/* Device states as defined in DFU spec */
+#define STATE_APP_IDLE 0
+#define STATE_APP_DETACH 1
+#define STATE_DFU_IDLE 2
+#define STATE_DFU_DNLOAD_SYNC 3
+#define STATE_DFU_DNLOAD_BUSY 4
+#define STATE_DFU_DNLOAD_IDLE 5
+#define STATE_DFU_MANIFEST_SYNC 6
+#define STATE_DFU_MANIFEST 7
+#define STATE_DFU_MANIFEST_WAIT_RESET 8
+#define STATE_DFU_UPLOAD_IDLE 9
+#define STATE_DFU_ERROR 10
+
+/* DFU errors */
+#define DFU_ERROR_NONE 0x00
+#define DFU_ERROR_TARGET 0x01
+#define DFU_ERROR_FILE 0x02
+#define DFU_ERROR_WRITE 0x03
+#define DFU_ERROR_ERASE 0x04
+#define DFU_ERROR_CHECK_ERASED 0x05
+#define DFU_ERROR_PROG 0x06
+#define DFU_ERROR_VERIFY 0x07
+#define DFU_ERROR_ADDRESS 0x08
+#define DFU_ERROR_NOTDONE 0x09
+#define DFU_ERROR_FIRMWARE 0x0A
+#define DFU_ERROR_VENDOR 0x0B
+#define DFU_ERROR_USB 0x0C
+#define DFU_ERROR_POR 0x0D
+#define DFU_ERROR_UNKNOWN 0x0E
+#define DFU_ERROR_STALLEDPKT 0x0F
+
+/* DFU request */
+#define DFU_DETACH 0
+#define DFU_DNLOAD 1
+#define DFU_UPLOAD 2
+#define DFU_GETSTATUS 3
+#define DFU_CLRSTATUS 4
+#define DFU_GETSTATE 5
+#define DFU_ABORT 6
+
+static bool usb_dfu_detach_req;
+
+/*
+ * usb_dfu_init
+ * Initialize the DFU interface
+ * pdev: device instance
+ * cfgidx: Configuration index
+ * return: status
+ */
+static uint8_t usb_dfu_init(struct usb_handle *pdev, uint8_t cfgidx)
+{
+ (void)pdev;
+ (void)cfgidx;
+
+ /* Nothing to do in this stage */
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_de_init
+ * De-Initialize the DFU layer
+ * pdev: device instance
+ * cfgidx: Configuration index
+ * return: status
+ */
+static uint8_t usb_dfu_de_init(struct usb_handle *pdev, uint8_t cfgidx)
+{
+ (void)pdev;
+ (void)cfgidx;
+
+ /* Nothing to do in this stage */
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_data_in
+ * handle data IN Stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_data_in(struct usb_handle *pdev, uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_ep0_rx_ready
+ * handle EP0 Rx Ready event
+ * pdev: device
+ * return: status
+ */
+static uint8_t usb_dfu_ep0_rx_ready(struct usb_handle *pdev)
+{
+ (void)pdev;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_ep0_tx_ready
+ * handle EP0 TRx Ready event
+ * pdev: device instance
+ * return: status
+ */
+static uint8_t usb_dfu_ep0_tx_ready(struct usb_handle *pdev)
+{
+ (void)pdev;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_sof
+ * handle SOF event
+ * pdev: device instance
+ * return: status
+ */
+static uint8_t usb_dfu_sof(struct usb_handle *pdev)
+{
+ (void)pdev;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_iso_in_incomplete
+ * handle data ISO IN Incomplete event
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_iso_in_incomplete(struct usb_handle *pdev, uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_iso_out_incomplete
+ * handle data ISO OUT Incomplete event
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_iso_out_incomplete(struct usb_handle *pdev,
+ uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_data_out
+ * handle data OUT Stage
+ * pdev: device instance
+ * epnum: endpoint index
+ * return: status
+ */
+static uint8_t usb_dfu_data_out(struct usb_handle *pdev, uint8_t epnum)
+{
+ (void)pdev;
+ (void)epnum;
+
+ return USBD_OK;
+}
+
+/*
+ * usb_dfu_detach
+ * Handles the DFU DETACH request.
+ * pdev: device instance
+ * req: pointer to the request structure.
+ */
+static void usb_dfu_detach(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+ INFO("Receive DFU Detach\n");
+
+ if ((hdfu->dev_state == STATE_DFU_IDLE) ||
+ (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) ||
+ (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) ||
+ (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) ||
+ (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) {
+ /* Update the state machine */
+ hdfu->dev_state = STATE_DFU_IDLE;
+ hdfu->dev_status = DFU_ERROR_NONE;
+ }
+
+ usb_dfu_detach_req = true;
+}
+
+/*
+ * usb_dfu_download
+ * Handles the DFU DNLOAD request.
+ * pdev: device instance
+ * req: pointer to the request structure
+ */
+static void usb_dfu_download(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+ uintptr_t data_ptr;
+ uint32_t length;
+ int ret;
+
+ /* Data setup request */
+ if (req->length > 0) {
+ /* Unsupported state */
+ if ((hdfu->dev_state != STATE_DFU_IDLE) &&
+ (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE)) {
+ /* Call the error management function (command will be nacked) */
+ usb_core_ctl_error(pdev);
+ return;
+ }
+
+ /* Get the data address */
+ length = req->length;
+ ret = hdfu->callback->download(hdfu->alt_setting, &data_ptr,
+ &length, pdev->user_data);
+ if (ret == 0U) {
+ /* Update the state machine */
+ hdfu->dev_state = STATE_DFU_DNLOAD_SYNC;
+ /* Start the transfer */
+ usb_core_receive_ep0(pdev, (uint8_t *)data_ptr, length);
+ } else {
+ usb_core_ctl_error(pdev);
+ }
+ } else {
+ /* End of DNLOAD operation*/
+ if (hdfu->dev_state != STATE_DFU_DNLOAD_IDLE) {
+ /* Call the error management function (command will be nacked) */
+ usb_core_ctl_error(pdev);
+ return;
+ }
+ /* End of DNLOAD operation*/
+ hdfu->dev_state = STATE_DFU_MANIFEST_SYNC;
+ ret = hdfu->callback->manifestation(hdfu->alt_setting, pdev->user_data);
+ if (ret == 0U) {
+ hdfu->dev_state = STATE_DFU_MANIFEST_SYNC;
+ } else {
+ usb_core_ctl_error(pdev);
+ }
+ }
+}
+
+/*
+ * usb_dfu_upload
+ * Handles the DFU UPLOAD request.
+ * pdev: instance
+ * req: pointer to the request structure
+ */
+static void usb_dfu_upload(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+ uintptr_t data_ptr;
+ uint32_t length;
+ int ret;
+
+ /* Data setup request */
+ if (req->length == 0) {
+ /* No Data setup request */
+ hdfu->dev_state = STATE_DFU_IDLE;
+ return;
+ }
+
+ /* Unsupported state */
+ if ((hdfu->dev_state != STATE_DFU_IDLE) && (hdfu->dev_state != STATE_DFU_UPLOAD_IDLE)) {
+ ERROR("UPLOAD : Unsupported State\n");
+ /* Call the error management function (command will be nacked) */
+ usb_core_ctl_error(pdev);
+ return;
+ }
+
+ /* Update the data address */
+ length = req->length;
+ ret = hdfu->callback->upload(hdfu->alt_setting, &data_ptr, &length, pdev->user_data);
+ if (ret == 0U) {
+ /* Short frame */
+ hdfu->dev_state = (req->length > length) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE;
+
+ /* Start the transfer */
+ usb_core_transmit_ep0(pdev, (uint8_t *)data_ptr, length);
+ } else {
+ ERROR("UPLOAD : bad block %i on alt %i\n", req->value, req->index);
+ hdfu->dev_state = STATE_DFU_ERROR;
+ hdfu->dev_status = DFU_ERROR_STALLEDPKT;
+
+ /* Call the error management function (command will be nacked) */
+ usb_core_ctl_error(pdev);
+ }
+}
+
+/*
+ * usb_dfu_get_status
+ * Handles the DFU GETSTATUS request.
+ * pdev: instance
+ */
+static void usb_dfu_get_status(struct usb_handle *pdev)
+{
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+ hdfu->status[0] = hdfu->dev_status; /* bStatus */
+ hdfu->status[1] = 0; /* bwPollTimeout[3] */
+ hdfu->status[2] = 0;
+ hdfu->status[3] = 0;
+ hdfu->status[4] = hdfu->dev_state; /* bState */
+ hdfu->status[5] = 0; /* iString */
+
+ /* next step */
+ switch (hdfu->dev_state) {
+ case STATE_DFU_DNLOAD_SYNC:
+ hdfu->dev_state = STATE_DFU_DNLOAD_IDLE;
+ break;
+ case STATE_DFU_MANIFEST_SYNC:
+ /* the device is 'ManifestationTolerant' */
+ hdfu->status[4] = STATE_DFU_MANIFEST;
+ hdfu->status[1] = 1U; /* bwPollTimeout = 1ms */
+ hdfu->dev_state = STATE_DFU_IDLE;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Start the transfer */
+ usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->status[0], sizeof(hdfu->status));
+}
+
+/*
+ * usb_dfu_clear_status
+ * Handles the DFU CLRSTATUS request.
+ * pdev: device instance
+ */
+static void usb_dfu_clear_status(struct usb_handle *pdev)
+{
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+ if (hdfu->dev_state == STATE_DFU_ERROR) {
+ hdfu->dev_state = STATE_DFU_IDLE;
+ hdfu->dev_status = DFU_ERROR_NONE;
+ } else {
+ /* State Error */
+ hdfu->dev_state = STATE_DFU_ERROR;
+ hdfu->dev_status = DFU_ERROR_UNKNOWN;
+ }
+}
+
+/*
+ * usb_dfu_get_state
+ * Handles the DFU GETSTATE request.
+ * pdev: device instance
+ */
+static void usb_dfu_get_state(struct usb_handle *pdev)
+{
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+ /* Return the current state of the DFU interface */
+ usb_core_transmit_ep0(pdev, &hdfu->dev_state, 1);
+}
+
+/*
+ * usb_dfu_abort
+ * Handles the DFU ABORT request.
+ * pdev: device instance
+ */
+static void usb_dfu_abort(struct usb_handle *pdev)
+{
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+ if ((hdfu->dev_state == STATE_DFU_IDLE) ||
+ (hdfu->dev_state == STATE_DFU_DNLOAD_SYNC) ||
+ (hdfu->dev_state == STATE_DFU_DNLOAD_IDLE) ||
+ (hdfu->dev_state == STATE_DFU_MANIFEST_SYNC) ||
+ (hdfu->dev_state == STATE_DFU_UPLOAD_IDLE)) {
+ hdfu->dev_state = STATE_DFU_IDLE;
+ hdfu->dev_status = DFU_ERROR_NONE;
+ }
+}
+
+/*
+ * usb_dfu_setup
+ * Handle the DFU specific requests
+ * pdev: instance
+ * req: usb requests
+ * return: status
+ */
+static uint8_t usb_dfu_setup(struct usb_handle *pdev, struct usb_setup_req *req)
+{
+ uint8_t *pbuf = NULL;
+ uint16_t len = 0U;
+ uint8_t ret = USBD_OK;
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+ switch (req->bm_request & USB_REQ_TYPE_MASK) {
+ case USB_REQ_TYPE_CLASS:
+ switch (req->b_request) {
+ case DFU_DNLOAD:
+ usb_dfu_download(pdev, req);
+ break;
+
+ case DFU_UPLOAD:
+ usb_dfu_upload(pdev, req);
+ break;
+
+ case DFU_GETSTATUS:
+ usb_dfu_get_status(pdev);
+ break;
+
+ case DFU_CLRSTATUS:
+ usb_dfu_clear_status(pdev);
+ break;
+
+ case DFU_GETSTATE:
+ usb_dfu_get_state(pdev);
+ break;
+
+ case DFU_ABORT:
+ usb_dfu_abort(pdev);
+ break;
+
+ case DFU_DETACH:
+ usb_dfu_detach(pdev, req);
+ break;
+
+ default:
+ ERROR("unknown request %x on alternate %i\n",
+ req->b_request, hdfu->alt_setting);
+ usb_core_ctl_error(pdev);
+ ret = USBD_FAIL;
+ break;
+ }
+ break;
+ case USB_REQ_TYPE_STANDARD:
+ switch (req->b_request) {
+ case USB_REQ_GET_DESCRIPTOR:
+ if (HIBYTE(req->value) == DFU_DESCRIPTOR_TYPE) {
+ pbuf = pdev->desc->get_config_desc(&len);
+ /* DFU descriptor at the end of the USB */
+ pbuf += len - 9U;
+ len = 9U;
+ len = MIN(len, req->length);
+ }
+
+ /* Start the transfer */
+ usb_core_transmit_ep0(pdev, pbuf, len);
+
+ break;
+
+ case USB_REQ_GET_INTERFACE:
+ /* Start the transfer */
+ usb_core_transmit_ep0(pdev, (uint8_t *)&hdfu->alt_setting, 1U);
+ break;
+
+ case USB_REQ_SET_INTERFACE:
+ hdfu->alt_setting = LOBYTE(req->value);
+ break;
+
+ default:
+ usb_core_ctl_error(pdev);
+ ret = USBD_FAIL;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static const struct usb_class usb_dfu = {
+ .init = usb_dfu_init,
+ .de_init = usb_dfu_de_init,
+ .setup = usb_dfu_setup,
+ .ep0_tx_sent = usb_dfu_ep0_tx_ready,
+ .ep0_rx_ready = usb_dfu_ep0_rx_ready,
+ .data_in = usb_dfu_data_in,
+ .data_out = usb_dfu_data_out,
+ .sof = usb_dfu_sof,
+ .iso_in_incomplete = usb_dfu_iso_in_incomplete,
+ .iso_out_incomplete = usb_dfu_iso_out_incomplete,
+};
+
+void usb_dfu_register(struct usb_handle *pdev, struct usb_dfu_handle *phandle)
+{
+ pdev->class = (struct usb_class *)&usb_dfu;
+ pdev->class_data = phandle;
+
+ phandle->dev_state = STATE_DFU_IDLE;
+ phandle->dev_status = DFU_ERROR_NONE;
+}
+
+int usb_dfu_loop(struct usb_handle *pdev, const struct usb_dfu_media *pmedia)
+{
+ uint32_t it_count;
+ enum usb_status ret;
+ struct usb_dfu_handle *hdfu = (struct usb_dfu_handle *)pdev->class_data;
+
+ hdfu->callback = pmedia;
+ usb_dfu_detach_req = false;
+ /* Continue to handle USB core IT to assure complete data transmission */
+ it_count = 100U;
+
+ /* DFU infinite loop until DETACH_REQ */
+ while (it_count != 0U) {
+ ret = usb_core_handle_it(pdev);
+ if (ret != USBD_OK) {
+ return -EIO;
+ }
+
+ /* Detach request received */
+ if (usb_dfu_detach_req) {
+ it_count--;
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
new file mode 100644
index 0000000..4f04a6f
--- /dev/null
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/regulator_fixed.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32_rng.h>
+#include <drivers/st/stm32_uart.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp1_pwr.h>
+#include <drivers/st/stm32mp1_ram.h>
+#include <drivers/st/stm32mp_pmic.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+#include <stm32mp_common.h>
+#include <stm32mp1_dbgmcu.h>
+
+#if DEBUG
+static const char debug_msg[] = {
+ "***************************************************\n"
+ "** DEBUG ACCESS PORT IS OPEN! **\n"
+ "** This boot image is only for debugging purpose **\n"
+ "** and is unsafe for production use. **\n"
+ "** **\n"
+ "** If you see this message and you are not **\n"
+ "** debugging report this immediately to your **\n"
+ "** vendor! **\n"
+ "***************************************************\n"
+};
+#endif
+
+static void print_reset_reason(void)
+{
+ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
+
+ if (rstsr == 0U) {
+ WARN("Reset reason unknown\n");
+ return;
+ }
+
+ INFO("Reset reason (0x%x):\n", rstsr);
+
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
+ if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
+ INFO("System exits from STANDBY\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
+ INFO("MPU exits from CSTANDBY\n");
+ return;
+ }
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
+ INFO(" Power-on Reset (rst_por)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
+ INFO(" Brownout Reset (rst_bor)\n");
+ return;
+ }
+
+#if STM32MP15
+ if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) {
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
+ INFO(" System reset generated by MCU (MCSYSRST)\n");
+ } else {
+ INFO(" Local reset generated by MCU (MCSYSRST)\n");
+ }
+ return;
+ }
+#endif
+
+ if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
+ INFO(" System reset generated by MPU (MPSYSRST)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
+ INFO(" Reset due to a clock failure on HSE\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
+ INFO(" IWDG1 Reset (rst_iwdg1)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
+ INFO(" IWDG2 Reset (rst_iwdg2)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0U) {
+ INFO(" MPU Processor 0 Reset\n");
+ return;
+ }
+
+#if STM32MP15
+ if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) {
+ INFO(" MPU Processor 1 Reset\n");
+ return;
+ }
+#endif
+
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
+ INFO(" Pad Reset from NRST\n");
+ return;
+ }
+
+ if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
+ INFO(" Reset due to a failure of VDD_CORE\n");
+ return;
+ }
+
+ ERROR(" Unidentified reset reason\n");
+}
+
+void bl2_el3_early_platform_setup(u_register_t arg0,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ stm32mp_setup_early_console();
+
+ stm32mp_save_boot_ctx_address(arg0);
+}
+
+void bl2_platform_setup(void)
+{
+ int ret;
+
+ ret = stm32mp1_ddr_probe();
+ if (ret < 0) {
+ ERROR("Invalid DDR init: error %d\n", ret);
+ panic();
+ }
+
+ /* Map DDR for binary load, now with cacheable attribute */
+ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
+ STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
+ if (ret < 0) {
+ ERROR("DDR mapping: error %d\n", ret);
+ panic();
+ }
+}
+
+#if STM32MP15
+static void update_monotonic_counter(void)
+{
+ uint32_t version;
+ uint32_t otp;
+
+ CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE,
+ assert_stm32mp1_monotonic_counter_reach_max);
+
+ /* Check if monotonic counter needs to be incremented */
+ if (stm32_get_otp_index(MONOTONIC_OTP, &otp, NULL) != 0) {
+ panic();
+ }
+
+ if (stm32_get_otp_value_from_idx(otp, &version) != 0) {
+ panic();
+ }
+
+ if ((version + 1U) < BIT(STM32_TF_VERSION)) {
+ uint32_t result;
+
+ /* Need to increment the monotonic counter. */
+ version = BIT(STM32_TF_VERSION) - 1U;
+
+ result = bsec_program_otp(version, otp);
+ if (result != BSEC_OK) {
+ ERROR("BSEC: MONOTONIC_OTP program Error %u\n",
+ result);
+ panic();
+ }
+ INFO("Monotonic counter has been incremented (value 0x%x)\n",
+ version);
+ }
+}
+#endif
+
+void bl2_el3_plat_arch_setup(void)
+{
+ const char *board_model;
+ boot_api_context_t *boot_context =
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+ uintptr_t pwr_base;
+ uintptr_t rcc_base;
+
+ if (bsec_probe() != 0U) {
+ panic();
+ }
+
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+
+ /* Prevent corruption of preloaded Device Tree */
+ mmap_add_region(DTB_BASE, DTB_BASE,
+ DTB_LIMIT - DTB_BASE,
+ MT_RO_DATA | MT_SECURE);
+
+ configure_mmu();
+
+ if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
+ panic();
+ }
+
+ pwr_base = stm32mp_pwr_base();
+ rcc_base = stm32mp_rcc_base();
+
+ /*
+ * Disable the backup domain write protection.
+ * The protection is enable at each reset by hardware
+ * and must be disabled by software.
+ */
+ mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP);
+
+ while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) {
+ ;
+ }
+
+ /* Reset backup domain on cold boot cases */
+ if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+
+ while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) ==
+ 0U) {
+ ;
+ }
+
+ mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+ }
+
+#if STM32MP15
+ /* Disable MCKPROT */
+ mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
+#endif
+
+ /*
+ * Set minimum reset pulse duration to 31ms for discrete power
+ * supplied boards.
+ */
+ if (dt_pmic_status() <= 0) {
+ mmio_clrsetbits_32(rcc_base + RCC_RDLSICR,
+ RCC_RDLSICR_MRD_MASK,
+ 31U << RCC_RDLSICR_MRD_SHIFT);
+ }
+
+ generic_delay_timer_init();
+
+#if STM32MP_UART_PROGRAMMER
+ /* Disable programmer UART before changing clock tree */
+ if (boot_context->boot_interface_selected ==
+ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) {
+ uintptr_t uart_prog_addr =
+ get_uart_address(boot_context->boot_interface_instance);
+
+ stm32_uart_stop(uart_prog_addr);
+ }
+#endif
+ if (stm32mp1_clk_probe() < 0) {
+ panic();
+ }
+
+ if (stm32mp1_clk_init() < 0) {
+ panic();
+ }
+
+ stm32_save_boot_interface(boot_context->boot_interface_selected,
+ boot_context->boot_interface_instance);
+ stm32_save_boot_auth(boot_context->auth_status,
+ boot_context->boot_partition_used_toboot);
+
+#if STM32MP_USB_PROGRAMMER && STM32MP15
+ /* Deconfigure all UART RX pins configured by ROM code */
+ stm32mp1_deconfigure_uart_pins();
+#endif
+
+ if (stm32mp_uart_console_setup() != 0) {
+ goto skip_console_init;
+ }
+
+ stm32mp_print_cpuinfo();
+
+ board_model = dt_get_board_model();
+ if (board_model != NULL) {
+ NOTICE("Model: %s\n", board_model);
+ }
+
+ stm32mp_print_boardinfo();
+
+ if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) {
+ NOTICE("Bootrom authentication %s\n",
+ (boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ?
+ "failed" : "succeeded");
+ }
+
+skip_console_init:
+#if !TRUSTED_BOARD_BOOT
+ if (stm32mp_is_closed_device()) {
+ /* Closed chip mandates authentication */
+ ERROR("Secure chip: TRUSTED_BOARD_BOOT must be enabled\n");
+ panic();
+ }
+#endif
+
+ if (fixed_regulator_register() != 0) {
+ panic();
+ }
+
+ if (dt_pmic_status() > 0) {
+ initialize_pmic();
+ if (pmic_voltages_init() != 0) {
+ ERROR("PMIC voltages init failed\n");
+ panic();
+ }
+ print_pmic_info_and_debug();
+ }
+
+ stm32mp1_syscfg_init();
+
+ if (stm32_iwdg_init() < 0) {
+ panic();
+ }
+
+ stm32_iwdg_refresh();
+
+ if (bsec_read_debug_conf() != 0U) {
+ if (stm32mp_is_closed_device()) {
+#if DEBUG
+ WARN("\n%s", debug_msg);
+#else
+ ERROR("***Debug opened on closed chip***\n");
+#endif
+ }
+ }
+
+#if STM32MP13
+ if (stm32_rng_init() != 0) {
+ panic();
+ }
+#endif
+
+ stm32mp1_arch_security_setup();
+
+ print_reset_reason();
+
+#if STM32MP15
+ update_monotonic_counter();
+#endif
+
+ stm32mp1_syscfg_enable_io_compensation_finish();
+
+ fconf_populate("TB_FW", STM32MP_DTB_BASE);
+
+ stm32mp_io_setup();
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ bl_mem_params_node_t *bl32_mem_params;
+ bl_mem_params_node_t *pager_mem_params __unused;
+ bl_mem_params_node_t *paged_mem_params __unused;
+ const struct dyn_cfg_dtb_info_t *config_info;
+ bl_mem_params_node_t *tos_fw_mem_params;
+ unsigned int i;
+ unsigned int idx;
+ unsigned long long ddr_top __unused;
+ const unsigned int image_ids[] = {
+ BL32_IMAGE_ID,
+ BL33_IMAGE_ID,
+ HW_CONFIG_ID,
+ TOS_FW_CONFIG_ID,
+ };
+
+ assert(bl_mem_params != NULL);
+
+ switch (image_id) {
+ case FW_CONFIG_ID:
+ /* Set global DTB info for fixed fw_config information */
+ set_config_info(STM32MP_FW_CONFIG_BASE, ~0UL, STM32MP_FW_CONFIG_MAX_SIZE,
+ FW_CONFIG_ID);
+ fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
+
+ idx = dyn_cfg_dtb_info_get_index(TOS_FW_CONFIG_ID);
+
+ /* Iterate through all the fw config IDs */
+ for (i = 0U; i < ARRAY_SIZE(image_ids); i++) {
+ if ((image_ids[i] == TOS_FW_CONFIG_ID) && (idx == FCONF_INVALID_IDX)) {
+ continue;
+ }
+
+ bl_mem_params = get_bl_mem_params_node(image_ids[i]);
+ assert(bl_mem_params != NULL);
+
+ config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]);
+ if (config_info == NULL) {
+ continue;
+ }
+
+ bl_mem_params->image_info.image_base = config_info->config_addr;
+ bl_mem_params->image_info.image_max_size = config_info->config_max_size;
+
+ bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+
+ switch (image_ids[i]) {
+ case BL32_IMAGE_ID:
+ bl_mem_params->ep_info.pc = config_info->config_addr;
+
+ /* In case of OPTEE, initialize address space with tos_fw addr */
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params != NULL);
+ pager_mem_params->image_info.image_base = config_info->config_addr;
+ pager_mem_params->image_info.image_max_size =
+ config_info->config_max_size;
+
+ /* Init base and size for pager if exist */
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ if (paged_mem_params != NULL) {
+ paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+ (dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
+ STM32MP_DDR_SHMEM_SIZE);
+ paged_mem_params->image_info.image_max_size =
+ STM32MP_DDR_S_SIZE;
+ }
+ break;
+
+ case BL33_IMAGE_ID:
+ bl_mem_params->ep_info.pc = config_info->config_addr;
+ break;
+
+ case HW_CONFIG_ID:
+ case TOS_FW_CONFIG_ID:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case BL32_IMAGE_ID:
+ if (optee_header_is_valid(bl_mem_params->image_info.image_base)) {
+ image_info_t *paged_image_info = NULL;
+
+ /* BL32 is OP-TEE header */
+ bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params != NULL);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ if (paged_mem_params != NULL) {
+ paged_image_info = &paged_mem_params->image_info;
+ }
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ paged_image_info);
+ if (err != 0) {
+ ERROR("OPTEE header parse error.\n");
+ panic();
+ }
+
+ /* Set optee boot info from parsed header data */
+ if (paged_mem_params != NULL) {
+ bl_mem_params->ep_info.args.arg0 =
+ paged_mem_params->image_info.image_base;
+ } else {
+ bl_mem_params->ep_info.args.arg0 = 0U;
+ }
+
+ bl_mem_params->ep_info.args.arg1 = 0U; /* Unused */
+ bl_mem_params->ep_info.args.arg2 = 0U; /* No DT supported */
+ } else {
+ bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+ tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
+ assert(tos_fw_mem_params != NULL);
+ bl_mem_params->image_info.image_max_size +=
+ tos_fw_mem_params->image_info.image_max_size;
+ bl_mem_params->ep_info.args.arg0 = 0;
+ }
+ break;
+
+ case BL33_IMAGE_ID:
+ bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
+ assert(bl32_mem_params != NULL);
+ bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
+#if PSA_FWU_SUPPORT
+ stm32mp1_fwu_set_boot_idx();
+#endif /* PSA_FWU_SUPPORT */
+ break;
+
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+ /*
+ * Invalidate remaining data read from MMC but not flushed by load_image_flush().
+ * We take the worst case which is 2 MMC blocks.
+ */
+ if ((image_id != FW_CONFIG_ID) &&
+ ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
+ inv_dcache_range(bl_mem_params->image_info.image_base +
+ bl_mem_params->image_info.image_size,
+ 2U * MMC_BLOCK_SIZE);
+ }
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+ return err;
+}
+
+void bl2_el3_plat_prepare_exit(void)
+{
+ uint16_t boot_itf = stm32mp_get_boot_itf_selected();
+
+ switch (boot_itf) {
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+ /* Invalidate the downloaded buffer used with io_memmap */
+ inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
+ break;
+#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ stm32mp1_security_setup();
+}
diff --git a/plat/st/stm32mp1/cert_create_tbbr.mk b/plat/st/stm32mp1/cert_create_tbbr.mk
new file mode 100644
index 0000000..5b1a3ed
--- /dev/null
+++ b/plat/st/stm32mp1/cert_create_tbbr.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Override TBBR Cert to update generic certificate
+
+$(eval $(call add_define,PDEF_CERTS))
+
+PLAT_INCLUDE += -I${PLAT_DIR}include
+
+src/stm32mp1_tbb_cert.o: ${PLAT_DIR}stm32mp1_tbb_cert.c
+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
+
+PLAT_OBJECTS = src/stm32mp1_tbb_cert.o
+
+OBJECTS += $(PLAT_OBJECTS)
+
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
new file mode 100644
index 0000000..1054609
--- /dev/null
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOOT_API_H
+#define BOOT_API_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+/*
+ * Possible value of boot context field 'auth_status'
+ */
+#if STM32MP13
+ /* No authentication done */
+#define BOOT_API_CTX_AUTH_NO 0x7CFDD351U
+ /* Authentication done and failed */
+#define BOOT_API_CTX_AUTH_FAILED 0x51330884U
+ /* Authentication done and success */
+#define BOOT_API_CTX_AUTH_SUCCESS 0x67E8CAE1U
+#endif
+#if STM32MP15
+/* No authentication done */
+#define BOOT_API_CTX_AUTH_NO 0x0U
+/* Authentication done and failed */
+#define BOOT_API_CTX_AUTH_FAILED 0x1U
+/* Authentication done and succeeded */
+#define BOOT_API_CTX_AUTH_SUCCESS 0x2U
+#endif
+
+/*
+ * Possible value of boot context field 'boot_interface_sel'
+ */
+
+/* Value of field 'boot_interface_sel' when no boot occurred */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_NO 0x0U
+
+/* Boot occurred on SD */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD 0x1U
+
+/* Boot occurred on EMMC */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U
+
+/* Boot occurred on FMC */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U
+
+/* Boot occurred on QSPI NOR */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI 0x4U
+
+/* Boot occurred on UART */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U
+
+/* Boot occurred on USB */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U
+
+/* Boot occurred on QSPI NAND */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U
+
+/**
+ * @brief Possible value of boot context field 'EmmcXferStatus'
+ */
+/*
+ * Possible value of boot context field 'emmc_xfer_status'
+ */
+#define BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED 0x0U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED 0x1U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED 0x2U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT 0x3U
+
+/*
+ * Possible value of boot context field 'emmc_error_status'
+ */
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_NONE 0x0U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT 0x1U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT 0x2U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL 0x3U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX 0x4U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND 0x5U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_ERROR 0x8U
+
+/* Image Header related definitions */
+
+/* Definition of header version */
+#if STM32MP13
+#define BOOT_API_HEADER_VERSION 0x00020000U
+#endif
+#if STM32MP15
+#define BOOT_API_HEADER_VERSION 0x00010000U
+#endif
+
+/*
+ * Magic number used to detect header in memory
+ * Its value must be 'S' 'T' 'M' 0x32, i.e 0x324D5453 as field
+ * 'bootapi_image_header_t.magic'
+ * This identifies the start of a boot image.
+ */
+#define BOOT_API_IMAGE_HEADER_MAGIC_NB 0x324D5453U
+
+/* Definitions related to Authentication used in image header structure */
+#define BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES 64
+#define BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES 64
+#define BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES 32
+
+/* Possible values of the field 'boot_api_image_header_t.ecc_algo_type' */
+#define BOOT_API_ECDSA_ALGO_TYPE_P256NIST 1
+#define BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256 2
+
+/*
+ * Extension headers related definitions
+ */
+/* 'bootapi_image_header_t.extension_flag' used for authentication feature */
+#define BOOT_API_AUTHENTICATION_EXTENSION_BIT BIT(0)
+/* 'bootapi_image_header_t.extension_flag' used for FSBL decryption feature */
+#define BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT BIT(1)
+/* 'bootapi_image_header_t.extension_flag' used for padding header feature */
+#define BOOT_API_PADDING_EXTENSION_BIT BIT(31)
+/*
+ * mask of bits of field 'bootapi_image_header_t.extension_flag'
+ * used for extension headers
+ */
+#define BOOT_API_ALL_EXTENSIONS_MASK \
+ (BOOT_API_AUTHENTICATION_EXTENSION_BIT | \
+ BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT | \
+ BOOT_API_PADDING_EXTENSION_BIT)
+/*
+ * Magic number of FSBL decryption extension header
+ * The value shall gives the four bytes 'S','T',0x00,0x01 in memory
+ */
+#define BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB 0x01005453U
+
+/*
+ * Magic number of PKH revocation extension header
+ * The value shall gives the four bytes 'S','T',0x00,0x02 in memory
+ */
+#define BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB 0x02005453U
+
+/* Max number of ECDSA public key hash in table */
+#define BOOT_API_AUTHENTICATION_NB_PKH_MAX 8U
+
+/* ECDSA public key hash table size in bytes */
+#define BOOT_API_AUTHENTICATION_TABLE_SIZE_BYTES \
+ (BOOT_API_AUTHENTICATION_NB_PKH_MAX * \
+ BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)
+
+/*
+ * Magic number of padding extension header
+ * The value shall gives the four bytes 'S','T',0xFF,0xFF in memory
+ */
+#define BOOT_API_PADDING_HEADER_MAGIC_NB 0xFFFF5453U
+
+/*
+ * Cores secure magic numbers
+ * Constant to be stored in bakcup register
+ * BOOT_API_MAGIC_NUMBER_TAMP_BCK_REG_IDX
+ */
+#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0U
+#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U
+
+/*
+ * TAMP_BCK4R register index
+ * This register is used to write a Magic Number in order to restart
+ * Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R
+ */
+#define BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX 4U
+
+/*
+ * TAMP_BCK5R register index
+ * This register is used to contain the branch address of
+ * Cortex A7 Core 1 when restarted by a TAMP_BCK4R magic number writing
+ */
+#define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX 5U
+
+/*
+ * Possible value of boot context field 'hse_clock_value_in_hz'
+ */
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED 0U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_24_MHZ 24000000U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_25_MHZ 25000000U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_26_MHZ 26000000U
+
+/*
+ * Possible value of boot context field 'boot_partition_used_toboot'
+ */
+#define BOOT_API_CTX_BOOT_PARTITION_UNDEFINED 0U
+
+/* Used FSBL1 to boot */
+#define BOOT_API_CTX_BOOT_PARTITION_FSBL1 1U
+
+/* Used FSBL2 to boot */
+#define BOOT_API_CTX_BOOT_PARTITION_FSBL2 2U
+
+/* OTP_CFG0 */
+#define BOOT_API_OTP_MODE_WORD_NB 0
+/* Closed = OTP_CFG0[6] */
+#define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6
+
+#define BOOT_API_RETURN_OK 0x77U
+
+/*
+ * Boot Context related definitions
+ */
+
+/*
+ * Boot core boot configuration structure
+ * Specifies all items of the cold boot configuration
+ * Memory and peripheral part.
+ */
+typedef struct {
+ /*
+ * Boot interface used to boot : take values from defines
+ * BOOT_API_CTX_BOOT_INTERFACE_SEL_XXX above
+ */
+ uint16_t boot_interface_selected;
+ uint16_t boot_interface_instance;
+#if STM32MP13
+ uint32_t reserved1[12];
+#endif
+#if STM32MP15
+ uint32_t reserved1[13];
+#endif
+ uint32_t otp_afmux_values[3];
+ uint32_t reserved[3];
+#if STM32MP15
+ uint32_t reserved2[2];
+#endif
+ uint32_t auth_status;
+
+#if STM32MP15
+ /*
+ * Pointers to bootROM External Secure Services
+ * - ECDSA verify signature
+ */
+ uint32_t reserved3;
+ uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in,
+ uint8_t *pubkey_in,
+ uint8_t *signature,
+ uint32_t ecc_algo);
+ uint32_t reserved4;
+#endif
+ /*
+ * Information specific to an SD boot
+ * Updated each time an SD boot is at least attempted,
+ * even if not successful
+ * Note : This is useful to understand why an SD boot failed
+ * in particular
+ */
+ uint32_t sd_err_internal_timeout_cnt;
+ uint32_t sd_err_dcrc_fail_cnt;
+ uint32_t sd_err_dtimeout_cnt;
+ uint32_t sd_err_ctimeout_cnt;
+ uint32_t sd_err_ccrc_fail_cnt;
+ uint32_t sd_overall_retry_cnt;
+ /*
+ * Information specific to an eMMC boot
+ * Updated each time an eMMC boot is at least attempted,
+ * even if not successful
+ * Note : This is useful to understand why an eMMC boot failed
+ * in particular
+ */
+ uint32_t emmc_xfer_status;
+ uint32_t emmc_error_status;
+ uint32_t emmc_nbbytes_rxcopied_tosysram_download_area;
+ uint32_t hse_clock_value_in_hz;
+ /*
+ * Boot partition :
+ * ie FSBL partition on which the boot was successful
+ */
+ uint32_t boot_partition_used_toboot;
+
+} __packed boot_api_context_t;
+
+/*
+ * Image Header related definitions
+ */
+
+/*
+ * Structure used to define the common Header format used for FSBL, xloader,
+ * ... and in particular used by bootROM for FSBL header readout.
+ * FSBL header size is 256 Bytes = 0x100
+ */
+typedef struct {
+ /* BOOT_API_IMAGE_HEADER_MAGIC_NB */
+ uint32_t magic;
+ uint8_t image_signature[BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES];
+ /*
+ * Checksum of payload
+ * 32-bit sum all payload bytes considered as 8 bit unsigned
+ * numbers, discarding any overflow bits.
+ * Use to check UART/USB downloaded image integrity when signature
+ * is not used
+ */
+ uint32_t payload_checksum;
+ /* Image header version : should have value BOOT_API_HEADER_VERSION */
+ uint32_t header_version;
+ /* Image length in bytes */
+ uint32_t image_length;
+ /*
+ * Image Entry point address : should be in the SYSRAM area
+ * and at least within the download area range
+ */
+ uint32_t image_entry_point;
+ /* Reserved */
+ uint32_t reserved1;
+ /*
+ * Image load address : not used by bootROM but to be consistent
+ * with header format for other packages (xloader, ...)
+ */
+ uint32_t load_address;
+ /* Reserved */
+ uint32_t reserved2;
+ /* Image version to be compared by bootROM with monotonic
+ * counter value in OTP_CFG4 prior executing the downloaded image
+ */
+ uint32_t image_version;
+
+#if STM32MP13
+ /*
+ * Extension flags :
+ *
+ * Bit 0 : Authentication extension header
+ * value 0 : No signature check request
+ * Bit 1 : Encryption extension header
+ * Bit 2 : Padding extension header
+ */
+ uint32_t extension_flags;
+ /* Length in bytes of all extension headers */
+ uint32_t extension_headers_length;
+ /* Add binary type information */
+ uint32_t binary_type;
+ /* Pad up to 128 byte total size */
+ uint8_t pad[16];
+ /* Followed by extension header */
+ uint8_t ext_header[];
+#endif
+#if STM32MP15
+ /*
+ * Option flags:
+ * Bit 0 : No signature check request : 'No_sig_check'
+ * value 1 : for No signature check request
+ * value 0 : No request to bypass the signature check
+ * Note : No signature check is never allowed on a Secured chip
+ */
+ uint32_t option_flags;
+ /*
+ * Type of ECC algorithm to use :
+ * value 1 : for P-256 NIST algorithm
+ * value 2 : for Brainpool 256 algorithm
+ * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
+ */
+ uint32_t ecc_algo_type;
+ /*
+ * OEM ECC Public Key (aka Root pubk) provided in header on 512 bits.
+ * The SHA-256 hash of the OEM ECC pubk must match the one stored
+ * in OTP cells.
+ */
+ uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
+ /* Pad up to 256 byte total size */
+ uint8_t pad[83];
+ /* Add binary type information */
+ uint8_t binary_type;
+#endif
+} __packed boot_api_image_header_t;
+
+typedef uint8_t boot_api_sha256_t[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+
+typedef struct {
+ /* Extension header type:
+ * BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB or
+ * BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB
+ * BOOT_API_PADDING_HEADER_MAGIC_NB
+ */
+ uint32_t type;
+ /* Extension header len in byte */
+ uint32_t len;
+ /* parameters of this extension */
+ uint8_t params[];
+} __packed boot_extension_header_t;
+
+typedef struct {
+ /* Idx of ECDSA public key to be used in table */
+ uint32_t pk_idx;
+ /* Number of ECDSA public key in table */
+ uint32_t nb_pk;
+ /*
+ * Type of ECC algorithm to use :
+ * value 1 : for P-256 NIST algorithm
+ * value 2 : for Brainpool 256 algorithm
+ * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
+ */
+ uint32_t ecc_algo_type;
+ /* ECDSA public key to be used to check signature. */
+ uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
+ /* table of Hash of Algo+ECDSA public key */
+ boot_api_sha256_t pk_hashes[];
+} __packed boot_ext_header_params_authentication_t;
+
+typedef struct {
+ /* Size of encryption key (128 or 256) */
+ uint32_t key_size;
+ uint32_t derivation_cont;
+ /* 128 msb bits of plain payload SHA256 */
+ uint32_t hash[4];
+} __packed boot_ext_header_params_encrypted_fsbl_t;
+
+#endif /* BOOT_API_H */
diff --git a/plat/st/stm32mp1/include/plat_def_fip_uuid.h b/plat/st/stm32mp1/include/plat_def_fip_uuid.h
new file mode 100644
index 0000000..e5fbc2d
--- /dev/null
+++ b/plat/st/stm32mp1/include/plat_def_fip_uuid.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_FIP_UUID_H
+#define PLAT_DEF_FIP_UUID_H
+
+#define UUID_STM32MP_CONFIG_CERT \
+ {{0x50, 0x1d, 0x8d, 0xd2}, {0x8b, 0xce}, {0x49, 0xa5}, 0x84, 0xeb, \
+ {0x55, 0x9a, 0x9f, 0x2e, 0xae, 0xaf} }
+#endif /* PLAT_DEF_FIP_UUID_H */
+
diff --git a/plat/st/stm32mp1/include/plat_tbbr_img_def.h b/plat/st/stm32mp1/include/plat_tbbr_img_def.h
new file mode 100644
index 0000000..984aae8
--- /dev/null
+++ b/plat/st/stm32mp1/include/plat_tbbr_img_def.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef STM32MP1_IMG_DEF_H
+#define STM32MP1_IMG_DEF_H
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/* Undef the existing values */
+#undef BL32_EXTRA1_IMAGE_ID
+#undef BL32_EXTRA2_IMAGE_ID
+#undef TOS_FW_CONFIG_ID
+#undef TRUSTED_BOOT_FW_CERT_ID
+#undef FWU_METADATA_IMAGE_ID
+#undef BKUP_FWU_METADATA_IMAGE_ID
+#undef FW_CONFIG_ID
+#undef HW_CONFIG_ID
+#undef GPT_IMAGE_ID
+#undef ENC_IMAGE_ID
+
+/* Define the STM32MP1 used ID */
+#define FW_CONFIG_ID U(1)
+#define HW_CONFIG_ID U(2)
+#define GPT_IMAGE_ID U(3)
+#define ENC_IMAGE_ID U(6)
+#define BL32_EXTRA1_IMAGE_ID U(8)
+#define BL32_EXTRA2_IMAGE_ID U(9)
+#define FWU_METADATA_IMAGE_ID U(12)
+#define BKUP_FWU_METADATA_IMAGE_ID U(13)
+#define TOS_FW_CONFIG_ID U(16)
+#define STM32MP_CONFIG_CERT_ID U(17)
+
+/* Increase the MAX_NUMBER_IDS to match the authentication pool required */
+#define MAX_NUMBER_IDS U(19)
+
+#endif /* STM32MP1_IMG_DEF_H */
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
new file mode 100644
index 0000000..61b847f
--- /dev/null
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "../stm32mp1_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x600
+#else
+#define PLATFORM_STACK_SIZE 0xC00
+#endif
+
+#define FIP_IMAGE_NAME "fip"
+#define METADATA_PART_1 "metadata1"
+#define METADATA_PART_2 "metadata2"
+
+#define STM32MP_PRIMARY_CPU U(0x0)
+#define STM32MP_SECONDARY_CPU U(0x1)
+
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(2)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 2
+
+#define MAX_IO_DEVICES U(4)
+#define MAX_IO_HANDLES U(4)
+#define MAX_IO_BLOCK_DEVICES U(1)
+#define MAX_IO_MTD_DEVICES U(1)
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define BL2_BASE STM32MP_BL2_BASE
+#define BL2_LIMIT (STM32MP_BL2_BASE + \
+ STM32MP_BL2_SIZE)
+
+#define BL2_RO_BASE STM32MP_BL2_RO_BASE
+#define BL2_RO_LIMIT (STM32MP_BL2_RO_BASE + \
+ STM32MP_BL2_RO_SIZE)
+
+#define BL2_RW_BASE STM32MP_BL2_RW_BASE
+#define BL2_RW_LIMIT (STM32MP_BL2_RW_BASE + \
+ STM32MP_BL2_RW_SIZE)
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#if defined(IMAGE_BL32)
+#if ENABLE_PIE
+#define BL32_BASE 0
+#define BL32_LIMIT STM32MP_BL32_SIZE
+#else
+#define BL32_BASE STM32MP_BL32_BASE
+#define BL32_LIMIT (STM32MP_BL32_BASE + \
+ STM32MP_BL32_SIZE)
+#endif
+#endif /* defined(IMAGE_BL32) */
+
+/*******************************************************************************
+ * BL33 specific defines.
+ ******************************************************************************/
+#define BL33_BASE STM32MP_BL33_BASE
+
+/*
+ * Load address of BL33 for this platform port
+ */
+#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE
+
+/* Needed by STM32CubeProgrammer support */
+#define DWL_BUFFER_SIZE U(0x01000000)
+
+/*
+ * SSBL offset in case it's stored in eMMC boot partition.
+ * We can fix it to 256K because TF-A size can't be bigger than SRAM
+ */
+#define PLAT_EMMC_BOOT_SSBL_OFFSET U(0x40000)
+
+/*******************************************************************************
+ * DTB specific defines.
+ ******************************************************************************/
+#define DTB_BASE STM32MP_DTB_BASE
+#define DTB_LIMIT (STM32MP_DTB_BASE + \
+ STM32MP_DTB_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Secure Interrupt: based on the standard ARM mapping
+ */
+#define ARM_IRQ_SEC_PHY_TIMER U(29)
+
+#define ARM_IRQ_SEC_SGI_0 U(8)
+#define ARM_IRQ_SEC_SGI_1 U(9)
+#define ARM_IRQ_SEC_SGI_2 U(10)
+#define ARM_IRQ_SEC_SGI_3 U(11)
+#define ARM_IRQ_SEC_SGI_4 U(12)
+#define ARM_IRQ_SEC_SGI_5 U(13)
+#define ARM_IRQ_SEC_SGI_6 U(14)
+#define ARM_IRQ_SEC_SGI_7 U(15)
+
+#define STM32MP1_IRQ_TZC400 U(36)
+#define STM32MP1_IRQ_TAMPSERRS U(229)
+#define STM32MP1_IRQ_AXIERRIRQ U(244)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLATFORM_G1S_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(STM32MP1_IRQ_TZC400, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE)
+
+/*
+ * Power
+ */
+#define PLAT_MAX_PWR_LVL U(1)
+
+/* Local power state for power domains in Run state. */
+#define ARM_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define ARM_LOCAL_STATE_RET U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains */
+#define ARM_LOCAL_STATE_OFF U(2)
+/*
+ * This macro defines the deepest retention state possible.
+ * A higher state id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE ARM_LOCAL_STATE_RET
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE ARM_LOCAL_STATE_OFF
+
+/*******************************************************************************
+ * Size of the per-cpu data in bytes that should be reserved in the generic
+ * per-cpu data structure for the FVP port.
+ ******************************************************************************/
+#define PLAT_PCPU_DATA_SIZE 2
+
+/*******************************************************************************
+ * Number of parallel entry slots in SMT SCMI server entry context. For this
+ * platform, SCMI server is reached through SMC only, hence the number of
+ * entry slots.
+ ******************************************************************************/
+#define PLAT_SMT_ENTRY_COUNT PLATFORM_CORE_COUNT
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
new file mode 100644
index 0000000..3663bce
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_DBGMCU_H
+#define STM32MP1_DBGMCU_H
+
+#include <stdint.h>
+
+/* Get chip version and ID from DBGMCU registers */
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version);
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id);
+
+#endif /* STM32MP1_DBGMCU_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h b/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
new file mode 100644
index 0000000..2f07621
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/*
+ * Key algorithms currently supported on mbed TLS libraries
+ */
+#define TF_MBEDTLS_USE_RSA 0
+#define TF_MBEDTLS_USE_ECDSA 1
+
+/*
+ * Hash algorithms currently supported on mbed TLS libraries
+ */
+#define TF_MBEDTLS_SHA256 1
+#define TF_MBEDTLS_SHA384 2
+#define TF_MBEDTLS_SHA512 3
+
+/*
+ * Configuration file to build mbed TLS with the required features for
+ * Trusted Boot
+ */
+
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PKCS1_V21
+
+#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+#define MBEDTLS_X509_CHECK_KEY_USAGE
+#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_MD_C
+
+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+#define MBEDTLS_OID_C
+
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+
+#define MBEDTLS_PLATFORM_C
+
+#if TF_MBEDTLS_USE_ECDSA
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_NO_INTERNAL_RNG
+#endif
+#if TF_MBEDTLS_USE_RSA
+#define MBEDTLS_RSA_C
+#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+#endif
+
+#define MBEDTLS_SHA256_C
+#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256)
+#define MBEDTLS_SHA512_C
+#endif
+
+#define MBEDTLS_VERSION_C
+
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+
+#if TF_MBEDTLS_USE_AES_GCM
+#define MBEDTLS_AES_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_GCM_C
+#endif
+
+/* MPI / BIGNUM options */
+#define MBEDTLS_MPI_WINDOW_SIZE 2
+
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE <= 2048
+#define MBEDTLS_MPI_MAX_SIZE 256
+#else
+#define MBEDTLS_MPI_MAX_SIZE 512
+#endif
+#else
+#define MBEDTLS_MPI_MAX_SIZE 256
+#endif
+
+/* Memory buffer allocator options */
+#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8
+
+/*
+ * Prevent the use of 128-bit division which
+ * creates dependency on external libraries.
+ */
+#define MBEDTLS_NO_UDBL_DIVISION
+
+#ifndef __ASSEMBLER__
+/* System headers required to build mbed TLS with the current configuration */
+#include <stdlib.h>
+#include <mbedtls/check_config.h>
+#endif
+
+/*
+ * Mbed TLS heap size is smal as we only use the asn1
+ * parsing functions
+ * digest, signature and crypto algorithm are done by
+ * other library.
+ */
+
+#define TF_MBEDTLS_HEAP_SIZE U(5120)
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
new file mode 100644
index 0000000..21ef60d
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_PRIVATE_H
+#define STM32MP1_PRIVATE_H
+
+#include <stdint.h>
+
+void configure_mmu(void);
+
+void stm32mp1_arch_security_setup(void);
+void stm32mp1_security_setup(void);
+
+void stm32mp1_gic_pcpu_init(void);
+void stm32mp1_gic_init(void);
+
+void stm32mp1_syscfg_init(void);
+void stm32mp1_syscfg_enable_io_compensation_start(void);
+void stm32mp1_syscfg_enable_io_compensation_finish(void);
+void stm32mp1_syscfg_disable_io_compensation(void);
+uint32_t stm32mp1_syscfg_get_chip_version(void);
+uint32_t stm32mp1_syscfg_get_chip_dev_id(void);
+#if STM32MP13
+void stm32mp1_syscfg_boot_mode_enable(void);
+void stm32mp1_syscfg_boot_mode_disable(void);
+#endif
+#if STM32MP15
+static inline void stm32mp1_syscfg_boot_mode_enable(void){}
+static inline void stm32mp1_syscfg_boot_mode_disable(void){}
+#endif
+
+void stm32mp1_deconfigure_uart_pins(void);
+
+void stm32mp1_init_scmi_server(void);
+#endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
new file mode 100644
index 0000000..3f6367e
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SHARED_RESOURCES_H
+#define STM32MP1_SHARED_RESOURCES_H
+
+#include <stm32mp_shared_resources.h>
+
+#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i))
+
+enum stm32mp_shres {
+ STM32MP1_SHRES_CRYP1,
+ STM32MP1_SHRES_GPIOZ_0,
+ STM32MP1_SHRES_GPIOZ_1,
+ STM32MP1_SHRES_GPIOZ_2,
+ STM32MP1_SHRES_GPIOZ_3,
+ STM32MP1_SHRES_GPIOZ_4,
+ STM32MP1_SHRES_GPIOZ_5,
+ STM32MP1_SHRES_GPIOZ_6,
+ STM32MP1_SHRES_GPIOZ_7,
+ STM32MP1_SHRES_HASH1,
+ STM32MP1_SHRES_I2C4,
+ STM32MP1_SHRES_I2C6,
+ STM32MP1_SHRES_IWDG1,
+ STM32MP1_SHRES_MCU,
+ STM32MP1_SHRES_MDMA,
+ STM32MP1_SHRES_PLL3,
+ STM32MP1_SHRES_RNG1,
+ STM32MP1_SHRES_RTC,
+ STM32MP1_SHRES_SPI6,
+ STM32MP1_SHRES_USART1,
+
+ STM32MP1_SHRES_COUNT
+};
+#endif /* STM32MP1_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
new file mode 100644
index 0000000..52088de
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SMC_H
+#define STM32MP1_SMC_H
+
+/*
+ * SMC function IDs for STM32 Service queries
+ * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
+ * like this is defined in SMC calling Convention by ARM
+ * for SiP (silicon Partner)
+ * https://developer.arm.com/docs/den0028/latest
+ */
+
+/* Secure Service access from Non-secure */
+
+/*
+ * STM32_SMC_BSEC call API
+ *
+ * Argument a0: (input) SMCC ID
+ * (output) status return code
+ * Argument a1: (input) Service ID (STM32_SMC_BSEC_xxx)
+ * Argument a2: (input) OTP index
+ * (output) OTP read value, if applicable
+ * Argument a3: (input) OTP value if applicable
+ */
+#define STM32_SMC_BSEC 0x82001003
+
+/*
+ * STM32_SIP_SMC_SCMI_AGENT0
+ * STM32_SIP_SMC_SCMI_AGENT1
+ * Process SCMI message pending in SCMI shared memory buffer.
+ *
+ * Argument a0: (input) SMCC ID
+ */
+#define STM32_SIP_SMC_SCMI_AGENT0 0x82002000
+#define STM32_SIP_SMC_SCMI_AGENT1 0x82002001
+
+/* SMC function IDs for SiP Service queries */
+#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
+#define STM32_SIP_SVC_UID 0x8200ff01
+/* 0x8200ff02 is reserved */
+#define STM32_SIP_SVC_VERSION 0x8200ff03
+
+/* STM32 SiP Service Calls version numbers */
+#define STM32_SIP_SVC_VERSION_MAJOR 0x0
+#define STM32_SIP_SVC_VERSION_MINOR 0x1
+
+/* Number of STM32 SiP Calls implemented */
+#define STM32_COMMON_SIP_NUM_CALLS 3
+
+/* Service for BSEC */
+#define STM32_SMC_READ_SHADOW 0x01
+#define STM32_SMC_PROG_OTP 0x02
+#define STM32_SMC_WRITE_SHADOW 0x03
+#define STM32_SMC_READ_OTP 0x04
+
+/* SMC error codes */
+#define STM32_SMC_OK 0x00000000U
+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
+#define STM32_SMC_FAILED 0xFFFFFFFEU
+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
+
+#endif /* STM32MP1_SMC_H */
diff --git a/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h b/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
new file mode 100644
index 0000000..2cc1e19
--- /dev/null
+++ b/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_TBB_CERT_H
+#define STM32MP1_TBB_CERT_H
+
+#include <tbbr/tbb_cert.h>
+
+/*
+ * Enumerate the certificates that are used to establish the chain of trust
+ */
+enum {
+ STM32MP_CONFIG_CERT = FWU_CERT + 1
+};
+
+#endif /* STM32MP1_TBB_CERT_H */
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
new file mode 100644
index 0000000..9ca0930
--- /dev/null
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ /* Fill FW_CONFIG related information if it exists */
+ {
+ .image_id = FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+
+ .image_info.image_base = STM32MP_FW_CONFIG_BASE,
+ .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+
+ .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+ SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /* Fill BL32 external 1 image related information */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#if STM32MP15
+ /* Fill BL32 external 2 image related information */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif
+
+ /* Fill HW_CONFIG related information if it exists */
+ {
+ .image_id = HW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill TOS_FW_CONFIG related information if it exists */
+ {
+ .image_id = TOS_FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+
+ .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+ SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/st/stm32mp1/plat_def_uuid_config.c b/plat/st/stm32mp1/plat_def_uuid_config.c
new file mode 100644
index 0000000..efaf567
--- /dev/null
+++ b/plat/st/stm32mp1/plat_def_uuid_config.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <firmware_image_package.h>
+
+#include "tbbr_config.h"
+
+toc_entry_t plat_def_toc_entries[] = {
+ {
+ .name = "STM32MP CONFIG CERT",
+ .uuid = UUID_STM32MP_CONFIG_CERT,
+ .cmdline_name = "stm32mp-cfg-cert"
+ }
+};
+
diff --git a/plat/st/stm32mp1/plat_fiptool.mk b/plat/st/stm32mp1/plat_fiptool.mk
new file mode 100644
index 0000000..00570c2
--- /dev/null
+++ b/plat/st/stm32mp1/plat_fiptool.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Name of the platform defined source file name,
+# which contains platform defined UUID entries populated
+# in the plat_def_toc_entries[].
+PLAT_DEF_UUID_FILE_NAME := plat_def_uuid_config
+
+INCLUDE_PATHS += -I${PLAT_DIR}/include -I./
+
+PLAT_DEF_UUID := yes
+
+ifeq (${PLAT_DEF_UUID},yes)
+HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
+
+${PLAT_DEF_UUID_FILE_NAME}.o: ${PLAT_DIR}${PLAT_DEF_UUID_FILE_NAME}.c
+ ${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
+
+PLAT_OBJECTS += ${PLAT_DEF_UUID_FILE_NAME}.o
+endif
+
+OBJECTS += ${PLAT_OBJECTS}
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
new file mode 100644
index 0000000..c4048fc
--- /dev/null
+++ b/plat/st/stm32mp1/plat_image_load.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ bl_params_t *bl_params = get_next_bl_params_from_mem_params_desc();
+
+ populate_next_bl_params_config(bl_params);
+
+ return bl_params;
+}
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
new file mode 100644
index 0000000..7eecf30
--- /dev/null
+++ b/plat/st/stm32mp1/platform.mk
@@ -0,0 +1,553 @@
+#
+# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ARM_CORTEX_A7 := yes
+ARM_WITH_NEON := yes
+BL2_AT_EL3 := 1
+USE_COHERENT_MEM := 0
+
+STM32MP_EARLY_CONSOLE ?= 0
+STM32MP_RECONFIGURE_CONSOLE ?= 0
+STM32MP_UART_BAUDRATE ?= 115200
+
+TRUSTED_BOARD_BOOT ?= 0
+STM32MP_USE_EXTERNAL_HEAP ?= 0
+
+# Use secure library from the ROM code for authentication
+STM32MP_CRYPTO_ROM_LIB ?= 0
+
+# Please don't increment this value without good understanding of
+# the monotonic counter
+STM32_TF_VERSION ?= 0
+
+# Enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC := 1
+
+# Default Device tree
+DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
+
+STM32MP13 ?= 0
+STM32MP15 ?= 0
+
+ifeq ($(STM32MP13),1)
+ifeq ($(STM32MP15),1)
+$(error Cannot enable both flags STM32MP13 and STM32MP15)
+endif
+STM32MP13 := 1
+STM32MP15 := 0
+else ifeq ($(STM32MP15),1)
+STM32MP13 := 0
+STM32MP15 := 1
+else ifneq ($(findstring stm32mp13,$(DTB_FILE_NAME)),)
+STM32MP13 := 1
+STM32MP15 := 0
+else ifneq ($(findstring stm32mp15,$(DTB_FILE_NAME)),)
+STM32MP13 := 0
+STM32MP15 := 1
+endif
+
+ifeq ($(STM32MP13),1)
+# Will use SRAM2 as mbedtls heap
+STM32MP_USE_EXTERNAL_HEAP := 1
+
+# DDR controller with single AXI port and 16-bit interface
+STM32MP_DDR_DUAL_AXI_PORT:= 0
+STM32MP_DDR_32BIT_INTERFACE:= 0
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+# PKA algo to include
+PKA_USE_NIST_P256 := 1
+PKA_USE_BRAINPOOL_P256T1:= 1
+endif
+
+# STM32 image header version v2.0
+STM32_HEADER_VERSION_MAJOR:= 2
+STM32_HEADER_VERSION_MINOR:= 0
+endif
+
+ifeq ($(STM32MP15),1)
+# DDR controller with dual AXI port and 32-bit interface
+STM32MP_DDR_DUAL_AXI_PORT:= 1
+STM32MP_DDR_32BIT_INTERFACE:= 1
+
+# STM32 image header version v1.0
+STM32_HEADER_VERSION_MAJOR:= 1
+STM32_HEADER_VERSION_MINOR:= 0
+
+# Add OP-TEE reserved shared memory area in mapping
+STM32MP15_OPTEE_RSV_SHM := 1
+$(eval $(call add_defines,STM32MP15_OPTEE_RSV_SHM))
+
+STM32MP_CRYPTO_ROM_LIB := 1
+
+# Decryption support
+ifneq ($(DECRYPTION_SUPPORT),none)
+$(error "DECRYPTION_SUPPORT not supported on STM32MP15")
+endif
+endif
+
+# STM32 image header binary type for BL2
+STM32_HEADER_BL2_BINARY_TYPE:= 0x10
+
+ifeq ($(AARCH32_SP),sp_min)
+# Disable Neon support: sp_min runtime may conflict with non-secure world
+TF_CFLAGS += -mfloat-abi=soft
+endif
+
+TF_CFLAGS += -Wsign-compare
+TF_CFLAGS += -Wformat-signedness
+
+# Not needed for Cortex-A7
+WORKAROUND_CVE_2017_5715:= 0
+WORKAROUND_CVE_2022_23960:= 0
+
+# Number of TF-A copies in the device
+STM32_TF_A_COPIES := 2
+
+# PLAT_PARTITION_MAX_ENTRIES must take care of STM32_TF-A_COPIES and other partitions
+# such as metadata (2) to find all the FIP partitions (default is 2).
+PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 4)))
+
+ifeq (${PSA_FWU_SUPPORT},1)
+# Number of banks of updatable firmware
+NR_OF_FW_BANKS := 2
+NR_OF_IMAGES_IN_FW_BANK := 1
+
+FWU_MAX_PART = $(shell echo $$(($(STM32_TF_A_COPIES) + 2 + $(NR_OF_FW_BANKS))))
+ifeq ($(shell test $(FWU_MAX_PART) -gt $(PLAT_PARTITION_MAX_ENTRIES); echo $$?),0)
+$(error "Required partition number is $(FWU_MAX_PART) where PLAT_PARTITION_MAX_ENTRIES is only \
+$(PLAT_PARTITION_MAX_ENTRIES)")
+endif
+endif
+
+ifeq ($(STM32MP13),1)
+STM32_HASH_VER := 4
+STM32_RNG_VER := 4
+else # Assuming STM32MP15
+STM32_HASH_VER := 2
+STM32_RNG_VER := 2
+endif
+
+# Boot devices
+STM32MP_EMMC ?= 0
+STM32MP_SDMMC ?= 0
+STM32MP_RAW_NAND ?= 0
+STM32MP_SPI_NAND ?= 0
+STM32MP_SPI_NOR ?= 0
+STM32MP_EMMC_BOOT ?= 0
+
+# Serial boot devices
+STM32MP_USB_PROGRAMMER ?= 0
+STM32MP_UART_PROGRAMMER ?= 0
+
+# Download load address for serial boot devices
+DWL_BUFFER_BASE ?= 0xC7000000
+
+# Device tree
+ifeq ($(STM32MP13),1)
+BL2_DTSI := stm32mp13-bl2.dtsi
+FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+else
+BL2_DTSI := stm32mp15-bl2.dtsi
+FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+ifeq ($(AARCH32_SP),sp_min)
+BL32_DTSI := stm32mp15-bl32.dtsi
+FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME)))
+endif
+endif
+
+$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}'))
+$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g" | grep -o "[0-9]*")))
+DTC_CPPFLAGS += ${INCLUDES}
+DTC_FLAGS += -Wno-unit_address_vs_reg
+ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0)
+DTC_FLAGS += -Wno-interrupt_provider
+endif
+
+# Macros and rules to build TF binary
+STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed
+STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
+STM32_TF_LINKERFILE := ${BUILD_PLAT}/stm32mp1.ld
+
+ASFLAGS += -DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\"
+ifeq ($(AARCH32_SP),sp_min)
+# BL32 is built only if using SP_MIN
+BL32_DEP := bl32
+ASFLAGS += -DBL32_BIN_PATH=\"${BUILD_PLAT}/bl32.bin\"
+endif
+
+# Variables for use with stm32image
+STM32IMAGEPATH ?= tools/stm32image
+STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
+STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c
+
+FIP_DEPS += dtbs
+STM32MP_HW_CONFIG := ${BL33_CFG}
+STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
+STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
+ifneq (${AARCH32_SP},none)
+FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME)))
+endif
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
+ifeq ($(GENERATE_COT),1)
+STM32MP_CFG_CERT := $(BUILD_PLAT)/stm32mp_cfg_cert.crt
+# Add the STM32MP_CFG_CERT to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_CFG_CERT},--stm32mp-cfg-cert))
+endif
+ifeq ($(AARCH32_SP),sp_min)
+STM32MP_TOS_FW_CONFIG := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME)))
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config))
+else
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
+endif
+endif
+
+# Enable flags for C files
+$(eval $(call assert_booleans,\
+ $(sort \
+ PKA_USE_BRAINPOOL_P256T1 \
+ PKA_USE_NIST_P256 \
+ PLAT_TBBR_IMG_DEF \
+ PLAT_XLAT_TABLES_DYNAMIC \
+ STM32MP_CRYPTO_ROM_LIB \
+ STM32MP_DDR_32BIT_INTERFACE \
+ STM32MP_DDR_DUAL_AXI_PORT \
+ STM32MP_EARLY_CONSOLE \
+ STM32MP_EMMC \
+ STM32MP_EMMC_BOOT \
+ STM32MP_RAW_NAND \
+ STM32MP_RECONFIGURE_CONSOLE \
+ STM32MP_SDMMC \
+ STM32MP_SPI_NAND \
+ STM32MP_SPI_NOR \
+ STM32MP_UART_PROGRAMMER \
+ STM32MP_USB_PROGRAMMER \
+ STM32MP_USE_EXTERNAL_HEAP \
+ STM32MP13 \
+ STM32MP15 \
+)))
+
+$(eval $(call assert_numerics,\
+ $(sort \
+ PLAT_PARTITION_MAX_ENTRIES \
+ STM32_HASH_VER \
+ STM32_HEADER_VERSION_MAJOR \
+ STM32_RNG_VER \
+ STM32_TF_A_COPIES \
+ STM32_TF_VERSION \
+ STM32MP_UART_BAUDRATE \
+)))
+
+$(eval $(call add_defines,\
+ $(sort \
+ DWL_BUFFER_BASE \
+ PKA_USE_BRAINPOOL_P256T1 \
+ PKA_USE_NIST_P256 \
+ PLAT_PARTITION_MAX_ENTRIES \
+ PLAT_TBBR_IMG_DEF \
+ PLAT_XLAT_TABLES_DYNAMIC \
+ STM32_HASH_VER \
+ STM32_HEADER_VERSION_MAJOR \
+ STM32_RNG_VER \
+ STM32_TF_A_COPIES \
+ STM32_TF_VERSION \
+ STM32MP_CRYPTO_ROM_LIB \
+ STM32MP_DDR_32BIT_INTERFACE \
+ STM32MP_DDR_DUAL_AXI_PORT \
+ STM32MP_EARLY_CONSOLE \
+ STM32MP_EMMC \
+ STM32MP_EMMC_BOOT \
+ STM32MP_RAW_NAND \
+ STM32MP_RECONFIGURE_CONSOLE \
+ STM32MP_SDMMC \
+ STM32MP_SPI_NAND \
+ STM32MP_SPI_NOR \
+ STM32MP_UART_BAUDRATE \
+ STM32MP_UART_PROGRAMMER \
+ STM32MP_USB_PROGRAMMER \
+ STM32MP_USE_EXTERNAL_HEAP \
+ STM32MP13 \
+ STM32MP15 \
+)))
+
+# Include paths and source files
+PLAT_INCLUDES := -Iplat/st/common/include/
+PLAT_INCLUDES += -Iplat/st/stm32mp1/include/
+
+include lib/fconf/fconf.mk
+include lib/libfdt/libfdt.mk
+
+PLAT_BL_COMMON_SOURCES := common/uuid.c \
+ plat/st/common/stm32mp_common.c \
+ plat/st/stm32mp1/stm32mp1_private.c
+
+PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += plat/st/stm32mp1/stm32mp1_stack_protector.c
+endif
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S
+
+PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \
+ drivers/clk/clk.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/st/bsec/bsec2.c \
+ drivers/st/clk/stm32mp_clkfunc.c \
+ drivers/st/ddr/stm32mp_ddr.c \
+ drivers/st/ddr/stm32mp1_ddr_helpers.c \
+ drivers/st/gpio/stm32_gpio.c \
+ drivers/st/i2c/stm32_i2c.c \
+ drivers/st/iwdg/stm32_iwdg.c \
+ drivers/st/pmic/stm32mp_pmic.c \
+ drivers/st/pmic/stpmic1.c \
+ drivers/st/regulator/regulator_core.c \
+ drivers/st/regulator/regulator_fixed.c \
+ drivers/st/reset/stm32mp1_reset.c \
+ plat/st/common/stm32mp_dt.c \
+ plat/st/stm32mp1/stm32mp1_dbgmcu.c \
+ plat/st/stm32mp1/stm32mp1_helper.S \
+ plat/st/stm32mp1/stm32mp1_syscfg.c
+
+ifeq ($(STM32MP13),1)
+PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \
+ drivers/st/clk/clk-stm32mp13.c \
+ drivers/st/crypto/stm32_rng.c
+else
+PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c
+endif
+
+BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+
+BL2_SOURCES += drivers/io/io_fip.c \
+ plat/st/common/bl2_io_storage.c \
+ plat/st/common/stm32mp_fconf_io.c \
+ plat/st/stm32mp1/plat_bl2_mem_params_desc.c \
+ plat/st/stm32mp1/stm32mp1_fconf_firewall.c
+
+include lib/zlib/zlib.mk
+
+ifeq (${PSA_FWU_SUPPORT},1)
+include drivers/fwu/fwu.mk
+endif
+
+
+BL2_SOURCES += $(ZLIB_SOURCES)
+
+BL2_SOURCES += drivers/io/io_block.c \
+ drivers/io/io_mtd.c \
+ drivers/io/io_storage.c \
+ drivers/st/crypto/stm32_hash.c \
+ plat/st/stm32mp1/bl2_plat_setup.c
+
+ifneq (${DECRYPTION_SUPPORT},none)
+BL2_SOURCES += drivers/io/io_encrypted.c
+endif
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c
+
+ifeq (${GENERATE_COT},1)
+TFW_NVCTR_VAL := 0
+NTFW_NVCTR_VAL := 0
+KEY_SIZE :=
+KEY_ALG := ecdsa
+HASH_ALG := sha256
+
+ifeq (${SAVE_KEYS},1)
+TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/trusted.pem
+NON_TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/non-trusted.pem
+BL32_KEY ?= ${BUILD_PLAT}/trusted_os.pem
+BL33_KEY ?= ${BUILD_PLAT}/non-trusted_os.pem
+endif
+
+endif
+TF_MBEDTLS_KEY_ALG := ecdsa
+MBEDTLS_CONFIG_FILE ?= "<stm32mp1_mbedtls_config.h>"
+
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+COT_DESC_IN_DTB := 1
+AUTH_SOURCES += lib/fconf/fconf_cot_getter.c \
+ lib/fconf/fconf_tbbr_getter.c \
+ plat/st/common/stm32mp_crypto_lib.c
+
+ifeq ($(STM32MP13),1)
+AUTH_SOURCES += drivers/st/crypto/stm32_pka.c
+AUTH_SOURCES += drivers/st/crypto/stm32_saes.c
+endif
+
+BL2_SOURCES += $(AUTH_SOURCES) \
+ plat/st/common/stm32mp_trusted_boot.c
+endif
+
+ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
+BL2_SOURCES += drivers/mmc/mmc.c \
+ drivers/partition/gpt.c \
+ drivers/partition/partition.c \
+ drivers/st/io/io_mmc.c \
+ drivers/st/mmc/stm32_sdmmc2.c
+endif
+
+ifeq (${STM32MP_RAW_NAND},1)
+$(eval $(call add_define_val,NAND_ONFI_DETECT,1))
+BL2_SOURCES += drivers/mtd/nand/raw_nand.c \
+ drivers/st/fmc/stm32_fmc2_nand.c
+endif
+
+ifeq (${STM32MP_SPI_NAND},1)
+BL2_SOURCES += drivers/mtd/nand/spi_nand.c
+endif
+
+ifeq (${STM32MP_SPI_NOR},1)
+ifneq (${STM32MP_FORCE_MTD_START_OFFSET},)
+$(eval $(call add_define_val,STM32MP_NOR_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET}))
+endif
+BL2_SOURCES += drivers/mtd/nor/spi_nor.c
+endif
+
+ifneq ($(filter 1,${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
+BL2_SOURCES += drivers/mtd/spi-mem/spi_mem.c \
+ drivers/st/spi/stm32_qspi.c
+endif
+
+ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),)
+ifneq (${STM32MP_FORCE_MTD_START_OFFSET},)
+$(eval $(call add_define_val,STM32MP_NAND_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET}))
+endif
+BL2_SOURCES += drivers/mtd/nand/core.c
+endif
+
+ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
+BL2_SOURCES += plat/st/stm32mp1/stm32mp1_boot_device.c
+endif
+
+ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),)
+BL2_SOURCES += drivers/io/io_memmap.c
+endif
+
+ifeq (${STM32MP_UART_PROGRAMMER},1)
+BL2_SOURCES += drivers/st/uart/stm32_uart.c \
+ plat/st/common/stm32cubeprogrammer_uart.c
+endif
+
+ifeq (${STM32MP_USB_PROGRAMMER},1)
+#The DFU stack uses only one end point, reduce the USB stack footprint
+$(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U))
+BL2_SOURCES += drivers/st/usb/stm32mp1_usb.c \
+ drivers/usb/usb_device.c \
+ plat/st/common/stm32cubeprogrammer_usb.c \
+ plat/st/common/usb_dfu.c \
+ plat/st/stm32mp1/stm32mp1_usb_dfu.c
+endif
+
+BL2_SOURCES += drivers/st/ddr/stm32mp_ddr_test.c \
+ drivers/st/ddr/stm32mp_ram.c \
+ drivers/st/ddr/stm32mp1_ddr.c \
+ drivers/st/ddr/stm32mp1_ram.c
+
+BL2_SOURCES += common/desc_image_load.c \
+ plat/st/stm32mp1/plat_image_load.c
+
+BL2_SOURCES += lib/optee/optee_utils.c
+
+# Compilation rules
+.PHONY: check_dtc_version stm32image clean_stm32image check_boot_device
+.SUFFIXES:
+
+all: check_dtc_version stm32image ${STM32_TF_STM32}
+
+distclean realclean clean: clean_stm32image
+
+bl2: check_boot_device
+
+check_boot_device:
+ @if [ ${STM32MP_EMMC} != 1 ] && \
+ [ ${STM32MP_SDMMC} != 1 ] && \
+ [ ${STM32MP_RAW_NAND} != 1 ] && \
+ [ ${STM32MP_SPI_NAND} != 1 ] && \
+ [ ${STM32MP_SPI_NOR} != 1 ] && \
+ [ ${STM32MP_UART_PROGRAMMER} != 1 ] && \
+ [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \
+ echo "No boot device driver is enabled"; \
+ false; \
+ fi
+
+stm32image: ${STM32IMAGE}
+
+${STM32IMAGE}: ${STM32IMAGE_SRC}
+ ${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH}
+
+clean_stm32image:
+ ${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean
+
+check_dtc_version:
+ @if [ ${DTC_VERSION} -lt 10404 ]; then \
+ echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \
+ false; \
+ fi
+
+# Create DTB file for BL2
+${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs
+ @echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+ @echo '#include "${BL2_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts
+
+ifeq ($(AARCH32_SP),sp_min)
+# Create DTB file for BL32
+${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs
+ @echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+ @echo '#include "${BL32_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts
+endif
+
+${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2
+ @echo " AS stm32mp1.S"
+ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+ -DDTB_BIN_PATH=\"$<\" \
+ -c plat/st/stm32mp1/stm32mp1.S -o $@
+
+$(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,bl2))
+
+tf-a-%.elf: stm32mp1-%.o ${STM32_TF_LINKERFILE}
+ @echo " LDS $<"
+ ${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $<
+
+tf-a-%.bin: tf-a-%.elf
+ ${Q}${OC} -O binary $< $@
+ @echo
+ @echo "Built $@ successfully"
+ @echo
+
+tf-a-%.stm32: ${STM32IMAGE} tf-a-%.bin
+ @echo
+ @echo "Generate $@"
+ $(eval LOADADDR = $(shell cat $(@:.stm32=.map) | grep RAM | awk '{print $$2}'))
+ $(eval ENTRY = $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
+ ${Q}${STM32IMAGE} -s $(word 2,$^) -d $@ \
+ -l $(LOADADDR) -e ${ENTRY} \
+ -v ${STM32_TF_VERSION} \
+ -m ${STM32_HEADER_VERSION_MAJOR} \
+ -n ${STM32_HEADER_VERSION_MINOR} \
+ -b ${STM32_HEADER_BL2_BINARY_TYPE}
+ @echo
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
new file mode 100644
index 0000000..1fb44b4
--- /dev/null
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/bsec2_reg.h>
+
+#include <stm32mp1_smc.h>
+
+#include "bsec_svc.h"
+
+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
+ uint32_t *ret_otp_value)
+{
+ uint32_t result;
+ uint32_t tmp_data = 0U;
+
+ switch (x1) {
+ case STM32_SMC_READ_SHADOW:
+ result = bsec_read_otp(ret_otp_value, x2);
+ break;
+ case STM32_SMC_PROG_OTP:
+ *ret_otp_value = 0U;
+ result = bsec_program_otp(x3, x2);
+ break;
+ case STM32_SMC_WRITE_SHADOW:
+ *ret_otp_value = 0U;
+ result = bsec_write_otp(x3, x2);
+ break;
+ case STM32_SMC_READ_OTP:
+ *ret_otp_value = 0U;
+ result = bsec_read_otp(&tmp_data, x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_shadow_register(x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_read_otp(ret_otp_value, x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_write_otp(tmp_data, x2);
+ break;
+
+ default:
+ return STM32_SMC_INVALID_PARAMS;
+ }
+
+ return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED;
+}
diff --git a/plat/st/stm32mp1/services/bsec_svc.h b/plat/st/stm32mp1/services/bsec_svc.h
new file mode 100644
index 0000000..06752ef
--- /dev/null
+++ b/plat/st/stm32mp1/services/bsec_svc.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BSEC_SVC_H
+#define BSEC_SVC_H
+
+#include <stdint.h>
+
+/* version of this service */
+/* must be increase at each structure modification */
+#define BSEC_SERVICE_VERSION 0x01U
+
+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
+ uint32_t *ret_otp_value);
+
+#endif /* BSEC_SVC_H */
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
new file mode 100644
index 0000000..ed8a448
--- /dev/null
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/scmi-msg.h>
+#include <lib/psci/psci.h>
+#include <tools_share/uuid.h>
+
+#include <stm32mp1_smc.h>
+
+#include "bsec_svc.h"
+
+/* STM32 SiP Service UUID */
+DEFINE_SVC_UUID2(stm32_sip_svc_uid,
+ 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e,
+ 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14);
+
+/* Setup STM32MP1 Standard Services */
+static int32_t stm32mp1_svc_setup(void)
+{
+ /*
+ * PSCI is the only specification implemented as a Standard Service.
+ * Invoke PSCI setup from here.
+ */
+ return 0;
+}
+
+/*
+ * Top-level Standard Service SMC handler. This handler will in turn dispatch
+ * calls to PSCI SMC handler.
+ */
+static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, void *cookie,
+ void *handle, u_register_t flags)
+{
+ uint32_t ret1 = 0U, ret2 = 0U;
+ bool ret_uid = false, ret2_enabled = false;
+
+ switch (smc_fid) {
+ case STM32_SIP_SVC_CALL_COUNT:
+ ret1 = STM32_COMMON_SIP_NUM_CALLS;
+ break;
+
+ case STM32_SIP_SVC_UID:
+ /* Return UUID to the caller */
+ ret_uid = true;
+ break;
+
+ case STM32_SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ ret1 = STM32_SIP_SVC_VERSION_MAJOR;
+ ret2 = STM32_SIP_SVC_VERSION_MINOR;
+ ret2_enabled = true;
+ break;
+
+ case STM32_SMC_BSEC:
+ ret1 = bsec_main(x1, x2, x3, &ret2);
+ ret2_enabled = true;
+ break;
+
+ case STM32_SIP_SMC_SCMI_AGENT0:
+ scmi_smt_fastcall_smc_entry(0);
+ break;
+ case STM32_SIP_SMC_SCMI_AGENT1:
+ scmi_smt_fastcall_smc_entry(1);
+ break;
+
+ default:
+ WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
+ ret1 = STM32_SMC_NOT_SUPPORTED;
+ break;
+ }
+
+ if (ret_uid) {
+ SMC_UUID_RET(handle, stm32_sip_svc_uid);
+ }
+
+ if (ret2_enabled) {
+ SMC_RET2(handle, ret1, ret2);
+ }
+
+ SMC_RET1(handle, ret1);
+}
+
+/* Register Standard Service Calls as runtime service */
+DECLARE_RT_SVC(stm32mp1_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ stm32mp1_svc_setup,
+ stm32mp1_svc_smc_handler
+);
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
new file mode 100644
index 0000000..1d754d9
--- /dev/null
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq ($(STM32MP13),1)
+$(error "SP_min is not supported on STM32MP13 platform")
+endif
+
+SP_MIN_WITH_SECURE_FIQ := 1
+
+override ENABLE_PIE := 1
+BL32_CFLAGS += -fpie -DENABLE_PIE
+BL32_LDFLAGS += $(PIE_LDFLAGS)
+
+BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES
+
+BL32_SOURCES += drivers/st/etzpc/etzpc.c \
+ plat/common/aarch32/platform_mp_stack.S \
+ plat/st/stm32mp1/sp_min/sp_min_setup.c \
+ plat/st/stm32mp1/stm32mp1_pm.c \
+ plat/st/stm32mp1/stm32mp1_shared_resources.c \
+ plat/st/stm32mp1/stm32mp1_topology.c
+
+# FDT wrappers
+include common/fdt_wrappers.mk
+BL32_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+# Generic GIC v2
+include drivers/arm/gic/v2/gicv2.mk
+
+BL32_SOURCES += ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/st/stm32mp1/stm32mp1_gic.c
+
+# Generic PSCI
+BL32_SOURCES += plat/common/plat_psci_common.c
+
+# SCMI server drivers
+BL32_SOURCES += drivers/scmi-msg/base.c \
+ drivers/scmi-msg/clock.c \
+ drivers/scmi-msg/entry.c \
+ drivers/scmi-msg/reset_domain.c \
+ drivers/scmi-msg/smt.c
+
+# stm32mp1 specific services
+BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \
+ plat/st/stm32mp1/services/stm32mp1_svc_setup.c \
+ plat/st/stm32mp1/stm32mp1_scmi.c
+
+# Arm Archtecture services
+BL32_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
new file mode 100644
index 0000000..50b0794
--- /dev/null
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/tzc400.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <platform_sp_min.h>
+
+/******************************************************************************
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL32 from BL2.
+ ******************************************************************************/
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Interrupt handler for FIQ (secure IRQ)
+ ******************************************************************************/
+void sp_min_plat_fiq_handler(uint32_t id)
+{
+ (void)plat_crash_console_init();
+
+ switch (id & INT_ID_MASK) {
+ case STM32MP1_IRQ_TZC400:
+ tzc400_init(STM32MP1_TZC_BASE);
+ (void)tzc400_it_handler();
+ panic();
+ break;
+ case STM32MP1_IRQ_AXIERRIRQ:
+ ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n");
+ panic();
+ break;
+ default:
+ ERROR("SECURE IT handler not define for it : %u\n", id);
+ break;
+ }
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = &bl33_image_ep_info;
+
+ if (next_image_info->pc == 0U) {
+ return NULL;
+ }
+
+ return next_image_info;
+}
+
+CASSERT((STM32MP_SEC_SYSRAM_BASE == STM32MP_SYSRAM_BASE) &&
+ ((STM32MP_SEC_SYSRAM_BASE + STM32MP_SEC_SYSRAM_SIZE) <=
+ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+ assert_secure_sysram_fits_at_begining_of_sysram);
+
+#ifdef STM32MP_NS_SYSRAM_BASE
+CASSERT((STM32MP_NS_SYSRAM_BASE >= STM32MP_SEC_SYSRAM_BASE) &&
+ ((STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE) ==
+ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+ assert_non_secure_sysram_fits_at_end_of_sysram);
+
+CASSERT((STM32MP_NS_SYSRAM_BASE & (PAGE_SIZE_4KB - U(1))) == 0U,
+ assert_non_secure_sysram_base_is_4kbyte_aligned);
+
+#define TZMA1_SECURE_RANGE \
+ (((STM32MP_NS_SYSRAM_BASE - STM32MP_SYSRAM_BASE) >> FOUR_KB_SHIFT) - 1U)
+#else
+#define TZMA1_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
+#endif /* STM32MP_NS_SYSRAM_BASE */
+#define TZMA0_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
+
+static void stm32mp1_etzpc_early_setup(void)
+{
+ if (etzpc_init() != 0) {
+ panic();
+ }
+
+ etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
+ etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
+}
+
+/*******************************************************************************
+ * Perform any BL32 specific platform actions.
+ ******************************************************************************/
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
+ uintptr_t dt_addr = arg1;
+
+ stm32mp_setup_early_console();
+
+ /* Imprecise aborts can be masked in NonSecure */
+ write_scr(read_scr() | SCR_AW_BIT);
+
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+
+ configure_mmu();
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params != NULL) {
+ if (bl_params->image_id == BL33_IMAGE_ID) {
+ bl33_image_ep_info = *bl_params->ep_info;
+ /*
+ * Check if hw_configuration is given to BL32 and
+ * share it to BL33.
+ */
+ if (arg2 != 0U) {
+ bl33_image_ep_info.args.arg0 = 0U;
+ bl33_image_ep_info.args.arg1 = 0U;
+ bl33_image_ep_info.args.arg2 = arg2;
+ }
+
+ break;
+ }
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (dt_open_and_check(dt_addr) < 0) {
+ panic();
+ }
+
+ if (bsec_probe() != 0) {
+ panic();
+ }
+
+ if (stm32mp1_clk_probe() < 0) {
+ panic();
+ }
+
+ (void)stm32mp_uart_console_setup();
+
+ stm32mp1_etzpc_early_setup();
+}
+
+/*******************************************************************************
+ * Initialize the MMU, security and the GIC.
+ ******************************************************************************/
+void sp_min_platform_setup(void)
+{
+ generic_delay_timer_init();
+
+ stm32mp1_gic_init();
+
+ if (stm32_iwdg_init() < 0) {
+ panic();
+ }
+
+ stm32mp_lock_periph_registering();
+
+ stm32mp1_init_scmi_server();
+}
+
+void sp_min_plat_arch_setup(void)
+{
+}
diff --git a/plat/st/stm32mp1/stm32mp1.S b/plat/st/stm32mp1/stm32mp1.S
new file mode 100644
index 0000000..aee4f0e
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1.S
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+.section .bl2_image
+.incbin BL2_BIN_PATH
+
+.section .dtb_image
+.incbin DTB_BIN_PATH
diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S
new file mode 100644
index 0000000..1be8219
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1.ld.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_LD_S
+#define STM32MP1_LD_S
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <platform_def.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+
+ENTRY(__BL2_IMAGE_START__)
+
+MEMORY {
+ HEADER (rw) : ORIGIN = 0x00000000, LENGTH = STM32MP_HEADER_RESERVED_SIZE
+ RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE
+}
+
+SECTIONS
+{
+ /*
+ * TF mapping must conform to ROM code specification.
+ */
+ .header : {
+ __HEADER_START__ = .;
+ KEEP(*(.header))
+ . = ALIGN(4);
+ __HEADER_END__ = .;
+ } >HEADER
+
+ . = STM32MP_BINARY_BASE;
+ .data . : {
+ . = ALIGN(PAGE_SIZE);
+ __DATA_START__ = .;
+ *(.data*)
+
+ /*
+ * dtb.
+ * The strongest and only alignment contraint is MMU 4K page.
+ * Indeed as images below will be removed, 4K pages will be re-used.
+ */
+ . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE );
+ __DTB_IMAGE_START__ = .;
+ *(.dtb_image*)
+ __DTB_IMAGE_END__ = .;
+
+ /*
+ * bl2.
+ * The strongest and only alignment contraint is MMU 4K page.
+ * Indeed as images below will be removed, 4K pages will be re-used.
+ */
+#if SEPARATE_CODE_AND_RODATA
+ . = ( STM32MP_BL2_RO_BASE - STM32MP_BINARY_BASE );
+#else
+ . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE );
+#endif
+ __BL2_IMAGE_START__ = .;
+ *(.bl2_image*)
+ __BL2_IMAGE_END__ = .;
+
+ __DATA_END__ = .;
+ } >RAM
+
+ __TF_END__ = .;
+
+}
+#endif /* STM32MP1_LD_S */
diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c
new file mode 100644
index 0000000..3a8a27a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_boot_device.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/nand.h>
+#include <drivers/raw_nand.h>
+#include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
+#if STM32MP13
+void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size)
+{
+ assert(buffer_addr != NULL);
+ assert(buf_size != NULL);
+
+ *buffer_addr = (void *)STM32MP_MTD_BUFFER;
+ *buf_size = PLATFORM_MTD_MAX_PAGE_SIZE;
+}
+#endif
+
+static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc)
+{
+ uint32_t nand_param;
+ uint32_t nand2_param __maybe_unused;
+
+ /* Check if NAND parameters are stored in OTP */
+ if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) {
+ ERROR("BSEC: NAND_OTP Error\n");
+ return -EACCES;
+ }
+
+ if (nand_param == 0U) {
+#if STM32MP13
+ if (is_slc) {
+ return 0;
+ }
+#endif
+#if STM32MP15
+ return 0;
+#endif
+ }
+
+ if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) {
+#if STM32MP13
+ if (is_slc) {
+ goto ecc;
+ }
+#endif
+#if STM32MP15
+ goto ecc;
+#endif
+ }
+
+#if STM32MP13
+ if (stm32_get_otp_value(NAND2_OTP, &nand2_param) != 0) {
+ ERROR("BSEC: NAND_OTP Error\n");
+ return -EACCES;
+ }
+
+ /* Check OTP configuration for this device */
+ if ((((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND1_SNAND_NAND2) && !is_slc) ||
+ (((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND2_SNAND_NAND1) && is_slc)) {
+ nand_param = nand2_param << (NAND_PAGE_SIZE_SHIFT - NAND2_PAGE_SIZE_SHIFT);
+ }
+#endif
+
+ /* NAND parameter shall be read from OTP */
+ if ((nand_param & NAND_WIDTH_MASK) != 0U) {
+ nand_dev->buswidth = NAND_BUS_WIDTH_16;
+ } else {
+ nand_dev->buswidth = NAND_BUS_WIDTH_8;
+ }
+
+ switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) {
+ case NAND_PAGE_SIZE_2K:
+ nand_dev->page_size = 0x800U;
+ break;
+
+ case NAND_PAGE_SIZE_4K:
+ nand_dev->page_size = 0x1000U;
+ break;
+
+ case NAND_PAGE_SIZE_8K:
+ nand_dev->page_size = 0x2000U;
+ break;
+
+ default:
+ ERROR("Cannot read NAND page size\n");
+ return -EINVAL;
+ }
+
+ switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) {
+ case NAND_BLOCK_SIZE_64_PAGES:
+ nand_dev->block_size = 64U * nand_dev->page_size;
+ break;
+
+ case NAND_BLOCK_SIZE_128_PAGES:
+ nand_dev->block_size = 128U * nand_dev->page_size;
+ break;
+
+ case NAND_BLOCK_SIZE_256_PAGES:
+ nand_dev->block_size = 256U * nand_dev->page_size;
+ break;
+
+ default:
+ ERROR("Cannot read NAND block size\n");
+ return -EINVAL;
+ }
+
+ nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >>
+ NAND_BLOCK_NB_SHIFT) *
+ NAND_BLOCK_NB_UNIT * nand_dev->block_size;
+
+ecc:
+ if (is_slc) {
+ switch ((nand_param & NAND_ECC_BIT_NB_MASK) >>
+ NAND_ECC_BIT_NB_SHIFT) {
+ case NAND_ECC_BIT_NB_1_BITS:
+ nand_dev->ecc.max_bit_corr = 1U;
+ break;
+
+ case NAND_ECC_BIT_NB_4_BITS:
+ nand_dev->ecc.max_bit_corr = 4U;
+ break;
+
+ case NAND_ECC_BIT_NB_8_BITS:
+ nand_dev->ecc.max_bit_corr = 8U;
+ break;
+
+ case NAND_ECC_ON_DIE:
+ nand_dev->ecc.mode = NAND_ECC_ONDIE;
+ break;
+
+ default:
+ if (nand_dev->ecc.max_bit_corr == 0U) {
+ ERROR("No valid eccbit number\n");
+ return -EINVAL;
+ }
+ }
+ } else {
+ /* Selected multiple plane NAND */
+ if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) {
+ nand_dev->nb_planes = 2U;
+ } else {
+ nand_dev->nb_planes = 1U;
+ }
+ }
+
+ VERBOSE("OTP: Block %u Page %u Size %llu\n", nand_dev->block_size,
+ nand_dev->page_size, nand_dev->size);
+
+ return 0;
+}
+#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */
+
+#if STM32MP_RAW_NAND
+int plat_get_raw_nand_data(struct rawnand_device *device)
+{
+ device->nand_dev->ecc.mode = NAND_ECC_HW;
+ device->nand_dev->ecc.size = SZ_512;
+
+ return get_data_from_otp(device->nand_dev, true);
+}
+#endif
+
+#if STM32MP_SPI_NAND
+int plat_get_spi_nand_data(struct spinand_device *device)
+{
+ zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op));
+ device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X;
+ device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->spi_read_cache_op.addr.nbytes = 2U;
+ device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->spi_read_cache_op.dummy.nbytes = 1U;
+ device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
+ device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN;
+
+ return get_data_from_otp(device->nand_dev, false);
+}
+#endif
+
+#if STM32MP_SPI_NOR
+int plat_get_nor_data(struct nor_device *device)
+{
+ device->size = SZ_64M;
+
+ zeromem(&device->read_op, sizeof(struct spi_mem_op));
+ device->read_op.cmd.opcode = SPI_NOR_OP_READ_1_1_4;
+ device->read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->read_op.addr.nbytes = 3U;
+ device->read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->read_op.dummy.nbytes = 1U;
+ device->read_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->read_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
+ device->read_op.data.dir = SPI_MEM_DATA_IN;
+
+ return 0;
+}
+#endif
diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
new file mode 100644
index 0000000..08e332a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/bsec2_reg.h>
+#include <drivers/st/stm32mp1_rcc.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+#include <stm32mp1_dbgmcu.h>
+
+#define DBGMCU_IDC U(0x00)
+
+#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
+#define DBGMCU_IDC_REV_ID_SHIFT 16
+
+static int stm32mp1_dbgmcu_init(void)
+{
+ if ((bsec_read_debug_conf() & BSEC_DBGSWGEN) == 0U) {
+ INFO("Software access to all debug components is disabled\n");
+ return -1;
+ }
+
+ mmio_setbits_32(RCC_BASE + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
+
+ return 0;
+}
+
+/*
+ * @brief Get silicon revision from DBGMCU registers.
+ * @param chip_version: pointer to the read value.
+ * @retval 0 on success, negative value on failure.
+ */
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version)
+{
+ assert(chip_version != NULL);
+
+ if (stm32mp1_dbgmcu_init() != 0) {
+ return -EPERM;
+ }
+
+ *chip_version = (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
+ DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
+
+ return 0;
+}
+
+/*
+ * @brief Get device ID from DBGMCU registers.
+ * @param chip_dev_id: pointer to the read value.
+ * @retval 0 on success, negative value on failure.
+ */
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id)
+{
+ assert(chip_dev_id != NULL);
+
+ if (stm32mp1_dbgmcu_init() != 0) {
+ return -EPERM;
+ }
+
+ *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
+ DBGMCU_IDC_DEV_ID_MASK;
+
+ return 0;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
new file mode 100644
index 0000000..f0d8526
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -0,0 +1,669 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_DEF_H
+#define STM32MP1_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/st/stm32mp1_rcc.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+#ifndef __ASSEMBLER__
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32mp1_clk.h>
+
+#include <boot_api.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp1_dbgmcu.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_shared_resources.h>
+#endif
+
+#include "stm32mp1_fip_def.h"
+
+/*******************************************************************************
+ * CHIP ID
+ ******************************************************************************/
+#if STM32MP13
+#define STM32MP1_CHIP_ID U(0x501)
+
+#define STM32MP135C_PART_NB U(0x05010000)
+#define STM32MP135A_PART_NB U(0x05010001)
+#define STM32MP133C_PART_NB U(0x050100C0)
+#define STM32MP133A_PART_NB U(0x050100C1)
+#define STM32MP131C_PART_NB U(0x050106C8)
+#define STM32MP131A_PART_NB U(0x050106C9)
+#define STM32MP135F_PART_NB U(0x05010800)
+#define STM32MP135D_PART_NB U(0x05010801)
+#define STM32MP133F_PART_NB U(0x050108C0)
+#define STM32MP133D_PART_NB U(0x050108C1)
+#define STM32MP131F_PART_NB U(0x05010EC8)
+#define STM32MP131D_PART_NB U(0x05010EC9)
+#endif
+#if STM32MP15
+#define STM32MP1_CHIP_ID U(0x500)
+
+#define STM32MP157C_PART_NB U(0x05000000)
+#define STM32MP157A_PART_NB U(0x05000001)
+#define STM32MP153C_PART_NB U(0x05000024)
+#define STM32MP153A_PART_NB U(0x05000025)
+#define STM32MP151C_PART_NB U(0x0500002E)
+#define STM32MP151A_PART_NB U(0x0500002F)
+#define STM32MP157F_PART_NB U(0x05000080)
+#define STM32MP157D_PART_NB U(0x05000081)
+#define STM32MP153F_PART_NB U(0x050000A4)
+#define STM32MP153D_PART_NB U(0x050000A5)
+#define STM32MP151F_PART_NB U(0x050000AE)
+#define STM32MP151D_PART_NB U(0x050000AF)
+#endif
+
+#define STM32MP1_REV_B U(0x2000)
+#if STM32MP13
+#define STM32MP1_REV_Y U(0x1003)
+#define STM32MP1_REV_Z U(0x1001)
+#endif
+#if STM32MP15
+#define STM32MP1_REV_Z U(0x2001)
+#endif
+
+/*******************************************************************************
+ * PACKAGE ID
+ ******************************************************************************/
+#if STM32MP15
+#define PKG_AA_LFBGA448 U(4)
+#define PKG_AB_LFBGA354 U(3)
+#define PKG_AC_TFBGA361 U(2)
+#define PKG_AD_TFBGA257 U(1)
+#endif
+
+/*******************************************************************************
+ * STM32MP1 memory map related constants
+ ******************************************************************************/
+#define STM32MP_ROM_BASE U(0x00000000)
+#define STM32MP_ROM_SIZE U(0x00020000)
+#define STM32MP_ROM_SIZE_2MB_ALIGNED U(0x00200000)
+
+#if STM32MP13
+#define STM32MP_SYSRAM_BASE U(0x2FFE0000)
+#define STM32MP_SYSRAM_SIZE U(0x00020000)
+#define SRAM1_BASE U(0x30000000)
+#define SRAM1_SIZE U(0x00004000)
+#define SRAM2_BASE U(0x30004000)
+#define SRAM2_SIZE U(0x00002000)
+#define SRAM3_BASE U(0x30006000)
+#define SRAM3_SIZE U(0x00002000)
+#define SRAMS_BASE SRAM1_BASE
+#define SRAMS_SIZE_2MB_ALIGNED U(0x00200000)
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_SYSRAM_BASE U(0x2FFC0000)
+#define STM32MP_SYSRAM_SIZE U(0x00040000)
+#endif /* STM32MP15 */
+
+#define STM32MP_NS_SYSRAM_SIZE PAGE_SIZE
+#define STM32MP_NS_SYSRAM_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ STM32MP_NS_SYSRAM_SIZE)
+
+#define STM32MP_SCMI_NS_SHM_BASE STM32MP_NS_SYSRAM_BASE
+#define STM32MP_SCMI_NS_SHM_SIZE STM32MP_NS_SYSRAM_SIZE
+
+#define STM32MP_SEC_SYSRAM_BASE STM32MP_SYSRAM_BASE
+#define STM32MP_SEC_SYSRAM_SIZE (STM32MP_SYSRAM_SIZE - \
+ STM32MP_NS_SYSRAM_SIZE)
+
+/* DDR configuration */
+#define STM32MP_DDR_BASE U(0xC0000000)
+#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */
+
+/* DDR power initializations */
+#ifndef __ASSEMBLER__
+enum ddr_type {
+ STM32MP_DDR3,
+ STM32MP_LPDDR2,
+ STM32MP_LPDDR3
+};
+#endif
+
+/* Section used inside TF binaries */
+#if STM32MP13
+/* 512 Octets reserved for header */
+#define STM32MP_HEADER_RESERVED_SIZE U(0x200)
+
+#define STM32MP_BINARY_BASE STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_BINARY_SIZE STM32MP_SEC_SYSRAM_SIZE
+#endif
+#if STM32MP15
+#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */
+/* 256 Octets reserved for header */
+#define STM32MP_HEADER_SIZE U(0x00000100)
+/* round_up(STM32MP_PARAM_LOAD_SIZE + STM32MP_HEADER_SIZE, PAGE_SIZE) */
+#define STM32MP_HEADER_RESERVED_SIZE U(0x3000)
+
+#define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \
+ STM32MP_PARAM_LOAD_SIZE + \
+ STM32MP_HEADER_SIZE)
+
+#define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \
+ (STM32MP_PARAM_LOAD_SIZE + \
+ STM32MP_HEADER_SIZE))
+#endif
+
+/* BL2 and BL32/sp_min require finer granularity tables */
+#if defined(IMAGE_BL2)
+#define MAX_XLAT_TABLES U(2) /* 8 KB for mapping */
+#endif
+
+#if defined(IMAGE_BL32)
+#define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */
+#endif
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL2)
+ #if STM32MP_USB_PROGRAMMER
+ #define MAX_MMAP_REGIONS 8
+ #else
+ #define MAX_MMAP_REGIONS 7
+ #endif
+#endif
+
+#if STM32MP13
+#define STM32MP_BL33_BASE STM32MP_DDR_BASE
+#endif
+#if STM32MP15
+#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000))
+#endif
+#define STM32MP_BL33_MAX_SIZE U(0x400000)
+
+/* Define maximum page size for NAND devices */
+#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000)
+
+/* Define location for the MTD scratch buffer */
+#if STM32MP13
+#define STM32MP_MTD_BUFFER (SRAM1_BASE + \
+ SRAM1_SIZE - \
+ PLATFORM_MTD_MAX_PAGE_SIZE)
+#endif
+/*******************************************************************************
+ * STM32MP1 device/io map related constants (used for MMU)
+ ******************************************************************************/
+#define STM32MP1_DEVICE1_BASE U(0x40000000)
+#define STM32MP1_DEVICE1_SIZE U(0x40000000)
+
+#define STM32MP1_DEVICE2_BASE U(0x80000000)
+#define STM32MP1_DEVICE2_SIZE U(0x40000000)
+
+/*******************************************************************************
+ * STM32MP1 RCC
+ ******************************************************************************/
+#define RCC_BASE U(0x50000000)
+
+/*******************************************************************************
+ * STM32MP1 PWR
+ ******************************************************************************/
+#define PWR_BASE U(0x50001000)
+
+/*******************************************************************************
+ * STM32MP1 GPIO
+ ******************************************************************************/
+#define GPIOA_BASE U(0x50002000)
+#define GPIOB_BASE U(0x50003000)
+#define GPIOC_BASE U(0x50004000)
+#define GPIOD_BASE U(0x50005000)
+#define GPIOE_BASE U(0x50006000)
+#define GPIOF_BASE U(0x50007000)
+#define GPIOG_BASE U(0x50008000)
+#define GPIOH_BASE U(0x50009000)
+#define GPIOI_BASE U(0x5000A000)
+#if STM32MP15
+#define GPIOJ_BASE U(0x5000B000)
+#define GPIOK_BASE U(0x5000C000)
+#define GPIOZ_BASE U(0x54004000)
+#endif
+#define GPIO_BANK_OFFSET U(0x1000)
+
+/* Bank IDs used in GPIO driver API */
+#define GPIO_BANK_A U(0)
+#define GPIO_BANK_B U(1)
+#define GPIO_BANK_C U(2)
+#define GPIO_BANK_D U(3)
+#define GPIO_BANK_E U(4)
+#define GPIO_BANK_F U(5)
+#define GPIO_BANK_G U(6)
+#define GPIO_BANK_H U(7)
+#define GPIO_BANK_I U(8)
+#if STM32MP15
+#define GPIO_BANK_J U(9)
+#define GPIO_BANK_K U(10)
+#define GPIO_BANK_Z U(25)
+
+#define STM32MP_GPIOZ_PIN_MAX_COUNT 8
+#endif
+
+/*******************************************************************************
+ * STM32MP1 UART
+ ******************************************************************************/
+#if STM32MP13
+#define USART1_BASE U(0x4C000000)
+#define USART2_BASE U(0x4C001000)
+#endif
+#if STM32MP15
+#define USART1_BASE U(0x5C000000)
+#define USART2_BASE U(0x4000E000)
+#endif
+#define USART3_BASE U(0x4000F000)
+#define UART4_BASE U(0x40010000)
+#define UART5_BASE U(0x40011000)
+#define USART6_BASE U(0x44003000)
+#define UART7_BASE U(0x40018000)
+#define UART8_BASE U(0x40019000)
+
+/* For UART crash console */
+#define STM32MP_DEBUG_USART_BASE UART4_BASE
+#if STM32MP13
+/* UART4 on HSI@64MHz, TX on GPIOF12 Alternate 8 (Disco board) */
+#define STM32MP_DEBUG_USART_CLK_FRQ 64000000
+#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOD_BASE
+#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_S_AHB4ENSETR
+#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_S_AHB4ENSETR_GPIODEN
+#define DEBUG_UART_TX_GPIO_PORT 6
+#define DEBUG_UART_TX_GPIO_ALTERNATE 8
+#define DEBUG_UART_TX_CLKSRC_REG RCC_UART4CKSELR
+#define DEBUG_UART_TX_CLKSRC RCC_UART4CKSELR_HSI
+#endif /* STM32MP13 */
+#if STM32MP15
+/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */
+#define STM32MP_DEBUG_USART_CLK_FRQ 64000000
+#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE
+#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR
+#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN
+#define DEBUG_UART_TX_GPIO_PORT 11
+#define DEBUG_UART_TX_GPIO_ALTERNATE 6
+#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR
+#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI
+#endif /* STM32MP15 */
+#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR
+#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN
+#define DEBUG_UART_RST_REG RCC_APB1RSTSETR
+#define DEBUG_UART_RST_BIT RCC_APB1RSTSETR_UART4RST
+
+/*******************************************************************************
+ * STM32MP1 ETZPC
+ ******************************************************************************/
+#define STM32MP1_ETZPC_BASE U(0x5C007000)
+
+/* ETZPC TZMA IDs */
+#define STM32MP1_ETZPC_TZMA_ROM U(0)
+#define STM32MP1_ETZPC_TZMA_SYSRAM U(1)
+
+#define STM32MP1_ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0)
+
+/* ETZPC DECPROT IDs */
+#define STM32MP1_ETZPC_STGENC_ID 0
+#define STM32MP1_ETZPC_BKPSRAM_ID 1
+#define STM32MP1_ETZPC_IWDG1_ID 2
+#define STM32MP1_ETZPC_USART1_ID 3
+#define STM32MP1_ETZPC_SPI6_ID 4
+#define STM32MP1_ETZPC_I2C4_ID 5
+#define STM32MP1_ETZPC_RNG1_ID 7
+#define STM32MP1_ETZPC_HASH1_ID 8
+#define STM32MP1_ETZPC_CRYP1_ID 9
+#define STM32MP1_ETZPC_DDRCTRL_ID 10
+#define STM32MP1_ETZPC_DDRPHYC_ID 11
+#define STM32MP1_ETZPC_I2C6_ID 12
+#define STM32MP1_ETZPC_SEC_ID_LIMIT 13
+
+#define STM32MP1_ETZPC_TIM2_ID 16
+#define STM32MP1_ETZPC_TIM3_ID 17
+#define STM32MP1_ETZPC_TIM4_ID 18
+#define STM32MP1_ETZPC_TIM5_ID 19
+#define STM32MP1_ETZPC_TIM6_ID 20
+#define STM32MP1_ETZPC_TIM7_ID 21
+#define STM32MP1_ETZPC_TIM12_ID 22
+#define STM32MP1_ETZPC_TIM13_ID 23
+#define STM32MP1_ETZPC_TIM14_ID 24
+#define STM32MP1_ETZPC_LPTIM1_ID 25
+#define STM32MP1_ETZPC_WWDG1_ID 26
+#define STM32MP1_ETZPC_SPI2_ID 27
+#define STM32MP1_ETZPC_SPI3_ID 28
+#define STM32MP1_ETZPC_SPDIFRX_ID 29
+#define STM32MP1_ETZPC_USART2_ID 30
+#define STM32MP1_ETZPC_USART3_ID 31
+#define STM32MP1_ETZPC_UART4_ID 32
+#define STM32MP1_ETZPC_UART5_ID 33
+#define STM32MP1_ETZPC_I2C1_ID 34
+#define STM32MP1_ETZPC_I2C2_ID 35
+#define STM32MP1_ETZPC_I2C3_ID 36
+#define STM32MP1_ETZPC_I2C5_ID 37
+#define STM32MP1_ETZPC_CEC_ID 38
+#define STM32MP1_ETZPC_DAC_ID 39
+#define STM32MP1_ETZPC_UART7_ID 40
+#define STM32MP1_ETZPC_UART8_ID 41
+#define STM32MP1_ETZPC_MDIOS_ID 44
+#define STM32MP1_ETZPC_TIM1_ID 48
+#define STM32MP1_ETZPC_TIM8_ID 49
+#define STM32MP1_ETZPC_USART6_ID 51
+#define STM32MP1_ETZPC_SPI1_ID 52
+#define STM32MP1_ETZPC_SPI4_ID 53
+#define STM32MP1_ETZPC_TIM15_ID 54
+#define STM32MP1_ETZPC_TIM16_ID 55
+#define STM32MP1_ETZPC_TIM17_ID 56
+#define STM32MP1_ETZPC_SPI5_ID 57
+#define STM32MP1_ETZPC_SAI1_ID 58
+#define STM32MP1_ETZPC_SAI2_ID 59
+#define STM32MP1_ETZPC_SAI3_ID 60
+#define STM32MP1_ETZPC_DFSDM_ID 61
+#define STM32MP1_ETZPC_TT_FDCAN_ID 62
+#define STM32MP1_ETZPC_LPTIM2_ID 64
+#define STM32MP1_ETZPC_LPTIM3_ID 65
+#define STM32MP1_ETZPC_LPTIM4_ID 66
+#define STM32MP1_ETZPC_LPTIM5_ID 67
+#define STM32MP1_ETZPC_SAI4_ID 68
+#define STM32MP1_ETZPC_VREFBUF_ID 69
+#define STM32MP1_ETZPC_DCMI_ID 70
+#define STM32MP1_ETZPC_CRC2_ID 71
+#define STM32MP1_ETZPC_ADC_ID 72
+#define STM32MP1_ETZPC_HASH2_ID 73
+#define STM32MP1_ETZPC_RNG2_ID 74
+#define STM32MP1_ETZPC_CRYP2_ID 75
+#define STM32MP1_ETZPC_SRAM1_ID 80
+#define STM32MP1_ETZPC_SRAM2_ID 81
+#define STM32MP1_ETZPC_SRAM3_ID 82
+#define STM32MP1_ETZPC_SRAM4_ID 83
+#define STM32MP1_ETZPC_RETRAM_ID 84
+#define STM32MP1_ETZPC_OTG_ID 85
+#define STM32MP1_ETZPC_SDMMC3_ID 86
+#define STM32MP1_ETZPC_DLYBSD3_ID 87
+#define STM32MP1_ETZPC_DMA1_ID 88
+#define STM32MP1_ETZPC_DMA2_ID 89
+#define STM32MP1_ETZPC_DMAMUX_ID 90
+#define STM32MP1_ETZPC_FMC_ID 91
+#define STM32MP1_ETZPC_QSPI_ID 92
+#define STM32MP1_ETZPC_DLYBQ_ID 93
+#define STM32MP1_ETZPC_ETH_ID 94
+#define STM32MP1_ETZPC_RSV_ID 95
+
+#define STM32MP_ETZPC_MAX_ID 96
+
+/*******************************************************************************
+ * STM32MP1 TZC (TZ400)
+ ******************************************************************************/
+#define STM32MP1_TZC_BASE U(0x5C006000)
+
+#if STM32MP13
+#define STM32MP1_FILTER_BIT_ALL TZC_400_REGION_ATTR_FILTER_BIT(0)
+#endif
+#if STM32MP15
+#define STM32MP1_FILTER_BIT_ALL (TZC_400_REGION_ATTR_FILTER_BIT(0) | \
+ TZC_400_REGION_ATTR_FILTER_BIT(1))
+#endif
+
+/*******************************************************************************
+ * STM32MP1 SDMMC
+ ******************************************************************************/
+#define STM32MP_SDMMC1_BASE U(0x58005000)
+#define STM32MP_SDMMC2_BASE U(0x58007000)
+#define STM32MP_SDMMC3_BASE U(0x48004000)
+
+#define STM32MP_MMC_INIT_FREQ U(400000) /*400 KHz*/
+#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ U(25000000) /*25 MHz*/
+#define STM32MP_SD_HIGH_SPEED_MAX_FREQ U(50000000) /*50 MHz*/
+#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ U(26000000) /*26 MHz*/
+#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ U(52000000) /*52 MHz*/
+
+/*******************************************************************************
+ * STM32MP1 BSEC / OTP
+ ******************************************************************************/
+#define STM32MP1_OTP_MAX_ID 0x5FU
+#define STM32MP1_UPPER_OTP_START 0x20U
+
+#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U)
+
+/* OTP labels */
+#define CFG0_OTP "cfg0_otp"
+#define PART_NUMBER_OTP "part_number_otp"
+#if STM32MP15
+#define PACKAGE_OTP "package_otp"
+#endif
+#define HW2_OTP "hw2_otp"
+#if STM32MP13
+#define NAND_OTP "cfg9_otp"
+#define NAND2_OTP "cfg10_otp"
+#endif
+#if STM32MP15
+#define NAND_OTP "nand_otp"
+#endif
+#define MONOTONIC_OTP "monotonic_otp"
+#define UID_OTP "uid_otp"
+#define PKH_OTP "pkh_otp"
+#define ENCKEY_OTP "enckey_otp"
+#define BOARD_ID_OTP "board_id"
+
+/* OTP mask */
+/* CFG0 */
+#if STM32MP13
+#define CFG0_OTP_MODE_MASK GENMASK_32(9, 0)
+#define CFG0_OTP_MODE_SHIFT 0
+#define CFG0_OPEN_DEVICE 0x17U
+#define CFG0_CLOSED_DEVICE 0x3FU
+#define CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN 0x17FU
+#define CFG0_CLOSED_DEVICE_NO_JTAG 0x3FFU
+#endif
+#if STM32MP15
+#define CFG0_CLOSED_DEVICE BIT(6)
+#endif
+
+/* PART NUMBER */
+#if STM32MP13
+#define PART_NUMBER_OTP_PART_MASK GENMASK_32(11, 0)
+#endif
+#if STM32MP15
+#define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0)
+#endif
+#define PART_NUMBER_OTP_PART_SHIFT 0
+
+/* PACKAGE */
+#if STM32MP15
+#define PACKAGE_OTP_PKG_MASK GENMASK_32(29, 27)
+#define PACKAGE_OTP_PKG_SHIFT 27
+#endif
+
+/* IWDG OTP */
+#define HW2_OTP_IWDG_HW_POS U(3)
+#define HW2_OTP_IWDG_FZ_STOP_POS U(5)
+#define HW2_OTP_IWDG_FZ_STANDBY_POS U(7)
+
+/* HW2 OTP */
+#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13)
+
+/* NAND OTP */
+/* NAND parameter storage flag */
+#define NAND_PARAM_STORED_IN_OTP BIT(31)
+
+/* NAND page size in bytes */
+#define NAND_PAGE_SIZE_MASK GENMASK_32(30, 29)
+#define NAND_PAGE_SIZE_SHIFT 29
+#define NAND_PAGE_SIZE_2K U(0)
+#define NAND_PAGE_SIZE_4K U(1)
+#define NAND_PAGE_SIZE_8K U(2)
+
+/* NAND block size in pages */
+#define NAND_BLOCK_SIZE_MASK GENMASK_32(28, 27)
+#define NAND_BLOCK_SIZE_SHIFT 27
+#define NAND_BLOCK_SIZE_64_PAGES U(0)
+#define NAND_BLOCK_SIZE_128_PAGES U(1)
+#define NAND_BLOCK_SIZE_256_PAGES U(2)
+
+/* NAND number of block (in unit of 256 blocks) */
+#define NAND_BLOCK_NB_MASK GENMASK_32(26, 19)
+#define NAND_BLOCK_NB_SHIFT 19
+#define NAND_BLOCK_NB_UNIT U(256)
+
+/* NAND bus width in bits */
+#define NAND_WIDTH_MASK BIT(18)
+#define NAND_WIDTH_SHIFT 18
+
+/* NAND number of ECC bits per 512 bytes */
+#define NAND_ECC_BIT_NB_MASK GENMASK_32(17, 15)
+#define NAND_ECC_BIT_NB_SHIFT 15
+#define NAND_ECC_BIT_NB_UNSET U(0)
+#define NAND_ECC_BIT_NB_1_BITS U(1)
+#define NAND_ECC_BIT_NB_4_BITS U(2)
+#define NAND_ECC_BIT_NB_8_BITS U(3)
+#define NAND_ECC_ON_DIE U(4)
+
+/* NAND number of planes */
+#define NAND_PLANE_BIT_NB_MASK BIT(14)
+
+/* NAND2 OTP */
+#define NAND2_PAGE_SIZE_SHIFT 16
+
+/* NAND2 config distribution */
+#define NAND2_CONFIG_DISTRIB BIT(0)
+#define NAND2_PNAND_NAND2_SNAND_NAND1 U(0)
+#define NAND2_PNAND_NAND1_SNAND_NAND2 U(1)
+
+/* MONOTONIC OTP */
+#define MAX_MONOTONIC_VALUE 32
+
+/* UID OTP */
+#define UID_WORD_NB U(3)
+
+/* FWU configuration (max supported value is 15) */
+#define FWU_MAX_TRIAL_REBOOT U(3)
+
+/*******************************************************************************
+ * STM32MP1 TAMP
+ ******************************************************************************/
+#define TAMP_BASE U(0x5C00A000)
+#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100))
+#define TAMP_COUNTR U(0x40)
+
+#if !(defined(__LINKER__) || defined(__ASSEMBLER__))
+static inline uintptr_t tamp_bkpr(uint32_t idx)
+{
+ return TAMP_BKP_REGISTER_BASE + (idx << 2);
+}
+#endif
+
+/*******************************************************************************
+ * STM32MP1 USB
+ ******************************************************************************/
+#define USB_OTG_BASE U(0x49000000)
+
+/*******************************************************************************
+ * STM32MP1 DDRCTRL
+ ******************************************************************************/
+#define DDRCTRL_BASE U(0x5A003000)
+
+/*******************************************************************************
+ * STM32MP1 DDRPHYC
+ ******************************************************************************/
+#define DDRPHYC_BASE U(0x5A004000)
+
+/*******************************************************************************
+ * STM32MP1 IWDG
+ ******************************************************************************/
+#define IWDG_MAX_INSTANCE U(2)
+#define IWDG1_INST U(0)
+#define IWDG2_INST U(1)
+
+#define IWDG1_BASE U(0x5C003000)
+#define IWDG2_BASE U(0x5A002000)
+
+/*******************************************************************************
+ * Miscellaneous STM32MP1 peripherals base address
+ ******************************************************************************/
+#define BSEC_BASE U(0x5C005000)
+#if STM32MP13
+#define CRYP_BASE U(0x54002000)
+#endif
+#if STM32MP15
+#define CRYP1_BASE U(0x54001000)
+#endif
+#define DBGMCU_BASE U(0x50081000)
+#if STM32MP13
+#define HASH_BASE U(0x54003000)
+#endif
+#if STM32MP15
+#define HASH1_BASE U(0x54002000)
+#endif
+#if STM32MP13
+#define I2C3_BASE U(0x4C004000)
+#define I2C4_BASE U(0x4C005000)
+#define I2C5_BASE U(0x4C006000)
+#endif
+#if STM32MP15
+#define I2C4_BASE U(0x5C002000)
+#define I2C6_BASE U(0x5c009000)
+#endif
+#if STM32MP13
+#define RNG_BASE U(0x54004000)
+#endif
+#if STM32MP15
+#define RNG1_BASE U(0x54003000)
+#endif
+#define RTC_BASE U(0x5c004000)
+#if STM32MP13
+#define SPI4_BASE U(0x4C002000)
+#define SPI5_BASE U(0x4C003000)
+#endif
+#if STM32MP15
+#define SPI6_BASE U(0x5c001000)
+#endif
+#define STGEN_BASE U(0x5c008000)
+#define SYSCFG_BASE U(0x50020000)
+
+/*******************************************************************************
+ * STM32MP13 SAES
+ ******************************************************************************/
+#define SAES_BASE U(0x54005000)
+
+/*******************************************************************************
+ * STM32MP13 PKA
+ ******************************************************************************/
+#define PKA_BASE U(0x54006000)
+
+/*******************************************************************************
+ * REGULATORS
+ ******************************************************************************/
+/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */
+#define PLAT_NB_RDEVS U(19)
+/* 2 FIXED */
+#define PLAT_NB_FIXED_REGS U(2)
+
+/*******************************************************************************
+ * Device Tree defines
+ ******************************************************************************/
+#define DT_BSEC_COMPAT "st,stm32mp15-bsec"
+#if STM32MP13
+#define DT_DDR_COMPAT "st,stm32mp13-ddr"
+#endif
+#if STM32MP15
+#define DT_DDR_COMPAT "st,stm32mp1-ddr"
+#endif
+#define DT_IWDG_COMPAT "st,stm32mp1-iwdg"
+#define DT_PWR_COMPAT "st,stm32mp1,pwr-reg"
+#if STM32MP13
+#define DT_RCC_CLK_COMPAT "st,stm32mp13-rcc"
+#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp13-rcc-secure"
+#endif
+#if STM32MP15
+#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc"
+#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp1-rcc-secure"
+#endif
+#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2"
+#define DT_UART_COMPAT "st,stm32h7-uart"
+
+#endif /* STM32MP1_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
new file mode 100644
index 0000000..f2568ab
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/tzc400.h>
+#include <drivers/clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
+
+#define STM32MP_REGION_PARAMS 4
+#define STM32MP_MAX_REGIONS 8
+#define FORCE_SEC_REGION BIT(31)
+
+static uint32_t nb_regions;
+
+struct dt_id_attr {
+ fdt32_t id_attr[STM32MP_MAX_REGIONS];
+};
+
+void stm32mp1_arch_security_setup(void)
+{
+#if STM32MP13
+ clk_enable(TZC);
+#endif
+#if STM32MP15
+ clk_enable(TZC1);
+ clk_enable(TZC2);
+#endif
+
+ tzc400_init(STM32MP1_TZC_BASE);
+ tzc400_disable_filters();
+
+ /*
+ * Region 0 set to cover all DRAM at 0xC000_0000
+ * Only secure access is granted in read/write.
+ */
+ tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+
+ tzc400_set_action(TZC_ACTION_ERR);
+ tzc400_enable_filters();
+}
+
+void stm32mp1_security_setup(void)
+{
+ uint8_t i;
+
+ assert(nb_regions > 0U);
+
+ tzc400_init(STM32MP1_TZC_BASE);
+ tzc400_disable_filters();
+
+ /*
+ * Region 0 set to cover all DRAM at 0xC000_0000
+ * No access is allowed.
+ */
+ tzc400_configure_region0(TZC_REGION_S_NONE, 0);
+
+ for (i = 1U; i <= nb_regions; i++) {
+ tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL);
+ }
+
+ tzc400_set_action(TZC_ACTION_INT);
+ tzc400_enable_filters();
+}
+
+static int fconf_populate_stm32mp1_firewall(uintptr_t config)
+{
+ int node, len;
+ unsigned int i;
+ const struct dt_id_attr *conf_list;
+ const void *dtb = (const void *)config;
+
+ /* Assert the node offset point to "st,mem-firewall" compatible property */
+ const char *compatible_str = "st,mem-firewall";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+ return node;
+ }
+
+ conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len);
+ if (conf_list == NULL) {
+ WARN("FCONF: Read cell failed for %s\n", "memory-ranges");
+ return -1;
+ }
+
+ /* Locate the memory cells and read all values */
+ for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) {
+ uint32_t base;
+ uint32_t size;
+ uint32_t sec_attr;
+ uint32_t nsaid;
+
+ base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]);
+ size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]);
+ sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]);
+ nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]);
+
+ VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n",
+ base, size, sec_attr, nsaid);
+
+ nb_regions++;
+
+ /* Configure region but keep disabled for secure access for BL2 load */
+ tzc400_configure_region(0U, nb_regions, (unsigned long long)base,
+ (unsigned long long)base + size - 1ULL, sec_attr, nsaid);
+ }
+
+ /* Force flush as the value will be used cache off */
+ flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t));
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall);
diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h
new file mode 100644
index 0000000..4098386
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fip_def.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_FIP_DEF_H
+#define STM32MP1_FIP_DEF_H
+
+#if STM32MP15_OPTEE_RSV_SHM
+#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */
+#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */
+#else
+#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */
+#define STM32MP_DDR_SHMEM_SIZE U(0) /* empty */
+#endif
+
+#if TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP
+#if STM32MP15
+#define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */
+#define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */
+#endif /* STM32MP15 */
+#else /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
+#if STM32MP13
+#if BL2_IN_XIP_MEM
+#define STM32MP_BL2_RO_SIZE U(0x00015000) /* 84 KB */
+#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */
+#else
+/* STM32MP_BL2_RO_SIZE not used if !BL2_IN_XIP_MEM */
+#define STM32MP_BL2_SIZE U(0x0001B000) /* 108KB for BL2 */
+ /* with 20KB for DTB, SYSRAM is full */
+#endif
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */
+#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */
+#endif /* STM32MP15 */
+#endif /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
+
+#if STM32MP13
+#if TRUSTED_BOARD_BOOT
+#define STM32MP_BL2_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
+#else /* TRUSTED_BOARD_BOOT */
+#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */
+#endif /* TRUSTED_BOARD_BOOT */
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_DTB_SIZE U(0x00007000) /* 28 KB for DTB */
+#endif /* STM32MP15 */
+#define STM32MP_BL32_SIZE U(0x0001B000) /* 108 KB for BL32 */
+#define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
+#define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE /* 4 KB for FCONF DTB */
+#define STM32MP_HW_CONFIG_MAX_SIZE U(0x40000) /* 256 KB for HW config DTB */
+
+#if STM32MP13
+#define STM32MP_BL2_BASE (STM32MP_BL2_DTB_BASE + \
+ STM32MP_BL2_DTB_SIZE)
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \
+ STM32MP_SEC_SYSRAM_SIZE - \
+ STM32MP_BL2_SIZE)
+#endif /* STM32MP15 */
+
+#define STM32MP_BL2_RO_BASE STM32MP_BL2_BASE
+
+#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \
+ STM32MP_BL2_RO_SIZE)
+
+#if STM32MP13
+#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ STM32MP_BL2_RW_BASE)
+
+#define STM32MP_BL2_DTB_BASE STM32MP_SEC_SYSRAM_BASE
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_RW_SIZE (STM32MP_SEC_SYSRAM_BASE + \
+ STM32MP_SEC_SYSRAM_SIZE - \
+ STM32MP_BL2_RW_BASE)
+
+#define STM32MP_BL2_DTB_BASE (STM32MP_BL2_BASE - \
+ STM32MP_BL2_DTB_SIZE)
+#endif /* STM32MP15 */
+
+#define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE
+
+#define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \
+ STM32MP_BL32_DTB_SIZE)
+
+
+#if defined(IMAGE_BL2)
+#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE
+#define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE
+#endif
+#if defined(IMAGE_BL32)
+#define STM32MP_DTB_SIZE STM32MP_BL32_DTB_SIZE
+#define STM32MP_DTB_BASE STM32MP_BL32_DTB_BASE
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_OPTEE_BASE STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_OPTEE_SIZE (STM32MP_BL2_DTB_BASE - \
+ STM32MP_OPTEE_BASE)
+#endif
+
+#if STM32MP13
+#define STM32MP_FW_CONFIG_BASE SRAM3_BASE
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_FW_CONFIG_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ PAGE_SIZE)
+#endif /* STM32MP15 */
+#define STM32MP_HW_CONFIG_BASE (STM32MP_BL33_BASE + \
+ STM32MP_BL33_MAX_SIZE)
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL32)
+#define MAX_MMAP_REGIONS 10
+#endif
+
+/*******************************************************************************
+ * STM32MP1 RAW partition offset for devices without GPT
+ ******************************************************************************/
+#define STM32MP_EMMC_BOOT_FIP_OFFSET U(0x00040000)
+#ifndef STM32MP_NOR_FIP_OFFSET
+#define STM32MP_NOR_FIP_OFFSET U(0x00080000)
+#endif
+#ifndef STM32MP_NAND_FIP_OFFSET
+#define STM32MP_NAND_FIP_OFFSET U(0x00200000)
+#endif
+
+#endif /* STM32MP1_FIP_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c
new file mode 100644
index 0000000..851a9cf
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_gic.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+struct stm32_gic_instance {
+ uint32_t cells;
+ uint32_t phandle_node;
+};
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t stm32mp1_interrupt_props[] = {
+ PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
+ PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
+};
+
+/* Fix target_mask_array as secondary core is not able to initialize it */
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2};
+
+static gicv2_driver_data_t platform_gic_data = {
+ .interrupt_props = stm32mp1_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+static struct stm32_gic_instance stm32_gic;
+
+void stm32mp1_gic_init(void)
+{
+ int node;
+ void *fdt;
+ const fdt32_t *cuint;
+ struct dt_node_info dt_gic;
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic");
+ if (node < 0) {
+ panic();
+ }
+
+ platform_gic_data.gicd_base = dt_gic.base;
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2));
+
+ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ stm32_gic.cells = fdt32_to_cpu(*cuint);
+
+ stm32_gic.phandle_node = fdt_get_phandle(fdt, node);
+ if (stm32_gic.phandle_node == 0U) {
+ panic();
+ }
+
+ gicv2_driver_init(&platform_gic_data);
+ gicv2_distif_init();
+
+ stm32mp1_gic_pcpu_init();
+}
+
+void stm32mp1_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
new file mode 100644
index 0000000..eb8823b
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <drivers/st/stm32_gpio.h>
+
+#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1)
+
+ .globl platform_mem_init
+ .globl plat_report_exception
+ .globl plat_report_prefetch_abort
+ .globl plat_report_data_abort
+ .globl plat_get_my_entrypoint
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_reset_handler
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_flush
+ .globl plat_crash_console_putc
+ .globl plat_panic_handler
+
+func platform_mem_init
+ /* Nothing to do, don't need to init SYSRAM */
+ bx lr
+endfunc platform_mem_init
+
+#if DEBUG
+func plat_report_exception
+ mov r8, lr
+
+ /*
+ * Test if an abort occurred
+ * In this case the error message has already been displayed
+ * by dedicated functions
+ */
+ cmp r0, #MODE32_abt
+ beq 1f
+
+ /* Test for an undefined instruction */
+ cmp r0, #MODE32_und
+ bne other_exception_lbl
+ ldr r4, =undefined_str
+ bl asm_print_str
+ mrs r4, lr_und
+ b print_exception_info
+
+other_exception_lbl:
+ /* Other exceptions */
+ mov r9, r0
+ ldr r4, =exception_start_str
+ bl asm_print_str
+ mov r4, r9
+ bl asm_print_hex
+ ldr r4, =exception_end_str
+ bl asm_print_str
+ mov r4, r6
+
+print_exception_info:
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+1:
+ bx r8
+endfunc plat_report_exception
+
+func plat_report_prefetch_abort
+ mov r8, lr
+ mov r9, r0
+
+ ldr r4, =prefetch_abort_str
+ bl asm_print_str
+
+ mov r4, r9
+ sub r4, r4, #4
+ bl asm_print_hex
+
+ ldr r4, =ifsr_str
+ bl asm_print_str
+
+ ldcopr r4, IFSR
+ bl asm_print_hex
+
+ ldr r4, =ifar_str
+ bl asm_print_str
+
+ ldcopr r4, IFAR
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+endfunc plat_report_prefetch_abort
+
+func plat_report_data_abort
+ mov r8, lr
+ mov r9, r0
+
+ ldr r4, =data_abort_str
+ bl asm_print_str
+
+ mov r4, r9
+ sub r4, r4, #8
+ bl asm_print_hex
+
+ ldr r4, =dfsr_str
+ bl asm_print_str
+
+ ldcopr r4, DFSR
+ bl asm_print_hex
+
+ ldr r4, =dfar_str
+ bl asm_print_str
+
+ ldcopr r4, DFAR
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+endfunc plat_report_data_abort
+#endif /* DEBUG */
+
+func plat_reset_handler
+ bx lr
+endfunc plat_reset_handler
+
+ /* ------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot.
+ *
+ * Currently supports only cold boot
+ * ------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mov r0, #0
+ bx lr
+endfunc plat_get_my_entrypoint
+
+ /* ---------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * Cold-booting secondary CPUs is not supported.
+ * ---------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ b .
+endfunc plat_secondary_cold_boot_setup
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ ldcopr r0, MPIDR
+ ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ and r0, r1
+ cmp r0, #STM32MP_PRIMARY_CPU
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+endfunc plat_is_my_cpu_primary
+
+ /* -------------------------------------------
+ * int plat_stm32mp1_get_core_pos(int mpidr);
+ *
+ * Return CorePos = (ClusterId * 4) + CoreId
+ * -------------------------------------------
+ */
+func plat_stm32mp1_get_core_pos
+ and r1, r0, #MPIDR_CPU_MASK
+ and r0, r0, #MPIDR_CLUSTER_MASK
+ add r0, r1, r0, LSR #6
+ bx lr
+endfunc plat_stm32mp1_get_core_pos
+
+ /* ------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * ------------------------------------
+ */
+func plat_my_core_pos
+ ldcopr r0, MPIDR
+ b plat_stm32mp1_get_core_pos
+endfunc plat_my_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ *
+ * Initialize the crash console without a C Runtime stack.
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ /* Reset UART peripheral */
+ ldr r1, =(RCC_BASE + DEBUG_UART_RST_REG)
+ ldr r2, =DEBUG_UART_RST_BIT
+ str r2, [r1]
+1:
+ ldr r0, [r1]
+ ands r2, r0, r2
+ beq 1b
+ str r2, [r1, #4] /* RSTCLR register */
+2:
+ ldr r0, [r1]
+ ands r2, r0, r2
+ bne 2b
+ /* Enable GPIOs for UART TX */
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
+ ldr r2, [r1]
+ /* Configure GPIO */
+ orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN
+ str r2, [r1]
+ ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS
+ /* Set GPIO mode alternate */
+ ldr r2, [r1, #GPIO_MODE_OFFSET]
+ bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT)
+ orr r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT)
+ str r2, [r1, #GPIO_MODE_OFFSET]
+ /* Set GPIO speed low */
+ ldr r2, [r1, #GPIO_SPEED_OFFSET]
+ bic r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT)
+ str r2, [r1, #GPIO_SPEED_OFFSET]
+ /* Set no-pull */
+ ldr r2, [r1, #GPIO_PUPD_OFFSET]
+ bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
+ str r2, [r1, #GPIO_PUPD_OFFSET]
+ /* Set alternate */
+#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT
+ ldr r2, [r1, #GPIO_AFRH_OFFSET]
+ bic r2, r2, #(GPIO_ALTERNATE_MASK << \
+ ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \
+ ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+ str r2, [r1, #GPIO_AFRH_OFFSET]
+#else
+ ldr r2, [r1, #GPIO_AFRL_OFFSET]
+ bic r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2))
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2))
+ str r2, [r1, #GPIO_AFRL_OFFSET]
+#endif
+ /* Enable UART clock, with its source */
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG)
+ mov r2, #DEBUG_UART_TX_CLKSRC
+ str r2, [r1]
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG)
+ ldr r2, [r1]
+ orr r2, r2, #DEBUG_UART_TX_EN
+ str r2, [r1]
+
+ ldr r0, =STM32MP_DEBUG_USART_BASE
+ ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ
+ ldr r2, =STM32MP_UART_BAUDRATE
+ b console_stm32_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush(void)
+ *
+ * Flush the crash console without a C Runtime stack.
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ ldr r0, =STM32MP_DEBUG_USART_BASE
+ b console_stm32_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ *
+ * Print a character on the crash console without a C Runtime stack.
+ * Clobber list : r1 - r3
+ *
+ * In case of bootloading through uart, we keep console crash as this.
+ * Characters could be sent to the programmer, but will be ignored.
+ * No specific code in that case.
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ ldr r1, =STM32MP_DEBUG_USART_BASE
+ b console_stm32_core_putc
+endfunc plat_crash_console_putc
+
+ /* ----------------------------------------------------------
+ * void plat_panic_handler(void) __dead2;
+ * Report exception + endless loop.
+ *
+ * r6 holds the address where the fault occurred.
+ * Filling lr with this value allows debuggers to reconstruct
+ * the backtrace.
+ * ----------------------------------------------------------
+ */
+func plat_panic_handler
+ mrs r0, cpsr
+ and r0, #MODE32_MASK
+ bl plat_report_exception
+ mov lr, r6
+ b .
+endfunc plat_panic_handler
+
+#if DEBUG
+.section .rodata.rev_err_str, "aS"
+prefetch_abort_str:
+ .asciz "\nPrefetch Abort at: 0x"
+data_abort_str:
+ .asciz "\nData Abort at: 0x"
+undefined_str:
+ .asciz "\nUndefined instruction at: 0x"
+exception_start_str:
+ .asciz "\nException mode=0x"
+exception_end_str:
+ .asciz " at: 0x"
+dfsr_str:
+ .asciz " DFSR = 0x"
+dfar_str:
+ .asciz " DFAR = 0x"
+ifsr_str:
+ .asciz " IFSR = 0x"
+ifar_str:
+ .asciz " IFAR = 0x"
+end_error_str:
+ .asciz "\n\r"
+#endif
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
new file mode 100644
index 0000000..6e438c4
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl32/sp_min/platform_sp_min.h>
+#include <common/debug.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+static uintptr_t stm32_sec_entrypoint;
+static uint32_t cntfrq_core0;
+
+/*******************************************************************************
+ * STM32MP1 handler called when a CPU is about to enter standby.
+ * call by core 1 to enter in wfi
+ ******************************************************************************/
+static void stm32_cpu_standby(plat_local_state_t cpu_state)
+{
+ uint32_t interrupt = GIC_SPURIOUS_INTERRUPT;
+
+ assert(cpu_state == ARM_LOCAL_STATE_RET);
+
+ /*
+ * Enter standby state
+ * dsb is good practice before using wfi to enter low power states
+ */
+ isb();
+ dsb();
+ while (interrupt == GIC_SPURIOUS_INTERRUPT) {
+ wfi();
+
+ /* Acknoledge IT */
+ interrupt = gicv2_acknowledge_interrupt();
+ /* If Interrupt == 1022 it will be acknowledged by non secure */
+ if ((interrupt != PENDING_G1_INTID) &&
+ (interrupt != GIC_SPURIOUS_INTERRUPT)) {
+ gicv2_end_of_interrupt(interrupt);
+ }
+ }
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ * call by core 0 to activate core 1
+ ******************************************************************************/
+static int stm32_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned long current_cpu_mpidr = read_mpidr_el1();
+ uintptr_t bkpr_core1_addr =
+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+ uintptr_t bkpr_core1_magic =
+ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
+
+ if (mpidr == current_cpu_mpidr) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ /* Only one valid entry point */
+ if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) {
+ return PSCI_E_INVALID_ADDRESS;
+ }
+
+ clk_enable(RTCAPB);
+
+ cntfrq_core0 = read_cntfrq_el0();
+
+ /* Write entrypoint in backup RAM register */
+ mmio_write_32(bkpr_core1_addr, stm32_sec_entrypoint);
+
+ /* Write magic number in backup register */
+ mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER);
+
+ clk_disable(RTCAPB);
+
+ /* Generate an IT to core 1 */
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, false, STM32MP_SECONDARY_CPU);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void stm32_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ /* Nothing to do */
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ /* Nothing to do, power domain is not disabled */
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ * call by core 1 just after wake up
+ ******************************************************************************/
+static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ stm32mp1_gic_pcpu_init();
+
+ write_cntfrq_el0(cntfrq_core0);
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ ******************************************************************************/
+static void stm32_pwr_domain_suspend_finish(const psci_power_state_t
+ *target_state)
+{
+ /* Nothing to do, power domain is not disabled */
+}
+
+static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ ERROR("stm32mpu1 Power Down WFI: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 stm32_system_off(void)
+{
+ ERROR("stm32mpu1 System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 stm32_system_reset(void)
+{
+ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
+ RCC_MP_GRSTCSETR_MPSYSRST);
+
+ /* Loop in case system reset is not immediately caught */
+ for ( ; ; ) {
+ ;
+ }
+}
+
+static int stm32_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+
+ if (pstate != 0) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (psci_get_pstate_pwrlvl(power_state)) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (psci_get_pstate_id(power_state)) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_RET;
+ req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_RUN;
+
+ return PSCI_E_SUCCESS;
+}
+
+static int stm32_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /* The non-secure entry point must be in DDR */
+ if (entrypoint < STM32MP_DDR_BASE) {
+ return PSCI_E_INVALID_ADDRESS;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+static int stm32_node_hw_state(u_register_t target_cpu,
+ unsigned int power_level)
+{
+ /*
+ * The format of 'power_level' is implementation-defined, but 0 must
+ * mean a CPU. Only allow level 0.
+ */
+ if (power_level != MPIDR_AFFLVL0) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ /*
+ * From psci view the CPU 0 is always ON,
+ * CPU 1 can be SUSPEND or RUNNING.
+ * Therefore do not manage POWER OFF state and always return HW_ON.
+ */
+
+ return (int)HW_ON;
+}
+
+/*******************************************************************************
+ * Export the platform handlers. The ARM Standard platform layer will take care
+ * of registering the handlers with PSCI.
+ ******************************************************************************/
+static const plat_psci_ops_t stm32_psci_ops = {
+ .cpu_standby = stm32_cpu_standby,
+ .pwr_domain_on = stm32_pwr_domain_on,
+ .pwr_domain_off = stm32_pwr_domain_off,
+ .pwr_domain_suspend = stm32_pwr_domain_suspend,
+ .pwr_domain_on_finish = stm32_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi,
+ .system_off = stm32_system_off,
+ .system_reset = stm32_system_reset,
+ .validate_power_state = stm32_validate_power_state,
+ .validate_ns_entrypoint = stm32_validate_ns_entrypoint,
+ .get_node_hw_state = stm32_node_hw_state
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ stm32_sec_entrypoint = sec_entrypoint;
+ *psci_ops = &stm32_psci_ops;
+
+ return 0;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
new file mode 100644
index 0000000..9bdb075
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -0,0 +1,788 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/clk.h>
+#include <drivers/st/stm32_gpio.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <libfdt.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/* Internal layout of the 32bit OTP word board_id */
+#define BOARD_ID_BOARD_NB_MASK GENMASK(31, 16)
+#define BOARD_ID_BOARD_NB_SHIFT 16
+#define BOARD_ID_VARCPN_MASK GENMASK(15, 12)
+#define BOARD_ID_VARCPN_SHIFT 12
+#define BOARD_ID_REVISION_MASK GENMASK(11, 8)
+#define BOARD_ID_REVISION_SHIFT 8
+#define BOARD_ID_VARFG_MASK GENMASK(7, 4)
+#define BOARD_ID_VARFG_SHIFT 4
+#define BOARD_ID_BOM_MASK GENMASK(3, 0)
+
+#define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \
+ BOARD_ID_BOARD_NB_SHIFT)
+#define BOARD_ID2VARCPN(_id) (((_id) & BOARD_ID_VARCPN_MASK) >> \
+ BOARD_ID_VARCPN_SHIFT)
+#define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \
+ BOARD_ID_REVISION_SHIFT)
+#define BOARD_ID2VARFG(_id) (((_id) & BOARD_ID_VARFG_MASK) >> \
+ BOARD_ID_VARFG_SHIFT)
+#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK)
+
+#if STM32MP13
+#define TAMP_BOOT_MODE_BACKUP_REG_ID U(30)
+#endif
+#if STM32MP15
+#define TAMP_BOOT_MODE_BACKUP_REG_ID U(20)
+#endif
+#define TAMP_BOOT_MODE_ITF_MASK GENMASK(15, 8)
+#define TAMP_BOOT_MODE_ITF_SHIFT 8
+#define TAMP_BOOT_MODE_AUTH_MASK GENMASK(23, 16)
+#define TAMP_BOOT_MODE_AUTH_SHIFT 16
+
+/*
+ * Backup register to store fwu update information.
+ * It should be writeable only by secure world, but also readable by non secure
+ * (so it should be in Zone 2).
+ */
+#define TAMP_BOOT_FWU_INFO_REG_ID U(10)
+#define TAMP_BOOT_FWU_INFO_IDX_MSK GENMASK(3, 0)
+#define TAMP_BOOT_FWU_INFO_IDX_OFF U(0)
+#define TAMP_BOOT_FWU_INFO_CNT_MSK GENMASK(7, 4)
+#define TAMP_BOOT_FWU_INFO_CNT_OFF U(4)
+
+#if defined(IMAGE_BL2)
+#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
+ STM32MP_SYSRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+#elif defined(IMAGE_BL32)
+#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SEC_SYSRAM_BASE, \
+ STM32MP_SEC_SYSRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+/* Non-secure SYSRAM is used a uncached memory for SCMI message transfer */
+#define MAP_NS_SYSRAM MAP_REGION_FLAT(STM32MP_NS_SYSRAM_BASE, \
+ STM32MP_NS_SYSRAM_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_NS | \
+ MT_EXECUTE_NEVER)
+#endif
+
+#if STM32MP13
+#define MAP_SRAM_ALL MAP_REGION_FLAT(SRAMS_BASE, \
+ SRAMS_SIZE_2MB_ALIGNED, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+#endif
+
+#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
+ STM32MP1_DEVICE1_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \
+ STM32MP1_DEVICE2_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#if defined(IMAGE_BL2)
+static const mmap_region_t stm32mp1_mmap[] = {
+ MAP_SEC_SYSRAM,
+#if STM32MP13
+ MAP_SRAM_ALL,
+#endif
+ MAP_DEVICE1,
+#if STM32MP_RAW_NAND
+ MAP_DEVICE2,
+#endif
+ {0}
+};
+#endif
+#if defined(IMAGE_BL32)
+static const mmap_region_t stm32mp1_mmap[] = {
+ MAP_SEC_SYSRAM,
+ MAP_NS_SYSRAM,
+ MAP_DEVICE1,
+ MAP_DEVICE2,
+ {0}
+};
+#endif
+
+void configure_mmu(void)
+{
+ mmap_add(stm32mp1_mmap);
+ init_xlat_tables();
+
+ enable_mmu_svc_mon(0);
+}
+
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
+{
+#if STM32MP13
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return GPIOZ_BASE;
+ }
+
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+#endif
+
+ return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
+}
+
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
+{
+#if STM32MP13
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return 0;
+ }
+
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+#endif
+
+ return bank * GPIO_BANK_OFFSET;
+}
+
+bool stm32_gpio_is_secure_at_reset(unsigned int bank)
+{
+#if STM32MP13
+ return true;
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return true;
+ }
+
+ return false;
+#endif
+}
+
+unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
+{
+#if STM32MP13
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return GPIOZ;
+ }
+
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+#endif
+
+ return GPIOA + (bank - GPIO_BANK_A);
+}
+
+int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank)
+{
+ const char *node_compatible = NULL;
+
+ switch (bank) {
+ case GPIO_BANK_A:
+ case GPIO_BANK_B:
+ case GPIO_BANK_C:
+ case GPIO_BANK_D:
+ case GPIO_BANK_E:
+ case GPIO_BANK_F:
+ case GPIO_BANK_G:
+ case GPIO_BANK_H:
+ case GPIO_BANK_I:
+#if STM32MP13
+ node_compatible = "st,stm32mp135-pinctrl";
+ break;
+#endif
+#if STM32MP15
+ case GPIO_BANK_J:
+ case GPIO_BANK_K:
+ node_compatible = "st,stm32mp157-pinctrl";
+ break;
+ case GPIO_BANK_Z:
+ node_compatible = "st,stm32mp157-z-pinctrl";
+ break;
+#endif
+ default:
+ panic();
+ }
+
+ return fdt_node_offset_by_compatible(fdt, -1, node_compatible);
+}
+
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+/*
+ * UART Management
+ */
+static const uintptr_t stm32mp1_uart_addresses[8] = {
+ USART1_BASE,
+ USART2_BASE,
+ USART3_BASE,
+ UART4_BASE,
+ UART5_BASE,
+ USART6_BASE,
+ UART7_BASE,
+ UART8_BASE,
+};
+
+uintptr_t get_uart_address(uint32_t instance_nb)
+{
+ if ((instance_nb == 0U) ||
+ (instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) {
+ return 0U;
+ }
+
+ return stm32mp1_uart_addresses[instance_nb - 1U];
+}
+#endif
+
+#if STM32MP_USB_PROGRAMMER
+struct gpio_bank_pin_list {
+ uint32_t bank;
+ uint32_t pin;
+};
+
+static const struct gpio_bank_pin_list gpio_list[] = {
+ { /* USART2_RX: GPIOA3 */
+ .bank = 0U,
+ .pin = 3U,
+ },
+ { /* USART3_RX: GPIOB12 */
+ .bank = 1U,
+ .pin = 12U,
+ },
+ { /* UART4_RX: GPIOB2 */
+ .bank = 1U,
+ .pin = 2U,
+ },
+ { /* UART5_RX: GPIOB4 */
+ .bank = 1U,
+ .pin = 5U,
+ },
+ { /* USART6_RX: GPIOC7 */
+ .bank = 2U,
+ .pin = 7U,
+ },
+ { /* UART7_RX: GPIOF6 */
+ .bank = 5U,
+ .pin = 6U,
+ },
+ { /* UART8_RX: GPIOE0 */
+ .bank = 4U,
+ .pin = 0U,
+ },
+};
+
+void stm32mp1_deconfigure_uart_pins(void)
+{
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(gpio_list); i++) {
+ set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin);
+ }
+}
+#endif
+
+uint32_t stm32mp_get_chip_version(void)
+{
+#if STM32MP13
+ return stm32mp1_syscfg_get_chip_version();
+#endif
+#if STM32MP15
+ uint32_t version = 0U;
+
+ if (stm32mp1_dbgmcu_get_chip_version(&version) < 0) {
+ INFO("Cannot get CPU version, debug disabled\n");
+ return 0U;
+ }
+
+ return version;
+#endif
+}
+
+uint32_t stm32mp_get_chip_dev_id(void)
+{
+#if STM32MP13
+ return stm32mp1_syscfg_get_chip_dev_id();
+#endif
+#if STM32MP15
+ uint32_t dev_id;
+
+ if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) {
+ INFO("Use default chip ID, debug disabled\n");
+ dev_id = STM32MP1_CHIP_ID;
+ }
+
+ return dev_id;
+#endif
+}
+
+static uint32_t get_part_number(void)
+{
+ static uint32_t part_number;
+
+ if (part_number != 0U) {
+ return part_number;
+ }
+
+ if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) {
+ panic();
+ }
+
+ part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >>
+ PART_NUMBER_OTP_PART_SHIFT;
+
+ part_number |= stm32mp_get_chip_dev_id() << 16;
+
+ return part_number;
+}
+
+#if STM32MP15
+static uint32_t get_cpu_package(void)
+{
+ uint32_t package;
+
+ if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) {
+ panic();
+ }
+
+ package = (package & PACKAGE_OTP_PKG_MASK) >>
+ PACKAGE_OTP_PKG_SHIFT;
+
+ return package;
+}
+#endif
+
+void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE])
+{
+ char *cpu_s, *cpu_r, *pkg;
+
+ /* MPUs Part Numbers */
+ switch (get_part_number()) {
+#if STM32MP13
+ case STM32MP135F_PART_NB:
+ cpu_s = "135F";
+ break;
+ case STM32MP135D_PART_NB:
+ cpu_s = "135D";
+ break;
+ case STM32MP135C_PART_NB:
+ cpu_s = "135C";
+ break;
+ case STM32MP135A_PART_NB:
+ cpu_s = "135A";
+ break;
+ case STM32MP133F_PART_NB:
+ cpu_s = "133F";
+ break;
+ case STM32MP133D_PART_NB:
+ cpu_s = "133D";
+ break;
+ case STM32MP133C_PART_NB:
+ cpu_s = "133C";
+ break;
+ case STM32MP133A_PART_NB:
+ cpu_s = "133A";
+ break;
+ case STM32MP131F_PART_NB:
+ cpu_s = "131F";
+ break;
+ case STM32MP131D_PART_NB:
+ cpu_s = "131D";
+ break;
+ case STM32MP131C_PART_NB:
+ cpu_s = "131C";
+ break;
+ case STM32MP131A_PART_NB:
+ cpu_s = "131A";
+ break;
+#endif
+#if STM32MP15
+ case STM32MP157C_PART_NB:
+ cpu_s = "157C";
+ break;
+ case STM32MP157A_PART_NB:
+ cpu_s = "157A";
+ break;
+ case STM32MP153C_PART_NB:
+ cpu_s = "153C";
+ break;
+ case STM32MP153A_PART_NB:
+ cpu_s = "153A";
+ break;
+ case STM32MP151C_PART_NB:
+ cpu_s = "151C";
+ break;
+ case STM32MP151A_PART_NB:
+ cpu_s = "151A";
+ break;
+ case STM32MP157F_PART_NB:
+ cpu_s = "157F";
+ break;
+ case STM32MP157D_PART_NB:
+ cpu_s = "157D";
+ break;
+ case STM32MP153F_PART_NB:
+ cpu_s = "153F";
+ break;
+ case STM32MP153D_PART_NB:
+ cpu_s = "153D";
+ break;
+ case STM32MP151F_PART_NB:
+ cpu_s = "151F";
+ break;
+ case STM32MP151D_PART_NB:
+ cpu_s = "151D";
+ break;
+#endif
+ default:
+ cpu_s = "????";
+ break;
+ }
+
+ /* Package */
+#if STM32MP13
+ /* On STM32MP13, package is not present in OTP */
+ pkg = "";
+#endif
+#if STM32MP15
+ switch (get_cpu_package()) {
+ case PKG_AA_LFBGA448:
+ pkg = "AA";
+ break;
+ case PKG_AB_LFBGA354:
+ pkg = "AB";
+ break;
+ case PKG_AC_TFBGA361:
+ pkg = "AC";
+ break;
+ case PKG_AD_TFBGA257:
+ pkg = "AD";
+ break;
+ default:
+ pkg = "??";
+ break;
+ }
+#endif
+
+ /* REVISION */
+ switch (stm32mp_get_chip_version()) {
+ case STM32MP1_REV_B:
+ cpu_r = "B";
+ break;
+#if STM32MP13
+ case STM32MP1_REV_Y:
+ cpu_r = "Y";
+ break;
+#endif
+ case STM32MP1_REV_Z:
+ cpu_r = "Z";
+ break;
+ default:
+ cpu_r = "?";
+ break;
+ }
+
+ snprintf(name, STM32_SOC_NAME_SIZE,
+ "STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r);
+}
+
+void stm32mp_print_cpuinfo(void)
+{
+ char name[STM32_SOC_NAME_SIZE];
+
+ stm32mp_get_soc_name(name);
+ NOTICE("CPU: %s\n", name);
+}
+
+void stm32mp_print_boardinfo(void)
+{
+ uint32_t board_id = 0;
+
+ if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) {
+ return;
+ }
+
+ if (board_id != 0U) {
+ char rev[2];
+
+ rev[0] = BOARD_ID2REV(board_id) - 1 + 'A';
+ rev[1] = '\0';
+ NOTICE("Board: MB%04x Var%u.%u Rev.%s-%02u\n",
+ BOARD_ID2NB(board_id),
+ BOARD_ID2VARCPN(board_id),
+ BOARD_ID2VARFG(board_id),
+ rev,
+ BOARD_ID2BOM(board_id));
+ }
+}
+
+/* Return true when SoC provides a single Cortex-A7 core, and false otherwise */
+bool stm32mp_is_single_core(void)
+{
+#if STM32MP13
+ return true;
+#endif
+#if STM32MP15
+ bool single_core = false;
+
+ switch (get_part_number()) {
+ case STM32MP151A_PART_NB:
+ case STM32MP151C_PART_NB:
+ case STM32MP151D_PART_NB:
+ case STM32MP151F_PART_NB:
+ single_core = true;
+ break;
+ default:
+ break;
+ }
+
+ return single_core;
+#endif
+}
+
+/* Return true when device is in closed state */
+bool stm32mp_is_closed_device(void)
+{
+ uint32_t value;
+
+ if (stm32_get_otp_value(CFG0_OTP, &value) != 0) {
+ return true;
+ }
+
+#if STM32MP13
+ value = (value & CFG0_OTP_MODE_MASK) >> CFG0_OTP_MODE_SHIFT;
+
+ switch (value) {
+ case CFG0_OPEN_DEVICE:
+ return false;
+ case CFG0_CLOSED_DEVICE:
+ case CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN:
+ case CFG0_CLOSED_DEVICE_NO_JTAG:
+ return true;
+ default:
+ panic();
+ }
+#endif
+#if STM32MP15
+ return (value & CFG0_CLOSED_DEVICE) == CFG0_CLOSED_DEVICE;
+#endif
+}
+
+/* Return true when device supports secure boot */
+bool stm32mp_is_auth_supported(void)
+{
+ bool supported = false;
+
+ switch (get_part_number()) {
+#if STM32MP13
+ case STM32MP131C_PART_NB:
+ case STM32MP131F_PART_NB:
+ case STM32MP133C_PART_NB:
+ case STM32MP133F_PART_NB:
+ case STM32MP135C_PART_NB:
+ case STM32MP135F_PART_NB:
+#endif
+#if STM32MP15
+ case STM32MP151C_PART_NB:
+ case STM32MP151F_PART_NB:
+ case STM32MP153C_PART_NB:
+ case STM32MP153F_PART_NB:
+ case STM32MP157C_PART_NB:
+ case STM32MP157F_PART_NB:
+#endif
+ supported = true;
+ break;
+ default:
+ break;
+ }
+
+ return supported;
+}
+
+uint32_t stm32_iwdg_get_instance(uintptr_t base)
+{
+ switch (base) {
+ case IWDG1_BASE:
+ return IWDG1_INST;
+ case IWDG2_BASE:
+ return IWDG2_INST;
+ default:
+ panic();
+ }
+}
+
+uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst)
+{
+ uint32_t iwdg_cfg = 0U;
+ uint32_t otp_value;
+
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
+ panic();
+ }
+
+ if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_HW_POS)) != 0U) {
+ iwdg_cfg |= IWDG_HW_ENABLED;
+ }
+
+ if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS)) != 0U) {
+ iwdg_cfg |= IWDG_DISABLE_ON_STOP;
+ }
+
+ if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS)) != 0U) {
+ iwdg_cfg |= IWDG_DISABLE_ON_STANDBY;
+ }
+
+ return iwdg_cfg;
+}
+
+#if defined(IMAGE_BL2)
+uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags)
+{
+ uint32_t otp_value;
+ uint32_t otp;
+ uint32_t result;
+
+ if (stm32_get_otp_index(HW2_OTP, &otp, NULL) != 0) {
+ panic();
+ }
+
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
+ panic();
+ }
+
+ if ((flags & IWDG_DISABLE_ON_STOP) != 0) {
+ otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS);
+ }
+
+ if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) {
+ otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS);
+ }
+
+ result = bsec_write_otp(otp_value, otp);
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ /* Sticky lock OTP_IWDG (read and write) */
+ if ((bsec_set_sr_lock(otp) != BSEC_OK) ||
+ (bsec_set_sw_lock(otp) != BSEC_OK)) {
+ return BSEC_LOCK_FAIL;
+ }
+
+ return BSEC_OK;
+}
+#endif
+
+void stm32_save_boot_interface(uint32_t interface, uint32_t instance)
+{
+ uintptr_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+ clk_enable(RTCAPB);
+
+ mmio_clrsetbits_32(bkpr_itf_idx,
+ TAMP_BOOT_MODE_ITF_MASK,
+ ((interface << 4) | (instance & 0xFU)) <<
+ TAMP_BOOT_MODE_ITF_SHIFT);
+
+ clk_disable(RTCAPB);
+}
+
+void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance)
+{
+ static uint32_t itf;
+
+ if (itf == 0U) {
+ uintptr_t bkpr = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+ clk_enable(RTCAPB);
+
+ itf = (mmio_read_32(bkpr) & TAMP_BOOT_MODE_ITF_MASK) >>
+ TAMP_BOOT_MODE_ITF_SHIFT;
+
+ clk_disable(RTCAPB);
+ }
+
+ *interface = itf >> 4;
+ *instance = itf & 0xFU;
+}
+
+void stm32_save_boot_auth(uint32_t auth_status, uint32_t boot_partition)
+{
+ uint32_t boot_status = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+ clk_enable(RTCAPB);
+
+ mmio_clrsetbits_32(boot_status,
+ TAMP_BOOT_MODE_AUTH_MASK,
+ ((auth_status << 4) | (boot_partition & 0xFU)) <<
+ TAMP_BOOT_MODE_AUTH_SHIFT);
+
+ clk_disable(RTCAPB);
+}
+
+#if PSA_FWU_SUPPORT
+void stm32mp1_fwu_set_boot_idx(void)
+{
+ clk_enable(RTCAPB);
+ mmio_clrsetbits_32(tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID),
+ TAMP_BOOT_FWU_INFO_IDX_MSK,
+ (plat_fwu_get_boot_idx() << TAMP_BOOT_FWU_INFO_IDX_OFF) &
+ TAMP_BOOT_FWU_INFO_IDX_MSK);
+ clk_disable(RTCAPB);
+}
+
+uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void)
+{
+ uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID);
+ uint32_t try_cnt;
+
+ clk_enable(RTCAPB);
+ try_cnt = (mmio_read_32(bkpr_fwu_cnt) & TAMP_BOOT_FWU_INFO_CNT_MSK) >>
+ TAMP_BOOT_FWU_INFO_CNT_OFF;
+
+ assert(try_cnt <= FWU_MAX_TRIAL_REBOOT);
+
+ if (try_cnt != 0U) {
+ mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK,
+ (try_cnt - 1U) << TAMP_BOOT_FWU_INFO_CNT_OFF);
+ }
+ clk_disable(RTCAPB);
+
+ return try_cnt;
+}
+
+void stm32_set_max_fwu_trial_boot_cnt(void)
+{
+ uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID);
+
+ clk_enable(RTCAPB);
+ mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK,
+ (FWU_MAX_TRIAL_REBOOT << TAMP_BOOT_FWU_INFO_CNT_OFF) &
+ TAMP_BOOT_FWU_INFO_CNT_MSK);
+ clk_disable(RTCAPB);
+}
+#endif /* PSA_FWU_SUPPORT */
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
new file mode 100644
index 0000000..98585dc
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <drivers/clk.h>
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+
+#define TIMEOUT_US_1MS 1000U
+
+#define SCMI_CLOCK_NAME_SIZE 16U
+#define SCMI_RSTD_NAME_SIZE 16U
+
+/*
+ * struct stm32_scmi_clk - Data for the exposed clock
+ * @clock_id: Clock identifier in RCC clock driver
+ * @name: Clock string ID exposed to agent
+ * @enabled: State of the SCMI clock
+ */
+struct stm32_scmi_clk {
+ unsigned long clock_id;
+ const char *name;
+ bool enabled;
+};
+
+/*
+ * struct stm32_scmi_rstd - Data for the exposed reset controller
+ * @reset_id: Reset identifier in RCC reset driver
+ * @name: Reset string ID exposed to agent
+ */
+struct stm32_scmi_rstd {
+ unsigned long reset_id;
+ const char *name;
+};
+
+/* Locate all non-secure SMT message buffers in last page of SYSRAM */
+#define SMT_BUFFER_BASE STM32MP_SCMI_NS_SHM_BASE
+#define SMT_BUFFER0_BASE SMT_BUFFER_BASE
+#define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + 0x200)
+
+CASSERT((STM32MP_SCMI_NS_SHM_BASE + STM32MP_SCMI_NS_SHM_SIZE) >=
+ (SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE),
+ assert_scmi_non_secure_shm_fits_scmi_overall_buffer_size);
+
+static struct scmi_msg_channel scmi_channel[] = {
+ [0] = {
+ .shm_addr = SMT_BUFFER0_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+ [1] = {
+ .shm_addr = SMT_BUFFER1_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+};
+
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(scmi_channel));
+
+ return &scmi_channel[agent_id];
+}
+
+#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
+ [_scmi_id] = { \
+ .clock_id = _id, \
+ .name = _name, \
+ .enabled = _init_enabled, \
+ }
+
+static struct stm32_scmi_clk stm32_scmi0_clock[] = {
+ CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true),
+ CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true),
+ CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true),
+ CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true),
+ CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true),
+ CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true),
+ CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true),
+ CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true),
+ CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true),
+ CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true),
+ CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false),
+ CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false),
+ CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false),
+ CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false),
+ CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false),
+ CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false),
+ CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true),
+ CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true),
+ CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true),
+ CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false),
+ CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false),
+};
+
+static struct stm32_scmi_clk stm32_scmi1_clock[] = {
+ CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true),
+ CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true),
+ CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false),
+};
+
+#define RESET_CELL(_scmi_id, _id, _name) \
+ [_scmi_id] = { \
+ .reset_id = _id, \
+ .name = _name, \
+ }
+
+static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = {
+ RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"),
+ RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"),
+ RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"),
+ RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"),
+ RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"),
+ RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"),
+ RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"),
+ RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"),
+ RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
+ RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
+ RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
+};
+
+struct scmi_agent_resources {
+ struct stm32_scmi_clk *clock;
+ size_t clock_count;
+ struct stm32_scmi_rstd *rstd;
+ size_t rstd_count;
+};
+
+static const struct scmi_agent_resources agent_resources[] = {
+ [0] = {
+ .clock = stm32_scmi0_clock,
+ .clock_count = ARRAY_SIZE(stm32_scmi0_clock),
+ .rstd = stm32_scmi0_reset_domain,
+ .rstd_count = ARRAY_SIZE(stm32_scmi0_reset_domain),
+ },
+ [1] = {
+ .clock = stm32_scmi1_clock,
+ .clock_count = ARRAY_SIZE(stm32_scmi1_clock),
+ },
+};
+
+static const struct scmi_agent_resources *find_resource(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(agent_resources));
+
+ return &agent_resources[agent_id];
+}
+
+#if ENABLE_ASSERTIONS
+static size_t plat_scmi_protocol_count_paranoid(void)
+{
+ unsigned int n = 0U;
+ unsigned int count = 0U;
+
+ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+ if (agent_resources[n].clock_count) {
+ count++;
+ break;
+ }
+ }
+
+ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+ if (agent_resources[n].rstd_count) {
+ count++;
+ break;
+ }
+ }
+
+ return count;
+}
+#endif
+
+static const char vendor[] = "ST";
+static const char sub_vendor[] = "";
+
+const char *plat_scmi_vendor_name(void)
+{
+ return vendor;
+}
+
+const char *plat_scmi_sub_vendor_name(void)
+{
+ return sub_vendor;
+}
+
+/* Currently supporting Clocks and Reset Domains */
+static const uint8_t plat_protocol_list[] = {
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_PROTOCOL_ID_RESET_DOMAIN,
+ 0U /* Null termination */
+};
+
+size_t plat_scmi_protocol_count(void)
+{
+ const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U;
+
+ assert(count == plat_scmi_protocol_count_paranoid());
+
+ return count;
+}
+
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
+{
+ assert(plat_scmi_protocol_count_paranoid() ==
+ (ARRAY_SIZE(plat_protocol_list) - 1U));
+
+ return plat_protocol_list;
+}
+
+/*
+ * Platform SCMI clocks
+ */
+static struct stm32_scmi_clk *find_clock(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+ size_t n = 0U;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->clock_count; n++) {
+ if (n == scmi_id) {
+ return &resource->clock[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+ if (resource == NULL) {
+ return 0U;
+ }
+
+ return resource->clock_count;
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return NULL;
+ }
+
+ return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
+ unsigned long *array, size_t *nb_elts)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if (clock == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (array == NULL) {
+ *nb_elts = 1U;
+ } else if (*nb_elts == 1U) {
+ *array = clk_get_rate(clock->clock_id);
+ } else {
+ return SCMI_GENERIC_ERROR;
+ }
+
+ return SCMI_SUCCESS;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return 0U;
+ }
+
+ return clk_get_rate(clock->clock_id);
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return 0U;
+ }
+
+ return (int32_t)clock->enabled;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool enable_not_disable)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if (clock == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (enable_not_disable) {
+ if (!clock->enabled) {
+ VERBOSE("SCMI clock %u enable\n", scmi_id);
+ clk_enable(clock->clock_id);
+ clock->enabled = true;
+ }
+ } else {
+ if (clock->enabled) {
+ VERBOSE("SCMI clock %u disable\n", scmi_id);
+ clk_disable(clock->clock_id);
+ clock->enabled = false;
+ }
+ }
+
+ return SCMI_SUCCESS;
+}
+
+/*
+ * Platform SCMI reset domains
+ */
+static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+ size_t n;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->rstd_count; n++) {
+ if (n == scmi_id) {
+ return &resource->rstd[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return NULL;
+ }
+
+ return rstd->name;
+}
+
+size_t plat_scmi_rstd_count(unsigned int agent_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+ if (resource == NULL) {
+ return 0U;
+ }
+
+ return resource->rstd_count;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
+ uint32_t state)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+ return SCMI_DENIED;
+ }
+
+ /* Supports only reset with context loss */
+ if (state != 0U) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id);
+
+ if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) {
+ return SCMI_HARDWARE_ERROR;
+ }
+
+ if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) {
+ return SCMI_HARDWARE_ERROR;
+ }
+
+ return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool assert_not_deassert)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (assert_not_deassert) {
+ VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
+ stm32mp_reset_set(rstd->reset_id);
+ } else {
+ VERBOSE("SCMI reset %lu release\n", rstd->reset_id);
+ stm32mp_reset_release(rstd->reset_id);
+ }
+
+ return SCMI_SUCCESS;
+}
+
+/*
+ * Initialize platform SCMI resources
+ */
+void stm32mp1_init_scmi_server(void)
+{
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
+ scmi_smt_init_agent_channel(&scmi_channel[i]);
+ }
+
+ for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) {
+ const struct scmi_agent_resources *res = &agent_resources[i];
+ size_t j;
+
+ for (j = 0U; j < res->clock_count; j++) {
+ struct stm32_scmi_clk *clk = &res->clock[j];
+
+ if ((clk->name == NULL) ||
+ (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) {
+ ERROR("Invalid SCMI clock name\n");
+ panic();
+ }
+
+ /* Sync SCMI clocks with their targeted initial state */
+ if (clk->enabled &&
+ stm32mp_nsec_can_access_clock(clk->clock_id)) {
+ clk_enable(clk->clock_id);
+ }
+ }
+
+ for (j = 0U; j < res->rstd_count; j++) {
+ struct stm32_scmi_rstd *rstd = &res->rstd[j];
+
+ if ((rstd->name == NULL) ||
+ (strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) {
+ ERROR("Invalid SCMI reset domain name\n");
+ panic();
+ }
+ }
+ }
+}
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
new file mode 100644
index 0000000..a0ca697
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+
+#include <platform_def.h>
+#include <stm32mp_shared_resources.h>
+
+/*
+ * Once one starts to get the resource registering state, one cannot register
+ * new resources. This ensures resource state cannot change.
+ */
+static bool registering_locked;
+
+/*
+ * Shared peripherals and resources registration
+ *
+ * Each resource assignation is stored in a table. The state defaults
+ * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
+ *
+ * Resource driver that as not embedded (a.k.a their related CFG_xxx build
+ * directive is disabled) are assigned to the non-secure world.
+ *
+ * Each pin of the GPIOZ bank can be secure or non-secure.
+ *
+ * It is the platform responsibility the ensure resource assignation
+ * matches the access permission firewalls configuration.
+ */
+enum shres_state {
+ SHRES_UNREGISTERED = 0,
+ SHRES_SECURE,
+ SHRES_NON_SECURE,
+};
+
+/* Force uint8_t array for array of enum shres_state for size considerations */
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = {
+ [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
+ [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
+ [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
+ [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
+ [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
+ [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
+ [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
+ [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
+ [STM32MP1_SHRES_IWDG1] = "IWDG1",
+ [STM32MP1_SHRES_USART1] = "USART1",
+ [STM32MP1_SHRES_SPI6] = "SPI6",
+ [STM32MP1_SHRES_I2C4] = "I2C4",
+ [STM32MP1_SHRES_RNG1] = "RNG1",
+ [STM32MP1_SHRES_HASH1] = "HASH1",
+ [STM32MP1_SHRES_CRYP1] = "CRYP1",
+ [STM32MP1_SHRES_I2C6] = "I2C6",
+ [STM32MP1_SHRES_RTC] = "RTC",
+ [STM32MP1_SHRES_MCU] = "MCU",
+ [STM32MP1_SHRES_MDMA] = "MDMA",
+ [STM32MP1_SHRES_PLL3] = "PLL3",
+};
+
+static const char __unused *shres2str_id(enum stm32mp_shres id)
+{
+ assert(id < ARRAY_SIZE(shres2str_id_tbl));
+
+ return shres2str_id_tbl[id];
+}
+
+static const char __unused *shres2str_state_tbl[] = {
+ [SHRES_UNREGISTERED] = "unregistered",
+ [SHRES_NON_SECURE] = "non-secure",
+ [SHRES_SECURE] = "secure",
+};
+
+static const char __unused *shres2str_state(unsigned int state)
+{
+ assert(state < ARRAY_SIZE(shres2str_state_tbl));
+
+ return shres2str_state_tbl[state];
+}
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+ registering_locked = true;
+}
+
+static bool periph_is_non_secure(enum stm32mp_shres id)
+{
+ lock_registering();
+
+ return (shres_state[id] == SHRES_NON_SECURE) ||
+ (shres_state[id] == SHRES_UNREGISTERED);
+}
+
+static bool periph_is_secure(enum stm32mp_shres id)
+{
+ return !periph_is_non_secure(id);
+}
+
+/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
+static int8_t gpioz_nbpin = -1;
+
+static unsigned int get_gpio_nbpin(unsigned int bank)
+{
+ if (bank != GPIO_BANK_Z) {
+ int count = fdt_get_gpio_bank_pin_count(bank);
+
+ assert((count >= 0) && ((unsigned int)count <= (GPIO_PIN_MAX + 1)));
+
+ return (unsigned int)count;
+ }
+
+ if (gpioz_nbpin < 0) {
+ int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z);
+
+ assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT));
+
+ gpioz_nbpin = count;
+ }
+
+ return (unsigned int)gpioz_nbpin;
+}
+
+static unsigned int get_gpioz_nbpin(void)
+{
+ return get_gpio_nbpin(GPIO_BANK_Z);
+}
+
+static void register_periph(enum stm32mp_shres id, unsigned int state)
+{
+ assert((id < STM32MP1_SHRES_COUNT) &&
+ ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE)));
+
+ if (registering_locked) {
+ if (shres_state[id] == state) {
+ return;
+ }
+ panic();
+ }
+
+ if ((shres_state[id] != SHRES_UNREGISTERED) &&
+ (shres_state[id] != state)) {
+ VERBOSE("Cannot change %s from %s to %s\n",
+ shres2str_id(id),
+ shres2str_state(shres_state[id]),
+ shres2str_state(state));
+ panic();
+ }
+
+ if (shres_state[id] == SHRES_UNREGISTERED) {
+ VERBOSE("Register %s as %s\n",
+ shres2str_id(id), shres2str_state(state));
+ }
+
+ if ((id >= STM32MP1_SHRES_GPIOZ(0)) &&
+ (id <= STM32MP1_SHRES_GPIOZ(7)) &&
+ ((unsigned int)(id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
+ ERROR("Invalid GPIO pin %d, %u pin(s) available\n",
+ (int)(id - STM32MP1_SHRES_GPIOZ(0)), get_gpioz_nbpin());
+ panic();
+ }
+
+ shres_state[id] = (uint8_t)state;
+
+ /* Explore clock tree to lock dependencies */
+ if (state == SHRES_SECURE) {
+ enum stm32mp_shres clock_res_id;
+
+ switch (id) {
+ case STM32MP1_SHRES_GPIOZ(0):
+ case STM32MP1_SHRES_GPIOZ(1):
+ case STM32MP1_SHRES_GPIOZ(2):
+ case STM32MP1_SHRES_GPIOZ(3):
+ case STM32MP1_SHRES_GPIOZ(4):
+ case STM32MP1_SHRES_GPIOZ(5):
+ case STM32MP1_SHRES_GPIOZ(6):
+ case STM32MP1_SHRES_GPIOZ(7):
+ clock_res_id = GPIOZ;
+ break;
+ case STM32MP1_SHRES_IWDG1:
+ clock_res_id = IWDG1;
+ break;
+ case STM32MP1_SHRES_USART1:
+ clock_res_id = USART1_K;
+ break;
+ case STM32MP1_SHRES_SPI6:
+ clock_res_id = SPI6_K;
+ break;
+ case STM32MP1_SHRES_I2C4:
+ clock_res_id = I2C4_K;
+ break;
+ case STM32MP1_SHRES_RNG1:
+ clock_res_id = RNG1_K;
+ break;
+ case STM32MP1_SHRES_HASH1:
+ clock_res_id = HASH1;
+ break;
+ case STM32MP1_SHRES_CRYP1:
+ clock_res_id = CRYP1;
+ break;
+ case STM32MP1_SHRES_I2C6:
+ clock_res_id = I2C6_K;
+ break;
+ case STM32MP1_SHRES_RTC:
+ clock_res_id = RTC;
+ break;
+ default:
+ /* No clock resource dependency */
+ return;
+ }
+
+ stm32mp1_register_clock_parents_secure(clock_res_id);
+ }
+}
+
+/* Register resource by ID */
+void stm32mp_register_secure_periph(enum stm32mp_shres id)
+{
+ register_periph(id, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
+{
+ register_periph(id, SHRES_NON_SECURE);
+}
+
+static void register_periph_iomem(uintptr_t base, unsigned int state)
+{
+ enum stm32mp_shres id;
+
+ switch (base) {
+ case CRYP1_BASE:
+ id = STM32MP1_SHRES_CRYP1;
+ break;
+ case HASH1_BASE:
+ id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_BASE:
+ id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_BASE:
+ id = STM32MP1_SHRES_I2C6;
+ break;
+ case IWDG1_BASE:
+ id = STM32MP1_SHRES_IWDG1;
+ break;
+ case RNG1_BASE:
+ id = STM32MP1_SHRES_RNG1;
+ break;
+ case RTC_BASE:
+ id = STM32MP1_SHRES_RTC;
+ break;
+ case SPI6_BASE:
+ id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_BASE:
+ id = STM32MP1_SHRES_USART1;
+ break;
+
+ case GPIOA_BASE:
+ case GPIOB_BASE:
+ case GPIOC_BASE:
+ case GPIOD_BASE:
+ case GPIOE_BASE:
+ case GPIOF_BASE:
+ case GPIOG_BASE:
+ case GPIOH_BASE:
+ case GPIOI_BASE:
+ case GPIOJ_BASE:
+ case GPIOK_BASE:
+ case USART2_BASE:
+ case USART3_BASE:
+ case UART4_BASE:
+ case UART5_BASE:
+ case USART6_BASE:
+ case UART7_BASE:
+ case UART8_BASE:
+ case IWDG2_BASE:
+ /* Allow drivers to register some non-secure resources */
+ VERBOSE("IO for non-secure resource 0x%x\n",
+ (unsigned int)base);
+ if (state != SHRES_NON_SECURE) {
+ panic();
+ }
+
+ return;
+
+ default:
+ panic();
+ }
+
+ register_periph(id, state);
+}
+
+void stm32mp_register_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_NON_SECURE);
+}
+
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
+ break;
+ default:
+ ERROR("GPIO bank %u cannot be secured\n", bank);
+ panic();
+ }
+}
+
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
+{
+ unsigned int non_secure = 0U;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return true;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) {
+ non_secure++;
+ }
+ }
+
+ return non_secure == get_gpioz_nbpin();
+}
+
+static bool stm32mp_gpio_bank_is_secure(unsigned int bank)
+{
+ unsigned int secure = 0U;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return false;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
+ secure++;
+ }
+ }
+
+ return secure == get_gpioz_nbpin();
+}
+
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+{
+ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+ switch (clock_id) {
+ case CK_CSI:
+ case CK_HSE:
+ case CK_HSE_DIV2:
+ case CK_HSI:
+ case CK_LSE:
+ case CK_LSI:
+ case PLL1_P:
+ case PLL1_Q:
+ case PLL1_R:
+ case PLL2_P:
+ case PLL2_Q:
+ case PLL2_R:
+ case PLL3_P:
+ case PLL3_Q:
+ case PLL3_R:
+ case RTCAPB:
+ return true;
+ case GPIOZ:
+ /* Allow clock access if at least one pin is non-secure */
+ return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
+ case CRYP1:
+ shres_id = STM32MP1_SHRES_CRYP1;
+ break;
+ case HASH1:
+ shres_id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_K:
+ shres_id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_K:
+ shres_id = STM32MP1_SHRES_I2C6;
+ break;
+ case IWDG1:
+ shres_id = STM32MP1_SHRES_IWDG1;
+ break;
+ case RNG1_K:
+ shres_id = STM32MP1_SHRES_RNG1;
+ break;
+ case RTC:
+ shres_id = STM32MP1_SHRES_RTC;
+ break;
+ case SPI6_K:
+ shres_id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_K:
+ shres_id = STM32MP1_SHRES_USART1;
+ break;
+ default:
+ return false;
+ }
+
+ return periph_is_non_secure(shres_id);
+}
+
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
+{
+ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+ switch (reset_id) {
+ case CRYP1_R:
+ shres_id = STM32MP1_SHRES_CRYP1;
+ break;
+ case GPIOZ_R:
+ /* GPIOZ reset mandates all pins are non-secure */
+ return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
+ case HASH1_R:
+ shres_id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_R:
+ shres_id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_R:
+ shres_id = STM32MP1_SHRES_I2C6;
+ break;
+ case MCU_R:
+ shres_id = STM32MP1_SHRES_MCU;
+ break;
+ case MDMA_R:
+ shres_id = STM32MP1_SHRES_MDMA;
+ break;
+ case RNG1_R:
+ shres_id = STM32MP1_SHRES_RNG1;
+ break;
+ case SPI6_R:
+ shres_id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_R:
+ shres_id = STM32MP1_SHRES_USART1;
+ break;
+ default:
+ return false;
+ }
+
+ return periph_is_non_secure(shres_id);
+}
+
+static bool mckprot_protects_periph(enum stm32mp_shres id)
+{
+ switch (id) {
+ case STM32MP1_SHRES_MCU:
+ case STM32MP1_SHRES_PLL3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
+{
+ assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
+ (id > STM32MP1_SHRES_GPIOZ(7)));
+
+ if (periph_is_non_secure(id)) {
+ return ETZPC_DECPROT_NS_RW;
+ }
+
+ return ETZPC_DECPROT_S_RW;
+}
+
+static void set_etzpc_secure_configuration(void)
+{
+ /* Some system peripherals shall be secure */
+ etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
+ etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
+ etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+ ETZPC_DECPROT_NS_R_S_W);
+ etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+ ETZPC_DECPROT_NS_R_S_W);
+
+ /* Configure ETZPC with peripheral registering */
+ etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_CRYP1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_HASH1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
+ shres2decprot_attr(STM32MP1_SHRES_I2C4));
+ etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
+ shres2decprot_attr(STM32MP1_SHRES_I2C6));
+ etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_IWDG1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_RNG1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_USART1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
+ shres2decprot_attr(STM32MP1_SHRES_SPI6));
+}
+
+static void check_rcc_secure_configuration(void)
+{
+ uint32_t n;
+ uint32_t error = 0U;
+ bool mckprot = stm32mp1_rcc_is_mckprot();
+ bool secure = stm32mp1_rcc_is_secure();
+
+ for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
+ if (shres_state[n] != SHRES_SECURE) {
+ continue;
+ }
+
+ if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
+ ERROR("RCC %s MCKPROT %s and %s secure\n",
+ secure ? "secure" : "non-secure",
+ mckprot ? "set" : "not set",
+ shres2str_id(n));
+ error++;
+ }
+ }
+
+ if (error != 0U) {
+ panic();
+ }
+}
+
+static void set_gpio_secure_configuration(void)
+{
+ uint32_t pin;
+
+ for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+ bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+ set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
+ }
+}
+
+static void print_shared_resources_state(void)
+{
+ unsigned int id;
+
+ for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
+ switch (shres_state[id]) {
+ case SHRES_SECURE:
+ INFO("stm32mp1 %s is secure\n", shres2str_id(id));
+ break;
+ case SHRES_NON_SECURE:
+ case SHRES_UNREGISTERED:
+ VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id));
+ break;
+ default:
+ VERBOSE("stm32mp %s is invalid\n", shres2str_id(id));
+ panic();
+ }
+ }
+}
+
+void stm32mp_lock_periph_registering(void)
+{
+ registering_locked = true;
+
+ print_shared_resources_state();
+
+ check_rcc_secure_configuration();
+ set_etzpc_secure_configuration();
+ set_gpio_secure_configuration();
+}
diff --git a/plat/st/stm32mp1/stm32mp1_stack_protector.c b/plat/st/stm32mp1/stm32mp1_stack_protector.c
new file mode 100644
index 0000000..14e8e16
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_stack_protector.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE 2144346116U
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * Ideally, a random number should be returned instead of the
+ * combination of a timer's value and a compile-time constant.
+ */
+ return RANDOM_CANARY_VALUE ^ (u_register_t)read_cntpct_el0();
+}
+
diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c
new file mode 100644
index 0000000..ff79428
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stpmic1.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp1_private.h>
+
+/*
+ * SYSCFG REGISTER OFFSET (base relative)
+ */
+#define SYSCFG_BOOTR 0x00U
+#define SYSCFG_BOOTCR 0x0CU
+#if STM32MP15
+#define SYSCFG_IOCTRLSETR 0x18U
+#define SYSCFG_ICNR 0x1CU
+#endif
+#define SYSCFG_CMPCR 0x20U
+#define SYSCFG_CMPENSETR 0x24U
+#define SYSCFG_CMPENCLRR 0x28U
+#if STM32MP13
+#define SYSCFG_CMPSD1CR 0x30U
+#define SYSCFG_CMPSD1ENSETR 0x34U
+#define SYSCFG_CMPSD1ENCLRR 0x38U
+#define SYSCFG_CMPSD2CR 0x40U
+#define SYSCFG_CMPSD2ENSETR 0x44U
+#define SYSCFG_CMPSD2ENCLRR 0x48U
+#define SYSCFG_HSLVEN0R 0x50U
+#endif
+#define SYSCFG_IDC 0x380U
+
+#define CMPCR_CMPENSETR_OFFSET 0x4U
+#define CMPCR_CMPENCLRR_OFFSET 0x8U
+
+/*
+ * SYSCFG_BOOTR Register
+ */
+#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
+#if STM32MP15
+#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
+#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
+#endif
+
+/*
+ * SYSCFG_BOOTCR Register
+ */
+#define SYSCFG_BOOTCR_BMEN BIT(0)
+
+/*
+ * SYSCFG_IOCTRLSETR Register
+ */
+#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
+#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
+#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
+
+/*
+ * SYSCFG_ICNR Register
+ */
+#define SYSCFG_ICNR_AXI_M9 BIT(9)
+
+/*
+ * SYSCFG_CMPCR Register
+ */
+#define SYSCFG_CMPCR_SW_CTRL BIT(1)
+#define SYSCFG_CMPCR_READY BIT(8)
+#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
+#define SYSCFG_CMPCR_RANSRC_SHIFT 16
+#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
+#define SYSCFG_CMPCR_ANSRC_SHIFT 24
+
+#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
+
+/*
+ * SYSCFG_CMPENSETR Register
+ */
+#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
+
+/*
+ * HSLV definitions
+ */
+#define HSLV_IDX_TPIU 0U
+#define HSLV_IDX_QSPI 1U
+#define HSLV_IDX_ETH1 2U
+#define HSLV_IDX_ETH2 3U
+#define HSLV_IDX_SDMMC1 4U
+#define HSLV_IDX_SDMMC2 5U
+#define HSLV_IDX_SPI1 6U
+#define HSLV_IDX_SPI2 7U
+#define HSLV_IDX_SPI3 8U
+#define HSLV_IDX_SPI4 9U
+#define HSLV_IDX_SPI5 10U
+#define HSLV_IDX_LTDC 11U
+#define HSLV_NB_IDX 12U
+
+#define HSLV_KEY 0x1018U
+
+/*
+ * SYSCFG_IDC Register
+ */
+#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16)
+#define SYSCFG_IDC_REV_ID_SHIFT 16
+
+static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
+{
+ uint64_t start;
+
+ start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
+
+ while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
+ if (timeout_elapsed(start)) {
+ /* Failure on IO compensation enable is not a issue: warn only. */
+ WARN("IO compensation cell not ready\n");
+ break;
+ }
+ }
+
+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
+}
+
+static void disable_io_comp_cell(uintptr_t cmpcr_off)
+{
+ uint32_t value;
+
+ if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
+ ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
+ SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
+ return;
+ }
+
+ value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
+
+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
+
+ value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
+ value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
+
+ mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
+
+ mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
+}
+
+#if STM32MP13
+static int get_regu_max_voltage(void *fdt, int sdmmc_node,
+ const char *regu_name, uint32_t *regu_val)
+{
+ int node;
+ const fdt32_t *cuint;
+
+ cuint = fdt_getprop(fdt, sdmmc_node, regu_name, NULL);
+ if (cuint == NULL) {
+ return -ENODEV;
+ }
+
+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+ if (node < 0) {
+ return -ENODEV;
+ }
+
+ cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
+ if (cuint == NULL) {
+ return -ENODEV;
+ }
+
+ *regu_val = fdt32_to_cpu(*cuint);
+
+ return 0;
+}
+
+static bool sdmmc_is_low_voltage(uintptr_t sdmmc_base)
+{
+ int ret;
+ int node;
+ void *fdt = NULL;
+ uint32_t regu_max_val;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return false;
+ }
+
+ if (fdt == NULL) {
+ return false;
+ }
+
+ node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, sdmmc_base);
+ if (node < 0) {
+ /* No SD or eMMC device on this instance, enable HSLV */
+ return true;
+ }
+
+ ret = get_regu_max_voltage(fdt, node, "vqmmc-supply", &regu_max_val);
+ if ((ret < 0) || (regu_max_val > 1800000U)) {
+ /*
+ * The vqmmc-supply property should always be present for eMMC.
+ * For SD-card, if it is not, then the card only supports 3.3V.
+ */
+ return false;
+ }
+
+ return true;
+}
+
+static void enable_hslv_by_index(uint32_t index)
+{
+ bool apply_hslv;
+
+ assert(index < HSLV_NB_IDX);
+
+ switch (index) {
+ case HSLV_IDX_SDMMC1:
+ apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC1_BASE);
+ break;
+ case HSLV_IDX_SDMMC2:
+ apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC2_BASE);
+ break;
+ default:
+ apply_hslv = true;
+ break;
+ }
+
+ if (apply_hslv) {
+ mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + index * sizeof(uint32_t), HSLV_KEY);
+ }
+}
+#endif
+
+static void enable_high_speed_mode_low_voltage(void)
+{
+#if STM32MP13
+ uint32_t idx;
+
+ for (idx = 0U; idx < HSLV_NB_IDX; idx++) {
+ enable_hslv_by_index(idx);
+ }
+#endif
+#if STM32MP15
+ mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
+ SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+ SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+ SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+ SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+ SYSCFG_IOCTRLSETR_HSLVEN_SPI);
+#endif
+}
+
+static void stm32mp1_syscfg_set_hslv(void)
+{
+ uint32_t otp_value;
+ uint32_t vdd_voltage;
+ bool product_below_2v5;
+
+ /*
+ * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
+ * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
+ * It could be disabled for low frequencies or if AFMUX is selected
+ * but the function is not used, typically for TRACE.
+ * If high speed low voltage pad mode is node enable, platform will
+ * over consume.
+ *
+ * WARNING:
+ * Enabling High Speed mode while VDD > 2.7V
+ * with the OTP product_below_2v5 (OTP 18, BIT 13)
+ * erroneously set to 1 can damage the SoC!
+ * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
+ * but this value needs to be consistent with board design.
+ */
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
+ panic();
+ }
+
+ product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
+
+ /* Get VDD supply */
+ vdd_voltage = dt_get_pwr_vdd_voltage();
+
+ /* Check if VDD is Low Voltage */
+ if (vdd_voltage == 0U) {
+ WARN("VDD unknown\n");
+ } else if (vdd_voltage < 2700000U) {
+ enable_high_speed_mode_low_voltage();
+
+ if (!product_below_2v5) {
+ INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
+ }
+ } else {
+ if (product_below_2v5) {
+ ERROR("Product_below_2v5=1:\n");
+ ERROR("\tHSLVEN update is destructive,\n");
+ ERROR("\tno update as VDD > 2.7V\n");
+ panic();
+ }
+ }
+}
+
+void stm32mp1_syscfg_init(void)
+{
+#if STM32MP15
+ uint32_t bootr;
+
+ /*
+ * Interconnect update : select master using the port 1.
+ * LTDC = AXI_M9.
+ */
+ mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
+
+ /* Disable Pull-Down for boot pin connected to VDD */
+ bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
+ SYSCFG_BOOTR_BOOT_MASK;
+ mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
+ bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
+#endif
+
+ stm32mp1_syscfg_set_hslv();
+
+ stm32mp1_syscfg_enable_io_compensation_start();
+}
+
+void stm32mp1_syscfg_enable_io_compensation_start(void)
+{
+ /*
+ * Activate automatic I/O compensation.
+ * Warning: need to ensure CSI enabled and ready in clock driver.
+ * Enable non-secure clock, we assume non-secure is suspended.
+ */
+ clk_enable(SYSCFG);
+
+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
+ SYSCFG_CMPENSETR_MPU_EN);
+#if STM32MP13
+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR,
+ SYSCFG_CMPENSETR_MPU_EN);
+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR,
+ SYSCFG_CMPENSETR_MPU_EN);
+
+#endif
+}
+
+void stm32mp1_syscfg_enable_io_compensation_finish(void)
+{
+ enable_io_comp_cell_finish(SYSCFG_CMPCR);
+#if STM32MP13
+ enable_io_comp_cell_finish(SYSCFG_CMPSD1CR);
+ enable_io_comp_cell_finish(SYSCFG_CMPSD2CR);
+#endif
+}
+
+void stm32mp1_syscfg_disable_io_compensation(void)
+{
+ clk_enable(SYSCFG);
+
+ /*
+ * Deactivate automatic I/O compensation.
+ * Warning: CSI is disabled automatically in STOP if not
+ * requested for other usages and always OFF in STANDBY.
+ * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
+ */
+ disable_io_comp_cell(SYSCFG_CMPCR);
+#if STM32MP13
+ disable_io_comp_cell(SYSCFG_CMPSD1CR);
+ disable_io_comp_cell(SYSCFG_CMPSD2CR);
+#endif
+
+ clk_disable(SYSCFG);
+}
+
+/*
+ * @brief Get silicon revision from SYSCFG registers.
+ * @retval chip version (REV_ID).
+ */
+uint32_t stm32mp1_syscfg_get_chip_version(void)
+{
+ return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
+ SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
+}
+
+/*
+ * @brief Get device ID from SYSCFG registers.
+ * @retval device ID (DEV_ID).
+ */
+uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
+{
+ return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
+}
+
+#if STM32MP13
+void stm32mp1_syscfg_boot_mode_enable(void)
+{
+ mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
+}
+
+void stm32mp1_syscfg_boot_mode_disable(void)
+{
+ mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
+}
+#endif
diff --git a/plat/st/stm32mp1/stm32mp1_tbb_cert.c b/plat/st/stm32mp1/stm32mp1_tbb_cert.c
new file mode 100644
index 0000000..0e77397
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_tbb_cert.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "tbbr/tbb_ext.h"
+#include "tbbr/tbb_key.h"
+
+#include "tbbr/stm32mp1_tbb_cert.h"
+
+/*
+ * Certificates used in the chain of trust
+ *
+ * The order of the certificates must follow the enumeration specified in
+ * stm32mp1_tbb_cert.h. All certificates are self-signed, so the issuer certificate
+ * field points to itself.
+ */
+static cert_t stm32mp1_tbb_certs[] = {
+ [0] = {
+ .id = STM32MP_CONFIG_CERT,
+ .opt = "stm32mp-cfg-cert",
+ .help_msg = "STM32MP Config Certificate (output file)",
+ .fn = NULL,
+ .cn = "STM32MP config FW Certificate",
+ .key = ROT_KEY,
+ .issuer = STM32MP_CONFIG_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ HW_CONFIG_HASH_EXT,
+ FW_CONFIG_HASH_EXT
+ },
+ .num_ext = 3
+ },
+};
+
+PLAT_REGISTER_COT(stm32mp1_tbb_certs);
diff --git a/plat/st/stm32mp1/stm32mp1_topology.c b/plat/st/stm32mp1/stm32mp1_topology.c
new file mode 100644
index 0000000..59a0c17
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_topology.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+/* 1 cluster, all cores into */
+static const unsigned char stm32mp1_power_domain_tree_desc[] = {
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_CORE_COUNT,
+};
+
+/* This function returns the platform topology */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return stm32mp1_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+ u_register_t mpidr_copy = mpidr;
+
+ mpidr_copy &= MPIDR_AFFINITY_MASK;
+
+ if ((mpidr_copy & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) {
+ return -1;
+ }
+
+ cluster_id = (mpidr_copy >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr_copy >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in one
+ * of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_CORE_COUNT) {
+ return -1;
+ }
+
+ return (int)cpu_id;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_usb_dfu.c b/plat/st/stm32mp1/stm32mp1_usb_dfu.c
new file mode 100644
index 0000000..0fe2d24
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_usb_dfu.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32mp1_usb.h>
+#include <drivers/usb_device.h>
+
+#include <platform_def.h>
+#include <stm32cubeprogrammer.h>
+#include <stm32mp_common.h>
+#include <usb_dfu.h>
+
+/* String size (1 byte) + type (1 byte) + 24 UTF16 characters: 2 bytes each */
+#define SIZ_STRING_SERIAL U(24)
+#define USB_SIZ_STRING_SERIAL (1U + 1U + (SIZ_STRING_SERIAL * 2U))
+#define USBD_MAX_STR_DESC_SIZ 0x100
+#define USBD_VID 0x0483
+#define USBD_PID 0xDF11
+#define USBD_LANGID_STRING 0x409
+#define USBD_MANUFACTURER_STRING "STMicroelectronics"
+#define USBD_CONFIGURATION_STRING "DFU Config"
+#define USBD_INTERFACE_STRING "DFU Interface"
+
+#if STM32MP13
+#define USB_DFU_ITF_NUM 2
+#endif
+#if STM32MP15
+#define USB_DFU_ITF_NUM 6
+#endif
+
+#define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM)
+
+/* DFU devices */
+static struct usb_dfu_handle usb_dfu_handle;
+
+/* USB Standard Device Descriptor */
+static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = {
+ USB_LEN_DEV_DESC, /* bLength */
+ USB_DESC_TYPE_DEVICE, /* bDescriptorType */
+ 0x00, /* bcdUSB */
+ 0x02, /* version */
+ 0x00, /* bDeviceClass */
+ 0x00, /* bDeviceSubClass */
+ 0x00, /* bDeviceProtocol */
+ USB_MAX_EP0_SIZE, /* bMaxPacketSize */
+ LOBYTE(USBD_VID), /* idVendor */
+ HIBYTE(USBD_VID), /* idVendor */
+ LOBYTE(USBD_PID), /* idVendor */
+ HIBYTE(USBD_PID), /* idVendor */
+ 0x00, /* bcdDevice rel. 2.00 */
+ 0x02,
+ USBD_IDX_MFC_STR, /* Index of manufacturer string */
+ USBD_IDX_PRODUCT_STR, /* Index of product string */
+ USBD_IDX_SERIAL_STR, /* Index of serial number string */
+ USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
+}; /* USB_DeviceDescriptor */
+
+/* USB Standard String Descriptor */
+static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = {
+ USB_LEN_LANGID_STR_DESC,
+ USB_DESC_TYPE_STRING,
+ LOBYTE(USBD_LANGID_STRING),
+ HIBYTE(USBD_LANGID_STRING),
+};
+
+/* USB Standard Device Descriptor */
+static const uint8_t
+usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = {
+ USB_LEN_DEV_QUALIFIER_DESC,
+ USB_DESC_TYPE_DEVICE_QUALIFIER,
+ 0x00,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x01,
+ 0x00,
+};
+
+/* USB serial number: build dynamically */
+static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1];
+
+/* USB DFU device Configuration Descriptor */
+static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = {
+ 0x09, /* bLength: Configuration Descriptor size */
+ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
+ USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
+ 0x00,
+ 0x01, /* bNumInterfaces: 1 interface */
+ 0x01, /* bConfigurationValue: Configuration value */
+ 0x02, /* iConfiguration: Index of string descriptor for configuration */
+ 0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */
+ 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
+
+ /* Descriptor of DFU interface 0 Alternate setting 0..N */
+ USBD_DFU_IF_DESC(0),
+ USBD_DFU_IF_DESC(1),
+#if USB_DFU_ITF_NUM > 2
+ USBD_DFU_IF_DESC(2),
+#endif
+#if USB_DFU_ITF_NUM > 3
+ USBD_DFU_IF_DESC(3),
+#endif
+#if USB_DFU_ITF_NUM > 4
+ USBD_DFU_IF_DESC(4),
+#endif
+#if USB_DFU_ITF_NUM > 5
+ USBD_DFU_IF_DESC(5),
+#endif
+ /* DFU Functional Descriptor */
+ 0x09, /* blength = 9 Bytes */
+ DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */
+ DFU_BM_ATTRIBUTE, /* bmAttribute for DFU */
+ 0xFF, /* DetachTimeOut = 255 ms */
+ 0x00,
+ TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */
+ ((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */
+ ((USB_DFU_VERSION >> 8) & 0xFF)
+};
+
+/* The user strings: one by alternate as defined in USBD_DFU_IF_DESC */
+#if STM32MP13
+const char *const if_desc_string[USB_DFU_ITF_NUM] = {
+ "@SSBL /0x03/1*16Me",
+ "@virtual /0xF1/1*512Ba"
+};
+#endif
+#if STM32MP15
+const char *const if_desc_string[USB_DFU_ITF_NUM] = {
+ "@Partition0 /0x00/1*256Ke",
+ "@FSBL /0x01/1*1Me",
+ "@Partition2 /0x02/1*1Me",
+ "@Partition3 /0x03/1*16Me",
+ "@Partition4 /0x04/1*16Me",
+ "@virtual /0xF1/1*512Ba"
+};
+#endif
+
+/* Buffer to build the unicode string provided to USB device stack */
+static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ];
+
+/*
+ * Convert Ascii string into unicode one
+ * desc : descriptor buffer
+ * unicode : Formatted string buffer (unicode)
+ * len : descriptor length
+ */
+static void stm32mp1_get_string(const char *desc, uint8_t *unicode, uint16_t *len)
+{
+ uint8_t idx = 0U;
+
+ if (desc == NULL) {
+ return;
+ }
+
+ *len = strlen(desc) * 2U + 2U;
+ unicode[idx++] = *len;
+ unicode[idx++] = USB_DESC_TYPE_STRING;
+
+ while (*desc != '\0') {
+ unicode[idx++] = *desc++;
+ unicode[idx++] = 0x00U;
+ }
+}
+
+/*
+ * Create the serial number string descriptor
+ */
+static void update_serial_num_string(void)
+{
+ uint8_t i;
+ char serial_string[SIZ_STRING_SERIAL + 2U];
+ /* serial number is set to 0 */
+ uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U};
+ uint32_t otp;
+ uint32_t len;
+ uint16_t length;
+
+ if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) {
+ ERROR("BSEC: Get UID_OTP number Error\n");
+ return;
+ }
+
+ if ((len / __WORD_BIT) != UID_WORD_NB) {
+ ERROR("BSEC: Get UID_OTP length Error\n");
+ return;
+ }
+
+ for (i = 0; i < UID_WORD_NB; i++) {
+ if (bsec_shadow_read_otp(&deviceserial[i], i + otp) !=
+ BSEC_OK) {
+ ERROR("BSEC: UID%d Error\n", i);
+ return;
+ }
+ }
+ /* build serial number with OTP value as in ROM code */
+ snprintf(serial_string, sizeof(serial_string), "%08X%08X%08X",
+ deviceserial[0], deviceserial[1], deviceserial[2]);
+
+ length = USB_SIZ_STRING_SERIAL;
+ stm32mp1_get_string(serial_string, usb_stm32mp1_serial, &length);
+}
+
+/*
+ * Return Device Qualifier descriptor
+ * length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length)
+{
+ *length = sizeof(usbd_stm32mp1_qualifier_desc);
+
+ return (uint8_t *)usbd_stm32mp1_qualifier_desc;
+}
+
+/*
+ * Return configuration descriptor
+ * length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_config_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_config_desc);
+
+ return (uint8_t *)usb_stm32mp1_config_desc;
+}
+
+/*
+ * Returns the device descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_device_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_desc);
+
+ return (uint8_t *)usb_stm32mp1_desc;
+}
+
+/*
+ * Returns the LangID string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_lang_id_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_lang_id_desc);
+
+ return (uint8_t *)usb_stm32mp1_lang_id_desc;
+}
+
+/*
+ * Returns the product string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_product_desc(uint16_t *length)
+{
+ char name[STM32_SOC_NAME_SIZE];
+ char product[128];
+ uint32_t chip_id;
+ uint32_t chip_version;
+
+ stm32mp_get_soc_name(name);
+ chip_id = stm32mp_get_chip_dev_id();
+ chip_version = stm32mp_get_chip_version();
+
+ snprintf(product, sizeof(product),
+ "DFU @Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,",
+ chip_id, chip_version, name);
+
+ stm32mp1_get_string(product, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Returns the manufacturer string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length)
+{
+ stm32mp1_get_string(USBD_MANUFACTURER_STRING, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Returns the serial number string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_serial_desc(uint16_t *length)
+{
+ *length = USB_SIZ_STRING_SERIAL;
+
+ return (uint8_t *)usb_stm32mp1_serial;
+}
+
+/*
+ * Returns the configuration string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_config_desc(uint16_t *length)
+{
+ stm32mp1_get_string(USBD_CONFIGURATION_STRING, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Returns the interface string descriptor.
+ * length : Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_interface_desc(uint16_t *length)
+{
+ stm32mp1_get_string(USBD_INTERFACE_STRING, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Manages the transfer of memory interfaces string descriptors.
+ * index: descriptor index
+ * length : pointer data length
+ * return : pointer to the descriptor table or NULL if the descriptor
+ * is not supported.
+ */
+static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length)
+{
+ if (index >= ARRAY_SIZE(if_desc_string)) {
+ return NULL;
+ }
+
+ stm32mp1_get_string(if_desc_string[index], usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+static const struct usb_desc dfu_desc = {
+ .get_device_desc = stm32mp1_device_desc,
+ .get_lang_id_desc = stm32mp1_lang_id_desc,
+ .get_manufacturer_desc = stm32mp1_manufacturer_desc,
+ .get_product_desc = stm32mp1_product_desc,
+ .get_configuration_desc = stm32mp1_config_desc,
+ .get_serial_desc = stm32mp1_serial_desc,
+ .get_interface_desc = stm32mp1_interface_desc,
+ .get_usr_desc = stm32mp1_get_usr_desc,
+ .get_config_desc = stm32mp1_get_config_desc,
+ .get_device_qualifier_desc = stm32mp1_get_qualifier_desc,
+ /* only HS is supported, as ROM code */
+ .get_other_speed_config_desc = NULL,
+};
+
+static struct usb_handle usb_core_handle;
+static struct pcd_handle pcd_handle;
+
+struct usb_handle *usb_dfu_plat_init(void)
+{
+ /* Prepare USB Driver */
+ pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE;
+ pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE;
+ stm32mp1_usb_init_driver(&usb_core_handle, &pcd_handle,
+ (uint32_t *)USB_OTG_BASE);
+
+#if STM32MP15
+ /* STM32MP15 = keep the configuration from ROM code */
+ usb_core_handle.ep0_state = USBD_EP0_DATA_IN;
+ usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
+#endif
+
+ /* Update the serial number string descriptor from the unique ID */
+ update_serial_num_string();
+
+ /* Prepare USB DFU stack */
+ usb_dfu_register(&usb_core_handle, &usb_dfu_handle);
+
+ /* Register DFU descriptor in USB stack */
+ register_platform(&usb_core_handle, &dfu_desc);
+
+ return &usb_core_handle;
+}
+
+/* Link between USB alternate and STM32CubeProgramer phase */
+uint8_t usb_dfu_get_phase(uint8_t alt)
+{
+ uint8_t ret;
+
+ switch (alt) {
+#if STM32MP13
+ case 0:
+ ret = PHASE_SSBL;
+ break;
+ case 1:
+ ret = PHASE_CMD;
+ break;
+#endif
+#if STM32MP15
+ case 3:
+ ret = PHASE_SSBL;
+ break;
+ case 5:
+ ret = PHASE_CMD;
+ break;
+#endif
+ default:
+ ret = PHASE_RESET;
+ break;
+ }
+
+ return ret;
+}
diff --git a/plat/ti/k3/board/generic/board.mk b/plat/ti/k3/board/generic/board.mk
new file mode 100644
index 0000000..ef74cd6
--- /dev/null
+++ b/plat/ti/k3/board/generic/board.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_BASE ?= 0x9e800000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x80080000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x82000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
+
+# Define sec_proxy usage as the full prioritized communication scheme
+K3_SEC_PROXY_LITE := 0
+$(eval $(call add_define,K3_SEC_PROXY_LITE))
+
+# System coherency is managed in hardware
+USE_COHERENT_MEM := 1
+
+PLAT_INCLUDES += \
+ -Iplat/ti/k3/board/generic/include \
diff --git a/plat/ti/k3/board/generic/include/board_def.h b/plat/ti/k3/board/generic/include/board_def.h
new file mode 100644
index 0000000..4ff687c
--- /dev/null
+++ b/plat/ti/k3/board/generic/include/board_def.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_DEF_H
+#define BOARD_DEF_H
+
+#include <lib/utils_def.h>
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT U(2)
+#define K3_CLUSTER1_CORE_COUNT U(2)
+#define K3_CLUSTER2_CORE_COUNT U(2)
+#define K3_CLUSTER3_CORE_COUNT U(2)
+
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ *
+ * The link addresses are determined by SEC_SRAM_BASE + offset.
+ * When ENABLE_PIE is set, the TF images can be loaded anywhere, so
+ * SEC_SRAM_BASE is really arbitrary.
+ *
+ * When ENABLE_PIE is unset, SEC_SRAM_BASE should be chosen so that
+ * it matches to the physical address where BL31 is loaded, that is,
+ * SEC_SRAM_BASE should be the base address of the RAM region.
+ *
+ * Lets make things explicit by mapping SRAM_BASE to 0x0 since ENABLE_PIE is
+ * defined as default for our platform.
+ */
+#define SEC_SRAM_BASE UL(0x00000000) /* PIE remapped on fly */
+#define SEC_SRAM_SIZE UL(0x00020000) /* 128k */
+
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define PLAT_PROC_START_ID U(32)
+#define PLAT_PROC_DEVICE_START_ID U(202)
+#define PLAT_CLUSTER_DEVICE_START_ID U(198)
+
+#endif /* BOARD_DEF_H */
diff --git a/plat/ti/k3/board/j784s4/board.mk b/plat/ti/k3/board/j784s4/board.mk
new file mode 100644
index 0000000..92433ab
--- /dev/null
+++ b/plat/ti/k3/board/j784s4/board.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_BASE ?= 0x9e800000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x80080000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x82000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
+
+# Define sec_proxy usage as the full prioritized communication scheme
+K3_SEC_PROXY_LITE := 0
+$(eval $(call add_define,K3_SEC_PROXY_LITE))
+
+# System coherency is managed in hardware
+USE_COHERENT_MEM := 1
+
+PLAT_INCLUDES += \
+ -Iplat/ti/k3/board/j784s4/include \
diff --git a/plat/ti/k3/board/j784s4/include/board_def.h b/plat/ti/k3/board/j784s4/include/board_def.h
new file mode 100644
index 0000000..c2debc7
--- /dev/null
+++ b/plat/ti/k3/board/j784s4/include/board_def.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_DEF_H
+#define BOARD_DEF_H
+
+#include <lib/utils_def.h>
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT U(4)
+#define K3_CLUSTER1_CORE_COUNT U(4)
+#define K3_CLUSTER2_CORE_COUNT U(0)
+#define K3_CLUSTER3_CORE_COUNT U(0)
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ *
+ * The link addresses are determined by SEC_SRAM_BASE + offset.
+ * When ENABLE_PIE is set, the TF images can be loaded anywhere, so
+ * SEC_SRAM_BASE is really arbitrary.
+ *
+ * When ENABLE_PIE is unset, SEC_SRAM_BASE should be chosen so that
+ * it matches to the physical address where BL31 is loaded, that is,
+ * SEC_SRAM_BASE should be the base address of the RAM region.
+ *
+ * Lets make things explicit by mapping SRAM_BASE to 0x0 since ENABLE_PIE is
+ * defined as default for our platform.
+ */
+#define SEC_SRAM_BASE UL(0x00000000) /* PIE remapped on fly */
+#define SEC_SRAM_SIZE UL(0x00020000) /* 128k */
+
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define PLAT_PROC_START_ID U(32)
+
+#define PLAT_PROC_DEVICE_START_ID U(202)
+#define PLAT_CLUSTER_DEVICE_START_ID U(198)
+
+#endif /* BOARD_DEF_H */
diff --git a/plat/ti/k3/board/lite/board.mk b/plat/ti/k3/board/lite/board.mk
new file mode 100644
index 0000000..76246be
--- /dev/null
+++ b/plat/ti/k3/board/lite/board.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+BL32_BASE ?= 0x9e800000
+$(eval $(call add_define,BL32_BASE))
+
+PRELOADED_BL33_BASE ?= 0x80080000
+$(eval $(call add_define,PRELOADED_BL33_BASE))
+
+K3_HW_CONFIG_BASE ?= 0x82000000
+$(eval $(call add_define,K3_HW_CONFIG_BASE))
+
+# Define sec_proxy usage as the lite version
+K3_SEC_PROXY_LITE := 1
+$(eval $(call add_define,K3_SEC_PROXY_LITE))
+
+# We dont have system level coherency capability
+USE_COHERENT_MEM := 0
+
+PLAT_INCLUDES += \
+ -Iplat/ti/k3/board/lite/include \
diff --git a/plat/ti/k3/board/lite/include/board_def.h b/plat/ti/k3/board/lite/include/board_def.h
new file mode 100644
index 0000000..fd4e5b1
--- /dev/null
+++ b/plat/ti/k3/board/lite/include/board_def.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOARD_DEF_H
+#define BOARD_DEF_H
+
+#include <lib/utils_def.h>
+
+/* The ports must be in order and contiguous */
+#define K3_CLUSTER0_CORE_COUNT U(4)
+#define K3_CLUSTER1_CORE_COUNT U(0)
+#define K3_CLUSTER2_CORE_COUNT U(0)
+#define K3_CLUSTER3_CORE_COUNT U(0)
+
+/*
+ * This RAM will be used for the bootloader including code, bss, and stacks.
+ * It may need to be increased if BL31 grows in size.
+ * Current computation assumes data structures necessary for GIC and ARM for
+ * a single cluster of 4 processor.
+ *
+ * The link addresses are determined by SEC_SRAM_BASE + offset.
+ * When ENABLE_PIE is set, the TF images can be loaded anywhere, so
+ * SEC_SRAM_BASE is really arbitrary.
+ *
+ * When ENABLE_PIE is unset, SEC_SRAM_BASE should be chosen so that
+ * it matches to the physical address where BL31 is loaded, that is,
+ * SEC_SRAM_BASE should be the base address of the RAM region.
+ *
+ * Lets make things explicit by mapping SRAM_BASE to 0x0 since ENABLE_PIE is
+ * defined as default for our platform.
+ */
+#define SEC_SRAM_BASE UL(0x00000000) /* PIE remapped on fly */
+#define SEC_SRAM_SIZE UL(0x00020000) /* 128k */
+
+#define PLAT_MAX_OFF_STATE U(2)
+#define PLAT_MAX_RET_STATE U(1)
+
+#define PLAT_PROC_START_ID U(32)
+#define PLAT_PROC_DEVICE_START_ID U(135)
+#define PLAT_CLUSTER_DEVICE_START_ID U(134)
+
+#endif /* BOARD_DEF_H */
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
new file mode 100644
index 0000000..a0bfdee
--- /dev/null
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
@@ -0,0 +1,341 @@
+/*
+ * Texas Instruments K3 Secure Proxy Driver
+ * Based on Linux and U-Boot implementation
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#include "sec_proxy.h"
+
+/* SEC PROXY RT THREAD STATUS */
+#define RT_THREAD_STATUS (0x0)
+#define RT_THREAD_STATUS_ERROR_SHIFT (31)
+#define RT_THREAD_STATUS_ERROR_MASK BIT(31)
+#define RT_THREAD_STATUS_CUR_CNT_SHIFT (0)
+#define RT_THREAD_STATUS_CUR_CNT_MASK GENMASK(7, 0)
+
+/* SEC PROXY SCFG THREAD CTRL */
+#define SCFG_THREAD_CTRL (0x1000)
+#define SCFG_THREAD_CTRL_DIR_SHIFT (31)
+#define SCFG_THREAD_CTRL_DIR_MASK BIT(31)
+
+#define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x)))
+#define THREAD_IS_RX (1)
+#define THREAD_IS_TX (0)
+
+/**
+ * struct k3_sec_proxy_desc - Description of secure proxy integration
+ * @timeout_us: Timeout for communication (in Microseconds)
+ * @max_msg_size: Message size in bytes
+ * @data_start_offset: Offset of the First data register of the thread
+ * @data_end_offset: Offset of the Last data register of the thread
+ */
+struct k3_sec_proxy_desc {
+ uint32_t timeout_us;
+ uint16_t max_msg_size;
+ uint16_t data_start_offset;
+ uint16_t data_end_offset;
+};
+
+/**
+ * struct k3_sec_proxy_thread - Description of a Secure Proxy Thread
+ * @name: Thread Name
+ * @data: Thread Data path region for target
+ * @scfg: Secure Config Region for Thread
+ * @rt: RealTime Region for Thread
+ */
+struct k3_sec_proxy_thread {
+ const char *name;
+ uintptr_t data;
+ uintptr_t scfg;
+ uintptr_t rt;
+};
+
+/**
+ * struct k3_sec_proxy_mbox - Description of a Secure Proxy Instance
+ * @desc: Description of the SoC integration
+ * @chans: Array for valid thread instances
+ */
+struct k3_sec_proxy_mbox {
+ const struct k3_sec_proxy_desc desc;
+ struct k3_sec_proxy_thread threads[];
+};
+
+/*
+ * Thread ID #0: DMSC notify
+ * Thread ID #1: DMSC request response
+ * Thread ID #2: DMSC request high priority
+ * Thread ID #3: DMSC request low priority
+ * Thread ID #4: DMSC notify response
+ */
+#define SP_THREAD(_x) \
+ [_x] = { \
+ .name = #_x, \
+ .data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, _x), \
+ .scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, _x), \
+ .rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, _x), \
+ }
+
+static struct k3_sec_proxy_mbox spm = {
+ .desc = {
+ .timeout_us = SEC_PROXY_TIMEOUT_US,
+ .max_msg_size = SEC_PROXY_MAX_MESSAGE_SIZE,
+ .data_start_offset = 0x4,
+ .data_end_offset = 0x3C,
+ },
+ .threads = {
+#if !K3_SEC_PROXY_LITE
+ SP_THREAD(SP_NOTIFY),
+ SP_THREAD(SP_RESPONSE),
+ SP_THREAD(SP_HIGH_PRIORITY),
+ SP_THREAD(SP_LOW_PRIORITY),
+ SP_THREAD(SP_NOTIFY_RESP),
+#else
+ SP_THREAD(SP_RESPONSE),
+ SP_THREAD(SP_HIGH_PRIORITY),
+#endif /* K3_SEC_PROXY_LITE */
+ },
+};
+
+/**
+ * struct sec_msg_hdr - Message header for secure messages and responses
+ * @checksum: CRC of message for integrity checking
+ */
+union sec_msg_hdr {
+ struct {
+ uint16_t checksum;
+ uint16_t reserved;
+ } __packed;
+ uint32_t data;
+};
+
+/**
+ * k3_sec_proxy_verify_thread() - Verify thread status before
+ * sending/receiving data
+ * @spt: Pointer to Secure Proxy thread description
+ * @dir: Direction of the thread
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+static inline int k3_sec_proxy_verify_thread(struct k3_sec_proxy_thread *spt,
+ uint32_t dir)
+{
+ /* Check for any errors already available */
+ if (mmio_read_32(spt->rt + RT_THREAD_STATUS) &
+ RT_THREAD_STATUS_ERROR_MASK) {
+ ERROR("Thread %s is corrupted, cannot send data\n", spt->name);
+ return -EINVAL;
+ }
+
+ /* Make sure thread is configured for right direction */
+ if ((mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK)
+ != (dir << SCFG_THREAD_CTRL_DIR_SHIFT)) {
+ if (dir == THREAD_IS_TX)
+ ERROR("Trying to send data on RX Thread %s\n",
+ spt->name);
+ else
+ ERROR("Trying to receive data on TX Thread %s\n",
+ spt->name);
+ return -EINVAL;
+ }
+
+ /* Check the message queue before sending/receiving data */
+ uint32_t tick_start = (uint32_t)read_cntpct_el0();
+ uint32_t ticks_per_us = SYS_COUNTER_FREQ_IN_TICKS / 1000000;
+ while (!(mmio_read_32(spt->rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK)) {
+ VERBOSE("Waiting for thread %s to %s\n",
+ spt->name, (dir == THREAD_IS_TX) ? "empty" : "fill");
+ if (((uint32_t)read_cntpct_el0() - tick_start) >
+ (spm.desc.timeout_us * ticks_per_us)) {
+ ERROR("Timeout waiting for thread %s to %s\n",
+ spt->name, (dir == THREAD_IS_TX) ? "empty" : "fill");
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * k3_sec_proxy_clear_rx_thread() - Clear Secure Proxy thread
+ *
+ * @id: Channel Identifier
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int k3_sec_proxy_clear_rx_thread(enum k3_sec_proxy_chan_id id)
+{
+ struct k3_sec_proxy_thread *spt = &spm.threads[id];
+
+ /* Check for any errors already available */
+ if (mmio_read_32(spt->rt + RT_THREAD_STATUS) &
+ RT_THREAD_STATUS_ERROR_MASK) {
+ ERROR("Thread %s is corrupted, cannot send data\n", spt->name);
+ return -EINVAL;
+ }
+
+ /* Make sure thread is configured for right direction */
+ if (!(mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK)) {
+ ERROR("Cannot clear a transmit thread %s\n", spt->name);
+ return -EINVAL;
+ }
+
+ /* Read off messages from thread until empty */
+ uint32_t try_count = 10;
+ while (mmio_read_32(spt->rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK) {
+ if (!(try_count--)) {
+ ERROR("Could not clear all messages from thread %s\n", spt->name);
+ return -ETIMEDOUT;
+ }
+ WARN("Clearing message from thread %s\n", spt->name);
+ mmio_read_32(spt->data + spm.desc.data_end_offset);
+ }
+
+ return 0;
+}
+
+/**
+ * k3_sec_proxy_send() - Send data over a Secure Proxy thread
+ * @id: Channel Identifier
+ * @msg: Pointer to k3_sec_proxy_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg)
+{
+ struct k3_sec_proxy_thread *spt = &spm.threads[id];
+ union sec_msg_hdr secure_header;
+ int num_words, trail_bytes, i, ret;
+ uintptr_t data_reg;
+
+ ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_TX);
+ if (ret) {
+ ERROR("Thread %s verification failed (%d)\n", spt->name, ret);
+ return ret;
+ }
+
+ /* Check the message size */
+ if (msg->len + sizeof(secure_header) > spm.desc.max_msg_size) {
+ ERROR("Thread %s message length %lu > max msg size\n",
+ spt->name, msg->len);
+ return -EINVAL;
+ }
+
+ /* TODO: Calculate checksum */
+ secure_header.checksum = 0;
+
+ /* Send the secure header */
+ data_reg = spm.desc.data_start_offset;
+ mmio_write_32(spt->data + data_reg, secure_header.data);
+ data_reg += sizeof(uint32_t);
+
+ /* Send whole words */
+ num_words = msg->len / sizeof(uint32_t);
+ for (i = 0; i < num_words; i++) {
+ mmio_write_32(spt->data + data_reg, ((uint32_t *)msg->buf)[i]);
+ data_reg += sizeof(uint32_t);
+ }
+
+ /* Send remaining bytes */
+ trail_bytes = msg->len % sizeof(uint32_t);
+ if (trail_bytes) {
+ uint32_t data_trail = 0;
+
+ i = msg->len - trail_bytes;
+ while (trail_bytes--) {
+ data_trail <<= 8;
+ data_trail |= msg->buf[i++];
+ }
+
+ mmio_write_32(spt->data + data_reg, data_trail);
+ data_reg += sizeof(uint32_t);
+ }
+ /*
+ * 'data_reg' indicates next register to write. If we did not already
+ * write on tx complete reg(last reg), we must do so for transmit
+ * In addition, we also need to make sure all intermediate data
+ * registers(if any required), are reset to 0 for TISCI backward
+ * compatibility to be maintained.
+ */
+ while (data_reg <= spm.desc.data_end_offset) {
+ mmio_write_32(spt->data + data_reg, 0);
+ data_reg += sizeof(uint32_t);
+ }
+
+ VERBOSE("Message successfully sent on thread %s\n", spt->name);
+
+ return 0;
+}
+
+/**
+ * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread
+ * @id: Channel Identifier
+ * @msg: Pointer to k3_sec_proxy_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg)
+{
+ struct k3_sec_proxy_thread *spt = &spm.threads[id];
+ union sec_msg_hdr secure_header;
+ uintptr_t data_reg;
+ int num_words, trail_bytes, i, ret;
+
+ ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_RX);
+ if (ret) {
+ ERROR("Thread %s verification failed (%d)\n", spt->name, ret);
+ return ret;
+ }
+
+ /* Read secure header */
+ data_reg = spm.desc.data_start_offset;
+ secure_header.data = mmio_read_32(spt->data + data_reg);
+ data_reg += sizeof(uint32_t);
+
+ /* Read whole words */
+ num_words = msg->len / sizeof(uint32_t);
+ for (i = 0; i < num_words; i++) {
+ ((uint32_t *)msg->buf)[i] = mmio_read_32(spt->data + data_reg);
+ data_reg += sizeof(uint32_t);
+ }
+
+ /* Read remaining bytes */
+ trail_bytes = msg->len % sizeof(uint32_t);
+ if (trail_bytes) {
+ uint32_t data_trail = mmio_read_32(spt->data + data_reg);
+ data_reg += sizeof(uint32_t);
+
+ i = msg->len - trail_bytes;
+ while (trail_bytes--) {
+ msg->buf[i] = data_trail & 0xff;
+ data_trail >>= 8;
+ }
+ }
+
+ /*
+ * 'data_reg' indicates next register to read. If we did not already
+ * read on rx complete reg(last reg), we must do so for receive
+ */
+ if (data_reg <= spm.desc.data_end_offset)
+ mmio_read_32(spt->data + spm.desc.data_end_offset);
+
+ /* TODO: Verify checksum */
+ (void)secure_header.checksum;
+
+ VERBOSE("Message successfully received from thread %s\n", spt->name);
+
+ return 0;
+}
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
new file mode 100644
index 0000000..f4b0b4b
--- /dev/null
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
@@ -0,0 +1,82 @@
+/*
+ * Texas Instruments K3 Secure Proxy Driver
+ * Based on Linux and U-Boot implementation
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SEC_PROXY_H
+#define SEC_PROXY_H
+
+#include <stdint.h>
+
+/**
+ * enum k3_sec_proxy_chan_id - Secure Proxy thread IDs
+ *
+ * These the available IDs used in k3_sec_proxy_{send,recv}()
+ * There are two schemes we use:
+ * * if K3_SEC_PROXY_LITE = 1, we just have two threads to talk
+ * * if K3_SEC_PROXY_LITE = 0, we have the full fledged
+ * communication scheme available.
+ */
+enum k3_sec_proxy_chan_id {
+#if !K3_SEC_PROXY_LITE
+ SP_NOTIFY = 0,
+ SP_RESPONSE,
+ SP_HIGH_PRIORITY,
+ SP_LOW_PRIORITY,
+ SP_NOTIFY_RESP,
+#else
+ SP_RESPONSE = 8,
+ /*
+ * Note: TISCI documentation indicates "low priority", but in reality
+ * with a single thread, there is no low or high priority.. This usage
+ * is more appropriate for TF-A since we can reduce the churn as a
+ * result.
+ */
+ SP_HIGH_PRIORITY,
+#endif /* K3_SEC_PROXY_LITE */
+};
+
+/**
+ * struct k3_sec_proxy_msg - Secure proxy message structure
+ * @len: Length of data in the Buffer
+ * @buf: Buffer pointer
+ *
+ * This is the structure for data used in k3_sec_proxy_{send,recv}()
+ */
+struct k3_sec_proxy_msg {
+ size_t len;
+ uint8_t *buf;
+};
+
+/**
+ * k3_sec_proxy_send() - Send data over a Secure Proxy thread
+ * @id: Channel Identifier
+ * @msg: Pointer to k3_sec_proxy_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int k3_sec_proxy_clear_rx_thread(enum k3_sec_proxy_chan_id id);
+
+/**
+ * k3_sec_proxy_send() - Send data over a Secure Proxy thread
+ * @id: Channel Identifier
+ * @msg: Pointer to k3_sec_proxy_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int k3_sec_proxy_send(enum k3_sec_proxy_chan_id id, const struct k3_sec_proxy_msg *msg);
+
+/**
+ * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread
+ * @id: Channel Identifier
+ * @msg: Pointer to k3_sec_proxy_msg
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int k3_sec_proxy_recv(enum k3_sec_proxy_chan_id id, struct k3_sec_proxy_msg *msg);
+
+#endif /* SEC_PROXY_H */
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
new file mode 100644
index 0000000..2cbfa3d
--- /dev/null
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
@@ -0,0 +1,1739 @@
+/*
+ * Texas Instruments System Control Interface Driver
+ * Based on Linux and U-Boot implementation
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <sec_proxy.h>
+
+#include "ti_sci_protocol.h"
+#include "ti_sci.h"
+
+#if USE_COHERENT_MEM
+__section("tzfw_coherent_mem")
+#endif
+static uint8_t message_sequence;
+
+/**
+ * struct ti_sci_xfer - Structure representing a message flow
+ * @tx_message: Transmit message
+ * @rx_message: Receive message
+ */
+struct ti_sci_xfer {
+ struct k3_sec_proxy_msg tx_message;
+ struct k3_sec_proxy_msg rx_message;
+};
+
+/**
+ * ti_sci_setup_one_xfer() - Setup one message type
+ *
+ * @msg_type: Message type
+ * @msg_flags: Flag to set for the message
+ * @tx_buf: Buffer to be sent to mailbox channel
+ * @tx_message_size: transmit message size
+ * @rx_buf: Buffer to be received from mailbox channel
+ * @rx_message_size: receive message size
+ *
+ * Helper function which is used by various command functions that are
+ * exposed to clients of this driver for allocating a message traffic event.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags,
+ void *tx_buf,
+ size_t tx_message_size,
+ void *rx_buf,
+ size_t rx_message_size,
+ struct ti_sci_xfer *xfer)
+{
+ struct ti_sci_msg_hdr *hdr;
+
+ /* Ensure we have sane transfer sizes */
+ if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
+ tx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
+ rx_message_size < sizeof(*hdr) ||
+ tx_message_size < sizeof(*hdr))
+ return -ERANGE;
+
+ hdr = (struct ti_sci_msg_hdr *)tx_buf;
+ hdr->seq = ++message_sequence;
+ hdr->type = msg_type;
+ hdr->host = TI_SCI_HOST_ID;
+ hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
+
+ xfer->tx_message.buf = tx_buf;
+ xfer->tx_message.len = tx_message_size;
+
+ xfer->rx_message.buf = rx_buf;
+ xfer->rx_message.len = rx_message_size;
+
+ return 0;
+}
+
+/**
+ * ti_sci_get_response() - Receive response from mailbox channel
+ *
+ * @xfer: Transfer to initiate and wait for response
+ * @chan: Channel to receive the response
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+static inline int ti_sci_get_response(struct ti_sci_xfer *xfer,
+ enum k3_sec_proxy_chan_id chan)
+{
+ struct k3_sec_proxy_msg *msg = &xfer->rx_message;
+ struct ti_sci_msg_hdr *hdr;
+ unsigned int retry = 5;
+ int ret;
+
+ for (; retry > 0; retry--) {
+ /* Receive the response */
+ ret = k3_sec_proxy_recv(chan, msg);
+ if (ret) {
+ ERROR("Message receive failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* msg is updated by Secure Proxy driver */
+ hdr = (struct ti_sci_msg_hdr *)msg->buf;
+
+ /* Sanity check for message response */
+ if (hdr->seq == message_sequence)
+ break;
+ else
+ WARN("Message with sequence ID %u is not expected\n", hdr->seq);
+ }
+ if (!retry) {
+ ERROR("Timed out waiting for message\n");
+ return -EINVAL;
+ }
+
+ if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) {
+ ERROR("Unable to handle %lu xfer (max %d)\n",
+ msg->len, TI_SCI_MAX_MESSAGE_SIZE);
+ return -EINVAL;
+ }
+
+ if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK))
+ return -ENODEV;
+
+ return 0;
+}
+
+/**
+ * ti_sci_do_xfer() - Do one transfer
+ *
+ * @xfer: Transfer to initiate and wait for response
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
+{
+ struct k3_sec_proxy_msg *msg = &xfer->tx_message;
+ int ret;
+
+ /* Clear any spurious messages in receive queue */
+ ret = k3_sec_proxy_clear_rx_thread(SP_RESPONSE);
+ if (ret) {
+ ERROR("Could not clear response queue (%d)\n", ret);
+ return ret;
+ }
+
+ /* Send the message */
+ ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, msg);
+ if (ret) {
+ ERROR("Message sending failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Get the response */
+ ret = ti_sci_get_response(xfer, SP_RESPONSE);
+ if (ret) {
+ ERROR("Failed to get response (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_get_revision() - Get the revision of the SCI entity
+ *
+ * Updates the SCI information in the internal data structure.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info)
+{
+ struct ti_sci_msg_hdr hdr;
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0,
+ &hdr, sizeof(hdr),
+ rev_info, sizeof(*rev_info),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_set_state() - Set device state
+ *
+ * @id: Device identifier
+ * @flags: flags to setup for the device
+ * @state: State to move the device to
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state)
+{
+ struct ti_sci_msg_req_set_device_state req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.id = id;
+ req.state = state;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_get_state() - Get device state
+ *
+ * @id: Device Identifier
+ * @clcnt: Pointer to Context Loss Count
+ * @resets: pointer to resets
+ * @p_state: pointer to p_state
+ * @c_state: pointer to c_state
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+static int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt,
+ uint32_t *resets, uint8_t *p_state,
+ uint8_t *c_state)
+{
+ struct ti_sci_msg_req_get_device_state req;
+ struct ti_sci_msg_resp_get_device_state resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ if (!clcnt && !resets && !p_state && !c_state)
+ return -EINVAL;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.id = id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ if (clcnt)
+ *clcnt = resp.context_loss_count;
+ if (resets)
+ *resets = resp.resets;
+ if (p_state)
+ *p_state = resp.programmed_state;
+ if (c_state)
+ *c_state = resp.current_state;
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_get() - Request for device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get(uint32_t id)
+{
+ return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON);
+}
+
+/**
+ * ti_sci_device_get_exclusive() - Exclusive request for device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * NOTE: This _exclusive version of the get API is for exclusive access to the
+ * device. Any other host in the system will fail to get this device after this
+ * call until exclusive access is released with device_put or a non-exclusive
+ * set call.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get_exclusive(uint32_t id)
+{
+ return ti_sci_device_set_state(id,
+ MSG_FLAG_DEVICE_EXCLUSIVE,
+ MSG_DEVICE_SW_STATE_ON);
+}
+
+/**
+ * ti_sci_device_idle() - Idle a device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_idle(uint32_t id)
+{
+ return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_RETENTION);
+}
+
+/**
+ * ti_sci_device_idle_exclusive() - Exclusive idle a device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * NOTE: This _exclusive version of the idle API is for exclusive access to
+ * the device. Any other host in the system will fail to get this device after
+ * this call until exclusive access is released with device_put or a
+ * non-exclusive set call.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_idle_exclusive(uint32_t id)
+{
+ return ti_sci_device_set_state(id,
+ MSG_FLAG_DEVICE_EXCLUSIVE,
+ MSG_DEVICE_SW_STATE_RETENTION);
+}
+
+/**
+ * ti_sci_device_put() - Release a device managed by TISCI
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_put(uint32_t id)
+{
+ return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
+}
+
+/**
+ * ti_sci_device_put_no_wait() - Release a device without requesting or waiting
+ * for a response.
+ *
+ * @id: Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_put_no_wait(uint32_t id)
+{
+ struct ti_sci_msg_req_set_device_state req;
+ struct ti_sci_msg_hdr *hdr;
+ struct k3_sec_proxy_msg tx_message;
+ int ret;
+
+ /* Ensure we have sane transfer size */
+ if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE)
+ return -ERANGE;
+
+ hdr = (struct ti_sci_msg_hdr *)&req;
+ hdr->seq = ++message_sequence;
+ hdr->type = TI_SCI_MSG_SET_DEVICE_STATE;
+ hdr->host = TI_SCI_HOST_ID;
+ /* Setup with NORESPONSE flag to keep response queue clean */
+ hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE;
+
+ req.id = id;
+ req.state = MSG_DEVICE_SW_STATE_AUTO_OFF;
+
+ tx_message.buf = (uint8_t *)&req;
+ tx_message.len = sizeof(req);
+
+ /* Send message */
+ ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message);
+ if (ret) {
+ ERROR("Message sending failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Return without waiting for response */
+ return 0;
+}
+
+/**
+ * ti_sci_device_is_valid() - Is the device valid
+ *
+ * @id: Device Identifier
+ *
+ * Return: 0 if all goes well and the device ID is valid, else return
+ * appropriate error
+ */
+int ti_sci_device_is_valid(uint32_t id)
+{
+ uint8_t unused;
+
+ /* check the device state which will also tell us if the ID is valid */
+ return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused);
+}
+
+/**
+ * ti_sci_device_get_clcnt() - Get context loss counter
+ *
+ * @id: Device Identifier
+ * @count: Pointer to Context Loss counter to populate
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count)
+{
+ return ti_sci_device_get_state(id, count, NULL, NULL, NULL);
+}
+
+/**
+ * ti_sci_device_is_idle() - Check if the device is requested to be idle
+ *
+ * @id: Device Identifier
+ * @r_state: true if requested to be idle
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_idle(uint32_t id, bool *r_state)
+{
+ int ret;
+ uint8_t state;
+
+ if (!r_state)
+ return -EINVAL;
+
+ ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL);
+ if (ret)
+ return ret;
+
+ *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_is_stop() - Check if the device is requested to be stopped
+ *
+ * @id: Device Identifier
+ * @r_state: true if requested to be stopped
+ * @curr_state: true if currently stopped
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state)
+{
+ int ret;
+ uint8_t p_state, c_state;
+
+ if (!r_state && !curr_state)
+ return -EINVAL;
+
+ ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
+ if (ret)
+ return ret;
+
+ if (r_state)
+ *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
+ if (curr_state)
+ *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_is_on() - Check if the device is requested to be ON
+ *
+ * @id: Device Identifier
+ * @r_state: true if requested to be ON
+ * @curr_state: true if currently ON and active
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state)
+{
+ int ret;
+ uint8_t p_state, c_state;
+
+ if (!r_state && !curr_state)
+ return -EINVAL;
+
+ ret =
+ ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
+ if (ret)
+ return ret;
+
+ if (r_state)
+ *r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
+ if (curr_state)
+ *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_is_trans() - Check if the device is currently transitioning
+ *
+ * @id: Device Identifier
+ * @curr_state: true if currently transitioning
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_is_trans(uint32_t id, bool *curr_state)
+{
+ int ret;
+ uint8_t state;
+
+ if (!curr_state)
+ return -EINVAL;
+
+ ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state);
+ if (ret)
+ return ret;
+
+ *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_set_resets() - Set resets for device managed by TISCI
+ *
+ * @id: Device Identifier
+ * @reset_state: Device specific reset bit field
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state)
+{
+ struct ti_sci_msg_req_set_device_resets req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.id = id;
+ req.resets = reset_state;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_device_get_resets() - Get reset state for device managed by TISCI
+ *
+ * @id: Device Identifier
+ * @reset_state: Pointer to reset state to populate
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state)
+{
+ return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL);
+}
+
+/**
+ * ti_sci_clock_set_state() - Set clock state helper
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request,
+ * Each device has its own set of clock inputs, This indexes
+ * which clock input to modify
+ * @flags: Header flags as needed
+ * @state: State to request for the clock
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id,
+ uint32_t flags, uint8_t state)
+{
+ struct ti_sci_msg_req_set_clock_state req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, flags,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+ req.request_state = state;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_get_state() - Get clock state helper
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @programmed_state: State requested for clock to move to
+ * @current_state: State that the clock is currently in
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id,
+ uint8_t *programmed_state,
+ uint8_t *current_state)
+{
+ struct ti_sci_msg_req_get_clock_state req;
+ struct ti_sci_msg_resp_get_clock_state resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ if (!programmed_state && !current_state)
+ return -EINVAL;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ if (programmed_state)
+ *programmed_state = resp.programmed_state;
+ if (current_state)
+ *current_state = resp.current_state;
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_get() - Get control of a clock from TI SCI
+
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @needs_ssc: 'true' iff Spread Spectrum clock is desired
+ * @can_change_freq: 'true' iff frequency change is desired
+ * @enable_input_term: 'true' iff input termination is desired
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id,
+ bool needs_ssc, bool can_change_freq,
+ bool enable_input_term)
+{
+ uint32_t flags = 0;
+
+ flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
+ flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
+ flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
+
+ return ti_sci_clock_set_state(dev_id, clk_id, flags,
+ MSG_CLOCK_SW_STATE_REQ);
+}
+
+/**
+ * ti_sci_clock_idle() - Idle a clock which is in our control
+
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ *
+ * NOTE: This clock must have been requested by get_clock previously.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id)
+{
+ return ti_sci_clock_set_state(dev_id, clk_id, 0,
+ MSG_CLOCK_SW_STATE_UNREQ);
+}
+
+/**
+ * ti_sci_clock_put() - Release a clock from our control
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ *
+ * NOTE: This clock must have been requested by get_clock previously.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id)
+{
+ return ti_sci_clock_set_state(dev_id, clk_id, 0,
+ MSG_CLOCK_SW_STATE_AUTO);
+}
+
+/**
+ * ti_sci_clock_is_auto() - Is the clock being auto managed
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @req_state: state indicating if the clock is auto managed
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state)
+{
+ uint8_t state = 0;
+ int ret;
+
+ if (!req_state)
+ return -EINVAL;
+
+ ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL);
+ if (ret)
+ return ret;
+
+ *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_is_on() - Is the clock ON
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @req_state: state indicating if the clock is managed by us and enabled
+ * @curr_state: state indicating if the clock is ready for operation
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id,
+ bool *req_state, bool *curr_state)
+{
+ uint8_t c_state = 0, r_state = 0;
+ int ret;
+
+ if (!req_state && !curr_state)
+ return -EINVAL;
+
+ ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
+ if (ret)
+ return ret;
+
+ if (req_state)
+ *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
+ if (curr_state)
+ *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_is_off() - Is the clock OFF
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @req_state: state indicating if the clock is managed by us and disabled
+ * @curr_state: state indicating if the clock is NOT ready for operation
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id,
+ bool *req_state, bool *curr_state)
+{
+ uint8_t c_state = 0, r_state = 0;
+ int ret;
+
+ if (!req_state && !curr_state)
+ return -EINVAL;
+
+ ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
+ if (ret)
+ return ret;
+
+ if (req_state)
+ *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
+ if (curr_state)
+ *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_set_parent() - Set the clock source of a specific device clock
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @parent_id: Parent clock identifier to set
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id)
+{
+ struct ti_sci_msg_req_set_clock_parent req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+ req.parent_id = parent_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_get_parent() - Get current parent clock source
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @parent_id: Current clock parent
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id)
+{
+ struct ti_sci_msg_req_get_clock_parent req;
+ struct ti_sci_msg_resp_get_clock_parent resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ *parent_id = resp.parent_id;
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_get_num_parents() - Get num parents of the current clk source
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @num_parents: Returns he number of parents to the current clock.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id,
+ uint8_t *num_parents)
+{
+ struct ti_sci_msg_req_get_clock_num_parents req;
+ struct ti_sci_msg_resp_get_clock_num_parents resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ *num_parents = resp.num_parents;
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_get_match_freq() - Find a good match for frequency
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @min_freq: The minimum allowable frequency in Hz. This is the minimum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @target_freq: The target clock frequency in Hz. A frequency will be
+ * processed as close to this target frequency as possible.
+ * @max_freq: The maximum allowable frequency in Hz. This is the maximum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @match_freq: Frequency match in Hz response.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id,
+ uint64_t min_freq, uint64_t target_freq,
+ uint64_t max_freq, uint64_t *match_freq)
+{
+ struct ti_sci_msg_req_query_clock_freq req;
+ struct ti_sci_msg_resp_query_clock_freq resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+ req.min_freq_hz = min_freq;
+ req.target_freq_hz = target_freq;
+ req.max_freq_hz = max_freq;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ *match_freq = resp.freq_hz;
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_set_freq() - Set a frequency for clock
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @min_freq: The minimum allowable frequency in Hz. This is the minimum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @target_freq: The target clock frequency in Hz. A frequency will be
+ * processed as close to this target frequency as possible.
+ * @max_freq: The maximum allowable frequency in Hz. This is the maximum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq,
+ uint64_t target_freq, uint64_t max_freq)
+{
+ struct ti_sci_msg_req_set_clock_freq req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+ req.min_freq_hz = min_freq;
+ req.target_freq_hz = target_freq;
+ req.max_freq_hz = max_freq;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_clock_get_freq() - Get current frequency
+ *
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @freq: Currently frequency in Hz
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq)
+{
+ struct ti_sci_msg_req_get_clock_freq req;
+ struct ti_sci_msg_resp_get_clock_freq resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.dev_id = dev_id;
+ req.clk_id = clk_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ *freq = resp.freq_hz;
+
+ return 0;
+}
+
+/**
+ * ti_sci_core_reboot() - Command to request system reset
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_core_reboot(void)
+{
+ struct ti_sci_msg_req_reboot req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+ req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_request() - Request a physical processor control
+ *
+ * @proc_id: Processor ID this request is for
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_request(uint8_t proc_id)
+{
+ struct ti_sci_msg_req_proc_request req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_release() - Release a physical processor control
+ *
+ * @proc_id: Processor ID this request is for
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_release(uint8_t proc_id)
+{
+ struct ti_sci_msg_req_proc_release req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_handover() - Handover a physical processor control to a host in
+ * the processor's access control list.
+ *
+ * @proc_id: Processor ID this request is for
+ * @host_id: Host ID to get the control of the processor
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id)
+{
+ struct ti_sci_msg_req_proc_handover req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+ req.host_id = host_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags
+ *
+ * @proc_id: Processor ID this request is for
+ * @config_flags_set: Configuration flags to be set
+ * @config_flags_clear: Configuration flags to be cleared
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
+ uint32_t config_flags_set,
+ uint32_t config_flags_clear)
+{
+ struct ti_sci_msg_req_set_proc_boot_config req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+ req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
+ req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
+ TISCI_ADDR_HIGH_SHIFT;
+ req.config_flags_set = config_flags_set;
+ req.config_flags_clear = config_flags_clear;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags
+ *
+ * @proc_id: Processor ID this request is for
+ * @control_flags_set: Control flags to be set
+ * @control_flags_clear: Control flags to be cleared
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
+ uint32_t control_flags_clear)
+{
+ struct ti_sci_msg_req_set_proc_boot_ctrl req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+ req.control_flags_set = control_flags_set;
+ req.control_flags_clear = control_flags_clear;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_set_boot_ctrl_no_wait() - Set the processor boot control flags
+ * without requesting or waiting for a
+ * response.
+ *
+ * @proc_id: Processor ID this request is for
+ * @control_flags_set: Control flags to be set
+ * @control_flags_clear: Control flags to be cleared
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id,
+ uint32_t control_flags_set,
+ uint32_t control_flags_clear)
+{
+ struct ti_sci_msg_req_set_proc_boot_ctrl req;
+ struct ti_sci_msg_hdr *hdr;
+ struct k3_sec_proxy_msg tx_message;
+ int ret;
+
+ /* Ensure we have sane transfer size */
+ if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE)
+ return -ERANGE;
+
+ hdr = (struct ti_sci_msg_hdr *)&req;
+ hdr->seq = ++message_sequence;
+ hdr->type = TISCI_MSG_SET_PROC_BOOT_CTRL;
+ hdr->host = TI_SCI_HOST_ID;
+ /* Setup with NORESPONSE flag to keep response queue clean */
+ hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE;
+
+ req.processor_id = proc_id;
+ req.control_flags_set = control_flags_set;
+ req.control_flags_clear = control_flags_clear;
+
+ tx_message.buf = (uint8_t *)&req;
+ tx_message.len = sizeof(req);
+
+ /* Send message */
+ ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message);
+ if (ret) {
+ ERROR("Message sending failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Return without waiting for response */
+ return 0;
+}
+
+/**
+ * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the
+ * processor configuration flags
+ *
+ * @proc_id: Processor ID this request is for
+ * @cert_addr: Memory address at which payload image certificate is located
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr)
+{
+ struct ti_sci_msg_req_proc_auth_boot_image req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMIAGE, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+ req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
+ req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
+ TISCI_ADDR_HIGH_SHIFT;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_get_boot_status() - Get the processor boot status
+ *
+ * @proc_id: Processor ID this request is for
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
+ uint32_t *cfg_flags,
+ uint32_t *ctrl_flags,
+ uint32_t *sts_flags)
+{
+ struct ti_sci_msg_req_get_proc_boot_status req;
+ struct ti_sci_msg_resp_get_proc_boot_status resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) |
+ (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) &
+ TISCI_ADDR_HIGH_MASK);
+ *cfg_flags = resp.config_flags;
+ *ctrl_flags = resp.control_flags;
+ *sts_flags = resp.status_flags;
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_wait_boot_status() - Wait for a processor boot status
+ *
+ * @proc_id: Processor ID this request is for
+ * @num_wait_iterations Total number of iterations we will check before
+ * we will timeout and give up
+ * @num_match_iterations How many iterations should we have continued
+ * status to account for status bits glitching.
+ * This is to make sure that match occurs for
+ * consecutive checks. This implies that the
+ * worst case should consider that the stable
+ * time should at the worst be num_wait_iterations
+ * num_match_iterations to prevent timeout.
+ * @delay_per_iteration_us Specifies how long to wait (in micro seconds)
+ * between each status checks. This is the minimum
+ * duration, and overhead of register reads and
+ * checks are on top of this and can vary based on
+ * varied conditions.
+ * @delay_before_iterations_us Specifies how long to wait (in micro seconds)
+ * before the very first check in the first
+ * iteration of status check loop. This is the
+ * minimum duration, and overhead of register
+ * reads and checks are.
+ * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the
+ * status matching this field requested MUST be 1.
+ * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the
+ * bits matching this field requested MUST be 1.
+ * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the
+ * status matching this field requested MUST be 0.
+ * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the
+ * bits matching this field requested MUST be 0.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations,
+ uint8_t num_match_iterations,
+ uint8_t delay_per_iteration_us,
+ uint8_t delay_before_iterations_us,
+ uint32_t status_flags_1_set_all_wait,
+ uint32_t status_flags_1_set_any_wait,
+ uint32_t status_flags_1_clr_all_wait,
+ uint32_t status_flags_1_clr_any_wait)
+{
+ struct ti_sci_msg_req_wait_proc_boot_status req;
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0,
+ &req, sizeof(req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ req.processor_id = proc_id;
+ req.num_wait_iterations = num_wait_iterations;
+ req.num_match_iterations = num_match_iterations;
+ req.delay_per_iteration_us = delay_per_iteration_us;
+ req.delay_before_iterations_us = delay_before_iterations_us;
+ req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
+ req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
+ req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
+ req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
+
+ ret = ti_sci_do_xfer(&xfer);
+ if (ret) {
+ ERROR("Transfer send failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_wait_boot_status_no_wait() - Wait for a processor boot status
+ * without requesting or waiting for
+ * a response.
+ *
+ * @proc_id: Processor ID this request is for
+ * @num_wait_iterations Total number of iterations we will check before
+ * we will timeout and give up
+ * @num_match_iterations How many iterations should we have continued
+ * status to account for status bits glitching.
+ * This is to make sure that match occurs for
+ * consecutive checks. This implies that the
+ * worst case should consider that the stable
+ * time should at the worst be num_wait_iterations
+ * num_match_iterations to prevent timeout.
+ * @delay_per_iteration_us Specifies how long to wait (in micro seconds)
+ * between each status checks. This is the minimum
+ * duration, and overhead of register reads and
+ * checks are on top of this and can vary based on
+ * varied conditions.
+ * @delay_before_iterations_us Specifies how long to wait (in micro seconds)
+ * before the very first check in the first
+ * iteration of status check loop. This is the
+ * minimum duration, and overhead of register
+ * reads and checks are.
+ * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the
+ * status matching this field requested MUST be 1.
+ * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the
+ * bits matching this field requested MUST be 1.
+ * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the
+ * status matching this field requested MUST be 0.
+ * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the
+ * bits matching this field requested MUST be 0.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id,
+ uint8_t num_wait_iterations,
+ uint8_t num_match_iterations,
+ uint8_t delay_per_iteration_us,
+ uint8_t delay_before_iterations_us,
+ uint32_t status_flags_1_set_all_wait,
+ uint32_t status_flags_1_set_any_wait,
+ uint32_t status_flags_1_clr_all_wait,
+ uint32_t status_flags_1_clr_any_wait)
+{
+ struct ti_sci_msg_req_wait_proc_boot_status req;
+ struct ti_sci_msg_hdr *hdr;
+ struct k3_sec_proxy_msg tx_message;
+ int ret;
+
+ /* Ensure we have sane transfer size */
+ if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE)
+ return -ERANGE;
+
+ hdr = (struct ti_sci_msg_hdr *)&req;
+ hdr->seq = ++message_sequence;
+ hdr->type = TISCI_MSG_WAIT_PROC_BOOT_STATUS;
+ hdr->host = TI_SCI_HOST_ID;
+ /* Setup with NORESPONSE flag to keep response queue clean */
+ hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE;
+
+ req.processor_id = proc_id;
+ req.num_wait_iterations = num_wait_iterations;
+ req.num_match_iterations = num_match_iterations;
+ req.delay_per_iteration_us = delay_per_iteration_us;
+ req.delay_before_iterations_us = delay_before_iterations_us;
+ req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
+ req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
+ req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
+ req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
+
+ tx_message.buf = (uint8_t *)&req;
+ tx_message.len = sizeof(req);
+
+ /* Send message */
+ ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message);
+ if (ret) {
+ ERROR("Message sending failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Return without waiting for response */
+ return 0;
+}
+
+/**
+ * ti_sci_enter_sleep - Command to initiate system transition into suspend.
+ *
+ * @proc_id: Processor ID.
+ * @mode: Low power mode to enter.
+ * @core_resume_addr: Address that core should be
+ * resumed from after low power transition.
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_enter_sleep(uint8_t proc_id,
+ uint8_t mode,
+ uint64_t core_resume_addr)
+{
+ struct ti_sci_msg_req_enter_sleep req;
+ struct ti_sci_msg_hdr *hdr;
+ struct k3_sec_proxy_msg tx_message;
+ int ret;
+
+ /* Ensure we have sane transfer size */
+ if (sizeof(req) > TI_SCI_MAX_MESSAGE_SIZE) {
+ return -ERANGE;
+ }
+
+ hdr = (struct ti_sci_msg_hdr *)&req;
+ hdr->seq = ++message_sequence;
+ hdr->type = TI_SCI_MSG_ENTER_SLEEP;
+ hdr->host = TI_SCI_HOST_ID;
+ /* Setup with NORESPONSE flag to keep response queue clean */
+ hdr->flags = TI_SCI_FLAG_REQ_GENERIC_NORESPONSE;
+
+ req.processor_id = proc_id;
+ req.mode = mode;
+ req.core_resume_lo = core_resume_addr & TISCI_ADDR_LOW_MASK;
+ req.core_resume_hi = (core_resume_addr & TISCI_ADDR_HIGH_MASK) >>
+ TISCI_ADDR_HIGH_SHIFT;
+
+ tx_message.buf = (uint8_t *)&req;
+ tx_message.len = sizeof(req);
+
+ /* Send message */
+ ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &tx_message);
+ if (ret != 0) {
+ ERROR("Message sending failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Return without waiting for response */
+ return 0;
+}
+
+/**
+ * ti_sci_init() - Basic initialization
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_init(void)
+{
+ struct ti_sci_msg_resp_version rev_info;
+ int ret;
+
+ ret = ti_sci_get_revision(&rev_info);
+ if (ret) {
+ ERROR("Unable to communicate with control firmware (%d)\n", ret);
+ return ret;
+ }
+
+ INFO("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
+ rev_info.abi_major, rev_info.abi_minor,
+ rev_info.firmware_revision,
+ rev_info.firmware_description);
+
+ return 0;
+}
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
new file mode 100644
index 0000000..06944a7
--- /dev/null
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
@@ -0,0 +1,232 @@
+/*
+ * Texas Instruments System Control Interface API
+ * Based on Linux and U-Boot implementation
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TI_SCI_H
+#define TI_SCI_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * Device control operations
+ *
+ * - ti_sci_device_get - command to request for device managed by TISCI
+ * - ti_sci_device_get_exclusive - exclusively request a device
+ * - ti_sci_device_idle - Command to idle a device managed by TISCI
+ * - ti_sci_device_idle_exclusive - exclusively idle a device
+ * - ti_sci_device_put - command to release a device managed by TISCI
+ * - ti_sci_device_put_no_wait - release a device without waiting for response
+ * - ti_sci_device_is_valid - Is the device valid
+ * - ti_sci_device_get_clcnt - Get context loss counter
+ * @count: Pointer to Context Loss counter to populate
+ * - ti_sci_device_is_idle - Check if the device is requested to be idle
+ * @r_state: true if requested to be idle
+ * - ti_sci_device_is_stop - Check if the device is requested to be stopped
+ * @r_state: true if requested to be stopped
+ * @curr_state: true if currently stopped.
+ * - ti_sci_device_is_on - Check if the device is requested to be ON
+ * @r_state: true if requested to be ON
+ * @curr_state: true if currently ON and active
+ * - ti_sci_device_is_trans - Check if the device is currently transitioning
+ * @curr_state: true if currently transitioning.
+ * - ti_sci_device_set_resets - Command to set resets for
+ * device managed by TISCI
+ * @reset_state: Device specific reset bit field
+ * - ti_sci_device_get_resets - Get reset state for device managed by TISCI
+ * @reset_state: Pointer to reset state to populate
+ *
+ * NOTE: for all these functions, the following are generic in nature:
+ * @id: Device Identifier
+ * Returns 0 for successful request, else returns corresponding error message.
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ */
+int ti_sci_device_get(uint32_t id);
+int ti_sci_device_get_exclusive(uint32_t id);
+int ti_sci_device_idle(uint32_t id);
+int ti_sci_device_idle_exclusive(uint32_t id);
+int ti_sci_device_put(uint32_t id);
+int ti_sci_device_put_no_wait(uint32_t id);
+int ti_sci_device_is_valid(uint32_t id);
+int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count);
+int ti_sci_device_is_idle(uint32_t id, bool *r_state);
+int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state);
+int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state);
+int ti_sci_device_is_trans(uint32_t id, bool *curr_state);
+int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state);
+int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state);
+
+/**
+ * Clock control operations
+ *
+ * - ti_sci_clock_get - Get control of a clock from TI SCI
+ * @needs_ssc: 'true' iff Spread Spectrum clock is desired
+ * @can_change_freq: 'true' iff frequency change is desired
+ * @enable_input_term: 'true' iff input termination is desired
+ * - ti_sci_clock_idle - Idle a clock which is in our control
+ * - ti_sci_clock_put - Release a clock from our control
+ * - ti_sci_clock_is_auto - Is the clock being auto managed
+ * @req_state: state indicating if the clock is auto managed
+ * - ti_sci_clock_is_on - Is the clock ON
+ * @req_state: state indicating if the clock is managed by us and enabled
+ * @curr_state: state indicating if the clock is ready for operation
+ * - ti_sci_clock_is_off - Is the clock OFF
+ * @req_state: state indicating if the clock is managed by us and disabled
+ * @curr_state: state indicating if the clock is NOT ready for operation
+ * - ti_sci_clock_set_parent - Set the clock source of a specific device clock
+ * @parent_id: Parent clock identifier to set
+ * - ti_sci_clock_get_parent - Get current parent clock source
+ * @parent_id: Current clock parent
+ * - ti_sci_clock_get_num_parents - Get num parents of the current clk source
+ * @num_parents: Returns he number of parents to the current clock.
+ * - ti_sci_clock_get_match_freq - Find a good match for frequency
+ * @match_freq: Frequency match in Hz response.
+ * - ti_sci_clock_set_freq - Set a frequency for clock
+ * - ti_sci_clock_get_freq - Get current frequency
+ * @freq: Currently frequency in Hz
+ *
+ * NOTE: for all these functions, the following are generic in nature:
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has its own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @min_freq: The minimum allowable frequency in Hz. This is the minimum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @target_freq: The target clock frequency in Hz. A frequency will be
+ * processed as close to this target frequency as possible.
+ * @max_freq: The maximum allowable frequency in Hz. This is the maximum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * Returns 0 for successful request, else returns corresponding error message.
+ *
+ * Request for the clock - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_clock with put_clock. No refcounting is
+ * managed by driver for that purpose.
+ */
+int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id,
+ bool needs_ssc, bool can_change_freq,
+ bool enable_input_term);
+int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id);
+int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id);
+int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id,
+ bool *req_state);
+int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id,
+ bool *req_state, bool *curr_state);
+int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id,
+ bool *req_state, bool *curr_state);
+int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id,
+ uint8_t parent_id);
+int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id,
+ uint8_t *parent_id);
+int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id,
+ uint8_t *num_parents);
+int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id,
+ uint64_t min_freq, uint64_t target_freq,
+ uint64_t max_freq, uint64_t *match_freq);
+int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id,
+ uint64_t min_freq, uint64_t target_freq,
+ uint64_t max_freq);
+int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq);
+
+/**
+ * Core control operations
+ *
+ * - ti_sci_core_reboot() - Command to request system reset
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+int ti_sci_core_reboot(void);
+
+/**
+ * Processor control operations
+ *
+ * - ti_sci_proc_request - Command to request a physical processor control
+ * - ti_sci_proc_release - Command to release a physical processor control
+ * - ti_sci_proc_handover - Command to handover a physical processor control to
+ * a host in the processor's access control list.
+ * @host_id: Host ID to get the control of the processor
+ * - ti_sci_proc_set_boot_cfg - Command to set the processor boot configuration flags
+ * @config_flags_set: Configuration flags to be set
+ * @config_flags_clear: Configuration flags to be cleared.
+ * - ti_sci_proc_set_boot_ctrl - Command to set the processor boot control flags
+ * @control_flags_set: Control flags to be set
+ * @control_flags_clear: Control flags to be cleared
+ * - ti_sci_proc_set_boot_ctrl_no_wait - Same as above without waiting for response
+ * - ti_sci_proc_auth_boot_image - Command to authenticate and load the image
+ * and then set the processor configuration flags.
+ * @cert_addr: Memory address at which payload image certificate is located.
+ * - ti_sci_proc_get_boot_status - Command to get the processor boot status
+ * - ti_sci_proc_wait_boot_status - Command to wait for a processor boot status
+ * - ti_sci_proc_wait_boot_status_no_wait - Same as above without waiting for response
+ *
+ * NOTE: for all these functions, the following are generic in nature:
+ * @proc_id: Processor ID
+ * Returns 0 for successful request, else returns corresponding error message.
+ */
+int ti_sci_proc_request(uint8_t proc_id);
+int ti_sci_proc_release(uint8_t proc_id);
+int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id);
+int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
+ uint32_t config_flags_set,
+ uint32_t config_flags_clear);
+int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
+ uint32_t control_flags_clear);
+int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id,
+ uint32_t control_flags_set,
+ uint32_t control_flags_clear);
+int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr);
+int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
+ uint32_t *cfg_flags,
+ uint32_t *ctrl_flags,
+ uint32_t *sts_flags);
+int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations,
+ uint8_t num_match_iterations,
+ uint8_t delay_per_iteration_us,
+ uint8_t delay_before_iterations_us,
+ uint32_t status_flags_1_set_all_wait,
+ uint32_t status_flags_1_set_any_wait,
+ uint32_t status_flags_1_clr_all_wait,
+ uint32_t status_flags_1_clr_any_wait);
+int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id,
+ uint8_t num_wait_iterations,
+ uint8_t num_match_iterations,
+ uint8_t delay_per_iteration_us,
+ uint8_t delay_before_iterations_us,
+ uint32_t status_flags_1_set_all_wait,
+ uint32_t status_flags_1_set_any_wait,
+ uint32_t status_flags_1_clr_all_wait,
+ uint32_t status_flags_1_clr_any_wait);
+
+/**
+ * System Low Power Operations
+ *
+ * - ti_sci_enter_sleep - Command to initiate system transition into suspend.
+ * @proc_id: Processor ID.
+ * @mode: Low power mode to enter.
+ * @core_resume_addr: Address that core should be resumed from
+ * after low power transition.
+ *
+ * NOTE: for all these functions, the following are generic in nature:
+ * Returns 0 for successful request, else returns corresponding error message.
+ */
+int ti_sci_enter_sleep(uint8_t proc_id,
+ uint8_t mode,
+ uint64_t core_resume_addr);
+
+/**
+ * ti_sci_init() - Basic initialization
+ *
+ * Return: 0 if all goes good, else appropriate error message.
+ */
+int ti_sci_init(void);
+
+#endif /* TI_SCI_H */
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
new file mode 100644
index 0000000..d220612
--- /dev/null
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
@@ -0,0 +1,734 @@
+/*
+ * Texas Instruments System Control Interface (TISCI) Protocol
+ *
+ * Communication protocol with TI SCI hardware
+ * The system works in a message response protocol
+ * See: http://processors.wiki.ti.com/index.php/TISCI for details
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TI_SCI_PROTOCOL_H
+#define TI_SCI_PROTOCOL_H
+
+#include <stdint.h>
+
+/* Generic Messages */
+#define TI_SCI_MSG_ENABLE_WDT 0x0000
+#define TI_SCI_MSG_WAKE_RESET 0x0001
+#define TI_SCI_MSG_VERSION 0x0002
+#define TI_SCI_MSG_WAKE_REASON 0x0003
+#define TI_SCI_MSG_GOODBYE 0x0004
+#define TI_SCI_MSG_SYS_RESET 0x0005
+
+/* Device requests */
+#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200
+#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201
+#define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202
+
+/* Low Power Mode Requests */
+#define TI_SCI_MSG_ENTER_SLEEP 0x0301
+
+/* Clock requests */
+#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100
+#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101
+#define TI_SCI_MSG_SET_CLOCK_PARENT 0x0102
+#define TI_SCI_MSG_GET_CLOCK_PARENT 0x0103
+#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104
+#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c
+#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
+#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
+
+/* Processor Control Messages */
+#define TISCI_MSG_PROC_REQUEST 0xc000
+#define TISCI_MSG_PROC_RELEASE 0xc001
+#define TISCI_MSG_PROC_HANDOVER 0xc005
+#define TISCI_MSG_SET_PROC_BOOT_CONFIG 0xc100
+#define TISCI_MSG_SET_PROC_BOOT_CTRL 0xc101
+#define TISCI_MSG_PROC_AUTH_BOOT_IMIAGE 0xc120
+#define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400
+#define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401
+
+/**
+ * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
+ * @type: Type of messages: One of TI_SCI_MSG* values
+ * @host: Host of the message
+ * @seq: Message identifier indicating a transfer sequence
+ * @flags: Flag for the message
+ */
+struct ti_sci_msg_hdr {
+ uint16_t type;
+ uint8_t host;
+ uint8_t seq;
+#define TI_SCI_MSG_FLAG(val) (1 << (val))
+#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0
+#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0)
+#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1)
+#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0
+#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1)
+ /* Additional Flags */
+ uint32_t flags;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_version - Response for a message
+ * @hdr: Generic header
+ * @firmware_description: String describing the firmware
+ * @firmware_revision: Firmware revision
+ * @abi_major: Major version of the ABI that firmware supports
+ * @abi_minor: Minor version of the ABI that firmware supports
+ *
+ * In general, ABI version changes follow the rule that minor version increments
+ * are backward compatible. Major revision changes in ABI may not be
+ * backward compatible.
+ *
+ * Response to a generic message with message type TI_SCI_MSG_VERSION
+ */
+struct ti_sci_msg_resp_version {
+ struct ti_sci_msg_hdr hdr;
+#define FIRMWARE_DESCRIPTION_LENGTH 32
+ char firmware_description[FIRMWARE_DESCRIPTION_LENGTH];
+ uint16_t firmware_revision;
+ uint8_t abi_major;
+ uint8_t abi_minor;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_reboot - Reboot the SoC
+ * @hdr: Generic Header
+ * @domain: Domain to be reset, 0 for full SoC reboot
+ *
+ * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_reboot {
+ struct ti_sci_msg_hdr hdr;
+#define TI_SCI_DOMAIN_FULL_SOC_RESET 0x0
+ uint8_t domain;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_device_state - Set the desired state of the device
+ * @hdr: Generic header
+ * @id: Indicates which device to modify
+ * @reserved: Reserved space in message, must be 0 for backward compatibility
+ * @state: The desired state of the device.
+ *
+ * Certain flags can also be set to alter the device state:
+ * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source.
+ * The meaning of this flag will vary slightly from device to device and from
+ * SoC to SoC but it generally allows the device to wake the SoC out of deep
+ * suspend states.
+ * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device.
+ * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed
+ * with STATE_RETENTION or STATE_ON, it will claim the device exclusively.
+ * If another host already has this device set to STATE_RETENTION or STATE_ON,
+ * the message will fail. Once successful, other hosts attempting to set
+ * STATE_RETENTION or STATE_ON will fail.
+ *
+ * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_set_device_state {
+ /* Additional hdr->flags options */
+#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8)
+#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9)
+#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10)
+ struct ti_sci_msg_hdr hdr;
+ uint32_t id;
+ uint32_t reserved;
+
+#define MSG_DEVICE_SW_STATE_AUTO_OFF 0
+#define MSG_DEVICE_SW_STATE_RETENTION 1
+#define MSG_DEVICE_SW_STATE_ON 2
+ uint8_t state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_device_state - Request to get device.
+ * @hdr: Generic header
+ * @id: Device Identifier
+ *
+ * Request type is TI_SCI_MSG_GET_DEVICE_STATE, responded device state
+ * information
+ */
+struct ti_sci_msg_req_get_device_state {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_device_state - Response to get device request.
+ * @hdr: Generic header
+ * @context_loss_count: Indicates how many times the device has lost context. A
+ * driver can use this monotonic counter to determine if the device has
+ * lost context since the last time this message was exchanged.
+ * @resets: Programmed state of the reset lines.
+ * @programmed_state: The state as programmed by set_device.
+ * - Uses the MSG_DEVICE_SW_* macros
+ * @current_state: The actual state of the hardware.
+ *
+ * Response to request TI_SCI_MSG_GET_DEVICE_STATE.
+ */
+struct ti_sci_msg_resp_get_device_state {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t context_loss_count;
+ uint32_t resets;
+ uint8_t programmed_state;
+#define MSG_DEVICE_HW_STATE_OFF 0
+#define MSG_DEVICE_HW_STATE_ON 1
+#define MSG_DEVICE_HW_STATE_TRANS 2
+ uint8_t current_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_device_resets - Set the desired resets
+ * configuration of the device
+ * @hdr: Generic header
+ * @id: Indicates which device to modify
+ * @resets: A bit field of resets for the device. The meaning, behavior,
+ * and usage of the reset flags are device specific. 0 for a bit
+ * indicates releasing the reset represented by that bit while 1
+ * indicates keeping it held.
+ *
+ * Request type is TI_SCI_MSG_SET_DEVICE_RESETS, responded with a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_set_device_resets {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t id;
+ uint32_t resets;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state
+ * @hdr: Generic Header, Certain flags can be set specific to the clocks:
+ * MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified
+ * via spread spectrum clocking.
+ * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's
+ * frequency to be changed while it is running so long as it
+ * is within the min/max limits.
+ * MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this
+ * is only applicable to clock inputs on the SoC pseudo-device.
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has it's own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @request_state: Request the state for the clock to be set to.
+ * MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock,
+ * it can be disabled, regardless of the state of the device
+ * MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to
+ * automatically manage the state of this clock. If the device
+ * is enabled, then the clock is enabled. If the device is set
+ * to off or retention, then the clock is internally set as not
+ * being required by the device.(default)
+ * MSG_CLOCK_SW_STATE_REQ: Configure the clock to be enabled,
+ * regardless of the state of the device.
+ *
+ * Normally, all required clocks are managed by TISCI entity, this is used
+ * only for specific control *IF* required. Auto managed state is
+ * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote
+ * will explicitly control.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic
+ * ACK or NACK message.
+ */
+struct ti_sci_msg_req_set_clock_state {
+ /* Additional hdr->flags options */
+#define MSG_FLAG_CLOCK_ALLOW_SSC TI_SCI_MSG_FLAG(8)
+#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TI_SCI_MSG_FLAG(9)
+#define MSG_FLAG_CLOCK_INPUT_TERM TI_SCI_MSG_FLAG(10)
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint8_t clk_id;
+#define MSG_CLOCK_SW_STATE_UNREQ 0
+#define MSG_CLOCK_SW_STATE_AUTO 1
+#define MSG_CLOCK_SW_STATE_REQ 2
+ uint8_t request_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_state - Request for clock state
+ * @hdr: Generic Header
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has it's own set of clock inputs. This indexes
+ * which clock input to get state of.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state
+ * of the clock
+ */
+struct ti_sci_msg_req_get_clock_state {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint8_t clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_state - Response to get clock state
+ * @hdr: Generic Header
+ * @programmed_state: Any programmed state of the clock. This is one of
+ * MSG_CLOCK_SW_STATE* values.
+ * @current_state: Current state of the clock. This is one of:
+ * MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready
+ * MSG_CLOCK_HW_STATE_READY: Clock is ready
+ *
+ * Response to TI_SCI_MSG_GET_CLOCK_STATE.
+ */
+struct ti_sci_msg_resp_get_clock_state {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t programmed_state;
+#define MSG_CLOCK_HW_STATE_NOT_READY 0
+#define MSG_CLOCK_HW_STATE_READY 1
+ uint8_t current_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_parent - Set the clock parent
+ * @hdr: Generic Header
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has it's own set of clock inputs. This indexes
+ * which clock input to modify.
+ * @parent_id: The new clock parent is selectable by an index via this
+ * parameter.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic
+ * ACK / NACK message.
+ */
+struct ti_sci_msg_req_set_clock_parent {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint8_t clk_id;
+ uint8_t parent_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_parent - Get the clock parent
+ * @hdr: Generic Header
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ * Each device has it's own set of clock inputs. This indexes
+ * which clock input to get the parent for.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information
+ */
+struct ti_sci_msg_req_get_clock_parent {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint8_t clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent
+ * @hdr: Generic Header
+ * @parent_id: The current clock parent
+ *
+ * Response to TI_SCI_MSG_GET_CLOCK_PARENT.
+ */
+struct ti_sci_msg_resp_get_clock_parent {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t parent_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents
+ * @hdr: Generic header
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ *
+ * This request provides information about how many clock parent options
+ * are available for a given clock to a device. This is typically used
+ * for input clocks.
+ *
+ * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate
+ * message, or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_get_clock_num_parents {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint8_t clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents
+ * @hdr: Generic header
+ * @num_parents: Number of clock parents
+ *
+ * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS
+ */
+struct ti_sci_msg_resp_get_clock_num_parents {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t num_parents;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency
+ * @hdr: Generic Header
+ * @dev_id: Device identifier this request is for
+ * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @target_freq_hz: The target clock frequency. A frequency will be found
+ * as close to this target frequency as possible.
+ * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @clk_id: Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In case of specific requests, TISCI evaluates capability to achieve
+ * requested frequency within provided range and responds with
+ * result message.
+ *
+ * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message,
+ * or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_query_clock_freq {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint64_t min_freq_hz;
+ uint64_t target_freq_hz;
+ uint64_t max_freq_hz;
+ uint8_t clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query
+ * @hdr: Generic Header
+ * @freq_hz: Frequency that is the best match in Hz.
+ *
+ * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request
+ * cannot be satisfied, the message will be of type NACK.
+ */
+struct ti_sci_msg_resp_query_clock_freq {
+ struct ti_sci_msg_hdr hdr;
+ uint64_t freq_hz;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency
+ * @hdr: Generic Header
+ * @dev_id: Device identifier this request is for
+ * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @target_freq_hz: The target clock frequency. The clock will be programmed
+ * at a rate as close to this target frequency as possible.
+ * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
+ * allowable programmed frequency and does not account for clock
+ * tolerances and jitter.
+ * @clk_id: Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In case of specific requests, TISCI evaluates capability to achieve
+ * requested range and responds with success/failure message.
+ *
+ * This sets the desired frequency for a clock within an allowable
+ * range. This message will fail on an enabled clock unless
+ * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally,
+ * if other clocks have their frequency modified due to this message,
+ * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled.
+ *
+ * Calling set frequency on a clock input to the SoC pseudo-device will
+ * inform the PMMC of that clock's frequency. Setting a frequency of
+ * zero will indicate the clock is disabled.
+ *
+ * Calling set frequency on clock outputs from the SoC pseudo-device will
+ * function similarly to setting the clock frequency on a device.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK
+ * message.
+ */
+struct ti_sci_msg_req_set_clock_freq {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint64_t min_freq_hz;
+ uint64_t target_freq_hz;
+ uint64_t max_freq_hz;
+ uint8_t clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency
+ * @hdr: Generic Header
+ * @dev_id: Device identifier this request is for
+ * @clk_id: Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In some cases, clock frequencies are configured by host.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency
+ * that the clock is currently at.
+ */
+struct ti_sci_msg_req_get_clock_freq {
+ struct ti_sci_msg_hdr hdr;
+ uint32_t dev_id;
+ uint8_t clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request
+ * @hdr: Generic Header
+ * @freq_hz: Frequency that the clock is currently on, in Hz.
+ *
+ * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ.
+ */
+struct ti_sci_msg_resp_get_clock_freq {
+ struct ti_sci_msg_hdr hdr;
+ uint64_t freq_hz;
+} __packed;
+
+#define TISCI_ADDR_LOW_MASK 0x00000000ffffffff
+#define TISCI_ADDR_HIGH_MASK 0xffffffff00000000
+#define TISCI_ADDR_HIGH_SHIFT 32
+
+/**
+ * struct ti_sci_msg_req_proc_request - Request a processor
+ *
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ *
+ * Request type is TISCI_MSG_PROC_REQUEST, response is a generic ACK/NACK
+ * message.
+ */
+struct ti_sci_msg_req_proc_request {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_proc_release - Release a processor
+ *
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ *
+ * Request type is TISCI_MSG_PROC_RELEASE, response is a generic ACK/NACK
+ * message.
+ */
+struct ti_sci_msg_req_proc_release {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_proc_handover - Handover a processor to a host
+ *
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ * @host_id: New Host we want to give control to
+ *
+ * Request type is TISCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK
+ * message.
+ */
+struct ti_sci_msg_req_proc_handover {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+ uint8_t host_id;
+} __packed;
+
+/* A53 Config Flags */
+#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_EN 0x00000001
+#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_NIDEN 0x00000002
+#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPIDEN 0x00000004
+#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPNIDEN 0x00000008
+#define PROC_BOOT_CFG_FLAG_ARMV8_AARCH32 0x00000100
+
+/* R5 Config Flags */
+#define PROC_BOOT_CFG_FLAG_R5_DBG_EN 0x00000001
+#define PROC_BOOT_CFG_FLAG_R5_DBG_NIDEN 0x00000002
+#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP 0x00000100
+#define PROC_BOOT_CFG_FLAG_R5_TEINIT 0x00000200
+#define PROC_BOOT_CFG_FLAG_R5_NMFI_EN 0x00000400
+#define PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE 0x00000800
+#define PROC_BOOT_CFG_FLAG_R5_BTCM_EN 0x00001000
+#define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000
+
+/**
+ * struct ti_sci_msg_req_set_proc_boot_config - Set Processor boot configuration
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ * @bootvector_low: Lower 32bit (Little Endian) of boot vector
+ * @bootvector_high: Higher 32bit (Little Endian) of boot vector
+ * @config_flags_set: Optional Processor specific Config Flags to set.
+ * Setting a bit here implies required bit sets to 1.
+ * @config_flags_clear: Optional Processor specific Config Flags to clear.
+ * Setting a bit here implies required bit gets cleared.
+ *
+ * Request type is TISCI_MSG_SET_PROC_BOOT_CONFIG, response is a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_set_proc_boot_config {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+ uint32_t bootvector_low;
+ uint32_t bootvector_high;
+ uint32_t config_flags_set;
+ uint32_t config_flags_clear;
+} __packed;
+
+/* ARMV8 Control Flags */
+#define PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM 0x00000001
+#define PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS 0x00000002
+#define PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ 0x00000100
+
+/* R5 Control Flags */
+#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001
+
+/**
+ * struct ti_sci_msg_req_set_proc_boot_ctrl - Set Processor boot control flags
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ * @config_flags_set: Optional Processor specific Config Flags to set.
+ * Setting a bit here implies required bit sets to 1.
+ * @config_flags_clear: Optional Processor specific Config Flags to clear.
+ * Setting a bit here implies required bit gets cleared.
+ *
+ * Request type is TISCI_MSG_SET_PROC_BOOT_CTRL, response is a generic ACK/NACK
+ * message.
+ */
+struct ti_sci_msg_req_set_proc_boot_ctrl {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+ uint32_t control_flags_set;
+ uint32_t control_flags_clear;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_proc_auth_start_image - Authenticate and start image
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ * @cert_addr_low: Lower 32bit (Little Endian) of certificate
+ * @cert_addr_high: Higher 32bit (Little Endian) of certificate
+ *
+ * Request type is TISCI_MSG_PROC_AUTH_BOOT_IMAGE, response is a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_proc_auth_boot_image {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+ uint32_t cert_addr_low;
+ uint32_t cert_addr_high;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_proc_boot_status - Get processor boot status
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ *
+ * Request type is TISCI_MSG_GET_PROC_BOOT_STATUS, response is appropriate
+ * message, or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_get_proc_boot_status {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+} __packed;
+
+/* ARMv8 Status Flags */
+#define PROC_BOOT_STATUS_FLAG_ARMV8_WFE 0x00000001
+#define PROC_BOOT_STATUS_FLAG_ARMV8_WFI 0x00000002
+#define PROC_BOOT_STATUS_FLAG_ARMV8_L2F_DONE 0x00000010
+#define PROC_BOOT_STATUS_FLAG_ARMV8_STANDBYWFIL2 0x00000020
+
+/* R5 Status Flags */
+#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001
+#define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002
+#define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004
+#define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100
+
+/**
+ * \brief Processor Status Response
+ * struct ti_sci_msg_resp_get_proc_boot_status - Processor boot status response
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ * @bootvector_low: Lower 32bit (Little Endian) of boot vector
+ * @bootvector_high: Higher 32bit (Little Endian) of boot vector
+ * @config_flags: Optional Processor specific Config Flags set.
+ * @control_flags: Optional Processor specific Control Flags.
+ * @status_flags: Optional Processor specific Status Flags set.
+ *
+ * Response to TISCI_MSG_GET_PROC_BOOT_STATUS.
+ */
+struct ti_sci_msg_resp_get_proc_boot_status {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+ uint32_t bootvector_low;
+ uint32_t bootvector_high;
+ uint32_t config_flags;
+ uint32_t control_flags;
+ uint32_t status_flags;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_wait_proc_boot_status - Wait for a processor boot status
+ * @hdr: Generic Header
+ * @processor_id: ID of processor
+ * @num_wait_iterations Total number of iterations we will check before
+ * we will timeout and give up
+ * @num_match_iterations How many iterations should we have continued
+ * status to account for status bits glitching.
+ * This is to make sure that match occurs for
+ * consecutive checks. This implies that the
+ * worst case should consider that the stable
+ * time should at the worst be num_wait_iterations
+ * num_match_iterations to prevent timeout.
+ * @delay_per_iteration_us Specifies how long to wait (in micro seconds)
+ * between each status checks. This is the minimum
+ * duration, and overhead of register reads and
+ * checks are on top of this and can vary based on
+ * varied conditions.
+ * @delay_before_iterations_us Specifies how long to wait (in micro seconds)
+ * before the very first check in the first
+ * iteration of status check loop. This is the
+ * minimum duration, and overhead of register
+ * reads and checks are.
+ * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the
+ * status matching this field requested MUST be 1.
+ * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the
+ * bits matching this field requested MUST be 1.
+ * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the
+ * status matching this field requested MUST be 0.
+ * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the
+ * bits matching this field requested MUST be 0.
+ *
+ * Request type is TISCI_MSG_WAIT_PROC_BOOT_STATUS, response is appropriate
+ * message, or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_wait_proc_boot_status {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t processor_id;
+ uint8_t num_wait_iterations;
+ uint8_t num_match_iterations;
+ uint8_t delay_per_iteration_us;
+ uint8_t delay_before_iterations_us;
+ uint32_t status_flags_1_set_all_wait;
+ uint32_t status_flags_1_set_any_wait;
+ uint32_t status_flags_1_clr_all_wait;
+ uint32_t status_flags_1_clr_any_wait;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_enter_sleep - Request for TI_SCI_MSG_ENTER_SLEEP.
+ *
+ * @hdr Generic Header
+ * @mode Low power mode to enter.
+ * @proc_id Processor id to be restored.
+ * @core_resume_lo Low 32-bits of physical pointer to address for core
+ * to begin execution upon resume.
+ * @core_resume_hi High 32-bits of physical pointer to address for core
+ * to begin execution upon resume.
+ *
+ * This message is to be sent after TI_SCI_MSG_PREPARE_SLEEP is sent from OS
+ * and is what actually triggers entry into the specified low power mode.
+ */
+struct ti_sci_msg_req_enter_sleep {
+ struct ti_sci_msg_hdr hdr;
+ uint8_t mode;
+ uint8_t processor_id;
+ uint32_t core_resume_lo;
+ uint32_t core_resume_hi;
+} __packed;
+
+#endif /* TI_SCI_PROTOCOL_H */
diff --git a/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
new file mode 100644
index 0000000..457c95d
--- /dev/null
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <k3_console.h>
+#include <k3_gicv3.h>
+#include <ti_sci.h>
+
+/* Table of regions to map using the MMU */
+const mmap_region_t plat_k3_mmap[] = {
+ MAP_REGION_FLAT(K3_USART_BASE, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(K3_GIC_BASE, K3_GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(K3_GTC_BASE, K3_GTC_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ { /* sentinel */ }
+};
+
+/*
+ * Placeholder variables for maintaining information about the next image(s)
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Gets SPSR for BL33 entry
+ ******************************************************************************/
+static uint32_t k3_get_spsr_for_bl33_entry(void)
+{
+ unsigned long el_status;
+ unsigned int mode;
+ uint32_t spsr;
+
+ /* Figure out what mode we enter the non-secure world in */
+ el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+ el_status &= ID_AA64PFR0_ELX_MASK;
+
+ mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+ return spsr;
+}
+
+/*******************************************************************************
+ * Perform any BL3-1 early platform setup, such as console init and deciding on
+ * memory layout.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(arg0 == 0U);
+ assert(arg1 == 0U);
+
+ bl31_console_setup();
+
+#ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+#endif
+
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+ bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
+ bl33_image_ep_info.spsr = k3_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef K3_HW_CONFIG_BASE
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ */
+ bl33_image_ep_info.args.arg0 = (u_register_t)K3_HW_CONFIG_BASE;
+ bl33_image_ep_info.args.arg1 = 0U;
+ bl33_image_ep_info.args.arg2 = 0U;
+ bl33_image_ep_info.args.arg3 = 0U;
+#endif
+}
+
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL31_START, BL31_SIZE, MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, MT_CODE | MT_RO | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE, MT_RO_DATA | MT_RO | MT_SECURE),
+#if USE_COHERENT_MEM
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+ { /* sentinel */ }
+ };
+
+ setup_page_tables(bl_regions, plat_k3_mmap);
+ enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+ k3_gic_driver_init(K3_GIC_BASE);
+ k3_gic_init();
+
+ ti_sci_init();
+}
+
+void platform_mem_init(void)
+{
+ /* Do nothing for now... */
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+ uint32_t gtc_freq;
+ uint32_t gtc_ctrl;
+
+ /* Lets try and provide basic diagnostics - cost is low */
+ gtc_ctrl = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTCR_OFFSET);
+ /* Did the bootloader fail to enable timer and OS guys are confused? */
+ if ((gtc_ctrl & K3_GTC_CNTCR_EN_MASK) == 0U) {
+ ERROR("GTC is disabled! Timekeeping broken. Fix Bootloader\n");
+ }
+ /*
+ * If debug will not pause time, we will have issues like
+ * drivers timing out while debugging, in cases of OS like Linux,
+ * RCU stall errors, which can be hard to differentiate vs real issues.
+ */
+ if ((gtc_ctrl & K3_GTC_CNTCR_HDBG_MASK) == 0U) {
+ WARN("GTC: Debug access doesn't stop time. Fix Bootloader\n");
+ }
+
+ gtc_freq = mmio_read_32(K3_GTC_BASE + K3_GTC_CNTFID0_OFFSET);
+ /* Many older bootloaders may have missed programming FID0 register */
+ if (gtc_freq != 0U) {
+ return gtc_freq;
+ }
+
+ /*
+ * We could have just warned about this, but this can have serious
+ * hard to debug side effects if we are NOT sure what the actual
+ * frequency is. Lets make sure people don't miss this.
+ */
+ ERROR("GTC_CNTFID0 is 0! Assuming %d Hz. Fix Bootloader\n",
+ SYS_COUNTER_FREQ_IN_TICKS);
+
+ return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+/*
+ * Empty function to prevent the console from being uninitialized after BL33 is
+ * started and allow us to see messages from BL31.
+ */
+void bl31_plat_runtime_setup(void)
+{
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image
+ * for the security state specified. BL3-3 corresponds to the non-secure
+ * image type while BL3-2 corresponds to the secure image type. A NULL
+ * pointer is returned if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ next_image_info = (type == NON_SECURE) ? &bl33_image_ep_info :
+ &bl32_image_ep_info;
+ /*
+ * None of the images on the ARM development platforms can have 0x0
+ * as the entrypoint
+ */
+ if (next_image_info->pc)
+ return next_image_info;
+
+ NOTICE("Requested nonexistent image\n");
+ return NULL;
+}
diff --git a/plat/ti/k3/common/k3_console.c b/plat/ti/k3/common/k3_console.c
new file mode 100644
index 0000000..8c44c17
--- /dev/null
+++ b/plat/ti/k3/common/k3_console.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <drivers/console.h>
+#include <drivers/ti/uart/uart_16550.h>
+
+#include <k3_console.h>
+
+void bl31_console_setup(void)
+{
+ static console_t console;
+
+ /* Initialize the console to provide early debug support */
+ console_16550_register(K3_USART_BASE, K3_USART_CLK_SPEED,
+ K3_USART_BAUD, &console);
+}
diff --git a/plat/ti/k3/common/k3_gicv3.c b/plat/ti/k3/common/k3_gicv3.c
new file mode 100644
index 0000000..0199822
--- /dev/null
+++ b/plat/ti/k3/common/k3_gicv3.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include <k3_gicv3.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+#if K3_PM_SYSTEM_SUSPEND
+static gicv3_redist_ctx_t rdist_ctx[PLATFORM_CORE_COUNT];
+static gicv3_dist_ctx_t dist_ctx;
+#endif
+
+static const interrupt_prop_t k3_interrupt_props[] = {
+ PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+static unsigned int k3_mpidr_to_core_pos(unsigned long mpidr)
+{
+ return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+gicv3_driver_data_t k3_gic_data = {
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .interrupt_props = k3_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(k3_interrupt_props),
+ .mpidr_to_core_pos = k3_mpidr_to_core_pos,
+};
+
+void k3_gic_driver_init(uintptr_t gic_base)
+{
+ /* GIC Distributor is always at the base of the IP */
+ uintptr_t gicd_base = gic_base;
+ /* GIC Redistributor base is run-time detected */
+ uintptr_t gicr_base = 0;
+
+ for (unsigned int gicr_shift = 18; gicr_shift < 21; gicr_shift++) {
+ uintptr_t gicr_check = gic_base + BIT(gicr_shift);
+ uint32_t iidr = mmio_read_32(gicr_check + GICR_IIDR);
+ if (iidr != 0) {
+ /* Found the GICR base */
+ gicr_base = gicr_check;
+ break;
+ }
+ }
+ /* Assert if we have not found the GICR base */
+ assert(gicr_base != 0);
+
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+ k3_gic_data.gicd_base = gicd_base;
+ k3_gic_data.gicr_base = gicr_base;
+ gicv3_driver_init(&k3_gic_data);
+}
+
+void k3_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void k3_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+void k3_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+void k3_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+#if K3_PM_SYSTEM_SUSPEND
+void k3_gic_save_context(void)
+{
+ for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
+ gicv3_rdistif_save(i, &rdist_ctx[i]);
+ }
+ gicv3_distif_save(&dist_ctx);
+}
+
+void k3_gic_restore_context(void)
+{
+ gicv3_distif_init_restore(&dist_ctx);
+ for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
+ gicv3_rdistif_init_restore(i, &rdist_ctx[i]);
+ }
+}
+#endif
diff --git a/plat/ti/k3/common/k3_helpers.S b/plat/ti/k3/common/k3_helpers.S
new file mode 100644
index 0000000..f4f7d18
--- /dev/null
+++ b/plat/ti/k3/common/k3_helpers.S
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cortex_a72.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+#define K3_BOOT_REASON_COLD_RESET 0x1
+
+ /* ------------------------------------------------------------------
+ * uintptr_t plat_get_my_entrypoint(void)
+ * ------------------------------------------------------------------
+ *
+ * This function is called with the called with the MMU and caches
+ * disabled (SCTLR_EL3.M = 0 and SCTLR_EL3.C = 0). The function is
+ * responsible for distinguishing between a warm and cold reset for the
+ * current CPU using platform-specific means. If it's a warm reset,
+ * then it returns the warm reset entrypoint point provided to
+ * plat_setup_psci_ops() during BL31 initialization. If it's a cold
+ * reset then this function must return zero.
+ *
+ * This function does not follow the Procedure Call Standard used by
+ * the Application Binary Interface for the ARM 64-bit architecture.
+ * The caller should not assume that callee saved registers are
+ * preserved across a call to this function.
+ */
+ .globl plat_get_my_entrypoint
+func plat_get_my_entrypoint
+ ldr x0, k3_boot_reason_data_store
+ cmp x0, #K3_BOOT_REASON_COLD_RESET
+
+ /* We ONLY support cold boot at this point */
+ bne plat_unsupported_boot
+ mov x0, #0
+ ret
+
+ /*
+ * We self manage our boot reason.
+ * At load time, we have just a default reason - which is cold reset
+ */
+k3_boot_reason_data_store:
+ .word K3_BOOT_REASON_COLD_RESET
+
+plat_unsupported_boot:
+ b plat_unsupported_boot
+
+endfunc plat_get_my_entrypoint
+
+ /* ------------------------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * ------------------------------------------------------------------
+ *
+ * This function returns the index of the calling CPU which is used as a
+ * CPU-specific linear index into blocks of memory (for example while
+ * allocating per-CPU stacks). This function will be invoked very early
+ * in the initialization sequence which mandates that this function
+ * should be implemented in assembly and should not rely on the
+ * avalability of a C runtime environment. This function can clobber x0
+ * - x8 and must preserve x9 - x29.
+ *
+ * This function plays a crucial role in the power domain topology
+ * framework in PSCI and details of this can be found in Power Domain
+ * Topology Design.
+ */
+ .globl plat_my_core_pos
+func plat_my_core_pos
+ mrs x0, MPIDR_EL1
+
+ and x1, x0, #MPIDR_CLUSTER_MASK
+ lsr x1, x1, #MPIDR_AFF1_SHIFT
+ and x0, x0, #MPIDR_CPU_MASK
+
+ cmp x1, 0
+ b.eq out
+ add x0, x0, #K3_CLUSTER0_CORE_COUNT
+
+ cmp x1, 1
+ b.eq out
+ add x0, x0, #K3_CLUSTER1_CORE_COUNT
+
+ cmp x1, 2
+ b.eq out
+ add x0, x0, #K3_CLUSTER2_CORE_COUNT
+
+out:
+ ret
+endfunc plat_my_core_pos
+
+ /* --------------------------------------------------------------------
+ * This handler does the following:
+ * - Set the L2 Data RAM latency to 2 (i.e. 3 cycles) for Cortex-A72
+ * --------------------------------------------------------------------
+ */
+ .globl plat_reset_handler
+func plat_reset_handler
+ /* Only on Cortex-A72 */
+ jump_if_cpu_midr CORTEX_A72_MIDR, a72
+ ret
+
+ /* Cortex-A72 specific settings */
+a72:
+ mrs x0, CORTEX_A72_L2CTLR_EL1
+ orr x0, x0, #(CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT)
+ msr CORTEX_A72_L2CTLR_EL1, x0
+ isb
+ ret
+endfunc plat_reset_handler
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ * ---------------------------------------------
+ */
+ .globl plat_crash_console_init
+func plat_crash_console_init
+ mov_imm x0, CRASH_CONSOLE_BASE
+ mov_imm x1, CRASH_CONSOLE_CLK
+ mov_imm x2, CRASH_CONSOLE_BAUD_RATE
+ mov w3, #0x0
+ b console_16550_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(void)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+ .globl plat_crash_console_putc
+func plat_crash_console_putc
+ mov_imm x1, CRASH_CONSOLE_BASE
+ b console_16550_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+ .globl plat_crash_console_flush
+func plat_crash_console_flush
+ mov_imm x0, CRASH_CONSOLE_BASE
+ b console_16550_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c
new file mode 100644
index 0000000..6febbc6
--- /dev/null
+++ b/plat/ti/k3/common/k3_psci.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/el3_runtime/cpu_data.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <ti_sci_protocol.h>
+#include <k3_gicv3.h>
+#include <ti_sci.h>
+
+#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
+uintptr_t k3_sec_entrypoint;
+
+static void k3_cpu_standby(plat_local_state_t cpu_state)
+{
+ u_register_t scr;
+
+ scr = read_scr_el3();
+ /* Enable the Non secure interrupt to wake the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+ isb();
+ /* dsb is good practice before using wfi to enter low power states */
+ dsb();
+ /* Enter standby state */
+ wfi();
+ /* Restore SCR */
+ write_scr_el3(scr);
+}
+
+static int k3_pwr_domain_on(u_register_t mpidr)
+{
+ int core, proc_id, device_id, ret;
+
+ core = plat_core_pos_by_mpidr(mpidr);
+ if (core < 0) {
+ ERROR("Could not get target core id: %d\n", core);
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ proc_id = PLAT_PROC_START_ID + core;
+ device_id = PLAT_PROC_DEVICE_START_ID + core;
+
+ ret = ti_sci_proc_request(proc_id);
+ if (ret) {
+ ERROR("Request for processor failed: %d\n", ret);
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ ret = ti_sci_proc_set_boot_cfg(proc_id, k3_sec_entrypoint, 0, 0);
+ if (ret) {
+ ERROR("Request to set core boot address failed: %d\n", ret);
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ /* sanity check these are off before starting a core */
+ ret = ti_sci_proc_set_boot_ctrl(proc_id,
+ 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ |
+ PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS |
+ PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM);
+ if (ret) {
+ ERROR("Request to clear boot configuration failed: %d\n", ret);
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ ret = ti_sci_device_get(device_id);
+ if (ret) {
+ ERROR("Request to start core failed: %d\n", ret);
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+void k3_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ int core, cluster, proc_id, device_id, cluster_id, ret;
+
+ /* At very least the local core should be powering down */
+ assert(CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ k3_gic_cpuif_disable();
+
+ core = plat_my_core_pos();
+ cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
+ proc_id = PLAT_PROC_START_ID + core;
+ device_id = PLAT_PROC_DEVICE_START_ID + core;
+ cluster_id = PLAT_CLUSTER_DEVICE_START_ID + (cluster * 2);
+
+ /*
+ * If we are the last core in the cluster then we take a reference to
+ * the cluster device so that it does not get shutdown before we
+ * execute the entire cluster L2 cleaning sequence below.
+ */
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
+ ret = ti_sci_device_get(cluster_id);
+ if (ret) {
+ ERROR("Request to get cluster failed: %d\n", ret);
+ return;
+ }
+ }
+
+ /* Start by sending wait for WFI command */
+ ret = ti_sci_proc_wait_boot_status_no_wait(proc_id,
+ /*
+ * Wait maximum time to give us the best chance to get
+ * to WFI before this command timeouts
+ */
+ UINT8_MAX, 100, UINT8_MAX, UINT8_MAX,
+ /* Wait for WFI */
+ PROC_BOOT_STATUS_FLAG_ARMV8_WFI, 0, 0, 0);
+ if (ret) {
+ ERROR("Sending wait for WFI failed (%d)\n", ret);
+ return;
+ }
+
+ /* Now queue up the core shutdown request */
+ ret = ti_sci_device_put_no_wait(device_id);
+ if (ret) {
+ ERROR("Sending core shutdown message failed (%d)\n", ret);
+ return;
+ }
+
+ /* If our cluster is not going down we stop here */
+ if (CLUSTER_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
+ return;
+
+ /* set AINACTS */
+ ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
+ PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS, 0);
+ if (ret) {
+ ERROR("Sending set control message failed (%d)\n", ret);
+ return;
+ }
+
+ /* set L2FLUSHREQ */
+ ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
+ PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ, 0);
+ if (ret) {
+ ERROR("Sending set control message failed (%d)\n", ret);
+ return;
+ }
+
+ /* wait for L2FLUSHDONE*/
+ ret = ti_sci_proc_wait_boot_status_no_wait(proc_id,
+ UINT8_MAX, 2, UINT8_MAX, UINT8_MAX,
+ PROC_BOOT_STATUS_FLAG_ARMV8_L2F_DONE, 0, 0, 0);
+ if (ret) {
+ ERROR("Sending wait message failed (%d)\n", ret);
+ return;
+ }
+
+ /* clear L2FLUSHREQ */
+ ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
+ 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ);
+ if (ret) {
+ ERROR("Sending set control message failed (%d)\n", ret);
+ return;
+ }
+
+ /* set ACINACTM */
+ ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id,
+ PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM, 0);
+ if (ret) {
+ ERROR("Sending set control message failed (%d)\n", ret);
+ return;
+ }
+
+ /* wait for STANDBYWFIL2 */
+ ret = ti_sci_proc_wait_boot_status_no_wait(proc_id,
+ UINT8_MAX, 2, UINT8_MAX, UINT8_MAX,
+ PROC_BOOT_STATUS_FLAG_ARMV8_STANDBYWFIL2, 0, 0, 0);
+ if (ret) {
+ ERROR("Sending wait message failed (%d)\n", ret);
+ return;
+ }
+
+ /* Now queue up the cluster shutdown request */
+ ret = ti_sci_device_put_no_wait(cluster_id);
+ if (ret) {
+ ERROR("Sending cluster shutdown message failed (%d)\n", ret);
+ return;
+ }
+}
+
+void k3_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* TODO: Indicate to System firmware about completion */
+
+ k3_gic_pcpu_init();
+ k3_gic_cpuif_enable();
+}
+
+static void __dead2 k3_system_off(void)
+{
+ ERROR("System Off: operation not handled.\n");
+ while (true)
+ wfi();
+}
+
+static void __dead2 k3_system_reset(void)
+{
+ /* Send the system reset request to system firmware */
+ ti_sci_core_reboot();
+
+ while (true)
+ wfi();
+}
+
+static int k3_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ /* TODO: perform the proper validation */
+
+ return PSCI_E_SUCCESS;
+}
+
+static int k3_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /* TODO: perform the proper validation */
+
+ return PSCI_E_SUCCESS;
+}
+
+#if K3_PM_SYSTEM_SUSPEND
+static void k3_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ unsigned int core, proc_id;
+
+ core = plat_my_core_pos();
+ proc_id = PLAT_PROC_START_ID + core;
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ k3_gic_cpuif_disable();
+ k3_gic_save_context();
+
+ k3_pwr_domain_off(target_state);
+
+ ti_sci_enter_sleep(proc_id, 0, k3_sec_entrypoint);
+}
+
+static void k3_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ k3_gic_restore_context();
+ k3_gic_cpuif_enable();
+}
+
+static void k3_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ /* CPU & cluster off, system in retention */
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) {
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ }
+}
+#endif
+
+static const plat_psci_ops_t k3_plat_psci_ops = {
+ .cpu_standby = k3_cpu_standby,
+ .pwr_domain_on = k3_pwr_domain_on,
+ .pwr_domain_off = k3_pwr_domain_off,
+ .pwr_domain_on_finish = k3_pwr_domain_on_finish,
+#if K3_PM_SYSTEM_SUSPEND
+ .pwr_domain_suspend = k3_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = k3_pwr_domain_suspend_finish,
+ .get_sys_suspend_power_state = k3_get_sys_suspend_power_state,
+#endif
+ .system_off = k3_system_off,
+ .system_reset = k3_system_reset,
+ .validate_power_state = k3_validate_power_state,
+ .validate_ns_entrypoint = k3_validate_ns_entrypoint
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ k3_sec_entrypoint = sec_entrypoint;
+
+ *psci_ops = &k3_plat_psci_ops;
+
+ return 0;
+}
diff --git a/plat/ti/k3/common/k3_topology.c b/plat/ti/k3/common/k3_topology.c
new file mode 100644
index 0000000..139f1fd
--- /dev/null
+++ b/plat/ti/k3/common/k3_topology.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <lib/psci/psci.h>
+
+/* The power domain tree descriptor */
+static unsigned char power_domain_tree_desc[] = {
+ PLATFORM_SYSTEM_COUNT,
+ PLATFORM_CLUSTER_COUNT,
+ K3_CLUSTER0_CORE_COUNT,
+ K3_CLUSTER1_CORE_COUNT,
+ K3_CLUSTER2_CORE_COUNT,
+ K3_CLUSTER3_CORE_COUNT,
+};
+
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return power_domain_tree_desc;
+}
+
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
+
+ if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
+ MPIDR_AFFLVL2_VAL(mpidr) > 0) {
+ return -1;
+ }
+
+ if (cluster > 0)
+ core += K3_CLUSTER0_CORE_COUNT;
+ if (cluster > 1)
+ core += K3_CLUSTER1_CORE_COUNT;
+ if (cluster > 2)
+ core += K3_CLUSTER2_CORE_COUNT;
+ if (cluster > 3)
+ return -1;
+
+ return core;
+}
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
new file mode 100644
index 0000000..026d6a3
--- /dev/null
+++ b/plat/ti/k3/common/plat_common.mk
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# We don't use BL1 or BL2, so BL31 is the first image to execute
+RESET_TO_BL31 := 1
+# Only one core starts up at first
+COLD_BOOT_SINGLE_CPU := 1
+# We can choose where a core starts executing
+PROGRAMMABLE_RESET_ADDRESS:= 1
+
+# ARM coherency is managed in hardware
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
+
+# A53 erratum for SoC. (enable them all)
+ERRATA_A53_826319 := 1
+ERRATA_A53_835769 := 1
+ERRATA_A53_836870 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
+
+# A72 Erratum for SoC
+ERRATA_A72_859971 := 1
+ERRATA_A72_1319367 := 1
+
+CRASH_REPORTING := 1
+HANDLE_EA_EL3_FIRST_NS := 1
+
+# Split out RO data into a non-executable section
+SEPARATE_CODE_AND_RODATA := 1
+
+# Generate a Position Independent Executable
+ENABLE_PIE := 1
+
+TI_16550_MDR_QUIRK := 1
+$(eval $(call add_define,TI_16550_MDR_QUIRK))
+
+K3_USART := 0
+$(eval $(call add_define,K3_USART))
+
+# Allow customizing the UART baud rate
+K3_USART_BAUD := 115200
+$(eval $(call add_define,K3_USART_BAUD))
+
+# Enable system suspend modes
+K3_PM_SYSTEM_SUSPEND := 0
+$(eval $(call add_define,K3_PM_SYSTEM_SUSPEND))
+
+# Libraries
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES += \
+ -I${PLAT_PATH}/include \
+ -I${PLAT_PATH}/common/drivers/sec_proxy \
+ -I${PLAT_PATH}/common/drivers/ti_sci \
+
+K3_CONSOLE_SOURCES += \
+ drivers/ti/uart/aarch64/16550_console.S \
+ ${PLAT_PATH}/common/k3_console.c \
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+K3_GIC_SOURCES += \
+ ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ ${PLAT_PATH}/common/k3_gicv3.c \
+
+K3_PSCI_SOURCES += \
+ plat/common/plat_psci_common.c \
+ ${PLAT_PATH}/common/k3_psci.c \
+
+K3_SEC_PROXY_SOURCES += \
+ ${PLAT_PATH}/common/drivers/sec_proxy/sec_proxy.c \
+
+K3_TI_SCI_SOURCES += \
+ ${PLAT_PATH}/common/drivers/ti_sci/ti_sci.c \
+
+PLAT_BL_COMMON_SOURCES += \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${K3_CONSOLE_SOURCES} \
+
+BL31_SOURCES += \
+ ${PLAT_PATH}/common/k3_bl31_setup.c \
+ ${PLAT_PATH}/common/k3_helpers.S \
+ ${PLAT_PATH}/common/k3_topology.c \
+ ${K3_GIC_SOURCES} \
+ ${K3_PSCI_SOURCES} \
+ ${K3_SEC_PROXY_SOURCES} \
+ ${K3_TI_SCI_SOURCES} \
diff --git a/plat/ti/k3/include/k3_console.h b/plat/ti/k3/include/k3_console.h
new file mode 100644
index 0000000..6376ab3
--- /dev/null
+++ b/plat/ti/k3/include/k3_console.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef K3_CONSOLE_H
+#define K3_CONSOLE_H
+
+void bl31_console_setup(void);
+
+#endif /* K3_CONSOLE_H */
diff --git a/plat/ti/k3/include/k3_gicv3.h b/plat/ti/k3/include/k3_gicv3.h
new file mode 100644
index 0000000..2c68a75
--- /dev/null
+++ b/plat/ti/k3/include/k3_gicv3.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef K3_GICV3_H
+#define K3_GICV3_H
+
+#include <stdint.h>
+
+void k3_gic_driver_init(uintptr_t gic_base);
+void k3_gic_init(void);
+void k3_gic_cpuif_enable(void);
+void k3_gic_cpuif_disable(void);
+void k3_gic_pcpu_init(void);
+void k3_gic_save_context(void);
+void k3_gic_restore_context(void);
+
+#endif /* K3_GICV3_H */
diff --git a/plat/ti/k3/include/plat_macros.S b/plat/ti/k3/include/plat_macros.S
new file mode 100644
index 0000000..38056b5
--- /dev/null
+++ b/plat/ti/k3/include/plat_macros.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /* STUB */
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
new file mode 100644
index 0000000..81a383a
--- /dev/null
+++ b/plat/ti/k3/include/platform_def.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <plat/common/common_def.h>
+
+#include <board_def.h>
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stack */
+#if IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#else
+#define PLATFORM_STACK_SIZE 0x1000
+#endif
+
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CORE_COUNT (K3_CLUSTER0_CORE_COUNT + \
+ K3_CLUSTER1_CORE_COUNT + \
+ K3_CLUSTER2_CORE_COUNT + \
+ K3_CLUSTER3_CORE_COUNT)
+
+#define PLATFORM_CLUSTER_COUNT ((K3_CLUSTER0_CORE_COUNT != 0) + \
+ (K3_CLUSTER1_CORE_COUNT != 0) + \
+ (K3_CLUSTER2_CORE_COUNT != 0) + \
+ (K3_CLUSTER3_CORE_COUNT != 0))
+
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+/*******************************************************************************
+ * Memory layout constants
+ ******************************************************************************/
+
+/*
+ * ARM-TF lives in SRAM, partition it here
+ *
+ * BL3-1 specific defines.
+ *
+ * Put BL3-1 at the base of the Trusted SRAM.
+ */
+#define BL31_BASE SEC_SRAM_BASE
+#define BL31_SIZE SEC_SRAM_SIZE
+#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+
+/*
+ * Defines the maximum number of translation tables that are allocated by the
+ * translation table library code. To minimize the amount of runtime memory
+ * used, choose the smallest value needed to map the required virtual addresses
+ * for each BL stage.
+ */
+#if USE_COHERENT_MEM
+#define MAX_XLAT_TABLES 10
+#else
+#define MAX_XLAT_TABLES 9
+#endif
+
+/*
+ * Defines the maximum number of regions that are allocated by the translation
+ * table library code. A region consists of physical base address, virtual base
+ * address, size and attributes (Device/Memory, RO/RW, Secure/Non-Secure), as
+ * defined in the `mmap_region_t` structure. The platform defines the regions
+ * that should be mapped. Then, the translation table library will create the
+ * corresponding tables and descriptors at runtime. To minimize the amount of
+ * runtime memory used, choose the smallest value needed to register the
+ * required regions for each BL stage.
+ */
+#define MAX_MMAP_REGIONS 11
+
+/*
+ * Defines the total size of the address space in bytes. For example, for a 32
+ * bit address space, this value should be `(1ull << 32)`.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/* Platform default console definitions */
+#ifndef K3_USART_BASE
+#define K3_USART_BASE (0x02800000 + 0x10000 * K3_USART)
+#endif
+
+/* USART has a default size for address space */
+#define K3_USART_SIZE 0x1000
+
+#ifndef K3_USART_CLK_SPEED
+#define K3_USART_CLK_SPEED 48000000
+#endif
+
+/* Crash console defaults */
+#define CRASH_CONSOLE_BASE K3_USART_BASE
+#define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED
+#define CRASH_CONSOLE_BAUD_RATE K3_USART_BAUD
+
+/* Timer frequency */
+#ifndef SYS_COUNTER_FREQ_IN_TICKS
+#define SYS_COUNTER_FREQ_IN_TICKS 200000000
+#endif
+
+/* Interrupt numbers */
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+
+
+#define K3_GTC_BASE 0x00A90000
+/* We just need 20 byte offset, but simpler to just remap the 64K page in */
+#define K3_GTC_SIZE 0x10000
+#define K3_GTC_CNTCR_OFFSET 0x00
+#define K3_GTC_CNTCR_EN_MASK 0x01
+#define K3_GTC_CNTCR_HDBG_MASK 0x02
+#define K3_GTC_CNTFID0_OFFSET 0x20
+
+#define K3_GIC_BASE 0x01800000
+#define K3_GIC_SIZE 0x200000
+
+#if !K3_SEC_PROXY_LITE
+#define SEC_PROXY_DATA_BASE 0x32C00000
+#define SEC_PROXY_DATA_SIZE 0x80000
+#define SEC_PROXY_SCFG_BASE 0x32800000
+#define SEC_PROXY_SCFG_SIZE 0x80000
+#define SEC_PROXY_RT_BASE 0x32400000
+#define SEC_PROXY_RT_SIZE 0x80000
+#else
+#define SEC_PROXY_DATA_BASE 0x4D000000
+#define SEC_PROXY_DATA_SIZE 0x80000
+#define SEC_PROXY_SCFG_BASE 0x4A400000
+#define SEC_PROXY_SCFG_SIZE 0x80000
+#define SEC_PROXY_RT_BASE 0x4A600000
+#define SEC_PROXY_RT_SIZE 0x80000
+#endif /* K3_SEC_PROXY_LITE */
+
+#define SEC_PROXY_TIMEOUT_US 1000000
+#define SEC_PROXY_MAX_MESSAGE_SIZE 56
+
+#define TI_SCI_HOST_ID 10
+#define TI_SCI_MAX_MESSAGE_SIZE 52
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/ti/k3/platform.mk b/plat/ti/k3/platform.mk
new file mode 100644
index 0000000..2de21aa
--- /dev/null
+++ b/plat/ti/k3/platform.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_PATH := plat/ti/k3
+TARGET_BOARD ?= generic
+
+include ${PLAT_PATH}/common/plat_common.mk
+include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk
+
+# modify BUILD_PLAT to point to board specific build directory
+BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
diff --git a/plat/xilinx/common/include/ipi.h b/plat/xilinx/common/include/ipi.h
new file mode 100644
index 0000000..1d62f3e
--- /dev/null
+++ b/plat/xilinx/common/include/ipi.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Xilinx IPI management configuration data and macros */
+
+#ifndef IPI_H
+#define IPI_H
+
+#include <stdint.h>
+
+/*********************************************************************
+ * IPI mailbox status macros
+ ********************************************************************/
+#define IPI_MB_STATUS_IDLE (0U)
+#define IPI_MB_STATUS_SEND_PENDING (1U)
+#define IPI_MB_STATUS_RECV_PENDING (2U)
+
+/*********************************************************************
+ * IPI mailbox call is secure or not macros
+ ********************************************************************/
+#define IPI_MB_CALL_NOTSECURE (0U)
+#define IPI_MB_CALL_SECURE (1U)
+
+/*********************************************************************
+ * IPI secure check
+ ********************************************************************/
+#define IPI_SECURE_MASK (0x1U)
+#define IPI_IS_SECURE(I) ((ipi_table[(I)].secure_only & \
+ IPI_SECURE_MASK) ? 1 : 0)
+
+/*********************************************************************
+ * Struct definitions
+ ********************************************************************/
+
+/* structure to maintain IPI configuration information */
+struct ipi_config {
+ unsigned int ipi_bit_mask;
+ unsigned int ipi_reg_base;
+ unsigned char secure_only;
+};
+
+/*********************************************************************
+ * IPI APIs declarations
+ ********************************************************************/
+
+/* Initialize IPI configuration table */
+void ipi_config_table_init(const struct ipi_config *ipi_config_table,
+ uint32_t total_ipi);
+
+/* Validate IPI mailbox access */
+int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure);
+
+/* Open the IPI mailbox */
+void ipi_mb_open(uint32_t local, uint32_t remote);
+
+/* Release the IPI mailbox */
+void ipi_mb_release(uint32_t local, uint32_t remote);
+
+/* Enquire IPI mailbox status */
+int ipi_mb_enquire_status(uint32_t local, uint32_t remote);
+
+/* Trigger notification on the IPI mailbox */
+void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking);
+
+/* Ack IPI mailbox notification */
+void ipi_mb_ack(uint32_t local, uint32_t remote);
+
+/* Disable IPI mailbox notification interrupt */
+void ipi_mb_disable_irq(uint32_t local, uint32_t remote);
+
+/* Enable IPI mailbox notification interrupt */
+void ipi_mb_enable_irq(uint32_t local, uint32_t remote);
+
+#endif /* IPI_H */
diff --git a/plat/xilinx/common/include/plat_startup.h b/plat/xilinx/common/include/plat_startup.h
new file mode 100644
index 0000000..1733930
--- /dev/null
+++ b/plat/xilinx/common/include/plat_startup.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_STARTUP_H
+#define PLAT_STARTUP_H
+
+#include <common/bl_common.h>
+
+/* For FSBL handover */
+enum fsbl_handoff {
+ FSBL_HANDOFF_SUCCESS = 0,
+ FSBL_HANDOFF_NO_STRUCT,
+ FSBL_HANDOFF_INVAL_STRUCT,
+ FSBL_HANDOFF_TOO_MANY_PARTS
+};
+
+#define FSBL_MAX_PARTITIONS 8U
+
+/* Structure corresponding to each partition entry */
+struct xfsbl_partition {
+ uint64_t entry_point;
+ uint64_t flags;
+};
+
+/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */
+struct xfsbl_atf_handoff_params {
+ uint8_t magic[4];
+ uint32_t num_entries;
+ struct xfsbl_partition partition[FSBL_MAX_PARTITIONS];
+};
+
+#define ATF_HANDOFF_PARAMS_MAX_SIZE sizeof(struct xfsbl_atf_handoff_params)
+
+enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32,
+ entry_point_info_t *bl33,
+ uint64_t atf_handoff_addr);
+
+#endif /* PLAT_STARTUP_H */
diff --git a/plat/xilinx/common/include/pm_client.h b/plat/xilinx/common/include/pm_client.h
new file mode 100644
index 0000000..eae1d98
--- /dev/null
+++ b/plat/xilinx/common/include/pm_client.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Contains APU specific macros and macros to be defined depending on
+ * the execution environment.
+ */
+
+#ifndef PM_CLIENT_H
+#define PM_CLIENT_H
+
+#include "pm_common.h"
+#include "pm_defs.h"
+
+/* Functions to be implemented by each PU */
+void pm_client_suspend(const struct pm_proc *proc, uint32_t state);
+void pm_client_abort_suspend(void);
+void pm_client_wakeup(const struct pm_proc *proc);
+
+/* Global variables to be set in pm_client.c */
+extern const struct pm_proc *primary_proc;
+
+#if defined(PLAT_zynqmp)
+enum pm_ret_status pm_set_suspend_mode(uint32_t mode);
+const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid);
+#endif /* PLAT_zynqmp */
+
+#endif /* PM_CLIENT_H */
diff --git a/plat/xilinx/common/include/pm_common.h b/plat/xilinx/common/include/pm_common.h
new file mode 100644
index 0000000..89626e5
--- /dev/null
+++ b/plat/xilinx/common/include/pm_common.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Contains definitions of commonly used macros and data types needed
+ * for PU Power Management. This file should be common for all PU's.
+ */
+
+#ifndef PM_COMMON_H
+#define PM_COMMON_H
+
+#include <stdint.h>
+#include <plat_pm_common.h>
+
+#if IPI_CRC_CHECK
+#define PAYLOAD_ARG_CNT 8U
+#define IPI_W0_TO_W6_SIZE 28U
+#define PAYLOAD_CRC_POS 7U
+#define CRC_INIT_VALUE 0x4F4EU
+#define CRC_ORDER 16U
+#define CRC_POLYNOM 0x8005U
+#else
+#define PAYLOAD_ARG_CNT 6U
+#endif
+#define PAYLOAD_ARG_SIZE 4U /* size in bytes */
+
+#define TZ_VERSION_MAJOR 1
+#define TZ_VERSION_MINOR 0
+#define TZ_VERSION ((TZ_VERSION_MAJOR << 16) | \
+ TZ_VERSION_MINOR)
+
+/**
+ * pm_ipi - struct for capturing IPI-channel specific info
+ * @local_ipi_id Local IPI agent ID
+ * @remote_ipi_id Remote IPI Agent ID
+ * @buffer_base base address for payload buffer
+ */
+struct pm_ipi {
+ const uint32_t local_ipi_id;
+ const uint32_t remote_ipi_id;
+ const uintptr_t buffer_base;
+};
+
+/**
+ * pm_proc - struct for capturing processor related info
+ * @node_id node-ID of the processor
+ * @pwrdn_mask cpu-specific mask to be used for power control register
+ * @ipi pointer to IPI channel structure
+ * (in APU all processors share one IPI channel)
+ */
+struct pm_proc {
+ const uint32_t node_id;
+ const uint32_t pwrdn_mask;
+ const struct pm_ipi *ipi;
+};
+
+const struct pm_proc *pm_get_proc(uint32_t cpuid);
+
+#endif /* PM_COMMON_H */
diff --git a/plat/xilinx/common/include/pm_ipi.h b/plat/xilinx/common/include/pm_ipi.h
new file mode 100644
index 0000000..52dfc47
--- /dev/null
+++ b/plat/xilinx/common/include/pm_ipi.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_IPI_H
+#define PM_IPI_H
+
+#include <plat_ipi.h>
+#include <stddef.h>
+#include "pm_common.h"
+
+#define IPI_BLOCKING 1
+#define IPI_NON_BLOCKING 0
+
+void pm_ipi_init(const struct pm_proc *proc);
+
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT]);
+enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT]);
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT],
+ uint32_t *value, size_t count);
+void pm_ipi_buff_read_callb(uint32_t *value, size_t count);
+void pm_ipi_irq_enable(const struct pm_proc *proc);
+void pm_ipi_irq_clear(const struct pm_proc *proc);
+uint32_t pm_ipi_irq_status(const struct pm_proc *proc);
+#if IPI_CRC_CHECK
+uint32_t calculate_crc(uint32_t payload[PAYLOAD_ARG_CNT], uint32_t buffersize);
+#endif
+
+#endif /* PM_IPI_H */
diff --git a/plat/xilinx/common/ipi.c b/plat/xilinx/common/ipi.c
new file mode 100644
index 0000000..6438896
--- /dev/null
+++ b/plat/xilinx/common/ipi.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Xilinx IPI agent registers access management
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include <ipi.h>
+#include <plat_private.h>
+
+/*********************************************************************
+ * Macros definitions
+ ********************************************************************/
+
+/* IPI registers offsets macros */
+#define IPI_TRIG_OFFSET 0x00U
+#define IPI_OBR_OFFSET 0x04U
+#define IPI_ISR_OFFSET 0x10U
+#define IPI_IMR_OFFSET 0x14U
+#define IPI_IER_OFFSET 0x18U
+#define IPI_IDR_OFFSET 0x1CU
+
+/* IPI register start offset */
+#define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base)
+
+/* IPI register bit mask */
+#define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask)
+
+/* IPI configuration table */
+const static struct ipi_config *ipi_table;
+
+/* Total number of IPI */
+static uint32_t ipi_total;
+
+/**
+ * ipi_config_init() - Initialize IPI configuration data
+ *
+ * @ipi_config_table - IPI configuration table
+ * @ipi_total - Total number of IPI available
+ *
+ */
+void ipi_config_table_init(const struct ipi_config *ipi_config_table,
+ uint32_t total_ipi)
+{
+ ipi_table = ipi_config_table;
+ ipi_total = total_ipi;
+}
+
+/* is_ipi_mb_within_range() - verify if IPI mailbox is within range
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ *
+ * return - 1 if within range, 0 if not
+ */
+static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote)
+{
+ int ret = 1;
+
+ if (remote >= ipi_total || local >= ipi_total) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/**
+ * ipi_mb_validate() - validate IPI mailbox access
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ * @is_secure - indicate if the requester is from secure software
+ *
+ * return - 0 success, negative value for errors
+ */
+int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure)
+{
+ int ret = 0;
+
+ if (!is_ipi_mb_within_range(local, remote)) {
+ ret = -EINVAL;
+ } else if (IPI_IS_SECURE(local) && !is_secure) {
+ ret = -EPERM;
+ } else if (IPI_IS_SECURE(remote) && !is_secure) {
+ ret = -EPERM;
+ } else {
+ /* To fix the misra 15.7 warning */
+ }
+
+ return ret;
+}
+
+/**
+ * ipi_mb_open() - Open IPI mailbox.
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ *
+ */
+void ipi_mb_open(uint32_t local, uint32_t remote)
+{
+ mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
+ IPI_BIT_MASK(remote));
+ mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
+ IPI_BIT_MASK(remote));
+}
+
+/**
+ * ipi_mb_release() - Open IPI mailbox.
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ *
+ */
+void ipi_mb_release(uint32_t local, uint32_t remote)
+{
+ mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
+ IPI_BIT_MASK(remote));
+}
+
+/**
+ * ipi_mb_enquire_status() - Enquire IPI mailbox status
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ *
+ * return - 0 idle, positive value for pending sending or receiving,
+ * negative value for errors
+ */
+int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
+{
+ int ret = 0U;
+ uint32_t status;
+
+ status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
+ if (status & IPI_BIT_MASK(remote)) {
+ ret |= IPI_MB_STATUS_SEND_PENDING;
+ }
+ status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
+ if (status & IPI_BIT_MASK(remote)) {
+ ret |= IPI_MB_STATUS_RECV_PENDING;
+ }
+
+ return ret;
+}
+
+/* ipi_mb_notify() - Trigger IPI mailbox notification
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ * @is_blocking - if to trigger the notification in blocking mode or not.
+ *
+ * It sets the remote bit in the IPI agent trigger register.
+ *
+ */
+void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
+{
+ uint32_t status;
+
+ mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
+ IPI_BIT_MASK(remote));
+ if (is_blocking) {
+ do {
+ status = mmio_read_32(IPI_REG_BASE(local) +
+ IPI_OBR_OFFSET);
+ } while (status & IPI_BIT_MASK(remote));
+ }
+}
+
+/* ipi_mb_ack() - Ack IPI mailbox notification from the other end
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ *
+ * It will clear the remote bit in the isr register.
+ *
+ */
+void ipi_mb_ack(uint32_t local, uint32_t remote)
+{
+ mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET,
+ IPI_BIT_MASK(remote));
+}
+
+/* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ *
+ * It will mask the remote bit in the idr register.
+ *
+ */
+void ipi_mb_disable_irq(uint32_t local, uint32_t remote)
+{
+ mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET,
+ IPI_BIT_MASK(remote));
+}
+
+/* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt
+ *
+ * @local - local IPI ID
+ * @remote - remote IPI ID
+ *
+ * It will mask the remote bit in the idr register.
+ *
+ */
+void ipi_mb_enable_irq(uint32_t local, uint32_t remote)
+{
+ mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET,
+ IPI_BIT_MASK(remote));
+}
diff --git a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
new file mode 100644
index 0000000..cb6aaa5
--- /dev/null
+++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Top-level SMC handler for ZynqMP IPI Mailbox doorbell functions.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include <ipi.h>
+#include <plat_ipi.h>
+#include <plat_private.h>
+
+#include "ipi_mailbox_svc.h"
+#include "../../../services/spd/trusty/smcall.h"
+
+/*********************************************************************
+ * Macros definitions
+ ********************************************************************/
+
+/* IPI SMC calls macros: */
+#define IPI_SMC_OPEN_IRQ_MASK 0x00000001U /* IRQ enable bit in IPI
+ * open SMC call
+ */
+#define IPI_SMC_NOTIFY_BLOCK_MASK 0x00000001U /* Flag to indicate if
+ * IPI notification needs
+ * to be blocking.
+ */
+#define IPI_SMC_ENQUIRY_DIRQ_MASK 0x00000001U /* Flag to indicate if
+ * notification interrupt
+ * to be disabled.
+ */
+#define IPI_SMC_ACK_EIRQ_MASK 0x00000001U /* Flag to indicate if
+ * notification interrupt
+ * to be enable.
+ */
+
+#define UNSIGNED32_MASK 0xFFFFFFFFU /* 32bit mask */
+
+/**
+ * ipi_smc_handler() - SMC handler for IPI SMC calls
+ *
+ * @smc_fid - Function identifier
+ * @x1 - x4 - Arguments
+ * @cookie - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return - Unused
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t ipi_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
+ uint64_t x3, uint64_t x4, const void *cookie,
+ void *handle, uint64_t flags)
+{
+ int32_t ret;
+ uint32_t ipi_local_id;
+ uint32_t ipi_remote_id;
+ uint32_t is_secure;
+
+ ipi_local_id = x1 & UNSIGNED32_MASK;
+ ipi_remote_id = x2 & UNSIGNED32_MASK;
+
+ if (SMC_ENTITY(smc_fid) >= SMC_ENTITY_TRUSTED_APP)
+ is_secure = 1;
+ else
+ is_secure = 0;
+
+ /* Validate IPI mailbox access */
+ ret = ipi_mb_validate(ipi_local_id, ipi_remote_id, is_secure);
+ if (ret)
+ SMC_RET1(handle, ret);
+
+ switch (SMC_FUNCTION(smc_fid)) {
+ case IPI_MAILBOX_OPEN:
+ ipi_mb_open(ipi_local_id, ipi_remote_id);
+ SMC_RET1(handle, 0);
+ case IPI_MAILBOX_RELEASE:
+ ipi_mb_release(ipi_local_id, ipi_remote_id);
+ SMC_RET1(handle, 0);
+ case IPI_MAILBOX_STATUS_ENQUIRY:
+ {
+ int32_t disable_irq;
+
+ disable_irq = (x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) ? 1 : 0;
+ ret = ipi_mb_enquire_status(ipi_local_id, ipi_remote_id);
+ if ((ret & IPI_MB_STATUS_RECV_PENDING) && disable_irq)
+ ipi_mb_disable_irq(ipi_local_id, ipi_remote_id);
+ SMC_RET1(handle, ret);
+ }
+ case IPI_MAILBOX_NOTIFY:
+ {
+ uint32_t is_blocking;
+
+ is_blocking = (x3 & IPI_SMC_NOTIFY_BLOCK_MASK) ? 1 : 0;
+ ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking);
+ SMC_RET1(handle, 0);
+ }
+ case IPI_MAILBOX_ACK:
+ {
+ int32_t enable_irq;
+
+ enable_irq = (x3 & IPI_SMC_ACK_EIRQ_MASK) ? 1 : 0;
+ ipi_mb_ack(ipi_local_id, ipi_remote_id);
+ if (enable_irq)
+ ipi_mb_enable_irq(ipi_local_id, ipi_remote_id);
+ SMC_RET1(handle, 0);
+ }
+ case IPI_MAILBOX_ENABLE_IRQ:
+ ipi_mb_enable_irq(ipi_local_id, ipi_remote_id);
+ SMC_RET1(handle, 0);
+ case IPI_MAILBOX_DISABLE_IRQ:
+ ipi_mb_disable_irq(ipi_local_id, ipi_remote_id);
+ SMC_RET1(handle, 0);
+ default:
+ WARN("Unimplemented IPI service call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h
new file mode 100644
index 0000000..af13db9
--- /dev/null
+++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* ZynqMP IPI mailbox doorbell service enums and defines */
+
+#ifndef IPI_MAILBOX_SVC_H
+#define IPI_MAILBOX_SVC_H
+
+#include <stdint.h>
+
+/*********************************************************************
+ * Enum definitions
+ ********************************************************************/
+
+/* IPI SMC function numbers enum definition */
+enum ipi_api_id {
+ /* IPI mailbox operations functions: */
+ IPI_MAILBOX_OPEN = 0x1000,
+ IPI_MAILBOX_RELEASE,
+ IPI_MAILBOX_STATUS_ENQUIRY,
+ IPI_MAILBOX_NOTIFY,
+ IPI_MAILBOX_ACK,
+ IPI_MAILBOX_ENABLE_IRQ,
+ IPI_MAILBOX_DISABLE_IRQ
+};
+
+/*********************************************************************
+ * IPI mailbox service APIs declarations
+ ********************************************************************/
+
+/* IPI SMC handler */
+uint64_t ipi_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
+ uint64_t x3, uint64_t x4, const void *cookie, void *handle,
+ uint64_t flags);
+
+#endif /* IPI_MAILBOX_SVC_H */
diff --git a/plat/xilinx/common/plat_startup.c b/plat/xilinx/common/plat_startup.c
new file mode 100644
index 0000000..de9cf4d
--- /dev/null
+++ b/plat/xilinx/common/plat_startup.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat_startup.h>
+
+
+/*
+ * ATFHandoffParams
+ * Parameter bitfield encoding
+ * -----------------------------------------------------------------------------
+ * Exec State 0 0 -> Aarch64, 1-> Aarch32
+ * endianness 1 0 -> LE, 1 -> BE
+ * secure (TZ) 2 0 -> Non secure, 1 -> secure
+ * EL 3:4 00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3
+ * CPU# 5:6 00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3
+ */
+
+#define FSBL_FLAGS_ESTATE_SHIFT 0U
+#define FSBL_FLAGS_ESTATE_MASK (1U << FSBL_FLAGS_ESTATE_SHIFT)
+#define FSBL_FLAGS_ESTATE_A64 0U
+#define FSBL_FLAGS_ESTATE_A32 1U
+
+#define FSBL_FLAGS_ENDIAN_SHIFT 1U
+#define FSBL_FLAGS_ENDIAN_MASK (1U << FSBL_FLAGS_ENDIAN_SHIFT)
+#define FSBL_FLAGS_ENDIAN_LE 0U
+#define FSBL_FLAGS_ENDIAN_BE 1U
+
+#define FSBL_FLAGS_TZ_SHIFT 2U
+#define FSBL_FLAGS_TZ_MASK (1U << FSBL_FLAGS_TZ_SHIFT)
+#define FSBL_FLAGS_NON_SECURE 0U
+#define FSBL_FLAGS_SECURE 1U
+
+#define FSBL_FLAGS_EL_SHIFT 3U
+#define FSBL_FLAGS_EL_MASK (3U << FSBL_FLAGS_EL_SHIFT)
+#define FSBL_FLAGS_EL0 0U
+#define FSBL_FLAGS_EL1 1U
+#define FSBL_FLAGS_EL2 2U
+#define FSBL_FLAGS_EL3 3U
+
+#define FSBL_FLAGS_CPU_SHIFT 5U
+#define FSBL_FLAGS_CPU_MASK (3U << FSBL_FLAGS_CPU_SHIFT)
+#define FSBL_FLAGS_A53_0 0U
+#define FSBL_FLAGS_A53_1 1U
+#define FSBL_FLAGS_A53_2 2U
+#define FSBL_FLAGS_A53_3 3U
+
+/**
+ * @partition: Pointer to partition struct
+ *
+ * Get the target CPU for @partition.
+ *
+ * Return: FSBL_FLAGS_A53_0, FSBL_FLAGS_A53_1, FSBL_FLAGS_A53_2 or FSBL_FLAGS_A53_3
+ */
+static int32_t get_fsbl_cpu(const struct xfsbl_partition *partition)
+{
+ uint64_t flags = partition->flags & FSBL_FLAGS_CPU_MASK;
+
+ return flags >> FSBL_FLAGS_CPU_SHIFT;
+}
+
+/**
+ * @partition: Pointer to partition struct
+ *
+ * Get the target exception level for @partition.
+ *
+ * Return: FSBL_FLAGS_EL0, FSBL_FLAGS_EL1, FSBL_FLAGS_EL2 or FSBL_FLAGS_EL3
+ */
+static int32_t get_fsbl_el(const struct xfsbl_partition *partition)
+{
+ uint64_t flags = partition->flags & FSBL_FLAGS_EL_MASK;
+
+ return flags >> FSBL_FLAGS_EL_SHIFT;
+}
+
+/**
+ * @partition: Pointer to partition struct
+ *
+ * Get the target security state for @partition.
+ *
+ * Return: FSBL_FLAGS_NON_SECURE or FSBL_FLAGS_SECURE
+ */
+static int32_t get_fsbl_ss(const struct xfsbl_partition *partition)
+{
+ uint64_t flags = partition->flags & FSBL_FLAGS_TZ_MASK;
+
+ return flags >> FSBL_FLAGS_TZ_SHIFT;
+}
+
+/**
+ * @partition: Pointer to partition struct
+ *
+ * Get the target endianness for @partition.
+ *
+ * Return: SPSR_E_LITTLE or SPSR_E_BIG
+ */
+static int32_t get_fsbl_endian(const struct xfsbl_partition *partition)
+{
+ uint64_t flags = partition->flags & FSBL_FLAGS_ENDIAN_MASK;
+
+ flags >>= FSBL_FLAGS_ENDIAN_SHIFT;
+
+ if (flags == FSBL_FLAGS_ENDIAN_BE) {
+ return SPSR_E_BIG;
+ } else {
+ return SPSR_E_LITTLE;
+ }
+}
+
+/**
+ * @partition: Pointer to partition struct
+ *
+ * Get the target execution state for @partition.
+ *
+ * Return: FSBL_FLAGS_ESTATE_A32 or FSBL_FLAGS_ESTATE_A64
+ */
+static int32_t get_fsbl_estate(const struct xfsbl_partition *partition)
+{
+ uint64_t flags = partition->flags & FSBL_FLAGS_ESTATE_MASK;
+
+ return flags >> FSBL_FLAGS_ESTATE_SHIFT;
+}
+
+/**
+ * Populates the bl32 and bl33 image info structures
+ * @bl32: BL32 image info structure
+ * @bl33: BL33 image info structure
+ * atf_handoff_addr: ATF handoff address
+ *
+ * Process the handoff paramters from the FSBL and populate the BL32 and BL33
+ * image info structures accordingly.
+ *
+ * Return: Return the status of the handoff. The value will be from the
+ * fsbl_handoff enum.
+ */
+enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32,
+ entry_point_info_t *bl33,
+ uint64_t atf_handoff_addr)
+{
+ const struct xfsbl_atf_handoff_params *ATFHandoffParams;
+ if (!atf_handoff_addr) {
+ WARN("BL31: No ATF handoff structure passed\n");
+ return FSBL_HANDOFF_NO_STRUCT;
+ }
+
+ ATFHandoffParams = (struct xfsbl_atf_handoff_params *)atf_handoff_addr;
+ if ((ATFHandoffParams->magic[0] != 'X') ||
+ (ATFHandoffParams->magic[1] != 'L') ||
+ (ATFHandoffParams->magic[2] != 'N') ||
+ (ATFHandoffParams->magic[3] != 'X')) {
+ ERROR("BL31: invalid ATF handoff structure at %" PRIx64 "\n",
+ atf_handoff_addr);
+ return FSBL_HANDOFF_INVAL_STRUCT;
+ }
+
+ VERBOSE("BL31: ATF handoff params at:0x%" PRIx64 ", entries:%u\n",
+ atf_handoff_addr, ATFHandoffParams->num_entries);
+ if (ATFHandoffParams->num_entries > FSBL_MAX_PARTITIONS) {
+ ERROR("BL31: ATF handoff params: too many partitions (%u/%u)\n",
+ ATFHandoffParams->num_entries, FSBL_MAX_PARTITIONS);
+ return FSBL_HANDOFF_TOO_MANY_PARTS;
+ }
+
+ /*
+ * we loop over all passed entries but only populate two image structs
+ * (bl32, bl33). I.e. the last applicable images in the handoff
+ * structure will be used for the hand off
+ */
+ for (size_t i = 0; i < ATFHandoffParams->num_entries; i++) {
+ entry_point_info_t *image;
+ int32_t target_estate, target_secure, target_cpu;
+ uint32_t target_endianness, target_el;
+
+ VERBOSE("BL31: %zd: entry:0x%" PRIx64 ", flags:0x%" PRIx64 "\n", i,
+ ATFHandoffParams->partition[i].entry_point,
+ ATFHandoffParams->partition[i].flags);
+
+ target_cpu = get_fsbl_cpu(&ATFHandoffParams->partition[i]);
+ if (target_cpu != FSBL_FLAGS_A53_0) {
+ WARN("BL31: invalid target CPU (%i)\n", target_cpu);
+ continue;
+ }
+
+ target_el = get_fsbl_el(&ATFHandoffParams->partition[i]);
+ if ((target_el == FSBL_FLAGS_EL3) ||
+ (target_el == FSBL_FLAGS_EL0)) {
+ WARN("BL31: invalid exception level (%i)\n", target_el);
+ continue;
+ }
+
+ target_secure = get_fsbl_ss(&ATFHandoffParams->partition[i]);
+ if (target_secure == FSBL_FLAGS_SECURE &&
+ target_el == FSBL_FLAGS_EL2) {
+ WARN("BL31: invalid security state (%i) for exception level (%i)\n",
+ target_secure, target_el);
+ continue;
+ }
+
+ target_estate = get_fsbl_estate(&ATFHandoffParams->partition[i]);
+ target_endianness = get_fsbl_endian(&ATFHandoffParams->partition[i]);
+
+ if (target_secure == FSBL_FLAGS_SECURE) {
+ image = bl32;
+
+ if (target_estate == FSBL_FLAGS_ESTATE_A32) {
+ bl32->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+ target_endianness,
+ DISABLE_ALL_EXCEPTIONS);
+ } else {
+ bl32->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ }
+ } else {
+ image = bl33;
+
+ if (target_estate == FSBL_FLAGS_ESTATE_A32) {
+ if (target_el == FSBL_FLAGS_EL2) {
+ target_el = MODE32_hyp;
+ } else {
+ target_el = MODE32_sys;
+ }
+
+ bl33->spsr = SPSR_MODE32(target_el, SPSR_T_ARM,
+ target_endianness,
+ DISABLE_ALL_EXCEPTIONS);
+ } else {
+ if (target_el == FSBL_FLAGS_EL2) {
+ target_el = MODE_EL2;
+ } else {
+ target_el = MODE_EL1;
+ }
+
+ bl33->spsr = SPSR_64(target_el, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+ }
+ }
+
+ VERBOSE("Setting up %s entry point to:%" PRIx64 ", el:%x\n",
+ target_secure == FSBL_FLAGS_SECURE ? "BL32" : "BL33",
+ ATFHandoffParams->partition[i].entry_point,
+ target_el);
+ image->pc = ATFHandoffParams->partition[i].entry_point;
+
+ if (target_endianness == SPSR_E_BIG) {
+ EP_SET_EE(image->h.attr, EP_EE_BIG);
+ } else {
+ EP_SET_EE(image->h.attr, EP_EE_LITTLE);
+ }
+ }
+
+ return FSBL_HANDOFF_SUCCESS;
+}
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
new file mode 100644
index 0000000..513d6be
--- /dev/null
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <arch_helpers.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <ipi.h>
+#include <plat_ipi.h>
+#include <plat_private.h>
+#include <plat/common/platform.h>
+
+#include "pm_defs.h"
+#include "pm_ipi.h"
+
+#define ERROR_CODE_MASK (0xFFFFU)
+#define PM_OFFSET (0U)
+
+DEFINE_BAKERY_LOCK(pm_secure_lock);
+
+/**
+ * pm_ipi_init() - Initialize IPI peripheral for communication with
+ * remote processor
+ *
+ * @proc Pointer to the processor who is initiating request
+ * @return On success, the initialization function must return 0.
+ * Any other return value will cause the framework to ignore
+ * the service
+ *
+ * Called from pm_setup initialization function
+ */
+void pm_ipi_init(const struct pm_proc *proc)
+{
+ bakery_lock_init(&pm_secure_lock);
+ ipi_mb_open(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id);
+}
+
+/**
+ * pm_ipi_send_common() - Sends IPI request to the remote processor
+ * @proc Pointer to the processor who is initiating request
+ * @payload API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller. Caller needs to hold
+ * the 'pm_secure_lock' lock.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT],
+ uint32_t is_blocking)
+{
+ uint32_t offset = PM_OFFSET;
+ uintptr_t buffer_base = proc->ipi->buffer_base +
+ IPI_BUFFER_TARGET_REMOTE_OFFSET +
+ IPI_BUFFER_REQ_OFFSET;
+#if IPI_CRC_CHECK
+ payload[PAYLOAD_CRC_POS] = calculate_crc(payload, IPI_W0_TO_W6_SIZE);
+#endif
+
+ /* Write payload into IPI buffer */
+ for (size_t i = 0; i < PAYLOAD_ARG_CNT; i++) {
+ mmio_write_32(buffer_base + offset, payload[i]);
+ offset += PAYLOAD_ARG_SIZE;
+ }
+
+ /* Generate IPI to remote processor */
+ ipi_mb_notify(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id,
+ is_blocking);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ipi_send_non_blocking() - Sends IPI request to the remote processor
+ * without blocking notification
+ * @proc Pointer to the processor who is initiating request
+ * @payload API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ipi_send_non_blocking(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT])
+{
+ enum pm_ret_status ret;
+
+ bakery_lock_get(&pm_secure_lock);
+
+ ret = pm_ipi_send_common(proc, payload, IPI_NON_BLOCKING);
+
+ bakery_lock_release(&pm_secure_lock);
+
+ return ret;
+}
+
+/**
+ * pm_ipi_send() - Sends IPI request to the remote processor
+ * @proc Pointer to the processor who is initiating request
+ * @payload API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT])
+{
+ enum pm_ret_status ret;
+
+ bakery_lock_get(&pm_secure_lock);
+
+ ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);
+
+ bakery_lock_release(&pm_secure_lock);
+
+ return ret;
+}
+
+
+/**
+ * pm_ipi_buff_read() - Reads IPI response after remote processor has handled
+ * interrupt
+ * @proc Pointer to the processor who is waiting and reading response
+ * @value Used to return value from IPI buffer element (optional)
+ * @count Number of values to return in @value
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
+ uint32_t *value, size_t count)
+{
+ size_t i;
+#if IPI_CRC_CHECK
+ size_t j;
+ uint32_t response_payload[PAYLOAD_ARG_CNT];
+#endif
+ uintptr_t buffer_base = proc->ipi->buffer_base +
+ IPI_BUFFER_TARGET_REMOTE_OFFSET +
+ IPI_BUFFER_RESP_OFFSET;
+
+ /*
+ * Read response from IPI buffer
+ * buf-0: success or error+reason
+ * buf-1: value
+ * buf-2: unused
+ * buf-3: unused
+ */
+ for (i = 1; i <= count; i++) {
+ *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
+ value++;
+ }
+#if IPI_CRC_CHECK
+ for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
+ response_payload[j] = mmio_read_32(buffer_base +
+ (j * PAYLOAD_ARG_SIZE));
+ }
+
+ if (response_payload[PAYLOAD_CRC_POS] !=
+ calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
+ NOTICE("ERROR in CRC response payload value:0x%x\n",
+ response_payload[PAYLOAD_CRC_POS]);
+ }
+#endif
+
+ return mmio_read_32(buffer_base);
+}
+
+/**
+ * pm_ipi_buff_read_callb() - Reads IPI response after remote processor has
+ * handled interrupt
+ * @value Used to return value from IPI buffer element (optional)
+ * @count Number of values to return in @value
+ *
+ * @return Returns status, either success or error+reason
+ */
+void pm_ipi_buff_read_callb(uint32_t *value, size_t count)
+{
+ size_t i;
+#if IPI_CRC_CHECK
+ size_t j;
+ unsigned int response_payload[PAYLOAD_ARG_CNT] = {0};
+#endif
+ uintptr_t buffer_base = IPI_BUFFER_REMOTE_BASE +
+ IPI_BUFFER_TARGET_LOCAL_OFFSET +
+ IPI_BUFFER_REQ_OFFSET;
+
+ if (count > IPI_BUFFER_MAX_WORDS) {
+ count = IPI_BUFFER_MAX_WORDS;
+ }
+
+ for (i = 0; i <= count; i++) {
+ *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
+ value++;
+ }
+#if IPI_CRC_CHECK
+ for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
+ response_payload[j] = mmio_read_32(buffer_base +
+ (j * PAYLOAD_ARG_SIZE));
+ }
+
+ if (response_payload[PAYLOAD_CRC_POS] !=
+ calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
+ NOTICE("ERROR in CRC response payload value:0x%x\n",
+ response_payload[PAYLOAD_CRC_POS]);
+ }
+#endif
+}
+
+/**
+ * pm_ipi_send_sync() - Sends IPI request to the remote processor
+ * @proc Pointer to the processor who is initiating request
+ * @payload API id and call arguments to be written in IPI buffer
+ * @value Used to return value from IPI buffer element (optional)
+ * @count Number of values to return in @value
+ *
+ * Send an IPI request to the power controller and wait for it to be handled.
+ *
+ * @return Returns status, either success or error+reason and, optionally,
+ * @value
+ */
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+ uint32_t payload[PAYLOAD_ARG_CNT],
+ uint32_t *value, size_t count)
+{
+ enum pm_ret_status ret;
+
+ bakery_lock_get(&pm_secure_lock);
+
+ ret = pm_ipi_send_common(proc, payload, IPI_BLOCKING);
+ if (ret != PM_RET_SUCCESS) {
+ goto unlock;
+ }
+
+ ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));
+
+unlock:
+ bakery_lock_release(&pm_secure_lock);
+
+ return ret;
+}
+
+void pm_ipi_irq_enable(const struct pm_proc *proc)
+{
+ ipi_mb_enable_irq(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id);
+}
+
+void pm_ipi_irq_clear(const struct pm_proc *proc)
+{
+ ipi_mb_ack(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id);
+}
+
+uint32_t pm_ipi_irq_status(const struct pm_proc *proc)
+{
+ int32_t ret;
+
+ ret = ipi_mb_enquire_status(proc->ipi->local_ipi_id,
+ proc->ipi->remote_ipi_id);
+ if (ret & IPI_MB_STATUS_RECV_PENDING) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+#if IPI_CRC_CHECK
+uint32_t calculate_crc(uint32_t payload[PAYLOAD_ARG_CNT], uint32_t bufsize)
+{
+ uint32_t crcinit = CRC_INIT_VALUE;
+ uint32_t order = CRC_ORDER;
+ uint32_t polynom = CRC_POLYNOM;
+ uint32_t i, j, c, bit, datain, crcmask, crchighbit;
+ uint32_t crc = crcinit;
+
+ crcmask = ((uint32_t)((1U << (order - 1U)) - 1U) << 1U) | 1U;
+ crchighbit = (uint32_t)(1U << (order - 1U));
+
+ for (i = 0U; i < bufsize; i++) {
+ datain = mmio_read_8((unsigned long)payload + i);
+ c = datain;
+ j = 0x80U;
+ while (j != 0U) {
+ bit = crc & crchighbit;
+ crc <<= 1U;
+ if (0U != (c & j))
+ bit ^= crchighbit;
+ if (bit != 0U)
+ crc ^= polynom;
+ j >>= 1U;
+ }
+ crc &= crcmask;
+ }
+ return crc;
+}
+#endif
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
new file mode 100644
index 0000000..f55cde9
--- /dev/null
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_ipi.h>
+#include <versal_def.h>
+#include <plat_private.h>
+#include <common/debug.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+
+/*
+ * Table of regions to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+const mmap_region_t plat_versal_mmap[] = {
+ MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(FPD_MAINCCI_BASE, FPD_MAINCCI_SIZE, MT_DEVICE | MT_RW |
+ MT_SECURE),
+ { 0 }
+};
+
+const mmap_region_t *plat_versal_get_mmap(void)
+{
+ return plat_versal_mmap;
+}
+
+static void versal_print_platform_name(void)
+{
+ NOTICE("ATF running on Xilinx %s\n", PLATFORM_NAME);
+}
+
+void versal_config_setup(void)
+{
+ /* Configure IPI data for versal */
+ versal_ipi_config_table_init();
+
+ versal_print_platform_name();
+
+ generic_delay_timer_init();
+}
+
+uint32_t plat_get_syscnt_freq2(void)
+{
+ return VERSAL_CPU_CLOCK;
+}
+
diff --git a/plat/xilinx/versal/aarch64/versal_helpers.S b/plat/xilinx/versal/aarch64/versal_helpers.S
new file mode 100644
index 0000000..26eb052
--- /dev/null
+++ b/plat/xilinx/versal/aarch64/versal_helpers.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/gicv3.h>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_is_my_cpu_primary
+ .globl versal_calc_core_pos
+ .globl platform_mem_init
+ .globl plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * TODO: Should we read the PSYS register to make sure
+ * that the request has gone through.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ mrs x0, mpidr_el1
+
+ /*
+ * There is no sane reason to come out of this wfi. This
+ * cpu will be powered on and reset by the cpu_on pm api
+ */
+ dsb sy
+ bl plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+ mov x9, x30
+ bl plat_my_core_pos
+ cmp x0, #VERSAL_PRIMARY_CPU
+ cset x0, eq
+ ret x9
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the versal_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b versal_calc_core_pos
+endfunc plat_my_core_pos
+
+func versal_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc versal_calc_core_pos
+
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on VERSAL
+ * platform. The Secure RAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
new file mode 100644
index 0000000..9b36208
--- /dev/null
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <plat_arm.h>
+#include <plat_private.h>
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/dcc.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
+#include <versal_def.h>
+#include <plat_private.h>
+#include <plat_startup.h>
+#include <pm_ipi.h>
+#include "pm_client.h"
+#include "pm_api_sys.h"
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ */
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ assert(sec_state_is_valid(type));
+
+ if (type == NON_SECURE) {
+ return &bl33_image_ep_info;
+ }
+
+ return &bl32_image_ep_info;
+}
+
+/*
+ * Set the build time defaults,if we can't find any config data.
+ */
+static inline void bl31_set_default_config(void)
+{
+ bl32_image_ep_info.pc = (uintptr_t)BL32_BASE;
+ bl32_image_ep_info.spsr = (uint32_t)arm_get_spsr_for_bl32_entry();
+ bl33_image_ep_info.pc = (uintptr_t)plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = (uint32_t)SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+}
+
+/*
+ * Perform any BL31 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ */
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ uint64_t atf_handoff_addr;
+ uint32_t payload[PAYLOAD_ARG_CNT], max_size = ATF_HANDOFF_PARAMS_MAX_SIZE;
+ enum pm_ret_status ret_status;
+ uint64_t addr[ATF_HANDOFF_PARAMS_MAX_SIZE];
+
+ if (VERSAL_CONSOLE_IS(pl011) || (VERSAL_CONSOLE_IS(pl011_1))) {
+ static console_t versal_runtime_console;
+ /* Initialize the console to provide early debug support */
+ int32_t rc = console_pl011_register((uintptr_t)VERSAL_UART_BASE,
+ (uint32_t)VERSAL_UART_CLOCK,
+ (uint32_t)VERSAL_UART_BAUDRATE,
+ &versal_runtime_console);
+ if (rc == 0) {
+ panic();
+ }
+
+ console_set_scope(&versal_runtime_console, (uint32_t)(CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME));
+ } else if (VERSAL_CONSOLE_IS(dcc)) {
+ /* Initialize the dcc console for debug */
+ int32_t rc = console_dcc_register();
+ if (rc == 0) {
+ panic();
+ }
+ } else {
+ NOTICE("BL31: Did not register for any console.\n");
+ }
+
+ /* Initialize the platform config for future decision making */
+ versal_config_setup();
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(arg0 == 0U);
+ assert(arg1 == 0U);
+
+ /*
+ * Do initial security configuration to allow DRAM/device access. On
+ * Base VERSAL only DRAM security is programmable (via TrustZone), but
+ * other platforms might have more programmable security devices
+ * present.
+ */
+
+ /* Populate common information for BL32 and BL33 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, 1, PM_LOAD_GET_HANDOFF_PARAMS,
+ (uintptr_t)addr >> 32U, (uintptr_t)addr, max_size);
+ ret_status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ if (ret_status == PM_RET_SUCCESS) {
+ INFO("BL31: GET_HANDOFF_PARAMS call success=%d\n", ret_status);
+ atf_handoff_addr = (uintptr_t)&addr;
+ } else {
+ ERROR("BL31: GET_HANDOFF_PARAMS Failed, read atf_handoff_addr from reg\n");
+ atf_handoff_addr = mmio_read_32(PMC_GLOBAL_GLOB_GEN_STORAGE4);
+ }
+
+ enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info,
+ &bl33_image_ep_info,
+ atf_handoff_addr);
+ if (ret == FSBL_HANDOFF_NO_STRUCT || ret == FSBL_HANDOFF_INVAL_STRUCT) {
+ bl31_set_default_config();
+ } else if (ret == FSBL_HANDOFF_TOO_MANY_PARTS) {
+ ERROR("BL31: Error too many partitions %u\n", ret);
+ } else if (ret != FSBL_HANDOFF_SUCCESS) {
+ panic();
+ } else {
+ INFO("BL31: fsbl-atf handover success %u\n", ret);
+ }
+
+ NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
+ NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
+}
+
+static versal_intr_info_type_el3_t type_el3_interrupt_table[MAX_INTR_EL3];
+
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
+{
+ static uint32_t index;
+ uint32_t i;
+
+ /* Validate 'handler' and 'id' parameters */
+ if (handler == NULL || index >= MAX_INTR_EL3) {
+ return -EINVAL;
+ }
+
+ /* Check if a handler has already been registered */
+ for (i = 0; i < index; i++) {
+ if (id == type_el3_interrupt_table[i].id) {
+ return -EALREADY;
+ }
+ }
+
+ type_el3_interrupt_table[index].id = id;
+ type_el3_interrupt_table[index].handler = handler;
+
+ index++;
+
+ return 0;
+}
+
+static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint32_t intr_id;
+ uint32_t i;
+ interrupt_type_handler_t handler = NULL;
+
+ intr_id = plat_ic_get_pending_interrupt_id();
+
+ for (i = 0; i < MAX_INTR_EL3; i++) {
+ if (intr_id == type_el3_interrupt_table[i].id) {
+ handler = type_el3_interrupt_table[i].handler;
+ }
+ }
+
+ if (handler != NULL) {
+ return handler(intr_id, flags, handle, cookie);
+ }
+
+ return 0;
+}
+void bl31_platform_setup(void)
+{
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_versal_gic_driver_init();
+ plat_versal_gic_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ uint64_t flags = 0;
+ int32_t rc;
+
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_EL3,
+ rdo_el3_interrupt_handler, flags);
+ if (rc != 0) {
+ panic();
+ }
+}
+
+/*
+ * Perform the very early platform specific architectural setup here.
+ */
+void bl31_plat_arch_setup(void)
+{
+ plat_arm_interconnect_init();
+ plat_arm_interconnect_enter_coherency();
+
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_versal_get_mmap());
+ enable_mmu_el3(0);
+}
diff --git a/plat/xilinx/versal/include/plat_ipi.h b/plat/xilinx/versal/include/plat_ipi.h
new file mode 100644
index 0000000..36a4380
--- /dev/null
+++ b/plat/xilinx/versal/include/plat_ipi.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Versal IPI management enums and defines */
+
+#ifndef PLAT_IPI_H
+#define PLAT_IPI_H
+
+#include <ipi.h>
+#include <stdint.h>
+
+/*********************************************************************
+ * IPI agent IDs macros
+ ********************************************************************/
+#define IPI_ID_PMC 1U
+#define IPI_ID_APU 2U
+#define IPI_ID_RPU0 3U
+#define IPI_ID_RPU1 4U
+#define IPI_ID_3 5U
+#define IPI_ID_4 6U
+#define IPI_ID_5 7U
+
+/*********************************************************************
+ * IPI message buffers
+ ********************************************************************/
+#define IPI_BUFFER_BASEADDR 0xFF3F0000U
+
+#define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U)
+#define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200U)
+
+#define IPI_BUFFER_TARGET_APU_OFFSET 0x80U
+#define IPI_BUFFER_TARGET_PMC_OFFSET 0x40U
+
+#define IPI_BUFFER_LOCAL_BASE IPI_BUFFER_APU_BASE
+#define IPI_BUFFER_REMOTE_BASE IPI_BUFFER_PMC_BASE
+
+#define IPI_BUFFER_TARGET_LOCAL_OFFSET IPI_BUFFER_TARGET_APU_OFFSET
+#define IPI_BUFFER_TARGET_REMOTE_OFFSET IPI_BUFFER_TARGET_PMC_OFFSET
+
+#define IPI_BUFFER_MAX_WORDS 8
+
+#define IPI_BUFFER_REQ_OFFSET 0x0U
+#define IPI_BUFFER_RESP_OFFSET 0x20U
+
+/*********************************************************************
+ * Platform specific IPI API declarations
+ ********************************************************************/
+
+/* Configure IPI table for versal */
+void versal_ipi_config_table_init(void);
+
+#endif /* PLAT_IPI_H */
diff --git a/plat/xilinx/versal/include/plat_macros.S b/plat/xilinx/versal/include/plat_macros.S
new file mode 100644
index 0000000..3a52212
--- /dev/null
+++ b/plat/xilinx/versal/include/plat_macros.S
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+
+#include "../include/platform_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+ .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+ /* ---------------------------------------------
+ * The below utility macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31 on Versal platform.
+ * Expects: GICD base in x16, GICC base in x17
+ * Clobbers: x0 - x10, sp
+ * ---------------------------------------------
+ */
+ .macro versal_print_gic_regs
+ /* Check for GICv3 system register access */
+ mrs x7, id_aa64pfr0_el1
+ ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x7, #1
+ b.ne print_gicv2
+
+ /* Check for SRE enable */
+ mrs x8, ICC_SRE_EL3
+ tst x8, #ICC_SRE_SRE_BIT
+ b.eq print_gicv2
+
+ /* Load the icc reg list to x6 */
+ adr x6, icc_regs
+ /* Load the icc regs to gp regs used by str_in_crash_buf_print */
+ mrs x8, ICC_HPPIR0_EL1
+ mrs x9, ICC_HPPIR1_EL1
+ mrs x10, ICC_CTLR_EL3
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ b print_gic_common
+
+print_gicv2:
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+print_gic_common:
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+ .endm
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x17, PLAT_VERSAL_GICD_BASE
+ mov_imm x16, PLAT_VERSAL_GICR_BASE
+ versal_print_gic_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/xilinx/versal/include/plat_pm_common.h b/plat/xilinx/versal/include/plat_pm_common.h
new file mode 100644
index 0000000..4c057b8
--- /dev/null
+++ b/plat/xilinx/versal/include/plat_pm_common.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Contains platform specific definitions of commonly used macros data types
+ * for PU Power Management. This file should be common for all PU's.
+ */
+
+#ifndef PLAT_PM_COMMON_H
+#define PLAT_PM_COMMON_H
+
+#include <common/debug.h>
+#include <stdint.h>
+#include "pm_defs.h"
+
+#define NON_SECURE_FLAG 1U
+#define SECURE_FLAG 0U
+
+#endif /* PLAT_PM_COMMON_H */
diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h
new file mode 100644
index 0000000..818797d
--- /dev/null
+++ b/plat/xilinx/versal/include/plat_private.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+#include <lib/xlat_tables/xlat_tables.h>
+#include <bl31/interrupt_mgmt.h>
+
+typedef struct versal_intr_info_type_el3 {
+ uint32_t id;
+ interrupt_type_handler_t handler;
+} versal_intr_info_type_el3_t;
+
+void versal_config_setup(void);
+
+const mmap_region_t *plat_versal_get_mmap(void);
+
+void plat_versal_gic_driver_init(void);
+void plat_versal_gic_init(void);
+void plat_versal_gic_cpuif_enable(void);
+void plat_versal_gic_cpuif_disable(void);
+void plat_versal_gic_pcpu_init(void);
+void plat_versal_gic_save(void);
+void plat_versal_gic_resume(void);
+
+uint32_t versal_calc_core_pos(u_register_t mpidr);
+/*
+ * Register handler to specific GIC entrance
+ * for INTR_TYPE_EL3 type of interrupt
+ */
+int32_t request_intr_type_el3(uint32_t irq, interrupt_type_handler_t fiq_handler);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h
new file mode 100644
index 0000000..6d95fdc
--- /dev/null
+++ b/plat/xilinx/versal/include/platform_def.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include "versal_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE U(0x440)
+
+#define PLATFORM_CORE_COUNT U(2)
+#define PLAT_MAX_PWR_LVL U(1)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#ifndef VERSAL_ATF_MEM_BASE
+# define BL31_BASE U(0xfffe0000)
+# define BL31_LIMIT U(0xffffffff)
+#else
+# define BL31_BASE (VERSAL_ATF_MEM_BASE)
+# define BL31_LIMIT (VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_SIZE - 1)
+# ifdef VERSAL_ATF_MEM_PROGBITS_SIZE
+# define BL31_PROGBITS_LIMIT (VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_PROGBITS_SIZE - 1)
+# endif
+#endif
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#ifndef VERSAL_BL32_MEM_BASE
+# define BL32_BASE U(0x60000000)
+# define BL32_LIMIT U(0x7fffffff)
+#else
+# define BL32_BASE (VERSAL_BL32_MEM_BASE)
+# define BL32_LIMIT (VERSAL_BL32_MEM_BASE + VERSAL_BL32_MEM_SIZE - 1)
+#endif
+
+/*******************************************************************************
+ * BL33 specific defines.
+ ******************************************************************************/
+#ifndef PRELOADED_BL33_BASE
+# define PLAT_ARM_NS_IMAGE_BASE U(0x8000000)
+#else
+# define PLAT_ARM_NS_IMAGE_BASE PRELOADED_BL33_BASE
+#endif
+
+/*******************************************************************************
+ * TSP specific defines.
+ ******************************************************************************/
+#define TSP_SEC_MEM_BASE BL32_BASE
+#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1)
+
+/* ID of the secure physical generic timer interrupt used by the TSP */
+#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32)
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 5
+
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#define PLAT_VERSAL_GICD_BASE U(0xF9000000)
+#define PLAT_VERSAL_GICR_BASE U(0xF9080000)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_VERSAL_G1S_IRQS VERSAL_IRQ_SEC_PHY_TIMER
+#define PLAT_VERSAL_G0_IRQS VERSAL_IRQ_SEC_PHY_TIMER
+#define PLAT_VERSAL_IPI_IRQ U(62)
+
+#define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_VERSAL_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
new file mode 100644
index 0000000..60431a5
--- /dev/null
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VERSAL_DEF_H
+#define VERSAL_DEF_H
+
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+
+/* number of interrupt handlers. increase as required */
+#define MAX_INTR_EL3 2
+/* List all consoles */
+#define VERSAL_CONSOLE_ID_pl011 1
+#define VERSAL_CONSOLE_ID_pl011_0 1
+#define VERSAL_CONSOLE_ID_pl011_1 2
+#define VERSAL_CONSOLE_ID_dcc 3
+
+#define VERSAL_CONSOLE_IS(con) (VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE)
+
+/* List all supported platforms */
+#define VERSAL_PLATFORM_ID_versal_virt 1
+#define VERSAL_PLATFORM_ID_spp_itr6 2
+#define VERSAL_PLATFORM_ID_emu_itr6 3
+#define VERSAL_PLATFORM_ID_silicon 4
+
+#define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM)
+
+/* Firmware Image Package */
+#define VERSAL_PRIMARY_CPU 0
+
+/*******************************************************************************
+ * memory map related constants
+ ******************************************************************************/
+#define DEVICE0_BASE 0xFF000000
+#define DEVICE0_SIZE 0x00E00000
+#define DEVICE1_BASE 0xF9000000
+#define DEVICE1_SIZE 0x00800000
+
+/*******************************************************************************
+ * IRQ constants
+ ******************************************************************************/
+#define VERSAL_IRQ_SEC_PHY_TIMER U(29)
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_ARM_CCI_BASE 0xFD000000
+#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4
+#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 5
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define VERSAL_UART0_BASE 0xFF000000
+#define VERSAL_UART1_BASE 0xFF010000
+
+#if VERSAL_CONSOLE_IS(pl011) || VERSAL_CONSOLE_IS(dcc)
+# define VERSAL_UART_BASE VERSAL_UART0_BASE
+#elif VERSAL_CONSOLE_IS(pl011_1)
+# define VERSAL_UART_BASE VERSAL_UART1_BASE
+#else
+# error "invalid VERSAL_CONSOLE"
+#endif
+
+#define PLAT_VERSAL_CRASH_UART_BASE VERSAL_UART_BASE
+#define PLAT_VERSAL_CRASH_UART_CLK_IN_HZ VERSAL_UART_CLOCK
+#define VERSAL_CONSOLE_BAUDRATE VERSAL_UART_BAUDRATE
+
+/*******************************************************************************
+ * Platform related constants
+ ******************************************************************************/
+#if VERSAL_PLATFORM_IS(versal_virt)
+# define PLATFORM_NAME "Versal Virt"
+# define VERSAL_UART_CLOCK 25000000
+# define VERSAL_UART_BAUDRATE 115200
+# define VERSAL_CPU_CLOCK 2720000
+#elif VERSAL_PLATFORM_IS(silicon)
+# define PLATFORM_NAME "Versal Silicon"
+# define VERSAL_UART_CLOCK 100000000
+# define VERSAL_UART_BAUDRATE 115200
+# define VERSAL_CPU_CLOCK 100000000
+#elif VERSAL_PLATFORM_IS(spp_itr6)
+# define PLATFORM_NAME "SPP ITR6"
+# define VERSAL_UART_CLOCK 25000000
+# define VERSAL_UART_BAUDRATE 115200
+# define VERSAL_CPU_CLOCK 2720000
+#elif VERSAL_PLATFORM_IS(emu_itr6)
+# define PLATFORM_NAME "EMU ITR6"
+# define VERSAL_UART_CLOCK 212000
+# define VERSAL_UART_BAUDRATE 9600
+# define VERSAL_CPU_CLOCK 212000
+#endif
+
+/* Access control register defines */
+#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
+#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
+
+/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/
+#define CRF_BASE 0xFD1A0000
+#define CRF_SIZE 0x00600000
+
+/* CRF registers and bitfields */
+#define CRF_RST_APU (CRF_BASE + 0X00000300)
+
+#define CRF_RST_APU_ACPU_RESET (1 << 0)
+#define CRF_RST_APU_ACPU_PWRON_RESET (1 << 10)
+
+#define FPD_MAINCCI_BASE 0xFD000000
+#define FPD_MAINCCI_SIZE 0x00100000
+
+/* APU registers and bitfields */
+#define FPD_APU_BASE 0xFD5C0000U
+#define FPD_APU_CONFIG_0 (FPD_APU_BASE + 0x20U)
+#define FPD_APU_RVBAR_L_0 (FPD_APU_BASE + 0x40U)
+#define FPD_APU_RVBAR_H_0 (FPD_APU_BASE + 0x44U)
+#define FPD_APU_PWRCTL (FPD_APU_BASE + 0x90U)
+
+#define FPD_APU_CONFIG_0_VINITHI_SHIFT 8U
+#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1U
+#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2U
+
+/* PMC registers and bitfields */
+#define PMC_GLOBAL_BASE 0xF1110000U
+#define PMC_GLOBAL_GLOB_GEN_STORAGE4 (PMC_GLOBAL_BASE + 0x40U)
+
+/* IPI registers and bitfields */
+#define IPI0_REG_BASE U(0xFF330000)
+#define IPI0_TRIG_BIT (1U << 2U)
+#define PMC_IPI_TRIG_BIT (1U << 1U)
+#define IPI1_REG_BASE U(0xFF340000)
+#define IPI1_TRIG_BIT (1U << 3U)
+#define IPI2_REG_BASE U(0xFF350000)
+#define IPI2_TRIG_BIT (1U << 4U)
+#define IPI3_REG_BASE U(0xFF360000)
+#define IPI3_TRIG_BIT (1U << 5U)
+#define IPI4_REG_BASE U(0xFF370000)
+#define IPI4_TRIG_BIT (1U << 5U)
+#define IPI5_REG_BASE U(0xFF380000)
+#define IPI5_TRIG_BIT (1U << 6U)
+
+#endif /* VERSAL_DEF_H */
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
new file mode 100644
index 0000000..6787f31
--- /dev/null
+++ b/plat/xilinx/versal/plat_psci.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <plat_arm.h>
+#include <plat_private.h>
+#include <pm_common.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "pm_api_sys.h"
+#include "pm_client.h"
+
+static uintptr_t versal_sec_entry;
+
+static int32_t versal_pwr_domain_on(u_register_t mpidr)
+{
+ int32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+ const struct pm_proc *proc;
+
+ VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
+
+ if (cpu_id == -1) {
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ proc = pm_get_proc((uint32_t)cpu_id);
+
+ /* Send request to PMC to wake up selected ACPU core */
+ (void)pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFFU) | 0x1U,
+ versal_sec_entry >> 32, 0, SECURE_FLAG);
+
+ /* Clear power down request */
+ pm_client_wakeup(proc);
+
+ return PSCI_E_SUCCESS;
+}
+
+/**
+ * versal_pwr_domain_suspend() - This function sends request to PMC to suspend
+ * core.
+ *
+ * @target_state Targated state
+ */
+static void versal_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint32_t state;
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ plat_versal_gic_cpuif_disable();
+
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_versal_gic_save();
+ }
+
+ state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
+ PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
+
+ /* Send request to PMC to suspend this core */
+ (void)pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_sec_entry,
+ SECURE_FLAG);
+
+ /* APU is to be turned off */
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ /* disable coherency */
+ plat_arm_interconnect_exit_coherency();
+ }
+}
+
+/**
+ * versal_pwr_domain_suspend_finish() - This function performs actions to finish
+ * suspend procedure.
+ *
+ * @target_state Targated state
+ */
+static void versal_pwr_domain_suspend_finish(
+ const psci_power_state_t *target_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ /* Clear the APU power control register for this cpu */
+ pm_client_wakeup(proc);
+
+ /* enable coherency */
+ plat_arm_interconnect_enter_coherency();
+
+ /* APU was turned off, so restore GIC context */
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_versal_gic_resume();
+ }
+
+ plat_versal_gic_cpuif_enable();
+}
+
+void versal_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ /* Enable the gic cpu interface */
+ plat_versal_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_versal_gic_cpuif_enable();
+}
+
+/**
+ * versal_system_off() - This function sends the system off request
+ * to firmware. This function does not return.
+ */
+static void __dead2 versal_system_off(void)
+{
+ /* Send the power down request to the PMC */
+ (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN,
+ pm_get_shutdown_scope(), SECURE_FLAG);
+
+ while (1) {
+ wfi();
+ }
+}
+
+/**
+ * versal_system_reset() - This function sends the reset request
+ * to firmware for the system to reset. This function does not return.
+ */
+static void __dead2 versal_system_reset(void)
+{
+ /* Send the system reset request to the PMC */
+ (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
+ pm_get_shutdown_scope(), SECURE_FLAG);
+
+ while (1) {
+ wfi();
+ }
+}
+
+/**
+ * versal_pwr_domain_off() - This function performs actions to turn off core
+ *
+ * @target_state Targated state
+ */
+static void versal_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_versal_gic_cpuif_disable();
+
+ /*
+ * Send request to PMC to power down the appropriate APU CPU
+ * core.
+ * According to PSCI specification, CPU_off function does not
+ * have resume address and CPU core can only be woken up
+ * invoking CPU_on function, during which resume address will
+ * be set.
+ */
+ (void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
+ SECURE_FLAG);
+}
+
+/**
+ * versal_validate_power_state() - This function ensures that the power state
+ * parameter in request is valid.
+ *
+ * @power_state Power state of core
+ * @req_state Requested state
+ *
+ * @return Returns status, either success or reason
+ */
+static int32_t versal_validate_power_state(uint32_t power_state,
+ psci_power_state_t *req_state)
+{
+ VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+ uint32_t pstate = psci_get_pstate_type(power_state);
+
+ assert(req_state);
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ } else {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+ }
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state) != 0U) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/**
+ * versal_get_sys_suspend_power_state() - Get power state for system suspend
+ *
+ * @req_state Requested state
+ */
+static void versal_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
+}
+
+static const struct plat_psci_ops versal_nopmc_psci_ops = {
+ .pwr_domain_on = versal_pwr_domain_on,
+ .pwr_domain_off = versal_pwr_domain_off,
+ .pwr_domain_on_finish = versal_pwr_domain_on_finish,
+ .pwr_domain_suspend = versal_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = versal_pwr_domain_suspend_finish,
+ .system_off = versal_system_off,
+ .system_reset = versal_system_reset,
+ .validate_power_state = versal_validate_power_state,
+ .get_sys_suspend_power_state = versal_get_sys_suspend_power_state,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int32_t plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ versal_sec_entry = sec_entrypoint;
+
+ *psci_ops = &versal_nopmc_psci_ops;
+
+ return 0;
+}
diff --git a/plat/xilinx/versal/plat_topology.c b/plat/xilinx/versal/plat_topology.c
new file mode 100644
index 0000000..6a94544
--- /dev/null
+++ b/plat/xilinx/versal/plat_topology.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+static const uint8_t plat_power_domain_tree_desc[] = {1, PLATFORM_CORE_COUNT};
+
+const uint8_t *plat_get_power_domain_tree_desc(void)
+{
+ return plat_power_domain_tree_desc;
+}
diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c
new file mode 100644
index 0000000..132c7b7
--- /dev/null
+++ b/plat/xilinx/versal/plat_versal.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_private.h>
+#include <plat/common/platform.h>
+
+int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ if ((mpidr & MPIDR_CLUSTER_MASK) != 0U) {
+ return -1;
+ }
+
+ if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) {
+ return -1;
+ }
+
+ return (int32_t)versal_calc_core_pos(mpidr);
+}
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
new file mode 100644
index 0000000..8087297
--- /dev/null
+++ b/plat/xilinx/versal/platform.mk
@@ -0,0 +1,98 @@
+# Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+override PROGRAMMABLE_RESET_ADDRESS := 1
+PSCI_EXTENDED_STATE_ID := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+SEPARATE_CODE_AND_RODATA := 1
+override RESET_TO_BL31 := 1
+PL011_GENERIC_UART := 1
+IPI_CRC_CHECK := 0
+HARDEN_SLS_ALL := 0
+
+# A72 Erratum for SoC
+ERRATA_A72_859971 := 1
+ERRATA_A72_1319367 := 1
+
+ifdef VERSAL_ATF_MEM_BASE
+ $(eval $(call add_define,VERSAL_ATF_MEM_BASE))
+
+ ifndef VERSAL_ATF_MEM_SIZE
+ $(error "VERSAL_ATF_BASE defined without VERSAL_ATF_SIZE")
+ endif
+ $(eval $(call add_define,VERSAL_ATF_MEM_SIZE))
+
+ ifdef VERSAL_ATF_MEM_PROGBITS_SIZE
+ $(eval $(call add_define,VERSAL_ATF_MEM_PROGBITS_SIZE))
+ endif
+endif
+
+ifdef VERSAL_BL32_MEM_BASE
+ $(eval $(call add_define,VERSAL_BL32_MEM_BASE))
+
+ ifndef VERSAL_BL32_MEM_SIZE
+ $(error "VERSAL_BL32_BASE defined without VERSAL_BL32_SIZE")
+ endif
+ $(eval $(call add_define,VERSAL_BL32_MEM_SIZE))
+endif
+
+ifdef IPI_CRC_CHECK
+ $(eval $(call add_define,IPI_CRC_CHECK))
+endif
+
+VERSAL_PLATFORM ?= silicon
+$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM}))
+
+PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
+ -Iplat/xilinx/common/include/ \
+ -Iplat/xilinx/common/ipi_mailbox_service/ \
+ -Iplat/xilinx/versal/include/ \
+ -Iplat/xilinx/versal/pm_service/
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ drivers/arm/dcc/dcc_console.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${GICV3_SOURCES} \
+ drivers/arm/pl011/aarch64/pl011_console.S \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/arm/common/arm_cci.c \
+ plat/arm/common/arm_common.c \
+ plat/common/plat_gicv3.c \
+ plat/xilinx/versal/aarch64/versal_helpers.S \
+ plat/xilinx/versal/aarch64/versal_common.c
+
+VERSAL_CONSOLE ?= pl011
+ifeq (${VERSAL_CONSOLE}, $(filter ${VERSAL_CONSOLE},pl011 pl011_0 pl011_1 dcc))
+else
+ $(error "Please define VERSAL_CONSOLE")
+endif
+
+$(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE}))
+
+BL31_SOURCES += drivers/arm/cci/cci.c \
+ lib/cpus/aarch64/cortex_a72.S \
+ plat/common/plat_psci_common.c \
+ plat/xilinx/common/ipi.c \
+ plat/xilinx/common/plat_startup.c \
+ plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \
+ plat/xilinx/common/pm_service/pm_ipi.c \
+ plat/xilinx/versal/bl31_versal_setup.c \
+ plat/xilinx/versal/plat_psci.c \
+ plat/xilinx/versal/plat_versal.c \
+ plat/xilinx/versal/plat_topology.c \
+ plat/xilinx/versal/sip_svc_setup.c \
+ plat/xilinx/versal/versal_gicv3.c \
+ plat/xilinx/versal/versal_ipi.c \
+ plat/xilinx/versal/pm_service/pm_svc_main.c \
+ plat/xilinx/versal/pm_service/pm_api_sys.c \
+ plat/xilinx/versal/pm_service/pm_client.c
+
+ifeq ($(HARDEN_SLS_ALL), 1)
+TF_CFLAGS_aarch64 += -mharden-sls=all
+endif
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
new file mode 100644
index 0000000..db9fae4
--- /dev/null
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Versal system level PM-API functions and communication with PMC via
+ * IPI interrupts
+ */
+
+#include <pm_common.h>
+#include <pm_ipi.h>
+#include <plat/common/platform.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_defs.h"
+#include "pm_svc_main.h"
+
+/* default shutdown/reboot scope is system(2) */
+static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
+
+/**
+ * pm_get_shutdown_scope() - Get the currently set shutdown scope
+ *
+ * @return Shutdown scope value
+ */
+uint32_t pm_get_shutdown_scope(void)
+{
+ return pm_shutdown_scope;
+}
+
+/* PM API functions */
+
+/**
+ * pm_handle_eemi_call() - PM call for processor to send eemi payload
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ * @x0 to x5 Arguments received per SMC64 standard
+ * @result Payload received from firmware
+ *
+ * @return PM_RET_SUCCESS on success or error code
+ */
+enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
+ uint32_t x2, uint32_t x3, uint32_t x4,
+ uint32_t x5, uint64_t *result)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT] = {0};
+ uint32_t module_id;
+
+ module_id = (x0 & MODULE_ID_MASK) >> 8U;
+
+ //default module id is for LIBPM
+ if (module_id == 0) {
+ module_id = LIBPM_MODULE_ID;
+ }
+
+ PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
+ return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
+}
+
+/**
+ * pm_self_suspend() - PM call for processor to suspend itself
+ * @nid Node id of the processor or subsystem
+ * @latency Requested maximum wakeup latency (not supported)
+ * @state Requested state
+ * @address Resume address
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * This is a blocking call, it will return only once PMU has responded.
+ * On a wakeup, resume address will be automatically set by PMU.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_self_suspend(uint32_t nid,
+ uint32_t latency,
+ uint32_t state,
+ uintptr_t address, uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ uint32_t cpuid = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpuid);
+
+ if (proc == NULL) {
+ WARN("Failed to get proc %d\n", cpuid);
+ return PM_RET_ERROR_INTERNAL;
+ }
+
+ /*
+ * Do client specific suspend operations
+ * (e.g. set powerdown request bit)
+ */
+ pm_client_suspend(proc, state);
+
+ /* Send request to the PLM */
+ PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND,
+ proc->node_id, latency, state, address,
+ (address >> 32));
+ return pm_ipi_send_sync(proc, payload, NULL, 0);
+}
+
+/**
+ * pm_abort_suspend() - PM call to announce that a prior suspend request
+ * is to be aborted.
+ * @reason Reason for the abort
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * Calling PU expects the PMU to abort the initiated suspend procedure.
+ * This is a non-blocking call without any acknowledge.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /*
+ * Do client specific abort suspend operations
+ * (e.g. enable interrupts and clear powerdown request bit)
+ */
+ pm_client_abort_suspend();
+
+ /* Send request to the PLM */
+ PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND,
+ reason, primary_proc->node_id);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_req_suspend() - PM call to request for another PU or subsystem to
+ * be suspended gracefully.
+ * @target Node id of the targeted PU or subsystem
+ * @ack Flag to specify whether acknowledge is requested
+ * @latency Requested wakeup latency (not supported)
+ * @state Requested state (not supported)
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack,
+ uint32_t latency, uint32_t state,
+ uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target,
+ latency, state);
+ if (ack == IPI_BLOCKING) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return pm_ipi_send(primary_proc, payload);
+ }
+}
+
+/**
+ * pm_req_wakeup() - PM call for processor to wake up selected processor
+ * or subsystem
+ * @target Device ID of the processor or subsystem to wake up
+ * @set_address Resume address presence indicator
+ * 1 - resume address specified, 0 - otherwise
+ * @address Resume address
+ * @ack Flag to specify whether acknowledge requested
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * This API function is either used to power up another APU core for SMP
+ * (by PSCI) or to power up an entirely different PU or subsystem, such
+ * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
+ * automatically set by PMC.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
+ uintptr_t address, uint8_t ack, uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMC to perform the wake of the PU */
+ PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target,
+ set_address, address, ack);
+
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_get_callbackdata() - Read from IPI response buffer
+ * @data - array of PAYLOAD_ARG_CNT elements
+ * @flag - 0 - Call from secure source
+ * 1 - Call from non-secure source
+ * @ack - 0 - Do not ack IPI after reading payload
+ * 1 - Ack IPI after reading payload
+ *
+ * Read value from ipi buffer response buffer.
+ */
+void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
+{
+ /* Return if interrupt is not from PMU */
+ if (pm_ipi_irq_status(primary_proc) == 0) {
+ return;
+ }
+
+ pm_ipi_buff_read_callb(data, count);
+
+ if (ack != 0U) {
+ pm_ipi_irq_clear(primary_proc);
+ }
+}
+
+/**
+ * pm_pll_set_param() - Set PLL parameter
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id PLL clock ID
+ * @param PLL parameter ID
+ * @value Value to set for PLL parameter
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
+ uint32_t value, uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_PARAMETER,
+ clk_id, param, value);
+
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_param() - Get PLL parameter value
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id PLL clock ID
+ * @param PLL parameter ID
+ * @value: Buffer to store PLL parameter value
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
+ uint32_t *value, uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_PARAMETER,
+ clk_id, param);
+
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_pll_set_mode() - Set PLL mode
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id PLL clock ID
+ * @mode PLL mode
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode,
+ uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_MODE,
+ clk_id, mode);
+
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_mode() - Get PLL mode
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id PLL clock ID
+ * @mode: Buffer to store PLL mode
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode,
+ uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_MODE,
+ clk_id);
+
+ return pm_ipi_send_sync(primary_proc, payload, mode, 1);
+}
+
+/**
+ * pm_force_powerdown() - PM call to request for another PU or subsystem to
+ * be powered down forcefully
+ * @target Device ID of the PU node to be forced powered down.
+ * @ack Flag to specify whether acknowledge is requested
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack,
+ uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN,
+ target, ack);
+
+ if (ack == IPI_BLOCKING) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return pm_ipi_send(primary_proc, payload);
+ }
+}
+
+/**
+ * pm_system_shutdown() - PM call to request a system shutdown or restart
+ * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
+ * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype,
+ uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
+ /* Setting scope for subsequent PSCI reboot or shutdown */
+ pm_shutdown_scope = subtype;
+ return PM_RET_SUCCESS;
+ }
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN,
+ type, subtype);
+
+ return pm_ipi_send_non_blocking(primary_proc, payload);
+}
+
+/**
+ * pm_query_data() - PM API for querying firmware data
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @qid The type of data to query
+ * @arg1 Argument 1 to requested query data call
+ * @arg2 Argument 2 to requested query data call
+ * @arg3 Argument 3 to requested query data call
+ * @data Returned output data
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @retur - 0 if success else non-zero error code of type
+ * enum pm_ret_status
+ */
+enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
+ uint32_t arg3, uint32_t *data, uint32_t flag)
+{
+ uint32_t ret;
+ uint32_t version[PAYLOAD_ARG_CNT] = {0};
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ uint32_t fw_api_version;
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_QUERY_DATA, qid,
+ arg1, arg2, arg3);
+
+ ret = pm_feature_check(PM_QUERY_DATA, &version[0], flag);
+ if (ret == PM_RET_SUCCESS) {
+ fw_api_version = version[0] & 0xFFFFU;
+ if ((fw_api_version == 2U) &&
+ ((qid == XPM_QID_CLOCK_GET_NAME) ||
+ (qid == XPM_QID_PINCTRL_GET_FUNCTION_NAME))) {
+ ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
+ if (ret == PM_RET_SUCCESS) {
+ ret = data[0];
+ data[0] = data[1];
+ data[1] = data[2];
+ data[2] = data[3];
+ }
+ } else {
+ ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
+ }
+ }
+ return ret;
+}
+/**
+ * pm_api_ioctl() - PM IOCTL API for device control and configs
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @device_id Device ID
+ * @ioctl_id ID of the requested IOCTL
+ * @arg1 Argument 1 to requested IOCTL call
+ * @arg2 Argument 2 to requested IOCTL call
+ * @arg3 Argument 3 to requested IOCTL call
+ * @value Returned output value
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return Returns status, either 0 on success or non-zero error code
+ * of type enum pm_ret_status
+ */
+enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
+ uint32_t arg1, uint32_t arg2, uint32_t arg3,
+ uint32_t *value, uint32_t flag)
+{
+ enum pm_ret_status ret;
+
+ switch (ioctl_id) {
+ case IOCTL_SET_PLL_FRAC_MODE:
+ ret = pm_pll_set_mode(arg1, arg2, flag);
+ break;
+ case IOCTL_GET_PLL_FRAC_MODE:
+ ret = pm_pll_get_mode(arg1, value, flag);
+ break;
+ case IOCTL_SET_PLL_FRAC_DATA:
+ ret = pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag);
+ break;
+ case IOCTL_GET_PLL_FRAC_DATA:
+ ret = pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag);
+ break;
+ case IOCTL_SET_SGI:
+ /* Get the sgi number */
+ ret = pm_register_sgi(arg1, arg2);
+ if (ret != 0) {
+ return PM_RET_ERROR_ARGS;
+ }
+ ret = PM_RET_SUCCESS;
+ break;
+ default:
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+
+ return ret;
+}
+
+/**
+ * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
+ * @target Device id of the targeted PU or subsystem
+ * @wkup_node Device id of the wakeup peripheral
+ * @enable Enable or disable the specified peripheral as wake source
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device,
+ uint8_t enable, uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE,
+ target, wkup_device, enable);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_feature_check() - Returns the supported API version if supported
+ * @api_id API ID to check
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ * @ret_payload pointer to array of PAYLOAD_ARG_CNT number of
+ * words Returned supported API version and bitmasks
+ * for IOCTL and QUERY ID
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
+ uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ uint32_t module_id;
+
+ /* Return version of API which are implemented in ATF only */
+ switch (api_id) {
+ case PM_GET_CALLBACK_DATA:
+ case PM_GET_TRUSTZONE_VERSION:
+ ret_payload[0] = PM_API_VERSION_2;
+ return PM_RET_SUCCESS;
+ case TF_A_PM_REGISTER_SGI:
+ ret_payload[0] = PM_API_BASE_VERSION;
+ return PM_RET_SUCCESS;
+ default:
+ break;
+ }
+
+ module_id = (api_id & MODULE_ID_MASK) >> 8U;
+
+ /*
+ * feature check should be done only for LIBPM module
+ * If module_id is 0, then we consider it LIBPM module as default id
+ */
+ if ((module_id > 0) && (module_id != LIBPM_MODULE_ID)) {
+ return PM_RET_SUCCESS;
+ }
+
+ PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
+ PM_FEATURE_CHECK, api_id);
+ return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
+}
+
+/**
+ * pm_load_pdi() - Load the PDI
+ *
+ * This function provides support to load PDI from linux
+ *
+ * src: Source device of pdi(DDR, OCM, SD etc)
+ * address_low: lower 32-bit Linear memory space address
+ * address_high: higher 32-bit Linear memory space address
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low,
+ uint32_t address_high, uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src,
+ address_high, address_low);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_register_notifier() - PM call to register a subsystem to be notified
+ * about the device event
+ * @device_id Device ID for the Node to which the event is related
+ * @event Event in question
+ * @wake Wake subsystem upon capturing the event if value 1
+ * @enable Enable the registration for value 1, disable for value 0
+ * @flag 0 - Call from secure source
+ * 1 - Call from non-secure source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
+ uint32_t wake, uint32_t enable,
+ uint32_t flag)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMC */
+ PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER,
+ device_id, event, wake, enable);
+
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
new file mode 100644
index 0000000..c539aa7
--- /dev/null
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_API_SYS_H
+#define PM_API_SYS_H
+
+#include <stdint.h>
+#include "pm_defs.h"
+
+/*********************************************************************
+ * Target module IDs macros
+ ********************************************************************/
+#define LIBPM_MODULE_ID 0x2U
+#define LOADER_MODULE_ID 0x7U
+
+#define MODULE_ID_MASK 0x0000ff00U
+/**********************************************************
+ * PM API function declarations
+ **********************************************************/
+
+enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
+ uint32_t x2, uint32_t x3, uint32_t x4,
+ uint32_t x5, uint64_t *result);
+enum pm_ret_status pm_self_suspend(uint32_t nid,
+ uint32_t latency,
+ uint32_t state,
+ uintptr_t address, uint32_t flag);
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag);
+enum pm_ret_status pm_req_suspend(uint32_t target,
+ uint8_t ack,
+ uint32_t latency,
+ uint32_t state, uint32_t flag);
+enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
+ uintptr_t address, uint8_t ack, uint32_t flag);
+enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id,
+ uint8_t enable, uint32_t flag);
+void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag,
+ uint32_t ack);
+enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
+ uint32_t value, uint32_t flag);
+enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
+ uint32_t *value, uint32_t flag);
+enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode,
+ uint32_t flag);
+enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode,
+ uint32_t flag);
+enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack,
+ uint32_t flag);
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype,
+ uint32_t flag);
+enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
+ uint32_t arg1, uint32_t arg2, uint32_t arg3,
+ uint32_t *value, uint32_t flag);
+enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
+ uint32_t arg3, uint32_t *data, uint32_t flag);
+uint32_t pm_get_shutdown_scope(void);
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
+ uint32_t flag);
+enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low,
+ uint32_t address_high, uint32_t flag);
+enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
+ uint32_t wake, uint32_t enable,
+ uint32_t flag);
+
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, mid, flag, arg0) { \
+ pl[0] = (uint32_t)(((uint32_t)(arg0) & 0xFFU) | ((mid) << 8U) | ((flag) << 24U)); \
+}
+
+#define PM_PACK_PAYLOAD2(pl, mid, flag, arg0, arg1) { \
+ pl[1] = (uint32_t)(arg1); \
+ PM_PACK_PAYLOAD1(pl, (mid), (flag), (arg0)); \
+}
+
+#define PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2) { \
+ pl[2] = (uint32_t)(arg2); \
+ PM_PACK_PAYLOAD2(pl, (mid), (flag), (arg0), (arg1)); \
+}
+
+#define PM_PACK_PAYLOAD4(pl, mid, flag, arg0, arg1, arg2, arg3) { \
+ pl[3] = (uint32_t)(arg3); \
+ PM_PACK_PAYLOAD3(pl, (mid), (flag), (arg0), (arg1), (arg2)); \
+}
+
+#define PM_PACK_PAYLOAD5(pl, mid, flag, arg0, arg1, arg2, arg3, arg4) { \
+ pl[4] = (uint32_t)(arg4); \
+ PM_PACK_PAYLOAD4(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3)); \
+}
+
+#define PM_PACK_PAYLOAD6(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5) { \
+ pl[5] = (uint32_t)(arg5); \
+ PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4)); \
+}
+
+#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c
new file mode 100644
index 0000000..ce5e533
--- /dev/null
+++ b/plat/xilinx/versal/pm_service/pm_client.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * APU specific definition of processors in the subsystem as well as functions
+ * for getting information about and changing state of the APU.
+ */
+
+#include <assert.h>
+#include <plat_ipi.h>
+#include <platform_def.h>
+#include <versal_def.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/arm/gic_common.h>
+#include <plat/common/platform.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_defs.h"
+
+#define UNDEFINED_CPUID (~0)
+#define IRQ_MAX 142U
+#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5U) + 1U)
+
+DEFINE_BAKERY_LOCK(pm_client_secure_lock);
+
+static const struct pm_ipi apu_ipi = {
+ .local_ipi_id = IPI_ID_APU,
+ .remote_ipi_id = IPI_ID_PMC,
+ .buffer_base = IPI_BUFFER_APU_BASE,
+};
+
+/* Order in pm_procs_all array must match cpu ids */
+static const struct pm_proc pm_procs_all[] = {
+ {
+ .node_id = XPM_DEVID_ACPU_0,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
+ },
+ {
+ .node_id = XPM_DEVID_ACPU_1,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
+ }
+};
+
+const struct pm_proc *primary_proc = &pm_procs_all[0];
+
+/* Interrupt to PM node index map */
+static enum pm_device_node_idx irq_node_map[IRQ_MAX + 1] = {
+ [13] = XPM_NODEIDX_DEV_GPIO,
+ [14] = XPM_NODEIDX_DEV_I2C_0,
+ [15] = XPM_NODEIDX_DEV_I2C_1,
+ [16] = XPM_NODEIDX_DEV_SPI_0,
+ [17] = XPM_NODEIDX_DEV_SPI_1,
+ [18] = XPM_NODEIDX_DEV_UART_0,
+ [19] = XPM_NODEIDX_DEV_UART_1,
+ [20] = XPM_NODEIDX_DEV_CAN_FD_0,
+ [21] = XPM_NODEIDX_DEV_CAN_FD_1,
+ [22] = XPM_NODEIDX_DEV_USB_0,
+ [23] = XPM_NODEIDX_DEV_USB_0,
+ [24] = XPM_NODEIDX_DEV_USB_0,
+ [25] = XPM_NODEIDX_DEV_USB_0,
+ [26] = XPM_NODEIDX_DEV_USB_0,
+ [37] = XPM_NODEIDX_DEV_TTC_0,
+ [38] = XPM_NODEIDX_DEV_TTC_0,
+ [39] = XPM_NODEIDX_DEV_TTC_0,
+ [40] = XPM_NODEIDX_DEV_TTC_1,
+ [41] = XPM_NODEIDX_DEV_TTC_1,
+ [42] = XPM_NODEIDX_DEV_TTC_1,
+ [43] = XPM_NODEIDX_DEV_TTC_2,
+ [44] = XPM_NODEIDX_DEV_TTC_2,
+ [45] = XPM_NODEIDX_DEV_TTC_2,
+ [46] = XPM_NODEIDX_DEV_TTC_3,
+ [47] = XPM_NODEIDX_DEV_TTC_3,
+ [48] = XPM_NODEIDX_DEV_TTC_3,
+ [56] = XPM_NODEIDX_DEV_GEM_0,
+ [57] = XPM_NODEIDX_DEV_GEM_0,
+ [58] = XPM_NODEIDX_DEV_GEM_1,
+ [59] = XPM_NODEIDX_DEV_GEM_1,
+ [60] = XPM_NODEIDX_DEV_ADMA_0,
+ [61] = XPM_NODEIDX_DEV_ADMA_1,
+ [62] = XPM_NODEIDX_DEV_ADMA_2,
+ [63] = XPM_NODEIDX_DEV_ADMA_3,
+ [64] = XPM_NODEIDX_DEV_ADMA_4,
+ [65] = XPM_NODEIDX_DEV_ADMA_5,
+ [66] = XPM_NODEIDX_DEV_ADMA_6,
+ [67] = XPM_NODEIDX_DEV_ADMA_7,
+ [74] = XPM_NODEIDX_DEV_USB_0,
+ [126] = XPM_NODEIDX_DEV_SDIO_0,
+ [127] = XPM_NODEIDX_DEV_SDIO_0,
+ [128] = XPM_NODEIDX_DEV_SDIO_1,
+ [129] = XPM_NODEIDX_DEV_SDIO_1,
+ [142] = XPM_NODEIDX_DEV_RTC,
+};
+
+/**
+ * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number
+ * @irq: Interrupt number
+ *
+ * Return: PM node index corresponding to the specified interrupt
+ */
+static enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
+{
+ assert(irq <= IRQ_MAX);
+ return irq_node_map[irq];
+}
+
+/**
+ * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as
+ * wake sources in the LibPM.
+ * @node_id: Node id of processor
+ */
+static void pm_client_set_wakeup_sources(uint32_t node_id)
+{
+ uint32_t reg_num;
+ uint32_t device_id;
+ uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX];
+ uintptr_t isenabler1 = PLAT_VERSAL_GICD_BASE + GICD_ISENABLER + 4;
+
+ zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set));
+
+ for (reg_num = 0U; reg_num < NUM_GICD_ISENABLER; reg_num++) {
+ uint32_t base_irq = reg_num << ISENABLER_SHIFT;
+ uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2));
+
+ if (reg == 0U) {
+ continue;
+ }
+
+ while (reg != 0U) {
+ enum pm_device_node_idx node_idx;
+ uint32_t idx, irq, lowest_set = reg & (-reg);
+ enum pm_ret_status ret;
+
+ idx = __builtin_ctz(lowest_set);
+ irq = base_irq + idx;
+
+ if (irq > IRQ_MAX) {
+ break;
+ }
+
+ node_idx = irq_to_pm_node_idx(irq);
+ reg &= ~lowest_set;
+
+ if (node_idx > XPM_NODEIDX_DEV_MIN && node_idx < XPM_NODEIDX_DEV_MAX) {
+ if (pm_wakeup_nodes_set[node_idx] == 0U) {
+ /* Get device ID from node index */
+ device_id = PERIPH_DEVID(node_idx);
+ ret = pm_set_wakeup_source(node_id,
+ device_id, 1,
+ SECURE_FLAG);
+ pm_wakeup_nodes_set[node_idx] = (ret == PM_RET_SUCCESS) ?
+ 1 : 0;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * pm_client_suspend() - Client-specific suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required prior to sending suspend request to PMU
+ * Actions taken depend on the state system is suspending to.
+ */
+void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
+{
+ bakery_lock_get(&pm_client_secure_lock);
+
+ if (state == PM_STATE_SUSPEND_TO_RAM) {
+ pm_client_set_wakeup_sources((uint32_t)proc->node_id);
+ }
+
+ /* Set powerdown request */
+ mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
+ (uint32_t)proc->pwrdn_mask);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+/**
+ * pm_client_abort_suspend() - Client-specific abort-suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required for aborting a prior suspend request
+ */
+void pm_client_abort_suspend(void)
+{
+ /* Enable interrupts at processor level (for current cpu) */
+ gicv3_cpuif_enable(plat_my_core_pos());
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* Clear powerdown request */
+ mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
+ ~((uint32_t)primary_proc->pwrdn_mask));
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+/**
+ * pm_get_cpuid() - get the local cpu ID for a global node ID
+ * @nid: node id of the processor
+ *
+ * Return: the cpu ID (starting from 0) for the subsystem
+ */
+static uint32_t pm_get_cpuid(uint32_t nid)
+{
+ for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
+ if (pm_procs_all[i].node_id == nid) {
+ return i;
+ }
+ }
+ return UNDEFINED_CPUID;
+}
+
+/**
+ * pm_client_wakeup() - Client-specific wakeup actions
+ *
+ * This function should contain any PU-specific actions
+ * required for waking up another APU core
+ */
+void pm_client_wakeup(const struct pm_proc *proc)
+{
+ uint32_t cpuid = pm_get_cpuid(proc->node_id);
+
+ if (cpuid == UNDEFINED_CPUID) {
+ return;
+ }
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* clear powerdown bit for affected cpu */
+ uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
+ val &= ~(proc->pwrdn_mask);
+ mmio_write_32(FPD_APU_PWRCTL, val);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+/**
+ * pm_get_proc() - returns pointer to the proc structure
+ * @cpuid: id of the cpu whose proc struct pointer should be returned
+ *
+ * Return: pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc(uint32_t cpuid)
+{
+ if (cpuid < ARRAY_SIZE(pm_procs_all)) {
+ return &pm_procs_all[cpuid];
+ }
+
+ return NULL;
+}
diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h
new file mode 100644
index 0000000..2922b5d
--- /dev/null
+++ b/plat/xilinx/versal/pm_service/pm_defs.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Versal power management enums and defines */
+
+#ifndef PM_DEFS_H
+#define PM_DEFS_H
+
+#include "pm_node.h"
+
+/*********************************************************************
+ * Macro definitions
+ ********************************************************************/
+
+/* State arguments of the self suspend */
+#define PM_STATE_CPU_IDLE 0x0U
+#define PM_STATE_SUSPEND_TO_RAM 0xFU
+
+#define MAX_LATENCY (~0U)
+#define MAX_QOS 100U
+
+/* Processor core device IDs */
+#define APU_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, XPM_NODESUBCL_DEV_CORE, \
+ XPM_NODETYPE_DEV_CORE_APU, (IDX))
+
+#define XPM_DEVID_ACPU_0 APU_DEVID(XPM_NODEIDX_DEV_ACPU_0)
+#define XPM_DEVID_ACPU_1 APU_DEVID(XPM_NODEIDX_DEV_ACPU_1)
+
+#define PERIPH_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, \
+ XPM_NODESUBCL_DEV_PERIPH, \
+ XPM_NODETYPE_DEV_PERIPH, (IDX))
+
+#define PM_GET_CALLBACK_DATA 0xa01U
+#define PM_GET_TRUSTZONE_VERSION 0xa03U
+#define TF_A_PM_REGISTER_SGI 0xa04U
+
+/* PM API Versions */
+#define PM_API_BASE_VERSION 1U
+#define PM_API_VERSION_2 2U
+
+/* PM API ids */
+#define PM_REGISTER_NOTIFIER 5U
+#define PM_REQ_SUSPEND 6U
+#define PM_SELF_SUSPEND 7U
+#define PM_FORCE_POWERDOWN 8U
+#define PM_ABORT_SUSPEND 9U
+#define PM_REQ_WAKEUP 10U
+#define PM_SET_WAKEUP_SOURCE 11U
+#define PM_SYSTEM_SHUTDOWN 12U
+#define PM_IOCTL 34U
+#define PM_QUERY_DATA 35U
+#define PM_PLL_SET_PARAMETER 48U
+#define PM_PLL_GET_PARAMETER 49U
+#define PM_PLL_SET_MODE 50U
+#define PM_PLL_GET_MODE 51U
+#define PM_FEATURE_CHECK 63U
+
+/* Loader API ids */
+#define PM_LOAD_PDI 0x701U
+#define PM_LOAD_GET_HANDOFF_PARAMS 0x70BU
+
+/* IOCTL IDs for clock driver */
+#define IOCTL_SET_PLL_FRAC_MODE 8U
+#define IOCTL_GET_PLL_FRAC_MODE 9U
+#define IOCTL_SET_PLL_FRAC_DATA 10U
+#define IOCTL_GET_PLL_FRAC_DATA 11U
+#define IOCTL_SET_SGI 25U
+
+/* Parameter ID for PLL IOCTLs */
+/* Fractional data portion for PLL */
+#define PM_PLL_PARAM_DATA 2
+
+/* System shutdown macros */
+#define XPM_SHUTDOWN_TYPE_SHUTDOWN 0U
+#define XPM_SHUTDOWN_TYPE_RESET 1U
+#define XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY 2U
+
+#define XPM_SHUTDOWN_SUBTYPE_RST_SUBSYSTEM 0U
+#define XPM_SHUTDOWN_SUBTYPE_RST_PS_ONLY 1U
+#define XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM 2U
+
+/*********************************************************************
+ * Enum definitions
+ ********************************************************************/
+
+enum pm_abort_reason {
+ ABORT_REASON_WKUP_EVENT = 100,
+ ABORT_REASON_PU_BUSY,
+ ABORT_REASON_NO_PWRDN,
+ ABORT_REASON_UNKNOWN,
+};
+
+enum pm_opchar_type {
+ PM_OPCHAR_TYPE_POWER = 1,
+ PM_OPCHAR_TYPE_TEMP,
+ PM_OPCHAR_TYPE_LATENCY,
+};
+
+/**
+ * Subsystem IDs
+ */
+typedef enum {
+ XPM_SUBSYSID_PMC,
+ XPM_SUBSYSID_PSM,
+ XPM_SUBSYSID_APU,
+ XPM_SUBSYSID_RPU0_LOCK,
+ XPM_SUBSYSID_RPU0_0,
+ XPM_SUBSYSID_RPU0_1,
+ XPM_SUBSYSID_DDR0,
+ XPM_SUBSYSID_ME,
+ XPM_SUBSYSID_PL,
+ XPM_SUBSYSID_MAX,
+} XPm_SubsystemId;
+
+/**
+ * @PM_RET_SUCCESS: success
+ * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated)
+ * @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated)
+ * @PM_RET_ERROR_NOFEATURE: feature is not available
+ * @PM_RET_ERROR_INTERNAL: internal error
+ * @PM_RET_ERROR_CONFLICT: conflict
+ * @PM_RET_ERROR_ACCESS: access rights violation
+ * @PM_RET_ERROR_INVALID_NODE: invalid node
+ * @PM_RET_ERROR_DOUBLE_REQ: duplicate request for same node
+ * @PM_RET_ERROR_ABORT_SUSPEND: suspend procedure has been aborted
+ * @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU
+ * @PM_RET_ERROR_NODE_USED: node is already in use
+ */
+enum pm_ret_status {
+ PM_RET_SUCCESS,
+ PM_RET_ERROR_ARGS = 1,
+ PM_RET_ERROR_NOTSUPPORTED = 4,
+ PM_RET_ERROR_NOFEATURE = 19,
+ PM_RET_ERROR_INTERNAL = 2000,
+ PM_RET_ERROR_CONFLICT = 2001,
+ PM_RET_ERROR_ACCESS = 2002,
+ PM_RET_ERROR_INVALID_NODE = 2003,
+ PM_RET_ERROR_DOUBLE_REQ = 2004,
+ PM_RET_ERROR_ABORT_SUSPEND = 2005,
+ PM_RET_ERROR_TIMEOUT = 2006,
+ PM_RET_ERROR_NODE_USED = 2007
+};
+
+/**
+ * Qids
+ */
+enum pm_query_id {
+ XPM_QID_INVALID,
+ XPM_QID_CLOCK_GET_NAME,
+ XPM_QID_CLOCK_GET_TOPOLOGY,
+ XPM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
+ XPM_QID_CLOCK_GET_MUXSOURCES,
+ XPM_QID_CLOCK_GET_ATTRIBUTES,
+ XPM_QID_PINCTRL_GET_NUM_PINS,
+ XPM_QID_PINCTRL_GET_NUM_FUNCTIONS,
+ XPM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+ XPM_QID_PINCTRL_GET_FUNCTION_NAME,
+ XPM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+ XPM_QID_PINCTRL_GET_PIN_GROUPS,
+ XPM_QID_CLOCK_GET_NUM_CLOCKS,
+ XPM_QID_CLOCK_GET_MAX_DIVISOR,
+ XPM_QID_PLD_GET_PARENT,
+};
+#endif /* PM_DEFS_H */
diff --git a/plat/xilinx/versal/pm_service/pm_node.h b/plat/xilinx/versal/pm_service/pm_node.h
new file mode 100644
index 0000000..1b82ec7
--- /dev/null
+++ b/plat/xilinx/versal/pm_service/pm_node.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Versal PM nodes enums and defines */
+
+#ifndef PM_NODE_H
+#define PM_NODE_H
+
+/*********************************************************************
+ * Macro definitions
+ ********************************************************************/
+
+#define NODE_CLASS_SHIFT 26U
+#define NODE_SUBCLASS_SHIFT 20U
+#define NODE_TYPE_SHIFT 14U
+#define NODE_INDEX_SHIFT 0U
+#define NODE_CLASS_MASK_BITS 0x3F
+#define NODE_SUBCLASS_MASK_BITS 0x3F
+#define NODE_TYPE_MASK_BITS 0x3F
+#define NODE_INDEX_MASK_BITS 0x3FFF
+#define NODE_CLASS_MASK (NODE_CLASS_MASK_BITS << NODE_CLASS_SHIFT)
+#define NODE_SUBCLASS_MASK (NODE_SUBCLASS_MASK_BITS << NODE_SUBCLASS_SHIFT)
+#define NODE_TYPE_MASK (NODE_TYPE_MASK_BITS << NODE_TYPE_SHIFT)
+#define NODE_INDEX_MASK (NODE_INDEX_MASK_BITS << NODE_INDEX_SHIFT)
+
+#define NODEID(CLASS, SUBCLASS, TYPE, INDEX) \
+ ((((CLASS) & NODE_CLASS_MASK_BITS) << NODE_CLASS_SHIFT) | \
+ (((SUBCLASS) & NODE_SUBCLASS_MASK_BITS) << NODE_SUBCLASS_SHIFT) | \
+ (((TYPE) & NODE_TYPE_MASK_BITS) << NODE_TYPE_SHIFT) | \
+ (((INDEX) & NODE_INDEX_MASK_BITS) << NODE_INDEX_SHIFT))
+
+#define NODECLASS(ID) (((ID) & NODE_CLASS_MASK) >> NODE_CLASS_SHIFT)
+#define NODESUBCLASS(ID) (((ID) & NODE_SUBCLASS_MASK) >> \
+ NODE_SUBCLASS_SHIFT)
+#define NODETYPE(ID) (((ID) & NODE_TYPE_MASK) >> NODE_TYPE_SHIFT)
+#define NODEINDEX(ID) (((ID) & NODE_INDEX_MASK) >> NODE_INDEX_SHIFT)
+
+/*********************************************************************
+ * Enum definitions
+ ********************************************************************/
+
+/* Node class types */
+enum pm_node_class {
+ XPM_NODECLASS_MIN,
+
+ XPM_NODECLASS_POWER,
+ XPM_NODECLASS_CLOCK,
+ XPM_NODECLASS_RESET,
+ XPM_NODECLASS_MEMIC,
+ XPM_NODECLASS_STMIC,
+ XPM_NODECLASS_DEVICE,
+
+ XPM_NODECLASS_MAX
+};
+
+enum pm_device_node_subclass {
+ /* Device types */
+ XPM_NODESUBCL_DEV_CORE = 1,
+ XPM_NODESUBCL_DEV_PERIPH,
+ XPM_NODESUBCL_DEV_MEM,
+ XPM_NODESUBCL_DEV_SOC,
+ XPM_NODESUBCL_DEV_MEM_CTRLR,
+ XPM_NODESUBCL_DEV_PHY,
+};
+
+enum pm_device_node_type {
+ /* Device types */
+ XPM_NODETYPE_DEV_CORE_PMC = 1,
+ XPM_NODETYPE_DEV_CORE_PSM,
+ XPM_NODETYPE_DEV_CORE_APU,
+ XPM_NODETYPE_DEV_CORE_RPU,
+ XPM_NODETYPE_DEV_OCM,
+ XPM_NODETYPE_DEV_TCM,
+ XPM_NODETYPE_DEV_L2CACHE,
+ XPM_NODETYPE_DEV_DDR,
+ XPM_NODETYPE_DEV_PERIPH,
+ XPM_NODETYPE_DEV_SOC,
+ XPM_NODETYPE_DEV_GT,
+};
+
+/* Device node Indexes */
+enum pm_device_node_idx {
+ /* Device nodes */
+ XPM_NODEIDX_DEV_MIN,
+
+ /* Processor devices */
+ XPM_NODEIDX_DEV_PMC_PROC,
+ XPM_NODEIDX_DEV_PSM_PROC,
+ XPM_NODEIDX_DEV_ACPU_0,
+ XPM_NODEIDX_DEV_ACPU_1,
+ XPM_NODEIDX_DEV_RPU0_0,
+ XPM_NODEIDX_DEV_RPU0_1,
+
+ /* Memory devices */
+ XPM_NODEIDX_DEV_OCM_0,
+ XPM_NODEIDX_DEV_OCM_1,
+ XPM_NODEIDX_DEV_OCM_2,
+ XPM_NODEIDX_DEV_OCM_3,
+ XPM_NODEIDX_DEV_TCM_0_A,
+ XPM_NODEIDX_DEV_TCM_0_B,
+ XPM_NODEIDX_DEV_TCM_1_A,
+ XPM_NODEIDX_DEV_TCM_1_B,
+ XPM_NODEIDX_DEV_L2_BANK_0,
+ XPM_NODEIDX_DEV_DDR_0,
+ XPM_NODEIDX_DEV_DDR_1,
+ XPM_NODEIDX_DEV_DDR_2,
+ XPM_NODEIDX_DEV_DDR_3,
+ XPM_NODEIDX_DEV_DDR_4,
+ XPM_NODEIDX_DEV_DDR_5,
+ XPM_NODEIDX_DEV_DDR_6,
+ XPM_NODEIDX_DEV_DDR_7,
+
+ /* LPD Peripheral devices */
+ XPM_NODEIDX_DEV_USB_0,
+ XPM_NODEIDX_DEV_GEM_0,
+ XPM_NODEIDX_DEV_GEM_1,
+ XPM_NODEIDX_DEV_SPI_0,
+ XPM_NODEIDX_DEV_SPI_1,
+ XPM_NODEIDX_DEV_I2C_0,
+ XPM_NODEIDX_DEV_I2C_1,
+ XPM_NODEIDX_DEV_CAN_FD_0,
+ XPM_NODEIDX_DEV_CAN_FD_1,
+ XPM_NODEIDX_DEV_UART_0,
+ XPM_NODEIDX_DEV_UART_1,
+ XPM_NODEIDX_DEV_GPIO,
+ XPM_NODEIDX_DEV_TTC_0,
+ XPM_NODEIDX_DEV_TTC_1,
+ XPM_NODEIDX_DEV_TTC_2,
+ XPM_NODEIDX_DEV_TTC_3,
+ XPM_NODEIDX_DEV_SWDT_LPD,
+
+ /* FPD Peripheral devices */
+ XPM_NODEIDX_DEV_SWDT_FPD,
+
+ /* PMC Peripheral devices */
+ XPM_NODEIDX_DEV_OSPI,
+ XPM_NODEIDX_DEV_QSPI,
+ XPM_NODEIDX_DEV_GPIO_PMC,
+ XPM_NODEIDX_DEV_I2C_PMC,
+ XPM_NODEIDX_DEV_SDIO_0,
+ XPM_NODEIDX_DEV_SDIO_1,
+
+ XPM_NODEIDX_DEV_PL_0,
+ XPM_NODEIDX_DEV_PL_1,
+ XPM_NODEIDX_DEV_PL_2,
+ XPM_NODEIDX_DEV_PL_3,
+ XPM_NODEIDX_DEV_RTC,
+ XPM_NODEIDX_DEV_ADMA_0,
+ XPM_NODEIDX_DEV_ADMA_1,
+ XPM_NODEIDX_DEV_ADMA_2,
+ XPM_NODEIDX_DEV_ADMA_3,
+ XPM_NODEIDX_DEV_ADMA_4,
+ XPM_NODEIDX_DEV_ADMA_5,
+ XPM_NODEIDX_DEV_ADMA_6,
+ XPM_NODEIDX_DEV_ADMA_7,
+ XPM_NODEIDX_DEV_IPI_0,
+ XPM_NODEIDX_DEV_IPI_1,
+ XPM_NODEIDX_DEV_IPI_2,
+ XPM_NODEIDX_DEV_IPI_3,
+ XPM_NODEIDX_DEV_IPI_4,
+ XPM_NODEIDX_DEV_IPI_5,
+ XPM_NODEIDX_DEV_IPI_6,
+
+ /* Entire SoC */
+ XPM_NODEIDX_DEV_SOC,
+
+ /* DDR memory controllers */
+ XPM_NODEIDX_DEV_DDRMC_0,
+ XPM_NODEIDX_DEV_DDRMC_1,
+ XPM_NODEIDX_DEV_DDRMC_2,
+ XPM_NODEIDX_DEV_DDRMC_3,
+
+ /* GT devices */
+ XPM_NODEIDX_DEV_GT_0,
+ XPM_NODEIDX_DEV_GT_1,
+ XPM_NODEIDX_DEV_GT_2,
+ XPM_NODEIDX_DEV_GT_3,
+ XPM_NODEIDX_DEV_GT_4,
+ XPM_NODEIDX_DEV_GT_5,
+ XPM_NODEIDX_DEV_GT_6,
+ XPM_NODEIDX_DEV_GT_7,
+ XPM_NODEIDX_DEV_GT_8,
+ XPM_NODEIDX_DEV_GT_9,
+ XPM_NODEIDX_DEV_GT_10,
+
+ XPM_NODEIDX_DEV_MAX
+};
+
+#endif /* PM_NODE_H */
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
new file mode 100644
index 0000000..9eb426a
--- /dev/null
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Top-level SMC handler for Versal power management calls and
+ * IPI setup functions for communication with PMC.
+ */
+
+#include <errno.h>
+#include <plat_private.h>
+#include <stdbool.h>
+#include <common/runtime_svc.h>
+#include <plat/common/platform.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_ipi.h"
+#include <drivers/arm/gicv3.h>
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+
+#define MODE 0x80000000U
+
+#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U
+#define INVALID_SGI 0xFFU
+#define PM_INIT_SUSPEND_CB (30U)
+#define PM_NOTIFY_CB (32U)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
+
+/* pm_up = true - UP, pm_up = false - DOWN */
+static bool pm_up;
+static uint32_t sgi = (uint32_t)INVALID_SGI;
+
+static void notify_os(void)
+{
+ int32_t cpu;
+ uint32_t reg;
+
+ cpu = plat_my_core_pos() + 1U;
+
+ reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT));
+ write_icc_asgi1r_el1(reg);
+}
+
+static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
+ void *cookie)
+{
+ uint32_t payload[4] = {0};
+
+ VERBOSE("Received IPI FIQ from firmware\n");
+
+ (void)plat_ic_acknowledge_interrupt();
+
+ pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
+ switch (payload[0]) {
+ case PM_INIT_SUSPEND_CB:
+ case PM_NOTIFY_CB:
+ if (sgi != INVALID_SGI) {
+ notify_os();
+ }
+ break;
+ default:
+ pm_ipi_irq_clear(primary_proc);
+ WARN("Invalid IPI payload\n");
+ break;
+ }
+
+ /* Clear FIQ */
+ plat_ic_end_of_interrupt(id);
+
+ return 0;
+}
+
+/**
+ * pm_register_sgi() - PM register the IPI interrupt
+ *
+ * @sgi - SGI number to be used for communication.
+ * @reset - Reset to invalid SGI when reset=1.
+ * @return On success, the initialization function must return 0.
+ * Any other return value will cause the framework to ignore
+ * the service
+ *
+ * Update the SGI number to be used.
+ *
+ */
+int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset)
+{
+ if (reset == 1U) {
+ sgi = INVALID_SGI;
+ return 0;
+ }
+
+ if (sgi != INVALID_SGI) {
+ return -EBUSY;
+ }
+
+ if (sgi_num >= GICV3_MAX_SGI_TARGETS) {
+ return -EINVAL;
+ }
+
+ sgi = (uint32_t)sgi_num;
+ return 0;
+}
+
+/**
+ * pm_setup() - PM service setup
+ *
+ * @return On success, the initialization function must return 0.
+ * Any other return value will cause the framework to ignore
+ * the service
+ *
+ * Initialization functions for Versal power management for
+ * communicaton with PMC.
+ *
+ * Called from sip_svc_setup initialization function with the
+ * rt_svc_init signature.
+ */
+int32_t pm_setup(void)
+{
+ int32_t ret = 0;
+
+ pm_ipi_init(primary_proc);
+ pm_up = true;
+
+ /*
+ * Enable IPI IRQ
+ * assume the rich OS is OK to handle callback IRQs now.
+ * Even if we were wrong, it would not enable the IRQ in
+ * the GIC.
+ */
+ pm_ipi_irq_enable(primary_proc);
+
+ ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler);
+ if (ret != 0) {
+ WARN("BL31: registering IPI interrupt failed\n");
+ }
+
+ gicd_write_irouter(gicv3_driver_data->gicd_base, PLAT_VERSAL_IPI_IRQ, MODE);
+ return ret;
+}
+
+/**
+ * eemi_for_compatibility() - EEMI calls handler for deprecated calls
+ *
+ * @return - If EEMI API found then, uintptr_t type address, else 0
+ *
+ * Some EEMI API's use case needs to be changed in Linux driver, so they
+ * can take advantage of common EEMI handler in TF-A. As of now the old
+ * implementation of these APIs are required to maintain backward compatibility
+ * until their use case in linux driver changes.
+ */
+static uintptr_t eemi_for_compatibility(uint32_t api_id, uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+
+ switch (api_id) {
+
+ case PM_IOCTL:
+ {
+ uint32_t value;
+
+ ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], pm_arg[4],
+ &value, security_flag);
+ if (ret == PM_RET_ERROR_NOTSUPPORTED)
+ return (uintptr_t)0;
+
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case PM_QUERY_DATA:
+ {
+ uint32_t data[PAYLOAD_ARG_CNT] = { 0 };
+
+ ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], data, security_flag);
+
+ SMC_RET2(handle, (uint64_t)ret | ((uint64_t)data[0] << 32U),
+ (uint64_t)data[1] | ((uint64_t)data[2] << 32U));
+ }
+
+ case PM_FEATURE_CHECK:
+ {
+ uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+
+ ret = pm_feature_check(pm_arg[0], result, security_flag);
+ SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
+ (uint64_t)result[1] | ((uint64_t)result[2] << 32U));
+ }
+
+ case PM_LOAD_PDI:
+ {
+ ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2],
+ security_flag);
+ SMC_RET1(handle, (uint64_t)ret);
+ }
+
+ default:
+ return (uintptr_t)0;
+ }
+}
+
+/**
+ * eemi_psci_debugfs_handler() - EEMI API invoked from PSCI
+ *
+ * These EEMI APIs performs CPU specific power management tasks.
+ * These EEMI APIs are invoked either from PSCI or from debugfs in kernel.
+ * These calls require CPU specific processing before sending IPI request to
+ * Platform Management Controller. For example enable/disable CPU specific
+ * interrupts. This requires separate handler for these calls and may not be
+ * handled using common eemi handler
+ */
+static uintptr_t eemi_psci_debugfs_handler(uint32_t api_id, uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+
+ switch (api_id) {
+
+ case PM_SELF_SUSPEND:
+ ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case PM_FORCE_POWERDOWN:
+ ret = pm_force_powerdown(pm_arg[0], pm_arg[1], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case PM_REQ_SUSPEND:
+ ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case PM_ABORT_SUSPEND:
+ ret = pm_abort_suspend(pm_arg[0], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case PM_SYSTEM_SHUTDOWN:
+ ret = pm_system_shutdown(pm_arg[0], pm_arg[1], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ default:
+ return (uintptr_t)0;
+ }
+}
+
+/**
+ * TF_A_specific_handler() - SMC handler for TF-A specific functionality
+ *
+ * These EEMI calls performs functionality that does not require
+ * IPI transaction. The handler ends in TF-A and returns requested data to
+ * kernel from TF-A.
+ */
+static uintptr_t TF_A_specific_handler(uint32_t api_id, uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ switch (api_id) {
+
+ case TF_A_PM_REGISTER_SGI:
+ {
+ int32_t ret;
+
+ ret = pm_register_sgi(pm_arg[0], pm_arg[1]);
+ if (ret != 0) {
+ SMC_RET1(handle, (uint32_t)PM_RET_ERROR_ARGS);
+ }
+
+ SMC_RET1(handle, (uint32_t)PM_RET_SUCCESS);
+ }
+
+ case PM_GET_CALLBACK_DATA:
+ {
+ uint32_t result[4] = {0};
+
+ pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
+ SMC_RET2(handle,
+ (uint64_t)result[0] | ((uint64_t)result[1] << 32U),
+ (uint64_t)result[2] | ((uint64_t)result[3] << 32U));
+ }
+
+ case PM_GET_TRUSTZONE_VERSION:
+ SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+ ((uint64_t)TZ_VERSION << 32U));
+
+ default:
+ return (uintptr_t)0;
+ }
+}
+
+/**
+ * eemi_handler() - Prepare EEMI payload and perform IPI transaction
+ *
+ * EEMI - Embedded Energy Management Interface is Xilinx proprietary protocol
+ * to allow communication between power management controller and different
+ * processing clusters.
+ *
+ * This handler prepares EEMI protocol payload received from kernel and performs
+ * IPI transaction.
+ */
+static uintptr_t eemi_handler(uint32_t api_id, uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+ uint32_t buf[PAYLOAD_ARG_CNT] = {0};
+
+ ret = pm_handle_eemi_call(security_flag, api_id, pm_arg[0], pm_arg[1],
+ pm_arg[2], pm_arg[3], pm_arg[4],
+ (uint64_t *)buf);
+ /*
+ * Two IOCTLs, to get clock name and pinctrl name of pm_query_data API
+ * receives 5 words of respoonse from firmware. Currently linux driver can
+ * receive only 4 words from TF-A. So, this needs to be handled separately
+ * than other eemi calls.
+ */
+ if (api_id == PM_QUERY_DATA) {
+ if ((pm_arg[0] == XPM_QID_CLOCK_GET_NAME ||
+ pm_arg[0] == XPM_QID_PINCTRL_GET_FUNCTION_NAME) &&
+ ret == PM_RET_SUCCESS) {
+ SMC_RET2(handle, (uint64_t)buf[0] | ((uint64_t)buf[1] << 32U),
+ (uint64_t)buf[2] | ((uint64_t)buf[3] << 32U));
+ }
+ }
+
+ SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32U),
+ (uint64_t)buf[1] | ((uint64_t)buf[2] << 32U));
+}
+
+/**
+ * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - SMC64 Arguments from kernel
+ * x3 (upper 32-bits) and x4 are Unused
+ * @cookie - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return - Unused
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, const void *cookie, void *handle, uint64_t flags)
+{
+ uintptr_t ret;
+ uint32_t pm_arg[PAYLOAD_ARG_CNT] = {0};
+ uint32_t security_flag = SECURE_FLAG;
+ uint32_t api_id;
+
+ /* Handle case where PM wasn't initialized properly */
+ if (pm_up == false) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ /*
+ * Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as non-secure (1)
+ * if smc called is non secure
+ */
+ if (is_caller_non_secure(flags) != 0) {
+ security_flag = NON_SECURE_FLAG;
+ }
+
+ pm_arg[0] = (uint32_t)x1;
+ pm_arg[1] = (uint32_t)(x1 >> 32U);
+ pm_arg[2] = (uint32_t)x2;
+ pm_arg[3] = (uint32_t)(x2 >> 32U);
+ pm_arg[4] = (uint32_t)x3;
+ (void)(x4);
+ api_id = smc_fid & FUNCID_NUM_MASK;
+
+ ret = eemi_for_compatibility(api_id, pm_arg, handle, security_flag);
+ if (ret != (uintptr_t)0) {
+ return ret;
+ }
+
+ ret = eemi_psci_debugfs_handler(api_id, pm_arg, handle, flags);
+ if (ret != (uintptr_t)0) {
+ return ret;
+ }
+
+ ret = TF_A_specific_handler(api_id, pm_arg, handle, security_flag);
+ if (ret != (uintptr_t)0) {
+ return ret;
+ }
+
+ ret = eemi_handler(api_id, pm_arg, handle, security_flag);
+
+ return ret;
+}
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.h b/plat/xilinx/versal/pm_service/pm_svc_main.h
new file mode 100644
index 0000000..b6e764f
--- /dev/null
+++ b/plat/xilinx/versal/pm_service/pm_svc_main.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_SVC_MAIN_H
+#define PM_SVC_MAIN_H
+
+#include <pm_common.h>
+
+int32_t pm_setup(void);
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, const void *cookie, void *handle,
+ uint64_t flags);
+
+int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset);
+#endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c
new file mode 100644
index 0000000..6f2ff94
--- /dev/null
+++ b/plat/xilinx/versal/sip_svc_setup.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <tools_share/uuid.h>
+
+#include "ipi_mailbox_svc.h"
+#include "pm_svc_main.h"
+
+/* SMC function IDs for SiP Service queries */
+#define VERSAL_SIP_SVC_CALL_COUNT U(0x8200ff00)
+#define VERSAL_SIP_SVC_UID U(0x8200ff01)
+#define VERSAL_SIP_SVC_VERSION U(0x8200ff03)
+
+/* SiP Service Calls version numbers */
+#define SIP_SVC_VERSION_MAJOR U(0)
+#define SIP_SVC_VERSION_MINOR U(1)
+
+/* These macros are used to identify PM calls from the SMC function ID */
+#define PM_FID_MASK 0xf000u
+#define PM_FID_VALUE 0u
+#define IPI_FID_VALUE 0x1000u
+#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
+#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE)
+
+/* SiP Service UUID */
+DEFINE_SVC_UUID2(versal_sip_uuid,
+ 0x2ab9e4ecU, 0x93b9U, 0x11e7U, 0xa0U, 0x19U,
+ 0xdfU, 0xe0U, 0xdbU, 0xadU, 0x0aU, 0xe0U);
+
+/**
+ * sip_svc_setup() - Setup SiP Service
+ *
+ * Invokes PM setup
+ */
+static int32_t sip_svc_setup(void)
+{
+ /* PM implementation as SiP Service */
+ (void)pm_setup();
+
+ return 0;
+}
+
+/**
+ * sip_svc_smc_handler() - Top-level SiP Service SMC handler
+ *
+ * Handler for all SiP SMC calls. Handles standard SIP requests
+ * and calls PM SMC handler if the call is for a PM-API function.
+ */
+uintptr_t sip_svc_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ /* Let PM SMC handler deal with PM-related requests */
+ if (is_pm_fid(smc_fid)) {
+ return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ }
+
+ /* Let IPI SMC handler deal with IPI-related requests */
+ if (is_ipi_fid(smc_fid)) {
+ return ipi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ }
+
+ /* Let PM SMC handler deal with PM-related requests */
+ switch (smc_fid) {
+ case VERSAL_SIP_SVC_CALL_COUNT:
+ /* PM functions + default functions */
+ SMC_RET1(handle, 2);
+
+ case VERSAL_SIP_SVC_UID:
+ SMC_UUID_RET(handle, versal_sip_uuid);
+
+ case VERSAL_SIP_SVC_VERSION:
+ SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR);
+
+ default:
+ WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
+
+/* Register PM Service Calls as runtime service */
+DECLARE_RT_SVC(
+ sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ sip_svc_setup,
+ sip_svc_smc_handler);
diff --git a/plat/xilinx/versal/versal_gicv3.c b/plat/xilinx/versal/versal_gicv3.c
new file mode 100644
index 0000000..d410906
--- /dev/null
+++ b/plat/xilinx/versal/versal_gicv3.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_private.h>
+#include <platform_def.h>
+
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_versal_gic_driver_init
+#pragma weak plat_versal_gic_init
+#pragma weak plat_versal_gic_cpuif_enable
+#pragma weak plat_versal_gic_cpuif_disable
+#pragma weak plat_versal_gic_pcpu_init
+#pragma weak plat_versal_gic_redistif_on
+#pragma weak plat_versal_gic_redistif_off
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const interrupt_prop_t versal_interrupt_props[] = {
+ PLAT_VERSAL_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_VERSAL_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * We save and restore the GICv3 context on system suspend. Allocate the
+ * data in the designated EL3 Secure carve-out memory.
+ */
+static gicv3_redist_ctx_t rdist_ctx __section("versal_el3_tzc_dram");
+static gicv3_dist_ctx_t dist_ctx __section("versal_el3_tzc_dram");
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ * - No CPUs implemented in the system use affinity level 3.
+ */
+static uint32_t versal_gicv3_mpidr_hash(u_register_t mpidr)
+{
+ mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+ return versal_calc_core_pos(mpidr);
+}
+
+static const gicv3_driver_data_t versal_gic_data __unused = {
+ .gicd_base = PLAT_VERSAL_GICD_BASE,
+ .gicr_base = PLAT_VERSAL_GICR_BASE,
+ .interrupt_props = versal_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(versal_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = versal_gicv3_mpidr_hash
+};
+
+void __init plat_versal_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if IMAGE_BL31
+ gicv3_driver_init(&versal_gic_data);
+#endif
+}
+
+/******************************************************************************
+ * Versal common helper to initialize the GIC. Only invoked by BL31
+ *****************************************************************************/
+void __init plat_versal_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_versal_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_versal_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to initialize the per-cpu redistributor interface in
+ * GICv3
+ *****************************************************************************/
+void plat_versal_gic_pcpu_init(void)
+{
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helpers to power GIC redistributor interface
+ *****************************************************************************/
+void plat_versal_gic_redistif_on(void)
+{
+ gicv3_rdistif_on(plat_my_core_pos());
+}
+
+void plat_versal_gic_redistif_off(void)
+{
+ gicv3_rdistif_off(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal common helper to save & restore the GICv3 on resume from system
+ * suspend
+ *****************************************************************************/
+void plat_versal_gic_save(void)
+{
+ /*
+ * If an ITS is available, save its context before
+ * the Redistributor using:
+ * gicv3_its_save_disable(gits_base, &its_ctx[i])
+ * Additionnaly, an implementation-defined sequence may
+ * be required to save the whole ITS state.
+ */
+
+ /*
+ * Save the GIC Redistributors and ITS contexts before the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to save the context of the CPU that is issuing
+ * the SYSTEM SUSPEND call, i.e. the current CPU.
+ */
+ gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+
+ /* Save the GIC Distributor context */
+ gicv3_distif_save(&dist_ctx);
+
+ /*
+ * From here, all the components of the GIC can be safely powered down
+ * as long as there is an alternate way to handle wakeup interrupt
+ * sources.
+ */
+}
+
+void plat_versal_gic_resume(void)
+{
+ /* Restore the GIC Distributor context */
+ gicv3_distif_init_restore(&dist_ctx);
+
+ /*
+ * Restore the GIC Redistributor and ITS contexts after the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to restore the context of the CPU that issued
+ * the SYSTEM SUSPEND call.
+ */
+ gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+
+ /*
+ * If an ITS is available, restore its context after
+ * the Redistributor using:
+ * gicv3_its_restore(gits_base, &its_ctx[i])
+ * An implementation-defined sequence may be required to
+ * restore the whole ITS state. The ITS must also be
+ * re-enabled after this sequence has been executed.
+ */
+}
diff --git a/plat/xilinx/versal/versal_ipi.c b/plat/xilinx/versal/versal_ipi.c
new file mode 100644
index 0000000..f99af82
--- /dev/null
+++ b/plat/xilinx/versal/versal_ipi.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Versal IPI agent registers access management
+ */
+
+#include <errno.h>
+#include <ipi.h>
+#include <plat_ipi.h>
+#include <plat_private.h>
+#include <string.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+/* versal ipi configuration table */
+const static struct ipi_config versal_ipi_table[] = {
+ /* A72 IPI */
+ [IPI_ID_APU] = {
+ .ipi_bit_mask = IPI0_TRIG_BIT,
+ .ipi_reg_base = IPI0_REG_BASE,
+ .secure_only = 0U,
+ },
+
+ /* PMC IPI */
+ [IPI_ID_PMC] = {
+ .ipi_bit_mask = PMC_IPI_TRIG_BIT,
+ .ipi_reg_base = IPI0_REG_BASE,
+ .secure_only = 0U,
+ },
+
+ /* RPU0 IPI */
+ [IPI_ID_RPU0] = {
+ .ipi_bit_mask = IPI1_TRIG_BIT,
+ .ipi_reg_base = IPI1_REG_BASE,
+ .secure_only = 0U,
+ },
+
+ /* RPU1 IPI */
+ [IPI_ID_RPU1] = {
+ .ipi_bit_mask = IPI2_TRIG_BIT,
+ .ipi_reg_base = IPI2_REG_BASE,
+ .secure_only = 0U,
+ },
+
+ /* IPI3 IPI */
+ [IPI_ID_3] = {
+ .ipi_bit_mask = IPI3_TRIG_BIT,
+ .ipi_reg_base = IPI3_REG_BASE,
+ .secure_only = 0U,
+ },
+
+ /* IPI4 IPI */
+ [IPI_ID_4] = {
+ .ipi_bit_mask = IPI4_TRIG_BIT,
+ .ipi_reg_base = IPI4_REG_BASE,
+ .secure_only = 0U,
+ },
+
+ /* IPI5 IPI */
+ [IPI_ID_5] = {
+ .ipi_bit_mask = IPI5_TRIG_BIT,
+ .ipi_reg_base = IPI5_REG_BASE,
+ .secure_only = 0U,
+ },
+};
+
+/* versal_ipi_config_table_init() - Initialize versal IPI configuration data
+ *
+ * @ipi_config_table - IPI configuration table
+ * @ipi_total - Total number of IPI available
+ *
+ */
+void versal_ipi_config_table_init(void)
+{
+ ipi_config_table_init(versal_ipi_table, ARRAY_SIZE(versal_ipi_table));
+}
diff --git a/plat/xilinx/versal_net/aarch64/versal_net_common.c b/plat/xilinx/versal_net/aarch64/versal_net_common.c
new file mode 100644
index 0000000..c78b5d0
--- /dev/null
+++ b/plat/xilinx/versal_net/aarch64/versal_net_common.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+#include <plat_ipi.h>
+
+#include <plat_private.h>
+#include <versal_net_def.h>
+
+uint32_t platform_id, platform_version;
+
+/*
+ * Table of regions to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+const mmap_region_t plat_versal_net_mmap[] = {
+ MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(IPI_BASE, IPI_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ { 0 }
+};
+
+const mmap_region_t *plat_versal_net_get_mmap(void)
+{
+ return plat_versal_net_mmap;
+}
+
+/* For saving cpu clock for certain platform */
+uint32_t cpu_clock;
+
+char *board_name_decode(void)
+{
+ switch (platform_id) {
+ case VERSAL_NET_SPP:
+ return "IPP";
+ case VERSAL_NET_EMU:
+ return "EMU";
+ case VERSAL_NET_SILICON:
+ return "Silicon";
+ case VERSAL_NET_QEMU:
+ return "QEMU";
+ default:
+ return "Unknown";
+ }
+}
+
+void board_detection(void)
+{
+ uint32_t version;
+
+ version = mmio_read_32(PMC_TAP_VERSION);
+ platform_id = FIELD_GET(PLATFORM_MASK, version);
+ platform_version = FIELD_GET(PLATFORM_VERSION_MASK, version);
+
+ if (platform_id == VERSAL_NET_QEMU_COSIM) {
+ platform_id = VERSAL_NET_QEMU;
+ }
+
+ if ((platform_id == VERSAL_NET_SPP) ||
+ (platform_id == VERSAL_NET_EMU) ||
+ (platform_id == VERSAL_NET_QEMU)) {
+ /*
+ * 9 is diff for
+ * 0 means 0.9 version
+ * 1 means 1.0 version
+ * 2 means 1.1 version
+ * etc,
+ */
+ platform_version += 9U;
+ }
+
+ /* Make sure that console is setup to see this message */
+ VERBOSE("Platform id: %d version: %d.%d\n", platform_id,
+ platform_version / 10U, platform_version % 10U);
+}
+
+void versal_net_config_setup(void)
+{
+ uint32_t val;
+ uintptr_t crl_base, iou_scntrs_base, psx_base;
+
+ crl_base = VERSAL_NET_CRL;
+ iou_scntrs_base = VERSAL_NET_IOU_SCNTRS;
+ psx_base = PSX_CRF;
+
+ /* Reset for system timestamp generator in FPX */
+ mmio_write_32(psx_base + PSX_CRF_RST_TIMESTAMP_OFFSET, 0);
+
+ /* Global timer init - Program time stamp reference clk */
+ val = mmio_read_32(crl_base + VERSAL_NET_CRL_TIMESTAMP_REF_CTRL_OFFSET);
+ val |= VERSAL_NET_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
+ mmio_write_32(crl_base + VERSAL_NET_CRL_TIMESTAMP_REF_CTRL_OFFSET, val);
+
+ /* Clear reset of timestamp reg */
+ mmio_write_32(crl_base + VERSAL_NET_CRL_RST_TIMESTAMP_OFFSET, 0);
+
+ /* Program freq register in System counter and enable system counter. */
+ mmio_write_32(iou_scntrs_base + VERSAL_NET_IOU_SCNTRS_BASE_FREQ_OFFSET,
+ cpu_clock);
+ mmio_write_32(iou_scntrs_base + VERSAL_NET_IOU_SCNTRS_COUNTER_CONTROL_REG_OFFSET,
+ VERSAL_NET_IOU_SCNTRS_CONTROL_EN);
+
+ generic_delay_timer_init();
+
+#if (TFA_NO_PM == 0)
+ /* Configure IPI data for versal_net */
+ versal_net_ipi_config_table_init();
+#endif
+}
+
+uint32_t plat_get_syscnt_freq2(void)
+{
+ return cpu_clock;
+}
diff --git a/plat/xilinx/versal_net/aarch64/versal_net_helpers.S b/plat/xilinx/versal_net/aarch64/versal_net_helpers.S
new file mode 100644
index 0000000..48082a6
--- /dev/null
+++ b/plat/xilinx/versal_net/aarch64/versal_net_helpers.S
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/gicv3.h>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_is_my_cpu_primary
+ .globl platform_mem_init
+ .globl plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * TODO: Should we read the PSYS register to make sure
+ * that the request has gone through.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ mrs x0, mpidr_el1
+
+ /*
+ * There is no sane reason to come out of this wfi. This
+ * cpu will be powered on and reset by the cpu_on pm api
+ */
+ dsb sy
+ bl plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+ mov x9, x30
+ bl plat_my_core_pos
+ cmp x0, #VERSAL_NET_PRIMARY_CPU
+ cset x0, eq
+ ret x9
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the plat_core_pos_by_mpidr()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b plat_core_pos_by_mpidr
+endfunc plat_my_core_pos
+
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on Versal NET
+ * platform. The Secure RAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
+
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0, x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+/* mov_imm x0, PLAT_VERSAL_NET_CRASH_UART_BASE
+ mov_imm x1, PLAT_VERSAL_NET_CRASH_UART_CLK_IN_HZ
+ mov_imm x2, VERSAL_NET_CONSOLE_BAUDRATE
+ b console_pl011_core_init */
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, PLAT_VERSAL_NET_CRASH_UART_BASE
+ b console_pl011_core_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : void.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x0, PLAT_VERSAL_NET_CRASH_UART_BASE
+ b console_pl011_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/xilinx/versal_net/bl31_versal_net_setup.c b/plat/xilinx/versal_net/bl31_versal_net_setup.c
new file mode 100644
index 0000000..c9942d6
--- /dev/null
+++ b/plat/xilinx/versal_net/bl31_versal_net_setup.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+#include <plat_arm.h>
+
+#include <plat_private.h>
+#include <plat_startup.h>
+#include <versal_net_def.h>
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static console_t versal_net_runtime_console;
+
+/*
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ */
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ assert(sec_state_is_valid(type));
+
+ if (type == NON_SECURE) {
+ return &bl33_image_ep_info;
+ }
+
+ return &bl32_image_ep_info;
+}
+
+/*
+ * Set the build time defaults,if we can't find any config data.
+ */
+static inline void bl31_set_default_config(void)
+{
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+}
+
+/*
+ * Perform any BL31 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ */
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ uint32_t uart_clock;
+ int32_t rc;
+
+ board_detection();
+
+ switch (platform_id) {
+ case VERSAL_NET_SPP:
+ cpu_clock = 1000000;
+ uart_clock = 1000000;
+ break;
+ case VERSAL_NET_EMU:
+ cpu_clock = 3660000;
+ uart_clock = 25000000;
+ break;
+ case VERSAL_NET_QEMU:
+ /* Random values now */
+ cpu_clock = 100000000;
+ uart_clock = 25000000;
+ break;
+ case VERSAL_NET_SILICON:
+ cpu_clock = 100000000;
+ uart_clock = 100000000;
+ break;
+ default:
+ panic();
+ }
+
+ /* Initialize the console to provide early debug support */
+ rc = console_pl011_register(VERSAL_NET_UART_BASE, uart_clock,
+ VERSAL_NET_UART_BAUDRATE,
+ &versal_net_runtime_console);
+ if (rc == 0) {
+ panic();
+ }
+
+ console_set_scope(&versal_net_runtime_console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME);
+
+ NOTICE("TF-A running on Xilinx %s %d.%d\n", board_name_decode(),
+ platform_version / 10U, platform_version % 10U);
+
+ /* Initialize the platform config for future decision making */
+ versal_net_config_setup();
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(arg0 == 0U);
+ assert(arg1 == 0U);
+
+ /*
+ * Do initial security configuration to allow DRAM/device access. On
+ * Base VERSAL_NET only DRAM security is programmable (via TrustZone), but
+ * other platforms might have more programmable security devices
+ * present.
+ */
+
+ /* Populate common information for BL32 and BL33 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ bl31_set_default_config();
+
+ NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
+ NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
+}
+
+static versal_intr_info_type_el3_t type_el3_interrupt_table[MAX_INTR_EL3];
+
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
+{
+ static uint32_t index;
+ uint32_t i;
+
+ /* Validate 'handler' and 'id' parameters */
+ if (handler == NULL || index >= MAX_INTR_EL3) {
+ return -EINVAL;
+ }
+
+ /* Check if a handler has already been registered */
+ for (i = 0; i < index; i++) {
+ if (id == type_el3_interrupt_table[i].id) {
+ return -EALREADY;
+ }
+ }
+
+ type_el3_interrupt_table[index].id = id;
+ type_el3_interrupt_table[index].handler = handler;
+
+ index++;
+
+ return 0;
+}
+
+static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint32_t intr_id;
+ uint32_t i;
+ interrupt_type_handler_t handler = NULL;
+
+ intr_id = plat_ic_get_pending_interrupt_id();
+
+ for (i = 0; i < MAX_INTR_EL3; i++) {
+ if (intr_id == type_el3_interrupt_table[i].id) {
+ handler = type_el3_interrupt_table[i].handler;
+ }
+ }
+
+ if (handler != NULL) {
+ handler(intr_id, flags, handle, cookie);
+ }
+
+ return 0;
+}
+
+void bl31_platform_setup(void)
+{
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_versal_net_gic_driver_init();
+ plat_versal_net_gic_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+ uint64_t flags = 0;
+ int32_t rc;
+
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_EL3,
+ rdo_el3_interrupt_handler, flags);
+ if (rc != 0) {
+ panic();
+ }
+}
+
+/*
+ * Perform the very early platform specific architectural setup here.
+ */
+void bl31_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_versal_net_get_mmap());
+ enable_mmu(0);
+}
diff --git a/plat/xilinx/versal_net/include/plat_ipi.h b/plat/xilinx/versal_net/include/plat_ipi.h
new file mode 100644
index 0000000..5255f8f
--- /dev/null
+++ b/plat/xilinx/versal_net/include/plat_ipi.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Versal IPI management enums and defines */
+
+#ifndef PLAT_IPI_H
+#define PLAT_IPI_H
+
+#include <stdint.h>
+
+#include <ipi.h>
+
+/*********************************************************************
+ * IPI agent IDs macros
+ ********************************************************************/
+#define IPI_ID_PMC 1U
+#define IPI_ID_APU 2U
+#define IPI_ID_RPU0 3U
+#define IPI_ID_RPU1 4U
+#define IPI_ID_3 5U
+#define IPI_ID_4 6U
+#define IPI_ID_5 7U
+#define IPI_ID_MAX 8U
+
+/*********************************************************************
+ * IPI message buffers
+ ********************************************************************/
+#define IPI_BUFFER_BASEADDR (0xEB3F0000U)
+
+#define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U)
+#define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200U)
+
+#define IPI_BUFFER_TARGET_APU_OFFSET 0x80U
+#define IPI_BUFFER_TARGET_PMC_OFFSET 0x40U
+
+#define IPI_BUFFER_LOCAL_BASE IPI_BUFFER_APU_BASE
+#define IPI_BUFFER_REMOTE_BASE IPI_BUFFER_PMC_BASE
+
+#define IPI_BUFFER_TARGET_LOCAL_OFFSET IPI_BUFFER_TARGET_APU_OFFSET
+#define IPI_BUFFER_TARGET_REMOTE_OFFSET IPI_BUFFER_TARGET_PMC_OFFSET
+
+#define IPI_BUFFER_MAX_WORDS 8
+
+#define IPI_BUFFER_REQ_OFFSET 0x0U
+#define IPI_BUFFER_RESP_OFFSET 0x20U
+
+/*********************************************************************
+ * Platform specific IPI API declarations
+ ********************************************************************/
+
+/* Configure IPI table for versal_net */
+void versal_net_ipi_config_table_init(void);
+
+#endif /* PLAT_IPI_H */
diff --git a/plat/xilinx/versal_net/include/plat_macros.S b/plat/xilinx/versal_net/include/plat_macros.S
new file mode 100644
index 0000000..fb108b6
--- /dev/null
+++ b/plat/xilinx/versal_net/include/plat_macros.S
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+
+#include "../include/platform_def.h"
+
+.section .rodata.gic_reg_name, "aS"
+/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
+gicc_regs:
+ .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+
+/* Applicable only to GICv3 with SRE enabled */
+icc_regs:
+ .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
+
+/* Registers common to both GICv2 and GICv3 */
+gicd_pend_reg:
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
+newline:
+ .asciz "\n"
+spacer:
+ .asciz ":\t\t0x"
+
+ /* ---------------------------------------------
+ * The below utility macro prints out relevant GIC
+ * registers whenever an unhandled exception is
+ * taken in BL31 on Versal NET platform.
+ * Expects: GICD base in x16, GICC base in x17
+ * Clobbers: x0 - x10, sp
+ * ---------------------------------------------
+ */
+ .macro versal_net_print_gic_regs
+ /* Check for GICv3 system register access */
+ mrs x7, id_aa64pfr0_el1
+ ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
+ cmp x7, #1
+ b.ne print_gicv2
+
+ /* Check for SRE enable */
+ mrs x8, ICC_SRE_EL3
+ tst x8, #ICC_SRE_SRE_BIT
+ b.eq print_gicv2
+
+ /* Load the icc reg list to x6 */
+ adr x6, icc_regs
+ /* Load the icc regs to gp regs used by str_in_crash_buf_print */
+ mrs x8, ICC_HPPIR0_EL1
+ mrs x9, ICC_HPPIR1_EL1
+ mrs x10, ICC_CTLR_EL3
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+ b print_gic_common
+
+print_gicv2:
+ /* Load the gicc reg list to x6 */
+ adr x6, gicc_regs
+ /* Load the gicc regs to gp regs used by str_in_crash_buf_print */
+ ldr w8, [x17, #GICC_HPPIR]
+ ldr w9, [x17, #GICC_AHPPIR]
+ ldr w10, [x17, #GICC_CTLR]
+ /* Store to the crash buf and print to console */
+ bl str_in_crash_buf_print
+
+print_gic_common:
+ /* Print the GICD_ISPENDR regs */
+ add x7, x16, #GICD_ISPENDR
+ adr x4, gicd_pend_reg
+ bl asm_print_str
+gicd_ispendr_loop:
+ sub x4, x7, x16
+ cmp x4, #0x280
+ b.eq exit_print_gic_regs
+ bl asm_print_hex
+
+ adr x4, spacer
+ bl asm_print_str
+
+ ldr x4, [x7], #8
+ bl asm_print_hex
+
+ adr x4, newline
+ bl asm_print_str
+ b gicd_ispendr_loop
+exit_print_gic_regs:
+ .endm
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ /*
+ * Empty for now to handle more platforms variant.
+ * Uncomment it when versions are stable
+ */
+ /*
+ mov_imm x17, PLAT_VERSAL_NET_GICD_BASE
+ mov_imm x16, PLAT_VERSAL_NET_GICR_BASE
+ versal_net_print_gic_regs
+ */
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/xilinx/versal_net/include/plat_pm_common.h b/plat/xilinx/versal_net/include/plat_pm_common.h
new file mode 100644
index 0000000..ad7b40f
--- /dev/null
+++ b/plat/xilinx/versal_net/include/plat_pm_common.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Contains platform specific definitions of commonly used macros data types
+ * for PU Power Management. This file should be common for all PU's.
+ */
+
+#ifndef PLAT_PM_COMMON_H
+#define PLAT_PM_COMMON_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#include "pm_defs.h"
+
+#define NON_SECURE_FLAG 1U
+#define SECURE_FLAG 0U
+
+#endif /* PLAT_PM_COMMON_H */
diff --git a/plat/xilinx/versal_net/include/plat_private.h b/plat/xilinx/versal_net/include/plat_private.h
new file mode 100644
index 0000000..6a3bc19
--- /dev/null
+++ b/plat/xilinx/versal_net/include/plat_private.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+#include <bl31/interrupt_mgmt.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+typedef struct versal_intr_info_type_el3 {
+ uint32_t id;
+ interrupt_type_handler_t handler;
+} versal_intr_info_type_el3_t;
+
+void versal_net_config_setup(void);
+
+const mmap_region_t *plat_versal_net_get_mmap(void);
+
+void plat_versal_net_gic_driver_init(void);
+void plat_versal_net_gic_init(void);
+void plat_versal_net_gic_cpuif_enable(void);
+void plat_versal_net_gic_cpuif_disable(void);
+void plat_versal_net_gic_pcpu_init(void);
+void plat_versal_net_gic_save(void);
+void plat_versal_net_gic_resume(void);
+void plat_versal_net_gic_redistif_on(void);
+void plat_versal_net_gic_redistif_off(void);
+
+extern uint32_t cpu_clock, platform_id, platform_version;
+void board_detection(void);
+char *board_name_decode(void);
+uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle, uint64_t flags);
+int32_t sip_svc_setup_init(void);
+/*
+ * Register handler to specific GIC entrance
+ * for INTR_TYPE_EL3 type of interrupt
+ */
+int request_intr_type_el3(uint32_t irq, interrupt_type_handler_t fiq_handler);
+
+#define PM_GET_CHIPID (24U)
+#define IOCTL_OSPI_MUX_SELECT (21U)
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/xilinx/versal_net/include/platform_def.h b/plat/xilinx/versal_net/include/platform_def.h
new file mode 100644
index 0000000..696771f
--- /dev/null
+++ b/plat/xilinx/versal_net/include/platform_def.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include "versal_net_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE U(0x440)
+
+#define PLATFORM_CLUSTER_COUNT U(4)
+#define PLATFORM_CORE_COUNT_PER_CLUSTER U(4) /* 4 CPUs per cluster */
+
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * PLATFORM_CORE_COUNT_PER_CLUSTER)
+
+#define PLAT_MAX_PWR_LVL U(2)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#ifndef VERSAL_NET_ATF_MEM_BASE
+# define BL31_BASE U(0xBBF00000)
+# define BL31_LIMIT U(0xBBFFFFFF)
+#else
+# define BL31_BASE U(VERSAL_NET_ATF_MEM_BASE)
+# define BL31_LIMIT U(VERSAL_NET_ATF_MEM_BASE + VERSAL_NET_ATF_MEM_SIZE - 1)
+# ifdef VERSAL_NET_ATF_MEM_PROGBITS_SIZE
+# define BL31_PROGBITS_LIMIT U(VERSAL_NET_ATF_MEM_BASE + \
+ VERSAL_NET_ATF_MEM_PROGBITS_SIZE - 1)
+# endif
+#endif
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#ifndef VERSAL_NET_BL32_MEM_BASE
+# define BL32_BASE U(0x60000000)
+# define BL32_LIMIT U(0x7FFFFFFF)
+#else
+# define BL32_BASE U(VERSAL_NET_BL32_MEM_BASE)
+# define BL32_LIMIT U(VERSAL_NET_BL32_MEM_BASE + VERSAL_NET_BL32_MEM_SIZE - 1)
+#endif
+
+/*******************************************************************************
+ * BL33 specific defines.
+ ******************************************************************************/
+#ifndef PRELOADED_BL33_BASE
+# define PLAT_ARM_NS_IMAGE_BASE U(0x8000000)
+#else
+# define PLAT_ARM_NS_IMAGE_BASE U(PRELOADED_BL33_BASE)
+#endif
+
+/*******************************************************************************
+ * TSP specific defines.
+ ******************************************************************************/
+#define TSP_SEC_MEM_BASE BL32_BASE
+#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1U)
+
+/* ID of the secure physical generic timer interrupt used by the TSP */
+#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_DDR_LOWMEM_MAX U(0x80000000)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32U)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32U)
+#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX)
+#define MAX_MMAP_REGIONS U(10)
+#else
+#define MAX_MMAP_REGIONS U(9)
+#endif
+
+#define MAX_XLAT_TABLES U(8)
+
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#define PLAT_VERSAL_NET_GICD_BASE U(0xE2000000)
+#define PLAT_VERSAL_NET_GICR_BASE U(0xE2060000)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_VERSAL_IPI_IRQ 62
+
+#define PLAT_VERSAL_NET_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(VERSAL_NET_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL)
+
+#define PLAT_VERSAL_NET_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/xilinx/versal_net/include/versal_net_def.h b/plat/xilinx/versal_net/include/versal_net_def.h
new file mode 100644
index 0000000..8cb5bf3
--- /dev/null
+++ b/plat/xilinx/versal_net/include/versal_net_def.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VERSAL_NET_DEF_H
+#define VERSAL_NET_DEF_H
+
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+
+#define MAX_INTR_EL3 2
+/* This part is taken from U-Boot project under GPL that's why dual license above */
+#define __bf_shf(x) (__builtin_ffsll(x) - 1U)
+#define FIELD_GET(_mask, _reg) \
+ ({ \
+ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
+ })
+
+/* List all consoles */
+#define VERSAL_NET_CONSOLE_ID_pl011 U(1)
+#define VERSAL_NET_CONSOLE_ID_pl011_0 U(1)
+#define VERSAL_NET_CONSOLE_ID_pl011_1 U(2)
+
+#define VERSAL_NET_CONSOLE_IS(con) (VERSAL_NET_CONSOLE_ID_ ## con == VERSAL_NET_CONSOLE)
+
+/* List all platforms */
+#define VERSAL_NET_SILICON U(0)
+#define VERSAL_NET_SPP U(1)
+#define VERSAL_NET_EMU U(2)
+#define VERSAL_NET_QEMU U(3)
+#define VERSAL_NET_QEMU_COSIM U(7)
+
+/* For platform detection */
+#define PMC_TAP U(0xF11A0000)
+#define PMC_TAP_VERSION (PMC_TAP + 0x4U)
+# define PLATFORM_MASK GENMASK(27U, 24U)
+# define PLATFORM_VERSION_MASK GENMASK(31U, 28U)
+
+/* Global timer reset */
+#define PSX_CRF U(0xEC200000)
+#define ACPU0_CLK_CTRL U(0x10C)
+#define ACPU_CLK_CTRL_CLKACT BIT(25)
+
+#define RST_APU0_OFFSET U(0x300)
+#define RST_APU_COLD_RESET BIT(0)
+#define RST_APU_WARN_RESET BIT(4)
+#define RST_APU_CLUSTER_COLD_RESET BIT(8)
+#define RST_APU_CLUSTER_WARM_RESET BIT(9)
+
+#define PSX_CRF_RST_TIMESTAMP_OFFSET U(0x33C)
+
+#define APU_PCLI U(0xECB10000)
+#define APU_PCLI_CPU_STEP U(0x30)
+#define APU_PCLI_CLUSTER_CPU_STEP (4U * APU_PCLI_CPU_STEP)
+#define APU_PCLI_CLUSTER_OFFSET U(0x8000)
+#define APU_PCLI_CLUSTER_STEP U(0x1000)
+#define PCLI_PREQ_OFFSET U(0x4)
+#define PREQ_CHANGE_REQUEST BIT(0)
+#define PCLI_PSTATE_OFFSET U(0x8)
+#define PCLI_PSTATE_VAL_SET U(0x48)
+#define PCLI_PSTATE_VAL_CLEAR U(0x38)
+
+/* Firmware Image Package */
+#define VERSAL_NET_PRIMARY_CPU U(0)
+
+#define CORE_0_IEN_POWER_OFFSET (0x00000018U)
+#define APU_PCIL_CORE_X_IEN_POWER_REG(cpu_id) (APU_PCLI + (CORE_0_IEN_POWER_OFFSET + \
+ (0x30 * cpu_id)))
+#define APU_PCIL_CORE_X_IEN_POWER_MASK (0x00000001U)
+#define CORE_0_IDS_POWER_OFFSET (0x0000001CU)
+#define APU_PCIL_CORE_X_IDS_POWER_REG(cpu_id) (APU_PCLI + (CORE_0_IDS_POWER_OFFSET + \
+ (0x30 * cpu_id)))
+#define APU_PCIL_CORE_X_IDS_POWER_MASK (0x00000001U)
+#define CORE_PWRDN_EN_BIT_MASK (0x1U)
+
+/*******************************************************************************
+ * memory map related constants
+ ******************************************************************************/
+/* IPP 1.2/SPP 0.9 mapping */
+#define DEVICE0_BASE U(0xE8000000) /* psx, crl, iou */
+#define DEVICE0_SIZE U(0x08000000)
+#define DEVICE1_BASE U(0xE2000000) /* gic */
+#define DEVICE1_SIZE U(0x00800000)
+#define DEVICE2_BASE U(0xF1000000) /* uart, pmc_tap */
+#define DEVICE2_SIZE U(0x01000000)
+#define CRF_BASE U(0xFD1A0000)
+#define CRF_SIZE U(0x00600000)
+#define IPI_BASE U(0xEB300000)
+#define IPI_SIZE U(0x00100000)
+
+/* CRL */
+#define VERSAL_NET_CRL U(0xEB5E0000)
+#define VERSAL_NET_CRL_TIMESTAMP_REF_CTRL_OFFSET U(0x14C)
+#define VERSAL_NET_CRL_RST_TIMESTAMP_OFFSET U(0x348)
+
+#define VERSAL_NET_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1U << 25U)
+
+/* IOU SCNTRS */
+#define VERSAL_NET_IOU_SCNTRS U(0xEC920000)
+#define VERSAL_NET_IOU_SCNTRS_COUNTER_CONTROL_REG_OFFSET U(0)
+#define VERSAL_NET_IOU_SCNTRS_BASE_FREQ_OFFSET U(0x20)
+
+#define VERSAL_NET_IOU_SCNTRS_CONTROL_EN U(1)
+
+#define APU_CLUSTER0 U(0xECC00000)
+#define APU_RVBAR_L_0 U(0x40)
+#define APU_RVBAR_H_0 U(0x44)
+#define APU_CLUSTER_STEP U(0x100000)
+
+#define SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL U(0xF1060504)
+
+/*******************************************************************************
+ * IRQ constants
+ ******************************************************************************/
+#define VERSAL_NET_IRQ_SEC_PHY_TIMER U(29)
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define VERSAL_NET_UART0_BASE U(0xF1920000)
+#define VERSAL_NET_UART_BAUDRATE 115200
+
+#define VERSAL_NET_UART_BASE VERSAL_NET_UART0_BASE
+
+#define PLAT_VERSAL_NET_CRASH_UART_BASE VERSAL_NET_UART_BASE
+#define PLAT_VERSAL_NET_CRASH_UART_CLK_IN_HZ VERSAL_NET_UART_CLOCK
+#define VERSAL_NET_CONSOLE_BAUDRATE VERSAL_NET_UART_BAUDRATE
+
+/*******************************************************************************
+ * IPI registers and bitfields
+ ******************************************************************************/
+#define IPI0_REG_BASE (0xEB330000U)
+#define IPI0_TRIG_BIT (1 << 2)
+#define PMC_IPI_TRIG_BIT (1 << 1)
+#define IPI1_REG_BASE (0xEB340000U)
+#define IPI1_TRIG_BIT (1 << 3)
+#define IPI2_REG_BASE (0xEB350000U)
+#define IPI2_TRIG_BIT (1 << 4)
+#define IPI3_REG_BASE (0xEB360000U)
+#define IPI3_TRIG_BIT (1 << 5)
+#define IPI4_REG_BASE (0xEB370000U)
+#define IPI4_TRIG_BIT (1 << 6)
+#define IPI5_REG_BASE (0xEB380000U)
+#define IPI5_TRIG_BIT (1 << 7)
+
+/* Processor core device IDs */
+#define PM_DEV_CLUSTER0_ACPU_0 (0x1810C0AFU)
+#define PM_DEV_CLUSTER0_ACPU_1 (0x1810C0B0U)
+#define PM_DEV_CLUSTER0_ACPU_2 (0x1810C0B1U)
+#define PM_DEV_CLUSTER0_ACPU_3 (0x1810C0B2U)
+
+#define PM_DEV_CLUSTER1_ACPU_0 (0x1810C0B3U)
+#define PM_DEV_CLUSTER1_ACPU_1 (0x1810C0B4U)
+#define PM_DEV_CLUSTER1_ACPU_2 (0x1810C0B5U)
+#define PM_DEV_CLUSTER1_ACPU_3 (0x1810C0B6U)
+
+#define PM_DEV_CLUSTER2_ACPU_0 (0x1810C0B7U)
+#define PM_DEV_CLUSTER2_ACPU_1 (0x1810C0B8U)
+#define PM_DEV_CLUSTER2_ACPU_2 (0x1810C0B9U)
+#define PM_DEV_CLUSTER2_ACPU_3 (0x1810C0BAU)
+
+#define PM_DEV_CLUSTER3_ACPU_0 (0x1810C0BBU)
+#define PM_DEV_CLUSTER3_ACPU_1 (0x1810C0BCU)
+#define PM_DEV_CLUSTER3_ACPU_2 (0x1810C0BDU)
+#define PM_DEV_CLUSTER3_ACPU_3 (0x1810C0BEU)
+
+#endif /* VERSAL_NET_DEF_H */
diff --git a/plat/xilinx/versal_net/plat_psci.c b/plat/xilinx/versal_net/plat_psci.c
new file mode 100644
index 0000000..c5833a9
--- /dev/null
+++ b/plat/xilinx/versal_net/plat_psci.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <plat_arm.h>
+
+#include <plat_private.h>
+
+#define PM_RET_ERROR_NOFEATURE U(19)
+
+#define PM_IOCTL 34U
+
+static uintptr_t versal_net_sec_entry;
+
+static void zynqmp_cpu_standby(plat_local_state_t cpu_state)
+{
+ dsb();
+ wfi();
+}
+
+static int32_t zynqmp_nopmu_pwr_domain_on(u_register_t mpidr)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+ uint32_t cpu = cpu_id % PLATFORM_CORE_COUNT_PER_CLUSTER;
+ uint32_t cluster = cpu_id / PLATFORM_CORE_COUNT_PER_CLUSTER;
+ uintptr_t apu_cluster_base = 0, apu_pcli_base, apu_pcli_cluster = 0;
+ uintptr_t rst_apu_cluster = PSX_CRF + RST_APU0_OFFSET + (cluster * 0x4);
+
+ VERBOSE("%s: mpidr: 0x%lx, cpuid: %x, cpu: %x, cluster: %x\n",
+ __func__, mpidr, cpu_id, cpu, cluster);
+
+ if (cpu_id == -1) {
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ if (platform_id == VERSAL_NET_SPP && cluster > 1) {
+ panic();
+ }
+
+ if (cluster > 3) {
+ panic();
+ }
+
+ apu_pcli_cluster = APU_PCLI + APU_PCLI_CLUSTER_OFFSET + (cluster * APU_PCLI_CLUSTER_STEP);
+ apu_cluster_base = APU_CLUSTER0 + (cluster * APU_CLUSTER_STEP);
+
+ /* Enable clock */
+ mmio_setbits_32(PSX_CRF + ACPU0_CLK_CTRL + (cluster * 0x4), ACPU_CLK_CTRL_CLKACT);
+
+ /* Enable cluster states */
+ mmio_setbits_32(apu_pcli_cluster + PCLI_PSTATE_OFFSET, PCLI_PSTATE_VAL_SET);
+ mmio_setbits_32(apu_pcli_cluster + PCLI_PREQ_OFFSET, PREQ_CHANGE_REQUEST);
+
+ /* assert core reset */
+ mmio_setbits_32(rst_apu_cluster, ((RST_APU_COLD_RESET|RST_APU_WARN_RESET) << cpu));
+
+ /* program RVBAR */
+ mmio_write_32(apu_cluster_base + APU_RVBAR_L_0 + (cpu << 3),
+ (uint32_t)versal_net_sec_entry);
+ mmio_write_32(apu_cluster_base + APU_RVBAR_H_0 + (cpu << 3),
+ versal_net_sec_entry >> 32);
+
+ /* de-assert core reset */
+ mmio_clrbits_32(rst_apu_cluster, ((RST_APU_COLD_RESET|RST_APU_WARN_RESET) << cpu));
+
+ /* clear cluster resets */
+ mmio_clrbits_32(rst_apu_cluster, RST_APU_CLUSTER_WARM_RESET);
+ mmio_clrbits_32(rst_apu_cluster, RST_APU_CLUSTER_COLD_RESET);
+
+ apu_pcli_base = APU_PCLI + (APU_PCLI_CPU_STEP * cpu) +
+ (APU_PCLI_CLUSTER_CPU_STEP * cluster);
+
+ mmio_write_32(apu_pcli_base + PCLI_PSTATE_OFFSET, PCLI_PSTATE_VAL_CLEAR);
+ mmio_write_32(apu_pcli_base + PCLI_PREQ_OFFSET, PREQ_CHANGE_REQUEST);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_nopmu_pwr_domain_off(const psci_power_state_t *target_state)
+{
+}
+
+static void __dead2 zynqmp_nopmu_system_reset(void)
+{
+ while (1)
+ wfi();
+}
+
+static int32_t zynqmp_validate_ns_entrypoint(uint64_t ns_entrypoint)
+{
+ return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+}
+
+static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ plat_versal_net_gic_pcpu_init();
+ plat_versal_net_gic_cpuif_enable();
+}
+
+static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+}
+
+static void __dead2 zynqmp_system_off(void)
+{
+ while (1)
+ wfi();
+}
+
+static int32_t zynqmp_validate_power_state(uint32_t power_state, psci_power_state_t *req_state)
+{
+ return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
+}
+
+static const struct plat_psci_ops versal_net_nopmc_psci_ops = {
+ .cpu_standby = zynqmp_cpu_standby,
+ .pwr_domain_on = zynqmp_nopmu_pwr_domain_on,
+ .pwr_domain_off = zynqmp_nopmu_pwr_domain_off,
+ .system_reset = zynqmp_nopmu_system_reset,
+ .validate_ns_entrypoint = zynqmp_validate_ns_entrypoint,
+ .pwr_domain_suspend = zynqmp_pwr_domain_suspend,
+ .pwr_domain_on_finish = zynqmp_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = zynqmp_pwr_domain_suspend_finish,
+ .system_off = zynqmp_system_off,
+ .validate_power_state = zynqmp_validate_power_state,
+ .get_sys_suspend_power_state = zynqmp_get_sys_suspend_power_state,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int32_t plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ versal_net_sec_entry = sec_entrypoint;
+
+ VERBOSE("Setting up entry point %lx\n", versal_net_sec_entry);
+
+ *psci_ops = &versal_net_nopmc_psci_ops;
+
+ return 0;
+}
+
+int sip_svc_setup_init(void)
+{
+ return 0;
+}
+
+static int32_t no_pm_ioctl(uint32_t device_id, uint32_t ioctl_id,
+ uint32_t arg1, uint32_t arg2)
+{
+ VERBOSE("%s: ioctl_id: %x, arg1: %x\n", __func__, ioctl_id, arg1);
+ if (ioctl_id == IOCTL_OSPI_MUX_SELECT) {
+ mmio_write_32(SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL, arg1);
+ return 0;
+ }
+ return PM_RET_ERROR_NOFEATURE;
+}
+
+static uint64_t no_pm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+ int32_t ret;
+ uint32_t arg[4], api_id;
+
+ arg[0] = (uint32_t)x1;
+ arg[1] = (uint32_t)(x1 >> 32);
+ arg[2] = (uint32_t)x2;
+ arg[3] = (uint32_t)(x2 >> 32);
+
+ api_id = smc_fid & FUNCID_NUM_MASK;
+ VERBOSE("%s: smc_fid: %x, api_id=0x%x\n", __func__, smc_fid, api_id);
+
+ switch (api_id) {
+ case PM_IOCTL:
+ {
+ ret = no_pm_ioctl(arg[0], arg[1], arg[2], arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+ }
+ case PM_GET_CHIPID:
+ {
+ uint32_t idcode, version;
+
+ idcode = mmio_read_32(PMC_TAP);
+ version = mmio_read_32(PMC_TAP_VERSION);
+ SMC_RET2(handle, ((uint64_t)idcode << 32), version);
+ }
+ default:
+ WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
+
+uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+ void *cookie, void *handle, uint64_t flags)
+{
+ return no_pm_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+}
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
new file mode 100644
index 0000000..8beaa9a
--- /dev/null
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <plat_arm.h>
+
+#include <plat_private.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include <pm_common.h>
+#include "pm_svc_main.h"
+#include "versal_net_def.h"
+
+static uintptr_t versal_net_sec_entry;
+
+static int32_t versal_net_pwr_domain_on(u_register_t mpidr)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+ const struct pm_proc *proc;
+
+ VERBOSE("%s: mpidr: 0x%lx, cpuid: %x\n",
+ __func__, mpidr, cpu_id);
+
+ if (cpu_id == -1) {
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ proc = pm_get_proc(cpu_id);
+ if (!proc) {
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ pm_req_wakeup(proc->node_id, (versal_net_sec_entry & 0xFFFFFFFFU) | 0x1U,
+ versal_net_sec_entry >> 32, 0, 0);
+
+ /* Clear power down request */
+ pm_client_wakeup(proc);
+
+ return PSCI_E_SUCCESS;
+}
+
+/**
+ * versal_net_pwr_domain_off() - This function performs actions to turn off core
+ *
+ * @param target_state Targeted state
+ */
+static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ plat_versal_net_gic_cpuif_disable();
+
+ /*
+ * Send request to PMC to power down the appropriate APU CPU
+ * core.
+ * According to PSCI specification, CPU_off function does not
+ * have resume address and CPU core can only be woken up
+ * invoking CPU_on function, during which resume address will
+ * be set.
+ */
+ pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
+ SECURE_FLAG);
+}
+
+/**
+ * versal_net_system_reset() - This function sends the reset request
+ * to firmware for the system to reset. This function does not return.
+ */
+static void __dead2 versal_net_system_reset(void)
+{
+ /* Send the system reset request to the PMC */
+ pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
+ pm_get_shutdown_scope(), SECURE_FLAG);
+
+ while (1) {
+ wfi();
+ }
+}
+
+/**
+ * versal_net_pwr_domain_suspend() - This function sends request to PMC to suspend
+ * core.
+ *
+ * @param target_state Targeted state
+ */
+static void versal_net_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint32_t state;
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ plat_versal_net_gic_cpuif_disable();
+
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_versal_net_gic_save();
+ }
+
+ state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
+ PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
+
+ /* Send request to PMC to suspend this core */
+ pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_net_sec_entry,
+ SECURE_FLAG);
+
+ /* TODO: disable coherency */
+}
+
+static void versal_net_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ (void)target_state;
+
+ /* Enable the gic cpu interface */
+ plat_versal_net_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_versal_net_gic_cpuif_enable();
+}
+
+/**
+ * versal_net_pwr_domain_suspend_finish() - This function performs actions to finish
+ * suspend procedure.
+ *
+ * @param target_state Targeted state
+ */
+static void versal_net_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+
+ /* Clear the APU power control register for this cpu */
+ pm_client_wakeup(proc);
+
+ /* TODO: enable coherency */
+
+ /* APU was turned off, so restore GIC context */
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_versal_net_gic_resume();
+ }
+
+ plat_versal_net_gic_cpuif_enable();
+}
+
+/**
+ * versal_net_system_off() - This function sends the system off request
+ * to firmware. This function does not return.
+ */
+static void __dead2 versal_net_system_off(void)
+{
+ /* Send the power down request to the PMC */
+ pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN,
+ pm_get_shutdown_scope(), SECURE_FLAG);
+
+ while (1) {
+ wfi();
+ }
+}
+
+/**
+ * versal_net_validate_power_state() - This function ensures that the power state
+ * parameter in request is valid.
+ *
+ * @param power_state Power state of core
+ * @param req_state Requested state
+ *
+ * @return Returns status, either PSCI_E_SUCCESS or reason
+ */
+static int32_t versal_net_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+ int32_t pstate = psci_get_pstate_type(power_state);
+
+ assert(req_state);
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ } else {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+ }
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state)) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/**
+ * versal_net_get_sys_suspend_power_state() - Get power state for system suspend
+ *
+ * @param req_state Requested state
+ */
+static void versal_net_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
+}
+
+static const struct plat_psci_ops versal_net_nopmc_psci_ops = {
+ .pwr_domain_on = versal_net_pwr_domain_on,
+ .pwr_domain_off = versal_net_pwr_domain_off,
+ .pwr_domain_on_finish = versal_net_pwr_domain_on_finish,
+ .pwr_domain_suspend = versal_net_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = versal_net_pwr_domain_suspend_finish,
+ .system_off = versal_net_system_off,
+ .system_reset = versal_net_system_reset,
+ .validate_power_state = versal_net_validate_power_state,
+ .get_sys_suspend_power_state = versal_net_get_sys_suspend_power_state,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int32_t plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ versal_net_sec_entry = sec_entrypoint;
+
+ VERBOSE("Setting up entry point %lx\n", versal_net_sec_entry);
+
+ *psci_ops = &versal_net_nopmc_psci_ops;
+
+ return 0;
+}
+
+int32_t sip_svc_setup_init(void)
+{
+ return pm_setup();
+}
+
+uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+ void *cookie, void *handle, uint64_t flags)
+{
+ return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+}
diff --git a/plat/xilinx/versal_net/plat_topology.c b/plat/xilinx/versal_net/plat_topology.c
new file mode 100644
index 0000000..7f985b0
--- /dev/null
+++ b/plat/xilinx/versal_net/plat_topology.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include <platform_def.h>
+
+static const uint8_t plat_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ 1,
+ /* Number of clusters */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+ /* Number of children for the second cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+ /* Number of children for the third cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+ /* Number of children for the fourth cluster node */
+ PLATFORM_CORE_COUNT_PER_CLUSTER,
+};
+
+const uint8_t *plat_get_power_domain_tree_desc(void)
+{
+ return plat_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ uint32_t cluster_id, cpu_id;
+
+ mpidr &= MPIDR_AFFINITY_MASK;
+
+ cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
+ cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -3;
+ }
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in
+ * one of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) {
+ return -1;
+ }
+
+ return (cpu_id + (cluster_id * PLATFORM_CORE_COUNT_PER_CLUSTER));
+}
diff --git a/plat/xilinx/versal_net/platform.mk b/plat/xilinx/versal_net/platform.mk
new file mode 100644
index 0000000..b3d56bc
--- /dev/null
+++ b/plat/xilinx/versal_net/platform.mk
@@ -0,0 +1,102 @@
+# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
+# Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+PLAT_PATH := plat/xilinx/versal_net
+
+# A78 Erratum for SoC
+ERRATA_A78_AE_1941500 := 1
+ERRATA_A78_AE_1951502 := 1
+ERRATA_A78_AE_2376748 := 1
+ERRATA_A78_AE_2395408 := 1
+
+override PROGRAMMABLE_RESET_ADDRESS := 1
+PSCI_EXTENDED_STATE_ID := 1
+SEPARATE_CODE_AND_RODATA := 1
+override RESET_TO_BL31 := 1
+PL011_GENERIC_UART := 1
+GIC_ENABLE_V4_EXTN := 0
+GICV3_SUPPORT_GIC600 := 1
+TFA_NO_PM := 0
+
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+ifdef TFA_NO_PM
+ $(eval $(call add_define,TFA_NO_PM))
+endif
+
+ifdef VERSAL_NET_ATF_MEM_BASE
+ $(eval $(call add_define,VERSAL_NET_ATF_MEM_BASE))
+
+ ifndef VERSAL_NET_ATF_MEM_SIZE
+ $(error "VERSAL_NET_ATF_BASE defined without VERSAL_NET_ATF_SIZE")
+ endif
+ $(eval $(call add_define,VERSAL_NET_ATF_MEM_SIZE))
+
+ ifdef VERSAL_NET_ATF_MEM_PROGBITS_SIZE
+ $(eval $(call add_define,VERSAL_NET_ATF_MEM_PROGBITS_SIZE))
+ endif
+endif
+
+ifdef VERSAL_NET_BL32_MEM_BASE
+ $(eval $(call add_define,VERSAL_NET_BL32_MEM_BASE))
+
+ ifndef VERSAL_NET_BL32_MEM_SIZE
+ $(error "VERSAL_NET_BL32_BASE defined without VERSAL_NET_BL32_SIZE")
+ endif
+ $(eval $(call add_define,VERSAL_NET_BL32_MEM_SIZE))
+endif
+
+USE_COHERENT_MEM := 0
+HW_ASSISTED_COHERENCY := 1
+
+VERSAL_NET_CONSOLE ?= pl011
+$(eval $(call add_define_val,VERSAL_NET_CONSOLE,VERSAL_NET_CONSOLE_ID_${VERSAL_NET_CONSOLE}))
+
+PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
+ -Iplat/xilinx/common/include/ \
+ -Iplat/xilinx/common/ipi_mailbox_service/ \
+ -I${PLAT_PATH}/include/ \
+ -Iplat/xilinx/versal/pm_service/
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+include lib/libfdt/libfdt.mk
+
+PLAT_BL_COMMON_SOURCES := \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${GICV3_SOURCES} \
+ drivers/arm/pl011/aarch64/pl011_console.S \
+ plat/arm/common/arm_common.c \
+ plat/common/plat_gicv3.c \
+ ${PLAT_PATH}/aarch64/versal_net_helpers.S \
+ ${PLAT_PATH}/aarch64/versal_net_common.c
+
+BL31_SOURCES += drivers/arm/cci/cci.c \
+ lib/cpus/aarch64/cortex_a78_ae.S \
+ lib/cpus/aarch64/cortex_a78.S \
+ plat/common/plat_psci_common.c
+ifeq ($(TFA_NO_PM), 0)
+BL31_SOURCES += plat/xilinx/versal/pm_service/pm_api_sys.c \
+ plat/xilinx/common/pm_service/pm_ipi.c \
+ ${PLAT_PATH}/plat_psci_pm.c \
+ plat/xilinx/versal/pm_service/pm_svc_main.c \
+ ${PLAT_PATH}/pm_service/pm_client.c \
+ ${PLAT_PATH}/versal_net_ipi.c
+else
+BL31_SOURCES += ${PLAT_PATH}/plat_psci.c
+endif
+BL31_SOURCES += plat/xilinx/common/plat_startup.c \
+ plat/xilinx/common/ipi.c \
+ plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \
+ ${PLAT_PATH}/bl31_versal_net_setup.c \
+ ${PLAT_PATH}/plat_topology.c \
+ common/fdt_fixup.c \
+ ${LIBFDT_SRCS} \
+ ${PLAT_PATH}/sip_svc_setup.c \
+ ${PLAT_PATH}/versal_net_gicv3.c \
+ ${XLAT_TABLES_LIB_SRCS}
diff --git a/plat/xilinx/versal_net/pm_service/pm_client.c b/plat/xilinx/versal_net/pm_service/pm_client.c
new file mode 100644
index 0000000..6487324
--- /dev/null
+++ b/plat/xilinx/versal_net/pm_service/pm_client.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * APU specific definition of processors in the subsystem as well as functions
+ * for getting information about and changing state of the APU.
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <plat_ipi.h>
+#include <platform_def.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include <versal_net_def.h>
+
+#define UNDEFINED_CPUID (~0)
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(cpu_pwrctrl_val, S3_0_C15_C2_7)
+DEFINE_BAKERY_LOCK(pm_client_secure_lock);
+
+static const struct pm_ipi apu_ipi = {
+ .local_ipi_id = IPI_ID_APU,
+ .remote_ipi_id = IPI_ID_PMC,
+ .buffer_base = IPI_BUFFER_APU_BASE,
+};
+
+/* Order in pm_procs_all array must match cpu ids */
+static const struct pm_proc pm_procs_all[] = {
+ {
+ .node_id = PM_DEV_CLUSTER0_ACPU_0,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER0_ACPU_1,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER0_ACPU_2,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER0_ACPU_3,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER1_ACPU_0,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER1_ACPU_1,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER1_ACPU_2,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER1_ACPU_3,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER2_ACPU_0,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER2_ACPU_1,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER2_ACPU_2,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER2_ACPU_3,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER3_ACPU_0,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER3_ACPU_1,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER3_ACPU_2,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER3_ACPU_3,
+ .ipi = &apu_ipi,
+ .pwrdn_mask = 0,
+ }
+};
+
+const struct pm_proc *primary_proc = &pm_procs_all[0];
+
+/**
+ * pm_get_proc() - returns pointer to the proc structure
+ * @param cpuid id of the cpu whose proc struct pointer should be returned
+ *
+ * @return pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc(uint32_t cpuid)
+{
+ if (cpuid < ARRAY_SIZE(pm_procs_all)) {
+ return &pm_procs_all[cpuid];
+ }
+
+ NOTICE("ERROR: cpuid: %d proc NULL\n", cpuid);
+ return NULL;
+}
+
+/**
+ * pm_client_suspend() - Client-specific suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required prior to sending suspend request to PMU
+ * Actions taken depend on the state system is suspending to.
+ *
+ * @param proc processor which need to suspend
+ * @param state desired suspend state
+ */
+void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ uintptr_t val;
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* TODO: Set wakeup source */
+
+ val = read_cpu_pwrctrl_val();
+ val |= CORE_PWRDN_EN_BIT_MASK;
+ write_cpu_pwrctrl_val(val);
+
+ isb();
+
+ mmio_write_32(APU_PCIL_CORE_X_IEN_POWER_REG(cpu_id),
+ APU_PCIL_CORE_X_IEN_POWER_MASK);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+/**
+ * pm_get_cpuid() - get the local cpu ID for a global node ID
+ * @param nid node id of the processor
+ *
+ * @return the cpu ID (starting from 0) for the subsystem
+ */
+static uint32_t pm_get_cpuid(uint32_t nid)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+ if (pm_procs_all[i].node_id == nid) {
+ return i;
+ }
+ }
+ return UNDEFINED_CPUID;
+}
+
+/**
+ * pm_client_wakeup() - Client-specific wakeup actions
+ *
+ * This function should contain any PU-specific actions
+ * required for waking up another APU core
+ *
+ * @param proc Processor which need to wakeup
+ */
+void pm_client_wakeup(const struct pm_proc *proc)
+{
+ uint32_t cpuid = pm_get_cpuid(proc->node_id);
+
+ if (cpuid == UNDEFINED_CPUID) {
+ return;
+ }
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* TODO: clear powerdown bit for affected cpu */
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+/**
+ * pm_client_abort_suspend() - Client-specific abort-suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required for aborting a prior suspend request
+ */
+void pm_client_abort_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ uintptr_t val;
+
+ /* Enable interrupts at processor level (for current cpu) */
+ gicv3_cpuif_enable(plat_my_core_pos());
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* Clear powerdown request */
+ val = read_cpu_pwrctrl_val();
+ val &= ~CORE_PWRDN_EN_BIT_MASK;
+ write_cpu_pwrctrl_val(val);
+
+ isb();
+
+ /* Disabled power down interrupt */
+ mmio_write_32(APU_PCIL_CORE_X_IDS_POWER_REG(cpu_id),
+ APU_PCIL_CORE_X_IDS_POWER_MASK);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
diff --git a/plat/xilinx/versal_net/sip_svc_setup.c b/plat/xilinx/versal_net/sip_svc_setup.c
new file mode 100644
index 0000000..0e3940f
--- /dev/null
+++ b/plat/xilinx/versal_net/sip_svc_setup.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <tools_share/uuid.h>
+
+#include "ipi_mailbox_svc.h"
+#include "plat_private.h"
+#include "pm_svc_main.h"
+
+/* SMC function IDs for SiP Service queries */
+#define VERSAL_NET_SIP_SVC_CALL_COUNT (0x8200ff00U)
+#define VERSAL_NET_SIP_SVC_UID (0x8200ff01U)
+#define VERSAL_NET_SIP_SVC_VERSION (0x8200ff03U)
+
+/* SiP Service Calls version numbers */
+#define SIP_SVC_VERSION_MAJOR (0U)
+#define SIP_SVC_VERSION_MINOR (1U)
+
+/* These macros are used to identify PM calls from the SMC function ID */
+#define PM_FID_MASK 0xf000u
+#define PM_FID_VALUE 0u
+#define IPI_FID_VALUE 0x1000u
+#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
+#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE)
+
+/* SiP Service UUID */
+DEFINE_SVC_UUID2(versal_net_sip_uuid,
+ 0x80d4c25a, 0xebaf, 0x11eb, 0x94, 0x68,
+ 0x0b, 0x4e, 0x3b, 0x8f, 0xc3, 0x60);
+
+/**
+ * sip_svc_setup() - Setup SiP Service
+ */
+static int32_t sip_svc_setup(void)
+{
+ return sip_svc_setup_init();
+}
+
+/*
+ * sip_svc_smc_handler() - Top-level SiP Service SMC handler
+ *
+ * Handler for all SiP SMC calls. Handles standard SIP requests
+ * and calls PM SMC handler if the call is for a PM-API function.
+ */
+static uintptr_t sip_svc_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ /* Let PM SMC handler deal with PM-related requests */
+ if (is_pm_fid(smc_fid)) {
+ return smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ }
+
+ /* Let IPI SMC handler deal with IPI-related requests if platform */
+ if (is_ipi_fid(smc_fid)) {
+ return ipi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+ }
+
+ /* Let PM SMC handler deal with PM-related requests */
+ switch (smc_fid) {
+ case VERSAL_NET_SIP_SVC_CALL_COUNT:
+ /* PM functions + default functions */
+ SMC_RET1(handle, 2);
+
+ case VERSAL_NET_SIP_SVC_UID:
+ SMC_UUID_RET(handle, versal_net_sip_uuid);
+
+ case VERSAL_NET_SIP_SVC_VERSION:
+ SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR);
+
+ default:
+ WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
+
+/* Register PM Service Calls as runtime service */
+DECLARE_RT_SVC(
+ sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ sip_svc_setup,
+ sip_svc_smc_handler);
diff --git a/plat/xilinx/versal_net/versal_net_gicv3.c b/plat/xilinx/versal_net/versal_net_gicv3.c
new file mode 100644
index 0000000..b7ac6ab
--- /dev/null
+++ b/plat/xilinx/versal_net/versal_net_gicv3.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include <platform_def.h>
+
+/******************************************************************************
+ * The following functions are defined as weak to allow a platform to override
+ * the way the GICv3 driver is initialised and used.
+ *****************************************************************************/
+#pragma weak plat_versal_net_gic_driver_init
+#pragma weak plat_versal_net_gic_init
+#pragma weak plat_versal_net_gic_cpuif_enable
+#pragma weak plat_versal_net_gic_cpuif_disable
+#pragma weak plat_versal_net_gic_pcpu_init
+#pragma weak plat_versal_net_gic_redistif_on
+#pragma weak plat_versal_net_gic_redistif_off
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static const uintptr_t gicr_base_addrs[2] = {
+ PLAT_VERSAL_NET_GICR_BASE, /* GICR Base address of the primary CPU */
+ 0U /* Zero Termination */
+};
+
+/* List of zero terminated GICR frame addresses which CPUs will probe */
+static const uintptr_t *gicr_frames;
+
+static const interrupt_prop_t versal_net_interrupt_props[] = {
+ PLAT_VERSAL_NET_G1S_IRQ_PROPS(INTR_GROUP1S),
+ PLAT_VERSAL_NET_G0_IRQ_PROPS(INTR_GROUP0)
+};
+
+/*
+ * We save and restore the GICv3 context on system suspend. Allocate the
+ * data in the designated EL3 Secure carve-out memory.
+ */
+static gicv3_redist_ctx_t rdist_ctx __section("versal_net_el3_tzc_dram");
+static gicv3_dist_ctx_t dist_ctx __section("versal_net_el3_tzc_dram");
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ * - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ * - No CPUs implemented in the system use affinity level 3.
+ */
+static uint32_t versal_net_gicv3_mpidr_hash(u_register_t mpidr)
+{
+ mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+ return plat_core_pos_by_mpidr(mpidr);
+}
+
+static const gicv3_driver_data_t versal_net_gic_data __unused = {
+ .gicd_base = PLAT_VERSAL_NET_GICD_BASE,
+ .gicr_base = 0U,
+ .interrupt_props = versal_net_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(versal_net_interrupt_props),
+ .rdistif_num = PLATFORM_CORE_COUNT,
+ .rdistif_base_addrs = rdistif_base_addrs,
+ .mpidr_to_core_pos = versal_net_gicv3_mpidr_hash
+};
+
+void __init plat_versal_net_gic_driver_init(void)
+{
+ /*
+ * The GICv3 driver is initialized in EL3 and does not need
+ * to be initialized again in SEL1. This is because the S-EL1
+ * can use GIC system registers to manage interrupts and does
+ * not need GIC interface base addresses to be configured.
+ */
+#if IMAGE_BL31
+ gicv3_driver_init(&versal_net_gic_data);
+ gicr_frames = gicr_base_addrs;
+
+ if (gicv3_rdistif_probe(gicr_frames[0]) == -1) {
+ ERROR("No GICR base frame found for Primary CPU\n");
+ panic();
+ }
+#endif
+}
+
+/******************************************************************************
+ * Versal NET common helper to initialize the GIC. Only invoked by BL31
+ *****************************************************************************/
+void __init plat_versal_net_gic_init(void)
+{
+ gicv3_distif_init();
+ gicv3_rdistif_init(plat_my_core_pos());
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal NET common helper to enable the GIC CPU interface
+ *****************************************************************************/
+void plat_versal_net_gic_cpuif_enable(void)
+{
+ gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal NET common helper to disable the GIC CPU interface
+ *****************************************************************************/
+void plat_versal_net_gic_cpuif_disable(void)
+{
+ gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal NET common helper to initialize the per-cpu redistributor interface in
+ * GICv3
+ *****************************************************************************/
+void plat_versal_net_gic_pcpu_init(void)
+{
+ int32_t result;
+ const uintptr_t *plat_gicr_frames = gicr_frames;
+
+ do {
+ result = gicv3_rdistif_probe(*plat_gicr_frames);
+
+ /* If the probe is successful, no need to proceed further */
+ if (result == 0) {
+ break;
+ }
+
+ plat_gicr_frames++;
+ } while (*plat_gicr_frames != 0U);
+
+ if (result == -1) {
+ ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
+ panic();
+ }
+
+ gicv3_rdistif_init(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal NET common helpers to power GIC redistributor interface
+ *****************************************************************************/
+void plat_versal_net_gic_redistif_on(void)
+{
+ gicv3_rdistif_on(plat_my_core_pos());
+}
+
+void plat_versal_net_gic_redistif_off(void)
+{
+ gicv3_rdistif_off(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Versal NET common helper to save & restore the GICv3 on resume from system
+ * suspend
+ *****************************************************************************/
+void plat_versal_net_gic_save(void)
+{
+ /*
+ * If an ITS is available, save its context before
+ * the Redistributor using:
+ * gicv3_its_save_disable(gits_base, &its_ctx[i])
+ * Additionnaly, an implementation-defined sequence may
+ * be required to save the whole ITS state.
+ */
+
+ /*
+ * Save the GIC Redistributors and ITS contexts before the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to save the context of the CPU that is issuing
+ * the SYSTEM SUSPEND call, i.e. the current CPU.
+ */
+ gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx);
+
+ /* Save the GIC Distributor context */
+ gicv3_distif_save(&dist_ctx);
+
+ /*
+ * From here, all the components of the GIC can be safely powered down
+ * as long as there is an alternate way to handle wakeup interrupt
+ * sources.
+ */
+}
+
+void plat_versal_net_gic_resume(void)
+{
+ /* Restore the GIC Distributor context */
+ gicv3_distif_init_restore(&dist_ctx);
+
+ /*
+ * Restore the GIC Redistributor and ITS contexts after the
+ * Distributor context. As we only handle SYSTEM SUSPEND API,
+ * we only need to restore the context of the CPU that issued
+ * the SYSTEM SUSPEND call.
+ */
+ gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx);
+
+ /*
+ * If an ITS is available, restore its context after
+ * the Redistributor using:
+ * gicv3_its_restore(gits_base, &its_ctx[i])
+ * An implementation-defined sequence may be required to
+ * restore the whole ITS state. The ITS must also be
+ * re-enabled after this sequence has been executed.
+ */
+}
diff --git a/plat/xilinx/versal_net/versal_net_ipi.c b/plat/xilinx/versal_net/versal_net_ipi.c
new file mode 100644
index 0000000..26ded89
--- /dev/null
+++ b/plat/xilinx/versal_net/versal_net_ipi.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Versal NET IPI agent registers access management
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include <ipi.h>
+#include <plat_ipi.h>
+#include <plat_private.h>
+
+/* versal_net ipi configuration table */
+static const struct ipi_config versal_net_ipi_table[IPI_ID_MAX] = {
+ /* A72 IPI */
+ [IPI_ID_APU] = {
+ .ipi_bit_mask = IPI0_TRIG_BIT,
+ .ipi_reg_base = IPI0_REG_BASE,
+ .secure_only = 0,
+ },
+
+ /* PMC IPI */
+ [IPI_ID_PMC] = {
+ .ipi_bit_mask = PMC_IPI_TRIG_BIT,
+ .ipi_reg_base = IPI0_REG_BASE,
+ .secure_only = 0,
+ },
+
+ /* RPU0 IPI */
+ [IPI_ID_RPU0] = {
+ .ipi_bit_mask = IPI1_TRIG_BIT,
+ .ipi_reg_base = IPI1_REG_BASE,
+ .secure_only = 0,
+ },
+
+ /* RPU1 IPI */
+ [IPI_ID_RPU1] = {
+ .ipi_bit_mask = IPI2_TRIG_BIT,
+ .ipi_reg_base = IPI2_REG_BASE,
+ .secure_only = 0,
+ },
+
+ /* IPI3 IPI */
+ [IPI_ID_3] = {
+ .ipi_bit_mask = IPI3_TRIG_BIT,
+ .ipi_reg_base = IPI3_REG_BASE,
+ .secure_only = 0,
+ },
+
+ /* IPI4 IPI */
+ [IPI_ID_4] = {
+ .ipi_bit_mask = IPI4_TRIG_BIT,
+ .ipi_reg_base = IPI4_REG_BASE,
+ .secure_only = 0,
+ },
+
+ /* IPI5 IPI */
+ [IPI_ID_5] = {
+ .ipi_bit_mask = IPI5_TRIG_BIT,
+ .ipi_reg_base = IPI5_REG_BASE,
+ .secure_only = 0,
+ },
+};
+
+/* versal_net_ipi_config_table_init() - Initialize versal_net IPI configuration data
+ *
+ * @ipi_config_table - IPI configuration table
+ * @ipi_total - Total number of IPI available
+ *
+ */
+void versal_net_ipi_config_table_init(void)
+{
+ ipi_config_table_init(versal_net_ipi_table, ARRAY_SIZE(versal_net_ipi_table));
+}
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
new file mode 100644
index 0000000..3946e9b
--- /dev/null
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+#include <plat_ipi.h>
+#include <plat_private.h>
+#include <plat/common/platform.h>
+
+#include "pm_api_sys.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * This doesn't include TZRAM as the 'mem_layout' argument passed to
+ * configure_mmu_elx() will give the available subset of that,
+ */
+const mmap_region_t plat_arm_mmap[] = {
+ { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
+ { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
+ { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
+ {0}
+};
+
+static uint32_t zynqmp_get_silicon_ver(void)
+{
+ static unsigned int ver;
+
+ if (!ver) {
+ ver = mmio_read_32(ZYNQMP_CSU_BASEADDR +
+ ZYNQMP_CSU_VERSION_OFFSET);
+ ver &= ZYNQMP_SILICON_VER_MASK;
+ ver >>= ZYNQMP_SILICON_VER_SHIFT;
+ }
+
+ return ver;
+}
+
+uint32_t zynqmp_get_uart_clk(void)
+{
+ unsigned int ver = zynqmp_get_silicon_ver();
+
+ if (ver == ZYNQMP_CSU_VERSION_QEMU) {
+ return 133000000;
+ } else {
+ return 100000000;
+ }
+}
+
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
+static const struct {
+ uint32_t id;
+ uint32_t ver;
+ char *name;
+ bool evexists;
+} zynqmp_devices[] = {
+ {
+ .id = 0x10,
+ .name = "XCZU3EG",
+ },
+ {
+ .id = 0x10,
+ .ver = 0x2c,
+ .name = "XCZU3CG",
+ },
+ {
+ .id = 0x11,
+ .name = "XCZU2EG",
+ },
+ {
+ .id = 0x11,
+ .ver = 0x2c,
+ .name = "XCZU2CG",
+ },
+ {
+ .id = 0x20,
+ .name = "XCZU5EV",
+ .evexists = true,
+ },
+ {
+ .id = 0x20,
+ .ver = 0x100,
+ .name = "XCZU5EG",
+ .evexists = true,
+ },
+ {
+ .id = 0x20,
+ .ver = 0x12c,
+ .name = "XCZU5CG",
+ },
+ {
+ .id = 0x21,
+ .name = "XCZU4EV",
+ .evexists = true,
+ },
+ {
+ .id = 0x21,
+ .ver = 0x100,
+ .name = "XCZU4EG",
+ .evexists = true,
+ },
+ {
+ .id = 0x21,
+ .ver = 0x12c,
+ .name = "XCZU4CG",
+ },
+ {
+ .id = 0x30,
+ .name = "XCZU7EV",
+ .evexists = true,
+ },
+ {
+ .id = 0x30,
+ .ver = 0x100,
+ .name = "XCZU7EG",
+ .evexists = true,
+ },
+ {
+ .id = 0x30,
+ .ver = 0x12c,
+ .name = "XCZU7CG",
+ },
+ {
+ .id = 0x38,
+ .name = "XCZU9EG",
+ },
+ {
+ .id = 0x38,
+ .ver = 0x2c,
+ .name = "XCZU9CG",
+ },
+ {
+ .id = 0x39,
+ .name = "XCZU6EG",
+ },
+ {
+ .id = 0x39,
+ .ver = 0x2c,
+ .name = "XCZU6CG",
+ },
+ {
+ .id = 0x40,
+ .name = "XCZU11EG",
+ },
+ {
+ .id = 0x50,
+ .name = "XCZU15EG",
+ },
+ {
+ .id = 0x58,
+ .name = "XCZU19EG",
+ },
+ {
+ .id = 0x59,
+ .name = "XCZU17EG",
+ },
+ {
+ .id = 0x60,
+ .name = "XCZU28DR",
+ },
+ {
+ .id = 0x61,
+ .name = "XCZU21DR",
+ },
+ {
+ .id = 0x62,
+ .name = "XCZU29DR",
+ },
+ {
+ .id = 0x63,
+ .name = "XCZU23DR",
+ },
+ {
+ .id = 0x64,
+ .name = "XCZU27DR",
+ },
+ {
+ .id = 0x65,
+ .name = "XCZU25DR",
+ },
+ {
+ .id = 0x66,
+ .name = "XCZU39DR",
+ },
+ {
+ .id = 0x7d,
+ .name = "XCZU43DR",
+ },
+ {
+ .id = 0x78,
+ .name = "XCZU46DR",
+ },
+ {
+ .id = 0x7f,
+ .name = "XCZU47DR",
+ },
+ {
+ .id = 0x7b,
+ .name = "XCZU48DR",
+ },
+ {
+ .id = 0x7e,
+ .name = "XCZU49DR",
+ },
+};
+
+#define ZYNQMP_PL_STATUS_BIT 9
+#define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT)
+#define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK)
+
+#define SILICON_ID_XCK24 0x4714093U
+#define SILICON_ID_XCK26 0x4724093U
+
+static char *zynqmp_get_silicon_idcode_name(void)
+{
+ uint32_t id, ver, chipid[2];
+ size_t i, j, len;
+ const char *name = "EG/EV";
+
+#ifdef IMAGE_BL32
+ /*
+ * For BL32, get the chip id info directly by reading corresponding
+ * registers instead of making pm call. This has limitation
+ * that these registers should be configured to have access
+ * from APU which is default case.
+ */
+ chipid[0] = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
+ chipid[1] = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET);
+#else
+ if (pm_get_chipid(chipid) != PM_RET_SUCCESS) {
+ return "XCZUUNKN";
+ }
+#endif
+
+ id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
+ ZYNQMP_CSU_IDCODE_SVD_MASK);
+ id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
+ ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
+
+ for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
+ if (zynqmp_devices[i].id == id &&
+ zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK)) {
+ break;
+ }
+ }
+
+ if (i >= ARRAY_SIZE(zynqmp_devices)) {
+ switch (chipid[0]) {
+ case SILICON_ID_XCK24:
+ return "XCK24";
+ case SILICON_ID_XCK26:
+ return "XCK26";
+ default:
+ return "XCZUUNKN";
+ }
+ }
+
+ if (!zynqmp_devices[i].evexists) {
+ return zynqmp_devices[i].name;
+ }
+
+ if ((ver & ZYNQMP_PL_STATUS_MASK) != 0U) {
+ return zynqmp_devices[i].name;
+ }
+
+ len = strlen(zynqmp_devices[i].name) - 2;
+ for (j = 0; j < strlen(name); j++) {
+ zynqmp_devices[i].name[len] = name[j];
+ len++;
+ }
+ zynqmp_devices[i].name[len] = '\0';
+
+ return zynqmp_devices[i].name;
+}
+
+static unsigned int zynqmp_get_rtl_ver(void)
+{
+ uint32_t ver;
+
+ ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
+ ver &= ZYNQMP_RTL_VER_MASK;
+ ver >>= ZYNQMP_RTL_VER_SHIFT;
+
+ return ver;
+}
+
+static char *zynqmp_print_silicon_idcode(void)
+{
+ uint32_t id, maskid, tmp;
+
+ id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
+
+ tmp = id;
+ tmp &= ZYNQMP_CSU_IDCODE_XILINX_ID_MASK |
+ ZYNQMP_CSU_IDCODE_FAMILY_MASK;
+ maskid = ZYNQMP_CSU_IDCODE_XILINX_ID << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT |
+ ZYNQMP_CSU_IDCODE_FAMILY << ZYNQMP_CSU_IDCODE_FAMILY_SHIFT;
+ if (tmp != maskid) {
+ ERROR("Incorrect XILINX IDCODE 0x%x, maskid 0x%x\n", id, maskid);
+ return "UNKN";
+ }
+ VERBOSE("Xilinx IDCODE 0x%x\n", id);
+ return zynqmp_get_silicon_idcode_name();
+}
+
+static uint32_t zynqmp_get_ps_ver(void)
+{
+ uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET);
+
+ ver &= ZYNQMP_PS_VER_MASK;
+ ver >>= ZYNQMP_PS_VER_SHIFT;
+
+ return ver + 1U;
+}
+
+static void zynqmp_print_platform_name(void)
+{
+ uint32_t ver = zynqmp_get_silicon_ver();
+ uint32_t rtl = zynqmp_get_rtl_ver();
+ char *label = "Unknown";
+
+ switch (ver) {
+ case ZYNQMP_CSU_VERSION_QEMU:
+ label = "QEMU";
+ break;
+ case ZYNQMP_CSU_VERSION_SILICON:
+ label = "silicon";
+ break;
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ VERBOSE("TF-A running on %s/%s at 0x%x\n",
+ zynqmp_print_silicon_idcode(), label, BL31_BASE);
+ VERBOSE("TF-A running on v%d/RTL%d.%d\n",
+ zynqmp_get_ps_ver(), (rtl & 0xf0) >> 4, rtl & 0xf);
+}
+#else
+static inline void zynqmp_print_platform_name(void) { }
+#endif
+
+uint32_t zynqmp_get_bootmode(void)
+{
+ uint32_t r;
+ unsigned int ret;
+
+ ret = pm_mmio_read(CRL_APB_BOOT_MODE_USER, &r);
+
+ if (ret != PM_RET_SUCCESS) {
+ r = mmio_read_32(CRL_APB_BOOT_MODE_USER);
+ }
+
+ return r & CRL_APB_BOOT_MODE_MASK;
+}
+
+void zynqmp_config_setup(void)
+{
+ uint64_t counter_freq;
+
+ /* Configure IPI data for ZynqMP */
+ zynqmp_ipi_config_table_init();
+
+ zynqmp_print_platform_name();
+
+ /* Configure counter frequency */
+ counter_freq = read_cntfrq_el0();
+ if (counter_freq == ZYNQMP_DEFAULT_COUNTER_FREQ) {
+ write_cntfrq_el0(plat_get_syscnt_freq2());
+ }
+
+ generic_delay_timer_init();
+}
+
+uint32_t plat_get_syscnt_freq2(void)
+{
+ uint32_t ver = zynqmp_get_silicon_ver();
+
+ if (ver == ZYNQMP_CSU_VERSION_QEMU) {
+ return 65000000;
+ } else {
+ return mmio_read_32(IOU_SCNTRS_BASEFREQ);
+ }
+}
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
new file mode 100644
index 0000000..d8439f7
--- /dev/null
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <drivers/arm/gicv2.h>
+#include <platform_def.h>
+
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_is_my_cpu_primary
+ .globl zynqmp_calc_core_pos
+ .globl plat_my_core_pos
+ .globl platform_mem_init
+
+ /* -----------------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ * TODO: Should we read the PSYS register to make sure
+ * that the request has gone through.
+ * -----------------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ mrs x0, mpidr_el1
+
+ /* Deactivate the gic cpu interface */
+ ldr x1, =BASE_GICC_BASE
+ mov w0, #(IRQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP1)
+ orr w0, w0, #(IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP0)
+ str w0, [x1, #GICC_CTLR]
+
+ /*
+ * There is no sane reason to come out of this wfi. This
+ * cpu will be powered on and reset by the cpu_on pm api
+ */
+ dsb sy
+1:
+ no_ret plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+func plat_is_my_cpu_primary
+ mov x9, x30
+ bl plat_my_core_pos
+ cmp x0, #ZYNQMP_PRIMARY_CPU
+ cset x0, eq
+ ret x9
+endfunc plat_is_my_cpu_primary
+
+ /* -----------------------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * This function uses the zynqmp_calc_core_pos()
+ * definition to get the index of the calling CPU.
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b zynqmp_calc_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * unsigned int zynqmp_calc_core_pos(u_register_t mpidr)
+ * Helper function to calculate the core position.
+ * With this function: CorePos = (ClusterId * 4) +
+ * CoreId
+ * -----------------------------------------------------
+ */
+func zynqmp_calc_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc zynqmp_calc_core_pos
+
+ /* ---------------------------------------------------------------------
+ * We don't need to carry out any memory initialization on ARM
+ * platforms. The Secure RAM is accessible straight away.
+ * ---------------------------------------------------------------------
+ */
+func platform_mem_init
+ ret
+endfunc platform_mem_init
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
new file mode 100644
index 0000000..1d59537
--- /dev/null
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <bl31/bl31.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/dcc.h>
+#include <drivers/console.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <lib/mmio.h>
+
+#include <plat_startup.h>
+#include <plat_private.h>
+#include <zynqmp_def.h>
+
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/*
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ */
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+ entry_point_info_t *next_image_info;
+
+ assert(sec_state_is_valid(type));
+ if (type == NON_SECURE) {
+ next_image_info = &bl33_image_ep_info;
+ } else {
+ next_image_info = &bl32_image_ep_info;
+ }
+
+ return next_image_info;
+}
+
+/*
+ * Set the build time defaults. We want to do this when doing a JTAG boot
+ * or if we can't find any other config data.
+ */
+static inline void bl31_set_default_config(void)
+{
+ bl32_image_ep_info.pc = BL32_BASE;
+ bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+ bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS);
+}
+
+/*
+ * Perform any BL31 specific platform actions. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they
+ * are lost (potentially). This needs to be done before the MMU is initialized
+ * so that the memory layout can be used while creating page tables.
+ */
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ uint64_t atf_handoff_addr;
+
+ if (ZYNQMP_CONSOLE_IS(cadence) || (ZYNQMP_CONSOLE_IS(cadence1))) {
+ /* Register the console to provide early debug support */
+ static console_t bl31_boot_console;
+ (void)console_cdns_register(ZYNQMP_UART_BASE,
+ zynqmp_get_uart_clk(),
+ ZYNQMP_UART_BAUDRATE,
+ &bl31_boot_console);
+ console_set_scope(&bl31_boot_console,
+ CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
+ } else if (ZYNQMP_CONSOLE_IS(dcc)) {
+ /* Initialize the dcc console for debug */
+ int32_t rc = console_dcc_register();
+ if (rc == 0) {
+ panic();
+ }
+ } else {
+ ERROR("BL31: No console device found.\n");
+ }
+ /* Initialize the platform config for future decision making */
+ zynqmp_config_setup();
+
+ /* There are no parameters from BL2 if BL31 is a reset vector */
+ assert(arg0 == 0U);
+ assert(arg1 == 0U);
+
+ /*
+ * Do initial security configuration to allow DRAM/device access. On
+ * Base ZYNQMP only DRAM security is programmable (via TrustZone), but
+ * other platforms might have more programmable security devices
+ * present.
+ */
+
+ /* Populate common information for BL32 and BL33 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ atf_handoff_addr = mmio_read_32(PMU_GLOBAL_GEN_STORAGE6);
+
+ if (zynqmp_get_bootmode() == ZYNQMP_BOOTMODE_JTAG) {
+ bl31_set_default_config();
+ } else {
+ /* use parameters from FSBL */
+ enum fsbl_handoff ret = fsbl_atf_handover(&bl32_image_ep_info,
+ &bl33_image_ep_info,
+ atf_handoff_addr);
+ if (ret == FSBL_HANDOFF_NO_STRUCT) {
+ bl31_set_default_config();
+ } else if (ret != FSBL_HANDOFF_SUCCESS) {
+ panic();
+ }
+ }
+ if (bl32_image_ep_info.pc != 0) {
+ VERBOSE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
+ }
+ if (bl33_image_ep_info.pc != 0) {
+ VERBOSE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
+ }
+}
+
+#if ZYNQMP_WDT_RESTART
+static interrupt_type_handler_t type_el3_interrupt_table[MAX_INTR_EL3];
+
+int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler)
+{
+ /* Validate 'handler' and 'id' parameters */
+ if (!handler || id >= MAX_INTR_EL3) {
+ return -EINVAL;
+ }
+
+ /* Check if a handler has already been registered */
+ if (type_el3_interrupt_table[id]) {
+ return -EALREADY;
+ }
+
+ type_el3_interrupt_table[id] = handler;
+
+ return 0;
+}
+
+static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint32_t intr_id;
+ interrupt_type_handler_t handler;
+
+ intr_id = plat_ic_get_pending_interrupt_id();
+ handler = type_el3_interrupt_table[intr_id];
+ if (handler != NULL) {
+ handler(intr_id, flags, handle, cookie);
+ }
+
+ return 0;
+}
+#endif
+
+#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX)
+static void prepare_dtb(void)
+{
+ void *dtb = (void *)XILINX_OF_BOARD_DTB_ADDR;
+ int ret;
+
+ /* Return if no device tree is detected */
+ if (fdt_check_header(dtb) != 0) {
+ NOTICE("Can't read DT at %p\n", dtb);
+ return;
+ }
+
+ ret = fdt_open_into(dtb, dtb, XILINX_OF_BOARD_DTB_MAX_SIZE);
+ if (ret < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
+ return;
+ }
+
+ if (dt_add_psci_node(dtb)) {
+ ERROR("Failed to add PSCI Device Tree node\n");
+ return;
+ }
+
+ if (dt_add_psci_cpu_enable_methods(dtb)) {
+ ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
+ return;
+ }
+
+ /* Reserve memory used by Trusted Firmware. */
+ if (fdt_add_reserved_memory(dtb, "tf-a", BL31_BASE, BL31_LIMIT - BL31_BASE)) {
+ WARN("Failed to add reserved memory nodes to DT.\n");
+ }
+
+ ret = fdt_pack(dtb);
+ if (ret < 0) {
+ ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
+ }
+
+ clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
+ INFO("Changed device tree to advertise PSCI and reserved memories.\n");
+}
+#endif
+
+void bl31_platform_setup(void)
+{
+#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX)
+ prepare_dtb();
+#endif
+
+ /* Initialize the gic cpu and distributor interfaces */
+ plat_arm_gic_driver_init();
+ plat_arm_gic_init();
+}
+
+void bl31_plat_runtime_setup(void)
+{
+#if ZYNQMP_WDT_RESTART
+ uint64_t flags = 0;
+ uint64_t rc;
+
+ set_interrupt_rm_flag(flags, NON_SECURE);
+ rc = register_interrupt_type_handler(INTR_TYPE_EL3,
+ rdo_el3_interrupt_handler, flags);
+ if (rc) {
+ panic();
+ }
+#endif
+}
+
+/*
+ * Perform the very early platform specific architectural setup here.
+ */
+void bl31_plat_arch_setup(void)
+{
+ plat_arm_interconnect_init();
+ plat_arm_interconnect_enter_coherency();
+
+
+ const mmap_region_t bl_regions[] = {
+#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX)
+ MAP_REGION_FLAT(XILINX_OF_BOARD_DTB_ADDR, XILINX_OF_BOARD_DTB_MAX_SIZE,
+ MT_MEMORY | MT_RW | MT_NS),
+#endif
+ MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+ enable_mmu_el3(0);
+}
diff --git a/plat/xilinx/zynqmp/include/plat_ipi.h b/plat/xilinx/zynqmp/include/plat_ipi.h
new file mode 100644
index 0000000..a78f93a
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/plat_ipi.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* ZynqMP IPI management enums and defines */
+
+#ifndef PLAT_IPI_H
+#define PLAT_IPI_H
+
+#include <stdint.h>
+#include <ipi.h>
+
+/*********************************************************************
+ * IPI agent IDs macros
+ ********************************************************************/
+#define IPI_ID_APU 0U
+#define IPI_ID_RPU0 1U
+#define IPI_ID_RPU1 2U
+#define IPI_ID_PMU0 3U
+#define IPI_ID_PMU1 4U
+#define IPI_ID_PMU2 5U
+#define IPI_ID_PMU3 6U
+#define IPI_ID_PL0 7U
+#define IPI_ID_PL1 8U
+#define IPI_ID_PL2 9U
+#define IPI_ID_PL3 10U
+
+/*********************************************************************
+ * IPI message buffers
+ ********************************************************************/
+#define IPI_BUFFER_BASEADDR 0xFF990000U
+
+#define IPI_BUFFER_APU_BASE (IPI_BUFFER_BASEADDR + 0x400U)
+#define IPI_BUFFER_PMU_BASE (IPI_BUFFER_BASEADDR + 0xE00U)
+
+#define IPI_BUFFER_LOCAL_BASE IPI_BUFFER_APU_BASE
+#define IPI_BUFFER_REMOTE_BASE IPI_BUFFER_PMU_BASE
+
+#define IPI_BUFFER_TARGET_LOCAL_OFFSET 0x80U
+#define IPI_BUFFER_TARGET_REMOTE_OFFSET 0x1C0U
+
+#define IPI_BUFFER_MAX_WORDS 8U
+
+#define IPI_BUFFER_REQ_OFFSET 0x0U
+#define IPI_BUFFER_RESP_OFFSET 0x20U
+
+/*********************************************************************
+ * Platform specific IPI API declarations
+ ********************************************************************/
+
+/* Configure IPI table for zynqmp */
+void zynqmp_ipi_config_table_init(void);
+
+#endif /* PLAT_IPI_H */
diff --git a/plat/xilinx/zynqmp/include/plat_macros.S b/plat/xilinx/zynqmp/include/plat_macros.S
new file mode 100644
index 0000000..bf1ff82
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/plat_macros.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+#include <cci_macros.S>
+#include "zynqmp_def.h"
+
+ /* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant GIC and CCI registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ * Clobbers: x0 - x10, x16, x17, sp
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ mov_imm x17, BASE_GICC_BASE
+ mov_imm x16, BASE_GICD_BASE
+ arm_print_gic_regs
+ print_cci_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/xilinx/zynqmp/include/plat_pm_common.h b/plat/xilinx/zynqmp/include/plat_pm_common.h
new file mode 100644
index 0000000..a57aebe
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/plat_pm_common.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Contains platform specific definitions of commonly used macros data types
+ * for PU Power Management. This file should be common for all PU's.
+ */
+
+#ifndef PLAT_PM_COMMON_H
+#define PLAT_PM_COMMON_H
+
+#include <stdint.h>
+#include <common/debug.h>
+#include "pm_defs.h"
+
+
+#define ZYNQMP_TZ_VERSION_MAJOR 1
+#define ZYNQMP_TZ_VERSION_MINOR 0
+#define ZYNQMP_TZ_VERSION ((ZYNQMP_TZ_VERSION_MAJOR << 16) | \
+ ZYNQMP_TZ_VERSION_MINOR)
+#endif /* _PLAT_PM_COMMON_H_ */
diff --git a/plat/xilinx/zynqmp/include/plat_private.h b/plat/xilinx/zynqmp/include/plat_private.h
new file mode 100644
index 0000000..534777b
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/plat_private.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+#include <stdint.h>
+
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <drivers/cadence/cdns_uart.h>
+
+void zynqmp_config_setup(void);
+
+uint32_t zynqmp_calc_core_pos(u_register_t mpidr);
+
+/* ZynqMP specific functions */
+uint32_t zynqmp_get_uart_clk(void);
+uint32_t zynqmp_get_bootmode(void);
+
+
+#if ZYNQMP_WDT_RESTART
+/*
+ * Register handler to specific GIC entrance
+ * for INTR_TYPE_EL3 type of interrupt
+ */
+int request_intr_type_el3(uint32_t, interrupt_type_handler_t);
+#endif
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
new file mode 100644
index 0000000..c2d22c2
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/utils_def.h>
+
+#include "zynqmp_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE 0x440
+
+#define PLATFORM_CORE_COUNT U(4)
+#define PLAT_NUM_POWER_DOMAINS U(5)
+#define PLAT_MAX_PWR_LVL U(1)
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#ifndef ZYNQMP_ATF_MEM_BASE
+#if !DEBUG && defined(SPD_none) && !SDEI_SUPPORT
+# define BL31_BASE U(0xfffea000)
+# define BL31_LIMIT U(0x100000000)
+#else
+# define BL31_BASE U(0xfffe5000)
+# define BL31_LIMIT U(0x100000000)
+#endif
+#else
+# define BL31_BASE (ZYNQMP_ATF_MEM_BASE)
+# define BL31_LIMIT (ZYNQMP_ATF_MEM_BASE + ZYNQMP_ATF_MEM_SIZE - 1)
+# ifdef ZYNQMP_ATF_MEM_PROGBITS_SIZE
+# define BL31_PROGBITS_LIMIT (ZYNQMP_ATF_MEM_BASE + ZYNQMP_ATF_MEM_PROGBITS_SIZE - 1)
+# endif
+#endif
+
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#ifndef ZYNQMP_BL32_MEM_BASE
+# define BL32_BASE U(0x60000000)
+# define BL32_LIMIT U(0x7fffffff)
+#else
+# define BL32_BASE (ZYNQMP_BL32_MEM_BASE)
+# define BL32_LIMIT (ZYNQMP_BL32_MEM_BASE + ZYNQMP_BL32_MEM_SIZE - 1)
+#endif
+
+/*******************************************************************************
+ * BL33 specific defines.
+ ******************************************************************************/
+#ifndef PRELOADED_BL33_BASE
+# define PLAT_ARM_NS_IMAGE_BASE U(0x8000000)
+#else
+# define PLAT_ARM_NS_IMAGE_BASE PRELOADED_BL33_BASE
+#endif
+
+/*******************************************************************************
+ * TSP specific defines.
+ ******************************************************************************/
+#define TSP_SEC_MEM_BASE BL32_BASE
+#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1)
+
+/* ID of the secure physical generic timer interrupt used by the TSP */
+#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define XILINX_OF_BOARD_DTB_ADDR U(0x100000)
+#define XILINX_OF_BOARD_DTB_MAX_SIZE U(0x200000)
+#define PLAT_DDR_LOWMEM_MAX U(0x80000000)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX)
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 6
+#else
+#define MAX_MMAP_REGIONS 7
+#define MAX_XLAT_TABLES 5
+#endif
+
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+#define ZYNQMP_SDEI_SGI_PRIVATE U(8)
+
+/* Platform macros to support exception handling framework */
+#define PLAT_PRI_BITS U(3)
+#define PLAT_SDEI_CRITICAL_PRI 0x10
+#define PLAT_SDEI_NORMAL_PRI 0x20
+
+#define PLAT_ARM_GICD_BASE BASE_GICD_BASE
+#define PLAT_ARM_GICC_BASE BASE_GICC_BASE
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#if !ZYNQMP_WDT_RESTART
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+#else
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(IRQ_TTC3_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
+#endif
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, grp, \
+ GIC_INTR_CFG_EDGE)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
new file mode 100644
index 0000000..428bed5
--- /dev/null
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ZYNQMP_DEF_H
+#define ZYNQMP_DEF_H
+
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+
+#define ZYNQMP_CONSOLE_ID_cadence 1
+#define ZYNQMP_CONSOLE_ID_cadence0 1
+#define ZYNQMP_CONSOLE_ID_cadence1 2
+#define ZYNQMP_CONSOLE_ID_dcc 3
+
+#define ZYNQMP_CONSOLE_IS(con) (ZYNQMP_CONSOLE_ID_ ## con == ZYNQMP_CONSOLE)
+
+/* Default counter frequency */
+#define ZYNQMP_DEFAULT_COUNTER_FREQ 0U
+
+/* Firmware Image Package */
+#define ZYNQMP_PRIMARY_CPU 0
+
+/* Memory location options for Shared data and TSP in ZYNQMP */
+#define ZYNQMP_IN_TRUSTED_SRAM 0
+#define ZYNQMP_IN_TRUSTED_DRAM 1
+
+/*******************************************************************************
+ * ZYNQMP memory map related constants
+ ******************************************************************************/
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE U(0xFF000000)
+#define DEVICE0_SIZE U(0x00E00000)
+#define DEVICE1_BASE U(0xF9000000)
+#define DEVICE1_SIZE U(0x00800000)
+
+/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/
+#define CRF_APB_BASE U(0xFD1A0000)
+#define CRF_APB_SIZE U(0x00600000)
+#define CRF_APB_CLK_BASE U(0xFD1A0020)
+
+/* CRF registers and bitfields */
+#define CRF_APB_RST_FPD_APU (CRF_APB_BASE + 0X00000104)
+
+#define CRF_APB_RST_FPD_APU_ACPU_RESET (U(1) << 0)
+#define CRF_APB_RST_FPD_APU_ACPU_PWRON_RESET (U(1) << 10)
+
+/* CRL registers and bitfields */
+#define CRL_APB_BASE U(0xFF5E0000)
+#define CRL_APB_BOOT_MODE_USER (CRL_APB_BASE + 0x200)
+#define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218)
+#define CRL_APB_RST_LPD_TOP (CRL_APB_BASE + 0x23C)
+#define CRL_APB_BOOT_PIN_CTRL (CRL_APB_BASE + U(0x250))
+#define CRL_APB_CLK_BASE U(0xFF5E0020)
+
+#define CRL_APB_RPU_AMBA_RESET (U(1) << 2)
+#define CRL_APB_RPLL_CTRL_BYPASS (U(1) << 3)
+
+#define CRL_APB_RESET_CTRL_SOFT_RESET (U(1) << 4)
+
+#define CRL_APB_BOOT_MODE_MASK (U(0xf) << 0)
+#define CRL_APB_BOOT_PIN_MASK (U(0xf0f) << 0)
+#define CRL_APB_BOOT_DRIVE_PIN_1_SHIFT U(9)
+#define CRL_APB_BOOT_ENABLE_PIN_1_SHIFT U(1)
+#define CRL_APB_BOOT_ENABLE_PIN_1 (U(0x1) << \
+ CRL_APB_BOOT_ENABLE_PIN_1_SHIFT)
+#define CRL_APB_BOOT_DRIVE_PIN_1 (U(0x1) << \
+ CRL_APB_BOOT_DRIVE_PIN_1_SHIFT)
+#define ZYNQMP_BOOTMODE_JTAG U(0)
+#define ZYNQMP_ULPI_RESET_VAL_HIGH (CRL_APB_BOOT_ENABLE_PIN_1 | \
+ CRL_APB_BOOT_DRIVE_PIN_1)
+#define ZYNQMP_ULPI_RESET_VAL_LOW CRL_APB_BOOT_ENABLE_PIN_1
+
+/* system counter registers and bitfields */
+#define IOU_SCNTRS_BASE U(0xFF260000)
+#define IOU_SCNTRS_BASEFREQ (IOU_SCNTRS_BASE + 0x20)
+
+/* APU registers and bitfields */
+#define APU_BASE U(0xFD5C0000)
+#define APU_CONFIG_0 (APU_BASE + 0x20)
+#define APU_RVBAR_L_0 (APU_BASE + 0x40)
+#define APU_RVBAR_H_0 (APU_BASE + 0x44)
+#define APU_PWRCTL (APU_BASE + 0x90)
+
+#define APU_CONFIG_0_VINITHI_SHIFT 8
+#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1
+#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2
+#define APU_2_PWRCTL_CPUPWRDWNREQ_MASK 4
+#define APU_3_PWRCTL_CPUPWRDWNREQ_MASK 8
+
+/* PMU registers and bitfields */
+#define PMU_GLOBAL_BASE U(0xFFD80000)
+#define PMU_GLOBAL_CNTRL (PMU_GLOBAL_BASE + 0)
+#define PMU_GLOBAL_GEN_STORAGE6 (PMU_GLOBAL_BASE + 0x48)
+#define PMU_GLOBAL_REQ_PWRUP_STATUS (PMU_GLOBAL_BASE + 0x110)
+#define PMU_GLOBAL_REQ_PWRUP_EN (PMU_GLOBAL_BASE + 0x118)
+#define PMU_GLOBAL_REQ_PWRUP_DIS (PMU_GLOBAL_BASE + 0x11c)
+#define PMU_GLOBAL_REQ_PWRUP_TRIG (PMU_GLOBAL_BASE + 0x120)
+
+#define PMU_GLOBAL_CNTRL_FW_IS_PRESENT (1 << 4)
+
+/*******************************************************************************
+ * CCI-400 related constants
+ ******************************************************************************/
+#define PLAT_ARM_CCI_BASE U(0xFD6E0000)
+#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 3
+#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 4
+
+/*******************************************************************************
+ * GIC-400 & interrupt handling related constants
+ ******************************************************************************/
+#define BASE_GICD_BASE U(0xF9010000)
+#define BASE_GICC_BASE U(0xF9020000)
+#define BASE_GICH_BASE U(0xF9040000)
+#define BASE_GICV_BASE U(0xF9060000)
+
+#if ZYNQMP_WDT_RESTART
+#define IRQ_SEC_IPI_APU 67
+#define IRQ_TTC3_1 77
+#define TTC3_BASE_ADDR U(0xFF140000)
+#define TTC3_INTR_REGISTER_1 (TTC3_BASE_ADDR + 0x54)
+#define TTC3_INTR_ENABLE_1 (TTC3_BASE_ADDR + 0x60)
+#endif
+
+#define ARM_IRQ_SEC_PHY_TIMER 29
+
+#define ARM_IRQ_SEC_SGI_0 8
+#define ARM_IRQ_SEC_SGI_1 9
+#define ARM_IRQ_SEC_SGI_2 10
+#define ARM_IRQ_SEC_SGI_3 11
+#define ARM_IRQ_SEC_SGI_4 12
+#define ARM_IRQ_SEC_SGI_5 13
+#define ARM_IRQ_SEC_SGI_6 14
+#define ARM_IRQ_SEC_SGI_7 15
+
+#define MAX_INTR_EL3 128
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define ZYNQMP_UART0_BASE U(0xFF000000)
+#define ZYNQMP_UART1_BASE U(0xFF010000)
+
+#if ZYNQMP_CONSOLE_IS(cadence) || ZYNQMP_CONSOLE_IS(dcc)
+# define ZYNQMP_UART_BASE ZYNQMP_UART0_BASE
+#elif ZYNQMP_CONSOLE_IS(cadence1)
+# define ZYNQMP_UART_BASE ZYNQMP_UART1_BASE
+#else
+# error "invalid ZYNQMP_CONSOLE"
+#endif
+
+#define ZYNQMP_CRASH_UART_BASE ZYNQMP_UART_BASE
+/* impossible to call C routine how it is done now - hardcode any value */
+#define ZYNQMP_CRASH_UART_CLK_IN_HZ 100000000 /* FIXME */
+/* Must be non zero */
+#define ZYNQMP_UART_BAUDRATE 115200
+
+/* Silicon version detection */
+#define ZYNQMP_SILICON_VER_MASK 0xF000
+#define ZYNQMP_SILICON_VER_SHIFT 12
+#define ZYNQMP_CSU_VERSION_SILICON 0
+#define ZYNQMP_CSU_VERSION_QEMU 3
+
+#define ZYNQMP_RTL_VER_MASK 0xFF0U
+#define ZYNQMP_RTL_VER_SHIFT 4
+
+#define ZYNQMP_PS_VER_MASK 0xFU
+#define ZYNQMP_PS_VER_SHIFT 0
+
+#define ZYNQMP_CSU_BASEADDR U(0xFFCA0000)
+#define ZYNQMP_CSU_IDCODE_OFFSET 0x40U
+
+#define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT 0U
+#define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK (0xFFFU << \
+ ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT)
+#define ZYNQMP_CSU_IDCODE_XILINX_ID 0x093
+
+#define ZYNQMP_CSU_IDCODE_SVD_SHIFT 12U
+#define ZYNQMP_CSU_IDCODE_SVD_MASK (0x7U << \
+ ZYNQMP_CSU_IDCODE_SVD_SHIFT)
+#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT 15U
+#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK (0xFU << \
+ ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT)
+#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT 19U
+#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_MASK (0x3U << \
+ ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT)
+#define ZYNQMP_CSU_IDCODE_FAMILY_SHIFT 21U
+#define ZYNQMP_CSU_IDCODE_FAMILY_MASK (0x7FU << \
+ ZYNQMP_CSU_IDCODE_FAMILY_SHIFT)
+#define ZYNQMP_CSU_IDCODE_FAMILY 0x23
+
+#define ZYNQMP_CSU_IDCODE_REVISION_SHIFT 28U
+#define ZYNQMP_CSU_IDCODE_REVISION_MASK (0xFU << \
+ ZYNQMP_CSU_IDCODE_REVISION_SHIFT)
+#define ZYNQMP_CSU_IDCODE_REVISION 0U
+
+#define ZYNQMP_CSU_VERSION_OFFSET 0x44U
+
+/* Efuse */
+#define EFUSE_BASEADDR U(0xFFCC0000)
+#define EFUSE_IPDISABLE_OFFSET 0x1018
+#define EFUSE_IPDISABLE_VERSION 0x1FFU
+#define ZYNQMP_EFUSE_IPDISABLE_SHIFT 20
+
+/* Access control register defines */
+#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
+#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
+
+#define FPD_SLCR_BASEADDR U(0xFD610000)
+#define IOU_SLCR_BASEADDR U(0xFF180000)
+
+#define ZYNQMP_RPU_GLBL_CNTL U(0xFF9A0000)
+#define ZYNQMP_RPU0_CFG U(0xFF9A0100)
+#define ZYNQMP_RPU1_CFG U(0xFF9A0200)
+#define ZYNQMP_SLSPLIT_MASK U(0x08)
+#define ZYNQMP_TCM_COMB_MASK U(0x40)
+#define ZYNQMP_SLCLAMP_MASK U(0x10)
+#define ZYNQMP_VINITHI_MASK U(0x04)
+
+/* Tap delay bypass */
+#define IOU_TAPDLY_BYPASS U(0XFF180390)
+#define TAP_DELAY_MASK U(0x7)
+
+/* SGMII mode */
+#define IOU_GEM_CTRL U(0xFF180360)
+#define IOU_GEM_CLK_CTRL U(0xFF180308)
+#define SGMII_SD_MASK U(0x3)
+#define SGMII_SD_OFFSET U(2)
+#define SGMII_PCS_SD_0 U(0x0)
+#define SGMII_PCS_SD_1 U(0x1)
+#define SGMII_PCS_SD_PHY U(0x2)
+#define GEM_SGMII_MASK U(0x4)
+#define GEM_CLK_CTRL_MASK U(0xF)
+#define GEM_CLK_CTRL_OFFSET U(5)
+#define GEM_RX_SRC_SEL_GTR U(0x1)
+#define GEM_SGMII_MODE U(0x4)
+
+/* SD DLL reset */
+#define ZYNQMP_SD_DLL_CTRL U(0xFF180358)
+#define ZYNQMP_SD0_DLL_RST_MASK U(0x00000004)
+#define ZYNQMP_SD0_DLL_RST U(0x00000004)
+#define ZYNQMP_SD1_DLL_RST_MASK U(0x00040000)
+#define ZYNQMP_SD1_DLL_RST U(0x00040000)
+
+/* SD tap delay */
+#define ZYNQMP_SD_DLL_CTRL U(0xFF180358)
+#define ZYNQMP_SD_ITAP_DLY U(0xFF180314)
+#define ZYNQMP_SD_OTAP_DLY U(0xFF180318)
+#define ZYNQMP_SD_TAP_OFFSET U(16)
+#define ZYNQMP_SD_ITAPCHGWIN_MASK U(0x200)
+#define ZYNQMP_SD_ITAPCHGWIN U(0x200)
+#define ZYNQMP_SD_ITAPDLYENA_MASK U(0x100)
+#define ZYNQMP_SD_ITAPDLYENA U(0x100)
+#define ZYNQMP_SD_ITAPDLYSEL_MASK U(0xFF)
+#define ZYNQMP_SD_OTAPDLYSEL_MASK U(0x3F)
+#define ZYNQMP_SD_OTAPDLYENA_MASK U(0x40)
+#define ZYNQMP_SD_OTAPDLYENA U(0x40)
+
+/* Clock control registers */
+/* Full power domain clocks */
+#define CRF_APB_APLL_CTRL (CRF_APB_CLK_BASE + 0x00)
+#define CRF_APB_DPLL_CTRL (CRF_APB_CLK_BASE + 0x0c)
+#define CRF_APB_VPLL_CTRL (CRF_APB_CLK_BASE + 0x18)
+#define CRF_APB_PLL_STATUS (CRF_APB_CLK_BASE + 0x24)
+#define CRF_APB_APLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x28)
+#define CRF_APB_DPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x2c)
+#define CRF_APB_VPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x30)
+/* Peripheral clocks */
+#define CRF_APB_ACPU_CTRL (CRF_APB_CLK_BASE + 0x40)
+#define CRF_APB_DBG_TRACE_CTRL (CRF_APB_CLK_BASE + 0x44)
+#define CRF_APB_DBG_FPD_CTRL (CRF_APB_CLK_BASE + 0x48)
+#define CRF_APB_DP_VIDEO_REF_CTRL (CRF_APB_CLK_BASE + 0x50)
+#define CRF_APB_DP_AUDIO_REF_CTRL (CRF_APB_CLK_BASE + 0x54)
+#define CRF_APB_DP_STC_REF_CTRL (CRF_APB_CLK_BASE + 0x5c)
+#define CRF_APB_DDR_CTRL (CRF_APB_CLK_BASE + 0x60)
+#define CRF_APB_GPU_REF_CTRL (CRF_APB_CLK_BASE + 0x64)
+#define CRF_APB_SATA_REF_CTRL (CRF_APB_CLK_BASE + 0x80)
+#define CRF_APB_PCIE_REF_CTRL (CRF_APB_CLK_BASE + 0x94)
+#define CRF_APB_GDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x98)
+#define CRF_APB_DPDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x9c)
+#define CRF_APB_TOPSW_MAIN_CTRL (CRF_APB_CLK_BASE + 0xa0)
+#define CRF_APB_TOPSW_LSBUS_CTRL (CRF_APB_CLK_BASE + 0xa4)
+#define CRF_APB_GTGREF0_REF_CTRL (CRF_APB_CLK_BASE + 0xa8)
+#define CRF_APB_DBG_TSTMP_CTRL (CRF_APB_CLK_BASE + 0xd8)
+
+/* Low power domain clocks */
+#define CRL_APB_IOPLL_CTRL (CRL_APB_CLK_BASE + 0x00)
+#define CRL_APB_RPLL_CTRL (CRL_APB_CLK_BASE + 0x10)
+#define CRL_APB_PLL_STATUS (CRL_APB_CLK_BASE + 0x20)
+#define CRL_APB_IOPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x24)
+#define CRL_APB_RPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x28)
+/* Peripheral clocks */
+#define CRL_APB_USB3_DUAL_REF_CTRL (CRL_APB_CLK_BASE + 0x2c)
+#define CRL_APB_GEM0_REF_CTRL (CRL_APB_CLK_BASE + 0x30)
+#define CRL_APB_GEM1_REF_CTRL (CRL_APB_CLK_BASE + 0x34)
+#define CRL_APB_GEM2_REF_CTRL (CRL_APB_CLK_BASE + 0x38)
+#define CRL_APB_GEM3_REF_CTRL (CRL_APB_CLK_BASE + 0x3c)
+#define CRL_APB_USB0_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x40)
+#define CRL_APB_USB1_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x44)
+#define CRL_APB_QSPI_REF_CTRL (CRL_APB_CLK_BASE + 0x48)
+#define CRL_APB_SDIO0_REF_CTRL (CRL_APB_CLK_BASE + 0x4c)
+#define CRL_APB_SDIO1_REF_CTRL (CRL_APB_CLK_BASE + 0x50)
+#define CRL_APB_UART0_REF_CTRL (CRL_APB_CLK_BASE + 0x54)
+#define CRL_APB_UART1_REF_CTRL (CRL_APB_CLK_BASE + 0x58)
+#define CRL_APB_SPI0_REF_CTRL (CRL_APB_CLK_BASE + 0x5c)
+#define CRL_APB_SPI1_REF_CTRL (CRL_APB_CLK_BASE + 0x60)
+#define CRL_APB_CAN0_REF_CTRL (CRL_APB_CLK_BASE + 0x64)
+#define CRL_APB_CAN1_REF_CTRL (CRL_APB_CLK_BASE + 0x68)
+#define CRL_APB_CPU_R5_CTRL (CRL_APB_CLK_BASE + 0x70)
+#define CRL_APB_IOU_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x7c)
+#define CRL_APB_CSU_PLL_CTRL (CRL_APB_CLK_BASE + 0x80)
+#define CRL_APB_PCAP_CTRL (CRL_APB_CLK_BASE + 0x84)
+#define CRL_APB_LPD_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x88)
+#define CRL_APB_LPD_LSBUS_CTRL (CRL_APB_CLK_BASE + 0x8c)
+#define CRL_APB_DBG_LPD_CTRL (CRL_APB_CLK_BASE + 0x90)
+#define CRL_APB_NAND_REF_CTRL (CRL_APB_CLK_BASE + 0x94)
+#define CRL_APB_ADMA_REF_CTRL (CRL_APB_CLK_BASE + 0x98)
+#define CRL_APB_PL0_REF_CTRL (CRL_APB_CLK_BASE + 0xa0)
+#define CRL_APB_PL1_REF_CTRL (CRL_APB_CLK_BASE + 0xa4)
+#define CRL_APB_PL2_REF_CTRL (CRL_APB_CLK_BASE + 0xa8)
+#define CRL_APB_PL3_REF_CTRL (CRL_APB_CLK_BASE + 0xac)
+#define CRL_APB_PL0_THR_CNT (CRL_APB_CLK_BASE + 0xb4)
+#define CRL_APB_PL1_THR_CNT (CRL_APB_CLK_BASE + 0xbc)
+#define CRL_APB_PL2_THR_CNT (CRL_APB_CLK_BASE + 0xc4)
+#define CRL_APB_PL3_THR_CNT (CRL_APB_CLK_BASE + 0xdc)
+#define CRL_APB_GEM_TSU_REF_CTRL (CRL_APB_CLK_BASE + 0xe0)
+#define CRL_APB_DLL_REF_CTRL (CRL_APB_CLK_BASE + 0xe4)
+#define CRL_APB_AMS_REF_CTRL (CRL_APB_CLK_BASE + 0xe8)
+#define CRL_APB_I2C0_REF_CTRL (CRL_APB_CLK_BASE + 0x100)
+#define CRL_APB_I2C1_REF_CTRL (CRL_APB_CLK_BASE + 0x104)
+#define CRL_APB_TIMESTAMP_REF_CTRL (CRL_APB_CLK_BASE + 0x108)
+#define IOU_SLCR_GEM_CLK_CTRL (IOU_SLCR_BASEADDR + 0x308)
+#define IOU_SLCR_CAN_MIO_CTRL (IOU_SLCR_BASEADDR + 0x304)
+#define FPD_SLCR_WDT_CLK_SEL (FPD_SLCR_BASEADDR + 0x100)
+#define IOU_SLCR_WDT_CLK_SEL (IOU_SLCR_BASEADDR + 0x300)
+
+/* Global general storage register base address */
+#define GGS_BASEADDR (0xFFD80030U)
+#define GGS_NUM_REGS U(4)
+
+/* Persistent global general storage register base address */
+#define PGGS_BASEADDR (0xFFD80050U)
+#define PGGS_NUM_REGS U(4)
+
+/* PMU GGS4 register 4 is used for warm restart boot health status */
+#define PMU_GLOBAL_GEN_STORAGE4 (GGS_BASEADDR + 0x10)
+/* Warm restart boot health status mask */
+#define PM_BOOT_HEALTH_STATUS_MASK U(0x01)
+/* WDT restart scope shift and mask */
+#define RESTART_SCOPE_SHIFT (3)
+#define RESTART_SCOPE_MASK (0x3U << RESTART_SCOPE_SHIFT)
+
+/* AFI registers */
+#define AFIFM6_WRCTRL U(13)
+#define FABRIC_WIDTH U(3)
+
+/* CSUDMA Module Base Address*/
+#define CSUDMA_BASE U(0xFFC80000)
+
+/* RSA-CORE Module Base Address*/
+#define RSA_CORE_BASE U(0xFFCE0000)
+
+#endif /* ZYNQMP_DEF_H */
diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c
new file mode 100644
index 0000000..b7408b1
--- /dev/null
+++ b/plat/xilinx/zynqmp/plat_psci.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+
+static uintptr_t zynqmp_sec_entry;
+
+static void zynqmp_cpu_standby(plat_local_state_t cpu_state)
+{
+ VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state);
+
+ dsb();
+ wfi();
+}
+
+static int32_t zynqmp_pwr_domain_on(u_register_t mpidr)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+ const struct pm_proc *proc;
+ uint32_t buff[3];
+ enum pm_ret_status ret;
+
+ VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
+
+ if (cpu_id == -1) {
+ return PSCI_E_INTERN_FAIL;
+ }
+ proc = pm_get_proc(cpu_id);
+
+ /* Check the APU proc status before wakeup */
+ ret = pm_get_node_status(proc->node_id, buff);
+ if ((ret != PM_RET_SUCCESS) || (buff[0] == PM_PROC_STATE_SUSPENDING)) {
+ return PSCI_E_INTERN_FAIL;
+ }
+
+ /* Clear power down request */
+ pm_client_wakeup(proc);
+
+ /* Send request to PMU to wake up selected APU CPU core */
+ pm_req_wakeup(proc->node_id, 1, zynqmp_sec_entry, REQ_ACK_BLOCKING);
+
+ return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gicv2_cpuif_disable();
+
+ /*
+ * Send request to PMU to power down the appropriate APU CPU
+ * core.
+ * According to PSCI specification, CPU_off function does not
+ * have resume address and CPU core can only be woken up
+ * invoking CPU_on function, during which resume address will
+ * be set.
+ */
+ pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0);
+}
+
+static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ uint32_t state;
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++)
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+
+ state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
+ PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
+
+ /* Send request to PMU to suspend this core */
+ pm_self_suspend(proc->node_id, MAX_LATENCY, state, zynqmp_sec_entry);
+
+ /* APU is to be turned off */
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ /* disable coherency */
+ plat_arm_interconnect_exit_coherency();
+ }
+}
+
+static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+ plat_arm_gic_pcpu_init();
+ gicv2_cpuif_enable();
+}
+
+static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpu_id);
+
+ for (size_t i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ /* Clear the APU power control register for this cpu */
+ pm_client_wakeup(proc);
+
+ /* enable coherency */
+ plat_arm_interconnect_enter_coherency();
+ /* APU was turned off */
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_arm_gic_init();
+ } else {
+ gicv2_cpuif_enable();
+ gicv2_pcpu_distif_init();
+ }
+}
+
+/*******************************************************************************
+ * ZynqMP handlers to shutdown/reboot the system
+ ******************************************************************************/
+
+static void __dead2 zynqmp_system_off(void)
+{
+ /* disable coherency */
+ plat_arm_interconnect_exit_coherency();
+
+ /* Send the power down request to the PMU */
+ pm_system_shutdown(PMF_SHUTDOWN_TYPE_SHUTDOWN,
+ pm_get_shutdown_scope());
+
+ while (1) {
+ wfi();
+ }
+}
+
+static void __dead2 zynqmp_system_reset(void)
+{
+ /* disable coherency */
+ plat_arm_interconnect_exit_coherency();
+
+ /* Send the system reset request to the PMU */
+ pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET,
+ pm_get_shutdown_scope());
+
+ while (1) {
+ wfi();
+ }
+}
+
+static int32_t zynqmp_validate_power_state(uint32_t power_state,
+ psci_power_state_t *req_state)
+{
+ VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+ uint32_t pstate = psci_get_pstate_type(power_state);
+
+ assert(req_state);
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ } else {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+ }
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state)) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
+}
+
+/*******************************************************************************
+ * Export the platform handlers to enable psci to invoke them
+ ******************************************************************************/
+static const struct plat_psci_ops zynqmp_psci_ops = {
+ .cpu_standby = zynqmp_cpu_standby,
+ .pwr_domain_on = zynqmp_pwr_domain_on,
+ .pwr_domain_off = zynqmp_pwr_domain_off,
+ .pwr_domain_suspend = zynqmp_pwr_domain_suspend,
+ .pwr_domain_on_finish = zynqmp_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = zynqmp_pwr_domain_suspend_finish,
+ .system_off = zynqmp_system_off,
+ .system_reset = zynqmp_system_reset,
+ .validate_power_state = zynqmp_validate_power_state,
+ .get_sys_suspend_power_state = zynqmp_get_sys_suspend_power_state,
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ zynqmp_sec_entry = sec_entrypoint;
+
+ *psci_ops = &zynqmp_psci_ops;
+
+ return 0;
+}
diff --git a/plat/xilinx/zynqmp/plat_topology.c b/plat/xilinx/zynqmp/plat_topology.c
new file mode 100644
index 0000000..41add9f
--- /dev/null
+++ b/plat/xilinx/zynqmp/plat_topology.c
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdint.h>
+
+static const uint8_t plat_power_domain_tree_desc[] = {1, 4};
+
+const uint8_t *plat_get_power_domain_tree_desc(void)
+{
+ return plat_power_domain_tree_desc;
+}
diff --git a/plat/xilinx/zynqmp/plat_zynqmp.c b/plat/xilinx/zynqmp/plat_zynqmp.c
new file mode 100644
index 0000000..25ebac6
--- /dev/null
+++ b/plat/xilinx/zynqmp/plat_zynqmp.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_private.h>
+#include <plat/common/platform.h>
+
+int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ if (mpidr & MPIDR_CLUSTER_MASK) {
+ return -1;
+ }
+
+ if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) {
+ return -1;
+ }
+
+ return zynqmp_calc_core_pos(mpidr);
+}
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
new file mode 100644
index 0000000..05adbd0
--- /dev/null
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -0,0 +1,143 @@
+#
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+# Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+override ERRATA_A53_855873 := 1
+override PROGRAMMABLE_RESET_ADDRESS := 1
+PSCI_EXTENDED_STATE_ID := 1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+SEPARATE_CODE_AND_RODATA := 1
+ZYNQMP_WDT_RESTART := 0
+IPI_CRC_CHECK := 0
+override RESET_TO_BL31 := 1
+override WARMBOOT_ENABLE_DCACHE_EARLY := 1
+
+EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT)
+
+# pncd SPD requires secure SGI to be handled at EL1
+ifeq (${SPD},pncd)
+ifeq (${ZYNQMP_WDT_RESTART},1)
+$(error "Error: ZYNQMP_WDT_RESTART and SPD=pncd are incompatible")
+endif
+override GICV2_G0_FOR_EL3 := 0
+else
+override GICV2_G0_FOR_EL3 := 1
+endif
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+WORKAROUND_CVE_2017_5715 := 0
+
+ARM_XLAT_TABLES_LIB_V1 := 1
+$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
+$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
+
+ifdef ZYNQMP_ATF_MEM_BASE
+ $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))
+
+ ifndef ZYNQMP_ATF_MEM_SIZE
+ $(error "ZYNQMP_ATF_BASE defined without ZYNQMP_ATF_SIZE")
+ endif
+ $(eval $(call add_define,ZYNQMP_ATF_MEM_SIZE))
+
+ ifdef ZYNQMP_ATF_MEM_PROGBITS_SIZE
+ $(eval $(call add_define,ZYNQMP_ATF_MEM_PROGBITS_SIZE))
+ endif
+endif
+
+ifdef ZYNQMP_BL32_MEM_BASE
+ $(eval $(call add_define,ZYNQMP_BL32_MEM_BASE))
+
+ ifndef ZYNQMP_BL32_MEM_SIZE
+ $(error "ZYNQMP_BL32_BASE defined without ZYNQMP_BL32_SIZE")
+ endif
+ $(eval $(call add_define,ZYNQMP_BL32_MEM_SIZE))
+endif
+
+
+ifdef ZYNQMP_WDT_RESTART
+ $(eval $(call add_define,ZYNQMP_WDT_RESTART))
+endif
+
+ifdef ZYNQMP_IPI_CRC_CHECK
+ $(warning "ZYNQMP_IPI_CRC_CHECK macro is deprecated...instead please use IPI_CRC_CHECK.")
+endif
+
+ifdef IPI_CRC_CHECK
+ $(eval $(call add_define,IPI_CRC_CHECK))
+endif
+
+ifdef ZYNQMP_SECURE_EFUSES
+ $(eval $(call add_define,ZYNQMP_SECURE_EFUSES))
+endif
+
+PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
+ -Iinclude/plat/arm/common/aarch64/ \
+ -Iplat/xilinx/common/include/ \
+ -Iplat/xilinx/common/ipi_mailbox_service/ \
+ -Iplat/xilinx/zynqmp/include/ \
+ -Iplat/xilinx/zynqmp/pm_service/ \
+
+include lib/libfdt/libfdt.mk
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
+ lib/xlat_tables/aarch64/xlat_tables.c \
+ drivers/arm/dcc/dcc_console.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ ${GICV2_SOURCES} \
+ drivers/cadence/uart/aarch64/cdns_console.S \
+ plat/arm/common/arm_cci.c \
+ plat/arm/common/arm_common.c \
+ plat/arm/common/arm_gicv2.c \
+ plat/common/plat_gicv2.c \
+ plat/xilinx/common/ipi.c \
+ plat/xilinx/zynqmp/zynqmp_ipi.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S \
+ plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+
+ZYNQMP_CONSOLE ?= cadence
+ifeq (${ZYNQMP_CONSOLE}, $(filter ${ZYNQMP_CONSOLE},cadence cadence0 cadence1 dcc))
+else
+ $(error "Please define ZYNQMP_CONSOLE")
+endif
+$(eval $(call add_define_val,ZYNQMP_CONSOLE,ZYNQMP_CONSOLE_ID_${ZYNQMP_CONSOLE}))
+
+BL31_SOURCES += drivers/arm/cci/cci.c \
+ lib/cpus/aarch64/aem_generic.S \
+ lib/cpus/aarch64/cortex_a53.S \
+ plat/common/plat_psci_common.c \
+ common/fdt_fixup.c \
+ ${LIBFDT_SRCS} \
+ plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \
+ plat/xilinx/common/pm_service/pm_ipi.c \
+ plat/xilinx/common/plat_startup.c \
+ plat/xilinx/zynqmp/bl31_zynqmp_setup.c \
+ plat/xilinx/zynqmp/plat_psci.c \
+ plat/xilinx/zynqmp/plat_zynqmp.c \
+ plat/xilinx/zynqmp/plat_topology.c \
+ plat/xilinx/zynqmp/sip_svc_setup.c \
+ plat/xilinx/zynqmp/pm_service/pm_svc_main.c \
+ plat/xilinx/zynqmp/pm_service/pm_api_sys.c \
+ plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c \
+ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c \
+ plat/xilinx/zynqmp/pm_service/pm_api_clock.c \
+ plat/xilinx/zynqmp/pm_service/pm_client.c
+
+ifeq (${SDEI_SUPPORT},1)
+BL31_SOURCES += plat/xilinx/zynqmp/zynqmp_ehf.c \
+ plat/xilinx/zynqmp/zynqmp_sdei.c
+endif
+
+BL31_CPPFLAGS += -fno-jump-tables
+TF_CFLAGS_aarch64 += -mbranch-protection=none
+
+ifneq (${RESET_TO_BL31},1)
+ $(error "Using BL31 as the reset vector is only one option supported on ZynqMP. Please set RESET_TO_BL31 to 1.")
+endif
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
new file mode 100644
index 0000000..e61310a
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -0,0 +1,3048 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for clock control.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+
+#include "pm_api_clock.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+
+#define CLK_NODE_MAX (6U)
+
+#define CLK_PARENTS_ID_LEN (16U)
+#define CLK_TOPOLOGY_NODE_OFFSET (16U)
+#define CLK_TOPOLOGY_PAYLOAD_LEN (12U)
+#define CLK_PARENTS_PAYLOAD_LEN (12U)
+#define CLK_TYPE_SHIFT (2U)
+#define CLK_CLKFLAGS_SHIFT (8U)
+#define CLK_TYPEFLAGS_SHIFT (24U)
+#define CLK_TYPEFLAGS2_SHIFT (4U)
+#define CLK_TYPEFLAGS_BITS_MASK (0xFFU)
+#define CLK_TYPEFLAGS2_BITS_MASK (0x0F00U)
+#define CLK_TYPEFLAGS_BITS (8U)
+
+#define CLK_EXTERNAL_PARENT (PARENT_CLK_EXTERNAL << CLK_PARENTS_ID_LEN)
+
+#define NA_MULT (0U)
+#define NA_DIV (0U)
+#define NA_SHIFT (0U)
+#define NA_WIDTH (0U)
+#define NA_CLK_FLAGS (0U)
+#define NA_TYPE_FLAGS (0U)
+
+/* PLL nodes related definitions */
+#define PLL_PRESRC_MUX_SHIFT (20U)
+#define PLL_PRESRC_MUX_WIDTH (3U)
+#define PLL_POSTSRC_MUX_SHIFT (24U)
+#define PLL_POSTSRC_MUX_WIDTH (3U)
+#define PLL_DIV2_MUX_SHIFT (16U)
+#define PLL_DIV2_MUX_WIDTH (1U)
+#define PLL_BYPASS_MUX_SHIFT (3U)
+#define PLL_BYPASS_MUX_WIDTH (1U)
+
+/* Peripheral nodes related definitions */
+/* Peripheral Clocks */
+#define PERIPH_MUX_SHIFT (0U)
+#define PERIPH_MUX_WIDTH (3U)
+#define PERIPH_DIV1_SHIFT (8U)
+#define PERIPH_DIV1_WIDTH (6U)
+#define PERIPH_DIV2_SHIFT (16U)
+#define PERIPH_DIV2_WIDTH (6U)
+#define PERIPH_GATE_SHIFT (24U)
+#define PERIPH_GATE_WIDTH (1U)
+
+#define USB_GATE_SHIFT (25U)
+
+/* External clock related definitions */
+
+#define EXT_CLK_MIO_DATA(mio) \
+ [EXT_CLK_INDEX(EXT_CLK_MIO##mio)] = { \
+ .name = "mio_clk_"#mio, \
+ }
+
+#define EXT_CLK_INDEX(n) (n - CLK_MAX_OUTPUT_CLK)
+
+/* Clock control related definitions */
+#define BIT_MASK(x, y) (((1U << (y)) - 1) << (x))
+
+#define ISPLL(id) (id == CLK_APLL_INT || \
+ id == CLK_DPLL_INT || \
+ id == CLK_VPLL_INT || \
+ id == CLK_IOPLL_INT || \
+ id == CLK_RPLL_INT)
+
+
+#define PLLCTRL_BP_MASK BIT(3)
+#define PLLCTRL_RESET_MASK (1U)
+#define PLL_FRAC_OFFSET (8U)
+#define PLL_FRAC_MODE (1U)
+#define PLL_INT_MODE (0U)
+#define PLL_FRAC_MODE_MASK (0x80000000U)
+#define PLL_FRAC_MODE_SHIFT (31U)
+#define PLL_FRAC_DATA_MASK (0xFFFFU)
+#define PLL_FRAC_DATA_SHIFT (0U)
+#define PLL_FBDIV_MASK (0x7F00U)
+#define PLL_FBDIV_WIDTH (7U)
+#define PLL_FBDIV_SHIFT (8U)
+
+#define CLK_PLL_RESET_ASSERT (1U)
+#define CLK_PLL_RESET_RELEASE (2U)
+#define CLK_PLL_RESET_PULSE (CLK_PLL_RESET_ASSERT | CLK_PLL_RESET_RELEASE)
+
+/* Common topology definitions */
+#define GENERIC_MUX \
+ { \
+ .type = TYPE_MUX, \
+ .offset = PERIPH_MUX_SHIFT, \
+ .width = PERIPH_MUX_WIDTH, \
+ .clkflags = CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define IGNORE_UNUSED_MUX \
+ { \
+ .type = TYPE_MUX, \
+ .offset = PERIPH_MUX_SHIFT, \
+ .width = PERIPH_MUX_WIDTH, \
+ .clkflags = CLK_IGNORE_UNUSED | \
+ CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define GENERIC_DIV1 \
+ { \
+ .type = TYPE_DIV1, \
+ .offset = PERIPH_DIV1_SHIFT, \
+ .width = PERIPH_DIV1_WIDTH, \
+ .clkflags = CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = CLK_DIVIDER_ONE_BASED | \
+ CLK_DIVIDER_ALLOW_ZERO, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define GENERIC_DIV2 \
+ { \
+ .type = TYPE_DIV2, \
+ .offset = PERIPH_DIV2_SHIFT, \
+ .width = PERIPH_DIV2_WIDTH, \
+ .clkflags = CLK_SET_RATE_NO_REPARENT | \
+ CLK_SET_RATE_PARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = CLK_DIVIDER_ONE_BASED | \
+ CLK_DIVIDER_ALLOW_ZERO, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define IGNORE_UNUSED_DIV(id) \
+ { \
+ .type = TYPE_DIV##id, \
+ .offset = PERIPH_DIV##id##_SHIFT, \
+ .width = PERIPH_DIV##id##_WIDTH, \
+ .clkflags = CLK_IGNORE_UNUSED | \
+ CLK_SET_RATE_NO_REPARENT | \
+ CLK_IS_BASIC, \
+ .typeflags = CLK_DIVIDER_ONE_BASED | \
+ CLK_DIVIDER_ALLOW_ZERO, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define GENERIC_GATE \
+ { \
+ .type = TYPE_GATE, \
+ .offset = PERIPH_GATE_SHIFT, \
+ .width = PERIPH_GATE_WIDTH, \
+ .clkflags = CLK_SET_RATE_PARENT | \
+ CLK_SET_RATE_GATE | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+#define IGNORE_UNUSED_GATE \
+ { \
+ .type = TYPE_GATE, \
+ .offset = PERIPH_GATE_SHIFT, \
+ .width = PERIPH_GATE_WIDTH, \
+ .clkflags = CLK_SET_RATE_PARENT | \
+ CLK_IGNORE_UNUSED | \
+ CLK_IS_BASIC, \
+ .typeflags = NA_TYPE_FLAGS, \
+ .mult = NA_MULT, \
+ .div = NA_DIV, \
+ }
+
+/**
+ * struct pm_clock_node - Clock topology node information
+ * @type: Topology type (mux/div1/div2/gate/pll/fixed factor)
+ * @offset: Offset in control register
+ * @width: Width of the specific type in control register
+ * @clkflags: Clk specific flags
+ * @typeflags: Type specific flags
+ * @mult: Multiplier for fixed factor
+ * @div: Divisor for fixed factor
+ */
+struct pm_clock_node {
+ uint16_t clkflags;
+ uint16_t typeflags;
+ uint8_t type;
+ uint8_t offset;
+ uint8_t width;
+ uint8_t mult:4;
+ uint8_t div:4;
+};
+
+/**
+ * struct pm_clock - Clock structure
+ * @name: Clock name
+ * @control_reg: Control register address
+ * @status_reg: Status register address
+ * @parents: Parents for first clock node. Lower byte indicates parent
+ * clock id and upper byte indicate flags for that id.
+ * pm_clock_node: Clock nodes
+ */
+struct pm_clock {
+ char name[CLK_NAME_LEN];
+ uint8_t num_nodes;
+ uint32_t control_reg;
+ uint32_t status_reg;
+ int32_t (*parents)[];
+ struct pm_clock_node(*nodes)[];
+};
+
+/**
+ * struct pm_clock - Clock structure
+ * @name: Clock name
+ */
+struct pm_ext_clock {
+ char name[CLK_NAME_LEN];
+};
+
+/* PLL Clocks */
+static struct pm_clock_node generic_pll_nodes[] = {
+ {
+ .type = TYPE_PLL,
+ .offset = NA_SHIFT,
+ .width = NA_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node ignore_unused_pll_nodes[] = {
+ {
+ .type = TYPE_PLL,
+ .offset = NA_SHIFT,
+ .width = NA_WIDTH,
+ .clkflags = CLK_IGNORE_UNUSED | CLK_SET_RATE_NO_REPARENT,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_pre_src_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_PRESRC_MUX_SHIFT,
+ .width = PLL_PRESRC_MUX_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_half_nodes[] = {
+ {
+ .type = TYPE_FIXEDFACTOR,
+ .offset = NA_SHIFT,
+ .width = NA_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = 1,
+ .div = 2,
+ },
+};
+
+static struct pm_clock_node generic_pll_int_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_DIV2_MUX_SHIFT,
+ .width = PLL_DIV2_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT |
+ CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_post_src_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_POSTSRC_MUX_SHIFT,
+ .width = PLL_POSTSRC_MUX_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_pll_system_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PLL_BYPASS_MUX_SHIFT,
+ .width = PLL_BYPASS_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT |
+ CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node acpu_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PERIPH_MUX_SHIFT,
+ .width = PERIPH_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV1,
+ .offset = PERIPH_DIV1_SHIFT,
+ .width = PERIPH_DIV1_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_mux_div_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV1,
+};
+
+static struct pm_clock_node generic_mux_div_gate_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV1,
+ GENERIC_GATE,
+};
+
+static struct pm_clock_node generic_mux_div_unused_gate_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV1,
+ IGNORE_UNUSED_GATE,
+};
+
+static struct pm_clock_node generic_mux_div_div_gate_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV1,
+ GENERIC_DIV2,
+ GENERIC_GATE,
+};
+
+static struct pm_clock_node dp_audio_video_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = PERIPH_MUX_SHIFT,
+ .width = PERIPH_MUX_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT |
+ CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = CLK_FRAC,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV1,
+ .offset = PERIPH_DIV1_SHIFT,
+ .width = PERIPH_DIV1_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
+ CLK_FRAC,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV2,
+ .offset = PERIPH_DIV2_SHIFT,
+ .width = PERIPH_DIV2_WIDTH,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
+ CLK_FRAC,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = PERIPH_GATE_SHIFT,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_GATE |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node usb_nodes[] = {
+ GENERIC_MUX,
+ GENERIC_DIV1,
+ GENERIC_DIV2,
+ {
+ .type = TYPE_GATE,
+ .offset = USB_GATE_SHIFT,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC |
+ CLK_SET_RATE_GATE,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node generic_domain_crossing_nodes[] = {
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node rpll_to_fpd_nodes[] = {
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node acpu_half_nodes[] = {
+ {
+ .type = TYPE_FIXEDFACTOR,
+ .offset = 0,
+ .width = 1,
+ .clkflags = 0,
+ .typeflags = 0,
+ .mult = 1,
+ .div = 2,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_IGNORE_UNUSED |
+ CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node acpu_full_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 24,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_IGNORE_UNUSED |
+ CLK_SET_RATE_PARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node wdt_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 0,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node ddr_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC | CLK_IS_CRITICAL,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node pl_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = PERIPH_DIV1_SHIFT,
+ .width = PERIPH_DIV1_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV2,
+ .offset = PERIPH_DIV2_SHIFT,
+ .width = PERIPH_DIV2_WIDTH,
+ .clkflags = CLK_IS_BASIC | CLK_SET_RATE_PARENT,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_GATE,
+ .offset = PERIPH_GATE_SHIFT,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gpu_pp0_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gpu_pp1_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 26,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem_ref_ungated_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ {
+ .type = TYPE_DIV2,
+ .offset = 16,
+ .width = 6,
+ .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC |
+ CLK_SET_RATE_PARENT,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem0_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 1,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem1_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 6,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem2_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 11,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem3_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 16,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem_tx_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem_rx_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 26,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node gem_tsu_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 20,
+ .width = 2,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can0_mio_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 0,
+ .width = 7,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can1_mio_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 15,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can0_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 7,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node can1_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 22,
+ .width = 1,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node cpu_r5_core_nodes[] = {
+ {
+ .type = TYPE_GATE,
+ .offset = 25,
+ .width = PERIPH_GATE_WIDTH,
+ .clkflags = CLK_IGNORE_UNUSED |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node dll_ref_nodes[] = {
+ {
+ .type = TYPE_MUX,
+ .offset = 0,
+ .width = 3,
+ .clkflags = CLK_SET_RATE_PARENT |
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_IS_BASIC,
+ .typeflags = NA_TYPE_FLAGS,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+};
+
+static struct pm_clock_node timestamp_ref_nodes[] = {
+ GENERIC_MUX,
+ {
+ .type = TYPE_DIV1,
+ .offset = 8,
+ .width = 6,
+ .clkflags = CLK_IS_BASIC,
+ .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ .mult = NA_MULT,
+ .div = NA_DIV,
+ },
+ IGNORE_UNUSED_GATE,
+};
+
+static int32_t can_mio_parents[] = {
+ EXT_CLK_MIO0, EXT_CLK_MIO1, EXT_CLK_MIO2, EXT_CLK_MIO3,
+ EXT_CLK_MIO4, EXT_CLK_MIO5, EXT_CLK_MIO6, EXT_CLK_MIO7,
+ EXT_CLK_MIO8, EXT_CLK_MIO9, EXT_CLK_MIO10, EXT_CLK_MIO11,
+ EXT_CLK_MIO12, EXT_CLK_MIO13, EXT_CLK_MIO14, EXT_CLK_MIO15,
+ EXT_CLK_MIO16, EXT_CLK_MIO17, EXT_CLK_MIO18, EXT_CLK_MIO19,
+ EXT_CLK_MIO20, EXT_CLK_MIO21, EXT_CLK_MIO22, EXT_CLK_MIO23,
+ EXT_CLK_MIO24, EXT_CLK_MIO25, EXT_CLK_MIO26, EXT_CLK_MIO27,
+ EXT_CLK_MIO28, EXT_CLK_MIO29, EXT_CLK_MIO30, EXT_CLK_MIO31,
+ EXT_CLK_MIO32, EXT_CLK_MIO33, EXT_CLK_MIO34, EXT_CLK_MIO35,
+ EXT_CLK_MIO36, EXT_CLK_MIO37, EXT_CLK_MIO38, EXT_CLK_MIO39,
+ EXT_CLK_MIO40, EXT_CLK_MIO41, EXT_CLK_MIO42, EXT_CLK_MIO43,
+ EXT_CLK_MIO44, EXT_CLK_MIO45, EXT_CLK_MIO46, EXT_CLK_MIO47,
+ EXT_CLK_MIO48, EXT_CLK_MIO49, EXT_CLK_MIO50, EXT_CLK_MIO51,
+ EXT_CLK_MIO52, EXT_CLK_MIO53, EXT_CLK_MIO54, EXT_CLK_MIO55,
+ EXT_CLK_MIO56, EXT_CLK_MIO57, EXT_CLK_MIO58, EXT_CLK_MIO59,
+ EXT_CLK_MIO60, EXT_CLK_MIO61, EXT_CLK_MIO62, EXT_CLK_MIO63,
+ EXT_CLK_MIO64, EXT_CLK_MIO65, EXT_CLK_MIO66, EXT_CLK_MIO67,
+ EXT_CLK_MIO68, EXT_CLK_MIO69, EXT_CLK_MIO70, EXT_CLK_MIO71,
+ EXT_CLK_MIO72, EXT_CLK_MIO73, EXT_CLK_MIO74, EXT_CLK_MIO75,
+ EXT_CLK_MIO76, EXT_CLK_MIO77, CLK_NA_PARENT
+};
+
+/* Clock array containing clock informaton */
+static struct pm_clock clocks[] = {
+ [CLK_APLL_INT] = {
+ .name = "apll_int",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_APLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &ignore_unused_pll_nodes,
+ .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes),
+ },
+ [CLK_APLL_PRE_SRC] = {
+ .name = "apll_pre_src",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_APLL_HALF] = {
+ .name = "apll_half",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_APLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_APLL_INT_MUX] = {
+ .name = "apll_int_mux",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_APLL_INT,
+ CLK_APLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_APLL_POST_SRC] = {
+ .name = "apll_post_src",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_APLL] = {
+ .name = "apll",
+ .control_reg = CRF_APB_APLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_APLL_INT_MUX,
+ CLK_APLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_DPLL_INT] = {
+ .name = "dpll_int",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_DPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &generic_pll_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_nodes),
+ },
+ [CLK_DPLL_PRE_SRC] = {
+ .name = "dpll_pre_src",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_DPLL_HALF] = {
+ .name = "dpll_half",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_DPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_DPLL_INT_MUX] = {
+ .name = "dpll_int_mux",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_DPLL_INT,
+ CLK_DPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_DPLL_POST_SRC] = {
+ .name = "dpll_post_src",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_DPLL] = {
+ .name = "dpll",
+ .control_reg = CRF_APB_DPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_DPLL_INT_MUX,
+ CLK_DPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_VPLL_INT] = {
+ .name = "vpll_int",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_VPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &ignore_unused_pll_nodes,
+ .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes),
+ },
+ [CLK_VPLL_PRE_SRC] = {
+ .name = "vpll_pre_src",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_VPLL_HALF] = {
+ .name = "vpll_half",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_VPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_VPLL_INT_MUX] = {
+ .name = "vpll_int_mux",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_VPLL_INT,
+ CLK_VPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_VPLL_POST_SRC] = {
+ .name = "vpll_post_src",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_VPLL] = {
+ .name = "vpll",
+ .control_reg = CRF_APB_VPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_VPLL_INT_MUX,
+ CLK_VPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_IOPLL_INT] = {
+ .name = "iopll_int",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_IOPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &generic_pll_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_nodes),
+ },
+ [CLK_IOPLL_PRE_SRC] = {
+ .name = "iopll_pre_src",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_IOPLL_HALF] = {
+ .name = "iopll_half",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_IOPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_IOPLL_INT_MUX] = {
+ .name = "iopll_int_mux",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_INT,
+ CLK_IOPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_IOPLL_POST_SRC] = {
+ .name = "iopll_post_src",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_IOPLL] = {
+ .name = "iopll",
+ .control_reg = CRL_APB_IOPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_INT_MUX,
+ CLK_IOPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ [CLK_RPLL_INT] = {
+ .name = "rpll_int",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_RPLL_PRE_SRC, CLK_NA_PARENT}),
+ .nodes = &generic_pll_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_nodes),
+ },
+ [CLK_RPLL_PRE_SRC] = {
+ .name = "rpll_pre_src",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+
+ .nodes = &generic_pll_pre_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes),
+ },
+ [CLK_RPLL_HALF] = {
+ .name = "rpll_half",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {CLK_RPLL_INT, CLK_NA_PARENT}),
+ .nodes = &generic_pll_half_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_half_nodes),
+ },
+ [CLK_RPLL_INT_MUX] = {
+ .name = "rpll_int_mux",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_RPLL_INT,
+ CLK_RPLL_HALF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_int_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_int_nodes),
+ },
+ [CLK_RPLL_POST_SRC] = {
+ .name = "rpll_post_src",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRF_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_post_src_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes),
+ },
+ [CLK_RPLL] = {
+ .name = "rpll",
+ .control_reg = CRL_APB_RPLL_CTRL,
+ .status_reg = CRL_APB_PLL_STATUS,
+ .parents = &((int32_t []) {
+ CLK_RPLL_INT_MUX,
+ CLK_RPLL_POST_SRC,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_pll_system_nodes,
+ .num_nodes = ARRAY_SIZE(generic_pll_system_nodes),
+ },
+ /* Peripheral Clocks */
+ [CLK_ACPU] = {
+ .name = "acpu",
+ .control_reg = CRF_APB_ACPU_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_VPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &acpu_nodes,
+ .num_nodes = ARRAY_SIZE(acpu_nodes),
+ },
+ [CLK_ACPU_FULL] = {
+ .name = "acpu_full",
+ .control_reg = CRF_APB_ACPU_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_ACPU | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_NA_PARENT
+ }),
+ .nodes = &acpu_full_nodes,
+ .num_nodes = ARRAY_SIZE(acpu_full_nodes),
+ },
+ [CLK_DBG_TRACE] = {
+ .name = "dbg_trace",
+ .control_reg = CRF_APB_DBG_TRACE_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_APLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DBG_FPD] = {
+ .name = "dbg_fpd",
+ .control_reg = CRF_APB_DBG_FPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_APLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DBG_TSTMP] = {
+ .name = "dbg_tstmp",
+ .control_reg = CRF_APB_DBG_TSTMP_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_APLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_nodes),
+ },
+ [CLK_DP_VIDEO_REF] = {
+ .name = "dp_video_ref",
+ .control_reg = CRF_APB_DP_VIDEO_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_VPLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_RPLL_TO_FPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &dp_audio_video_ref_nodes,
+ .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes),
+ },
+ [CLK_DP_AUDIO_REF] = {
+ .name = "dp_audio_ref",
+ .control_reg = CRF_APB_DP_AUDIO_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_VPLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_RPLL_TO_FPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &dp_audio_video_ref_nodes,
+ .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes),
+ },
+ [CLK_DP_STC_REF] = {
+ .name = "dp_stc_ref",
+ .control_reg = CRF_APB_DP_STC_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_VPLL,
+ CLK_DUMMY_PARENT,
+ CLK_DPLL,
+ CLK_RPLL_TO_FPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_DPDMA_REF] = {
+ .name = "dpdma_ref",
+ .control_reg = CRF_APB_DPDMA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DDR_REF] = {
+ .name = "ddr_ref",
+ .control_reg = CRF_APB_DDR_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_DPLL,
+ CLK_VPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &ddr_nodes,
+ .num_nodes = ARRAY_SIZE(ddr_nodes),
+ },
+ [CLK_GPU_REF] = {
+ .name = "gpu_ref",
+ .control_reg = CRF_APB_GPU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_SATA_REF] = {
+ .name = "sata_ref",
+ .control_reg = CRF_APB_SATA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_APLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_PCIE_REF] = {
+ .name = "pcie_ref",
+ .control_reg = CRF_APB_PCIE_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL_TO_FPD,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_GDMA_REF] = {
+ .name = "gdma_ref",
+ .control_reg = CRF_APB_GDMA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_GTGREF0_REF] = {
+ .name = "gtgref0_ref",
+ .control_reg = CRF_APB_GTGREF0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL_TO_FPD,
+ CLK_DUMMY_PARENT,
+ CLK_APLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_TOPSW_MAIN] = {
+ .name = "topsw_main",
+ .control_reg = CRF_APB_TOPSW_MAIN_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_VPLL,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_TOPSW_LSBUS] = {
+ .name = "topsw_lsbus",
+ .control_reg = CRF_APB_TOPSW_LSBUS_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_APLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL_TO_FPD,
+ CLK_DPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_IOU_SWITCH] = {
+ .name = "iou_switch",
+ .control_reg = CRL_APB_IOU_SWITCH_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_GEM0_REF_UNGATED] = {
+ .name = "gem0_ref_ung",
+ .control_reg = CRL_APB_GEM0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_ref_ungated_nodes,
+ .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes),
+ },
+ [CLK_GEM1_REF_UNGATED] = {
+ .name = "gem1_ref_ung",
+ .control_reg = CRL_APB_GEM1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_ref_ungated_nodes,
+ .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes),
+ },
+ [CLK_GEM2_REF_UNGATED] = {
+ .name = "gem2_ref_ung",
+ .control_reg = CRL_APB_GEM2_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_ref_ungated_nodes,
+ .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes),
+ },
+ [CLK_GEM3_REF_UNGATED] = {
+ .name = "gem3_ref_ung",
+ .control_reg = CRL_APB_GEM3_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_ref_ungated_nodes,
+ .num_nodes = ARRAY_SIZE(gem_ref_ungated_nodes),
+ },
+ [CLK_GEM0_REF] = {
+ .name = "gem0_ref",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM0_REF_UNGATED |
+ (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM0_TX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem0_ref_nodes,
+ .num_nodes = ARRAY_SIZE(gem0_ref_nodes),
+ },
+ [CLK_GEM1_REF] = {
+ .name = "gem1_ref",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM1_REF_UNGATED |
+ (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM1_TX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem1_ref_nodes,
+ .num_nodes = ARRAY_SIZE(gem1_ref_nodes),
+ },
+ [CLK_GEM2_REF] = {
+ .name = "gem2_ref",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM2_REF_UNGATED |
+ (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM2_TX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem2_ref_nodes,
+ .num_nodes = ARRAY_SIZE(gem2_ref_nodes),
+ },
+ [CLK_GEM3_REF] = {
+ .name = "gem3_ref",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM3_REF_UNGATED |
+ (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN),
+ EXT_CLK_GEM3_TX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem3_ref_nodes,
+ .num_nodes = ARRAY_SIZE(gem3_ref_nodes),
+ },
+ [CLK_USB0_BUS_REF] = {
+ .name = "usb0_bus_ref",
+ .control_reg = CRL_APB_USB0_BUS_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &usb_nodes,
+ .num_nodes = ARRAY_SIZE(usb_nodes),
+ },
+ [CLK_USB1_BUS_REF] = {
+ .name = "usb1_bus_ref",
+ .control_reg = CRL_APB_USB1_BUS_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &usb_nodes,
+ .num_nodes = ARRAY_SIZE(usb_nodes),
+ },
+ [CLK_USB3_DUAL_REF] = {
+ .name = "usb3_dual_ref",
+ .control_reg = CRL_APB_USB3_DUAL_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &usb_nodes,
+ .num_nodes = ARRAY_SIZE(usb_nodes),
+ },
+ [CLK_QSPI_REF] = {
+ .name = "qspi_ref",
+ .control_reg = CRL_APB_QSPI_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SDIO0_REF] = {
+ .name = "sdio0_ref",
+ .control_reg = CRL_APB_SDIO0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_VPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SDIO1_REF] = {
+ .name = "sdio1_ref",
+ .control_reg = CRL_APB_SDIO1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_VPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_UART0_REF] = {
+ .name = "uart0_ref",
+ .control_reg = CRL_APB_UART0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_UART1_REF] = {
+ .name = "uart1_ref",
+ .control_reg = CRL_APB_UART1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SPI0_REF] = {
+ .name = "spi0_ref",
+ .control_reg = CRL_APB_SPI0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_SPI1_REF] = {
+ .name = "spi1_ref",
+ .control_reg = CRL_APB_SPI1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_CAN0_REF] = {
+ .name = "can0_ref",
+ .control_reg = CRL_APB_CAN0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_CAN1_REF] = {
+ .name = "can1_ref",
+ .control_reg = CRL_APB_CAN1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_NAND_REF] = {
+ .name = "nand_ref",
+ .control_reg = CRL_APB_NAND_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_GEM_TSU_REF] = {
+ .name = "gem_tsu_ref",
+ .control_reg = CRL_APB_GEM_TSU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_DLL_REF] = {
+ .name = "dll_ref",
+ .control_reg = CRL_APB_DLL_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_RPLL,
+ CLK_NA_PARENT
+ }),
+ .nodes = &dll_ref_nodes,
+ .num_nodes = ARRAY_SIZE(dll_ref_nodes),
+ },
+ [CLK_ADMA_REF] = {
+ .name = "adma_ref",
+ .control_reg = CRL_APB_ADMA_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_DBG_LPD] = {
+ .name = "dbg_lpd",
+ .control_reg = CRL_APB_DBG_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_CPU_R5] = {
+ .name = "cpu_r5",
+ .control_reg = CRL_APB_CPU_R5_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_CSU_PLL] = {
+ .name = "csu_pll",
+ .control_reg = CRL_APB_CSU_PLL_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_PCAP] = {
+ .name = "pcap",
+ .control_reg = CRL_APB_PCAP_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes),
+ },
+ [CLK_LPD_LSBUS] = {
+ .name = "lpd_lsbus",
+ .control_reg = CRL_APB_LPD_LSBUS_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_LPD_SWITCH] = {
+ .name = "lpd_switch",
+ .control_reg = CRL_APB_LPD_SWITCH_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_unused_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes),
+ },
+ [CLK_I2C0_REF] = {
+ .name = "i2c0_ref",
+ .control_reg = CRL_APB_I2C0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_I2C1_REF] = {
+ .name = "i2c1_ref",
+ .control_reg = CRL_APB_I2C1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_TIMESTAMP_REF] = {
+ .name = "timestamp_ref",
+ .control_reg = CRL_APB_TIMESTAMP_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &timestamp_ref_nodes,
+ .num_nodes = ARRAY_SIZE(timestamp_ref_nodes),
+ },
+ [CLK_PL0_REF] = {
+ .name = "pl0_ref",
+ .control_reg = CRL_APB_PL0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_PL1_REF] = {
+ .name = "pl1_ref",
+ .control_reg = CRL_APB_PL1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_PL2_REF] = {
+ .name = "pl2_ref",
+ .control_reg = CRL_APB_PL2_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_PL3_REF] = {
+ .name = "pl3_ref",
+ .control_reg = CRL_APB_PL3_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_IOPLL,
+ CLK_DUMMY_PARENT,
+ CLK_RPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &pl_nodes,
+ .num_nodes = ARRAY_SIZE(pl_nodes),
+ },
+ [CLK_AMS_REF] = {
+ .name = "ams_ref",
+ .control_reg = CRL_APB_AMS_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_RPLL,
+ CLK_DUMMY_PARENT,
+ CLK_IOPLL,
+ CLK_DPLL_TO_LPD,
+ CLK_NA_PARENT
+ }),
+ .nodes = &generic_mux_div_div_gate_nodes,
+ .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes),
+ },
+ [CLK_IOPLL_TO_FPD] = {
+ .name = "iopll_to_fpd",
+ .control_reg = CRL_APB_IOPLL_TO_FPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_IOPLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ [CLK_RPLL_TO_FPD] = {
+ .name = "rpll_to_fpd",
+ .control_reg = CRL_APB_RPLL_TO_FPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_RPLL, CLK_NA_PARENT}),
+ .nodes = &rpll_to_fpd_nodes,
+ .num_nodes = ARRAY_SIZE(rpll_to_fpd_nodes),
+ },
+ [CLK_APLL_TO_LPD] = {
+ .name = "apll_to_lpd",
+ .control_reg = CRF_APB_APLL_TO_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_APLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ [CLK_DPLL_TO_LPD] = {
+ .name = "dpll_to_lpd",
+ .control_reg = CRF_APB_DPLL_TO_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_DPLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ [CLK_VPLL_TO_LPD] = {
+ .name = "vpll_to_lpd",
+ .control_reg = CRF_APB_VPLL_TO_LPD_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {CLK_VPLL, CLK_NA_PARENT}),
+ .nodes = &generic_domain_crossing_nodes,
+ .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes),
+ },
+ [CLK_GEM0_TX] = {
+ .name = "gem0_tx",
+ .control_reg = CRL_APB_GEM0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM0_REF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_tx_nodes),
+ },
+ [CLK_GEM1_TX] = {
+ .name = "gem1_tx",
+ .control_reg = CRL_APB_GEM1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM1_REF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_tx_nodes),
+ },
+ [CLK_GEM2_TX] = {
+ .name = "gem2_tx",
+ .control_reg = CRL_APB_GEM2_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM2_REF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_tx_nodes),
+ },
+ [CLK_GEM3_TX] = {
+ .name = "gem3_tx",
+ .control_reg = CRL_APB_GEM3_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM3_REF,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_tx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_tx_nodes),
+ },
+ [CLK_GEM0_RX] = {
+ .name = "gem0_rx",
+ .control_reg = CRL_APB_GEM0_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ EXT_CLK_GEM0_RX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_rx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_rx_nodes),
+ },
+ [CLK_GEM1_RX] = {
+ .name = "gem1_rx",
+ .control_reg = CRL_APB_GEM1_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ EXT_CLK_GEM1_RX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_rx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_rx_nodes),
+ },
+ [CLK_GEM2_RX] = {
+ .name = "gem2_rx",
+ .control_reg = CRL_APB_GEM2_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ EXT_CLK_GEM2_RX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_rx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_rx_nodes),
+ },
+ [CLK_GEM3_RX] = {
+ .name = "gem3_rx",
+ .control_reg = CRL_APB_GEM3_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ EXT_CLK_GEM3_RX_EMIO | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_rx_nodes,
+ .num_nodes = ARRAY_SIZE(gem_rx_nodes),
+ },
+ [CLK_ACPU_HALF] = {
+ .name = "acpu_half",
+ .control_reg = CRF_APB_ACPU_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_ACPU | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_NA_PARENT
+ }),
+ .nodes = &acpu_half_nodes,
+ .num_nodes = ARRAY_SIZE(acpu_half_nodes),
+ },
+ [CLK_FPD_WDT] = {
+ .name = "fpd_wdt",
+ .control_reg = FPD_SLCR_WDT_CLK_SEL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_TOPSW_LSBUS,
+ EXT_CLK_SWDT0 | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &wdt_nodes,
+ .num_nodes = ARRAY_SIZE(wdt_nodes),
+ },
+ [CLK_GPU_PP0_REF] = {
+ .name = "gpu_pp0_ref",
+ .control_reg = CRF_APB_GPU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gpu_pp0_nodes,
+ .num_nodes = ARRAY_SIZE(gpu_pp0_nodes),
+ },
+ [CLK_GPU_PP1_REF] = {
+ .name = "gpu_pp1_ref",
+ .control_reg = CRF_APB_GPU_REF_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gpu_pp1_nodes,
+ .num_nodes = ARRAY_SIZE(gpu_pp1_nodes),
+ },
+ [CLK_GEM_TSU] = {
+ .name = "gem_tsu",
+ .control_reg = IOU_SLCR_GEM_CLK_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_GEM_TSU_REF,
+ CLK_GEM_TSU_REF,
+ EXT_CLK_MIO26 | CLK_EXTERNAL_PARENT,
+ EXT_CLK_MIO50_OR_MIO51 | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &gem_tsu_nodes,
+ .num_nodes = ARRAY_SIZE(gem_tsu_nodes),
+ },
+ [CLK_CPU_R5_CORE] = {
+ .name = "cpu_r5_core",
+ .control_reg = CRL_APB_CPU_R5_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_CPU_R5 | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN,
+ CLK_DUMMY_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &cpu_r5_core_nodes,
+ .num_nodes = ARRAY_SIZE(cpu_r5_core_nodes),
+ },
+ [CLK_CAN0_MIO] = {
+ .name = "can0_mio",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &can_mio_parents,
+ .nodes = &can0_mio_nodes,
+ .num_nodes = ARRAY_SIZE(can0_mio_nodes),
+ },
+ [CLK_CAN1_MIO] = {
+ .name = "can1_mio",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &can_mio_parents,
+ .nodes = &can1_mio_nodes,
+ .num_nodes = ARRAY_SIZE(can1_mio_nodes),
+ },
+ [CLK_CAN0] = {
+ .name = "can0",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_CAN0_REF,
+ CLK_CAN0_MIO,
+ CLK_NA_PARENT
+ }),
+ .nodes = &can0_nodes,
+ .num_nodes = ARRAY_SIZE(can0_nodes),
+ },
+ [CLK_CAN1] = {
+ .name = "can1",
+ .control_reg = IOU_SLCR_CAN_MIO_CTRL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_CAN1_REF,
+ CLK_CAN1_MIO,
+ CLK_NA_PARENT
+ }),
+ .nodes = &can1_nodes,
+ .num_nodes = ARRAY_SIZE(can1_nodes),
+ },
+ [CLK_LPD_WDT] = {
+ .name = "lpd_wdt",
+ .control_reg = IOU_SLCR_WDT_CLK_SEL,
+ .status_reg = 0,
+ .parents = &((int32_t []) {
+ CLK_LPD_LSBUS,
+ EXT_CLK_SWDT1 | CLK_EXTERNAL_PARENT,
+ CLK_NA_PARENT
+ }),
+ .nodes = &wdt_nodes,
+ .num_nodes = ARRAY_SIZE(wdt_nodes),
+ },
+};
+
+static struct pm_ext_clock ext_clocks[] = {
+ [EXT_CLK_INDEX(EXT_CLK_PSS_REF)] = {
+ .name = "pss_ref_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_VIDEO)] = {
+ .name = "video_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_PSS_ALT_REF)] = {
+ .name = "pss_alt_ref_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_AUX_REF)] = {
+ .name = "aux_ref_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GT_CRX_REF)] = {
+ .name = "video_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_SWDT0)] = {
+ .name = "swdt0_ext_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_SWDT1)] = {
+ .name = "swdt1_ext_clk",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM0_TX_EMIO)] = {
+ .name = "gem0_tx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM1_TX_EMIO)] = {
+ .name = "gem1_tx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM2_TX_EMIO)] = {
+ .name = "gem2_tx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM3_TX_EMIO)] = {
+ .name = "gem3_tx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM0_RX_EMIO)] = {
+ .name = "gem0_rx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM1_RX_EMIO)] = {
+ .name = "gem1_rx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM2_RX_EMIO)] = {
+ .name = "gem2_rx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_GEM3_RX_EMIO)] = {
+ .name = "gem3_rx_ext",
+ },
+ [EXT_CLK_INDEX(EXT_CLK_MIO50_OR_MIO51)] = {
+ .name = "mio_clk_50_51",
+ },
+ EXT_CLK_MIO_DATA(0),
+ EXT_CLK_MIO_DATA(1),
+ EXT_CLK_MIO_DATA(2),
+ EXT_CLK_MIO_DATA(3),
+ EXT_CLK_MIO_DATA(4),
+ EXT_CLK_MIO_DATA(5),
+ EXT_CLK_MIO_DATA(6),
+ EXT_CLK_MIO_DATA(7),
+ EXT_CLK_MIO_DATA(8),
+ EXT_CLK_MIO_DATA(9),
+ EXT_CLK_MIO_DATA(10),
+ EXT_CLK_MIO_DATA(11),
+ EXT_CLK_MIO_DATA(12),
+ EXT_CLK_MIO_DATA(13),
+ EXT_CLK_MIO_DATA(14),
+ EXT_CLK_MIO_DATA(15),
+ EXT_CLK_MIO_DATA(16),
+ EXT_CLK_MIO_DATA(17),
+ EXT_CLK_MIO_DATA(18),
+ EXT_CLK_MIO_DATA(19),
+ EXT_CLK_MIO_DATA(20),
+ EXT_CLK_MIO_DATA(21),
+ EXT_CLK_MIO_DATA(22),
+ EXT_CLK_MIO_DATA(23),
+ EXT_CLK_MIO_DATA(24),
+ EXT_CLK_MIO_DATA(25),
+ EXT_CLK_MIO_DATA(26),
+ EXT_CLK_MIO_DATA(27),
+ EXT_CLK_MIO_DATA(28),
+ EXT_CLK_MIO_DATA(29),
+ EXT_CLK_MIO_DATA(30),
+ EXT_CLK_MIO_DATA(31),
+ EXT_CLK_MIO_DATA(32),
+ EXT_CLK_MIO_DATA(33),
+ EXT_CLK_MIO_DATA(34),
+ EXT_CLK_MIO_DATA(35),
+ EXT_CLK_MIO_DATA(36),
+ EXT_CLK_MIO_DATA(37),
+ EXT_CLK_MIO_DATA(38),
+ EXT_CLK_MIO_DATA(39),
+ EXT_CLK_MIO_DATA(40),
+ EXT_CLK_MIO_DATA(41),
+ EXT_CLK_MIO_DATA(42),
+ EXT_CLK_MIO_DATA(43),
+ EXT_CLK_MIO_DATA(44),
+ EXT_CLK_MIO_DATA(45),
+ EXT_CLK_MIO_DATA(46),
+ EXT_CLK_MIO_DATA(47),
+ EXT_CLK_MIO_DATA(48),
+ EXT_CLK_MIO_DATA(49),
+ EXT_CLK_MIO_DATA(50),
+ EXT_CLK_MIO_DATA(51),
+ EXT_CLK_MIO_DATA(52),
+ EXT_CLK_MIO_DATA(53),
+ EXT_CLK_MIO_DATA(54),
+ EXT_CLK_MIO_DATA(55),
+ EXT_CLK_MIO_DATA(56),
+ EXT_CLK_MIO_DATA(57),
+ EXT_CLK_MIO_DATA(58),
+ EXT_CLK_MIO_DATA(59),
+ EXT_CLK_MIO_DATA(60),
+ EXT_CLK_MIO_DATA(61),
+ EXT_CLK_MIO_DATA(62),
+ EXT_CLK_MIO_DATA(63),
+ EXT_CLK_MIO_DATA(64),
+ EXT_CLK_MIO_DATA(65),
+ EXT_CLK_MIO_DATA(66),
+ EXT_CLK_MIO_DATA(67),
+ EXT_CLK_MIO_DATA(68),
+ EXT_CLK_MIO_DATA(69),
+ EXT_CLK_MIO_DATA(70),
+ EXT_CLK_MIO_DATA(71),
+ EXT_CLK_MIO_DATA(72),
+ EXT_CLK_MIO_DATA(73),
+ EXT_CLK_MIO_DATA(74),
+ EXT_CLK_MIO_DATA(75),
+ EXT_CLK_MIO_DATA(76),
+ EXT_CLK_MIO_DATA(77),
+};
+
+/* Array of clock which are invalid for this variant */
+static uint32_t pm_clk_invalid_list[] = {CLK_USB0, CLK_USB1, CLK_CSU_SPB,
+ CLK_ACPU_FULL,
+ CLK_ACPU_HALF,
+ CLK_APLL_TO_LPD,
+ CLK_DBG_FPD,
+ CLK_DBG_LPD,
+ CLK_DBG_TRACE,
+ CLK_DBG_TSTMP,
+ CLK_DDR_REF,
+ CLK_TOPSW_MAIN,
+ CLK_GTGREF0_REF,
+ CLK_LPD_SWITCH,
+ CLK_CPU_R5,
+ CLK_CPU_R5_CORE,
+ CLK_CSU_SPB,
+ CLK_CSU_PLL,
+ CLK_PCAP,
+ CLK_IOU_SWITCH,
+ CLK_DLL_REF,
+ CLK_TIMESTAMP_REF,
+};
+
+/**
+ * pm_clock_valid - Check if clock is valid or not
+ * @clock_id Id of the clock to be queried
+ *
+ * This function is used to check if given clock is valid
+ * or not for the chip variant.
+ *
+ * List of invalid clocks are maintained in array list for
+ * different variants.
+ *
+ * Return: Returns 1 if clock is valid else 0.
+ */
+static bool pm_clock_valid(uint32_t clock_id)
+{
+ unsigned int i;
+
+ for (i = 0U; i < ARRAY_SIZE(pm_clk_invalid_list); i++)
+ if (pm_clk_invalid_list[i] == clock_id)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * pm_clock_type - Get clock's type
+ * @clock_id Id of the clock to be queried
+ *
+ * This function is used to check type of clock (OUTPUT/EXTERNAL).
+ *
+ * Return: Returns type of clock (OUTPUT/EXTERNAL).
+ */
+static uint32_t pm_clock_type(uint32_t clock_id)
+{
+ return (clock_id < CLK_MAX_OUTPUT_CLK) ?
+ CLK_TYPE_OUTPUT : CLK_TYPE_EXTERNAL;
+}
+
+/**
+ * pm_api_clock_get_num_clocks() - PM call to request number of clocks
+ * @nclocks Number of clocks
+ *
+ * This function is used by master to get number of clocks.
+ *
+ * @return Returns success.
+ */
+enum pm_ret_status pm_api_clock_get_num_clocks(uint32_t *nclocks)
+{
+ *nclocks = CLK_MAX;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_name() - PM call to request a clock's name
+ * @clock_id Clock ID
+ * @name Name of clock (max 16 bytes)
+ *
+ * This function is used by master to get nmae of clock specified
+ * by given clock ID.
+ */
+void pm_api_clock_get_name(uint32_t clock_id, char *name)
+{
+ if (clock_id == CLK_MAX) {
+ memcpy(name, END_OF_CLK, sizeof(END_OF_CLK) > CLK_NAME_LEN ?
+ CLK_NAME_LEN : sizeof(END_OF_CLK));
+ } else if (!pm_clock_valid(clock_id)) {
+ memset(name, 0, CLK_NAME_LEN);
+ } else if (clock_id < CLK_MAX_OUTPUT_CLK) {
+ memcpy(name, clocks[clock_id].name, CLK_NAME_LEN);
+ } else {
+ memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name,
+ CLK_NAME_LEN);
+ }
+}
+
+/**
+ * pm_api_clock_get_topology() - PM call to request a clock's topology
+ * @clock_id Clock ID
+ * @index Topology index for next toplogy node
+ * @topology Buffer to store nodes in topology and flags
+ *
+ * This function is used by master to get topology information for the
+ * clock specified by given clock ID. Each response would return 3
+ * topology nodes. To get next nodes, caller needs to call this API with
+ * index of next node. Index starts from 0.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_topology(uint32_t clock_id,
+ uint32_t index,
+ uint32_t *topology)
+{
+ struct pm_clock_node *clock_nodes;
+ uint8_t num_nodes;
+ uint32_t i;
+ uint16_t typeflags;
+
+ if (!pm_clock_valid(clock_id)) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+
+ memset(topology, 0, CLK_TOPOLOGY_PAYLOAD_LEN);
+ clock_nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+
+ /* Skip parent till index */
+ if (index >= num_nodes) {
+ return PM_RET_SUCCESS;
+ }
+
+ for (i = 0; i < 3U; i++) {
+ if ((index + i) == num_nodes) {
+ break;
+ }
+
+ topology[i] = clock_nodes[index + i].type;
+ topology[i] |= clock_nodes[index + i].clkflags <<
+ CLK_CLKFLAGS_SHIFT;
+ typeflags = clock_nodes[index + i].typeflags;
+ topology[i] |= (typeflags & CLK_TYPEFLAGS_BITS_MASK) <<
+ CLK_TYPEFLAGS_SHIFT;
+ topology[i] |= (typeflags & CLK_TYPEFLAGS2_BITS_MASK) >>
+ (CLK_TYPEFLAGS_BITS - CLK_TYPEFLAGS2_SHIFT);
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_fixedfactor_params() - PM call to request a clock's fixed
+ * factor parameters for fixed clock
+ * @clock_id Clock ID
+ * @mul Multiplication value
+ * @div Divisor value
+ *
+ * This function is used by master to get fixed factor parameers for the
+ * fixed clock. This API is application only for the fixed clock.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_fixedfactor_params(uint32_t clock_id,
+ uint32_t *mul,
+ uint32_t *div)
+{
+ struct pm_clock_node *clock_nodes;
+ uint8_t num_nodes;
+ uint32_t type, i;
+
+ if (!pm_clock_valid(clock_id)) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+
+ clock_nodes = *clocks[clock_id].nodes;
+ num_nodes = clocks[clock_id].num_nodes;
+
+ for (i = 0; i < num_nodes; i++) {
+ type = clock_nodes[i].type;
+ if (type == TYPE_FIXEDFACTOR) {
+ *mul = clock_nodes[i].mult;
+ *div = clock_nodes[i].div;
+ break;
+ }
+ }
+
+ /* Clock is not fixed clock */
+ if (i == num_nodes) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_parents() - PM call to request a clock's first 3 parents
+ * @clock_id Clock ID
+ * @index Index of next parent
+ * @parents Parents of the given clock
+ *
+ * This function is used by master to get clock's parents information.
+ * This API will return 3 parents with a single response. To get other
+ * parents, master should call same API in loop with new parent index
+ * till error is returned.
+ *
+ * E.g First call should have index 0 which will return parents 0, 1 and
+ * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
+ * so on.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_parents(uint32_t clock_id,
+ uint32_t index,
+ uint32_t *parents)
+{
+ uint32_t i;
+ int32_t *clk_parents;
+
+ if (!pm_clock_valid(clock_id)) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+
+ clk_parents = *clocks[clock_id].parents;
+ if (clk_parents == NULL) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ memset(parents, 0, CLK_PARENTS_PAYLOAD_LEN);
+
+ /* Skip parent till index */
+ for (i = 0; i < index; i++) {
+ if (clk_parents[i] == CLK_NA_PARENT) {
+ return PM_RET_SUCCESS;
+ }
+ }
+
+ for (i = 0; i < 3U; i++) {
+ parents[i] = clk_parents[index + i];
+ if (clk_parents[index + i] == CLK_NA_PARENT) {
+ break;
+ }
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_attributes() - PM call to request a clock's attributes
+ * @clock_id Clock ID
+ * @attr Clock attributes
+ *
+ * This function is used by master to get clock's attributes
+ * (e.g. valid, clock type, etc).
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_attributes(uint32_t clock_id,
+ uint32_t *attr)
+{
+ if (clock_id >= CLK_MAX) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Clock valid bit */
+ *attr = pm_clock_valid(clock_id);
+
+ /* Clock type (Output/External) */
+ *attr |= (pm_clock_type(clock_id) << CLK_TYPE_SHIFT);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_clock_get_max_divisor - PM call to get max divisor
+ * @clock_id Clock ID
+ * @div_type Divisor Type (TYPE_DIV1 or TYPE_DIV2)
+ * @max_div Maximum supported divisor
+ *
+ * This function is used by master to get maximum supported value.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_get_max_divisor(enum clock_id clock_id,
+ uint8_t div_type,
+ uint32_t *max_div)
+{
+ uint32_t i;
+ struct pm_clock_node *nodes;
+
+ if (clock_id >= CLK_MAX_OUTPUT_CLK) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ nodes = *clocks[clock_id].nodes;
+ for (i = 0; i < clocks[clock_id].num_nodes; i++) {
+ if (nodes[i].type == div_type) {
+ if (CLK_DIVIDER_POWER_OF_TWO &
+ nodes[i].typeflags) {
+ *max_div = (1U << (BIT(nodes[i].width) - 1U));
+ } else {
+ *max_div = BIT(nodes[i].width) - 1U;
+ }
+ return PM_RET_SUCCESS;
+ }
+ }
+
+ return PM_RET_ERROR_ARGS;
+}
+
+/**
+ * struct pm_pll - PLL related data required to map IOCTL-based PLL control
+ * implemented by linux to system-level EEMI APIs
+ * @nid: PLL node ID
+ * @cid: PLL clock ID
+ * @pre_src: Pre-source PLL clock ID
+ * @post_src: Post-source PLL clock ID
+ * @div2: DIV2 PLL clock ID
+ * @bypass: PLL output clock ID that maps to bypass select output
+ * @mode: PLL mode currently set via IOCTL (PLL_FRAC_MODE/PLL_INT_MODE)
+ */
+struct pm_pll {
+ const enum pm_node_id nid;
+ const enum clock_id cid;
+ const enum clock_id pre_src;
+ const enum clock_id post_src;
+ const enum clock_id div2;
+ const enum clock_id bypass;
+ uint8_t mode;
+};
+
+static struct pm_pll pm_plls[] = {
+ {
+ .nid = NODE_IOPLL,
+ .cid = CLK_IOPLL_INT,
+ .pre_src = CLK_IOPLL_PRE_SRC,
+ .post_src = CLK_IOPLL_POST_SRC,
+ .div2 = CLK_IOPLL_INT_MUX,
+ .bypass = CLK_IOPLL,
+ }, {
+ .nid = NODE_RPLL,
+ .cid = CLK_RPLL_INT,
+ .pre_src = CLK_RPLL_PRE_SRC,
+ .post_src = CLK_RPLL_POST_SRC,
+ .div2 = CLK_RPLL_INT_MUX,
+ .bypass = CLK_RPLL,
+ }, {
+ .nid = NODE_APLL,
+ .cid = CLK_APLL_INT,
+ .pre_src = CLK_APLL_PRE_SRC,
+ .post_src = CLK_APLL_POST_SRC,
+ .div2 = CLK_APLL_INT_MUX,
+ .bypass = CLK_APLL,
+ }, {
+ .nid = NODE_VPLL,
+ .cid = CLK_VPLL_INT,
+ .pre_src = CLK_VPLL_PRE_SRC,
+ .post_src = CLK_VPLL_POST_SRC,
+ .div2 = CLK_VPLL_INT_MUX,
+ .bypass = CLK_VPLL,
+ }, {
+ .nid = NODE_DPLL,
+ .cid = CLK_DPLL_INT,
+ .pre_src = CLK_DPLL_PRE_SRC,
+ .post_src = CLK_DPLL_POST_SRC,
+ .div2 = CLK_DPLL_INT_MUX,
+ .bypass = CLK_DPLL,
+ },
+};
+
+/**
+ * pm_clock_get_pll() - Get PLL structure by PLL clock ID
+ * @clock_id Clock ID of the target PLL
+ *
+ * @return Pointer to PLL structure if found, NULL otherwise
+ */
+struct pm_pll *pm_clock_get_pll(enum clock_id clock_id)
+{
+ uint32_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pm_plls); i++) {
+ if (pm_plls[i].cid == clock_id) {
+ return &pm_plls[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * pm_clock_get_pll_node_id() - Get PLL node ID by PLL clock ID
+ * @clock_id Clock ID of the target PLL
+ * @node_id Location to store node ID of the target PLL
+ *
+ * @return PM_RET_SUCCESS if node ID is found, PM_RET_ERROR_ARGS otherwise
+ */
+enum pm_ret_status pm_clock_get_pll_node_id(enum clock_id clock_id,
+ enum pm_node_id *node_id)
+{
+ struct pm_pll *pll = pm_clock_get_pll(clock_id);
+
+ if (pll) {
+ *node_id = pll->nid;
+ return PM_RET_SUCCESS;
+ }
+
+ return PM_RET_ERROR_ARGS;
+}
+
+/**
+ * pm_clock_get_pll_by_related_clk() - Get PLL structure by PLL-related clock ID
+ * @clock_id Clock ID
+ *
+ * @return Pointer to PLL structure if found, NULL otherwise
+ */
+struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id)
+{
+ uint32_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pm_plls); i++) {
+ if (pm_plls[i].pre_src == clock_id ||
+ pm_plls[i].post_src == clock_id ||
+ pm_plls[i].div2 == clock_id ||
+ pm_plls[i].bypass == clock_id) {
+ return &pm_plls[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * pm_clock_pll_enable() - "Enable" the PLL clock (lock the PLL)
+ * @pll: PLL to be locked
+ *
+ * This function is used to map IOCTL/linux-based PLL handling to system-level
+ * EEMI APIs
+ *
+ * Return: Error if the argument is not valid or status as returned by PMU
+ */
+enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll)
+{
+ if (pll == NULL) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Set the PLL mode according to the buffered mode value */
+ if (pll->mode == PLL_FRAC_MODE) {
+ return pm_pll_set_mode(pll->nid, PM_PLL_MODE_FRACTIONAL);
+ }
+
+ return pm_pll_set_mode(pll->nid, PM_PLL_MODE_INTEGER);
+}
+
+/**
+ * pm_clock_pll_disable - "Disable" the PLL clock (bypass/reset the PLL)
+ * @pll PLL to be bypassed/reset
+ *
+ * This function is used to map IOCTL/linux-based PLL handling to system-level
+ * EEMI APIs
+ *
+ * Return: Error if the argument is not valid or status as returned by PMU
+ */
+enum pm_ret_status pm_clock_pll_disable(struct pm_pll *pll)
+{
+ if (pll == NULL) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return pm_pll_set_mode(pll->nid, PM_PLL_MODE_RESET);
+}
+
+/**
+ * pm_clock_pll_get_state - Get state of the PLL
+ * @pll Pointer to the target PLL structure
+ * @state Location to store the state: 1/0 ("Enabled"/"Disabled")
+ *
+ * "Enable" actually means that the PLL is locked and its bypass is deasserted,
+ * "Disable" means that it is bypassed.
+ *
+ * Return: PM_RET_ERROR_ARGS error if the argument is not valid, success if
+ * returned state value is valid or an error if returned by PMU
+ */
+enum pm_ret_status pm_clock_pll_get_state(struct pm_pll *pll,
+ uint32_t *state)
+{
+ enum pm_ret_status status;
+ enum pm_pll_mode mode;
+
+ if ((pll == NULL) || !state) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ status = pm_pll_get_mode(pll->nid, &mode);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ if (mode == PM_PLL_MODE_RESET) {
+ *state = 0;
+ } else {
+ *state = 1;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_clock_pll_set_parent - Set the clock parent for PLL-related clock id
+ * @pll Target PLL structure
+ * @clock_id Id of the clock
+ * @parent_index parent index (=mux select value)
+ *
+ * The whole clock-tree implementation relies on the fact that parent indexes
+ * match to the multiplexer select values. This function has to rely on that
+ * assumption as well => parent_index is actually the mux select value.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_pll_set_parent(struct pm_pll *pll,
+ enum clock_id clock_id,
+ uint32_t parent_index)
+{
+ if (pll == NULL) {
+ return PM_RET_ERROR_ARGS;
+ }
+ if (pll->pre_src == clock_id) {
+ return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC,
+ parent_index);
+ }
+ if (pll->post_src == clock_id) {
+ return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_POST_SRC,
+ parent_index);
+ }
+ if (pll->div2 == clock_id) {
+ return pm_pll_set_parameter(pll->nid, PM_PLL_PARAM_DIV2,
+ parent_index);
+ }
+
+ return PM_RET_ERROR_ARGS;
+}
+
+/**
+ * pm_clock_pll_get_parent - Get mux select value of PLL-related clock parent
+ * @pll Target PLL structure
+ * @clock_id Id of the clock
+ * @parent_index parent index (=mux select value)
+ *
+ * This function is used by master to get parent index for PLL-related clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_pll_get_parent(struct pm_pll *pll,
+ enum clock_id clock_id,
+ uint32_t *parent_index)
+{
+ if (pll == NULL) {
+ return PM_RET_ERROR_ARGS;
+ }
+ if (pll->pre_src == clock_id) {
+ return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_PRE_SRC,
+ parent_index);
+ }
+ if (pll->post_src == clock_id) {
+ return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_POST_SRC,
+ parent_index);
+ }
+ if (pll->div2 == clock_id) {
+ return pm_pll_get_parameter(pll->nid, PM_PLL_PARAM_DIV2,
+ parent_index);
+ }
+ if (pll->bypass == clock_id) {
+ *parent_index = 0;
+ return PM_RET_SUCCESS;
+ }
+
+ return PM_RET_ERROR_ARGS;
+}
+
+/**
+ * pm_clock_set_pll_mode() - Set PLL mode
+ * @clock_id PLL clock id
+ * @mode Mode fractional/integer
+ *
+ * This function buffers/saves the PLL mode that is set.
+ *
+ * @return Success if mode is buffered or error if an argument is invalid
+ */
+enum pm_ret_status pm_clock_set_pll_mode(enum clock_id clock_id,
+ uint32_t mode)
+{
+ struct pm_pll *pll = pm_clock_get_pll(clock_id);
+
+ if ((pll == NULL) || (mode != PLL_FRAC_MODE && mode != PLL_INT_MODE)) {
+ return PM_RET_ERROR_ARGS;
+ }
+ pll->mode = mode;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_clock_get_pll_mode() - Get PLL mode
+ * @clock_id PLL clock id
+ * @mode Location to store the mode (fractional/integer)
+ *
+ * This function returns buffered PLL mode.
+ *
+ * @return Success if mode is stored or error if an argument is invalid
+ */
+enum pm_ret_status pm_clock_get_pll_mode(enum clock_id clock_id,
+ uint32_t *mode)
+{
+ struct pm_pll *pll = pm_clock_get_pll(clock_id);
+
+ if ((pll == NULL) || !mode) {
+ return PM_RET_ERROR_ARGS;
+ }
+ *mode = pll->mode;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_clock_id_is_valid() - Check if given clock ID is valid
+ * @clock_id ID of the clock to be checked
+ *
+ * @return Returns success if clock_id is valid, otherwise an error
+ */
+enum pm_ret_status pm_clock_id_is_valid(uint32_t clock_id)
+{
+ if (!pm_clock_valid(clock_id)) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) {
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_clock_has_div() - Check if the clock has divider with given ID
+ * @clock_id Clock ID
+ * @div_id Divider ID
+ *
+ * @return True(1)=clock has the divider, false(0)=otherwise
+ */
+uint8_t pm_clock_has_div(uint32_t clock_id, enum pm_clock_div_id div_id)
+{
+ uint32_t i;
+ struct pm_clock_node *nodes;
+
+ if (clock_id >= CLK_MAX_OUTPUT_CLK) {
+ return 0;
+ }
+
+ nodes = *clocks[clock_id].nodes;
+ for (i = 0; i < clocks[clock_id].num_nodes; i++) {
+ if (nodes[i].type == TYPE_DIV1) {
+ if (div_id == PM_CLOCK_DIV0_ID)
+ return 1;
+ } else if (nodes[i].type == TYPE_DIV2) {
+ if (div_id == PM_CLOCK_DIV1_ID)
+ return 1;
+ } else {
+ /* To fix the misra 15.7 warning */
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
new file mode 100644
index 0000000..cc0dacc
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for clock control.
+ */
+
+#ifndef PM_API_CLOCK_H
+#define PM_API_CLOCK_H
+
+#include <lib/utils_def.h>
+
+#include "pm_common.h"
+
+#define CLK_NAME_LEN (15U)
+#define MAX_PARENTS (100U)
+#define CLK_NA_PARENT -1
+#define CLK_DUMMY_PARENT -2
+
+/* Flags for parent id */
+#define PARENT_CLK_SELF (0U)
+#define PARENT_CLK_NODE1 (1U)
+#define PARENT_CLK_NODE2 (2U)
+#define PARENT_CLK_NODE3 (3U)
+#define PARENT_CLK_NODE4 (4U)
+#define PARENT_CLK_EXTERNAL (5U)
+#define PARENT_CLK_MIO0_MIO77 (6U)
+
+#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */
+#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */
+#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */
+#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */
+/* unused */
+#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */
+#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
+#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
+#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
+#define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */
+#define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */
+#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
+/* parents need enable during gate/ungate, set rate and re-parent */
+#define CLK_OPS_PARENT_ENABLE BIT(12)
+
+#define CLK_DIVIDER_ONE_BASED BIT(0)
+#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
+#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
+#define CLK_DIVIDER_HIWORD_MASK BIT(3)
+#define CLK_DIVIDER_ROUND_CLOSEST BIT(4)
+#define CLK_DIVIDER_READ_ONLY BIT(5)
+#define CLK_DIVIDER_MAX_AT_ZERO BIT(6)
+#define CLK_FRAC BIT(8)
+
+#define END_OF_CLK "END_OF_CLK"
+
+//CLock Ids
+enum clock_id {
+ CLK_IOPLL = (0U),
+ CLK_RPLL = (1U),
+ CLK_APLL = (2U),
+ CLK_DPLL = (3U),
+ CLK_VPLL = (4U),
+ CLK_IOPLL_TO_FPD = (5U),
+ CLK_RPLL_TO_FPD = (6U),
+ CLK_APLL_TO_LPD = (7U),
+ CLK_DPLL_TO_LPD = (8U),
+ CLK_VPLL_TO_LPD = (9U),
+ CLK_ACPU = (10U),
+ CLK_ACPU_HALF = (11U),
+ CLK_DBG_FPD = (12U),
+ CLK_DBG_LPD = (13U),
+ CLK_DBG_TRACE = (14U),
+ CLK_DBG_TSTMP = (15U),
+ CLK_DP_VIDEO_REF = (16U),
+ CLK_DP_AUDIO_REF = (17U),
+ CLK_DP_STC_REF = (18U),
+ CLK_GDMA_REF = (19U),
+ CLK_DPDMA_REF = (20U),
+ CLK_DDR_REF = (21U),
+ CLK_SATA_REF = (22U),
+ CLK_PCIE_REF = (23U),
+ CLK_GPU_REF = (24U),
+ CLK_GPU_PP0_REF = (25U),
+ CLK_GPU_PP1_REF = (26U),
+ CLK_TOPSW_MAIN = (27U),
+ CLK_TOPSW_LSBUS = (28U),
+ CLK_GTGREF0_REF = (29U),
+ CLK_LPD_SWITCH = (30U),
+ CLK_LPD_LSBUS = (31U),
+ CLK_USB0_BUS_REF = (32U),
+ CLK_USB1_BUS_REF = (33U),
+ CLK_USB3_DUAL_REF = (34U),
+ CLK_USB0 = (35U),
+ CLK_USB1 = (36U),
+ CLK_CPU_R5 = (37U),
+ CLK_CPU_R5_CORE = (38U),
+ CLK_CSU_SPB = (39U),
+ CLK_CSU_PLL = (40U),
+ CLK_PCAP = (41U),
+ CLK_IOU_SWITCH = (42U),
+ CLK_GEM_TSU_REF = (43U),
+ CLK_GEM_TSU = (44U),
+ CLK_GEM0_TX = (45U),
+ CLK_GEM1_TX = (46U),
+ CLK_GEM2_TX = (47U),
+ CLK_GEM3_TX = (48U),
+ CLK_GEM0_RX = (49U),
+ CLK_GEM1_RX = (50U),
+ CLK_GEM2_RX = (51U),
+ CLK_GEM3_RX = (52U),
+ CLK_QSPI_REF = (53U),
+ CLK_SDIO0_REF = (54U),
+ CLK_SDIO1_REF = (55U),
+ CLK_UART0_REF = (56U),
+ CLK_UART1_REF = (57U),
+ CLK_SPI0_REF = (58U),
+ CLK_SPI1_REF = (59U),
+ CLK_NAND_REF = (60U),
+ CLK_I2C0_REF = (61U),
+ CLK_I2C1_REF = (62U),
+ CLK_CAN0_REF = (63U),
+ CLK_CAN1_REF = (64U),
+ CLK_CAN0 = (65U),
+ CLK_CAN1 = (66U),
+ CLK_DLL_REF = (67U),
+ CLK_ADMA_REF = (68U),
+ CLK_TIMESTAMP_REF = (69U),
+ CLK_AMS_REF = (70U),
+ CLK_PL0_REF = (71U),
+ CLK_PL1_REF = (72U),
+ CLK_PL2_REF = (73U),
+ CLK_PL3_REF = (74U),
+ CLK_FPD_WDT = (75U),
+ CLK_IOPLL_INT = (76U),
+ CLK_IOPLL_PRE_SRC = (77U),
+ CLK_IOPLL_HALF = (78U),
+ CLK_IOPLL_INT_MUX = (79U),
+ CLK_IOPLL_POST_SRC = (80U),
+ CLK_RPLL_INT = (81U),
+ CLK_RPLL_PRE_SRC = (82U),
+ CLK_RPLL_HALF = (83U),
+ CLK_RPLL_INT_MUX = (84U),
+ CLK_RPLL_POST_SRC = (85U),
+ CLK_APLL_INT = (86U),
+ CLK_APLL_PRE_SRC = (87U),
+ CLK_APLL_HALF = (88U),
+ CLK_APLL_INT_MUX = (89U),
+ CLK_APLL_POST_SRC = (90U),
+ CLK_DPLL_INT = (91U),
+ CLK_DPLL_PRE_SRC = (92U),
+ CLK_DPLL_HALF = (93U),
+ CLK_DPLL_INT_MUX = (94U),
+ CLK_DPLL_POST_SRC = (95U),
+ CLK_VPLL_INT = (96U),
+ CLK_VPLL_PRE_SRC = (97U),
+ CLK_VPLL_HALF = (98U),
+ CLK_VPLL_INT_MUX = (99U),
+ CLK_VPLL_POST_SRC = (100U),
+ CLK_CAN0_MIO = (101U),
+ CLK_CAN1_MIO = (102U),
+ CLK_ACPU_FULL = (103U),
+ CLK_GEM0_REF = (104U),
+ CLK_GEM1_REF = (105U),
+ CLK_GEM2_REF = (106U),
+ CLK_GEM3_REF = (107U),
+ CLK_GEM0_REF_UNGATED = (108U),
+ CLK_GEM1_REF_UNGATED = (109U),
+ CLK_GEM2_REF_UNGATED = (110U),
+ CLK_GEM3_REF_UNGATED = (111U),
+ CLK_LPD_WDT = (112U),
+ END_OF_OUTPUT_CLKS = (113U),
+};
+
+#define CLK_MAX_OUTPUT_CLK END_OF_OUTPUT_CLKS
+
+//External clock ids
+enum {
+ EXT_CLK_PSS_REF = END_OF_OUTPUT_CLKS,
+ EXT_CLK_VIDEO = (114U),
+ EXT_CLK_PSS_ALT_REF = (115U),
+ EXT_CLK_AUX_REF = (116U),
+ EXT_CLK_GT_CRX_REF = (117U),
+ EXT_CLK_SWDT0 = (118U),
+ EXT_CLK_SWDT1 = (119U),
+ EXT_CLK_GEM0_TX_EMIO = (120U),
+ EXT_CLK_GEM1_TX_EMIO = (121U),
+ EXT_CLK_GEM2_TX_EMIO = (122U),
+ EXT_CLK_GEM3_TX_EMIO = (123U),
+ EXT_CLK_GEM0_RX_EMIO = (124U),
+ EXT_CLK_GEM1_RX_EMIO = (125U),
+ EXT_CLK_GEM2_RX_EMIO = (126U),
+ EXT_CLK_GEM3_RX_EMIO = (127U),
+ EXT_CLK_MIO50_OR_MIO51 = (128U),
+ EXT_CLK_MIO0 = (129U),
+ EXT_CLK_MIO1 = (130U),
+ EXT_CLK_MIO2 = (131U),
+ EXT_CLK_MIO3 = (132U),
+ EXT_CLK_MIO4 = (133U),
+ EXT_CLK_MIO5 = (134U),
+ EXT_CLK_MIO6 = (135U),
+ EXT_CLK_MIO7 = (136U),
+ EXT_CLK_MIO8 = (137U),
+ EXT_CLK_MIO9 = (138U),
+ EXT_CLK_MIO10 = (139U),
+ EXT_CLK_MIO11 = (140U),
+ EXT_CLK_MIO12 = (141U),
+ EXT_CLK_MIO13 = (142U),
+ EXT_CLK_MIO14 = (143U),
+ EXT_CLK_MIO15 = (144U),
+ EXT_CLK_MIO16 = (145U),
+ EXT_CLK_MIO17 = (146U),
+ EXT_CLK_MIO18 = (147U),
+ EXT_CLK_MIO19 = (148U),
+ EXT_CLK_MIO20 = (149U),
+ EXT_CLK_MIO21 = (150U),
+ EXT_CLK_MIO22 = (151U),
+ EXT_CLK_MIO23 = (152U),
+ EXT_CLK_MIO24 = (153U),
+ EXT_CLK_MIO25 = (154U),
+ EXT_CLK_MIO26 = (155U),
+ EXT_CLK_MIO27 = (156U),
+ EXT_CLK_MIO28 = (157U),
+ EXT_CLK_MIO29 = (158U),
+ EXT_CLK_MIO30 = (159U),
+ EXT_CLK_MIO31 = (160U),
+ EXT_CLK_MIO32 = (161U),
+ EXT_CLK_MIO33 = (162U),
+ EXT_CLK_MIO34 = (163U),
+ EXT_CLK_MIO35 = (164U),
+ EXT_CLK_MIO36 = (165U),
+ EXT_CLK_MIO37 = (166U),
+ EXT_CLK_MIO38 = (167U),
+ EXT_CLK_MIO39 = (168U),
+ EXT_CLK_MIO40 = (169U),
+ EXT_CLK_MIO41 = (170U),
+ EXT_CLK_MIO42 = (171U),
+ EXT_CLK_MIO43 = (172U),
+ EXT_CLK_MIO44 = (173U),
+ EXT_CLK_MIO45 = (174U),
+ EXT_CLK_MIO46 = (175U),
+ EXT_CLK_MIO47 = (176U),
+ EXT_CLK_MIO48 = (177U),
+ EXT_CLK_MIO49 = (178U),
+ EXT_CLK_MIO50 = (179U),
+ EXT_CLK_MIO51 = (180U),
+ EXT_CLK_MIO52 = (181U),
+ EXT_CLK_MIO53 = (182U),
+ EXT_CLK_MIO54 = (183U),
+ EXT_CLK_MIO55 = (184U),
+ EXT_CLK_MIO56 = (185U),
+ EXT_CLK_MIO57 = (186U),
+ EXT_CLK_MIO58 = (187U),
+ EXT_CLK_MIO59 = (188U),
+ EXT_CLK_MIO60 = (189U),
+ EXT_CLK_MIO61 = (190U),
+ EXT_CLK_MIO62 = (191U),
+ EXT_CLK_MIO63 = (192U),
+ EXT_CLK_MIO64 = (193U),
+ EXT_CLK_MIO65 = (194U),
+ EXT_CLK_MIO66 = (195U),
+ EXT_CLK_MIO67 = (196U),
+ EXT_CLK_MIO68 = (197U),
+ EXT_CLK_MIO69 = (198U),
+ EXT_CLK_MIO70 = (199U),
+ EXT_CLK_MIO71 = (200U),
+ EXT_CLK_MIO72 = (201U),
+ EXT_CLK_MIO73 = (202U),
+ EXT_CLK_MIO74 = (203U),
+ EXT_CLK_MIO75 = (204U),
+ EXT_CLK_MIO76 = (205U),
+ EXT_CLK_MIO77 = (206U),
+ END_OF_CLKS = (207U),
+};
+
+#define CLK_MAX END_OF_CLKS
+
+//CLock types
+#define CLK_TYPE_OUTPUT 0U
+#define CLK_TYPE_EXTERNAL 1U
+
+//Topology types
+#define TYPE_INVALID 0U
+#define TYPE_MUX 1U
+#define TYPE_PLL 2U
+#define TYPE_FIXEDFACTOR 3U
+#define TYPE_DIV1 4U
+#define TYPE_DIV2 5U
+#define TYPE_GATE 6U
+
+struct pm_pll;
+struct pm_pll *pm_clock_get_pll(enum clock_id clock_id);
+struct pm_pll *pm_clock_get_pll_by_related_clk(enum clock_id clock_id);
+uint8_t pm_clock_has_div(uint32_t clock_id, enum pm_clock_div_id div_id);
+
+void pm_api_clock_get_name(uint32_t clock_id, char *name);
+enum pm_ret_status pm_api_clock_get_num_clocks(uint32_t *nclocks);
+enum pm_ret_status pm_api_clock_get_topology(uint32_t clock_id,
+ uint32_t index,
+ uint32_t *topology);
+enum pm_ret_status pm_api_clock_get_fixedfactor_params(uint32_t clock_id,
+ uint32_t *mul,
+ uint32_t *div);
+enum pm_ret_status pm_api_clock_get_parents(uint32_t clock_id,
+ uint32_t index,
+ uint32_t *parents);
+enum pm_ret_status pm_api_clock_get_attributes(uint32_t clock_id,
+ uint32_t *attr);
+enum pm_ret_status pm_api_clock_get_max_divisor(enum clock_id clock_id,
+ uint8_t div_type,
+ uint32_t *max_div);
+
+enum pm_ret_status pm_clock_get_pll_node_id(enum clock_id clock_id,
+ enum pm_node_id *node_id);
+enum pm_ret_status pm_clock_id_is_valid(uint32_t clock_id);
+
+enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll);
+enum pm_ret_status pm_clock_pll_disable(struct pm_pll *pll);
+enum pm_ret_status pm_clock_pll_get_state(struct pm_pll *pll,
+ uint32_t *state);
+enum pm_ret_status pm_clock_pll_set_parent(struct pm_pll *pll,
+ enum clock_id clock_id,
+ uint32_t parent_index);
+enum pm_ret_status pm_clock_pll_get_parent(struct pm_pll *pll,
+ enum clock_id clock_id,
+ uint32_t *parent_index);
+enum pm_ret_status pm_clock_set_pll_mode(enum clock_id clock_id,
+ uint32_t mode);
+enum pm_ret_status pm_clock_get_pll_mode(enum clock_id clock_id,
+ uint32_t *mode);
+
+#endif /* PM_API_CLOCK_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
new file mode 100644
index 0000000..c0bfd51
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for ioctl.
+ */
+
+#include <arch_helpers.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <zynqmp_def.h>
+
+#include "pm_api_clock.h"
+#include "pm_api_ioctl.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+
+/**
+ * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode
+ * @mode Buffer to store value of oper mode(Split/Lock-step)
+ *
+ * This function provides current configured RPU operational mode.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_rpu_oper_mode(uint32_t *mode)
+{
+ uint32_t val;
+
+ val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+ val &= ZYNQMP_SLSPLIT_MASK;
+ if (val == 0U) {
+ *mode = PM_RPU_MODE_LOCKSTEP;
+ } else {
+ *mode = PM_RPU_MODE_SPLIT;
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_set_rpu_oper_mode () - Configure RPU operation mode
+ * @mode Value to set for oper mode(Split/Lock-step)
+ *
+ * This function configures RPU operational mode(Split/Lock-step).
+ * It also sets TCM combined mode in RPU lock-step and TCM non-combined
+ * mode for RPU split mode. In case of Lock step mode, RPU1's output is
+ * clamped.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_rpu_oper_mode(uint32_t mode)
+{
+ uint32_t val;
+
+ if (mmio_read_32(CRL_APB_RST_LPD_TOP) & CRL_APB_RPU_AMBA_RESET) {
+ return PM_RET_ERROR_ACCESS;
+ }
+
+ val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+
+ if (mode == PM_RPU_MODE_SPLIT) {
+ val |= ZYNQMP_SLSPLIT_MASK;
+ val &= ~ZYNQMP_TCM_COMB_MASK;
+ val &= ~ZYNQMP_SLCLAMP_MASK;
+ } else if (mode == PM_RPU_MODE_LOCKSTEP) {
+ val &= ~ZYNQMP_SLSPLIT_MASK;
+ val |= ZYNQMP_TCM_COMB_MASK;
+ val |= ZYNQMP_SLCLAMP_MASK;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_config_boot_addr() - Configure RPU boot address
+ * @nid Node ID of RPU
+ * @value Value to set for boot address (TCM/OCM)
+ *
+ * This function configures RPU boot address(memory).
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_config_boot_addr(enum pm_node_id nid,
+ uint32_t value)
+{
+ uint32_t rpu_cfg_addr, val;
+
+ if (nid == NODE_RPU_0) {
+ rpu_cfg_addr = ZYNQMP_RPU0_CFG;
+ } else if (nid == NODE_RPU_1) {
+ rpu_cfg_addr = ZYNQMP_RPU1_CFG;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ val = mmio_read_32(rpu_cfg_addr);
+
+ if (value == PM_RPU_BOOTMEM_LOVEC) {
+ val &= ~ZYNQMP_VINITHI_MASK;
+ } else if (value == PM_RPU_BOOTMEM_HIVEC) {
+ val |= ZYNQMP_VINITHI_MASK;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ mmio_write_32(rpu_cfg_addr, val);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_config_tcm_comb() - Configure TCM combined mode
+ * @value Value to set (Split/Combined)
+ *
+ * This function configures TCM to be in split mode or combined
+ * mode.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_config_tcm_comb(uint32_t value)
+{
+ uint32_t val;
+
+ val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL);
+
+ if (value == PM_RPU_TCM_SPLIT) {
+ val &= ~ZYNQMP_TCM_COMB_MASK;
+ } else if (value == PM_RPU_TCM_COMB) {
+ val |= ZYNQMP_TCM_COMB_MASK;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ mmio_write_32(ZYNQMP_RPU_GLBL_CNTL, val);
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ioctl_set_tapdelay_bypass() - Enable/Disable tap delay bypass
+ * @type Type of tap delay to enable/disable (e.g. QSPI)
+ * @value Enable/Disable
+ *
+ * This function enable/disable tap delay bypass.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_tapdelay_bypass(uint32_t type,
+ uint32_t value)
+{
+ if ((value != PM_TAPDELAY_BYPASS_ENABLE &&
+ value != PM_TAPDELAY_BYPASS_DISABLE) || type >= PM_TAPDELAY_MAX) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return pm_mmio_write(IOU_TAPDLY_BYPASS, TAP_DELAY_MASK, value << type);
+}
+
+/**
+ * pm_ioctl_set_sgmii_mode() - Set SGMII mode for the GEM device
+ * @nid Node ID of the device
+ * @value Enable/Disable
+ *
+ * This function enable/disable SGMII mode for the GEM device.
+ * While enabling SGMII mode, it also ties the GEM PCS Signal
+ * Detect to 1 and selects EMIO for RX clock generation.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_sgmii_mode(enum pm_node_id nid,
+ uint32_t value)
+{
+ uint32_t val, mask, shift;
+ enum pm_ret_status ret;
+
+ if (value != PM_SGMII_DISABLE && value != PM_SGMII_ENABLE) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ switch (nid) {
+ case NODE_ETH_0:
+ shift = 0;
+ break;
+ case NODE_ETH_1:
+ shift = 1;
+ break;
+ case NODE_ETH_2:
+ shift = 2;
+ break;
+ case NODE_ETH_3:
+ shift = 3;
+ break;
+ default:
+ return PM_RET_ERROR_ARGS;
+ }
+
+ if (value == PM_SGMII_DISABLE) {
+ mask = GEM_SGMII_MASK << GEM_CLK_CTRL_OFFSET * shift;
+ ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, 0U);
+ } else {
+ /* Tie the GEM PCS Signal Detect to 1 */
+ mask = SGMII_SD_MASK << SGMII_SD_OFFSET * shift;
+ val = SGMII_PCS_SD_1 << SGMII_SD_OFFSET * shift;
+ ret = pm_mmio_write(IOU_GEM_CTRL, mask, val);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+
+ /* Set the GEM to SGMII mode */
+ mask = GEM_CLK_CTRL_MASK << GEM_CLK_CTRL_OFFSET * shift;
+ val = GEM_RX_SRC_SEL_GTR | GEM_SGMII_MODE;
+ val <<= GEM_CLK_CTRL_OFFSET * shift;
+ ret = pm_mmio_write(IOU_GEM_CLK_CTRL, mask, val);
+ }
+
+ return ret;
+}
+
+/**
+ * pm_ioctl_sd_dll_reset() - Reset DLL logic
+ * @nid Node ID of the device
+ * @type Reset type
+ *
+ * This function resets DLL logic for the SD device.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_sd_dll_reset(enum pm_node_id nid,
+ uint32_t type)
+{
+ uint32_t mask, val;
+ enum pm_ret_status ret;
+
+ if (nid == NODE_SD_0) {
+ mask = ZYNQMP_SD0_DLL_RST_MASK;
+ val = ZYNQMP_SD0_DLL_RST;
+ } else if (nid == NODE_SD_1) {
+ mask = ZYNQMP_SD1_DLL_RST_MASK;
+ val = ZYNQMP_SD1_DLL_RST;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ switch (type) {
+ case PM_DLL_RESET_ASSERT:
+ case PM_DLL_RESET_PULSE:
+ ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, val);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+
+ if (type == PM_DLL_RESET_ASSERT) {
+ break;
+ }
+ mdelay(1);
+ /* Fallthrough */
+ case PM_DLL_RESET_RELEASE:
+ ret = pm_mmio_write(ZYNQMP_SD_DLL_CTRL, mask, 0);
+ break;
+ default:
+ ret = PM_RET_ERROR_ARGS;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * pm_ioctl_sd_set_tapdelay() - Set tap delay for the SD device
+ * @nid Node ID of the device
+ * @type Type of tap delay to set (input/output)
+ * @value Value to set fot the tap delay
+ *
+ * This function sets input/output tap delay for the SD device.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_sd_set_tapdelay(enum pm_node_id nid,
+ enum tap_delay_type type,
+ uint32_t value)
+{
+ uint32_t shift;
+ enum pm_ret_status ret;
+ uint32_t val, mask;
+
+ if (nid == NODE_SD_0) {
+ shift = 0;
+ mask = ZYNQMP_SD0_DLL_RST_MASK;
+ } else if (nid == NODE_SD_1) {
+ shift = ZYNQMP_SD_TAP_OFFSET;
+ mask = ZYNQMP_SD1_DLL_RST_MASK;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ ret = pm_mmio_read(ZYNQMP_SD_DLL_CTRL, &val);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+
+ if ((val & mask) == 0U) {
+ ret = pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_ASSERT);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+ }
+
+ if (type == PM_TAPDELAY_INPUT) {
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPCHGWIN_MASK << shift),
+ (ZYNQMP_SD_ITAPCHGWIN << shift));
+
+ if (ret != PM_RET_SUCCESS) {
+ goto reset_release;
+ }
+
+ if (value == 0U) {
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPDLYENA_MASK <<
+ shift), 0);
+ } else {
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPDLYENA_MASK <<
+ shift), (ZYNQMP_SD_ITAPDLYENA <<
+ shift));
+ }
+
+ if (ret != PM_RET_SUCCESS) {
+ goto reset_release;
+ }
+
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPDLYSEL_MASK << shift),
+ (value << shift));
+
+ if (ret != PM_RET_SUCCESS) {
+ goto reset_release;
+ }
+
+ ret = pm_mmio_write(ZYNQMP_SD_ITAP_DLY,
+ (ZYNQMP_SD_ITAPCHGWIN_MASK << shift), 0);
+ } else if (type == PM_TAPDELAY_OUTPUT) {
+ ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
+ (ZYNQMP_SD_OTAPDLYENA_MASK << shift), 0);
+
+ if (ret != PM_RET_SUCCESS) {
+ goto reset_release;
+ }
+
+ ret = pm_mmio_write(ZYNQMP_SD_OTAP_DLY,
+ (ZYNQMP_SD_OTAPDLYSEL_MASK << shift),
+ (value << shift));
+ } else {
+ ret = PM_RET_ERROR_ARGS;
+ }
+
+reset_release:
+ if ((val & mask) == 0) {
+ (void)pm_ioctl_sd_dll_reset(nid, PM_DLL_RESET_RELEASE);
+ }
+
+ return ret;
+}
+
+/**
+ * pm_ioctl_set_pll_frac_mode() - Ioctl function for
+ * setting pll mode
+ * @pll PLL clock id
+ * @mode Mode fraction/integar
+ *
+ * This function sets PLL mode
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_pll_frac_mode
+ (uint32_t pll, uint32_t mode)
+{
+ return pm_clock_set_pll_mode(pll, mode);
+}
+
+/**
+ * pm_ioctl_get_pll_frac_mode() - Ioctl function for
+ * getting pll mode
+ * @pll PLL clock id
+ * @mode Mode fraction/integar
+ *
+ * This function return current PLL mode
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_pll_frac_mode
+ (uint32_t pll, uint32_t *mode)
+{
+ return pm_clock_get_pll_mode(pll, mode);
+}
+
+/**
+ * pm_ioctl_set_pll_frac_data() - Ioctl function for
+ * setting pll fraction data
+ * @pll PLL clock id
+ * @data fraction data
+ *
+ * This function sets fraction data.
+ * It is valid for fraction mode only.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_pll_frac_data
+ (uint32_t pll, uint32_t data)
+{
+ enum pm_node_id pll_nid;
+ enum pm_ret_status status;
+
+ /* Get PLL node ID using PLL clock ID */
+ status = pm_clock_get_pll_node_id(pll, &pll_nid);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ return pm_pll_set_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
+}
+
+/**
+ * pm_ioctl_get_pll_frac_data() - Ioctl function for
+ * getting pll fraction data
+ * @pll PLL clock id
+ * @data fraction data
+ *
+ * This function returns fraction data value.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_pll_frac_data
+ (uint32_t pll, uint32_t *data)
+{
+ enum pm_node_id pll_nid;
+ enum pm_ret_status status;
+
+ /* Get PLL node ID using PLL clock ID */
+ status = pm_clock_get_pll_node_id(pll, &pll_nid);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ return pm_pll_get_parameter(pll_nid, PM_PLL_PARAM_DATA, data);
+}
+
+/**
+ * pm_ioctl_write_ggs() - Ioctl function for writing
+ * global general storage (ggs)
+ * @index GGS register index
+ * @value Register value to be written
+ *
+ * This function writes value to GGS register.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_write_ggs(uint32_t index,
+ uint32_t value)
+{
+ if (index >= GGS_NUM_REGS) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return pm_mmio_write(GGS_BASEADDR + (index << 2),
+ 0xFFFFFFFFU, value);
+}
+
+/**
+ * pm_ioctl_read_ggs() - Ioctl function for reading
+ * global general storage (ggs)
+ * @index GGS register index
+ * @value Register value
+ *
+ * This function returns GGS register value.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_read_ggs(uint32_t index,
+ uint32_t *value)
+{
+ if (index >= GGS_NUM_REGS) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return pm_mmio_read(GGS_BASEADDR + (index << 2), value);
+}
+
+/**
+ * pm_ioctl_write_pggs() - Ioctl function for writing persistent
+ * global general storage (pggs)
+ * @index PGGS register index
+ * @value Register value to be written
+ *
+ * This function writes value to PGGS register.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_write_pggs(uint32_t index,
+ uint32_t value)
+{
+ if (index >= PGGS_NUM_REGS) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return pm_mmio_write(PGGS_BASEADDR + (index << 2),
+ 0xFFFFFFFFU, value);
+}
+
+/**
+ * pm_ioctl_afi() - Ioctl function for writing afi values
+ *
+ * @index AFI register index
+ * @value Register value to be written
+ *
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_afi(uint32_t index,
+ uint32_t value)
+{
+ uint32_t mask;
+ uint32_t regarr[] = {0xFD360000U,
+ 0xFD360014U,
+ 0xFD370000U,
+ 0xFD370014U,
+ 0xFD380000U,
+ 0xFD380014U,
+ 0xFD390000U,
+ 0xFD390014U,
+ 0xFD3a0000U,
+ 0xFD3a0014U,
+ 0xFD3b0000U,
+ 0xFD3b0014U,
+ 0xFF9b0000U,
+ 0xFF9b0014U,
+ 0xFD615000U,
+ 0xFF419000U,
+ };
+
+ if (index >= ARRAY_SIZE(regarr)) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ if (index <= AFIFM6_WRCTRL) {
+ mask = FABRIC_WIDTH;
+ } else {
+ mask = 0xf00;
+ }
+
+ return pm_mmio_write(regarr[index], mask, value);
+}
+
+/**
+ * pm_ioctl_read_pggs() - Ioctl function for reading persistent
+ * global general storage (pggs)
+ * @index PGGS register index
+ * @value Register value
+ *
+ * This function returns PGGS register value.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_read_pggs(uint32_t index,
+ uint32_t *value)
+{
+ if (index >= PGGS_NUM_REGS) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ return pm_mmio_read(PGGS_BASEADDR + (index << 2), value);
+}
+
+/**
+ * pm_ioctl_ulpi_reset() - Ioctl function for performing ULPI reset
+ *
+ * This function peerforms the ULPI reset sequence for resetting
+ * the ULPI transceiver.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_ulpi_reset(void)
+{
+ enum pm_ret_status ret;
+
+ ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
+ ZYNQMP_ULPI_RESET_VAL_HIGH);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+
+ /* Drive ULPI assert for atleast 1ms */
+ mdelay(1);
+
+ ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
+ ZYNQMP_ULPI_RESET_VAL_LOW);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+
+ /* Drive ULPI de-assert for atleast 1ms */
+ mdelay(1);
+
+ ret = pm_mmio_write(CRL_APB_BOOT_PIN_CTRL, CRL_APB_BOOT_PIN_MASK,
+ ZYNQMP_ULPI_RESET_VAL_HIGH);
+
+ return ret;
+}
+
+/**
+ * pm_ioctl_set_boot_health_status() - Ioctl for setting healthy boot status
+ *
+ * This function sets healthy bit value to indicate boot health status
+ * to firmware.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_boot_health_status(uint32_t value)
+{
+ return pm_mmio_write(PMU_GLOBAL_GEN_STORAGE4,
+ PM_BOOT_HEALTH_STATUS_MASK, value);
+}
+
+/**
+ * pm_api_ioctl() - PM IOCTL API for device control and configs
+ * @node_id Node ID of the device
+ * @ioctl_id ID of the requested IOCTL
+ * @arg1 Argument 1 to requested IOCTL call
+ * @arg2 Argument 2 to requested IOCTL call
+ * @value Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
+ uint32_t ioctl_id,
+ uint32_t arg1,
+ uint32_t arg2,
+ uint32_t *value)
+{
+ enum pm_ret_status ret;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ switch (ioctl_id) {
+ case IOCTL_GET_RPU_OPER_MODE:
+ ret = pm_ioctl_get_rpu_oper_mode(value);
+ break;
+ case IOCTL_SET_RPU_OPER_MODE:
+ ret = pm_ioctl_set_rpu_oper_mode(arg1);
+ break;
+ case IOCTL_RPU_BOOT_ADDR_CONFIG:
+ ret = pm_ioctl_config_boot_addr(nid, arg1);
+ break;
+ case IOCTL_TCM_COMB_CONFIG:
+ ret = pm_ioctl_config_tcm_comb(arg1);
+ break;
+ case IOCTL_SET_TAPDELAY_BYPASS:
+ ret = pm_ioctl_set_tapdelay_bypass(arg1, arg2);
+ break;
+ case IOCTL_SET_SGMII_MODE:
+ ret = pm_ioctl_set_sgmii_mode(nid, arg1);
+ break;
+ case IOCTL_SD_DLL_RESET:
+ ret = pm_ioctl_sd_dll_reset(nid, arg1);
+ break;
+ case IOCTL_SET_SD_TAPDELAY:
+ ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2);
+ break;
+ case IOCTL_SET_PLL_FRAC_MODE:
+ ret = pm_ioctl_set_pll_frac_mode(arg1, arg2);
+ break;
+ case IOCTL_GET_PLL_FRAC_MODE:
+ ret = pm_ioctl_get_pll_frac_mode(arg1, value);
+ break;
+ case IOCTL_SET_PLL_FRAC_DATA:
+ ret = pm_ioctl_set_pll_frac_data(arg1, arg2);
+ break;
+ case IOCTL_GET_PLL_FRAC_DATA:
+ ret = pm_ioctl_get_pll_frac_data(arg1, value);
+ break;
+ case IOCTL_WRITE_GGS:
+ ret = pm_ioctl_write_ggs(arg1, arg2);
+ break;
+ case IOCTL_READ_GGS:
+ ret = pm_ioctl_read_ggs(arg1, value);
+ break;
+ case IOCTL_WRITE_PGGS:
+ ret = pm_ioctl_write_pggs(arg1, arg2);
+ break;
+ case IOCTL_READ_PGGS:
+ ret = pm_ioctl_read_pggs(arg1, value);
+ break;
+ case IOCTL_ULPI_RESET:
+ ret = pm_ioctl_ulpi_reset();
+ break;
+ case IOCTL_SET_BOOT_HEALTH_STATUS:
+ ret = pm_ioctl_set_boot_health_status(arg1);
+ break;
+ case IOCTL_AFI:
+ ret = pm_ioctl_afi(arg1, arg2);
+ break;
+ default:
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_IOCTL, nid, ioctl_id, arg1, arg2);
+
+ ret = pm_ipi_send_sync(primary_proc, payload, value, 1);
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * pm_update_ioctl_bitmask() - API to get supported IOCTL ID mask
+ * @bit_mask Returned bit mask of supported IOCTL IDs
+ */
+enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask)
+{
+ uint8_t supported_ids[] = {
+ IOCTL_GET_RPU_OPER_MODE,
+ IOCTL_SET_RPU_OPER_MODE,
+ IOCTL_RPU_BOOT_ADDR_CONFIG,
+ IOCTL_TCM_COMB_CONFIG,
+ IOCTL_SET_TAPDELAY_BYPASS,
+ IOCTL_SET_SGMII_MODE,
+ IOCTL_SD_DLL_RESET,
+ IOCTL_SET_SD_TAPDELAY,
+ IOCTL_SET_PLL_FRAC_MODE,
+ IOCTL_GET_PLL_FRAC_MODE,
+ IOCTL_SET_PLL_FRAC_DATA,
+ IOCTL_GET_PLL_FRAC_DATA,
+ IOCTL_WRITE_GGS,
+ IOCTL_READ_GGS,
+ IOCTL_WRITE_PGGS,
+ IOCTL_READ_PGGS,
+ IOCTL_ULPI_RESET,
+ IOCTL_SET_BOOT_HEALTH_STATUS,
+ IOCTL_AFI,
+ };
+ uint8_t i, ioctl_id;
+ int32_t ret;
+
+ for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) {
+ ioctl_id = supported_ids[i];
+ if (ioctl_id >= 64U) {
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+ ret = check_api_dependency(ioctl_id);
+ if (ret == PM_RET_SUCCESS) {
+ bit_mask[ioctl_id / 32U] |= BIT(ioctl_id % 32U);
+ }
+ }
+
+ return PM_RET_SUCCESS;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
new file mode 100644
index 0000000..3b0d6ee
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for pin control.
+ */
+
+#ifndef PM_API_IOCTL_H
+#define PM_API_IOCTL_H
+
+#include "pm_common.h"
+
+//ioctl id
+enum {
+ IOCTL_GET_RPU_OPER_MODE = 0,
+ IOCTL_SET_RPU_OPER_MODE = 1,
+ IOCTL_RPU_BOOT_ADDR_CONFIG = 2,
+ IOCTL_TCM_COMB_CONFIG = 3,
+ IOCTL_SET_TAPDELAY_BYPASS = 4,
+ IOCTL_SET_SGMII_MODE = 5,
+ IOCTL_SD_DLL_RESET = 6,
+ IOCTL_SET_SD_TAPDELAY = 7,
+ /* Ioctl for clock driver */
+ IOCTL_SET_PLL_FRAC_MODE = 8,
+ IOCTL_GET_PLL_FRAC_MODE = 9,
+ IOCTL_SET_PLL_FRAC_DATA = 10,
+ IOCTL_GET_PLL_FRAC_DATA = 11,
+ IOCTL_WRITE_GGS = 12,
+ IOCTL_READ_GGS = 13,
+ IOCTL_WRITE_PGGS = 14,
+ IOCTL_READ_PGGS = 15,
+ /* IOCTL for ULPI reset */
+ IOCTL_ULPI_RESET = 16,
+ /* Set healthy bit value */
+ IOCTL_SET_BOOT_HEALTH_STATUS = 17,
+ IOCTL_AFI = 18,
+ /* Probe counter read/write */
+ IOCTL_PROBE_COUNTER_READ = 19,
+ IOCTL_PROBE_COUNTER_WRITE = 20,
+ IOCTL_OSPI_MUX_SELECT = 21,
+ /* IOCTL for USB power request */
+ IOCTL_USB_SET_STATE = 22,
+ /* IOCTL to get last reset reason */
+ IOCTL_GET_LAST_RESET_REASON = 23,
+ /* AI engine NPI ISR clear */
+ IOCTL_AIE_ISR_CLEAR = 24,
+ /* Register SGI to ATF */
+ IOCTL_REGISTER_SGI = 25,
+};
+
+//RPU operation mode
+#define PM_RPU_MODE_LOCKSTEP 0U
+#define PM_RPU_MODE_SPLIT 1U
+
+//RPU boot mem
+#define PM_RPU_BOOTMEM_LOVEC 0U
+#define PM_RPU_BOOTMEM_HIVEC 1U
+
+//RPU tcm mpde
+#define PM_RPU_TCM_SPLIT 0U
+#define PM_RPU_TCM_COMB 1U
+
+//tap delay signal type
+#define PM_TAPDELAY_NAND_DQS_IN 0U
+#define PM_TAPDELAY_NAND_DQS_OUT 1U
+#define PM_TAPDELAY_QSPI 2U
+#define PM_TAPDELAY_MAX 3U
+
+//tap delay bypass
+#define PM_TAPDELAY_BYPASS_DISABLE 0U
+#define PM_TAPDELAY_BYPASS_ENABLE 1U
+
+//sgmii mode
+#define PM_SGMII_DISABLE 0U
+#define PM_SGMII_ENABLE 1U
+
+enum tap_delay_type {
+ PM_TAPDELAY_INPUT,
+ PM_TAPDELAY_OUTPUT,
+};
+
+//dll reset type
+#define PM_DLL_RESET_ASSERT 0U
+#define PM_DLL_RESET_RELEASE 1U
+#define PM_DLL_RESET_PULSE 2U
+
+enum pm_ret_status pm_api_ioctl(enum pm_node_id nid,
+ uint32_t ioctl_id,
+ uint32_t arg1,
+ uint32_t arg2,
+ uint32_t *value);
+enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask);
+#endif /* PM_API_IOCTL_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
new file mode 100644
index 0000000..8f37341
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
@@ -0,0 +1,2112 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for pin control.
+ */
+
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#include "pm_api_pinctrl.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+
+struct pinctrl_function {
+ char name[FUNCTION_NAME_LEN];
+ uint16_t group_base;
+ uint8_t group_size;
+ uint8_t regval;
+};
+
+/* Max groups for one pin */
+#define MAX_PIN_GROUPS (13U)
+
+struct zynqmp_pin_group {
+ uint16_t (*groups)[];
+};
+
+static struct pinctrl_function pinctrl_functions[MAX_FUNCTION] = {
+ [PINCTRL_FUNC_CAN0] = {
+ .name = "can0",
+ .regval = 0x20,
+ .group_base = PINCTRL_GRP_CAN0_0,
+ .group_size = PINCTRL_GRP_CAN0_18 - PINCTRL_GRP_CAN0_0 + 1U,
+ },
+ [PINCTRL_FUNC_CAN1] = {
+ .name = "can1",
+ .regval = 0x20,
+ .group_base = PINCTRL_GRP_CAN1_0,
+ .group_size = PINCTRL_GRP_CAN1_19 - PINCTRL_GRP_CAN1_0 + 1U,
+ },
+ [PINCTRL_FUNC_ETHERNET0] = {
+ .name = "ethernet0",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_ETHERNET0_0,
+ .group_size = PINCTRL_GRP_ETHERNET0_0 - PINCTRL_GRP_ETHERNET0_0 + 1U,
+ },
+ [PINCTRL_FUNC_ETHERNET1] = {
+ .name = "ethernet1",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_ETHERNET1_0,
+ .group_size = PINCTRL_GRP_ETHERNET1_0 - PINCTRL_GRP_ETHERNET1_0 + 1U,
+ },
+ [PINCTRL_FUNC_ETHERNET2] = {
+ .name = "ethernet2",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_ETHERNET2_0,
+ .group_size = PINCTRL_GRP_ETHERNET2_0 - PINCTRL_GRP_ETHERNET2_0 + 1U,
+ },
+ [PINCTRL_FUNC_ETHERNET3] = {
+ .name = "ethernet3",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_ETHERNET3_0,
+ .group_size = PINCTRL_GRP_ETHERNET3_0 - PINCTRL_GRP_ETHERNET3_0 + 1U,
+ },
+ [PINCTRL_FUNC_GEMTSU0] = {
+ .name = "gemtsu0",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_GEMTSU0_0,
+ .group_size = PINCTRL_GRP_GEMTSU0_2 - PINCTRL_GRP_GEMTSU0_0 + 1U,
+ },
+ [PINCTRL_FUNC_GPIO0] = {
+ .name = "gpio0",
+ .regval = 0x00,
+ .group_base = PINCTRL_GRP_GPIO0_0,
+ .group_size = PINCTRL_GRP_GPIO0_77 - PINCTRL_GRP_GPIO0_0 + 1U,
+ },
+ [PINCTRL_FUNC_I2C0] = {
+ .name = "i2c0",
+ .regval = 0x40,
+ .group_base = PINCTRL_GRP_I2C0_0,
+ .group_size = PINCTRL_GRP_I2C0_18 - PINCTRL_GRP_I2C0_0 + 1U,
+ },
+ [PINCTRL_FUNC_I2C1] = {
+ .name = "i2c1",
+ .regval = 0x40,
+ .group_base = PINCTRL_GRP_I2C1_0,
+ .group_size = PINCTRL_GRP_I2C1_19 - PINCTRL_GRP_I2C1_0 + 1U,
+ },
+ [PINCTRL_FUNC_MDIO0] = {
+ .name = "mdio0",
+ .regval = 0x60,
+ .group_base = PINCTRL_GRP_MDIO0_0,
+ .group_size = PINCTRL_GRP_MDIO0_0 - PINCTRL_GRP_MDIO0_0 + 1U,
+ },
+ [PINCTRL_FUNC_MDIO1] = {
+ .name = "mdio1",
+ .regval = 0x80,
+ .group_base = PINCTRL_GRP_MDIO1_0,
+ .group_size = PINCTRL_GRP_MDIO1_1 - PINCTRL_GRP_MDIO1_0 + 1U,
+ },
+ [PINCTRL_FUNC_MDIO2] = {
+ .name = "mdio2",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_MDIO2_0,
+ .group_size = PINCTRL_GRP_MDIO2_0 - PINCTRL_GRP_MDIO2_0 + 1U,
+ },
+ [PINCTRL_FUNC_MDIO3] = {
+ .name = "mdio3",
+ .regval = 0xc0,
+ .group_base = PINCTRL_GRP_MDIO3_0,
+ .group_size = PINCTRL_GRP_MDIO3_0 - PINCTRL_GRP_MDIO3_0 + 1U,
+ },
+ [PINCTRL_FUNC_QSPI0] = {
+ .name = "qspi0",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_QSPI0_0,
+ .group_size = PINCTRL_GRP_QSPI0_0 - PINCTRL_GRP_QSPI0_0 + 1U,
+ },
+ [PINCTRL_FUNC_QSPI_FBCLK] = {
+ .name = "qspi_fbclk",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_QSPI_FBCLK,
+ .group_size = PINCTRL_GRP_QSPI_FBCLK - PINCTRL_GRP_QSPI_FBCLK + 1U,
+ },
+ [PINCTRL_FUNC_QSPI_SS] = {
+ .name = "qspi_ss",
+ .regval = 0x02,
+ .group_base = PINCTRL_GRP_QSPI_SS,
+ .group_size = PINCTRL_GRP_QSPI_SS - PINCTRL_GRP_QSPI_SS + 1U,
+ },
+ [PINCTRL_FUNC_SPI0] = {
+ .name = "spi0",
+ .regval = 0x80,
+ .group_base = PINCTRL_GRP_SPI0_0,
+ .group_size = PINCTRL_GRP_SPI0_5 - PINCTRL_GRP_SPI0_0 + 1U,
+ },
+ [PINCTRL_FUNC_SPI1] = {
+ .name = "spi1",
+ .regval = 0x80,
+ .group_base = PINCTRL_GRP_SPI1_0,
+ .group_size = PINCTRL_GRP_SPI1_5 - PINCTRL_GRP_SPI1_0 + 1U,
+ },
+ [PINCTRL_FUNC_SPI0_SS] = {
+ .name = "spi0_ss",
+ .regval = 0x80,
+ .group_base = PINCTRL_GRP_SPI0_0_SS0,
+ .group_size = PINCTRL_GRP_SPI0_5_SS2 - PINCTRL_GRP_SPI0_0_SS0 + 1U,
+ },
+ [PINCTRL_FUNC_SPI1_SS] = {
+ .name = "spi1_ss",
+ .regval = 0x80,
+ .group_base = PINCTRL_GRP_SPI1_0_SS0,
+ .group_size = PINCTRL_GRP_SPI1_5_SS2 - PINCTRL_GRP_SPI1_0_SS0 + 1U,
+ },
+ [PINCTRL_FUNC_SDIO0] = {
+ .name = "sdio0",
+ .regval = 0x08,
+ .group_base = PINCTRL_GRP_SDIO0_0,
+ .group_size = PINCTRL_GRP_SDIO0_1BIT_2_7 - PINCTRL_GRP_SDIO0_0 + 1U,
+ },
+ [PINCTRL_FUNC_SDIO0_PC] = {
+ .name = "sdio0_pc",
+ .regval = 0x08,
+ .group_base = PINCTRL_GRP_SDIO0_0_PC,
+ .group_size = PINCTRL_GRP_SDIO0_2_PC - PINCTRL_GRP_SDIO0_0_PC + 1U,
+ },
+ [PINCTRL_FUNC_SDIO0_CD] = {
+ .name = "sdio0_cd",
+ .regval = 0x08,
+ .group_base = PINCTRL_GRP_SDIO0_0_CD,
+ .group_size = PINCTRL_GRP_SDIO0_2_CD - PINCTRL_GRP_SDIO0_0_CD + 1U,
+ },
+ [PINCTRL_FUNC_SDIO0_WP] = {
+ .name = "sdio0_wp",
+ .regval = 0x08,
+ .group_base = PINCTRL_GRP_SDIO0_0_WP,
+ .group_size = PINCTRL_GRP_SDIO0_2_WP - PINCTRL_GRP_SDIO0_0_WP + 1U,
+ },
+ [PINCTRL_FUNC_SDIO1] = {
+ .name = "sdio1",
+ .regval = 0x10,
+ .group_base = PINCTRL_GRP_SDIO1_0,
+ .group_size = PINCTRL_GRP_SDIO1_1BIT_1_3 - PINCTRL_GRP_SDIO1_0 + 1U,
+ },
+ [PINCTRL_FUNC_SDIO1_PC] = {
+ .name = "sdio1_pc",
+ .regval = 0x10,
+ .group_base = PINCTRL_GRP_SDIO1_0_PC,
+ .group_size = PINCTRL_GRP_SDIO1_1_PC - PINCTRL_GRP_SDIO1_0_PC + 1U,
+ },
+ [PINCTRL_FUNC_SDIO1_CD] = {
+ .name = "sdio1_cd",
+ .regval = 0x10,
+ .group_base = PINCTRL_GRP_SDIO1_0_CD,
+ .group_size = PINCTRL_GRP_SDIO1_1_CD - PINCTRL_GRP_SDIO1_0_CD + 1U,
+ },
+ [PINCTRL_FUNC_SDIO1_WP] = {
+ .name = "sdio1_wp",
+ .regval = 0x10,
+ .group_base = PINCTRL_GRP_SDIO1_0_WP,
+ .group_size = PINCTRL_GRP_SDIO1_1_WP - PINCTRL_GRP_SDIO1_0_WP + 1U,
+ },
+ [PINCTRL_FUNC_NAND0] = {
+ .name = "nand0",
+ .regval = 0x04,
+ .group_base = PINCTRL_GRP_NAND0_0,
+ .group_size = PINCTRL_GRP_NAND0_0 - PINCTRL_GRP_NAND0_0 + 1U,
+ },
+ [PINCTRL_FUNC_NAND0_CE] = {
+ .name = "nand0_ce",
+ .regval = 0x04,
+ .group_base = PINCTRL_GRP_NAND0_0_CE,
+ .group_size = PINCTRL_GRP_NAND0_1_CE - PINCTRL_GRP_NAND0_0_CE + 1U,
+ },
+ [PINCTRL_FUNC_NAND0_RB] = {
+ .name = "nand0_rb",
+ .regval = 0x04,
+ .group_base = PINCTRL_GRP_NAND0_0_RB,
+ .group_size = PINCTRL_GRP_NAND0_1_RB - PINCTRL_GRP_NAND0_0_RB + 1U,
+ },
+ [PINCTRL_FUNC_NAND0_DQS] = {
+ .name = "nand0_dqs",
+ .regval = 0x04,
+ .group_base = PINCTRL_GRP_NAND0_0_DQS,
+ .group_size = PINCTRL_GRP_NAND0_1_DQS - PINCTRL_GRP_NAND0_0_DQS + 1U,
+ },
+ [PINCTRL_FUNC_TTC0_CLK] = {
+ .name = "ttc0_clk",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC0_0_CLK,
+ .group_size = PINCTRL_GRP_TTC0_8_CLK - PINCTRL_GRP_TTC0_0_CLK + 1U,
+ },
+ [PINCTRL_FUNC_TTC0_WAV] = {
+ .name = "ttc0_wav",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC0_0_WAV,
+ .group_size = PINCTRL_GRP_TTC0_8_WAV - PINCTRL_GRP_TTC0_0_WAV + 1U,
+ },
+ [PINCTRL_FUNC_TTC1_CLK] = {
+ .name = "ttc1_clk",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC1_0_CLK,
+ .group_size = PINCTRL_GRP_TTC1_8_CLK - PINCTRL_GRP_TTC1_0_CLK + 1U,
+ },
+ [PINCTRL_FUNC_TTC1_WAV] = {
+ .name = "ttc1_wav",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC1_0_WAV,
+ .group_size = PINCTRL_GRP_TTC1_8_WAV - PINCTRL_GRP_TTC1_0_WAV + 1U,
+ },
+ [PINCTRL_FUNC_TTC2_CLK] = {
+ .name = "ttc2_clk",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC2_0_CLK,
+ .group_size = PINCTRL_GRP_TTC2_8_CLK - PINCTRL_GRP_TTC2_0_CLK + 1U,
+ },
+ [PINCTRL_FUNC_TTC2_WAV] = {
+ .name = "ttc2_wav",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC2_0_WAV,
+ .group_size = PINCTRL_GRP_TTC2_8_WAV - PINCTRL_GRP_TTC2_0_WAV + 1U,
+ },
+ [PINCTRL_FUNC_TTC3_CLK] = {
+ .name = "ttc3_clk",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC3_0_CLK,
+ .group_size = PINCTRL_GRP_TTC3_8_CLK - PINCTRL_GRP_TTC3_0_CLK + 1U,
+ },
+ [PINCTRL_FUNC_TTC3_WAV] = {
+ .name = "ttc3_wav",
+ .regval = 0xa0,
+ .group_base = PINCTRL_GRP_TTC3_0_WAV,
+ .group_size = PINCTRL_GRP_TTC3_8_WAV - PINCTRL_GRP_TTC3_0_WAV + 1U,
+ },
+ [PINCTRL_FUNC_UART0] = {
+ .name = "uart0",
+ .regval = 0xc0,
+ .group_base = PINCTRL_GRP_UART0_0,
+ .group_size = PINCTRL_GRP_UART0_18 - PINCTRL_GRP_UART0_0 + 1U,
+ },
+ [PINCTRL_FUNC_UART1] = {
+ .name = "uart1",
+ .regval = 0xc0,
+ .group_base = PINCTRL_GRP_UART1_0,
+ .group_size = PINCTRL_GRP_UART1_18 - PINCTRL_GRP_UART1_0 + 1U,
+ },
+ [PINCTRL_FUNC_USB0] = {
+ .name = "usb0",
+ .regval = 0x04,
+ .group_base = PINCTRL_GRP_USB0_0,
+ .group_size = PINCTRL_GRP_USB0_0 - PINCTRL_GRP_USB0_0 + 1U,
+ },
+ [PINCTRL_FUNC_USB1] = {
+ .name = "usb1",
+ .regval = 0x04,
+ .group_base = PINCTRL_GRP_USB1_0,
+ .group_size = PINCTRL_GRP_USB1_0 - PINCTRL_GRP_USB1_0 + 1U,
+ },
+ [PINCTRL_FUNC_SWDT0_CLK] = {
+ .name = "swdt0_clk",
+ .regval = 0x60,
+ .group_base = PINCTRL_GRP_SWDT0_0_CLK,
+ .group_size = PINCTRL_GRP_SWDT0_12_CLK - PINCTRL_GRP_SWDT0_0_CLK + 1U,
+ },
+ [PINCTRL_FUNC_SWDT0_RST] = {
+ .name = "swdt0_rst",
+ .regval = 0x60,
+ .group_base = PINCTRL_GRP_SWDT0_0_RST,
+ .group_size = PINCTRL_GRP_SWDT0_12_RST - PINCTRL_GRP_SWDT0_0_RST + 1U,
+ },
+ [PINCTRL_FUNC_SWDT1_CLK] = {
+ .name = "swdt1_clk",
+ .regval = 0x60,
+ .group_base = PINCTRL_GRP_SWDT1_0_CLK,
+ .group_size = PINCTRL_GRP_SWDT1_12_CLK - PINCTRL_GRP_SWDT1_0_CLK + 1U,
+ },
+ [PINCTRL_FUNC_SWDT1_RST] = {
+ .name = "swdt1_rst",
+ .regval = 0x60,
+ .group_base = PINCTRL_GRP_SWDT1_0_RST,
+ .group_size = PINCTRL_GRP_SWDT1_12_RST - PINCTRL_GRP_SWDT1_0_RST + 1U,
+ },
+ [PINCTRL_FUNC_PMU0] = {
+ .name = "pmu0",
+ .regval = 0x08,
+ .group_base = PINCTRL_GRP_PMU0_0,
+ .group_size = PINCTRL_GRP_PMU0_11 - PINCTRL_GRP_PMU0_0 + 1U,
+ },
+ [PINCTRL_FUNC_PCIE0] = {
+ .name = "pcie0",
+ .regval = 0x04,
+ .group_base = PINCTRL_GRP_PCIE0_0,
+ .group_size = PINCTRL_GRP_PCIE0_7 - PINCTRL_GRP_PCIE0_0 + 1U,
+ },
+ [PINCTRL_FUNC_CSU0] = {
+ .name = "csu0",
+ .regval = 0x18,
+ .group_base = PINCTRL_GRP_CSU0_0,
+ .group_size = PINCTRL_GRP_CSU0_11 - PINCTRL_GRP_CSU0_0 + 1U,
+ },
+ [PINCTRL_FUNC_DPAUX0] = {
+ .name = "dpaux0",
+ .regval = 0x18,
+ .group_base = PINCTRL_GRP_DPAUX0_0,
+ .group_size = PINCTRL_GRP_DPAUX0_3 - PINCTRL_GRP_DPAUX0_0 + 1U,
+ },
+ [PINCTRL_FUNC_PJTAG0] = {
+ .name = "pjtag0",
+ .regval = 0x60,
+ .group_base = PINCTRL_GRP_PJTAG0_0,
+ .group_size = PINCTRL_GRP_PJTAG0_5 - PINCTRL_GRP_PJTAG0_0 + 1U,
+ },
+ [PINCTRL_FUNC_TRACE0] = {
+ .name = "trace0",
+ .regval = 0xe0,
+ .group_base = PINCTRL_GRP_TRACE0_0,
+ .group_size = PINCTRL_GRP_TRACE0_2 - PINCTRL_GRP_TRACE0_0 + 1U,
+ },
+ [PINCTRL_FUNC_TRACE0_CLK] = {
+ .name = "trace0_clk",
+ .regval = 0xe0,
+ .group_base = PINCTRL_GRP_TRACE0_0_CLK,
+ .group_size = PINCTRL_GRP_TRACE0_2_CLK - PINCTRL_GRP_TRACE0_0_CLK + 1U,
+ },
+ [PINCTRL_FUNC_TESTSCAN0] = {
+ .name = "testscan0",
+ .regval = 0x10,
+ .group_base = PINCTRL_GRP_TESTSCAN0_0,
+ .group_size = PINCTRL_GRP_TESTSCAN0_0 - PINCTRL_GRP_TESTSCAN0_0 + 1U,
+ },
+};
+
+static struct zynqmp_pin_group zynqmp_pin_groups[MAX_PIN] = {
+ [PINCTRL_PIN_0] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_0,
+ PINCTRL_GRP_CAN1_0,
+ PINCTRL_GRP_I2C1_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_TTC3_0_CLK,
+ PINCTRL_GRP_UART1_0,
+ PINCTRL_GRP_TRACE0_0_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_1] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_1,
+ PINCTRL_GRP_CAN1_0,
+ PINCTRL_GRP_I2C1_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0_SS2,
+ PINCTRL_GRP_TTC3_0_WAV,
+ PINCTRL_GRP_UART1_0,
+ PINCTRL_GRP_TRACE0_0_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_2] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_2,
+ PINCTRL_GRP_CAN0_0,
+ PINCTRL_GRP_I2C0_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0_SS1,
+ PINCTRL_GRP_TTC2_0_CLK,
+ PINCTRL_GRP_UART0_0,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_3] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_3,
+ PINCTRL_GRP_CAN0_0,
+ PINCTRL_GRP_I2C0_0,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_SPI0_0_SS0,
+ PINCTRL_GRP_TTC2_0_WAV,
+ PINCTRL_GRP_UART0_0,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_4] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_4,
+ PINCTRL_GRP_CAN1_1,
+ PINCTRL_GRP_I2C1_1,
+ PINCTRL_GRP_SWDT1_0_CLK,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_TTC1_0_CLK,
+ PINCTRL_GRP_UART1_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_5] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_SS,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_5,
+ PINCTRL_GRP_CAN1_1,
+ PINCTRL_GRP_I2C1_1,
+ PINCTRL_GRP_SWDT1_0_RST,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_TTC1_0_WAV,
+ PINCTRL_GRP_UART1_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_6] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_FBCLK,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_6,
+ PINCTRL_GRP_CAN0_1,
+ PINCTRL_GRP_I2C0_1,
+ PINCTRL_GRP_SWDT0_0_CLK,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_TTC0_0_CLK,
+ PINCTRL_GRP_UART0_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_7] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI_SS,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_7,
+ PINCTRL_GRP_CAN0_1,
+ PINCTRL_GRP_I2C0_1,
+ PINCTRL_GRP_SWDT0_0_RST,
+ PINCTRL_GRP_SPI1_0_SS2,
+ PINCTRL_GRP_TTC0_0_WAV,
+ PINCTRL_GRP_UART0_1,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_8] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_8,
+ PINCTRL_GRP_CAN1_2,
+ PINCTRL_GRP_I2C1_2,
+ PINCTRL_GRP_SWDT1_1_CLK,
+ PINCTRL_GRP_SPI1_0_SS1,
+ PINCTRL_GRP_TTC3_1_CLK,
+ PINCTRL_GRP_UART1_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_9] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_CE,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_9,
+ PINCTRL_GRP_CAN1_2,
+ PINCTRL_GRP_I2C1_2,
+ PINCTRL_GRP_SWDT1_1_RST,
+ PINCTRL_GRP_SPI1_0_SS0,
+ PINCTRL_GRP_TTC3_1_WAV,
+ PINCTRL_GRP_UART1_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_10] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_RB,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_10,
+ PINCTRL_GRP_CAN0_2,
+ PINCTRL_GRP_I2C0_2,
+ PINCTRL_GRP_SWDT0_1_CLK,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_TTC2_1_CLK,
+ PINCTRL_GRP_UART0_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_11] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_RB,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_11,
+ PINCTRL_GRP_CAN0_2,
+ PINCTRL_GRP_I2C0_2,
+ PINCTRL_GRP_SWDT0_1_RST,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_TTC2_1_WAV,
+ PINCTRL_GRP_UART0_2,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_12] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_NAND0_0_DQS,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_12,
+ PINCTRL_GRP_CAN1_3,
+ PINCTRL_GRP_I2C1_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_TTC1_1_CLK,
+ PINCTRL_GRP_UART1_3,
+ PINCTRL_GRP_TRACE0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_13] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_13,
+ PINCTRL_GRP_CAN1_3,
+ PINCTRL_GRP_I2C1_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1_SS2,
+ PINCTRL_GRP_TTC1_1_WAV,
+ PINCTRL_GRP_UART1_3,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_14] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_14,
+ PINCTRL_GRP_CAN0_3,
+ PINCTRL_GRP_I2C0_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1_SS1,
+ PINCTRL_GRP_TTC0_1_CLK,
+ PINCTRL_GRP_UART0_3,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_15] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_15,
+ PINCTRL_GRP_CAN0_3,
+ PINCTRL_GRP_I2C0_3,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_SPI0_1_SS0,
+ PINCTRL_GRP_TTC0_1_WAV,
+ PINCTRL_GRP_UART0_3,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_16] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_16,
+ PINCTRL_GRP_CAN1_4,
+ PINCTRL_GRP_I2C1_4,
+ PINCTRL_GRP_SWDT1_2_CLK,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_TTC3_2_CLK,
+ PINCTRL_GRP_UART1_4,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_17] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_17,
+ PINCTRL_GRP_CAN1_4,
+ PINCTRL_GRP_I2C1_4,
+ PINCTRL_GRP_SWDT1_2_RST,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_TTC3_2_WAV,
+ PINCTRL_GRP_UART1_4,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_18] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_0,
+ PINCTRL_GRP_GPIO0_18,
+ PINCTRL_GRP_CAN0_4,
+ PINCTRL_GRP_I2C0_4,
+ PINCTRL_GRP_SWDT0_2_CLK,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_TTC2_2_CLK,
+ PINCTRL_GRP_UART0_4,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_19] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_1,
+ PINCTRL_GRP_GPIO0_19,
+ PINCTRL_GRP_CAN0_4,
+ PINCTRL_GRP_I2C0_4,
+ PINCTRL_GRP_SWDT0_2_RST,
+ PINCTRL_GRP_SPI1_1_SS2,
+ PINCTRL_GRP_TTC2_2_WAV,
+ PINCTRL_GRP_UART0_4,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_20] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_2,
+ PINCTRL_GRP_GPIO0_20,
+ PINCTRL_GRP_CAN1_5,
+ PINCTRL_GRP_I2C1_5,
+ PINCTRL_GRP_SWDT1_3_CLK,
+ PINCTRL_GRP_SPI1_1_SS1,
+ PINCTRL_GRP_TTC1_2_CLK,
+ PINCTRL_GRP_UART1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_21] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_3,
+ PINCTRL_GRP_GPIO0_21,
+ PINCTRL_GRP_CAN1_5,
+ PINCTRL_GRP_I2C1_5,
+ PINCTRL_GRP_SWDT1_3_RST,
+ PINCTRL_GRP_SPI1_1_SS0,
+ PINCTRL_GRP_TTC1_2_WAV,
+ PINCTRL_GRP_UART1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_22] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_4,
+ PINCTRL_GRP_GPIO0_22,
+ PINCTRL_GRP_CAN0_5,
+ PINCTRL_GRP_I2C0_5,
+ PINCTRL_GRP_SWDT0_3_CLK,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_TTC0_2_CLK,
+ PINCTRL_GRP_UART0_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_23] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0_PC,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_5,
+ PINCTRL_GRP_GPIO0_23,
+ PINCTRL_GRP_CAN0_5,
+ PINCTRL_GRP_I2C0_5,
+ PINCTRL_GRP_SWDT0_3_RST,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_TTC0_2_WAV,
+ PINCTRL_GRP_UART0_5,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_24] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0_CD,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_6,
+ PINCTRL_GRP_GPIO0_24,
+ PINCTRL_GRP_CAN1_6,
+ PINCTRL_GRP_I2C1_6,
+ PINCTRL_GRP_SWDT1_4_CLK,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TTC3_3_CLK,
+ PINCTRL_GRP_UART1_6,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_25] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_SDIO0_0_WP,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_7,
+ PINCTRL_GRP_GPIO0_25,
+ PINCTRL_GRP_CAN1_6,
+ PINCTRL_GRP_I2C1_6,
+ PINCTRL_GRP_SWDT1_4_RST,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_TTC3_3_WAV,
+ PINCTRL_GRP_UART1_6,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_26] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_GEMTSU0_0,
+ PINCTRL_GRP_NAND0_1_CE,
+ PINCTRL_GRP_PMU0_0,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_8,
+ PINCTRL_GRP_GPIO0_26,
+ PINCTRL_GRP_CAN0_6,
+ PINCTRL_GRP_I2C0_6,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_TTC2_3_CLK,
+ PINCTRL_GRP_UART0_6,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_27] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_NAND0_1_RB,
+ PINCTRL_GRP_PMU0_1,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_0,
+ PINCTRL_GRP_GPIO0_27,
+ PINCTRL_GRP_CAN0_6,
+ PINCTRL_GRP_I2C0_6,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2_SS2,
+ PINCTRL_GRP_TTC2_3_WAV,
+ PINCTRL_GRP_UART0_6,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_28] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_NAND0_1_RB,
+ PINCTRL_GRP_PMU0_2,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_0,
+ PINCTRL_GRP_GPIO0_28,
+ PINCTRL_GRP_CAN1_7,
+ PINCTRL_GRP_I2C1_7,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2_SS1,
+ PINCTRL_GRP_TTC1_3_CLK,
+ PINCTRL_GRP_UART1_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_29] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_0,
+ PINCTRL_GRP_PMU0_3,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_1,
+ PINCTRL_GRP_GPIO0_29,
+ PINCTRL_GRP_CAN1_7,
+ PINCTRL_GRP_I2C1_7,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_SPI0_2_SS0,
+ PINCTRL_GRP_TTC1_3_WAV,
+ PINCTRL_GRP_UART1_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_30] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_1,
+ PINCTRL_GRP_PMU0_4,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_1,
+ PINCTRL_GRP_GPIO0_30,
+ PINCTRL_GRP_CAN0_7,
+ PINCTRL_GRP_I2C0_7,
+ PINCTRL_GRP_SWDT0_4_CLK,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_TTC0_3_CLK,
+ PINCTRL_GRP_UART0_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_31] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_2,
+ PINCTRL_GRP_PMU0_5,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_9,
+ PINCTRL_GRP_GPIO0_31,
+ PINCTRL_GRP_CAN0_7,
+ PINCTRL_GRP_I2C0_7,
+ PINCTRL_GRP_SWDT0_4_RST,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_TTC0_3_WAV,
+ PINCTRL_GRP_UART0_7,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_32] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_NAND0_1_DQS,
+ PINCTRL_GRP_PMU0_6,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_10,
+ PINCTRL_GRP_GPIO0_32,
+ PINCTRL_GRP_CAN1_8,
+ PINCTRL_GRP_I2C1_8,
+ PINCTRL_GRP_SWDT1_5_CLK,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_TTC3_4_CLK,
+ PINCTRL_GRP_UART1_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_33] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_3,
+ PINCTRL_GRP_PMU0_7,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_CSU0_11,
+ PINCTRL_GRP_GPIO0_33,
+ PINCTRL_GRP_CAN1_8,
+ PINCTRL_GRP_I2C1_8,
+ PINCTRL_GRP_SWDT1_5_RST,
+ PINCTRL_GRP_SPI1_2_SS2,
+ PINCTRL_GRP_TTC3_4_WAV,
+ PINCTRL_GRP_UART1_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_34] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_4,
+ PINCTRL_GRP_PMU0_8,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_2,
+ PINCTRL_GRP_GPIO0_34,
+ PINCTRL_GRP_CAN0_8,
+ PINCTRL_GRP_I2C0_8,
+ PINCTRL_GRP_SWDT0_5_CLK,
+ PINCTRL_GRP_SPI1_2_SS1,
+ PINCTRL_GRP_TTC2_4_CLK,
+ PINCTRL_GRP_UART0_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_35] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_5,
+ PINCTRL_GRP_PMU0_9,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_2,
+ PINCTRL_GRP_GPIO0_35,
+ PINCTRL_GRP_CAN0_8,
+ PINCTRL_GRP_I2C0_8,
+ PINCTRL_GRP_SWDT0_5_RST,
+ PINCTRL_GRP_SPI1_2_SS0,
+ PINCTRL_GRP_TTC2_4_WAV,
+ PINCTRL_GRP_UART0_8,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_36] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_6,
+ PINCTRL_GRP_PMU0_10,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_3,
+ PINCTRL_GRP_GPIO0_36,
+ PINCTRL_GRP_CAN1_9,
+ PINCTRL_GRP_I2C1_9,
+ PINCTRL_GRP_SWDT1_6_CLK,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_TTC1_4_CLK,
+ PINCTRL_GRP_UART1_9,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_37] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_PCIE0_7,
+ PINCTRL_GRP_PMU0_11,
+ PINCTRL_GRP_TESTSCAN0_0,
+ PINCTRL_GRP_DPAUX0_3,
+ PINCTRL_GRP_GPIO0_37,
+ PINCTRL_GRP_CAN1_9,
+ PINCTRL_GRP_I2C1_9,
+ PINCTRL_GRP_SWDT1_6_RST,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_TTC1_4_WAV,
+ PINCTRL_GRP_UART1_9,
+ PINCTRL_GRP_TRACE0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_38] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_38,
+ PINCTRL_GRP_CAN0_9,
+ PINCTRL_GRP_I2C0_9,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_TTC0_4_CLK,
+ PINCTRL_GRP_UART0_9,
+ PINCTRL_GRP_TRACE0_1_CLK,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_39] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1_CD,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_39,
+ PINCTRL_GRP_CAN0_9,
+ PINCTRL_GRP_I2C0_9,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3_SS2,
+ PINCTRL_GRP_TTC0_4_WAV,
+ PINCTRL_GRP_UART0_9,
+ PINCTRL_GRP_TRACE0_1_CLK,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_40] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_40,
+ PINCTRL_GRP_CAN1_10,
+ PINCTRL_GRP_I2C1_10,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3_SS1,
+ PINCTRL_GRP_TTC3_5_CLK,
+ PINCTRL_GRP_UART1_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_41] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_41,
+ PINCTRL_GRP_CAN1_10,
+ PINCTRL_GRP_I2C1_10,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_SPI0_3_SS0,
+ PINCTRL_GRP_TTC3_5_WAV,
+ PINCTRL_GRP_UART1_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_42] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_42,
+ PINCTRL_GRP_CAN0_10,
+ PINCTRL_GRP_I2C0_10,
+ PINCTRL_GRP_SWDT0_6_CLK,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_TTC2_5_CLK,
+ PINCTRL_GRP_UART0_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_43] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0_PC,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_43,
+ PINCTRL_GRP_CAN0_10,
+ PINCTRL_GRP_I2C0_10,
+ PINCTRL_GRP_SWDT0_6_RST,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_TTC2_5_WAV,
+ PINCTRL_GRP_UART0_10,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_44] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0_WP,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_44,
+ PINCTRL_GRP_CAN1_11,
+ PINCTRL_GRP_I2C1_11,
+ PINCTRL_GRP_SWDT1_7_CLK,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_TTC1_5_CLK,
+ PINCTRL_GRP_UART1_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_45] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0_CD,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_45,
+ PINCTRL_GRP_CAN1_11,
+ PINCTRL_GRP_I2C1_11,
+ PINCTRL_GRP_SWDT1_7_RST,
+ PINCTRL_GRP_SPI1_3_SS2,
+ PINCTRL_GRP_TTC1_5_WAV,
+ PINCTRL_GRP_UART1_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_46] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_46,
+ PINCTRL_GRP_CAN0_11,
+ PINCTRL_GRP_I2C0_11,
+ PINCTRL_GRP_SWDT0_7_CLK,
+ PINCTRL_GRP_SPI1_3_SS1,
+ PINCTRL_GRP_TTC0_5_CLK,
+ PINCTRL_GRP_UART0_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_47] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_47,
+ PINCTRL_GRP_CAN0_11,
+ PINCTRL_GRP_I2C0_11,
+ PINCTRL_GRP_SWDT0_7_RST,
+ PINCTRL_GRP_SPI1_3_SS0,
+ PINCTRL_GRP_TTC0_5_WAV,
+ PINCTRL_GRP_UART0_11,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_48] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_48,
+ PINCTRL_GRP_CAN1_12,
+ PINCTRL_GRP_I2C1_12,
+ PINCTRL_GRP_SWDT1_8_CLK,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_TTC3_6_CLK,
+ PINCTRL_GRP_UART1_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_49] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1_PC,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_49,
+ PINCTRL_GRP_CAN1_12,
+ PINCTRL_GRP_I2C1_12,
+ PINCTRL_GRP_SWDT1_8_RST,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_TTC3_6_WAV,
+ PINCTRL_GRP_UART1_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_50] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_GEMTSU0_1,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_1_WP,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_50,
+ PINCTRL_GRP_CAN0_12,
+ PINCTRL_GRP_I2C0_12,
+ PINCTRL_GRP_SWDT0_8_CLK,
+ PINCTRL_GRP_MDIO1_0,
+ PINCTRL_GRP_TTC2_6_CLK,
+ PINCTRL_GRP_UART0_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_51] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_GEMTSU0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_51,
+ PINCTRL_GRP_CAN0_12,
+ PINCTRL_GRP_I2C0_12,
+ PINCTRL_GRP_SWDT0_8_RST,
+ PINCTRL_GRP_MDIO1_0,
+ PINCTRL_GRP_TTC2_6_WAV,
+ PINCTRL_GRP_UART0_12,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_52] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_52,
+ PINCTRL_GRP_CAN1_13,
+ PINCTRL_GRP_I2C1_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_TTC1_6_CLK,
+ PINCTRL_GRP_UART1_13,
+ PINCTRL_GRP_TRACE0_2_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_53] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_53,
+ PINCTRL_GRP_CAN1_13,
+ PINCTRL_GRP_I2C1_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4_SS2,
+ PINCTRL_GRP_TTC1_6_WAV,
+ PINCTRL_GRP_UART1_13,
+ PINCTRL_GRP_TRACE0_2_CLK,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_54] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_54,
+ PINCTRL_GRP_CAN0_13,
+ PINCTRL_GRP_I2C0_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4_SS1,
+ PINCTRL_GRP_TTC0_6_CLK,
+ PINCTRL_GRP_UART0_13,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_55] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_55,
+ PINCTRL_GRP_CAN0_13,
+ PINCTRL_GRP_I2C0_13,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_SPI0_4_SS0,
+ PINCTRL_GRP_TTC0_6_WAV,
+ PINCTRL_GRP_UART0_13,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_56] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_56,
+ PINCTRL_GRP_CAN1_14,
+ PINCTRL_GRP_I2C1_14,
+ PINCTRL_GRP_SWDT1_9_CLK,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_TTC3_7_CLK,
+ PINCTRL_GRP_UART1_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_57] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_57,
+ PINCTRL_GRP_CAN1_14,
+ PINCTRL_GRP_I2C1_14,
+ PINCTRL_GRP_SWDT1_9_RST,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_TTC3_7_WAV,
+ PINCTRL_GRP_UART1_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_58] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_58,
+ PINCTRL_GRP_CAN0_14,
+ PINCTRL_GRP_I2C0_14,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_TTC2_7_CLK,
+ PINCTRL_GRP_UART0_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_59] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_59,
+ PINCTRL_GRP_CAN0_14,
+ PINCTRL_GRP_I2C0_14,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4_SS2,
+ PINCTRL_GRP_TTC2_7_WAV,
+ PINCTRL_GRP_UART0_14,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_60] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_60,
+ PINCTRL_GRP_CAN1_15,
+ PINCTRL_GRP_I2C1_15,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4_SS1,
+ PINCTRL_GRP_TTC1_7_CLK,
+ PINCTRL_GRP_UART1_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_61] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_61,
+ PINCTRL_GRP_CAN1_15,
+ PINCTRL_GRP_I2C1_15,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_SPI1_4_SS0,
+ PINCTRL_GRP_TTC1_7_WAV,
+ PINCTRL_GRP_UART1_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_62] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_62,
+ PINCTRL_GRP_CAN0_15,
+ PINCTRL_GRP_I2C0_15,
+ PINCTRL_GRP_SWDT0_9_CLK,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_TTC0_7_CLK,
+ PINCTRL_GRP_UART0_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_63] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_63,
+ PINCTRL_GRP_CAN0_15,
+ PINCTRL_GRP_I2C0_15,
+ PINCTRL_GRP_SWDT0_9_RST,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_TTC0_7_WAV,
+ PINCTRL_GRP_UART0_15,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_64] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_64,
+ PINCTRL_GRP_CAN1_16,
+ PINCTRL_GRP_I2C1_16,
+ PINCTRL_GRP_SWDT1_10_CLK,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_TTC3_8_CLK,
+ PINCTRL_GRP_UART1_16,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_65] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2_CD,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_65,
+ PINCTRL_GRP_CAN1_16,
+ PINCTRL_GRP_I2C1_16,
+ PINCTRL_GRP_SWDT1_10_RST,
+ PINCTRL_GRP_SPI0_5_SS2,
+ PINCTRL_GRP_TTC3_8_WAV,
+ PINCTRL_GRP_UART1_16,
+ PINCTRL_GRP_TRACE0_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_66] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_66,
+ PINCTRL_GRP_CAN0_16,
+ PINCTRL_GRP_I2C0_16,
+ PINCTRL_GRP_SWDT0_10_CLK,
+ PINCTRL_GRP_SPI0_5_SS1,
+ PINCTRL_GRP_TTC2_8_CLK,
+ PINCTRL_GRP_UART0_16,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_67] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_67,
+ PINCTRL_GRP_CAN0_16,
+ PINCTRL_GRP_I2C0_16,
+ PINCTRL_GRP_SWDT0_10_RST,
+ PINCTRL_GRP_SPI0_5_SS0,
+ PINCTRL_GRP_TTC2_8_WAV,
+ PINCTRL_GRP_UART0_16,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_68] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_68,
+ PINCTRL_GRP_CAN1_17,
+ PINCTRL_GRP_I2C1_17,
+ PINCTRL_GRP_SWDT1_11_CLK,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_TTC1_8_CLK,
+ PINCTRL_GRP_UART1_17,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_69] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_1_WP,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_69,
+ PINCTRL_GRP_CAN1_17,
+ PINCTRL_GRP_I2C1_17,
+ PINCTRL_GRP_SWDT1_11_RST,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_TTC1_8_WAV,
+ PINCTRL_GRP_UART1_17,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_70] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_1_PC,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_70,
+ PINCTRL_GRP_CAN0_17,
+ PINCTRL_GRP_I2C0_17,
+ PINCTRL_GRP_SWDT0_11_CLK,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_TTC0_8_CLK,
+ PINCTRL_GRP_UART0_17,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_71] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_71,
+ PINCTRL_GRP_CAN0_17,
+ PINCTRL_GRP_I2C0_17,
+ PINCTRL_GRP_SWDT0_11_RST,
+ PINCTRL_GRP_SPI1_5_SS2,
+ PINCTRL_GRP_TTC0_8_WAV,
+ PINCTRL_GRP_UART0_17,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_72] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_72,
+ PINCTRL_GRP_CAN1_18,
+ PINCTRL_GRP_I2C1_18,
+ PINCTRL_GRP_SWDT1_12_CLK,
+ PINCTRL_GRP_SPI1_5_SS1,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART1_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_73] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_73,
+ PINCTRL_GRP_CAN1_18,
+ PINCTRL_GRP_I2C1_18,
+ PINCTRL_GRP_SWDT1_12_RST,
+ PINCTRL_GRP_SPI1_5_SS0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART1_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_74] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_74,
+ PINCTRL_GRP_CAN0_18,
+ PINCTRL_GRP_I2C0_18,
+ PINCTRL_GRP_SWDT0_12_CLK,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART0_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_75] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_SDIO0_2_PC,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_75,
+ PINCTRL_GRP_CAN0_18,
+ PINCTRL_GRP_I2C0_18,
+ PINCTRL_GRP_SWDT0_12_RST,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_UART0_18,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_76] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO0_2_WP,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_76,
+ PINCTRL_GRP_CAN1_19,
+ PINCTRL_GRP_I2C1_19,
+ PINCTRL_GRP_MDIO0_0,
+ PINCTRL_GRP_MDIO1_1,
+ PINCTRL_GRP_MDIO2_0,
+ PINCTRL_GRP_MDIO3_0,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ END_OF_GROUPS,
+ }),
+ },
+ [PINCTRL_PIN_77] = {
+ .groups = &((uint16_t []) {
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_SDIO1_1_CD,
+ PINCTRL_GRP_RESERVED,
+ PINCTRL_GRP_GPIO0_77,
+ PINCTRL_GRP_CAN1_19,
+ PINCTRL_GRP_I2C1_19,
+ PINCTRL_GRP_MDIO0_0,
+ PINCTRL_GRP_MDIO1_1,
+ PINCTRL_GRP_MDIO2_0,
+ PINCTRL_GRP_MDIO3_0,
+ PINCTRL_GRP_RESERVED,
+ END_OF_GROUPS,
+ }),
+ },
+};
+
+/**
+ * pm_api_pinctrl_get_num_pins() - PM call to request number of pins
+ * @npins Number of pins
+ *
+ * This function is used by master to get number of pins
+ *
+ * @return Returns success.
+ */
+enum pm_ret_status pm_api_pinctrl_get_num_pins(uint32_t *npins)
+{
+ *npins = MAX_PIN;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_num_functions() - PM call to request number of functions
+ * @nfuncs Number of functions
+ *
+ * This function is used by master to get number of functions
+ *
+ * @return Returns success.
+ */
+enum pm_ret_status pm_api_pinctrl_get_num_functions(uint32_t *nfuncs)
+{
+ *nfuncs = MAX_FUNCTION;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_num_func_groups() - PM call to request number of
+ * function groups
+ * @fid Function Id
+ * @ngroups Number of function groups
+ *
+ * This function is used by master to get number of function groups
+ *
+ * @return Returns success.
+ */
+enum pm_ret_status pm_api_pinctrl_get_num_func_groups(uint32_t fid,
+ uint32_t *ngroups)
+{
+ if (fid >= MAX_FUNCTION) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ *ngroups = pinctrl_functions[fid].group_size;
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_function_name() - PM call to request a function name
+ * @fid Function ID
+ * @name Name of function (max 16 bytes)
+ *
+ * This function is used by master to get name of function specified
+ * by given function ID.
+ */
+void pm_api_pinctrl_get_function_name(uint32_t fid, char *name)
+{
+ if (fid >= MAX_FUNCTION) {
+ memcpy(name, END_OF_FUNCTION, FUNCTION_NAME_LEN);
+ } else {
+ memcpy(name, pinctrl_functions[fid].name, FUNCTION_NAME_LEN);
+ }
+}
+
+/**
+ * pm_api_pinctrl_get_function_groups() - PM call to request first 6 function
+ * groups of function Id
+ * @fid Function ID
+ * @index Index of next function groups
+ * @groups Function groups
+ *
+ * This function is used by master to get function groups specified
+ * by given function Id. This API will return 6 function groups with
+ * a single response. To get other function groups, master should call
+ * same API in loop with new function groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return function groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * function groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_pinctrl_get_function_groups(uint32_t fid,
+ uint32_t index,
+ uint16_t *groups)
+{
+ uint16_t grps;
+ uint16_t end_of_grp_offset;
+ uint16_t i;
+
+ if (fid >= MAX_FUNCTION) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN);
+
+ grps = pinctrl_functions[fid].group_base;
+ end_of_grp_offset = grps + pinctrl_functions[fid].group_size;
+
+ for (i = 0U; i < NUM_GROUPS_PER_RESP; i++) {
+ if ((grps + index + i) >= end_of_grp_offset) {
+ break;
+ }
+ groups[i] = (grps + index + i);
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_api_pinctrl_get_pin_groups() - PM call to request first 6 pin
+ * groups of pin
+ * @pin Pin
+ * @index Index of next pin groups
+ * @groups pin groups
+ *
+ * This function is used by master to get pin groups specified
+ * by given pin Id. This API will return 6 pin groups with
+ * a single response. To get other pin groups, master should call
+ * same API in loop with new pin groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return pin groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * pin groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_pinctrl_get_pin_groups(uint32_t pin,
+ uint32_t index,
+ uint16_t *groups)
+{
+ uint32_t i;
+ uint16_t *grps;
+
+ if (pin >= MAX_PIN) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN);
+
+ grps = *zynqmp_pin_groups[pin].groups;
+ if (grps == NULL) {
+ return PM_RET_SUCCESS;
+ }
+
+ /* Skip groups till index */
+ for (i = 0; i < index; i++) {
+ if (grps[i] == (uint16_t)END_OF_GROUPS) {
+ return PM_RET_SUCCESS;
+ }
+ }
+
+ for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+ groups[i] = grps[index + i];
+ if (groups[i] == (uint16_t)END_OF_GROUPS) {
+ break;
+ }
+ }
+
+ return PM_RET_SUCCESS;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
new file mode 100644
index 0000000..5c4cb45
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for pin control.
+ */
+
+#ifndef PM_API_PINCTRL_H
+#define PM_API_PINCTRL_H
+
+#include "pm_common.h"
+
+#define FUNCTION_NAME_LEN (16U)
+#define GROUPS_PAYLOAD_LEN (12U)
+#define NUM_GROUPS_PER_RESP (6U)
+#define END_OF_FUNCTION "END_OF_FUNCTION"
+#define END_OF_GROUPS -1
+#define PINCTRL_GRP_RESERVED -2
+
+//pinctrl function ids
+enum {
+ PINCTRL_FUNC_CAN0 = (0U),
+ PINCTRL_FUNC_CAN1 = (1U),
+ PINCTRL_FUNC_ETHERNET0 = (2U),
+ PINCTRL_FUNC_ETHERNET1 = (3U),
+ PINCTRL_FUNC_ETHERNET2 = (4U),
+ PINCTRL_FUNC_ETHERNET3 = (5U),
+ PINCTRL_FUNC_GEMTSU0 = (6U),
+ PINCTRL_FUNC_GPIO0 = (7U),
+ PINCTRL_FUNC_I2C0 = (8U),
+ PINCTRL_FUNC_I2C1 = (9U),
+ PINCTRL_FUNC_MDIO0 = (10U),
+ PINCTRL_FUNC_MDIO1 = (11U),
+ PINCTRL_FUNC_MDIO2 = (12U),
+ PINCTRL_FUNC_MDIO3 = (13U),
+ PINCTRL_FUNC_QSPI0 = (14U),
+ PINCTRL_FUNC_QSPI_FBCLK = (15U),
+ PINCTRL_FUNC_QSPI_SS = (16U),
+ PINCTRL_FUNC_SPI0 = (17U),
+ PINCTRL_FUNC_SPI1 = (18U),
+ PINCTRL_FUNC_SPI0_SS = (19U),
+ PINCTRL_FUNC_SPI1_SS = (20U),
+ PINCTRL_FUNC_SDIO0 = (21U),
+ PINCTRL_FUNC_SDIO0_PC = (22U),
+ PINCTRL_FUNC_SDIO0_CD = (23U),
+ PINCTRL_FUNC_SDIO0_WP = (24U),
+ PINCTRL_FUNC_SDIO1 = (25U),
+ PINCTRL_FUNC_SDIO1_PC = (26U),
+ PINCTRL_FUNC_SDIO1_CD = (27U),
+ PINCTRL_FUNC_SDIO1_WP = (28U),
+ PINCTRL_FUNC_NAND0 = (29U),
+ PINCTRL_FUNC_NAND0_CE = (30U),
+ PINCTRL_FUNC_NAND0_RB = (31U),
+ PINCTRL_FUNC_NAND0_DQS = (32U),
+ PINCTRL_FUNC_TTC0_CLK = (33U),
+ PINCTRL_FUNC_TTC0_WAV = (34U),
+ PINCTRL_FUNC_TTC1_CLK = (35U),
+ PINCTRL_FUNC_TTC1_WAV = (36U),
+ PINCTRL_FUNC_TTC2_CLK = (37U),
+ PINCTRL_FUNC_TTC2_WAV = (38U),
+ PINCTRL_FUNC_TTC3_CLK = (39U),
+ PINCTRL_FUNC_TTC3_WAV = (40U),
+ PINCTRL_FUNC_UART0 = (41U),
+ PINCTRL_FUNC_UART1 = (42U),
+ PINCTRL_FUNC_USB0 = (43U),
+ PINCTRL_FUNC_USB1 = (44U),
+ PINCTRL_FUNC_SWDT0_CLK = (45U),
+ PINCTRL_FUNC_SWDT0_RST = (46U),
+ PINCTRL_FUNC_SWDT1_CLK = (47U),
+ PINCTRL_FUNC_SWDT1_RST = (48U),
+ PINCTRL_FUNC_PMU0 = (49U),
+ PINCTRL_FUNC_PCIE0 = (50U),
+ PINCTRL_FUNC_CSU0 = (51U),
+ PINCTRL_FUNC_DPAUX0 = (52U),
+ PINCTRL_FUNC_PJTAG0 = (53U),
+ PINCTRL_FUNC_TRACE0 = (54U),
+ PINCTRL_FUNC_TRACE0_CLK = (55U),
+ PINCTRL_FUNC_TESTSCAN0 = (56U),
+ END_FUNCTION = (57U),
+};
+
+#define MAX_FUNCTION END_FUNCTION
+
+// pinctrl pin numbers
+enum {
+ PINCTRL_PIN_0,
+ PINCTRL_PIN_1,
+ PINCTRL_PIN_2,
+ PINCTRL_PIN_3,
+ PINCTRL_PIN_4,
+ PINCTRL_PIN_5,
+ PINCTRL_PIN_6,
+ PINCTRL_PIN_7,
+ PINCTRL_PIN_8,
+ PINCTRL_PIN_9,
+ PINCTRL_PIN_10,
+ PINCTRL_PIN_11,
+ PINCTRL_PIN_12,
+ PINCTRL_PIN_13,
+ PINCTRL_PIN_14,
+ PINCTRL_PIN_15,
+ PINCTRL_PIN_16,
+ PINCTRL_PIN_17,
+ PINCTRL_PIN_18,
+ PINCTRL_PIN_19,
+ PINCTRL_PIN_20,
+ PINCTRL_PIN_21,
+ PINCTRL_PIN_22,
+ PINCTRL_PIN_23,
+ PINCTRL_PIN_24,
+ PINCTRL_PIN_25,
+ PINCTRL_PIN_26,
+ PINCTRL_PIN_27,
+ PINCTRL_PIN_28,
+ PINCTRL_PIN_29,
+ PINCTRL_PIN_30,
+ PINCTRL_PIN_31,
+ PINCTRL_PIN_32,
+ PINCTRL_PIN_33,
+ PINCTRL_PIN_34,
+ PINCTRL_PIN_35,
+ PINCTRL_PIN_36,
+ PINCTRL_PIN_37,
+ PINCTRL_PIN_38,
+ PINCTRL_PIN_39,
+ PINCTRL_PIN_40,
+ PINCTRL_PIN_41,
+ PINCTRL_PIN_42,
+ PINCTRL_PIN_43,
+ PINCTRL_PIN_44,
+ PINCTRL_PIN_45,
+ PINCTRL_PIN_46,
+ PINCTRL_PIN_47,
+ PINCTRL_PIN_48,
+ PINCTRL_PIN_49,
+ PINCTRL_PIN_50,
+ PINCTRL_PIN_51,
+ PINCTRL_PIN_52,
+ PINCTRL_PIN_53,
+ PINCTRL_PIN_54,
+ PINCTRL_PIN_55,
+ PINCTRL_PIN_56,
+ PINCTRL_PIN_57,
+ PINCTRL_PIN_58,
+ PINCTRL_PIN_59,
+ PINCTRL_PIN_60,
+ PINCTRL_PIN_61,
+ PINCTRL_PIN_62,
+ PINCTRL_PIN_63,
+ PINCTRL_PIN_64,
+ PINCTRL_PIN_65,
+ PINCTRL_PIN_66,
+ PINCTRL_PIN_67,
+ PINCTRL_PIN_68,
+ PINCTRL_PIN_69,
+ PINCTRL_PIN_70,
+ PINCTRL_PIN_71,
+ PINCTRL_PIN_72,
+ PINCTRL_PIN_73,
+ PINCTRL_PIN_74,
+ PINCTRL_PIN_75,
+ PINCTRL_PIN_76,
+ PINCTRL_PIN_77,
+ END_PINS = (78U),
+};
+
+#define MAX_PIN END_PINS
+
+// pinctrl group ids
+enum {
+ PINCTRL_GRP_ETHERNET0_0,
+ PINCTRL_GRP_ETHERNET1_0,
+ PINCTRL_GRP_ETHERNET2_0,
+ PINCTRL_GRP_ETHERNET3_0,
+ PINCTRL_GRP_GEMTSU0_0,
+ PINCTRL_GRP_GEMTSU0_1,
+ PINCTRL_GRP_GEMTSU0_2,
+ PINCTRL_GRP_MDIO0_0,
+ PINCTRL_GRP_MDIO1_0,
+ PINCTRL_GRP_MDIO1_1,
+ PINCTRL_GRP_MDIO2_0,
+ PINCTRL_GRP_MDIO3_0,
+ PINCTRL_GRP_QSPI0_0,
+ PINCTRL_GRP_QSPI_SS,
+ PINCTRL_GRP_QSPI_FBCLK,
+ PINCTRL_GRP_SPI0_0,
+ PINCTRL_GRP_SPI0_1,
+ PINCTRL_GRP_SPI0_2,
+ PINCTRL_GRP_SPI0_3,
+ PINCTRL_GRP_SPI0_4,
+ PINCTRL_GRP_SPI0_5,
+ PINCTRL_GRP_SPI0_0_SS0,
+ PINCTRL_GRP_SPI0_0_SS1,
+ PINCTRL_GRP_SPI0_0_SS2,
+ PINCTRL_GRP_SPI0_1_SS0,
+ PINCTRL_GRP_SPI0_1_SS1,
+ PINCTRL_GRP_SPI0_1_SS2,
+ PINCTRL_GRP_SPI0_2_SS0,
+ PINCTRL_GRP_SPI0_2_SS1,
+ PINCTRL_GRP_SPI0_2_SS2,
+ PINCTRL_GRP_SPI0_3_SS0,
+ PINCTRL_GRP_SPI0_3_SS1,
+ PINCTRL_GRP_SPI0_3_SS2,
+ PINCTRL_GRP_SPI0_4_SS0,
+ PINCTRL_GRP_SPI0_4_SS1,
+ PINCTRL_GRP_SPI0_4_SS2,
+ PINCTRL_GRP_SPI0_5_SS0,
+ PINCTRL_GRP_SPI0_5_SS1,
+ PINCTRL_GRP_SPI0_5_SS2,
+ PINCTRL_GRP_SPI1_0,
+ PINCTRL_GRP_SPI1_1,
+ PINCTRL_GRP_SPI1_2,
+ PINCTRL_GRP_SPI1_3,
+ PINCTRL_GRP_SPI1_4,
+ PINCTRL_GRP_SPI1_5,
+ PINCTRL_GRP_SPI1_0_SS0,
+ PINCTRL_GRP_SPI1_0_SS1,
+ PINCTRL_GRP_SPI1_0_SS2,
+ PINCTRL_GRP_SPI1_1_SS0,
+ PINCTRL_GRP_SPI1_1_SS1,
+ PINCTRL_GRP_SPI1_1_SS2,
+ PINCTRL_GRP_SPI1_2_SS0,
+ PINCTRL_GRP_SPI1_2_SS1,
+ PINCTRL_GRP_SPI1_2_SS2,
+ PINCTRL_GRP_SPI1_3_SS0,
+ PINCTRL_GRP_SPI1_3_SS1,
+ PINCTRL_GRP_SPI1_3_SS2,
+ PINCTRL_GRP_SPI1_4_SS0,
+ PINCTRL_GRP_SPI1_4_SS1,
+ PINCTRL_GRP_SPI1_4_SS2,
+ PINCTRL_GRP_SPI1_5_SS0,
+ PINCTRL_GRP_SPI1_5_SS1,
+ PINCTRL_GRP_SPI1_5_SS2,
+ PINCTRL_GRP_SDIO0_0,
+ PINCTRL_GRP_SDIO0_1,
+ PINCTRL_GRP_SDIO0_2,
+ PINCTRL_GRP_SDIO0_4BIT_0_0,
+ PINCTRL_GRP_SDIO0_4BIT_0_1,
+ PINCTRL_GRP_SDIO0_4BIT_1_0,
+ PINCTRL_GRP_SDIO0_4BIT_1_1,
+ PINCTRL_GRP_SDIO0_4BIT_2_0,
+ PINCTRL_GRP_SDIO0_4BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_0,
+ PINCTRL_GRP_SDIO0_1BIT_0_1,
+ PINCTRL_GRP_SDIO0_1BIT_0_2,
+ PINCTRL_GRP_SDIO0_1BIT_0_3,
+ PINCTRL_GRP_SDIO0_1BIT_0_4,
+ PINCTRL_GRP_SDIO0_1BIT_0_5,
+ PINCTRL_GRP_SDIO0_1BIT_0_6,
+ PINCTRL_GRP_SDIO0_1BIT_0_7,
+ PINCTRL_GRP_SDIO0_1BIT_1_0,
+ PINCTRL_GRP_SDIO0_1BIT_1_1,
+ PINCTRL_GRP_SDIO0_1BIT_1_2,
+ PINCTRL_GRP_SDIO0_1BIT_1_3,
+ PINCTRL_GRP_SDIO0_1BIT_1_4,
+ PINCTRL_GRP_SDIO0_1BIT_1_5,
+ PINCTRL_GRP_SDIO0_1BIT_1_6,
+ PINCTRL_GRP_SDIO0_1BIT_1_7,
+ PINCTRL_GRP_SDIO0_1BIT_2_0,
+ PINCTRL_GRP_SDIO0_1BIT_2_1,
+ PINCTRL_GRP_SDIO0_1BIT_2_2,
+ PINCTRL_GRP_SDIO0_1BIT_2_3,
+ PINCTRL_GRP_SDIO0_1BIT_2_4,
+ PINCTRL_GRP_SDIO0_1BIT_2_5,
+ PINCTRL_GRP_SDIO0_1BIT_2_6,
+ PINCTRL_GRP_SDIO0_1BIT_2_7,
+ PINCTRL_GRP_SDIO0_0_PC,
+ PINCTRL_GRP_SDIO0_1_PC,
+ PINCTRL_GRP_SDIO0_2_PC,
+ PINCTRL_GRP_SDIO0_0_CD,
+ PINCTRL_GRP_SDIO0_1_CD,
+ PINCTRL_GRP_SDIO0_2_CD,
+ PINCTRL_GRP_SDIO0_0_WP,
+ PINCTRL_GRP_SDIO0_1_WP,
+ PINCTRL_GRP_SDIO0_2_WP,
+ PINCTRL_GRP_SDIO1_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_0,
+ PINCTRL_GRP_SDIO1_4BIT_0_1,
+ PINCTRL_GRP_SDIO1_4BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_0,
+ PINCTRL_GRP_SDIO1_1BIT_0_1,
+ PINCTRL_GRP_SDIO1_1BIT_0_2,
+ PINCTRL_GRP_SDIO1_1BIT_0_3,
+ PINCTRL_GRP_SDIO1_1BIT_0_4,
+ PINCTRL_GRP_SDIO1_1BIT_0_5,
+ PINCTRL_GRP_SDIO1_1BIT_0_6,
+ PINCTRL_GRP_SDIO1_1BIT_0_7,
+ PINCTRL_GRP_SDIO1_1BIT_1_0,
+ PINCTRL_GRP_SDIO1_1BIT_1_1,
+ PINCTRL_GRP_SDIO1_1BIT_1_2,
+ PINCTRL_GRP_SDIO1_1BIT_1_3,
+ PINCTRL_GRP_SDIO1_0_PC,
+ PINCTRL_GRP_SDIO1_1_PC,
+ PINCTRL_GRP_SDIO1_0_CD,
+ PINCTRL_GRP_SDIO1_1_CD,
+ PINCTRL_GRP_SDIO1_0_WP,
+ PINCTRL_GRP_SDIO1_1_WP,
+ PINCTRL_GRP_NAND0_0,
+ PINCTRL_GRP_NAND0_0_CE,
+ PINCTRL_GRP_NAND0_1_CE,
+ PINCTRL_GRP_NAND0_0_RB,
+ PINCTRL_GRP_NAND0_1_RB,
+ PINCTRL_GRP_NAND0_0_DQS,
+ PINCTRL_GRP_NAND0_1_DQS,
+ PINCTRL_GRP_CAN0_0,
+ PINCTRL_GRP_CAN0_1,
+ PINCTRL_GRP_CAN0_2,
+ PINCTRL_GRP_CAN0_3,
+ PINCTRL_GRP_CAN0_4,
+ PINCTRL_GRP_CAN0_5,
+ PINCTRL_GRP_CAN0_6,
+ PINCTRL_GRP_CAN0_7,
+ PINCTRL_GRP_CAN0_8,
+ PINCTRL_GRP_CAN0_9,
+ PINCTRL_GRP_CAN0_10,
+ PINCTRL_GRP_CAN0_11,
+ PINCTRL_GRP_CAN0_12,
+ PINCTRL_GRP_CAN0_13,
+ PINCTRL_GRP_CAN0_14,
+ PINCTRL_GRP_CAN0_15,
+ PINCTRL_GRP_CAN0_16,
+ PINCTRL_GRP_CAN0_17,
+ PINCTRL_GRP_CAN0_18,
+ PINCTRL_GRP_CAN1_0,
+ PINCTRL_GRP_CAN1_1,
+ PINCTRL_GRP_CAN1_2,
+ PINCTRL_GRP_CAN1_3,
+ PINCTRL_GRP_CAN1_4,
+ PINCTRL_GRP_CAN1_5,
+ PINCTRL_GRP_CAN1_6,
+ PINCTRL_GRP_CAN1_7,
+ PINCTRL_GRP_CAN1_8,
+ PINCTRL_GRP_CAN1_9,
+ PINCTRL_GRP_CAN1_10,
+ PINCTRL_GRP_CAN1_11,
+ PINCTRL_GRP_CAN1_12,
+ PINCTRL_GRP_CAN1_13,
+ PINCTRL_GRP_CAN1_14,
+ PINCTRL_GRP_CAN1_15,
+ PINCTRL_GRP_CAN1_16,
+ PINCTRL_GRP_CAN1_17,
+ PINCTRL_GRP_CAN1_18,
+ PINCTRL_GRP_CAN1_19,
+ PINCTRL_GRP_UART0_0,
+ PINCTRL_GRP_UART0_1,
+ PINCTRL_GRP_UART0_2,
+ PINCTRL_GRP_UART0_3,
+ PINCTRL_GRP_UART0_4,
+ PINCTRL_GRP_UART0_5,
+ PINCTRL_GRP_UART0_6,
+ PINCTRL_GRP_UART0_7,
+ PINCTRL_GRP_UART0_8,
+ PINCTRL_GRP_UART0_9,
+ PINCTRL_GRP_UART0_10,
+ PINCTRL_GRP_UART0_11,
+ PINCTRL_GRP_UART0_12,
+ PINCTRL_GRP_UART0_13,
+ PINCTRL_GRP_UART0_14,
+ PINCTRL_GRP_UART0_15,
+ PINCTRL_GRP_UART0_16,
+ PINCTRL_GRP_UART0_17,
+ PINCTRL_GRP_UART0_18,
+ PINCTRL_GRP_UART1_0,
+ PINCTRL_GRP_UART1_1,
+ PINCTRL_GRP_UART1_2,
+ PINCTRL_GRP_UART1_3,
+ PINCTRL_GRP_UART1_4,
+ PINCTRL_GRP_UART1_5,
+ PINCTRL_GRP_UART1_6,
+ PINCTRL_GRP_UART1_7,
+ PINCTRL_GRP_UART1_8,
+ PINCTRL_GRP_UART1_9,
+ PINCTRL_GRP_UART1_10,
+ PINCTRL_GRP_UART1_11,
+ PINCTRL_GRP_UART1_12,
+ PINCTRL_GRP_UART1_13,
+ PINCTRL_GRP_UART1_14,
+ PINCTRL_GRP_UART1_15,
+ PINCTRL_GRP_UART1_16,
+ PINCTRL_GRP_UART1_17,
+ PINCTRL_GRP_UART1_18,
+ PINCTRL_GRP_I2C0_0,
+ PINCTRL_GRP_I2C0_1,
+ PINCTRL_GRP_I2C0_2,
+ PINCTRL_GRP_I2C0_3,
+ PINCTRL_GRP_I2C0_4,
+ PINCTRL_GRP_I2C0_5,
+ PINCTRL_GRP_I2C0_6,
+ PINCTRL_GRP_I2C0_7,
+ PINCTRL_GRP_I2C0_8,
+ PINCTRL_GRP_I2C0_9,
+ PINCTRL_GRP_I2C0_10,
+ PINCTRL_GRP_I2C0_11,
+ PINCTRL_GRP_I2C0_12,
+ PINCTRL_GRP_I2C0_13,
+ PINCTRL_GRP_I2C0_14,
+ PINCTRL_GRP_I2C0_15,
+ PINCTRL_GRP_I2C0_16,
+ PINCTRL_GRP_I2C0_17,
+ PINCTRL_GRP_I2C0_18,
+ PINCTRL_GRP_I2C1_0,
+ PINCTRL_GRP_I2C1_1,
+ PINCTRL_GRP_I2C1_2,
+ PINCTRL_GRP_I2C1_3,
+ PINCTRL_GRP_I2C1_4,
+ PINCTRL_GRP_I2C1_5,
+ PINCTRL_GRP_I2C1_6,
+ PINCTRL_GRP_I2C1_7,
+ PINCTRL_GRP_I2C1_8,
+ PINCTRL_GRP_I2C1_9,
+ PINCTRL_GRP_I2C1_10,
+ PINCTRL_GRP_I2C1_11,
+ PINCTRL_GRP_I2C1_12,
+ PINCTRL_GRP_I2C1_13,
+ PINCTRL_GRP_I2C1_14,
+ PINCTRL_GRP_I2C1_15,
+ PINCTRL_GRP_I2C1_16,
+ PINCTRL_GRP_I2C1_17,
+ PINCTRL_GRP_I2C1_18,
+ PINCTRL_GRP_I2C1_19,
+ PINCTRL_GRP_TTC0_0_CLK,
+ PINCTRL_GRP_TTC0_1_CLK,
+ PINCTRL_GRP_TTC0_2_CLK,
+ PINCTRL_GRP_TTC0_3_CLK,
+ PINCTRL_GRP_TTC0_4_CLK,
+ PINCTRL_GRP_TTC0_5_CLK,
+ PINCTRL_GRP_TTC0_6_CLK,
+ PINCTRL_GRP_TTC0_7_CLK,
+ PINCTRL_GRP_TTC0_8_CLK,
+ PINCTRL_GRP_TTC0_0_WAV,
+ PINCTRL_GRP_TTC0_1_WAV,
+ PINCTRL_GRP_TTC0_2_WAV,
+ PINCTRL_GRP_TTC0_3_WAV,
+ PINCTRL_GRP_TTC0_4_WAV,
+ PINCTRL_GRP_TTC0_5_WAV,
+ PINCTRL_GRP_TTC0_6_WAV,
+ PINCTRL_GRP_TTC0_7_WAV,
+ PINCTRL_GRP_TTC0_8_WAV,
+ PINCTRL_GRP_TTC1_0_CLK,
+ PINCTRL_GRP_TTC1_1_CLK,
+ PINCTRL_GRP_TTC1_2_CLK,
+ PINCTRL_GRP_TTC1_3_CLK,
+ PINCTRL_GRP_TTC1_4_CLK,
+ PINCTRL_GRP_TTC1_5_CLK,
+ PINCTRL_GRP_TTC1_6_CLK,
+ PINCTRL_GRP_TTC1_7_CLK,
+ PINCTRL_GRP_TTC1_8_CLK,
+ PINCTRL_GRP_TTC1_0_WAV,
+ PINCTRL_GRP_TTC1_1_WAV,
+ PINCTRL_GRP_TTC1_2_WAV,
+ PINCTRL_GRP_TTC1_3_WAV,
+ PINCTRL_GRP_TTC1_4_WAV,
+ PINCTRL_GRP_TTC1_5_WAV,
+ PINCTRL_GRP_TTC1_6_WAV,
+ PINCTRL_GRP_TTC1_7_WAV,
+ PINCTRL_GRP_TTC1_8_WAV,
+ PINCTRL_GRP_TTC2_0_CLK,
+ PINCTRL_GRP_TTC2_1_CLK,
+ PINCTRL_GRP_TTC2_2_CLK,
+ PINCTRL_GRP_TTC2_3_CLK,
+ PINCTRL_GRP_TTC2_4_CLK,
+ PINCTRL_GRP_TTC2_5_CLK,
+ PINCTRL_GRP_TTC2_6_CLK,
+ PINCTRL_GRP_TTC2_7_CLK,
+ PINCTRL_GRP_TTC2_8_CLK,
+ PINCTRL_GRP_TTC2_0_WAV,
+ PINCTRL_GRP_TTC2_1_WAV,
+ PINCTRL_GRP_TTC2_2_WAV,
+ PINCTRL_GRP_TTC2_3_WAV,
+ PINCTRL_GRP_TTC2_4_WAV,
+ PINCTRL_GRP_TTC2_5_WAV,
+ PINCTRL_GRP_TTC2_6_WAV,
+ PINCTRL_GRP_TTC2_7_WAV,
+ PINCTRL_GRP_TTC2_8_WAV,
+ PINCTRL_GRP_TTC3_0_CLK,
+ PINCTRL_GRP_TTC3_1_CLK,
+ PINCTRL_GRP_TTC3_2_CLK,
+ PINCTRL_GRP_TTC3_3_CLK,
+ PINCTRL_GRP_TTC3_4_CLK,
+ PINCTRL_GRP_TTC3_5_CLK,
+ PINCTRL_GRP_TTC3_6_CLK,
+ PINCTRL_GRP_TTC3_7_CLK,
+ PINCTRL_GRP_TTC3_8_CLK,
+ PINCTRL_GRP_TTC3_0_WAV,
+ PINCTRL_GRP_TTC3_1_WAV,
+ PINCTRL_GRP_TTC3_2_WAV,
+ PINCTRL_GRP_TTC3_3_WAV,
+ PINCTRL_GRP_TTC3_4_WAV,
+ PINCTRL_GRP_TTC3_5_WAV,
+ PINCTRL_GRP_TTC3_6_WAV,
+ PINCTRL_GRP_TTC3_7_WAV,
+ PINCTRL_GRP_TTC3_8_WAV,
+ PINCTRL_GRP_SWDT0_0_CLK,
+ PINCTRL_GRP_SWDT0_1_CLK,
+ PINCTRL_GRP_SWDT0_2_CLK,
+ PINCTRL_GRP_SWDT0_3_CLK,
+ PINCTRL_GRP_SWDT0_4_CLK,
+ PINCTRL_GRP_SWDT0_5_CLK,
+ PINCTRL_GRP_SWDT0_6_CLK,
+ PINCTRL_GRP_SWDT0_7_CLK,
+ PINCTRL_GRP_SWDT0_8_CLK,
+ PINCTRL_GRP_SWDT0_9_CLK,
+ PINCTRL_GRP_SWDT0_10_CLK,
+ PINCTRL_GRP_SWDT0_11_CLK,
+ PINCTRL_GRP_SWDT0_12_CLK,
+ PINCTRL_GRP_SWDT0_0_RST,
+ PINCTRL_GRP_SWDT0_1_RST,
+ PINCTRL_GRP_SWDT0_2_RST,
+ PINCTRL_GRP_SWDT0_3_RST,
+ PINCTRL_GRP_SWDT0_4_RST,
+ PINCTRL_GRP_SWDT0_5_RST,
+ PINCTRL_GRP_SWDT0_6_RST,
+ PINCTRL_GRP_SWDT0_7_RST,
+ PINCTRL_GRP_SWDT0_8_RST,
+ PINCTRL_GRP_SWDT0_9_RST,
+ PINCTRL_GRP_SWDT0_10_RST,
+ PINCTRL_GRP_SWDT0_11_RST,
+ PINCTRL_GRP_SWDT0_12_RST,
+ PINCTRL_GRP_SWDT1_0_CLK,
+ PINCTRL_GRP_SWDT1_1_CLK,
+ PINCTRL_GRP_SWDT1_2_CLK,
+ PINCTRL_GRP_SWDT1_3_CLK,
+ PINCTRL_GRP_SWDT1_4_CLK,
+ PINCTRL_GRP_SWDT1_5_CLK,
+ PINCTRL_GRP_SWDT1_6_CLK,
+ PINCTRL_GRP_SWDT1_7_CLK,
+ PINCTRL_GRP_SWDT1_8_CLK,
+ PINCTRL_GRP_SWDT1_9_CLK,
+ PINCTRL_GRP_SWDT1_10_CLK,
+ PINCTRL_GRP_SWDT1_11_CLK,
+ PINCTRL_GRP_SWDT1_12_CLK,
+ PINCTRL_GRP_SWDT1_0_RST,
+ PINCTRL_GRP_SWDT1_1_RST,
+ PINCTRL_GRP_SWDT1_2_RST,
+ PINCTRL_GRP_SWDT1_3_RST,
+ PINCTRL_GRP_SWDT1_4_RST,
+ PINCTRL_GRP_SWDT1_5_RST,
+ PINCTRL_GRP_SWDT1_6_RST,
+ PINCTRL_GRP_SWDT1_7_RST,
+ PINCTRL_GRP_SWDT1_8_RST,
+ PINCTRL_GRP_SWDT1_9_RST,
+ PINCTRL_GRP_SWDT1_10_RST,
+ PINCTRL_GRP_SWDT1_11_RST,
+ PINCTRL_GRP_SWDT1_12_RST,
+ PINCTRL_GRP_GPIO0_0,
+ PINCTRL_GRP_GPIO0_1,
+ PINCTRL_GRP_GPIO0_2,
+ PINCTRL_GRP_GPIO0_3,
+ PINCTRL_GRP_GPIO0_4,
+ PINCTRL_GRP_GPIO0_5,
+ PINCTRL_GRP_GPIO0_6,
+ PINCTRL_GRP_GPIO0_7,
+ PINCTRL_GRP_GPIO0_8,
+ PINCTRL_GRP_GPIO0_9,
+ PINCTRL_GRP_GPIO0_10,
+ PINCTRL_GRP_GPIO0_11,
+ PINCTRL_GRP_GPIO0_12,
+ PINCTRL_GRP_GPIO0_13,
+ PINCTRL_GRP_GPIO0_14,
+ PINCTRL_GRP_GPIO0_15,
+ PINCTRL_GRP_GPIO0_16,
+ PINCTRL_GRP_GPIO0_17,
+ PINCTRL_GRP_GPIO0_18,
+ PINCTRL_GRP_GPIO0_19,
+ PINCTRL_GRP_GPIO0_20,
+ PINCTRL_GRP_GPIO0_21,
+ PINCTRL_GRP_GPIO0_22,
+ PINCTRL_GRP_GPIO0_23,
+ PINCTRL_GRP_GPIO0_24,
+ PINCTRL_GRP_GPIO0_25,
+ PINCTRL_GRP_GPIO0_26,
+ PINCTRL_GRP_GPIO0_27,
+ PINCTRL_GRP_GPIO0_28,
+ PINCTRL_GRP_GPIO0_29,
+ PINCTRL_GRP_GPIO0_30,
+ PINCTRL_GRP_GPIO0_31,
+ PINCTRL_GRP_GPIO0_32,
+ PINCTRL_GRP_GPIO0_33,
+ PINCTRL_GRP_GPIO0_34,
+ PINCTRL_GRP_GPIO0_35,
+ PINCTRL_GRP_GPIO0_36,
+ PINCTRL_GRP_GPIO0_37,
+ PINCTRL_GRP_GPIO0_38,
+ PINCTRL_GRP_GPIO0_39,
+ PINCTRL_GRP_GPIO0_40,
+ PINCTRL_GRP_GPIO0_41,
+ PINCTRL_GRP_GPIO0_42,
+ PINCTRL_GRP_GPIO0_43,
+ PINCTRL_GRP_GPIO0_44,
+ PINCTRL_GRP_GPIO0_45,
+ PINCTRL_GRP_GPIO0_46,
+ PINCTRL_GRP_GPIO0_47,
+ PINCTRL_GRP_GPIO0_48,
+ PINCTRL_GRP_GPIO0_49,
+ PINCTRL_GRP_GPIO0_50,
+ PINCTRL_GRP_GPIO0_51,
+ PINCTRL_GRP_GPIO0_52,
+ PINCTRL_GRP_GPIO0_53,
+ PINCTRL_GRP_GPIO0_54,
+ PINCTRL_GRP_GPIO0_55,
+ PINCTRL_GRP_GPIO0_56,
+ PINCTRL_GRP_GPIO0_57,
+ PINCTRL_GRP_GPIO0_58,
+ PINCTRL_GRP_GPIO0_59,
+ PINCTRL_GRP_GPIO0_60,
+ PINCTRL_GRP_GPIO0_61,
+ PINCTRL_GRP_GPIO0_62,
+ PINCTRL_GRP_GPIO0_63,
+ PINCTRL_GRP_GPIO0_64,
+ PINCTRL_GRP_GPIO0_65,
+ PINCTRL_GRP_GPIO0_66,
+ PINCTRL_GRP_GPIO0_67,
+ PINCTRL_GRP_GPIO0_68,
+ PINCTRL_GRP_GPIO0_69,
+ PINCTRL_GRP_GPIO0_70,
+ PINCTRL_GRP_GPIO0_71,
+ PINCTRL_GRP_GPIO0_72,
+ PINCTRL_GRP_GPIO0_73,
+ PINCTRL_GRP_GPIO0_74,
+ PINCTRL_GRP_GPIO0_75,
+ PINCTRL_GRP_GPIO0_76,
+ PINCTRL_GRP_GPIO0_77,
+ PINCTRL_GRP_USB0_0,
+ PINCTRL_GRP_USB1_0,
+ PINCTRL_GRP_PMU0_0,
+ PINCTRL_GRP_PMU0_1,
+ PINCTRL_GRP_PMU0_2,
+ PINCTRL_GRP_PMU0_3,
+ PINCTRL_GRP_PMU0_4,
+ PINCTRL_GRP_PMU0_5,
+ PINCTRL_GRP_PMU0_6,
+ PINCTRL_GRP_PMU0_7,
+ PINCTRL_GRP_PMU0_8,
+ PINCTRL_GRP_PMU0_9,
+ PINCTRL_GRP_PMU0_10,
+ PINCTRL_GRP_PMU0_11,
+ PINCTRL_GRP_PCIE0_0,
+ PINCTRL_GRP_PCIE0_1,
+ PINCTRL_GRP_PCIE0_2,
+ PINCTRL_GRP_PCIE0_3,
+ PINCTRL_GRP_PCIE0_4,
+ PINCTRL_GRP_PCIE0_5,
+ PINCTRL_GRP_PCIE0_6,
+ PINCTRL_GRP_PCIE0_7,
+ PINCTRL_GRP_CSU0_0,
+ PINCTRL_GRP_CSU0_1,
+ PINCTRL_GRP_CSU0_2,
+ PINCTRL_GRP_CSU0_3,
+ PINCTRL_GRP_CSU0_4,
+ PINCTRL_GRP_CSU0_5,
+ PINCTRL_GRP_CSU0_6,
+ PINCTRL_GRP_CSU0_7,
+ PINCTRL_GRP_CSU0_8,
+ PINCTRL_GRP_CSU0_9,
+ PINCTRL_GRP_CSU0_10,
+ PINCTRL_GRP_CSU0_11,
+ PINCTRL_GRP_DPAUX0_0,
+ PINCTRL_GRP_DPAUX0_1,
+ PINCTRL_GRP_DPAUX0_2,
+ PINCTRL_GRP_DPAUX0_3,
+ PINCTRL_GRP_PJTAG0_0,
+ PINCTRL_GRP_PJTAG0_1,
+ PINCTRL_GRP_PJTAG0_2,
+ PINCTRL_GRP_PJTAG0_3,
+ PINCTRL_GRP_PJTAG0_4,
+ PINCTRL_GRP_PJTAG0_5,
+ PINCTRL_GRP_TRACE0_0,
+ PINCTRL_GRP_TRACE0_1,
+ PINCTRL_GRP_TRACE0_2,
+ PINCTRL_GRP_TRACE0_0_CLK,
+ PINCTRL_GRP_TRACE0_1_CLK,
+ PINCTRL_GRP_TRACE0_2_CLK,
+ PINCTRL_GRP_TESTSCAN0_0,
+};
+
+// pinctrl config parameters
+enum {
+ PINCTRL_CONFIG_SLEW_RATE,
+ PINCTRL_CONFIG_BIAS_STATUS,
+ PINCTRL_CONFIG_PULL_CTRL,
+ PINCTRL_CONFIG_SCHMITT_CMOS,
+ PINCTRL_CONFIG_DRIVE_STRENGTH,
+ PINCTRL_CONFIG_VOLTAGE_STATUS,
+ PINCTRL_CONFIG_MAX,
+};
+
+// pinctrl slew rate
+#define PINCTRL_SLEW_RATE_FAST 0U
+#define PINCTRL_SLEW_RATE_SLOW 1U
+
+// pinctrl bias status
+#define PINCTRL_BIAS_DISABLE 0U
+#define PINCTRL_BIAS_ENABLE 1U
+
+// pinctrl pull control
+#define PINCTRL_BIAS_PULL_DOWN 0U
+#define PINCTRL_BIAS_PULL_UP 1U
+
+// pinctrl schmitt cmos type
+#define PINCTRL_INPUT_TYPE_CMOS 0U
+#define PINCTRL_INPUT_TYPE_SCHMITT 1U
+
+//pinctrl drive strength values
+#define PINCTRL_DRIVE_STRENGTH_2MA 0U
+#define PINCTRL_DRIVE_STRENGTH_4MA 1U
+#define PINCTRL_DRIVE_STRENGTH_8MA 2U
+#define PINCTRL_DRIVE_STRENGTH_12MA 3U
+
+void pm_api_pinctrl_get_function_name(uint32_t fid, char *name);
+enum pm_ret_status pm_api_pinctrl_get_function_groups(uint32_t fid,
+ uint32_t index,
+ uint16_t *groups);
+enum pm_ret_status pm_api_pinctrl_get_pin_groups(uint32_t pin,
+ uint32_t index,
+ uint16_t *groups);
+enum pm_ret_status pm_api_pinctrl_get_num_pins(uint32_t *npins);
+enum pm_ret_status pm_api_pinctrl_get_num_functions(uint32_t *nfuncs);
+enum pm_ret_status pm_api_pinctrl_get_num_func_groups(uint32_t fid,
+ uint32_t *ngroups);
+#endif /* PM_API_PINCTRL_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
new file mode 100644
index 0000000..a17b6c5
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -0,0 +1,1836 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions and communication with PMU via
+ * IPI interrupts
+ */
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#include "pm_api_clock.h"
+#include "pm_api_ioctl.h"
+#include "pm_api_pinctrl.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+
+#define PM_QUERY_FEATURE_BITMASK ( \
+ (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
+ (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \
+ (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
+ (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
+ (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
+ (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
+ (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
+ (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
+ (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
+ (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
+ (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
+ (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
+ (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
+
+/**
+ * struct eemi_api_dependency - Dependent EEMI APIs which are implemented
+ * on both the ATF and firmware
+ *
+ * @id: EEMI API id or IOCTL id to be checked
+ * @api_id: Dependent EEMI API
+ */
+typedef struct __attribute__((packed)) {
+ uint8_t id;
+ uint8_t api_id;
+} eemi_api_dependency;
+
+/* Dependent APIs for ATF to check their version from firmware */
+static const eemi_api_dependency api_dep_table[] = {
+ {
+ .id = PM_SELF_SUSPEND,
+ .api_id = PM_SELF_SUSPEND,
+ },
+ {
+ .id = PM_REQ_WAKEUP,
+ .api_id = PM_REQ_WAKEUP,
+ },
+ {
+ .id = PM_ABORT_SUSPEND,
+ .api_id = PM_ABORT_SUSPEND,
+ },
+ {
+ .id = PM_SET_WAKEUP_SOURCE,
+ .api_id = PM_SET_WAKEUP_SOURCE,
+ },
+ {
+ .id = PM_SYSTEM_SHUTDOWN,
+ .api_id = PM_SYSTEM_SHUTDOWN,
+ },
+ {
+ .id = PM_GET_API_VERSION,
+ .api_id = PM_GET_API_VERSION,
+ },
+ {
+ .id = PM_CLOCK_ENABLE,
+ .api_id = PM_PLL_SET_MODE,
+ },
+ {
+ .id = PM_CLOCK_ENABLE,
+ .api_id = PM_CLOCK_ENABLE,
+ },
+ {
+ .id = PM_CLOCK_DISABLE,
+ .api_id = PM_PLL_SET_MODE,
+ },
+ {
+ .id = PM_CLOCK_DISABLE,
+ .api_id = PM_CLOCK_DISABLE,
+ },
+ {
+ .id = PM_CLOCK_GETSTATE,
+ .api_id = PM_PLL_GET_MODE,
+ },
+ {
+ .id = PM_CLOCK_GETSTATE,
+ .api_id = PM_CLOCK_GETSTATE,
+ },
+ {
+ .id = PM_CLOCK_SETDIVIDER,
+ .api_id = PM_PLL_SET_PARAMETER,
+ },
+ {
+ .id = PM_CLOCK_SETDIVIDER,
+ .api_id = PM_CLOCK_SETDIVIDER,
+ },
+ {
+ .id = PM_CLOCK_GETDIVIDER,
+ .api_id = PM_PLL_GET_PARAMETER,
+ },
+ {
+ .id = PM_CLOCK_GETDIVIDER,
+ .api_id = PM_CLOCK_GETDIVIDER,
+ },
+ {
+ .id = PM_CLOCK_SETPARENT,
+ .api_id = PM_PLL_SET_PARAMETER,
+ },
+ {
+ .id = PM_CLOCK_SETPARENT,
+ .api_id = PM_CLOCK_SETPARENT,
+ },
+ {
+ .id = PM_CLOCK_GETPARENT,
+ .api_id = PM_PLL_GET_PARAMETER,
+ },
+ {
+ .id = PM_CLOCK_GETPARENT,
+ .api_id = PM_CLOCK_GETPARENT,
+ },
+ {
+ .id = PM_PLL_SET_PARAMETER,
+ .api_id = PM_PLL_SET_PARAMETER,
+ },
+ {
+ .id = PM_PLL_GET_PARAMETER,
+ .api_id = PM_PLL_GET_PARAMETER,
+ },
+ {
+ .id = PM_PLL_SET_MODE,
+ .api_id = PM_PLL_SET_MODE,
+ },
+ {
+ .id = PM_PLL_GET_MODE,
+ .api_id = PM_PLL_GET_MODE,
+ },
+ {
+ .id = PM_REGISTER_ACCESS,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = PM_REGISTER_ACCESS,
+ .api_id = PM_MMIO_READ,
+ },
+ {
+ .id = PM_FEATURE_CHECK,
+ .api_id = PM_FEATURE_CHECK,
+ },
+ {
+ .id = IOCTL_SET_TAPDELAY_BYPASS,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_SET_SGMII_MODE,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_SD_DLL_RESET,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_SET_SD_TAPDELAY,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_SET_SD_TAPDELAY,
+ .api_id = PM_MMIO_READ,
+ },
+ {
+ .id = IOCTL_SET_PLL_FRAC_DATA,
+ .api_id = PM_PLL_SET_PARAMETER,
+ },
+ {
+ .id = IOCTL_GET_PLL_FRAC_DATA,
+ .api_id = PM_PLL_GET_PARAMETER,
+ },
+ {
+ .id = IOCTL_WRITE_GGS,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_READ_GGS,
+ .api_id = PM_MMIO_READ,
+ },
+ {
+ .id = IOCTL_WRITE_PGGS,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_READ_PGGS,
+ .api_id = PM_MMIO_READ,
+ },
+ {
+ .id = IOCTL_ULPI_RESET,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_SET_BOOT_HEALTH_STATUS,
+ .api_id = PM_MMIO_WRITE,
+ },
+ {
+ .id = IOCTL_AFI,
+ .api_id = PM_MMIO_WRITE,
+ },
+};
+
+/* Expected firmware API version to ATF */
+static const uint8_t atf_expected_ver_id[] = {
+ [PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
+ [PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
+ [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
+ [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
+ [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
+ [PM_GET_API_VERSION] = FW_API_BASE_VERSION,
+ [PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
+ [PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
+ [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
+ [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
+ [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
+ [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
+ [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
+ [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
+ [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
+ [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
+ [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
+ [PM_MMIO_WRITE] = FW_API_BASE_VERSION,
+ [PM_MMIO_READ] = FW_API_BASE_VERSION,
+ [PM_FEATURE_CHECK] = FW_API_VERSION_2,
+};
+
+/* default shutdown/reboot scope is system(2) */
+static uint32_t pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
+
+/**
+ * pm_get_shutdown_scope() - Get the currently set shutdown scope
+ *
+ * @return Shutdown scope value
+ */
+uint32_t pm_get_shutdown_scope(void)
+{
+ return pm_shutdown_scope;
+}
+
+#define EM_PACK_PAYLOAD1(pl, arg0) { \
+ pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
+}
+
+/**
+ * pm_self_suspend() - PM call for processor to suspend itself
+ * @nid Node id of the processor or subsystem
+ * @latency Requested maximum wakeup latency (not supported)
+ * @state Requested state
+ * @address Resume address
+ *
+ * This is a blocking call, it will return only once PMU has responded.
+ * On a wakeup, resume address will be automatically set by PMU.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+ uint32_t latency,
+ uint32_t state,
+ uintptr_t address)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ uint32_t cpuid = plat_my_core_pos();
+ const struct pm_proc *proc = pm_get_proc(cpuid);
+
+ /*
+ * Do client specific suspend operations
+ * (e.g. set powerdown request bit)
+ */
+ pm_client_suspend(proc, state);
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
+ state, address, (address >> 32));
+ return pm_ipi_send_sync(proc, payload, NULL, 0);
+}
+
+/**
+ * pm_req_suspend() - PM call to request for another PU or subsystem to
+ * be suspended gracefully.
+ * @target Node id of the targeted PU or subsystem
+ * @ack Flag to specify whether acknowledge is requested
+ * @latency Requested wakeup latency (not supported)
+ * @state Requested state (not supported)
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_suspend(enum pm_node_id target,
+ enum pm_request_ack ack,
+ uint32_t latency, uint32_t state)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
+ if (ack == REQ_ACK_BLOCKING) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return pm_ipi_send(primary_proc, payload);
+ }
+}
+
+/**
+ * pm_req_wakeup() - PM call for processor to wake up selected processor
+ * or subsystem
+ * @target Node id of the processor or subsystem to wake up
+ * @ack Flag to specify whether acknowledge requested
+ * @set_address Resume address presence indicator
+ * 1 resume address specified, 0 otherwise
+ * @address Resume address
+ *
+ * This API function is either used to power up another APU core for SMP
+ * (by PSCI) or to power up an entirely different PU or subsystem, such
+ * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
+ * automatically set by PMU.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
+ uint32_t set_address,
+ uintptr_t address,
+ enum pm_request_ack ack)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ uint64_t encoded_address;
+
+
+ /* encode set Address into 1st bit of address */
+ encoded_address = address;
+ encoded_address |= !!set_address;
+
+ /* Send request to the PMU to perform the wake of the PU */
+ PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
+ encoded_address >> 32, ack);
+
+ if (ack == REQ_ACK_BLOCKING) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return pm_ipi_send(primary_proc, payload);
+ }
+}
+
+/**
+ * pm_force_powerdown() - PM call to request for another PU or subsystem to
+ * be powered down forcefully
+ * @target Node id of the targeted PU or subsystem
+ * @ack Flag to specify whether acknowledge is requested
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
+ enum pm_request_ack ack)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
+
+ if (ack == REQ_ACK_BLOCKING) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return pm_ipi_send(primary_proc, payload);
+ }
+}
+
+/**
+ * pm_abort_suspend() - PM call to announce that a prior suspend request
+ * is to be aborted.
+ * @reason Reason for the abort
+ *
+ * Calling PU expects the PMU to abort the initiated suspend procedure.
+ * This is a non-blocking call without any acknowledge.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /*
+ * Do client specific abort suspend operations
+ * (e.g. enable interrupts and clear powerdown request bit)
+ */
+ pm_client_abort_suspend();
+ /* Send request to the PMU */
+ /* TODO: allow passing the node ID of the affected CPU */
+ PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
+ primary_proc->node_id);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
+ * @target Node id of the targeted PU or subsystem
+ * @wkup_node Node id of the wakeup peripheral
+ * @enable Enable or disable the specified peripheral as wake source
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+ enum pm_node_id wkup_node,
+ uint32_t enable)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
+ enable);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_system_shutdown() - PM call to request a system shutdown or restart
+ * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
+ * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
+ /* Setting scope for subsequent PSCI reboot or shutdown */
+ pm_shutdown_scope = subtype;
+ return PM_RET_SUCCESS;
+ }
+
+ PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
+ return pm_ipi_send_non_blocking(primary_proc, payload);
+}
+
+/* APIs for managing PM slaves: */
+
+/**
+ * pm_req_node() - PM call to request a node with specific capabilities
+ * @nid Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos Quality of service (not supported)
+ * @ack Flag to specify whether acknowledge is requested
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+ uint32_t capabilities,
+ uint32_t qos,
+ enum pm_request_ack ack)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
+
+ if (ack == REQ_ACK_BLOCKING) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return pm_ipi_send(primary_proc, payload);
+ }
+}
+
+/**
+ * pm_set_requirement() - PM call to set requirement for PM slaves
+ * @nid Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos Quality of service (not supported)
+ * @ack Flag to specify whether acknowledge is requested
+ *
+ * This API function is to be used for slaves a PU already has requested
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+ uint32_t capabilities,
+ uint32_t qos,
+ enum pm_request_ack ack)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
+ ack);
+
+ if (ack == REQ_ACK_BLOCKING) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return pm_ipi_send(primary_proc, payload);
+ }
+}
+
+/* Miscellaneous API functions */
+
+/**
+ * pm_get_api_version() - Get version number of PMU PM firmware
+ * @version Returns 32-bit version number of PMU Power Management Firmware
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_api_version(uint32_t *version)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
+ return pm_ipi_send_sync(primary_proc, payload, version, 1);
+}
+
+/**
+ * pm_get_node_status() - PM call to request a node's current status
+ * @nid Node id
+ * @ret_buff Buffer for the return values:
+ * [0] - Current power state of the node
+ * [1] - Current requirements for the node (slave nodes only)
+ * [2] - Current usage status for the node (slave nodes only)
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
+ uint32_t *ret_buff)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
+ return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
+}
+
+/**
+ * pm_mmio_write() - Perform write to protected mmio
+ * @address Address to write to
+ * @mask Mask to apply
+ * @value Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_write(uintptr_t address,
+ uint32_t mask,
+ uint32_t value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_mmio_read() - Read value from protected mmio
+ * @address Address to write to
+ * @value Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_fpga_load() - Load the bitstream into the PL.
+ *
+ * This function provides access to the xilfpga library to load
+ * the Bit-stream into PL.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ *
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * size: Number of 32bit words
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_fpga_load(uint32_t address_low,
+ uint32_t address_high,
+ uint32_t size,
+ uint32_t flags)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
+ size, flags);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_fpga_get_status() - Read value from fpga status register
+ * @value Value to read
+ *
+ * This function provides access to the xilfpga library to get
+ * the fpga status
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_fpga_get_status(uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_get_chipid() - Read silicon ID registers
+ * @value Buffer for return values. Must be large enough
+ * to hold 8 bytes.
+ *
+ * @return Returns silicon ID registers
+ */
+enum pm_ret_status pm_get_chipid(uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
+ return pm_ipi_send_sync(primary_proc, payload, value, 2);
+}
+
+/**
+ * pm_secure_rsaaes() - Load the secure images.
+ *
+ * This function provides access to the xilsecure library to load
+ * the authenticated, encrypted, and authenicated/encrypted images.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ *
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * size: Number of 32bit words
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
+ uint32_t address_high,
+ uint32_t size,
+ uint32_t flags)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
+ size, flags);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_aes_engine() - Aes data blob encryption/decryption
+ * This function provides access to the xilsecure library to
+ * encrypt/decrypt data blobs.
+ *
+ * address_low: lower 32-bit address of the AesParams structure
+ *
+ * address_high: higher 32-bit address of the AesParams structure
+ *
+ * value: Returned output value
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_aes_engine(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_get_callbackdata() - Read from IPI response buffer
+ * @data - array of PAYLOAD_ARG_CNT elements
+ *
+ * Read value from ipi buffer response buffer.
+ */
+void pm_get_callbackdata(uint32_t *data, size_t count)
+{
+ /* Return if interrupt is not from PMU */
+ if (!pm_ipi_irq_status(primary_proc)) {
+ return;
+ }
+
+ pm_ipi_buff_read_callb(data, count);
+ pm_ipi_irq_clear(primary_proc);
+}
+
+/**
+ * pm_ioctl() - PM IOCTL API for device control and configs
+ * @node_id Node ID of the device
+ * @ioctl_id ID of the requested IOCTL
+ * @arg1 Argument 1 to requested IOCTL call
+ * @arg2 Argument 2 to requested IOCTL call
+ * @out Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+ uint32_t ioctl_id,
+ uint32_t arg1,
+ uint32_t arg2,
+ uint32_t *value)
+{
+ return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
+}
+
+/**
+ * fw_api_version() - Returns API version implemented in firmware
+ * @api_id API ID to check
+ * @version Returned supported API version
+ * @len Number of words to be returned
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
+ uint32_t len)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
+ return pm_ipi_send_sync(primary_proc, payload, version, len);
+}
+
+/**
+ * check_api_dependency() - API to check dependent EEMI API version
+ * @id EEMI API ID to check
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status check_api_dependency(uint8_t id)
+{
+ uint8_t i;
+ uint32_t version;
+ int ret;
+
+ for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
+ if (api_dep_table[i].id == id) {
+ if (api_dep_table[i].api_id == 0U) {
+ break;
+ }
+
+ ret = fw_api_version(api_dep_table[i].api_id,
+ &version, 1);
+ if (ret != PM_RET_SUCCESS) {
+ return ret;
+ }
+
+ /* Check if fw version matches ATF expected version */
+ if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
+ return PM_RET_ERROR_NOTSUPPORTED;
+ }
+ }
+ }
+
+ return PM_RET_SUCCESS;
+}
+
+/**
+ * feature_check_atf() - These are API's completely implemented in ATF
+ * @api_id API ID to check
+ * @version Returned supported API version
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
+ uint32_t *bit_mask)
+{
+ switch (api_id) {
+ case PM_QUERY_DATA:
+ *version = ATF_API_BASE_VERSION;
+ bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
+ bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
+ return PM_RET_SUCCESS;
+ case PM_GET_CALLBACK_DATA:
+ case PM_GET_TRUSTZONE_VERSION:
+ case PM_SET_SUSPEND_MODE:
+ *version = ATF_API_BASE_VERSION;
+ return PM_RET_SUCCESS;
+ default:
+ return PM_RET_ERROR_NO_FEATURE;
+ }
+}
+
+/**
+ * get_atf_version_for_partial_apis() - Return ATF version for partially
+ * implemented APIs
+ * @api_id API ID to check
+ * @version Returned supported API version
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
+ uint32_t *version)
+{
+ switch (api_id) {
+ case PM_SELF_SUSPEND:
+ case PM_REQ_WAKEUP:
+ case PM_ABORT_SUSPEND:
+ case PM_SET_WAKEUP_SOURCE:
+ case PM_SYSTEM_SHUTDOWN:
+ case PM_GET_API_VERSION:
+ case PM_CLOCK_ENABLE:
+ case PM_CLOCK_DISABLE:
+ case PM_CLOCK_GETSTATE:
+ case PM_CLOCK_SETDIVIDER:
+ case PM_CLOCK_GETDIVIDER:
+ case PM_CLOCK_SETPARENT:
+ case PM_CLOCK_GETPARENT:
+ case PM_PLL_SET_PARAMETER:
+ case PM_PLL_GET_PARAMETER:
+ case PM_PLL_SET_MODE:
+ case PM_PLL_GET_MODE:
+ case PM_REGISTER_ACCESS:
+ *version = ATF_API_BASE_VERSION;
+ return PM_RET_SUCCESS;
+ case PM_FEATURE_CHECK:
+ *version = FW_API_VERSION_2;
+ return PM_RET_SUCCESS;
+ default:
+ return PM_RET_ERROR_ARGS;
+ }
+}
+
+/**
+ * feature_check_partial() - These are API's partially implemented in
+ * ATF and firmware both
+ * @api_id API ID to check
+ * @version Returned supported API version
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status feature_check_partial(uint32_t api_id,
+ uint32_t *version)
+{
+ uint32_t status;
+
+ switch (api_id) {
+ case PM_SELF_SUSPEND:
+ case PM_REQ_WAKEUP:
+ case PM_ABORT_SUSPEND:
+ case PM_SET_WAKEUP_SOURCE:
+ case PM_SYSTEM_SHUTDOWN:
+ case PM_GET_API_VERSION:
+ case PM_CLOCK_ENABLE:
+ case PM_CLOCK_DISABLE:
+ case PM_CLOCK_GETSTATE:
+ case PM_CLOCK_SETDIVIDER:
+ case PM_CLOCK_GETDIVIDER:
+ case PM_CLOCK_SETPARENT:
+ case PM_CLOCK_GETPARENT:
+ case PM_PLL_SET_PARAMETER:
+ case PM_PLL_GET_PARAMETER:
+ case PM_PLL_SET_MODE:
+ case PM_PLL_GET_MODE:
+ case PM_REGISTER_ACCESS:
+ case PM_FEATURE_CHECK:
+ status = check_api_dependency(api_id);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+ return get_atf_version_for_partial_apis(api_id, version);
+ default:
+ return PM_RET_ERROR_NO_FEATURE;
+ }
+}
+
+/**
+ * pm_feature_check() - Returns the supported API version if supported
+ * @api_id API ID to check
+ * @version Returned supported API version
+ * @bit_mask Returned supported IOCTL id version
+ * @len Number of bytes to be returned in bit_mask variable
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
+ uint32_t *bit_mask, uint8_t len)
+{
+ uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t status;
+
+ /* Get API version implemented in ATF */
+ status = feature_check_atf(api_id, version, bit_mask);
+ if (status != PM_RET_ERROR_NO_FEATURE) {
+ return status;
+ }
+
+ /* Get API version implemented by firmware and ATF both */
+ status = feature_check_partial(api_id, version);
+ if (status != PM_RET_ERROR_NO_FEATURE) {
+ return status;
+ }
+
+ /* Get API version implemented by firmware */
+ status = fw_api_version(api_id, ret_payload, 3);
+ /* IOCTL call may return failure whose ID is not implemented in
+ * firmware but implemented in ATF
+ */
+ if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
+ return status;
+ }
+
+ *version = ret_payload[0];
+
+ /* Update IOCTL bit mask which are implemented in ATF */
+ if (api_id == PM_IOCTL) {
+ if (len < 2) {
+ return PM_RET_ERROR_ARGS;
+ }
+ bit_mask[0] = ret_payload[1];
+ bit_mask[1] = ret_payload[2];
+ /* Get IOCTL's implemented by ATF */
+ status = atf_ioctl_bitmask(bit_mask);
+ } else {
+ /* Requires for MISRA */
+ }
+
+ return status;
+}
+
+/**
+ * pm_clock_get_max_divisor - PM call to get max divisor
+ * @clock_id Clock ID
+ * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
+ * @max_div Maximum supported divisor
+ *
+ * This function is used by master to get maximum supported value.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_clock_get_max_divisor(uint32_t clock_id,
+ uint8_t div_type,
+ uint32_t *max_div)
+{
+ return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
+}
+
+/**
+ * pm_clock_get_num_clocks - PM call to request number of clocks
+ * @nclockss: Number of clocks
+ *
+ * This function is used by master to get number of clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
+{
+ return pm_api_clock_get_num_clocks(nclocks);
+}
+
+/**
+ * pm_clock_get_name() - PM call to request a clock's name
+ * @clock_id Clock ID
+ * @name Name of clock (max 16 bytes)
+ *
+ * This function is used by master to get nmae of clock specified
+ * by given clock ID.
+ */
+static void pm_clock_get_name(uint32_t clock_id, char *name)
+{
+ pm_api_clock_get_name(clock_id, name);
+}
+
+/**
+ * pm_clock_get_topology() - PM call to request a clock's topology
+ * @clock_id Clock ID
+ * @index Topology index for next toplogy node
+ * @topology Buffer to store nodes in topology and flags
+ *
+ * This function is used by master to get topology information for the
+ * clock specified by given clock ID. Each response would return 3
+ * topology nodes. To get next nodes, caller needs to call this API with
+ * index of next node. Index starts from 0.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_topology(uint32_t clock_id,
+ uint32_t index,
+ uint32_t *topology)
+{
+ return pm_api_clock_get_topology(clock_id, index, topology);
+}
+
+/**
+ * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
+ * parameters for fixed clock
+ * @clock_id Clock ID
+ * @mul Multiplication value
+ * @div Divisor value
+ *
+ * This function is used by master to get fixed factor parameers for the
+ * fixed clock. This API is application only for the fixed clock.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_fixedfactor_params(uint32_t clock_id,
+ uint32_t *mul,
+ uint32_t *div)
+{
+ return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
+}
+
+/**
+ * pm_clock_get_parents() - PM call to request a clock's first 3 parents
+ * @clock_id Clock ID
+ * @index Index of next parent
+ * @parents Parents of the given clock
+ *
+ * This function is used by master to get clock's parents information.
+ * This API will return 3 parents with a single response. To get other
+ * parents, master should call same API in loop with new parent index
+ * till error is returned.
+ *
+ * E.g First call should have index 0 which will return parents 0, 1 and
+ * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
+ * so on.
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_parents(uint32_t clock_id,
+ uint32_t index,
+ uint32_t *parents)
+{
+ return pm_api_clock_get_parents(clock_id, index, parents);
+}
+
+/**
+ * pm_clock_get_attributes() - PM call to request a clock's attributes
+ * @clock_id Clock ID
+ * @attr Clock attributes
+ *
+ * This function is used by master to get clock's attributes
+ * (e.g. valid, clock type, etc).
+ *
+ * @return Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_attributes(uint32_t clock_id,
+ uint32_t *attr)
+{
+ return pm_api_clock_get_attributes(clock_id, attr);
+}
+
+/**
+ * pm_clock_gate() - Configure clock gate
+ * @clock_id Id of the clock to be configured
+ * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
+ *
+ * @return Error if an argument is not valid or status as returned by the
+ * PM controller (PMU)
+ */
+static enum pm_ret_status pm_clock_gate(uint32_t clock_id,
+ uint8_t enable)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status status;
+ enum pm_api_id api_id;
+
+ /* Check if clock ID is valid and return an error if it is not */
+ status = pm_clock_id_is_valid(clock_id);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ if (enable) {
+ api_id = PM_CLOCK_ENABLE;
+ } else {
+ api_id = PM_CLOCK_DISABLE;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, api_id, clock_id);
+ status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+ /* If action fails due to the lack of permissions filter the error */
+ if (status == PM_RET_ERROR_ACCESS) {
+ status = PM_RET_SUCCESS;
+ }
+
+ return status;
+}
+
+/**
+ * pm_clock_enable() - Enable the clock for given id
+ * @clock_id: Id of the clock to be enabled
+ *
+ * This function is used by master to enable the clock
+ * including peripherals and PLL clocks.
+ *
+ * @return: Error if an argument is not valid or status as returned by the
+ * pm_clock_gate
+ */
+enum pm_ret_status pm_clock_enable(uint32_t clock_id)
+{
+ struct pm_pll *pll;
+
+ /* First try to handle it as a PLL */
+ pll = pm_clock_get_pll(clock_id);
+ if (pll) {
+ return pm_clock_pll_enable(pll);
+ }
+
+ /* It's an on-chip clock, PMU should configure clock's gate */
+ return pm_clock_gate(clock_id, 1);
+}
+
+/**
+ * pm_clock_disable - Disable the clock for given id
+ * @clock_id: Id of the clock to be disable
+ *
+ * This function is used by master to disable the clock
+ * including peripherals and PLL clocks.
+ *
+ * @return: Error if an argument is not valid or status as returned by the
+ * pm_clock_gate
+ */
+enum pm_ret_status pm_clock_disable(uint32_t clock_id)
+{
+ struct pm_pll *pll;
+
+ /* First try to handle it as a PLL */
+ pll = pm_clock_get_pll(clock_id);
+ if (pll) {
+ return pm_clock_pll_disable(pll);
+ }
+
+ /* It's an on-chip clock, PMU should configure clock's gate */
+ return pm_clock_gate(clock_id, 0);
+}
+
+/**
+ * pm_clock_getstate - Get the clock state for given id
+ * @clock_id: Id of the clock to be queried
+ * @state: 1/0 (Enabled/Disabled)
+ *
+ * This function is used by master to get the state of clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
+ uint32_t *state)
+{
+ struct pm_pll *pll;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status status;
+
+ /* First try to handle it as a PLL */
+ pll = pm_clock_get_pll(clock_id);
+ if (pll)
+ return pm_clock_pll_get_state(pll, state);
+
+ /* Check if clock ID is a valid on-chip clock */
+ status = pm_clock_id_is_valid(clock_id);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
+ return pm_ipi_send_sync(primary_proc, payload, state, 1);
+}
+
+/**
+ * pm_clock_setdivider - Set the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to set divider for any clock
+ * to achieve desired rate.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
+ uint32_t divider)
+{
+ enum pm_ret_status status;
+ enum pm_node_id nid;
+ enum pm_clock_div_id div_id;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ const uint32_t div0 = 0xFFFF0000;
+ const uint32_t div1 = 0x0000FFFF;
+ uint32_t val;
+
+ /* Get PLL node ID using PLL clock ID */
+ status = pm_clock_get_pll_node_id(clock_id, &nid);
+ if (status == PM_RET_SUCCESS) {
+ return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+ }
+
+ /* Check if clock ID is a valid on-chip clock */
+ status = pm_clock_id_is_valid(clock_id);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ if (div0 == (divider & div0)) {
+ div_id = PM_CLOCK_DIV0_ID;
+ val = divider & ~div0;
+ } else if (div1 == (divider & div1)) {
+ div_id = PM_CLOCK_DIV1_ID;
+ val = (divider & ~div1) >> 16;
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_clock_getdivider - Get the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to get divider values
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
+ uint32_t *divider)
+{
+ enum pm_ret_status status;
+ enum pm_node_id nid;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ uint32_t val;
+
+ /* Get PLL node ID using PLL clock ID */
+ status = pm_clock_get_pll_node_id(clock_id, &nid);
+ if (status == PM_RET_SUCCESS) {
+ return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+ }
+
+ /* Check if clock ID is a valid on-chip clock */
+ status = pm_clock_id_is_valid(clock_id);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
+ /* Send request to the PMU to get div0 */
+ PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
+ PM_CLOCK_DIV0_ID);
+ status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+ *divider = val;
+ }
+
+ if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
+ /* Send request to the PMU to get div1 */
+ PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
+ PM_CLOCK_DIV1_ID);
+ status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+ *divider |= val << 16;
+ }
+
+ return status;
+}
+
+/**
+ * pm_clock_setrate - Set the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to set rate for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
+ uint64_t rate)
+{
+ return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_clock_getrate - Get the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to get rate
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
+ uint64_t *rate)
+{
+ return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_clock_setparent - Set the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_index: Index of the parent clock into clock's parents array
+ *
+ * This function is used by master to set parent for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
+ uint32_t parent_index)
+{
+ struct pm_pll *pll;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status status;
+
+ /* First try to handle it as a PLL */
+ pll = pm_clock_get_pll_by_related_clk(clock_id);
+ if (pll) {
+ return pm_clock_pll_set_parent(pll, clock_id, parent_index);
+ }
+
+ /* Check if clock ID is a valid on-chip clock */
+ status = pm_clock_id_is_valid(clock_id);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_clock_getparent - Get the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_index: parent index
+ *
+ * This function is used by master to get parent index
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
+ uint32_t *parent_index)
+{
+ struct pm_pll *pll;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status status;
+
+ /* First try to handle it as a PLL */
+ pll = pm_clock_get_pll_by_related_clk(clock_id);
+ if (pll) {
+ return pm_clock_pll_get_parent(pll, clock_id, parent_index);
+ }
+
+ /* Check if clock ID is a valid on-chip clock */
+ status = pm_clock_id_is_valid(clock_id);
+ if (status != PM_RET_SUCCESS) {
+ return status;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
+ return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
+}
+
+/**
+ * pm_pinctrl_get_num_pins - PM call to request number of pins
+ * @npins: Number of pins
+ *
+ * This function is used by master to get number of pins
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
+{
+ return pm_api_pinctrl_get_num_pins(npins);
+}
+
+/**
+ * pm_pinctrl_get_num_functions - PM call to request number of functions
+ * @nfuncs: Number of functions
+ *
+ * This function is used by master to get number of functions
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
+{
+ return pm_api_pinctrl_get_num_functions(nfuncs);
+}
+
+/**
+ * pm_pinctrl_get_num_function_groups - PM call to request number of
+ * function groups
+ * @fid: Id of function
+ * @ngroups: Number of function groups
+ *
+ * This function is used by master to get number of function groups specified
+ * by given function Id
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_function_groups(uint32_t fid,
+ uint32_t *ngroups)
+{
+ return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
+}
+
+/**
+ * pm_pinctrl_get_function_name - PM call to request function name
+ * @fid: Id of function
+ * @name: Name of function
+ *
+ * This function is used by master to get name of function specified
+ * by given function Id
+ */
+static void pm_pinctrl_get_function_name(uint32_t fid, char *name)
+{
+ pm_api_pinctrl_get_function_name(fid, name);
+}
+
+/**
+ * pm_pinctrl_get_function_groups - PM call to request function groups
+ * @fid: Id of function
+ * @index: Index of next function groups
+ * @groups: Function groups
+ *
+ * This function is used by master to get function groups specified
+ * by given function Id. This API will return 6 function groups with
+ * a single response. To get other function groups, master should call
+ * same API in loop with new function groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return function groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * function groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_function_groups(uint32_t fid,
+ uint32_t index,
+ uint16_t *groups)
+{
+ return pm_api_pinctrl_get_function_groups(fid, index, groups);
+}
+
+/**
+ * pm_pinctrl_get_pin_groups - PM call to request pin groups
+ * @pin_id: Id of pin
+ * @index: Index of next pin groups
+ * @groups: pin groups
+ *
+ * This function is used by master to get pin groups specified
+ * by given pin Id. This API will return 6 pin groups with
+ * a single response. To get other pin groups, master should call
+ * same API in loop with new pin groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return pin groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * pin groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_pin_groups(uint32_t pin_id,
+ uint32_t index,
+ uint16_t *groups)
+{
+ return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
+}
+
+/**
+ * pm_query_data() - PM API for querying firmware data
+ * @arg1 Argument 1 to requested IOCTL call
+ * @arg2 Argument 2 to requested IOCTL call
+ * @arg3 Argument 3 to requested IOCTL call
+ * @arg4 Argument 4 to requested IOCTL call
+ * @data Returned output data
+ *
+ * This function returns requested data.
+ */
+void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
+ uint32_t arg3, uint32_t *data)
+{
+ switch (qid) {
+ case PM_QID_CLOCK_GET_NAME:
+ pm_clock_get_name(arg1, (char *)data);
+ break;
+ case PM_QID_CLOCK_GET_TOPOLOGY:
+ data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
+ break;
+ case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
+ data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
+ &data[2]);
+ break;
+ case PM_QID_CLOCK_GET_PARENTS:
+ data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
+ break;
+ case PM_QID_CLOCK_GET_ATTRIBUTES:
+ data[0] = pm_clock_get_attributes(arg1, &data[1]);
+ break;
+ case PM_QID_PINCTRL_GET_NUM_PINS:
+ data[0] = pm_pinctrl_get_num_pins(&data[1]);
+ break;
+ case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
+ data[0] = pm_pinctrl_get_num_functions(&data[1]);
+ break;
+ case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
+ data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
+ break;
+ case PM_QID_PINCTRL_GET_FUNCTION_NAME:
+ pm_pinctrl_get_function_name(arg1, (char *)data);
+ break;
+ case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
+ data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
+ break;
+ case PM_QID_PINCTRL_GET_PIN_GROUPS:
+ data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
+ (uint16_t *)&data[1]);
+ break;
+ case PM_QID_CLOCK_GET_NUM_CLOCKS:
+ data[0] = pm_clock_get_num_clocks(&data[1]);
+ break;
+
+ case PM_QID_CLOCK_GET_MAX_DIVISOR:
+ data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
+ break;
+ default:
+ data[0] = PM_RET_ERROR_ARGS;
+ WARN("Unimplemented query service call: 0x%x\n", qid);
+ break;
+ }
+}
+
+enum pm_ret_status pm_sha_hash(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t size,
+ uint32_t flags)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
+ size, flags);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+enum pm_ret_status pm_rsa_core(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t size,
+ uint32_t flags)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
+ size, flags);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+enum pm_ret_status pm_secure_image(uint32_t address_low,
+ uint32_t address_high,
+ uint32_t key_lo,
+ uint32_t key_hi,
+ uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
+ key_hi, key_lo);
+ return pm_ipi_send_sync(primary_proc, payload, value, 2);
+}
+
+/**
+ * pm_fpga_read - Perform the fpga configuration readback
+ *
+ * @reg_numframes: Configuration register offset (or) Number of frames to read
+ * @address_low: lower 32-bit Linear memory space address
+ * @address_high: higher 32-bit Linear memory space address
+ * @readback_type: Type of fpga readback operation
+ * 0 -- Configuration Register readback
+ * 1 -- Configuration Data readback
+ * @value: Value to read
+ *
+ * This function provides access to the xilfpga library to read
+ * the PL configuration.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
+ uint32_t address_low,
+ uint32_t address_high,
+ uint32_t readback_type,
+ uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
+ address_high, readback_type);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/*
+ * pm_pll_set_parameter() - Set the PLL parameter value
+ * @nid Node id of the target PLL
+ * @param_id ID of the PLL parameter
+ * @value Parameter value to be set
+ *
+ * Setting the parameter will have physical effect once the PLL mode is set to
+ * integer or fractional.
+ *
+ * @return Error if an argument is not valid or status as returned by the
+ * PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
+ enum pm_pll_param param_id,
+ uint32_t value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Check if given node ID is a PLL node */
+ if (nid < NODE_APLL || nid > NODE_IOPLL) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Check if parameter ID is valid and return an error if it's not */
+ if (param_id >= PM_PLL_PARAM_MAX) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_parameter() - Get the PLL parameter value
+ * @nid Node id of the target PLL
+ * @param_id ID of the PLL parameter
+ * @value Location to store the parameter value
+ *
+ * @return Error if an argument is not valid or status as returned by the
+ * PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
+ enum pm_pll_param param_id,
+ uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Check if given node ID is a PLL node */
+ if (nid < NODE_APLL || nid > NODE_IOPLL) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Check if parameter ID is valid and return an error if it's not */
+ if (param_id >= PM_PLL_PARAM_MAX) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_pll_set_mode() - Set the PLL mode
+ * @nid Node id of the target PLL
+ * @mode PLL mode to be set
+ *
+ * If reset mode is set the PM controller will first bypass the PLL and then
+ * assert the reset. If integer or fractional mode is set the PM controller will
+ * ensure that the complete PLL programming sequence is satisfied. After this
+ * function returns success the PLL is locked and its bypass is deasserted.
+ *
+ * @return Error if an argument is not valid or status as returned by the
+ * PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Check if given node ID is a PLL node */
+ if (nid < NODE_APLL || nid > NODE_IOPLL) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Check if PLL mode is valid */
+ if (mode >= PM_PLL_MODE_MAX) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_mode() - Get the PLL mode
+ * @nid Node id of the target PLL
+ * @mode Location to store the mode of the PLL
+ *
+ * @return Error if an argument is not valid or status as returned by the
+ * PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Check if given node ID is a PLL node */
+ if (nid < NODE_APLL || nid > NODE_IOPLL) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
+ return pm_ipi_send_sync(primary_proc, payload, mode, 1);
+}
+
+/**
+ * pm_register_access() - PM API for register read/write access data
+ *
+ * @register_access_id Register_access_id which says register read/write
+ *
+ * @address Address of the register to be accessed
+ *
+ * @mask Mask value to be used while writing value
+ *
+ * @value Value to be written to register
+ *
+ * @out Returned output data
+ *
+ * This function returns requested data.
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_access(uint32_t register_access_id,
+ uint32_t address,
+ uint32_t mask,
+ uint32_t value,
+ uint32_t *out)
+{
+ enum pm_ret_status ret;
+
+ if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
+ ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
+ ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
+ ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) {
+ return PM_RET_ERROR_ACCESS;
+ }
+
+ switch (register_access_id) {
+ case CONFIG_REG_WRITE:
+ ret = pm_mmio_write(address, mask, value);
+ break;
+ case CONFIG_REG_READ:
+ ret = pm_mmio_read(address, out);
+ break;
+ default:
+ ret = PM_RET_ERROR_ARGS;
+ WARN("Unimplemented register_access call\n\r");
+ break;
+ }
+ return ret;
+}
+
+/**
+ * pm_efuse_access() - To program or read efuse bits.
+ *
+ * This function provides access to the xilskey library to program/read
+ * efuse bits.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * value: Returned output value
+ *
+ * @return Returns status, either success or error+reason
+ *
+ */
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
+
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_set_action(uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_remove_action(uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+enum pm_ret_status em_send_errors(uint32_t *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
+ return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
new file mode 100644
index 0000000..9ba9475
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_API_SYS_H
+#define PM_API_SYS_H
+
+#include <stdint.h>
+
+#include "pm_defs.h"
+
+enum pm_query_id {
+ PM_QID_INVALID,
+ PM_QID_CLOCK_GET_NAME,
+ PM_QID_CLOCK_GET_TOPOLOGY,
+ PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
+ PM_QID_CLOCK_GET_PARENTS,
+ PM_QID_CLOCK_GET_ATTRIBUTES,
+ PM_QID_PINCTRL_GET_NUM_PINS,
+ PM_QID_PINCTRL_GET_NUM_FUNCTIONS,
+ PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+ PM_QID_PINCTRL_GET_FUNCTION_NAME,
+ PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+ PM_QID_PINCTRL_GET_PIN_GROUPS,
+ PM_QID_CLOCK_GET_NUM_CLOCKS,
+ PM_QID_CLOCK_GET_MAX_DIVISOR,
+};
+
+enum pm_register_access_id {
+ CONFIG_REG_WRITE,
+ CONFIG_REG_READ,
+};
+
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, arg0) { \
+ pl[0] = (uint32_t)(arg0); \
+}
+
+#define PM_PACK_PAYLOAD2(pl, arg0, arg1) { \
+ pl[1] = (uint32_t)(arg1); \
+ PM_PACK_PAYLOAD1(pl, arg0); \
+}
+
+#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) { \
+ pl[2] = (uint32_t)(arg2); \
+ PM_PACK_PAYLOAD2(pl, arg0, arg1); \
+}
+
+#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) { \
+ pl[3] = (uint32_t)(arg3); \
+ PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2); \
+}
+
+#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) { \
+ pl[4] = (uint32_t)(arg4); \
+ PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3); \
+}
+
+#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) { \
+ pl[5] = (uint32_t)(arg5); \
+ PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \
+}
+
+/**********************************************************
+ * System-level API function declarations
+ **********************************************************/
+enum pm_ret_status pm_req_suspend(enum pm_node_id target,
+ enum pm_request_ack ack,
+ uint32_t latency,
+ uint32_t state);
+
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+ uint32_t latency,
+ uint32_t state,
+ uintptr_t address);
+
+enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
+ enum pm_request_ack ack);
+
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason);
+
+enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
+ uint32_t set_address,
+ uintptr_t address,
+ enum pm_request_ack ack);
+
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+ enum pm_node_id wkup_node,
+ uint32_t enable);
+
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype);
+
+/* API functions for managing PM Slaves */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+ uint32_t capabilities,
+ uint32_t qos,
+ enum pm_request_ack ack);
+
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+ uint32_t capabilities,
+ uint32_t qos,
+ enum pm_request_ack ack);
+
+/* Miscellaneous API functions */
+enum pm_ret_status pm_get_api_version(uint32_t *version);
+enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
+ uint32_t *ret_buff);
+
+/* Direct-Control API functions */
+enum pm_ret_status pm_mmio_write(uintptr_t address,
+ uint32_t mask,
+ uint32_t value);
+enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value);
+enum pm_ret_status pm_fpga_load(uint32_t address_low,
+ uint32_t address_high,
+ uint32_t size,
+ uint32_t flags);
+enum pm_ret_status pm_fpga_get_status(uint32_t *value);
+
+enum pm_ret_status pm_get_chipid(uint32_t *value);
+enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
+ uint32_t address_high,
+ uint32_t size,
+ uint32_t flags);
+uint32_t pm_get_shutdown_scope(void);
+void pm_get_callbackdata(uint32_t *data, size_t count);
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+ uint32_t ioctl_id,
+ uint32_t arg1,
+ uint32_t arg2,
+ uint32_t *value);
+enum pm_ret_status pm_clock_enable(uint32_t clock_id);
+enum pm_ret_status pm_clock_disable(uint32_t clock_id);
+enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
+ uint32_t *state);
+enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
+ uint32_t divider);
+enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
+ uint32_t *divider);
+enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
+ uint64_t rate);
+enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
+ uint64_t *rate);
+enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
+ uint32_t parent_index);
+enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
+ uint32_t *parent_index);
+void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
+ uint32_t arg3, uint32_t *data);
+enum pm_ret_status pm_sha_hash(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t size,
+ uint32_t flags);
+enum pm_ret_status pm_rsa_core(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t size,
+ uint32_t flags);
+enum pm_ret_status pm_secure_image(uint32_t address_low,
+ uint32_t address_high,
+ uint32_t key_lo,
+ uint32_t key_hi,
+ uint32_t *value);
+enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
+ uint32_t address_low,
+ uint32_t address_high,
+ uint32_t readback_type,
+ uint32_t *value);
+enum pm_ret_status pm_aes_engine(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t *value);
+enum pm_ret_status pm_register_access(uint32_t register_access_id,
+ uint32_t address,
+ uint32_t mask,
+ uint32_t value,
+ uint32_t *out);
+enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
+ enum pm_pll_param param_id,
+ uint32_t value);
+enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
+ enum pm_pll_param param_id,
+ uint32_t *value);
+enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
+enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+ uint32_t address_low, uint32_t *value);
+enum pm_ret_status em_set_action(uint32_t *value);
+enum pm_ret_status em_remove_action(uint32_t *value);
+enum pm_ret_status em_send_errors(uint32_t *value);
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
+ uint32_t *bit_mask, uint8_t len);
+enum pm_ret_status check_api_dependency(uint8_t id);
+
+#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c
new file mode 100644
index 0000000..7217fa1
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * APU specific definition of processors in the subsystem as well as functions
+ * for getting information about and changing state of the APU.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/bl_common.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+
+#include <plat_ipi.h>
+#include <zynqmp_def.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_ipi.h"
+
+#define IRQ_MAX 84U
+#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5U) + 1U)
+#define UNDEFINED_CPUID (~0U)
+
+#define PM_SUSPEND_MODE_STD 0U
+#define PM_SUSPEND_MODE_POWER_OFF 1U
+
+DEFINE_BAKERY_LOCK(pm_client_secure_lock);
+
+extern const struct pm_ipi apu_ipi;
+
+const struct pm_ipi apu_ipi = {
+ .local_ipi_id = IPI_ID_APU,
+ .remote_ipi_id = IPI_ID_PMU0,
+ .buffer_base = IPI_BUFFER_APU_BASE,
+};
+
+static uint32_t suspend_mode = PM_SUSPEND_MODE_STD;
+
+/* Order in pm_procs_all array must match cpu ids */
+static const struct pm_proc pm_procs_all[] = {
+ {
+ .node_id = NODE_APU_0,
+ .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = NODE_APU_1,
+ .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = NODE_APU_2,
+ .pwrdn_mask = APU_2_PWRCTL_CPUPWRDWNREQ_MASK,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = NODE_APU_3,
+ .pwrdn_mask = APU_3_PWRCTL_CPUPWRDWNREQ_MASK,
+ .ipi = &apu_ipi,
+ },
+};
+
+/* Interrupt to PM node ID map */
+static enum pm_node_id irq_node_map[IRQ_MAX + 1U] = {
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 3 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 7 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 11 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_NAND,
+ NODE_QSPI, /* 15 */
+ NODE_GPIO,
+ NODE_I2C_0,
+ NODE_I2C_1,
+ NODE_SPI_0, /* 19 */
+ NODE_SPI_1,
+ NODE_UART_0,
+ NODE_UART_1,
+ NODE_CAN_0, /* 23 */
+ NODE_CAN_1,
+ NODE_UNKNOWN,
+ NODE_RTC,
+ NODE_RTC, /* 27 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 31 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 35, NODE_IPI_APU */
+ NODE_TTC_0,
+ NODE_TTC_0,
+ NODE_TTC_0,
+ NODE_TTC_1, /* 39 */
+ NODE_TTC_1,
+ NODE_TTC_1,
+ NODE_TTC_2,
+ NODE_TTC_2, /* 43 */
+ NODE_TTC_2,
+ NODE_TTC_3,
+ NODE_TTC_3,
+ NODE_TTC_3, /* 47 */
+ NODE_SD_0,
+ NODE_SD_1,
+ NODE_SD_0,
+ NODE_SD_1, /* 51 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 55 */
+ NODE_UNKNOWN,
+ NODE_ETH_0,
+ NODE_ETH_0,
+ NODE_ETH_1, /* 59 */
+ NODE_ETH_1,
+ NODE_ETH_2,
+ NODE_ETH_2,
+ NODE_ETH_3, /* 63 */
+ NODE_ETH_3,
+ NODE_USB_0,
+ NODE_USB_0,
+ NODE_USB_0, /* 67 */
+ NODE_USB_0,
+ NODE_USB_0,
+ NODE_USB_1,
+ NODE_USB_1, /* 71 */
+ NODE_USB_1,
+ NODE_USB_1,
+ NODE_USB_1,
+ NODE_USB_0, /* 75 */
+ NODE_USB_0,
+ NODE_ADMA,
+ NODE_ADMA,
+ NODE_ADMA, /* 79 */
+ NODE_ADMA,
+ NODE_ADMA,
+ NODE_ADMA,
+ NODE_ADMA, /* 83 */
+ NODE_ADMA,
+};
+
+/**
+ * irq_to_pm_node - Get PM node ID corresponding to the interrupt number
+ * @irq: Interrupt number
+ *
+ * Return: PM node ID corresponding to the specified interrupt
+ */
+static enum pm_node_id irq_to_pm_node(uint32_t irq)
+{
+ assert(irq <= IRQ_MAX);
+ return irq_node_map[irq];
+}
+
+/**
+ * pm_client_set_wakeup_sources - Set all slaves with enabled interrupts as wake
+ * sources in the PMU firmware
+ */
+static void pm_client_set_wakeup_sources(void)
+{
+ uint32_t reg_num;
+ uint8_t pm_wakeup_nodes_set[NODE_MAX] = { 0 };
+ uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4U;
+
+ /* In case of power-off suspend, only NODE_EXTERN must be set */
+ if (suspend_mode == PM_SUSPEND_MODE_POWER_OFF) {
+ enum pm_ret_status ret;
+
+ ret = pm_set_wakeup_source(NODE_APU, NODE_EXTERN, 1U);
+ /**
+ * If NODE_EXTERN could not be set as wake source, proceed with
+ * standard suspend (no one will wake the system otherwise)
+ */
+ if (ret == PM_RET_SUCCESS) {
+ return;
+ }
+ }
+
+ zeromem(&pm_wakeup_nodes_set, sizeof(pm_wakeup_nodes_set));
+
+ for (reg_num = 0U; reg_num < NUM_GICD_ISENABLER; reg_num++) {
+ uint32_t base_irq = reg_num << ISENABLER_SHIFT;
+ uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2U));
+
+ if (reg == 0) {
+ continue;
+ }
+
+ while (reg) {
+ enum pm_node_id node;
+ uint32_t idx, ret, irq, lowest_set = reg & (-reg);
+
+ idx = __builtin_ctz(lowest_set);
+ irq = base_irq + idx;
+
+ if (irq > IRQ_MAX) {
+ break;
+ }
+
+ node = irq_to_pm_node(irq);
+ reg &= ~lowest_set;
+
+ if (node > NODE_UNKNOWN && node < NODE_MAX) {
+ if (pm_wakeup_nodes_set[node] == 0U) {
+ ret = pm_set_wakeup_source(NODE_APU, node, 1U);
+ pm_wakeup_nodes_set[node] = (ret == PM_RET_SUCCESS) ? 1U : 0U;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * pm_get_proc() - returns pointer to the proc structure
+ * @cpuid: id of the cpu whose proc struct pointer should be returned
+ *
+ * Return: pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc(uint32_t cpuid)
+{
+ if (cpuid < ARRAY_SIZE(pm_procs_all)) {
+ return &pm_procs_all[cpuid];
+ }
+
+ return NULL;
+}
+
+/**
+ * pm_get_proc_by_node() - returns pointer to the proc structure
+ * @nid: node id of the processor
+ *
+ * Return: pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+ if (nid == pm_procs_all[i].node_id) {
+ return &pm_procs_all[i];
+ }
+ }
+ return NULL;
+}
+
+/**
+ * pm_get_cpuid() - get the local cpu ID for a global node ID
+ * @nid: node id of the processor
+ *
+ * Return: the cpu ID (starting from 0) for the subsystem
+ */
+static uint32_t pm_get_cpuid(enum pm_node_id nid)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+ if (pm_procs_all[i].node_id == nid) {
+ return i;
+ }
+ }
+ return UNDEFINED_CPUID;
+}
+
+const struct pm_proc *primary_proc = &pm_procs_all[0];
+
+/**
+ * pm_client_suspend() - Client-specific suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required prior to sending suspend request to PMU
+ * Actions taken depend on the state system is suspending to.
+ */
+void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
+{
+ bakery_lock_get(&pm_client_secure_lock);
+
+ if (state == PM_STATE_SUSPEND_TO_RAM) {
+ pm_client_set_wakeup_sources();
+ }
+
+ /* Set powerdown request */
+ mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+
+/**
+ * pm_client_abort_suspend() - Client-specific abort-suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required for aborting a prior suspend request
+ */
+void pm_client_abort_suspend(void)
+{
+ /* Enable interrupts at processor level (for current cpu) */
+ gicv2_cpuif_enable();
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* Clear powerdown request */
+ mmio_write_32(APU_PWRCTL,
+ mmio_read_32(APU_PWRCTL) & ~primary_proc->pwrdn_mask);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+/**
+ * pm_client_wakeup() - Client-specific wakeup actions
+ *
+ * This function should contain any PU-specific actions
+ * required for waking up another APU core
+ */
+void pm_client_wakeup(const struct pm_proc *proc)
+{
+ uint32_t cpuid = pm_get_cpuid(proc->node_id);
+
+ if (cpuid == UNDEFINED_CPUID) {
+ return;
+ }
+
+ bakery_lock_get(&pm_client_secure_lock);
+
+ /* clear powerdown bit for affected cpu */
+ uint32_t val = mmio_read_32(APU_PWRCTL);
+ val &= ~(proc->pwrdn_mask);
+ mmio_write_32(APU_PWRCTL, val);
+
+ bakery_lock_release(&pm_client_secure_lock);
+}
+
+enum pm_ret_status pm_set_suspend_mode(uint32_t mode)
+{
+ if ((mode != PM_SUSPEND_MODE_STD) &&
+ (mode != PM_SUSPEND_MODE_POWER_OFF)) {
+ return PM_RET_ERROR_ARGS;
+ }
+
+ suspend_mode = mode;
+ return PM_RET_SUCCESS;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
new file mode 100644
index 0000000..e335b94
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* ZynqMP power management enums and defines */
+
+#ifndef PM_DEFS_H
+#define PM_DEFS_H
+
+/*********************************************************************
+ * Macro definitions
+ ********************************************************************/
+
+/*
+ * Version number is a 32bit value, like:
+ * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
+ */
+#define PM_VERSION_MAJOR 1U
+#define PM_VERSION_MINOR 1U
+
+#define PM_VERSION ((PM_VERSION_MAJOR << 16U) | PM_VERSION_MINOR)
+
+/**
+ * PM API versions
+ */
+/* Expected version of firmware APIs */
+#define FW_API_BASE_VERSION (1U)
+/* Expected version of firmware API for feature check */
+#define FW_API_VERSION_2 (2U)
+/* Version of APIs implemented in ATF */
+#define ATF_API_BASE_VERSION (1U)
+
+/* Capabilities for RAM */
+#define PM_CAP_ACCESS 0x1U
+#define PM_CAP_CONTEXT 0x2U
+
+#define MAX_LATENCY (~0U)
+#define MAX_QOS 100U
+
+/* State arguments of the self suspend */
+#define PM_STATE_CPU_IDLE 0x0U
+#define PM_STATE_SUSPEND_TO_RAM 0xFU
+
+/* APU processor states */
+#define PM_PROC_STATE_FORCEDOFF 0U
+#define PM_PROC_STATE_ACTIVE 1U
+#define PM_PROC_STATE_SLEEP 2U
+#define PM_PROC_STATE_SUSPENDING 3U
+
+#define EM_FUNID_NUM_MASK 0xF0000U
+
+#define PM_GET_CALLBACK_DATA 0xa01
+#define PM_SET_SUSPEND_MODE 0xa02
+#define PM_GET_TRUSTZONE_VERSION 0xa03
+
+/*********************************************************************
+ * Enum definitions
+ ********************************************************************/
+
+enum pm_api_id {
+ /* Miscellaneous API functions: */
+ PM_GET_API_VERSION = 1, /* Do not change or move */
+ PM_SET_CONFIGURATION,
+ PM_GET_NODE_STATUS,
+ PM_GET_OP_CHARACTERISTIC,
+ PM_REGISTER_NOTIFIER,
+ /* API for suspending of PUs: */
+ PM_REQ_SUSPEND,
+ PM_SELF_SUSPEND,
+ PM_FORCE_POWERDOWN,
+ PM_ABORT_SUSPEND,
+ PM_REQ_WAKEUP,
+ PM_SET_WAKEUP_SOURCE,
+ PM_SYSTEM_SHUTDOWN,
+ /* API for managing PM slaves: */
+ PM_REQ_NODE,
+ PM_RELEASE_NODE,
+ PM_SET_REQUIREMENT,
+ PM_SET_MAX_LATENCY,
+ /* Direct control API functions: */
+ PM_RESET_ASSERT,
+ PM_RESET_GET_STATUS,
+ PM_MMIO_WRITE,
+ PM_MMIO_READ,
+ PM_INIT_FINALIZE,
+ PM_FPGA_LOAD,
+ PM_FPGA_GET_STATUS,
+ PM_GET_CHIPID,
+ PM_SECURE_RSA_AES,
+ PM_SECURE_SHA,
+ PM_SECURE_RSA,
+ PM_PINCTRL_REQUEST,
+ PM_PINCTRL_RELEASE,
+ PM_PINCTRL_GET_FUNCTION,
+ PM_PINCTRL_SET_FUNCTION,
+ PM_PINCTRL_CONFIG_PARAM_GET,
+ PM_PINCTRL_CONFIG_PARAM_SET,
+ PM_IOCTL,
+ /* API to query information from firmware */
+ PM_QUERY_DATA,
+ /* Clock control API functions */
+ PM_CLOCK_ENABLE,
+ PM_CLOCK_DISABLE,
+ PM_CLOCK_GETSTATE,
+ PM_CLOCK_SETDIVIDER,
+ PM_CLOCK_GETDIVIDER,
+ PM_CLOCK_SETRATE,
+ PM_CLOCK_GETRATE,
+ PM_CLOCK_SETPARENT,
+ PM_CLOCK_GETPARENT,
+ PM_SECURE_IMAGE,
+ /* FPGA PL Readback */
+ PM_FPGA_READ,
+ PM_SECURE_AES,
+ /* PLL control API functions */
+ PM_PLL_SET_PARAMETER,
+ PM_PLL_GET_PARAMETER,
+ PM_PLL_SET_MODE,
+ PM_PLL_GET_MODE,
+ /* PM Register Access API */
+ PM_REGISTER_ACCESS,
+ PM_EFUSE_ACCESS,
+ PM_FPGA_GET_VERSION,
+ PM_FPGA_GET_FEATURE_LIST,
+ PM_FEATURE_CHECK = 63,
+ PM_API_MAX
+};
+
+enum pm_node_id {
+ NODE_UNKNOWN = 0,
+ NODE_APU,
+ NODE_APU_0,
+ NODE_APU_1,
+ NODE_APU_2,
+ NODE_APU_3,
+ NODE_RPU,
+ NODE_RPU_0,
+ NODE_RPU_1,
+ NODE_PLD,
+ NODE_FPD,
+ NODE_OCM_BANK_0,
+ NODE_OCM_BANK_1,
+ NODE_OCM_BANK_2,
+ NODE_OCM_BANK_3,
+ NODE_TCM_0_A,
+ NODE_TCM_0_B,
+ NODE_TCM_1_A,
+ NODE_TCM_1_B,
+ NODE_L2,
+ NODE_GPU_PP_0,
+ NODE_GPU_PP_1,
+ NODE_USB_0,
+ NODE_USB_1,
+ NODE_TTC_0,
+ NODE_TTC_1,
+ NODE_TTC_2,
+ NODE_TTC_3,
+ NODE_SATA,
+ NODE_ETH_0,
+ NODE_ETH_1,
+ NODE_ETH_2,
+ NODE_ETH_3,
+ NODE_UART_0,
+ NODE_UART_1,
+ NODE_SPI_0,
+ NODE_SPI_1,
+ NODE_I2C_0,
+ NODE_I2C_1,
+ NODE_SD_0,
+ NODE_SD_1,
+ NODE_DP,
+ NODE_GDMA,
+ NODE_ADMA,
+ NODE_NAND,
+ NODE_QSPI,
+ NODE_GPIO,
+ NODE_CAN_0,
+ NODE_CAN_1,
+ NODE_EXTERN,
+ NODE_APLL,
+ NODE_VPLL,
+ NODE_DPLL,
+ NODE_RPLL,
+ NODE_IOPLL,
+ NODE_DDR,
+ NODE_IPI_APU,
+ NODE_IPI_RPU_0,
+ NODE_GPU,
+ NODE_PCIE,
+ NODE_PCAP,
+ NODE_RTC,
+ NODE_LPD,
+ NODE_VCU,
+ NODE_IPI_RPU_1,
+ NODE_IPI_PL_0,
+ NODE_IPI_PL_1,
+ NODE_IPI_PL_2,
+ NODE_IPI_PL_3,
+ NODE_PL,
+ NODE_GEM_TSU,
+ NODE_SWDT_0,
+ NODE_SWDT_1,
+ NODE_CSU,
+ NODE_PJTAG,
+ NODE_TRACE,
+ NODE_TESTSCAN,
+ NODE_PMU,
+ NODE_MAX,
+};
+
+enum pm_request_ack {
+ REQ_ACK_NO = 1,
+ REQ_ACK_BLOCKING,
+ REQ_ACK_NON_BLOCKING,
+};
+
+enum pm_abort_reason {
+ ABORT_REASON_WKUP_EVENT = 100,
+ ABORT_REASON_PU_BUSY,
+ ABORT_REASON_NO_PWRDN,
+ ABORT_REASON_UNKNOWN,
+};
+
+enum pm_suspend_reason {
+ SUSPEND_REASON_PU_REQ = 201,
+ SUSPEND_REASON_ALERT,
+ SUSPEND_REASON_SYS_SHUTDOWN,
+};
+
+enum pm_ram_state {
+ PM_RAM_STATE_OFF = 1,
+ PM_RAM_STATE_RETENTION,
+ PM_RAM_STATE_ON,
+};
+
+enum pm_opchar_type {
+ PM_OPCHAR_TYPE_POWER = 1,
+ PM_OPCHAR_TYPE_TEMP,
+ PM_OPCHAR_TYPE_LATENCY,
+};
+
+/**
+ * @PM_RET_SUCCESS: success
+ * @PM_RET_ERROR_ARGS: illegal arguments provided (deprecated)
+ * @PM_RET_ERROR_NOTSUPPORTED: feature not supported (deprecated)
+ * @PM_RET_ERROR_NOT_ENABLED: feature is not enabled
+ * @PM_RET_ERROR_INTERNAL: internal error
+ * @PM_RET_ERROR_CONFLICT: conflict
+ * @PM_RET_ERROR_ACCESS: access rights violation
+ * @PM_RET_ERROR_INVALID_NODE: invalid node
+ * @PM_RET_ERROR_DOUBLE_REQ: duplicate request for same node
+ * @PM_RET_ERROR_ABORT_SUSPEND: suspend procedure has been aborted
+ * @PM_RET_ERROR_TIMEOUT: timeout in communication with PMU
+ * @PM_RET_ERROR_NODE_USED: node is already in use
+ */
+enum pm_ret_status {
+ PM_RET_SUCCESS = (0U),
+ PM_RET_ERROR_ARGS = (1U),
+ PM_RET_ERROR_NOTSUPPORTED = (4U),
+ PM_RET_ERROR_NOT_ENABLED = (29U),
+ PM_RET_ERROR_INTERNAL = (2000U),
+ PM_RET_ERROR_CONFLICT = (2001U),
+ PM_RET_ERROR_ACCESS = (2002U),
+ PM_RET_ERROR_INVALID_NODE = (2003U),
+ PM_RET_ERROR_DOUBLE_REQ = (2004U),
+ PM_RET_ERROR_ABORT_SUSPEND = (2005U),
+ PM_RET_ERROR_TIMEOUT = (2006U),
+ PM_RET_ERROR_NODE_USED = (2007U),
+ PM_RET_ERROR_NO_FEATURE = (2008U)
+};
+
+/**
+ * @PM_INITIAL_BOOT: boot is a fresh system startup
+ * @PM_RESUME: boot is a resume
+ * @PM_BOOT_ERROR: error, boot cause cannot be identified
+ */
+enum pm_boot_status {
+ PM_INITIAL_BOOT,
+ PM_RESUME,
+ PM_BOOT_ERROR,
+};
+
+/**
+ * @PMF_SHUTDOWN_TYPE_SHUTDOWN: shutdown
+ * @PMF_SHUTDOWN_TYPE_RESET: reset/reboot
+ * @PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY: set the shutdown/reboot scope
+ */
+enum pm_shutdown_type {
+ PMF_SHUTDOWN_TYPE_SHUTDOWN,
+ PMF_SHUTDOWN_TYPE_RESET,
+ PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY,
+};
+
+/**
+ * @PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM: shutdown/reboot APU subsystem only
+ * @PMF_SHUTDOWN_SUBTYPE_PS_ONLY: shutdown/reboot entire PS (but not PL)
+ * @PMF_SHUTDOWN_SUBTYPE_SYSTEM: shutdown/reboot entire system
+ */
+enum pm_shutdown_subtype {
+ PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM,
+ PMF_SHUTDOWN_SUBTYPE_PS_ONLY,
+ PMF_SHUTDOWN_SUBTYPE_SYSTEM,
+};
+
+/**
+ * @PM_PLL_PARAM_DIV2: Enable for divide by 2 function inside the PLL
+ * @PM_PLL_PARAM_FBDIV: Feedback divisor integer portion for the PLL
+ * @PM_PLL_PARAM_DATA: Feedback divisor fractional portion for the PLL
+ * @PM_PLL_PARAM_PRE_SRC: Clock source for PLL input
+ * @PM_PLL_PARAM_POST_SRC: Clock source for PLL Bypass mode
+ * @PM_PLL_PARAM_LOCK_DLY: Lock circuit config settings for lock windowsize
+ * @PM_PLL_PARAM_LOCK_CNT: Lock circuit counter setting
+ * @PM_PLL_PARAM_LFHF: PLL loop filter high frequency capacitor control
+ * @PM_PLL_PARAM_CP: PLL charge pump control
+ * @PM_PLL_PARAM_RES: PLL loop filter resistor control
+ */
+enum pm_pll_param {
+ PM_PLL_PARAM_DIV2,
+ PM_PLL_PARAM_FBDIV,
+ PM_PLL_PARAM_DATA,
+ PM_PLL_PARAM_PRE_SRC,
+ PM_PLL_PARAM_POST_SRC,
+ PM_PLL_PARAM_LOCK_DLY,
+ PM_PLL_PARAM_LOCK_CNT,
+ PM_PLL_PARAM_LFHF,
+ PM_PLL_PARAM_CP,
+ PM_PLL_PARAM_RES,
+ PM_PLL_PARAM_MAX,
+};
+
+/**
+ * @PM_PLL_MODE_RESET: PLL is in reset (not locked)
+ * @PM_PLL_MODE_INTEGER: PLL is locked in integer mode
+ * @PM_PLL_MODE_FRACTIONAL: PLL is locked in fractional mode
+ */
+enum pm_pll_mode {
+ PM_PLL_MODE_RESET,
+ PM_PLL_MODE_INTEGER,
+ PM_PLL_MODE_FRACTIONAL,
+ PM_PLL_MODE_MAX,
+};
+
+/**
+ * @PM_CLOCK_DIV0_ID: Clock divider 0
+ * @PM_CLOCK_DIV1_ID: Clock divider 1
+ */
+enum pm_clock_div_id {
+ PM_CLOCK_DIV0_ID,
+ PM_CLOCK_DIV1_ID,
+};
+
+/**
+ * EM API IDs
+ */
+enum em_api_id {
+ EM_SET_ACTION = 1,
+ EM_REMOVE_ACTION,
+ EM_SEND_ERRORS,
+};
+
+#endif /* PM_DEFS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
new file mode 100644
index 0000000..03fa316
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Top-level SMC handler for ZynqMP power management calls and
+ * IPI setup functions for communication with PMU.
+ */
+
+#include <errno.h>
+
+#include <common/runtime_svc.h>
+#if ZYNQMP_WDT_RESTART
+#include <arch_helpers.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+#endif
+
+#include <plat_private.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_defs.h"
+#include "pm_ipi.h"
+
+/* pm_up = !0 - UP, pm_up = 0 - DOWN */
+static int32_t pm_up, ipi_irq_flag;
+
+#if ZYNQMP_WDT_RESTART
+static spinlock_t inc_lock;
+static int active_cores = 0;
+#endif
+
+/**
+ * pm_context - Structure which contains data for power management
+ * @api_version version of PM API, must match with one on PMU side
+ * @payload payload array used to store received
+ * data from ipi buffer registers
+ */
+static struct {
+ uint32_t api_version;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+} pm_ctx;
+
+#if ZYNQMP_WDT_RESTART
+/**
+ * trigger_wdt_restart() - Trigger warm restart event to APU cores
+ *
+ * This function triggers SGI for all active APU CPUs. SGI handler then
+ * power down CPU and call system reset.
+ */
+static void trigger_wdt_restart(void)
+{
+ uint32_t core_count = 0;
+ uint32_t core_status[3];
+ uint32_t target_cpu_list = 0;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ pm_get_node_status(NODE_APU_0 + i, core_status);
+ if (core_status[0] == 1) {
+ core_count++;
+ target_cpu_list |= (1 << i);
+ }
+ }
+
+ spin_lock(&inc_lock);
+ active_cores = core_count;
+ spin_unlock(&inc_lock);
+
+ INFO("Active Cores: %d\n", active_cores);
+
+ for (i = PLATFORM_CORE_COUNT - 1; i >= 0; i--) {
+ if (target_cpu_list & (1 << i)) {
+ /* trigger SGI to active cores */
+ plat_ic_raise_el3_sgi(ARM_IRQ_SEC_SGI_7, i);
+ }
+ }
+}
+
+/**
+ * ttc_fiq_handler() - TTC Handler for timer event
+ * @id number of the highest priority pending interrupt of the type
+ * that this handler was registered for
+ * @flags security state, bit[0]
+ * @handler pointer to 'cpu_context' structure of the current CPU for the
+ * security state specified in the 'flags' parameter
+ * @cookie unused
+ *
+ * Function registered as INTR_TYPE_EL3 interrupt handler
+ *
+ * When WDT event is received in PMU, PMU needs to notify master to do cleanup
+ * if required. PMU sets up timer and starts timer to overflow in zero time upon
+ * WDT event. ATF handles this timer event and takes necessary action required
+ * for warm restart.
+ *
+ * In presence of non-secure software layers (EL1/2) sets the interrupt
+ * at registered entrance in GIC and informs that PMU responsed or demands
+ * action.
+ */
+static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle,
+ void *cookie)
+{
+ INFO("BL31: Got TTC FIQ\n");
+
+ plat_ic_end_of_interrupt(id);
+
+ /* Clear TTC interrupt by reading interrupt register */
+ mmio_read_32(TTC3_INTR_REGISTER_1);
+
+ /* Disable the timer interrupts */
+ mmio_write_32(TTC3_INTR_ENABLE_1, 0);
+
+ trigger_wdt_restart();
+
+ return 0;
+}
+
+/**
+ * zynqmp_sgi7_irq() - Handler for SGI7 IRQ
+ * @id number of the highest priority pending interrupt of the type
+ * that this handler was registered for
+ * @flags security state, bit[0]
+ * @handler pointer to 'cpu_context' structure of the current CPU for the
+ * security state specified in the 'flags' parameter
+ * @cookie unused
+ *
+ * Function registered as INTR_TYPE_EL3 interrupt handler
+ *
+ * On receiving WDT event from PMU, ATF generates SGI7 to all running CPUs.
+ * In response to SGI7 interrupt, each CPUs do clean up if required and last
+ * running CPU calls system restart.
+ */
+static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ int i;
+ uint32_t value;
+
+ /* enter wfi and stay there */
+ INFO("Entering wfi\n");
+
+ spin_lock(&inc_lock);
+ active_cores--;
+
+ for (i = 0; i < 4; i++) {
+ mmio_write_32(BASE_GICD_BASE + GICD_CPENDSGIR + 4 * i,
+ 0xffffffff);
+ }
+
+ dsb();
+
+ spin_unlock(&inc_lock);
+
+ if (active_cores == 0) {
+ pm_mmio_read(PMU_GLOBAL_GEN_STORAGE4, &value);
+ value = (value & RESTART_SCOPE_MASK) >> RESTART_SCOPE_SHIFT;
+ pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, value);
+ }
+
+ /* enter wfi and stay there */
+ while (1)
+ wfi();
+}
+
+/**
+ * pm_wdt_restart_setup() - Setup warm restart interrupts
+ *
+ * This function sets up handler for SGI7 and TTC interrupts
+ * used for warm restart.
+ */
+static int pm_wdt_restart_setup(void)
+{
+ int ret;
+
+ /* register IRQ handler for SGI7 */
+ ret = request_intr_type_el3(ARM_IRQ_SEC_SGI_7, zynqmp_sgi7_irq);
+ if (ret) {
+ WARN("BL31: registering SGI7 interrupt failed\n");
+ goto err;
+ }
+
+ ret = request_intr_type_el3(IRQ_TTC3_1, ttc_fiq_handler);
+ if (ret)
+ WARN("BL31: registering TTC3 interrupt failed\n");
+
+err:
+ return ret;
+}
+#endif
+
+/**
+ * pm_setup() - PM service setup
+ *
+ * @return On success, the initialization function must return 0.
+ * Any other return value will cause the framework to ignore
+ * the service
+ *
+ * Initialization functions for ZynqMP power management for
+ * communicaton with PMU.
+ *
+ * Called from sip_svc_setup initialization function with the
+ * rt_svc_init signature.
+ */
+int32_t pm_setup(void)
+{
+
+ pm_ipi_init(primary_proc);
+
+ pm_get_api_version(&pm_ctx.api_version);
+ if (pm_ctx.api_version < PM_VERSION) {
+ ERROR("BL31: Platform Management API version error. Expected: "
+ "v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR,
+ PM_VERSION_MINOR, pm_ctx.api_version >> 16,
+ pm_ctx.api_version & 0xFFFFU);
+ return -EINVAL;
+ }
+
+ int32_t status = 0, ret = 0;
+#if ZYNQMP_WDT_RESTART
+ status = pm_wdt_restart_setup();
+ if (status)
+ WARN("BL31: warm-restart setup failed\n");
+#endif
+
+ if (status >= 0) {
+ INFO("BL31: PM Service Init Complete: API v%d.%d\n",
+ PM_VERSION_MAJOR, PM_VERSION_MINOR);
+ ret = 0;
+ } else {
+ INFO("BL31: PM Service Init Failed, Error Code %d!\n", status);
+ ret = status;
+ }
+
+ pm_up = !status;
+
+ return ret;
+}
+
+/**
+ * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return - Unused
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, const void *cookie, void *handle, uint64_t flags)
+{
+ enum pm_ret_status ret;
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ uint32_t pm_arg[5];
+ uint32_t result[PAYLOAD_ARG_CNT] = {0};
+ uint32_t api_id;
+
+ /* Handle case where PM wasn't initialized properly */
+ if (pm_up == 0)
+ SMC_RET1(handle, SMC_UNK);
+
+ pm_arg[0] = (uint32_t)x1;
+ pm_arg[1] = (uint32_t)(x1 >> 32);
+ pm_arg[2] = (uint32_t)x2;
+ pm_arg[3] = (uint32_t)(x2 >> 32);
+ pm_arg[4] = (uint32_t)x3;
+
+ api_id = smc_fid & FUNCID_NUM_MASK;
+
+ switch (api_id) {
+ /* PM API Functions */
+ case PM_SELF_SUSPEND:
+ ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_REQ_SUSPEND:
+ ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_REQ_WAKEUP:
+ {
+ /* Use address flag is encoded in the 1st bit of the low-word */
+ uint32_t set_addr = pm_arg[1] & 0x1U;
+ uint64_t address = (uint64_t)pm_arg[2] << 32U;
+
+ address |= pm_arg[1] & (~0x1U);
+ ret = pm_req_wakeup(pm_arg[0], set_addr, address,
+ pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+ }
+
+ case PM_FORCE_POWERDOWN:
+ ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_ABORT_SUSPEND:
+ ret = pm_abort_suspend(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_SET_WAKEUP_SOURCE:
+ ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_SYSTEM_SHUTDOWN:
+ ret = pm_system_shutdown(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_REQ_NODE:
+ ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_SET_REQUIREMENT:
+ ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_GET_API_VERSION:
+ /* Check is PM API version already verified */
+ if (pm_ctx.api_version >= PM_VERSION) {
+ if (ipi_irq_flag == 0U) {
+ /*
+ * Enable IPI IRQ
+ * assume the rich OS is OK to handle callback IRQs now.
+ * Even if we were wrong, it would not enable the IRQ in
+ * the GIC.
+ */
+ pm_ipi_irq_enable(primary_proc);
+ ipi_irq_flag = 1U;
+ }
+ SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+ ((uint64_t)pm_ctx.api_version << 32));
+ }
+
+ case PM_FPGA_LOAD:
+ ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_FPGA_GET_STATUS:
+ {
+ uint32_t value = 0;
+
+ ret = pm_fpga_get_status(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_SECURE_RSA_AES:
+ ret = pm_secure_rsaaes(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_GET_CALLBACK_DATA:
+ pm_get_callbackdata(result, ARRAY_SIZE(result));
+ SMC_RET2(handle,
+ (uint64_t)result[0] | ((uint64_t)result[1] << 32),
+ (uint64_t)result[2] | ((uint64_t)result[3] << 32));
+ case PM_IOCTL:
+ {
+ uint32_t value = 0;
+
+ ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_QUERY_DATA:
+ {
+ uint32_t data[4] = { 0 };
+
+ pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], data);
+ SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32),
+ (uint64_t)data[2] | ((uint64_t)data[3] << 32));
+ }
+
+ case PM_CLOCK_ENABLE:
+ ret = pm_clock_enable(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_DISABLE:
+ ret = pm_clock_disable(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETSTATE:
+ {
+ uint32_t value = 0;
+
+ ret = pm_clock_getstate(pm_arg[0], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_CLOCK_SETDIVIDER:
+ ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETDIVIDER:
+ {
+ uint32_t value = 0;
+
+ ret = pm_clock_getdivider(pm_arg[0], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_CLOCK_SETRATE:
+ ret = pm_clock_setrate(pm_arg[0],
+ ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]);
+
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETRATE:
+ {
+ uint64_t value = 0;
+
+ ret = pm_clock_getrate(pm_arg[0], &value);
+ SMC_RET2(handle, (uint64_t)ret |
+ (((uint64_t)value & 0xFFFFFFFFU) << 32U),
+ (value >> 32U) & 0xFFFFFFFFU);
+
+ }
+
+ case PM_CLOCK_SETPARENT:
+ ret = pm_clock_setparent(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_CLOCK_GETPARENT:
+ {
+ uint32_t value = 0;
+
+ ret = pm_clock_getparent(pm_arg[0], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case PM_GET_TRUSTZONE_VERSION:
+ SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+ ((uint64_t)ZYNQMP_TZ_VERSION << 32U));
+
+ case PM_SET_SUSPEND_MODE:
+ ret = pm_set_suspend_mode(pm_arg[0]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_SECURE_SHA:
+ ret = pm_sha_hash(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_SECURE_RSA:
+ ret = pm_rsa_core(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_SECURE_IMAGE:
+ {
+ ret = pm_secure_image(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], &result[0]);
+ SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
+ result[1]);
+ }
+
+ case PM_FPGA_READ:
+ {
+ uint32_t value = 0;
+
+ ret = pm_fpga_read(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
+ &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case PM_SECURE_AES:
+ {
+ uint32_t value = 0;
+
+ ret = pm_aes_engine(pm_arg[0], pm_arg[1], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case PM_PLL_SET_PARAMETER:
+ ret = pm_pll_set_parameter(pm_arg[0], pm_arg[1], pm_arg[2]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_PLL_GET_PARAMETER:
+ {
+ uint32_t value = 0;
+
+ ret = pm_pll_get_parameter(pm_arg[0], pm_arg[1], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32U));
+ }
+
+ case PM_PLL_SET_MODE:
+ ret = pm_pll_set_mode(pm_arg[0], pm_arg[1]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_PLL_GET_MODE:
+ {
+ uint32_t mode = 0;
+
+ ret = pm_pll_get_mode(pm_arg[0], &mode);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32U));
+ }
+
+ case PM_REGISTER_ACCESS:
+ {
+ uint32_t value = 0;
+
+ ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case PM_EFUSE_ACCESS:
+ {
+ uint32_t value = 0;
+
+#if defined(ZYNQMP_SECURE_EFUSES)
+ if (is_caller_non_secure(flags)) {
+ SMC_RET1(handle,
+ (((uint64_t)PM_RET_ERROR_NOT_ENABLED) << 32U) |
+ (uint64_t)PM_RET_ERROR_ACCESS);
+ }
+#endif
+ ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case PM_FPGA_GET_VERSION:
+ case PM_FPGA_GET_FEATURE_LIST:
+ {
+ uint32_t ret_payload[PAYLOAD_ARG_CNT];
+
+ PM_PACK_PAYLOAD5(payload, smc_fid & FUNCID_NUM_MASK,
+ pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+ ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, 3U);
+ SMC_RET2(handle, (uint64_t)ret | (uint64_t)ret_payload[0] << 32U,
+ (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32U);
+ }
+
+ case PM_FEATURE_CHECK:
+ {
+ uint32_t version = 0;
+ uint32_t bit_mask[2] = {0};
+
+ ret = pm_feature_check(pm_arg[0], &version, bit_mask,
+ ARRAY_SIZE(bit_mask));
+ SMC_RET2(handle, (uint64_t)ret | ((uint64_t)version << 32U),
+ (uint64_t)bit_mask[0] | ((uint64_t)bit_mask[1] << 32U));
+ }
+
+ default:
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
+ pm_arg[2], pm_arg[3], pm_arg[4]);
+ ret = pm_ipi_send_sync(primary_proc, payload, result,
+ PAYLOAD_ARG_CNT);
+ SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
+ (uint64_t)result[1] | ((uint64_t)result[2] << 32U));
+ }
+}
+
+/**
+ * em_smc_handler() - SMC handler for EM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return - Unused
+ *
+ * Determines that smc_fid is valid and supported EM SMC Function ID from the
+ * list of em_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for EM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, const void *cookie, void *handle, uint64_t flags)
+{
+ enum pm_ret_status ret;
+
+ switch (smc_fid & FUNCID_NUM_MASK) {
+ /* EM API Functions */
+ case EM_SET_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_set_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case EM_REMOVE_ACTION:
+ {
+ uint32_t value;
+
+ ret = em_remove_action(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ case EM_SEND_ERRORS:
+ {
+ uint32_t value;
+
+ ret = em_send_errors(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+ }
+
+ default:
+ WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
new file mode 100644
index 0000000..c1781f3
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_SVC_MAIN_H
+#define PM_SVC_MAIN_H
+
+#include "pm_common.h"
+
+int32_t pm_setup(void);
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, const void *cookie, void *handle,
+ uint64_t flags);
+
+uint64_t em_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, const void *cookie, void *handle,
+ uint64_t flags);
+#endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/zynqmp/sip_svc_setup.c b/plat/xilinx/zynqmp/sip_svc_setup.c
new file mode 100644
index 0000000..4ce9b8a
--- /dev/null
+++ b/plat/xilinx/zynqmp/sip_svc_setup.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */
+
+#include <common/runtime_svc.h>
+#include <tools_share/uuid.h>
+
+#include "ipi_mailbox_svc.h"
+#include "pm_svc_main.h"
+
+/* SMC function IDs for SiP Service queries */
+#define ZYNQMP_SIP_SVC_CALL_COUNT U(0x8200ff00)
+#define ZYNQMP_SIP_SVC_UID U(0x8200ff01)
+#define ZYNQMP_SIP_SVC_VERSION U(0x8200ff03)
+
+/* SiP Service Calls version numbers */
+#define SIP_SVC_VERSION_MAJOR 0
+#define SIP_SVC_VERSION_MINOR 1
+
+/* These macros are used to identify PM, IPI calls from the SMC function ID */
+#define PM_FID_MASK 0xf000u
+#define PM_FID_VALUE 0u
+#define IPI_FID_VALUE 0x1000u
+#define EM_FID_MASK 0xf0000u
+#define EM_FID_VALUE 0xE0000u
+#define is_em_fid(_fid) (((_fid) & EM_FID_MASK) == EM_FID_VALUE)
+#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE)
+#define is_ipi_fid(_fid) (((_fid) & PM_FID_MASK) == IPI_FID_VALUE)
+
+/* SiP Service UUID */
+DEFINE_SVC_UUID2(zynqmp_sip_uuid,
+ 0x5c9b1b2a, 0x0586, 0x2340, 0xa6, 0x1b,
+ 0xb9, 0x25, 0x82, 0x2d, 0xe3, 0xa5);
+
+/**
+ * sip_svc_setup() - Setup SiP Service
+ *
+ * Invokes PM setup
+ */
+static int32_t sip_svc_setup(void)
+{
+ /* PM implementation as SiP Service */
+ return pm_setup();
+}
+
+/**
+ * sip_svc_smc_handler() - Top-level SiP Service SMC handler
+ *
+ * Handler for all SiP SMC calls. Handles standard SIP requests
+ * and calls PM SMC handler if the call is for a PM-API function.
+ */
+static uintptr_t sip_svc_smc_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ /* Let EM SMC handler deal with EM-related requests */
+ if (is_em_fid(smc_fid)) {
+ return em_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ } else if (is_pm_fid(smc_fid)) {
+ /* Let PM SMC handler deal with PM-related requests */
+ return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ }
+
+ /* Let IPI SMC handler deal with IPI-related requests */
+ if (is_ipi_fid(smc_fid)) {
+ return ipi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
+ flags);
+ }
+
+ switch (smc_fid) {
+ case ZYNQMP_SIP_SVC_CALL_COUNT:
+ /* PM functions + default functions */
+ SMC_RET1(handle, PM_API_MAX + 2);
+
+ case ZYNQMP_SIP_SVC_UID:
+ SMC_UUID_RET(handle, zynqmp_sip_uuid);
+
+ case ZYNQMP_SIP_SVC_VERSION:
+ SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR);
+
+ default:
+ WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
+
+/* Register PM Service Calls as runtime service */
+DECLARE_RT_SVC(
+ sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ (uint8_t)SMC_TYPE_FAST,
+ sip_svc_setup,
+ sip_svc_smc_handler);
diff --git a/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk b/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk
new file mode 100644
index 0000000..318b01d
--- /dev/null
+++ b/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+# TSP source files specific to ZynqMP platform
+BL32_SOURCES += plat/common/aarch64/platform_mp_stack.S \
+ plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
new file mode 100644
index 0000000..352ba82
--- /dev/null
+++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat_private.h>
+#include <platform_tsp.h>
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+void tsp_early_platform_setup(void)
+{
+ /*
+ * Register a different console than already in use to display
+ * messages from TSP
+ */
+ static console_t tsp_boot_console;
+ (void)console_cdns_register(ZYNQMP_UART_BASE,
+ zynqmp_get_uart_clk(),
+ ZYNQMP_UART_BAUDRATE,
+ &tsp_boot_console);
+ console_set_scope(&tsp_boot_console,
+ CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
+
+ /* Initialize the platform config for future decision making */
+ zynqmp_config_setup();
+}
+
+/*******************************************************************************
+ * Perform platform specific setup placeholder
+ ******************************************************************************/
+void tsp_platform_setup(void)
+{
+ plat_arm_gic_driver_init();
+ plat_arm_gic_init();
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the MMU
+ ******************************************************************************/
+void tsp_plat_arch_setup(void)
+{
+ const mmap_region_t bl_regions[] = {
+ MAP_REGION_FLAT(BL32_BASE, BL32_END - BL32_BASE,
+ MT_MEMORY | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE),
+ MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE,
+ MT_RO_DATA | MT_SECURE),
+ MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+ BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ {0}
+ };
+
+ setup_page_tables(bl_regions, plat_arm_get_mmap());
+ enable_mmu_el1(0);
+}
diff --git a/plat/xilinx/zynqmp/zynqmp_ehf.c b/plat/xilinx/zynqmp/zynqmp_ehf.c
new file mode 100644
index 0000000..fbf1ed0
--- /dev/null
+++ b/plat/xilinx/zynqmp/zynqmp_ehf.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) Siemens AG, 2020-2021
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <bl31/ehf.h>
+
+/*
+ * Enumeration of priority levels on ARM platforms.
+ */
+ehf_pri_desc_t zynqmp_exceptions[] = {
+ /* Critical priority SDEI */
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_CRITICAL_PRI),
+
+ /* Normal priority SDEI */
+ EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI),
+};
+
+/* Plug in ARM exceptions to Exception Handling Framework. */
+EHF_REGISTER_PRIORITIES(zynqmp_exceptions, ARRAY_SIZE(zynqmp_exceptions), PLAT_PRI_BITS);
diff --git a/plat/xilinx/zynqmp/zynqmp_ipi.c b/plat/xilinx/zynqmp/zynqmp_ipi.c
new file mode 100644
index 0000000..4ea3c6a
--- /dev/null
+++ b/plat/xilinx/zynqmp/zynqmp_ipi.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Zynq UltraScale+ MPSoC IPI agent registers access management
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include <ipi.h>
+#include <plat_ipi.h>
+#include <plat_private.h>
+
+/* Zynqmp ipi configuration table */
+const static struct ipi_config zynqmp_ipi_table[] = {
+ /* APU IPI */
+ {
+ .ipi_bit_mask = 0x1,
+ .ipi_reg_base = 0xFF300000U,
+ .secure_only = 0,
+ },
+ /* RPU0 IPI */
+ {
+ .ipi_bit_mask = 0x100,
+ .ipi_reg_base = 0xFF310000U,
+ .secure_only = 0,
+ },
+ /* RPU1 IPI */
+ {
+ .ipi_bit_mask = 0x200,
+ .ipi_reg_base = 0xFF320000U,
+ .secure_only = 0,
+ },
+ /* PMU0 IPI */
+ {
+ .ipi_bit_mask = 0x10000,
+ .ipi_reg_base = 0xFF330000U,
+ .secure_only = IPI_SECURE_MASK,
+ },
+ /* PMU1 IPI */
+ {
+ .ipi_bit_mask = 0x20000,
+ .ipi_reg_base = 0xFF331000U,
+ .secure_only = 0,
+ },
+ /* PMU2 IPI */
+ {
+ .ipi_bit_mask = 0x40000,
+ .ipi_reg_base = 0xFF332000U,
+ .secure_only = IPI_SECURE_MASK,
+ },
+ /* PMU3 IPI */
+ {
+ .ipi_bit_mask = 0x80000,
+ .ipi_reg_base = 0xFF333000U,
+ .secure_only = IPI_SECURE_MASK,
+ },
+ /* PL0 IPI */
+ {
+ .ipi_bit_mask = 0x1000000,
+ .ipi_reg_base = 0xFF340000U,
+ .secure_only = 0,
+ },
+ /* PL1 IPI */
+ {
+ .ipi_bit_mask = 0x2000000,
+ .ipi_reg_base = 0xFF350000U,
+ .secure_only = 0,
+ },
+ /* PL2 IPI */
+ {
+ .ipi_bit_mask = 0x4000000,
+ .ipi_reg_base = 0xFF360000U,
+ .secure_only = 0,
+ },
+ /* PL3 IPI */
+ {
+ .ipi_bit_mask = 0x8000000,
+ .ipi_reg_base = 0xFF370000U,
+ .secure_only = 0,
+ },
+};
+
+/**
+ * zynqmp_ipi_config_table_init() - Initialize ZynqMP IPI configuration data
+ *
+ */
+void zynqmp_ipi_config_table_init(void)
+{
+ ipi_config_table_init(zynqmp_ipi_table, ARRAY_SIZE(zynqmp_ipi_table));
+}
diff --git a/plat/xilinx/zynqmp/zynqmp_sdei.c b/plat/xilinx/zynqmp/zynqmp_sdei.c
new file mode 100644
index 0000000..7e92b58
--- /dev/null
+++ b/plat/xilinx/zynqmp/zynqmp_sdei.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) Siemens AG, 2020-2021
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* SDEI configuration for ARM platforms */
+
+#include <bl31/ehf.h>
+#include <common/debug.h>
+#include <services/sdei.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+int arm_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ return (entrypoint < BL31_BASE || entrypoint > BL31_LIMIT) ? 0 : -1;
+}
+
+/* Private event mappings */
+static sdei_ev_map_t zynqmp_sdei_private[] = {
+ SDEI_DEFINE_EVENT_0(ZYNQMP_SDEI_SGI_PRIVATE),
+};
+
+/* Shared event mappings */
+static sdei_ev_map_t zynqmp_sdei_shared[] = {
+};
+
+void plat_sdei_setup(void)
+{
+ INFO("SDEI platform setup\n");
+}
+
+/* Export ARM SDEI events */
+REGISTER_SDEI_MAP(zynqmp_sdei_private, zynqmp_sdei_shared);